Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BSP_DISCO_F746NG_patch mbed-rtos mbed
usbh_ctlreq.c
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>© 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
Generated on Tue Jul 12 2022 14:58:21 by
1.7.2