Fix USB mass storage error responses on windows with no SD card inserted
[SCSI2SD-V6.git] / src / firmware / usb_device / usbd_msc_bot.c
1 /**
2   ******************************************************************************
3   * @file    usbd_msc_bot.c
4   * @author  MCD Application Team
5   * @version V2.4.1
6   * @date    19-June-2015
7   * @brief   This file provides all the BOT protocol core functions.
8   ******************************************************************************
9   * @attention
10   *
11   * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
12   *
13   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
14   * You may not use this file except in compliance with the License.
15   * You may obtain a copy of the License at:
16   *
17   *        http://www.st.com/software_license_agreement_liberty_v2
18   *
19   * Unless required by applicable law or agreed to in writing, software 
20   * distributed under the License is distributed on an "AS IS" BASIS, 
21   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22   * See the License for the specific language governing permissions and
23   * limitations under the License.
24   *
25   ******************************************************************************
26   */ 
27
28 /* Includes ------------------------------------------------------------------*/
29 #include "usbd_composite.h"
30 #include "usbd_msc_bot.h"
31 #include "usbd_msc.h"
32 #include "usbd_msc_scsi.h"
33 #include "usbd_ioreq.h"
34
35 /** @addtogroup STM32_USB_DEVICE_LIBRARY
36   * @{
37   */
38
39
40 /** @defgroup MSC_BOT 
41   * @brief BOT protocol module
42   * @{
43   */ 
44
45 /** @defgroup MSC_BOT_Private_TypesDefinitions
46   * @{
47   */ 
48 /**
49   * @}
50   */ 
51
52
53 /** @defgroup MSC_BOT_Private_Defines
54   * @{
55   */ 
56
57 /**
58   * @}
59   */ 
60
61
62 /** @defgroup MSC_BOT_Private_Macros
63   * @{
64   */ 
65 /**
66   * @}
67   */ 
68
69
70 /** @defgroup MSC_BOT_Private_Variables
71   * @{
72   */ 
73
74 /**
75   * @}
76   */ 
77
78
79 /** @defgroup MSC_BOT_Private_FunctionPrototypes
80   * @{
81   */ 
82 static void MSC_BOT_CBW_Decode (USBD_HandleTypeDef  *pdev);
83
84 static void MSC_BOT_SendData (USBD_HandleTypeDef  *pdev, 
85                               uint8_t* pbuf, 
86                               uint16_t len);
87
88 static void MSC_BOT_Abort(USBD_HandleTypeDef  *pdev);
89 /**
90   * @}
91   */ 
92
93
94 /** @defgroup MSC_BOT_Private_Functions
95   * @{
96   */ 
97
98
99
100 /**
101 * @brief  MSC_BOT_Init
102 *         Initialize the BOT Process
103 * @param  pdev: device instance
104 * @retval None
105 */
106 void MSC_BOT_Init (USBD_HandleTypeDef  *pdev)
107 {
108         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
109         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
110
111         hmsc->bot_state  = USBD_BOT_IDLE;
112         hmsc->bot_status = USBD_BOT_STATUS_NORMAL;
113
114         hmsc->scsi_sense_tail = 0;
115         hmsc->scsi_sense_head = 0;
116
117         ((USBD_StorageTypeDef *)pdev->pUserData)->Init(0);
118
119         USBD_LL_FlushEP(pdev, MSC_EPOUT_ADDR);
120         USBD_LL_FlushEP(pdev, MSC_EPIN_ADDR);
121
122         /* Prapare EP to Receive First BOT Cmd */
123         USBD_LL_PrepareReceive (pdev,
124                 MSC_EPOUT_ADDR,
125                 (uint8_t *)&hmsc->cbw,
126                 USBD_BOT_CBW_LENGTH);
127 }
128
129 /**
130 * @brief  MSC_BOT_Reset
131 *         Reset the BOT Machine
132 * @param  pdev: device instance
133 * @retval  None
134 */
135 void MSC_BOT_Reset (USBD_HandleTypeDef  *pdev)
136 {
137         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
138         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
139
140         hmsc->bot_state  = USBD_BOT_IDLE;
141         hmsc->bot_status = USBD_BOT_STATUS_RECOVERY;
142
143         /* Prapare EP to Receive First BOT Cmd */
144         USBD_LL_PrepareReceive (pdev,
145                 MSC_EPOUT_ADDR,
146                 (uint8_t *)&hmsc->cbw,
147                 USBD_BOT_CBW_LENGTH);
148 }
149
150 /**
151 * @brief  MSC_BOT_DeInit
152 *         Deinitialize the BOT Machine
153 * @param  pdev: device instance
154 * @retval None
155 */
156 void MSC_BOT_DeInit (USBD_HandleTypeDef  *pdev)
157 {
158         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
159         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
160         hmsc->bot_state  = USBD_BOT_IDLE;
161 }
162
163 /**
164 * @brief  MSC_BOT_DataIn
165 *         Handle BOT IN data stage
166 * @param  pdev: device instance
167 * @param  epnum: endpoint index
168 * @retval None
169 */
170 void MSC_BOT_DataIn (USBD_HandleTypeDef  *pdev)
171 {
172         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
173         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
174
175         switch (hmsc->bot_state)
176         {
177         case USBD_BOT_DATA_IN:
178                 if(SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0)
179                 {
180                         MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);
181                 }
182                 break;
183
184         case USBD_BOT_SEND_DATA:
185         case USBD_BOT_LAST_DATA_IN:
186                 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED);
187                 break;
188
189         default:
190                 break;
191         }
192 }
193 /**
194 * @brief  MSC_BOT_DataOut
195 *         Process MSC OUT data
196 * @param  pdev: device instance
197 * @retval None
198 */
199 void MSC_BOT_DataOut (USBD_HandleTypeDef  *pdev)
200 {
201         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
202         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
203
204         switch (hmsc->bot_state)
205         {
206         case USBD_BOT_IDLE:
207                 MSC_BOT_CBW_Decode(pdev);
208                 break;
209
210         case USBD_BOT_DATA_OUT:
211                 if(SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0)
212                 {
213                         MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);
214                 }
215                 break;
216
217         default:
218                 break;
219         }
220 }
221
222 /**
223 * @brief  MSC_BOT_CBW_Decode
224 *         Decode the CBW command and set the BOT state machine accordingly  
225 * @param  pdev: device instance
226 * @retval None
227 */
228 static void  MSC_BOT_CBW_Decode (USBD_HandleTypeDef  *pdev)
229 {
230         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
231         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
232
233         hmsc->csw.dTag = hmsc->cbw.dTag;
234         hmsc->csw.dDataResidue = hmsc->cbw.dDataLength;
235
236         if ((USBD_LL_GetRxDataSize (pdev ,MSC_EPOUT_ADDR) != USBD_BOT_CBW_LENGTH) ||
237                 (hmsc->cbw.dSignature != USBD_BOT_CBW_SIGNATURE)||
238                 //(hmsc->cbw.bLUN > 1) || 
239                 (hmsc->cbw.bCBLength < 1) || 
240                 (hmsc->cbw.bCBLength > 16))
241         {
242                 SCSI_SenseCode(pdev,
243                         hmsc->cbw.bLUN,
244                         ILLEGAL_REQUEST,
245                         INVALID_CDB);
246
247                 hmsc->bot_status = USBD_BOT_STATUS_ERROR;
248                 MSC_BOT_Abort(pdev);
249         }
250         else
251         {
252                 if(SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0)
253                 {
254                         if(hmsc->bot_state == USBD_BOT_NO_DATA)
255                         {
256                                 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);
257                         }
258                         else
259                         {
260                                 MSC_BOT_Abort(pdev);
261                         }
262                 }
263                 /*Burst xfer handled internally*/
264                 else if ((hmsc->bot_state != USBD_BOT_DATA_IN) &&
265                         (hmsc->bot_state != USBD_BOT_DATA_OUT) &&
266                         (hmsc->bot_state != USBD_BOT_LAST_DATA_IN))
267                 {
268                         if (hmsc->bot_data_length > 0)
269                         {
270                                 MSC_BOT_SendData(pdev, hmsc->bot_data, hmsc->bot_data_length);
271                         }
272                         else if (hmsc->bot_data_length == 0)
273                         {
274                                 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED);
275                         }
276                 }
277         }
278 }
279
280 /**
281 * @brief  MSC_BOT_SendData
282 *         Send the requested data
283 * @param  pdev: device instance
284 * @param  buf: pointer to data buffer
285 * @param  len: Data Length
286 * @retval None
287 */
288 static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev,
289         uint8_t* buf,
290         uint16_t len)
291 {
292         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
293         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
294
295     uint16_t length = (uint16_t)MIN(hmsc->cbw.dDataLength, len);
296
297         hmsc->csw.dDataResidue -= len;
298         hmsc->csw.bStatus = USBD_CSW_CMD_PASSED;
299         hmsc->bot_state = USBD_BOT_SEND_DATA;
300
301         USBD_LL_Transmit (pdev, MSC_EPIN_ADDR, buf, length);
302 }
303
304 /**
305 * @brief  MSC_BOT_SendCSW
306 *         Send the Command Status Wrapper
307 * @param  pdev: device instance
308 * @param  status : CSW status
309 * @retval None
310 */
311 void MSC_BOT_SendCSW (USBD_HandleTypeDef  *pdev, uint8_t CSW_Status)
312 {
313         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
314         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
315
316         hmsc->csw.dSignature = USBD_BOT_CSW_SIGNATURE;
317         hmsc->csw.bStatus = CSW_Status;
318         hmsc->bot_state = USBD_BOT_IDLE;
319
320         USBD_LL_Transmit (pdev,
321                 MSC_EPIN_ADDR,
322                 (uint8_t *)&hmsc->csw,
323                 USBD_BOT_CSW_LENGTH);
324
325         /* Prepare EP to Receive next Cmd */
326         USBD_LL_PrepareReceive (pdev,
327                 MSC_EPOUT_ADDR,
328                 (uint8_t *)&hmsc->cbw,
329                 USBD_BOT_CBW_LENGTH);
330
331 }
332
333 /**
334 * @brief  MSC_BOT_Abort
335 *         Abort the current transfer
336 * @param  pdev: device instance
337 * @retval status
338 */
339
340 static void  MSC_BOT_Abort (USBD_HandleTypeDef  *pdev)
341 {
342         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
343         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
344
345         if ((hmsc->cbw.bmFlags == 0) &&
346                 (hmsc->cbw.dDataLength != 0) &&
347                 (hmsc->bot_status == USBD_BOT_STATUS_NORMAL) )
348         {
349                 USBD_LL_StallEP(pdev, MSC_EPOUT_ADDR );
350         }
351         USBD_LL_StallEP(pdev, MSC_EPIN_ADDR);
352
353         if(hmsc->bot_status == USBD_BOT_STATUS_ERROR)
354         {
355                 USBD_LL_PrepareReceive (pdev,
356                         MSC_EPOUT_ADDR,
357                         (uint8_t *)&hmsc->cbw,
358                         USBD_BOT_CBW_LENGTH);
359         }
360 }
361
362 /**
363 * @brief  MSC_BOT_CplClrFeature
364 *         Complete the clear feature request
365 * @param  pdev: device instance
366 * @param  epnum: endpoint index
367 * @retval None
368 */
369
370 void  MSC_BOT_CplClrFeature (USBD_HandleTypeDef  *pdev, uint8_t epnum)
371 {
372         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
373         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
374
375         if(hmsc->bot_status == USBD_BOT_STATUS_ERROR )/* Bad CBW Signature */
376         {
377                 USBD_LL_StallEP(pdev, MSC_EPIN_ADDR);
378                 hmsc->bot_status = USBD_BOT_STATUS_NORMAL;
379         }
380         else if((epnum == MSC_EPIN_ADDR) && ( hmsc->bot_status != USBD_BOT_STATUS_RECOVERY))
381         {
382                 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);
383         }
384 }
385