| /** @file | |
| Wrapper function for usb host controller interface. | |
| Copyright (c) 2007 - 2009, Intel Corporation | |
| All rights reserved. This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| 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 | |
| // | |
| 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. | |
| @param UsbBus The usb driver. | |
| @param MaxSpeed The maximum speed this host controller supports. | |
| @param NumOfPort The number of the root hub port. | |
| @param Is64BitCapable Whether this controller support 64 bit addressing. | |
| @retval EFI_SUCCESS The host controller capability is returned. | |
| @retval Others Failed to retrieve the host controller capability. | |
| **/ | |
| EFI_STATUS | |
| UsbHcGetCapability ( | |
| IN USB_BUS *UsbBus, | |
| OUT UINT8 *MaxSpeed, | |
| OUT UINT8 *NumOfPort, | |
| OUT UINT8 *Is64BitCapable | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| if (UsbBus->Usb2Hc != NULL) { | |
| Status = UsbBus->Usb2Hc->GetCapability ( | |
| UsbBus->Usb2Hc, | |
| MaxSpeed, | |
| NumOfPort, | |
| Is64BitCapable | |
| ); | |
| } else { | |
| Status = UsbBus->UsbHc->GetRootHubPortNumber (UsbBus->UsbHc, NumOfPort); | |
| *MaxSpeed = EFI_USB_SPEED_FULL; | |
| *Is64BitCapable = (UINT8) FALSE; | |
| } | |
| return Status; | |
| } | |
| /** | |
| Reset the host controller. | |
| @param UsbBus The usb bus driver. | |
| @param Attributes The reset type, only global reset is used by this driver. | |
| @retval EFI_SUCCESS The reset operation succeeded. | |
| @retval EFI_INVALID_PARAMETER Attributes is not valid. | |
| @retval EFI_UNSUPPOURTED The type of reset specified by Attributes is | |
| not currently supported by the host controller. | |
| @retval EFI_DEVICE_ERROR Host controller isn't halted to reset. | |
| **/ | |
| EFI_STATUS | |
| UsbHcReset ( | |
| IN USB_BUS *UsbBus, | |
| IN UINT16 Attributes | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| if (UsbBus->Usb2Hc != NULL) { | |
| Status = UsbBus->Usb2Hc->Reset (UsbBus->Usb2Hc, Attributes); | |
| } else { | |
| Status = UsbBus->UsbHc->Reset (UsbBus->UsbHc, Attributes); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Get the current operation state of the host controller. | |
| @param UsbBus The USB bus driver. | |
| @param State The host controller operation state. | |
| @retval EFI_SUCCESS The operation state is returned in State. | |
| @retval Others Failed to get the host controller state. | |
| **/ | |
| EFI_STATUS | |
| UsbHcGetState ( | |
| IN USB_BUS *UsbBus, | |
| OUT EFI_USB_HC_STATE *State | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| if (UsbBus->Usb2Hc != NULL) { | |
| Status = UsbBus->Usb2Hc->GetState (UsbBus->Usb2Hc, State); | |
| } else { | |
| Status = UsbBus->UsbHc->GetState (UsbBus->UsbHc, State); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Set the host controller operation state. | |
| @param UsbBus The USB bus driver. | |
| @param State The state to set. | |
| @retval EFI_SUCCESS The host controller is now working at State. | |
| @retval Others Failed to set operation state. | |
| **/ | |
| EFI_STATUS | |
| UsbHcSetState ( | |
| IN USB_BUS *UsbBus, | |
| IN EFI_USB_HC_STATE State | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| if (UsbBus->Usb2Hc != NULL) { | |
| Status = UsbBus->Usb2Hc->SetState (UsbBus->Usb2Hc, State); | |
| } else { | |
| Status = UsbBus->UsbHc->SetState (UsbBus->UsbHc, State); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Get the root hub port state. | |
| @param UsbBus The USB bus driver. | |
| @param PortIndex The index of port. | |
| @param PortStatus The variable to save port state. | |
| @retval EFI_SUCCESS The root port state is returned in. | |
| @retval Others Failed to get the root hub port state. | |
| **/ | |
| EFI_STATUS | |
| UsbHcGetRootHubPortStatus ( | |
| IN USB_BUS *UsbBus, | |
| IN UINT8 PortIndex, | |
| OUT EFI_USB_PORT_STATUS *PortStatus | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| if (UsbBus->Usb2Hc != NULL) { | |
| Status = UsbBus->Usb2Hc->GetRootHubPortStatus (UsbBus->Usb2Hc, PortIndex, PortStatus); | |
| } else { | |
| Status = UsbBus->UsbHc->GetRootHubPortStatus (UsbBus->UsbHc, PortIndex, PortStatus); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Set the root hub port feature. | |
| @param UsbBus The USB bus driver. | |
| @param PortIndex The port index. | |
| @param Feature The port feature to set. | |
| @retval EFI_SUCCESS The port feature is set. | |
| @retval Others Failed to set port feature. | |
| **/ | |
| EFI_STATUS | |
| UsbHcSetRootHubPortFeature ( | |
| IN USB_BUS *UsbBus, | |
| IN UINT8 PortIndex, | |
| IN EFI_USB_PORT_FEATURE Feature | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| if (UsbBus->Usb2Hc != NULL) { | |
| Status = UsbBus->Usb2Hc->SetRootHubPortFeature (UsbBus->Usb2Hc, PortIndex, Feature); | |
| } else { | |
| Status = UsbBus->UsbHc->SetRootHubPortFeature (UsbBus->UsbHc, PortIndex, Feature); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Clear the root hub port feature. | |
| @param UsbBus The USB bus driver. | |
| @param PortIndex The port index. | |
| @param Feature The port feature to clear. | |
| @retval EFI_SUCCESS The port feature is clear. | |
| @retval Others Failed to clear port feature. | |
| **/ | |
| EFI_STATUS | |
| UsbHcClearRootHubPortFeature ( | |
| IN USB_BUS *UsbBus, | |
| IN UINT8 PortIndex, | |
| IN EFI_USB_PORT_FEATURE Feature | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| if (UsbBus->Usb2Hc != NULL) { | |
| Status = UsbBus->Usb2Hc->ClearRootHubPortFeature (UsbBus->Usb2Hc, PortIndex, Feature); | |
| } else { | |
| Status = UsbBus->UsbHc->ClearRootHubPortFeature (UsbBus->UsbHc, PortIndex, Feature); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Execute a control transfer to the device. | |
| @param UsbBus The USB bus driver. | |
| @param DevAddr The device address. | |
| @param DevSpeed The device speed. | |
| @param MaxPacket Maximum packet size of endpoint 0. | |
| @param Request The control transfer request. | |
| @param Direction The direction of data stage. | |
| @param Data The buffer holding data. | |
| @param DataLength The length of the data. | |
| @param TimeOut Timeout (in ms) to wait until timeout. | |
| @param Translator The transaction translator for low/full speed device. | |
| @param UsbResult The result of transfer. | |
| @retval EFI_SUCCESS The control transfer finished without error. | |
| @retval Others The control transfer failed, reason returned in UsbReslt. | |
| **/ | |
| EFI_STATUS | |
| UsbHcControlTransfer ( | |
| IN USB_BUS *UsbBus, | |
| IN UINT8 DevAddr, | |
| IN UINT8 DevSpeed, | |
| IN UINTN MaxPacket, | |
| IN EFI_USB_DEVICE_REQUEST *Request, | |
| IN EFI_USB_DATA_DIRECTION Direction, | |
| IN OUT VOID *Data, | |
| IN OUT UINTN *DataLength, | |
| IN UINTN TimeOut, | |
| IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, | |
| OUT UINT32 *UsbResult | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| BOOLEAN IsSlowDevice; | |
| if (UsbBus->Usb2Hc != NULL) { | |
| Status = UsbBus->Usb2Hc->ControlTransfer ( | |
| UsbBus->Usb2Hc, | |
| DevAddr, | |
| DevSpeed, | |
| MaxPacket, | |
| Request, | |
| Direction, | |
| Data, | |
| DataLength, | |
| TimeOut, | |
| Translator, | |
| UsbResult | |
| ); | |
| } else { | |
| IsSlowDevice = (BOOLEAN)(EFI_USB_SPEED_LOW == DevSpeed); | |
| Status = UsbBus->UsbHc->ControlTransfer ( | |
| UsbBus->UsbHc, | |
| DevAddr, | |
| IsSlowDevice, | |
| (UINT8) MaxPacket, | |
| Request, | |
| Direction, | |
| Data, | |
| DataLength, | |
| TimeOut, | |
| UsbResult | |
| ); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Execute a bulk transfer to the device's endpoint. | |
| @param UsbBus The USB bus driver. | |
| @param DevAddr The target device address. | |
| @param EpAddr The target endpoint address, with direction encoded in | |
| bit 7. | |
| @param DevSpeed The device's speed. | |
| @param MaxPacket The endpoint's max packet size. | |
| @param BufferNum The number of data buffer. | |
| @param Data Array of pointers to data buffer. | |
| @param DataLength The length of data buffer. | |
| @param DataToggle On input, the initial data toggle to use, also return | |
| the next toggle on output. | |
| @param TimeOut The time to wait until timeout. | |
| @param Translator The transaction translator for low/full speed device. | |
| @param UsbResult The result of USB execution. | |
| @retval EFI_SUCCESS The bulk transfer is finished without error. | |
| @retval Others Failed to execute bulk transfer, result in UsbResult. | |
| **/ | |
| EFI_STATUS | |
| UsbHcBulkTransfer ( | |
| IN USB_BUS *UsbBus, | |
| IN UINT8 DevAddr, | |
| IN UINT8 EpAddr, | |
| IN UINT8 DevSpeed, | |
| IN UINTN MaxPacket, | |
| IN UINT8 BufferNum, | |
| IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], | |
| IN OUT UINTN *DataLength, | |
| IN OUT UINT8 *DataToggle, | |
| IN UINTN TimeOut, | |
| IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, | |
| OUT UINT32 *UsbResult | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| if (UsbBus->Usb2Hc != NULL) { | |
| Status = UsbBus->Usb2Hc->BulkTransfer ( | |
| UsbBus->Usb2Hc, | |
| DevAddr, | |
| EpAddr, | |
| DevSpeed, | |
| MaxPacket, | |
| BufferNum, | |
| Data, | |
| DataLength, | |
| DataToggle, | |
| TimeOut, | |
| Translator, | |
| UsbResult | |
| ); | |
| } else { | |
| Status = UsbBus->UsbHc->BulkTransfer ( | |
| UsbBus->UsbHc, | |
| DevAddr, | |
| EpAddr, | |
| (UINT8) MaxPacket, | |
| *Data, | |
| DataLength, | |
| DataToggle, | |
| TimeOut, | |
| UsbResult | |
| ); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Queue or cancel an asynchronous interrupt transfer. | |
| @param UsbBus The USB bus driver. | |
| @param DevAddr The target device address. | |
| @param EpAddr The target endpoint address, with direction encoded in | |
| bit 7. | |
| @param DevSpeed The device's speed. | |
| @param MaxPacket The endpoint's max packet size. | |
| @param IsNewTransfer Whether this is a new request. If not, cancel the old | |
| request. | |
| @param DataToggle Data toggle to use on input, next toggle on output. | |
| @param PollingInterval The interval to poll the interrupt transfer (in ms). | |
| @param DataLength The length of periodical data receive. | |
| @param Translator The transaction translator for low/full speed device. | |
| @param Callback Function to call when data is received. | |
| @param Context The context to the callback. | |
| @retval EFI_SUCCESS The asynchronous transfer is queued. | |
| @retval Others Failed to queue the transfer. | |
| **/ | |
| EFI_STATUS | |
| UsbHcAsyncInterruptTransfer ( | |
| IN USB_BUS *UsbBus, | |
| IN UINT8 DevAddr, | |
| IN UINT8 EpAddr, | |
| IN UINT8 DevSpeed, | |
| IN UINTN MaxPacket, | |
| IN BOOLEAN IsNewTransfer, | |
| IN OUT UINT8 *DataToggle, | |
| IN UINTN PollingInterval, | |
| IN UINTN DataLength, | |
| IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, | |
| IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, | |
| IN VOID *Context OPTIONAL | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| BOOLEAN IsSlowDevice; | |
| if (UsbBus->Usb2Hc != NULL) { | |
| Status = UsbBus->Usb2Hc->AsyncInterruptTransfer ( | |
| UsbBus->Usb2Hc, | |
| DevAddr, | |
| EpAddr, | |
| DevSpeed, | |
| MaxPacket, | |
| IsNewTransfer, | |
| DataToggle, | |
| PollingInterval, | |
| DataLength, | |
| Translator, | |
| Callback, | |
| Context | |
| ); | |
| } else { | |
| IsSlowDevice = (BOOLEAN)(EFI_USB_SPEED_LOW == DevSpeed); | |
| Status = UsbBus->UsbHc->AsyncInterruptTransfer ( | |
| UsbBus->UsbHc, | |
| DevAddr, | |
| EpAddr, | |
| IsSlowDevice, | |
| (UINT8) MaxPacket, | |
| IsNewTransfer, | |
| DataToggle, | |
| PollingInterval, | |
| DataLength, | |
| Callback, | |
| Context | |
| ); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Execute a synchronous interrupt transfer to the target endpoint. | |
| @param UsbBus The USB bus driver. | |
| @param DevAddr The target device address. | |
| @param EpAddr The target endpoint address, with direction encoded in | |
| bit 7. | |
| @param DevSpeed The device's speed. | |
| @param MaxPacket The endpoint's max packet size. | |
| @param Data Pointer to data buffer. | |
| @param DataLength The length of data buffer. | |
| @param DataToggle On input, the initial data toggle to use, also return | |
| the next toggle on output. | |
| @param TimeOut The time to wait until timeout. | |
| @param Translator The transaction translator for low/full speed device. | |
| @param UsbResult The result of USB execution. | |
| @retval EFI_SUCCESS The synchronous interrupt transfer is OK. | |
| @retval Others Failed to execute the synchronous interrupt transfer. | |
| **/ | |
| EFI_STATUS | |
| UsbHcSyncInterruptTransfer ( | |
| IN USB_BUS *UsbBus, | |
| IN UINT8 DevAddr, | |
| IN UINT8 EpAddr, | |
| IN UINT8 DevSpeed, | |
| IN UINTN MaxPacket, | |
| IN OUT VOID *Data, | |
| IN OUT UINTN *DataLength, | |
| IN OUT UINT8 *DataToggle, | |
| IN UINTN TimeOut, | |
| IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, | |
| OUT UINT32 *UsbResult | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| BOOLEAN IsSlowDevice; | |
| if (UsbBus->Usb2Hc != NULL) { | |
| Status = UsbBus->Usb2Hc->SyncInterruptTransfer ( | |
| UsbBus->Usb2Hc, | |
| DevAddr, | |
| EpAddr, | |
| DevSpeed, | |
| MaxPacket, | |
| Data, | |
| DataLength, | |
| DataToggle, | |
| TimeOut, | |
| Translator, | |
| UsbResult | |
| ); | |
| } else { | |
| IsSlowDevice = (BOOLEAN) ((EFI_USB_SPEED_LOW == DevSpeed) ? TRUE : FALSE); | |
| Status = UsbBus->UsbHc->SyncInterruptTransfer ( | |
| UsbBus->UsbHc, | |
| DevAddr, | |
| EpAddr, | |
| IsSlowDevice, | |
| (UINT8) MaxPacket, | |
| Data, | |
| DataLength, | |
| DataToggle, | |
| TimeOut, | |
| UsbResult | |
| ); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Execute a synchronous Isochronous USB transfer. | |
| @param UsbBus The USB bus driver. | |
| @param DevAddr The target device address. | |
| @param EpAddr The target endpoint address, with direction encoded in | |
| bit 7. | |
| @param DevSpeed The device's speed. | |
| @param MaxPacket The endpoint's max packet size. | |
| @param BufferNum The number of data buffer. | |
| @param Data Array of pointers to data buffer. | |
| @param DataLength The length of data buffer. | |
| @param Translator The transaction translator for low/full speed device. | |
| @param UsbResult The result of USB execution. | |
| @retval EFI_UNSUPPORTED The isochronous transfer isn't supported now. | |
| **/ | |
| EFI_STATUS | |
| UsbHcIsochronousTransfer ( | |
| IN USB_BUS *UsbBus, | |
| IN UINT8 DevAddr, | |
| IN UINT8 EpAddr, | |
| IN UINT8 DevSpeed, | |
| IN UINTN MaxPacket, | |
| IN UINT8 BufferNum, | |
| IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], | |
| IN UINTN DataLength, | |
| IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, | |
| OUT UINT32 *UsbResult | |
| ) | |
| { | |
| return EFI_UNSUPPORTED; | |
| } | |
| /** | |
| Queue an asynchronous isochronous transfer. | |
| @param UsbBus The USB bus driver. | |
| @param DevAddr The target device address. | |
| @param EpAddr The target endpoint address, with direction encoded in | |
| bit 7. | |
| @param DevSpeed The device's speed. | |
| @param MaxPacket The endpoint's max packet size. | |
| @param BufferNum The number of data buffer. | |
| @param Data Array of pointers to data buffer. | |
| @param DataLength The length of data buffer. | |
| @param Translator The transaction translator for low/full speed device. | |
| @param Callback The function to call when data is transferred. | |
| @param Context The context to the callback function. | |
| @retval EFI_UNSUPPORTED The asynchronous isochronous transfer isn't supported. | |
| **/ | |
| EFI_STATUS | |
| UsbHcAsyncIsochronousTransfer ( | |
| IN USB_BUS *UsbBus, | |
| IN UINT8 DevAddr, | |
| IN UINT8 EpAddr, | |
| IN UINT8 DevSpeed, | |
| IN UINTN MaxPacket, | |
| IN UINT8 BufferNum, | |
| IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], | |
| IN UINTN DataLength, | |
| IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, | |
| IN EFI_ASYNC_USB_TRANSFER_CALLBACK Callback, | |
| IN VOID *Context | |
| ) | |
| { | |
| return EFI_UNSUPPORTED; | |
| } | |
| /** | |
| Open the USB host controller protocol BY_CHILD. | |
| @param Bus The USB bus driver. | |
| @param Child The child handle. | |
| @return The open protocol return. | |
| **/ | |
| EFI_STATUS | |
| UsbOpenHostProtoByChild ( | |
| IN USB_BUS *Bus, | |
| IN EFI_HANDLE Child | |
| ) | |
| { | |
| EFI_USB_HC_PROTOCOL *UsbHc; | |
| EFI_USB2_HC_PROTOCOL *Usb2Hc; | |
| EFI_STATUS Status; | |
| if (Bus->Usb2Hc != NULL) { | |
| Status = gBS->OpenProtocol ( | |
| Bus->HostHandle, | |
| &gEfiUsb2HcProtocolGuid, | |
| (VOID **) &Usb2Hc, | |
| mUsbBusDriverBinding.DriverBindingHandle, | |
| Child, | |
| EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER | |
| ); | |
| } else { | |
| Status = gBS->OpenProtocol ( | |
| Bus->HostHandle, | |
| &gEfiUsbHcProtocolGuid, | |
| (VOID **) &UsbHc, | |
| mUsbBusDriverBinding.DriverBindingHandle, | |
| Child, | |
| EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER | |
| ); | |
| } | |
| return Status; | |
| } | |
| /** | |
| Close the USB host controller protocol BY_CHILD. | |
| @param Bus The USB bus driver. | |
| @param Child The child handle. | |
| **/ | |
| VOID | |
| UsbCloseHostProtoByChild ( | |
| IN USB_BUS *Bus, | |
| IN EFI_HANDLE Child | |
| ) | |
| { | |
| if (Bus->Usb2Hc != NULL) { | |
| gBS->CloseProtocol ( | |
| Bus->HostHandle, | |
| &gEfiUsb2HcProtocolGuid, | |
| mUsbBusDriverBinding.DriverBindingHandle, | |
| Child | |
| ); | |
| } else { | |
| gBS->CloseProtocol ( | |
| Bus->HostHandle, | |
| &gEfiUsbHcProtocolGuid, | |
| mUsbBusDriverBinding.DriverBindingHandle, | |
| Child | |
| ); | |
| } | |
| } | |
| /** | |
| return the current TPL, copied from the EDKII glue lib. | |
| @param VOID. | |
| @return Current TPL. | |
| **/ | |
| EFI_TPL | |
| UsbGetCurrentTpl ( | |
| VOID | |
| ) | |
| { | |
| EFI_TPL Tpl; | |
| Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); | |
| gBS->RestoreTPL (Tpl); | |
| 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 ( (!IsDevicePathEnd (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 ((!IsDevicePathEnd (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. | |
| @param 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 If parameters are invalid, return this value. | |
| @retval EFI_SUCCESS If Add operation is successful, return this value. | |
| **/ | |
| 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; | |
| ASSERT (IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING); | |
| 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 UsbWWIDDevicePathPtr 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. | |
| **/ | |
| 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; | |
| ASSERT (IfDesc->ActiveIndex < USB_MAX_INTERFACE_SETTING); | |
| 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) == 0)) { | |
| return TRUE; | |
| } | |
| return FALSE; | |
| } | |
| /** | |
| Free a DEVICE_PATH_LIST_ITEM list. | |
| @param UsbIoDPList a DEVICE_PATH_LIST_ITEM list pointer. | |
| @retval EFI_INVALID_PARAMETER If parameters are invalid, return this value. | |
| @retval EFI_SUCCESS If free operation is successful, return this value. | |
| **/ | |
| 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 Add operation is successful. | |
| @retval EFI_INVALID_PARAMETER The parameters are invalid. | |
| **/ | |
| 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 && !IsDevicePathEnd (RemainingDevicePath)) { | |
| 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 if (!IsDevicePathEnd (RemainingDevicePath)) { | |
| // | |
| // If RemainingDevicePath isn't the End of Device Path Node, | |
| // Create new Usb device path according to the usb part in remaining device path | |
| // | |
| DevicePathPtr = GetUsbDPFromFullDP (RemainingDevicePath); | |
| } else { | |
| // | |
| // If RemainingDevicePath is the End of Device Path Node, | |
| // skip enumerate any device and return EFI_SUCESSS | |
| // | |
| return EFI_SUCCESS; | |
| } | |
| ASSERT (DevicePathPtr != NULL); | |
| Status = AddUsbDPToList (DevicePathPtr, &Bus->WantedUsbIoDPList); | |
| ASSERT (!EFI_ERROR (Status)); | |
| 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 True If a usb child device is the wanted device in a bus. | |
| @retval False If a usb child device is *NOT* the wanted device in a bus. | |
| **/ | |
| 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 Connect is done successfully. | |
| @retval EFI_INVALID_PARAMETER The parameter is invalid. | |
| **/ | |
| 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", (UINT32)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", (UINT32)UsbGetCurrentTpl())); | |
| } | |
| } | |
| } | |
| return EFI_SUCCESS; | |
| } | |