summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Bus/Usb/UsbBusDxe
diff options
context:
space:
mode:
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2007-12-26 06:38:15 +0000
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2007-12-26 06:38:15 +0000
commitecb575d9e65c9d52c17866eebba5f798f178effe (patch)
tree2f81da2590be7aa8f6743cbf4bc0839e21c22aef /MdeModulePkg/Bus/Usb/UsbBusDxe
parentbe0187bbbad2039b83b15aebf9352de27a9d3c00 (diff)
downloadedk2-platforms-ecb575d9e65c9d52c17866eebba5f798f178effe.tar.xz
Enhance the Usb bus driver to support Star with Remaining device path.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4437 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Bus/Usb/UsbBusDxe')
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c22
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h1
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.c637
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c397
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h64
5 files changed, 947 insertions, 174 deletions
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
index 65eb2dd77f..6b46e5c3ce 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
@@ -288,18 +288,24 @@ UsbConnectDriver (
// twisted TPL used. It should be no problem for us to connect
// or disconnect at CALLBACK.
//
- OldTpl = UsbGetCurrentTpl ();
- DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL before connect is %d\n", OldTpl));
+
+ //
+ // Only recursively wanted usb child device
+ //
+ if (UsbBusIsWantedUsbIO (UsbIf->Device->Bus, UsbIf)) {
+ OldTpl = UsbGetCurrentTpl ();
+ DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL before connect is %d\n", OldTpl));
- gBS->RestoreTPL (TPL_CALLBACK);
+ gBS->RestoreTPL (TPL_CALLBACK);
- Status = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);
- UsbIf->IsManaged = (BOOLEAN)!EFI_ERROR (Status);
+ Status = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);
+ UsbIf->IsManaged = (BOOLEAN)!EFI_ERROR (Status);
- DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL after connect is %d\n", UsbGetCurrentTpl()));
- ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
+ DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL after connect is %d\n", UsbGetCurrentTpl()));
+ ASSERT (UsbGetCurrentTpl () == TPL_CALLBACK);
- gBS->RaiseTPL (OldTpl);
+ gBS->RaiseTPL (OldTpl);
+ }
}
return Status;
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h
index 23bcdf93fc..54f4dd2ca0 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.h
@@ -140,6 +140,7 @@ UsbRemoveDevice (
);
VOID
+EFIAPI
UsbHubEnumeration (
IN EFI_EVENT Event,
IN VOID *Context
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.c
index d4184fe1a2..37e6c05a2f 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.c
@@ -25,6 +25,34 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "UsbBus.h"
+//
+// if RemainingDevicePath== NULL, then all Usb child devices in this bus are wanted.
+// Use a shor form Usb class Device Path, which could match any usb device, in WantedUsbIoDPList to indicate all Usb devices
+// are wanted Usb devices
+//
+STATIC USB_CLASS_FORMAT_DEVICE_PATH mAllUsbClassDevicePath = {
+ {
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_USB_CLASS_DP,
+ (UINT8) (sizeof (USB_CLASS_DEVICE_PATH)),
+ (UINT8) ((sizeof (USB_CLASS_DEVICE_PATH)) >> 8)
+ },
+ 0xffff, // VendorId
+ 0xffff, // ProductId
+ 0xff, // DeviceClass
+ 0xff, // DeviceSubClass
+ 0xff // DeviceProtocol
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+};
+
/**
Get the capability of the host controller
@@ -711,3 +739,612 @@ UsbGetCurrentTpl (
return Tpl;
}
+/**
+ Create a new device path which only contain the first Usb part of the DevicePath
+
+ @param DevicePath A full device path which contain the usb nodes
+
+ @return A new device path which only contain the Usb part of the DevicePath
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+GetUsbDPFromFullDP (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *UsbDevicePathPtr;
+ EFI_DEVICE_PATH_PROTOCOL *UsbDevicePathBeginPtr;
+ EFI_DEVICE_PATH_PROTOCOL *UsbDevicePathEndPtr;
+ UINTN Size;
+
+ //
+ // Get the Usb part first Begin node in full device path
+ //
+ UsbDevicePathBeginPtr = DevicePath;
+ while ( (!EfiIsDevicePathEnd (UsbDevicePathBeginPtr))&&
+ ((UsbDevicePathBeginPtr->Type != MESSAGING_DEVICE_PATH) ||
+ (UsbDevicePathBeginPtr->SubType != MSG_USB_DP &&
+ UsbDevicePathBeginPtr->SubType != MSG_USB_CLASS_DP
+ && UsbDevicePathBeginPtr->SubType != MSG_USB_WWID_DP
+ ))) {
+
+ UsbDevicePathBeginPtr = NextDevicePathNode(UsbDevicePathBeginPtr);
+ }
+
+ //
+ // Get the Usb part first End node in full device path
+ //
+ UsbDevicePathEndPtr = UsbDevicePathBeginPtr;
+ while ((!EfiIsDevicePathEnd (UsbDevicePathEndPtr))&&
+ (UsbDevicePathEndPtr->Type == MESSAGING_DEVICE_PATH) &&
+ (UsbDevicePathEndPtr->SubType == MSG_USB_DP ||
+ UsbDevicePathEndPtr->SubType == MSG_USB_CLASS_DP
+ || UsbDevicePathEndPtr->SubType == MSG_USB_WWID_DP
+ )) {
+
+ UsbDevicePathEndPtr = NextDevicePathNode(UsbDevicePathEndPtr);
+ }
+
+ Size = GetDevicePathSize (UsbDevicePathBeginPtr);
+ Size -= GetDevicePathSize (UsbDevicePathEndPtr);
+ if (Size ==0){
+ //
+ // The passed in DevicePath does not contain the usb nodes
+ //
+ return NULL;
+ }
+
+ //
+ // Create a new device path which only contain the above Usb part
+ //
+ UsbDevicePathPtr = AllocateZeroPool (Size + sizeof (EFI_DEVICE_PATH_PROTOCOL));
+ ASSERT (UsbDevicePathPtr != NULL);
+ CopyMem (UsbDevicePathPtr, UsbDevicePathBeginPtr, Size);
+ //
+ // Append end device path node
+ //
+ UsbDevicePathEndPtr = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) UsbDevicePathPtr + Size);
+ SetDevicePathEndNode (UsbDevicePathEndPtr);
+ return UsbDevicePathPtr;
+}
+
+/**
+ Check whether a usb device path is in a DEVICE_PATH_LIST_ITEM list.
+
+ @param UsbDP a usb device path of DEVICE_PATH_LIST_ITEM
+ @parem UsbIoDPList a DEVICE_PATH_LIST_ITEM list
+
+ @retval TRUE there is a DEVICE_PATH_LIST_ITEM in UsbIoDPList which contains the passed in UsbDP
+ @retval FALSE there is no DEVICE_PATH_LIST_ITEM in UsbIoDPList which contains the passed in UsbDP
+
+**/
+BOOLEAN
+EFIAPI
+SearchUsbDPInList (
+ IN EFI_DEVICE_PATH_PROTOCOL *UsbDP,
+ IN LIST_ENTRY *UsbIoDPList
+ )
+{
+ LIST_ENTRY *ListIndex;
+ DEVICE_PATH_LIST_ITEM *ListItem;
+ BOOLEAN Found;
+ UINTN UsbDpDevicePathSize;
+
+ //
+ // Check that UsbDP and UsbIoDPList are valid
+ //
+ if ((UsbIoDPList == NULL) || (UsbDP == NULL)) {
+ return FALSE;
+ }
+
+ Found = FALSE;
+ ListIndex = UsbIoDPList->ForwardLink;
+ while (ListIndex != UsbIoDPList){
+ ListItem = CR(ListIndex, DEVICE_PATH_LIST_ITEM, Link, DEVICE_PATH_LIST_ITEM_SIGNATURE);
+ //
+ // Compare DEVICE_PATH_LIST_ITEM.DevicePath[]
+ //
+ ASSERT (ListItem->DevicePath != NULL);
+
+ UsbDpDevicePathSize = GetDevicePathSize (UsbDP);
+ if (UsbDpDevicePathSize == GetDevicePathSize (ListItem->DevicePath)) {
+ if ((CompareMem (UsbDP, ListItem->DevicePath, UsbDpDevicePathSize)) == 0) {
+ Found = TRUE;
+ break;
+ }
+ }
+ ListIndex = ListIndex->ForwardLink;
+ }
+
+ return Found;
+}
+
+/**
+ Add a usb device path into the DEVICE_PATH_LIST_ITEM list.
+
+ @param UsbDP a usb device path of DEVICE_PATH_LIST_ITEM
+ @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+AddUsbDPToList (
+ IN EFI_DEVICE_PATH_PROTOCOL *UsbDP,
+ IN LIST_ENTRY *UsbIoDPList
+ )
+{
+ DEVICE_PATH_LIST_ITEM *ListItem;
+
+ //
+ // Check that UsbDP and UsbIoDPList are valid
+ //
+ if ((UsbIoDPList == NULL) || (UsbDP == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (SearchUsbDPInList (UsbDP, UsbIoDPList)){
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Prepare the usbio device path DEVICE_PATH_LIST_ITEM structure.
+ //
+ ListItem = AllocateZeroPool (sizeof (DEVICE_PATH_LIST_ITEM));
+ ASSERT (ListItem != NULL);
+ ListItem->Signature = DEVICE_PATH_LIST_ITEM_SIGNATURE;
+ ListItem->DevicePath = DuplicateDevicePath (UsbDP);
+
+ InsertTailList (UsbIoDPList, &ListItem->Link);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check whether usb device, whose interface is UsbIf, matches the usb class which indicated by
+ UsbClassDevicePathPtr whose is a short form usb class device path
+
+ @param UsbClassDevicePathPtr a short form usb class device path
+ @param UsbIf a usb device interface
+
+ @retval TRUE the usb device match the usb class
+ @retval FALSE the usb device does not match the usb class
+
+**/
+BOOLEAN
+EFIAPI
+MatchUsbClass (
+ IN USB_CLASS_DEVICE_PATH *UsbClassDevicePathPtr,
+ IN USB_INTERFACE *UsbIf
+ )
+{
+ USB_INTERFACE_DESC *IfDesc;
+ EFI_USB_INTERFACE_DESCRIPTOR *ActIfDesc;
+ EFI_USB_DEVICE_DESCRIPTOR *DevDesc;
+
+
+ if ((UsbClassDevicePathPtr->Header.Type != MESSAGING_DEVICE_PATH) ||
+ (UsbClassDevicePathPtr->Header.SubType != MSG_USB_CLASS_DP)){
+ ASSERT (0);
+ return FALSE;
+ }
+
+ IfDesc = UsbIf->IfDesc;
+ ActIfDesc = &(IfDesc->Settings[IfDesc->ActiveIndex]->Desc);
+ DevDesc = &(UsbIf->Device->DevDesc->Desc);
+
+ //
+ // If connect class policy, determine whether to create device handle by the five fields
+ // in class device path node.
+ //
+ // In addtion, hub interface is always matched for this policy.
+ //
+ if ((ActIfDesc->InterfaceClass == USB_HUB_CLASS_CODE) &&
+ (ActIfDesc->InterfaceSubClass == USB_HUB_SUBCLASS_CODE)) {
+ return TRUE;
+ }
+
+ //
+ // If vendor id or product id is 0xffff, they will be ignored.
+ //
+ if ((UsbClassDevicePathPtr->VendorId == 0xffff || UsbClassDevicePathPtr->VendorId == DevDesc->IdVendor) &&
+ (UsbClassDevicePathPtr->ProductId == 0xffff || UsbClassDevicePathPtr->ProductId == DevDesc->IdProduct)) {
+
+ //
+ // If class or subclass or protocol is 0, the counterparts in interface should be checked.
+ //
+ if (DevDesc->DeviceClass == 0 &&
+ DevDesc->DeviceSubClass == 0 &&
+ DevDesc->DeviceProtocol == 0) {
+
+ if ((UsbClassDevicePathPtr->DeviceClass == ActIfDesc->InterfaceClass ||
+ UsbClassDevicePathPtr->DeviceClass == 0xff) &&
+ (UsbClassDevicePathPtr->DeviceSubClass == ActIfDesc->InterfaceSubClass ||
+ UsbClassDevicePathPtr->DeviceSubClass == 0xff) &&
+ (UsbClassDevicePathPtr->DeviceProtocol == ActIfDesc->InterfaceProtocol) ||
+ UsbClassDevicePathPtr->DeviceProtocol == 0xff) {
+ return TRUE;
+ }
+
+ } else if ((UsbClassDevicePathPtr->DeviceClass != DevDesc->DeviceClass ||
+ UsbClassDevicePathPtr->DeviceClass == 0xff) &&
+ (UsbClassDevicePathPtr->DeviceSubClass == DevDesc->DeviceSubClass ||
+ UsbClassDevicePathPtr->DeviceSubClass == 0xff) &&
+ (UsbClassDevicePathPtr->DeviceProtocol == DevDesc->DeviceProtocol) ||
+ UsbClassDevicePathPtr->DeviceProtocol == 0xff) {
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Check whether usb device, whose interface is UsbIf, matches the usb WWID requirement which indicated by
+ UsbWWIDDevicePathPtr whose is a short form usb WWID device path
+
+ @param UsbClassDevicePathPtr a short form usb WWID device path
+ @param UsbIf a usb device interface
+
+ @retval TRUE the usb device match the usb WWID requirement
+ @retval FALSE the usb device does not match the usb WWID requirement
+
+**/
+STATIC
+BOOLEAN
+MatchUsbWwid (
+ IN USB_WWID_DEVICE_PATH *UsbWWIDDevicePathPtr,
+ IN USB_INTERFACE *UsbIf
+ )
+{
+ USB_INTERFACE_DESC *IfDesc;
+ EFI_USB_INTERFACE_DESCRIPTOR *ActIfDesc;
+ EFI_USB_DEVICE_DESCRIPTOR *DevDesc;
+ EFI_USB_STRING_DESCRIPTOR *StrDesc;
+ UINT16 *SnString;
+
+ if ((UsbWWIDDevicePathPtr->Header.Type != MESSAGING_DEVICE_PATH) ||
+ (UsbWWIDDevicePathPtr->Header.SubType != MSG_USB_WWID_DP )){
+ ASSERT (0);
+ return FALSE;
+ }
+
+ IfDesc = UsbIf->IfDesc;
+ ActIfDesc = &(IfDesc->Settings[IfDesc->ActiveIndex]->Desc);
+ DevDesc = &(UsbIf->Device->DevDesc->Desc);
+ StrDesc = UsbGetOneString (UsbIf->Device, DevDesc->StrSerialNumber, USB_US_LAND_ID);
+ SnString = (UINT16 *) ((UINT8 *)UsbWWIDDevicePathPtr + 10);
+
+ //
+ //In addtion, hub interface is always matched for this policy.
+ //
+ if ((ActIfDesc->InterfaceClass == USB_HUB_CLASS_CODE) &&
+ (ActIfDesc->InterfaceSubClass == USB_HUB_SUBCLASS_CODE)) {
+ return TRUE;
+ }
+ //
+ // If connect wwid policy, determine the objective device by the serial number of
+ // device descriptor.
+ // Get serial number index from device descriptor, then get serial number by index
+ // and land id, compare the serial number with wwid device path node at last
+ //
+ // BugBug: only check serial number here, should check Interface Number, Device Vendor Id, Device Product Id in later version
+ //
+ if (StrDesc != NULL && !StrnCmp (StrDesc->String, SnString, StrDesc->Length)) {
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Free a DEVICE_PATH_LIST_ITEM list
+
+ @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list pointer
+
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+EFIAPI
+UsbBusFreeUsbDPList (
+ IN LIST_ENTRY *UsbIoDPList
+ )
+{
+ LIST_ENTRY *ListIndex;
+ DEVICE_PATH_LIST_ITEM *ListItem;
+
+ //
+ // Check that ControllerHandle is a valid handle
+ //
+ if (UsbIoDPList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ListIndex = UsbIoDPList->ForwardLink;
+ while (ListIndex != UsbIoDPList){
+ ListItem = CR(ListIndex, DEVICE_PATH_LIST_ITEM, Link, DEVICE_PATH_LIST_ITEM_SIGNATURE);
+ //
+ // Free DEVICE_PATH_LIST_ITEM.DevicePath[]
+ //
+ if (ListItem->DevicePath != NULL){
+ FreePool(ListItem->DevicePath);
+ }
+ //
+ // Free DEVICE_PATH_LIST_ITEM itself
+ //
+ ListIndex = ListIndex->ForwardLink;
+ RemoveEntryList (&ListItem->Link);
+ FreePool (ListItem);
+ }
+
+ InitializeListHead (UsbIoDPList);
+ return EFI_SUCCESS;
+}
+
+/**
+ Store a wanted usb child device info (its Usb part of device path) which is indicated by
+ RemainingDevicePath in a Usb bus which is indicated by UsbBusId
+
+ @param UsbBusId Point to EFI_USB_BUS_PROTOCOL interface
+ @param RemainingDevicePath The remaining device patch
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_OUT_OF_RESOURCES
+
+**/
+EFI_STATUS
+EFIAPI
+UsbBusAddWantedUsbIoDP (
+ IN EFI_USB_BUS_PROTOCOL *UsbBusId,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ USB_BUS *Bus;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathPtr;
+
+ //
+ // Check whether remaining device path is valid
+ //
+ if (RemainingDevicePath != NULL) {
+ if ((RemainingDevicePath->Type != MESSAGING_DEVICE_PATH) ||
+ (RemainingDevicePath->SubType != MSG_USB_DP &&
+ RemainingDevicePath->SubType != MSG_USB_CLASS_DP
+ && RemainingDevicePath->SubType != MSG_USB_WWID_DP
+ )) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (UsbBusId == NULL){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Bus = USB_BUS_FROM_THIS (UsbBusId);
+
+ if (RemainingDevicePath == NULL) {
+ //
+ // RemainingDevicePath== NULL means all Usb devices in this bus are wanted.
+ // Here use a Usb class Device Path in WantedUsbIoDPList to indicate all Usb devices
+ // are wanted Usb devices
+ //
+ Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);
+ ASSERT (!EFI_ERROR (Status));
+ DevicePathPtr = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) &mAllUsbClassDevicePath);
+ } else {
+ //
+ // Create new Usb device path according to the usb part in remaining device path
+ //
+ DevicePathPtr = GetUsbDPFromFullDP (RemainingDevicePath);
+ }
+
+ ASSERT (DevicePathPtr != NULL);
+ Status = AddUsbDPToList (DevicePathPtr, &Bus->WantedUsbIoDPList);
+ ASSERT (!EFI_ERROR (Status));
+ gBS->FreePool (DevicePathPtr);
+ return EFI_SUCCESS;
+}
+
+/**
+ Check whether a usb child device is the wanted device in a bus
+
+ @param Bus The Usb bus's private data pointer
+ @param UsbIf The usb child device inferface
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_OUT_OF_RESOURCES
+
+**/
+BOOLEAN
+EFIAPI
+UsbBusIsWantedUsbIO (
+ IN USB_BUS *Bus,
+ IN USB_INTERFACE *UsbIf
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathPtr;
+ LIST_ENTRY *WantedUsbIoDPListPtr;
+ LIST_ENTRY *WantedListIndex;
+ DEVICE_PATH_LIST_ITEM *WantedListItem;
+ BOOLEAN DoConvert;
+ UINTN FirstDevicePathSize;
+
+ //
+ // Check whether passed in parameters are valid
+ //
+ if ((UsbIf == NULL) || (Bus == NULL)) {
+ return FALSE;
+ }
+ //
+ // Check whether UsbIf is Hub
+ //
+ if (UsbIf->IsHub) {
+ return TRUE;
+ }
+
+ //
+ // Check whether all Usb devices in this bus are wanted
+ //
+ if (SearchUsbDPInList ((EFI_DEVICE_PATH_PROTOCOL *)&mAllUsbClassDevicePath, &Bus->WantedUsbIoDPList)){
+ return TRUE;
+ }
+
+ //
+ // Check whether the Usb device match any item in WantedUsbIoDPList
+ //
+ WantedUsbIoDPListPtr = &Bus->WantedUsbIoDPList;
+ //
+ // Create new Usb device path according to the usb part in UsbIo full device path
+ //
+ DevicePathPtr = GetUsbDPFromFullDP (UsbIf->DevicePath);
+ ASSERT (DevicePathPtr != NULL);
+
+ DoConvert = FALSE;
+ WantedListIndex = WantedUsbIoDPListPtr->ForwardLink;
+ while (WantedListIndex != WantedUsbIoDPListPtr){
+ WantedListItem = CR(WantedListIndex, DEVICE_PATH_LIST_ITEM, Link, DEVICE_PATH_LIST_ITEM_SIGNATURE);
+ ASSERT (WantedListItem->DevicePath->Type == MESSAGING_DEVICE_PATH);
+ switch (WantedListItem->DevicePath->SubType) {
+ case MSG_USB_DP:
+ FirstDevicePathSize = GetDevicePathSize (WantedListItem->DevicePath);
+ if (FirstDevicePathSize == GetDevicePathSize (DevicePathPtr)) {
+ if (CompareMem (
+ WantedListItem->DevicePath,
+ DevicePathPtr,
+ GetDevicePathSize (DevicePathPtr)) == 0
+ ) {
+ DoConvert = TRUE;
+ }
+ }
+ break;
+ case MSG_USB_CLASS_DP:
+ if (MatchUsbClass((USB_CLASS_DEVICE_PATH *)WantedListItem->DevicePath, UsbIf)) {
+ DoConvert = TRUE;
+ }
+ break;
+ case MSG_USB_WWID_DP:
+ if (MatchUsbWwid((USB_WWID_DEVICE_PATH *)WantedListItem->DevicePath, UsbIf)) {
+ DoConvert = TRUE;
+ }
+ break;
+ default:
+ ASSERT (0);
+ break;
+ }
+
+ if (DoConvert) {
+ break;
+ }
+
+ WantedListIndex = WantedListIndex->ForwardLink;
+ }
+ gBS->FreePool (DevicePathPtr);
+
+ //
+ // Check whether the new Usb device path is wanted
+ //
+ if (DoConvert){
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Recursively connnect every wanted usb child device to ensure they all fully connected.
+ Check all the child Usb IO handles in this bus, recursively connecte if it is wanted usb child device
+
+ @param UsbBusId point to EFI_USB_BUS_PROTOCOL interface
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER
+ @retval EFI_OUT_OF_RESOURCES
+
+**/
+EFI_STATUS
+EFIAPI
+UsbBusRecursivelyConnectWantedUsbIo (
+ IN EFI_USB_BUS_PROTOCOL *UsbBusId
+ )
+{
+ USB_BUS *Bus;
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ USB_INTERFACE *UsbIf;
+ UINTN UsbIoHandleCount;
+ EFI_HANDLE *UsbIoBuffer;
+ EFI_DEVICE_PATH_PROTOCOL *UsbIoDevicePath;
+
+ if (UsbBusId == NULL){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Bus = USB_BUS_FROM_THIS (UsbBusId);
+
+ //
+ // Get all Usb IO handles in system
+ //
+ UsbIoHandleCount = 0;
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiUsbIoProtocolGuid, NULL, &UsbIoHandleCount, &UsbIoBuffer);
+ if (Status == EFI_NOT_FOUND || UsbIoHandleCount == 0) {
+ return EFI_SUCCESS;
+ }
+ ASSERT (!EFI_ERROR (Status));
+
+ for (Index = 0; Index < UsbIoHandleCount; Index++) {
+ //
+ // Check whether the USB IO handle is a child of this bus
+ // Note: The usb child handle maybe invalid because of hot plugged out during the loop
+ //
+ UsbIoDevicePath = NULL;
+ Status = gBS->HandleProtocol (UsbIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &UsbIoDevicePath);
+ if (EFI_ERROR (Status) || UsbIoDevicePath == NULL) {
+ continue;
+ }
+ if (CompareMem (
+ UsbIoDevicePath,
+ Bus->DevicePath,
+ (GetDevicePathSize (Bus->DevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL))
+ ) != 0) {
+ continue;
+ }
+
+ //
+ // Get the child Usb IO interface
+ //
+ Status = gBS->HandleProtocol(
+ UsbIoBuffer[Index],
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ UsbIf = USB_INTERFACE_FROM_USBIO (UsbIo);
+
+ if (UsbBusIsWantedUsbIO (Bus, UsbIf)) {
+ if (!UsbIf->IsManaged) {
+ //
+ // Recursively connect the wanted Usb Io handle
+ //
+ DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL before connect is %d\n", UsbGetCurrentTpl ()));
+ Status = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);
+ UsbIf->IsManaged = (BOOLEAN)!EFI_ERROR (Status);
+ DEBUG ((EFI_D_INFO, "UsbConnectDriver: TPL after connect is %d\n", UsbGetCurrentTpl()));
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c
index 910ebc5d23..332871a685 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.c
@@ -868,6 +868,192 @@ ON_EXIT:
return Status;
}
+
+/**
+ Install Usb Bus Protocol on host controller, and start the Usb bus
+
+ @param This The USB bus driver binding instance
+ @param Controller The controller to check
+ @param RemainingDevicePath The remaining device patch
+
+ @retval EFI_SUCCESS The controller is controlled by the usb bus
+ @retval EFI_ALREADY_STARTED The controller is already controlled by the usb bus
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources
+
+**/
+EFI_STATUS
+EFIAPI
+UsbBusBuildProtocol (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ USB_BUS *UsbBus;
+ USB_DEVICE *RootHub;
+ USB_INTERFACE *RootIf;
+ EFI_STATUS Status;
+ EFI_STATUS Status2;
+
+ UsbBus = AllocateZeroPool (sizeof (USB_BUS));
+
+ if (UsbBus == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UsbBus->Signature = USB_BUS_SIGNATURE;
+ UsbBus->HostHandle = Controller;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &UsbBus->DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));
+
+ gBS->FreePool (UsbBus);
+ return Status;
+ }
+
+ //
+ // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
+ // This is for backward compatbility with EFI 1.x. In UEFI
+ // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
+ // and USB_HC because EHCI driver will install both protocols
+ // (for the same reason). If we don't consume both of them,
+ // the unconsumed one may be opened by others.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ (VOID **) &(UsbBus->Usb2Hc),
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ Status2 = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ (VOID **) &(UsbBus->UsbHc),
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));
+
+ Status = EFI_DEVICE_ERROR;
+ goto CLOSE_HC;
+ }
+
+ UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);
+ UsbHcSetState (UsbBus, EfiUsbHcStateOperational);
+
+ //
+ // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &mUsbBusProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &UsbBus->BusId
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));
+ goto CLOSE_HC;
+ }
+
+ //
+ // Initial the wanted child device path list, and add first RemainingDevicePath
+ //
+ InitializeListHead (&UsbBus->WantedUsbIoDPList);
+ Status = UsbBusAddWantedUsbIoDP (&UsbBus->BusId, RemainingDevicePath);
+ ASSERT (!EFI_ERROR (Status));
+ //
+ // Create a fake usb device for root hub
+ //
+ RootHub = AllocateZeroPool (sizeof (USB_DEVICE));
+
+ if (RootHub == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UNINSTALL_USBBUS;
+ }
+
+ RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));
+
+ if (RootIf == NULL) {
+ gBS->FreePool (RootHub);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FREE_ROOTHUB;
+ }
+
+ RootHub->Bus = UsbBus;
+ RootHub->NumOfInterface = 1;
+ RootHub->Interfaces[0] = RootIf;
+ RootIf->Signature = USB_INTERFACE_SIGNATURE;
+ RootIf->Device = RootHub;
+ RootIf->DevicePath = UsbBus->DevicePath;
+
+ Status = mUsbRootHubApi.Init (RootIf);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));
+ goto FREE_ROOTHUB;
+ }
+
+ UsbBus->Devices[0] = RootHub;
+
+ DEBUG ((EFI_D_INFO, "UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf));
+ return EFI_SUCCESS;
+
+FREE_ROOTHUB:
+ if (RootIf != NULL) {
+ gBS->FreePool (RootIf);
+ }
+ if (RootHub != NULL) {
+ gBS->FreePool (RootHub);
+ }
+
+UNINSTALL_USBBUS:
+ gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);
+
+CLOSE_HC:
+ if (UsbBus->Usb2Hc != NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ if (UsbBus->UsbHc != NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->FreePool (UsbBus);
+
+ DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));
+ return Status;
+}
+
EFI_USB_IO_PROTOCOL mUsbIoProtocol = {
UsbIoControlTransfer,
UsbIoBulkTransfer,
@@ -952,8 +1138,10 @@ UsbBusControllerDriverSupported (
DevicePathNode.DevPath = RemainingDevicePath;
if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) ||
- (DevicePathNode.DevPath->SubType != MSG_USB_DP) ||
- (DevicePathNodeLength (DevicePathNode.DevPath) != sizeof (USB_DEVICE_PATH))) {
+ (DevicePathNode.DevPath->SubType != MSG_USB_DP &&
+ DevicePathNode.DevPath->SubType != MSG_USB_CLASS_DP
+ && DevicePathNode.DevPath->SubType != MSG_USB_WWID_DP
+ )) {
return EFI_UNSUPPORTED;
}
@@ -1060,12 +1248,8 @@ UsbBusControllerDriverStart (
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
- USB_BUS *UsbBus;
- USB_DEVICE *RootHub;
- USB_INTERFACE *RootIf;
- EFI_USB_BUS_PROTOCOL *UsbBusId;
- EFI_STATUS Status;
- EFI_STATUS Status2;
+ EFI_USB_BUS_PROTOCOL *UsbBusId;
+ EFI_STATUS Status;
//
// Locate the USB bus protocol, if it is found, USB bus
@@ -1080,161 +1264,47 @@ UsbBusControllerDriverStart (
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
- if (!EFI_ERROR (Status)) {
- return EFI_ALREADY_STARTED;
- }
-
- UsbBus = AllocateZeroPool (sizeof (USB_BUS));
-
- if (UsbBus == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- UsbBus->Signature = USB_BUS_SIGNATURE;
- UsbBus->HostHandle = Controller;
-
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &UsbBus->DevicePath,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
-
if (EFI_ERROR (Status)) {
- DEBUG (( EFI_D_ERROR, "UsbBusStart: Failed to open device path %r\n", Status));
-
- gBS->FreePool (UsbBus);
- return Status;
- }
-
- //
- // Get USB_HC2/USB_HC host controller protocol (EHCI/UHCI).
- // This is for backward compatbility with EFI 1.x. In UEFI
- // 2.x, USB_HC2 replaces USB_HC. We will open both USB_HC2
- // and USB_HC because EHCI driver will install both protocols
- // (for the same reason). If we don't consume both of them,
- // the unconsumed one may be opened by others.
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiUsb2HcProtocolGuid,
- (VOID **) &(UsbBus->Usb2Hc),
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
-
- Status2 = gBS->OpenProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- (VOID **) &(UsbBus->UsbHc),
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
-
- if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {
- DEBUG (( EFI_D_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC %r\n", Status));
-
- Status = EFI_DEVICE_ERROR;
- goto CLOSE_HC;
- }
-
- UsbHcReset (UsbBus, EFI_USB_HC_RESET_GLOBAL);
- UsbHcSetState (UsbBus, EfiUsbHcStateOperational);
-
- //
- // Install an EFI_USB_BUS_PROTOCOL to host controler to identify it.
- //
- Status = gBS->InstallProtocolInterface (
- &Controller,
- &mUsbBusProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &UsbBus->BusId
- );
-
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "UsbBusStart: Failed to install bus protocol %r\n", Status));
- goto CLOSE_HC;
- }
-
- //
- // Create a fake usb device for root hub
- //
- RootHub = AllocateZeroPool (sizeof (USB_DEVICE));
-
- if (RootHub == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto UNINSTALL_USBBUS;
- }
-
- RootIf = AllocateZeroPool (sizeof (USB_INTERFACE));
-
- if (RootIf == NULL) {
- gBS->FreePool (RootHub);
- Status = EFI_OUT_OF_RESOURCES;
- goto FREE_ROOTHUB;
- }
-
- RootHub->Bus = UsbBus;
- RootHub->NumOfInterface = 1;
- RootHub->Interfaces[0] = RootIf;
- RootIf->Signature = USB_INTERFACE_SIGNATURE;
- RootIf->Device = RootHub;
- RootIf->DevicePath = UsbBus->DevicePath;
-
- Status = mUsbRootHubApi.Init (RootIf);
-
- if (EFI_ERROR (Status)) {
- DEBUG (( EFI_D_ERROR, "UsbBusStart: Failed to init root hub %r\n", Status));
- goto FREE_ROOTHUB;
+ //
+ // If first start, build the bus execute enviorment and install bus protocol
+ //
+ Status = UsbBusBuildProtocol (This, Controller, RemainingDevicePath);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Try get the Usb Bus protocol interface again
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &mUsbBusProtocolGuid,
+ (VOID **) &UsbBusId,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ ASSERT (!EFI_ERROR (Status));
+ } else {
+ //
+ // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
+ // usb child device will be recursively connected.
+ // The RemainingDevicePath indicate the child usb device which user want to fully recursively connecte this time.
+ // All wanted usb child devices will be remembered by the usb bus driver itself.
+ // If RemainingDevicePath == NULL, all the usb child devices in the usb bus are wanted devices.
+ //
+ // Save the passed in RemainingDevicePath this time
+ //
+ Status = UsbBusAddWantedUsbIoDP (UsbBusId, RemainingDevicePath);
+ ASSERT (!EFI_ERROR (Status));
+ //
+ // Ensure all wanted child usb devices are fully recursively connected
+ //
+ Status = UsbBusRecursivelyConnectWantedUsbIo (UsbBusId);
+ ASSERT (!EFI_ERROR (Status));
}
- UsbBus->Devices[0] = RootHub;
- DEBUG (( EFI_D_INFO, "UsbBusStart: usb bus started on %x, root hub %x\n", Controller, RootIf));
return EFI_SUCCESS;
-
-FREE_ROOTHUB:
- if (RootIf != NULL) {
- gBS->FreePool (RootIf);
- }
- if (RootHub != NULL) {
- gBS->FreePool (RootHub);
- }
-
-UNINSTALL_USBBUS:
- gBS->UninstallProtocolInterface (Controller, &mUsbBusProtocolGuid, &UsbBus->BusId);
-
-CLOSE_HC:
- if (UsbBus->Usb2Hc != NULL) {
- gBS->CloseProtocol (
- Controller,
- &gEfiUsb2HcProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- }
- if (UsbBus->UsbHc != NULL) {
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- }
- gBS->CloseProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- gBS->FreePool (UsbBus);
-
- DEBUG (( EFI_D_ERROR, "UsbBusStart: Failed to start bus driver %r\n", Status));
- return Status;
}
@@ -1274,7 +1344,10 @@ UsbBusControllerDriverStop (
Status = EFI_SUCCESS;
if (NumberOfChildren > 0) {
- OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
+ //
+ // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
+ //
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
for (Index = 0; Index < NumberOfChildren; Index++) {
Status = gBS->OpenProtocol (
@@ -1329,7 +1402,9 @@ UsbBusControllerDriverStop (
//
// Stop the root hub, then free all the devices
//
- OldTpl = gBS->RaiseTPL (USB_BUS_TPL);
+ // BugBug: Raise TPL to callback level instead of USB_BUS_TPL to avoid TPL conflict
+ //
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
UsbHcSetState (Bus, EfiUsbHcStateHalt);
RootHub = Bus->Devices[0];
@@ -1347,6 +1422,8 @@ UsbBusControllerDriverStop (
gBS->FreePool (RootIf);
gBS->FreePool (RootHub);
+ Status = UsbBusFreeUsbDPList (&Bus->WantedUsbIoDPList);
+ ASSERT (!EFI_ERROR (Status));
//
// Uninstall the bus identifier and close USB_HC/USB2_HC protocols
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h
index 971e01b47a..e85fc84fe8 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/usbbus.h
@@ -32,6 +32,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/UsbIo.h>
#include <Protocol/DevicePath.h>
+#include <library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiDriverEntryPoint.h>
@@ -75,7 +76,7 @@ enum {
//
USB_WAIT_PORT_STABLE_STALL = 100 * USB_BUS_1_MILLISECOND,
- //
+ //
// Wait for port statue reg change, set by experience
//
USB_WAIT_PORT_STS_CHANGE_STALL = 5 * USB_BUS_1_MILLISECOND,
@@ -98,8 +99,8 @@ enum {
USB_SET_PORT_POWER_STALL = 2 * USB_BUS_1_MILLISECOND,
//
- // Wait for port reset, refers to specification
- // [USB20-7.1.7.5, it says 10ms for hub and 50ms for
+ // Wait for port reset, refers to specification
+ // [USB20-7.1.7.5, it says 10ms for hub and 50ms for
// root hub]
//
USB_SET_PORT_RESET_STALL = 20 * USB_BUS_1_MILLISECOND,
@@ -112,11 +113,11 @@ enum {
//
// Wait for set roothub port enable, set by experience
- //
+ //
USB_SET_ROOT_PORT_ENABLE_STALL = 20 * USB_BUS_1_MILLISECOND,
//
- // Send general device request timeout, refers to
+ // Send general device request timeout, refers to
// specification[USB20-11.24.1]
//
USB_GENERAL_DEVICE_REQUEST_TIMEOUT = 50 * USB_BUS_1_MILLISECOND,
@@ -125,7 +126,7 @@ enum {
// Send clear feature request timeout, set by experience
//
USB_CLEAR_FEATURE_REQUEST_TIMEOUT = 10 * USB_BUS_1_MILLISECOND,
-
+
//
// Bus raises TPL to TPL_NOTIFY to serialize all its operations
// to protect shared data structures.
@@ -251,8 +252,59 @@ struct _USB_BUS {
// for root hub. Device with address i is at Devices[i].
//
USB_DEVICE *Devices[USB_MAX_DEVICES];
+
+ //
+ // USB Bus driver need to control the recursive connect policy of the bus, only those wanted
+ // usb child device will be recursively connected.
+ //
+ // WantedUsbIoDPList tracks the Usb child devices which user want to recursivly fully connecte,
+ // every wanted child device is stored in a item of the WantedUsbIoDPList, whose structrure is
+ // DEVICE_PATH_LIST_ITEM
+ //
+ LIST_ENTRY WantedUsbIoDPList;
+
};
+#define USB_US_LAND_ID 0x0409
+
+#define DEVICE_PATH_LIST_ITEM_SIGNATURE EFI_SIGNATURE_32('d','p','l','i')
+typedef struct _DEVICE_PATH_LIST_ITEM{
+ UINTN Signature;
+ LIST_ENTRY Link;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+} DEVICE_PATH_LIST_ITEM;
+
+typedef struct {
+ USB_CLASS_DEVICE_PATH UsbClass;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} USB_CLASS_FORMAT_DEVICE_PATH;
+
+EFI_STATUS
+EFIAPI
+UsbBusFreeUsbDPList (
+ IN LIST_ENTRY *UsbIoDPList
+ );
+
+EFI_STATUS
+EFIAPI
+UsbBusAddWantedUsbIoDP (
+ IN EFI_USB_BUS_PROTOCOL *UsbBusId,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+BOOLEAN
+EFIAPI
+UsbBusIsWantedUsbIO (
+ IN USB_BUS *Bus,
+ IN USB_INTERFACE *UsbIf
+ );
+
+EFI_STATUS
+EFIAPI
+UsbBusRecursivelyConnectWantedUsbIo (
+ IN EFI_USB_BUS_PROTOCOL *UsbBusId
+ );
+
extern EFI_USB_IO_PROTOCOL mUsbIoProtocol;
extern EFI_DRIVER_BINDING_PROTOCOL mUsbBusDriverBinding;
extern EFI_COMPONENT_NAME_PROTOCOL mUsbBusComponentName;