1 /**
2   ******************************************************************************
3   * @file    usbh_core.c
4   * @author  MCD Application Team
5   * @version V3.0.0
6   * @date    18-February-2014
7   * @brief   This file implements the functions for the core state machine process
8   *          the enumeration and the control transfer process
9   ******************************************************************************
10   * @attention
11   *
12   * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
13   *
14   * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
15   * You may not use this file except in compliance with the License.
16   * You may obtain a copy of the License at:
17   *
18   *        http://www.st.com/software_license_agreement_liberty_v2
19   *
20   * Unless required by applicable law or agreed to in writing, software
21   * distributed under the License is distributed on an "AS IS" BASIS,
22   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23   * See the License for the specific language governing permissions and
24   * limitations under the License.
25   *
26   ******************************************************************************
27   */
28 /* Includes ------------------------------------------------------------------*/
29 
30 #include "usbh_core.h"
31 
32 
33 /** @addtogroup USBH_LIB
34   * @{
35   */
36 
37 /** @addtogroup USBH_LIB_CORE
38   * @{
39   */
40 
41 /** @defgroup USBH_CORE
42   * @brief TThis file handles the basic enumaration when a device is connected
43   *          to the host.
44   * @{
45   */
46 
47 
48 /** @defgroup USBH_CORE_Private_Defines
49   * @{
50   */
51 #define USBH_ADDRESS_DEFAULT                     0
52 #define USBH_ADDRESS_ASSIGNED                    1
53 #define USBH_MPS_DEFAULT                         0x40
54 /**
55   * @}
56   */
57 
58 /** @defgroup USBH_CORE_Private_Macros
59   * @{
60   */
61 /**
62   * @}
63   */
64 
65 
66 /** @defgroup USBH_CORE_Private_Variables
67   * @{
68   */
69 /**
70   * @}
71   */
72 
73 
74 /** @defgroup USBH_CORE_Private_Functions
75   * @{
76   */
77 static USBH_StatusTypeDef  USBH_HandleEnum    (USBH_HandleTypeDef *phost);
78 static void                USBH_HandleSof     (USBH_HandleTypeDef *phost);
79 static USBH_StatusTypeDef  DeInitStateMachine(USBH_HandleTypeDef *phost);
80 
81 #if (USBH_USE_OS == 1)
82 static void USBH_Process_OS(void const * argument);
83 #endif
84 
85 /**
86   * @brief  HCD_Init
87   *         Initialize the HOST Core.
88   * @param  phost: Host Handle
89   * @param  pUsrFunc: User Callback
90   * @retval USBH Status
91   */
USBH_Init(USBH_HandleTypeDef * phost,void (* pUsrFunc)(USBH_HandleTypeDef * phost,uint8_t),uint8_t id)92 USBH_StatusTypeDef  USBH_Init(USBH_HandleTypeDef *phost, void (*pUsrFunc)(USBH_HandleTypeDef *phost, uint8_t ), uint8_t id)
93 {
94   /* Check whether the USB Host handle is valid */
95   if(phost == NULL)
96   {
97     USBH_ErrLog("Invalid Host handle");
98     return USBH_FAIL;
99   }
100 
101   /* Set DRiver ID */
102   phost->id = id;
103 
104   /* Unlink class*/
105   phost->pActiveClass = NULL;
106   phost->ClassNumber = 0;
107 
108   /* Restore default states and prepare EP0 */
109   DeInitStateMachine(phost);
110 
111   /* Assign User process */
112   if(pUsrFunc != NULL)
113   {
114     phost->pUser = pUsrFunc;
115   }
116 
117 #if (USBH_USE_OS == 1)
118 
119   /* Create USB Host Queue */
120   osMessageQDef(USBH_Queue, 10, uint16_t);
121   phost->os_event = osMessageCreate (osMessageQ(USBH_Queue), NULL);
122 
123   /*Create USB Host Task */
124   osThreadDef(USBH_Thread, USBH_Process_OS, USBH_PROCESS_PRIO, 0, 8 * configMINIMAL_STACK_SIZE);
125   phost->thread = osThreadCreate (osThread(USBH_Thread), phost);
126 #endif
127 
128   /* Initialize low level driver */
129   USBH_LL_Init(phost);
130   return USBH_OK;
131 }
132 
133 /**
134   * @brief  HCD_Init
135   *         De-Initialize the Host portion of the driver.
136   * @param  phost: Host Handle
137   * @retval USBH Status
138   */
USBH_DeInit(USBH_HandleTypeDef * phost)139 USBH_StatusTypeDef  USBH_DeInit(USBH_HandleTypeDef *phost)
140 {
141   DeInitStateMachine(phost);
142 
143   if(phost->pData != NULL)
144   {
145     phost->pActiveClass->pData = NULL;
146     USBH_LL_Stop(phost);
147   }
148 
149   return USBH_OK;
150 }
151 
152 /**
153   * @brief  DeInitStateMachine
154   *         De-Initialize the Host state machine.
155   * @param  phost: Host Handle
156   * @retval USBH Status
157   */
DeInitStateMachine(USBH_HandleTypeDef * phost)158 static USBH_StatusTypeDef  DeInitStateMachine(USBH_HandleTypeDef *phost)
159 {
160   uint32_t i = 0;
161 
162   /* Clear Pipes flags*/
163   for ( ; i < USBH_MAX_PIPES_NBR; i++)
164   {
165     phost->Pipes[i] = 0;
166   }
167 
168   for(i = 0; i< USBH_MAX_DATA_BUFFER; i++)
169   {
170     phost->device.Data[i] = 0;
171   }
172 
173   phost->gState = HOST_IDLE;
174   phost->EnumState = ENUM_IDLE;
175   phost->RequestState = CMD_SEND;
176   phost->Timer = 0;
177 
178   phost->Control.state = CTRL_SETUP;
179   phost->Control.pipe_size = USBH_MPS_DEFAULT;
180   phost->Control.errorcount = 0;
181 
182   phost->device.address = USBH_ADDRESS_DEFAULT;
183   phost->device.speed   = USBH_SPEED_FULL;
184 
185   return USBH_OK;
186 }
187 
188 /**
189   * @brief  USBH_RegisterClass
190   *         Link class driver to Host Core.
191   * @param  phost : Host Handle
192   * @param  pclass: Class handle
193   * @retval USBH Status
194   */
USBH_RegisterClass(USBH_HandleTypeDef * phost,USBH_ClassTypeDef * pclass)195 USBH_StatusTypeDef  USBH_RegisterClass(USBH_HandleTypeDef *phost, USBH_ClassTypeDef *pclass)
196 {
197   USBH_StatusTypeDef   status = USBH_OK;
198 
199   if(pclass != 0)
200   {
201     if(phost->ClassNumber < USBH_MAX_NUM_SUPPORTED_CLASS)
202     {
203       /* link the class tgo the USB Host handle */
204       phost->pClass[phost->ClassNumber++] = pclass;
205       status = USBH_OK;
206     }
207     else
208     {
209       USBH_ErrLog("Max Class Number reached");
210       status = USBH_FAIL;
211     }
212   }
213   else
214   {
215     USBH_ErrLog("Invalid Class handle");
216     status = USBH_FAIL;
217   }
218 
219   return status;
220 }
221 
222 /**
223   * @brief  USBH_SelectInterface
224   *         Select current interface.
225   * @param  phost: Host Handle
226   * @param  interface: Interface number
227   * @retval USBH Status
228   */
USBH_SelectInterface(USBH_HandleTypeDef * phost,uint8_t interface)229 USBH_StatusTypeDef USBH_SelectInterface(USBH_HandleTypeDef *phost, uint8_t interface)
230 {
231   USBH_StatusTypeDef   status = USBH_OK;
232 
233   if(interface < phost->device.CfgDesc.bNumInterfaces)
234   {
235     phost->device.current_interface = interface;
236     USBH_UsrLog ("Switching to Interface (#%d)", interface);
237     USBH_UsrLog ("Class    : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceClass );
238     USBH_UsrLog ("SubClass : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceSubClass );
239     USBH_UsrLog ("Protocol : %xh", phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol );
240   }
241   else
242   {
243     USBH_ErrLog ("Cannot Select This Interface.");
244     status = USBH_FAIL;
245   }
246   return status;
247 }
248 
249 /**
250   * @brief  USBH_GetActiveClass
251   *         Return Device Class.
252   * @param  phost: Host Handle
253   * @param  interface: Interface index
254   * @retval Class Code
255   */
USBH_GetActiveClass(USBH_HandleTypeDef * phost)256 uint8_t USBH_GetActiveClass(USBH_HandleTypeDef *phost)
257 {
258    return (phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass);
259 }
260 /**
261   * @brief  USBH_FindInterface
262   *         Find the interface index for a specific class.
263   * @param  phost: Host Handle
264   * @param  Class: Class code
265   * @param  SubClass: SubClass code
266   * @param  Protocol: Protocol code
267   * @retval interface index in the configuration structure
268   * @note : (1)interface index 0xFF means interface index not found
269   */
USBH_FindInterface(USBH_HandleTypeDef * phost,uint8_t Class,uint8_t SubClass,uint8_t Protocol)270 uint8_t  USBH_FindInterface(USBH_HandleTypeDef *phost, uint8_t Class, uint8_t SubClass, uint8_t Protocol)
271 {
272   USBH_InterfaceDescTypeDef    *pif ;
273   USBH_CfgDescTypeDef          *pcfg ;
274   int8_t                        if_ix = 0;
275 
276   pif = (USBH_InterfaceDescTypeDef *)0;
277   pcfg = &phost->device.CfgDesc;
278 
279   if((pif->bInterfaceClass == 0xFF) &&(pif->bInterfaceSubClass == 0xFF) && (pif->bInterfaceProtocol == 0xFF))
280   {
281     return 0xFF;
282   }
283 
284   while (if_ix < USBH_MAX_NUM_INTERFACES)
285   {
286     pif = &pcfg->Itf_Desc[if_ix];
287     if(((pif->bInterfaceClass == Class) || (Class == 0xFF))&&
288        ((pif->bInterfaceSubClass == SubClass) || (SubClass == 0xFF))&&
289          ((pif->bInterfaceProtocol == Protocol) || (Protocol == 0xFF)))
290     {
291       return  if_ix;
292     }
293     if_ix++;
294   }
295   return 0xFF;
296 }
297 
298 /**
299   * @brief  USBH_FindInterfaceIndex
300   *         Find the interface index for a specific class interface and alternate setting number.
301   * @param  phost: Host Handle
302   * @param  interface_number: interface number
303   * @param  alt_settings    : alaternate setting number
304   * @retval interface index in the configuration structure
305   * @note : (1)interface index 0xFF means interface index not found
306   */
USBH_FindInterfaceIndex(USBH_HandleTypeDef * phost,uint8_t interface_number,uint8_t alt_settings)307 uint8_t  USBH_FindInterfaceIndex(USBH_HandleTypeDef *phost, uint8_t interface_number, uint8_t alt_settings)
308 {
309   USBH_InterfaceDescTypeDef    *pif ;
310   USBH_CfgDescTypeDef          *pcfg ;
311   int8_t                        if_ix = 0;
312 
313   pif = (USBH_InterfaceDescTypeDef *)0;
314   pcfg = &phost->device.CfgDesc;
315 
316   while (if_ix < USBH_MAX_NUM_INTERFACES)
317   {
318     pif = &pcfg->Itf_Desc[if_ix];
319     if((pif->bInterfaceNumber == interface_number) && (pif->bAlternateSetting == alt_settings))
320     {
321       return  if_ix;
322     }
323     if_ix++;
324   }
325   return 0xFF;
326 }
327 
328 /**
329   * @brief  USBH_Start
330   *         Start the USB Host Core.
331   * @param  phost: Host Handle
332   * @retval USBH Status
333   */
USBH_Start(USBH_HandleTypeDef * phost)334 USBH_StatusTypeDef  USBH_Start  (USBH_HandleTypeDef *phost)
335 {
336   /* Start the low level driver  */
337   USBH_LL_Start(phost);
338 
339   /* Activate VBUS on the port */
340   USBH_LL_DriverVBUS (phost, TRUE);
341 
342   return USBH_OK;
343 }
344 
345 /**
346   * @brief  USBH_Stop
347   *         Stop the USB Host Core.
348   * @param  phost: Host Handle
349   * @retval USBH Status
350   */
USBH_Stop(USBH_HandleTypeDef * phost)351 USBH_StatusTypeDef  USBH_Stop   (USBH_HandleTypeDef *phost)
352 {
353   /* Stop and cleanup the low level driver  */
354   USBH_LL_Stop(phost);
355 
356   /* DeActivate VBUS on the port */
357   USBH_LL_DriverVBUS (phost, FALSE);
358 
359   /* FRee Control Pipes */
360   USBH_FreePipe  (phost, phost->Control.pipe_in);
361   USBH_FreePipe  (phost, phost->Control.pipe_out);
362 
363   return USBH_OK;
364 }
365 
366 /**
367   * @brief  HCD_ReEnumerate
368   *         Perform a new Enumeration phase.
369   * @param  phost: Host Handle
370   * @retval USBH Status
371   */
USBH_ReEnumerate(USBH_HandleTypeDef * phost)372 USBH_StatusTypeDef  USBH_ReEnumerate   (USBH_HandleTypeDef *phost)
373 {
374   /*Stop Host */
375   USBH_Stop(phost);
376 
377   /*Device has disconnected, so wait for 200 ms */
378   USBH_Delay(200);
379 
380   /* Set State machines in default state */
381   DeInitStateMachine(phost);
382 
383   /* Start again the host */
384   USBH_Start(phost);
385 
386 #if (USBH_USE_OS == 1)
387       osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0);
388 #endif
389   return USBH_OK;
390 }
391 
392 /**
393   * @brief  USBH_Process
394   *         Background process of the USB Core.
395   * @param  phost: Host Handle
396   * @retval USBH Status
397   */
USBH_Process(USBH_HandleTypeDef * phost)398 USBH_StatusTypeDef  USBH_Process(USBH_HandleTypeDef *phost)
399 {
400   __IO USBH_StatusTypeDef status = USBH_FAIL;
401   uint8_t idx = 0;
402 
403   switch (phost->gState)
404   {
405   case HOST_IDLE :
406 
407     if (phost->device.is_connected)
408     {
409       /* Wait for 200 ms after connection */
410       phost->gState = HOST_DEV_WAIT_FOR_ATTACHMENT;
411       USBH_Delay(200);
412       USBH_LL_ResetPort(phost);
413 #if (USBH_USE_OS == 1)
414       osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0);
415 #endif
416     }
417     break;
418 
419   case HOST_DEV_WAIT_FOR_ATTACHMENT:
420     break;
421 
422   case HOST_DEV_ATTACHED :
423 
424     USBH_UsrLog("USB Device Attached");
425 
426     /* Wait for 100 ms after Reset */
427     USBH_Delay(100);
428 
429     phost->device.speed = USBH_LL_GetSpeed(phost);
430 
431     phost->gState = HOST_ENUMERATION;
432 
433     phost->Control.pipe_out = USBH_AllocPipe (phost, 0x00);
434     phost->Control.pipe_in  = USBH_AllocPipe (phost, 0x80);
435 
436 
437     /* Open Control pipes */
438     USBH_OpenPipe (phost,
439                    phost->Control.pipe_in,
440                    0x80,
441                    phost->device.address,
442                    phost->device.speed,
443                    USBH_EP_CONTROL,
444                    phost->Control.pipe_size);
445 
446     /* Open Control pipes */
447     USBH_OpenPipe (phost,
448                    phost->Control.pipe_out,
449                    0x00,
450                    phost->device.address,
451                    phost->device.speed,
452                    USBH_EP_CONTROL,
453                    phost->Control.pipe_size);
454 
455 #if (USBH_USE_OS == 1)
456     osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0);
457 #endif
458 
459     break;
460 
461   case HOST_ENUMERATION:
462     /* Check for enumeration status */
463     if ( USBH_HandleEnum(phost) == USBH_OK)
464     {
465       /* The function shall return USBH_OK when full enumeration is complete */
466       USBH_UsrLog ("Enumeration done.");
467       phost->device.current_interface = 0;
468       if(phost->device.DevDesc.bNumConfigurations == 1)
469       {
470         USBH_UsrLog ("This device has only 1 configuration.");
471         phost->gState  = HOST_SET_CONFIGURATION;
472 
473       }
474       else
475       {
476         phost->gState  = HOST_INPUT;
477       }
478 
479     }
480     break;
481 
482   case HOST_INPUT:
483     {
484       /* user callback for end of device basic enumeration */
485       if(phost->pUser != NULL)
486       {
487         phost->pUser(phost, HOST_USER_SELECT_CONFIGURATION);
488         phost->gState = HOST_SET_CONFIGURATION;
489 
490 #if (USBH_USE_OS == 1)
491         osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
492 #endif
493       }
494     }
495     break;
496 
497   case HOST_SET_CONFIGURATION:
498     /* set configuration */
499     if (USBH_SetCfg(phost, phost->device.CfgDesc.bConfigurationValue) == USBH_OK)
500     {
501       phost->gState  = HOST_CHECK_CLASS;
502       USBH_UsrLog ("Default configuration set.");
503 
504     }
505 
506     break;
507 
508   case HOST_CHECK_CLASS:
509 
510     if(phost->ClassNumber == 0)
511     {
512       USBH_UsrLog ("No Class has been registered.");
513     }
514     else
515     {
516       phost->pActiveClass = NULL;
517 
518       for (idx = 0; idx < USBH_MAX_NUM_SUPPORTED_CLASS ; idx ++)
519       {
520         if(phost->pClass[idx]->ClassCode == phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass)
521         {
522           phost->pActiveClass = phost->pClass[idx];
523         }
524       }
525 
526       if(phost->pActiveClass != NULL)
527       {
528         if(phost->pActiveClass->Init(phost)== USBH_OK)
529         {
530           phost->gState  = HOST_CLASS_REQUEST;
531           USBH_UsrLog ("%s class started.", phost->pActiveClass->Name);
532 
533           /* Inform user that a class has been activated */
534           phost->pUser(phost, HOST_USER_CLASS_SELECTED);
535         }
536         else
537         {
538           phost->gState  = HOST_ABORT_STATE;
539           USBH_UsrLog ("Device not supporting %s class.", phost->pActiveClass->Name);
540         }
541       }
542       else
543       {
544         phost->gState  = HOST_ABORT_STATE;
545         USBH_UsrLog ("No registered class for this device.");
546       }
547     }
548 
549 #if (USBH_USE_OS == 1)
550     osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
551 #endif
552     break;
553 
554   case HOST_CLASS_REQUEST:
555     /* process class standard contol requests state machine */
556 
557     if(phost->pActiveClass != NULL)
558     {
559       status = phost->pActiveClass->Requests(phost);
560 
561       if(status == USBH_OK)
562       {
563         phost->gState  = HOST_CLASS;
564       }
565     }
566     else
567     {
568       phost->gState  = HOST_ABORT_STATE;
569       USBH_ErrLog ("Invalid Class Driver.");
570 
571 #if (USBH_USE_OS == 1)
572     osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
573 #endif
574     }
575 
576     break;
577   case HOST_CLASS:
578     /* process class state machine */
579     if(phost->pActiveClass != NULL)
580     {
581       phost->pActiveClass->BgndProcess(phost);
582     }
583     break;
584 
585   case HOST_DEV_DISCONNECTED :
586 
587     DeInitStateMachine(phost);
588 
589     /* Re-Initilaize Host for new Enumeration */
590     if(phost->pActiveClass != NULL)
591     {
592       phost->pActiveClass->DeInit(phost);
593       phost->pActiveClass = NULL;
594     }
595     break;
596 
597   case HOST_ABORT_STATE:
598   default :
599     break;
600   }
601  return USBH_OK;
602 }
603 
604 
605 /**
606   * @brief  USBH_HandleEnum
607   *         This function includes the complete enumeration process
608   * @param  phost: Host Handle
609   * @retval USBH_Status
610   */
USBH_HandleEnum(USBH_HandleTypeDef * phost)611 static USBH_StatusTypeDef USBH_HandleEnum (USBH_HandleTypeDef *phost)
612 {
613   USBH_StatusTypeDef Status = USBH_BUSY;
614 
615   switch (phost->EnumState)
616   {
617   case ENUM_IDLE:
618     /* Get Device Desc for only 1st 8 bytes : To get EP0 MaxPacketSize */
619     if ( USBH_Get_DevDesc(phost, 8) == USBH_OK)
620     {
621       phost->Control.pipe_size = phost->device.DevDesc.bMaxPacketSize;
622 
623       phost->EnumState = ENUM_GET_FULL_DEV_DESC;
624 
625       /* modify control channels configuration for MaxPacket size */
626       USBH_OpenPipe (phost,
627                            phost->Control.pipe_in,
628                            0x80,
629                            phost->device.address,
630                            phost->device.speed,
631                            USBH_EP_CONTROL,
632                            phost->Control.pipe_size);
633 
634       /* Open Control pipes */
635       USBH_OpenPipe (phost,
636                            phost->Control.pipe_out,
637                            0x00,
638                            phost->device.address,
639                            phost->device.speed,
640                            USBH_EP_CONTROL,
641                            phost->Control.pipe_size);
642 
643     }
644     break;
645 
646   case ENUM_GET_FULL_DEV_DESC:
647     /* Get FULL Device Desc  */
648     if ( USBH_Get_DevDesc(phost, USB_DEVICE_DESC_SIZE)== USBH_OK)
649     {
650       USBH_UsrLog("PID: %xh", phost->device.DevDesc.idProduct );
651       USBH_UsrLog("VID: %xh", phost->device.DevDesc.idVendor );
652 
653       phost->EnumState = ENUM_SET_ADDR;
654 
655     }
656     break;
657 
658   case ENUM_SET_ADDR:
659     /* set address */
660     if ( USBH_SetAddress(phost, USBH_DEVICE_ADDRESS) == USBH_OK)
661     {
662       USBH_Delay(2);
663       phost->device.address = USBH_DEVICE_ADDRESS;
664 
665       /* user callback for device address assigned */
666       USBH_UsrLog("Address (#%d) assigned.", phost->device.address);
667       phost->EnumState = ENUM_GET_CFG_DESC;
668 
669       /* modify control channels to update device address */
670       USBH_OpenPipe (phost,
671                            phost->Control.pipe_in,
672                            0x80,
673                            phost->device.address,
674                            phost->device.speed,
675                            USBH_EP_CONTROL,
676                            phost->Control.pipe_size);
677 
678       /* Open Control pipes */
679       USBH_OpenPipe (phost,
680                            phost->Control.pipe_out,
681                            0x00,
682                            phost->device.address,
683                            phost->device.speed,
684                            USBH_EP_CONTROL,
685                            phost->Control.pipe_size);
686     }
687     break;
688 
689   case ENUM_GET_CFG_DESC:
690     /* get standard configuration descriptor */
691     if ( USBH_Get_CfgDesc(phost,
692                           USB_CONFIGURATION_DESC_SIZE) == USBH_OK)
693     {
694       phost->EnumState = ENUM_GET_FULL_CFG_DESC;
695     }
696     break;
697 
698   case ENUM_GET_FULL_CFG_DESC:
699     /* get FULL config descriptor (config, interface, endpoints) */
700     if (USBH_Get_CfgDesc(phost,
701                          phost->device.CfgDesc.wTotalLength) == USBH_OK)
702     {
703       phost->EnumState = ENUM_GET_MFC_STRING_DESC;
704     }
705     break;
706 
707   case ENUM_GET_MFC_STRING_DESC:
708     if (phost->device.DevDesc.iManufacturer != 0)
709     { /* Check that Manufacturer String is available */
710 
711       if ( USBH_Get_StringDesc(phost,
712                                phost->device.DevDesc.iManufacturer,
713                                 phost->device.Data ,
714                                0xff) == USBH_OK)
715       {
716         /* User callback for Manufacturing string */
717         USBH_UsrLog("Manufacturer : %s",  (char *)phost->device.Data);
718         phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC;
719 
720 #if (USBH_USE_OS == 1)
721     osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
722 #endif
723       }
724     }
725     else
726     {
727      USBH_UsrLog("Manufacturer : N/A");
728      phost->EnumState = ENUM_GET_PRODUCT_STRING_DESC;
729 #if (USBH_USE_OS == 1)
730     osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
731 #endif
732     }
733     break;
734 
735   case ENUM_GET_PRODUCT_STRING_DESC:
736     if (phost->device.DevDesc.iProduct != 0)
737     { /* Check that Product string is available */
738       if ( USBH_Get_StringDesc(phost,
739                                phost->device.DevDesc.iProduct,
740                                phost->device.Data,
741                                0xff) == USBH_OK)
742       {
743         /* User callback for Product string */
744         USBH_UsrLog("Product : %s",  (char *)phost->device.Data);
745         phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC;
746       }
747     }
748     else
749     {
750       USBH_UsrLog("Product : N/A");
751       phost->EnumState = ENUM_GET_SERIALNUM_STRING_DESC;
752 #if (USBH_USE_OS == 1)
753     osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
754 #endif
755     }
756     break;
757 
758   case ENUM_GET_SERIALNUM_STRING_DESC:
759     if (phost->device.DevDesc.iSerialNumber != 0)
760     { /* Check that Serial number string is available */
761       if ( USBH_Get_StringDesc(phost,
762                                phost->device.DevDesc.iSerialNumber,
763                                phost->device.Data,
764                                0xff) == USBH_OK)
765       {
766         /* User callback for Serial number string */
767          USBH_UsrLog("Serial Number : %s",  (char *)phost->device.Data);
768         Status = USBH_OK;
769       }
770     }
771     else
772     {
773       USBH_UsrLog("Serial Number : N/A");
774       Status = USBH_OK;
775 #if (USBH_USE_OS == 1)
776     osMessagePut ( phost->os_event, USBH_STATE_CHANGED_EVENT, 0);
777 #endif
778     }
779     break;
780 
781   default:
782     break;
783   }
784   return Status;
785 }
786 
787 /**
788   * @brief  USBH_LL_SetTimer
789   *         Set the initial Host Timer tick
790   * @param  phost: Host Handle
791   * @retval None
792   */
USBH_LL_SetTimer(USBH_HandleTypeDef * phost,uint32_t time)793 void  USBH_LL_SetTimer  (USBH_HandleTypeDef *phost, uint32_t time)
794 {
795   phost->Timer = time;
796 }
797 /**
798   * @brief  USBH_LL_IncTimer
799   *         Increment Host Timer tick
800   * @param  phost: Host Handle
801   * @retval None
802   */
USBH_LL_IncTimer(USBH_HandleTypeDef * phost)803 void  USBH_LL_IncTimer  (USBH_HandleTypeDef *phost)
804 {
805   phost->Timer ++;
806   USBH_HandleSof(phost);
807 }
808 
809 /**
810   * @brief  USBH_HandleSof
811   *         Call SOF process
812   * @param  phost: Host Handle
813   * @retval None
814   */
USBH_HandleSof(USBH_HandleTypeDef * phost)815 void  USBH_HandleSof  (USBH_HandleTypeDef *phost)
816 {
817   if((phost->gState == HOST_CLASS)&&(phost->pActiveClass != NULL))
818   {
819     phost->pActiveClass->SOFProcess(phost);
820   }
821 }
822 /**
823   * @brief  USBH_LL_Connect
824   *         Handle USB Host connexion event
825   * @param  phost: Host Handle
826   * @retval USBH_Status
827   */
USBH_LL_Connect(USBH_HandleTypeDef * phost)828 USBH_StatusTypeDef  USBH_LL_Connect  (USBH_HandleTypeDef *phost)
829 {
830   if(phost->gState == HOST_IDLE )
831   {
832     phost->device.is_connected = 1;
833     phost->gState = HOST_IDLE ;
834 
835     if(phost->pUser != NULL)
836     {
837       phost->pUser(phost, HOST_USER_CONNECTION);
838     }
839   }
840   else if(phost->gState == HOST_DEV_WAIT_FOR_ATTACHMENT )
841   {
842     phost->gState = HOST_DEV_ATTACHED ;
843   }
844 #if (USBH_USE_OS == 1)
845   osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0);
846 #endif
847 
848   return USBH_OK;
849 }
850 
851 /**
852   * @brief  USBH_LL_Disconnect
853   *         Handle USB Host disconnexion event
854   * @param  phost: Host Handle
855   * @retval USBH_Status
856   */
USBH_LL_Disconnect(USBH_HandleTypeDef * phost)857 USBH_StatusTypeDef  USBH_LL_Disconnect  (USBH_HandleTypeDef *phost)
858 {
859   /*Stop Host */
860   USBH_LL_Stop(phost);
861 
862   /* FRee Control Pipes */
863   USBH_FreePipe  (phost, phost->Control.pipe_in);
864   USBH_FreePipe  (phost, phost->Control.pipe_out);
865 
866   phost->device.is_connected = 0;
867 
868   if(phost->pUser != NULL)
869   {
870     phost->pUser(phost, HOST_USER_DISCONNECTION);
871   }
872   USBH_UsrLog("USB Device disconnected");
873 
874   /* Start the low level driver  */
875   USBH_LL_Start(phost);
876 
877   phost->gState = HOST_DEV_DISCONNECTED;
878 
879 #if (USBH_USE_OS == 1)
880   osMessagePut ( phost->os_event, USBH_PORT_EVENT, 0);
881 #endif
882 
883   return USBH_OK;
884 }
885 
886 
887 #if (USBH_USE_OS == 1)
888 /**
889   * @brief  USB Host Thread task
890   * @param  pvParameters not used
891   * @retval None
892   */
USBH_Process_OS(void const * argument)893 static void USBH_Process_OS(void const * argument)
894 {
895   osEvent event;
896 
897   for(;;)
898   {
899     event = osMessageGet(((USBH_HandleTypeDef *)argument)->os_event, osWaitForever );
900 
901     if( event.status == osEventMessage )
902     {
903       USBH_Process((USBH_HandleTypeDef *)argument);
904     }
905    }
906 }
907 
908 /**
909 * @brief  USBH_LL_NotifyURBChange
910 *         Notify URB state Change
911 * @param  phost: Host handle
912 * @retval USBH Status
913 */
USBH_LL_NotifyURBChange(USBH_HandleTypeDef * phost)914 USBH_StatusTypeDef  USBH_LL_NotifyURBChange (USBH_HandleTypeDef *phost)
915 {
916   osMessagePut ( phost->os_event, USBH_URB_EVENT, 0);
917   return USBH_OK;
918 }
919 #endif
920 /**
921   * @}
922   */
923 
924 /**
925   * @}
926   */
927 
928 /**
929   * @}
930   */
931 
932 /**
933   * @}
934   */
935 
936 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
937