gcc-11 (fedora 35): /home/kraxel/projects/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c: In function ?UsbIoBulkTransfer?: /home/kraxel/projects/edk2/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c:277:12: error: ?UsbHcBulkTransfer? accessing 80 bytes in a region of size 8 [-Werror=stringop-overflow=] Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
		
			
				
	
	
		
			1215 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1215 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
 | 
						|
    Wrapper function for usb host controller interface.
 | 
						|
 | 
						|
Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#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;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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[],
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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 addition, 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 in Device Descriptor is set to 0, the counterparts in interface should be checked.
 | 
						|
    //
 | 
						|
    if (DevDesc->DeviceClass == 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                        Index;
 | 
						|
  CHAR16                        *CompareStr;
 | 
						|
  UINTN                         CompareLen;
 | 
						|
  UINTN                         Length;
 | 
						|
 | 
						|
  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);
 | 
						|
 | 
						|
  //
 | 
						|
  // In addition, Hub interface is always matched for this policy.
 | 
						|
  //
 | 
						|
  if ((ActIfDesc->InterfaceClass == USB_HUB_CLASS_CODE) &&
 | 
						|
      (ActIfDesc->InterfaceSubClass == USB_HUB_SUBCLASS_CODE))
 | 
						|
  {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check Vendor Id, Product Id and Interface Number.
 | 
						|
  //
 | 
						|
  if ((DevDesc->IdVendor != UsbWWIDDevicePathPtr->VendorId) ||
 | 
						|
      (DevDesc->IdProduct != UsbWWIDDevicePathPtr->ProductId) ||
 | 
						|
      (ActIfDesc->InterfaceNumber != UsbWWIDDevicePathPtr->InterfaceNumber))
 | 
						|
  {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check SerialNumber.
 | 
						|
  //
 | 
						|
  if (DevDesc->StrSerialNumber == 0) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Serial number in USB WWID device path is the last 64-or-less UTF-16 characters.
 | 
						|
  //
 | 
						|
  CompareStr = (CHAR16 *)(UINTN)(UsbWWIDDevicePathPtr + 1);
 | 
						|
  CompareLen = (DevicePathNodeLength (UsbWWIDDevicePathPtr) - sizeof (USB_WWID_DEVICE_PATH)) / sizeof (CHAR16);
 | 
						|
  if (CompareStr[CompareLen - 1] == L'\0') {
 | 
						|
    CompareLen--;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Compare serial number in each supported language.
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < UsbIf->Device->TotalLangId; Index++) {
 | 
						|
    StrDesc = UsbGetOneString (UsbIf->Device, DevDesc->StrSerialNumber, UsbIf->Device->LangId[Index]);
 | 
						|
    if (StrDesc == NULL) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    Length = (StrDesc->Length - 2) / sizeof (CHAR16);
 | 
						|
    if ((Length >= CompareLen) &&
 | 
						|
        (CompareMem (StrDesc->String + Length - CompareLen, CompareStr, CompareLen * sizeof (CHAR16)) == 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_SUCCESS
 | 
						|
    //
 | 
						|
    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 interface.
 | 
						|
 | 
						|
  @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 connect 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 ((DEBUG_INFO, "UsbBusRecursivelyConnectWantedUsbIo: TPL before connect is %d\n", (UINT32)UsbGetCurrentTpl ()));
 | 
						|
        Status           = gBS->ConnectController (UsbIf->Handle, NULL, NULL, TRUE);
 | 
						|
        UsbIf->IsManaged = (BOOLEAN) !EFI_ERROR (Status);
 | 
						|
        DEBUG ((DEBUG_INFO, "UsbBusRecursivelyConnectWantedUsbIo: TPL after connect is %d\n", (UINT32)UsbGetCurrentTpl ()));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (UsbIoBuffer);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |