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_ctlreq.c Source File

usbh_ctlreq.c

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    usbh_ctlreq.c 
00004   * @author  MCD Application Team
00005   * @version V3.2.2
00006   * @date    07-July-2015
00007   * @brief   This file implements the control requests for device enumeration
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 /* Includes ------------------------------------------------------------------*/
00028 
00029 #include "usbh_ctlreq.h"
00030 
00031 /** @addtogroup USBH_LIB
00032 * @{
00033 */
00034 
00035 /** @addtogroup USBH_LIB_CORE
00036 * @{
00037 */
00038 
00039 /** @defgroup USBH_CTLREQ 
00040 * @brief This file implements the standard requests for device enumeration
00041 * @{
00042 */
00043 
00044 
00045 /** @defgroup USBH_CTLREQ_Private_Defines
00046 * @{
00047 */ 
00048 /**
00049 * @}
00050 */ 
00051 
00052 
00053 /** @defgroup USBH_CTLREQ_Private_TypesDefinitions
00054 * @{
00055 */ 
00056 /**
00057 * @}
00058 */ 
00059 
00060 
00061 
00062 /** @defgroup USBH_CTLREQ_Private_Macros
00063 * @{
00064 */ 
00065 /**
00066 * @}
00067 */ 
00068 
00069 
00070 /** @defgroup USBH_CTLREQ_Private_Variables
00071 * @{
00072 */
00073 /**
00074 * @}
00075 */ 
00076 
00077 /** @defgroup USBH_CTLREQ_Private_FunctionPrototypes
00078 * @{
00079 */
00080 static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost);
00081 
00082 static void USBH_ParseDevDesc (USBH_DevDescTypeDef* , uint8_t *buf, uint16_t length);
00083 
00084 static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc,
00085                                uint8_t *buf, 
00086                                uint16_t length);
00087 
00088 
00089 static void USBH_ParseEPDesc (USBH_EpDescTypeDef  *ep_descriptor, uint8_t *buf);
00090 static void USBH_ParseStringDesc (uint8_t* psrc, uint8_t* pdest, uint16_t length);
00091 static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef  *if_descriptor, uint8_t *buf);
00092 
00093 
00094 /**
00095 * @}
00096 */ 
00097 
00098 
00099 /** @defgroup USBH_CTLREQ_Private_Functions
00100 * @{
00101 */ 
00102 
00103 
00104 /**
00105   * @brief  USBH_Get_DevDesc
00106   *         Issue Get Device Descriptor command to the device. Once the response 
00107   *         received, it parses the device descriptor and updates the status.
00108   * @param  phost: Host Handle
00109   * @param  length: Length of the descriptor
00110   * @retval USBH Status
00111   */
00112 USBH_StatusTypeDef USBH_Get_DevDesc(USBH_HandleTypeDef *phost, uint8_t length)
00113 {
00114   USBH_StatusTypeDef status;
00115   
00116   if((status = USBH_GetDescriptor(phost,
00117                                   USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,                          
00118                                   USB_DESC_DEVICE, 
00119                                   phost->device.Data,
00120                                   length)) == USBH_OK)
00121   {
00122     /* Commands successfully sent and Response Received */       
00123     USBH_ParseDevDesc(&phost->device.DevDesc, phost->device.Data, length);
00124   }
00125   return status;      
00126 }
00127 
00128 /**
00129   * @brief  USBH_Get_CfgDesc
00130   *         Issues Configuration Descriptor to the device. Once the response 
00131   *         received, it parses the configuration descriptor and updates the 
00132   *         status.
00133   * @param  phost: Host Handle
00134   * @param  length: Length of the descriptor
00135   * @retval USBH Status
00136   */
00137 USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost,                      
00138                              uint16_t length)
00139 
00140 {
00141   USBH_StatusTypeDef status;
00142   uint8_t *pData;
00143 #if (USBH_KEEP_CFG_DESCRIPTOR == 1)  
00144   pData = phost->device.CfgDesc_Raw;
00145 #else
00146   pData = phost->device.Data;
00147 #endif  
00148   if((status = USBH_GetDescriptor(phost,
00149                                   USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,                          
00150                                   USB_DESC_CONFIGURATION, 
00151                                   pData,
00152                                   length)) == USBH_OK)
00153   {
00154     
00155     /* Commands successfully sent and Response Received  */       
00156     USBH_ParseCfgDesc (&phost->device.CfgDesc,
00157                        pData,
00158                        length); 
00159     
00160   }
00161   return status;
00162 }
00163 
00164 
00165 /**
00166   * @brief  USBH_Get_StringDesc
00167   *         Issues string Descriptor command to the device. Once the response 
00168   *         received, it parses the string descriptor and updates the status.
00169   * @param  phost: Host Handle
00170   * @param  string_index: String index for the descriptor
00171   * @param  buff: Buffer address for the descriptor
00172   * @param  length: Length of the descriptor
00173   * @retval USBH Status
00174   */
00175 USBH_StatusTypeDef USBH_Get_StringDesc(USBH_HandleTypeDef *phost,
00176                                 uint8_t string_index, 
00177                                 uint8_t *buff, 
00178                                 uint16_t length)
00179 {
00180   USBH_StatusTypeDef status;
00181   if((status = USBH_GetDescriptor(phost,
00182                                   USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,                                    
00183                                   USB_DESC_STRING | string_index, 
00184                                   phost->device.Data,
00185                                   length)) == USBH_OK)
00186   {
00187     /* Commands successfully sent and Response Received  */       
00188     USBH_ParseStringDesc(phost->device.Data,buff, length);    
00189   }
00190   return status;
00191 }
00192 
00193 /**
00194   * @brief  USBH_GetDescriptor
00195   *         Issues Descriptor command to the device. Once the response received,
00196   *         it parses the descriptor and updates the status.
00197   * @param  phost: Host Handle
00198   * @param  req_type: Descriptor type
00199   * @param  value_idx: Value for the GetDescriptr request
00200   * @param  buff: Buffer to store the descriptor
00201   * @param  length: Length of the descriptor
00202   * @retval USBH Status
00203   */
00204 USBH_StatusTypeDef USBH_GetDescriptor(USBH_HandleTypeDef *phost,                          
00205                                uint8_t  req_type,
00206                                uint16_t value_idx, 
00207                                uint8_t* buff, 
00208                                uint16_t length )
00209 { 
00210   if(phost->RequestState == CMD_SEND)
00211   {
00212     phost->Control.setup.b.bmRequestType = USB_D2H | req_type;
00213     phost->Control.setup.b.bRequest = USB_REQ_GET_DESCRIPTOR;
00214     phost->Control.setup.b.wValue.w = value_idx;
00215     
00216     if ((value_idx & 0xff00) == USB_DESC_STRING)
00217     {
00218       phost->Control.setup.b.wIndex.w = 0x0409;
00219     }
00220     else
00221     {
00222       phost->Control.setup.b.wIndex.w = 0;
00223     }
00224     phost->Control.setup.b.wLength.w = length; 
00225   }
00226   return USBH_CtlReq(phost, buff , length );     
00227 }
00228 
00229 /**
00230   * @brief  USBH_SetAddress
00231   *         This command sets the address to the connected device
00232   * @param  phost: Host Handle
00233   * @param  DeviceAddress: Device address to assign
00234   * @retval USBH Status
00235   */
00236 USBH_StatusTypeDef USBH_SetAddress(USBH_HandleTypeDef *phost, 
00237                                    uint8_t DeviceAddress)
00238 {
00239   if(phost->RequestState == CMD_SEND)
00240   {
00241     phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | \
00242       USB_REQ_TYPE_STANDARD;
00243     
00244     phost->Control.setup.b.bRequest = USB_REQ_SET_ADDRESS;
00245     
00246     phost->Control.setup.b.wValue.w = (uint16_t)DeviceAddress;
00247     phost->Control.setup.b.wIndex.w = 0;
00248     phost->Control.setup.b.wLength.w = 0;
00249   }
00250   return USBH_CtlReq(phost, 0 , 0 );
00251 }
00252 
00253 /**
00254   * @brief  USBH_SetCfg
00255   *         The command sets the configuration value to the connected device
00256   * @param  phost: Host Handle
00257   * @param  cfg_idx: Configuration value
00258   * @retval USBH Status
00259   */
00260 USBH_StatusTypeDef USBH_SetCfg(USBH_HandleTypeDef *phost, 
00261                                uint16_t cfg_idx)
00262 {
00263   if(phost->RequestState == CMD_SEND)
00264   {
00265     phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE |\
00266       USB_REQ_TYPE_STANDARD;
00267     phost->Control.setup.b.bRequest = USB_REQ_SET_CONFIGURATION;
00268     phost->Control.setup.b.wValue.w = cfg_idx;
00269     phost->Control.setup.b.wIndex.w = 0;
00270     phost->Control.setup.b.wLength.w = 0; 
00271   }
00272   
00273   return USBH_CtlReq(phost, 0 , 0 );      
00274 }
00275 
00276 /**
00277   * @brief  USBH_SetInterface
00278   *         The command sets the Interface value to the connected device
00279   * @param  phost: Host Handle
00280   * @param  altSetting: Interface value
00281   * @retval USBH Status
00282   */
00283 USBH_StatusTypeDef USBH_SetInterface(USBH_HandleTypeDef *phost, 
00284                         uint8_t ep_num, uint8_t altSetting)
00285 {
00286   
00287   if(phost->RequestState == CMD_SEND)
00288   {
00289     phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | \
00290       USB_REQ_TYPE_STANDARD;
00291     
00292     phost->Control.setup.b.bRequest = USB_REQ_SET_INTERFACE;
00293     phost->Control.setup.b.wValue.w = altSetting;
00294     phost->Control.setup.b.wIndex.w = ep_num;
00295     phost->Control.setup.b.wLength.w = 0;           
00296   }
00297   return USBH_CtlReq(phost, 0 , 0 );     
00298 }
00299 
00300 /**
00301   * @brief  USBH_ClrFeature
00302   *         This request is used to clear or disable a specific feature.
00303   * @param  phost: Host Handle
00304   * @param  ep_num: endpoint number 
00305   * @param  hc_num: Host channel number 
00306   * @retval USBH Status
00307   */
00308 USBH_StatusTypeDef USBH_ClrFeature(USBH_HandleTypeDef *phost,
00309                                    uint8_t ep_num) 
00310 {
00311   if(phost->RequestState == CMD_SEND)
00312   {
00313     phost->Control.setup.b.bmRequestType = USB_H2D | 
00314       USB_REQ_RECIPIENT_ENDPOINT |
00315         USB_REQ_TYPE_STANDARD;
00316     
00317     phost->Control.setup.b.bRequest = USB_REQ_CLEAR_FEATURE;
00318     phost->Control.setup.b.wValue.w = FEATURE_SELECTOR_ENDPOINT;
00319     phost->Control.setup.b.wIndex.w = ep_num;
00320     phost->Control.setup.b.wLength.w = 0;           
00321   }
00322   return USBH_CtlReq(phost, 0 , 0 );   
00323 }
00324 
00325 /**
00326   * @brief  USBH_ParseDevDesc 
00327   *         This function Parses the device descriptor
00328   * @param  dev_desc: device_descriptor destination address 
00329   * @param  buf: Buffer where the source descriptor is available
00330   * @param  length: Length of the descriptor
00331   * @retval None
00332   */
00333 static void  USBH_ParseDevDesc (USBH_DevDescTypeDef* dev_desc,
00334                                 uint8_t *buf, 
00335                                 uint16_t length)
00336 {
00337   dev_desc->bLength            = *(uint8_t  *) (buf +  0);
00338   dev_desc->bDescriptorType    = *(uint8_t  *) (buf +  1);
00339   dev_desc->bcdUSB             = LE16 (buf +  2);
00340   dev_desc->bDeviceClass       = *(uint8_t  *) (buf +  4);
00341   dev_desc->bDeviceSubClass    = *(uint8_t  *) (buf +  5);
00342   dev_desc->bDeviceProtocol    = *(uint8_t  *) (buf +  6);
00343   dev_desc->bMaxPacketSize     = *(uint8_t  *) (buf +  7);
00344   
00345   if (length > 8)
00346   { /* For 1st time after device connection, Host may issue only 8 bytes for 
00347     Device Descriptor Length  */
00348     dev_desc->idVendor           = LE16 (buf +  8);
00349     dev_desc->idProduct          = LE16 (buf + 10);
00350     dev_desc->bcdDevice          = LE16 (buf + 12);
00351     dev_desc->iManufacturer      = *(uint8_t  *) (buf + 14);
00352     dev_desc->iProduct           = *(uint8_t  *) (buf + 15);
00353     dev_desc->iSerialNumber      = *(uint8_t  *) (buf + 16);
00354     dev_desc->bNumConfigurations = *(uint8_t  *) (buf + 17);
00355   }
00356 }
00357 
00358 /**
00359   * @brief  USBH_ParseCfgDesc 
00360   *         This function Parses the configuration descriptor
00361   * @param  cfg_desc: Configuration Descriptor address
00362   * @param  buf: Buffer where the source descriptor is available
00363   * @param  length: Length of the descriptor
00364   * @retval None
00365   */
00366 static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc,
00367                                uint8_t *buf, 
00368                                uint16_t length)
00369 {  
00370   USBH_InterfaceDescTypeDef    *pif ;
00371   USBH_EpDescTypeDef           *pep;  
00372   USBH_DescHeader_t             *pdesc = (USBH_DescHeader_t *)buf;
00373   uint16_t                      ptr;
00374   int8_t                        if_ix = 0;
00375   int8_t                        ep_ix = 0;  
00376   
00377   pdesc   = (USBH_DescHeader_t *)buf;
00378   
00379   /* Parse configuration descriptor */
00380   cfg_desc->bLength             = *(uint8_t  *) (buf + 0);
00381   cfg_desc->bDescriptorType     = *(uint8_t  *) (buf + 1);
00382   cfg_desc->wTotalLength        = LE16 (buf + 2);
00383   cfg_desc->bNumInterfaces      = *(uint8_t  *) (buf + 4);
00384   cfg_desc->bConfigurationValue = *(uint8_t  *) (buf + 5);
00385   cfg_desc->iConfiguration      = *(uint8_t  *) (buf + 6);
00386   cfg_desc->bmAttributes        = *(uint8_t  *) (buf + 7);
00387   cfg_desc->bMaxPower           = *(uint8_t  *) (buf + 8);    
00388   
00389   
00390   if (length > USB_CONFIGURATION_DESC_SIZE)
00391   {
00392     ptr = USB_LEN_CFG_DESC;
00393     pif = (USBH_InterfaceDescTypeDef *)0;
00394     
00395     
00396     while ((if_ix < USBH_MAX_NUM_INTERFACES ) && (ptr < cfg_desc->wTotalLength))
00397     {
00398       pdesc = USBH_GetNextDesc((uint8_t *)pdesc, &ptr);
00399       if (pdesc->bDescriptorType   == USB_DESC_TYPE_INTERFACE) 
00400       {
00401         pif = &cfg_desc->Itf_Desc[if_ix];
00402         USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc);            
00403         
00404         ep_ix = 0;
00405         pep = (USBH_EpDescTypeDef *)0;        
00406         while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength))
00407         {
00408           pdesc = USBH_GetNextDesc((uint8_t*) pdesc, &ptr);
00409           if (pdesc->bDescriptorType   == USB_DESC_TYPE_ENDPOINT) 
00410           {  
00411             pep = &cfg_desc->Itf_Desc[if_ix].Ep_Desc[ep_ix];
00412             USBH_ParseEPDesc (pep, (uint8_t *)pdesc);
00413             ep_ix++;
00414           }
00415         }
00416         if_ix++;
00417       }
00418     }
00419   }  
00420 }
00421 
00422 
00423 
00424 /**
00425   * @brief  USBH_ParseInterfaceDesc 
00426   *         This function Parses the interface descriptor
00427   * @param  if_descriptor : Interface descriptor destination
00428   * @param  buf: Buffer where the descriptor data is available
00429   * @retval None
00430   */
00431 static void  USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, 
00432                                       uint8_t *buf)
00433 {
00434   if_descriptor->bLength            = *(uint8_t  *) (buf + 0);
00435   if_descriptor->bDescriptorType    = *(uint8_t  *) (buf + 1);
00436   if_descriptor->bInterfaceNumber   = *(uint8_t  *) (buf + 2);
00437   if_descriptor->bAlternateSetting  = *(uint8_t  *) (buf + 3);
00438   if_descriptor->bNumEndpoints      = *(uint8_t  *) (buf + 4);
00439   if_descriptor->bInterfaceClass    = *(uint8_t  *) (buf + 5);
00440   if_descriptor->bInterfaceSubClass = *(uint8_t  *) (buf + 6);
00441   if_descriptor->bInterfaceProtocol = *(uint8_t  *) (buf + 7);
00442   if_descriptor->iInterface         = *(uint8_t  *) (buf + 8);
00443 }
00444 
00445 /**
00446   * @brief  USBH_ParseEPDesc 
00447   *         This function Parses the endpoint descriptor
00448   * @param  ep_descriptor: Endpoint descriptor destination address
00449   * @param  buf: Buffer where the parsed descriptor stored
00450   * @retval None
00451   */
00452 static void  USBH_ParseEPDesc (USBH_EpDescTypeDef  *ep_descriptor, 
00453                                uint8_t *buf)
00454 {
00455   
00456   ep_descriptor->bLength          = *(uint8_t  *) (buf + 0);
00457   ep_descriptor->bDescriptorType  = *(uint8_t  *) (buf + 1);
00458   ep_descriptor->bEndpointAddress = *(uint8_t  *) (buf + 2);
00459   ep_descriptor->bmAttributes     = *(uint8_t  *) (buf + 3);
00460   ep_descriptor->wMaxPacketSize   = LE16 (buf + 4);
00461   ep_descriptor->bInterval        = *(uint8_t  *) (buf + 6);
00462 }
00463 
00464 /**
00465   * @brief  USBH_ParseStringDesc 
00466   *         This function Parses the string descriptor
00467   * @param  psrc: Source pointer containing the descriptor data
00468   * @param  pdest: Destination address pointer
00469   * @param  length: Length of the descriptor
00470   * @retval None
00471   */
00472 static void USBH_ParseStringDesc (uint8_t* psrc, 
00473                                   uint8_t* pdest, 
00474                                   uint16_t length)
00475 {
00476   uint16_t strlength;
00477   uint16_t idx;
00478   
00479   /* The UNICODE string descriptor is not NULL-terminated. The string length is
00480   computed by substracting two from the value of the first byte of the descriptor.
00481   */
00482   
00483   /* Check which is lower size, the Size of string or the length of bytes read 
00484   from the device */
00485   
00486   if ( psrc[1] == USB_DESC_TYPE_STRING)
00487   { /* Make sure the Descriptor is String Type */
00488     
00489     /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */      
00490     strlength = ( ( (psrc[0]-2) <= length) ? (psrc[0]-2) :length); 
00491     psrc += 2; /* Adjust the offset ignoring the String Len and Descriptor type */
00492     
00493     for (idx = 0; idx < strlength; idx+=2 )
00494     {/* Copy Only the string and ignore the UNICODE ID, hence add the src */
00495       *pdest =  psrc[idx];
00496       pdest++;
00497     }  
00498     *pdest = 0; /* mark end of string */  
00499   }
00500 }
00501 
00502 /**
00503   * @brief  USBH_GetNextDesc 
00504   *         This function return the next descriptor header
00505   * @param  buf: Buffer where the cfg descriptor is available
00506   * @param  ptr: data pointer inside the cfg descriptor
00507   * @retval next header
00508   */
00509 USBH_DescHeader_t  *USBH_GetNextDesc (uint8_t   *pbuf, uint16_t  *ptr)
00510 {
00511   USBH_DescHeader_t  *pnext;
00512  
00513   *ptr += ((USBH_DescHeader_t *)pbuf)->bLength;  
00514   pnext = (USBH_DescHeader_t *)((uint8_t *)pbuf + \
00515          ((USBH_DescHeader_t *)pbuf)->bLength);
00516  
00517   return(pnext);
00518 }
00519 
00520 
00521 /**
00522   * @brief  USBH_CtlReq
00523   *         USBH_CtlReq sends a control request and provide the status after 
00524   *            completion of the request
00525   * @param  phost: Host Handle
00526   * @param  req: Setup Request Structure
00527   * @param  buff: data buffer address to store the response
00528   * @param  length: length of the response
00529   * @retval USBH Status
00530   */
00531 USBH_StatusTypeDef USBH_CtlReq     (USBH_HandleTypeDef *phost, 
00532                              uint8_t             *buff,
00533                              uint16_t            length)
00534 {
00535   USBH_StatusTypeDef status;
00536   status = USBH_BUSY;
00537   
00538   switch (phost->RequestState)
00539   {
00540   case CMD_SEND:
00541     /* Start a SETUP transfer */
00542     phost->Control.buff = buff; 
00543     phost->Control.length = length;
00544     phost->Control.state = CTRL_SETUP;  
00545     phost->RequestState = CMD_WAIT;
00546     status = USBH_BUSY;
00547 #if (USBH_USE_OS == 1)
00548     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00549 #endif      
00550     break;
00551     
00552   case CMD_WAIT:
00553     status = USBH_HandleControl(phost);
00554      if (status == USBH_OK) 
00555     {
00556       /* Commands successfully sent and Response Received  */       
00557       phost->RequestState = CMD_SEND;
00558       phost->Control.state =CTRL_IDLE;  
00559       status = USBH_OK;      
00560     }
00561     else if  (status == USBH_FAIL)
00562     {
00563       /* Failure Mode */
00564       phost->RequestState = CMD_SEND;
00565       status = USBH_FAIL;
00566     }   
00567     break;
00568     
00569   default:
00570     break; 
00571   }
00572   return status;
00573 }
00574 
00575 /**
00576   * @brief  USBH_HandleControl
00577   *         Handles the USB control transfer state machine
00578   * @param  phost: Host Handle
00579   * @retval USBH Status
00580   */
00581 static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost)
00582 {
00583   uint8_t direction;  
00584   USBH_StatusTypeDef status = USBH_BUSY;
00585   USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
00586   
00587   switch (phost->Control.state)
00588   {
00589   case CTRL_SETUP:
00590     /* send a SETUP packet */
00591     USBH_CtlSendSetup     (phost, 
00592                        (uint8_t *)phost->Control.setup.d8 , 
00593                        phost->Control.pipe_out); 
00594     
00595     phost->Control.state = CTRL_SETUP_WAIT; 
00596     break; 
00597     
00598   case CTRL_SETUP_WAIT:
00599     
00600     URB_Status = USBH_LL_GetURBState(phost, phost->Control.pipe_out); 
00601     /* case SETUP packet sent successfully */
00602     if(URB_Status == USBH_URB_DONE)
00603     { 
00604       direction = (phost->Control.setup.b.bmRequestType & USB_REQ_DIR_MASK);
00605       
00606       /* check if there is a data stage */
00607       if (phost->Control.setup.b.wLength.w != 0 )
00608       {        
00609         if (direction == USB_D2H)
00610         {
00611           /* Data Direction is IN */
00612           phost->Control.state = CTRL_DATA_IN;
00613         }
00614         else
00615         {
00616           /* Data Direction is OUT */
00617           phost->Control.state = CTRL_DATA_OUT;
00618         } 
00619       }
00620       /* No DATA stage */
00621       else
00622       {
00623         /* If there is No Data Transfer Stage */
00624         if (direction == USB_D2H)
00625         {
00626           /* Data Direction is IN */
00627           phost->Control.state = CTRL_STATUS_OUT;
00628         }
00629         else
00630         {
00631           /* Data Direction is OUT */
00632           phost->Control.state = CTRL_STATUS_IN;
00633         } 
00634       }          
00635 #if (USBH_USE_OS == 1)
00636       osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00637 #endif
00638     }
00639     else if(URB_Status == USBH_URB_ERROR)
00640     {
00641       phost->Control.state = CTRL_ERROR;
00642 #if (USBH_USE_OS == 1)
00643     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00644 #endif      
00645     }    
00646     break;
00647     
00648   case CTRL_DATA_IN:  
00649     /* Issue an IN token */ 
00650      phost->Control.timer = phost->Timer;
00651     USBH_CtlReceiveData(phost,
00652                         phost->Control.buff, 
00653                         phost->Control.length,
00654                         phost->Control.pipe_in);
00655  
00656     phost->Control.state = CTRL_DATA_IN_WAIT;
00657     break;    
00658     
00659   case CTRL_DATA_IN_WAIT:
00660     
00661     URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in); 
00662     
00663     /* check is DATA packet transferred successfully */
00664     if  (URB_Status == USBH_URB_DONE)
00665     { 
00666       phost->Control.state = CTRL_STATUS_OUT;
00667 #if (USBH_USE_OS == 1)
00668     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00669 #endif      
00670     }
00671    
00672     /* manage error cases*/
00673     if  (URB_Status == USBH_URB_STALL) 
00674     { 
00675       /* In stall case, return to previous machine state*/
00676       status = USBH_NOT_SUPPORTED;
00677 #if (USBH_USE_OS == 1)
00678     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00679 #endif      
00680     }   
00681     else if (URB_Status == USBH_URB_ERROR)
00682     {
00683       /* Device error */
00684       phost->Control.state = CTRL_ERROR;  
00685 #if (USBH_USE_OS == 1)
00686     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00687 #endif      
00688     }
00689     break;
00690     
00691   case CTRL_DATA_OUT:
00692     
00693     USBH_CtlSendData (phost,
00694                       phost->Control.buff, 
00695                       phost->Control.length , 
00696                       phost->Control.pipe_out,
00697                       1);
00698      phost->Control.timer = phost->Timer;
00699     phost->Control.state = CTRL_DATA_OUT_WAIT;
00700     break;
00701     
00702   case CTRL_DATA_OUT_WAIT:
00703     
00704     URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out);     
00705     
00706     if  (URB_Status == USBH_URB_DONE)
00707     { /* If the Setup Pkt is sent successful, then change the state */
00708       phost->Control.state = CTRL_STATUS_IN;
00709 #if (USBH_USE_OS == 1)
00710       osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00711 #endif      
00712     }
00713     
00714     /* handle error cases */
00715     else if  (URB_Status == USBH_URB_STALL) 
00716     { 
00717       /* In stall case, return to previous machine state*/
00718       phost->Control.state = CTRL_STALLED; 
00719       status = USBH_NOT_SUPPORTED;
00720 #if (USBH_USE_OS == 1)
00721     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00722 #endif      
00723     } 
00724     else if  (URB_Status == USBH_URB_NOTREADY)
00725     { 
00726       /* Nack received from device */
00727       phost->Control.state = CTRL_DATA_OUT;
00728       
00729 #if (USBH_USE_OS == 1)
00730     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00731 #endif      
00732     }    
00733     else if (URB_Status == USBH_URB_ERROR)
00734     {
00735       /* device error */
00736       phost->Control.state = CTRL_ERROR;  
00737       status = USBH_FAIL;    
00738       
00739 #if (USBH_USE_OS == 1)
00740     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00741 #endif      
00742     } 
00743     break;
00744     
00745     
00746   case CTRL_STATUS_IN:
00747     /* Send 0 bytes out packet */
00748     USBH_CtlReceiveData (phost,
00749                          0,
00750                          0,
00751                          phost->Control.pipe_in);
00752     phost->Control.timer = phost->Timer;
00753     phost->Control.state = CTRL_STATUS_IN_WAIT;
00754     
00755     break;
00756     
00757   case CTRL_STATUS_IN_WAIT:
00758     
00759     URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in); 
00760     
00761     if  ( URB_Status == USBH_URB_DONE)
00762     { /* Control transfers completed, Exit the State Machine */
00763       phost->Control.state = CTRL_COMPLETE;
00764       status = USBH_OK;
00765 #if (USBH_USE_OS == 1)
00766     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00767 #endif      
00768     }
00769     
00770     else if (URB_Status == USBH_URB_ERROR)
00771     {
00772       phost->Control.state = CTRL_ERROR;
00773 #if (USBH_USE_OS == 1)
00774     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00775 #endif      
00776     }
00777      else if(URB_Status == USBH_URB_STALL)
00778     {
00779       /* Control transfers completed, Exit the State Machine */
00780       status = USBH_NOT_SUPPORTED;
00781       
00782 #if (USBH_USE_OS == 1)
00783     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00784 #endif      
00785     }
00786     break;
00787     
00788   case CTRL_STATUS_OUT:
00789     USBH_CtlSendData (phost,
00790                       0,
00791                       0,
00792                       phost->Control.pipe_out,
00793                       1);
00794      phost->Control.timer = phost->Timer;
00795     phost->Control.state = CTRL_STATUS_OUT_WAIT;
00796     break;
00797     
00798   case CTRL_STATUS_OUT_WAIT: 
00799     
00800     URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out);  
00801     if  (URB_Status == USBH_URB_DONE)
00802     { 
00803       status = USBH_OK;      
00804       phost->Control.state = CTRL_COMPLETE; 
00805       
00806 #if (USBH_USE_OS == 1)
00807     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00808 #endif      
00809     }
00810     else if  (URB_Status == USBH_URB_NOTREADY)
00811     { 
00812       phost->Control.state = CTRL_STATUS_OUT;
00813       
00814 #if (USBH_USE_OS == 1)
00815     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00816 #endif      
00817     }      
00818     else if (URB_Status == USBH_URB_ERROR)
00819     {
00820       phost->Control.state = CTRL_ERROR; 
00821       
00822 #if (USBH_USE_OS == 1)
00823     osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
00824 #endif      
00825     }
00826     break;
00827     
00828   case CTRL_ERROR:
00829     /* 
00830     After a halt condition is encountered or an error is detected by the 
00831     host, a control endpoint is allowed to recover by accepting the next Setup 
00832     PID; i.e., recovery actions via some other pipe are not required for control
00833     endpoints. For the Default Control Pipe, a device reset will ultimately be 
00834     required to clear the halt or error condition if the next Setup PID is not 
00835     accepted.
00836     */
00837     if (++ phost->Control.errorcount <= USBH_MAX_ERROR_COUNT)
00838     {
00839       /* try to recover control */
00840       USBH_LL_Stop(phost);
00841          
00842       /* Do the transmission again, starting from SETUP Packet */
00843       phost->Control.state = CTRL_SETUP; 
00844       phost->RequestState = CMD_SEND;
00845     }
00846     else
00847     {
00848       phost->pUser(phost, HOST_USER_UNRECOVERED_ERROR);
00849       phost->Control.errorcount = 0;
00850       USBH_ErrLog("Control error");
00851       status = USBH_FAIL;
00852     }
00853     break;
00854     
00855   default:
00856     break;
00857   }
00858   return status;
00859 }
00860 
00861 /**
00862 * @}
00863 */ 
00864 
00865 /**
00866 * @}
00867 */ 
00868 
00869 /**
00870 * @}
00871 */
00872 
00873 /**
00874 * @}
00875 */ 
00876 
00877 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
00878 
00879 
00880 
00881