Fix for more than 2 devices via USB MSC
[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, uint8_t epnum)
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 * @param  epnum: endpoint index
198 * @retval None
199 */
200 void MSC_BOT_DataOut (USBD_HandleTypeDef  *pdev, uint8_t epnum)
201 {
202         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
203         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
204
205         switch (hmsc->bot_state)
206         {
207         case USBD_BOT_IDLE:
208                 MSC_BOT_CBW_Decode(pdev);
209                 break;
210
211         case USBD_BOT_DATA_OUT:
212                 if(SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0)
213                 {
214                         MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);
215                 }
216                 break;
217
218         default:
219                 break;
220         }
221 }
222
223 /**
224 * @brief  MSC_BOT_CBW_Decode
225 *         Decode the CBW command and set the BOT state machine accordingly  
226 * @param  pdev: device instance
227 * @retval None
228 */
229 static void  MSC_BOT_CBW_Decode (USBD_HandleTypeDef  *pdev)
230 {
231         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
232         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
233
234         hmsc->csw.dTag = hmsc->cbw.dTag;
235         hmsc->csw.dDataResidue = hmsc->cbw.dDataLength;
236
237         if ((USBD_LL_GetRxDataSize (pdev ,MSC_EPOUT_ADDR) != USBD_BOT_CBW_LENGTH) ||
238                 (hmsc->cbw.dSignature != USBD_BOT_CBW_SIGNATURE)||
239                 //(hmsc->cbw.bLUN > 1) || 
240                 (hmsc->cbw.bCBLength < 1) || 
241                 (hmsc->cbw.bCBLength > 16))
242         {
243                 SCSI_SenseCode(pdev,
244                         hmsc->cbw.bLUN,
245                         ILLEGAL_REQUEST,
246                         INVALID_CDB);
247
248                 hmsc->bot_status = USBD_BOT_STATUS_ERROR;
249                 MSC_BOT_Abort(pdev);
250         }
251         else
252         {
253                 if(SCSI_ProcessCmd(pdev, hmsc->cbw.bLUN, &hmsc->cbw.CB[0]) < 0)
254                 {
255                         if(hmsc->bot_state == USBD_BOT_NO_DATA)
256                         {
257                                 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_FAILED);
258                         }
259                         else
260                         {
261                                 MSC_BOT_Abort(pdev);
262                         }
263                 }
264                 /*Burst xfer handled internally*/
265                 else if ((hmsc->bot_state != USBD_BOT_DATA_IN) &&
266                         (hmsc->bot_state != USBD_BOT_DATA_OUT) &&
267                         (hmsc->bot_state != USBD_BOT_LAST_DATA_IN))
268                 {
269                         if (hmsc->bot_data_length > 0)
270                         {
271                                 MSC_BOT_SendData(pdev, hmsc->bot_data, hmsc->bot_data_length);
272                         }
273                         else if (hmsc->bot_data_length == 0)
274                         {
275                                 MSC_BOT_SendCSW (pdev, USBD_CSW_CMD_PASSED);
276                         }
277                 }
278         }
279 }
280
281 /**
282 * @brief  MSC_BOT_SendData
283 *         Send the requested data
284 * @param  pdev: device instance
285 * @param  buf: pointer to data buffer
286 * @param  len: Data Length
287 * @retval None
288 */
289 static void MSC_BOT_SendData(USBD_HandleTypeDef *pdev,
290         uint8_t* buf,
291         uint16_t len)
292 {
293         USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
294         USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
295
296         len = MIN (hmsc->cbw.dDataLength, len);
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, len);
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