116033c65a4c6e4e62d31cd614be7dad9680dfae
[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