2. update SerialNumber comparing logic to handle possible NULL-terminator in WWID device path 3. fix bug in UsbIo->UsbIoGetSupportedLanguages(): TableSize is size in bytes of LangIDTable instead of number of LangID. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11197 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1380 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1380 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
 | 
						|
    Wrapper function for usb host controller interface.
 | 
						|
 | 
						|
Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
 | 
						|
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 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                        *SnString;
 | 
						|
  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);
 | 
						|
  SnString     = (UINT16 *) ((UINT8 *)UsbWWIDDevicePathPtr + 10);
 | 
						|
 | 
						|
  //
 | 
						|
  // 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_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;
 | 
						|
}
 | 
						|
 |