Nirvana Jay / Mbed 2 deprecated F7DISCO_Demo

Dependencies:   BSP_DISCO_F746NG_patch mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbh_msc_bot.c Source File

usbh_msc_bot.c

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    usbh_msc_bot.c 
00004   * @author  MCD Application Team
00005   * @version V3.2.2
00006   * @date    07-July-2015
00007   * @brief   This file includes the BOT protocol related functions
00008   ******************************************************************************
00009   * @attention
00010   *
00011   * <h2><center>&copy; COPYRIGHT 2015 STMicroelectronics</center></h2>
00012   *
00013   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
00014   * You may not use this file except in compliance with the License.
00015   * You may obtain a copy of the License at:
00016   *
00017   *        http://www.st.com/software_license_agreement_liberty_v2
00018   *
00019   * Unless required by applicable law or agreed to in writing, software 
00020   * distributed under the License is distributed on an "AS IS" BASIS, 
00021   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00022   * See the License for the specific language governing permissions and
00023   * limitations under the License.
00024   *
00025   ******************************************************************************
00026   */ 
00027 
00028 /* Includes ------------------------------------------------------------------*/
00029 #include "usbh_msc_bot.h"
00030 #include "usbh_msc.h"
00031 
00032 /** @addtogroup USBH_LIB
00033 * @{
00034 */
00035 
00036 /** @addtogroup USBH_CLASS
00037 * @{
00038 */
00039 
00040 /** @addtogroup USBH_MSC_CLASS
00041 * @{
00042 */
00043 
00044 /** @defgroup USBH_MSC_BOT 
00045 * @brief    This file includes the mass storage related functions
00046 * @{
00047 */ 
00048 
00049 
00050 /** @defgroup USBH_MSC_BOT_Private_TypesDefinitions
00051 * @{
00052 */ 
00053 /**
00054 * @}
00055 */ 
00056 
00057 /** @defgroup USBH_MSC_BOT_Private_Defines
00058 * @{
00059 */ 
00060 /**
00061 * @}
00062 */ 
00063 
00064 /** @defgroup USBH_MSC_BOT_Private_Macros
00065 * @{
00066 */ 
00067 /**
00068 * @}
00069 */ 
00070 
00071 
00072 /** @defgroup USBH_MSC_BOT_Private_Variables
00073 * @{
00074 */ 
00075 
00076 /**
00077 * @}
00078 */ 
00079 
00080 
00081 /** @defgroup USBH_MSC_BOT_Private_FunctionPrototypes
00082 * @{
00083 */ 
00084 static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t lun, uint8_t dir);
00085 static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost);
00086 /**
00087 * @}
00088 */ 
00089 
00090 
00091 /** @defgroup USBH_MSC_BOT_Exported_Variables
00092 * @{
00093 */ 
00094 /**
00095 * @}
00096 */ 
00097 
00098 
00099 /** @defgroup USBH_MSC_BOT_Private_Functions
00100 * @{
00101 */ 
00102 
00103 /**
00104   * @brief  USBH_MSC_BOT_REQ_Reset 
00105   *         The function the MSC BOT Reset request.
00106   * @param  phost: Host handle
00107   * @retval USBH Status
00108   */
00109 USBH_StatusTypeDef USBH_MSC_BOT_REQ_Reset(USBH_HandleTypeDef *phost)
00110 {
00111   
00112   phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_TYPE_CLASS | \
00113                               USB_REQ_RECIPIENT_INTERFACE;
00114   
00115   phost->Control.setup.b.bRequest = USB_REQ_BOT_RESET;
00116   phost->Control.setup.b.wValue.w = 0;
00117   phost->Control.setup.b.wIndex.w = 0;
00118   phost->Control.setup.b.wLength.w = 0;           
00119   
00120   return USBH_CtlReq(phost, 0 , 0 );  
00121 }
00122 
00123 /**
00124   * @brief  USBH_MSC_BOT_REQ_GetMaxLUN 
00125   *         The function the MSC BOT GetMaxLUN request.
00126   * @param  phost: Host handle
00127   * @param  Maxlun: pointer to Maxlun variable
00128   * @retval USBH Status
00129   */
00130 USBH_StatusTypeDef USBH_MSC_BOT_REQ_GetMaxLUN(USBH_HandleTypeDef *phost, uint8_t *Maxlun)
00131 {
00132   phost->Control.setup.b.bmRequestType = USB_D2H | USB_REQ_TYPE_CLASS | \
00133                               USB_REQ_RECIPIENT_INTERFACE;
00134   
00135   phost->Control.setup.b.bRequest = USB_REQ_GET_MAX_LUN;
00136   phost->Control.setup.b.wValue.w = 0;
00137   phost->Control.setup.b.wIndex.w = 0;
00138   phost->Control.setup.b.wLength.w = 1;           
00139   
00140   return USBH_CtlReq(phost, Maxlun , 1 ); 
00141 }
00142 
00143 
00144 
00145 /**
00146   * @brief  USBH_MSC_BOT_Init 
00147   *         The function Initializes the BOT protocol.
00148   * @param  phost: Host handle
00149   * @retval USBH Status
00150   */
00151 USBH_StatusTypeDef USBH_MSC_BOT_Init(USBH_HandleTypeDef *phost)
00152 {
00153   
00154   MSC_HandleTypeDef *MSC_Handle =  (MSC_HandleTypeDef *) phost->pActiveClass->pData;
00155   
00156   MSC_Handle->hbot.cbw.field.Signature = BOT_CBW_SIGNATURE;
00157   MSC_Handle->hbot.cbw.field.Tag = BOT_CBW_TAG;
00158   MSC_Handle->hbot.state = BOT_SEND_CBW;    
00159   MSC_Handle->hbot.cmd_state = BOT_CMD_SEND;   
00160   
00161   return USBH_OK;
00162 }
00163 
00164 
00165 
00166 /**
00167   * @brief  USBH_MSC_BOT_Process 
00168   *         The function handle the BOT protocol.
00169   * @param  phost: Host handle
00170   * @param  lun: Logical Unit Number
00171   * @retval USBH Status
00172   */
00173 USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun)
00174 {
00175   USBH_StatusTypeDef   status = USBH_BUSY;
00176   USBH_StatusTypeDef   error  = USBH_BUSY;  
00177   BOT_CSWStatusTypeDef CSW_Status = BOT_CSW_CMD_FAILED;
00178   USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
00179   MSC_HandleTypeDef *MSC_Handle =  (MSC_HandleTypeDef *) phost->pActiveClass->pData;
00180   uint8_t toggle = 0;
00181   
00182   switch (MSC_Handle->hbot.state)
00183   {
00184   case BOT_SEND_CBW:
00185     MSC_Handle->hbot.cbw.field.LUN = lun;
00186     MSC_Handle->hbot.state = BOT_SEND_CBW_WAIT;    
00187     USBH_BulkSendData (phost,
00188                        MSC_Handle->hbot.cbw.data, 
00189                        BOT_CBW_LENGTH, 
00190                        MSC_Handle->OutPipe,
00191                        1);
00192     
00193     break;
00194     
00195   case BOT_SEND_CBW_WAIT:
00196     
00197     URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe); 
00198     
00199     if(URB_Status == USBH_URB_DONE)
00200     { 
00201       if ( MSC_Handle->hbot.cbw.field.DataTransferLength != 0 )
00202       {
00203         /* If there is Data Transfer Stage */
00204         if (((MSC_Handle->hbot.cbw.field.Flags) & USB_REQ_DIR_MASK) == USB_D2H)
00205         {
00206           /* Data Direction is IN */
00207           MSC_Handle->hbot.state = BOT_DATA_IN;
00208         }
00209         else
00210         {
00211           /* Data Direction is OUT */
00212           MSC_Handle->hbot.state = BOT_DATA_OUT;
00213         } 
00214       }
00215       
00216       else
00217       {/* If there is NO Data Transfer Stage */
00218         MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
00219       }
00220 #if (USBH_USE_OS == 1)
00221     osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
00222 #endif   
00223     
00224     }   
00225     else if(URB_Status == USBH_URB_NOTREADY)
00226     {
00227       /* Re-send CBW */
00228       MSC_Handle->hbot.state = BOT_SEND_CBW;
00229 #if (USBH_USE_OS == 1)
00230     osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
00231 #endif       
00232     }     
00233     else if(URB_Status == USBH_URB_STALL)
00234     {
00235       MSC_Handle->hbot.state  = BOT_ERROR_OUT;
00236 #if (USBH_USE_OS == 1)
00237     osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
00238 #endif       
00239     }
00240     break;
00241     
00242   case BOT_DATA_IN:   
00243     /* Send first packet */        
00244     USBH_BulkReceiveData (phost,
00245                           MSC_Handle->hbot.pbuf, 
00246                           MSC_Handle->InEpSize , 
00247                           MSC_Handle->InPipe);
00248     
00249     MSC_Handle->hbot.state  = BOT_DATA_IN_WAIT;
00250     
00251     break;   
00252     
00253   case BOT_DATA_IN_WAIT:  
00254     
00255     URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe); 
00256     
00257     if(URB_Status == USBH_URB_DONE) 
00258     {
00259       /* Adjust Data pointer and data length */
00260       if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->InEpSize)
00261       {
00262           MSC_Handle->hbot.pbuf += MSC_Handle->InEpSize;
00263           MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->InEpSize;  
00264       }
00265       else
00266       {
00267         MSC_Handle->hbot.cbw.field.DataTransferLength = 0;
00268       }
00269         
00270       /* More Data To be Received */
00271       if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0)
00272       {
00273         /* Send next packet */        
00274         USBH_BulkReceiveData (phost,
00275                               MSC_Handle->hbot.pbuf, 
00276                               MSC_Handle->InEpSize , 
00277                               MSC_Handle->InPipe);
00278         
00279       }
00280       else
00281       {
00282         /* If value was 0, and successful transfer, then change the state */
00283         MSC_Handle->hbot.state  = BOT_RECEIVE_CSW;
00284 #if (USBH_USE_OS == 1)
00285         osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
00286 #endif 
00287       }
00288     }
00289     else if(URB_Status == USBH_URB_STALL)
00290     {
00291       /* This is Data IN Stage STALL Condition */
00292       MSC_Handle->hbot.state  = BOT_ERROR_IN;
00293       
00294       /* Refer to USB Mass-Storage Class : BOT (www.usb.org) 
00295       6.7.2 Host expects to receive data from the device
00296       3. On a STALL condition receiving data, then:
00297       The host shall accept the data received.
00298       The host shall clear the Bulk-In pipe.
00299       4. The host shall attempt to receive a CSW.*/
00300       
00301 #if (USBH_USE_OS == 1)
00302     osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
00303 #endif       
00304     }     
00305     break;  
00306     
00307   case BOT_DATA_OUT:
00308     
00309     USBH_BulkSendData (phost,
00310                        MSC_Handle->hbot.pbuf, 
00311                        MSC_Handle->OutEpSize , 
00312                        MSC_Handle->OutPipe,
00313                        1);
00314     
00315     
00316     MSC_Handle->hbot.state  = BOT_DATA_OUT_WAIT;
00317     break;
00318     
00319   case BOT_DATA_OUT_WAIT:
00320     URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe);     
00321     
00322     if(URB_Status == USBH_URB_DONE)
00323     {
00324       /* Adjust Data pointer and data length */
00325       if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->OutEpSize)
00326       {
00327           MSC_Handle->hbot.pbuf += MSC_Handle->OutEpSize;
00328           MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->OutEpSize; 
00329       }
00330       else
00331       {
00332         MSC_Handle->hbot.cbw.field.DataTransferLength = 0;
00333       } 
00334       
00335       /* More Data To be Sent */
00336       if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0)
00337       {
00338         USBH_BulkSendData (phost,
00339                            MSC_Handle->hbot.pbuf, 
00340                            MSC_Handle->OutEpSize , 
00341                            MSC_Handle->OutPipe,
00342                            1);
00343       }
00344       else
00345       {
00346         /* If value was 0, and successful transfer, then change the state */
00347         MSC_Handle->hbot.state  = BOT_RECEIVE_CSW;
00348       }  
00349 #if (USBH_USE_OS == 1)
00350     osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
00351 #endif       
00352     }
00353     
00354     else if(URB_Status == USBH_URB_NOTREADY)
00355     {
00356       /* Resend same data */      
00357       MSC_Handle->hbot.state  = BOT_DATA_OUT;
00358 #if (USBH_USE_OS == 1)
00359     osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
00360 #endif       
00361     }
00362     
00363     else if(URB_Status == USBH_URB_STALL)
00364     {
00365       MSC_Handle->hbot.state  = BOT_ERROR_OUT;
00366       
00367       /* Refer to USB Mass-Storage Class : BOT (www.usb.org) 
00368       6.7.3 Ho - Host expects to send data to the device
00369       3. On a STALL condition sending data, then:
00370       " The host shall clear the Bulk-Out pipe.
00371       4. The host shall attempt to receive a CSW.
00372       */      
00373 #if (USBH_USE_OS == 1)
00374       osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
00375 #endif       
00376     }
00377     break;
00378     
00379   case BOT_RECEIVE_CSW:
00380     
00381     USBH_BulkReceiveData (phost,
00382                           MSC_Handle->hbot.csw.data, 
00383                           BOT_CSW_LENGTH , 
00384                           MSC_Handle->InPipe);
00385     
00386     MSC_Handle->hbot.state  = BOT_RECEIVE_CSW_WAIT;
00387     break;
00388     
00389   case BOT_RECEIVE_CSW_WAIT:
00390     
00391     URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe); 
00392     
00393     /* Decode CSW */
00394     if(URB_Status == USBH_URB_DONE)
00395     {
00396       MSC_Handle->hbot.state = BOT_SEND_CBW;    
00397       MSC_Handle->hbot.cmd_state = BOT_CMD_SEND;        
00398       CSW_Status = USBH_MSC_DecodeCSW(phost);
00399       
00400       if(CSW_Status == BOT_CSW_CMD_PASSED)
00401       {
00402         status = USBH_OK;
00403       }
00404       else
00405       {
00406         status = USBH_FAIL;
00407       }
00408 #if (USBH_USE_OS == 1)
00409       osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
00410 #endif       
00411     }
00412     else if(URB_Status == USBH_URB_STALL)     
00413     {
00414       MSC_Handle->hbot.state  = BOT_ERROR_IN;
00415 #if (USBH_USE_OS == 1)
00416       osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
00417 #endif       
00418     }
00419     break;
00420     
00421   case BOT_ERROR_IN: 
00422     error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_IN);
00423     
00424     if (error == USBH_OK)
00425     {
00426       MSC_Handle->hbot.state = BOT_RECEIVE_CSW;
00427     }
00428     else if (error == USBH_UNRECOVERED_ERROR)
00429     {
00430       /* This means that there is a STALL Error limit, Do Reset Recovery */
00431       MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR;
00432     }
00433     break;
00434     
00435   case BOT_ERROR_OUT: 
00436     error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_OUT);
00437     
00438     if ( error == USBH_OK)
00439     { 
00440       
00441       toggle = USBH_LL_GetToggle(phost, MSC_Handle->OutPipe); 
00442       USBH_LL_SetToggle(phost, MSC_Handle->OutPipe, 1- toggle);   
00443       USBH_LL_SetToggle(phost, MSC_Handle->InPipe, 0);  
00444       MSC_Handle->hbot.state = BOT_ERROR_IN;        
00445     }
00446     else if (error == USBH_UNRECOVERED_ERROR)
00447     {
00448       MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR;
00449     }
00450     break;
00451     
00452     
00453   case BOT_UNRECOVERED_ERROR: 
00454     status = USBH_MSC_BOT_REQ_Reset(phost);
00455     if ( status == USBH_OK)
00456     {
00457       MSC_Handle->hbot.state = BOT_SEND_CBW; 
00458     }
00459     break;
00460     
00461   default:      
00462     break;
00463   }
00464   return status;
00465 }
00466 
00467 /**
00468   * @brief  USBH_MSC_BOT_Abort 
00469   *         The function handle the BOT Abort process.
00470   * @param  phost: Host handle
00471   * @param  lun: Logical Unit Number
00472   * @param  dir: direction (0: out / 1 : in)
00473   * @retval USBH Status
00474   */
00475 static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t lun, uint8_t dir)
00476 {
00477   USBH_StatusTypeDef status = USBH_FAIL;
00478   MSC_HandleTypeDef *MSC_Handle =  (MSC_HandleTypeDef *) phost->pActiveClass->pData;
00479   
00480   switch (dir)
00481   {
00482   case BOT_DIR_IN :
00483     /* send ClrFeture on Bulk IN endpoint */
00484     status = USBH_ClrFeature(phost, MSC_Handle->InEp);
00485     
00486     break;
00487     
00488   case BOT_DIR_OUT :
00489     /*send ClrFeature on Bulk OUT endpoint */
00490     status = USBH_ClrFeature(phost, MSC_Handle->OutEp);
00491     break;
00492     
00493   default:
00494     break;
00495   }
00496   return status;
00497 }
00498 
00499 /**
00500   * @brief  USBH_MSC_BOT_DecodeCSW
00501   *         This function decodes the CSW received by the device and updates the
00502   *         same to upper layer.
00503   * @param  phost: Host handle
00504   * @retval USBH Status
00505   * @notes
00506   *     Refer to USB Mass-Storage Class : BOT (www.usb.org)
00507   *    6.3.1 Valid CSW Conditions :
00508   *     The host shall consider the CSW valid when:
00509   *     1. dCSWSignature is equal to 53425355h
00510   *     2. the CSW is 13 (Dh) bytes in length,
00511   *     3. dCSWTag matches the dCBWTag from the corresponding CBW.
00512   */
00513 
00514 static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost)
00515 {
00516   MSC_HandleTypeDef *MSC_Handle =  (MSC_HandleTypeDef *) phost->pActiveClass->pData;
00517   BOT_CSWStatusTypeDef status = BOT_CSW_CMD_FAILED;
00518   
00519     /*Checking if the transfer length is different than 13*/    
00520     if(USBH_LL_GetLastXferSize(phost, MSC_Handle->InPipe) != BOT_CSW_LENGTH)
00521     {
00522       /*(4) Hi > Dn (Host expects to receive data from the device,
00523       Device intends to transfer no data)
00524       (5) Hi > Di (Host expects to receive data from the device,
00525       Device intends to send data to the host)
00526       (9) Ho > Dn (Host expects to send data to the device,
00527       Device intends to transfer no data)
00528       (11) Ho > Do  (Host expects to send data to the device,
00529       Device intends to receive data from the host)*/
00530       
00531       
00532       status = BOT_CSW_PHASE_ERROR;
00533     }
00534     else
00535     { /* CSW length is Correct */
00536       
00537       /* Check validity of the CSW Signature and CSWStatus */
00538       if(MSC_Handle->hbot.csw.field.Signature == BOT_CSW_SIGNATURE)
00539       {/* Check Condition 1. dCSWSignature is equal to 53425355h */
00540         
00541         if(MSC_Handle->hbot.csw.field.Tag == MSC_Handle->hbot.cbw.field.Tag)
00542         {
00543           /* Check Condition 3. dCSWTag matches the dCBWTag from the 
00544           corresponding CBW */
00545 
00546           if(MSC_Handle->hbot.csw.field.Status == 0) 
00547           {
00548             /* Refer to USB Mass-Storage Class : BOT (www.usb.org) 
00549             
00550             Hn Host expects no data transfers
00551             Hi Host expects to receive data from the device
00552             Ho Host expects to send data to the device
00553             
00554             Dn Device intends to transfer no data
00555             Di Device intends to send data to the host
00556             Do Device intends to receive data from the host
00557             
00558             Section 6.7 
00559             (1) Hn = Dn (Host expects no data transfers,
00560             Device intends to transfer no data)
00561             (6) Hi = Di (Host expects to receive data from the device,
00562             Device intends to send data to the host)
00563             (12) Ho = Do (Host expects to send data to the device, 
00564             Device intends to receive data from the host)
00565             
00566             */
00567             
00568             status = BOT_CSW_CMD_PASSED;
00569           }
00570           else if(MSC_Handle->hbot.csw.field.Status == 1)
00571           {
00572             status = BOT_CSW_CMD_FAILED;
00573           }
00574           
00575           else if(MSC_Handle->hbot.csw.field.Status == 2)
00576           { 
00577             /* Refer to USB Mass-Storage Class : BOT (www.usb.org) 
00578             Section 6.7 
00579             (2) Hn < Di ( Host expects no data transfers, 
00580             Device intends to send data to the host)
00581             (3) Hn < Do ( Host expects no data transfers, 
00582             Device intends to receive data from the host)
00583             (7) Hi < Di ( Host expects to receive data from the device, 
00584             Device intends to send data to the host)
00585             (8) Hi <> Do ( Host expects to receive data from the device, 
00586             Device intends to receive data from the host)
00587             (10) Ho <> Di (Host expects to send data to the device,
00588             Di Device intends to send data to the host)
00589             (13) Ho < Do (Host expects to send data to the device, 
00590             Device intends to receive data from the host)
00591             */
00592             
00593             status = BOT_CSW_PHASE_ERROR;
00594           }
00595         } /* CSW Tag Matching is Checked  */
00596       } /* CSW Signature Correct Checking */
00597       else
00598       {
00599         /* If the CSW Signature is not valid, We sall return the Phase Error to
00600         Upper Layers for Reset Recovery */
00601         
00602         status = BOT_CSW_PHASE_ERROR;
00603       }
00604     } /* CSW Length Check*/
00605     
00606   return status;
00607 }
00608 
00609 
00610 /**
00611 * @}
00612 */ 
00613 
00614 /**
00615 * @}
00616 */ 
00617 
00618 /**
00619 * @}
00620 */
00621 
00622 /**
00623 * @}
00624 */ 
00625 
00626 /**
00627 * @}
00628 */
00629 
00630 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
00631 
00632 
00633