2 ******************************************************************************
4 * @author MCD Application Team
7 * @brief This file implements the standard requests for device enumeration
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 ******************************************************************************
21 /* Includes ------------------------------------------------------------------*/
23 #include "usbh_ioreq.h"
24 #include "usbh_stdreq.h"
26 /** @addtogroup USBH_LIB
30 /** @addtogroup USBH_LIB_CORE
34 /** @defgroup USBH_STDREQ
35 * @brief This file implements the standard requests for device enumeration
40 /** @defgroup USBH_STDREQ_Private_Defines
48 /** @defgroup USBH_STDREQ_Private_TypesDefinitions
57 /** @defgroup USBH_STDREQ_Private_Macros
65 /** @defgroup USBH_STDREQ_Private_Variables
73 /** @defgroup USBH_STDREQ_Private_FunctionPrototypes
76 static void USBH_ParseDevDesc (USBH_DevDesc_TypeDef* , uint8_t *buf, uint16_t length);
78 static void USBH_ParseCfgDesc (USBH_CfgDesc_TypeDef* cfg_desc,
79 USBH_InterfaceDesc_TypeDef* itf_desc,
80 USBH_EpDesc_TypeDef* ep_desc,
83 static USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf,
86 static void USBH_ParseInterfaceDesc (USBH_InterfaceDesc_TypeDef *if_descriptor, uint8_t *buf);
87 static void USBH_ParseEPDesc (USBH_EpDesc_TypeDef *ep_descriptor, uint8_t *buf);
89 static void USBH_ParseStringDesc (uint8_t* psrc, uint8_t* pdest, uint16_t length);
95 /** @defgroup USBH_STDREQ_Private_Functions
101 * @brief USBH_Get_DevDesc
102 * Issue Get Device Descriptor command to the device. Once the response
103 * received, it parses the device descriptor and updates the status.
104 * @param pdev: Selected device
105 * @param dev_desc: Device Descriptor buffer address
106 * @param pdev->host.Rx_Buffer: Receive Buffer address
107 * @param length: Length of the descriptor
110 USBH_Status USBH_Get_DevDesc(USB_OTG_CORE_HANDLE *pdev,
117 if((status = USBH_GetDescriptor(pdev,
119 USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
121 pdev->host.Rx_Buffer,
124 /* Commands successfully sent and Response Received */
125 USBH_ParseDevDesc(&phost->device_prop.Dev_Desc, pdev->host.Rx_Buffer, length);
131 * @brief USBH_Get_CfgDesc
132 * Issues Configuration Descriptor to the device. Once the response
133 * received, it parses the configuartion descriptor and updates the
135 * @param pdev: Selected device
136 * @param cfg_desc: Configuration Descriptor address
137 * @param itf_desc: Interface Descriptor address
138 * @param ep_desc: Endpoint Descriptor address
139 * @param length: Length of the descriptor
142 USBH_Status USBH_Get_CfgDesc(USB_OTG_CORE_HANDLE *pdev,
149 if((status = USBH_GetDescriptor(pdev,
151 USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
152 USB_DESC_CONFIGURATION,
153 pdev->host.Rx_Buffer,
156 /* Commands successfully sent and Response Received */
157 USBH_ParseCfgDesc (&phost->device_prop.Cfg_Desc,
158 phost->device_prop.Itf_Desc,
159 phost->device_prop.Ep_Desc[0],
160 pdev->host.Rx_Buffer,
169 * @brief USBH_Get_StringDesc
170 * Issues string Descriptor command to the device. Once the response
171 * received, it parses the string descriptor and updates the status.
172 * @param pdev: Selected device
173 * @param string_index: String index for the descriptor
174 * @param buff: Buffer address for the descriptor
175 * @param length: Length of the descriptor
178 USBH_Status USBH_Get_StringDesc(USB_OTG_CORE_HANDLE *pdev,
180 uint8_t string_index,
186 if((status = USBH_GetDescriptor(pdev,
188 USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
189 USB_DESC_STRING | string_index,
190 pdev->host.Rx_Buffer,
193 /* Commands successfully sent and Response Received */
194 USBH_ParseStringDesc(pdev->host.Rx_Buffer,buff, length);
200 * @brief USBH_GetDescriptor
201 * Issues Descriptor command to the device. Once the response received,
202 * it parses the descriptor and updates the status.
203 * @param pdev: Selected device
204 * @param req_type: Descriptor type
205 * @param value_idx: wValue for the GetDescriptr request
206 * @param buff: Buffer to store the descriptor
207 * @param length: Length of the descriptor
210 USBH_Status USBH_GetDescriptor(USB_OTG_CORE_HANDLE *pdev,
217 phost->Control.setup.b.bmRequestType = USB_D2H | req_type;
218 phost->Control.setup.b.bRequest = USB_REQ_GET_DESCRIPTOR;
219 phost->Control.setup.b.wValue.w = value_idx;
221 if ((value_idx & 0xff00) == USB_DESC_STRING)
223 phost->Control.setup.b.wIndex.w = 0x0409;
227 phost->Control.setup.b.wIndex.w = 0;
229 phost->Control.setup.b.wLength.w = length;
230 return USBH_CtlReq(pdev, phost, buff , length );
234 * @brief USBH_SetAddress
235 * This command sets the address to the connected device
236 * @param pdev: Selected device
237 * @param DeviceAddress: Device address to assign
240 USBH_Status USBH_SetAddress(USB_OTG_CORE_HANDLE *pdev,
242 uint8_t DeviceAddress)
244 phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | \
245 USB_REQ_TYPE_STANDARD;
247 phost->Control.setup.b.bRequest = USB_REQ_SET_ADDRESS;
249 phost->Control.setup.b.wValue.w = (uint16_t)DeviceAddress;
250 phost->Control.setup.b.wIndex.w = 0;
251 phost->Control.setup.b.wLength.w = 0;
253 return USBH_CtlReq(pdev, phost, 0 , 0 );
258 * The command sets the configuration value to the connected device
259 * @param pdev: Selected device
260 * @param cfg_idx: Configuration value
263 USBH_Status USBH_SetCfg(USB_OTG_CORE_HANDLE *pdev,
268 phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE |\
269 USB_REQ_TYPE_STANDARD;
270 phost->Control.setup.b.bRequest = USB_REQ_SET_CONFIGURATION;
271 phost->Control.setup.b.wValue.w = cfg_idx;
272 phost->Control.setup.b.wIndex.w = 0;
273 phost->Control.setup.b.wLength.w = 0;
275 return USBH_CtlReq(pdev, phost, 0 , 0 );
279 * @brief USBH_ClrFeature
280 * This request is used to clear or disable a specific feature.
282 * @param pdev: Selected device
283 * @param ep_num: endpoint number
284 * @param hc_num: Host channel number
287 USBH_Status USBH_ClrFeature(USB_OTG_CORE_HANDLE *pdev,
293 phost->Control.setup.b.bmRequestType = USB_H2D |
294 USB_REQ_RECIPIENT_ENDPOINT |
295 USB_REQ_TYPE_STANDARD;
297 phost->Control.setup.b.bRequest = USB_REQ_CLEAR_FEATURE;
298 phost->Control.setup.b.wValue.w = FEATURE_SELECTOR_ENDPOINT;
299 phost->Control.setup.b.wIndex.w = ep_num;
300 phost->Control.setup.b.wLength.w = 0;
302 if ((ep_num & USB_REQ_DIR_MASK ) == USB_D2H)
303 { /* EP Type is IN */
304 pdev->host.hc[hc_num].toggle_in = 0;
307 {/* EP Type is OUT */
308 pdev->host.hc[hc_num].toggle_out = 0;
311 return USBH_CtlReq(pdev, phost, 0 , 0 );
315 * @brief USBH_ParseDevDesc
316 * This function Parses the device descriptor
317 * @param dev_desc: device_descriptor destinaton address
318 * @param buf: Buffer where the source descriptor is available
319 * @param length: Length of the descriptor
322 static void USBH_ParseDevDesc (USBH_DevDesc_TypeDef* dev_desc,
326 dev_desc->bLength = *(uint8_t *) (buf + 0);
327 dev_desc->bDescriptorType = *(uint8_t *) (buf + 1);
328 dev_desc->bcdUSB = LE16 (buf + 2);
329 dev_desc->bDeviceClass = *(uint8_t *) (buf + 4);
330 dev_desc->bDeviceSubClass = *(uint8_t *) (buf + 5);
331 dev_desc->bDeviceProtocol = *(uint8_t *) (buf + 6);
332 dev_desc->bMaxPacketSize = *(uint8_t *) (buf + 7);
335 { /* For 1st time after device connection, Host may issue only 8 bytes for
336 Device Descriptor Length */
337 dev_desc->idVendor = LE16 (buf + 8);
338 dev_desc->idProduct = LE16 (buf + 10);
339 dev_desc->bcdDevice = LE16 (buf + 12);
340 dev_desc->iManufacturer = *(uint8_t *) (buf + 14);
341 dev_desc->iProduct = *(uint8_t *) (buf + 15);
342 dev_desc->iSerialNumber = *(uint8_t *) (buf + 16);
343 dev_desc->bNumConfigurations = *(uint8_t *) (buf + 17);
348 * @brief USBH_ParseCfgDesc
349 * This function Parses the configuration descriptor
350 * @param cfg_desc: Configuration Descriptor address
351 * @param itf_desc: Interface Descriptor address
352 * @param ep_desc: Endpoint Descriptor address
353 * @param buf: Buffer where the source descriptor is available
354 * @param length: Length of the descriptor
357 static void USBH_ParseCfgDesc (USBH_CfgDesc_TypeDef* cfg_desc,
358 USBH_InterfaceDesc_TypeDef* itf_desc,
359 USBH_EpDesc_TypeDef* ep_desc,
363 USBH_InterfaceDesc_TypeDef *pif ;
364 USBH_EpDesc_TypeDef *pep;
365 USBH_DescHeader_t *pdesc = (USBH_DescHeader_t *)buf;
370 pdesc = (USBH_DescHeader_t *)buf;
372 /* Parse configuration descriptor */
373 cfg_desc->bLength = *(uint8_t *) (buf + 0);
374 cfg_desc->bDescriptorType = *(uint8_t *) (buf + 1);
375 cfg_desc->wTotalLength = LE16 (buf + 2);
376 cfg_desc->bNumInterfaces = *(uint8_t *) (buf + 4);
377 cfg_desc->bConfigurationValue = *(uint8_t *) (buf + 5);
378 cfg_desc->iConfiguration = *(uint8_t *) (buf + 6);
379 cfg_desc->bmAttributes = *(uint8_t *) (buf + 7);
380 cfg_desc->bMaxPower = *(uint8_t *) (buf + 8);
383 if (length > USB_CONFIGURATION_DESC_SIZE)
385 ptr = USB_LEN_CFG_DESC;
387 if ( cfg_desc->bNumInterfaces <= USBH_MAX_NUM_INTERFACES)
390 pif = (USBH_InterfaceDesc_TypeDef *)0;
392 /* Parse Interface descriptor relative to the current configuration */
393 if(cfg_desc->bNumInterfaces <= USBH_MAX_NUM_INTERFACES)
395 while (if_ix < cfg_desc->bNumInterfaces)
397 pdesc = USBH_GetNextDesc((uint8_t *)pdesc, &ptr);
398 if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE)
400 pif = &itf_desc[if_ix];
401 USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc);
404 /* Parse Ep descriptors relative to the current interface */
405 if(pif->bNumEndpoints <= USBH_MAX_NUM_ENDPOINTS)
407 while (ep_ix < pif->bNumEndpoints)
409 pdesc = USBH_GetNextDesc((void* )pdesc, &ptr);
410 if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT)
412 pep = &ep_desc[ep_ix];
413 USBH_ParseEPDesc (pep, (uint8_t *)pdesc);
418 ptr += pdesc->bLength;
426 ptr += pdesc->bLength;
436 * @brief USBH_ParseInterfaceDesc
437 * This function Parses the interface descriptor
438 * @param if_descriptor : Interface descriptor destination
439 * @param buf: Buffer where the descriptor data is available
442 static void USBH_ParseInterfaceDesc (USBH_InterfaceDesc_TypeDef *if_descriptor,
445 if_descriptor->bLength = *(uint8_t *) (buf + 0);
446 if_descriptor->bDescriptorType = *(uint8_t *) (buf + 1);
447 if_descriptor->bInterfaceNumber = *(uint8_t *) (buf + 2);
448 if_descriptor->bAlternateSetting = *(uint8_t *) (buf + 3);
449 if_descriptor->bNumEndpoints = *(uint8_t *) (buf + 4);
450 if_descriptor->bInterfaceClass = *(uint8_t *) (buf + 5);
451 if_descriptor->bInterfaceSubClass = *(uint8_t *) (buf + 6);
452 if_descriptor->bInterfaceProtocol = *(uint8_t *) (buf + 7);
453 if_descriptor->iInterface = *(uint8_t *) (buf + 8);
457 * @brief USBH_ParseEPDesc
458 * This function Parses the endpoint descriptor
459 * @param ep_descriptor: Endpoint descriptor destination address
460 * @param buf: Buffer where the parsed descriptor stored
463 static void USBH_ParseEPDesc (USBH_EpDesc_TypeDef *ep_descriptor,
467 ep_descriptor->bLength = *(uint8_t *) (buf + 0);
468 ep_descriptor->bDescriptorType = *(uint8_t *) (buf + 1);
469 ep_descriptor->bEndpointAddress = *(uint8_t *) (buf + 2);
470 ep_descriptor->bmAttributes = *(uint8_t *) (buf + 3);
471 ep_descriptor->wMaxPacketSize = LE16 (buf + 4);
472 ep_descriptor->bInterval = *(uint8_t *) (buf + 6);
476 * @brief USBH_ParseStringDesc
477 * This function Parses the string descriptor
478 * @param psrc: Source pointer containing the descriptor data
479 * @param pdest: Destination address pointer
480 * @param length: Length of the descriptor
483 static void USBH_ParseStringDesc (uint8_t* psrc,
490 /* The UNICODE string descriptor is not NULL-terminated. The string length is
491 computed by substracting two from the value of the first byte of the descriptor.
494 /* Check which is lower size, the Size of string or the length of bytes read
497 if ( psrc[1] == USB_DESC_TYPE_STRING)
498 { /* Make sure the Descriptor is String Type */
500 /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */
501 strlength = ( ( (psrc[0]-2) <= length) ? (psrc[0]-2) :length);
502 psrc += 2; /* Adjust the offset ignoring the String Len and Descriptor type */
504 for (idx = 0; idx < strlength; idx+=2 )
505 {/* Copy Only the string and ignore the UNICODE ID, hence add the src */
509 *pdest = 0; /* mark end of string */
514 * @brief USBH_GetNextDesc
515 * This function return the next descriptor header
516 * @param buf: Buffer where the cfg descriptor is available
517 * @param ptr: data popinter inside the cfg descriptor
518 * @retval next header
520 static USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf, uint16_t *ptr)
522 USBH_DescHeader_t *pnext;
524 *ptr += ((USBH_DescHeader_t *)pbuf)->bLength;
525 pnext = (USBH_DescHeader_t *)((uint8_t *)pbuf + \
526 ((USBH_DescHeader_t *)pbuf)->bLength);
547 /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/