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