3 Copyright (c) 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Usb bus enumeration support
29 Return the endpoint descriptor in this interface
31 @param UsbIf The interface to search in
32 @param EpAddr The address of the endpoint to return
34 @return The endpoint descriptor or NULL
39 IN USB_INTERFACE
*UsbIf
,
43 USB_ENDPOINT_DESC
*EpDesc
;
46 for (Index
= 0; Index
< UsbIf
->IfSetting
->Desc
.NumEndpoints
; Index
++) {
47 EpDesc
= UsbIf
->IfSetting
->Endpoints
[Index
];
49 if (EpDesc
->Desc
.EndpointAddress
== EpAddr
) {
59 Free the resource used by USB interface
61 @param UsbIf The USB interface to free
69 IN USB_INTERFACE
*UsbIf
72 UsbCloseHostProtoByChild (UsbIf
->Device
->Bus
, UsbIf
->Handle
);
74 gBS
->UninstallMultipleProtocolInterfaces (
76 &gEfiDevicePathProtocolGuid
,
78 &gEfiUsbIoProtocolGuid
,
83 if (UsbIf
->DevicePath
!= NULL
) {
84 gBS
->FreePool (UsbIf
->DevicePath
);
87 gBS
->FreePool (UsbIf
);
92 Create an interface for the descriptor IfDesc. Each
93 device's configuration can have several interfaces.
95 @param Device The device has the interface descriptor
96 @param IfDesc The interface descriptor
98 @return The created USB interface for the descriptor, or NULL.
104 IN USB_DEVICE
*Device
,
105 IN USB_INTERFACE_DESC
*IfDesc
108 USB_DEVICE_PATH UsbNode
;
109 USB_INTERFACE
*UsbIf
;
110 USB_INTERFACE
*HubIf
;
113 UsbIf
= AllocateZeroPool (sizeof (USB_INTERFACE
));
119 UsbIf
->Signature
= USB_INTERFACE_SIGNATURE
;
120 UsbIf
->Device
= Device
;
121 UsbIf
->IfDesc
= IfDesc
;
122 UsbIf
->IfSetting
= IfDesc
->Settings
[IfDesc
->ActiveIndex
];
127 sizeof (EFI_USB_IO_PROTOCOL
)
131 // Install protocols for USBIO and device path
133 UsbNode
.Header
.Type
= MESSAGING_DEVICE_PATH
;
134 UsbNode
.Header
.SubType
= MSG_USB_DP
;
135 UsbNode
.ParentPortNumber
= Device
->ParentPort
;
136 UsbNode
.InterfaceNumber
= UsbIf
->IfSetting
->Desc
.InterfaceNumber
;
138 SetDevicePathNodeLength (&UsbNode
.Header
, sizeof (UsbNode
));
140 HubIf
= Device
->ParentIf
;
141 ASSERT (HubIf
!= NULL
);
143 UsbIf
->DevicePath
= AppendDevicePathNode (HubIf
->DevicePath
, &UsbNode
.Header
);
145 if (UsbIf
->DevicePath
== NULL
) {
146 DEBUG ((EFI_D_ERROR
, "UsbCreateInterface: failed to create device path\n"));
148 Status
= EFI_OUT_OF_RESOURCES
;
152 Status
= gBS
->InstallMultipleProtocolInterfaces (
154 &gEfiDevicePathProtocolGuid
,
156 &gEfiUsbIoProtocolGuid
,
161 if (EFI_ERROR (Status
)) {
162 DEBUG ((EFI_D_ERROR
, "UsbCreateInterface: failed to install UsbIo - %r\n", Status
));
167 // Open USB Host Controller Protocol by Child
169 Status
= UsbOpenHostProtoByChild (Device
->Bus
, UsbIf
->Handle
);
171 if (EFI_ERROR (Status
)) {
172 gBS
->UninstallMultipleProtocolInterfaces (
174 &gEfiDevicePathProtocolGuid
,
176 &gEfiUsbIoProtocolGuid
,
181 DEBUG ((EFI_D_ERROR
, "UsbCreateInterface: failed to open host for child - %r\n", Status
));
188 if (UsbIf
->DevicePath
) {
189 gBS
->FreePool (UsbIf
->DevicePath
);
192 gBS
->FreePool (UsbIf
);
198 Free the resource used by this USB device
200 @param Device The USB device to free
208 IN USB_DEVICE
*Device
211 if (Device
->DevDesc
!= NULL
) {
212 UsbFreeDevDesc (Device
->DevDesc
);
215 gBS
->FreePool (Device
);
220 Create a device which is on the parent's ParentPort port.
222 @param ParentIf The parent HUB interface
223 @param ParentPort The port on the HUB this device is connected to
225 @return Created USB device
231 IN USB_INTERFACE
*ParentIf
,
237 ASSERT (ParentIf
!= NULL
);
239 Device
= AllocateZeroPool (sizeof (USB_DEVICE
));
241 if (Device
== NULL
) {
245 Device
->Bus
= ParentIf
->Device
->Bus
;
246 Device
->MaxPacket0
= 8;
247 Device
->ParentAddr
= ParentIf
->Device
->Address
;
248 Device
->ParentIf
= ParentIf
;
249 Device
->ParentPort
= ParentPort
;
255 Connect the USB interface with its driver. EFI USB bus will
256 create a USB interface for each seperate interface descriptor.
258 @param UsbIf The interface to connect driver to
260 @return EFI_SUCCESS : Interface is managed by some driver
261 @return Others : Failed to locate a driver for this interface
267 IN USB_INTERFACE
*UsbIf
273 Status
= EFI_SUCCESS
;
276 // Hub is maintained by the USB bus driver. Otherwise try to
277 // connect drivers with this interface
279 if (UsbIsHubInterface (UsbIf
)) {
280 DEBUG ((EFI_D_INFO
, "UsbConnectDriver: found a hub device\n"));
281 Status
= mUsbHubApi
.Init (UsbIf
);
285 // This function is called in both UsbIoControlTransfer and
286 // the timer callback in hub enumeration. So, at least it is
287 // called at TPL_CALLBACK. Some driver sitting on USB has
288 // twisted TPL used. It should be no problem for us to connect
289 // or disconnect at CALLBACK.
291 OldTpl
= UsbGetCurrentTpl ();
292 DEBUG ((EFI_D_INFO
, "UsbConnectDriver: TPL before connect is %d\n", OldTpl
));
294 gBS
->RestoreTPL (TPL_CALLBACK
);
296 Status
= gBS
->ConnectController (UsbIf
->Handle
, NULL
, NULL
, TRUE
);
297 UsbIf
->IsManaged
= (BOOLEAN
)!EFI_ERROR (Status
);
299 DEBUG ((EFI_D_INFO
, "UsbConnectDriver: TPL after connect is %d\n", UsbGetCurrentTpl()));
300 ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK
);
302 gBS
->RaiseTPL (OldTpl
);
310 Select an alternate setting for the interface.
311 Each interface can have several mutually exclusive
312 settings. Only one setting is active. It will
313 also reset its endpoints' toggle to zero.
315 @param IfDesc The interface descriptor to set
316 @param Alternate The alternate setting number to locate
318 @retval EFI_NOT_FOUND There is no setting with this alternate index
319 @retval EFI_SUCCESS The interface is set to Alternate setting.
324 IN USB_INTERFACE_DESC
*IfDesc
,
328 USB_INTERFACE_SETTING
*Setting
;
332 // Locate the active alternate setting
336 for (Index
= 0; Index
< IfDesc
->NumOfSetting
; Index
++) {
337 Setting
= IfDesc
->Settings
[Index
];
339 if (Setting
->Desc
.AlternateSetting
== Alternate
) {
344 if (Index
== IfDesc
->NumOfSetting
) {
345 return EFI_NOT_FOUND
;
348 IfDesc
->ActiveIndex
= Index
;
350 DEBUG ((EFI_D_INFO
, "UsbSelectSetting: setting %d selected for interface %d\n",
351 Alternate
, Setting
->Desc
.InterfaceNumber
));
354 // Reset the endpoint toggle to zero
356 for (Index
= 0; Index
< Setting
->Desc
.NumEndpoints
; Index
++) {
357 Setting
->Endpoints
[Index
]->Toggle
= 0;
365 Select a new configuration for the device. Each
366 device may support several configurations.
368 @param Device The device to select configuration
369 @param ConfigValue The index of the configuration ( != 0)
371 @retval EFI_NOT_FOUND There is no configuration with the index
372 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource
373 @retval EFI_SUCCESS The configuration is selected.
378 IN USB_DEVICE
*Device
,
382 USB_DEVICE_DESC
*DevDesc
;
383 USB_CONFIG_DESC
*ConfigDesc
;
384 USB_INTERFACE_DESC
*IfDesc
;
385 USB_INTERFACE
*UsbIf
;
390 // Locate the active config, then set the device's pointer
392 DevDesc
= Device
->DevDesc
;
395 for (Index
= 0; Index
< DevDesc
->Desc
.NumConfigurations
; Index
++) {
396 ConfigDesc
= DevDesc
->Configs
[Index
];
398 if (ConfigDesc
->Desc
.ConfigurationValue
== ConfigValue
) {
403 if (Index
== DevDesc
->Desc
.NumConfigurations
) {
404 return EFI_NOT_FOUND
;
407 Device
->ActiveConfig
= ConfigDesc
;
409 DEBUG ((EFI_D_INFO
, "UsbSelectConfig: config %d selected for device %d\n",
410 ConfigValue
, Device
->Address
));
413 // Create interfaces for each USB interface descriptor.
415 for (Index
= 0; Index
< ConfigDesc
->Desc
.NumInterfaces
; Index
++) {
417 // First select the default interface setting, and reset
418 // the endpoint toggles to zero for its endpoints.
420 IfDesc
= ConfigDesc
->Interfaces
[Index
];
421 UsbSelectSetting (IfDesc
, IfDesc
->Settings
[0]->Desc
.AlternateSetting
);
424 // Create a USB_INTERFACE and install USB_IO and other protocols
426 UsbIf
= UsbCreateInterface (Device
, ConfigDesc
->Interfaces
[Index
]);
429 return EFI_OUT_OF_RESOURCES
;
432 Device
->Interfaces
[Index
] = UsbIf
;
435 // Connect the device to drivers, if it failed, ignore
436 // the error. Don't let the unsupported interfaces to block
437 // the supported interfaces.
439 Status
= UsbConnectDriver (UsbIf
);
441 if (EFI_ERROR (Status
)) {
442 DEBUG ((EFI_D_ERROR
, "UsbSelectConfig: failed to connect driver %r, ignored\n", Status
));
446 Device
->NumOfInterface
= Index
;
454 Disconnect the USB interface with its driver.
456 @param UsbIf The interface to disconnect driver from
463 UsbDisconnectDriver (
464 IN USB_INTERFACE
*UsbIf
470 // Release the hub if it's a hub controller, otherwise
471 // disconnect the driver if it is managed by other drivers.
474 UsbIf
->HubApi
->Release (UsbIf
);
476 } else if (UsbIf
->IsManaged
) {
478 // This function is called in both UsbIoControlTransfer and
479 // the timer callback in hub enumeration. So, at least it is
480 // called at TPL_CALLBACK. Some driver sitting on USB has
481 // twisted TPL used. It should be no problem for us to connect
482 // or disconnect at CALLBACK.
484 OldTpl
= UsbGetCurrentTpl ();
485 DEBUG ((EFI_D_INFO
, "UsbDisconnectDriver: old TPL is %d\n", OldTpl
));
487 gBS
->RestoreTPL (TPL_CALLBACK
);
489 gBS
->DisconnectController (UsbIf
->Handle
, NULL
, NULL
);
490 UsbIf
->IsManaged
= FALSE
;
492 DEBUG (( EFI_D_INFO
, "UsbDisconnectDriver: TPL after disconnect is %d\n", UsbGetCurrentTpl()));
493 ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK
);
495 gBS
->RaiseTPL (OldTpl
);
502 Remove the current device configuration
504 @param Device The USB device to remove configuration from
511 IN USB_DEVICE
*Device
514 USB_INTERFACE
*UsbIf
;
518 // Remove each interface of the device
520 for (Index
= 0; Index
< Device
->NumOfInterface
; Index
++) {
521 UsbIf
= Device
->Interfaces
[Index
];
527 UsbDisconnectDriver (UsbIf
);
528 UsbFreeInterface (UsbIf
);
529 Device
->Interfaces
[Index
] = NULL
;
532 Device
->ActiveConfig
= NULL
;
533 Device
->NumOfInterface
= 0;
539 Remove the device and all its children from the bus.
541 @param Device The device to remove
543 @retval EFI_SUCCESS The device is removed
548 IN USB_DEVICE
*Device
559 // Remove all the devices on its downstream ports. Search from devices[1].
560 // Devices[0] is the root hub.
562 for (Index
= 1; Index
< USB_MAX_DEVICES
; Index
++) {
563 Child
= Bus
->Devices
[Index
];
565 if ((Child
== NULL
) || (Child
->ParentAddr
!= Device
->Address
)) {
569 Status
= UsbRemoveDevice (Child
);
571 if (EFI_ERROR (Status
)) {
572 DEBUG ((EFI_D_ERROR
, "UsbRemoveDevice: failed to remove child, ignore error\n"));
573 Bus
->Devices
[Index
] = NULL
;
577 UsbRemoveConfig (Device
);
579 DEBUG (( EFI_D_INFO
, "UsbRemoveDevice: device %d removed\n", Device
->Address
));
581 Bus
->Devices
[Device
->Address
] = NULL
;
582 UsbFreeDevice (Device
);
589 Find the child device on the hub's port
591 @param HubIf The hub interface
592 @param Port The port of the hub this child is connected to
594 @return The device on the hub's port, or NULL if there is none
600 IN USB_INTERFACE
*HubIf
,
608 Bus
= HubIf
->Device
->Bus
;
611 // Start checking from device 1, device 0 is the root hub
613 for (Index
= 1; Index
< USB_MAX_DEVICES
; Index
++) {
614 Device
= Bus
->Devices
[Index
];
616 if ((Device
!= NULL
) && (Device
->ParentAddr
== HubIf
->Device
->Address
) &&
617 (Device
->ParentPort
== Port
)) {
629 Enumerate and configure the new device on the port of this HUB interface.
631 @param HubIf The HUB that has the device connected
632 @param Port The port index of the hub (started with zero)
634 @retval EFI_SUCCESS The device is enumerated (added or removed)
635 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the device
636 @retval Others Failed to enumerate the device
642 IN USB_INTERFACE
*HubIf
,
650 EFI_USB_PORT_STATUS PortState
;
655 Address
= USB_MAX_DEVICES
;
656 Parent
= HubIf
->Device
;
658 HubApi
= HubIf
->HubApi
;
660 gBS
->Stall (USB_WAIT_PORT_STABLE_STALL
);
663 // Hub resets the device for at least 10 milliseconds.
664 // Host learns device speed. If device is of low/full speed
665 // and the hub is a EHCI root hub, ResetPort will release
666 // the device to its companion UHCI and return an error.
668 Status
= HubApi
->ResetPort (HubIf
, Port
);
670 if (EFI_ERROR (Status
)) {
671 DEBUG ((EFI_D_ERROR
, "UsbEnumerateNewDev: failed to reset port %d - %r\n", Port
, Status
));
676 DEBUG (( EFI_D_INFO
, "UsbEnumerateNewDev: hub port %d is reset\n", Port
));
678 Child
= UsbCreateDevice (HubIf
, Port
);
681 return EFI_OUT_OF_RESOURCES
;
685 // OK, now identify the device speed. After reset, hub
686 // fully knows the actual device speed.
688 Status
= HubApi
->GetPortStatus (HubIf
, Port
, &PortState
);
690 if (EFI_ERROR (Status
)) {
691 DEBUG ((EFI_D_ERROR
, "UsbEnumerateNewDev: failed to get speed of port %d\n", Port
));
695 if (USB_BIT_IS_SET (PortState
.PortStatus
, USB_PORT_STAT_LOW_SPEED
)) {
696 Child
->Speed
= EFI_USB_SPEED_LOW
;
698 } else if (USB_BIT_IS_SET (PortState
.PortStatus
, USB_PORT_STAT_HIGH_SPEED
)) {
699 Child
->Speed
= EFI_USB_SPEED_HIGH
;
702 Child
->Speed
= EFI_USB_SPEED_FULL
;
705 DEBUG (( EFI_D_INFO
, "UsbEnumerateNewDev: device is of %d speed\n", Child
->Speed
));
707 if (Child
->Speed
!= EFI_USB_SPEED_HIGH
) {
709 // If the child isn't a high speed device, it is necessary to
710 // set the transaction translator. This is quite simple:
711 // 1. if parent is of high speed, then parent is our translator
712 // 2. otherwise use parent's translator.
714 if (Parent
->Speed
== EFI_USB_SPEED_HIGH
) {
715 Child
->Translator
.TranslatorHubAddress
= Parent
->Address
;
716 Child
->Translator
.TranslatorPortNumber
= Port
;
719 Child
->Translator
= Parent
->Translator
;
722 DEBUG (( EFI_D_INFO
, "UsbEnumerateNewDev: device uses translator (%d, %d)\n",
723 Child
->Translator
.TranslatorHubAddress
,
724 Child
->Translator
.TranslatorPortNumber
));
728 // After port is reset, hub establishes a signal path between
729 // the device and host (DEFALUT state). Device¡¯s registers are
730 // reset, use default address 0 (host enumerates one device at
731 // a time) , and ready to respond to control transfer at EP 0.
735 // Host sends a Get_Descriptor request to learn the max packet
736 // size of default pipe (only part of the device¡¯s descriptor).
738 Status
= UsbGetMaxPacketSize0 (Child
);
740 if (EFI_ERROR (Status
)) {
741 DEBUG ((EFI_D_ERROR
, "UsbEnumerateNewDev: failed to get max packet for EP 0 - %r\n", Status
));
745 DEBUG (( EFI_D_INFO
, "UsbEnumerateNewDev: max packet size for EP 0 is %d\n", Child
->MaxPacket0
));
748 // Host assigns an address to the device. Device completes the
749 // status stage with default address, then switches to new address.
750 // ADDRESS state. Address zero is reserved for root hub.
752 for (Address
= 1; Address
< USB_MAX_DEVICES
; Address
++) {
753 if (Bus
->Devices
[Address
] == NULL
) {
758 if (Address
== USB_MAX_DEVICES
) {
759 DEBUG ((EFI_D_ERROR
, "UsbEnumerateNewDev: address pool is full for port %d\n", Port
));
761 Status
= EFI_ACCESS_DENIED
;
765 Bus
->Devices
[Address
] = Child
;
766 Status
= UsbSetAddress (Child
, Address
);
767 Child
->Address
= Address
;
769 if (EFI_ERROR (Status
)) {
770 DEBUG ((EFI_D_ERROR
, "UsbEnumerateNewDev: failed to set device address - %r\n", Status
));
774 gBS
->Stall (USB_SET_DEVICE_ADDRESS_STALL
);
776 DEBUG ((EFI_D_INFO
, "UsbEnumerateNewDev: device is now ADDRESSED at %d\n", Address
));
779 // Host learns about the device¡¯s abilities by requesting device's
780 // entire descriptions.
782 Status
= UsbBuildDescTable (Child
);
784 if (EFI_ERROR (Status
)) {
785 DEBUG ((EFI_D_ERROR
, "UsbEnumerateNewDev: failed to build descriptor table - %r\n", Status
));
790 // Select a default configuration: UEFI must set the configuration
791 // before the driver can connect to the device.
793 Config
= Child
->DevDesc
->Configs
[0]->Desc
.ConfigurationValue
;
794 Status
= UsbSetConfig (Child
, Config
);
796 if (EFI_ERROR (Status
)) {
797 DEBUG ((EFI_D_ERROR
, "UsbEnumerateNewDev: failed to set configure %d - %r\n", Config
, Status
));
801 DEBUG (( EFI_D_INFO
, "UsbEnumerateNewDev: device %d is now in CONFIGED state\n", Address
));
804 // Host assigns and loads a device driver.
806 Status
= UsbSelectConfig (Child
, Config
);
808 if (EFI_ERROR (Status
)) {
809 DEBUG ((EFI_D_ERROR
, "UsbEnumerateNewDev: failed to create interfaces - %r\n", Status
));
816 if (Address
!= USB_MAX_DEVICES
) {
817 Bus
->Devices
[Address
] = NULL
;
821 UsbFreeDevice (Child
);
830 Process the events on the port.
832 @param HubIf The HUB that has the device connected
833 @param Port The port index of the hub (started with zero)
835 @retval EFI_SUCCESS The device is enumerated (added or removed)
836 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the device
837 @retval Others Failed to enumerate the device
843 IN USB_INTERFACE
*HubIf
,
849 EFI_USB_PORT_STATUS PortState
;
853 HubApi
= HubIf
->HubApi
;
856 // Host learns of the new device by polling the hub for port changes.
858 Status
= HubApi
->GetPortStatus (HubIf
, Port
, &PortState
);
860 if (EFI_ERROR (Status
)) {
861 DEBUG ((EFI_D_ERROR
, "UsbEnumeratePort: failed to get state of port %d\n", Port
));
865 if (PortState
.PortChangeStatus
== 0) {
869 DEBUG (( EFI_D_INFO
, "UsbEnumeratePort: port %d state - %x, change - %x\n",
870 Port
, PortState
.PortStatus
, PortState
.PortChangeStatus
));
873 // This driver only process two kinds of events now: over current and
874 // connect/disconnect. Other three events are: ENABLE, SUSPEND, RESET.
875 // ENABLE/RESET is used to reset port. SUSPEND isn't supported.
878 if (USB_BIT_IS_SET (PortState
.PortChangeStatus
, USB_PORT_STAT_C_OVERCURRENT
)) {
880 if (USB_BIT_IS_SET (PortState
.PortStatus
, USB_PORT_STAT_OVERCURRENT
)) {
883 // Both OverCurrent and OverCurrentChange set, means over current occurs,
884 // which probably is caused by short circuit. It has to wait system hardware
885 // to perform recovery.
887 DEBUG (( EFI_D_ERROR
, "UsbEnumeratePort: Critical Over Current\n", Port
));
888 return EFI_DEVICE_ERROR
;
893 // Only OverCurrentChange set, means system has been recoveried from
894 // over current. As a result, all ports are nearly power-off, so
895 // it's necessary to detach and enumerate all ports again.
897 DEBUG (( EFI_D_ERROR
, "UsbEnumeratePort: 2.0 device Recovery Over Current\n", Port
));
900 if (USB_BIT_IS_SET (PortState
.PortChangeStatus
, USB_PORT_STAT_C_ENABLE
)) {
903 // 1.1 roothub port reg doesn't reflect over-current state, while its counterpart
904 // on 2.0 roothub does. When over-current has influence on 1.1 device, the port
905 // would be disabled, so it's also necessary to detach and enumerate again.
907 DEBUG (( EFI_D_ERROR
, "UsbEnumeratePort: 1.1 device Recovery Over Current\n", Port
));
910 if (USB_BIT_IS_SET (PortState
.PortChangeStatus
, USB_PORT_STAT_C_CONNECTION
)) {
913 // Device connected or disconnected normally.
915 DEBUG ((EFI_D_ERROR
, "UsbEnumeratePort: Device Connect/Discount Normally\n", Port
));
919 // Following as the above cases, it's safety to remove and create again.
921 Child
= UsbFindChild (HubIf
, Port
);
924 DEBUG (( EFI_D_INFO
, "UsbEnumeratePort: device at port %d removed from system\n", Port
));
925 UsbRemoveDevice (Child
);
928 if (USB_BIT_IS_SET (PortState
.PortStatus
, USB_PORT_STAT_CONNECTION
)) {
930 // Now, new device connected, enumerate and configure the device
932 DEBUG (( EFI_D_INFO
, "UsbEnumeratePort: new device connected at port %d\n", Port
));
933 Status
= UsbEnumerateNewDev (HubIf
, Port
);
936 DEBUG (( EFI_D_INFO
, "UsbEnumeratePort: device disconnected event on port %d\n", Port
));
939 HubApi
->ClearPortChange (HubIf
, Port
);
945 Enumerate all the changed hub ports
947 @param Event The event that is triggered
948 @param Context The context to the event
959 USB_INTERFACE
*HubIf
;
966 HubIf
= (USB_INTERFACE
*) Context
;
968 if (HubIf
->ChangeMap
== NULL
) {
973 // HUB starts its port index with 1.
978 for (Index
= 0; Index
< HubIf
->NumOfPort
; Index
++) {
979 if (USB_BIT_IS_SET (HubIf
->ChangeMap
[Byte
], USB_BIT (Bit
))) {
980 UsbEnumeratePort (HubIf
, Index
);
983 USB_NEXT_BIT (Byte
, Bit
);
986 UsbHubAckHubStatus (HubIf
->Device
);
988 gBS
->FreePool (HubIf
->ChangeMap
);
989 HubIf
->ChangeMap
= NULL
;
995 Enumerate all the changed hub ports
997 @param Event The event that is triggered
998 @param Context The context to the event
1005 UsbRootHubEnumeration (
1010 USB_INTERFACE
*RootHub
;
1013 RootHub
= (USB_INTERFACE
*) Context
;
1015 for (Index
= 0; Index
< RootHub
->NumOfPort
; Index
++) {
1016 UsbEnumeratePort (RootHub
, Index
);