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 Wrapper function for usb host controller interface
29 // if RemainingDevicePath== NULL, then all Usb child devices in this bus are wanted.
30 // Use a shor form Usb class Device Path, which could match any usb device, in WantedUsbIoDPList to indicate all Usb devices
31 // are wanted Usb devices
33 STATIC USB_CLASS_FORMAT_DEVICE_PATH mAllUsbClassDevicePath
= {
36 MESSAGING_DEVICE_PATH
,
38 (UINT8
) (sizeof (USB_CLASS_DEVICE_PATH
)),
39 (UINT8
) ((sizeof (USB_CLASS_DEVICE_PATH
)) >> 8)
44 0xff, // DeviceSubClass
45 0xff // DeviceProtocol
50 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
51 END_DEVICE_PATH_LENGTH
,
58 Get the capability of the host controller
60 @param UsbBus The usb driver
61 @param MaxSpeed The maximum speed this host controller supports
62 @param NumOfPort The number of the root hub port
63 @param Is64BitCapable Whether this controller support 64 bit addressing
65 @retval EFI_SUCCESS The host controller capability is returned
66 @retval Others Failed to retrieve the host controller capability.
74 OUT UINT8
*Is64BitCapable
79 if (UsbBus
->Usb2Hc
!= NULL
) {
80 Status
= UsbBus
->Usb2Hc
->GetCapability (
88 Status
= UsbBus
->UsbHc
->GetRootHubPortNumber (UsbBus
->UsbHc
, NumOfPort
);
90 *MaxSpeed
= EFI_USB_SPEED_FULL
;
91 *Is64BitCapable
= (UINT8
) FALSE
;
99 Reset the host controller
101 @param UsbBus The usb bus driver
102 @param Attributes The reset type, only global reset is used by this driver
104 @return GC_TODO: add return values
115 if (UsbBus
->Usb2Hc
!= NULL
) {
116 Status
= UsbBus
->Usb2Hc
->Reset (UsbBus
->Usb2Hc
, Attributes
);
118 Status
= UsbBus
->UsbHc
->Reset (UsbBus
->UsbHc
, Attributes
);
126 Get the current operation state of the host controller
128 @param UsbBus The USB bus driver
129 @param State The host controller operation state
131 @retval EFI_SUCCESS The operation state is returned in State
132 @retval Others Failed to get the host controller state
138 OUT EFI_USB_HC_STATE
*State
143 if (UsbBus
->Usb2Hc
!= NULL
) {
144 Status
= UsbBus
->Usb2Hc
->GetState (UsbBus
->Usb2Hc
, State
);
146 Status
= UsbBus
->UsbHc
->GetState (UsbBus
->UsbHc
, State
);
154 Set the host controller operation state
156 @param UsbBus The USB bus driver
157 @param State The state to set
159 @retval EFI_SUCCESS The host controller is now working at State
160 @retval Others Failed to set operation state
166 IN EFI_USB_HC_STATE State
171 if (UsbBus
->Usb2Hc
!= NULL
) {
172 Status
= UsbBus
->Usb2Hc
->SetState (UsbBus
->Usb2Hc
, State
);
174 Status
= UsbBus
->UsbHc
->SetState (UsbBus
->UsbHc
, State
);
182 Get the root hub port state
184 @param UsbBus The USB bus driver
185 @param PortIndex The index of port
186 @param PortStatus The variable to save port state
188 @retval EFI_SUCCESS The root port state is returned in
189 @retval Others Failed to get the root hub port state
193 UsbHcGetRootHubPortStatus (
196 OUT EFI_USB_PORT_STATUS
*PortStatus
201 if (UsbBus
->Usb2Hc
!= NULL
) {
202 Status
= UsbBus
->Usb2Hc
->GetRootHubPortStatus (UsbBus
->Usb2Hc
, PortIndex
, PortStatus
);
204 Status
= UsbBus
->UsbHc
->GetRootHubPortStatus (UsbBus
->UsbHc
, PortIndex
, PortStatus
);
212 Set the root hub port feature
214 @param UsbBus The USB bus driver
215 @param PortIndex The port index
216 @param Feature The port feature to set
218 @retval EFI_SUCCESS The port feature is set
219 @retval Others Failed to set port feature
223 UsbHcSetRootHubPortFeature (
226 IN EFI_USB_PORT_FEATURE Feature
232 if (UsbBus
->Usb2Hc
!= NULL
) {
233 Status
= UsbBus
->Usb2Hc
->SetRootHubPortFeature (UsbBus
->Usb2Hc
, PortIndex
, Feature
);
235 Status
= UsbBus
->UsbHc
->SetRootHubPortFeature (UsbBus
->UsbHc
, PortIndex
, Feature
);
243 Clear the root hub port feature
245 @param UsbBus The USB bus driver
246 @param PortIndex The port index
247 @param Feature The port feature to clear
249 @retval EFI_SUCCESS The port feature is clear
250 @retval Others Failed to clear port feature
254 UsbHcClearRootHubPortFeature (
257 IN EFI_USB_PORT_FEATURE Feature
262 if (UsbBus
->Usb2Hc
!= NULL
) {
263 Status
= UsbBus
->Usb2Hc
->ClearRootHubPortFeature (UsbBus
->Usb2Hc
, PortIndex
, Feature
);
265 Status
= UsbBus
->UsbHc
->ClearRootHubPortFeature (UsbBus
->UsbHc
, PortIndex
, Feature
);
273 Execute a control transfer to the device
275 @param UsbBus The USB bus driver
276 @param DevAddr The device address
277 @param DevSpeed The device speed
278 @param MaxPacket Maximum packet size of endpoint 0
279 @param Request The control transfer request
280 @param Direction The direction of data stage
281 @param Data The buffer holding data
282 @param DataLength The length of the data
283 @param TimeOut Timeout (in ms) to wait until timeout
284 @param Translator The transaction translator for low/full speed device
285 @param UsbResult The result of transfer
287 @retval EFI_SUCCESS The control transfer finished without error
288 @retval Others The control transfer failed, reason returned in UsbReslt
292 UsbHcControlTransfer (
297 IN EFI_USB_DEVICE_REQUEST
*Request
,
298 IN EFI_USB_DATA_DIRECTION Direction
,
300 IN OUT UINTN
*DataLength
,
302 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
303 OUT UINT32
*UsbResult
307 BOOLEAN IsSlowDevice
;
309 if (UsbBus
->Usb2Hc
!= NULL
) {
310 Status
= UsbBus
->Usb2Hc
->ControlTransfer (
325 IsSlowDevice
= (BOOLEAN
)(EFI_USB_SPEED_LOW
== DevSpeed
);
326 Status
= UsbBus
->UsbHc
->ControlTransfer (
345 Execute a bulk transfer to the device's endpoint
347 @param UsbBus The USB bus driver
348 @param DevAddr The target device address
349 @param EpAddr The target endpoint address, with direction encoded in
351 @param DevSpeed The device's speed
352 @param MaxPacket The endpoint's max packet size
353 @param BufferNum The number of data buffer
354 @param Data Array of pointers to data buffer
355 @param DataLength The length of data buffer
356 @param DataToggle On input, the initial data toggle to use, also return
357 the next toggle on output.
358 @param TimeOut The time to wait until timeout
359 @param Translator The transaction translator for low/full speed device
360 @param UsbResult The result of USB execution
362 @retval EFI_SUCCESS The bulk transfer is finished without error
363 @retval Others Failed to execute bulk transfer, result in UsbResult
374 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
375 IN OUT UINTN
*DataLength
,
376 IN OUT UINT8
*DataToggle
,
378 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
379 OUT UINT32
*UsbResult
384 if (UsbBus
->Usb2Hc
!= NULL
) {
385 Status
= UsbBus
->Usb2Hc
->BulkTransfer (
400 Status
= UsbBus
->UsbHc
->BulkTransfer (
418 Queue or cancel an asynchronous interrupt transfer
420 @param UsbBus The USB bus driver
421 @param DevAddr The target device address
422 @param EpAddr The target endpoint address, with direction encoded in
424 @param DevSpeed The device's speed
425 @param MaxPacket The endpoint's max packet size
426 @param IsNewTransfer Whether this is a new request. If not, cancel the old
428 @param DataToggle Data toggle to use on input, next toggle on output
429 @param PollingInterval The interval to poll the interrupt transfer (in ms)
430 @param DataLength The length of periodical data receive
431 @param Translator The transaction translator for low/full speed device
432 @param Callback Function to call when data is received
433 @param Context The context to the callback
435 @retval EFI_SUCCESS The asynchronous transfer is queued
436 @retval Others Failed to queue the transfer
440 UsbHcAsyncInterruptTransfer (
446 IN BOOLEAN IsNewTransfer
,
447 IN OUT UINT8
*DataToggle
,
448 IN UINTN PollingInterval
,
450 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
451 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
,
452 IN VOID
*Context OPTIONAL
456 BOOLEAN IsSlowDevice
;
458 if (UsbBus
->Usb2Hc
!= NULL
) {
459 Status
= UsbBus
->Usb2Hc
->AsyncInterruptTransfer (
474 IsSlowDevice
= (BOOLEAN
)(EFI_USB_SPEED_LOW
== DevSpeed
);
476 Status
= UsbBus
->UsbHc
->AsyncInterruptTransfer (
496 Execute a synchronous interrupt transfer to the target endpoint
498 @param UsbBus The USB bus driver
499 @param DevAddr The target device address
500 @param EpAddr The target endpoint address, with direction encoded in
502 @param DevSpeed The device's speed
503 @param MaxPacket The endpoint's max packet size
504 @param Data Pointer to data buffer
505 @param DataLength The length of data buffer
506 @param DataToggle On input, the initial data toggle to use, also return
507 the next toggle on output.
508 @param TimeOut The time to wait until timeout
509 @param Translator The transaction translator for low/full speed device
510 @param UsbResult The result of USB execution
512 @retval EFI_SUCCESS The synchronous interrupt transfer is OK
513 @retval Others Failed to execute the synchronous interrupt transfer
517 UsbHcSyncInterruptTransfer (
524 IN OUT UINTN
*DataLength
,
525 IN OUT UINT8
*DataToggle
,
527 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
528 OUT UINT32
*UsbResult
532 BOOLEAN IsSlowDevice
;
534 if (UsbBus
->Usb2Hc
!= NULL
) {
535 Status
= UsbBus
->Usb2Hc
->SyncInterruptTransfer (
549 IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DevSpeed
) ? TRUE
: FALSE
);
550 Status
= UsbBus
->UsbHc
->SyncInterruptTransfer (
569 Execute a synchronous Isochronous USB transfer
571 @param UsbBus The USB bus driver
572 @param DevAddr The target device address
573 @param EpAddr The target endpoint address, with direction encoded in
575 @param DevSpeed The device's speed
576 @param MaxPacket The endpoint's max packet size
577 @param BufferNum The number of data buffer
578 @param Data Array of pointers to data buffer
579 @param DataLength The length of data buffer
580 @param Translator The transaction translator for low/full speed device
581 @param UsbResult The result of USB execution
583 @retval EFI_UNSUPPORTED The isochronous transfer isn't supported now
587 UsbHcIsochronousTransfer (
594 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
596 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
597 OUT UINT32
*UsbResult
600 return EFI_UNSUPPORTED
;
605 Queue an asynchronous isochronous transfer
607 @param UsbBus The USB bus driver
608 @param DevAddr The target device address
609 @param EpAddr The target endpoint address, with direction encoded in
611 @param DevSpeed The device's speed
612 @param MaxPacket The endpoint's max packet size
613 @param BufferNum The number of data buffer
614 @param Data Array of pointers to data buffer
615 @param DataLength The length of data buffer
616 @param Translator The transaction translator for low/full speed device
617 @param Callback The function to call when data is transferred
618 @param Context The context to the callback function
620 @retval EFI_UNSUPPORTED The asynchronous isochronous transfer isn't supported
624 UsbHcAsyncIsochronousTransfer (
631 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
633 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
634 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
,
638 return EFI_UNSUPPORTED
;
643 Open the USB host controller protocol BY_CHILD
645 @param Bus The USB bus driver
646 @param Child The child handle
648 @return The open protocol return
652 UsbOpenHostProtoByChild (
657 EFI_USB_HC_PROTOCOL
*UsbHc
;
658 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
661 if (Bus
->Usb2Hc
!= NULL
) {
662 Status
= gBS
->OpenProtocol (
664 &gEfiUsb2HcProtocolGuid
,
666 mUsbBusDriverBinding
.DriverBindingHandle
,
668 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
672 Status
= gBS
->OpenProtocol (
674 &gEfiUsbHcProtocolGuid
,
676 mUsbBusDriverBinding
.DriverBindingHandle
,
678 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
687 Close the USB host controller protocol BY_CHILD
689 @param Bus The USB bus driver
690 @param Child The child handle
696 UsbCloseHostProtoByChild (
701 if (Bus
->Usb2Hc
!= NULL
) {
704 &gEfiUsb2HcProtocolGuid
,
705 mUsbBusDriverBinding
.DriverBindingHandle
,
712 &gEfiUsbHcProtocolGuid
,
713 mUsbBusDriverBinding
.DriverBindingHandle
,
722 return the current TPL, copied from the EDKII glue lib.
736 Tpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
737 gBS
->RestoreTPL (Tpl
);
743 Create a new device path which only contain the first Usb part of the DevicePath
745 @param DevicePath A full device path which contain the usb nodes
747 @return A new device path which only contain the Usb part of the DevicePath
750 EFI_DEVICE_PATH_PROTOCOL
*
753 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
756 EFI_DEVICE_PATH_PROTOCOL
*UsbDevicePathPtr
;
757 EFI_DEVICE_PATH_PROTOCOL
*UsbDevicePathBeginPtr
;
758 EFI_DEVICE_PATH_PROTOCOL
*UsbDevicePathEndPtr
;
762 // Get the Usb part first Begin node in full device path
764 UsbDevicePathBeginPtr
= DevicePath
;
765 while ( (!EfiIsDevicePathEnd (UsbDevicePathBeginPtr
))&&
766 ((UsbDevicePathBeginPtr
->Type
!= MESSAGING_DEVICE_PATH
) ||
767 (UsbDevicePathBeginPtr
->SubType
!= MSG_USB_DP
&&
768 UsbDevicePathBeginPtr
->SubType
!= MSG_USB_CLASS_DP
769 && UsbDevicePathBeginPtr
->SubType
!= MSG_USB_WWID_DP
772 UsbDevicePathBeginPtr
= NextDevicePathNode(UsbDevicePathBeginPtr
);
776 // Get the Usb part first End node in full device path
778 UsbDevicePathEndPtr
= UsbDevicePathBeginPtr
;
779 while ((!EfiIsDevicePathEnd (UsbDevicePathEndPtr
))&&
780 (UsbDevicePathEndPtr
->Type
== MESSAGING_DEVICE_PATH
) &&
781 (UsbDevicePathEndPtr
->SubType
== MSG_USB_DP
||
782 UsbDevicePathEndPtr
->SubType
== MSG_USB_CLASS_DP
783 || UsbDevicePathEndPtr
->SubType
== MSG_USB_WWID_DP
786 UsbDevicePathEndPtr
= NextDevicePathNode(UsbDevicePathEndPtr
);
789 Size
= GetDevicePathSize (UsbDevicePathBeginPtr
);
790 Size
-= GetDevicePathSize (UsbDevicePathEndPtr
);
793 // The passed in DevicePath does not contain the usb nodes
799 // Create a new device path which only contain the above Usb part
801 UsbDevicePathPtr
= AllocateZeroPool (Size
+ sizeof (EFI_DEVICE_PATH_PROTOCOL
));
802 ASSERT (UsbDevicePathPtr
!= NULL
);
803 CopyMem (UsbDevicePathPtr
, UsbDevicePathBeginPtr
, Size
);
805 // Append end device path node
807 UsbDevicePathEndPtr
= (EFI_DEVICE_PATH_PROTOCOL
*) ((UINTN
) UsbDevicePathPtr
+ Size
);
808 SetDevicePathEndNode (UsbDevicePathEndPtr
);
809 return UsbDevicePathPtr
;
813 Check whether a usb device path is in a DEVICE_PATH_LIST_ITEM list.
815 @param UsbDP a usb device path of DEVICE_PATH_LIST_ITEM
816 @parem UsbIoDPList a DEVICE_PATH_LIST_ITEM list
818 @retval TRUE there is a DEVICE_PATH_LIST_ITEM in UsbIoDPList which contains the passed in UsbDP
819 @retval FALSE there is no DEVICE_PATH_LIST_ITEM in UsbIoDPList which contains the passed in UsbDP
825 IN EFI_DEVICE_PATH_PROTOCOL
*UsbDP
,
826 IN LIST_ENTRY
*UsbIoDPList
829 LIST_ENTRY
*ListIndex
;
830 DEVICE_PATH_LIST_ITEM
*ListItem
;
832 UINTN UsbDpDevicePathSize
;
835 // Check that UsbDP and UsbIoDPList are valid
837 if ((UsbIoDPList
== NULL
) || (UsbDP
== NULL
)) {
842 ListIndex
= UsbIoDPList
->ForwardLink
;
843 while (ListIndex
!= UsbIoDPList
){
844 ListItem
= CR(ListIndex
, DEVICE_PATH_LIST_ITEM
, Link
, DEVICE_PATH_LIST_ITEM_SIGNATURE
);
846 // Compare DEVICE_PATH_LIST_ITEM.DevicePath[]
848 ASSERT (ListItem
->DevicePath
!= NULL
);
850 UsbDpDevicePathSize
= GetDevicePathSize (UsbDP
);
851 if (UsbDpDevicePathSize
== GetDevicePathSize (ListItem
->DevicePath
)) {
852 if ((CompareMem (UsbDP
, ListItem
->DevicePath
, UsbDpDevicePathSize
)) == 0) {
857 ListIndex
= ListIndex
->ForwardLink
;
864 Add a usb device path into the DEVICE_PATH_LIST_ITEM list.
866 @param UsbDP a usb device path of DEVICE_PATH_LIST_ITEM
867 @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list
869 @retval EFI_INVALID_PARAMETER
876 IN EFI_DEVICE_PATH_PROTOCOL
*UsbDP
,
877 IN LIST_ENTRY
*UsbIoDPList
880 DEVICE_PATH_LIST_ITEM
*ListItem
;
883 // Check that UsbDP and UsbIoDPList are valid
885 if ((UsbIoDPList
== NULL
) || (UsbDP
== NULL
)) {
886 return EFI_INVALID_PARAMETER
;
889 if (SearchUsbDPInList (UsbDP
, UsbIoDPList
)){
894 // Prepare the usbio device path DEVICE_PATH_LIST_ITEM structure.
896 ListItem
= AllocateZeroPool (sizeof (DEVICE_PATH_LIST_ITEM
));
897 ASSERT (ListItem
!= NULL
);
898 ListItem
->Signature
= DEVICE_PATH_LIST_ITEM_SIGNATURE
;
899 ListItem
->DevicePath
= DuplicateDevicePath (UsbDP
);
901 InsertTailList (UsbIoDPList
, &ListItem
->Link
);
907 Check whether usb device, whose interface is UsbIf, matches the usb class which indicated by
908 UsbClassDevicePathPtr whose is a short form usb class device path
910 @param UsbClassDevicePathPtr a short form usb class device path
911 @param UsbIf a usb device interface
913 @retval TRUE the usb device match the usb class
914 @retval FALSE the usb device does not match the usb class
920 IN USB_CLASS_DEVICE_PATH
*UsbClassDevicePathPtr
,
921 IN USB_INTERFACE
*UsbIf
924 USB_INTERFACE_DESC
*IfDesc
;
925 EFI_USB_INTERFACE_DESCRIPTOR
*ActIfDesc
;
926 EFI_USB_DEVICE_DESCRIPTOR
*DevDesc
;
929 if ((UsbClassDevicePathPtr
->Header
.Type
!= MESSAGING_DEVICE_PATH
) ||
930 (UsbClassDevicePathPtr
->Header
.SubType
!= MSG_USB_CLASS_DP
)){
935 IfDesc
= UsbIf
->IfDesc
;
936 ActIfDesc
= &(IfDesc
->Settings
[IfDesc
->ActiveIndex
]->Desc
);
937 DevDesc
= &(UsbIf
->Device
->DevDesc
->Desc
);
940 // If connect class policy, determine whether to create device handle by the five fields
941 // in class device path node.
943 // In addtion, hub interface is always matched for this policy.
945 if ((ActIfDesc
->InterfaceClass
== USB_HUB_CLASS_CODE
) &&
946 (ActIfDesc
->InterfaceSubClass
== USB_HUB_SUBCLASS_CODE
)) {
951 // If vendor id or product id is 0xffff, they will be ignored.
953 if ((UsbClassDevicePathPtr
->VendorId
== 0xffff || UsbClassDevicePathPtr
->VendorId
== DevDesc
->IdVendor
) &&
954 (UsbClassDevicePathPtr
->ProductId
== 0xffff || UsbClassDevicePathPtr
->ProductId
== DevDesc
->IdProduct
)) {
957 // If class or subclass or protocol is 0, the counterparts in interface should be checked.
959 if (DevDesc
->DeviceClass
== 0 &&
960 DevDesc
->DeviceSubClass
== 0 &&
961 DevDesc
->DeviceProtocol
== 0) {
963 if ((UsbClassDevicePathPtr
->DeviceClass
== ActIfDesc
->InterfaceClass
||
964 UsbClassDevicePathPtr
->DeviceClass
== 0xff) &&
965 (UsbClassDevicePathPtr
->DeviceSubClass
== ActIfDesc
->InterfaceSubClass
||
966 UsbClassDevicePathPtr
->DeviceSubClass
== 0xff) &&
967 (UsbClassDevicePathPtr
->DeviceProtocol
== ActIfDesc
->InterfaceProtocol
) ||
968 UsbClassDevicePathPtr
->DeviceProtocol
== 0xff) {
972 } else if ((UsbClassDevicePathPtr
->DeviceClass
!= DevDesc
->DeviceClass
||
973 UsbClassDevicePathPtr
->DeviceClass
== 0xff) &&
974 (UsbClassDevicePathPtr
->DeviceSubClass
== DevDesc
->DeviceSubClass
||
975 UsbClassDevicePathPtr
->DeviceSubClass
== 0xff) &&
976 (UsbClassDevicePathPtr
->DeviceProtocol
== DevDesc
->DeviceProtocol
) ||
977 UsbClassDevicePathPtr
->DeviceProtocol
== 0xff) {
987 Check whether usb device, whose interface is UsbIf, matches the usb WWID requirement which indicated by
988 UsbWWIDDevicePathPtr whose is a short form usb WWID device path
990 @param UsbClassDevicePathPtr a short form usb WWID device path
991 @param UsbIf a usb device interface
993 @retval TRUE the usb device match the usb WWID requirement
994 @retval FALSE the usb device does not match the usb WWID requirement
1000 IN USB_WWID_DEVICE_PATH
*UsbWWIDDevicePathPtr
,
1001 IN USB_INTERFACE
*UsbIf
1004 USB_INTERFACE_DESC
*IfDesc
;
1005 EFI_USB_INTERFACE_DESCRIPTOR
*ActIfDesc
;
1006 EFI_USB_DEVICE_DESCRIPTOR
*DevDesc
;
1007 EFI_USB_STRING_DESCRIPTOR
*StrDesc
;
1010 if ((UsbWWIDDevicePathPtr
->Header
.Type
!= MESSAGING_DEVICE_PATH
) ||
1011 (UsbWWIDDevicePathPtr
->Header
.SubType
!= MSG_USB_WWID_DP
)){
1016 IfDesc
= UsbIf
->IfDesc
;
1017 ActIfDesc
= &(IfDesc
->Settings
[IfDesc
->ActiveIndex
]->Desc
);
1018 DevDesc
= &(UsbIf
->Device
->DevDesc
->Desc
);
1019 StrDesc
= UsbGetOneString (UsbIf
->Device
, DevDesc
->StrSerialNumber
, USB_US_LAND_ID
);
1020 SnString
= (UINT16
*) ((UINT8
*)UsbWWIDDevicePathPtr
+ 10);
1023 //In addtion, hub interface is always matched for this policy.
1025 if ((ActIfDesc
->InterfaceClass
== USB_HUB_CLASS_CODE
) &&
1026 (ActIfDesc
->InterfaceSubClass
== USB_HUB_SUBCLASS_CODE
)) {
1030 // If connect wwid policy, determine the objective device by the serial number of
1031 // device descriptor.
1032 // Get serial number index from device descriptor, then get serial number by index
1033 // and land id, compare the serial number with wwid device path node at last
1035 // BugBug: only check serial number here, should check Interface Number, Device Vendor Id, Device Product Id in later version
1037 if (StrDesc
!= NULL
&& !StrnCmp (StrDesc
->String
, SnString
, StrDesc
->Length
)) {
1046 Free a DEVICE_PATH_LIST_ITEM list
1048 @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list pointer
1050 @retval EFI_INVALID_PARAMETER
1056 UsbBusFreeUsbDPList (
1057 IN LIST_ENTRY
*UsbIoDPList
1060 LIST_ENTRY
*ListIndex
;
1061 DEVICE_PATH_LIST_ITEM
*ListItem
;
1064 // Check that ControllerHandle is a valid handle
1066 if (UsbIoDPList
== NULL
) {
1067 return EFI_INVALID_PARAMETER
;
1070 ListIndex
= UsbIoDPList
->ForwardLink
;
1071 while (ListIndex
!= UsbIoDPList
){
1072 ListItem
= CR(ListIndex
, DEVICE_PATH_LIST_ITEM
, Link
, DEVICE_PATH_LIST_ITEM_SIGNATURE
);
1074 // Free DEVICE_PATH_LIST_ITEM.DevicePath[]
1076 if (ListItem
->DevicePath
!= NULL
){
1077 FreePool(ListItem
->DevicePath
);
1080 // Free DEVICE_PATH_LIST_ITEM itself
1082 ListIndex
= ListIndex
->ForwardLink
;
1083 RemoveEntryList (&ListItem
->Link
);
1084 FreePool (ListItem
);
1087 InitializeListHead (UsbIoDPList
);
1092 Store a wanted usb child device info (its Usb part of device path) which is indicated by
1093 RemainingDevicePath in a Usb bus which is indicated by UsbBusId
1095 @param UsbBusId Point to EFI_USB_BUS_PROTOCOL interface
1096 @param RemainingDevicePath The remaining device patch
1099 @retval EFI_INVALID_PARAMETER
1100 @retval EFI_OUT_OF_RESOURCES
1105 UsbBusAddWantedUsbIoDP (
1106 IN EFI_USB_BUS_PROTOCOL
*UsbBusId
,
1107 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1112 EFI_DEVICE_PATH_PROTOCOL
*DevicePathPtr
;
1115 // Check whether remaining device path is valid
1117 if (RemainingDevicePath
!= NULL
) {
1118 if ((RemainingDevicePath
->Type
!= MESSAGING_DEVICE_PATH
) ||
1119 (RemainingDevicePath
->SubType
!= MSG_USB_DP
&&
1120 RemainingDevicePath
->SubType
!= MSG_USB_CLASS_DP
1121 && RemainingDevicePath
->SubType
!= MSG_USB_WWID_DP
1123 return EFI_INVALID_PARAMETER
;
1127 if (UsbBusId
== NULL
){
1128 return EFI_INVALID_PARAMETER
;
1131 Bus
= USB_BUS_FROM_THIS (UsbBusId
);
1133 if (RemainingDevicePath
== NULL
) {
1135 // RemainingDevicePath== NULL means all Usb devices in this bus are wanted.
1136 // Here use a Usb class Device Path in WantedUsbIoDPList to indicate all Usb devices
1137 // are wanted Usb devices
1139 Status
= UsbBusFreeUsbDPList (&Bus
->WantedUsbIoDPList
);
1140 ASSERT (!EFI_ERROR (Status
));
1141 DevicePathPtr
= DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL
*) &mAllUsbClassDevicePath
);
1144 // Create new Usb device path according to the usb part in remaining device path
1146 DevicePathPtr
= GetUsbDPFromFullDP (RemainingDevicePath
);
1149 ASSERT (DevicePathPtr
!= NULL
);
1150 Status
= AddUsbDPToList (DevicePathPtr
, &Bus
->WantedUsbIoDPList
);
1151 ASSERT (!EFI_ERROR (Status
));
1152 gBS
->FreePool (DevicePathPtr
);
1157 Check whether a usb child device is the wanted device in a bus
1159 @param Bus The Usb bus's private data pointer
1160 @param UsbIf The usb child device inferface
1163 @retval EFI_INVALID_PARAMETER
1164 @retval EFI_OUT_OF_RESOURCES
1169 UsbBusIsWantedUsbIO (
1171 IN USB_INTERFACE
*UsbIf
1174 EFI_DEVICE_PATH_PROTOCOL
*DevicePathPtr
;
1175 LIST_ENTRY
*WantedUsbIoDPListPtr
;
1176 LIST_ENTRY
*WantedListIndex
;
1177 DEVICE_PATH_LIST_ITEM
*WantedListItem
;
1179 UINTN FirstDevicePathSize
;
1182 // Check whether passed in parameters are valid
1184 if ((UsbIf
== NULL
) || (Bus
== NULL
)) {
1188 // Check whether UsbIf is Hub
1195 // Check whether all Usb devices in this bus are wanted
1197 if (SearchUsbDPInList ((EFI_DEVICE_PATH_PROTOCOL
*)&mAllUsbClassDevicePath
, &Bus
->WantedUsbIoDPList
)){
1202 // Check whether the Usb device match any item in WantedUsbIoDPList
1204 WantedUsbIoDPListPtr
= &Bus
->WantedUsbIoDPList
;
1206 // Create new Usb device path according to the usb part in UsbIo full device path
1208 DevicePathPtr
= GetUsbDPFromFullDP (UsbIf
->DevicePath
);
1209 ASSERT (DevicePathPtr
!= NULL
);
1212 WantedListIndex
= WantedUsbIoDPListPtr
->ForwardLink
;
1213 while (WantedListIndex
!= WantedUsbIoDPListPtr
){
1214 WantedListItem
= CR(WantedListIndex
, DEVICE_PATH_LIST_ITEM
, Link
, DEVICE_PATH_LIST_ITEM_SIGNATURE
);
1215 ASSERT (WantedListItem
->DevicePath
->Type
== MESSAGING_DEVICE_PATH
);
1216 switch (WantedListItem
->DevicePath
->SubType
) {
1218 FirstDevicePathSize
= GetDevicePathSize (WantedListItem
->DevicePath
);
1219 if (FirstDevicePathSize
== GetDevicePathSize (DevicePathPtr
)) {
1221 WantedListItem
->DevicePath
,
1223 GetDevicePathSize (DevicePathPtr
)) == 0
1229 case MSG_USB_CLASS_DP
:
1230 if (MatchUsbClass((USB_CLASS_DEVICE_PATH
*)WantedListItem
->DevicePath
, UsbIf
)) {
1234 case MSG_USB_WWID_DP
:
1235 if (MatchUsbWwid((USB_WWID_DEVICE_PATH
*)WantedListItem
->DevicePath
, UsbIf
)) {
1248 WantedListIndex
= WantedListIndex
->ForwardLink
;
1250 gBS
->FreePool (DevicePathPtr
);
1253 // Check whether the new Usb device path is wanted
1263 Recursively connnect every wanted usb child device to ensure they all fully connected.
1264 Check all the child Usb IO handles in this bus, recursively connecte if it is wanted usb child device
1266 @param UsbBusId point to EFI_USB_BUS_PROTOCOL interface
1269 @retval EFI_INVALID_PARAMETER
1270 @retval EFI_OUT_OF_RESOURCES
1275 UsbBusRecursivelyConnectWantedUsbIo (
1276 IN EFI_USB_BUS_PROTOCOL
*UsbBusId
1282 EFI_USB_IO_PROTOCOL
*UsbIo
;
1283 USB_INTERFACE
*UsbIf
;
1284 UINTN UsbIoHandleCount
;
1285 EFI_HANDLE
*UsbIoBuffer
;
1286 EFI_DEVICE_PATH_PROTOCOL
*UsbIoDevicePath
;
1288 if (UsbBusId
== NULL
){
1289 return EFI_INVALID_PARAMETER
;
1292 Bus
= USB_BUS_FROM_THIS (UsbBusId
);
1295 // Get all Usb IO handles in system
1297 UsbIoHandleCount
= 0;
1298 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiUsbIoProtocolGuid
, NULL
, &UsbIoHandleCount
, &UsbIoBuffer
);
1299 if (Status
== EFI_NOT_FOUND
|| UsbIoHandleCount
== 0) {
1302 ASSERT (!EFI_ERROR (Status
));
1304 for (Index
= 0; Index
< UsbIoHandleCount
; Index
++) {
1306 // Check whether the USB IO handle is a child of this bus
1307 // Note: The usb child handle maybe invalid because of hot plugged out during the loop
1309 UsbIoDevicePath
= NULL
;
1310 Status
= gBS
->HandleProtocol (UsbIoBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*) &UsbIoDevicePath
);
1311 if (EFI_ERROR (Status
) || UsbIoDevicePath
== NULL
) {
1317 (GetDevicePathSize (Bus
->DevicePath
) - sizeof (EFI_DEVICE_PATH_PROTOCOL
))
1323 // Get the child Usb IO interface
1325 Status
= gBS
->HandleProtocol(
1327 &gEfiUsbIoProtocolGuid
,
1330 if (EFI_ERROR (Status
)) {
1333 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1335 if (UsbBusIsWantedUsbIO (Bus
, UsbIf
)) {
1336 if (!UsbIf
->IsManaged
) {
1338 // Recursively connect the wanted Usb Io handle
1340 DEBUG ((EFI_D_INFO
, "UsbConnectDriver: TPL before connect is %d\n", UsbGetCurrentTpl ()));
1341 Status
= gBS
->ConnectController (UsbIf
->Handle
, NULL
, NULL
, TRUE
);
1342 UsbIf
->IsManaged
= (BOOLEAN
)!EFI_ERROR (Status
);
1343 DEBUG ((EFI_D_INFO
, "UsbConnectDriver: TPL after connect is %d\n", UsbGetCurrentTpl()));