1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016,2019 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "usb_host_config.h"
10 #if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
11 
12 #include "usb_host.h"
13 #include "usb_host_hub.h"
14 #include "usb_host_hci.h"
15 #include "usb_host_hub_app.h"
16 #include "usb_host_devices.h"
17 
18 /*******************************************************************************
19  * Definitions
20  ******************************************************************************/
21 
22 #define USB_HostHubLockMutexCheck() hubGlobal->hubMutex != NULL
23 /*! @brief HUB lock */
24 #define USB_HostHubLock() OSA_MutexLock(hubGlobal->hubMutex, USB_OSA_WAIT_TIMEOUT)
25 /*! @brief HUB unlock */
26 #define USB_HostHubUnlock() OSA_MutexUnlock(hubGlobal->hubMutex)
27 
28 /*******************************************************************************
29  * Prototypes
30  ******************************************************************************/
31 
32 /*!
33  * @brief prime interrupt in data.
34  *
35  * @param hubInstance   hub instance pointer.
36  */
37 static void USB_HostHubGetInterruptStatus(usb_host_hub_instance_t *hubInstance);
38 
39 /*!
40  * @brief hub process state machine. hub is enable after the state machine.
41  *
42  * @param hubInstance  hub instance pointer.
43  */
44 static void USB_HostHubProcess(usb_host_hub_instance_t *hubInstance);
45 
46 /*!
47  * @brief hub port attach process state machine. one device is attached to the port after the state machine.
48  *
49  * @param hubInstance  hub instance pointer.
50  */
51 static void USB_HostHubProcessPortAttach(usb_host_hub_instance_t *hubInstance);
52 
53 /*!
54  * @brief hub port detach process state machine. one device is detached from the port after the state machine.
55  *
56  * @param hubInstance  hub instance pointer.
57  */
58 static void USB_HostHubProcessPortDetach(usb_host_hub_instance_t *hubInstance);
59 
60 /*!
61  * @brief hub port process.
62  *
63  * @param hubInstance  hub instance pointer.
64  */
65 static void USB_HostHubProcessPort(usb_host_hub_instance_t *hubInstance);
66 
67 /*!
68  * @brief hub interrupt in data process.
69  *
70  * @param hubInstance  hub instance pointer.
71  */
72 static void USB_HostHubProcessData(usb_host_hub_global_t *hubGlobal, usb_host_hub_instance_t *hubInstance);
73 
74 /*!
75  * @brief hub control pipe transfer callback.
76  *
77  * @param param       callback parameter.
78  * @param transfer    callback transfer.
79  * @param status      transfer status.
80  */
81 static void USB_HostHubControlCallback(void *param, uint8_t *data, uint32_t data_len, usb_status_t status);
82 
83 /*!
84  * @brief hub interrupt pipe transfer callback.
85  *
86  * @param param       callback parameter.
87  * @param transfer    callback transfer.
88  * @param status      transfer status.
89  */
90 void USB_HostHubInterruptInCallback(void *param, uint8_t *data, uint32_t data_len, usb_status_t status);
91 
92 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
93 static usb_status_t USB_HostSendHubRequest(usb_device_handle deviceHandle,
94                                            uint8_t requestType,
95                                            uint8_t request,
96                                            uint16_t wvalue,
97                                            uint16_t windex,
98                                            host_inner_transfer_callback_t callbackFn,
99                                            void *callbackParam);
100 
101 #endif
102 /*******************************************************************************
103  * Variables
104  ******************************************************************************/
105 
106 static usb_device_handle s_HubDeviceHandle;
107 static usb_host_interface_handle s_HubInterfaceHandle;
108 static usb_host_hub_global_t s_HubGlobalArray[USB_HOST_CONFIG_MAX_HOST];
109 
110 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
111 static usb_host_configuration_t *s_HubConfiguration;
112 #endif
113 
114 /*******************************************************************************
115  * Code
116  ******************************************************************************/
117 
USB_HostHubGetHubList(usb_host_handle hostHandle)118 static usb_host_hub_global_t *USB_HostHubGetHubList(usb_host_handle hostHandle)
119 {
120 #if (USB_HOST_CONFIG_MAX_HOST == 1U)
121     return &s_HubGlobalArray[0];
122 #else
123     uint8_t index;
124     for (index = 0; index < (uint8_t)USB_HOST_CONFIG_MAX_HOST; ++index)
125     {
126         if (s_HubGlobalArray[index].hostHandle == hostHandle)
127         {
128             return &s_HubGlobalArray[index];
129         }
130     }
131     /* There is no used usb_host_hub_global_t instance */
132     for (index = 0; index < (uint8_t)USB_HOST_CONFIG_MAX_HOST; ++index)
133     {
134         if (s_HubGlobalArray[index].hostHandle == NULL)
135         {
136             s_HubGlobalArray[index].hostHandle = hostHandle;
137             return &s_HubGlobalArray[index];
138         }
139     }
140     /* Look for the usb_host_hub_global_t instance that is not used any more */
141     for (index = 0; index < (uint8_t)USB_HOST_CONFIG_MAX_HOST; ++index)
142     {
143         if (s_HubGlobalArray[index].hubList == NULL)
144         {
145             s_HubGlobalArray[index].hostHandle = hostHandle;
146             return &s_HubGlobalArray[index];
147         }
148     }
149     return NULL;
150 #endif
151 }
152 
USB_HostHubGetInterruptStatus(usb_host_hub_instance_t * hubInstance)153 static void USB_HostHubGetInterruptStatus(usb_host_hub_instance_t *hubInstance)
154 {
155     uint16_t portNum;
156     if (hubInstance == NULL)
157     {
158         return;
159     }
160 
161     /* there is no prime for control or interrupt */
162     if (hubInstance->primeStatus != (uint8_t)kPrimeNone)
163     {
164         return;
165     }
166     portNum = (((uint16_t)hubInstance->portCount) >> 3U);
167     /* receive interrupt data */
168     if (USB_HostHubInterruptRecv(hubInstance, hubInstance->hubBitmapBuffer, (portNum + 1U),
169                                  USB_HostHubInterruptInCallback, hubInstance) != kStatus_USB_Success)
170     {
171 #ifdef HOST_ECHO
172         usb_echo("error in hub interrupt recv\r\n");
173 #endif
174     }
175     else
176     {
177         hubInstance->primeStatus = (uint8_t)kPrimeInterrupt;
178     }
179 }
180 
USB_HostHubProcess(usb_host_hub_instance_t * hubInstance)181 static void USB_HostHubProcess(usb_host_hub_instance_t *hubInstance)
182 {
183     uint8_t needPrimeInterrupt = 0; /* need to prime interrupt in transfer (0 - don't need; 1 - need) */
184     uint8_t processSuccess     = 0; /* the code execute successfully (0 - fail; 1 - success) */
185     uint32_t tmp               = 0;
186     usb_host_hub_descriptor_t *hubDescriptor;
187     void *temp;
188     usb_host_hub_app_status_t appStatus;
189     uint16_t portNum;
190 
191     appStatus = (usb_host_hub_app_status_t)hubInstance->hubStatus;
192     switch (appStatus)
193     {
194         case kHubRunIdle:
195         case kHubRunInvalid:
196             break;
197 
198         case kHubRunWaitSetInterface:
199             hubInstance->hubStatus = (uint8_t)kHubRunGetDescriptor7; /* update as next state */
200             /* get hub descriptor */
201             if (USB_HostHubGetDescriptor(hubInstance, hubInstance->hubDescriptor, 7, USB_HostHubControlCallback,
202                                          hubInstance) == kStatus_USB_Success)
203             {
204                 hubInstance->primeStatus = (uint8_t)kPrimeHubControl; /* control transfer is on-going */
205                 processSuccess           = 1U;
206 #ifdef HOST_ECHO
207                 usb_echo("hub get descriptor 7\r\n");
208 #endif
209             }
210             else
211             {
212 #ifdef HOST_ECHO
213                 usb_echo("hub get descriptor 7 error\r\n");
214 #endif
215                 break;
216             }
217             break;
218 
219         case kHubRunGetDescriptor7:
220             temp          = (void *)&hubInstance->hubDescriptor[0];
221             hubDescriptor = (usb_host_hub_descriptor_t *)temp;
222 
223             /* get the hub think time */
224             (void)USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, (uint32_t)kUSB_HostGetHubThinkTime,
225                                                          &tmp);
226             hubInstance->totalThinktime = (uint16_t)tmp;
227             tmp                         = ((((uint32_t)hubDescriptor->whubcharacteristics[0] &
228                      USB_HOST_HUB_DESCRIPTOR_CHARACTERISTICS_THINK_TIME_MASK) >>
229                     USB_HOST_HUB_DESCRIPTOR_CHARACTERISTICS_THINK_TIME_SHIFT));
230             /*
231             00 - 8 FS bit times;
232             01 - 16 FS bit times;
233             10 - 24 FS bit times;
234             11 - 32 FS bit times;
235             */
236             tmp = (tmp + 1U) << 3U;
237             hubInstance->totalThinktime += (uint16_t)tmp;
238 
239             /* get hub port number */
240             hubInstance->portCount = hubDescriptor->bnrports;
241             if (hubInstance->portCount > USB_HOST_HUB_MAX_PORT)
242             {
243 #ifdef HOST_ECHO
244                 usb_echo("port number is bigger than USB_HOST_HUB_MAX_PORT\r\n");
245 #endif
246                 return;
247             }
248 
249             hubInstance->hubStatus = (uint8_t)kHubRunSetPortPower; /* update as next state */
250             /* get hub descriptor */
251             portNum = (((uint16_t)hubInstance->portCount) >> 3U);
252             if (USB_HostHubGetDescriptor(hubInstance, hubInstance->hubDescriptor, ((uint16_t)7UL + (portNum) + 1U),
253                                          USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
254             {
255                 hubInstance->primeStatus = (uint8_t)kPrimeHubControl; /* control transfer is on-going */
256                 processSuccess           = 1U;
257 #ifdef HOST_ECHO
258                 usb_echo("hub get descriptor\r\n");
259 #endif
260             }
261             else
262             {
263 #ifdef HOST_ECHO
264                 usb_echo("hub get descriptor error\r\n");
265 #endif
266                 break;
267             }
268             break;
269         /*remove kHubRunGetDescriptor state for misra 16.3*/
270         case kHubRunSetPortPower:
271             /* malloc port instance for the hub's ports */
272             if (NULL == hubInstance->portList)
273             {
274                 hubInstance->portList = (usb_host_hub_port_instance_t *)OSA_MemoryAllocate(
275                     ((uint32_t)hubInstance->portCount) * sizeof(usb_host_hub_port_instance_t));
276                 if (hubInstance->portList == NULL)
277                 {
278 #ifdef HOST_ECHO
279                     usb_echo("port list allocate fail\r\n");
280 #endif
281                     hubInstance->hubStatus = (uint8_t)kHubRunInvalid;
282                     break;
283                 }
284                 /* TODO: port instance status -> can be removed.  app_status */
285                 hubInstance->portIndex = 0U;
286             }
287             /* set PORT_POWER for all ports */
288             if (hubInstance->portIndex < hubInstance->portCount)
289             {
290                 hubInstance->portIndex++;
291                 if (USB_HostHubSetPortFeature(hubInstance, hubInstance->portIndex, PORT_POWER,
292                                               USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
293                 {
294                     hubInstance->primeStatus = (uint8_t)kPrimeHubControl; /* update as next state */
295                     processSuccess           = 1U;
296 #ifdef HOST_ECHO
297                     usb_echo("set port feature PORT_POWER\r\n");
298 #endif
299                 }
300                 else
301                 {
302 #ifdef HOST_ECHO
303                     usb_echo("set port feature PORT_POWER fail\r\n");
304 #endif
305                     needPrimeInterrupt = 1U;
306                     break;
307                 }
308                 break;
309             }
310             hubInstance->portProcess = 0U;
311             /* reset port information as default */
312             for (tmp = 0; tmp < hubInstance->portCount; ++tmp)
313             {
314                 hubInstance->portList[tmp].deviceHandle = NULL;
315                 hubInstance->portList[tmp].resetCount   = USB_HOST_HUB_PORT_RESET_TIMES;
316                 hubInstance->portList[tmp].portStatus   = (uint8_t)kPortRunWaitPortChange;
317             }
318             hubInstance->hubStatus = (uint8_t)kHubRunIdle;
319             needPrimeInterrupt     = 1U;
320             break;
321 
322         case kHubRunGetStatusDone: /* process hub status change */
323             tmp                    = USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS((&hubInstance->hubStatusBuffer[2]));
324             hubInstance->hubStatus = (uint8_t)kHubRunIdle;
325             if (0U != ((1UL << C_HUB_LOCAL_POWER) & tmp)) /* C_HUB_LOCAL_POWER */
326             {
327                 if (USB_HostHubClearFeature(hubInstance, C_HUB_LOCAL_POWER, USB_HostHubControlCallback, hubInstance) ==
328                     kStatus_USB_Success)
329                 {
330                     hubInstance->primeStatus = (uint8_t)kPrimeHubControl;
331                     hubInstance->hubStatus   = (uint8_t)kHubRunClearDone;
332                     processSuccess           = 1U;
333                 }
334                 else
335                 {
336                     needPrimeInterrupt = 1U;
337                 }
338             }
339             else if (0U != ((1UL << C_HUB_OVER_CURRENT) & tmp)) /* C_HUB_OVER_CURRENT */
340             {
341                 if (USB_HostHubClearFeature(hubInstance, C_HUB_OVER_CURRENT, USB_HostHubControlCallback, hubInstance) ==
342                     kStatus_USB_Success)
343                 {
344                     hubInstance->primeStatus = (uint8_t)kPrimeHubControl;
345                     processSuccess           = 1U;
346                     hubInstance->hubStatus   = (uint8_t)kHubRunClearDone;
347                 }
348                 else
349                 {
350                     needPrimeInterrupt = 1U;
351                 }
352             }
353             else
354             {
355                 needPrimeInterrupt = 1U;
356             }
357             break;
358 
359         case kHubRunClearDone:
360             hubInstance->hubStatus = (uint8_t)kHubRunIdle;
361             needPrimeInterrupt     = 1U;
362             break;
363 
364         default:
365             /*no action*/
366             break;
367     }
368 
369     if (needPrimeInterrupt == 1U) /* prime interrupt in transfer */
370     {
371         hubInstance->hubStatus = (uint8_t)kHubRunIdle;
372         USB_HostHubGetInterruptStatus(hubInstance);
373     }
374     else
375     {
376         if (processSuccess == 0U)
377         {
378             hubInstance->hubStatus = (uint8_t)kHubRunInvalid;
379         }
380     }
381 }
382 
USB_HostHubProcessPort(usb_host_hub_instance_t * hubInstance)383 static void USB_HostHubProcessPort(usb_host_hub_instance_t *hubInstance)
384 {
385     usb_host_hub_port_instance_t *portInstance = &hubInstance->portList[hubInstance->portProcess - 1U];
386 
387     /* for device attach */
388     if (portInstance->deviceHandle == NULL)
389     {
390         USB_HostHubProcessPortAttach(hubInstance);
391     }
392     else /* for device detach */
393     {
394         USB_HostHubProcessPortDetach(hubInstance);
395     }
396 }
397 
USB_HostHubProcessPortAttach(usb_host_hub_instance_t * hubInstance)398 static void USB_HostHubProcessPortAttach(usb_host_hub_instance_t *hubInstance)
399 {
400     usb_host_hub_port_instance_t *portInstance = &hubInstance->portList[hubInstance->portProcess - 1U];
401     uint8_t processSuccess                     = 0U;
402     uint32_t specStatus;
403     uint8_t feature;
404     uint32_t infoValue               = 0U;
405     usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hubInstance->hostHandle);
406     usb_host_port_app_status_t appStatus;
407     if (hubGlobal == NULL)
408     {
409         return;
410     }
411     appStatus = (usb_host_port_app_status_t)portInstance->portStatus;
412     switch (appStatus)
413     {
414         case kPortRunIdle:
415             break;
416         case kPortRunInvalid:
417             break;
418         case kPortRunWaitPortChange: /* (1) port is changed, and get port status */
419             portInstance->portStatus = (uint8_t)kPortRunCheckCPortConnection; /* update as next state */
420             /* send class-specific request to get port status */
421             if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4,
422                                          USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
423             {
424                 hubInstance->primeStatus = (uint8_t)kPrimePortControl;
425                 processSuccess           = 1U;
426             }
427             break;
428 
429         case kPortRunCheckCPortConnection: /* (2) check port status, and clear the status bits */
430             feature    = 0U;
431             specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS((hubInstance->portStatusBuffer));
432             if (0U != ((1UL << C_PORT_CONNECTION) & specStatus))
433             {
434                 portInstance->portStatus = (uint8_t)kPortRunGetPortConnection; /* update as next state */
435                 /* clear C_PORT_CONNECTION */
436                 if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_CONNECTION,
437                                                 USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
438                 {
439                     hubInstance->primeStatus = (uint8_t)kPrimePortControl;
440                     processSuccess           = 1U;
441                 }
442                 break;
443             }
444             else if (0U != ((1UL << PORT_CONNECTION) & specStatus))
445             {
446                 portInstance->portStatus = (uint8_t)kPortRunWaitPortResetDone; /* update as next state */
447                 /* set PORT_RESET */
448                 if (USB_HostHubSetPortFeature(hubInstance, hubInstance->portProcess, PORT_RESET,
449                                               USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
450                 {
451                     hubInstance->primeStatus = (uint8_t)kPrimePortControl;
452                     processSuccess           = 1U;
453                     if (portInstance->resetCount > 0U)
454                     {
455                         portInstance->resetCount--;
456                     }
457                 }
458                 break;
459             }
460             else if (0U != ((1UL << C_PORT_RESET) & specStatus))
461             {
462                 feature = C_PORT_RESET; /* clear C_PORT_RESET */
463 #ifdef HOST_ECHO
464                 usb_echo("hub: C_PORT_RESET when detached\r\n");
465 #endif
466             }
467             else if (0U != ((1UL << C_PORT_ENABLE) & specStatus))
468             {
469                 feature = C_PORT_ENABLE; /* clear C_PORT_ENABLE */
470 #ifdef HOST_ECHO
471                 usb_echo("hub: C_PORT_ENABLE when detached\r\n");
472 #endif
473             }
474             else if (0U != ((1UL << C_PORT_OVER_CURRENT) & specStatus))
475             {
476                 feature = C_PORT_OVER_CURRENT; /* clear C_PORT_OVER_CURRENT */
477 #ifdef HOST_ECHO
478                 usb_echo("hub: C_PORT_OVER_CURRENT when detached\r\n");
479 #endif
480             }
481             else
482             {
483                 /*no action*/
484             }
485 
486             if (feature != 0U)
487             {
488                 portInstance->portStatus = (uint8_t)kPortRunWaitPortChange; /* update as next state */
489                 /* clear feature */
490                 if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, feature,
491                                                 USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
492                 {
493                     hubInstance->primeStatus = (uint8_t)kPrimePortControl;
494                     processSuccess           = 1U;
495                 }
496             }
497             break;
498 
499         case kPortRunGetPortConnection:                                      /* (3) get port status */
500             portInstance->portStatus = (uint8_t)kPortRunCheckPortConnection; /* update as next state */
501             /* get port status bits */
502             if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4,
503                                          USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
504             {
505                 hubInstance->primeStatus = (uint8_t)kPrimePortControl; /* control transfer is on-going */
506                 processSuccess           = 1U;
507             }
508             break;
509 
510         case kPortRunCheckPortConnection: /* (4) check PORT_CONNECTION bit */
511             specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer);
512             if (0U != ((1UL << PORT_CONNECTION) & specStatus))
513             {
514                 portInstance->portStatus = (uint8_t)kPortRunWaitPortResetDone; /* update as next state */
515                 /* set PORT_RESET */
516                 if (USB_HostHubSetPortFeature(hubInstance, hubInstance->portProcess, PORT_RESET,
517                                               USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
518                 {
519                     hubInstance->primeStatus = (uint8_t)kPrimePortControl;
520                     processSuccess           = 1;
521                     if (portInstance->resetCount > 0U)
522                     {
523                         portInstance->resetCount--;
524                     }
525                 }
526             }
527             break;
528 
529         case kPortRunWaitPortResetDone:                                 /* (5) wait port change */
530             portInstance->portStatus = (uint8_t)kPortRunWaitCPortReset; /* update as next state */
531             processSuccess           = 1U;
532             /* must wait the enumeration done, then operate the next port */
533             USB_HostHubGetInterruptStatus(hubInstance);
534             break;
535 
536         case kPortRunWaitCPortReset: /* (6) get port status for checking C_PORT_RESET */
537             portInstance->portStatus = (uint8_t)KPortRunCheckCPortReset; /* update as next state */
538             /* get port status bits */
539             if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4,
540                                          USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
541             {
542                 hubInstance->primeStatus = (uint8_t)kPrimePortControl;
543                 processSuccess           = 1U;
544             }
545             break;
546 
547         case KPortRunCheckCPortReset: /* (7) check C_PORT_RESET and clear C_PORT_RESET */
548             specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer);
549             if (0U != ((1UL << C_PORT_RESET) & specStatus))
550             {
551                 if (portInstance->resetCount == 0U)
552                 {
553                     portInstance->portStatus = (uint8_t)kPortRunPortAttached; /* update as next state */
554                     /* get port's device speed */
555                     if (0U != (specStatus & (1UL << PORT_HIGH_SPEED)))
556                     {
557                         portInstance->speed = USB_SPEED_HIGH;
558                     }
559                     else if (0U != (specStatus & (1UL << PORT_LOW_SPEED)))
560                     {
561                         portInstance->speed = USB_SPEED_LOW;
562                     }
563                     else
564                     {
565                         portInstance->speed = USB_SPEED_FULL;
566                     }
567                 }
568                 else
569                 {
570                     portInstance->portStatus = (uint8_t)kPortRunResetAgain; /* update as next state */
571                 }
572 
573                 /* clear C_PORT_RESET */
574                 if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_RESET,
575                                                 USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
576                 {
577                     hubInstance->primeStatus = (uint8_t)kPrimePortControl;
578                     processSuccess           = 1U;
579                 }
580             }
581             break;
582 
583         case kPortRunResetAgain:                                             /* (8) reset again */
584             portInstance->portStatus = (uint8_t)kPortRunCheckPortConnection; /* check connection then reset again */
585             if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4,
586                                          USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
587             {
588                 hubInstance->primeStatus = (uint8_t)kPrimePortControl;
589                 processSuccess           = 1U;
590             }
591             break;
592 
593         case kPortRunPortAttached: /* (9) the port have one device attached */
594             /*zero initilzied for misra 9.1*/
595             infoValue = 0U;
596             (void)USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, (uint32_t)kUSB_HostGetDeviceAddress,
597                                                          &infoValue);
598             (void)USB_HostAttachDevice(hubInstance->hostHandle, portInstance->speed, (uint8_t)infoValue,
599                                        hubInstance->portProcess, hubInstance->hubLevel + 1U,
600                                        &portInstance->deviceHandle);
601             processSuccess           = 1U;
602             hubInstance->portProcess = 0U;
603             hubGlobal->hubProcess    = NULL;
604             portInstance->resetCount = USB_HOST_HUB_PORT_RESET_TIMES;
605             USB_HostHubGetInterruptStatus(hubInstance);
606             break;
607         default:
608             /*no actino*/
609             break;
610     }
611 
612     if (processSuccess == 0U)
613     {
614         portInstance->portStatus = (uint8_t)kPortRunWaitPortChange;
615         hubInstance->portProcess = 0U;
616         hubGlobal->hubProcess    = NULL;
617         portInstance->resetCount = USB_HOST_HUB_PORT_RESET_TIMES;
618 
619         USB_HostHubGetInterruptStatus(hubInstance);
620     }
621 }
622 
USB_HostHubProcessPortDetach(usb_host_hub_instance_t * hubInstance)623 static void USB_HostHubProcessPortDetach(usb_host_hub_instance_t *hubInstance)
624 {
625     usb_host_hub_port_instance_t *portInstance = &hubInstance->portList[hubInstance->portProcess - 1U];
626 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
627     usb_host_instance_t *hostPointer = (usb_host_instance_t *)hubInstance->hostHandle;
628 #endif
629     uint8_t processSuccess = 0;
630     uint32_t specStatus;
631     usb_host_port_app_status_t appStatus;
632     usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hubInstance->hostHandle);
633     if (hubGlobal == NULL)
634     {
635         return;
636     }
637     appStatus = (usb_host_port_app_status_t)portInstance->portStatus;
638     switch (appStatus)
639     {
640         case kPortRunIdle:
641             break;
642         case kPortRunInvalid:
643             break;
644 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
645         case kPortRunPortSuspended:
646 #endif
647         case kPortRunPortAttached: /* (1) port is changed, then get port status */
648             portInstance->portStatus = (uint8_t)kPortRunCheckPortDetach;
649             /* get port status */
650             if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4U,
651                                          USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
652             {
653                 hubInstance->primeStatus = (uint8_t)kPrimePortControl;
654                 processSuccess           = 1U;
655             }
656             break;
657 
658         case kPortRunCheckPortDetach: /* (2) check port status bits */
659             specStatus               = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer);
660             portInstance->portStatus = (uint8_t)kPortRunGetConnectionBit;
661             if (0U != ((1UL << C_PORT_CONNECTION) & specStatus)) /* C_PORT_CONNECTION */
662             {
663                 if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_CONNECTION,
664                                                 USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
665                 {
666                     hubInstance->primeStatus = (uint8_t)kPrimePortControl;
667                     processSuccess           = 1U;
668                 }
669             }
670             else if (0U != ((1UL << C_PORT_ENABLE) & specStatus)) /* C_PORT_ENABLE */
671             {
672                 if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_ENABLE,
673                                                 USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
674                 {
675                     hubInstance->primeStatus = (uint8_t)kPrimePortControl;
676                     processSuccess           = 1U;
677                 }
678             }
679 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
680             else if (0U != ((1UL << C_PORT_SUSPEND) & specStatus))
681             {
682                 /* clear C_PORT_SUSPEND */
683                 if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_SUSPEND,
684                                                 USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
685                 {
686                     portInstance->portStatus = (uint8_t)kPortRunClearCPortSuspend; /* update as next state */
687                     hubInstance->primeStatus = (uint8_t)kPrimePortControl;
688                     processSuccess           = 1U;
689                 }
690             }
691 #endif
692             else
693             {
694                 /*for misra check and make sure hub state machine could keep work*/
695                 portInstance->portStatus = (uint8_t)kPortRunCheckConnectionBit;
696                 if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4,
697                                              USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
698                 {
699                     hubInstance->primeStatus = (uint8_t)kPrimePortControl;
700                     processSuccess           = 1U;
701                 }
702             }
703             break;
704         case kPortRunGetConnectionBit: /* (3) get port status */
705             portInstance->portStatus = (uint8_t)kPortRunCheckConnectionBit;
706             if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4,
707                                          USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
708             {
709                 hubInstance->primeStatus = (uint8_t)kPrimePortControl;
710                 processSuccess           = 1U;
711             }
712             break;
713 
714         case kPortRunCheckConnectionBit: /* (4) check port connection bit */
715             specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer);
716             if (0U != ((1UL << PORT_CONNECTION) & specStatus)) /* PORT_CONNECTION */
717             {
718                 portInstance->portStatus = (uint8_t)kPortRunPortAttached;
719 #ifdef HOST_ECHO
720                 usb_echo("PORT_CONNECTION in attach for detach\r\n");
721 #endif
722             }
723             else
724             {
725                 processSuccess = 1U;
726                 /* port's device is detached */
727                 portInstance->portStatus = (uint8_t)kPortRunWaitPortChange;
728                 (void)USB_HostDetachDeviceInternal(hubInstance->hostHandle, portInstance->deviceHandle);
729                 portInstance->deviceHandle = NULL;
730                 hubGlobal->hubProcess      = NULL;
731                 hubInstance->portProcess   = 0U;
732                 USB_HostHubGetInterruptStatus(hubInstance);
733             }
734             break;
735 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
736         case kPortRunClearCPortSuspend:
737             portInstance->portStatus = (uint8_t)kPortRunCheckPortSuspend; /* update as next state */
738             /* get port status bits */
739             if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4,
740                                          USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
741             {
742                 hubInstance->primeStatus = (uint8_t)kPrimePortControl;
743                 processSuccess           = 1U;
744             }
745             break;
746         case kPortRunCheckPortSuspend:
747             specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer);
748             if (0U != ((1UL << PORT_SUSPEND) & specStatus))
749             {
750                 portInstance->portStatus = (uint8_t)kPortRunPortSuspended; /* update as next state */
751                 /* call host callback function, function is initialized in USB_HostInit */
752                 (void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
753                                                   kUSB_HostEventSuspended); /* call host callback function */
754             }
755             else
756             {
757                 portInstance->portStatus = (uint8_t)kPortRunPortAttached; /* update as next state */
758                 /* call host callback function, function is initialized in USB_HostInit */
759                 (void)hostPointer->deviceCallback(hostPointer->suspendedDevice, NULL,
760                                                   kUSB_HostEventResumed); /* call host callback function */
761                 hostPointer->suspendedDevice = NULL;
762             }
763             break;
764 #endif
765         default:
766             /*no action*/
767             break;
768     }
769 
770     if (processSuccess == 0U)
771     {
772         portInstance->portStatus = (uint8_t)kPortRunPortAttached;
773         hubGlobal->hubProcess    = NULL;
774         hubInstance->portProcess = 0U;
775         USB_HostHubGetInterruptStatus(hubInstance);
776     }
777 }
778 
USB_HostHubProcessData(usb_host_hub_global_t * hubGlobal,usb_host_hub_instance_t * hubInstance)779 static void USB_HostHubProcessData(usb_host_hub_global_t *hubGlobal, usb_host_hub_instance_t *hubInstance)
780 {
781     uint8_t needPrimeInterrupt = 1U;
782     uint8_t portIndex;
783 
784     /* process the port which status change */
785     for (portIndex = 0U; portIndex <= hubInstance->portCount; ++portIndex)
786     {
787         if (0U != ((0x01U << (portIndex & 0x07U)) & (hubInstance->hubBitmapBuffer[portIndex >> 3U])))
788         {
789             if (portIndex == 0U) /* hub status change */
790             {
791                 if ((hubGlobal->hubProcess == NULL) ||
792                     ((hubGlobal->hubProcess == hubInstance) && (hubInstance->portProcess == 0U)))
793                 {
794                     hubInstance->hubStatus = (uint8_t)kHubRunGetStatusDone;
795                     if (USB_HostHubGetStatus(hubInstance, hubInstance->hubStatusBuffer, 4U, USB_HostHubControlCallback,
796                                              hubInstance) != kStatus_USB_Success)
797                     {
798 #ifdef HOST_ECHO
799                         usb_echo("error in usb_class_hub_get_status\r\n");
800 #endif
801                         hubInstance->hubStatus = (uint8_t)kHubRunIdle;
802                     }
803                     else
804                     {
805                         hubInstance->primeStatus = (uint8_t)kPrimeHubControl;
806                         return; /* return replace break because the misra */
807                     }
808                 }
809             }
810             else /* port's status change */
811             {
812                 /* process the on-going port or process one new port */
813                 if ((hubGlobal->hubProcess == NULL) ||
814                     ((hubGlobal->hubProcess == hubInstance) && (hubInstance->portProcess == 0U)) ||
815                     ((hubGlobal->hubProcess == hubInstance) && (hubInstance->portProcess == portIndex)))
816                 {
817                     if (hubInstance->controlTransfer == NULL)
818                     {
819                         hubGlobal->hubProcess    = hubInstance;
820                         hubInstance->portProcess = portIndex;
821                         needPrimeInterrupt       = 0U;
822                         USB_HostHubProcessPort(hubInstance);
823                     }
824                     break; /* process the port change in turn */
825                 }
826             }
827         }
828     }
829 
830     if (needPrimeInterrupt == 1U)
831     {
832         USB_HostHubGetInterruptStatus(hubInstance);
833     }
834 }
835 
USB_HostHubControlCallback(void * param,uint8_t * data,uint32_t data_len,usb_status_t status)836 static void USB_HostHubControlCallback(void *param, uint8_t *data, uint32_t data_len, usb_status_t status)
837 {
838     usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param;
839     usb_host_hub_global_t *hubGlobal     = USB_HostHubGetHubList(hubInstance->hostHandle);
840     if (hubGlobal == NULL)
841     {
842         return;
843     }
844 
845     if (hubInstance->invalid == 1U)
846     {
847         return;
848     }
849     if (status != kStatus_USB_Success)
850     {
851         /* if transfer fail, prime a new interrupt in transfer */
852         hubInstance->primeStatus = (uint8_t)kPrimeNone;
853         hubGlobal->hubProcess    = NULL;
854         hubInstance->portProcess = 0U;
855         USB_HostHubGetInterruptStatus(hubInstance);
856         return;
857     }
858 
859     if (hubInstance->primeStatus == (uint8_t)kPrimeHubControl) /* hub related control transfer */
860     {
861         hubInstance->primeStatus = (uint8_t)kPrimeNone;
862         USB_HostHubProcess(hubInstance);
863     }
864     else if (hubInstance->primeStatus == (uint8_t)kPrimePortControl) /* hub's port related control transfer */
865     {
866         hubInstance->primeStatus = (uint8_t)kPrimeNone;
867         USB_HostHubProcessPort(hubInstance);
868     }
869     else
870     {
871         /*no action*/
872     }
873 }
874 
875 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U)) || \
876      (defined(USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST > 0U)))
877 /*!
878  * @brief get device's hub device instance.
879  *
880  * @param parent_hub_no  device's parent hub instance.
881  *
882  * @return think time value.
883  */
USB_HostHubGetHubDeviceHandle(usb_host_handle hostHandle,uint8_t parentHubNo)884 usb_host_hub_instance_t *USB_HostHubGetHubDeviceHandle(usb_host_handle hostHandle, uint8_t parentHubNo)
885 {
886     usb_host_hub_instance_t *hubInstance;
887     uint32_t deviceAddress           = 0U;
888     usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle);
889     if (hubGlobal == NULL)
890     {
891         return NULL;
892     }
893     hubInstance = hubGlobal->hubList;
894 
895     /* get parentHubNo's hub instance handle */
896     while (hubInstance != NULL)
897     {
898         (void)USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, (uint32_t)kUSB_HostGetDeviceAddress,
899                                                      &deviceAddress);
900         if (parentHubNo == deviceAddress)
901         {
902             break;
903         }
904         hubInstance = hubInstance->next;
905     }
906     if (hubInstance != NULL)
907     {
908         return hubInstance;
909     }
910     return (usb_host_hub_instance_t *)NULL;
911 }
912 #endif
913 
914 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
USB_HostSetHubRequestCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)915 static void USB_HostSetHubRequestCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
916 {
917     usb_host_instance_t *hostInstance = (usb_host_instance_t *)param;
918     (void)USB_HostFreeTransfer(param, transfer);
919 
920     if (kStatus_USB_Success == status)
921     {
922         /* call host callback function, function is initialized in USB_HostInit */
923         (void)hostInstance->deviceCallback(hostInstance->suspendedDevice, NULL,
924                                            kUSB_HostEventSuspended); /* call host callback function */
925     }
926     else
927     {
928         /* call host callback function, function is initialized in USB_HostInit */
929         (void)hostInstance->deviceCallback(hostInstance->suspendedDevice, NULL,
930                                            kUSB_HostEventNotSuspended); /* call host callback function */
931     }
932 }
933 
USB_HostClearHubRequestCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)934 static void USB_HostClearHubRequestCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
935 {
936     (void)USB_HostFreeTransfer(param, transfer);
937 
938     if (kStatus_USB_Success == status)
939     {
940     }
941 }
942 
USB_HostHubRemoteWakeupCallback(void * param,usb_host_transfer_t * transfer,usb_status_t status)943 static void USB_HostHubRemoteWakeupCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
944 {
945     usb_host_hub_instance_t *hubInstance;
946     usb_host_instance_t *hostInstance;
947     usb_host_device_instance_t *deviceInstance;
948     if (NULL == param)
949     {
950         return;
951     }
952 
953     hubInstance = (usb_host_hub_instance_t *)param;
954 
955     hostInstance = (usb_host_instance_t *)hubInstance->hostHandle;
956     if (NULL == hostInstance)
957     {
958         return;
959     }
960 
961     (void)USB_HostFreeTransfer(hostInstance, transfer);
962 
963     if (kStatus_USB_Success != status)
964     {
965         (void)usb_echo("Transfer failed to set remote wakeup request to HUB.\r\n");
966     }
967 
968     if (kStatus_USB_Success == status)
969     {
970         hubInstance->controlRetry = USB_HOST_HUB_REMOTE_WAKEUP_TIMES;
971         hubInstance               = hubInstance->next;
972         while (NULL != hubInstance)
973         {
974             hubInstance->controlRetry = USB_HOST_HUB_REMOTE_WAKEUP_TIMES;
975             if (0U != hubInstance->supportRemoteWakeup)
976             {
977                 (void)usb_echo("Set HUB remote wakeup feature: level %d, address %d.\r\n",
978                                ((usb_host_device_instance_t *)hubInstance->deviceHandle)->level,
979                                ((usb_host_device_instance_t *)hubInstance->deviceHandle)->setAddress);
980                 status = USB_HostSendHubRequest(
981                     hubInstance->deviceHandle,
982                     USB_REQUEST_TYPE_RECIPIENT_DEVICE | USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_STANDARD,
983                     USB_REQUEST_STANDARD_SET_FEATURE, USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_REMOTE_WAKEUP, 0,
984                     USB_HostHubRemoteWakeupCallback, hubInstance);
985                 if (kStatus_USB_Success != status)
986                 {
987                     (void)usb_echo("Send set remote wakeup request to HUB failed.\r\n");
988                 }
989                 break;
990             }
991             hubInstance = hubInstance->next;
992         }
993     }
994     else
995     {
996         if (0U != hubInstance->controlRetry)
997         {
998             hubInstance->controlRetry--;
999             (void)usb_echo("Retry...\r\n", ((usb_host_device_instance_t *)hubInstance->deviceHandle)->level,
1000                            ((usb_host_device_instance_t *)hubInstance->deviceHandle)->setAddress);
1001             status = USB_HostSendHubRequest(
1002                 hubInstance->deviceHandle,
1003                 USB_REQUEST_TYPE_RECIPIENT_DEVICE | USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_STANDARD,
1004                 USB_REQUEST_STANDARD_SET_FEATURE, USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_REMOTE_WAKEUP, 0,
1005                 USB_HostHubRemoteWakeupCallback, hubInstance);
1006             if (kStatus_USB_Success != status)
1007             {
1008                 (void)usb_echo("Send set remote wakeup request to HUB failed.\r\n");
1009             }
1010         }
1011         else
1012         {
1013             (void)usb_echo("Transfer failed to set remote wakeup request to HUB.\r\n");
1014         }
1015     }
1016     if (kStatus_USB_Success != status)
1017     {
1018         /* call host callback function, function is initialized in USB_HostInit */
1019         (void)hostInstance->deviceCallback(hostInstance->suspendedDevice, NULL, kUSB_HostEventNotSuspended);
1020         return;
1021     }
1022     if (NULL == hubInstance)
1023     {
1024         status         = kStatus_USB_Error;
1025         deviceInstance = (usb_host_device_instance_t *)hostInstance->suspendedDevice;
1026         if (NULL == deviceInstance)
1027         {
1028             usb_host_bus_control_t type = kUSB_HostBusSuspend;
1029             /* the callbackFn is initialized in USB_HostGetControllerInterface */
1030             status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl,
1031                                                                     &type);
1032             if (kStatus_USB_Success != status)
1033             {
1034                 (void)usb_echo("Suspend USB BUS failed.\r\n");
1035             }
1036         }
1037         else
1038         {
1039             usb_host_hub_instance_t *hubInstance4Device =
1040                 USB_HostHubGetHubDeviceHandle(hostInstance, deviceInstance->hubNumber);
1041             if (NULL != hubInstance4Device)
1042             {
1043                 status = USB_HostSendHubRequest(
1044                     hubInstance4Device->deviceHandle,
1045                     USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER,
1046                     USB_REQUEST_STANDARD_SET_FEATURE, PORT_SUSPEND, deviceInstance->portNumber,
1047                     USB_HostSetHubRequestCallback, hostInstance);
1048                 if (kStatus_USB_Success != status)
1049                 {
1050                     (void)usb_echo("Send suspend request to HUB is failed.\r\n");
1051                 }
1052             }
1053             else
1054             {
1055                 (void)usb_echo("Invalid HUB instance of device.\r\n");
1056             }
1057         }
1058         if (kStatus_USB_Success != status)
1059         {
1060             /* call host callback function, function is initialized in USB_HostInit */
1061             (void)hostInstance->deviceCallback(hostInstance->suspendedDevice, NULL, kUSB_HostEventNotSuspended);
1062             return;
1063         }
1064     }
1065 }
1066 
USB_HostSendHubRequest(usb_device_handle deviceHandle,uint8_t requestType,uint8_t request,uint16_t wvalue,uint16_t windex,host_inner_transfer_callback_t callbackFn,void * callbackParam)1067 static usb_status_t USB_HostSendHubRequest(usb_device_handle deviceHandle,
1068                                            uint8_t requestType,
1069                                            uint8_t request,
1070                                            uint16_t wvalue,
1071                                            uint16_t windex,
1072                                            host_inner_transfer_callback_t callbackFn,
1073                                            void *callbackParam)
1074 {
1075     usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
1076     usb_host_transfer_t *transfer;
1077 
1078     /* get transfer */
1079     if (USB_HostMallocTransfer(deviceInstance->hostHandle, &transfer) != kStatus_USB_Success)
1080     {
1081 #ifdef HOST_ECHO
1082         usb_echo("error to get transfer\r\n");
1083 #endif
1084         return kStatus_USB_Error;
1085     }
1086 
1087     /* initialize transfer */
1088     transfer->transferBuffer             = NULL;
1089     transfer->transferLength             = 0U;
1090     transfer->callbackFn                 = callbackFn;
1091     transfer->callbackParam              = callbackParam;
1092     transfer->setupPacket->bmRequestType = requestType;
1093     transfer->setupPacket->bRequest      = request;
1094     transfer->setupPacket->wValue        = USB_SHORT_TO_LITTLE_ENDIAN(wvalue);
1095     transfer->setupPacket->wIndex        = USB_SHORT_TO_LITTLE_ENDIAN(windex);
1096     transfer->setupPacket->wLength       = USB_SHORT_TO_LITTLE_ENDIAN(0U);
1097 
1098     /* send transfer */
1099     if (USB_HostSendSetup(deviceInstance->hostHandle, deviceInstance->controlPipe, transfer) != kStatus_USB_Success)
1100     {
1101 #ifdef HOST_ECHO
1102         usb_echo("Error in sending hub set report!\r\n");
1103 #endif
1104         (void)USB_HostFreeTransfer(deviceInstance->hostHandle, transfer);
1105         return kStatus_USB_Error;
1106     }
1107     return kStatus_USB_Success;
1108 }
1109 #endif
1110 
USB_HostHubInterruptInCallback(void * param,uint8_t * data,uint32_t data_len,usb_status_t status)1111 void USB_HostHubInterruptInCallback(void *param, uint8_t *data, uint32_t data_len, usb_status_t status)
1112 {
1113     usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param;
1114     usb_host_hub_global_t *hubGlobal     = USB_HostHubGetHubList(hubInstance->hostHandle);
1115     if (hubGlobal == NULL)
1116     {
1117         return;
1118     }
1119 
1120     if (hubInstance->invalid == 1U)
1121     {
1122         return;
1123     }
1124     /* interrupt data received */
1125     hubInstance->primeStatus = (uint8_t)kPrimeNone;
1126     if (status != kStatus_USB_Success)
1127     {
1128 #ifdef HOST_ECHO
1129         usb_echo("hub interrupt in data callback error\r\n");
1130 #endif
1131         /* prime nexe interrupt transfer */
1132         if (hubInstance->controlTransfer == NULL)
1133         {
1134             hubGlobal->hubProcess    = NULL;
1135             hubInstance->portProcess = 0;
1136             USB_HostHubGetInterruptStatus(hubInstance);
1137         }
1138     }
1139     else
1140     {
1141         USB_HostHubProcessData(hubGlobal, hubInstance); /* process the interrupt data */
1142     }
1143 }
1144 
1145 /*!
1146  * @brief host hub callback function.
1147  *
1148  * This function should be called in the host callback function.
1149  *
1150  * @param hostHandle             host handle.
1151  * @param deviceHandle           device handle.
1152  * @param configurationHandle attached device's configuration descriptor information.
1153  * @param event_code           callback event code, please reference to enumeration host_event_t.
1154  *
1155  * @retval kStatus_USB_Success              The host is initialized successfully.
1156  * @retval kStatus_USB_NotSupported         The configuration don't contain hub interface.
1157  */
USB_HostHubDeviceEvent(usb_host_handle hostHandle,usb_device_handle deviceHandle,usb_host_configuration_handle configurationHandle,uint32_t eventCode)1158 usb_status_t USB_HostHubDeviceEvent(usb_host_handle hostHandle,
1159                                     usb_device_handle deviceHandle,
1160                                     usb_host_configuration_handle configurationHandle,
1161                                     uint32_t eventCode)
1162 {
1163     usb_host_configuration_t *configuration;
1164     usb_host_interface_t *interface;
1165     uint8_t interfaceIndex;
1166     uint8_t id;
1167     usb_status_t status                  = kStatus_USB_Success;
1168     usb_host_class_handle hubClassHandle = NULL;
1169     usb_host_hub_instance_t *hubInstance;
1170     usb_host_hub_instance_t *prevInstance;
1171     uint32_t infoValue = 0U;
1172     osa_status_t osaStatus;
1173     usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle);
1174     usb_host_event_t hostEventCode   = (usb_host_event_t)eventCode;
1175     if (hubGlobal == NULL)
1176     {
1177         return kStatus_USB_Error;
1178     }
1179 
1180     switch (hostEventCode)
1181     {
1182         case kUSB_HostEventAttach:
1183             /* judge whether is configurationHandle supported */
1184             configuration = (usb_host_configuration_t *)configurationHandle;
1185             for (interfaceIndex = 0U; interfaceIndex < configuration->interfaceCount; ++interfaceIndex)
1186             {
1187                 interface = &configuration->interfaceList[interfaceIndex];
1188                 id        = interface->interfaceDesc->bInterfaceClass;
1189                 if (id != USB_HOST_HUB_CLASS_CODE)
1190                 {
1191                     continue;
1192                 }
1193                 id = interface->interfaceDesc->bInterfaceSubClass;
1194                 if (id != USB_HOST_HUB_SUBCLASS_CODE_NONE)
1195                 {
1196                     continue;
1197                 }
1198                 else
1199                 {
1200                     (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceLevel,
1201                                                                  &infoValue);
1202                     if (infoValue > 5U)
1203                     {
1204 #if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
1205                         (void)usb_echo("Host can support max 5 level hubs\r\n");
1206 #endif
1207                         continue;
1208                     }
1209                     /* the interface is hub */
1210                     s_HubDeviceHandle    = deviceHandle;
1211                     s_HubInterfaceHandle = interface;
1212 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
1213                     s_HubConfiguration = configuration;
1214 #endif
1215                     return kStatus_USB_Success;
1216                 }
1217             }
1218             status = kStatus_USB_NotSupported;
1219             break;
1220 
1221         case kUSB_HostEventEnumerationDone:
1222             /* the device enumeration is done */
1223             if ((s_HubDeviceHandle != NULL) && (s_HubInterfaceHandle != NULL))
1224             {
1225                 /* print hub information */
1226                 (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceLevel,
1227                                                              &infoValue);
1228                 (void)usb_echo("hub attached:level=%u ", infoValue);
1229                 (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceAddress,
1230                                                              &infoValue);
1231                 (void)usb_echo("address=%u\r\n", infoValue);
1232 
1233                 /* initialize hub mutex */
1234                 if (hubGlobal->hubMutex == (osa_mutex_handle_t)NULL)
1235                 {
1236                     hubGlobal->hubMutex = (osa_mutex_handle_t)(&hubGlobal->mutexBuffer[0]);
1237                     osaStatus           = OSA_MutexCreate(hubGlobal->hubMutex);
1238                     if (osaStatus != KOSA_StatusSuccess)
1239                     {
1240                         hubGlobal->hubMutex = NULL;
1241 #ifdef HOST_ECHO
1242                         (void)usb_echo("hub mutex error\r\n");
1243 #endif
1244                     }
1245                 }
1246 
1247                 /* initialize hub class instance */
1248                 status      = USB_HostHubInit(s_HubDeviceHandle, &hubClassHandle);
1249                 hubInstance = (usb_host_hub_instance_t *)hubClassHandle;
1250 
1251                 /* link hub instance to list */
1252                 if (USB_HostHubLockMutexCheck())
1253                 {
1254                     (void)USB_HostHubLock();
1255                 }
1256                 hubInstance->next  = hubGlobal->hubList;
1257                 hubGlobal->hubList = hubInstance;
1258                 if (USB_HostHubLockMutexCheck())
1259                 {
1260                     (void)USB_HostHubUnlock();
1261                 }
1262 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
1263                 hubInstance->supportRemoteWakeup = 0U;
1264                 hubInstance->controlRetry        = USB_HOST_HUB_REMOTE_WAKEUP_TIMES;
1265                 if (0U != (s_HubConfiguration->configurationDesc->bmAttributes &
1266                            USB_DESCRIPTOR_CONFIGURE_ATTRIBUTE_REMOTE_WAKEUP_MASK))
1267                 {
1268                     hubInstance->supportRemoteWakeup = 1U;
1269                 }
1270 #endif
1271                 /* set hub instance's interface */
1272                 if (status == kStatus_USB_Success)
1273                 {
1274                     hubInstance->primeStatus = (uint8_t)kPrimeHubControl;
1275                     hubInstance->hubStatus   = (uint8_t)kHubRunWaitSetInterface;
1276                     if (USB_HostHubSetInterface(hubClassHandle, s_HubInterfaceHandle, 0, USB_HostHubControlCallback,
1277                                                 hubInstance) != kStatus_USB_Success)
1278                     {
1279                         hubInstance->hubStatus = (uint8_t)kHubRunInvalid;
1280                     }
1281                 }
1282             }
1283             break;
1284 
1285         case kUSB_HostEventDetach:
1286             /* the device is detached */
1287             hubInstance = NULL;
1288 
1289             /* get device's hub instance handle */
1290             if (USB_HostHubLockMutexCheck())
1291             {
1292                 (void)USB_HostHubLock();
1293             }
1294             prevInstance = hubGlobal->hubList;
1295             if (prevInstance->deviceHandle == deviceHandle)
1296             {
1297                 hubInstance        = prevInstance;
1298                 hubGlobal->hubList = prevInstance->next;
1299             }
1300             else
1301             {
1302                 hubInstance = prevInstance->next;
1303                 while (hubInstance != NULL)
1304                 {
1305                     if (hubInstance->deviceHandle == deviceHandle)
1306                     {
1307                         prevInstance->next = hubInstance->next;
1308                         break;
1309                     }
1310                     prevInstance = hubInstance;
1311                     hubInstance  = hubInstance->next;
1312                 }
1313             }
1314             if (USB_HostHubLockMutexCheck())
1315             {
1316                 (void)USB_HostHubUnlock();
1317             }
1318 
1319             if (hubInstance != NULL)
1320             {
1321                 if (hubInstance == hubGlobal->hubProcess)
1322                 {
1323                     hubGlobal->hubProcess = NULL;
1324                 }
1325                 /* print hub information */
1326                 (void)USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle,
1327                                                              (uint32_t)kUSB_HostGetDeviceLevel, &infoValue);
1328                 (void)usb_echo("hub detached:level=%u ", infoValue);
1329                 (void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceAddress,
1330                                                              &infoValue);
1331                 (void)usb_echo("address=%u\r\n", infoValue);
1332                 hubInstance->invalid = 1U;
1333                 /* detach hub ports' devices */
1334                 for (uint8_t portIndex = 0U; portIndex < hubInstance->portCount; ++portIndex)
1335                 {
1336                     if ((hubInstance->portList != NULL) && (hubInstance->portList[portIndex].deviceHandle != NULL))
1337                     {
1338                         (void)USB_HostDetachDeviceInternal(hubInstance->hostHandle,
1339                                                            hubInstance->portList[portIndex].deviceHandle);
1340                         hubInstance->portList[portIndex].deviceHandle = NULL;
1341                     }
1342                 }
1343                 if (hubInstance->portList != NULL)
1344                 {
1345                     (void)OSA_MemoryFree(hubInstance->portList);
1346                 }
1347                 (void)USB_HostHubDeinit(deviceHandle, hubInstance); /* de-initialize hub instance */
1348             }
1349 
1350             /* destroy hub mutex if there is no hub instance */
1351             if (hubGlobal->hubList == NULL)
1352             {
1353                 if (hubGlobal->hubMutex != NULL)
1354                 {
1355                     (void)OSA_MutexDestroy(hubGlobal->hubMutex);
1356                     hubGlobal->hubMutex = NULL;
1357                 }
1358             }
1359             status = kStatus_USB_Success;
1360             break;
1361 
1362         default:
1363             /*action*/
1364             break;
1365     }
1366 
1367     return status;
1368 }
1369 
1370 /*!
1371  * @brief remove attached device. called by USB_HostRemoveDevice.
1372  *
1373  * @param hubNumber   the device attached hub.
1374  * @param portNumber  the device attached port.
1375  *
1376  * @return kStatus_USB_Success or error codes.
1377  */
USB_HostHubRemovePort(usb_host_handle hostHandle,uint8_t hubNumber,uint8_t portNumber)1378 usb_status_t USB_HostHubRemovePort(usb_host_handle hostHandle, uint8_t hubNumber, uint8_t portNumber)
1379 {
1380     usb_host_hub_instance_t *hubInstance;
1381     uint32_t infoValue               = 0U;
1382     usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle);
1383     if (hubGlobal == NULL)
1384     {
1385         return kStatus_USB_Error;
1386     }
1387 
1388     /* get hub number's hub instance handle */
1389     hubInstance = (usb_host_hub_instance_t *)hubGlobal->hubList;
1390     while (hubInstance != NULL)
1391     {
1392         (void)USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, (uint8_t)kUSB_HostGetDeviceAddress,
1393                                                      &infoValue);
1394         if (infoValue == hubNumber)
1395         {
1396             break;
1397         }
1398         hubInstance = hubInstance->next;
1399     }
1400 
1401     /* set port's status as default, and reset port */
1402     if (hubInstance != NULL)
1403     {
1404         hubInstance->portList[portNumber - 1U].deviceHandle = NULL;
1405         hubInstance->portList[portNumber - 1U].portStatus   = (uint8_t)kPortRunInvalid;
1406         if (hubInstance->portProcess == portNumber)
1407         {
1408             hubInstance->portProcess = 0U;
1409         }
1410         (void)USB_HostHubSendPortReset(hubInstance, portNumber);
1411     }
1412     return kStatus_USB_Error;
1413 }
1414 
1415 /*!
1416  * @brief get device's high-speed hub's address.
1417  *
1418  * @param parent_hub_no device's parent hub's address.
1419  *
1420  * @return hub number.
1421  */
USB_HostHubGetHsHubNumber(usb_host_handle hostHandle,uint8_t parentHubNo)1422 uint32_t USB_HostHubGetHsHubNumber(usb_host_handle hostHandle, uint8_t parentHubNo)
1423 {
1424     usb_host_hub_instance_t *hubInstance;
1425     uint32_t deviceInfo              = 0U;
1426     uint32_t hubNumber               = 0U;
1427     usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle);
1428     if (hubGlobal == NULL)
1429     {
1430         return 0U;
1431     }
1432     hubInstance = hubGlobal->hubList;
1433 
1434     /* get parentHubNo's hub instance handle */
1435     while (hubInstance != NULL)
1436     {
1437         (void)USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, (uint32_t)kUSB_HostGetDeviceAddress,
1438                                                      &deviceInfo);
1439         if (parentHubNo == deviceInfo)
1440         {
1441             break;
1442         }
1443         hubInstance = hubInstance->next;
1444     }
1445     if (hubInstance != NULL)
1446     {
1447         (void)USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, (uint32_t)kUSB_HostGetDeviceSpeed,
1448                                                      &deviceInfo);
1449         if (deviceInfo == USB_SPEED_HIGH) /* parent hub is HS */
1450         {
1451             hubNumber = parentHubNo;
1452         }
1453         else /* parent hub is not HS */
1454         {
1455             (void)USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle,
1456                                                          (uint32_t)kUSB_HostGetDeviceHSHubNumber, &hubNumber);
1457         }
1458         return hubNumber;
1459     }
1460     return 0U;
1461 }
1462 
1463 /*!
1464  * @brief get device's high-speed hub's port number.
1465  *
1466  * @param parent_hub_no  device's parent hub's address.
1467  * @param parent_port_no device's parent port no.
1468  *
1469  * @return port number.
1470  */
USB_HostHubGetHsHubPort(usb_host_handle hostHandle,uint8_t parentHubNo,uint8_t parentPortNo)1471 uint32_t USB_HostHubGetHsHubPort(usb_host_handle hostHandle, uint8_t parentHubNo, uint8_t parentPortNo)
1472 {
1473     usb_host_hub_instance_t *hubInstance;
1474     uint32_t deviceInfo              = 0U;
1475     uint32_t hubPort                 = 0U;
1476     usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle);
1477     if (hubGlobal == NULL)
1478     {
1479         return 0U;
1480     }
1481     hubInstance = hubGlobal->hubList;
1482 
1483     /* get parentHubNo's hub instance handle */
1484     while (hubInstance != NULL)
1485     {
1486         (void)USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, (uint32_t)kUSB_HostGetDeviceAddress,
1487                                                      &deviceInfo);
1488         if (parentHubNo == deviceInfo)
1489         {
1490             break;
1491         }
1492         hubInstance = hubInstance->next;
1493     }
1494     if (hubInstance != NULL)
1495     {
1496         (void)USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, (uint32_t)kUSB_HostGetDeviceSpeed,
1497                                                      &deviceInfo);
1498         if (deviceInfo == USB_SPEED_HIGH) /* parent hub is HS */
1499         {
1500             hubPort = parentPortNo;
1501         }
1502         else /* parent hub is not HS */
1503         {
1504             (void)USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle,
1505                                                          (uint32_t)kUSB_HostGetDeviceHSHubNumber, &hubPort);
1506         }
1507         return hubPort;
1508     }
1509     return 0;
1510 }
1511 
1512 /*!
1513  * @brief get device's hub total think time.
1514  *
1515  * @param parent_hub_no  device's parent hub's address.
1516  *
1517  * @return think time value.
1518  */
USB_HostHubGetTotalThinkTime(usb_host_handle hostHandle,uint8_t parentHubNo)1519 uint32_t USB_HostHubGetTotalThinkTime(usb_host_handle hostHandle, uint8_t parentHubNo)
1520 {
1521     usb_host_hub_instance_t *hubInstance;
1522     uint32_t deviceAddress           = 0U;
1523     usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle);
1524     if (hubGlobal == NULL)
1525     {
1526         return 0U;
1527     }
1528     hubInstance = hubGlobal->hubList;
1529 
1530     /* get parentHubNo's hub instance handle */
1531     while (hubInstance != NULL)
1532     {
1533         (void)USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, (uint32_t)kUSB_HostGetDeviceAddress,
1534                                                      &deviceAddress);
1535         if (parentHubNo == deviceAddress)
1536         {
1537             break;
1538         }
1539         hubInstance = hubInstance->next;
1540     }
1541     if (hubInstance != NULL)
1542     {
1543         return hubInstance->totalThinktime;
1544     }
1545     return 0;
1546 }
1547 
1548 #if ((defined(USB_HOST_CONFIG_LOW_POWER_MODE)) && (USB_HOST_CONFIG_LOW_POWER_MODE > 0U))
1549 /*!
1550  * @brief Suspend the device.
1551  *
1552  * @param hostHandle  Host instance.
1553  *
1554  * @return kStatus_USB_Success or error codes.
1555  *
1556  */
USB_HostHubSuspendDevice(usb_host_handle hostHandle)1557 usb_status_t USB_HostHubSuspendDevice(usb_host_handle hostHandle)
1558 {
1559     usb_host_instance_t *hostInstance;
1560     usb_host_hub_instance_t *hubInstance;
1561     usb_status_t status              = kStatus_USB_Error;
1562     usb_host_hub_global_t *hubGlobal = USB_HostHubGetHubList(hostHandle);
1563     if (hubGlobal == NULL)
1564     {
1565         return kStatus_USB_Error;
1566     }
1567     hubInstance = hubGlobal->hubList;
1568 
1569     if (NULL == hostHandle)
1570     {
1571         return kStatus_USB_InvalidHandle;
1572     }
1573     hostInstance = (usb_host_instance_t *)hostHandle;
1574     if (NULL == hubInstance)
1575     {
1576         usb_host_bus_control_t type = kUSB_HostBusSuspend;
1577         /* the callbackFn is initialized in USB_HostGetControllerInterface */
1578         status =
1579             hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl, &type);
1580         if (kStatus_USB_Success != status)
1581         {
1582             (void)usb_echo("Suspend USB BUS failed.\r\n");
1583         }
1584         return status;
1585     }
1586     /* Scan HUB instance handle */
1587     while (hubInstance != NULL)
1588     {
1589         hubInstance->controlRetry = USB_HOST_HUB_REMOTE_WAKEUP_TIMES;
1590         if (0U != hubInstance->supportRemoteWakeup)
1591         {
1592             (void)usb_echo("Set HUB remote wakeup feature: level %d, address %d.\r\n",
1593                            ((usb_host_device_instance_t *)hubInstance->deviceHandle)->level,
1594                            ((usb_host_device_instance_t *)hubInstance->deviceHandle)->setAddress);
1595             status = USB_HostSendHubRequest(
1596                 hubInstance->deviceHandle,
1597                 USB_REQUEST_TYPE_RECIPIENT_DEVICE | USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_STANDARD,
1598                 USB_REQUEST_STANDARD_SET_FEATURE, USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_REMOTE_WAKEUP, 0,
1599                 USB_HostHubRemoteWakeupCallback, hubInstance);
1600             break;
1601         }
1602         hubInstance = hubInstance->next;
1603     }
1604     if (NULL == hubInstance)
1605     {
1606         usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)hostInstance->suspendedDevice;
1607         if (NULL == deviceInstance)
1608         {
1609             usb_host_bus_control_t type = kUSB_HostBusSuspend;
1610             /* the callbackFn is initialized in USB_HostGetControllerInterface */
1611             status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl,
1612                                                                     &type);
1613             if (kStatus_USB_Success != status)
1614             {
1615                 (void)usb_echo("Suspend USB BUS failed.\r\n");
1616             }
1617         }
1618         else
1619         {
1620             usb_host_hub_instance_t *hubInstance4Device =
1621                 USB_HostHubGetHubDeviceHandle(hostHandle, deviceInstance->hubNumber);
1622             if (NULL != hubInstance4Device)
1623             {
1624                 status = USB_HostSendHubRequest(
1625                     hubInstance4Device->deviceHandle,
1626                     USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER,
1627                     USB_REQUEST_STANDARD_SET_FEATURE, PORT_SUSPEND, deviceInstance->portNumber,
1628                     USB_HostSetHubRequestCallback, hostInstance);
1629                 if (kStatus_USB_Success != status)
1630                 {
1631                     (void)usb_echo("Send suspend request to HUB is failed.\r\n");
1632                 }
1633             }
1634             else
1635             {
1636                 (void)usb_echo("Invalid HUB instance of device.\r\n");
1637             }
1638         }
1639     }
1640     return status;
1641 }
1642 
1643 /*!
1644  * @brief Resume the device.
1645  *
1646  * @param hostHandle  Host instance.
1647  *
1648  * @return kStatus_USB_Success or error codes.
1649  *
1650  */
USB_HostHubResumeDevice(usb_host_handle hostHandle)1651 usb_status_t USB_HostHubResumeDevice(usb_host_handle hostHandle)
1652 {
1653     usb_host_instance_t *hostInstance;
1654     usb_host_device_instance_t *deviceInstance;
1655     usb_host_hub_instance_t *hubInstance = NULL;
1656     usb_status_t status                  = kStatus_USB_Error;
1657 
1658     if (NULL == hostHandle)
1659     {
1660         return kStatus_USB_InvalidHandle;
1661     }
1662     hostInstance = (usb_host_instance_t *)hostHandle;
1663 
1664     deviceInstance = (usb_host_device_instance_t *)hostInstance->suspendedDevice;
1665     if (NULL == deviceInstance)
1666     {
1667         return kStatus_USB_InvalidHandle;
1668     }
1669 
1670     hubInstance = USB_HostHubGetHubDeviceHandle(hostHandle, deviceInstance->hubNumber);
1671     if (NULL != hubInstance)
1672     {
1673         status = USB_HostSendHubRequest(
1674             hubInstance->deviceHandle,
1675             USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER,
1676             USB_REQUEST_STANDARD_CLEAR_FEATURE, PORT_SUSPEND, deviceInstance->portNumber,
1677             USB_HostClearHubRequestCallback, hostInstance);
1678     }
1679 
1680     return status;
1681 }
1682 #endif
1683 
1684 #endif /* USB_HOST_CONFIG_HUB */
1685