1 /**
2 ******************************************************************************
3 * @file usbh_ctlreq.c
4 * @author MCD Application Team
5 * @version V3.0.0
6 * @date 18-February-2014
7 * @brief This file implements the control requests for device enumeration
8 ******************************************************************************
9 * @attention
10 *
11 * <h2><center>© COPYRIGHT 2014 STMicroelectronics</center></h2>
12 *
13 * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
14 * You may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at:
16 *
17 * http://www.st.com/software_license_agreement_liberty_v2
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *
25 ******************************************************************************
26 */
27 /* Includes ------------------------------------------------------------------*/
28
29 #include "usbh_ctlreq.h"
30
31 /** @addtogroup USBH_LIB
32 * @{
33 */
34
35 /** @addtogroup USBH_LIB_CORE
36 * @{
37 */
38
39 /** @defgroup USBH_CTLREQ
40 * @brief This file implements the standard requests for device enumeration
41 * @{
42 */
43
44
45 /** @defgroup USBH_CTLREQ_Private_Defines
46 * @{
47 */
48 /**
49 * @}
50 */
51
52
53 /** @defgroup USBH_CTLREQ_Private_TypesDefinitions
54 * @{
55 */
56 /**
57 * @}
58 */
59
60
61
62 /** @defgroup USBH_CTLREQ_Private_Macros
63 * @{
64 */
65 /**
66 * @}
67 */
68
69
70 /** @defgroup USBH_CTLREQ_Private_Variables
71 * @{
72 */
73 /**
74 * @}
75 */
76
77 /** @defgroup USBH_CTLREQ_Private_FunctionPrototypes
78 * @{
79 */
80 static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost);
81
82 static void USBH_ParseDevDesc (USBH_DevDescTypeDef* , uint8_t *buf, uint16_t length);
83
84 static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc,
85 uint8_t *buf,
86 uint16_t length);
87
88
89 static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor, uint8_t *buf);
90 static void USBH_ParseStringDesc (uint8_t* psrc, uint8_t* pdest, uint16_t length);
91 static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor, uint8_t *buf);
92
93
94 /**
95 * @}
96 */
97
98
99 /** @defgroup USBH_CTLREQ_Private_Functions
100 * @{
101 */
102
103
104 /**
105 * @brief USBH_Get_DevDesc
106 * Issue Get Device Descriptor command to the device. Once the response
107 * received, it parses the device descriptor and updates the status.
108 * @param phost: Host Handle
109 * @param length: Length of the descriptor
110 * @retval USBH Status
111 */
USBH_Get_DevDesc(USBH_HandleTypeDef * phost,uint8_t length)112 USBH_StatusTypeDef USBH_Get_DevDesc(USBH_HandleTypeDef *phost, uint8_t length)
113 {
114 USBH_StatusTypeDef status;
115
116 if((status = USBH_GetDescriptor(phost,
117 USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
118 USB_DESC_DEVICE,
119 phost->device.Data,
120 length)) == USBH_OK)
121 {
122 /* Commands successfully sent and Response Received */
123 USBH_ParseDevDesc(&phost->device.DevDesc, phost->device.Data, length);
124 }
125 return status;
126 }
127
128 /**
129 * @brief USBH_Get_CfgDesc
130 * Issues Configuration Descriptor to the device. Once the response
131 * received, it parses the configuartion descriptor and updates the
132 * status.
133 * @param phost: Host Handle
134 * @param length: Length of the descriptor
135 * @retval USBH Status
136 */
USBH_Get_CfgDesc(USBH_HandleTypeDef * phost,uint16_t length)137 USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost,
138 uint16_t length)
139
140 {
141 USBH_StatusTypeDef status;
142 uint8_t *pData;
143 #if (USBH_KEEP_CFG_DESCRIPTOR == 1)
144 pData = phost->device.CfgDesc_Raw;
145 #else
146 pData = phost->device.Data;
147 #endif
148 if((status = USBH_GetDescriptor(phost,
149 USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
150 USB_DESC_CONFIGURATION,
151 pData,
152 length)) == USBH_OK)
153 {
154
155 /* Commands successfully sent and Response Received */
156 USBH_ParseCfgDesc (&phost->device.CfgDesc,
157 pData,
158 length);
159
160 }
161 return status;
162 }
163
164
165 /**
166 * @brief USBH_Get_StringDesc
167 * Issues string Descriptor command to the device. Once the response
168 * received, it parses the string descriptor and updates the status.
169 * @param phost: Host Handle
170 * @param string_index: String index for the descriptor
171 * @param buff: Buffer address for the descriptor
172 * @param length: Length of the descriptor
173 * @retval USBH Status
174 */
USBH_Get_StringDesc(USBH_HandleTypeDef * phost,uint8_t string_index,uint8_t * buff,uint16_t length)175 USBH_StatusTypeDef USBH_Get_StringDesc(USBH_HandleTypeDef *phost,
176 uint8_t string_index,
177 uint8_t *buff,
178 uint16_t length)
179 {
180 USBH_StatusTypeDef status;
181 if((status = USBH_GetDescriptor(phost,
182 USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD,
183 USB_DESC_STRING | string_index,
184 phost->device.Data,
185 length)) == USBH_OK)
186 {
187 /* Commands successfully sent and Response Received */
188 USBH_ParseStringDesc(phost->device.Data,buff, length);
189 }
190 return status;
191 }
192
193 /**
194 * @brief USBH_GetDescriptor
195 * Issues Descriptor command to the device. Once the response received,
196 * it parses the descriptor and updates the status.
197 * @param phost: Host Handle
198 * @param req_type: Descriptor type
199 * @param value_idx: wValue for the GetDescriptr request
200 * @param buff: Buffer to store the descriptor
201 * @param length: Length of the descriptor
202 * @retval USBH Status
203 */
USBH_GetDescriptor(USBH_HandleTypeDef * phost,uint8_t req_type,uint16_t value_idx,uint8_t * buff,uint16_t length)204 USBH_StatusTypeDef USBH_GetDescriptor(USBH_HandleTypeDef *phost,
205 uint8_t req_type,
206 uint16_t value_idx,
207 uint8_t* buff,
208 uint16_t length )
209 {
210 if(phost->RequestState == CMD_SEND)
211 {
212 phost->Control.setup.b.bmRequestType = USB_D2H | req_type;
213 phost->Control.setup.b.bRequest = USB_REQ_GET_DESCRIPTOR;
214 phost->Control.setup.b.wValue.w = value_idx;
215
216 if ((value_idx & 0xff00) == USB_DESC_STRING)
217 {
218 phost->Control.setup.b.wIndex.w = 0x0409;
219 }
220 else
221 {
222 phost->Control.setup.b.wIndex.w = 0;
223 }
224 phost->Control.setup.b.wLength.w = length;
225 }
226 return USBH_CtlReq(phost, buff , length );
227 }
228
229 /**
230 * @brief USBH_SetAddress
231 * This command sets the address to the connected device
232 * @param phost: Host Handle
233 * @param DeviceAddress: Device address to assign
234 * @retval USBH Status
235 */
USBH_SetAddress(USBH_HandleTypeDef * phost,uint8_t DeviceAddress)236 USBH_StatusTypeDef USBH_SetAddress(USBH_HandleTypeDef *phost,
237 uint8_t DeviceAddress)
238 {
239 if(phost->RequestState == CMD_SEND)
240 {
241 phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE | \
242 USB_REQ_TYPE_STANDARD;
243
244 phost->Control.setup.b.bRequest = USB_REQ_SET_ADDRESS;
245
246 phost->Control.setup.b.wValue.w = (uint16_t)DeviceAddress;
247 phost->Control.setup.b.wIndex.w = 0;
248 phost->Control.setup.b.wLength.w = 0;
249 }
250 return USBH_CtlReq(phost, 0 , 0 );
251 }
252
253 /**
254 * @brief USBH_SetCfg
255 * The command sets the configuration value to the connected device
256 * @param phost: Host Handle
257 * @param cfg_idx: Configuration value
258 * @retval USBH Status
259 */
USBH_SetCfg(USBH_HandleTypeDef * phost,uint16_t cfg_idx)260 USBH_StatusTypeDef USBH_SetCfg(USBH_HandleTypeDef *phost,
261 uint16_t cfg_idx)
262 {
263 if(phost->RequestState == CMD_SEND)
264 {
265 phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_DEVICE |\
266 USB_REQ_TYPE_STANDARD;
267 phost->Control.setup.b.bRequest = USB_REQ_SET_CONFIGURATION;
268 phost->Control.setup.b.wValue.w = cfg_idx;
269 phost->Control.setup.b.wIndex.w = 0;
270 phost->Control.setup.b.wLength.w = 0;
271 }
272
273 return USBH_CtlReq(phost, 0 , 0 );
274 }
275
276 /**
277 * @brief USBH_SetInterface
278 * The command sets the Interface value to the connected device
279 * @param phost: Host Handle
280 * @param altSetting: Interface value
281 * @retval USBH Status
282 */
USBH_SetInterface(USBH_HandleTypeDef * phost,uint8_t ep_num,uint8_t altSetting)283 USBH_StatusTypeDef USBH_SetInterface(USBH_HandleTypeDef *phost,
284 uint8_t ep_num, uint8_t altSetting)
285 {
286
287 if(phost->RequestState == CMD_SEND)
288 {
289 phost->Control.setup.b.bmRequestType = USB_H2D | USB_REQ_RECIPIENT_INTERFACE | \
290 USB_REQ_TYPE_STANDARD;
291
292 phost->Control.setup.b.bRequest = USB_REQ_SET_INTERFACE;
293 phost->Control.setup.b.wValue.w = altSetting;
294 phost->Control.setup.b.wIndex.w = ep_num;
295 phost->Control.setup.b.wLength.w = 0;
296 }
297 return USBH_CtlReq(phost, 0 , 0 );
298 }
299
300 /**
301 * @brief USBH_ClrFeature
302 * This request is used to clear or disable a specific feature.
303 * @param phost: Host Handle
304 * @param ep_num: endpoint number
305 * @param hc_num: Host channel number
306 * @retval USBH Status
307 */
USBH_ClrFeature(USBH_HandleTypeDef * phost,uint8_t ep_num)308 USBH_StatusTypeDef USBH_ClrFeature(USBH_HandleTypeDef *phost,
309 uint8_t ep_num)
310 {
311 if(phost->RequestState == CMD_SEND)
312 {
313 phost->Control.setup.b.bmRequestType = USB_H2D |
314 USB_REQ_RECIPIENT_ENDPOINT |
315 USB_REQ_TYPE_STANDARD;
316
317 phost->Control.setup.b.bRequest = USB_REQ_CLEAR_FEATURE;
318 phost->Control.setup.b.wValue.w = FEATURE_SELECTOR_ENDPOINT;
319 phost->Control.setup.b.wIndex.w = ep_num;
320 phost->Control.setup.b.wLength.w = 0;
321 }
322 return USBH_CtlReq(phost, 0 , 0 );
323 }
324
325 /**
326 * @brief USBH_ParseDevDesc
327 * This function Parses the device descriptor
328 * @param dev_desc: device_descriptor destinaton address
329 * @param buf: Buffer where the source descriptor is available
330 * @param length: Length of the descriptor
331 * @retval None
332 */
USBH_ParseDevDesc(USBH_DevDescTypeDef * dev_desc,uint8_t * buf,uint16_t length)333 static void USBH_ParseDevDesc (USBH_DevDescTypeDef* dev_desc,
334 uint8_t *buf,
335 uint16_t length)
336 {
337 dev_desc->bLength = *(uint8_t *) (buf + 0);
338 dev_desc->bDescriptorType = *(uint8_t *) (buf + 1);
339 dev_desc->bcdUSB = LE16 (buf + 2);
340 dev_desc->bDeviceClass = *(uint8_t *) (buf + 4);
341 dev_desc->bDeviceSubClass = *(uint8_t *) (buf + 5);
342 dev_desc->bDeviceProtocol = *(uint8_t *) (buf + 6);
343 dev_desc->bMaxPacketSize = *(uint8_t *) (buf + 7);
344
345 if (length > 8)
346 { /* For 1st time after device connection, Host may issue only 8 bytes for
347 Device Descriptor Length */
348 dev_desc->idVendor = LE16 (buf + 8);
349 dev_desc->idProduct = LE16 (buf + 10);
350 dev_desc->bcdDevice = LE16 (buf + 12);
351 dev_desc->iManufacturer = *(uint8_t *) (buf + 14);
352 dev_desc->iProduct = *(uint8_t *) (buf + 15);
353 dev_desc->iSerialNumber = *(uint8_t *) (buf + 16);
354 dev_desc->bNumConfigurations = *(uint8_t *) (buf + 17);
355 }
356 }
357
358 /**
359 * @brief USBH_ParseCfgDesc
360 * This function Parses the configuration descriptor
361 * @param cfg_desc: Configuration Descriptor address
362 * @param buf: Buffer where the source descriptor is available
363 * @param length: Length of the descriptor
364 * @retval None
365 */
USBH_ParseCfgDesc(USBH_CfgDescTypeDef * cfg_desc,uint8_t * buf,uint16_t length)366 static void USBH_ParseCfgDesc (USBH_CfgDescTypeDef* cfg_desc,
367 uint8_t *buf,
368 uint16_t length)
369 {
370 USBH_InterfaceDescTypeDef *pif ;
371 USBH_EpDescTypeDef *pep;
372 USBH_DescHeader_t *pdesc = (USBH_DescHeader_t *)buf;
373 uint16_t ptr;
374 int8_t if_ix = 0;
375 int8_t ep_ix = 0;
376
377 pdesc = (USBH_DescHeader_t *)buf;
378
379 /* Parse configuration descriptor */
380 cfg_desc->bLength = *(uint8_t *) (buf + 0);
381 cfg_desc->bDescriptorType = *(uint8_t *) (buf + 1);
382 cfg_desc->wTotalLength = LE16 (buf + 2);
383 cfg_desc->bNumInterfaces = *(uint8_t *) (buf + 4);
384 cfg_desc->bConfigurationValue = *(uint8_t *) (buf + 5);
385 cfg_desc->iConfiguration = *(uint8_t *) (buf + 6);
386 cfg_desc->bmAttributes = *(uint8_t *) (buf + 7);
387 cfg_desc->bMaxPower = *(uint8_t *) (buf + 8);
388
389
390 if (length > USB_CONFIGURATION_DESC_SIZE)
391 {
392 ptr = USB_LEN_CFG_DESC;
393 pif = (USBH_InterfaceDescTypeDef *)0;
394
395
396 while ((if_ix < USBH_MAX_NUM_INTERFACES ) && (ptr < cfg_desc->wTotalLength))
397 {
398 pdesc = USBH_GetNextDesc((uint8_t *)pdesc, &ptr);
399 if (pdesc->bDescriptorType == USB_DESC_TYPE_INTERFACE)
400 {
401 pif = &cfg_desc->Itf_Desc[if_ix];
402 USBH_ParseInterfaceDesc (pif, (uint8_t *)pdesc);
403
404 ep_ix = 0;
405 pep = (USBH_EpDescTypeDef *)0;
406 while ((ep_ix < pif->bNumEndpoints) && (ptr < cfg_desc->wTotalLength))
407 {
408 pdesc = USBH_GetNextDesc((void* )pdesc, &ptr);
409 if (pdesc->bDescriptorType == USB_DESC_TYPE_ENDPOINT)
410 {
411 pep = &cfg_desc->Itf_Desc[if_ix].Ep_Desc[ep_ix];
412 USBH_ParseEPDesc (pep, (uint8_t *)pdesc);
413 ep_ix++;
414 }
415 }
416 if_ix++;
417 }
418 }
419 }
420 }
421
422
423
424 /**
425 * @brief USBH_ParseInterfaceDesc
426 * This function Parses the interface descriptor
427 * @param if_descriptor : Interface descriptor destination
428 * @param buf: Buffer where the descriptor data is available
429 * @retval None
430 */
USBH_ParseInterfaceDesc(USBH_InterfaceDescTypeDef * if_descriptor,uint8_t * buf)431 static void USBH_ParseInterfaceDesc (USBH_InterfaceDescTypeDef *if_descriptor,
432 uint8_t *buf)
433 {
434 if_descriptor->bLength = *(uint8_t *) (buf + 0);
435 if_descriptor->bDescriptorType = *(uint8_t *) (buf + 1);
436 if_descriptor->bInterfaceNumber = *(uint8_t *) (buf + 2);
437 if_descriptor->bAlternateSetting = *(uint8_t *) (buf + 3);
438 if_descriptor->bNumEndpoints = *(uint8_t *) (buf + 4);
439 if_descriptor->bInterfaceClass = *(uint8_t *) (buf + 5);
440 if_descriptor->bInterfaceSubClass = *(uint8_t *) (buf + 6);
441 if_descriptor->bInterfaceProtocol = *(uint8_t *) (buf + 7);
442 if_descriptor->iInterface = *(uint8_t *) (buf + 8);
443 }
444
445 /**
446 * @brief USBH_ParseEPDesc
447 * This function Parses the endpoint descriptor
448 * @param ep_descriptor: Endpoint descriptor destination address
449 * @param buf: Buffer where the parsed descriptor stored
450 * @retval None
451 */
USBH_ParseEPDesc(USBH_EpDescTypeDef * ep_descriptor,uint8_t * buf)452 static void USBH_ParseEPDesc (USBH_EpDescTypeDef *ep_descriptor,
453 uint8_t *buf)
454 {
455
456 ep_descriptor->bLength = *(uint8_t *) (buf + 0);
457 ep_descriptor->bDescriptorType = *(uint8_t *) (buf + 1);
458 ep_descriptor->bEndpointAddress = *(uint8_t *) (buf + 2);
459 ep_descriptor->bmAttributes = *(uint8_t *) (buf + 3);
460 ep_descriptor->wMaxPacketSize = LE16 (buf + 4);
461 ep_descriptor->bInterval = *(uint8_t *) (buf + 6);
462 }
463
464 /**
465 * @brief USBH_ParseStringDesc
466 * This function Parses the string descriptor
467 * @param psrc: Source pointer containing the descriptor data
468 * @param pdest: Destination address pointer
469 * @param length: Length of the descriptor
470 * @retval None
471 */
USBH_ParseStringDesc(uint8_t * psrc,uint8_t * pdest,uint16_t length)472 static void USBH_ParseStringDesc (uint8_t* psrc,
473 uint8_t* pdest,
474 uint16_t length)
475 {
476 uint16_t strlength;
477 uint16_t idx;
478
479 /* The UNICODE string descriptor is not NULL-terminated. The string length is
480 computed by substracting two from the value of the first byte of the descriptor.
481 */
482
483 /* Check which is lower size, the Size of string or the length of bytes read
484 from the device */
485
486 if ( psrc[1] == USB_DESC_TYPE_STRING)
487 { /* Make sure the Descriptor is String Type */
488
489 /* psrc[0] contains Size of Descriptor, subtract 2 to get the length of string */
490 strlength = ( ( (psrc[0]-2) <= length) ? (psrc[0]-2) :length);
491 psrc += 2; /* Adjust the offset ignoring the String Len and Descriptor type */
492
493 for (idx = 0; idx < strlength; idx+=2 )
494 {/* Copy Only the string and ignore the UNICODE ID, hence add the src */
495 *pdest = psrc[idx];
496 pdest++;
497 }
498 *pdest = 0; /* mark end of string */
499 }
500 }
501
502 /**
503 * @brief USBH_GetNextDesc
504 * This function return the next descriptor header
505 * @param buf: Buffer where the cfg descriptor is available
506 * @param ptr: data popinter inside the cfg descriptor
507 * @retval next header
508 */
USBH_GetNextDesc(uint8_t * pbuf,uint16_t * ptr)509 USBH_DescHeader_t *USBH_GetNextDesc (uint8_t *pbuf, uint16_t *ptr)
510 {
511 USBH_DescHeader_t *pnext;
512
513 *ptr += ((USBH_DescHeader_t *)pbuf)->bLength;
514 pnext = (USBH_DescHeader_t *)((uint8_t *)pbuf + \
515 ((USBH_DescHeader_t *)pbuf)->bLength);
516
517 return(pnext);
518 }
519
520
521 /**
522 * @brief USBH_CtlReq
523 * USBH_CtlReq sends a control request and provide the status after
524 * completion of the request
525 * @param phost: Host Handle
526 * @param req: Setup Request Structure
527 * @param buff: data buffer address to store the response
528 * @param length: length of the response
529 * @retval USBH Status
530 */
USBH_CtlReq(USBH_HandleTypeDef * phost,uint8_t * buff,uint16_t length)531 USBH_StatusTypeDef USBH_CtlReq (USBH_HandleTypeDef *phost,
532 uint8_t *buff,
533 uint16_t length)
534 {
535 USBH_StatusTypeDef status;
536 status = USBH_BUSY;
537
538 switch (phost->RequestState)
539 {
540 case CMD_SEND:
541 /* Start a SETUP transfer */
542 phost->Control.buff = buff;
543 phost->Control.length = length;
544 phost->Control.state = CTRL_SETUP;
545 phost->RequestState = CMD_WAIT;
546 status = USBH_BUSY;
547 #if (USBH_USE_OS == 1)
548 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
549 #endif
550 break;
551
552 case CMD_WAIT:
553 status = USBH_HandleControl(phost);
554 if (status == USBH_OK)
555 {
556 /* Commands successfully sent and Response Received */
557 phost->RequestState = CMD_SEND;
558 phost->Control.state =CTRL_IDLE;
559 status = USBH_OK;
560 }
561 else if (status == USBH_FAIL)
562 {
563 /* Failure Mode */
564 phost->RequestState = CMD_SEND;
565 status = USBH_FAIL;
566 }
567 break;
568
569 default:
570 break;
571 }
572 return status;
573 }
574
575 /**
576 * @brief USBH_HandleControl
577 * Handles the USB control transfer state machine
578 * @param phost: Host Handle
579 * @retval USBH Status
580 */
USBH_HandleControl(USBH_HandleTypeDef * phost)581 static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost)
582 {
583 uint8_t direction;
584 USBH_StatusTypeDef status = USBH_BUSY;
585 USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE;
586
587 switch (phost->Control.state)
588 {
589 case CTRL_SETUP:
590 /* send a SETUP packet */
591 USBH_CtlSendSetup (phost,
592 (uint8_t *)phost->Control.setup.d8 ,
593 phost->Control.pipe_out);
594
595 phost->Control.state = CTRL_SETUP_WAIT;
596 break;
597
598 case CTRL_SETUP_WAIT:
599
600 URB_Status = USBH_LL_GetURBState(phost, phost->Control.pipe_out);
601 /* case SETUP packet sent successfully */
602 if(URB_Status == USBH_URB_DONE)
603 {
604 direction = (phost->Control.setup.b.bmRequestType & USB_REQ_DIR_MASK);
605
606 /* check if there is a data stage */
607 if (phost->Control.setup.b.wLength.w != 0 )
608 {
609 if (direction == USB_D2H)
610 {
611 /* Data Direction is IN */
612 phost->Control.state = CTRL_DATA_IN;
613 }
614 else
615 {
616 /* Data Direction is OUT */
617 phost->Control.state = CTRL_DATA_OUT;
618 }
619 }
620 /* No DATA stage */
621 else
622 {
623 /* If there is No Data Transfer Stage */
624 if (direction == USB_D2H)
625 {
626 /* Data Direction is IN */
627 phost->Control.state = CTRL_STATUS_OUT;
628 }
629 else
630 {
631 /* Data Direction is OUT */
632 phost->Control.state = CTRL_STATUS_IN;
633 }
634 }
635 #if (USBH_USE_OS == 1)
636 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
637 #endif
638 }
639 else if(URB_Status == USBH_URB_ERROR)
640 {
641 phost->Control.state = CTRL_ERROR;
642 #if (USBH_USE_OS == 1)
643 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
644 #endif
645 }
646 break;
647
648 case CTRL_DATA_IN:
649 /* Issue an IN token */
650 phost->Control.timer = phost->Timer;
651 USBH_CtlReceiveData(phost,
652 phost->Control.buff,
653 phost->Control.length,
654 phost->Control.pipe_in);
655
656 phost->Control.state = CTRL_DATA_IN_WAIT;
657 break;
658
659 case CTRL_DATA_IN_WAIT:
660
661 URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in);
662
663 /* check is DATA packet transfered successfully */
664 if (URB_Status == USBH_URB_DONE)
665 {
666 phost->Control.state = CTRL_STATUS_OUT;
667 #if (USBH_USE_OS == 1)
668 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
669 #endif
670 }
671
672 /* manage error cases*/
673 if (URB_Status == USBH_URB_STALL)
674 {
675 /* In stall case, return to previous machine state*/
676 status = USBH_NOT_SUPPORTED;
677 #if (USBH_USE_OS == 1)
678 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
679 #endif
680 }
681 else if (URB_Status == USBH_URB_ERROR)
682 {
683 /* Device error */
684 phost->Control.state = CTRL_ERROR;
685 #if (USBH_USE_OS == 1)
686 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
687 #endif
688 }
689 break;
690
691 case CTRL_DATA_OUT:
692
693 USBH_CtlSendData (phost,
694 phost->Control.buff,
695 phost->Control.length ,
696 phost->Control.pipe_out,
697 1);
698 phost->Control.timer = phost->Timer;
699 phost->Control.state = CTRL_DATA_OUT_WAIT;
700 break;
701
702 case CTRL_DATA_OUT_WAIT:
703
704 URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out);
705
706 if (URB_Status == USBH_URB_DONE)
707 { /* If the Setup Pkt is sent successful, then change the state */
708 phost->Control.state = CTRL_STATUS_IN;
709 #if (USBH_USE_OS == 1)
710 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
711 #endif
712 }
713
714 /* handle error cases */
715 else if (URB_Status == USBH_URB_STALL)
716 {
717 /* In stall case, return to previous machine state*/
718 phost->Control.state = CTRL_STALLED;
719 status = USBH_NOT_SUPPORTED;
720 #if (USBH_USE_OS == 1)
721 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
722 #endif
723 }
724 else if (URB_Status == USBH_URB_NOTREADY)
725 {
726 /* Nack received from device */
727 phost->Control.state = CTRL_DATA_OUT;
728
729 #if (USBH_USE_OS == 1)
730 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
731 #endif
732 }
733 else if (URB_Status == USBH_URB_ERROR)
734 {
735 /* device error */
736 phost->Control.state = CTRL_ERROR;
737 status = USBH_FAIL;
738
739 #if (USBH_USE_OS == 1)
740 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
741 #endif
742 }
743 break;
744
745
746 case CTRL_STATUS_IN:
747 /* Send 0 bytes out packet */
748 USBH_CtlReceiveData (phost,
749 0,
750 0,
751 phost->Control.pipe_in);
752 phost->Control.timer = phost->Timer;
753 phost->Control.state = CTRL_STATUS_IN_WAIT;
754
755 break;
756
757 case CTRL_STATUS_IN_WAIT:
758
759 URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in);
760
761 if ( URB_Status == USBH_URB_DONE)
762 { /* Control transfers completed, Exit the State Machine */
763 phost->Control.state = CTRL_COMPLETE;
764 status = USBH_OK;
765 #if (USBH_USE_OS == 1)
766 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
767 #endif
768 }
769
770 else if (URB_Status == USBH_URB_ERROR)
771 {
772 phost->Control.state = CTRL_ERROR;
773 #if (USBH_USE_OS == 1)
774 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
775 #endif
776 }
777 else if(URB_Status == USBH_URB_STALL)
778 {
779 /* Control transfers completed, Exit the State Machine */
780 status = USBH_NOT_SUPPORTED;
781
782 #if (USBH_USE_OS == 1)
783 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
784 #endif
785 }
786 break;
787
788 case CTRL_STATUS_OUT:
789 USBH_CtlSendData (phost,
790 0,
791 0,
792 phost->Control.pipe_out,
793 1);
794 phost->Control.timer = phost->Timer;
795 phost->Control.state = CTRL_STATUS_OUT_WAIT;
796 break;
797
798 case CTRL_STATUS_OUT_WAIT:
799
800 URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out);
801 if (URB_Status == USBH_URB_DONE)
802 {
803 status = USBH_OK;
804 phost->Control.state = CTRL_COMPLETE;
805
806 #if (USBH_USE_OS == 1)
807 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
808 #endif
809 }
810 else if (URB_Status == USBH_URB_NOTREADY)
811 {
812 phost->Control.state = CTRL_STATUS_OUT;
813
814 #if (USBH_USE_OS == 1)
815 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
816 #endif
817 }
818 else if (URB_Status == USBH_URB_ERROR)
819 {
820 phost->Control.state = CTRL_ERROR;
821
822 #if (USBH_USE_OS == 1)
823 osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0);
824 #endif
825 }
826 break;
827
828 case CTRL_ERROR:
829 /*
830 After a halt condition is encountered or an error is detected by the
831 host, a control endpoint is allowed to recover by accepting the next Setup
832 PID; i.e., recovery actions via some other pipe are not required for control
833 endpoints. For the Default Control Pipe, a device reset will ultimately be
834 required to clear the halt or error condition if the next Setup PID is not
835 accepted.
836 */
837 if (++ phost->Control.errorcount <= USBH_MAX_ERROR_COUNT)
838 {
839 /* try to recover control */
840 USBH_LL_Stop(phost);
841
842 /* Do the transmission again, starting from SETUP Packet */
843 phost->Control.state = CTRL_SETUP;
844 phost->RequestState = CMD_SEND;
845 }
846 else
847 {
848 phost->Control.errorcount = 0;
849 USBH_ErrLog("Control error");
850 status = USBH_FAIL;
851
852 }
853 break;
854
855 default:
856 break;
857 }
858 return status;
859 }
860
861 /**
862 * @}
863 */
864
865 /**
866 * @}
867 */
868
869 /**
870 * @}
871 */
872
873 /**
874 * @}
875 */
876
877 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
878
879
880
881
882