3 Wrapper function for usb host controller interface.
5 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
13 // if RemainingDevicePath== NULL, then all Usb child devices in this bus are wanted.
14 // Use a shor form Usb class Device Path, which could match any usb device, in WantedUsbIoDPList to indicate all Usb devices
15 // are wanted Usb devices
17 USB_CLASS_FORMAT_DEVICE_PATH mAllUsbClassDevicePath
= {
20 MESSAGING_DEVICE_PATH
,
23 (UINT8
)(sizeof (USB_CLASS_DEVICE_PATH
)),
24 (UINT8
)((sizeof (USB_CLASS_DEVICE_PATH
)) >> 8)
30 0xff, // DeviceSubClass
31 0xff // DeviceProtocol
36 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
38 END_DEVICE_PATH_LENGTH
,
45 Get the capability of the host controller.
47 @param UsbBus The usb driver.
48 @param MaxSpeed The maximum speed this host controller supports.
49 @param NumOfPort The number of the root hub port.
50 @param Is64BitCapable Whether this controller support 64 bit addressing.
52 @retval EFI_SUCCESS The host controller capability is returned.
53 @retval Others Failed to retrieve the host controller capability.
61 OUT UINT8
*Is64BitCapable
66 if (UsbBus
->Usb2Hc
!= NULL
) {
67 Status
= UsbBus
->Usb2Hc
->GetCapability (
74 Status
= UsbBus
->UsbHc
->GetRootHubPortNumber (UsbBus
->UsbHc
, NumOfPort
);
76 *MaxSpeed
= EFI_USB_SPEED_FULL
;
77 *Is64BitCapable
= (UINT8
)FALSE
;
84 Get the root hub port state.
86 @param UsbBus The USB bus driver.
87 @param PortIndex The index of port.
88 @param PortStatus The variable to save port state.
90 @retval EFI_SUCCESS The root port state is returned in.
91 @retval Others Failed to get the root hub port state.
95 UsbHcGetRootHubPortStatus (
98 OUT EFI_USB_PORT_STATUS
*PortStatus
103 if (UsbBus
->Usb2Hc
!= NULL
) {
104 Status
= UsbBus
->Usb2Hc
->GetRootHubPortStatus (UsbBus
->Usb2Hc
, PortIndex
, PortStatus
);
106 Status
= UsbBus
->UsbHc
->GetRootHubPortStatus (UsbBus
->UsbHc
, PortIndex
, PortStatus
);
113 Set the root hub port feature.
115 @param UsbBus The USB bus driver.
116 @param PortIndex The port index.
117 @param Feature The port feature to set.
119 @retval EFI_SUCCESS The port feature is set.
120 @retval Others Failed to set port feature.
124 UsbHcSetRootHubPortFeature (
127 IN EFI_USB_PORT_FEATURE Feature
132 if (UsbBus
->Usb2Hc
!= NULL
) {
133 Status
= UsbBus
->Usb2Hc
->SetRootHubPortFeature (UsbBus
->Usb2Hc
, PortIndex
, Feature
);
135 Status
= UsbBus
->UsbHc
->SetRootHubPortFeature (UsbBus
->UsbHc
, PortIndex
, Feature
);
142 Clear the root hub port feature.
144 @param UsbBus The USB bus driver.
145 @param PortIndex The port index.
146 @param Feature The port feature to clear.
148 @retval EFI_SUCCESS The port feature is clear.
149 @retval Others Failed to clear port feature.
153 UsbHcClearRootHubPortFeature (
156 IN EFI_USB_PORT_FEATURE Feature
161 if (UsbBus
->Usb2Hc
!= NULL
) {
162 Status
= UsbBus
->Usb2Hc
->ClearRootHubPortFeature (UsbBus
->Usb2Hc
, PortIndex
, Feature
);
164 Status
= UsbBus
->UsbHc
->ClearRootHubPortFeature (UsbBus
->UsbHc
, PortIndex
, Feature
);
171 Execute a control transfer to the device.
173 @param UsbBus The USB bus driver.
174 @param DevAddr The device address.
175 @param DevSpeed The device speed.
176 @param MaxPacket Maximum packet size of endpoint 0.
177 @param Request The control transfer request.
178 @param Direction The direction of data stage.
179 @param Data The buffer holding data.
180 @param DataLength The length of the data.
181 @param TimeOut Timeout (in ms) to wait until timeout.
182 @param Translator The transaction translator for low/full speed device.
183 @param UsbResult The result of transfer.
185 @retval EFI_SUCCESS The control transfer finished without error.
186 @retval Others The control transfer failed, reason returned in UsbReslt.
190 UsbHcControlTransfer (
195 IN EFI_USB_DEVICE_REQUEST
*Request
,
196 IN EFI_USB_DATA_DIRECTION Direction
,
198 IN OUT UINTN
*DataLength
,
200 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
201 OUT UINT32
*UsbResult
205 BOOLEAN IsSlowDevice
;
207 if (UsbBus
->Usb2Hc
!= NULL
) {
208 Status
= UsbBus
->Usb2Hc
->ControlTransfer (
222 IsSlowDevice
= (BOOLEAN
)(EFI_USB_SPEED_LOW
== DevSpeed
);
223 Status
= UsbBus
->UsbHc
->ControlTransfer (
241 Execute a bulk transfer to the device's endpoint.
243 @param UsbBus The USB bus driver.
244 @param DevAddr The target device address.
245 @param EpAddr The target endpoint address, with direction encoded in
247 @param DevSpeed The device's speed.
248 @param MaxPacket The endpoint's max packet size.
249 @param BufferNum The number of data buffer.
250 @param Data Array of pointers to data buffer.
251 @param DataLength The length of data buffer.
252 @param DataToggle On input, the initial data toggle to use, also return
253 the next toggle on output.
254 @param TimeOut The time to wait until timeout.
255 @param Translator The transaction translator for low/full speed device.
256 @param UsbResult The result of USB execution.
258 @retval EFI_SUCCESS The bulk transfer is finished without error.
259 @retval Others Failed to execute bulk transfer, result in UsbResult.
271 IN OUT UINTN
*DataLength
,
272 IN OUT UINT8
*DataToggle
,
274 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
275 OUT UINT32
*UsbResult
280 if (UsbBus
->Usb2Hc
!= NULL
) {
281 Status
= UsbBus
->Usb2Hc
->BulkTransfer (
296 Status
= UsbBus
->UsbHc
->BulkTransfer (
313 Queue or cancel an asynchronous interrupt transfer.
315 @param UsbBus The USB bus driver.
316 @param DevAddr The target device address.
317 @param EpAddr The target endpoint address, with direction encoded in
319 @param DevSpeed The device's speed.
320 @param MaxPacket The endpoint's max packet size.
321 @param IsNewTransfer Whether this is a new request. If not, cancel the old
323 @param DataToggle Data toggle to use on input, next toggle on output.
324 @param PollingInterval The interval to poll the interrupt transfer (in ms).
325 @param DataLength The length of periodical data receive.
326 @param Translator The transaction translator for low/full speed device.
327 @param Callback Function to call when data is received.
328 @param Context The context to the callback.
330 @retval EFI_SUCCESS The asynchronous transfer is queued.
331 @retval Others Failed to queue the transfer.
335 UsbHcAsyncInterruptTransfer (
341 IN BOOLEAN IsNewTransfer
,
342 IN OUT UINT8
*DataToggle
,
343 IN UINTN PollingInterval
,
345 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
346 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
,
347 IN VOID
*Context OPTIONAL
351 BOOLEAN IsSlowDevice
;
353 if (UsbBus
->Usb2Hc
!= NULL
) {
354 Status
= UsbBus
->Usb2Hc
->AsyncInterruptTransfer (
369 IsSlowDevice
= (BOOLEAN
)(EFI_USB_SPEED_LOW
== DevSpeed
);
371 Status
= UsbBus
->UsbHc
->AsyncInterruptTransfer (
390 Execute a synchronous interrupt transfer to the target endpoint.
392 @param UsbBus The USB bus driver.
393 @param DevAddr The target device address.
394 @param EpAddr The target endpoint address, with direction encoded in
396 @param DevSpeed The device's speed.
397 @param MaxPacket The endpoint's max packet size.
398 @param Data Pointer to data buffer.
399 @param DataLength The length of data buffer.
400 @param DataToggle On input, the initial data toggle to use, also return
401 the next toggle on output.
402 @param TimeOut The time to wait until timeout.
403 @param Translator The transaction translator for low/full speed device.
404 @param UsbResult The result of USB execution.
406 @retval EFI_SUCCESS The synchronous interrupt transfer is OK.
407 @retval Others Failed to execute the synchronous interrupt transfer.
411 UsbHcSyncInterruptTransfer (
418 IN OUT UINTN
*DataLength
,
419 IN OUT UINT8
*DataToggle
,
421 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
422 OUT UINT32
*UsbResult
426 BOOLEAN IsSlowDevice
;
428 if (UsbBus
->Usb2Hc
!= NULL
) {
429 Status
= UsbBus
->Usb2Hc
->SyncInterruptTransfer (
443 IsSlowDevice
= (BOOLEAN
)((EFI_USB_SPEED_LOW
== DevSpeed
) ? TRUE
: FALSE
);
444 Status
= UsbBus
->UsbHc
->SyncInterruptTransfer (
462 Open the USB host controller protocol BY_CHILD.
464 @param Bus The USB bus driver.
465 @param Child The child handle.
467 @return The open protocol return.
471 UsbOpenHostProtoByChild (
476 EFI_USB_HC_PROTOCOL
*UsbHc
;
477 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
480 if (Bus
->Usb2Hc
!= NULL
) {
481 Status
= gBS
->OpenProtocol (
483 &gEfiUsb2HcProtocolGuid
,
485 mUsbBusDriverBinding
.DriverBindingHandle
,
487 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
490 Status
= gBS
->OpenProtocol (
492 &gEfiUsbHcProtocolGuid
,
494 mUsbBusDriverBinding
.DriverBindingHandle
,
496 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
504 Close the USB host controller protocol BY_CHILD.
506 @param Bus The USB bus driver.
507 @param Child The child handle.
511 UsbCloseHostProtoByChild (
516 if (Bus
->Usb2Hc
!= NULL
) {
519 &gEfiUsb2HcProtocolGuid
,
520 mUsbBusDriverBinding
.DriverBindingHandle
,
526 &gEfiUsbHcProtocolGuid
,
527 mUsbBusDriverBinding
.DriverBindingHandle
,
534 return the current TPL, copied from the EDKII glue lib.
548 Tpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
549 gBS
->RestoreTPL (Tpl
);
555 Create a new device path which only contain the first Usb part of the DevicePath.
557 @param DevicePath A full device path which contain the usb nodes.
559 @return A new device path which only contain the Usb part of the DevicePath.
562 EFI_DEVICE_PATH_PROTOCOL
*
565 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
568 EFI_DEVICE_PATH_PROTOCOL
*UsbDevicePathPtr
;
569 EFI_DEVICE_PATH_PROTOCOL
*UsbDevicePathBeginPtr
;
570 EFI_DEVICE_PATH_PROTOCOL
*UsbDevicePathEndPtr
;
574 // Get the Usb part first Begin node in full device path
576 UsbDevicePathBeginPtr
= DevicePath
;
577 while ((!IsDevicePathEnd (UsbDevicePathBeginPtr
)) &&
578 ((UsbDevicePathBeginPtr
->Type
!= MESSAGING_DEVICE_PATH
) ||
579 ( UsbDevicePathBeginPtr
->SubType
!= MSG_USB_DP
&&
580 UsbDevicePathBeginPtr
->SubType
!= MSG_USB_CLASS_DP
581 && UsbDevicePathBeginPtr
->SubType
!= MSG_USB_WWID_DP
584 UsbDevicePathBeginPtr
= NextDevicePathNode (UsbDevicePathBeginPtr
);
588 // Get the Usb part first End node in full device path
590 UsbDevicePathEndPtr
= UsbDevicePathBeginPtr
;
591 while ((!IsDevicePathEnd (UsbDevicePathEndPtr
)) &&
592 (UsbDevicePathEndPtr
->Type
== MESSAGING_DEVICE_PATH
) &&
593 ( UsbDevicePathEndPtr
->SubType
== MSG_USB_DP
||
594 UsbDevicePathEndPtr
->SubType
== MSG_USB_CLASS_DP
595 || UsbDevicePathEndPtr
->SubType
== MSG_USB_WWID_DP
598 UsbDevicePathEndPtr
= NextDevicePathNode (UsbDevicePathEndPtr
);
601 Size
= GetDevicePathSize (UsbDevicePathBeginPtr
);
602 Size
-= GetDevicePathSize (UsbDevicePathEndPtr
);
605 // The passed in DevicePath does not contain the usb nodes
611 // Create a new device path which only contain the above Usb part
613 UsbDevicePathPtr
= AllocateZeroPool (Size
+ sizeof (EFI_DEVICE_PATH_PROTOCOL
));
614 ASSERT (UsbDevicePathPtr
!= NULL
);
615 CopyMem (UsbDevicePathPtr
, UsbDevicePathBeginPtr
, Size
);
617 // Append end device path node
619 UsbDevicePathEndPtr
= (EFI_DEVICE_PATH_PROTOCOL
*)((UINTN
)UsbDevicePathPtr
+ Size
);
620 SetDevicePathEndNode (UsbDevicePathEndPtr
);
621 return UsbDevicePathPtr
;
625 Check whether a usb device path is in a DEVICE_PATH_LIST_ITEM list.
627 @param UsbDP a usb device path of DEVICE_PATH_LIST_ITEM.
628 @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list.
630 @retval TRUE there is a DEVICE_PATH_LIST_ITEM in UsbIoDPList which contains the passed in UsbDP.
631 @retval FALSE there is no DEVICE_PATH_LIST_ITEM in UsbIoDPList which contains the passed in UsbDP.
637 IN EFI_DEVICE_PATH_PROTOCOL
*UsbDP
,
638 IN LIST_ENTRY
*UsbIoDPList
641 LIST_ENTRY
*ListIndex
;
642 DEVICE_PATH_LIST_ITEM
*ListItem
;
644 UINTN UsbDpDevicePathSize
;
647 // Check that UsbDP and UsbIoDPList are valid
649 if ((UsbIoDPList
== NULL
) || (UsbDP
== NULL
)) {
654 ListIndex
= UsbIoDPList
->ForwardLink
;
655 while (ListIndex
!= UsbIoDPList
) {
656 ListItem
= CR (ListIndex
, DEVICE_PATH_LIST_ITEM
, Link
, DEVICE_PATH_LIST_ITEM_SIGNATURE
);
658 // Compare DEVICE_PATH_LIST_ITEM.DevicePath[]
660 ASSERT (ListItem
->DevicePath
!= NULL
);
662 UsbDpDevicePathSize
= GetDevicePathSize (UsbDP
);
663 if (UsbDpDevicePathSize
== GetDevicePathSize (ListItem
->DevicePath
)) {
664 if ((CompareMem (UsbDP
, ListItem
->DevicePath
, UsbDpDevicePathSize
)) == 0) {
670 ListIndex
= ListIndex
->ForwardLink
;
677 Add a usb device path into the DEVICE_PATH_LIST_ITEM list.
679 @param UsbDP a usb device path of DEVICE_PATH_LIST_ITEM.
680 @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list.
682 @retval EFI_INVALID_PARAMETER If parameters are invalid, return this value.
683 @retval EFI_SUCCESS If Add operation is successful, return this value.
689 IN EFI_DEVICE_PATH_PROTOCOL
*UsbDP
,
690 IN LIST_ENTRY
*UsbIoDPList
693 DEVICE_PATH_LIST_ITEM
*ListItem
;
696 // Check that UsbDP and UsbIoDPList are valid
698 if ((UsbIoDPList
== NULL
) || (UsbDP
== NULL
)) {
699 return EFI_INVALID_PARAMETER
;
702 if (SearchUsbDPInList (UsbDP
, UsbIoDPList
)) {
707 // Prepare the usbio device path DEVICE_PATH_LIST_ITEM structure.
709 ListItem
= AllocateZeroPool (sizeof (DEVICE_PATH_LIST_ITEM
));
710 ASSERT (ListItem
!= NULL
);
711 ListItem
->Signature
= DEVICE_PATH_LIST_ITEM_SIGNATURE
;
712 ListItem
->DevicePath
= DuplicateDevicePath (UsbDP
);
714 InsertTailList (UsbIoDPList
, &ListItem
->Link
);
720 Check whether usb device, whose interface is UsbIf, matches the usb class which indicated by
721 UsbClassDevicePathPtr whose is a short form usb class device path.
723 @param UsbClassDevicePathPtr a short form usb class device path.
724 @param UsbIf a usb device interface.
726 @retval TRUE the usb device match the usb class.
727 @retval FALSE the usb device does not match the usb class.
733 IN USB_CLASS_DEVICE_PATH
*UsbClassDevicePathPtr
,
734 IN USB_INTERFACE
*UsbIf
737 USB_INTERFACE_DESC
*IfDesc
;
738 EFI_USB_INTERFACE_DESCRIPTOR
*ActIfDesc
;
739 EFI_USB_DEVICE_DESCRIPTOR
*DevDesc
;
741 if ((UsbClassDevicePathPtr
->Header
.Type
!= MESSAGING_DEVICE_PATH
) ||
742 (UsbClassDevicePathPtr
->Header
.SubType
!= MSG_USB_CLASS_DP
))
748 IfDesc
= UsbIf
->IfDesc
;
749 ASSERT (IfDesc
->ActiveIndex
< USB_MAX_INTERFACE_SETTING
);
750 ActIfDesc
= &(IfDesc
->Settings
[IfDesc
->ActiveIndex
]->Desc
);
751 DevDesc
= &(UsbIf
->Device
->DevDesc
->Desc
);
754 // If connect class policy, determine whether to create device handle by the five fields
755 // in class device path node.
757 // In addition, hub interface is always matched for this policy.
759 if ((ActIfDesc
->InterfaceClass
== USB_HUB_CLASS_CODE
) &&
760 (ActIfDesc
->InterfaceSubClass
== USB_HUB_SUBCLASS_CODE
))
766 // If vendor id or product id is 0xffff, they will be ignored.
768 if (((UsbClassDevicePathPtr
->VendorId
== 0xffff) || (UsbClassDevicePathPtr
->VendorId
== DevDesc
->IdVendor
)) &&
769 ((UsbClassDevicePathPtr
->ProductId
== 0xffff) || (UsbClassDevicePathPtr
->ProductId
== DevDesc
->IdProduct
)))
772 // If Class in Device Descriptor is set to 0, the counterparts in interface should be checked.
774 if (DevDesc
->DeviceClass
== 0) {
775 if (((UsbClassDevicePathPtr
->DeviceClass
== ActIfDesc
->InterfaceClass
) ||
776 (UsbClassDevicePathPtr
->DeviceClass
== 0xff)) &&
777 ((UsbClassDevicePathPtr
->DeviceSubClass
== ActIfDesc
->InterfaceSubClass
) ||
778 (UsbClassDevicePathPtr
->DeviceSubClass
== 0xff)) &&
779 ((UsbClassDevicePathPtr
->DeviceProtocol
== ActIfDesc
->InterfaceProtocol
) ||
780 (UsbClassDevicePathPtr
->DeviceProtocol
== 0xff)))
784 } else if (((UsbClassDevicePathPtr
->DeviceClass
== DevDesc
->DeviceClass
) ||
785 (UsbClassDevicePathPtr
->DeviceClass
== 0xff)) &&
786 ((UsbClassDevicePathPtr
->DeviceSubClass
== DevDesc
->DeviceSubClass
) ||
787 (UsbClassDevicePathPtr
->DeviceSubClass
== 0xff)) &&
788 ((UsbClassDevicePathPtr
->DeviceProtocol
== DevDesc
->DeviceProtocol
) ||
789 (UsbClassDevicePathPtr
->DeviceProtocol
== 0xff)))
799 Check whether usb device, whose interface is UsbIf, matches the usb WWID requirement which indicated by
800 UsbWWIDDevicePathPtr whose is a short form usb WWID device path.
802 @param UsbWWIDDevicePathPtr a short form usb WWID device path.
803 @param UsbIf a usb device interface.
805 @retval TRUE the usb device match the usb WWID requirement.
806 @retval FALSE the usb device does not match the usb WWID requirement.
811 IN USB_WWID_DEVICE_PATH
*UsbWWIDDevicePathPtr
,
812 IN USB_INTERFACE
*UsbIf
815 USB_INTERFACE_DESC
*IfDesc
;
816 EFI_USB_INTERFACE_DESCRIPTOR
*ActIfDesc
;
817 EFI_USB_DEVICE_DESCRIPTOR
*DevDesc
;
818 EFI_USB_STRING_DESCRIPTOR
*StrDesc
;
824 if ((UsbWWIDDevicePathPtr
->Header
.Type
!= MESSAGING_DEVICE_PATH
) ||
825 (UsbWWIDDevicePathPtr
->Header
.SubType
!= MSG_USB_WWID_DP
))
831 IfDesc
= UsbIf
->IfDesc
;
832 ASSERT (IfDesc
->ActiveIndex
< USB_MAX_INTERFACE_SETTING
);
833 ActIfDesc
= &(IfDesc
->Settings
[IfDesc
->ActiveIndex
]->Desc
);
834 DevDesc
= &(UsbIf
->Device
->DevDesc
->Desc
);
837 // In addition, Hub interface is always matched for this policy.
839 if ((ActIfDesc
->InterfaceClass
== USB_HUB_CLASS_CODE
) &&
840 (ActIfDesc
->InterfaceSubClass
== USB_HUB_SUBCLASS_CODE
))
846 // Check Vendor Id, Product Id and Interface Number.
848 if ((DevDesc
->IdVendor
!= UsbWWIDDevicePathPtr
->VendorId
) ||
849 (DevDesc
->IdProduct
!= UsbWWIDDevicePathPtr
->ProductId
) ||
850 (ActIfDesc
->InterfaceNumber
!= UsbWWIDDevicePathPtr
->InterfaceNumber
))
856 // Check SerialNumber.
858 if (DevDesc
->StrSerialNumber
== 0) {
863 // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.
865 CompareStr
= (CHAR16
*)(UINTN
)(UsbWWIDDevicePathPtr
+ 1);
866 CompareLen
= (DevicePathNodeLength (UsbWWIDDevicePathPtr
) - sizeof (USB_WWID_DEVICE_PATH
)) / sizeof (CHAR16
);
867 if (CompareStr
[CompareLen
- 1] == L
'\0') {
872 // Compare serial number in each supported language.
874 for (Index
= 0; Index
< UsbIf
->Device
->TotalLangId
; Index
++) {
875 StrDesc
= UsbGetOneString (UsbIf
->Device
, DevDesc
->StrSerialNumber
, UsbIf
->Device
->LangId
[Index
]);
876 if (StrDesc
== NULL
) {
880 Length
= (StrDesc
->Length
- 2) / sizeof (CHAR16
);
881 if ((Length
>= CompareLen
) &&
882 (CompareMem (StrDesc
->String
+ Length
- CompareLen
, CompareStr
, CompareLen
* sizeof (CHAR16
)) == 0))
892 Free a DEVICE_PATH_LIST_ITEM list.
894 @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list pointer.
896 @retval EFI_INVALID_PARAMETER If parameters are invalid, return this value.
897 @retval EFI_SUCCESS If free operation is successful, return this value.
902 UsbBusFreeUsbDPList (
903 IN LIST_ENTRY
*UsbIoDPList
906 LIST_ENTRY
*ListIndex
;
907 DEVICE_PATH_LIST_ITEM
*ListItem
;
910 // Check that ControllerHandle is a valid handle
912 if (UsbIoDPList
== NULL
) {
913 return EFI_INVALID_PARAMETER
;
916 ListIndex
= UsbIoDPList
->ForwardLink
;
917 while (ListIndex
!= UsbIoDPList
) {
918 ListItem
= CR (ListIndex
, DEVICE_PATH_LIST_ITEM
, Link
, DEVICE_PATH_LIST_ITEM_SIGNATURE
);
920 // Free DEVICE_PATH_LIST_ITEM.DevicePath[]
922 if (ListItem
->DevicePath
!= NULL
) {
923 FreePool (ListItem
->DevicePath
);
927 // Free DEVICE_PATH_LIST_ITEM itself
929 ListIndex
= ListIndex
->ForwardLink
;
930 RemoveEntryList (&ListItem
->Link
);
934 InitializeListHead (UsbIoDPList
);
939 Store a wanted usb child device info (its Usb part of device path) which is indicated by
940 RemainingDevicePath in a Usb bus which is indicated by UsbBusId.
942 @param UsbBusId Point to EFI_USB_BUS_PROTOCOL interface.
943 @param RemainingDevicePath The remaining device patch.
945 @retval EFI_SUCCESS Add operation is successful.
946 @retval EFI_INVALID_PARAMETER The parameters are invalid.
951 UsbBusAddWantedUsbIoDP (
952 IN EFI_USB_BUS_PROTOCOL
*UsbBusId
,
953 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
958 EFI_DEVICE_PATH_PROTOCOL
*DevicePathPtr
;
961 // Check whether remaining device path is valid
963 if ((RemainingDevicePath
!= NULL
) && !IsDevicePathEnd (RemainingDevicePath
)) {
964 if ((RemainingDevicePath
->Type
!= MESSAGING_DEVICE_PATH
) ||
965 ( (RemainingDevicePath
->SubType
!= MSG_USB_DP
) &&
966 (RemainingDevicePath
->SubType
!= MSG_USB_CLASS_DP
)
967 && (RemainingDevicePath
->SubType
!= MSG_USB_WWID_DP
)
970 return EFI_INVALID_PARAMETER
;
974 if (UsbBusId
== NULL
) {
975 return EFI_INVALID_PARAMETER
;
978 Bus
= USB_BUS_FROM_THIS (UsbBusId
);
980 if (RemainingDevicePath
== NULL
) {
982 // RemainingDevicePath == NULL means all Usb devices in this bus are wanted.
983 // Here use a Usb class Device Path in WantedUsbIoDPList to indicate all Usb devices
984 // are wanted Usb devices
986 Status
= UsbBusFreeUsbDPList (&Bus
->WantedUsbIoDPList
);
987 ASSERT (!EFI_ERROR (Status
));
988 DevicePathPtr
= DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL
*)&mAllUsbClassDevicePath
);
989 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
991 // If RemainingDevicePath isn't the End of Device Path Node,
992 // Create new Usb device path according to the usb part in remaining device path
994 DevicePathPtr
= GetUsbDPFromFullDP (RemainingDevicePath
);
997 // If RemainingDevicePath is the End of Device Path Node,
998 // skip enumerate any device and return EFI_SUCCESS
1003 ASSERT (DevicePathPtr
!= NULL
);
1004 Status
= AddUsbDPToList (DevicePathPtr
, &Bus
->WantedUsbIoDPList
);
1005 ASSERT (!EFI_ERROR (Status
));
1006 FreePool (DevicePathPtr
);
1011 Check whether a usb child device is the wanted device in a bus.
1013 @param Bus The Usb bus's private data pointer.
1014 @param UsbIf The usb child device interface.
1016 @retval True If a usb child device is the wanted device in a bus.
1017 @retval False If a usb child device is *NOT* the wanted device in a bus.
1022 UsbBusIsWantedUsbIO (
1024 IN USB_INTERFACE
*UsbIf
1027 EFI_DEVICE_PATH_PROTOCOL
*DevicePathPtr
;
1028 LIST_ENTRY
*WantedUsbIoDPListPtr
;
1029 LIST_ENTRY
*WantedListIndex
;
1030 DEVICE_PATH_LIST_ITEM
*WantedListItem
;
1032 UINTN FirstDevicePathSize
;
1035 // Check whether passed in parameters are valid
1037 if ((UsbIf
== NULL
) || (Bus
== NULL
)) {
1042 // Check whether UsbIf is Hub
1049 // Check whether all Usb devices in this bus are wanted
1051 if (SearchUsbDPInList ((EFI_DEVICE_PATH_PROTOCOL
*)&mAllUsbClassDevicePath
, &Bus
->WantedUsbIoDPList
)) {
1056 // Check whether the Usb device match any item in WantedUsbIoDPList
1058 WantedUsbIoDPListPtr
= &Bus
->WantedUsbIoDPList
;
1060 // Create new Usb device path according to the usb part in UsbIo full device path
1062 DevicePathPtr
= GetUsbDPFromFullDP (UsbIf
->DevicePath
);
1063 ASSERT (DevicePathPtr
!= NULL
);
1066 WantedListIndex
= WantedUsbIoDPListPtr
->ForwardLink
;
1067 while (WantedListIndex
!= WantedUsbIoDPListPtr
) {
1068 WantedListItem
= CR (WantedListIndex
, DEVICE_PATH_LIST_ITEM
, Link
, DEVICE_PATH_LIST_ITEM_SIGNATURE
);
1069 ASSERT (WantedListItem
->DevicePath
->Type
== MESSAGING_DEVICE_PATH
);
1070 switch (WantedListItem
->DevicePath
->SubType
) {
1072 FirstDevicePathSize
= GetDevicePathSize (WantedListItem
->DevicePath
);
1073 if (FirstDevicePathSize
== GetDevicePathSize (DevicePathPtr
)) {
1075 WantedListItem
->DevicePath
,
1077 GetDevicePathSize (DevicePathPtr
)
1086 case MSG_USB_CLASS_DP
:
1087 if (MatchUsbClass ((USB_CLASS_DEVICE_PATH
*)WantedListItem
->DevicePath
, UsbIf
)) {
1092 case MSG_USB_WWID_DP
:
1093 if (MatchUsbWwid ((USB_WWID_DEVICE_PATH
*)WantedListItem
->DevicePath
, UsbIf
)) {
1107 WantedListIndex
= WantedListIndex
->ForwardLink
;
1110 gBS
->FreePool (DevicePathPtr
);
1113 // Check whether the new Usb device path is wanted
1123 Recursively connect every wanted usb child device to ensure they all fully connected.
1124 Check all the child Usb IO handles in this bus, recursively connecte if it is wanted usb child device.
1126 @param UsbBusId Point to EFI_USB_BUS_PROTOCOL interface.
1128 @retval EFI_SUCCESS Connect is done successfully.
1129 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1134 UsbBusRecursivelyConnectWantedUsbIo (
1135 IN EFI_USB_BUS_PROTOCOL
*UsbBusId
1141 EFI_USB_IO_PROTOCOL
*UsbIo
;
1142 USB_INTERFACE
*UsbIf
;
1143 UINTN UsbIoHandleCount
;
1144 EFI_HANDLE
*UsbIoBuffer
;
1145 EFI_DEVICE_PATH_PROTOCOL
*UsbIoDevicePath
;
1147 if (UsbBusId
== NULL
) {
1148 return EFI_INVALID_PARAMETER
;
1151 Bus
= USB_BUS_FROM_THIS (UsbBusId
);
1154 // Get all Usb IO handles in system
1156 UsbIoHandleCount
= 0;
1157 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiUsbIoProtocolGuid
, NULL
, &UsbIoHandleCount
, &UsbIoBuffer
);
1158 if ((Status
== EFI_NOT_FOUND
) || (UsbIoHandleCount
== 0)) {
1162 ASSERT (!EFI_ERROR (Status
));
1164 for (Index
= 0; Index
< UsbIoHandleCount
; Index
++) {
1166 // Check whether the USB IO handle is a child of this bus
1167 // Note: The usb child handle maybe invalid because of hot plugged out during the loop
1169 UsbIoDevicePath
= NULL
;
1170 Status
= gBS
->HandleProtocol (UsbIoBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&UsbIoDevicePath
);
1171 if (EFI_ERROR (Status
) || (UsbIoDevicePath
== NULL
)) {
1178 (GetDevicePathSize (Bus
->DevicePath
) - sizeof (EFI_DEVICE_PATH_PROTOCOL
))
1185 // Get the child Usb IO interface
1187 Status
= gBS
->HandleProtocol (
1189 &gEfiUsbIoProtocolGuid
,
1192 if (EFI_ERROR (Status
)) {
1196 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1198 if (UsbBusIsWantedUsbIO (Bus
, UsbIf
)) {
1199 if (!UsbIf
->IsManaged
) {
1201 // Recursively connect the wanted Usb Io handle
1203 DEBUG ((DEBUG_INFO
, "UsbBusRecursivelyConnectWantedUsbIo: TPL before connect is %d\n", (UINT32
)UsbGetCurrentTpl ()));
1204 Status
= gBS
->ConnectController (UsbIf
->Handle
, NULL
, NULL
, TRUE
);
1205 UsbIf
->IsManaged
= (BOOLEAN
) !EFI_ERROR (Status
);
1206 DEBUG ((DEBUG_INFO
, "UsbBusRecursivelyConnectWantedUsbIo: TPL after connect is %d\n", (UINT32
)UsbGetCurrentTpl ()));
1211 FreePool (UsbIoBuffer
);