1 /**
2 ******************************************************************************
3 * @file usbh_core.c
4 * @author MCD Application Team
5 * @brief This file implements the functions for the core state machine process
6 * the enumeration and the control transfer process
7 ******************************************************************************
8 * @attention
9 *
10 * <h2><center>© Copyright (c) 2015 STMicroelectronics.
11 * All rights reserved.</center></h2>
12 *
13 * This software component is licensed by ST under Ultimate Liberty license
14 * SLA0044, the "License"; You may not use this file except in compliance with
15 * the License. You may obtain a copy of the License at:
16 * www.st.com/SLA0044
17 *
18 ******************************************************************************
19 */
20
21 /* Includes ------------------------------------------------------------------*/
22 #include "usbh_core.h"
23
24
25 /** @addtogroup USBH_LIB
26 * @{
27 */
28
29 /** @addtogroup USBH_LIB_CORE
30 * @{
31 */
32
33 /** @defgroup USBH_CORE
34 * @brief This file handles the basic enumeration when a device is connected
35 * to the host.
36 * @{
37 */
38
39
40 /** @defgroup USBH_CORE_Private_Defines
41 * @{
42 */
43 #define USBH_ADDRESS_DEFAULT 0x00U
44 #define USBH_ADDRESS_ASSIGNED 0x01U
45 #define USBH_MPS_DEFAULT 0x40U
46 /**
47 * @}
48 */
49
50 /** @defgroup USBH_CORE_Private_Macros
51 * @{
52 */
53 /**
54 * @}
55 */
56
57
58 /** @defgroup USBH_CORE_Private_Variables
59 * @{
60 */
61 #if (USBH_USE_OS == 1U)
62 #if (osCMSIS >= 0x20000U)
63 osThreadAttr_t USBH_Thread_Atrr;
64 #endif
65 #endif
66
67
68 /**
69 * @}
70 */
71
72
73 /** @defgroup USBH_CORE_Private_Functions
74 * @{
75 */
76 static USBH_StatusTypeDef USBH_HandleEnum(USBH_HandleTypeDef *phost);
77 static void USBH_HandleSof(USBH_HandleTypeDef *phost);
78 static USBH_StatusTypeDef DeInitStateMachine(USBH_HandleTypeDef *phost);
79
80 #if (USBH_USE_OS == 1U)
81 #if (osCMSIS < 0x20000U)
82 static void USBH_Process_OS(void const *argument);
83 #else
84 static void USBH_Process_OS(void *argument);
85 #endif
86 #endif
87
88
89 /**
90 * @brief HCD_Init
91 * Initialize the HOST Core.
92 * @param phost: Host Handle
93 * @param pUsrFunc: User Callback
94 * @retval USBH Status
95 */
USBH_Init(USBH_HandleTypeDef * phost,void (* pUsrFunc)(USBH_HandleTypeDef * phost,uint8_t id),uint8_t id)96 USBH_StatusTypeDef USBH_Init(USBH_HandleTypeDef *phost,
97 void (*pUsrFunc)(USBH_HandleTypeDef *phost,
98 uint8_t id), uint8_t id)
99 {
100 /* Check whether the USB Host handle is valid */
101 if (phost == NULL)
102 {
103 USBH_ErrLog("Invalid Host handle");
104 return USBH_FAIL;
105 }
106
107 /* Set DRiver ID */
108 phost->id = id;
109
110 /* Unlink class*/
111 phost->pActiveClass = NULL;
112 phost->ClassNumber = 0U;
113
114 /* Restore default states and prepare EP0 */
115 DeInitStateMachine(phost);
116
117 /* Restore default Device connection states */
118 phost->device.PortEnabled = 0U;
119 phost->device.is_connected = 0U;
120 phost->device.is_disconnected = 0U;
121 phost->device.is_ReEnumerated = 0U;
122
123 /* Assign User process */
124 if (pUsrFunc != NULL)
125 {
126 phost->pUser = pUsrFunc;
127 }
128
129 #if (USBH_USE_OS == 1U)
130 #if (osCMSIS < 0x20000U)
131
132 /* Create USB Host Queue */
133 osMessageQDef(USBH_Queue, MSGQUEUE_OBJECTS, uint16_t);
134 phost->os_event = osMessageCreate(osMessageQ(USBH_Queue), NULL);
135
136 /* Create USB Host Task */
137 #if defined (USBH_PROCESS_STACK_SIZE)
138 osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0U, USBH_PROCESS_STACK_SIZE);
139 #else
140 osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0U, 8U * configMINIMAL_STACK_SIZE);
141 #endif /* defined (USBH_PROCESS_STACK_SIZE) */
142
143 phost->thread = osThreadCreate(osThread(USBH_Thread), phost);
144
145 #else
146
147 /* Create USB Host Queue */
148 phost->os_event = osMessageQueueNew(MSGQUEUE_OBJECTS, sizeof(uint32_t), NULL);
149
150 /* Create USB Host Task */
151 USBH_Thread_Atrr.name = "USBH_Queue";
152
153 #if defined (USBH_PROCESS_STACK_SIZE)
154 USBH_Thread_Atrr.stack_size = USBH_PROCESS_STACK_SIZE;
155 #else
156 USBH_Thread_Atrr.stack_size = (8U * configMINIMAL_STACK_SIZE);
157 #endif /* defined (USBH_PROCESS_STACK_SIZE) */
158
159 USBH_Thread_Atrr.priority = USBH_PROCESS_PRIO;
160 phost->thread = osThreadNew(USBH_Process_OS, phost, &USBH_Thread_Atrr);
161
162 #endif /* (osCMSIS < 0x20000U) */
163 #endif /* (USBH_USE_OS == 1U) */
164
165 /* Initialize low level driver */
166 USBH_LL_Init(phost);
167
168 return USBH_OK;
169 }
170
171
172 /**
173 * @brief HCD_Init
174 * De-Initialize the Host portion of the driver.
175 * @param phost: Host Handle
176 * @retval USBH Status
177 */
USBH_DeInit(USBH_HandleTypeDef * phost)178 USBH_StatusTypeDef USBH_DeInit(USBH_HandleTypeDef *phost)
179 {
180 DeInitStateMachine(phost);
181
182 /* Restore default Device connection states */
183 phost->device.PortEnabled = 0U;
184 phost->device.is_connected = 0U;
185 phost->device.is_disconnected = 0U;
186 phost->device.is_ReEnumerated = 0U;
187 phost->device.RstCnt = 0U;
188 phost->device.EnumCnt = 0U;
189
190 if (phost->pData != NULL)
191 {
192 USBH_LL_Stop(phost);
193 }
194
195 return USBH_OK;
196 }
197
198
199 /**
200 * @brief DeInitStateMachine
201 * De-Initialize the Host state machine.
202 * @param phost: Host Handle
203 * @retval USBH Status
204 */
DeInitStateMachine(USBH_HandleTypeDef * phost)205 static USBH_StatusTypeDef DeInitStateMachine(USBH_HandleTypeDef *phost)
206 {
207 uint32_t i = 0U;
208
209 /* Clear Pipes flags*/
210 for (i = 0U; i < USBH_MAX_PIPES_NBR; i++)
211 {
212 phost->Pipes[i] = 0U;
213 }
214
215 for (i = 0U; i < USBH_MAX_DATA_BUFFER; i++)
216 {
217 phost->device.Data[i] = 0U;
218 }
219
220 phost->gState = HOST_IDLE;
221 phost->EnumState = ENUM_IDLE;
222 phost->RequestState = CMD_SEND;
223 phost->Timer = 0U;
224
225 phost->Control.state = CTRL_SETUP;
226 phost->Control.pipe_size = USBH_MPS_DEFAULT;
227 phost->Control.errorcount = 0U;
228
229 phost->device.address = USBH_ADDRESS_DEFAULT;
230 phost->device.speed = USBH_SPEED_FULL;
231 phost->device.RstCnt = 0U;
232 phost->device.EnumCnt = 0U;
233
234 return USBH_OK;
235 }
236
237
238 /**
239 * @brief USBH_RegisterClass
240 * Link class driver to Host Core.
241 * @param phost : Host Handle
242 * @param pclass: Class handle
243 * @retval USBH Status
244 */
USBH_RegisterClass(USBH_HandleTypeDef * phost,USBH_ClassTypeDef * pclass)245 USBH_StatusTypeDef USBH_RegisterClass(USBH_HandleTypeDef *phost, USBH_ClassTypeDef *pclass)
246 {
247 USBH_StatusTypeDef status = USBH_OK;
248
249 if (pclass != NULL)
250 {
251 if (phost->ClassNumber < USBH_MAX_NUM_SUPPORTED_CLASS)
252 {
253 /* link the class to the USB Host handle */
254 phost->pClass[phost->ClassNumber++] = pclass;
255 status = USBH_OK;
256 }
257 else
258 {
259 USBH_ErrLog("Max Class Number reached");
260 status = USBH_FAIL;
261 }
262 }
263 else
264 {
265 USBH_ErrLog("Invalid Class handle");
266 status = USBH_FAIL;
267 }
268
269 return status;
270 }
271
272
273 /**
274 * @brief USBH_SelectInterface
275 * Select current interface.
276 * @param phost: Host Handle
277 * @param interface: Interface number
278 * @retval USBH Status
279 */
USBH_SelectInterface(USBH_HandleTypeDef * phost,uint8_t interface)280 USBH_StatusTypeDef USBH_SelectInterface(USBH_HandleTypeDef *phost, uint8_t interface)
281 {
282 USBH_StatusTypeDef status = USBH_OK;
283
284 if (interface < phost->device.CfgDesc.bNumInterfaces)
285 {
286 phost->device.current_interface = interface;
287 USBH_UsrLog("Switching to Interface (#%d)", interface);
288 USBH_UsrLog("Class : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass);
289 USBH_UsrLog("SubClass : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceSubClass);
290 USBH_UsrLog("Protocol : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol);
291 }
292 else
293 {
294 USBH_ErrLog("Cannot Select This Interface.");
295 status = USBH_FAIL;
296 }
297
298 return status;
299 }
300
301
302 /**
303 * @brief USBH_GetActiveClass
304 * Return Device Class.
305 * @param phost: Host Handle
306 * @param interface: Interface index
307 * @retval Class Code
308 */
USBH_GetActiveClass(USBH_HandleTypeDef * phost)309 uint8_t USBH_GetActiveClass(USBH_HandleTypeDef *phost)
310 {
311 return (phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass);
312 }
313
314
315 /**
316 * @brief USBH_FindInterface
317 * Find the interface index for a specific class.
318 * @param phost: Host Handle
319 * @param Class: Class code
320 * @param SubClass: SubClass code
321 * @param Protocol: Protocol code
322 * @retval interface index in the configuration structure
323 * @note : (1)interface index 0xFF means interface index not found
324 */
USBH_FindInterface(USBH_HandleTypeDef * phost,uint8_t Class,uint8_t SubClass,uint8_t Protocol)325 uint8_t USBH_FindInterface(USBH_HandleTypeDef *phost, uint8_t Class, uint8_t SubClass, uint8_t Protocol)
326 {
327 USBH_InterfaceDescTypeDef *pif;
328 USBH_CfgDescTypeDef *pcfg;
329 uint8_t if_ix = 0U;
330
331 pif = (USBH_InterfaceDescTypeDef *)0;
332 pcfg = &phost->device.CfgDesc;
333
334 while (if_ix < USBH_MAX_NUM_INTERFACES)
335 {
336 pif = &pcfg->Itf_Desc[if_ix];
337 if (((pif->bInterfaceClass == Class) || (Class == 0xFFU)) &&
338 ((pif->bInterfaceSubClass == SubClass) || (SubClass == 0xFFU)) &&
339 ((pif->bInterfaceProtocol == Protocol) || (Protocol == 0xFFU)))
340 {
341 return if_ix;
342 }
343 if_ix++;
344 }
345 return 0xFFU;
346 }
347
348
349 /**
350 * @brief USBH_FindInterfaceIndex
351 * Find the interface index for a specific class interface and alternate setting number.
352 * @param phost: Host Handle
353 * @param interface_number: interface number
354 * @param alt_settings : alternate setting number
355 * @retval interface index in the configuration structure
356 * @note : (1)interface index 0xFF means interface index not found
357 */
USBH_FindInterfaceIndex(USBH_HandleTypeDef * phost,uint8_t interface_number,uint8_t alt_settings)358 uint8_t USBH_FindInterfaceIndex(USBH_HandleTypeDef *phost, uint8_t interface_number, uint8_t alt_settings)
359 {
360 USBH_InterfaceDescTypeDef *pif;
361 USBH_CfgDescTypeDef *pcfg;
362 uint8_t if_ix = 0U;
363
364 pif = (USBH_InterfaceDescTypeDef *)0;
365 pcfg = &phost->device.CfgDesc;
366
367 while (if_ix < USBH_MAX_NUM_INTERFACES)
368 {
369 pif = &pcfg->Itf_Desc[if_ix];
370 if ((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings))
371 {
372 return if_ix;
373 }
374 if_ix++;
375 }
376 return 0xFFU;
377 }
378
379
380 /**
381 * @brief USBH_Start
382 * Start the USB Host Core.
383 * @param phost: Host Handle
384 * @retval USBH Status
385 */
USBH_Start(USBH_HandleTypeDef * phost)386 USBH_StatusTypeDef USBH_Start(USBH_HandleTypeDef *phost)
387 {
388 /* Start the low level driver */
389 USBH_LL_Start(phost);
390
391 /* Activate VBUS on the port */
392 USBH_LL_DriverVBUS(phost, TRUE);
393
394 return USBH_OK;
395 }
396
397
398 /**
399 * @brief USBH_Stop
400 * Stop the USB Host Core.
401 * @param phost: Host Handle
402 * @retval USBH Status
403 */
USBH_Stop(USBH_HandleTypeDef * phost)404 USBH_StatusTypeDef USBH_Stop(USBH_HandleTypeDef *phost)
405 {
406 /* DeActivate VBUS on the port */
407 USBH_LL_DriverVBUS(phost, FALSE);
408
409 /* Stop and cleanup the low level driver */
410 USBH_LL_Stop(phost);
411
412 /* Free Control Pipes */
413 USBH_FreePipe(phost, phost->Control.pipe_in);
414 USBH_FreePipe(phost, phost->Control.pipe_out);
415
416 return USBH_OK;
417 }
418
419
420 /**
421 * @brief HCD_ReEnumerate
422 * Perform a new Enumeration phase.
423 * @param phost: Host Handle
424 * @retval USBH Status
425 */
USBH_ReEnumerate(USBH_HandleTypeDef * phost)426 USBH_StatusTypeDef USBH_ReEnumerate(USBH_HandleTypeDef *phost)
427 {
428 if (USBH_IsPortEnabled(phost))
429 {
430 phost->device.is_ReEnumerated = 1U;
431
432 /* Stop Host */
433 USBH_Stop(phost);
434
435 phost->device.is_disconnected = 1U;
436 }
437
438 #if (USBH_USE_OS == 1U)
439 phost->os_msg = (uint32_t)USBH_PORT_EVENT;
440 #if (osCMSIS < 0x20000U)
441 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
442 #else
443 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
444 #endif
445 #endif
446
447 return USBH_OK;
448 }
449
450
451 /**
452 * @brief USBH_Process
453 * Background process of the USB Core.
454 * @param phost: Host Handle
455 * @retval USBH Status
456 */
USBH_Process(USBH_HandleTypeDef * phost)457 USBH_StatusTypeDef USBH_Process(USBH_HandleTypeDef *phost)
458 {
459 __IO USBH_StatusTypeDef status = USBH_FAIL;
460 uint8_t idx = 0U;
461
462 /* check for Host pending port disconnect event */
463 if (phost->device.is_disconnected == 1U)
464 {
465 phost->gState = HOST_DEV_DISCONNECTED;
466 }
467
468 switch (phost->gState)
469 {
470 case HOST_IDLE :
471
472 if (phost->device.is_connected)
473 {
474 USBH_UsrLog("USB Device Connected");
475
476 /* Wait for 200 ms after connection */
477 phost->gState = HOST_DEV_WAIT_FOR_ATTACHMENT;
478 USBH_Delay(200U);
479 USBH_LL_ResetPort(phost);
480
481 /* Make sure to start with Default address */
482 phost->device.address = USBH_ADDRESS_DEFAULT;
483 phost->Timeout = 0U;
484
485 #if (USBH_USE_OS == 1U)
486 phost->os_msg = (uint32_t)USBH_PORT_EVENT;
487 #if (osCMSIS < 0x20000U)
488 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
489 #else
490 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
491 #endif
492 #endif
493 }
494 break;
495
496 case HOST_DEV_WAIT_FOR_ATTACHMENT: /* Wait for Port Enabled */
497
498 if (phost->device.PortEnabled == 1U)
499 {
500 USBH_UsrLog("USB Device Reset Completed");
501 phost->device.RstCnt = 0U;
502 phost->gState = HOST_DEV_ATTACHED;
503 }
504 else
505 {
506 if (phost->Timeout > USBH_DEV_RESET_TIMEOUT)
507 {
508 phost->device.RstCnt++;
509 if (phost->device.RstCnt > 3U)
510 {
511 /* Buggy Device can't complete reset */
512 USBH_UsrLog("USB Reset Failed, Please unplug the Device.");
513 phost->gState = HOST_ABORT_STATE;
514 }
515 else
516 {
517 phost->gState = HOST_IDLE;
518 }
519 }
520 else
521 {
522 phost->Timeout += 10U;
523 USBH_Delay(10U);
524 }
525 }
526 #if (USBH_USE_OS == 1U)
527 phost->os_msg = (uint32_t)USBH_PORT_EVENT;
528 #if (osCMSIS < 0x20000U)
529 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
530 #else
531 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
532 #endif
533 #endif
534 break;
535
536 case HOST_DEV_ATTACHED :
537
538 if (phost->pUser != NULL)
539 {
540 phost->pUser(phost, HOST_USER_CONNECTION);
541 }
542
543 /* Wait for 100 ms after Reset */
544 USBH_Delay(100U);
545
546 phost->device.speed = USBH_LL_GetSpeed(phost);
547
548 phost->gState = HOST_ENUMERATION;
549
550 phost->Control.pipe_out = USBH_AllocPipe(phost, 0x00U);
551 phost->Control.pipe_in = USBH_AllocPipe(phost, 0x80U);
552
553 /* Open Control pipes */
554 USBH_OpenPipe(phost, phost->Control.pipe_in, 0x80U,
555 phost->device.address, phost->device.speed,
556 USBH_EP_CONTROL, (uint16_t)phost->Control.pipe_size);
557
558 /* Open Control pipes */
559 USBH_OpenPipe(phost, phost->Control.pipe_out, 0x00U,
560 phost->device.address, phost->device.speed,
561 USBH_EP_CONTROL, (uint16_t)phost->Control.pipe_size);
562
563 #if (USBH_USE_OS == 1U)
564 phost->os_msg = (uint32_t)USBH_PORT_EVENT;
565 #if (osCMSIS < 0x20000U)
566 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
567 #else
568 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
569 #endif
570 #endif
571 break;
572
573 case HOST_ENUMERATION:
574 /* Check for enumeration status */
575 status = USBH_HandleEnum(phost);
576 if (status == USBH_OK)
577 {
578 /* The function shall return USBH_OK when full enumeration is complete */
579 USBH_UsrLog("Enumeration done.");
580
581 phost->device.current_interface = 0U;
582
583 if (phost->device.DevDesc.bNumConfigurations == 1U)
584 {
585 USBH_UsrLog("This device has only 1 configuration.");
586 phost->gState = HOST_SET_CONFIGURATION;
587 }
588 else
589 {
590 phost->gState = HOST_INPUT;
591 }
592 #if (USBH_USE_OS == 1U)
593 phost->os_msg = (uint32_t)USBH_STATE_CHANGED_EVENT;
594 #if (osCMSIS < 0x20000U)
595 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
596 #else
597 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
598 #endif
599 #endif
600 }
601 break;
602
603 case HOST_INPUT:
604 {
605 /* user callback for end of device basic enumeration */
606 if (phost->pUser != NULL)
607 {
608 phost->pUser(phost, HOST_USER_SELECT_CONFIGURATION);
609 phost->gState = HOST_SET_CONFIGURATION;
610
611 #if (USBH_USE_OS == 1U)
612 phost->os_msg = (uint32_t)USBH_STATE_CHANGED_EVENT;
613 #if (osCMSIS < 0x20000U)
614 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
615 #else
616 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
617 #endif
618 #endif
619 }
620 }
621 break;
622
623 case HOST_SET_CONFIGURATION:
624 /* set configuration */
625 if (USBH_SetCfg(phost, (uint16_t)phost->device.CfgDesc.bConfigurationValue) == USBH_OK)
626 {
627 phost->gState = HOST_SET_WAKEUP_FEATURE;
628 USBH_UsrLog("Default configuration set.");
629 }
630
631 #if (USBH_USE_OS == 1U)
632 phost->os_msg = (uint32_t)USBH_PORT_EVENT;
633 #if (osCMSIS < 0x20000U)
634 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
635 #else
636 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
637 #endif
638 #endif
639 break;
640
641 case HOST_SET_WAKEUP_FEATURE:
642
643 if ((phost->device.CfgDesc.bmAttributes) & (1U << 5))
644 {
645 if (USBH_SetFeature(phost, FEATURE_SELECTOR_REMOTEWAKEUP) == USBH_OK)
646 {
647 USBH_UsrLog("Device remote wakeup enabled");
648 phost->gState = HOST_CHECK_CLASS;
649 }
650 }
651 else
652 {
653 phost->gState = HOST_CHECK_CLASS;
654 }
655
656 #if (USBH_USE_OS == 1U)
657 phost->os_msg = (uint32_t)USBH_PORT_EVENT;
658 #if (osCMSIS < 0x20000U)
659 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
660 #else
661 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
662 #endif
663 #endif
664 break;
665
666 case HOST_CHECK_CLASS:
667
668 if (phost->ClassNumber == 0U)
669 {
670 USBH_UsrLog("No Class has been registered.");
671 }
672 else
673 {
674 phost->pActiveClass = NULL;
675
676 for (idx = 0U; idx < USBH_MAX_NUM_SUPPORTED_CLASS; idx++)
677 {
678 if (phost->pClass[idx]->ClassCode == phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass)
679 {
680 phost->pActiveClass = phost->pClass[idx];
681 break;
682 }
683 }
684
685 if (phost->pActiveClass != NULL)
686 {
687 if (phost->pActiveClass->Init(phost) == USBH_OK)
688 {
689 phost->gState = HOST_CLASS_REQUEST;
690 USBH_UsrLog("%s class started.", phost->pActiveClass->Name);
691
692 /* Inform user that a class has been activated */
693 phost->pUser(phost, HOST_USER_CLASS_SELECTED);
694 }
695 else
696 {
697 phost->gState = HOST_ABORT_STATE;
698 USBH_UsrLog("Device not supporting %s class.", phost->pActiveClass->Name);
699 }
700 }
701 else
702 {
703 phost->gState = HOST_ABORT_STATE;
704 USBH_UsrLog("No registered class for this device.");
705 }
706 }
707
708 #if (USBH_USE_OS == 1U)
709 phost->os_msg = (uint32_t)USBH_STATE_CHANGED_EVENT;
710 #if (osCMSIS < 0x20000U)
711 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
712 #else
713 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
714 #endif
715 #endif
716 break;
717
718 case HOST_CLASS_REQUEST:
719 /* process class standard control requests state machine */
720 if (phost->pActiveClass != NULL)
721 {
722 status = phost->pActiveClass->Requests(phost);
723
724 if (status == USBH_OK)
725 {
726 phost->gState = HOST_CLASS;
727 }
728 else if (status == USBH_FAIL)
729 {
730 phost->gState = HOST_ABORT_STATE;
731 USBH_ErrLog("Device not responding Please Unplug.");
732 }
733 else
734 {
735 /* .. */
736 }
737 }
738 else
739 {
740 phost->gState = HOST_ABORT_STATE;
741 USBH_ErrLog("Invalid Class Driver.");
742 }
743 #if (USBH_USE_OS == 1U)
744 phost->os_msg = (uint32_t)USBH_STATE_CHANGED_EVENT;
745 #if (osCMSIS < 0x20000U)
746 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
747 #else
748 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
749 #endif
750 #endif
751 break;
752
753 case HOST_CLASS:
754 /* process class state machine */
755 if (phost->pActiveClass != NULL)
756 {
757 phost->pActiveClass->BgndProcess(phost);
758 }
759 break;
760
761 case HOST_DEV_DISCONNECTED :
762 phost->device.is_disconnected = 0U;
763
764 DeInitStateMachine(phost);
765
766 /* Re-Initilaize Host for new Enumeration */
767 if (phost->pActiveClass != NULL)
768 {
769 phost->pActiveClass->DeInit(phost);
770 phost->pActiveClass = NULL;
771 }
772
773 if (phost->pUser != NULL)
774 {
775 phost->pUser(phost, HOST_USER_DISCONNECTION);
776 }
777 USBH_UsrLog("USB Device disconnected");
778
779 if (phost->device.is_ReEnumerated == 1U)
780 {
781 phost->device.is_ReEnumerated = 0U;
782
783 /* Start the host and re-enable Vbus */
784 USBH_Start(phost);
785 }
786 else
787 {
788 /* Device Disconnection Completed, start USB Driver */
789 USBH_LL_Start(phost);
790 }
791
792 #if (USBH_USE_OS == 1U)
793 phost->os_msg = (uint32_t)USBH_PORT_EVENT;
794 #if (osCMSIS < 0x20000U)
795 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
796 #else
797 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
798 #endif
799 #endif
800 break;
801
802 case HOST_ABORT_STATE:
803 default :
804 break;
805 }
806 return USBH_OK;
807 }
808
809
810 /**
811 * @brief USBH_HandleEnum
812 * This function includes the complete enumeration process
813 * @param phost: Host Handle
814 * @retval USBH_Status
815 */
USBH_HandleEnum(USBH_HandleTypeDef * phost)816 static USBH_StatusTypeDef USBH_HandleEnum(USBH_HandleTypeDef *phost)
817 {
818 USBH_StatusTypeDef Status = USBH_BUSY;
819 USBH_StatusTypeDef ReqStatus = USBH_BUSY;
820
821 switch (phost->EnumState)
822 {
823 case ENUM_IDLE:
824 /* Get Device Desc for only 1st 8 bytes : To get EP0 MaxPacketSize */
825 ReqStatus = USBH_Get_DevDesc(phost, 8U);
826 if (ReqStatus == USBH_OK)
827 {
828 phost->Control.pipe_size = phost->device.DevDesc.bMaxPacketSize;
829
830 phost->EnumState = ENUM_GET_FULL_DEV_DESC;
831
832 /* modify control channels configuration for MaxPacket size */
833 USBH_OpenPipe(phost, phost->Control.pipe_in, 0x80U, phost->device.address,
834 phost->device.speed, USBH_EP_CONTROL,
835 (uint16_t)phost->Control.pipe_size);
836
837 /* Open Control pipes */
838 USBH_OpenPipe(phost, phost->Control.pipe_out, 0x00U, phost->device.address,
839 phost->device.speed, USBH_EP_CONTROL,
840 (uint16_t)phost->Control.pipe_size);
841 }
842 else if (ReqStatus == USBH_NOT_SUPPORTED)
843 {
844 USBH_ErrLog("Control error: Get Device Descriptor request failed");
845 phost->device.EnumCnt++;
846 if (phost->device.EnumCnt > 3U)
847 {
848 /* Buggy Device can't complete get device desc request */
849 USBH_UsrLog("Control error, Device not Responding Please unplug the Device.");
850 phost->gState = HOST_ABORT_STATE;
851 }
852 else
853 {
854 /* free control pipes */
855 USBH_FreePipe(phost, phost->Control.pipe_out);
856 USBH_FreePipe(phost, phost->Control.pipe_in);
857
858 /* Reset the USB Device */
859 phost->gState = HOST_IDLE;
860 }
861 }
862 else
863 {
864 /* .. */
865 }
866 break;
867
868 case ENUM_GET_FULL_DEV_DESC:
869 /* Get FULL Device Desc */
870 ReqStatus = USBH_Get_DevDesc(phost, USB_DEVICE_DESC_SIZE);
871 if (ReqStatus == USBH_OK)
872 {
873 USBH_UsrLog("PID: %xh", phost->device.DevDesc.idProduct);
874 USBH_UsrLog("VID: %xh", phost->device.DevDesc.idVendor);
875
876 phost->EnumState = ENUM_SET_ADDR;
877 }
878 else if (ReqStatus == USBH_NOT_SUPPORTED)
879 {
880 USBH_ErrLog("Control error: Get Full Device Descriptor request failed");
881 phost->device.EnumCnt++;
882 if (phost->device.EnumCnt > 3U)
883 {
884 /* Buggy Device can't complete get device desc request */
885 USBH_UsrLog("Control error, Device not Responding Please unplug the Device.");
886 phost->gState = HOST_ABORT_STATE;
887 }
888 else
889 {
890 /* Free control pipes */
891 USBH_FreePipe(phost, phost->Control.pipe_out);
892 USBH_FreePipe(phost, phost->Control.pipe_in);
893
894 /* Reset the USB Device */
895 phost->EnumState = ENUM_IDLE;
896 phost->gState = HOST_IDLE;
897 }
898 }
899 else
900 {
901 /* .. */
902 }
903 break;
904
905 case ENUM_SET_ADDR:
906 /* set address */
907 ReqStatus = USBH_SetAddress(phost, USBH_DEVICE_ADDRESS);
908 if (ReqStatus == USBH_OK)
909 {
910 USBH_Delay(2U);
911 phost->device.address = USBH_DEVICE_ADDRESS;
912
913 /* user callback for device address assigned */
914 USBH_UsrLog("Address (#%d) assigned.", phost->device.address);
915 phost->EnumState = ENUM_GET_CFG_DESC;
916
917 /* modify control channels to update device address */
918 USBH_OpenPipe(phost, phost->Control.pipe_in, 0x80U, phost->device.address,
919 phost->device.speed, USBH_EP_CONTROL,
920 (uint16_t)phost->Control.pipe_size);
921
922 /* Open Control pipes */
923 USBH_OpenPipe(phost, phost->Control.pipe_out, 0x00U, phost->device.address,
924 phost->device.speed, USBH_EP_CONTROL,
925 (uint16_t)phost->Control.pipe_size);
926 }
927 else if (ReqStatus == USBH_NOT_SUPPORTED)
928 {
929 USBH_ErrLog("Control error: Device Set Address request failed");
930
931 /* Buggy Device can't complete get device desc request */
932 USBH_UsrLog("Control error, Device not Responding Please unplug the Device.");
933 phost->gState = HOST_ABORT_STATE;
934 phost->EnumState = ENUM_IDLE;
935 }
936 else
937 {
938 /* .. */
939 }
940 break;
941
942 case ENUM_GET_CFG_DESC:
943 /* get standard configuration descriptor */
944 ReqStatus = USBH_Get_CfgDesc(phost, USB_CONFIGURATION_DESC_SIZE);
945 if (ReqStatus == USBH_OK)
946 {
947 phost->EnumState = ENUM_GET_FULL_CFG_DESC;
948 }
949 else if (ReqStatus == USBH_NOT_SUPPORTED)
950 {
951 USBH_ErrLog("Control error: Get Device configuration descriptor request failed");
952 phost->device.EnumCnt++;
953 if (phost->device.EnumCnt > 3U)
954 {
955 /* Buggy Device can't complete get device desc request */
956 USBH_UsrLog("Control error, Device not Responding Please unplug the Device.");
957 phost->gState = HOST_ABORT_STATE;
958 }
959 else
960 {
961 /* Free control pipes */
962 USBH_FreePipe(phost, phost->Control.pipe_out);
963 USBH_FreePipe(phost, phost->Control.pipe_in);
964
965 /* Reset the USB Device */
966 phost->EnumState = ENUM_IDLE;
967 phost->gState = HOST_IDLE;
968 }
969 }
970 else
971 {
972 /* .. */
973 }
974 break;
975
976 case ENUM_GET_FULL_CFG_DESC:
977 /* get FULL config descriptor (config, interface, endpoints) */
978 ReqStatus = USBH_Get_CfgDesc(phost, phost->device.CfgDesc.wTotalLength);
979 if (ReqStatus == USBH_OK)
980 {
981 phost->EnumState = ENUM_GET_MFC_STRING_DESC;
982 }
983 else if (ReqStatus == USBH_NOT_SUPPORTED)
984 {
985 USBH_ErrLog("Control error: Get Device configuration descriptor request failed");
986 phost->device.EnumCnt++;
987 if (phost->device.EnumCnt > 3U)
988 {
989 /* Buggy Device can't complete get device desc request */
990 USBH_UsrLog("Control error, Device not Responding Please unplug the Device.");
991 phost->gState = HOST_ABORT_STATE;
992 }
993 else
994 {
995 /* Free control pipes */
996 USBH_FreePipe(phost, phost->Control.pipe_out);
997 USBH_FreePipe(phost, phost->Control.pipe_in);
998
999 /* Reset the USB Device */
1000 phost->EnumState = ENUM_IDLE;
1001 phost->gState = HOST_IDLE;
1002 }
1003 }
1004 else
1005 {
1006 /* .. */
1007 }
1008 break;
1009
1010 case ENUM_GET_MFC_STRING_DESC:
1011 if (phost->device.DevDesc.iManufacturer != 0U)
1012 {
1013 /* Check that Manufacturer String is available */
1014 ReqStatus = USBH_Get_StringDesc(phost, phost->device.DevDesc.iManufacturer,
1015 phost->device.Data, 0xFFU);
1016 if (ReqStatus == USBH_OK)
1017 {
1018 /* User callback for Manufacturing string */
1019 USBH_UsrLog("Manufacturer : %s", (char *)(void *)phost->device.Data);
1020 phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC;
1021
1022 #if (USBH_USE_OS == 1U)
1023 phost->os_msg = (uint32_t)USBH_STATE_CHANGED_EVENT;
1024 #if (osCMSIS < 0x20000U)
1025 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
1026 #else
1027 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
1028 #endif
1029 #endif
1030 }
1031 else if (ReqStatus == USBH_NOT_SUPPORTED)
1032 {
1033 USBH_UsrLog("Manufacturer : N/A");
1034 phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC;
1035
1036 #if (USBH_USE_OS == 1U)
1037 phost->os_msg = (uint32_t)USBH_STATE_CHANGED_EVENT;
1038 #if (osCMSIS < 0x20000U)
1039 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
1040 #else
1041 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
1042 #endif
1043 #endif
1044 }
1045 else
1046 {
1047 /* .. */
1048 }
1049 }
1050 else
1051 {
1052 USBH_UsrLog("Manufacturer : N/A");
1053 phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC;
1054
1055 #if (USBH_USE_OS == 1U)
1056 phost->os_msg = (uint32_t)USBH_STATE_CHANGED_EVENT;
1057 #if (osCMSIS < 0x20000U)
1058 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
1059 #else
1060 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
1061 #endif
1062 #endif
1063 }
1064 break;
1065
1066 case ENUM_GET_PRODUCT_STRING_DESC:
1067 if (phost->device.DevDesc.iProduct != 0U)
1068 {
1069 /* Check that Product string is available */
1070 ReqStatus = USBH_Get_StringDesc(phost, phost->device.DevDesc.iProduct,
1071 phost->device.Data, 0xFFU);
1072 if (ReqStatus == USBH_OK)
1073 {
1074 /* User callback for Product string */
1075 USBH_UsrLog("Product : %s", (char *)(void *)phost->device.Data);
1076 phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC;
1077 }
1078 else if (ReqStatus == USBH_NOT_SUPPORTED)
1079 {
1080 USBH_UsrLog("Product : N/A");
1081 phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC;
1082
1083 #if (USBH_USE_OS == 1U)
1084 phost->os_msg = (uint32_t)USBH_STATE_CHANGED_EVENT;
1085 #if (osCMSIS < 0x20000U)
1086 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
1087 #else
1088 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
1089 #endif
1090 #endif
1091 }
1092 else
1093 {
1094 /* .. */
1095 }
1096 }
1097 else
1098 {
1099 USBH_UsrLog("Product : N/A");
1100 phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC;
1101
1102 #if (USBH_USE_OS == 1U)
1103 phost->os_msg = (uint32_t)USBH_STATE_CHANGED_EVENT;
1104 #if (osCMSIS < 0x20000U)
1105 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
1106 #else
1107 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
1108 #endif
1109 #endif
1110 }
1111 break;
1112
1113 case ENUM_GET_SERIALNUM_STRING_DESC:
1114 if (phost->device.DevDesc.iSerialNumber != 0U)
1115 {
1116 /* Check that Serial number string is available */
1117 ReqStatus = USBH_Get_StringDesc(phost, phost->device.DevDesc.iSerialNumber,
1118 phost->device.Data, 0xFFU);
1119 if (ReqStatus == USBH_OK)
1120 {
1121 /* User callback for Serial number string */
1122 USBH_UsrLog("Serial Number : %s", (char *)(void *)phost->device.Data);
1123 Status = USBH_OK;
1124 }
1125 else if (ReqStatus == USBH_NOT_SUPPORTED)
1126 {
1127 USBH_UsrLog("Serial Number : N/A");
1128 Status = USBH_OK;
1129 }
1130 else
1131 {
1132 /* .. */
1133 }
1134 }
1135 else
1136 {
1137 USBH_UsrLog("Serial Number : N/A");
1138 Status = USBH_OK;
1139 }
1140 break;
1141
1142 default:
1143 break;
1144 }
1145 return Status;
1146 }
1147
1148
1149 /**
1150 * @brief USBH_LL_SetTimer
1151 * Set the initial Host Timer tick
1152 * @param phost: Host Handle
1153 * @retval None
1154 */
USBH_LL_SetTimer(USBH_HandleTypeDef * phost,uint32_t time)1155 void USBH_LL_SetTimer(USBH_HandleTypeDef *phost, uint32_t time)
1156 {
1157 phost->Timer = time;
1158 }
1159
1160
1161 /**
1162 * @brief USBH_LL_IncTimer
1163 * Increment Host Timer tick
1164 * @param phost: Host Handle
1165 * @retval None
1166 */
USBH_LL_IncTimer(USBH_HandleTypeDef * phost)1167 void USBH_LL_IncTimer(USBH_HandleTypeDef *phost)
1168 {
1169 phost->Timer++;
1170 USBH_HandleSof(phost);
1171 }
1172
1173
1174 /**
1175 * @brief USBH_HandleSof
1176 * Call SOF process
1177 * @param phost: Host Handle
1178 * @retval None
1179 */
USBH_HandleSof(USBH_HandleTypeDef * phost)1180 static void USBH_HandleSof(USBH_HandleTypeDef *phost)
1181 {
1182 if ((phost->gState == HOST_CLASS) && (phost->pActiveClass != NULL))
1183 {
1184 phost->pActiveClass->SOFProcess(phost);
1185 }
1186 }
1187
1188
1189 /**
1190 * @brief USBH_PortEnabled
1191 * Port Enabled
1192 * @param phost: Host Handle
1193 * @retval None
1194 */
USBH_LL_PortEnabled(USBH_HandleTypeDef * phost)1195 void USBH_LL_PortEnabled(USBH_HandleTypeDef *phost)
1196 {
1197 phost->device.PortEnabled = 1U;
1198
1199 #if (USBH_USE_OS == 1U)
1200 phost->os_msg = (uint32_t)USBH_PORT_EVENT;
1201 #if (osCMSIS < 0x20000U)
1202 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
1203 #else
1204 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
1205 #endif
1206 #endif
1207
1208 return;
1209 }
1210
1211
1212 /**
1213 * @brief USBH_LL_PortDisabled
1214 * Port Disabled
1215 * @param phost: Host Handle
1216 * @retval None
1217 */
USBH_LL_PortDisabled(USBH_HandleTypeDef * phost)1218 void USBH_LL_PortDisabled(USBH_HandleTypeDef *phost)
1219 {
1220 phost->device.PortEnabled = 0U;
1221
1222 return;
1223 }
1224
1225
1226 /**
1227 * @brief HCD_IsPortEnabled
1228 * Is Port Enabled
1229 * @param phost: Host Handle
1230 * @retval None
1231 */
USBH_IsPortEnabled(USBH_HandleTypeDef * phost)1232 uint8_t USBH_IsPortEnabled(USBH_HandleTypeDef *phost)
1233 {
1234 return (phost->device.PortEnabled);
1235 }
1236
1237
1238 /**
1239 * @brief USBH_LL_Connect
1240 * Handle USB Host connexion event
1241 * @param phost: Host Handle
1242 * @retval USBH_Status
1243 */
USBH_LL_Connect(USBH_HandleTypeDef * phost)1244 USBH_StatusTypeDef USBH_LL_Connect(USBH_HandleTypeDef *phost)
1245 {
1246 phost->device.is_connected = 1U;
1247 phost->device.is_disconnected = 0U;
1248 phost->device.is_ReEnumerated = 0U;
1249
1250
1251 #if (USBH_USE_OS == 1U)
1252 phost->os_msg = (uint32_t)USBH_PORT_EVENT;
1253 #if (osCMSIS < 0x20000U)
1254 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
1255 #else
1256 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
1257 #endif
1258 #endif
1259
1260 return USBH_OK;
1261 }
1262
1263
1264 /**
1265 * @brief USBH_LL_Disconnect
1266 * Handle USB Host disconnection event
1267 * @param phost: Host Handle
1268 * @retval USBH_Status
1269 */
USBH_LL_Disconnect(USBH_HandleTypeDef * phost)1270 USBH_StatusTypeDef USBH_LL_Disconnect(USBH_HandleTypeDef *phost)
1271 {
1272 /* update device connection states */
1273 phost->device.is_disconnected = 1U;
1274 phost->device.is_connected = 0U;
1275 phost->device.PortEnabled = 0U;
1276
1277 /* Stop Host */
1278 USBH_LL_Stop(phost);
1279
1280 /* FRee Control Pipes */
1281 USBH_FreePipe(phost, phost->Control.pipe_in);
1282 USBH_FreePipe(phost, phost->Control.pipe_out);
1283 #if (USBH_USE_OS == 1U)
1284 phost->os_msg = (uint32_t)USBH_PORT_EVENT;
1285 #if (osCMSIS < 0x20000U)
1286 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
1287 #else
1288 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
1289 #endif
1290 #endif
1291
1292 return USBH_OK;
1293 }
1294
1295
1296 #if (USBH_USE_OS == 1U)
1297 /**
1298 * @brief USB Host Thread task
1299 * @param pvParameters not used
1300 * @retval None
1301 */
1302
1303 #if (osCMSIS < 0x20000U)
USBH_Process_OS(void const * argument)1304 static void USBH_Process_OS(void const *argument)
1305 {
1306 osEvent event;
1307
1308 for (;;)
1309 {
1310 event = osMessageGet(((USBH_HandleTypeDef *)argument)->os_event, osWaitForever);
1311 if (event.status == osEventMessage)
1312 {
1313 USBH_Process((USBH_HandleTypeDef *)argument);
1314 }
1315 }
1316 }
1317 #else
USBH_Process_OS(void * argument)1318 static void USBH_Process_OS(void *argument)
1319 {
1320 osStatus_t status;
1321
1322 for (;;)
1323 {
1324 status = osMessageQueueGet(((USBH_HandleTypeDef *)argument)->os_event,
1325 &((USBH_HandleTypeDef *)argument)->os_msg, NULL, osWaitForever);
1326 if (status == osOK)
1327 {
1328 USBH_Process((USBH_HandleTypeDef *)argument);
1329 }
1330 }
1331 }
1332 #endif /* (osCMSIS < 0x20000U) */
1333
1334
1335 /**
1336 * @brief USBH_LL_NotifyURBChange
1337 * Notify URB state Change
1338 * @param phost: Host handle
1339 * @retval USBH Status
1340 */
USBH_LL_NotifyURBChange(USBH_HandleTypeDef * phost)1341 USBH_StatusTypeDef USBH_LL_NotifyURBChange(USBH_HandleTypeDef *phost)
1342 {
1343 phost->os_msg = (uint32_t)USBH_PORT_EVENT;
1344
1345 #if (osCMSIS < 0x20000U)
1346 (void)osMessagePut(phost->os_event, phost->os_msg, 0U);
1347 #else
1348 (void)osMessageQueuePut(phost->os_event, &phost->os_msg, 0U, NULL);
1349 #endif
1350
1351 return USBH_OK;
1352 }
1353 #endif
1354 /**
1355 * @}
1356 */
1357
1358 /**
1359 * @}
1360 */
1361
1362 /**
1363 * @}
1364 */
1365
1366 /**
1367 * @}
1368 */
1369
1370 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
1371