1 /** @file
2 
3     Unified interface for RootHub and Hub.
4 
5 Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution.  The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10 
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "UsbBus.h"
17 
18 //
19 // Array that maps the change bit to feature value which is
20 // used to clear these change bit. USB HUB API will clear
21 // these change bit automatically. For non-root hub, these
22 // bits determine whether hub will report the port in changed
23 // bit maps.
24 //
25 USB_CHANGE_FEATURE_MAP  mHubFeatureMap[] = {
26   {USB_PORT_STAT_C_CONNECTION,  EfiUsbPortConnectChange},
27   {USB_PORT_STAT_C_ENABLE,      EfiUsbPortEnableChange},
28   {USB_PORT_STAT_C_SUSPEND,     EfiUsbPortSuspendChange},
29   {USB_PORT_STAT_C_OVERCURRENT, EfiUsbPortOverCurrentChange},
30   {USB_PORT_STAT_C_RESET,       EfiUsbPortResetChange}
31 };
32 
33 USB_CHANGE_FEATURE_MAP  mRootHubFeatureMap[] = {
34   {USB_PORT_STAT_C_CONNECTION,  EfiUsbPortConnectChange},
35   {USB_PORT_STAT_C_ENABLE,      EfiUsbPortEnableChange},
36   {USB_PORT_STAT_C_SUSPEND,     EfiUsbPortSuspendChange},
37   {USB_PORT_STAT_C_OVERCURRENT, EfiUsbPortOverCurrentChange},
38   {USB_PORT_STAT_C_RESET,       EfiUsbPortResetChange},
39 };
40 
41 //
42 // USB hub class specific requests. Although USB hub
43 // is related to an interface, these requests are sent
44 // to the control endpoint of the device.
45 //
46 /**
47   USB hub control transfer to set the hub depth.
48 
49   @param  HubDev                The device of the hub.
50   @param  Depth                 The depth to set.
51 
52   @retval EFI_SUCCESS           Depth of the hub is set.
53   @retval Others                Failed to set the depth.
54 
55 **/
56 EFI_STATUS
UsbHubCtrlSetHubDepth(IN USB_DEVICE * HubDev,IN UINT16 Depth)57 UsbHubCtrlSetHubDepth (
58   IN  USB_DEVICE          *HubDev,
59   IN  UINT16              Depth
60   )
61 {
62   EFI_STATUS              Status;
63 
64   Status = UsbCtrlRequest (
65              HubDev,
66              EfiUsbNoData,
67              USB_REQ_TYPE_CLASS,
68              USB_HUB_TARGET_HUB,
69              USB_HUB_REQ_SET_DEPTH,
70              Depth,
71              0,
72              NULL,
73              0
74              );
75 
76   return Status;
77 }
78 
79 /**
80   USB hub control transfer to clear the hub feature.
81 
82   @param  HubDev                The device of the hub.
83   @param  Feature               The feature to clear.
84 
85   @retval EFI_SUCCESS           Feature of the hub is cleared.
86   @retval Others                Failed to clear the feature.
87 
88 **/
89 EFI_STATUS
UsbHubCtrlClearHubFeature(IN USB_DEVICE * HubDev,IN UINT16 Feature)90 UsbHubCtrlClearHubFeature (
91   IN USB_DEVICE           *HubDev,
92   IN UINT16               Feature
93   )
94 {
95   EFI_STATUS              Status;
96 
97   Status = UsbCtrlRequest (
98              HubDev,
99              EfiUsbNoData,
100              USB_REQ_TYPE_CLASS,
101              USB_HUB_TARGET_HUB,
102              USB_HUB_REQ_CLEAR_FEATURE,
103              Feature,
104              0,
105              NULL,
106              0
107              );
108 
109   return Status;
110 }
111 
112 
113 /**
114   Clear the feature of the device's port.
115 
116   @param  HubDev                The hub device.
117   @param  Port                  The port to clear feature.
118   @param  Feature               The feature to clear.
119 
120   @retval EFI_SUCCESS           The feature of the port is cleared.
121   @retval Others                Failed to clear the feature.
122 
123 **/
124 EFI_STATUS
UsbHubCtrlClearPortFeature(IN USB_DEVICE * HubDev,IN UINT8 Port,IN UINT16 Feature)125 UsbHubCtrlClearPortFeature (
126   IN USB_DEVICE           *HubDev,
127   IN UINT8                Port,
128   IN UINT16               Feature
129   )
130 {
131   EFI_STATUS              Status;
132 
133   //
134   // In USB bus, all the port index starts from 0. But HUB
135   // indexes its port from 1. So, port number is added one.
136   //
137   Status = UsbCtrlRequest (
138              HubDev,
139              EfiUsbNoData,
140              USB_REQ_TYPE_CLASS,
141              USB_HUB_TARGET_PORT,
142              USB_HUB_REQ_CLEAR_FEATURE,
143              Feature,
144              (UINT16) (Port + 1),
145              NULL,
146              0
147              );
148 
149   return Status;
150 }
151 
152 
153 /**
154   Clear the transaction translate buffer if full/low
155   speed control/bulk transfer failed and the transfer
156   uses this hub as translator.Remember to clear the TT
157   buffer of transaction translator, not that of the
158   parent.
159 
160   @param  HubDev                The hub device.
161   @param  Port                  The port of the hub.
162   @param  DevAddr               Address of the failed transaction.
163   @param  EpNum                 The endpoint number of the failed transaction.
164   @param  EpType                The type of failed transaction.
165 
166   @retval EFI_SUCCESS           The TT buffer is cleared.
167   @retval Others                Failed to clear the TT buffer.
168 
169 **/
170 EFI_STATUS
UsbHubCtrlClearTTBuffer(IN USB_DEVICE * HubDev,IN UINT8 Port,IN UINT16 DevAddr,IN UINT16 EpNum,IN UINT16 EpType)171 UsbHubCtrlClearTTBuffer (
172   IN USB_DEVICE           *HubDev,
173   IN UINT8                Port,
174   IN UINT16               DevAddr,
175   IN UINT16               EpNum,
176   IN UINT16               EpType
177   )
178 {
179   EFI_STATUS              Status;
180   UINT16                  Value;
181 
182   //
183   // Check USB2.0 spec page 424 for wValue's encoding
184   //
185   Value = (UINT16) ((EpNum & 0x0F) | (DevAddr << 4) |
186           ((EpType & 0x03) << 11) | ((EpNum & 0x80) << 15));
187 
188   Status = UsbCtrlRequest (
189              HubDev,
190              EfiUsbNoData,
191              USB_REQ_TYPE_CLASS,
192              USB_HUB_TARGET_PORT,
193              USB_HUB_REQ_CLEAR_TT,
194              Value,
195              (UINT16) (Port + 1),
196              NULL,
197              0
198              );
199 
200   return Status;
201 }
202 
203 /**
204   Usb hub control transfer to get the super speed hub descriptor.
205 
206   @param  HubDev                The hub device.
207   @param  Buf                   The buffer to hold the descriptor.
208 
209   @retval EFI_SUCCESS           The hub descriptor is retrieved.
210   @retval Others                Failed to retrieve the hub descriptor.
211 
212 **/
213 EFI_STATUS
UsbHubCtrlGetSuperSpeedHubDesc(IN USB_DEVICE * HubDev,OUT VOID * Buf)214 UsbHubCtrlGetSuperSpeedHubDesc (
215   IN  USB_DEVICE          *HubDev,
216   OUT VOID                *Buf
217   )
218 {
219   EFI_STATUS              Status;
220 
221   Status = EFI_INVALID_PARAMETER;
222 
223   Status = UsbCtrlRequest (
224              HubDev,
225              EfiUsbDataIn,
226              USB_REQ_TYPE_CLASS,
227              USB_HUB_TARGET_HUB,
228              USB_HUB_REQ_GET_DESC,
229              (UINT16) (USB_DESC_TYPE_HUB_SUPER_SPEED << 8),
230              0,
231              Buf,
232              32
233              );
234 
235   return Status;
236 }
237 
238 /**
239   Usb hub control transfer to get the hub descriptor.
240 
241   @param  HubDev                The hub device.
242   @param  Buf                   The buffer to hold the descriptor.
243   @param  Len                   The length to retrieve.
244 
245   @retval EFI_SUCCESS           The hub descriptor is retrieved.
246   @retval Others                Failed to retrieve the hub descriptor.
247 
248 **/
249 EFI_STATUS
UsbHubCtrlGetHubDesc(IN USB_DEVICE * HubDev,OUT VOID * Buf,IN UINTN Len)250 UsbHubCtrlGetHubDesc (
251   IN  USB_DEVICE          *HubDev,
252   OUT VOID                *Buf,
253   IN  UINTN               Len
254   )
255 {
256   EFI_STATUS              Status;
257 
258   Status = UsbCtrlRequest (
259              HubDev,
260              EfiUsbDataIn,
261              USB_REQ_TYPE_CLASS,
262              USB_HUB_TARGET_HUB,
263              USB_HUB_REQ_GET_DESC,
264              (UINT16) (USB_DESC_TYPE_HUB << 8),
265              0,
266              Buf,
267              Len
268              );
269 
270   return Status;
271 }
272 
273 
274 /**
275   Usb hub control transfer to get the hub status.
276 
277   @param  HubDev                The hub device.
278   @param  State                 The variable to return the status.
279 
280   @retval EFI_SUCCESS           The hub status is returned in State.
281   @retval Others                Failed to get the hub status.
282 
283 **/
284 EFI_STATUS
UsbHubCtrlGetHubStatus(IN USB_DEVICE * HubDev,OUT UINT32 * State)285 UsbHubCtrlGetHubStatus (
286   IN  USB_DEVICE          *HubDev,
287   OUT UINT32              *State
288   )
289 {
290   EFI_STATUS              Status;
291 
292   Status = UsbCtrlRequest (
293              HubDev,
294              EfiUsbDataIn,
295              USB_REQ_TYPE_CLASS,
296              USB_HUB_TARGET_HUB,
297              USB_HUB_REQ_GET_STATUS,
298              0,
299              0,
300              State,
301              4
302              );
303 
304   return Status;
305 }
306 
307 
308 /**
309   Usb hub control transfer to get the port status.
310 
311   @param  HubDev                The hub device.
312   @param  Port                  The port of the hub.
313   @param  State                 Variable to return the hub port state.
314 
315   @retval EFI_SUCCESS           The port state is returned in State.
316   @retval Others                Failed to retrieve the port state.
317 
318 **/
319 EFI_STATUS
UsbHubCtrlGetPortStatus(IN USB_DEVICE * HubDev,IN UINT8 Port,OUT VOID * State)320 UsbHubCtrlGetPortStatus (
321   IN  USB_DEVICE          *HubDev,
322   IN  UINT8               Port,
323   OUT VOID                *State
324   )
325 {
326   EFI_STATUS              Status;
327 
328   //
329   // In USB bus, all the port index starts from 0. But HUB
330   // indexes its port from 1. So, port number is added one.
331   // No need to convert the hub bit to UEFI definition, they
332   // are the same
333   //
334   Status = UsbCtrlRequest (
335              HubDev,
336              EfiUsbDataIn,
337              USB_REQ_TYPE_CLASS,
338              USB_HUB_TARGET_PORT,
339              USB_HUB_REQ_GET_STATUS,
340              0,
341              (UINT16) (Port + 1),
342              State,
343              4
344              );
345 
346   return Status;
347 }
348 
349 
350 /**
351   Usb hub control transfer to reset the TT (Transaction Transaltor).
352 
353   @param  HubDev                The hub device.
354   @param  Port                  The port of the hub.
355 
356   @retval EFI_SUCCESS           The TT of the hub is reset.
357   @retval Others                Failed to reset the port.
358 
359 **/
360 EFI_STATUS
UsbHubCtrlResetTT(IN USB_DEVICE * HubDev,IN UINT8 Port)361 UsbHubCtrlResetTT (
362   IN  USB_DEVICE          *HubDev,
363   IN  UINT8               Port
364   )
365 {
366   EFI_STATUS              Status;
367 
368   Status = UsbCtrlRequest (
369              HubDev,
370              EfiUsbNoData,
371              USB_REQ_TYPE_CLASS,
372              USB_HUB_TARGET_HUB,
373              USB_HUB_REQ_RESET_TT,
374              0,
375              (UINT16) (Port + 1),
376              NULL,
377              0
378              );
379 
380   return Status;
381 }
382 
383 
384 /**
385   Usb hub control transfer to set the hub feature.
386 
387   @param  HubDev                The hub device.
388   @param  Feature               The feature to set.
389 
390   @retval EFI_SUCESS            The feature is set for the hub.
391   @retval Others                Failed to set the feature.
392 
393 **/
394 EFI_STATUS
UsbHubCtrlSetHubFeature(IN USB_DEVICE * HubDev,IN UINT8 Feature)395 UsbHubCtrlSetHubFeature (
396   IN  USB_DEVICE          *HubDev,
397   IN  UINT8               Feature
398   )
399 {
400   EFI_STATUS              Status;
401 
402   Status = UsbCtrlRequest (
403              HubDev,
404              EfiUsbNoData,
405              USB_REQ_TYPE_CLASS,
406              USB_HUB_TARGET_HUB,
407              USB_HUB_REQ_SET_FEATURE,
408              Feature,
409              0,
410              NULL,
411              0
412              );
413 
414   return Status;
415 }
416 
417 
418 /**
419   Usb hub control transfer to set the port feature.
420 
421   @param  HubDev                The Usb hub device.
422   @param  Port                  The Usb port to set feature for.
423   @param  Feature               The feature to set.
424 
425   @retval EFI_SUCCESS           The feature is set for the port.
426   @retval Others                Failed to set the feature.
427 
428 **/
429 EFI_STATUS
UsbHubCtrlSetPortFeature(IN USB_DEVICE * HubDev,IN UINT8 Port,IN UINT8 Feature)430 UsbHubCtrlSetPortFeature (
431   IN USB_DEVICE           *HubDev,
432   IN UINT8                Port,
433   IN UINT8                Feature
434   )
435 {
436   EFI_STATUS              Status;
437 
438   //
439   // In USB bus, all the port index starts from 0. But HUB
440   // indexes its port from 1. So, port number is added one.
441   //
442   Status = UsbCtrlRequest (
443              HubDev,
444              EfiUsbNoData,
445              USB_REQ_TYPE_CLASS,
446              USB_HUB_TARGET_PORT,
447              USB_HUB_REQ_SET_FEATURE,
448              Feature,
449              (UINT16) (Port + 1),
450              NULL,
451              0
452              );
453 
454   return Status;
455 }
456 
457 
458 /**
459   Read the whole usb hub descriptor. It is necessary
460   to do it in two steps because hub descriptor is of
461   variable length.
462 
463   @param  HubDev                The hub device.
464   @param  HubDesc               The variable to return the descriptor.
465 
466   @retval EFI_SUCCESS           The hub descriptor is read.
467   @retval Others                Failed to read the hub descriptor.
468 
469 **/
470 EFI_STATUS
UsbHubReadDesc(IN USB_DEVICE * HubDev,OUT EFI_USB_HUB_DESCRIPTOR * HubDesc)471 UsbHubReadDesc (
472   IN  USB_DEVICE              *HubDev,
473   OUT EFI_USB_HUB_DESCRIPTOR  *HubDesc
474   )
475 {
476   EFI_STATUS              Status;
477 
478   if (HubDev->Speed == EFI_USB_SPEED_SUPER) {
479     //
480     // Get the super speed hub descriptor
481     //
482     Status = UsbHubCtrlGetSuperSpeedHubDesc (HubDev, HubDesc);
483   } else {
484 
485     //
486     // First get the hub descriptor length
487     //
488     Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, 2);
489 
490     if (EFI_ERROR (Status)) {
491       return Status;
492     }
493 
494     //
495     // Get the whole hub descriptor
496     //
497     Status = UsbHubCtrlGetHubDesc (HubDev, HubDesc, HubDesc->Length);
498   }
499 
500   return Status;
501 }
502 
503 
504 
505 /**
506   Ack the hub change bits. If these bits are not ACKed, Hub will
507   always return changed bit map from its interrupt endpoint.
508 
509   @param  HubDev                The hub device.
510 
511   @retval EFI_SUCCESS           The hub change status is ACKed.
512   @retval Others                Failed to ACK the hub status.
513 
514 **/
515 EFI_STATUS
UsbHubAckHubStatus(IN USB_DEVICE * HubDev)516 UsbHubAckHubStatus (
517   IN  USB_DEVICE         *HubDev
518   )
519 {
520   EFI_USB_PORT_STATUS     HubState;
521   EFI_STATUS              Status;
522 
523   Status = UsbHubCtrlGetHubStatus (HubDev, (UINT32 *) &HubState);
524 
525   if (EFI_ERROR (Status)) {
526     return Status;
527   }
528 
529   if (USB_BIT_IS_SET (HubState.PortChangeStatus, USB_HUB_STAT_C_LOCAL_POWER)) {
530     UsbHubCtrlClearHubFeature (HubDev, USB_HUB_C_HUB_LOCAL_POWER);
531   }
532 
533   if (USB_BIT_IS_SET (HubState.PortChangeStatus, USB_HUB_STAT_C_OVER_CURRENT)) {
534     UsbHubCtrlClearHubFeature (HubDev, USB_HUB_C_HUB_OVER_CURRENT);
535   }
536 
537   return EFI_SUCCESS;
538 }
539 
540 
541 /**
542   Test whether the interface is a hub interface.
543 
544   @param  UsbIf                 The interface to test.
545 
546   @retval TRUE                  The interface is a hub interface.
547   @retval FALSE                 The interface isn't a hub interface.
548 
549 **/
550 BOOLEAN
UsbIsHubInterface(IN USB_INTERFACE * UsbIf)551 UsbIsHubInterface (
552   IN USB_INTERFACE        *UsbIf
553   )
554 {
555   EFI_USB_INTERFACE_DESCRIPTOR  *Setting;
556 
557   //
558   // If the hub is a high-speed hub with multiple TT,
559   // the hub will has a default setting of single TT.
560   //
561   Setting = &UsbIf->IfSetting->Desc;
562 
563   if ((Setting->InterfaceClass == USB_HUB_CLASS_CODE) &&
564       (Setting->InterfaceSubClass == USB_HUB_SUBCLASS_CODE)) {
565 
566     return TRUE;
567   }
568 
569   return FALSE;
570 }
571 
572 
573 /**
574   The callback function to the USB hub status change
575   interrupt endpoint. It is called periodically by
576   the underlying host controller.
577 
578   @param  Data                  The data read.
579   @param  DataLength            The length of the data read.
580   @param  Context               The context.
581   @param  Result                The result of the last interrupt transfer.
582 
583   @retval EFI_SUCCESS           The process is OK.
584   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource.
585 
586 **/
587 EFI_STATUS
588 EFIAPI
UsbOnHubInterrupt(IN VOID * Data,IN UINTN DataLength,IN VOID * Context,IN UINT32 Result)589 UsbOnHubInterrupt (
590   IN  VOID                *Data,
591   IN  UINTN               DataLength,
592   IN  VOID                *Context,
593   IN  UINT32              Result
594   )
595 {
596   USB_INTERFACE               *HubIf;
597   EFI_USB_IO_PROTOCOL         *UsbIo;
598   EFI_USB_ENDPOINT_DESCRIPTOR *EpDesc;
599   EFI_STATUS                  Status;
600 
601   HubIf   = (USB_INTERFACE *) Context;
602   UsbIo   = &(HubIf->UsbIo);
603   EpDesc  = &(HubIf->HubEp->Desc);
604 
605   if (Result != EFI_USB_NOERROR) {
606     //
607     // If endpoint is stalled, clear the stall. Use UsbIo to access
608     // the control transfer so internal status are maintained.
609     //
610     if (USB_BIT_IS_SET (Result, EFI_USB_ERR_STALL)) {
611       UsbIoClearFeature (
612         UsbIo,
613         USB_TARGET_ENDPOINT,
614         USB_FEATURE_ENDPOINT_HALT,
615         EpDesc->EndpointAddress
616         );
617     }
618 
619     //
620     // Delete and submit a new async interrupt
621     //
622     Status = UsbIo->UsbAsyncInterruptTransfer (
623                       UsbIo,
624                       EpDesc->EndpointAddress,
625                       FALSE,
626                       0,
627                       0,
628                       NULL,
629                       NULL
630                       );
631 
632     if (EFI_ERROR (Status)) {
633       DEBUG (( EFI_D_ERROR, "UsbOnHubInterrupt: failed to remove async transfer - %r\n", Status));
634       return Status;
635     }
636 
637     Status = UsbIo->UsbAsyncInterruptTransfer (
638                       UsbIo,
639                       EpDesc->EndpointAddress,
640                       TRUE,
641                       USB_HUB_POLL_INTERVAL,
642                       HubIf->NumOfPort / 8 + 1,
643                       UsbOnHubInterrupt,
644                       HubIf
645                       );
646 
647     if (EFI_ERROR (Status)) {
648       DEBUG (( EFI_D_ERROR, "UsbOnHubInterrupt: failed to submit new async transfer - %r\n", Status));
649     }
650 
651     return Status;
652   }
653 
654   if ((DataLength == 0) || (Data == NULL)) {
655     return EFI_SUCCESS;
656   }
657 
658   //
659   // OK, actually something is changed, save the change map
660   // then signal the HUB to do enumeration. This is a good
661   // practise since UsbOnHubInterrupt is called in the context
662   // of host contrller's AsyncInterrupt monitor.
663   //
664   HubIf->ChangeMap = AllocateZeroPool (DataLength);
665 
666   if (HubIf->ChangeMap == NULL) {
667     return EFI_OUT_OF_RESOURCES;
668   }
669 
670   CopyMem (HubIf->ChangeMap, Data, DataLength);
671   gBS->SignalEvent (HubIf->HubNotify);
672 
673   return EFI_SUCCESS;
674 }
675 
676 
677 
678 
679 /**
680   Initialize the device for a non-root hub.
681 
682   @param  HubIf                 The USB hub interface.
683 
684   @retval EFI_SUCCESS           The hub is initialized.
685   @retval EFI_DEVICE_ERROR      Failed to initialize the hub.
686 
687 **/
688 EFI_STATUS
UsbHubInit(IN USB_INTERFACE * HubIf)689 UsbHubInit (
690   IN USB_INTERFACE        *HubIf
691   )
692 {
693   EFI_USB_HUB_DESCRIPTOR  HubDesc;
694   USB_ENDPOINT_DESC       *EpDesc;
695   USB_INTERFACE_SETTING   *Setting;
696   EFI_USB_IO_PROTOCOL     *UsbIo;
697   USB_DEVICE              *HubDev;
698   EFI_STATUS              Status;
699   UINT8                   Index;
700   UINT8                   NumEndpoints;
701   UINT16                  Depth;
702 
703   //
704   // Locate the interrupt endpoint for port change map
705   //
706   HubIf->IsHub  = FALSE;
707   Setting       = HubIf->IfSetting;
708   HubDev        = HubIf->Device;
709   EpDesc        = NULL;
710   NumEndpoints  = Setting->Desc.NumEndpoints;
711 
712   for (Index = 0; Index < NumEndpoints; Index++) {
713     ASSERT ((Setting->Endpoints != NULL) && (Setting->Endpoints[Index] != NULL));
714 
715     EpDesc = Setting->Endpoints[Index];
716 
717     if (USB_BIT_IS_SET (EpDesc->Desc.EndpointAddress, USB_ENDPOINT_DIR_IN) &&
718        (USB_ENDPOINT_TYPE (&EpDesc->Desc) == USB_ENDPOINT_INTERRUPT)) {
719       break;
720     }
721   }
722 
723   if (Index == NumEndpoints) {
724     DEBUG (( EFI_D_ERROR, "UsbHubInit: no interrupt endpoint found for hub %d\n", HubDev->Address));
725     return EFI_DEVICE_ERROR;
726   }
727 
728   Status = UsbHubReadDesc (HubDev, &HubDesc);
729 
730   if (EFI_ERROR (Status)) {
731     DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to read HUB descriptor %r\n", Status));
732     return Status;
733   }
734 
735   HubIf->NumOfPort = HubDesc.NumPorts;
736 
737   DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d has %d ports\n", HubDev->Address,HubIf->NumOfPort));
738 
739   //
740   // OK, set IsHub to TRUE. Now usb bus can handle this device
741   // as a working HUB. If failed eariler, bus driver will not
742   // recognize it as a hub. Other parts of the bus should be able
743   // to work.
744   //
745   HubIf->IsHub  = TRUE;
746   HubIf->HubApi = &mUsbHubApi;
747   HubIf->HubEp  = EpDesc;
748 
749   if (HubIf->Device->Speed == EFI_USB_SPEED_SUPER) {
750     Depth = (UINT16)(HubIf->Device->Tier - 1);
751     DEBUG ((EFI_D_INFO, "UsbHubInit: Set Hub Depth as 0x%x\n", Depth));
752     UsbHubCtrlSetHubDepth (HubIf->Device, Depth);
753 
754     for (Index = 0; Index < HubDesc.NumPorts; Index++) {
755       UsbHubCtrlSetPortFeature (HubIf->Device, Index, USB_HUB_PORT_REMOTE_WAKE_MASK);
756     }
757   } else {
758     //
759     // Feed power to all the hub ports. It should be ok
760     // for both gang/individual powered hubs.
761     //
762     for (Index = 0; Index < HubDesc.NumPorts; Index++) {
763       UsbHubCtrlSetPortFeature (HubIf->Device, Index, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_POWER);
764     }
765 
766     //
767     // Update for the usb hub has no power on delay requirement
768     //
769     if (HubDesc.PwrOn2PwrGood > 0) {
770       gBS->Stall (HubDesc.PwrOn2PwrGood * USB_SET_PORT_POWER_STALL);
771     }
772     UsbHubAckHubStatus (HubIf->Device);
773   }
774 
775   //
776   // Create an event to enumerate the hub's port. On
777   //
778   Status = gBS->CreateEvent (
779                   EVT_NOTIFY_SIGNAL,
780                   TPL_CALLBACK,
781                   UsbHubEnumeration,
782                   HubIf,
783                   &HubIf->HubNotify
784                   );
785 
786   if (EFI_ERROR (Status)) {
787     DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to create signal for hub %d - %r\n",
788                 HubDev->Address, Status));
789 
790     return Status;
791   }
792 
793   //
794   // Create AsyncInterrupt to query hub port change endpoint
795   // periodically. If the hub ports are changed, hub will return
796   // changed port map from the interrupt endpoint. The port map
797   // must be able to hold (HubIf->NumOfPort + 1) bits (one bit for
798   // host change status).
799   //
800   UsbIo  = &HubIf->UsbIo;
801   Status = UsbIo->UsbAsyncInterruptTransfer (
802                     UsbIo,
803                     EpDesc->Desc.EndpointAddress,
804                     TRUE,
805                     USB_HUB_POLL_INTERVAL,
806                     HubIf->NumOfPort / 8 + 1,
807                     UsbOnHubInterrupt,
808                     HubIf
809                     );
810 
811   if (EFI_ERROR (Status)) {
812     DEBUG (( EFI_D_ERROR, "UsbHubInit: failed to queue interrupt transfer for hub %d - %r\n",
813                 HubDev->Address, Status));
814 
815     gBS->CloseEvent (HubIf->HubNotify);
816     HubIf->HubNotify = NULL;
817 
818     return Status;
819   }
820 
821   DEBUG (( EFI_D_INFO, "UsbHubInit: hub %d initialized\n", HubDev->Address));
822   return Status;
823 }
824 
825 
826 
827 /**
828   Get the port status. This function is required to
829   ACK the port change bits although it will return
830   the port changes in PortState. Bus enumeration code
831   doesn't need to ACK the port change bits.
832 
833   @param  HubIf                 The hub interface.
834   @param  Port                  The port of the hub to get state.
835   @param  PortState             Variable to return the port state.
836 
837   @retval EFI_SUCCESS           The port status is successfully returned.
838   @retval Others                Failed to return the status.
839 
840 **/
841 EFI_STATUS
UsbHubGetPortStatus(IN USB_INTERFACE * HubIf,IN UINT8 Port,OUT EFI_USB_PORT_STATUS * PortState)842 UsbHubGetPortStatus (
843   IN  USB_INTERFACE       *HubIf,
844   IN  UINT8               Port,
845   OUT EFI_USB_PORT_STATUS *PortState
846   )
847 {
848   EFI_STATUS              Status;
849 
850   Status  = UsbHubCtrlGetPortStatus (HubIf->Device, Port, PortState);
851 
852   return Status;
853 }
854 
855 
856 
857 /**
858   Clear the port change status.
859 
860   @param  HubIf                 The hub interface.
861   @param  Port                  The hub port.
862 
863 **/
864 VOID
UsbHubClearPortChange(IN USB_INTERFACE * HubIf,IN UINT8 Port)865 UsbHubClearPortChange (
866   IN USB_INTERFACE        *HubIf,
867   IN UINT8                Port
868   )
869 {
870   EFI_USB_PORT_STATUS     PortState;
871   USB_CHANGE_FEATURE_MAP  *Map;
872   UINTN                   Index;
873   EFI_STATUS              Status;
874 
875   Status = UsbHubGetPortStatus (HubIf, Port, &PortState);
876 
877   if (EFI_ERROR (Status)) {
878     return;
879   }
880 
881   //
882   // OK, get the usb port status, now ACK the change bits.
883   // Don't return error when failed to clear the change bits.
884   // It may lead to extra port state report. USB bus should
885   // be able to handle this.
886   //
887   for (Index = 0; Index < sizeof (mHubFeatureMap) / sizeof (mHubFeatureMap[0]); Index++) {
888     Map = &mHubFeatureMap[Index];
889 
890     if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {
891       UsbHubCtrlClearPortFeature (HubIf->Device, Port, (UINT16) Map->Feature);
892     }
893   }
894 }
895 
896 
897 
898 /**
899   Function to set the port feature for non-root hub.
900 
901   @param  HubIf                 The hub interface.
902   @param  Port                  The port of the hub.
903   @param  Feature               The feature of the port to set.
904 
905   @retval EFI_SUCCESS           The hub port feature is set.
906   @retval Others                Failed to set the port feature.
907 
908 **/
909 EFI_STATUS
UsbHubSetPortFeature(IN USB_INTERFACE * HubIf,IN UINT8 Port,IN EFI_USB_PORT_FEATURE Feature)910 UsbHubSetPortFeature (
911   IN USB_INTERFACE        *HubIf,
912   IN UINT8                Port,
913   IN EFI_USB_PORT_FEATURE Feature
914   )
915 {
916   EFI_STATUS              Status;
917 
918   Status = UsbHubCtrlSetPortFeature (HubIf->Device, Port, (UINT8) Feature);
919 
920   return Status;
921 }
922 
923 
924 /**
925   Interface function to clear the port feature for non-root hub.
926 
927   @param  HubIf                 The hub interface.
928   @param  Port                  The port of the hub to clear feature for.
929   @param  Feature               The feature to clear.
930 
931   @retval EFI_SUCCESS           The port feature is cleared.
932   @retval Others                Failed to clear the port feature.
933 
934 **/
935 EFI_STATUS
UsbHubClearPortFeature(IN USB_INTERFACE * HubIf,IN UINT8 Port,IN EFI_USB_PORT_FEATURE Feature)936 UsbHubClearPortFeature (
937   IN USB_INTERFACE        *HubIf,
938   IN UINT8                Port,
939   IN EFI_USB_PORT_FEATURE Feature
940   )
941 {
942   EFI_STATUS              Status;
943 
944   Status = UsbHubCtrlClearPortFeature (HubIf->Device, Port, (UINT8) Feature);
945 
946   return Status;
947 }
948 
949 
950 /**
951   Interface function to reset the port.
952 
953   @param  HubIf                 The hub interface.
954   @param  Port                  The port to reset.
955 
956   @retval EFI_SUCCESS           The hub port is reset.
957   @retval EFI_TIMEOUT           Failed to reset the port in time.
958   @retval Others                Failed to reset the port.
959 
960 **/
961 EFI_STATUS
UsbHubResetPort(IN USB_INTERFACE * HubIf,IN UINT8 Port)962 UsbHubResetPort (
963   IN USB_INTERFACE        *HubIf,
964   IN UINT8                Port
965   )
966 {
967   EFI_USB_PORT_STATUS     PortState;
968   UINTN                   Index;
969   EFI_STATUS              Status;
970 
971   Status = UsbHubGetPortStatus (HubIf, Port, &PortState);
972 
973   if (EFI_ERROR (Status)) {
974     return Status;
975   } else if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
976     DEBUG (( EFI_D_INFO, "UsbHubResetPort: skip reset on hub %p port %d\n", HubIf, Port));
977     return EFI_SUCCESS;
978   }
979 
980   Status  = UsbHubSetPortFeature (HubIf, Port, (EFI_USB_PORT_FEATURE) USB_HUB_PORT_RESET);
981 
982   if (EFI_ERROR (Status)) {
983     return Status;
984   }
985 
986   //
987   // Drive the reset signal for worst 20ms. Check USB 2.0 Spec
988   // section 7.1.7.5 for timing requirements.
989   //
990   gBS->Stall (USB_SET_PORT_RESET_STALL);
991 
992   //
993   // Check USB_PORT_STAT_C_RESET bit to see if the resetting state is done.
994   //
995   ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));
996 
997   for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
998     Status = UsbHubGetPortStatus (HubIf, Port, &PortState);
999 
1000     if (EFI_ERROR (Status)) {
1001       return Status;
1002     }
1003 
1004     if (!EFI_ERROR (Status) &&
1005         USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
1006       gBS->Stall (USB_SET_PORT_RECOVERY_STALL);
1007       return EFI_SUCCESS;
1008     }
1009 
1010     gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);
1011   }
1012 
1013   return EFI_TIMEOUT;
1014 }
1015 
1016 
1017 /**
1018   Release the hub's control of the interface.
1019 
1020   @param  HubIf                 The hub interface.
1021 
1022   @retval EFI_SUCCESS           The interface is release of hub control.
1023 
1024 **/
1025 EFI_STATUS
UsbHubRelease(IN USB_INTERFACE * HubIf)1026 UsbHubRelease (
1027   IN USB_INTERFACE        *HubIf
1028   )
1029 {
1030   EFI_USB_IO_PROTOCOL     *UsbIo;
1031   EFI_STATUS              Status;
1032 
1033   UsbIo  = &HubIf->UsbIo;
1034   Status = UsbIo->UsbAsyncInterruptTransfer (
1035                     UsbIo,
1036                     HubIf->HubEp->Desc.EndpointAddress,
1037                     FALSE,
1038                     USB_HUB_POLL_INTERVAL,
1039                     0,
1040                     NULL,
1041                     0
1042                     );
1043 
1044   if (EFI_ERROR (Status)) {
1045     return Status;
1046   }
1047 
1048   gBS->CloseEvent (HubIf->HubNotify);
1049 
1050   HubIf->IsHub      = FALSE;
1051   HubIf->HubApi     = NULL;
1052   HubIf->HubEp      = NULL;
1053   HubIf->HubNotify  = NULL;
1054 
1055   DEBUG (( EFI_D_INFO, "UsbHubRelease: hub device %d released\n", HubIf->Device->Address));
1056   return EFI_SUCCESS;
1057 }
1058 
1059 
1060 
1061 /**
1062   Initialize the interface for root hub.
1063 
1064   @param  HubIf                 The root hub interface.
1065 
1066   @retval EFI_SUCCESS           The interface is initialized for root hub.
1067   @retval Others                Failed to initialize the hub.
1068 
1069 **/
1070 EFI_STATUS
UsbRootHubInit(IN USB_INTERFACE * HubIf)1071 UsbRootHubInit (
1072   IN USB_INTERFACE        *HubIf
1073   )
1074 {
1075   EFI_STATUS              Status;
1076   UINT8                   MaxSpeed;
1077   UINT8                   NumOfPort;
1078   UINT8                   Support64;
1079 
1080   Status = UsbHcGetCapability (HubIf->Device->Bus, &MaxSpeed, &NumOfPort, &Support64);
1081 
1082   if (EFI_ERROR (Status)) {
1083     return Status;
1084   }
1085 
1086   DEBUG (( EFI_D_INFO, "UsbRootHubInit: root hub %p - max speed %d, %d ports\n",
1087               HubIf, MaxSpeed, NumOfPort));
1088 
1089   HubIf->IsHub      = TRUE;
1090   HubIf->HubApi     = &mUsbRootHubApi;
1091   HubIf->HubEp      = NULL;
1092   HubIf->MaxSpeed   = MaxSpeed;
1093   HubIf->NumOfPort  = NumOfPort;
1094   HubIf->HubNotify  = NULL;
1095 
1096   //
1097   // Create a timer to poll root hub ports periodically
1098   //
1099   Status = gBS->CreateEvent (
1100                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
1101                   TPL_CALLBACK,
1102                   UsbRootHubEnumeration,
1103                   HubIf,
1104                   &HubIf->HubNotify
1105                   );
1106 
1107   if (EFI_ERROR (Status)) {
1108     return Status;
1109   }
1110 
1111   //
1112   // It should signal the event immediately here, or device detection
1113   // by bus enumeration might be delayed by the timer interval.
1114   //
1115   gBS->SignalEvent (HubIf->HubNotify);
1116 
1117   Status = gBS->SetTimer (
1118                   HubIf->HubNotify,
1119                   TimerPeriodic,
1120                   USB_ROOTHUB_POLL_INTERVAL
1121                   );
1122 
1123   if (EFI_ERROR (Status)) {
1124     gBS->CloseEvent (HubIf->HubNotify);
1125   }
1126 
1127   return Status;
1128 }
1129 
1130 
1131 /**
1132   Get the port status. This function is required to
1133   ACK the port change bits although it will return
1134   the port changes in PortState. Bus enumeration code
1135   doesn't need to ACK the port change bits.
1136 
1137   @param  HubIf                 The root hub interface.
1138   @param  Port                  The root hub port to get the state.
1139   @param  PortState             Variable to return the port state.
1140 
1141   @retval EFI_SUCCESS           The port state is returned.
1142   @retval Others                Failed to retrieve the port state.
1143 
1144 **/
1145 EFI_STATUS
UsbRootHubGetPortStatus(IN USB_INTERFACE * HubIf,IN UINT8 Port,OUT EFI_USB_PORT_STATUS * PortState)1146 UsbRootHubGetPortStatus (
1147   IN  USB_INTERFACE       *HubIf,
1148   IN  UINT8               Port,
1149   OUT EFI_USB_PORT_STATUS *PortState
1150   )
1151 {
1152   USB_BUS                 *Bus;
1153   EFI_STATUS              Status;
1154 
1155   Bus     = HubIf->Device->Bus;
1156   Status  = UsbHcGetRootHubPortStatus (Bus, Port, PortState);
1157 
1158   return Status;
1159 }
1160 
1161 
1162 /**
1163   Clear the port change status.
1164 
1165   @param  HubIf                 The root hub interface.
1166   @param  Port                  The root hub port.
1167 
1168 **/
1169 VOID
UsbRootHubClearPortChange(IN USB_INTERFACE * HubIf,IN UINT8 Port)1170 UsbRootHubClearPortChange (
1171   IN USB_INTERFACE        *HubIf,
1172   IN UINT8                Port
1173   )
1174 {
1175   EFI_USB_PORT_STATUS     PortState;
1176   USB_CHANGE_FEATURE_MAP  *Map;
1177   UINTN                   Index;
1178   EFI_STATUS              Status;
1179 
1180   Status = UsbRootHubGetPortStatus (HubIf, Port, &PortState);
1181 
1182   if (EFI_ERROR (Status)) {
1183     return;
1184   }
1185 
1186   //
1187   // OK, get the usb port status, now ACK the change bits.
1188   // Don't return error when failed to clear the change bits.
1189   // It may lead to extra port state report. USB bus should
1190   // be able to handle this.
1191   //
1192   for (Index = 0; Index < sizeof (mRootHubFeatureMap) / sizeof (mRootHubFeatureMap[0]); Index++) {
1193     Map = &mRootHubFeatureMap[Index];
1194 
1195     if (USB_BIT_IS_SET (PortState.PortChangeStatus, Map->ChangedBit)) {
1196       UsbHcClearRootHubPortFeature (HubIf->Device->Bus, Port, (EFI_USB_PORT_FEATURE) Map->Feature);
1197     }
1198   }
1199 }
1200 
1201 
1202 /**
1203   Set the root hub port feature.
1204 
1205   @param  HubIf                 The Usb hub interface.
1206   @param  Port                  The hub port.
1207   @param  Feature               The feature to set.
1208 
1209   @retval EFI_SUCCESS           The root hub port is set with the feature.
1210   @retval Others                Failed to set the feature.
1211 
1212 **/
1213 EFI_STATUS
UsbRootHubSetPortFeature(IN USB_INTERFACE * HubIf,IN UINT8 Port,IN EFI_USB_PORT_FEATURE Feature)1214 UsbRootHubSetPortFeature (
1215   IN USB_INTERFACE        *HubIf,
1216   IN UINT8                Port,
1217   IN EFI_USB_PORT_FEATURE Feature
1218   )
1219 {
1220   EFI_STATUS              Status;
1221 
1222   Status  = UsbHcSetRootHubPortFeature (HubIf->Device->Bus, Port, Feature);
1223 
1224   return Status;
1225 }
1226 
1227 
1228 /**
1229   Clear the root hub port feature.
1230 
1231   @param  HubIf                 The root hub interface.
1232   @param  Port                  The root hub port.
1233   @param  Feature               The feature to clear.
1234 
1235   @retval EFI_SUCCESS           The root hub port is cleared of the feature.
1236   @retval Others                Failed to clear the feature.
1237 
1238 **/
1239 EFI_STATUS
UsbRootHubClearPortFeature(IN USB_INTERFACE * HubIf,IN UINT8 Port,IN EFI_USB_PORT_FEATURE Feature)1240 UsbRootHubClearPortFeature (
1241   IN USB_INTERFACE        *HubIf,
1242   IN UINT8                Port,
1243   IN EFI_USB_PORT_FEATURE Feature
1244   )
1245 {
1246   EFI_STATUS              Status;
1247 
1248   Status  = UsbHcClearRootHubPortFeature (HubIf->Device->Bus, Port, Feature);
1249 
1250   return Status;
1251 }
1252 
1253 
1254 /**
1255   Interface function to reset the root hub port.
1256 
1257   @param  RootIf                The root hub interface.
1258   @param  Port                  The port to reset.
1259 
1260   @retval EFI_SUCCESS           The hub port is reset.
1261   @retval EFI_TIMEOUT           Failed to reset the port in time.
1262   @retval EFI_NOT_FOUND         The low/full speed device connected to high  speed.
1263                                 root hub is released to the companion UHCI.
1264   @retval Others                Failed to reset the port.
1265 
1266 **/
1267 EFI_STATUS
UsbRootHubResetPort(IN USB_INTERFACE * RootIf,IN UINT8 Port)1268 UsbRootHubResetPort (
1269   IN USB_INTERFACE        *RootIf,
1270   IN UINT8                Port
1271   )
1272 {
1273   USB_BUS                 *Bus;
1274   EFI_STATUS              Status;
1275   EFI_USB_PORT_STATUS     PortState;
1276   UINTN                   Index;
1277 
1278   //
1279   // Notice: although EHCI requires that ENABLED bit be cleared
1280   // when reset the port, we don't need to care that here. It
1281   // should be handled in the EHCI driver.
1282   //
1283   Bus     = RootIf->Device->Bus;
1284 
1285   Status = UsbHcGetRootHubPortStatus (Bus, Port, &PortState);
1286 
1287   if (EFI_ERROR (Status)) {
1288     return Status;
1289   } else if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
1290     DEBUG (( EFI_D_INFO, "UsbRootHubResetPort: skip reset on root port %d\n", Port));
1291     return EFI_SUCCESS;
1292   }
1293 
1294   Status  = UsbHcSetRootHubPortFeature (Bus, Port, EfiUsbPortReset);
1295 
1296   if (EFI_ERROR (Status)) {
1297     DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to start reset on port %d\n", Port));
1298     return Status;
1299   }
1300 
1301   //
1302   // Drive the reset signal for at least 50ms. Check USB 2.0 Spec
1303   // section 7.1.7.5 for timing requirements.
1304   //
1305   gBS->Stall (USB_SET_ROOT_PORT_RESET_STALL);
1306 
1307   Status = UsbHcClearRootHubPortFeature (Bus, Port, EfiUsbPortReset);
1308 
1309   if (EFI_ERROR (Status)) {
1310     DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to clear reset on port %d\n", Port));
1311     return Status;
1312   }
1313 
1314   gBS->Stall (USB_CLR_ROOT_PORT_RESET_STALL);
1315 
1316   //
1317   // USB host controller won't clear the RESET bit until
1318   // reset is actually finished.
1319   //
1320   ZeroMem (&PortState, sizeof (EFI_USB_PORT_STATUS));
1321 
1322   for (Index = 0; Index < USB_WAIT_PORT_STS_CHANGE_LOOP; Index++) {
1323     Status = UsbHcGetRootHubPortStatus (Bus, Port, &PortState);
1324 
1325     if (EFI_ERROR (Status)) {
1326       return Status;
1327     }
1328 
1329     if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_RESET)) {
1330       break;
1331     }
1332 
1333     gBS->Stall (USB_WAIT_PORT_STS_CHANGE_STALL);
1334   }
1335 
1336   if (Index == USB_WAIT_PORT_STS_CHANGE_LOOP) {
1337     DEBUG ((EFI_D_ERROR, "UsbRootHubResetPort: reset not finished in time on port %d\n", Port));
1338     return EFI_TIMEOUT;
1339   }
1340 
1341   if (!USB_BIT_IS_SET (PortState.PortStatus, USB_PORT_STAT_ENABLE)) {
1342     //
1343     // OK, the port is reset. If root hub is of high speed and
1344     // the device is of low/full speed, release the ownership to
1345     // companion UHCI. If root hub is of full speed, it won't
1346     // automatically enable the port, we need to enable it manually.
1347     //
1348     if (RootIf->MaxSpeed == EFI_USB_SPEED_HIGH) {
1349       DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: release low/full speed device (%d) to UHCI\n", Port));
1350 
1351       UsbRootHubSetPortFeature (RootIf, Port, EfiUsbPortOwner);
1352       return EFI_NOT_FOUND;
1353 
1354     } else {
1355 
1356       Status = UsbRootHubSetPortFeature (RootIf, Port, EfiUsbPortEnable);
1357 
1358       if (EFI_ERROR (Status)) {
1359         DEBUG (( EFI_D_ERROR, "UsbRootHubResetPort: failed to enable port %d for UHCI\n", Port));
1360         return Status;
1361       }
1362 
1363       gBS->Stall (USB_SET_ROOT_PORT_ENABLE_STALL);
1364     }
1365   }
1366 
1367   return EFI_SUCCESS;
1368 }
1369 
1370 
1371 /**
1372   Release the root hub's control of the interface.
1373 
1374   @param  HubIf                 The root hub interface.
1375 
1376   @retval EFI_SUCCESS           The root hub's control of the interface is
1377                                 released.
1378 
1379 **/
1380 EFI_STATUS
UsbRootHubRelease(IN USB_INTERFACE * HubIf)1381 UsbRootHubRelease (
1382   IN USB_INTERFACE        *HubIf
1383   )
1384 {
1385   DEBUG (( EFI_D_INFO, "UsbRootHubRelease: root hub released for hub %p\n", HubIf));
1386 
1387   gBS->SetTimer (HubIf->HubNotify, TimerCancel, USB_ROOTHUB_POLL_INTERVAL);
1388   gBS->CloseEvent (HubIf->HubNotify);
1389 
1390   return EFI_SUCCESS;
1391 }
1392 
1393 USB_HUB_API mUsbHubApi = {
1394   UsbHubInit,
1395   UsbHubGetPortStatus,
1396   UsbHubClearPortChange,
1397   UsbHubSetPortFeature,
1398   UsbHubClearPortFeature,
1399   UsbHubResetPort,
1400   UsbHubRelease
1401 };
1402 
1403 USB_HUB_API mUsbRootHubApi = {
1404   UsbRootHubInit,
1405   UsbRootHubGetPortStatus,
1406   UsbRootHubClearPortChange,
1407   UsbRootHubSetPortFeature,
1408   UsbRootHubClearPortFeature,
1409   UsbRootHubResetPort,
1410   UsbRootHubRelease
1411 };
1412