2 ******************************************************************************
4 * @author MCD Application Team
7 * @brief This file includes the mass storage related functions
8 ******************************************************************************
11 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
12 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
13 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
14 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
15 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
16 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
18 * <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
19 ******************************************************************************
22 /* Includes ------------------------------------------------------------------*/
23 #include "usbh_msc_core.h"
24 #include "usbh_msc_scsi.h"
25 #include "usbh_msc_bot.h"
26 #include "usbh_ioreq.h"
28 #include "usb_hcd_int.h"
31 /** @addtogroup USBH_LIB
35 /** @addtogroup USBH_CLASS
39 /** @addtogroup USBH_MSC_CLASS
43 /** @defgroup USBH_MSC_BOT
44 * @brief This file includes the mass storage related functions
49 /** @defgroup USBH_MSC_BOT_Private_TypesDefinitions
56 /** @defgroup USBH_MSC_BOT_Private_Defines
63 /** @defgroup USBH_MSC_BOT_Private_Macros
71 /** @defgroup USBH_MSC_BOT_Private_Variables
75 #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
76 #if defined ( __ICCARM__ ) /*!< IAR Compiler */
77 #pragma data_alignment=4
79 #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
80 __ALIGN_BEGIN HostCBWPkt_TypeDef USBH_MSC_CBWData __ALIGN_END ;
82 #ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
83 #if defined ( __ICCARM__ ) /*!< IAR Compiler */
84 #pragma data_alignment=4
86 #endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
87 __ALIGN_BEGIN HostCSWPkt_TypeDef USBH_MSC_CSWData __ALIGN_END ;
90 static uint32_t BOTStallErrorCount; /* Keeps count of STALL Error Cases*/
97 /** @defgroup USBH_MSC_BOT_Private_FunctionPrototypes
105 /** @defgroup USBH_MSC_BOT_Exported_Variables
108 USBH_BOTXfer_TypeDef USBH_MSC_BOTXferParam;
114 /** @defgroup USBH_MSC_BOT_Private_Functions
120 * @brief USBH_MSC_Init
121 * Initializes the mass storage parameters
125 void USBH_MSC_Init(USB_OTG_CORE_HANDLE *pdev )
127 if(HCD_IsDeviceConnected(pdev))
129 USBH_MSC_CBWData.field.CBWSignature = USBH_MSC_BOT_CBW_SIGNATURE;
130 USBH_MSC_CBWData.field.CBWTag = USBH_MSC_BOT_CBW_TAG;
131 USBH_MSC_CBWData.field.CBWLUN = 0; /*Only one LUN is supported*/
132 USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
135 BOTStallErrorCount = 0;
140 * @brief USBH_MSC_HandleBOTXfer
141 * This function manages the different states of BOT transfer and
142 * updates the status to upper layer.
147 void USBH_MSC_HandleBOTXfer (USB_OTG_CORE_HANDLE *pdev ,USBH_HOST *phost)
149 uint8_t xferDirection, index;
150 static uint32_t remainingDataLength;
151 static uint8_t *datapointer;
152 static uint8_t error_direction;
155 URB_STATE URB_Status = URB_IDLE;
157 if(HCD_IsDeviceConnected(pdev))
160 switch (USBH_MSC_BOTXferParam.BOTState)
162 case USBH_MSC_SEND_CBW:
164 USBH_BulkSendData (pdev,
165 &USBH_MSC_CBWData.CBWArray[0],
166 USBH_MSC_BOT_CBW_PACKET_LENGTH ,
167 MSC_Machine.hc_num_out);
169 USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_SEND_CBW;
170 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SENT_CBW;
174 case USBH_MSC_SENT_CBW:
175 URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_out);
177 if(URB_Status == URB_DONE)
179 BOTStallErrorCount = 0;
180 USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_SENT_CBW;
182 /* If the CBW Pkt is sent successful, then change the state */
183 xferDirection = (USBH_MSC_CBWData.field.CBWFlags & USB_REQ_DIR_MASK);
185 if ( USBH_MSC_CBWData.field.CBWTransferLength != 0 )
187 remainingDataLength = USBH_MSC_CBWData.field.CBWTransferLength ;
188 datapointer = USBH_MSC_BOTXferParam.pRxTxBuff;
190 /* If there is Data Transfer Stage */
191 if (xferDirection == USB_D2H)
193 /* Data Direction is IN */
194 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_DATAIN_STATE;
198 /* Data Direction is OUT */
199 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_DATAOUT_STATE;
204 {/* If there is NO Data Transfer Stage */
205 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE;
209 else if(URB_Status == URB_NOTREADY)
211 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp;
213 else if(URB_Status == URB_STALL)
215 error_direction = USBH_MSC_DIR_OUT;
216 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT;
220 case USBH_MSC_BOT_DATAIN_STATE:
222 URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_in);
223 /* BOT DATA IN stage */
224 if((URB_Status == URB_DONE) ||(USBH_MSC_BOTXferParam.BOTStateBkp != USBH_MSC_BOT_DATAIN_STATE))
226 BOTStallErrorCount = 0;
227 USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_BOT_DATAIN_STATE;
229 if(remainingDataLength > USBH_MSC_MPS_SIZE)
231 USBH_BulkReceiveData (pdev,
234 MSC_Machine.hc_num_in);
236 remainingDataLength -= USBH_MSC_MPS_SIZE;
237 datapointer = datapointer + USBH_MSC_MPS_SIZE;
239 else if ( remainingDataLength == 0)
241 /* If value was 0, and successful transfer, then change the state */
242 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE;
246 USBH_BulkReceiveData (pdev,
248 remainingDataLength ,
249 MSC_Machine.hc_num_in);
251 remainingDataLength = 0; /* Reset this value and keep in same state */
254 else if(URB_Status == URB_STALL)
256 /* This is Data Stage STALL Condition */
258 error_direction = USBH_MSC_DIR_IN;
259 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_IN;
261 /* Refer to USB Mass-Storage Class : BOT (www.usb.org)
262 6.7.2 Host expects to receive data from the device
263 3. On a STALL condition receiving data, then:
264 The host shall accept the data received.
265 The host shall clear the Bulk-In pipe.
266 4. The host shall attempt to receive a CSW.
268 USBH_MSC_BOTXferParam.BOTStateBkp is used to switch to the Original
269 state after the ClearFeature Command is issued.
271 USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE;
277 case USBH_MSC_BOT_DATAOUT_STATE:
278 /* BOT DATA OUT stage */
279 URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_out);
280 if(URB_Status == URB_DONE)
282 BOTStallErrorCount = 0;
283 USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_BOT_DATAOUT_STATE;
284 if(remainingDataLength > USBH_MSC_MPS_SIZE)
286 USBH_BulkSendData (pdev,
289 MSC_Machine.hc_num_out);
290 datapointer = datapointer + USBH_MSC_MPS_SIZE;
291 remainingDataLength = remainingDataLength - USBH_MSC_MPS_SIZE;
293 else if ( remainingDataLength == 0)
295 /* If value was 0, and successful transfer, then change the state */
296 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE;
300 USBH_BulkSendData (pdev,
302 remainingDataLength ,
303 MSC_Machine.hc_num_out);
305 remainingDataLength = 0; /* Reset this value and keep in same state */
309 else if(URB_Status == URB_NOTREADY)
311 USBH_BulkSendData (pdev,
312 (datapointer - USBH_MSC_MPS_SIZE),
314 MSC_Machine.hc_num_out);
317 else if(URB_Status == URB_STALL)
319 error_direction = USBH_MSC_DIR_OUT;
320 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT;
322 /* Refer to USB Mass-Storage Class : BOT (www.usb.org)
323 6.7.3 Ho - Host expects to send data to the device
324 3. On a STALL condition sending data, then:
325 " The host shall clear the Bulk-Out pipe.
326 4. The host shall attempt to receive a CSW.
328 The Above statement will do the clear the Bulk-Out pipe.
329 The Below statement will help in Getting the CSW.
331 USBH_MSC_BOTXferParam.BOTStateBkp is used to switch to the Original
332 state after the ClearFeature Command is issued.
335 USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE;
340 case USBH_MSC_RECEIVE_CSW_STATE:
342 /* NOTE: We cannot reset the BOTStallErrorCount here as it may come from
343 the clearFeature from previous command */
345 USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE;
347 USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray;
348 USBH_MSC_BOTXferParam.DataLength = USBH_MSC_CSW_MAX_LENGTH;
350 for(index = USBH_MSC_CSW_LENGTH; index != 0; index--)
352 USBH_MSC_CSWData.CSWArray[index] = 0;
355 USBH_MSC_CSWData.CSWArray[0] = 0;
357 USBH_BulkReceiveData (pdev,
358 USBH_MSC_BOTXferParam.pRxTxBuff,
359 USBH_MSC_CSW_MAX_LENGTH ,
360 MSC_Machine.hc_num_in);
361 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_DECODE_CSW;
365 case USBH_MSC_DECODE_CSW:
366 URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_in);
368 if(URB_Status == URB_DONE)
370 BOTStallErrorCount = 0;
371 USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE;
373 USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateCurrent ;
375 USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_DecodeCSW(pdev , phost);
377 else if(URB_Status == URB_STALL)
379 error_direction = USBH_MSC_DIR_IN;
380 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_IN;
384 case USBH_MSC_BOT_ERROR_IN:
385 status = USBH_MSC_BOT_Abort(pdev, phost, USBH_MSC_DIR_IN);
386 if (status == USBH_OK)
388 /* Check if the error was due in Both the directions */
389 if (error_direction == USBH_MSC_BOTH_DIR)
390 {/* If Both directions are Needed, Switch to OUT Direction */
391 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT;
395 /* Switch Back to the Original State, In many cases this will be
396 USBH_MSC_RECEIVE_CSW_STATE state */
397 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp;
400 else if (status == USBH_UNRECOVERED_ERROR)
402 /* This means that there is a STALL Error limit, Do Reset Recovery */
403 USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_PHASE_ERROR;
407 case USBH_MSC_BOT_ERROR_OUT:
408 status = USBH_MSC_BOT_Abort(pdev, phost, USBH_MSC_DIR_OUT);
409 if ( status == USBH_OK)
410 { /* Switch Back to the Original State */
411 USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp;
413 else if (status == USBH_UNRECOVERED_ERROR)
415 /* This means that there is a STALL Error limit, Do Reset Recovery */
416 USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_PHASE_ERROR;
427 * @brief USBH_MSC_BOT_Abort
428 * This function manages the different Error handling for STALL
429 * @param direction : IN / OUT
432 USBH_Status USBH_MSC_BOT_Abort(USB_OTG_CORE_HANDLE *pdev,
442 case USBH_MSC_DIR_IN :
443 /* send ClrFeture on Bulk IN endpoint */
444 status = USBH_ClrFeature(pdev,
446 MSC_Machine.MSBulkInEp,
447 MSC_Machine.hc_num_in);
451 case USBH_MSC_DIR_OUT :
452 /*send ClrFeature on Bulk OUT endpoint */
453 status = USBH_ClrFeature(pdev,
455 MSC_Machine.MSBulkOutEp,
456 MSC_Machine.hc_num_out);
463 BOTStallErrorCount++; /* Check Continous Number of times, STALL has Occured */
464 if (BOTStallErrorCount > MAX_BULK_STALL_COUNT_LIMIT )
466 status = USBH_UNRECOVERED_ERROR;
473 * @brief USBH_MSC_DecodeCSW
474 * This function decodes the CSW received by the device and updates the
475 * same to upper layer.
477 * @retval On success USBH_MSC_OK, on failure USBH_MSC_FAIL
479 * Refer to USB Mass-Storage Class : BOT (www.usb.org)
480 * 6.3.1 Valid CSW Conditions :
481 * The host shall consider the CSW valid when:
482 * 1. dCSWSignature is equal to 53425355h
483 * 2. the CSW is 13 (Dh) bytes in length,
484 * 3. dCSWTag matches the dCBWTag from the corresponding CBW.
487 uint8_t USBH_MSC_DecodeCSW(USB_OTG_CORE_HANDLE *pdev , USBH_HOST *phost)
490 uint32_t dataXferCount = 0;
491 status = USBH_MSC_FAIL;
493 if(HCD_IsDeviceConnected(pdev))
495 /*Checking if the transfer length is diffrent than 13*/
496 dataXferCount = HCD_GetXferCnt(pdev, MSC_Machine.hc_num_in);
498 if(dataXferCount != USBH_MSC_CSW_LENGTH)
500 /*(4) Hi > Dn (Host expects to receive data from the device,
501 Device intends to transfer no data)
502 (5) Hi > Di (Host expects to receive data from the device,
503 Device intends to send data to the host)
504 (9) Ho > Dn (Host expects to send data to the device,
505 Device intends to transfer no data)
506 (11) Ho > Do (Host expects to send data to the device,
507 Device intends to receive data from the host)*/
510 status = USBH_MSC_PHASE_ERROR;
513 { /* CSW length is Correct */
515 /* Check validity of the CSW Signature and CSWStatus */
516 if(USBH_MSC_CSWData.field.CSWSignature == USBH_MSC_BOT_CSW_SIGNATURE)
517 {/* Check Condition 1. dCSWSignature is equal to 53425355h */
519 if(USBH_MSC_CSWData.field.CSWTag == USBH_MSC_CBWData.field.CBWTag)
521 /* Check Condition 3. dCSWTag matches the dCBWTag from the
524 if(USBH_MSC_CSWData.field.CSWStatus == USBH_MSC_OK)
526 /* Refer to USB Mass-Storage Class : BOT (www.usb.org)
528 Hn Host expects no data transfers
529 Hi Host expects to receive data from the device
530 Ho Host expects to send data to the device
532 Dn Device intends to transfer no data
533 Di Device intends to send data to the host
534 Do Device intends to receive data from the host
537 (1) Hn = Dn (Host expects no data transfers,
538 Device intends to transfer no data)
539 (6) Hi = Di (Host expects to receive data from the device,
540 Device intends to send data to the host)
541 (12) Ho = Do (Host expects to send data to the device,
542 Device intends to receive data from the host)
546 status = USBH_MSC_OK;
548 else if(USBH_MSC_CSWData.field.CSWStatus == USBH_MSC_FAIL)
550 status = USBH_MSC_FAIL;
553 else if(USBH_MSC_CSWData.field.CSWStatus == USBH_MSC_PHASE_ERROR)
555 /* Refer to USB Mass-Storage Class : BOT (www.usb.org)
557 (2) Hn < Di ( Host expects no data transfers,
558 Device intends to send data to the host)
559 (3) Hn < Do ( Host expects no data transfers,
560 Device intends to receive data from the host)
561 (7) Hi < Di ( Host expects to receive data from the device,
562 Device intends to send data to the host)
563 (8) Hi <> Do ( Host expects to receive data from the device,
564 Device intends to receive data from the host)
565 (10) Ho <> Di (Host expects to send data to the device,
566 Di Device intends to send data to the host)
567 (13) Ho < Do (Host expects to send data to the device,
568 Device intends to receive data from the host)
571 status = USBH_MSC_PHASE_ERROR;
573 } /* CSW Tag Matching is Checked */
574 } /* CSW Signature Correct Checking */
577 /* If the CSW Signature is not valid, We sall return the Phase Error to
578 Upper Layers for Reset Recovery */
580 status = USBH_MSC_PHASE_ERROR;
582 } /* CSW Length Check*/
585 USBH_MSC_BOTXferParam.BOTXferStatus = status;
610 /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/