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
,
39 (UINT8
) (sizeof (USB_CLASS_DEVICE_PATH
)),
40 (UINT8
) ((sizeof (USB_CLASS_DEVICE_PATH
)) >> 8)
46 0xff, // DeviceSubClass
47 0xff // DeviceProtocol
52 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
54 END_DEVICE_PATH_LENGTH
,
62 Get the capability of the host controller
64 @param UsbBus The usb driver
65 @param MaxSpeed The maximum speed this host controller supports
66 @param NumOfPort The number of the root hub port
67 @param Is64BitCapable Whether this controller support 64 bit addressing
69 @retval EFI_SUCCESS The host controller capability is returned
70 @retval Others Failed to retrieve the host controller capability.
78 OUT UINT8
*Is64BitCapable
83 if (UsbBus
->Usb2Hc
!= NULL
) {
84 Status
= UsbBus
->Usb2Hc
->GetCapability (
92 Status
= UsbBus
->UsbHc
->GetRootHubPortNumber (UsbBus
->UsbHc
, NumOfPort
);
94 *MaxSpeed
= EFI_USB_SPEED_FULL
;
95 *Is64BitCapable
= (UINT8
) FALSE
;
103 Reset the host controller
105 @param UsbBus The usb bus driver
106 @param Attributes The reset type, only global reset is used by this driver
108 @return GC_TODO: add return values
119 if (UsbBus
->Usb2Hc
!= NULL
) {
120 Status
= UsbBus
->Usb2Hc
->Reset (UsbBus
->Usb2Hc
, Attributes
);
122 Status
= UsbBus
->UsbHc
->Reset (UsbBus
->UsbHc
, Attributes
);
130 Get the current operation state of the host controller
132 @param UsbBus The USB bus driver
133 @param State The host controller operation state
135 @retval EFI_SUCCESS The operation state is returned in State
136 @retval Others Failed to get the host controller state
142 OUT EFI_USB_HC_STATE
*State
147 if (UsbBus
->Usb2Hc
!= NULL
) {
148 Status
= UsbBus
->Usb2Hc
->GetState (UsbBus
->Usb2Hc
, State
);
150 Status
= UsbBus
->UsbHc
->GetState (UsbBus
->UsbHc
, State
);
158 Set the host controller operation state
160 @param UsbBus The USB bus driver
161 @param State The state to set
163 @retval EFI_SUCCESS The host controller is now working at State
164 @retval Others Failed to set operation state
170 IN EFI_USB_HC_STATE State
175 if (UsbBus
->Usb2Hc
!= NULL
) {
176 Status
= UsbBus
->Usb2Hc
->SetState (UsbBus
->Usb2Hc
, State
);
178 Status
= UsbBus
->UsbHc
->SetState (UsbBus
->UsbHc
, State
);
186 Get the root hub port state
188 @param UsbBus The USB bus driver
189 @param PortIndex The index of port
190 @param PortStatus The variable to save port state
192 @retval EFI_SUCCESS The root port state is returned in
193 @retval Others Failed to get the root hub port state
197 UsbHcGetRootHubPortStatus (
200 OUT EFI_USB_PORT_STATUS
*PortStatus
205 if (UsbBus
->Usb2Hc
!= NULL
) {
206 Status
= UsbBus
->Usb2Hc
->GetRootHubPortStatus (UsbBus
->Usb2Hc
, PortIndex
, PortStatus
);
208 Status
= UsbBus
->UsbHc
->GetRootHubPortStatus (UsbBus
->UsbHc
, PortIndex
, PortStatus
);
216 Set the root hub port feature
218 @param UsbBus The USB bus driver
219 @param PortIndex The port index
220 @param Feature The port feature to set
222 @retval EFI_SUCCESS The port feature is set
223 @retval Others Failed to set port feature
227 UsbHcSetRootHubPortFeature (
230 IN EFI_USB_PORT_FEATURE Feature
236 if (UsbBus
->Usb2Hc
!= NULL
) {
237 Status
= UsbBus
->Usb2Hc
->SetRootHubPortFeature (UsbBus
->Usb2Hc
, PortIndex
, Feature
);
239 Status
= UsbBus
->UsbHc
->SetRootHubPortFeature (UsbBus
->UsbHc
, PortIndex
, Feature
);
247 Clear the root hub port feature
249 @param UsbBus The USB bus driver
250 @param PortIndex The port index
251 @param Feature The port feature to clear
253 @retval EFI_SUCCESS The port feature is clear
254 @retval Others Failed to clear port feature
258 UsbHcClearRootHubPortFeature (
261 IN EFI_USB_PORT_FEATURE Feature
266 if (UsbBus
->Usb2Hc
!= NULL
) {
267 Status
= UsbBus
->Usb2Hc
->ClearRootHubPortFeature (UsbBus
->Usb2Hc
, PortIndex
, Feature
);
269 Status
= UsbBus
->UsbHc
->ClearRootHubPortFeature (UsbBus
->UsbHc
, PortIndex
, Feature
);
277 Execute a control transfer to the device
279 @param UsbBus The USB bus driver
280 @param DevAddr The device address
281 @param DevSpeed The device speed
282 @param MaxPacket Maximum packet size of endpoint 0
283 @param Request The control transfer request
284 @param Direction The direction of data stage
285 @param Data The buffer holding data
286 @param DataLength The length of the data
287 @param TimeOut Timeout (in ms) to wait until timeout
288 @param Translator The transaction translator for low/full speed device
289 @param UsbResult The result of transfer
291 @retval EFI_SUCCESS The control transfer finished without error
292 @retval Others The control transfer failed, reason returned in UsbReslt
296 UsbHcControlTransfer (
301 IN EFI_USB_DEVICE_REQUEST
*Request
,
302 IN EFI_USB_DATA_DIRECTION Direction
,
304 IN OUT UINTN
*DataLength
,
306 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
307 OUT UINT32
*UsbResult
311 BOOLEAN IsSlowDevice
;
313 if (UsbBus
->Usb2Hc
!= NULL
) {
314 Status
= UsbBus
->Usb2Hc
->ControlTransfer (
329 IsSlowDevice
= (BOOLEAN
)(EFI_USB_SPEED_LOW
== DevSpeed
);
330 Status
= UsbBus
->UsbHc
->ControlTransfer (
349 Execute a bulk transfer to the device's endpoint
351 @param UsbBus The USB bus driver
352 @param DevAddr The target device address
353 @param EpAddr The target endpoint address, with direction encoded in
355 @param DevSpeed The device's speed
356 @param MaxPacket The endpoint's max packet size
357 @param BufferNum The number of data buffer
358 @param Data Array of pointers to data buffer
359 @param DataLength The length of data buffer
360 @param DataToggle On input, the initial data toggle to use, also return
361 the next toggle on output.
362 @param TimeOut The time to wait until timeout
363 @param Translator The transaction translator for low/full speed device
364 @param UsbResult The result of USB execution
366 @retval EFI_SUCCESS The bulk transfer is finished without error
367 @retval Others Failed to execute bulk transfer, result in UsbResult
378 IN OUT VOID
*Data
[EFI_USB_MAX_BULK_BUFFER_NUM
],
379 IN OUT UINTN
*DataLength
,
380 IN OUT UINT8
*DataToggle
,
382 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
383 OUT UINT32
*UsbResult
388 if (UsbBus
->Usb2Hc
!= NULL
) {
389 Status
= UsbBus
->Usb2Hc
->BulkTransfer (
404 Status
= UsbBus
->UsbHc
->BulkTransfer (
422 Queue or cancel an asynchronous interrupt transfer
424 @param UsbBus The USB bus driver
425 @param DevAddr The target device address
426 @param EpAddr The target endpoint address, with direction encoded in
428 @param DevSpeed The device's speed
429 @param MaxPacket The endpoint's max packet size
430 @param IsNewTransfer Whether this is a new request. If not, cancel the old
432 @param DataToggle Data toggle to use on input, next toggle on output
433 @param PollingInterval The interval to poll the interrupt transfer (in ms)
434 @param DataLength The length of periodical data receive
435 @param Translator The transaction translator for low/full speed device
436 @param Callback Function to call when data is received
437 @param Context The context to the callback
439 @retval EFI_SUCCESS The asynchronous transfer is queued
440 @retval Others Failed to queue the transfer
444 UsbHcAsyncInterruptTransfer (
450 IN BOOLEAN IsNewTransfer
,
451 IN OUT UINT8
*DataToggle
,
452 IN UINTN PollingInterval
,
454 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
455 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
,
456 IN VOID
*Context OPTIONAL
460 BOOLEAN IsSlowDevice
;
462 if (UsbBus
->Usb2Hc
!= NULL
) {
463 Status
= UsbBus
->Usb2Hc
->AsyncInterruptTransfer (
478 IsSlowDevice
= (BOOLEAN
)(EFI_USB_SPEED_LOW
== DevSpeed
);
480 Status
= UsbBus
->UsbHc
->AsyncInterruptTransfer (
500 Execute a synchronous interrupt transfer to the target endpoint
502 @param UsbBus The USB bus driver
503 @param DevAddr The target device address
504 @param EpAddr The target endpoint address, with direction encoded in
506 @param DevSpeed The device's speed
507 @param MaxPacket The endpoint's max packet size
508 @param Data Pointer to data buffer
509 @param DataLength The length of data buffer
510 @param DataToggle On input, the initial data toggle to use, also return
511 the next toggle on output.
512 @param TimeOut The time to wait until timeout
513 @param Translator The transaction translator for low/full speed device
514 @param UsbResult The result of USB execution
516 @retval EFI_SUCCESS The synchronous interrupt transfer is OK
517 @retval Others Failed to execute the synchronous interrupt transfer
521 UsbHcSyncInterruptTransfer (
528 IN OUT UINTN
*DataLength
,
529 IN OUT UINT8
*DataToggle
,
531 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
532 OUT UINT32
*UsbResult
536 BOOLEAN IsSlowDevice
;
538 if (UsbBus
->Usb2Hc
!= NULL
) {
539 Status
= UsbBus
->Usb2Hc
->SyncInterruptTransfer (
553 IsSlowDevice
= (BOOLEAN
) ((EFI_USB_SPEED_LOW
== DevSpeed
) ? TRUE
: FALSE
);
554 Status
= UsbBus
->UsbHc
->SyncInterruptTransfer (
573 Execute a synchronous Isochronous USB transfer
575 @param UsbBus The USB bus driver
576 @param DevAddr The target device address
577 @param EpAddr The target endpoint address, with direction encoded in
579 @param DevSpeed The device's speed
580 @param MaxPacket The endpoint's max packet size
581 @param BufferNum The number of data buffer
582 @param Data Array of pointers to data buffer
583 @param DataLength The length of data buffer
584 @param Translator The transaction translator for low/full speed device
585 @param UsbResult The result of USB execution
587 @retval EFI_UNSUPPORTED The isochronous transfer isn't supported now
591 UsbHcIsochronousTransfer (
598 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
600 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
601 OUT UINT32
*UsbResult
604 return EFI_UNSUPPORTED
;
609 Queue an asynchronous isochronous transfer
611 @param UsbBus The USB bus driver
612 @param DevAddr The target device address
613 @param EpAddr The target endpoint address, with direction encoded in
615 @param DevSpeed The device's speed
616 @param MaxPacket The endpoint's max packet size
617 @param BufferNum The number of data buffer
618 @param Data Array of pointers to data buffer
619 @param DataLength The length of data buffer
620 @param Translator The transaction translator for low/full speed device
621 @param Callback The function to call when data is transferred
622 @param Context The context to the callback function
624 @retval EFI_UNSUPPORTED The asynchronous isochronous transfer isn't supported
628 UsbHcAsyncIsochronousTransfer (
635 IN OUT VOID
*Data
[EFI_USB_MAX_ISO_BUFFER_NUM
],
637 IN EFI_USB2_HC_TRANSACTION_TRANSLATOR
*Translator
,
638 IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback
,
642 return EFI_UNSUPPORTED
;
647 Open the USB host controller protocol BY_CHILD
649 @param Bus The USB bus driver
650 @param Child The child handle
652 @return The open protocol return
656 UsbOpenHostProtoByChild (
661 EFI_USB_HC_PROTOCOL
*UsbHc
;
662 EFI_USB2_HC_PROTOCOL
*Usb2Hc
;
665 if (Bus
->Usb2Hc
!= NULL
) {
666 Status
= gBS
->OpenProtocol (
668 &gEfiUsb2HcProtocolGuid
,
670 mUsbBusDriverBinding
.DriverBindingHandle
,
672 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
676 Status
= gBS
->OpenProtocol (
678 &gEfiUsbHcProtocolGuid
,
680 mUsbBusDriverBinding
.DriverBindingHandle
,
682 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
691 Close the USB host controller protocol BY_CHILD
693 @param Bus The USB bus driver
694 @param Child The child handle
700 UsbCloseHostProtoByChild (
705 if (Bus
->Usb2Hc
!= NULL
) {
708 &gEfiUsb2HcProtocolGuid
,
709 mUsbBusDriverBinding
.DriverBindingHandle
,
716 &gEfiUsbHcProtocolGuid
,
717 mUsbBusDriverBinding
.DriverBindingHandle
,
726 return the current TPL, copied from the EDKII glue lib.
740 Tpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
741 gBS
->RestoreTPL (Tpl
);
747 Create a new device path which only contain the first Usb part of the DevicePath
749 @param DevicePath A full device path which contain the usb nodes
751 @return A new device path which only contain the Usb part of the DevicePath
754 EFI_DEVICE_PATH_PROTOCOL
*
757 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
760 EFI_DEVICE_PATH_PROTOCOL
*UsbDevicePathPtr
;
761 EFI_DEVICE_PATH_PROTOCOL
*UsbDevicePathBeginPtr
;
762 EFI_DEVICE_PATH_PROTOCOL
*UsbDevicePathEndPtr
;
766 // Get the Usb part first Begin node in full device path
768 UsbDevicePathBeginPtr
= DevicePath
;
769 while ( (!EfiIsDevicePathEnd (UsbDevicePathBeginPtr
))&&
770 ((UsbDevicePathBeginPtr
->Type
!= MESSAGING_DEVICE_PATH
) ||
771 (UsbDevicePathBeginPtr
->SubType
!= MSG_USB_DP
&&
772 UsbDevicePathBeginPtr
->SubType
!= MSG_USB_CLASS_DP
773 && UsbDevicePathBeginPtr
->SubType
!= MSG_USB_WWID_DP
776 UsbDevicePathBeginPtr
= NextDevicePathNode(UsbDevicePathBeginPtr
);
780 // Get the Usb part first End node in full device path
782 UsbDevicePathEndPtr
= UsbDevicePathBeginPtr
;
783 while ((!EfiIsDevicePathEnd (UsbDevicePathEndPtr
))&&
784 (UsbDevicePathEndPtr
->Type
== MESSAGING_DEVICE_PATH
) &&
785 (UsbDevicePathEndPtr
->SubType
== MSG_USB_DP
||
786 UsbDevicePathEndPtr
->SubType
== MSG_USB_CLASS_DP
787 || UsbDevicePathEndPtr
->SubType
== MSG_USB_WWID_DP
790 UsbDevicePathEndPtr
= NextDevicePathNode(UsbDevicePathEndPtr
);
793 Size
= GetDevicePathSize (UsbDevicePathBeginPtr
);
794 Size
-= GetDevicePathSize (UsbDevicePathEndPtr
);
797 // The passed in DevicePath does not contain the usb nodes
803 // Create a new device path which only contain the above Usb part
805 UsbDevicePathPtr
= AllocateZeroPool (Size
+ sizeof (EFI_DEVICE_PATH_PROTOCOL
));
806 ASSERT (UsbDevicePathPtr
!= NULL
);
807 CopyMem (UsbDevicePathPtr
, UsbDevicePathBeginPtr
, Size
);
809 // Append end device path node
811 UsbDevicePathEndPtr
= (EFI_DEVICE_PATH_PROTOCOL
*) ((UINTN
) UsbDevicePathPtr
+ Size
);
812 SetDevicePathEndNode (UsbDevicePathEndPtr
);
813 return UsbDevicePathPtr
;
817 Check whether a usb device path is in a DEVICE_PATH_LIST_ITEM list.
819 @param UsbDP a usb device path of DEVICE_PATH_LIST_ITEM
820 @parem UsbIoDPList a DEVICE_PATH_LIST_ITEM list
822 @retval TRUE there is a DEVICE_PATH_LIST_ITEM in UsbIoDPList which contains the passed in UsbDP
823 @retval FALSE there is no DEVICE_PATH_LIST_ITEM in UsbIoDPList which contains the passed in UsbDP
829 IN EFI_DEVICE_PATH_PROTOCOL
*UsbDP
,
830 IN LIST_ENTRY
*UsbIoDPList
833 LIST_ENTRY
*ListIndex
;
834 DEVICE_PATH_LIST_ITEM
*ListItem
;
836 UINTN UsbDpDevicePathSize
;
839 // Check that UsbDP and UsbIoDPList are valid
841 if ((UsbIoDPList
== NULL
) || (UsbDP
== NULL
)) {
846 ListIndex
= UsbIoDPList
->ForwardLink
;
847 while (ListIndex
!= UsbIoDPList
){
848 ListItem
= CR(ListIndex
, DEVICE_PATH_LIST_ITEM
, Link
, DEVICE_PATH_LIST_ITEM_SIGNATURE
);
850 // Compare DEVICE_PATH_LIST_ITEM.DevicePath[]
852 ASSERT (ListItem
->DevicePath
!= NULL
);
854 UsbDpDevicePathSize
= GetDevicePathSize (UsbDP
);
855 if (UsbDpDevicePathSize
== GetDevicePathSize (ListItem
->DevicePath
)) {
856 if ((CompareMem (UsbDP
, ListItem
->DevicePath
, UsbDpDevicePathSize
)) == 0) {
861 ListIndex
= ListIndex
->ForwardLink
;
868 Add a usb device path into the DEVICE_PATH_LIST_ITEM list.
870 @param UsbDP a usb device path of DEVICE_PATH_LIST_ITEM
871 @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list
873 @retval EFI_INVALID_PARAMETER
880 IN EFI_DEVICE_PATH_PROTOCOL
*UsbDP
,
881 IN LIST_ENTRY
*UsbIoDPList
884 DEVICE_PATH_LIST_ITEM
*ListItem
;
887 // Check that UsbDP and UsbIoDPList are valid
889 if ((UsbIoDPList
== NULL
) || (UsbDP
== NULL
)) {
890 return EFI_INVALID_PARAMETER
;
893 if (SearchUsbDPInList (UsbDP
, UsbIoDPList
)){
898 // Prepare the usbio device path DEVICE_PATH_LIST_ITEM structure.
900 ListItem
= AllocateZeroPool (sizeof (DEVICE_PATH_LIST_ITEM
));
901 ASSERT (ListItem
!= NULL
);
902 ListItem
->Signature
= DEVICE_PATH_LIST_ITEM_SIGNATURE
;
903 ListItem
->DevicePath
= DuplicateDevicePath (UsbDP
);
905 InsertTailList (UsbIoDPList
, &ListItem
->Link
);
911 Check whether usb device, whose interface is UsbIf, matches the usb class which indicated by
912 UsbClassDevicePathPtr whose is a short form usb class device path
914 @param UsbClassDevicePathPtr a short form usb class device path
915 @param UsbIf a usb device interface
917 @retval TRUE the usb device match the usb class
918 @retval FALSE the usb device does not match the usb class
924 IN USB_CLASS_DEVICE_PATH
*UsbClassDevicePathPtr
,
925 IN USB_INTERFACE
*UsbIf
928 USB_INTERFACE_DESC
*IfDesc
;
929 EFI_USB_INTERFACE_DESCRIPTOR
*ActIfDesc
;
930 EFI_USB_DEVICE_DESCRIPTOR
*DevDesc
;
933 if ((UsbClassDevicePathPtr
->Header
.Type
!= MESSAGING_DEVICE_PATH
) ||
934 (UsbClassDevicePathPtr
->Header
.SubType
!= MSG_USB_CLASS_DP
)){
939 IfDesc
= UsbIf
->IfDesc
;
940 ActIfDesc
= &(IfDesc
->Settings
[IfDesc
->ActiveIndex
]->Desc
);
941 DevDesc
= &(UsbIf
->Device
->DevDesc
->Desc
);
944 // If connect class policy, determine whether to create device handle by the five fields
945 // in class device path node.
947 // In addtion, hub interface is always matched for this policy.
949 if ((ActIfDesc
->InterfaceClass
== USB_HUB_CLASS_CODE
) &&
950 (ActIfDesc
->InterfaceSubClass
== USB_HUB_SUBCLASS_CODE
)) {
955 // If vendor id or product id is 0xffff, they will be ignored.
957 if ((UsbClassDevicePathPtr
->VendorId
== 0xffff || UsbClassDevicePathPtr
->VendorId
== DevDesc
->IdVendor
) &&
958 (UsbClassDevicePathPtr
->ProductId
== 0xffff || UsbClassDevicePathPtr
->ProductId
== DevDesc
->IdProduct
)) {
961 // If class or subclass or protocol is 0, the counterparts in interface should be checked.
963 if (DevDesc
->DeviceClass
== 0 ||
964 DevDesc
->DeviceSubClass
== 0 ||
965 DevDesc
->DeviceProtocol
== 0) {
967 if ((UsbClassDevicePathPtr
->DeviceClass
== ActIfDesc
->InterfaceClass
||
968 UsbClassDevicePathPtr
->DeviceClass
== 0xff) &&
969 (UsbClassDevicePathPtr
->DeviceSubClass
== ActIfDesc
->InterfaceSubClass
||
970 UsbClassDevicePathPtr
->DeviceSubClass
== 0xff) &&
971 (UsbClassDevicePathPtr
->DeviceProtocol
== ActIfDesc
->InterfaceProtocol
||
972 UsbClassDevicePathPtr
->DeviceProtocol
== 0xff)) {
976 } else if ((UsbClassDevicePathPtr
->DeviceClass
== DevDesc
->DeviceClass
||
977 UsbClassDevicePathPtr
->DeviceClass
== 0xff) &&
978 (UsbClassDevicePathPtr
->DeviceSubClass
== DevDesc
->DeviceSubClass
||
979 UsbClassDevicePathPtr
->DeviceSubClass
== 0xff) &&
980 (UsbClassDevicePathPtr
->DeviceProtocol
== DevDesc
->DeviceProtocol
||
981 UsbClassDevicePathPtr
->DeviceProtocol
== 0xff)) {
991 Check whether usb device, whose interface is UsbIf, matches the usb WWID requirement which indicated by
992 UsbWWIDDevicePathPtr whose is a short form usb WWID device path
994 @param UsbClassDevicePathPtr a short form usb WWID device path
995 @param UsbIf a usb device interface
997 @retval TRUE the usb device match the usb WWID requirement
998 @retval FALSE the usb device does not match the usb WWID requirement
1004 IN USB_WWID_DEVICE_PATH
*UsbWWIDDevicePathPtr
,
1005 IN USB_INTERFACE
*UsbIf
1008 USB_INTERFACE_DESC
*IfDesc
;
1009 EFI_USB_INTERFACE_DESCRIPTOR
*ActIfDesc
;
1010 EFI_USB_DEVICE_DESCRIPTOR
*DevDesc
;
1011 EFI_USB_STRING_DESCRIPTOR
*StrDesc
;
1014 if ((UsbWWIDDevicePathPtr
->Header
.Type
!= MESSAGING_DEVICE_PATH
) ||
1015 (UsbWWIDDevicePathPtr
->Header
.SubType
!= MSG_USB_WWID_DP
)){
1020 IfDesc
= UsbIf
->IfDesc
;
1021 ActIfDesc
= &(IfDesc
->Settings
[IfDesc
->ActiveIndex
]->Desc
);
1022 DevDesc
= &(UsbIf
->Device
->DevDesc
->Desc
);
1023 StrDesc
= UsbGetOneString (UsbIf
->Device
, DevDesc
->StrSerialNumber
, USB_US_LAND_ID
);
1024 SnString
= (UINT16
*) ((UINT8
*)UsbWWIDDevicePathPtr
+ 10);
1027 //In addtion, hub interface is always matched for this policy.
1029 if ((ActIfDesc
->InterfaceClass
== USB_HUB_CLASS_CODE
) &&
1030 (ActIfDesc
->InterfaceSubClass
== USB_HUB_SUBCLASS_CODE
)) {
1034 // If connect wwid policy, determine the objective device by the serial number of
1035 // device descriptor.
1036 // Get serial number index from device descriptor, then get serial number by index
1037 // and land id, compare the serial number with wwid device path node at last
1039 // BugBug: only check serial number here, should check Interface Number, Device Vendor Id, Device Product Id in later version
1041 if (StrDesc
!= NULL
&& !StrnCmp (StrDesc
->String
, SnString
, StrDesc
->Length
)) {
1050 Free a DEVICE_PATH_LIST_ITEM list
1052 @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list pointer
1054 @retval EFI_INVALID_PARAMETER
1060 UsbBusFreeUsbDPList (
1061 IN LIST_ENTRY
*UsbIoDPList
1064 LIST_ENTRY
*ListIndex
;
1065 DEVICE_PATH_LIST_ITEM
*ListItem
;
1068 // Check that ControllerHandle is a valid handle
1070 if (UsbIoDPList
== NULL
) {
1071 return EFI_INVALID_PARAMETER
;
1074 ListIndex
= UsbIoDPList
->ForwardLink
;
1075 while (ListIndex
!= UsbIoDPList
){
1076 ListItem
= CR(ListIndex
, DEVICE_PATH_LIST_ITEM
, Link
, DEVICE_PATH_LIST_ITEM_SIGNATURE
);
1078 // Free DEVICE_PATH_LIST_ITEM.DevicePath[]
1080 if (ListItem
->DevicePath
!= NULL
){
1081 FreePool(ListItem
->DevicePath
);
1084 // Free DEVICE_PATH_LIST_ITEM itself
1086 ListIndex
= ListIndex
->ForwardLink
;
1087 RemoveEntryList (&ListItem
->Link
);
1088 FreePool (ListItem
);
1091 InitializeListHead (UsbIoDPList
);
1096 Store a wanted usb child device info (its Usb part of device path) which is indicated by
1097 RemainingDevicePath in a Usb bus which is indicated by UsbBusId
1099 @param UsbBusId Point to EFI_USB_BUS_PROTOCOL interface
1100 @param RemainingDevicePath The remaining device patch
1103 @retval EFI_INVALID_PARAMETER
1104 @retval EFI_OUT_OF_RESOURCES
1109 UsbBusAddWantedUsbIoDP (
1110 IN EFI_USB_BUS_PROTOCOL
*UsbBusId
,
1111 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
1116 EFI_DEVICE_PATH_PROTOCOL
*DevicePathPtr
;
1119 // Check whether remaining device path is valid
1121 if (RemainingDevicePath
!= NULL
) {
1122 if ((RemainingDevicePath
->Type
!= MESSAGING_DEVICE_PATH
) ||
1123 (RemainingDevicePath
->SubType
!= MSG_USB_DP
&&
1124 RemainingDevicePath
->SubType
!= MSG_USB_CLASS_DP
1125 && RemainingDevicePath
->SubType
!= MSG_USB_WWID_DP
1127 return EFI_INVALID_PARAMETER
;
1131 if (UsbBusId
== NULL
){
1132 return EFI_INVALID_PARAMETER
;
1135 Bus
= USB_BUS_FROM_THIS (UsbBusId
);
1137 if (RemainingDevicePath
== NULL
) {
1139 // RemainingDevicePath== NULL means all Usb devices in this bus are wanted.
1140 // Here use a Usb class Device Path in WantedUsbIoDPList to indicate all Usb devices
1141 // are wanted Usb devices
1143 Status
= UsbBusFreeUsbDPList (&Bus
->WantedUsbIoDPList
);
1144 ASSERT (!EFI_ERROR (Status
));
1145 DevicePathPtr
= DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL
*) &mAllUsbClassDevicePath
);
1148 // Create new Usb device path according to the usb part in remaining device path
1150 DevicePathPtr
= GetUsbDPFromFullDP (RemainingDevicePath
);
1153 ASSERT (DevicePathPtr
!= NULL
);
1154 Status
= AddUsbDPToList (DevicePathPtr
, &Bus
->WantedUsbIoDPList
);
1155 ASSERT (!EFI_ERROR (Status
));
1156 gBS
->FreePool (DevicePathPtr
);
1161 Check whether a usb child device is the wanted device in a bus
1163 @param Bus The Usb bus's private data pointer
1164 @param UsbIf The usb child device inferface
1167 @retval EFI_INVALID_PARAMETER
1168 @retval EFI_OUT_OF_RESOURCES
1173 UsbBusIsWantedUsbIO (
1175 IN USB_INTERFACE
*UsbIf
1178 EFI_DEVICE_PATH_PROTOCOL
*DevicePathPtr
;
1179 LIST_ENTRY
*WantedUsbIoDPListPtr
;
1180 LIST_ENTRY
*WantedListIndex
;
1181 DEVICE_PATH_LIST_ITEM
*WantedListItem
;
1183 UINTN FirstDevicePathSize
;
1186 // Check whether passed in parameters are valid
1188 if ((UsbIf
== NULL
) || (Bus
== NULL
)) {
1192 // Check whether UsbIf is Hub
1199 // Check whether all Usb devices in this bus are wanted
1201 if (SearchUsbDPInList ((EFI_DEVICE_PATH_PROTOCOL
*)&mAllUsbClassDevicePath
, &Bus
->WantedUsbIoDPList
)){
1206 // Check whether the Usb device match any item in WantedUsbIoDPList
1208 WantedUsbIoDPListPtr
= &Bus
->WantedUsbIoDPList
;
1210 // Create new Usb device path according to the usb part in UsbIo full device path
1212 DevicePathPtr
= GetUsbDPFromFullDP (UsbIf
->DevicePath
);
1213 ASSERT (DevicePathPtr
!= NULL
);
1216 WantedListIndex
= WantedUsbIoDPListPtr
->ForwardLink
;
1217 while (WantedListIndex
!= WantedUsbIoDPListPtr
){
1218 WantedListItem
= CR(WantedListIndex
, DEVICE_PATH_LIST_ITEM
, Link
, DEVICE_PATH_LIST_ITEM_SIGNATURE
);
1219 ASSERT (WantedListItem
->DevicePath
->Type
== MESSAGING_DEVICE_PATH
);
1220 switch (WantedListItem
->DevicePath
->SubType
) {
1222 FirstDevicePathSize
= GetDevicePathSize (WantedListItem
->DevicePath
);
1223 if (FirstDevicePathSize
== GetDevicePathSize (DevicePathPtr
)) {
1225 WantedListItem
->DevicePath
,
1227 GetDevicePathSize (DevicePathPtr
)) == 0
1233 case MSG_USB_CLASS_DP
:
1234 if (MatchUsbClass((USB_CLASS_DEVICE_PATH
*)WantedListItem
->DevicePath
, UsbIf
)) {
1238 case MSG_USB_WWID_DP
:
1239 if (MatchUsbWwid((USB_WWID_DEVICE_PATH
*)WantedListItem
->DevicePath
, UsbIf
)) {
1252 WantedListIndex
= WantedListIndex
->ForwardLink
;
1254 gBS
->FreePool (DevicePathPtr
);
1257 // Check whether the new Usb device path is wanted
1267 Recursively connnect every wanted usb child device to ensure they all fully connected.
1268 Check all the child Usb IO handles in this bus, recursively connecte if it is wanted usb child device
1270 @param UsbBusId point to EFI_USB_BUS_PROTOCOL interface
1273 @retval EFI_INVALID_PARAMETER
1274 @retval EFI_OUT_OF_RESOURCES
1279 UsbBusRecursivelyConnectWantedUsbIo (
1280 IN EFI_USB_BUS_PROTOCOL
*UsbBusId
1286 EFI_USB_IO_PROTOCOL
*UsbIo
;
1287 USB_INTERFACE
*UsbIf
;
1288 UINTN UsbIoHandleCount
;
1289 EFI_HANDLE
*UsbIoBuffer
;
1290 EFI_DEVICE_PATH_PROTOCOL
*UsbIoDevicePath
;
1292 if (UsbBusId
== NULL
){
1293 return EFI_INVALID_PARAMETER
;
1296 Bus
= USB_BUS_FROM_THIS (UsbBusId
);
1299 // Get all Usb IO handles in system
1301 UsbIoHandleCount
= 0;
1302 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiUsbIoProtocolGuid
, NULL
, &UsbIoHandleCount
, &UsbIoBuffer
);
1303 if (Status
== EFI_NOT_FOUND
|| UsbIoHandleCount
== 0) {
1306 ASSERT (!EFI_ERROR (Status
));
1308 for (Index
= 0; Index
< UsbIoHandleCount
; Index
++) {
1310 // Check whether the USB IO handle is a child of this bus
1311 // Note: The usb child handle maybe invalid because of hot plugged out during the loop
1313 UsbIoDevicePath
= NULL
;
1314 Status
= gBS
->HandleProtocol (UsbIoBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*) &UsbIoDevicePath
);
1315 if (EFI_ERROR (Status
) || UsbIoDevicePath
== NULL
) {
1321 (GetDevicePathSize (Bus
->DevicePath
) - sizeof (EFI_DEVICE_PATH_PROTOCOL
))
1327 // Get the child Usb IO interface
1329 Status
= gBS
->HandleProtocol(
1331 &gEfiUsbIoProtocolGuid
,
1334 if (EFI_ERROR (Status
)) {
1337 UsbIf
= USB_INTERFACE_FROM_USBIO (UsbIo
);
1339 if (UsbBusIsWantedUsbIO (Bus
, UsbIf
)) {
1340 if (!UsbIf
->IsManaged
) {
1342 // Recursively connect the wanted Usb Io handle
1344 DEBUG ((EFI_D_INFO
, "UsbConnectDriver: TPL before connect is %d\n", UsbGetCurrentTpl ()));
1345 Status
= gBS
->ConnectController (UsbIf
->Handle
, NULL
, NULL
, TRUE
);
1346 UsbIf
->IsManaged
= (BOOLEAN
)!EFI_ERROR (Status
);
1347 DEBUG ((EFI_D_INFO
, "UsbConnectDriver: TPL after connect is %d\n", UsbGetCurrentTpl()));