summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Bus/Usb
diff options
context:
space:
mode:
Diffstat (limited to 'EdkModulePkg/Bus/Usb')
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBot/Dxe/ComponentName.c190
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.mbd43
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.msa69
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c1088
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.h78
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBot/Dxe/build.xml47
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/ComponentName.c154
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.mbd44
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa76
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/build.xml47
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.c507
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.h138
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/usb.c825
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c2305
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h261
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c1176
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c556
-rw-r--r--EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.h94
-rw-r--r--EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c1042
-rw-r--r--EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/ComponentName.c192
-rw-r--r--EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.mbd43
-rw-r--r--EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.msa68
-rw-r--r--EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/build.xml47
-rw-r--r--EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.mbd43
-rw-r--r--EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.msa66
-rw-r--r--EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/build.xml47
-rw-r--r--EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/cbi1.c854
-rw-r--r--EdkModulePkg/Bus/Usb/UsbCbi/Dxe/cbi.h70
-rw-r--r--EdkModulePkg/Bus/Usb/UsbKb/Dxe/ComponentName.c215
-rw-r--r--EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.mbd44
-rw-r--r--EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.msa77
-rw-r--r--EdkModulePkg/Bus/Usb/UsbKb/Dxe/build.xml47
-rw-r--r--EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.c772
-rw-r--r--EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.h118
-rw-r--r--EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.c1150
-rw-r--r--EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.h106
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/ComponentName.c154
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.c727
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.h59
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.mbd43
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.msa70
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageData.h394
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c1653
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.h111
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/build.xml47
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMouse/Dxe/ComponentName.c216
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.mbd43
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.msa71
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMouse/Dxe/build.xml47
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.c395
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.h84
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.c1028
-rw-r--r--EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.h85
53 files changed, 17926 insertions, 0 deletions
diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/ComponentName.c
new file mode 100644
index 0000000000..6a9cf13456
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/ComponentName.c
@@ -0,0 +1,190 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "bot.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+UsbBotComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+UsbBotComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gUsbBotComponentName = {
+ UsbBotComponentNameGetDriverName,
+ UsbBotComponentNameGetControllerName,
+ "eng"
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mUsbBotDriverNameTable[] = {
+ { "eng", (CHAR16 *) L"Usb Bot Mass Storage Driver" },
+ { NULL , NULL }
+};
+
+
+EFI_STATUS
+EFIAPI
+UsbBotComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ Language - A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ DriverName - A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - DriverName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return LookupUnicodeString (
+ Language,
+ gUsbBotComponentName.SupportedLanguages,
+ mUsbBotDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UsbBotComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ ControllerHandle - The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ ChildHandle - The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ ControllerName - A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language from the point of view of the driver specified
+ by This.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - ControllerName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB_BOT_DEVICE *UsbBotDev;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapi;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbAtapiProtocolGuid,
+ (VOID **) &UsbAtapi,
+ gUsbBotDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UsbBotDev = USB_BOT_DEVICE_FROM_THIS (UsbAtapi);
+
+ return LookupUnicodeString (
+ Language,
+ gUsbBotComponentName.SupportedLanguages,
+ UsbBotDev->ControllerNameTable,
+ ControllerName
+ );
+
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.mbd b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.mbd
new file mode 100644
index 0000000000..1d18c75266
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.mbd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>UsbBot</BaseName>
+ <Guid>B40612B9-A063-11d4-9A3A-0090273FC14D</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>EdkUsbLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.msa b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.msa
new file mode 100644
index 0000000000..c00bebdce5
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.msa
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>UsbBot</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>B40612B9-A063-11d4-9A3A-0090273FC14D</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for UsbBot module</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">EdkUsbLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>bot.h</Filename>
+ <Filename>bot.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">DevicePath</Protocol>
+ <Protocol Usage="TO_START">UsbIo</Protocol>
+ <Protocol Usage="BY_START">UsbAtapi</Protocol>
+ </Protocols>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gUsbBotDriverBinding</DriverBinding>
+ <ComponentName>gUsbBotComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c
new file mode 100644
index 0000000000..0aa0507c2a
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c
@@ -0,0 +1,1088 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ BOT.c
+
+Abstract:
+
+--*/
+
+#include "bot.h"
+
+//
+// Function prototypes
+//
+EFI_STATUS
+EFIAPI
+UsbBotDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+//
+// Bot Driver Binding Protocol
+//
+EFI_STATUS
+EFIAPI
+BotDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+BotDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+BotDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+
+EFI_DRIVER_BINDING_PROTOCOL gUsbBotDriverBinding = {
+ BotDriverBindingSupported,
+ BotDriverBindingStart,
+ BotDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+//
+// Bot Protocol
+//
+STATIC
+EFI_STATUS
+BotCommandPhase (
+ IN USB_BOT_DEVICE *UsbBotDev,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ IN UINT32 DataTransferLength,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 Timeout
+ );
+
+STATIC
+EFI_STATUS
+BotDataPhase (
+ IN USB_BOT_DEVICE *UsbBotDev,
+ IN UINT32 *DataSize,
+ IN OUT VOID *DataBuffer,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 Timeout
+ );
+
+STATIC
+EFI_STATUS
+BotStatusPhase (
+ IN USB_BOT_DEVICE *UsbBotDev,
+ OUT UINT8 *TransferStatus,
+ IN UINT16 Timeout
+ );
+
+//
+// USB Atapi protocol prototype
+//
+STATIC
+EFI_STATUS
+EFIAPI
+BotAtapiCommand (
+ IN EFI_USB_ATAPI_PROTOCOL *This,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ IN VOID *DataBuffer,
+ IN UINT32 BufferLength,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 TimeOutInMilliSeconds
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+BotMassStorageReset (
+ IN EFI_USB_ATAPI_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+VOID
+BotReportStatusCode (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value
+ );
+
+STATIC EFI_USB_ATAPI_PROTOCOL BotAtapiProtocol = {
+ BotAtapiCommand,
+ BotMassStorageReset,
+ 0
+};
+
+EFI_STATUS
+EFIAPI
+BotDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ than contains a BlockIo and DiskIo protocol can be supported.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ControllerHandle - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver supports this device
+ EFI_ALREADY_STARTED - This driver is already running on this device
+ other - This driver does not support this device
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+
+ //
+ // Check if the Controller supports USB IO protocol
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get the Default interface descriptor, now we only
+ // suppose interface 1
+ //
+ Status = UsbIo->UsbGetInterfaceDescriptor (
+ UsbIo,
+ &InterfaceDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ //
+ // Check if it is a BOT type Mass Storage Device
+ //
+ if ((InterfaceDescriptor.InterfaceClass != 0x08) ||
+ (InterfaceDescriptor.InterfaceProtocol != BOT)) {
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+Exit:
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+BotDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Start this driver on ControllerHandle by opening a Block IO and Disk IO
+ protocol, reading Device Path, and creating a child handle with a
+ Disk IO and device path protocol.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ControllerHandle - Handle of device to bind driver to
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver is added to DeviceHandle
+ EFI_ALREADY_STARTED - This driver is already running on DeviceHandle
+ EFI_OUT_OF_RESOURCES- Can't allocate the memory resource
+ other - This driver does not support this device
+
+--*/
+{
+ USB_BOT_DEVICE *UsbBotDev;
+ UINT8 Index;
+ EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor;
+ EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor;
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ //
+ // Check if the Controller supports USB IO protocol
+ //
+ UsbBotDev = NULL;
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ InterfaceDescriptor = AllocateZeroPool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR));
+ if (InterfaceDescriptor == NULL) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Get the controller interface descriptor,
+ //
+ Status = UsbIo->UsbGetInterfaceDescriptor (
+ UsbIo,
+ InterfaceDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (InterfaceDescriptor);
+ goto ErrorExit;
+ }
+
+ BotAtapiProtocol.CommandProtocol = InterfaceDescriptor->InterfaceSubClass;
+
+ UsbBotDev = AllocateZeroPool (sizeof (USB_BOT_DEVICE));
+ if (UsbBotDev == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ gBS->FreePool (InterfaceDescriptor);
+ goto ErrorExit;
+ }
+
+ UsbBotDev->Signature = USB_BOT_DEVICE_SIGNATURE;
+ UsbBotDev->UsbIo = UsbIo;
+ UsbBotDev->InterfaceDescriptor = InterfaceDescriptor;
+ CopyMem (&UsbBotDev->UsbAtapiProtocol, &BotAtapiProtocol, sizeof (BotAtapiProtocol));
+
+ //
+ // Get the Device Path Protocol on Controller's handle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &UsbBotDev->DevicePath,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ for (Index = 0; Index < InterfaceDescriptor->NumEndpoints; Index++) {
+ EndpointDescriptor = AllocatePool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR));
+ if (EndpointDescriptor == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ UsbIo->UsbGetEndpointDescriptor (
+ UsbIo,
+ Index,
+ EndpointDescriptor
+ );
+
+ //
+ // We parse bulk endpoint
+ //
+ if ((EndpointDescriptor->Attributes & 0x03) == 0x02) {
+ if ((EndpointDescriptor->EndpointAddress & 0x80) != 0) {
+ UsbBotDev->BulkInEndpointDescriptor = EndpointDescriptor;
+ } else {
+ UsbBotDev->BulkOutEndpointDescriptor = EndpointDescriptor;
+ }
+
+ continue;
+ }
+
+ gBS->FreePool (EndpointDescriptor);
+ }
+ //
+ // Double check we have these endpoint descriptors
+ //
+ if (!(UsbBotDev->BulkInEndpointDescriptor &&
+ UsbBotDev->BulkOutEndpointDescriptor)) {
+ Status = EFI_DEVICE_ERROR;
+ goto ErrorExit;
+ }
+ //
+ // After installing Usb-Atapi protocol onto this handle
+ // it will be called by upper layer drivers such as Fat
+ //
+ BotReportStatusCode (
+ UsbBotDev->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE)
+ );
+
+ //
+ // Install Usb-Atapi Protocol onto the handle
+ //
+ Status = gBS->InstallProtocolInterface (
+ &ControllerHandle,
+ &gEfiUsbAtapiProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &UsbBotDev->UsbAtapiProtocol
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ UsbBotDev->ControllerNameTable = NULL;
+ AddUnicodeString (
+ "eng",
+ gUsbBotComponentName.SupportedLanguages,
+ &UsbBotDev->ControllerNameTable,
+ (CHAR16 *) L"Usb Bot Mass Storage"
+ );
+
+ return EFI_SUCCESS;
+
+ErrorExit:
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ if (UsbBotDev != NULL) {
+ if (UsbBotDev->InterfaceDescriptor != NULL) {
+ gBS->FreePool (UsbBotDev->InterfaceDescriptor);
+ }
+
+ if (UsbBotDev->BulkInEndpointDescriptor != NULL) {
+ gBS->FreePool (UsbBotDev->BulkInEndpointDescriptor);
+ }
+
+ if (UsbBotDev->BulkOutEndpointDescriptor != NULL) {
+ gBS->FreePool (UsbBotDev->BulkOutEndpointDescriptor);
+ }
+
+ gBS->FreePool (UsbBotDev);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+BotDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ControllerHandle - Handle of device to stop driver on
+ NumberOfChildren - Number of Children in the ChildHandleBuffer
+ ChildHandleBuffer - List of handles for the children we need to stop.
+
+ Returns:
+ EFI_SUCCESS - This driver is removed DeviceHandle
+ EFI_UNSUPPORTED - Can't open the gEfiUsbAtapiProtocolGuid protocl
+ other - This driver was not removed from this device
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_ATAPI_PROTOCOL *BotAtapiProtocol;
+ USB_BOT_DEVICE *UsbBotDev;
+
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ //
+ // Get our context back.
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbAtapiProtocolGuid,
+ (VOID **) &BotAtapiProtocol,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ UsbBotDev = USB_BOT_DEVICE_FROM_THIS (BotAtapiProtocol);
+
+ //
+ // After installing Usb-Atapi protocol onto this handle
+ // it will be called by upper layer drivers such as Fat
+ //
+ UsbIo = UsbBotDev->UsbIo;
+
+ BotReportStatusCode (
+ UsbBotDev->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE)
+ );
+
+ //
+ // Uninstall protocol
+ //
+ Status = gBS->UninstallProtocolInterface (
+ ControllerHandle,
+ &gEfiUsbAtapiProtocolGuid,
+ &UsbBotDev->UsbAtapiProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ //
+ // Free all allocated resources
+ //
+ if (UsbBotDev->InterfaceDescriptor != NULL) {
+ gBS->FreePool (UsbBotDev->InterfaceDescriptor);
+ }
+
+ if (UsbBotDev->BulkInEndpointDescriptor != NULL) {
+ gBS->FreePool (UsbBotDev->BulkInEndpointDescriptor);
+ }
+
+ if (UsbBotDev->BulkOutEndpointDescriptor != NULL) {
+ gBS->FreePool (UsbBotDev->BulkOutEndpointDescriptor);
+ }
+
+ if (UsbBotDev->ControllerNameTable) {
+ FreeUnicodeStringTable (UsbBotDev->ControllerNameTable);
+ }
+
+ gBS->FreePool (UsbBotDev);
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+BotRecoveryReset (
+ IN USB_BOT_DEVICE *UsbBotDev
+ )
+/*++
+
+Routine Description:
+
+ Bot reset routine
+
+Arguments:
+
+ UsbBotDev - USB_BOT_DEVICE pointer
+
+Returns:
+ EFI_SUCCESS - Success the operation
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 Result;
+ EFI_USB_DEVICE_REQUEST Request;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 EndpointAddr;
+
+ UsbIo = UsbBotDev->UsbIo;
+
+ BotReportStatusCode (
+ UsbBotDev->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET)
+ );
+
+ ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // See BOT specification
+ //
+ Request.RequestType = 0x21;
+ Request.Request = 0xFF;
+
+ Status = UsbIo->UsbControlTransfer (
+ UsbIo,
+ &Request,
+ EfiUsbNoData,
+ TIMEOUT_VALUE,
+ NULL,
+ 0,
+ &Result
+ );
+
+ gBS->Stall (100 * 1000);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // clear bulk in endpoint stall feature
+ //
+ EndpointAddr = UsbBotDev->BulkInEndpointDescriptor->EndpointAddress;
+
+ Status = UsbClearEndpointHalt (
+ UsbIo,
+ EndpointAddr,
+ &Result
+ );
+
+ //
+ // clear bulk out endpoint stall feature
+ //
+ EndpointAddr = UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress;
+ Status = UsbClearEndpointHalt (
+ UsbIo,
+ EndpointAddr,
+ &Result
+ );
+ }
+
+ return Status;
+}
+//
+// Bot Protocol Implementation
+//
+STATIC
+EFI_STATUS
+BotCommandPhase (
+ IN USB_BOT_DEVICE *UsbBotDev,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ IN UINT32 DataTransferLength,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 Timeout
+ )
+/*++
+
+ Routine Description:
+ Send ATAPI command through BOT interface.
+
+ Parameters:
+ UsbBotDev - USB_BOT_DEVICE
+ Command - command packet
+ CommandSize - Command size
+ DataTransferLength - Data Transfer Length
+ Direction - Data IN/OUT/NODATA
+ Timeout - Time out value in milliseconds
+ Return Values:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ CBW cbw;
+ EFI_STATUS Status;
+ UINT32 Result;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINTN DataSize;
+
+ UsbIo = UsbBotDev->UsbIo;
+
+ ZeroMem (&cbw, sizeof (CBW));
+
+ //
+ // Fill the command block, detailed see BOT spec
+ //
+ cbw.dCBWSignature = CBWSIG;
+ cbw.dCBWTag = 0x01;
+ cbw.dCBWDataTransferLength = DataTransferLength;
+ cbw.bmCBWFlags = (UINT8) (Direction << 7);
+ cbw.bCBWCBLength = CommandSize;
+
+ CopyMem (cbw.CBWCB, Command, CommandSize);
+
+ DataSize = sizeof (CBW);
+
+ Status = UsbIo->UsbBulkTransfer (
+ UsbIo,
+ (UsbBotDev->BulkOutEndpointDescriptor)->EndpointAddress,
+ &cbw,
+ &DataSize,
+ Timeout,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Command phase fail, we need to recovery reset this device
+ //
+ BotRecoveryReset (UsbBotDev);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+BotDataPhase (
+ IN USB_BOT_DEVICE *UsbBotDev,
+ IN UINT32 *DataSize,
+ IN OUT VOID *DataBuffer,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 Timeout
+ )
+/*++
+
+ Routine Description:
+ Get/Send Data through BOT interface
+
+ Parameters:
+ UsbBotDev - USB_BOT_DEVICE pointer
+ DataSize - Data size
+ DataBuffer - Data buffer pointer
+ Direction - IN/OUT/NODATA
+ Timeout - Time out value in milliseconds
+ Return Value:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 Result;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 EndpointAddr;
+ UINTN Remain;
+ UINTN Increment;
+ UINT32 MaxPacketLen;
+ UINT8 *BufferPtr;
+ UINTN TransferredSize;
+ UINTN RetryTimes;
+ UINTN MaxRetry;
+ UINTN BlockSize;
+ UINTN PackageNum;
+
+ UsbIo = UsbBotDev->UsbIo;
+ Remain = *DataSize;
+ BufferPtr = (UINT8 *) DataBuffer;
+ TransferredSize = 0;
+ MaxRetry = 10;
+ PackageNum = 15;
+
+ //
+ // retrieve the the max packet length of the given endpoint
+ //
+ if (Direction == EfiUsbDataIn) {
+ MaxPacketLen = (UsbBotDev->BulkInEndpointDescriptor)->MaxPacketSize;
+ EndpointAddr = (UsbBotDev->BulkInEndpointDescriptor)->EndpointAddress;
+ } else {
+ MaxPacketLen = (UsbBotDev->BulkOutEndpointDescriptor)->MaxPacketSize;
+ EndpointAddr = (UsbBotDev->BulkOutEndpointDescriptor)->EndpointAddress;
+ }
+
+ RetryTimes = MaxRetry;
+ BlockSize = PackageNum * MaxPacketLen;
+ while (Remain > 0) {
+ //
+ // Using 15 packets to aVOID Bitstuff error
+ //
+ if (Remain > PackageNum * MaxPacketLen) {
+ Increment = BlockSize;
+ } else {
+ Increment = Remain;
+ }
+
+ Status = UsbIo->UsbBulkTransfer (
+ UsbIo,
+ EndpointAddr,
+ BufferPtr,
+ &Increment,
+ Timeout,
+ &Result
+ );
+
+ TransferredSize += Increment;
+
+ if (EFI_ERROR (Status)) {
+ RetryTimes--;
+ if ((RetryTimes == 0) || ((Result & EFI_USB_ERR_TIMEOUT) == 0)) {
+ goto ErrorExit;
+ }
+
+ TransferredSize -= Increment;
+ continue;
+ } else {
+ //
+ // we try MaxTetry times for every bulk transfer
+ //
+ RetryTimes = MaxRetry;
+ }
+
+ BufferPtr += Increment;
+ Remain -= Increment;
+ if (Increment < BlockSize && TransferredSize <= *DataSize) {
+ //
+ // we get to the end of transter and transter size is
+ // less than requriedsize
+ //
+ break;
+ }
+ }
+
+ *DataSize = (UINT32) TransferredSize;
+
+ return EFI_SUCCESS;
+
+ErrorExit:
+ if (Direction == EfiUsbDataIn) {
+ BotReportStatusCode (
+ UsbBotDev->DevicePath,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR)
+ );
+ } else {
+ BotReportStatusCode (
+ UsbBotDev->DevicePath,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR)
+ );
+ }
+
+ if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
+ //
+ // just endpoint stall happens
+ //
+ UsbClearEndpointHalt (
+ UsbIo,
+ EndpointAddr,
+ &Result
+ );
+ }
+
+ *DataSize = (UINT32) TransferredSize;
+
+ return Status;
+
+}
+
+STATIC
+EFI_STATUS
+BotStatusPhase (
+ IN USB_BOT_DEVICE *UsbBotDev,
+ OUT UINT8 *TransferStatus,
+ IN UINT16 Timeout
+ )
+/*++
+
+ Routine Description:
+ Get transfer status through BOT interface
+
+ Parameters:
+ UsbBotDev - USB_BOT_DEVICE pointer
+ TransferStatus - TransferStatus
+ Timeout - Time out value in milliseconds
+ Return Value:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ CSW csw;
+ EFI_STATUS Status;
+ UINT32 Result;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 EndpointAddr;
+ UINTN DataSize;
+
+ UsbIo = UsbBotDev->UsbIo;
+
+ ZeroMem (&csw, sizeof (CSW));
+
+ EndpointAddr = (UsbBotDev->BulkInEndpointDescriptor)->EndpointAddress;
+
+ DataSize = sizeof (CSW);
+
+ //
+ // Get the status field from bulk transfer
+ //
+ Status = UsbIo->UsbBulkTransfer (
+ UsbIo,
+ EndpointAddr,
+ &csw,
+ &DataSize,
+ Timeout,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
+ //
+ // just endpoint stall happens
+ //
+ UsbClearEndpointHalt (
+ UsbIo,
+ EndpointAddr,
+ &Result
+ );
+ }
+
+ ZeroMem (&csw, sizeof (CSW));
+
+ EndpointAddr = (UsbBotDev->BulkInEndpointDescriptor)->EndpointAddress;
+
+ DataSize = sizeof (CSW);
+ Status = UsbIo->UsbBulkTransfer (
+ UsbIo,
+ EndpointAddr,
+ &csw,
+ &DataSize,
+ Timeout,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
+ UsbClearEndpointHalt (
+ UsbIo,
+ EndpointAddr,
+ &Result
+ );
+ }
+
+ return Status;
+ }
+ }
+
+ if (csw.dCSWSignature == CSWSIG) {
+ *TransferStatus = csw.bCSWStatus;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+//
+// Usb Atapi Protocol implementation
+//
+EFI_STATUS
+EFIAPI
+BotAtapiCommand (
+ IN EFI_USB_ATAPI_PROTOCOL *This,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ IN VOID *DataBuffer,
+ IN UINT32 BufferLength,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 TimeOutInMilliSeconds
+ )
+/*++
+
+ Routine Description:
+ Send ATAPI command using BOT protocol.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Command - Command buffer
+ CommandSize - Size of Command Buffer
+ DataBuffer - Data buffer
+ BufferLength - Length of Data buffer
+ Direction - Data direction of this command
+ TimeoutInMilliSeconds - Timeout value in ms
+
+ Returns:
+ EFI_SUCCESS - Command succeeded.
+ EFI_DEVICE_ERROR - Command failed.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS BotDataStatus;
+ UINT8 TransferStatus;
+ USB_BOT_DEVICE *UsbBotDev;
+ UINT32 BufferSize;
+
+ BotDataStatus = EFI_SUCCESS;
+ TransferStatus = 0;
+
+ //
+ // Get the context
+ //
+ UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This);
+
+ //
+ // First send ATAPI command through Bot
+ //
+ Status = BotCommandPhase (
+ UsbBotDev,
+ Command,
+ CommandSize,
+ BufferLength,
+ Direction,
+ TimeOutInMilliSeconds
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Send/Get Data if there is a Data Stage
+ //
+ switch (Direction) {
+
+ case EfiUsbDataIn:
+ case EfiUsbDataOut:
+ BufferSize = BufferLength;
+
+ BotDataStatus = BotDataPhase (
+ UsbBotDev,
+ &BufferSize,
+ DataBuffer,
+ Direction,
+ (UINT16) (TimeOutInMilliSeconds)
+ );
+
+ break;
+
+ case EfiUsbNoData:
+ break;
+ }
+
+ //
+ // Status Phase
+ //
+ Status = BotStatusPhase (
+ UsbBotDev,
+ &TransferStatus,
+ TimeOutInMilliSeconds
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (TransferStatus == 0x02) {
+ //
+ // Phase error
+ //
+ BotRecoveryReset (UsbBotDev);
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (TransferStatus == 0x01) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return BotDataStatus;
+}
+
+EFI_STATUS
+EFIAPI
+BotMassStorageReset (
+ IN EFI_USB_ATAPI_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+ Routine Description:
+ Reset Bot Devices
+
+ Arguments:
+ This - Protocol instance pointer.
+ ExtendedVerification - TRUE if we need to do strictly reset.
+
+ Returns:
+ EFI_SUCCESS - Command succeeded.
+ EFI_DEVICE_ERROR - Command failed.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB_BOT_DEVICE *UsbBotDev;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This);
+ UsbIo = UsbBotDev->UsbIo;
+
+ if (ExtendedVerification) {
+ //
+ // If we need to do strictly reset, reset its parent hub port
+ //
+ Status = UsbIo->UsbPortReset (UsbIo);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Status = BotRecoveryReset (UsbBotDev);
+
+ return Status;
+}
+
+VOID
+BotReportStatusCode (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value
+ )
+/*++
+
+ Routine Description:
+ Report Status Code in Usb Bot Driver
+
+ Arguments:
+ DevicePath - Use this to get Device Path
+ CodeType - Status Code Type
+ CodeValue - Status Code Value
+
+ Returns:
+ None
+
+--*/
+{
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ CodeType,
+ Value,
+ DevicePath
+ );
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.h b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.h
new file mode 100644
index 0000000000..575dfbea05
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.h
@@ -0,0 +1,78 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ BOT.h
+
+Abstract:
+
+--*/
+
+#ifndef _BOT_H
+#define _BOT_H
+
+
+#include <IndustryStandard/usb.h>
+
+#pragma pack(1)
+//
+// Bulk Only device protocol
+//
+typedef struct {
+ UINT32 dCBWSignature;
+ UINT32 dCBWTag;
+ UINT32 dCBWDataTransferLength;
+ UINT8 bmCBWFlags;
+ UINT8 bCBWLUN;
+ UINT8 bCBWCBLength;
+ UINT8 CBWCB[16];
+} CBW;
+
+typedef struct {
+ UINT32 dCSWSignature;
+ UINT32 dCSWTag;
+ UINT32 dCSWDataResidue;
+ UINT8 bCSWStatus;
+} CSW;
+
+#pragma pack()
+
+#define USB_BOT_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('u', 'b', 'o', 't')
+
+typedef struct {
+ UINTN Signature;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_USB_ATAPI_PROTOCOL UsbAtapiProtocol;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor;
+ EFI_USB_ENDPOINT_DESCRIPTOR *BulkInEndpointDescriptor;
+ EFI_USB_ENDPOINT_DESCRIPTOR *BulkOutEndpointDescriptor;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+} USB_BOT_DEVICE;
+
+#define USB_BOT_DEVICE_FROM_THIS(a) \
+ CR(a, USB_BOT_DEVICE, UsbAtapiProtocol, USB_BOT_DEVICE_SIGNATURE)
+
+//
+// Status code, see Usb Bot device spec
+//
+#define CSWSIG 0x53425355
+#define CBWSIG 0x43425355
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gUsbBotDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gUsbBotComponentName;
+extern EFI_GUID gUsbBotDriverGuid;
+
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/build.xml b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/build.xml
new file mode 100644
index 0000000000..aab054b222
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
+<project basedir="." default="UsbBot"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Usb\UsbBot\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="UsbBot">
+ <GenBuild baseName="UsbBot" mbdFilename="${MODULE_DIR}\UsbBot.mbd" msaFilename="${MODULE_DIR}\UsbBot.msa"/>
+ </target>
+ <target depends="UsbBot_clean" name="clean"/>
+ <target depends="UsbBot_cleanall" name="cleanall"/>
+ <target name="UsbBot_clean">
+ <OutputDirSetup baseName="UsbBot" mbdFilename="${MODULE_DIR}\UsbBot.mbd" msaFilename="${MODULE_DIR}\UsbBot.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbBot_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbBot_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="UsbBot_cleanall">
+ <OutputDirSetup baseName="UsbBot" mbdFilename="${MODULE_DIR}\UsbBot.mbd" msaFilename="${MODULE_DIR}\UsbBot.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbBot_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbBot_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**UsbBot*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/ComponentName.c
new file mode 100644
index 0000000000..347a0003f4
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/ComponentName.c
@@ -0,0 +1,154 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "UsbBus.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+UsbBusComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+UsbBusComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle, OPTIONAL
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gUsbBusComponentName = {
+ UsbBusComponentNameGetDriverName,
+ UsbBusComponentNameGetControllerName,
+ "eng"
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mUsbBusDriverNameTable[] = {
+ { "eng", (CHAR16 *) L"USB Bus Driver" },
+ { NULL , NULL }
+};
+
+EFI_STATUS
+EFIAPI
+UsbBusComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ Language - A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ DriverName - A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - DriverName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return LookupUnicodeString (
+ Language,
+ gUsbBusComponentName.SupportedLanguages,
+ mUsbBusDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UsbBusComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle, OPTIONAL
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ ControllerHandle - The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ ChildHandle - The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ ControllerName - A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language from the point of view of the driver specified
+ by This.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - ControllerName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.mbd b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.mbd
new file mode 100644
index 0000000000..4e46c13f97
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.mbd
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>UsbBus</BaseName>
+ <Guid>240612B7-A063-11d4-9A3A-0090273FC14D</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>EdkUsbLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ <Library>UefiDevicePathLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa
new file mode 100644
index 0000000000..f035473c61
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>UsbBus</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>240612B7-A063-11d4-9A3A-0090273FC14D</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for UsbBus module</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">EdkUsbLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DevicePathLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>UsbBus.h</Filename>
+ <Filename>usbutil.h</Filename>
+ <Filename>hub.h</Filename>
+ <Filename>UsbBus.c</Filename>
+ <Filename>UsbIo.c</Filename>
+ <Filename>usb.c</Filename>
+ <Filename>usbutil.c</Filename>
+ <Filename>Hub.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="BY_START">UsbIo</Protocol>
+ <Protocol Usage="TO_START">UsbHc</Protocol>
+ <Protocol Usage="TO_START">DevicePath</Protocol>
+ </Protocols>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gUsbBusDriverBinding</DriverBinding>
+ <ComponentName>gUsbBusComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/build.xml b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/build.xml
new file mode 100644
index 0000000000..508c7582b3
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
+<project basedir="." default="UsbBus"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Usb\UsbBus\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="UsbBus">
+ <GenBuild baseName="UsbBus" mbdFilename="${MODULE_DIR}\UsbBus.mbd" msaFilename="${MODULE_DIR}\UsbBus.msa"/>
+ </target>
+ <target depends="UsbBus_clean" name="clean"/>
+ <target depends="UsbBus_cleanall" name="cleanall"/>
+ <target name="UsbBus_clean">
+ <OutputDirSetup baseName="UsbBus" mbdFilename="${MODULE_DIR}\UsbBus.mbd" msaFilename="${MODULE_DIR}\UsbBus.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbBus_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbBus_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="UsbBus_cleanall">
+ <OutputDirSetup baseName="UsbBus" mbdFilename="${MODULE_DIR}\UsbBus.mbd" msaFilename="${MODULE_DIR}\UsbBus.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbBus_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbBus_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**UsbBus*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.c
new file mode 100644
index 0000000000..fd9e673b6c
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.c
@@ -0,0 +1,507 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name:
+
+ Hub.c
+
+ Abstract:
+
+ Usb Hub Request
+
+ Revision History
+
+--*/
+
+#include "usbbus.h"
+
+EFI_STATUS
+HubGetPortStatus (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Port,
+ OUT UINT32 *PortStatus
+ )
+/*++
+
+ Routine Description:
+ Get a given hub port status
+
+ Arguments:
+ UsbIo - EFI_USB_IO_PROTOCOL instance
+ Port - Usb hub port number (starting from 1).
+ PortStatus - Current Hub port status and change status.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE
+ EFI_TIME_OUT
+ EFI_INVALID_PARAMETER
+
+--*/
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS EfiStatus;
+ UINT32 UsbStatus;
+ UINT32 Timeout;
+
+ ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = HUB_GET_PORT_STATUS_REQ_TYPE;
+ DevReq.Request = HUB_GET_PORT_STATUS;
+ DevReq.Value = 0;
+ DevReq.Index = Port;
+ DevReq.Length = sizeof (UINT32);
+
+ Timeout = 3000;
+
+ EfiStatus = UsbIo->UsbControlTransfer (
+ UsbIo,
+ &DevReq,
+ EfiUsbDataIn,
+ Timeout,
+ PortStatus,
+ sizeof (UINT32),
+ &UsbStatus
+ );
+
+ return EfiStatus;
+}
+
+EFI_STATUS
+HubSetPortFeature (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Port,
+ IN UINT8 Value
+ )
+/*++
+
+ Routine Description:
+ Set specified feature to a give hub port
+
+ Arguments:
+ UsbIo - EFI_USB_IO_PROTOCOL instance
+ Port - Usb hub port number (starting from 1).
+ Value - New feature value.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE
+ EFI_TIME_OUT
+ EFI_INVALID_PARAMETER
+
+--*/
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS EfiStatus;
+ UINT32 UsbStatus;
+ UINT32 Timeout;
+
+ ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = HUB_SET_PORT_FEATURE_REQ_TYPE;
+ DevReq.Request = HUB_SET_PORT_FEATURE;
+ DevReq.Value = Value;
+ DevReq.Index = Port;
+ DevReq.Length = 0;
+
+ Timeout = 3000;
+ EfiStatus = UsbIo->UsbControlTransfer (
+ UsbIo,
+ &DevReq,
+ EfiUsbNoData,
+ Timeout,
+ NULL,
+ 0,
+ &UsbStatus
+ );
+
+ return EfiStatus;
+}
+
+EFI_STATUS
+HubClearPortFeature (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Port,
+ IN UINT8 Value
+ )
+/*++
+
+ Routine Description:
+ Clear a specified feature of a given hub port
+
+ Arguments:
+ UsbIo - EFI_USB_IO_PROTOCOL instance
+ Port - Usb hub port number (starting from 1).
+ Value - Feature value that will be cleared from
+ that hub port.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE
+ EFI_TIME_OUT
+ EFI_INVALID_PARAMETER
+
+--*/
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS EfiStatus;
+ UINT32 UsbStatus;
+ UINT32 Timeout;
+
+ ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = HUB_CLEAR_FEATURE_PORT_REQ_TYPE;
+ DevReq.Request = HUB_CLEAR_FEATURE_PORT;
+ DevReq.Value = Value;
+ DevReq.Index = Port;
+ DevReq.Length = 0;
+
+ Timeout = 3000;
+ EfiStatus = UsbIo->UsbControlTransfer (
+ UsbIo,
+ &DevReq,
+ EfiUsbNoData,
+ Timeout,
+ NULL,
+ 0,
+ &UsbStatus
+ );
+
+ return EfiStatus;
+}
+
+EFI_STATUS
+HubGetHubStatus (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ OUT UINT32 *HubStatus
+ )
+/*++
+
+ Routine Description:
+ Get Hub Status
+
+ Arguments:
+ UsbIo - EFI_USB_IO_PROTOCOL instance
+ HubStatus - Current Hub status and change status.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE
+ EFI_TIME_OUT
+
+--*/
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS EfiStatus;
+ UINT32 UsbStatus;
+ UINT32 Timeout;
+
+ ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = HUB_GET_HUB_STATUS_REQ_TYPE;
+ DevReq.Request = HUB_GET_HUB_STATUS;
+ DevReq.Value = 0;
+ DevReq.Index = 0;
+ DevReq.Length = sizeof (UINT32);
+
+ Timeout = 3000;
+ EfiStatus = UsbIo->UsbControlTransfer (
+ UsbIo,
+ &DevReq,
+ EfiUsbDataIn,
+ Timeout,
+ HubStatus,
+ sizeof (UINT32),
+ &UsbStatus
+ );
+
+ return EfiStatus;
+}
+
+EFI_STATUS
+HubSetHubFeature (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Value
+ )
+/*++
+
+ Routine Description:
+ Set a specified feature to the hub
+
+ Arguments:
+ UsbIo - EFI_USB_IO_PROTOCOL instance
+ Value - Feature value that will be set to the hub.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE
+ EFI_TIME_OUT
+
+--*/
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS EfiStatus;
+ UINT32 UsbStatus;
+ UINT32 Timeout;
+
+ ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = HUB_SET_HUB_FEATURE_REQ_TYPE;
+ DevReq.Request = HUB_SET_HUB_FEATURE;
+ DevReq.Value = Value;
+ DevReq.Index = 0;
+ DevReq.Length = 0;
+
+ Timeout = 3000;
+ EfiStatus = UsbIo->UsbControlTransfer (
+ UsbIo,
+ &DevReq,
+ EfiUsbNoData,
+ Timeout,
+ NULL,
+ 0,
+ &UsbStatus
+ );
+
+ return EfiStatus;
+}
+
+EFI_STATUS
+HubClearHubFeature (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Value
+ )
+/*++
+
+ Routine Description:
+ Set a specified feature to the hub
+
+ Arguments:
+ UsbIo - EFI_USB_IO_PROTOCOL instance
+ Value - Feature value that will be cleared from the hub.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE
+ EFI_TIME_OUT
+
+--*/
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS EfiStatus;
+ UINT32 UsbStatus;
+ UINT32 Timeout;
+
+ ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = HUB_CLEAR_FEATURE_REQ_TYPE;
+ DevReq.Request = HUB_CLEAR_FEATURE;
+ DevReq.Value = Value;
+ DevReq.Index = 0;
+ DevReq.Length = 0;
+
+ Timeout = 3000;
+ EfiStatus = UsbIo->UsbControlTransfer (
+ UsbIo,
+ &DevReq,
+ EfiUsbNoData,
+ Timeout,
+ NULL,
+ 0,
+ &UsbStatus
+ );
+
+ return EfiStatus;
+
+}
+
+EFI_STATUS
+GetHubDescriptor (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINTN DescriptorSize,
+ OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor
+ )
+/*++
+
+ Routine Description:
+ Get the hub descriptor
+
+ Arguments:
+ UsbIo - EFI_USB_IO_PROTOCOL instance
+ DescriptorSize - The length of Hub Descriptor buffer.
+ HubDescriptor - Caller allocated buffer to store the hub descriptor
+ if successfully returned.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE
+ EFI_TIME_OUT
+
+--*/
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+ EFI_STATUS EfiStatus;
+ UINT32 UsbStatus;
+ UINT32 Timeout;
+
+ ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Fill Device request packet
+ //
+ DevReq.RequestType = USB_RT_HUB | 0x80;
+ DevReq.Request = HUB_GET_DESCRIPTOR;
+ DevReq.Value = USB_DT_HUB << 8;
+ DevReq.Index = 0;
+ DevReq.Length = (UINT16) DescriptorSize;
+
+ Timeout = 3000;
+ EfiStatus = UsbIo->UsbControlTransfer (
+ UsbIo,
+ &DevReq,
+ EfiUsbDataIn,
+ Timeout,
+ HubDescriptor,
+ (UINT16) DescriptorSize,
+ &UsbStatus
+ );
+
+ return EfiStatus;
+
+}
+
+EFI_STATUS
+DoHubConfig (
+ IN USB_IO_CONTROLLER_DEVICE *HubController
+ )
+/*++
+
+ Routine Description:
+ Configure the hub
+
+ Arguments:
+ HubController - Indicating the hub controller device that
+ will be configured
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_HUB_DESCRIPTOR HubDescriptor;
+ EFI_STATUS Status;
+ EFI_USB_HUB_STATUS HubStatus;
+ UINTN Index;
+ UINT32 PortStatus;
+
+ UsbIo = &HubController->UsbIo;
+
+ ZeroMem (&HubDescriptor, sizeof (HubDescriptor));
+
+ //
+ // First get the hub descriptor length
+ //
+ Status = GetHubDescriptor (UsbIo, 2, &HubDescriptor);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // First get the whole descriptor, then
+ // get the number of hub ports
+ //
+ Status = GetHubDescriptor (
+ UsbIo,
+ HubDescriptor.Length,
+ &HubDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gUSBErrorLevel, "Get hub descriptor fail\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ HubController->DownstreamPorts = HubDescriptor.NbrPorts;
+
+ Status = HubGetHubStatus (UsbIo, (UINT32 *) &HubStatus);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gUSBErrorLevel, "Get hub status fail when configure\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get all hub ports status
+ //
+ for (Index = 0; Index < HubController->DownstreamPorts; Index++) {
+
+ Status = HubGetPortStatus (UsbIo, (UINT8) (Index + 1), &PortStatus);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ }
+ //
+ // Power all the hub ports
+ //
+ for (Index = 0; Index < HubController->DownstreamPorts; Index++) {
+ Status = HubSetPortFeature (
+ UsbIo,
+ (UINT8) (Index + 1),
+ EfiUsbPortPower
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ }
+
+ //
+ // Clear Hub Status Change
+ //
+ Status = HubGetHubStatus (UsbIo, (UINT32 *) &HubStatus);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((gUSBErrorLevel, "Get hub status fail\n"));
+ return EFI_DEVICE_ERROR;
+ } else {
+ //
+ // Hub power supply change happens
+ //
+ if (HubStatus.HubChange & HUB_CHANGE_LOCAL_POWER) {
+ HubClearHubFeature (UsbIo, C_HUB_LOCAL_POWER);
+ }
+ //
+ // Hub change overcurrent happens
+ //
+ if (HubStatus.HubChange & HUB_CHANGE_OVERCURRENT) {
+ HubClearHubFeature (UsbIo, C_HUB_OVER_CURRENT);
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.h b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.h
new file mode 100644
index 0000000000..4545d71c6a
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.h
@@ -0,0 +1,138 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name:
+
+ Hub.h
+
+ Abstract:
+
+ Constants definitions for Usb Hub
+
+ Revision History
+
+--*/
+
+#ifndef _HUB_H
+#define _HUB_H
+
+//
+// Hub feature numbers
+//
+#define C_HUB_LOCAL_POWER 0
+#define C_HUB_OVER_CURRENT 1
+
+//
+// Hub class code & sub class code
+//
+#define CLASS_CODE_HUB 0x09
+#define SUB_CLASS_CODE_HUB 0
+
+//
+// Hub Status & Hub Change bit masks
+//
+#define HUB_STATUS_LOCAL_POWER 0x0001
+#define HUB_STATUS_OVERCURRENT 0x0002
+
+#define HUB_CHANGE_LOCAL_POWER 0x0001
+#define HUB_CHANGE_OVERCURRENT 0x0002
+
+//
+// Hub Characteristics
+//
+#define HUB_CHAR_LPSM 0x0003
+#define HUB_CHAR_COMPOUND 0x0004
+#define HUB_CHAR_OCPM 0x0018
+
+//
+// Hub specific request
+//
+#define HUB_CLEAR_FEATURE 0x01
+#define HUB_CLEAR_FEATURE_REQ_TYPE 0x20
+
+#define HUB_CLEAR_FEATURE_PORT 0x01
+#define HUB_CLEAR_FEATURE_PORT_REQ_TYPE 0x23
+
+#define HUB_GET_BUS_STATE 0x02
+#define HUB_GET_BUS_STATE_REQ_TYPE 0xA3
+
+#define HUB_GET_DESCRIPTOR 0x06
+#define HUB_GET_DESCRIPTOR_REQ_TYPE 0xA0
+
+#define HUB_GET_HUB_STATUS 0x00
+#define HUB_GET_HUB_STATUS_REQ_TYPE 0xA0
+
+#define HUB_GET_PORT_STATUS 0x00
+#define HUB_GET_PORT_STATUS_REQ_TYPE 0xA3
+
+#define HUB_SET_DESCRIPTOR 0x07
+#define HUB_SET_DESCRIPTOR_REQ_TYPE 0x20
+
+#define HUB_SET_HUB_FEATURE 0x03
+#define HUB_SET_HUB_FEATURE_REQ_TYPE 0x20
+
+#define HUB_SET_PORT_FEATURE 0x03
+#define HUB_SET_PORT_FEATURE_REQ_TYPE 0x23
+
+#pragma pack(1)
+typedef struct usb_hub_status {
+ UINT16 HubStatus;
+ UINT16 HubChange;
+} EFI_USB_HUB_STATUS;
+#pragma pack()
+
+EFI_STATUS
+HubGetPortStatus (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Port,
+ OUT UINT32 *PortStatus
+ );
+
+EFI_STATUS
+HubSetPortFeature (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Port,
+ IN UINT8 Value
+ );
+
+EFI_STATUS
+HubSetHubFeature (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Value
+ );
+
+EFI_STATUS
+HubGetHubStatus (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ OUT UINT32 *HubStatus
+ );
+
+EFI_STATUS
+HubClearPortFeature (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Port,
+ IN UINT8 Value
+ );
+
+EFI_STATUS
+HubClearHubFeature (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 Value
+ );
+
+EFI_STATUS
+GetHubDescriptor (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINTN DescriptorSize,
+ OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor
+ );
+
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usb.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usb.c
new file mode 100644
index 0000000000..474e38829e
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usb.c
@@ -0,0 +1,825 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name:
+
+ Usb.c
+
+ Abstract:
+
+ Parse usb device configurations.
+
+ Revision History
+
+--*/
+
+#include "usbbus.h"
+
+//
+// Here are some internal helper functions
+//
+STATIC
+EFI_STATUS
+GetExpectedDescriptor (
+ IN UINT8 *Buffer,
+ IN UINTN Length,
+ IN UINT8 DescType,
+ IN UINT8 DescLength,
+ OUT UINTN *ParsedBytes
+ );
+
+STATIC
+EFI_STATUS
+ParseThisEndpoint (
+ IN ENDPOINT_DESC_LIST_ENTRY *EndpointEntry,
+ IN UINT8 *Buffer,
+ IN UINTN BufferLength,
+ OUT UINTN *ParsedBytes
+ );
+
+STATIC
+EFI_STATUS
+ParseThisInterface (
+ IN INTERFACE_DESC_LIST_ENTRY *InterfaceEntry,
+ IN UINT8 *Buffer,
+ IN UINTN *BufferLen,
+ OUT UINTN *ParsedBytes
+ );
+
+STATIC
+EFI_STATUS
+ParseThisConfig (
+ IN CONFIG_DESC_LIST_ENTRY *ConfigDescEntry,
+ IN UINT8 *Buffer,
+ IN UINTN Length
+ );
+
+//
+// Implementations
+//
+BOOLEAN
+IsHub (
+ IN USB_IO_CONTROLLER_DEVICE *Dev
+ )
+/*++
+
+ Routine Description:
+ Tell if a usb controller is a hub controller.
+
+ Arguments:
+ Dev - UsbIoController device structure.
+
+ Returns:
+ TRUE/FALSE
+--*/
+{
+ EFI_USB_INTERFACE_DESCRIPTOR Interface;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+ UINT8 Index;
+
+ if (Dev == NULL) {
+ return FALSE;
+ }
+
+ UsbIo = &Dev->UsbIo;
+
+ UsbIo->UsbGetInterfaceDescriptor (
+ UsbIo,
+ &Interface
+ );
+
+ //
+ // Check classcode
+ //
+ if (Interface.InterfaceClass != 0x09) {
+ return FALSE;
+ }
+
+ //
+ // Check protocol
+ //
+ if (Interface.InterfaceProtocol != 0x0) {
+ return FALSE;
+ }
+
+ for (Index = 0; Index < Interface.NumEndpoints; Index++) {
+ UsbIo->UsbGetEndpointDescriptor (
+ UsbIo,
+ Index,
+ &EndpointDescriptor
+ );
+
+ if ((EndpointDescriptor.EndpointAddress & 0x80) == 0) {
+ continue;
+ }
+
+ if (EndpointDescriptor.Attributes != 0x03) {
+ continue;
+ }
+
+ Dev->HubEndpointAddress = EndpointDescriptor.EndpointAddress;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+UsbGetStringtable (
+ IN USB_IO_DEVICE *Dev
+ )
+/*++
+
+ Routine Description:
+ Get the string table stored in a usb device.
+
+ Arguments:
+ Dev - UsbIoController device structure.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_UNSUPPORTED
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ EFI_STATUS Result;
+ UINT32 Status;
+ EFI_USB_SUPPORTED_LANGUAGES *LanguageTable;
+ UINT8 *Buffer;
+ UINT8 *ptr;
+ UINTN Index;
+ UINTN LangTableSize;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT16 TempBuffer;
+
+ UsbIo = &(Dev->UsbController[0]->UsbIo);
+
+ //
+ // We get first 2 byte of langID table,
+ // so we can have the whole table length
+ //
+ Result = UsbGetString (
+ UsbIo,
+ 0,
+ 0,
+ &TempBuffer,
+ 2,
+ &Status
+ );
+ if (EFI_ERROR (Result)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ LanguageTable = (EFI_USB_SUPPORTED_LANGUAGES *) &TempBuffer;
+
+ if (LanguageTable->Length == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // If length is 2, then there is no string table
+ //
+ if (LanguageTable->Length == 2) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Buffer = AllocateZeroPool (LanguageTable->Length);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Now we get the whole LangID table
+ //
+ Result = UsbGetString (
+ UsbIo,
+ 0,
+ 0,
+ Buffer,
+ LanguageTable->Length,
+ &Status
+ );
+ if (EFI_ERROR (Result)) {
+ gBS->FreePool (Buffer);
+ return EFI_UNSUPPORTED;
+ }
+
+ LanguageTable = (EFI_USB_SUPPORTED_LANGUAGES *) Buffer;
+
+ //
+ // ptr point to the LangID table
+ //
+ ptr = Buffer + 2;
+ LangTableSize = (LanguageTable->Length - 2) / 2;
+
+ for (Index = 0; Index < LangTableSize && Index < USB_MAXLANID; Index++) {
+ Dev->LangID[Index] = *((UINT16 *) ptr);
+ ptr += 2;
+ }
+
+ gBS->FreePool (Buffer);
+ LanguageTable = NULL;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+UsbGetAllConfigurations (
+ IN USB_IO_DEVICE *UsbIoDevice
+ )
+/*++
+
+ Routine Description:
+ This function is to parse all the configuration descriptor.
+
+ Arguments:
+ UsbIoDevice - USB_IO_DEVICE device structure.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ EFI_STATUS Result;
+ UINT32 Status;
+ UINTN Index;
+ UINTN TotalLength;
+ UINT8 *Buffer;
+ CONFIG_DESC_LIST_ENTRY *ConfigDescEntry;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ InitializeListHead (&UsbIoDevice->ConfigDescListHead);
+ UsbIo = &(UsbIoDevice->UsbController[0]->UsbIo);
+
+ for (Index = 0; Index < UsbIoDevice->DeviceDescriptor.NumConfigurations; Index++) {
+ ConfigDescEntry = NULL;
+
+ ConfigDescEntry = AllocateZeroPool (sizeof (CONFIG_DESC_LIST_ENTRY));
+ if (ConfigDescEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // 1st only get 1st 4 bytes config descriptor,
+ // so we can know the whole length
+ //
+ Result = UsbGetDescriptor (
+ UsbIo,
+ (UINT16) ((USB_DT_CONFIG << 8) | Index),
+ 0,
+ 4,
+ &ConfigDescEntry->CongfigDescriptor,
+ &Status
+ );
+ if (EFI_ERROR (Result)) {
+ DEBUG ((gUSBErrorLevel, "First get config descriptor error\n"));
+ gBS->FreePool (ConfigDescEntry);
+ return EFI_DEVICE_ERROR;
+ }
+
+ TotalLength = ConfigDescEntry->CongfigDescriptor.TotalLength;
+
+ Buffer = AllocateZeroPool (TotalLength);
+ if (Buffer == NULL) {
+ gBS->FreePool (ConfigDescEntry);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Then we get the total descriptors for this configuration
+ //
+ Result = UsbGetDescriptor (
+ UsbIo,
+ (UINT16) ((USB_DT_CONFIG << 8) | Index),
+ 0,
+ (UINT16) TotalLength,
+ Buffer,
+ &Status
+ );
+ if (EFI_ERROR (Result)) {
+ DEBUG ((gUSBErrorLevel, "Get whole config descriptor error\n"));
+ gBS->FreePool (ConfigDescEntry);
+ gBS->FreePool (Buffer);
+ return EFI_DEVICE_ERROR;
+ }
+
+ InitializeListHead (&ConfigDescEntry->InterfaceDescListHead);
+
+ //
+ // Parse this whole configuration
+ //
+ Result = ParseThisConfig (ConfigDescEntry, Buffer, TotalLength);
+
+ if (EFI_ERROR (Result)) {
+ //
+ // Ignore this configuration, parse next one
+ //
+ gBS->FreePool (ConfigDescEntry);
+ gBS->FreePool (Buffer);
+ continue;
+ }
+
+ InsertTailList (&UsbIoDevice->ConfigDescListHead, &ConfigDescEntry->Link);
+
+ gBS->FreePool (Buffer);
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+GetExpectedDescriptor (
+ IN UINT8 *Buffer,
+ IN UINTN Length,
+ IN UINT8 DescType,
+ IN UINT8 DescLength,
+ OUT UINTN *ParsedBytes
+ )
+/*++
+
+ Routine Description:
+ Get the start position of next wanted descriptor.
+
+ Arguments:
+ Buffer - Buffer to parse
+ Length - Buffer length
+ DescType - Descriptor type
+ DescLength - Descriptor length
+ ParsedBytes - Parsed Bytes to return
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ UINT16 DescriptorHeader;
+ UINT8 Len;
+ UINT8 *ptr;
+ UINTN Parsed;
+
+ Parsed = 0;
+ ptr = Buffer;
+
+ while (TRUE) {
+ //
+ // Buffer length should not less than Desc length
+ //
+ if (Length < DescLength) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // DescriptorHeader = *((UINT16 *)ptr), compatible with IPF
+ //
+ DescriptorHeader = (UINT16) ((*(ptr + 1) << 8) | *ptr);
+
+ Len = ptr[0];
+
+ //
+ // Check to see if it is a start of expected descriptor
+ //
+ if (DescriptorHeader == ((DescType << 8) | DescLength)) {
+ break;
+ }
+
+ if ((UINT8) (DescriptorHeader >> 8) == DescType) {
+ if (Len > DescLength) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // Descriptor length should be at least 2
+ // and should not exceed the buffer length
+ //
+ if (Len < 2) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (Len > Length) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Skip this mismatch descriptor
+ //
+ Length -= Len;
+ ptr += Len;
+ Parsed += Len;
+ }
+
+ *ParsedBytes = Parsed;
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS
+ParseThisEndpoint (
+ IN ENDPOINT_DESC_LIST_ENTRY *EndpointEntry,
+ IN UINT8 *Buffer,
+ IN UINTN BufferLength,
+ OUT UINTN *ParsedBytes
+ )
+/*++
+
+ Routine Description:
+ Get the start position of next wanted endpoint descriptor.
+
+ Arguments:
+ EndpointEntry - ENDPOINT_DESC_LIST_ENTRY
+ Buffer - Buffer to parse
+ BufferLength - Buffer Length
+ ParsedBytes - Parsed Bytes to return
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ UINT8 *ptr;
+ EFI_STATUS Status;
+ UINTN SkipBytes;
+
+ //
+ // Skip some data for this interface
+ //
+ Status = GetExpectedDescriptor (
+ Buffer,
+ BufferLength,
+ USB_DT_ENDPOINT,
+ sizeof (EFI_USB_ENDPOINT_DESCRIPTOR),
+ &SkipBytes
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ptr = Buffer + SkipBytes;
+ *ParsedBytes = SkipBytes;
+
+ CopyMem (
+ &EndpointEntry->EndpointDescriptor,
+ ptr,
+ sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)
+ );
+
+ *ParsedBytes += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR);
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+ParseThisInterface (
+ IN INTERFACE_DESC_LIST_ENTRY *InterfaceEntry,
+ IN UINT8 *Buffer,
+ IN UINTN *BufferLen,
+ OUT UINTN *ParsedBytes
+ )
+/*++
+
+ Routine Description:
+ Get the start position of next wanted interface descriptor.
+
+ Arguments:
+ InterfaceEntry - INTERFACE_DESC_LIST_ENTRY
+ Buffer - Buffer to parse
+ BufferLength - Buffer Length
+ ParsedBytes - Parsed Bytes to return
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ UINT8 *ptr;
+ UINTN SkipBytes;
+ UINTN Index;
+ UINTN Length;
+ UINTN Parsed;
+ ENDPOINT_DESC_LIST_ENTRY *EndpointEntry;
+ EFI_STATUS Status;
+
+ Parsed = 0;
+
+ //
+ // Skip some data for this interface
+ //
+ Status = GetExpectedDescriptor (
+ Buffer,
+ *BufferLen,
+ USB_DT_INTERFACE,
+ sizeof (EFI_USB_INTERFACE_DESCRIPTOR),
+ &SkipBytes
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ptr = Buffer + SkipBytes;
+ *ParsedBytes = SkipBytes;
+
+ //
+ // Copy the interface descriptor
+ //
+ CopyMem (
+ &InterfaceEntry->InterfaceDescriptor,
+ ptr,
+ sizeof (EFI_USB_INTERFACE_DESCRIPTOR)
+ );
+
+ ptr = Buffer + sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
+ *ParsedBytes += sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
+
+ InitializeListHead (&InterfaceEntry->EndpointDescListHead);
+
+ Length = *BufferLen - SkipBytes - sizeof (EFI_USB_INTERFACE_DESCRIPTOR);
+
+ for (Index = 0; Index < InterfaceEntry->InterfaceDescriptor.NumEndpoints; Index++) {
+ EndpointEntry = AllocateZeroPool (sizeof (ENDPOINT_DESC_LIST_ENTRY));
+ if (EndpointEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Parses all the endpoint descriptors within this interface.
+ //
+ Status = ParseThisEndpoint (EndpointEntry, ptr, Length, &Parsed);
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (EndpointEntry);
+ return Status;
+ }
+
+ InsertTailList (
+ &InterfaceEntry->EndpointDescListHead,
+ &EndpointEntry->Link
+ );
+
+ Length -= Parsed;
+ ptr += Parsed;
+ *ParsedBytes += Parsed;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+ParseThisConfig (
+ IN CONFIG_DESC_LIST_ENTRY *ConfigDescEntry,
+ IN UINT8 *Buffer,
+ IN UINTN Length
+ )
+/*++
+
+ Routine Description:
+ Parse the current configuration descriptior.
+
+ Arguments:
+ ConfigDescEntry - CONFIG_DESC_LIST_ENTRY
+ Buffer - Buffer to parse
+ Length - Buffer Length
+
+ Returns
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ UINT8 *ptr;
+ UINT8 NumInterface;
+ UINTN Index;
+ INTERFACE_DESC_LIST_ENTRY *InterfaceEntry;
+ UINTN SkipBytes;
+ UINTN Parsed;
+ EFI_STATUS Status;
+ UINTN LengthLeft;
+
+ Parsed = 0;
+
+ //
+ // First skip the current config descriptor;
+ //
+ Status = GetExpectedDescriptor (
+ Buffer,
+ Length,
+ USB_DT_CONFIG,
+ sizeof (EFI_USB_CONFIG_DESCRIPTOR),
+ &SkipBytes
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ptr = Buffer + SkipBytes;
+
+ CopyMem (
+ &ConfigDescEntry->CongfigDescriptor,
+ ptr,
+ sizeof (EFI_USB_CONFIG_DESCRIPTOR)
+ );
+
+ NumInterface = ConfigDescEntry->CongfigDescriptor.NumInterfaces;
+
+ //
+ // Skip size of Configuration Descriptor
+ //
+ ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR);
+
+ LengthLeft = Length - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR);
+
+ for (Index = 0; Index < NumInterface; Index++) {
+ //
+ // Parse all Interface
+ //
+ InterfaceEntry = AllocateZeroPool (sizeof (INTERFACE_DESC_LIST_ENTRY));
+ if (InterfaceEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = ParseThisInterface (InterfaceEntry, ptr, &LengthLeft, &Parsed);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (InterfaceEntry);
+ return Status;
+ }
+
+ InsertTailList (
+ &ConfigDescEntry->InterfaceDescListHead,
+ &InterfaceEntry->Link
+ );
+
+ //
+ // Parsed for next interface
+ //
+ LengthLeft -= Parsed;
+ ptr += Parsed;
+ }
+ //
+ // Parse for additional alt setting;
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UsbSetConfiguration (
+ IN USB_IO_DEVICE *UsbIoDev,
+ IN UINTN ConfigurationValue
+ )
+/*++
+
+ Routine Description:
+ Set the device to a configuration value.
+
+ Arguments:
+ UsbIoDev - USB_IO_DEVICE to be set configuration
+ ConfigrationValue - The configuration value to be set to that device
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ LIST_ENTRY *NextEntry;
+ CONFIG_DESC_LIST_ENTRY *ConfigEntry;
+ UINT32 Status;
+ EFI_STATUS Result;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ UsbIo = &(UsbIoDev->UsbController[0]->UsbIo);
+ NextEntry = UsbIoDev->ConfigDescListHead.ForwardLink;
+
+ while (NextEntry != &UsbIoDev->ConfigDescListHead) {
+ //
+ // Get one entry
+ //
+ ConfigEntry = (CONFIG_DESC_LIST_ENTRY *) NextEntry;
+ if (ConfigEntry->CongfigDescriptor.ConfigurationValue == ConfigurationValue) {
+ //
+ // Find one, set to the active configuration
+ //
+ UsbIoDev->ActiveConfig = ConfigEntry;
+ break;
+ }
+
+ NextEntry = NextEntry->ForwardLink;
+ }
+ //
+ // Next Entry should not be null
+ //
+ Result = UsbSetDeviceConfiguration (
+ UsbIo,
+ (UINT16) ConfigurationValue,
+ &Status
+ );
+
+ return Result;
+}
+
+EFI_STATUS
+UsbSetDefaultConfiguration (
+ IN USB_IO_DEVICE *UsbIoDev
+ )
+/*++
+
+ Routine Description:
+ Set the device to a default configuration value.
+
+ Arguments:
+ UsbIoDev - USB_IO_DEVICE to be set configuration
+
+ Returns
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ CONFIG_DESC_LIST_ENTRY *ConfigEntry;
+ UINT16 ConfigValue;
+ LIST_ENTRY *NextEntry;
+
+ if (IsListEmpty (&UsbIoDev->ConfigDescListHead)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ NextEntry = UsbIoDev->ConfigDescListHead.ForwardLink;
+
+ ConfigEntry = (CONFIG_DESC_LIST_ENTRY *) NextEntry;
+ ConfigValue = ConfigEntry->CongfigDescriptor.ConfigurationValue;
+
+ return UsbSetConfiguration (UsbIoDev, ConfigValue);
+}
+
+VOID
+UsbDestroyAllConfiguration (
+ IN USB_IO_DEVICE *UsbIoDevice
+ )
+/*++
+
+ Routine Description:
+ Delete all configuration data when device is not used.
+
+ Arguments:
+ UsbIoDevice - USB_IO_DEVICE to be set configuration
+
+ Returns:
+ N/A
+
+--*/
+{
+ CONFIG_DESC_LIST_ENTRY *ConfigEntry;
+ INTERFACE_DESC_LIST_ENTRY *InterfaceEntry;
+ ENDPOINT_DESC_LIST_ENTRY *EndpointEntry;
+ LIST_ENTRY *NextEntry;
+
+ //
+ // Delete all configuration descriptor data
+ //
+ ConfigEntry = (CONFIG_DESC_LIST_ENTRY *) UsbIoDevice->ConfigDescListHead.ForwardLink;
+
+ while (ConfigEntry != (CONFIG_DESC_LIST_ENTRY *) &UsbIoDevice->ConfigDescListHead) {
+ //
+ // Delete all its interface descriptors
+ //
+ InterfaceEntry = (INTERFACE_DESC_LIST_ENTRY *) ConfigEntry->InterfaceDescListHead.ForwardLink;
+
+ while (InterfaceEntry != (INTERFACE_DESC_LIST_ENTRY *) &ConfigEntry->InterfaceDescListHead) {
+ //
+ // Delete all its endpoint descriptors
+ //
+ EndpointEntry = (ENDPOINT_DESC_LIST_ENTRY *) InterfaceEntry->EndpointDescListHead.ForwardLink;
+ while (EndpointEntry != (ENDPOINT_DESC_LIST_ENTRY *) &InterfaceEntry->EndpointDescListHead) {
+ NextEntry = ((LIST_ENTRY *) EndpointEntry)->ForwardLink;
+ RemoveEntryList ((LIST_ENTRY *) EndpointEntry);
+ gBS->FreePool (EndpointEntry);
+ EndpointEntry = (ENDPOINT_DESC_LIST_ENTRY *) NextEntry;
+ }
+
+ NextEntry = ((LIST_ENTRY *) InterfaceEntry)->ForwardLink;
+ RemoveEntryList ((LIST_ENTRY *) InterfaceEntry);
+ gBS->FreePool (InterfaceEntry);
+ InterfaceEntry = (INTERFACE_DESC_LIST_ENTRY *) NextEntry;
+ }
+
+ NextEntry = ((LIST_ENTRY *) ConfigEntry)->ForwardLink;
+ RemoveEntryList ((LIST_ENTRY *) ConfigEntry);
+ gBS->FreePool (ConfigEntry);
+ ConfigEntry = (CONFIG_DESC_LIST_ENTRY *) NextEntry;
+ }
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c
new file mode 100644
index 0000000000..f4ac69e13f
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c
@@ -0,0 +1,2305 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name:
+
+ UsbBus.c
+
+ Abstract:
+
+ USB Bus Driver
+
+ Revision History
+
+--*/
+
+#include "usbbus.h"
+
+//#ifdef EFI_DEBUG
+UINTN gUSBDebugLevel = EFI_D_ERROR;
+UINTN gUSBErrorLevel = EFI_D_ERROR;
+//#endif
+//
+// The UsbBusProtocol is just used to locate USB_BUS_CONTROLLER
+// structure in the UsbBusDriverControllerDriverStop(). Then we can
+// Close all opened protocols and release this structure.
+//
+STATIC EFI_GUID mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID;
+
+
+
+//
+// EFI_DRIVER_BINDING_PROTOCOL Protocol Interface
+//
+EFI_STATUS
+EFIAPI
+UsbBusControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+UsbBusControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+UsbBusControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+EFI_DRIVER_BINDING_PROTOCOL gUsbBusDriverBinding = {
+ UsbBusControllerDriverSupported,
+ UsbBusControllerDriverStart,
+ UsbBusControllerDriverStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+//
+// Internal use only
+//
+STATIC
+EFI_STATUS
+ReportUsbStatusCode (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusController,
+ IN EFI_STATUS_CODE_TYPE Type,
+ IN EFI_STATUS_CODE_VALUE Code
+ );
+
+//
+// Supported function
+//
+VOID
+InitializeUsbIoInstance (
+ IN USB_IO_CONTROLLER_DEVICE *UsbIoController
+ );
+
+STATIC
+USB_IO_CONTROLLER_DEVICE *
+CreateUsbIoControllerDevice (
+ VOID
+ );
+
+STATIC
+EFI_STATUS
+InitUsbIoController (
+ IN USB_IO_CONTROLLER_DEVICE *UsbIoController
+ );
+
+//
+// USB Device Configuration / Deconfiguration
+//
+STATIC
+EFI_STATUS
+UsbDeviceConfiguration (
+ IN USB_IO_CONTROLLER_DEVICE *ParentHubController,
+ IN EFI_HANDLE HostController,
+ IN UINT8 ParentPort,
+ IN USB_IO_DEVICE *UsbIoDevice
+ );
+
+//
+// Usb Bus enumeration function
+//
+STATIC
+VOID
+EFIAPI
+UsbEnumeration (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+ResetRootPort (
+ IN EFI_USB_HC_PROTOCOL *UsbHCInterface,
+ IN UINT8 PortNum,
+ IN UINT8 RetryTimes
+ );
+
+EFI_STATUS
+ResetHubPort (
+ IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
+ IN UINT8 PortIndex
+ );
+
+EFI_STATUS
+ClearRootPortConnectionChangeStatus (
+ IN UINT8 PortNum,
+ IN EFI_USB_HC_PROTOCOL *UsbHCInterface
+ );
+
+STATIC
+EFI_STATUS
+ParentPortReset (
+ IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
+ IN BOOLEAN ReConfigure,
+ IN UINT8 RetryTimes
+ );
+
+//
+// Following are address allocate and free functions
+//
+STATIC
+UINT8
+UsbAllocateAddress (
+ IN UINT8 *AddressPool
+ )
+{
+ UINT8 ByteIndex;
+ UINT8 BitIndex;
+
+ for (ByteIndex = 0; ByteIndex < 16; ByteIndex++) {
+ for (BitIndex = 0; BitIndex < 8; BitIndex++) {
+ if ((AddressPool[ByteIndex] & (1 << BitIndex)) == 0) {
+ //
+ // Found one, covert to address, and mark it use
+ //
+ AddressPool[ByteIndex] |= (1 << BitIndex);
+ return (UINT8) (ByteIndex * 8 + BitIndex);
+ }
+ }
+ }
+
+ return 0;
+
+}
+
+STATIC
+VOID
+UsbFreeAddress (
+ IN UINT8 DevAddress,
+ IN UINT8 *AddressPool
+ )
+{
+ UINT8 WhichByte;
+ UINT8 WhichBit;
+ //
+ // Locate the position
+ //
+ WhichByte = (UINT8) (DevAddress / 8);
+ WhichBit = (UINT8) (DevAddress & 0x7);
+
+ AddressPool[WhichByte] &= (~(1 << WhichBit));
+}
+
+EFI_STATUS
+EFIAPI
+UsbBusControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ that has UsbHcProtocol installed will be supported.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver supports this device.
+ EFI_UNSUPPORTED - This driver does not support this device.
+
+--*/
+{
+ EFI_STATUS OpenStatus;
+
+ //
+ // Check whether USB Host Controller Protocol is already
+ // installed on this handle. If it is installed, we can start
+ // USB Bus Driver now.
+ //
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+
+ if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return OpenStatus;
+}
+
+
+EFI_STATUS
+EFIAPI
+UsbBusControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+
+ Starting the Usb Bus Driver
+
+ Arguments:
+
+ This - Protocol instance pointer.
+ Controller - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+
+ EFI_SUCCESS - This driver supports this device.
+ EFI_UNSUPPORTED - This driver does not support this device.
+ EFI_DEVICE_ERROR - This driver cannot be started due to device
+ Error
+ EFI_OUT_OF_RESOURCES- Can't allocate memory resources
+ EFI_ALREADY_STARTED - This driver has been started
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS OpenStatus;
+ USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
+ USB_IO_DEVICE *RootHub;
+ USB_IO_CONTROLLER_DEVICE *RootHubController;
+ EFI_USB_HC_PROTOCOL *UsbHCInterface;
+
+ //
+ // Allocate USB_BUS_CONTROLLER_DEVICE structure
+ //
+ UsbBusDev = NULL;
+ UsbBusDev = AllocateZeroPool (sizeof (USB_BUS_CONTROLLER_DEVICE));
+ if (UsbBusDev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UsbBusDev->Signature = USB_BUS_DEVICE_SIGNATURE;
+ UsbBusDev->AddressPool[0] = 1;
+
+ //
+ // Get the Device Path Protocol on Controller's handle
+ //
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &UsbBusDev->DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (OpenStatus)) {
+ gBS->FreePool (UsbBusDev);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Locate the Host Controller Interface
+ //
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ (VOID **) &UsbHCInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) {
+
+ //
+ // Report Status Code here since we will reset the host controller
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_IO_BUS_USB | EFI_IOB_EC_CONTROLLER_ERROR,
+ UsbBusDev->DevicePath
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->FreePool (UsbBusDev);
+ return EFI_UNSUPPORTED;
+ }
+
+ if (OpenStatus == EFI_ALREADY_STARTED) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->FreePool (UsbBusDev);
+ return EFI_ALREADY_STARTED;
+ }
+
+ UsbBusDev->UsbHCInterface = UsbHCInterface;
+
+ //
+ // Attach EFI_USB_BUS_PROTOCOL to controller handle,
+ // for locate UsbBusDev later
+ //
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &mUsbBusProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &UsbBusDev->BusIdentify
+ );
+
+ if (EFI_ERROR (Status)) {
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->FreePool (UsbBusDev);
+ return Status;
+ }
+ //
+ // Add root hub to the tree
+ //
+ RootHub = NULL;
+ RootHub = AllocateZeroPool (sizeof (USB_IO_DEVICE));
+ if (RootHub == NULL) {
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &mUsbBusProtocolGuid,
+ &UsbBusDev->BusIdentify
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->FreePool (UsbBusDev);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RootHub->BusController = UsbBusDev;
+ RootHub->DeviceAddress = UsbAllocateAddress (UsbBusDev->AddressPool);
+
+ UsbBusDev->Root = RootHub;
+
+ //
+ // Allocate Root Hub Controller
+ //
+ RootHubController = CreateUsbIoControllerDevice ();
+ if (RootHubController == NULL) {
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &mUsbBusProtocolGuid,
+ &UsbBusDev->BusIdentify
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->FreePool (UsbBusDev);
+ gBS->FreePool (RootHub);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UsbHCInterface->GetRootHubPortNumber (
+ UsbHCInterface,
+ &RootHubController->DownstreamPorts
+ );
+ RootHubController->UsbDevice = RootHub;
+ RootHubController->IsUsbHub = TRUE;
+ RootHubController->DevicePath = UsbBusDev->DevicePath;
+ RootHubController->HostController = Controller;
+
+ RootHub->NumOfControllers = 1;
+ RootHub->UsbController[0] = RootHubController;
+
+ //
+ // Report Status Code here since we will reset the host controller
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_USB | EFI_IOB_PC_RESET,
+ UsbBusDev->DevicePath
+ );
+
+ //
+ // Reset USB Host Controller
+ //
+ UsbHCInterface->Reset (
+ UsbHCInterface,
+ EFI_USB_HC_RESET_GLOBAL
+ );
+
+ //
+ // Report Status Code while we are going to bring up the Host Controller
+ // and start bus enumeration
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_USB | EFI_IOB_PC_ENABLE,
+ UsbBusDev->DevicePath
+ );
+
+ //
+ // Start USB Host Controller
+ //
+ UsbHCInterface->SetState (
+ UsbHCInterface,
+ EfiUsbHcStateOperational
+ );
+
+ //
+ // Create a timer to query root ports periodically
+ //
+ Status = gBS->CreateEvent (
+ EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ UsbEnumeration,
+ RootHubController,
+ &RootHubController->HubNotify
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &mUsbBusProtocolGuid,
+ &UsbBusDev->BusIdentify
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->FreePool (RootHubController);
+ gBS->FreePool (RootHub);
+ gBS->FreePool (UsbBusDev);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Before depending on the timer to check root ports periodically,
+ // here we should check them immediately for the first time, or
+ // there will be an interval between bus start and devices start.
+ //
+ gBS->SignalEvent (RootHubController->HubNotify);
+
+ Status = gBS->SetTimer (
+ RootHubController->HubNotify,
+ TimerPeriodic,
+ BUSPOLLING_PERIOD
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &mUsbBusProtocolGuid,
+ &UsbBusDev->BusIdentify
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseEvent (RootHubController->HubNotify);
+ gBS->FreePool (RootHubController);
+ gBS->FreePool (RootHub);
+ gBS->FreePool (UsbBusDev);
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+//
+// Stop the bus controller
+//
+EFI_STATUS
+EFIAPI
+UsbBusControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to stop driver on
+ NumberOfChildren - Number of Children in the ChildHandleBuffer
+ ChildHandleBuffer - List of handles for the children we need to stop.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+ others
+
+--*/
+{
+ EFI_STATUS Status;
+ USB_IO_DEVICE *Root;
+ USB_IO_CONTROLLER_DEVICE *RootHubController;
+ USB_BUS_CONTROLLER_DEVICE *UsbBusController;
+ EFI_USB_BUS_PROTOCOL *UsbIdentifier;
+ UINT8 Index2;
+ EFI_USB_HC_PROTOCOL *UsbHCInterface;
+ USB_IO_CONTROLLER_DEVICE *UsbController;
+ USB_IO_DEVICE *UsbIoDevice;
+ USB_IO_CONTROLLER_DEVICE *HubController;
+ UINTN Index;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ if (NumberOfChildren > 0) {
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+ Status = gBS->OpenProtocol (
+ ChildHandleBuffer[Index],
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // We are here since the handle passed in does not support
+ // UsbIo protocol. There are several reasons that will cause
+ // this.
+ // For combo device such as keyboard, it may have 2 devices
+ // in one, namely, keyboard and mouse. If we deconfigure one
+ // of them, the other will be freed at the same time. This will
+ // cause the status error. But this is the correct behavior.
+ // For hub device, if we deconfigure hub first, the other chile
+ // device will be disconnected also, this will also provide us
+ // a status error. Now we will only report EFI_SUCCESS since Uhc
+ // driver will be disconnected at the second time.(pls see
+ // CoreDisconnectController for details)
+ //
+ continue;
+ }
+
+ UsbController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (UsbIo);
+ UsbIoDevice = UsbController->UsbDevice;
+ HubController = UsbController->Parent;
+ UsbDeviceDeConfiguration (UsbIoDevice);
+ for (Index2 = 0; Index2 < HubController->DownstreamPorts; Index2++) {
+ if (HubController->Children[Index2] == UsbIoDevice) {
+ HubController->Children[Index2] = NULL;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+ }
+ //
+ // Get the USB_BUS_CONTROLLER_DEVICE
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &mUsbBusProtocolGuid,
+ (VOID **) &UsbIdentifier,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbBusController = USB_BUS_CONTROLLER_DEVICE_FROM_THIS (UsbIdentifier);
+
+ //
+ // Stop USB Host Controller
+ //
+ UsbHCInterface = UsbBusController->UsbHCInterface;
+
+ //
+ // Report Status Code here since we will reset the host controller
+ //
+ ReportUsbStatusCode (
+ UsbBusController,
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_USB | EFI_IOB_PC_RESET
+ );
+
+ UsbHCInterface->SetState (
+ UsbHCInterface,
+ EfiUsbHcStateHalt
+ );
+
+ //
+ // Deconfiguration all its devices
+ //
+ Root = UsbBusController->Root;
+ RootHubController = Root->UsbController[0];
+
+ gBS->CloseEvent (RootHubController->HubNotify);
+
+ for (Index2 = 0; Index2 < RootHubController->DownstreamPorts; Index2++) {
+ if (RootHubController->Children[Index2]) {
+ UsbDeviceDeConfiguration (RootHubController->Children[Index2]);
+ RootHubController->Children[Index2] = NULL;
+ }
+ }
+
+ gBS->FreePool (RootHubController);
+ gBS->FreePool (Root);
+
+ //
+ // Uninstall USB Bus Protocol
+ //
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &mUsbBusProtocolGuid,
+ &UsbBusController->BusIdentify
+ );
+
+ //
+ // Close USB_HC_PROTOCOL & DEVICE_PATH_PROTOCOL
+ // Opened by this Controller
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->FreePool (UsbBusController);
+
+ return EFI_SUCCESS;
+}
+//
+// USB Device Configuration
+//
+STATIC
+EFI_STATUS
+UsbDeviceConfiguration (
+ IN USB_IO_CONTROLLER_DEVICE *ParentHubController,
+ IN EFI_HANDLE HostController,
+ IN UINT8 ParentPort,
+ IN USB_IO_DEVICE *UsbIoDevice
+ )
+/*++
+
+ Routine Description:
+ Configurate a new device attached to the usb bus
+
+ Arguments:
+ ParentHubController - Parent Hub which this device is connected.
+ HostController - Host Controller handle
+ ParentPort - Parent Hub port which this device is connected.
+ UsbIoDevice - The device to be configured.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ UINT8 DevAddress;
+ UINT8 Index;
+ EFI_STATUS Result;
+ UINT32 Status;
+ CHAR16 *StrManufacturer;
+ CHAR16 *StrProduct;
+ CHAR16 *StrSerialNumber;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 NumOfInterface;
+ USB_IO_CONTROLLER_DEVICE *FirstController;
+ USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
+ USB_IO_CONTROLLER_DEVICE *UsbIoController;
+
+ UsbBusDev = UsbIoDevice->BusController;
+ //
+ // Since a USB device must have at least on interface,
+ // so create this instance first
+ //
+ FirstController = CreateUsbIoControllerDevice ();
+ FirstController->UsbDevice = UsbIoDevice;
+ UsbIoDevice->UsbController[0] = FirstController;
+ FirstController->InterfaceNumber = 0;
+ FirstController->ParentPort = ParentPort;
+ FirstController->Parent = ParentHubController;
+ FirstController->HostController = HostController;
+
+ InitializeUsbIoInstance (FirstController);
+
+ DEBUG ((gUSBDebugLevel, "Configuration Usb Device at 0x%x...\n", ParentPort));
+
+ //
+ // Ensure we used the correctly USB I/O instance
+ //
+ UsbIo = &FirstController->UsbIo;
+
+ //
+ // First retrieve the 1st 8 bytes of
+ // in order to get the MaxPacketSize for Endpoint 0
+ //
+ for (Index = 0; Index < 3; Index++) {
+
+ UsbIoDevice->DeviceDescriptor.MaxPacketSize0 = 8;
+
+ ParentPortReset (FirstController, FALSE, Index);
+
+ Result = UsbGetDescriptor (
+ UsbIo,
+ (USB_DT_DEVICE << 8),
+ 0,
+ 8,
+ &UsbIoDevice->DeviceDescriptor,
+ &Status
+ );
+ if (!EFI_ERROR (Result)) {
+ DEBUG ((gUSBDebugLevel,
+ "Get Device Descriptor Success, MaxPacketSize0 = 0x%x\n",
+ UsbIoDevice->DeviceDescriptor.MaxPacketSize0)
+ );
+ break;
+ }
+
+ }
+
+ if (Index == 3) {
+ ReportUsbStatusCode (
+ UsbBusDev,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR
+ );
+ DEBUG ((gUSBErrorLevel, "Get Device Descriptor Fail when configing\n"));
+ gBS->FreePool (FirstController);
+ return EFI_DEVICE_ERROR;
+ }
+
+ DevAddress = UsbAllocateAddress (UsbIoDevice->BusController->AddressPool);
+ if (DevAddress == 0) {
+ DEBUG ((gUSBErrorLevel, "Cannot allocate address\n"));
+ gBS->FreePool (FirstController);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Result = UsbSetDeviceAddress (UsbIo, DevAddress, &Status);
+
+ if (EFI_ERROR (Result)) {
+ DEBUG ((gUSBErrorLevel, "Set address error\n"));
+ ReportUsbStatusCode (
+ UsbBusDev,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR
+ );
+
+ UsbFreeAddress (
+ DevAddress,
+ UsbIoDevice->BusController->AddressPool
+ );
+
+ gBS->FreePool (FirstController);
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbIoDevice->DeviceAddress = DevAddress;
+
+ //
+ // Get the whole device descriptor
+ //
+ Result = UsbGetDescriptor (
+ UsbIo,
+ (USB_DT_DEVICE << 8),
+ 0,
+ sizeof (EFI_USB_DEVICE_DESCRIPTOR),
+ &UsbIoDevice->DeviceDescriptor,
+ &Status
+ );
+
+ if (EFI_ERROR (Result)) {
+ DEBUG ((gUSBErrorLevel, "Get whole Device Descriptor error\n"));
+ ReportUsbStatusCode (
+ UsbBusDev,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR
+ );
+ UsbFreeAddress (
+ DevAddress,
+ UsbIoDevice->BusController->AddressPool
+ );
+
+ gBS->FreePool (FirstController);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Get & parse all configurations for this device, including
+ // all configuration descriptors, all interface descriptors, all
+ // endpoint descriptors
+ //
+ Result = UsbGetAllConfigurations (UsbIoDevice);
+
+ if (EFI_ERROR (Result)) {
+ DEBUG ((gUSBErrorLevel, "Failed to get device configuration\n"));
+ ReportUsbStatusCode (
+ UsbBusDev,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR
+ );
+ UsbFreeAddress (
+ DevAddress,
+ UsbIoDevice->BusController->AddressPool
+ );
+
+ gBS->FreePool (FirstController);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Set the 1st configuration value
+ //
+ Result = UsbSetDefaultConfiguration (UsbIoDevice);
+ if (EFI_ERROR (Result)) {
+ DEBUG ((gUSBErrorLevel, "Failed to set device configuration\n"));
+ ReportUsbStatusCode (
+ UsbBusDev,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR
+ );
+ UsbFreeAddress (
+ DevAddress,
+ UsbIoDevice->BusController->AddressPool
+ );
+
+ gBS->FreePool (FirstController);
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbIoDevice->IsConfigured = TRUE;
+
+ //
+ // Get all string table if applicable
+ //
+ Result = UsbGetStringtable (UsbIoDevice);
+ if (EFI_ERROR (Result)) {
+ DEBUG ((gUSBDebugLevel, "Device doesn't support string table\n"));
+ } else {
+
+ StrManufacturer = NULL;
+ UsbIo->UsbGetStringDescriptor (
+ UsbIo,
+ UsbIoDevice->LangID[0],
+ (UsbIoDevice->DeviceDescriptor).StrManufacturer,
+ &StrManufacturer
+ );
+
+ StrProduct = NULL;
+ UsbIo->UsbGetStringDescriptor (
+ UsbIo,
+ UsbIoDevice->LangID[0],
+ (UsbIoDevice->DeviceDescriptor).StrProduct,
+ &StrProduct
+ );
+
+ StrSerialNumber = NULL;
+ UsbIo->UsbGetStringDescriptor (
+ UsbIo,
+ UsbIoDevice->LangID[0],
+ (UsbIoDevice->DeviceDescriptor).StrSerialNumber,
+ &StrSerialNumber
+ );
+
+ if (StrManufacturer) {
+ gBS->FreePool (StrManufacturer);
+ }
+
+ if (StrProduct) {
+ gBS->FreePool (StrProduct);
+ }
+
+ if (StrSerialNumber) {
+ gBS->FreePool (StrSerialNumber);
+ }
+ }
+ //
+ // Create USB_IO_CONTROLLER_DEVICE for
+ // each detected interface
+ //
+ FirstController->CurrentConfigValue =
+ UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue;
+
+ NumOfInterface =
+ UsbIoDevice->ActiveConfig->CongfigDescriptor.NumInterfaces;
+ UsbIoDevice->NumOfControllers = NumOfInterface;
+
+ Result = InitUsbIoController (FirstController);
+ if (EFI_ERROR (Result)) {
+ ReportUsbStatusCode (
+ UsbBusDev,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR
+ );
+ gBS->FreePool (FirstController);
+ UsbIoDevice->UsbController[0] = NULL;
+ return EFI_DEVICE_ERROR;
+ }
+
+ for (Index = 1; Index < NumOfInterface; Index++) {
+ UsbIoController = CreateUsbIoControllerDevice ();
+ UsbIoController->UsbDevice = UsbIoDevice;
+ UsbIoController->CurrentConfigValue =
+ UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue;
+ UsbIoController->InterfaceNumber = Index;
+ UsbIoDevice->UsbController[Index] = UsbIoController;
+ UsbIoController->ParentPort = ParentPort;
+ UsbIoController->Parent = ParentHubController;
+ UsbIoController->HostController = HostController;
+
+ //
+ // First copy the USB_IO Protocol instance
+ //
+ CopyMem (
+ &UsbIoController->UsbIo,
+ UsbIo,
+ sizeof (EFI_USB_IO_PROTOCOL)
+ );
+
+ Result = InitUsbIoController (UsbIoController);
+ if (EFI_ERROR (Result)) {
+ ReportUsbStatusCode (
+ UsbBusDev,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR
+ );
+ gBS->FreePool (UsbIoController);
+ UsbIoDevice->UsbController[Index] = NULL;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+//
+// USB Device DeConfiguration
+//
+
+EFI_STATUS
+UsbDeviceDeConfiguration (
+ IN USB_IO_DEVICE *UsbIoDevice
+ )
+/*++
+
+ Routine Description:
+ Remove Device, Device Handles, Uninstall Protocols.
+
+ Arguments:
+ UsbIoDevice - The device to be deconfigured.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ USB_IO_CONTROLLER_DEVICE *UsbController;
+ UINT8 index;
+ USB_IO_DEVICE *ChildDevice;
+ UINT8 Index;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ DEBUG ((gUSBDebugLevel, "Enter Usb Device Deconfiguration\n"));
+
+ //
+ // Double check UsbIoDevice exists
+ //
+ if (UsbIoDevice == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ for (index = 0; index < UsbIoDevice->NumOfControllers; index++) {
+ //
+ // Check if it is a hub, if so, de configuration all its
+ // downstream ports
+ //
+ UsbController = UsbIoDevice->UsbController[index];
+
+ //
+ // Check the controller pointer
+ //
+ if (UsbController == NULL) {
+ continue;
+ }
+
+ if (UsbController->IsUsbHub) {
+
+ DEBUG ((gUSBDebugLevel, "Hub Deconfig, First Deconfig its downstream ports\n"));
+
+ //
+ // First Remove interrupt transfer request for the status
+ // change port
+ //
+ UsbIo = &UsbController->UsbIo;
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ UsbController->HubEndpointAddress,
+ FALSE,
+ 0,
+ 0,
+ NULL,
+ NULL
+ );
+
+ if (NULL != UsbController->HubNotify) {
+ gBS->CloseEvent (UsbController->HubNotify);
+ }
+
+ for (Index = 0; Index < UsbController->DownstreamPorts; Index++) {
+ if (UsbController->Children[Index]) {
+ ChildDevice = UsbController->Children[Index];
+ UsbDeviceDeConfiguration (ChildDevice);
+ UsbController->Children[Index] = NULL;
+ }
+ }
+ }
+ //
+ // If the controller is managed by a device driver, we need to
+ // disconnect them
+ //
+ if (UsbController->IsManagedByDriver) {
+ gBS->DisconnectController (
+ UsbController->Handle,
+ NULL,
+ NULL
+ );
+ }
+
+ //
+ // remove child handle reference to the USB_HC_PROTOCOL
+ //
+ gBS->CloseProtocol (
+ UsbController->HostController,
+ &gEfiUsbHcProtocolGuid,
+ gUsbBusDriverBinding.DriverBindingHandle,
+ UsbController->Handle
+ );
+
+ //
+ // Uninstall EFI_USB_IO_PROTOCOL & DEVICE_PATH_PROTOCOL
+ // installed on this handle
+ //
+ gBS->UninstallMultipleProtocolInterfaces (
+ UsbController->Handle,
+ &gEfiDevicePathProtocolGuid,
+ UsbController->DevicePath,
+ &gEfiUsbIoProtocolGuid,
+ &UsbController->UsbIo,
+ NULL
+ );
+
+ if (UsbController->DevicePath != NULL) {
+ gBS->FreePool (UsbController->DevicePath);
+ }
+
+ gBS->FreePool (UsbController);
+ UsbIoDevice->UsbController[index] = NULL;
+ }
+ //
+ // Free address for later use
+ //
+ UsbFreeAddress (
+ UsbIoDevice->DeviceAddress,
+ UsbIoDevice->BusController->AddressPool
+ );
+
+ //
+ // Free all resouces allocated for all its configurations
+ //
+ UsbDestroyAllConfiguration (UsbIoDevice);
+
+ if (UsbIoDevice) {
+ gBS->FreePool (UsbIoDevice);
+ UsbIoDevice = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+//
+// After interrupt complete, this function will be called,
+// This function need to be well-defined later
+//
+STATIC
+EFI_STATUS
+EFIAPI
+OnHubInterruptComplete (
+ IN VOID *Data,
+ IN UINTN DataLength,
+ IN VOID *Context,
+ IN UINT32 Result
+ )
+/*++
+
+ Routine Description:
+ Whenever hub interrupt occurs, this routine will be called to check
+ which event happens.
+
+ Arguments:
+ Data - Hub interrupt transfer data.
+ DataLength - The length of the Data.
+ Context - Hub Controller Device.
+ Result - Hub interrupt transfer status.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ USB_IO_CONTROLLER_DEVICE *HubController;
+ UINT8 Index;
+ UINT8 *ptr;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT32 UsbResult;
+ BOOLEAN Disconnected;
+ EFI_STATUS Status;
+
+ HubController = (USB_IO_CONTROLLER_DEVICE *) Context;
+ UsbIo = &HubController->UsbIo;
+
+ //
+ // If something error in this interrupt transfer,
+ //
+ if (Result != EFI_USB_NOERROR) {
+ if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
+ UsbClearEndpointHalt (
+ UsbIo,
+ HubController->HubEndpointAddress,
+ &UsbResult
+ );
+ }
+
+ //
+ // Delete & Submit this interrupt again
+ //
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ HubController->HubEndpointAddress,
+ FALSE,
+ 0,
+ 0,
+ NULL,
+ NULL
+ );
+
+ //
+ // try to detect if the hub itself was disconnected or not
+ //
+ Status = IsDeviceDisconnected (
+ HubController,
+ &Disconnected
+ );
+
+ if (!EFI_ERROR (Status) && Disconnected == TRUE) {
+ DEBUG ((gUSBErrorLevel, "Hub is disconnected\n"));
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Hub ports < 7
+ //
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ HubController->HubEndpointAddress,
+ TRUE,
+ 100,
+ 1,
+ OnHubInterruptComplete,
+ HubController
+ );
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (DataLength == 0 || Data == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Scan which port has status change
+ // Bit 0 stands for hub itself, other bit stands for
+ // the corresponding port
+ //
+ for (Index = 0; Index < DataLength * 8; Index++) {
+ ptr = (UINT8 *) Data + Index / 8;
+ if ((*ptr) & (1 << (Index & 0x7))) {
+ HubController->StatusChangePort = Index;
+ break;
+ }
+ }
+ //
+ // Signal hub notify event
+ //
+ gBS->SignalEvent (HubController->HubNotify);
+
+ return EFI_SUCCESS;
+}
+//
+// USB Root Hub Enumerator
+//
+STATIC
+VOID
+EFIAPI
+UsbEnumeration (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+ Routine Description:
+ This is USB enumerator
+
+ Arguments:
+ Event - Indicating which event is signaled
+ Context - actually it is a USB_IO_DEVICE
+
+ Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ USB_IO_CONTROLLER_DEVICE *HubController;
+ EFI_USB_PORT_STATUS HubPortStatus;
+ EFI_STATUS Status;
+ UINT8 Index;
+ EFI_USB_HC_PROTOCOL *UsbHCInterface;
+ USB_IO_DEVICE *UsbIoDev;
+ USB_BUS_CONTROLLER_DEVICE *UsbBusDev;
+ EFI_HANDLE HostController;
+ USB_IO_DEVICE *OldUsbIoDevice;
+ USB_IO_DEVICE *NewDevice;
+ USB_IO_CONTROLLER_DEVICE *NewController;
+ UINT8 Index2;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 StatusChangePort;
+
+ HubController = (USB_IO_CONTROLLER_DEVICE *) Context;
+ HostController = HubController->HostController;
+ UsbBusDev = HubController->UsbDevice->BusController;
+
+ if (HubController->UsbDevice->DeviceAddress == 1) {
+ //
+ // Root hub has the address 1
+ //
+ UsbIoDev = HubController->UsbDevice;
+ UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;
+
+ for (Index = 0; Index < HubController->DownstreamPorts; Index++) {
+ UsbHCInterface->GetRootHubPortStatus (
+ UsbHCInterface,
+ Index,
+ (EFI_USB_PORT_STATUS *) &HubPortStatus
+ );
+
+ if (!IsPortConnectChange (HubPortStatus.PortChangeStatus)) {
+ continue;
+ }
+ //
+ // Clear root hub status change status
+ //
+ ClearRootPortConnectionChangeStatus (
+ Index,
+ UsbHCInterface
+ );
+
+ gBS->Stall (100 * 1000);
+
+ UsbHCInterface->GetRootHubPortStatus (
+ UsbHCInterface,
+ Index,
+ (EFI_USB_PORT_STATUS *) &HubPortStatus
+ );
+
+ if (IsPortConnect (HubPortStatus.PortStatus)) {
+
+ //
+ // There is something connected to this port
+ //
+ DEBUG ((gUSBDebugLevel, "Something attached from Root Hub in 0x%x\n", Index));
+
+ ReportUsbStatusCode (
+ UsbBusDev,
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG
+ );
+ //
+ // if there is something physically detached, but still logically
+ // attached...
+ //
+ OldUsbIoDevice = HubController->Children[Index];
+
+ if (NULL != OldUsbIoDevice) {
+ UsbDeviceDeConfiguration (OldUsbIoDevice);
+ HubController->Children[Index] = NULL;
+ }
+
+ NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));
+ if (NewDevice == NULL) {
+ return ;
+ }
+ //
+ // Initialize some fields by copying data from
+ // its parents
+ //
+ NewDevice->IsSlowDevice = IsPortLowSpeedDeviceAttached (HubPortStatus.PortStatus);
+
+ DEBUG ((gUSBDebugLevel, "DeviceSpeed 0x%x\n", NewDevice->IsSlowDevice));
+
+ NewDevice->BusController = UsbIoDev->BusController;
+
+ //
+ // Configure that device
+ //
+ Status = UsbDeviceConfiguration (
+ HubController,
+ HostController,
+ Index,
+ NewDevice
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (NewDevice);
+ return ;
+ }
+ //
+ // Add this device to the usb bus tree
+ //
+ HubController->Children[Index] = NewDevice;
+
+ for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {
+ //
+ // If this device is hub, add to the hub index
+ //
+ NewController = NewDevice->UsbController[Index2];
+
+ Status = gBS->ConnectController (
+ NewController->Handle,
+ NULL,
+ NULL,
+ TRUE
+ );
+ //
+ // If connect success, we need to disconnect when
+ // stop the controller, otherwise we need not call
+ // gBS->DisconnectController ()
+ // This is used by those usb devices we don't plan
+ // to support. We can allocate
+ // controller handles for them, but we don't have
+ // device drivers to manage them.
+ //
+ NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));
+
+ if (IsHub (NewController)) {
+
+ NewController->IsUsbHub = TRUE;
+
+ //
+ // Configure Hub Controller
+ //
+ Status = DoHubConfig (NewController);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ //
+ // Create an event to do hub enumeration
+ //
+ gBS->CreateEvent (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ UsbEnumeration,
+ NewController,
+ &NewController->HubNotify
+ );
+
+ //
+ // Add request to do query hub status
+ // change endpoint
+ // Hub ports < 7
+ //
+ UsbIo = &NewController->UsbIo;
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ NewController->HubEndpointAddress,
+ TRUE,
+ 100,
+ 1,
+ OnHubInterruptComplete,
+ NewController
+ );
+
+ }
+ }
+ } else {
+ //
+ // Something disconnected from USB root hub
+ //
+ DEBUG ((gUSBDebugLevel, "Something deteached from Root Hub\n"));
+
+ OldUsbIoDevice = HubController->Children[Index];
+
+ UsbDeviceDeConfiguration (OldUsbIoDevice);
+
+ HubController->Children[Index] = NULL;
+
+ UsbHCInterface->ClearRootHubPortFeature (
+ UsbHCInterface,
+ Index,
+ EfiUsbPortEnableChange
+ );
+
+ UsbHCInterface->GetRootHubPortStatus (
+ UsbHCInterface,
+ Index,
+ (EFI_USB_PORT_STATUS *) &HubPortStatus
+ );
+
+ }
+ }
+
+ return ;
+ } else {
+ //
+ // Event from Hub, Get the hub controller handle
+ //
+ //
+ // Get the status change endpoint
+ //
+ StatusChangePort = HubController->StatusChangePort;
+
+ //
+ // Clear HubController Status Change Bit
+ //
+ HubController->StatusChangePort = 0;
+
+ if (StatusChangePort == 0) {
+ //
+ // Hub changes, we don't handle here
+ //
+ return ;
+ }
+ //
+ // Check which event took place at that port
+ //
+ UsbIo = &HubController->UsbIo;
+ Status = HubGetPortStatus (
+ UsbIo,
+ StatusChangePort,
+ (UINT32 *) &HubPortStatus
+ );
+
+ if (EFI_ERROR (Status)) {
+ return ;
+ }
+ //
+ // Clear some change status
+ //
+ if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) {
+ //
+ // Clear Hub port enable change
+ //
+ DEBUG ((gUSBDebugLevel, "Port Enable Change\n"));
+ HubClearPortFeature (
+ UsbIo,
+ StatusChangePort,
+ EfiUsbPortEnableChange
+ );
+
+ HubGetPortStatus (
+ UsbIo,
+ StatusChangePort,
+ (UINT32 *) &HubPortStatus
+ );
+ }
+
+ if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) {
+ //
+ // Clear Hub reset change
+ //
+ DEBUG ((gUSBDebugLevel, "Port Reset Change\n"));
+ HubClearPortFeature (
+ UsbIo,
+ StatusChangePort,
+ EfiUsbPortResetChange
+ );
+
+ HubGetPortStatus (
+ UsbIo,
+ StatusChangePort,
+ (UINT32 *) &HubPortStatus
+ );
+ }
+
+ if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_OVERCURRENT) {
+ //
+ // Clear Hub overcurrent change
+ //
+ DEBUG ((gUSBDebugLevel, "Port Overcurrent Change\n"));
+ HubClearPortFeature (
+ UsbIo,
+ StatusChangePort,
+ EfiUsbPortOverCurrentChange
+ );
+
+ HubGetPortStatus (
+ UsbIo,
+ StatusChangePort,
+ (UINT32 *) &HubPortStatus
+ );
+ }
+
+ if (IsPortConnectChange (HubPortStatus.PortChangeStatus)) {
+ //
+ // First clear port connection change
+ //
+ DEBUG ((gUSBDebugLevel, "Port Connection Change\n"));
+ HubClearPortFeature (
+ UsbIo,
+ StatusChangePort,
+ EfiUsbPortConnectChange
+ );
+
+ HubGetPortStatus (
+ UsbIo,
+ StatusChangePort,
+ (UINT32 *) &HubPortStatus
+ );
+
+ if (IsPortConnect (HubPortStatus.PortStatus)) {
+
+ DEBUG ((gUSBDebugLevel, "New Device Connect on Hub port \n"));
+
+ ReportUsbStatusCode (
+ UsbBusDev,
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG
+ );
+
+ //
+ // if there is something physically detached, but still logically
+ // attached...
+ //
+ OldUsbIoDevice = HubController->Children[StatusChangePort - 1];
+
+ if (NULL != OldUsbIoDevice) {
+ UsbDeviceDeConfiguration (OldUsbIoDevice);
+ HubController->Children[StatusChangePort - 1] = NULL;
+ }
+
+ NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE));
+ if (NewDevice == NULL) {
+ return ;
+ }
+
+ ResetHubPort (HubController, StatusChangePort);
+
+ HubGetPortStatus (
+ UsbIo,
+ StatusChangePort,
+ (UINT32 *) &HubPortStatus
+ );
+
+ //
+ // Initialize some fields
+ //
+ NewDevice->IsSlowDevice = IsPortLowSpeedDeviceAttached (HubPortStatus.PortStatus);
+
+ NewDevice->BusController = HubController->UsbDevice->BusController;
+
+ //
+ // Configure that device
+ //
+ Status = UsbDeviceConfiguration (
+ HubController,
+ HostController,
+ (UINT8) (StatusChangePort - 1),
+ NewDevice
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (NewDevice);
+ return ;
+ }
+ //
+ // Add this device to the usb bus tree
+ // StatusChangePort is begin from 1,
+ //
+ HubController->Children[StatusChangePort - 1] = NewDevice;
+
+ for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) {
+ //
+ // If this device is hub, add to the hub index
+ //
+ NewController = NewDevice->UsbController[Index2];
+
+ //
+ // Connect the controller to the driver image
+ //
+ Status = gBS->ConnectController (
+ NewController->Handle,
+ NULL,
+ NULL,
+ TRUE
+ );
+ //
+ // If connect success, we need to disconnect when
+ // stop the controller, otherwise we need not call
+ // gBS->DisconnectController ()
+ // This is used by those usb devices we don't plan
+ // to support. We can allocate
+ // controller handles for them, but we don't have
+ // device drivers to manage them.
+ //
+ NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status));
+
+ //
+ // If this device is hub, add to the hub index
+ //
+ if (IsHub (NewController)) {
+
+ NewController->IsUsbHub = TRUE;
+
+ //
+ // Configure Hub
+ //
+ Status = DoHubConfig (NewController);
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ //
+ // Create an event to do hub enumeration
+ //
+ gBS->CreateEvent (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ UsbEnumeration,
+ NewController,
+ &NewController->HubNotify
+ );
+
+ //
+ // Add request to do query hub status
+ // change endpoint
+ //
+ UsbIo = &NewController->UsbIo;
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ NewController->HubEndpointAddress, // Hub endpoint address
+ TRUE,
+ 100,
+ 1, // Hub ports < 7
+ OnHubInterruptComplete,
+ NewController
+ );
+ }
+ }
+ } else {
+ //
+ // Something disconnected from USB hub
+ //
+ DEBUG ((gUSBDebugLevel, "Something Device Detached on Hub port\n"));
+
+ OldUsbIoDevice = HubController->Children[StatusChangePort - 1];
+
+ UsbDeviceDeConfiguration (OldUsbIoDevice);
+
+ HubController->Children[StatusChangePort - 1] = NULL;
+
+ }
+
+ return ;
+ }
+
+ return ;
+ }
+}
+//
+// Clear port connection change status over a given root hub port
+//
+EFI_STATUS
+ClearRootPortConnectionChangeStatus (
+ UINT8 PortNum,
+ EFI_USB_HC_PROTOCOL *UsbHCInterface
+ )
+/*++
+
+ Routine Description:
+ Clear port connection change status over a given root hub port
+
+ Arguments:
+ PortNum - The given port.
+ UsbHCInterface - The EFI_USB_HC_PROTOCOL instance.
+
+ Returns:
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+ Status = UsbHCInterface->ClearRootHubPortFeature (
+ UsbHCInterface,
+ PortNum,
+ EfiUsbPortConnectChange
+ );
+ return Status;
+}
+
+STATIC
+USB_IO_CONTROLLER_DEVICE *
+CreateUsbIoControllerDevice (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ Allocate a structure for USB_IO_CONTROLLER_DEVICE
+
+ Arguments:
+ N/A
+
+ Returns:
+ A pointer to a USB_IO_CONTROLLER_DEVICE structure,
+ Or NULL.
+
+--*/
+{
+ USB_IO_CONTROLLER_DEVICE *UsbIoControllerDev;
+
+ //
+ // Allocate USB_IO_CONTROLLER_DEVICE structure
+ //
+ UsbIoControllerDev = NULL;
+ UsbIoControllerDev = AllocateZeroPool (sizeof (USB_IO_CONTROLLER_DEVICE));
+
+ if (UsbIoControllerDev == NULL) {
+ return NULL;
+ }
+
+ UsbIoControllerDev->Signature = USB_IO_CONTROLLER_SIGNATURE;
+
+ return UsbIoControllerDev;
+}
+
+STATIC
+EFI_STATUS
+InitUsbIoController (
+ IN USB_IO_CONTROLLER_DEVICE *UsbIoController
+ )
+/*++
+
+ Routine Description:
+ Init and install EFI_USB_IO_PROTOCOL onto that controller.
+
+ Arguments:
+ UsbIoController - The Controller to be operated.
+
+ Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ USB_DEVICE_PATH UsbNode;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_USB_HC_PROTOCOL *UsbHcProtocol;
+
+ //
+ // Build the child device path for each new USB_IO device
+ //
+ ZeroMem (&UsbNode, sizeof (UsbNode));
+ UsbNode.Header.Type = MESSAGING_DEVICE_PATH;
+ UsbNode.Header.SubType = MSG_USB_DP;
+ SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode));
+ UsbNode.InterfaceNumber = UsbIoController->InterfaceNumber;
+ UsbNode.ParentPortNumber = UsbIoController->ParentPort;
+ ParentDevicePath = UsbIoController->Parent->DevicePath;
+
+ UsbIoController->DevicePath =
+ AppendDevicePathNode (ParentDevicePath, &UsbNode.Header);
+ if (UsbIoController->DevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &UsbIoController->Handle,
+ &gEfiDevicePathProtocolGuid,
+ UsbIoController->DevicePath,
+ &gEfiUsbIoProtocolGuid,
+ &UsbIoController->UsbIo,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ UsbIoController->HostController,
+ &gEfiUsbHcProtocolGuid,
+ (VOID **) &UsbHcProtocol,
+ gUsbBusDriverBinding.DriverBindingHandle,
+ UsbIoController->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+ParentPortReset (
+ IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
+ IN BOOLEAN ReConfigure,
+ IN UINT8 RetryTimes
+ )
+/*++
+
+ Routine Description:
+ Reset parent hub port to which this device is connected.
+
+ Arguments:
+ UsbIoController - Indicating the Usb Controller Device.
+ Reconfigure - Do we need to reconfigure it.
+ RetryTimes - Retry Times when failed
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ USB_IO_DEVICE *ParentIoDev;
+ USB_IO_DEVICE *UsbIoDev;
+ USB_IO_CONTROLLER_DEVICE *ParentController;
+ UINT8 HubPort;
+ UINT32 Status;
+ EFI_STATUS Result;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 Address;
+
+ ParentController = UsbIoController->Parent;
+ ParentIoDev = ParentController->UsbDevice;
+ UsbIoDev = UsbIoController->UsbDevice;
+ HubPort = UsbIoController->ParentPort;
+
+ gBS->Stall (100 * 1000);
+
+ if (ParentIoDev->DeviceAddress == 1) {
+ DEBUG ((gUSBDebugLevel, "Reset from Root Hub 0x%x\n", HubPort));
+ ResetRootPort (ParentIoDev->BusController->UsbHCInterface, HubPort, RetryTimes);
+ } else {
+ DEBUG ((gUSBDebugLevel, "Reset from Hub, Addr 0x%x\n", ParentIoDev->DeviceAddress));
+ ResetHubPort (ParentController, HubPort + 1);
+ }
+ //
+ // If we only need port reset, just return
+ //
+ if (!ReConfigure) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Re-config that USB device
+ //
+ UsbIo = &UsbIoController->UsbIo;
+
+ //
+ // Assign a unique address to this device
+ //
+ Address = UsbIoDev->DeviceAddress;
+ UsbIoDev->DeviceAddress = 0;
+
+ Result = UsbSetDeviceAddress (UsbIo, Address, &Status);
+ UsbIoDev->DeviceAddress = Address;
+
+ if (EFI_ERROR (Result)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Set the device to the default configuration
+ //
+ Result = UsbSetDefaultConfiguration (UsbIoDev);
+ if (EFI_ERROR (Result)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+UsbPortReset (
+ IN EFI_USB_IO_PROTOCOL *This
+ )
+/*++
+
+ Routine Description:
+ Resets and reconfigures the USB controller. This function will
+ work for all USB devices except USB Hub Controllers.
+
+ Arguments:
+ This - Indicates the calling context.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_INVALID_PARAMETER
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ USB_IO_CONTROLLER_DEVICE *UsbIoController;
+ EFI_STATUS Status;
+
+ UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
+
+ //
+ // Since at this time, this device has already been configured,
+ // it needs to be re-configured.
+ //
+ Status = ParentPortReset (UsbIoController, TRUE, 0);
+
+ return Status;
+}
+
+EFI_STATUS
+ResetRootPort (
+ IN EFI_USB_HC_PROTOCOL *UsbHCInterface,
+ IN UINT8 PortNum,
+ IN UINT8 RetryTimes
+ )
+/*++
+
+ Routine Description:
+ Reset Root Hub port.
+
+ Arguments:
+ UsbHCInterface - The EFI_USB_HC_PROTOCOL instance.
+ PortNum - The given port to be reset.
+ RetryTimes - RetryTimes when failed
+ Returns:
+ N/A
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // reset root port
+ //
+ Status = UsbHCInterface->SetRootHubPortFeature (
+ UsbHCInterface,
+ PortNum,
+ EfiUsbPortReset
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ gBS->Stall (50 * 1000);
+
+ //
+ // clear reset root port
+ //
+ Status = UsbHCInterface->ClearRootHubPortFeature (
+ UsbHCInterface,
+ PortNum,
+ EfiUsbPortReset
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ gBS->Stall (1000);
+
+ Status = ClearRootPortConnectionChangeStatus (PortNum, UsbHCInterface);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Set port enable
+ //
+ Status = UsbHCInterface->SetRootHubPortFeature (
+ UsbHCInterface,
+ PortNum,
+ EfiUsbPortEnable
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = UsbHCInterface->ClearRootHubPortFeature (
+ UsbHCInterface,
+ PortNum,
+ EfiUsbPortEnableChange
+ );
+ gBS->Stall ((1 + RetryTimes) * 50 * 1000);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+ResetHubPort (
+ IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
+ IN UINT8 PortIndex
+ )
+/*++
+
+ Routine Description:
+ Reset Hub port.
+
+ Arguments:
+ UsbIoController - The USB_IO_CONTROLLER_DEVICE instance.
+ PortIndex - The given port to be reset.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_PORT_STATUS HubPortStatus;
+ UINT8 Number;
+
+ ASSERT (UsbIoController->IsUsbHub == TRUE);
+
+ UsbIo = &UsbIoController->UsbIo;
+
+ HubSetPortFeature (
+ UsbIo,
+ PortIndex,
+ EfiUsbPortReset
+ );
+
+ gBS->Stall (10 * 1000);
+
+ //
+ // Wait for port reset complete
+ //
+ Number = 10;
+ do {
+ HubGetPortStatus (
+ UsbIo,
+ PortIndex,
+ (UINT32 *) &HubPortStatus
+ );
+ gBS->Stall (10 * 100);
+ Number -= 1;
+ } while ((HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0 && Number > 0);
+
+ if (Number == 0) {
+ //
+ // Cannot reset port, return error
+ //
+ return EFI_DEVICE_ERROR;
+ }
+
+ gBS->Stall (1000);
+
+ HubGetPortStatus (
+ UsbIo,
+ PortIndex,
+ (UINT32 *) &HubPortStatus
+ );
+ //
+ // reset port will cause some bits change, clear them
+ //
+ if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) {
+ DEBUG ((gUSBDebugLevel, "Port Enable Change\n"));
+ HubClearPortFeature (
+ UsbIo,
+ PortIndex,
+ EfiUsbPortEnableChange
+ );
+ }
+
+ if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) {
+ DEBUG ((gUSBDebugLevel, "Port Reset Change\n"));
+ HubClearPortFeature (
+ UsbIo,
+ PortIndex,
+ EfiUsbPortResetChange
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+
+
+STATIC
+EFI_STATUS
+ReportUsbStatusCode (
+ IN USB_BUS_CONTROLLER_DEVICE *UsbBusController,
+ IN EFI_STATUS_CODE_TYPE Type,
+ IN EFI_STATUS_CODE_VALUE Code
+ )
+/*++
+
+Routine Description:
+
+ report a error Status code of USB bus driver controller
+
+ Arguments:
+ UsbBusController - USB_BUS_CONTROLLER_DEVICE
+ Type - EFI_STATUS_CODE_TYPE
+ Code - EFI_STATUS_CODE_VALUE
+ Returns:
+
+ None
+
+--*/
+{
+ return REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ Type,
+ Code,
+ UsbBusController->DevicePath
+ );
+}
+
+
+EFI_STATUS
+IsDeviceDisconnected (
+ IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
+ IN OUT BOOLEAN *Disconnected
+ )
+/*++
+
+ Routine Description:
+ Reset if the device is disconencted or not
+
+ Arguments:
+ UsbIoController - Indicating the Usb Controller Device.
+ Disconnected - Indicate whether the device is disconencted or not
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ USB_IO_DEVICE *ParentIoDev;
+ USB_IO_DEVICE *UsbIoDev;
+ USB_IO_CONTROLLER_DEVICE *ParentController;
+ UINT8 HubPort;
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_PORT_STATUS PortStatus;
+ EFI_USB_HC_PROTOCOL *UsbHCInterface;
+
+ ParentController = UsbIoController->Parent;
+ ParentIoDev = ParentController->UsbDevice;
+ UsbIoDev = UsbIoController->UsbDevice;
+ HubPort = UsbIoController->ParentPort;
+
+ if (ParentIoDev->DeviceAddress == 1) {
+ //
+ // Connected to the root hub
+ //
+ UsbHCInterface = ParentIoDev->BusController->UsbHCInterface;
+ Status = UsbHCInterface->GetRootHubPortStatus (
+ UsbHCInterface,
+ HubPort,
+ &PortStatus
+ );
+
+ } else {
+ UsbIo = &UsbIoController->UsbIo;
+ Status = HubGetPortStatus (
+ &ParentController->UsbIo,
+ HubPort + 1,
+ (UINT32 *) &PortStatus
+ );
+
+ if (EFI_ERROR (Status)) {
+ return IsDeviceDisconnected (ParentController, Disconnected);
+ }
+ }
+
+ *Disconnected = FALSE;
+
+ if (!IsPortConnect (PortStatus.PortStatus)) {
+ *Disconnected = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h
new file mode 100644
index 0000000000..b32620342c
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h
@@ -0,0 +1,261 @@
+/*++
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name:
+
+ usbbus.h
+
+ Abstract:
+
+ Header file for USB bus driver Interface
+
+ Revision History
+
+
+
+--*/
+
+#ifndef _EFI_USB_BUS_H
+#define _EFI_USB_BUS_H
+
+
+#include <IndustryStandard/usb.h>
+#include "Hub.h"
+#include "Usbutil.h"
+
+//#ifdef EFI_DEBUG
+extern UINTN gUSBDebugLevel;
+extern UINTN gUSBErrorLevel;
+//#endif
+
+#define MICROSECOND 10000
+#define ONESECOND (1000 * MICROSECOND)
+#define BUSPOLLING_PERIOD ONESECOND
+//
+// We define some maximun value here
+//
+#define USB_MAXCONFIG 8
+#define USB_MAXALTSETTING 4
+#define USB_MAXINTERFACES 32
+#define USB_MAXENDPOINTS 16
+#define USB_MAXSTRINGS 16
+#define USB_MAXLANID 16
+#define USB_MAXCHILDREN 8
+#define USB_MAXCONTROLLERS 4
+
+#define USB_IO_CONTROLLER_SIGNATURE EFI_SIGNATURE_32 ('u', 's', 'b', 'd')
+
+typedef struct {
+ LIST_ENTRY Link;
+ UINT16 StringIndex;
+ CHAR16 *String;
+} STR_LIST_ENTRY;
+
+typedef struct {
+ LIST_ENTRY Link;
+ UINT16 Toggle;
+ EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+} ENDPOINT_DESC_LIST_ENTRY;
+
+typedef struct {
+ LIST_ENTRY Link;
+ EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+ LIST_ENTRY EndpointDescListHead;
+} INTERFACE_DESC_LIST_ENTRY;
+
+typedef struct {
+ LIST_ENTRY Link;
+ EFI_USB_CONFIG_DESCRIPTOR CongfigDescriptor;
+ LIST_ENTRY InterfaceDescListHead;
+ UINTN ActiveInterface;
+} CONFIG_DESC_LIST_ENTRY;
+
+//
+// Forward declaring
+//
+struct usb_io_device;
+
+//
+// This is used to form the USB Controller Handle
+//
+typedef struct usb_io_controller_device {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_USB_IO_PROTOCOL UsbIo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_HANDLE HostController;
+ UINT8 CurrentConfigValue;
+ UINT8 InterfaceNumber;
+ struct usb_io_device *UsbDevice;
+
+ BOOLEAN IsUsbHub;
+ BOOLEAN IsManagedByDriver;
+
+ //
+ // Fields specified for USB Hub
+ //
+ EFI_EVENT HubNotify;
+ UINT8 HubEndpointAddress;
+ UINT8 StatusChangePort;
+ UINT8 DownstreamPorts;
+
+ UINT8 ParentPort;
+ struct usb_io_controller_device *Parent;
+ struct usb_io_device *Children[USB_MAXCHILDREN];
+} USB_IO_CONTROLLER_DEVICE;
+
+#define USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS(a) \
+ CR(a, USB_IO_CONTROLLER_DEVICE, UsbIo, USB_IO_CONTROLLER_SIGNATURE)
+
+//
+// This is used to keep the topology of USB bus
+//
+struct _usb_bus_controller_device;
+
+typedef struct usb_io_device {
+ UINT8 DeviceAddress;
+ BOOLEAN IsConfigured;
+ BOOLEAN IsSlowDevice;
+ EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor;
+ LIST_ENTRY ConfigDescListHead;
+ CONFIG_DESC_LIST_ENTRY *ActiveConfig;
+ UINT16 LangID[USB_MAXLANID];
+
+ struct _usb_bus_controller_device *BusController;
+
+ //
+ // Track the controller handle
+ //
+ UINT8 NumOfControllers;
+ USB_IO_CONTROLLER_DEVICE *UsbController[USB_MAXCONTROLLERS];
+
+} USB_IO_DEVICE;
+
+//
+// Usb Bus Controller device strcuture
+//
+#define EFI_USB_BUS_PROTOCOL_GUID \
+ { 0x2B2F68CC, 0x0CD2, 0x44cf, { 0x8E, 0x8B, 0xBB, 0xA2, 0x0B, 0x1B, 0x5B, 0x75 } }
+
+typedef struct _EFI_USB_BUS_PROTOCOL {
+ UINT64 Reserved;
+} EFI_USB_BUS_PROTOCOL;
+
+#define USB_BUS_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('u', 'b', 'u', 's')
+
+typedef struct _usb_bus_controller_device {
+ UINTN Signature;
+
+ EFI_USB_BUS_PROTOCOL BusIdentify;
+ EFI_USB_HC_PROTOCOL *UsbHCInterface;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINT8 AddressPool[16];
+ USB_IO_DEVICE *Root;
+} USB_BUS_CONTROLLER_DEVICE;
+
+#define USB_BUS_CONTROLLER_DEVICE_FROM_THIS(a) \
+ CR(a, USB_BUS_CONTROLLER_DEVICE, BusIdentify, USB_BUS_DEVICE_SIGNATURE)
+
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gUsbBusDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gUsbBusComponentName;
+extern EFI_GUID gUSBBusDriverGuid;
+
+//
+// Usb Device Configuration functions
+//
+BOOLEAN
+IsHub (
+ IN USB_IO_CONTROLLER_DEVICE *Dev
+ );
+
+EFI_STATUS
+UsbGetStringtable (
+ IN USB_IO_DEVICE *UsbIoDevice
+ );
+
+EFI_STATUS
+UsbGetAllConfigurations (
+ IN USB_IO_DEVICE *UsbIoDevice
+ );
+
+EFI_STATUS
+UsbSetConfiguration (
+ IN USB_IO_DEVICE *Dev,
+ IN UINTN ConfigurationValue
+ );
+
+EFI_STATUS
+UsbSetDefaultConfiguration (
+ IN USB_IO_DEVICE *Dev
+ );
+
+//
+// Device Deconfiguration functions
+//
+VOID
+UsbDestroyAllConfiguration (
+ IN USB_IO_DEVICE *UsbIoDevice
+ );
+
+EFI_STATUS
+DoHubConfig (
+ IN USB_IO_CONTROLLER_DEVICE *HubIoDevice
+ );
+
+VOID
+GetDeviceEndPointMaxPacketLength (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 EndpointAddr,
+ OUT UINT8 *MaxPacketLength
+ );
+
+VOID
+GetDataToggleBit (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 EndpointAddr,
+ OUT UINT8 *DataToggle
+ );
+
+VOID
+SetDataToggleBit (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 EndpointAddr,
+ IN UINT8 DataToggle
+ );
+
+INTERFACE_DESC_LIST_ENTRY *
+FindInterfaceListEntry (
+ IN EFI_USB_IO_PROTOCOL *This
+ );
+
+ENDPOINT_DESC_LIST_ENTRY *
+FindEndPointListEntry (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT8 EndPointAddress
+ );
+
+
+EFI_STATUS
+IsDeviceDisconnected (
+ IN USB_IO_CONTROLLER_DEVICE *UsbIoController,
+ IN OUT BOOLEAN *Disconnected
+ );
+
+EFI_STATUS
+UsbDeviceDeConfiguration (
+ IN USB_IO_DEVICE *UsbIoDevice
+ );
+
+
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c
new file mode 100644
index 0000000000..bd87c5ca2e
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c
@@ -0,0 +1,1176 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name:
+
+ UsbIo.c
+
+ Abstract:
+
+ USB I/O Abstraction Driver
+
+ Revision History
+
+--*/
+
+#include "usbbus.h"
+
+//
+// USB I/O Support Function Prototypes
+//
+STATIC
+EFI_STATUS
+EFIAPI
+UsbControlTransfer (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT32 Timeout,
+ IN OUT VOID *Data, OPTIONAL
+ IN UINTN DataLength, OPTIONAL
+ OUT UINT32 *Status
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbBulkTransfer (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT8 DeviceEndpoint,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN Timeout,
+ OUT UINT32 *Status
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbAsyncInterruptTransfer (
+ IN EFI_USB_IO_PROTOCOL * This,
+ IN UINT8 DeviceEndpoint,
+ IN BOOLEAN IsNewTransfer,
+ IN UINTN PollingInterval, OPTIONAL
+ IN UINTN DataLength, OPTIONAL
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallBack, OPTIONAL
+ IN VOID *Context OPTIONAL
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbSyncInterruptTransfer (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT8 DeviceEndpoint,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN Timeout,
+ OUT UINT32 *Status
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbIsochronousTransfer (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT8 DeviceEndpoint,
+ IN OUT VOID *Data,
+ IN UINTN DataLength,
+ OUT UINT32 *Status
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbAsyncIsochronousTransfer (
+ IN EFI_USB_IO_PROTOCOL * This,
+ IN UINT8 DeviceEndpoint,
+ IN OUT VOID *Data,
+ IN UINTN DataLength,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context OPTIONAL
+ );
+
+extern
+EFI_STATUS
+EFIAPI
+UsbPortReset (
+ IN EFI_USB_IO_PROTOCOL *This
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbGetDeviceDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ OUT EFI_USB_DEVICE_DESCRIPTOR *DeviceDescriptor
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbGetActiveConfigDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ OUT EFI_USB_CONFIG_DESCRIPTOR *ConfigurationDescriptor
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbGetInterfaceDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ OUT EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbGetEndpointDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT8 EndpointIndex,
+ OUT EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbGetStringDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 LangID,
+ IN UINT8 StringIndex,
+ OUT CHAR16 **String
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbGetSupportedLanguages (
+ IN EFI_USB_IO_PROTOCOL *This,
+ OUT UINT16 **LangIDTable,
+ OUT UINT16 *TableSize
+ );
+
+//
+// USB I/O Interface structure
+//
+STATIC EFI_USB_IO_PROTOCOL UsbIoInterface = {
+ UsbControlTransfer,
+ UsbBulkTransfer,
+ UsbAsyncInterruptTransfer,
+ UsbSyncInterruptTransfer,
+ UsbIsochronousTransfer,
+ UsbAsyncIsochronousTransfer,
+ UsbGetDeviceDescriptor,
+ UsbGetActiveConfigDescriptor,
+ UsbGetInterfaceDescriptor,
+ UsbGetEndpointDescriptor,
+ UsbGetStringDescriptor,
+ UsbGetSupportedLanguages,
+ UsbPortReset
+};
+
+VOID
+InitializeUsbIoInstance (
+ IN USB_IO_CONTROLLER_DEVICE *UsbIoController
+ )
+{
+ //
+ // Copy EFI_USB_IO protocol instance
+ //
+ CopyMem (
+ &UsbIoController->UsbIo,
+ &UsbIoInterface,
+ sizeof (EFI_USB_IO_PROTOCOL)
+ );
+}
+//
+// Implementation
+//
+STATIC
+EFI_STATUS
+EFIAPI
+UsbControlTransfer (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT32 Timeout,
+ IN OUT VOID *Data, OPTIONAL
+ IN UINTN DataLength, OPTIONAL
+ OUT UINT32 *Status
+ )
+/*++
+
+ Routine Description:
+ This function is used to manage a USB device with a control transfer pipe.
+
+ Arguments:
+ This - Indicates calling context.
+ Request - A pointer to the USB device request that will be sent to
+ the USB device.
+ Direction - Indicates the data direction.
+ Data - A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ Timeout - Indicates the transfer should be completed within this time
+ frame.
+ DataLength - The size, in bytes, of the data buffer specified by Data.
+ Status - A pointer to the result of the USB transfer.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_INVALID_PARAMETER
+ EFI_OUT_OF_RESOURCES
+ EFI_TIMEOUT
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ USB_IO_CONTROLLER_DEVICE *UsbIoController;
+ EFI_USB_HC_PROTOCOL *UsbHCInterface;
+ EFI_STATUS RetStatus;
+ USB_IO_DEVICE *UsbIoDevice;
+ UINT8 MaxPacketLength;
+ UINT32 TransferResult;
+ BOOLEAN Disconnected;
+ //
+ // Parameters Checking
+ //
+ if (Status == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // leave the HostController's ControlTransfer
+ // to perform other parameters checking
+ //
+ UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
+ UsbIoDevice = UsbIoController->UsbDevice;
+ UsbHCInterface = UsbIoDevice->BusController->UsbHCInterface;
+ MaxPacketLength = UsbIoDevice->DeviceDescriptor.MaxPacketSize0;
+
+
+ if (Request->Request == USB_DEV_CLEAR_FEATURE &&
+ Request->RequestType == 0x02 &&
+ Request->Value == EfiUsbEndpointHalt) {
+ //
+ //Reduce the remove delay time for system response
+ //
+ IsDeviceDisconnected (UsbIoController, &Disconnected);
+ if (!EFI_ERROR (Status) && Disconnected == TRUE) {
+ DEBUG ((gUSBErrorLevel, "Device is disconnected when trying reset\n"));
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+
+
+ //
+ // using HostController's ControlTransfer to complete the request
+ //
+ RetStatus = UsbHCInterface->ControlTransfer (
+ UsbHCInterface,
+ UsbIoDevice->DeviceAddress,
+ UsbIoDevice->IsSlowDevice,
+ MaxPacketLength,
+ Request,
+ Direction,
+ Data,
+ &DataLength,
+ (UINTN) Timeout,
+ &TransferResult
+ );
+ *Status = TransferResult;
+
+ if (Request->Request == USB_DEV_CLEAR_FEATURE &&
+ Request->RequestType == 0x02 &&
+ Request->Value == EfiUsbEndpointHalt) {
+ //
+ // This is a UsbClearEndpointHalt request
+ // Need to clear data toggle
+ // Request.Index == EndpointAddress
+ //
+ if (!EFI_ERROR (RetStatus) && TransferResult == EFI_USB_NOERROR) {
+ SetDataToggleBit (
+ This,
+ (UINT8) Request->Index,
+ 0
+ );
+ }
+ }
+ return RetStatus;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbBulkTransfer (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT8 DeviceEndpoint,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN Timeout,
+ OUT UINT32 *Status
+ )
+/*++
+
+ Routine Description:
+ This function is used to manage a USB device with the bulk transfer pipe.
+
+ Arguments:
+ This - Indicates calling context.
+ DeviceEndpoint - The destination USB device endpoint to which the device
+ request is being sent.
+ Data - A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - On input, the size, in bytes, of the data buffer
+ specified by Data. On output, the number of bytes that
+ were actually transferred.
+ Timeout - Indicates the transfer should be completed within this
+ time frame.
+ Status - This parameter indicates the USB transfer status.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_INVALID_PARAMETER
+ EFI_OUT_OF_RESOURCES
+ EFI_TIMEOUT
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ USB_IO_DEVICE *UsbIoDev;
+ UINT8 MaxPacketLength;
+ UINT8 DataToggle;
+ UINT8 OldToggle;
+ EFI_STATUS RetStatus;
+ EFI_USB_HC_PROTOCOL *UsbHCInterface;
+ USB_IO_CONTROLLER_DEVICE *UsbIoController;
+ ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry;
+ UINT32 TransferResult;
+
+ UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
+ UsbIoDev = UsbIoController->UsbDevice;
+ UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;
+
+ //
+ // Parameters Checking
+ //
+ if ((DeviceEndpoint & 0x7F) == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DeviceEndpoint & 0x7F) > 15) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Status == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EndPointListEntry = FindEndPointListEntry (
+ This,
+ DeviceEndpoint
+ );
+
+ if (EndPointListEntry == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((EndPointListEntry->EndpointDescriptor.Attributes & 0x03) != 0x02) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // leave the HostController's BulkTransfer
+ // to perform other parameters checking
+ //
+ GetDeviceEndPointMaxPacketLength (
+ This,
+ DeviceEndpoint,
+ &MaxPacketLength
+ );
+
+ GetDataToggleBit (
+ This,
+ DeviceEndpoint,
+ &DataToggle
+ );
+
+ OldToggle = DataToggle;
+
+ //
+ // using HostController's BulkTransfer to complete the request
+ //
+ RetStatus = UsbHCInterface->BulkTransfer (
+ UsbHCInterface,
+ UsbIoDev->DeviceAddress,
+ DeviceEndpoint,
+ MaxPacketLength,
+ Data,
+ DataLength,
+ &DataToggle,
+ Timeout,
+ &TransferResult
+ );
+
+ if (OldToggle != DataToggle) {
+ //
+ // Write the toggle back
+ //
+ SetDataToggleBit (
+ This,
+ DeviceEndpoint,
+ DataToggle
+ );
+ }
+
+ *Status = TransferResult;
+
+ return RetStatus;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbSyncInterruptTransfer (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT8 DeviceEndpoint,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN UINTN Timeout,
+ OUT UINT32 *Status
+ )
+/*++
+
+ Routine Description:
+ Usb Sync Interrupt Transfer
+
+ Arguments:
+ This - Indicates calling context.
+ DeviceEndpoint - The destination USB device endpoint to which the device
+ request is being sent.
+ Data - A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - On input, the size, in bytes, of the data buffer
+ specified by Data. On output, the number of bytes that
+ were actually transferred.
+ Timeout - Indicates the transfer should be completed within this
+ time frame.
+ Status - This parameter indicates the USB transfer status.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_INVALID_PARAMETER
+ EFI_OUT_OF_RESOURCES
+ EFI_TIMEOUT
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ USB_IO_DEVICE *UsbIoDev;
+ UINT8 MaxPacketLength;
+ UINT8 DataToggle;
+ UINT8 OldToggle;
+ EFI_STATUS RetStatus;
+ EFI_USB_HC_PROTOCOL *UsbHCInterface;
+ USB_IO_CONTROLLER_DEVICE *UsbIoController;
+ ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry;
+
+ //
+ // Parameters Checking
+ //
+ if ((DeviceEndpoint & 0x7F) == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DeviceEndpoint & 0x7F) > 15) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Status == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EndPointListEntry = FindEndPointListEntry (
+ This,
+ DeviceEndpoint
+ );
+
+ if (EndPointListEntry == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((EndPointListEntry->EndpointDescriptor.Attributes & 0x03) != 0x03) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // leave the HostController's SyncInterruptTransfer
+ // to perform other parameters checking
+ //
+ UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
+ UsbIoDev = UsbIoController->UsbDevice;
+ UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;
+
+ GetDeviceEndPointMaxPacketLength (
+ This,
+ DeviceEndpoint,
+ &MaxPacketLength
+ );
+
+ GetDataToggleBit (
+ This,
+ DeviceEndpoint,
+ &DataToggle
+ );
+
+ OldToggle = DataToggle;
+ //
+ // using HostController's SyncInterruptTransfer to complete the request
+ //
+ RetStatus = UsbHCInterface->SyncInterruptTransfer (
+ UsbHCInterface,
+ UsbIoDev->DeviceAddress,
+ DeviceEndpoint,
+ UsbIoDev->IsSlowDevice,
+ MaxPacketLength,
+ Data,
+ DataLength,
+ &DataToggle,
+ Timeout,
+ Status
+ );
+
+ if (OldToggle != DataToggle) {
+ //
+ // Write the toggle back
+ //
+ SetDataToggleBit (
+ This,
+ DeviceEndpoint,
+ DataToggle
+ );
+ }
+
+ return RetStatus;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbAsyncInterruptTransfer (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT8 DeviceEndpoint,
+ IN BOOLEAN IsNewTransfer,
+ IN UINTN PollingInterval, OPTIONAL
+ IN UINTN DataLength, OPTIONAL
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallBack, OPTIONAL
+ IN VOID *Context OPTIONAL
+ )
+/*++
+
+ Routine Description:
+ Usb Async Interrput Transfer
+
+ Arguments:
+ This - Indicates calling context.
+ DeviceEndpoint - The destination USB device endpoint to which the
+ device request is being sent.
+ IsNewTransfer - If TRUE, a new transfer will be submitted to USB
+ controller. If FALSE, the interrupt transfer is
+ deleted from the device's interrupt transfer queue.
+ PollingInterval - Indicates the periodic rate, in milliseconds, that
+ the transfer is to be executed.
+ DataLength - Specifies the length, in bytes, of the data to be
+ received from the USB device.
+ InterruptCallback - The Callback function. This function is called if
+ the asynchronous interrupt transfer is completed.
+ Context - Passed to InterruptCallback
+ Returns:
+ EFI_SUCCESS
+ EFI_INVALID_PARAMETER
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ USB_IO_DEVICE *UsbIoDev;
+ UINT8 MaxPacketLength;
+ UINT8 DataToggle;
+ EFI_USB_HC_PROTOCOL *UsbHCInterface;
+ EFI_STATUS RetStatus;
+ USB_IO_CONTROLLER_DEVICE *UsbIoController;
+ ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry;
+
+ //
+ // Check endpoint
+ //
+ if ((DeviceEndpoint & 0x7F) == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DeviceEndpoint & 0x7F) > 15) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ EndpointListEntry = FindEndPointListEntry (
+ This,
+ DeviceEndpoint
+ );
+
+ if (EndpointListEntry == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((EndpointListEntry->EndpointDescriptor.Attributes & 0x03) != 0x03) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
+ UsbIoDev = UsbIoController->UsbDevice;
+ UsbHCInterface = UsbIoDev->BusController->UsbHCInterface;
+
+ if (!IsNewTransfer) {
+ //
+ // Delete this transfer
+ //
+ UsbHCInterface->AsyncInterruptTransfer (
+ UsbHCInterface,
+ UsbIoDev->DeviceAddress,
+ DeviceEndpoint,
+ UsbIoDev->IsSlowDevice,
+ 0,
+ FALSE,
+ &DataToggle,
+ PollingInterval,
+ DataLength,
+ NULL,
+ NULL
+ );
+
+ //
+ // We need to store the toggle value
+ //
+ SetDataToggleBit (
+ This,
+ DeviceEndpoint,
+ DataToggle
+ );
+
+ return EFI_SUCCESS;
+ }
+
+ GetDeviceEndPointMaxPacketLength (
+ This,
+ DeviceEndpoint,
+ &MaxPacketLength
+ );
+
+ GetDataToggleBit (
+ This,
+ DeviceEndpoint,
+ &DataToggle
+ );
+
+ RetStatus = UsbHCInterface->AsyncInterruptTransfer (
+ UsbHCInterface,
+ UsbIoDev->DeviceAddress,
+ DeviceEndpoint,
+ UsbIoDev->IsSlowDevice,
+ MaxPacketLength,
+ TRUE,
+ &DataToggle,
+ PollingInterval,
+ DataLength,
+ InterruptCallBack,
+ Context
+ );
+
+ return RetStatus;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbIsochronousTransfer (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT8 DeviceEndpoint,
+ IN OUT VOID *Data,
+ IN UINTN DataLength,
+ OUT UINT32 *Status
+ )
+/*++
+
+ Routine Description:
+ Usb Isochronous Transfer
+
+ Arguments:
+ This - Indicates calling context.
+ DeviceEndpoint - The destination USB device endpoint to which the
+ device request is being sent.
+ Data - A pointer to the buffer of data that will be
+ transmitted to USB device or received from USB device.
+ DataLength - The size, in bytes, of the data buffer specified by
+ Data.
+ Status - This parameter indicates the USB transfer status.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_INVALID_PARAMETER
+ EFI_OUT_OF_RESOURCES
+ EFI_TIMEOUT
+ EFI_DEVICE_ERROR
+ EFI_UNSUPPORTED
+--*/
+{
+ //
+ // Currently we don't support this transfer
+ //
+ return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbAsyncIsochronousTransfer (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT8 DeviceEndpoint,
+ IN OUT VOID *Data,
+ IN UINTN DataLength,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Usb Async Isochronous Transfer
+
+Arguments:
+
+ This - EFI_USB_IO_PROTOCOL
+ DeviceEndpoint - DeviceEndpoint number
+ Data - Data to transfer
+ DataLength - DataLength
+ IsochronousCallBack - Isochronous CallBack function
+ Context - Passed to IsochronousCallBack function
+Returns:
+
+ EFI_UNSUPPORTED - Unsupported now
+
+--*/
+{
+ //
+ // Currently we don't support this transfer
+ //
+ return EFI_UNSUPPORTED;
+}
+//
+// Here is new definitions
+//
+STATIC
+EFI_STATUS
+EFIAPI
+UsbGetDeviceDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ OUT EFI_USB_DEVICE_DESCRIPTOR *DeviceDescriptor
+ )
+/*++
+
+ Routine Description:
+ Retrieves the USB Device Descriptor.
+
+ Arguments:
+ This - Indicates the calling context.
+ DeviceDescriptor - A pointer to the caller allocated USB Device
+ Descriptor.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_INVALID_PARAMETER
+ EFI_NOT_FOUND
+
+--*/
+{
+ USB_IO_CONTROLLER_DEVICE *UsbIoController;
+ USB_IO_DEVICE *UsbIoDev;
+
+ //
+ // This function just wrapps UsbGetDeviceDescriptor.
+ //
+
+ if (DeviceDescriptor == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
+ UsbIoDev = UsbIoController->UsbDevice;
+
+ if (!UsbIoDev->IsConfigured) {
+ return EFI_NOT_FOUND;
+ }
+
+ CopyMem (
+ DeviceDescriptor,
+ &UsbIoDev->DeviceDescriptor,
+ sizeof (EFI_USB_DEVICE_DESCRIPTOR)
+ );
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbGetActiveConfigDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ OUT EFI_USB_CONFIG_DESCRIPTOR *ConfigurationDescriptor
+ )
+/*++
+
+ Routine Description:
+ Retrieves the current USB configuration Descriptor.
+
+ Arguments:
+ This - Indicates the calling context.
+ ConfigurationDescriptor - A pointer to the caller allocated USB active
+ Configuration Descriptor.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_INVALID_PARAMETER
+ EFI_NOT_FOUND
+
+--*/
+{
+ USB_IO_DEVICE *UsbIoDev;
+ USB_IO_CONTROLLER_DEVICE *UsbIoController;
+
+ //
+ // This function just wrapps UsbGetActiveConfigDescriptor.
+ //
+ if (ConfigurationDescriptor == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
+ UsbIoDev = UsbIoController->UsbDevice;
+
+ if (!UsbIoDev->IsConfigured) {
+ return EFI_NOT_FOUND;
+ }
+
+ CopyMem (
+ ConfigurationDescriptor,
+ &(UsbIoDev->ActiveConfig->CongfigDescriptor),
+ sizeof (EFI_USB_CONFIG_DESCRIPTOR)
+ );
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbGetInterfaceDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ OUT EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor
+ )
+/*++
+
+ Routine Description:
+ Retrieves the interface Descriptor for that controller.
+
+ Arguments:
+ This - Indicates the calling context.
+ InterfaceDescriptor - A pointer to the caller allocated USB interface
+ Descriptor.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_INVALID_PARAMETER
+ EFI_NOT_FOUND
+
+--*/
+{
+ INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry;
+
+ if (InterfaceDescriptor == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InterfaceListEntry = FindInterfaceListEntry (This);
+
+ if (InterfaceListEntry == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ CopyMem (
+ InterfaceDescriptor,
+ &(InterfaceListEntry->InterfaceDescriptor),
+ sizeof (EFI_USB_INTERFACE_DESCRIPTOR)
+ );
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbGetEndpointDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT8 EndpointIndex,
+ OUT EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor
+ )
+/*++
+
+ Routine Description:
+ Retrieves the endpoint Descriptor for a given endpoint.
+
+ Arguments:
+ This - Indicates the calling context.
+ EndpointIndex - Indicates which endpoint descriptor to retrieve.
+ The valid range is 0..15.
+ EndpointDescriptor - A pointer to the caller allocated USB Endpoint
+ Descriptor of a USB controller.
+
+ Returns:
+ EFI_SUCCESS - The endpoint descriptor was retrieved successfully.
+ EFI_INVALID_PARAMETER - EndpointIndex is not valid.
+ - EndpointDescriptor is NULL.
+ EFI_NOT_FOUND - The endpoint descriptor cannot be found.
+ The device may not be correctly configured.
+
+--*/
+{
+ INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry;
+ LIST_ENTRY *EndpointListHead;
+ ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry;
+
+ if (EndpointDescriptor == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (EndpointIndex > 15) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InterfaceListEntry = FindInterfaceListEntry (This);
+
+ if (InterfaceListEntry == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ EndpointListHead = (LIST_ENTRY *) (&InterfaceListEntry->EndpointDescListHead);
+ EndpointListEntry = (ENDPOINT_DESC_LIST_ENTRY *) (EndpointListHead->ForwardLink);
+
+ if (EndpointIndex >= InterfaceListEntry->InterfaceDescriptor.NumEndpoints) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Loop all endpoint descriptor to get match one.
+ //
+ while (EndpointIndex != 0) {
+ EndpointListEntry = (ENDPOINT_DESC_LIST_ENTRY *) (EndpointListEntry->Link.ForwardLink);
+ EndpointIndex--;
+ }
+
+ CopyMem (
+ EndpointDescriptor,
+ &EndpointListEntry->EndpointDescriptor,
+ sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)
+ );
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbGetSupportedLanguages (
+ IN EFI_USB_IO_PROTOCOL *This,
+ OUT UINT16 **LangIDTable,
+ OUT UINT16 *TableSize
+ )
+/*++
+
+ Routine Description:
+ Get all the languages that the USB device supports
+
+ Arguments:
+ This - Indicates the calling context.
+ LangIDTable - Language ID for the string the caller wants to get.
+ TableSize - The size, in bytes, of the table LangIDTable.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+
+--*/
+{
+ USB_IO_DEVICE *UsbIoDev;
+ USB_IO_CONTROLLER_DEVICE *UsbIoController;
+ UINTN Index;
+ BOOLEAN Found;
+
+ UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
+ UsbIoDev = UsbIoController->UsbDevice;
+
+ Found = FALSE;
+ Index = 0;
+ //
+ // Loop language table
+ //
+ while (UsbIoDev->LangID[Index]) {
+ Found = TRUE;
+ Index++;
+ }
+
+ if (!Found) {
+ return EFI_NOT_FOUND;
+ }
+
+ *LangIDTable = UsbIoDev->LangID;
+ *TableSize = (UINT16) Index;
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbGetStringDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 LangID,
+ IN UINT8 StringIndex,
+ OUT CHAR16 **String
+ )
+/*++
+
+ Routine Description:
+ Get a given string descriptor
+
+ Arguments:
+ This - Indicates the calling context.
+ LangID - The Language ID for the string being retrieved.
+ StringIndex - The ID of the string being retrieved.
+ String - A pointer to a buffer allocated by this function
+ with AllocatePool() to store the string. If this
+ function returns EFI_SUCCESS, it stores the string
+ the caller wants to get. The caller should release
+ the string buffer with FreePool() after the string
+ is not used any more.
+ Returns:
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ UINT32 Status;
+ EFI_STATUS Result;
+ EFI_USB_STRING_DESCRIPTOR *StrDescriptor;
+ UINT8 *Buffer;
+ CHAR16 *UsbString;
+ UINT16 TempBuffer;
+ USB_IO_DEVICE *UsbIoDev;
+ UINT8 Index;
+ BOOLEAN Found;
+ USB_IO_CONTROLLER_DEVICE *UsbIoController;
+
+ if (StringIndex == 0) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Search LanguageID, check if it is supported by this device
+ //
+ if (LangID == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
+ UsbIoDev = UsbIoController->UsbDevice;
+
+ Found = FALSE;
+ Index = 0;
+ while (UsbIoDev->LangID[Index]) {
+ if (UsbIoDev->LangID[Index] == LangID) {
+ Found = TRUE;
+ break;
+ }
+
+ Index++;
+ }
+
+ if (!Found) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Get String Length
+ //
+ Result = UsbGetString (
+ This,
+ LangID,
+ StringIndex,
+ &TempBuffer,
+ 2,
+ &Status
+ );
+ if (EFI_ERROR (Result)) {
+ return EFI_NOT_FOUND;
+ }
+
+ StrDescriptor = (EFI_USB_STRING_DESCRIPTOR *) &TempBuffer;
+
+ if (StrDescriptor->Length == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Buffer = AllocateZeroPool (StrDescriptor->Length);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Result = UsbGetString (
+ This,
+ LangID,
+ StringIndex,
+ Buffer,
+ StrDescriptor->Length,
+ &Status
+ );
+
+ if (EFI_ERROR (Result)) {
+ gBS->FreePool (Buffer);
+ return EFI_NOT_FOUND;
+ }
+
+ StrDescriptor = (EFI_USB_STRING_DESCRIPTOR *) Buffer;
+
+ //
+ // UsbString is a UNICODE string
+ //
+ UsbString = AllocateZeroPool (StrDescriptor->Length);
+ if (UsbString == NULL) {
+ gBS->FreePool (Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (
+ (VOID *) UsbString,
+ Buffer + 2,
+ StrDescriptor->Length - 2
+ );
+
+ *String = UsbString;
+
+ gBS->FreePool (Buffer);
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c
new file mode 100644
index 0000000000..07eb5805e9
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c
@@ -0,0 +1,556 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name:
+ usbutil.c
+
+ Abstract:
+
+ Helper functions for USB
+
+ Revision History
+
+--*/
+
+#include "usbbus.h"
+
+//
+// Following APIs are used to query Port Status
+//
+BOOLEAN
+IsPortConnect (
+ IN UINT16 PortStatus
+ )
+/*++
+
+ Routine Description:
+ Tell if there is a device connected to that port according to
+ the Port Status.
+
+ Parameters:
+ PortStatus - The status value of that port.
+
+ Return Value:
+ TRUE
+ FALSE
+
+--*/
+{
+ //
+ // return the bit 0 value of PortStatus
+ //
+ if ((PortStatus & USB_PORT_STAT_CONNECTION) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+BOOLEAN
+IsPortEnable (
+ IN UINT16 PortStatus
+ )
+/*++
+
+ Routine Description:
+ Tell if Port is enabled.
+
+ Arguments:
+ PortStatus - The status value of that port.
+
+ Returns:
+ TRUE - Port is enable
+ FALSE - Port is disable
+
+--*/
+{
+ //
+ // return the bit 1 value of PortStatus
+ //
+ if ((PortStatus & USB_PORT_STAT_ENABLE) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+BOOLEAN
+IsPortInReset (
+ IN UINT16 PortStatus
+ )
+/*++
+
+ Routine Description:
+ Tell if the port is being reset.
+
+ Arguments:
+ PortStatus - The status value of that port.
+
+ Returns:
+ TRUE
+ FALSE
+
+--*/
+{
+ //
+ // return the bit 4 value of PortStatus
+ //
+ if ((PortStatus & USB_PORT_STAT_RESET) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+BOOLEAN
+IsPortPowerApplied (
+ IN UINT16 PortStatus
+ )
+/*++
+
+ Routine Description:
+ Tell if there is power applied to that port.
+
+ Arguments:
+ PortStatus - The status value of that port.
+
+ Returns:
+ TRUE
+ FALSE
+
+--*/
+{
+ //
+ // return the bit 8 value of PortStatus
+ //
+ if ((PortStatus & USB_PORT_STAT_POWER) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+BOOLEAN
+IsPortLowSpeedDeviceAttached (
+ IN UINT16 PortStatus
+ )
+/*++
+
+ Routine Description:
+ Tell if the connected device is a low device.
+
+ Arguments:
+ PortStatus - The status value of that port.
+
+ Returns:
+ TRUE
+ FALSE
+
+--*/
+{
+ //
+ // return the bit 9 value of PortStatus
+ //
+ if ((PortStatus & USB_PORT_STAT_LOW_SPEED) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+BOOLEAN
+IsPortSuspend (
+ IN UINT16 PortStatus
+ )
+/*++
+
+ Routine Description:
+ Tell if the port is suspend.
+
+ Arguments:
+ PortStatus - The status value of that port.
+
+ Returns:
+ TRUE
+ FALSE
+
+--*/
+{
+ //
+ // return the bit 2 value of PortStatus
+ //
+ if ((PortStatus & USB_PORT_STAT_SUSPEND) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+//
+// Following APIs are used to query Port Change Status
+//
+BOOLEAN
+IsPortConnectChange (
+ IN UINT16 PortChangeStatus
+ )
+/*++
+
+ Routine Description:
+ Tell if there is a Connect Change status in that port.
+
+ Arguments:
+ PortChangeStatus - The status value of that port.
+
+ Returns:
+ TRUE
+ FALSE
+
+--*/
+{
+ //
+ // return the bit 0 value of PortChangeStatus
+ //
+ if ((PortChangeStatus & USB_PORT_STAT_C_CONNECTION) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+BOOLEAN
+IsPortEnableDisableChange (
+ IN UINT16 PortChangeStatus
+ )
+/*++
+
+ Routine Description:
+ Tell if there is a Enable/Disable change in that port.
+
+ Arguments:
+ PortChangeStatus - The status value of that port.
+
+ Returns:
+ TRUE
+ FALSE
+
+--*/
+{
+ //
+ // return the bit 1 value of PortChangeStatus
+ //
+ if ((PortChangeStatus & USB_PORT_STAT_C_ENABLE) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+BOOLEAN
+IsPortResetChange (
+ IN UINT16 PortChangeStatus
+ )
+/*++
+
+ Routine Description:
+ Tell if there is a Port Reset Change status in that port.
+
+ Arguments:
+ PortChangeStatus - The status value of that port.
+
+ Returns:
+ TRUE
+ FALSE
+
+--*/
+{
+ //
+ // return the bit 4 value of PortChangeStatus
+ //
+ if ((PortChangeStatus & USB_PORT_STAT_C_RESET) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+BOOLEAN
+IsPortSuspendChange (
+ IN UINT16 PortChangeStatus
+ )
+/*++
+
+ Routine Description:
+ Tell if there is a Suspend Change Status in that port.
+
+ Arguments:
+ PortChangeStatus - The status value of that port.
+
+ Returns:
+ TRUE
+ FALSE
+
+--*/
+{
+ //
+ // return the bit 2 value of PortChangeStatus
+ //
+ if ((PortChangeStatus & USB_PORT_STAT_C_SUSPEND) != 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+INTERFACE_DESC_LIST_ENTRY*
+FindInterfaceListEntry (
+ IN EFI_USB_IO_PROTOCOL *This
+ )
+/*++
+
+ Routine Description:
+ Find Interface ListEntry.
+
+ Arguments:
+ This - EFI_USB_IO_PROTOCOL
+
+ Returns:
+ INTERFACE_DESC_LIST_ENTRY pointer
+
+--*/
+{
+ USB_IO_CONTROLLER_DEVICE *UsbIoController;
+ USB_IO_DEVICE *UsbIoDev;
+ LIST_ENTRY *InterfaceListHead;
+ INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry;
+
+ UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This);
+ UsbIoDev = UsbIoController->UsbDevice;
+
+ if (!UsbIoDev->IsConfigured) {
+ return NULL;
+ }
+
+ InterfaceListHead = &UsbIoDev->ActiveConfig->InterfaceDescListHead;
+ InterfaceListEntry = (INTERFACE_DESC_LIST_ENTRY *) (InterfaceListHead->ForwardLink);
+
+ //
+ // Loop all interface descriptor to get match one.
+ //
+ while (InterfaceListEntry != (INTERFACE_DESC_LIST_ENTRY *) InterfaceListHead) {
+ if (InterfaceListEntry->InterfaceDescriptor.InterfaceNumber == UsbIoController->InterfaceNumber) {
+ return InterfaceListEntry;
+ }
+
+ InterfaceListEntry = (INTERFACE_DESC_LIST_ENTRY *) InterfaceListEntry->Link.ForwardLink;
+ }
+
+ return NULL;
+}
+
+ENDPOINT_DESC_LIST_ENTRY*
+FindEndPointListEntry (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT8 EndPointAddress
+ )
+/*++
+
+ Routine Description:
+ Find EndPoint ListEntry.
+
+ Arguments:
+ This - EFI_USB_IO_PROTOCOL
+ EndpointAddr - Endpoint address.
+
+ Returns:
+ ENDPOINT_DESC_LIST_ENTRY pointer
+
+--*/
+{
+ INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry;
+ LIST_ENTRY *EndpointDescListHead;
+ ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry;
+
+ InterfaceListEntry = FindInterfaceListEntry (This);
+ if (InterfaceListEntry != NULL) {
+ EndpointDescListHead = &InterfaceListEntry->EndpointDescListHead;
+ EndPointListEntry = (ENDPOINT_DESC_LIST_ENTRY *) (EndpointDescListHead->ForwardLink);
+
+ //
+ // Loop all interface descriptor to get match one.
+ //
+ while (EndPointListEntry != (ENDPOINT_DESC_LIST_ENTRY *) EndpointDescListHead) {
+ if (EndPointListEntry->EndpointDescriptor.EndpointAddress == EndPointAddress) {
+ return EndPointListEntry;
+ }
+
+ EndPointListEntry = (ENDPOINT_DESC_LIST_ENTRY *) EndPointListEntry->Link.ForwardLink;
+ }
+ }
+
+ return NULL;
+}
+
+VOID
+GetDataToggleBit (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 EndpointAddr,
+ OUT UINT8 *DataToggle
+ )
+/*++
+
+ Routine Description:
+ Get the datatoggle of a specified endpoint.
+
+ Arguments:
+ UsbIo - Given Usb Controller device.
+ EndpointAddr - Given Endpoint address.
+ DataToggle - The current data toggle of that endpoint
+
+ Returns:
+ N/A
+
+--*/
+{
+
+ ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry;
+
+ *DataToggle = 0;
+
+ EndpointListEntry = FindEndPointListEntry (UsbIo, EndpointAddr);
+ if (EndpointListEntry == NULL) {
+ return ;
+ }
+
+ *DataToggle = (UINT8) (EndpointListEntry->Toggle);
+ return ;
+}
+
+VOID
+SetDataToggleBit (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 EndpointAddr,
+ IN UINT8 DataToggle
+ )
+/*++
+
+ Routine Description:
+ Set the datatoggle of a specified endpoint
+
+ Arguments:
+ UsbIo - Given Usb Controller device.
+ EndpointAddr - Given Endpoint address.
+ DataToggle - The current data toggle of that endpoint to be set
+
+ Returns:
+ N/A
+
+--*/
+{
+
+ ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry;
+
+ EndpointListEntry = FindEndPointListEntry (UsbIo, EndpointAddr);
+ if (EndpointListEntry == NULL) {
+ return ;
+ }
+
+ EndpointListEntry->Toggle = DataToggle;
+ return ;
+}
+
+VOID
+GetDeviceEndPointMaxPacketLength (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT8 EndpointAddr,
+ OUT UINT8 *MaxPacketLength
+ )
+/*++
+
+ Routine Description:
+ Get the Max Packet Length of the speified Endpoint.
+
+ Arguments:
+ UsbIo - Given Usb Controller device.
+ EndpointAddr - Given Endpoint address.
+ MaxPacketLength - The max packet length of that endpoint
+
+ Returns:
+ N/A
+
+--*/
+{
+
+ ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry;
+
+ *MaxPacketLength = 0;
+
+ EndpointListEntry = FindEndPointListEntry (UsbIo, EndpointAddr);
+ if (EndpointListEntry == NULL) {
+ return ;
+ }
+
+ *MaxPacketLength = (UINT8) (EndpointListEntry->EndpointDescriptor.MaxPacketSize);
+
+ return ;
+}
+
+
+EFI_STATUS
+UsbSetDeviceAddress (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT16 AddressValue,
+ OUT UINT32 *Status
+ )
+/*++
+
+Routine Description:
+
+ Usb Set Device Address
+
+Arguments:
+
+ UsbIo - EFI_USB_IO_PROTOCOL
+ AddressValue - Device address
+ Status - Transfer status
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Parameter is error
+ EFI_SUCCESS - Success
+ EFI_TIMEOUT - Device has no response
+
+
+--*/
+{
+ EFI_USB_DEVICE_REQUEST DevReq;
+
+ if (UsbIo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ DevReq.RequestType = USB_DEV_SET_ADDRESS_REQ_TYPE;
+ DevReq.Request = USB_DEV_SET_ADDRESS;
+ DevReq.Value = AddressValue;
+
+ return UsbIo->UsbControlTransfer (
+ UsbIo,
+ &DevReq,
+ EfiUsbNoData,
+ TIMEOUT_VALUE,
+ NULL,
+ 0,
+ Status
+ );
+}
+
diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.h b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.h
new file mode 100644
index 0000000000..259276cbaf
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.h
@@ -0,0 +1,94 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name:
+ usbutil.h
+
+ Abstract:
+
+ Helper functions for USB
+
+ Revision History
+
+
+--*/
+
+#ifndef _USB_UTIL_H
+#define _USB_UTIL_H
+
+//
+// Following APIs are used to query Port Status
+//
+BOOLEAN
+IsPortConnect (
+ IN UINT16 PortStatus
+ );
+
+BOOLEAN
+IsPortEnable (
+ IN UINT16 PortStatus
+ );
+
+BOOLEAN
+IsPortInReset (
+ IN UINT16 PortStatus
+ );
+
+BOOLEAN
+IsPortPowerApplied (
+ IN UINT16 PortStatus
+ );
+
+BOOLEAN
+IsPortLowSpeedDeviceAttached (
+ IN UINT16 PortStatus
+ );
+
+BOOLEAN
+IsPortSuspend (
+ IN UINT16 PortStatus
+ );
+
+//
+// Following APIs are used to query Port Change Status
+//
+BOOLEAN
+IsPortConnectChange (
+ IN UINT16 PortChangeStatus
+ );
+
+BOOLEAN
+IsPortEnableDisableChange (
+ IN UINT16 PortChangeStatus
+ );
+
+BOOLEAN
+IsPortResetChange (
+ IN UINT16 PortChangeStatus
+ );
+
+BOOLEAN
+IsPortSuspendChange (
+ IN UINT16 PortChangeStatus
+ );
+
+//
+// Set device address;
+//
+EFI_STATUS
+UsbSetDeviceAddress (
+ IN EFI_USB_IO_PROTOCOL *UsbIo,
+ IN UINT16 AddressValue,
+ OUT UINT32 *Status
+ );
+
+
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c
new file mode 100644
index 0000000000..5bd8728fcf
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c
@@ -0,0 +1,1042 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Cbi0.c
+
+Abstract:
+
+--*/
+
+#include "../cbi.h"
+
+extern EFI_COMPONENT_NAME_PROTOCOL gUsbCbi0ComponentName;
+//
+// Function prototypes
+//
+EFI_STATUS
+EFIAPI
+UsbCbi0DriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+//
+// Bot Driver Binding Protocol
+//
+STATIC
+EFI_STATUS
+EFIAPI
+Cbi0DriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+Cbi0DriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+Cbi0DriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+VOID
+Cbi0ReportStatusCode (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value
+ );
+
+
+EFI_DRIVER_BINDING_PROTOCOL gUsbCbi0DriverBinding = {
+ Cbi0DriverBindingSupported,
+ Cbi0DriverBindingStart,
+ Cbi0DriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+STATIC
+EFI_STATUS
+Cbi0RecoveryReset (
+ IN USB_CBI_DEVICE *UsbCbiDev
+ );
+
+STATIC
+EFI_STATUS
+Cbi0CommandPhase (
+ IN USB_CBI_DEVICE *UsbCbiDev,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ IN UINT16 Timeout
+ );
+
+STATIC
+EFI_STATUS
+Cbi0DataPhase (
+ IN USB_CBI_DEVICE *UsbCbiDev,
+ IN UINT32 *DataSize,
+ IN OUT VOID *DataBuffer,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 Timeout
+ );
+
+STATIC
+EFI_STATUS
+Cbi0StatusPhase (
+ IN USB_CBI_DEVICE *UsbCbiDev,
+ OUT INTERRUPT_DATA_BLOCK *InterruptDataBlock,
+ IN UINT16 Timeout
+ );
+
+//
+// USB Atapi protocol prototype
+//
+STATIC
+EFI_STATUS
+EFIAPI
+Cbi0AtapiCommand (
+ IN EFI_USB_ATAPI_PROTOCOL *This,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ IN VOID *DataBuffer,
+ IN UINT32 BufferLength,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 TimeOutInMilliSeconds
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+Cbi0MassStorageReset (
+ IN EFI_USB_ATAPI_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+STATIC EFI_USB_ATAPI_PROTOCOL Cbi0AtapiProtocol = {
+ Cbi0AtapiCommand,
+ Cbi0MassStorageReset,
+ 0
+};
+
+STATIC
+EFI_STATUS
+EFIAPI
+Cbi0DriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ than contains a BlockIo and DiskIo protocol can be supported.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ControllerHandle - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver supports this device
+ EFI_ALREADY_STARTED - This driver is already running on this device
+ other - This driver does not support this device
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+
+ //
+ // Check if the Controller supports USB IO protocol
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get the Default interface descriptor, now we only
+ // suppose interface 1
+ //
+ Status = UsbIo->UsbGetInterfaceDescriptor (
+ UsbIo,
+ &InterfaceDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ return Status;
+ }
+ //
+ // Check if it is a Cbi0 Type Mass Storage Device
+ //
+ if((InterfaceDescriptor.InterfaceClass != MASS_STORAGE_CLASS) ||
+ (InterfaceDescriptor.InterfaceProtocol != CBI0_INTERFACE_PROTOCOL)) {
+ Status = EFI_UNSUPPORTED;
+ } else {
+ Status = EFI_SUCCESS;
+ }
+
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+Cbi0DriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Start this driver on ControllerHandle by opening a Block IO and Disk IO
+ protocol, reading Device Path, and creating a child handle with a
+ Disk IO and device path protocol.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ControllerHandle - Handle of device to bind driver to
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver is added to DeviceHandle
+ EFI_ALREADY_STARTED - This driver is already running on DeviceHandle
+ other - This driver does not support this device
+ EFI_OUT_OF_RESOURCES- Can't allocate memory
+ EFI_UNSUPPORTED - Endpoint is not as expected
+--*/
+{
+ USB_CBI_DEVICE *UsbCbiDev;
+ UINT8 Index;
+ EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+ EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 EndpointExistMask;
+
+ //
+ // Check if the Controller supports USB IO protocol
+ //
+ UsbCbiDev = NULL;
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get the controller interface descriptor
+ //
+ Status = UsbIo->UsbGetInterfaceDescriptor (
+ UsbIo,
+ &InterfaceDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ return Status;
+ }
+
+ Cbi0AtapiProtocol.CommandProtocol = InterfaceDescriptor.InterfaceSubClass;
+
+ UsbCbiDev = AllocateZeroPool (sizeof (USB_CBI_DEVICE));
+ if (UsbCbiDev == NULL) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UsbCbiDev->Signature = USB_CBI_DEVICE_SIGNATURE;
+ UsbCbiDev->UsbIo = UsbIo;
+ CopyMem (&UsbCbiDev->InterfaceDescriptor, &InterfaceDescriptor, sizeof (InterfaceDescriptor));
+ CopyMem (&UsbCbiDev->UsbAtapiProtocol, &Cbi0AtapiProtocol, sizeof (Cbi0AtapiProtocol));
+
+ //
+ // Get the Device Path Protocol on Controller's handle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &UsbCbiDev->DevicePath,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ if (UsbCbiDev != NULL) {
+ gBS->FreePool (UsbCbiDev);
+ }
+
+ return Status;
+ }
+ //
+ // Mask used to see whether all three kinds of endpoints exist,
+ // Mask value:
+ // bit0: bulk in endpoint;
+ // bit1: bulk out endpoint;
+ // bit2: interrupt in endpoint;
+ //
+ EndpointExistMask = 0;
+ for (Index = 0; Index < InterfaceDescriptor.NumEndpoints; Index++) {
+ UsbIo->UsbGetEndpointDescriptor (
+ UsbIo,
+ Index,
+ &EndpointDescriptor
+ );
+
+ //
+ // We parse bulk endpoint
+ //
+ if (EndpointDescriptor.Attributes == 0x02) {
+ if (EndpointDescriptor.EndpointAddress & 0x80) {
+ CopyMem (&UsbCbiDev->BulkInEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));
+ // UsbCbiDev->BulkInEndpointDescriptor = EndpointDescriptor;
+ EndpointExistMask |= bit (0);
+ } else {
+ CopyMem (&UsbCbiDev->BulkOutEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));
+ // UsbCbiDev->BulkOutEndpointDescriptor = EndpointDescriptor;
+ EndpointExistMask |= bit (1);
+ }
+ }
+ //
+ // We parse interrupt endpoint
+ //
+ if (EndpointDescriptor.Attributes == 0x03) {
+ CopyMem (&UsbCbiDev->InterruptEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));
+ // UsbCbiDev->InterruptEndpointDescriptor = EndpointDescriptor;
+ EndpointExistMask |= bit (2);
+ }
+
+ }
+ //
+ // Double check we have all endpoints needed
+ //
+ if (EndpointExistMask != (bit (0) | bit (1) | bit (2))) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ if (UsbCbiDev != NULL) {
+ gBS->FreePool (UsbCbiDev);
+ }
+
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // After installing Usb-Atapi protocol onto this handle
+ // it will be called by upper layer drivers such as Fat
+ //
+ Cbi0ReportStatusCode (
+ UsbCbiDev->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE)
+ );
+
+ Status = gBS->InstallProtocolInterface (
+ &ControllerHandle,
+ &gEfiUsbAtapiProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &UsbCbiDev->UsbAtapiProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ if (UsbCbiDev != NULL) {
+ gBS->FreePool (UsbCbiDev);
+ }
+
+ return Status;
+ }
+
+ UsbCbiDev->ControllerNameTable = NULL;
+ AddUnicodeString (
+ "eng",
+ gUsbCbi0ComponentName.SupportedLanguages,
+ &UsbCbiDev->ControllerNameTable,
+ (CHAR16 *) L"Usb Cbi0 Mass Storage"
+ );
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+Cbi0DriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ControllerHandle - Handle of device to stop driver on
+ NumberOfChildren - Number of Children in the ChildHandleBuffer
+ ChildHandleBuffer - List of handles for the children we need to stop.
+
+ Returns:
+ EFI_SUCCESS - This driver is removed DeviceHandle
+ EFI_UNSUPPORTED - This driver was not removed from this device
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_ATAPI_PROTOCOL *Cbi0AtapiProtocol;
+ USB_CBI_DEVICE *UsbCbiDev;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ //
+ // Get our context back.
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbAtapiProtocolGuid,
+ (VOID **) &Cbi0AtapiProtocol,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (Cbi0AtapiProtocol);
+
+ UsbIo = UsbCbiDev->UsbIo;
+
+ Cbi0ReportStatusCode (
+ UsbCbiDev->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE)
+ );
+
+ //
+ // Uninstall protocol
+ //
+ Status = gBS->UninstallProtocolInterface (
+ ControllerHandle,
+ &gEfiUsbAtapiProtocolGuid,
+ &UsbCbiDev->UsbAtapiProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ //
+ // Free all allocated resources
+ //
+ if (UsbCbiDev->ControllerNameTable) {
+ FreeUnicodeStringTable (UsbCbiDev->ControllerNameTable);
+ }
+
+ gBS->FreePool (UsbCbiDev);
+
+ return Status;
+}
+
+
+STATIC
+EFI_STATUS
+Cbi0RecoveryReset (
+ IN USB_CBI_DEVICE *UsbCbiDev
+ )
+/*++
+
+Routine Description:
+
+ Cbi0 Recovery Reset routine
+
+Arguments:
+
+ UsbCbiDev - Cbi0RecoveryReset
+
+Returns:
+
+ EFI_SUCCESS - Success
+
+--*/
+{
+ UINT8 ResetCommand[12];
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 EndpointAddress;
+ UINT32 Result;
+ UINT16 Timeout;
+
+ UsbIo = UsbCbiDev->UsbIo;
+
+ Cbi0ReportStatusCode (
+ UsbCbiDev->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET)
+ );
+ //
+ // CBI reset command protocol
+ //
+ SetMem (ResetCommand, sizeof (ResetCommand), 0xff);
+ ResetCommand[0] = 0x1d;
+ ResetCommand[1] = 0x04;
+
+ //
+ // (in millisecond unit)
+ //
+ Timeout = STALL_1_SECOND;
+
+ Status = Cbi0AtapiCommand (
+ &UsbCbiDev->UsbAtapiProtocol,
+ ResetCommand,
+ 12,
+ NULL,
+ 0,
+ EfiUsbNoData,
+ Timeout
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->Stall (100 * 1000);
+ //
+ // clear bulk in endpoint stall feature
+ //
+ EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress;
+ Status = UsbClearEndpointHalt (
+ UsbIo,
+ EndpointAddress,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // clear bulk out endpoint stall feature
+ //
+ EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress;
+ Status = UsbClearEndpointHalt (
+ UsbIo,
+ EndpointAddress,
+ &Result
+ );
+ //
+ // according to CBI spec, no need to clear interrupt endpoint feature.
+ //
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+Cbi0CommandPhase (
+ IN USB_CBI_DEVICE *UsbCbiDev,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ IN UINT16 Timeout
+ )
+/*++
+
+ Routine Description:
+ Send ATAPI command through CBI0 interface.
+
+ Arguments:
+ UsbCbiDev - USB_CBI_DEVICE
+ Command - Command to send
+ CommandSize - Command size
+ Timeout - Time out value in milliseconds
+ Returns:
+ EFI_SUCCESS - Success
+ EFI_DEVICE_ERROR - Fail
+ Others
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 Result;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_DEVICE_REQUEST Request;
+
+ UsbIo = UsbCbiDev->UsbIo;
+
+ ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Device request see CBI specification
+ //
+ Request.RequestType = 0x21;
+ Request.Request = 0x00;
+ Request.Value = 0;
+ Request.Index = 0;
+ Request.Length = CommandSize;
+
+ Status = UsbIo->UsbControlTransfer (
+ UsbIo,
+ &Request,
+ EfiUsbDataOut,
+ Timeout,
+ Command,
+ CommandSize,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+Cbi0DataPhase (
+ IN USB_CBI_DEVICE *UsbCbiDev,
+ IN UINT32 *DataSize,
+ IN OUT VOID *DataBuffer,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 Timeout
+ )
+/*++
+
+ Routine Description:
+ Get/Send Data through CBI0 interface
+
+ Arguments:
+ UsbCbiDev - USB_CBI_DEVICE
+ DataSize - Data size
+ DataBuffer - Data buffer
+ Direction - IN/OUT/NODATA
+ Timeout - Time out value in milliseconds
+ Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 EndpointAddress;
+ UINTN Remain;
+ UINTN Increment;
+ UINT32 MaxPacketLength;
+ UINT8 *BufferPtr;
+ UINT32 Result;
+ UINTN TransferredSize;
+
+ UsbIo = UsbCbiDev->UsbIo;
+
+ Remain = *DataSize;
+ BufferPtr = (UINT8 *) DataBuffer;
+ TransferredSize = 0;
+ //
+ // retrieve the the max packet length of the given endpoint
+ //
+ if (Direction == EfiUsbDataIn) {
+ MaxPacketLength = UsbCbiDev->BulkInEndpointDescriptor.MaxPacketSize;
+ EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress;
+ } else {
+ MaxPacketLength = UsbCbiDev->BulkOutEndpointDescriptor.MaxPacketSize;
+ EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress;
+ }
+
+ while (Remain > 0) {
+
+ if (Remain > 16 * MaxPacketLength) {
+ Increment = 16 * MaxPacketLength;
+ } else {
+ Increment = Remain;
+ }
+
+ Status = UsbIo->UsbBulkTransfer (
+ UsbIo,
+ EndpointAddress,
+ BufferPtr,
+ &Increment,
+ Timeout,
+ &Result
+ );
+ TransferredSize += Increment;
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ BufferPtr += Increment;
+ Remain -= Increment;
+ }
+
+ return EFI_SUCCESS;
+
+ErrorExit:
+
+ if (Direction == EfiUsbDataIn) {
+ Cbi0ReportStatusCode (
+ UsbCbiDev->DevicePath,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR)
+ );
+ } else {
+ Cbi0ReportStatusCode (
+ UsbCbiDev->DevicePath,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR)
+ );
+ }
+
+ if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
+ Status = Cbi0RecoveryReset (UsbCbiDev);
+ }
+
+ *DataSize = (UINT32) TransferredSize;
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+Cbi0StatusPhase (
+ IN USB_CBI_DEVICE *UsbCbiDev,
+ OUT INTERRUPT_DATA_BLOCK *InterruptDataBlock,
+ IN UINT16 Timeout
+ )
+/*++
+
+ Routine Description:
+ Get transfer status through BOT interface
+
+ Arguments:
+ UsbCbiDev - USB_CBI_DEVICE
+ InterruptDataBlock - Interrupt Data Block for interrupt transfer
+ Timeout - Time out value in milliseconds
+ Returns:
+ EFI_SUCCESS
+ Others
+
+--*/
+{
+ UINT8 EndpointAddress;
+ UINTN InterruptDataBlockLength;
+ UINT32 Result;
+ EFI_STATUS Status;
+
+ ZeroMem (InterruptDataBlock, sizeof (INTERRUPT_DATA_BLOCK));
+
+ EndpointAddress = UsbCbiDev->InterruptEndpointDescriptor.EndpointAddress;
+ InterruptDataBlockLength = sizeof (INTERRUPT_DATA_BLOCK);
+
+ Status = UsbCbiDev->UsbIo->UsbSyncInterruptTransfer (
+ UsbCbiDev->UsbIo,
+ EndpointAddress,
+ InterruptDataBlock,
+ &InterruptDataBlockLength,
+ Timeout,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
+ //
+ // just endpoint stall happens
+ //
+ UsbClearEndpointHalt (
+ UsbCbiDev->UsbIo,
+ EndpointAddress,
+ &Result
+ );
+ gBS->Stall (100 * 1000);
+ }
+
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+//
+// Cbi0 Atapi Protocol Implementation
+//
+STATIC
+EFI_STATUS
+EFIAPI
+Cbi0MassStorageReset (
+ IN EFI_USB_ATAPI_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+ Routine Description:
+ Reset CBI Devices
+
+ Arguments:
+ This - Protocol instance pointer.
+ ExtendedVerification - TRUE if we need to do strictly reset.
+
+ Returns:
+ EFI_SUCCESS - Command succeeded.
+ EFI_DEVICE_ERROR - Command failed.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ USB_CBI_DEVICE *UsbCbiDev;
+
+ UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);
+ UsbIo = UsbCbiDev->UsbIo;
+
+ if (ExtendedVerification) {
+ //
+ // UsbIo->UsbPortReset (UsbIo);
+ //
+ }
+
+ Status = Cbi0RecoveryReset (UsbCbiDev);
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+Cbi0AtapiCommand (
+ IN EFI_USB_ATAPI_PROTOCOL *This,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ IN VOID *DataBuffer,
+ IN UINT32 BufferLength,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 TimeOutInMilliSeconds
+ )
+/*++
+
+ Routine Description:
+ Send ATAPI command using BOT protocol.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Command - Command buffer
+ CommandSize - Size of Command Buffer
+ DataBuffer - Data buffer
+ BufferLength - Length of Data buffer
+ Direction - Data direction of this command
+ TimeOutInMilliSeconds - Timeout value in ms
+
+ Returns:
+ EFI_SUCCESS - Command succeeded.
+ EFI_DEVICE_ERROR - Command failed.
+ EFI_INVALID_PARAMETER - Invalidate parameter
+--*/
+{
+ EFI_STATUS Status;
+ USB_CBI_DEVICE *UsbCbiDev;
+ UINT32 BufferSize;
+ INTERRUPT_DATA_BLOCK InterruptDataBlock;
+ EFI_STATUS DataPhaseStatus;
+
+ if (Direction != EfiUsbNoData) {
+ if (DataBuffer == NULL || BufferLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ DataPhaseStatus = EFI_SUCCESS;
+ //
+ // Get the context
+ //
+ UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);
+
+ //
+ // First send ATAPI command through Cbi
+ //
+ Status = Cbi0CommandPhase (
+ UsbCbiDev,
+ Command,
+ CommandSize,
+ TimeOutInMilliSeconds
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Send/Get Data if there is a Data Stage
+ //
+ switch (Direction) {
+
+ case EfiUsbDataIn:
+ case EfiUsbDataOut:
+ BufferSize = BufferLength;
+
+ DataPhaseStatus = Cbi0DataPhase (
+ UsbCbiDev,
+ &BufferSize,
+ DataBuffer,
+ Direction,
+ TimeOutInMilliSeconds
+ );
+ break;
+
+ case EfiUsbNoData:
+ break;
+ }
+
+ if (EFI_ERROR (DataPhaseStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Status Phase
+ //
+ Status = Cbi0StatusPhase (
+ UsbCbiDev,
+ &InterruptDataBlock,
+ TimeOutInMilliSeconds
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (This->CommandProtocol != EFI_USB_SUBCLASS_UFI) {
+
+ if (InterruptDataBlock.bType == 0) {
+ //
+ // indicates command completion
+ //
+ switch (InterruptDataBlock.bValue & 0x03) {
+
+ case 0:
+ Status = EFI_SUCCESS;
+ break;
+
+ case 1:
+ Status = EFI_DEVICE_ERROR;
+ break;
+
+ case 2:
+ Status = Cbi0RecoveryReset (UsbCbiDev);
+ if (EFI_ERROR (Status)) {
+ UsbCbiDev->UsbIo->UsbPortReset (UsbCbiDev->UsbIo);
+ }
+
+ Status = EFI_DEVICE_ERROR;
+ break;
+
+ case 3:
+ Status = EFI_DEVICE_ERROR;
+ }
+ } else {
+ Status = DataPhaseStatus;
+ }
+
+ } else {
+ //
+ // UFI device, InterruptDataBlock.bType: ASC (Additional Sense Code)
+ // InterruptDataBlock.bValue: ASCQ (Additional Snese Code Qualifier)
+ //
+ Status = DataPhaseStatus;
+ }
+
+ return Status;
+}
+
+VOID
+Cbi0ReportStatusCode (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value
+ )
+/*++
+
+ Routine Description:
+ Report Status Code in Usb Cbi0 Driver
+
+ Arguments:
+ DevicePath - Use this to get Device Path
+ CodeType - Status Code Type
+ CodeValue - Status Code Value
+
+ Returns:
+ None
+
+--*/
+{
+
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ CodeType,
+ Value,
+ DevicePath
+ );
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/ComponentName.c
new file mode 100644
index 0000000000..0692c7fee5
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/ComponentName.c
@@ -0,0 +1,192 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "../cbi.h"
+
+extern EFI_DRIVER_BINDING_PROTOCOL gUsbCbi0DriverBinding;
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+UsbCbi0ComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+UsbCbi0ComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gUsbCbi0ComponentName = {
+ UsbCbi0ComponentNameGetDriverName,
+ UsbCbi0ComponentNameGetControllerName,
+ "eng"
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mUsbCbi0DriverNameTable[] = {
+ { "eng", (CHAR16 *) L"Usb Cbi0 Mass Storage Driver" },
+ { NULL , NULL }
+};
+
+
+EFI_STATUS
+EFIAPI
+UsbCbi0ComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ Language - A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ DriverName - A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - DriverName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return LookupUnicodeString (
+ Language,
+ gUsbCbi0ComponentName.SupportedLanguages,
+ mUsbCbi0DriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UsbCbi0ComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ ControllerHandle - The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ ChildHandle - The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ ControllerName - A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language from the point of view of the driver specified
+ by This.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - ControllerName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB_CBI_DEVICE *UsbCbiDev;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapi;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbAtapiProtocolGuid,
+ (VOID **) &UsbAtapi,
+ gUsbCbi0DriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (UsbAtapi);
+
+ return LookupUnicodeString (
+ Language,
+ gUsbCbi0ComponentName.SupportedLanguages,
+ UsbCbiDev->ControllerNameTable,
+ ControllerName
+ );
+
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.mbd b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.mbd
new file mode 100644
index 0000000000..17a63f9b21
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.mbd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>UsbCbi0</BaseName>
+ <Guid>A3527D16-E6CC-42f5-BADB-BF3DE177742B</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>EdkUsbLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.msa b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.msa
new file mode 100644
index 0000000000..a128159e12
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.msa
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>UsbCbi0</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>A3527D16-E6CC-42f5-BADB-BF3DE177742B</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for UsbCbi1 module</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">EdkUsbLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>cbi0.c</Filename>
+ <Filename>componentname.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">DevicePath</Protocol>
+ <Protocol Usage="TO_START">UsbIo</Protocol>
+ <Protocol Usage="BY_START">UsbAtapi</Protocol>
+ </Protocols>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gUsbCbi0DriverBinding</DriverBinding>
+ <ComponentName>gUsbCbi0ComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/build.xml b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/build.xml
new file mode 100644
index 0000000000..e406abee8b
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
+<project basedir="." default="UsbCbi0"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Usb\UsbCbi\Dxe\Cbi0"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="UsbCbi0">
+ <GenBuild baseName="UsbCbi0" mbdFilename="${MODULE_DIR}\UsbCbi0.mbd" msaFilename="${MODULE_DIR}\UsbCbi0.msa"/>
+ </target>
+ <target depends="UsbCbi0_clean" name="clean"/>
+ <target depends="UsbCbi0_cleanall" name="cleanall"/>
+ <target name="UsbCbi0_clean">
+ <OutputDirSetup baseName="UsbCbi0" mbdFilename="${MODULE_DIR}\UsbCbi0.mbd" msaFilename="${MODULE_DIR}\UsbCbi0.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbCbi0_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbCbi0_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="UsbCbi0_cleanall">
+ <OutputDirSetup baseName="UsbCbi0" mbdFilename="${MODULE_DIR}\UsbCbi0.mbd" msaFilename="${MODULE_DIR}\UsbCbi0.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbCbi0_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbCbi0_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**UsbCbi0*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.mbd b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.mbd
new file mode 100644
index 0000000000..e48251eb07
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.mbd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>UsbCbi1</BaseName>
+ <Guid>B40612B2-A063-11d4-9A3A-0090273FC14D</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>EdkUsbLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.msa b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.msa
new file mode 100644
index 0000000000..057585689e
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.msa
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>UsbCbi1</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>B40612B2-A063-11d4-9A3A-0090273FC14D</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for UsbCbi1 module</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">EdkUsbLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>cbi1.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">DevicePath</Protocol>
+ <Protocol Usage="TO_START">UsbIo</Protocol>
+ <Protocol Usage="BY_START">UsbAtapi</Protocol>
+ </Protocols>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gCBI1DriverBinding</DriverBinding>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/build.xml b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/build.xml
new file mode 100644
index 0000000000..132e52237c
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
+<project basedir="." default="UsbCbi1"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Usb\UsbCbi\Dxe\Cbi1"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="UsbCbi1">
+ <GenBuild baseName="UsbCbi1" mbdFilename="${MODULE_DIR}\UsbCbi1.mbd" msaFilename="${MODULE_DIR}\UsbCbi1.msa"/>
+ </target>
+ <target depends="UsbCbi1_clean" name="clean"/>
+ <target depends="UsbCbi1_cleanall" name="cleanall"/>
+ <target name="UsbCbi1_clean">
+ <OutputDirSetup baseName="UsbCbi1" mbdFilename="${MODULE_DIR}\UsbCbi1.mbd" msaFilename="${MODULE_DIR}\UsbCbi1.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbCbi1_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbCbi1_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="UsbCbi1_cleanall">
+ <OutputDirSetup baseName="UsbCbi1" mbdFilename="${MODULE_DIR}\UsbCbi1.mbd" msaFilename="${MODULE_DIR}\UsbCbi1.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbCbi1_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbCbi1_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**UsbCbi1*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/cbi1.c b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/cbi1.c
new file mode 100644
index 0000000000..71644acef8
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/cbi1.c
@@ -0,0 +1,854 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ cbi1.c
+
+Abstract:
+ cbi1 transportation protocol implementation files
+
+--*/
+
+#include "../cbi.h"
+
+EFI_STATUS
+EFIAPI
+UsbCBI1DriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+//
+// CBI Function prototypes
+//
+STATIC
+EFI_STATUS
+CBI1CommandPhase (
+ IN USB_CBI_DEVICE *UsbCbiDev,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ OUT UINT32 *Result
+ );
+
+STATIC
+EFI_STATUS
+CBI1DataPhase (
+ IN USB_CBI_DEVICE *UsbCbiDev,
+ IN UINT32 DataSize,
+ IN OUT VOID *DataBuffer,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 Timeout,
+ OUT UINT32 *Result
+ );
+
+//
+// USB Atapi implementation
+//
+STATIC
+EFI_STATUS
+EFIAPI
+CBI1AtapiCommand (
+ IN EFI_USB_ATAPI_PROTOCOL *This,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ IN VOID *DataBuffer,
+ IN UINT32 BufferLength,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 TimeOutInMilliSeconds
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+CBI1MassStorageReset (
+ IN EFI_USB_ATAPI_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+//
+// CBI1 Driver Binding Protocol
+//
+STATIC
+EFI_STATUS
+EFIAPI
+CBI1DriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+CBI1DriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+CBI1DriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+VOID
+Cbi1ReportStatusCode (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value
+ );
+
+
+EFI_DRIVER_BINDING_PROTOCOL gCBI1DriverBinding = {
+ CBI1DriverBindingSupported,
+ CBI1DriverBindingStart,
+ CBI1DriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+STATIC EFI_USB_ATAPI_PROTOCOL CBI1AtapiProtocol = {
+ CBI1AtapiCommand,
+ CBI1MassStorageReset,
+ 0
+};
+
+//
+// CBI1 Driver Binding implementation
+//
+STATIC
+EFI_STATUS
+EFIAPI
+CBI1DriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ than contains a BlockIo and DiskIo protocol can be supported.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ControllerHandle - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver supports this device
+ EFI_ALREADY_STARTED - This driver is already running on this device
+ other - This driver does not support this device
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+
+ //
+ // Check if the Controller supports USB IO protocol
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get the Controller interface descriptor
+ //
+ Status = UsbIo->UsbGetInterfaceDescriptor (
+ UsbIo,
+ &InterfaceDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+ //
+ // Bug here: just let Vendor specific CBI protocol get supported
+ //
+ if (!((InterfaceDescriptor.InterfaceClass == 0xFF) &&
+ (InterfaceDescriptor.InterfaceProtocol == 0))) {
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+Exit:
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ return Status;
+
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+CBI1DriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Start this driver on ControllerHandle by opening a Block IO and Disk IO
+ protocol, reading Device Path, and creating a child handle with a
+ Disk IO and device path protocol.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ControllerHandle - Handle of device to bind driver to
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver is added to DeviceHandle
+ EFI_ALREADY_STARTED - This driver is already running on DeviceHandle
+ other - This driver does not support this device
+
+--*/
+{
+ USB_CBI_DEVICE *UsbCbiDev;
+ UINT8 Index;
+ EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+ EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ BOOLEAN Found;
+
+ Found = FALSE;
+ //
+ // Check if the Controller supports USB IO protocol
+ //
+ UsbCbiDev = NULL;
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get the controller interface descriptor
+ //
+ Status = UsbIo->UsbGetInterfaceDescriptor (
+ UsbIo,
+ &InterfaceDescriptor
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ CBI1AtapiProtocol.CommandProtocol = InterfaceDescriptor.InterfaceSubClass;
+
+ UsbCbiDev = AllocateZeroPool (sizeof (USB_CBI_DEVICE));
+ if (UsbCbiDev == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ UsbCbiDev->Signature = USB_CBI_DEVICE_SIGNATURE;
+ UsbCbiDev->UsbIo = UsbIo;
+ CopyMem (&UsbCbiDev->InterfaceDescriptor, &InterfaceDescriptor, sizeof (InterfaceDescriptor));
+ CopyMem (&UsbCbiDev->UsbAtapiProtocol , &CBI1AtapiProtocol, sizeof (CBI1AtapiProtocol));
+
+ //
+ // Get the Device Path Protocol on Controller's handle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &UsbCbiDev->DevicePath,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ for (Index = 0; Index < InterfaceDescriptor.NumEndpoints; Index++) {
+ UsbIo->UsbGetEndpointDescriptor (
+ UsbIo,
+ Index,
+ &EndpointDescriptor
+ );
+
+ //
+ // We parse bulk endpoint
+ //
+ if (EndpointDescriptor.Attributes == 0x02) {
+ if (EndpointDescriptor.EndpointAddress & 0x80) {
+ CopyMem (&UsbCbiDev->BulkInEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));
+ //UsbCbiDev->BulkInEndpointDescriptor = EndpointDescriptor;
+ } else {
+ CopyMem (&UsbCbiDev->BulkOutEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));
+ //UsbCbiDev->BulkOutEndpointDescriptor = EndpointDescriptor;
+ }
+
+ Found = TRUE;
+ }
+ //
+ // We parse interrupt endpoint
+ //
+ if (EndpointDescriptor.Attributes == 0x03) {
+ CopyMem (&UsbCbiDev->InterruptEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));
+ //UsbCbiDev->InterruptEndpointDescriptor = EndpointDescriptor;
+ Found = TRUE;
+ }
+
+ }
+ //
+ // Double check we have these
+ //
+ if (!Found) {
+ goto ErrorExit;
+ }
+ //
+ // After installing Usb-Atapi protocol onto this handle
+ // it will be called by upper layer drivers such as Fat
+ //
+ Cbi1ReportStatusCode (
+ UsbCbiDev->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE)
+ );
+
+ Status = gBS->InstallProtocolInterface (
+ &ControllerHandle,
+ &gEfiUsbAtapiProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &UsbCbiDev->UsbAtapiProtocol
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ return EFI_SUCCESS;
+
+ErrorExit:
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ if (UsbCbiDev != NULL) {
+ gBS->FreePool (UsbCbiDev);
+ }
+
+ return Status;
+
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+CBI1DriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ControllerHandle - Handle of device to stop driver on
+ NumberOfChildren - Number of Children in the ChildHandleBuffer
+ ChildHandleBuffer - List of handles for the children we need to stop.
+
+ Returns:
+ EFI_SUCCESS - This driver is removed DeviceHandle
+ EFI_UNSUPPORTED - Can't open the gEfiUsbAtapiProtocolGuid protocol
+ other - This driver was not removed from this device
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_ATAPI_PROTOCOL *CBI1AtapiProtocol;
+ USB_CBI_DEVICE *UsbCbiDev;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ //
+ // Get our context back.
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbAtapiProtocolGuid,
+ (VOID **) &CBI1AtapiProtocol,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (CBI1AtapiProtocol);
+
+ UsbIo = UsbCbiDev->UsbIo;
+
+ Cbi1ReportStatusCode (
+ UsbCbiDev->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE)
+ );
+
+ Status = gBS->UninstallProtocolInterface (
+ ControllerHandle,
+ &gEfiUsbAtapiProtocolGuid,
+ &UsbCbiDev->UsbAtapiProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ gBS->FreePool (UsbCbiDev);
+
+ return Status;
+
+}
+//
+// CBI1 command
+//
+STATIC
+EFI_STATUS
+CBI1CommandPhase (
+ IN USB_CBI_DEVICE *UsbCbiDev,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ OUT UINT32 *Result
+ )
+/*++
+
+ Routine Description:
+ In order to make consistence, CBI transportation protocol does only use
+ the first 3 parameters. Other parameters are not used here.
+
+ Arguments:
+ UsbCbiDev - USB_CBI_DEVICE
+ Command - Command to send
+ CommandSize - Command Size
+ Result - Result to return
+
+ Returns:
+ EFI_SUCCESS - This driver is removed DeviceHandle
+ other - This driver was not removed from this device
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_DEVICE_REQUEST Request;
+ UINT32 TimeOutInMilliSeconds;
+
+ UsbIo = UsbCbiDev->UsbIo;
+
+ ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST));
+
+ //
+ // Device request see CBI specification
+ //
+ Request.RequestType = 0x21;
+ Request.Length = CommandSize;
+
+ TimeOutInMilliSeconds = 1000;
+
+ Status = UsbIo->UsbControlTransfer (
+ UsbIo,
+ &Request,
+ EfiUsbDataOut,
+ TimeOutInMilliSeconds,
+ Command,
+ CommandSize,
+ Result
+ );
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+CBI1DataPhase (
+ IN USB_CBI_DEVICE *UsbCbiDev,
+ IN UINT32 DataSize,
+ IN OUT VOID *DataBuffer,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 Timeout,
+ OUT UINT32 *Result
+ )
+/*++
+
+Routine Description:
+
+ CBI1 Data Phase
+
+Arguments:
+
+ UsbCbiDev - USB_CBI_DEVICE
+ DataSize - Data Size
+ DataBuffer - Data Buffer
+ Direction - IN/OUT/NODATA
+ Timeout - Time out value in milliseconds
+ Result - Transfer result
+
+Returns:
+
+ EFI_SUCCESS - Success
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 EndpointAddr;
+ UINTN Remain;
+ UINTN Increment;
+ UINT32 MaxPacketLen;
+ UINT8 *BufferPtr;
+
+ UsbIo = UsbCbiDev->UsbIo;
+
+ Remain = DataSize;
+ BufferPtr = (UINT8 *) DataBuffer;
+
+ //
+ // retrieve the the max packet length of the given endpoint
+ //
+ if (Direction == EfiUsbDataIn) {
+ MaxPacketLen = (UsbCbiDev->BulkInEndpointDescriptor).MaxPacketSize;
+ EndpointAddr = (UsbCbiDev->BulkInEndpointDescriptor).EndpointAddress;
+ } else {
+ MaxPacketLen = (UsbCbiDev->BulkOutEndpointDescriptor).MaxPacketSize;
+ EndpointAddr = (UsbCbiDev->BulkOutEndpointDescriptor).EndpointAddress;
+ }
+
+ while (Remain > 0) {
+ //
+ // Using 15 packets to aVOID Bitstuff error
+ //
+ if (Remain > 15 * MaxPacketLen) {
+ Increment = 15 * MaxPacketLen;
+ } else {
+ Increment = Remain;
+ }
+
+ Status = UsbIo->UsbBulkTransfer (
+ UsbIo,
+ EndpointAddr,
+ BufferPtr,
+ &Increment,
+ Timeout,
+ Result
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ BufferPtr += Increment;
+ Remain -= Increment;
+ }
+
+ return EFI_SUCCESS;
+
+ErrorExit:
+
+ if (Direction == EfiUsbDataIn) {
+ Cbi1ReportStatusCode (
+ UsbCbiDev->DevicePath,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR)
+ );
+ } else {
+ Cbi1ReportStatusCode (
+ UsbCbiDev->DevicePath,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR)
+ );
+ }
+
+ if (((*Result) & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
+ //
+ // just endpoint stall happens
+ //
+ UsbClearEndpointHalt (
+ UsbIo,
+ EndpointAddr,
+ Result
+ );
+ }
+
+ return Status;
+}
+//
+// CBI1 USB ATAPI Protocol
+//
+STATIC
+EFI_STATUS
+EFIAPI
+CBI1MassStorageReset (
+ IN EFI_USB_ATAPI_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+ Routine Description:
+ Reset CBI Devices
+
+ Arguments:
+ This - Protocol instance pointer.
+ ExtendedVerification - TRUE if we need to do strictly reset.
+
+ Returns:
+ EFI_SUCCESS - Command succeeded.
+ EFI_DEVICE_ERROR - Command failed.
+
+--*/
+{
+ UINT8 ResetCommand[12];
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ USB_CBI_DEVICE *UsbCbiDev;
+ UINT8 EndpointAddr;
+ UINT32 Result;
+
+ UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);
+ UsbIo = UsbCbiDev->UsbIo;
+
+ Cbi1ReportStatusCode (
+ UsbCbiDev->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET)
+ );
+
+ if (ExtendedVerification) {
+ UsbIo->UsbPortReset (UsbIo);
+ }
+ //
+ // CBI reset command protocol
+ //
+ SetMem (ResetCommand, sizeof (ResetCommand), 0xff);
+ ResetCommand[0] = 0x1d;
+ ResetCommand[1] = 0x04;
+
+ Status = CBI1CommandPhase (
+ UsbCbiDev,
+ ResetCommand,
+ 12,
+ &Result
+ );
+
+ //
+ // clear bulk in endpoint stall feature
+ //
+ EndpointAddr = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress;
+ UsbClearEndpointHalt (
+ UsbIo,
+ EndpointAddr,
+ &Result
+ );
+
+ //
+ // clear bulk out endpoint stall feature
+ //
+ EndpointAddr = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress;
+ UsbClearEndpointHalt (
+ UsbIo,
+ EndpointAddr,
+ &Result
+ );
+
+ return EFI_SUCCESS;
+
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+CBI1AtapiCommand (
+ IN EFI_USB_ATAPI_PROTOCOL *This,
+ IN VOID *Command,
+ IN UINT8 CommandSize,
+ IN VOID *DataBuffer,
+ IN UINT32 BufferLength,
+ IN EFI_USB_DATA_DIRECTION Direction,
+ IN UINT16 TimeOutInMilliSeconds
+ )
+/*++
+
+ Routine Description:
+ Send ATAPI command using CBI1 protocol.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Command - Command buffer
+ CommandSize - Size of Command Buffer
+ DataBuffer - Data buffer
+ BufferLength - Length of Data buffer
+ Direction - Data direction of this command
+ TimeOutInMilliSeconds - Timeout value in ms
+
+ Returns:
+ EFI_SUCCESS - Command succeeded.
+ EFI_DEVICE_ERROR - Command failed.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB_CBI_DEVICE *UsbCbiDev;
+ UINT32 Result;
+ UINT8 Index;
+ UINT8 MaxRetryNum;
+
+ UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This);
+
+ MaxRetryNum = 3;
+
+ for (Index = 0; Index < MaxRetryNum; Index++) {
+
+ //
+ // First send ATAPI command through CBI1
+ //
+ Status = CBI1CommandPhase (
+ UsbCbiDev,
+ Command,
+ CommandSize,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+
+ switch (Result) {
+
+ case EFI_USB_NOERROR:
+ case EFI_USB_ERR_STALL:
+ case EFI_USB_ERR_SYSTEM:
+ return EFI_DEVICE_ERROR;
+
+ default:
+ continue;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (Index == MaxRetryNum) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ for (Index = 0; Index < MaxRetryNum; Index++) {
+ //
+ // Send/Get Data if there is a Data Stage
+ //
+ switch (Direction) {
+
+ case EfiUsbDataIn:
+ case EfiUsbDataOut:
+ Status = CBI1DataPhase (
+ UsbCbiDev,
+ BufferLength,
+ DataBuffer,
+ Direction,
+ TimeOutInMilliSeconds,
+ &Result
+ );
+
+ if (EFI_ERROR (Status)) {
+ switch (Result) {
+
+ case EFI_USB_NOERROR:
+ case EFI_USB_ERR_STALL:
+ case EFI_USB_ERR_SYSTEM:
+ return EFI_DEVICE_ERROR;
+
+ default:
+ continue;
+ break;
+ }
+
+ } else {
+
+ return EFI_SUCCESS;
+ }
+ break;
+
+ case EfiUsbNoData:
+ return EFI_SUCCESS;
+ }
+ }
+ //
+ // If goes here, means met error.
+ //
+ return EFI_DEVICE_ERROR;
+}
+
+VOID
+Cbi1ReportStatusCode (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value
+ )
+/*++
+
+ Routine Description:
+ Report Status Code in Usb Cbi1 Driver
+
+ Arguments:
+ DevicePath - Use this to get Device Path
+ CodeType - Status Code Type
+ CodeValue - Status Code Value
+
+ Returns:
+ None
+
+--*/
+{
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ CodeType,
+ Value,
+ DevicePath
+ );
+
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/cbi.h b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/cbi.h
new file mode 100644
index 0000000000..dfbe4d9886
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/cbi.h
@@ -0,0 +1,70 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ cbi.h
+
+Abstract:
+
+ USB CBI transportation protocol definitions.
+--*/
+
+#ifndef _CBI_H
+#define _CBI_H
+
+
+#include <IndustryStandard/usb.h>
+
+#define bit(a) (1 << (a))
+
+#define MASS_STORAGE_CLASS 0x08
+#define CBI0_INTERFACE_PROTOCOL 0x00
+#define CBI1_INTERFACE_PROTOCOL 0x01
+
+//
+// in millisecond unit
+//
+#define STALL_1_SECOND 1000
+
+#pragma pack(1)
+//
+// Data block definition for transportation through interrupt endpoint
+//
+typedef struct {
+ UINT8 bType;
+ UINT8 bValue;
+} INTERRUPT_DATA_BLOCK;
+
+#pragma pack()
+
+#define USB_CBI_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('u', 'c', 'b', 'i')
+
+//
+// Device structure for CBI, interrupt endpoint may be not used in
+// CBI1 Protocol
+//
+typedef struct {
+ UINT32 Signature;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_USB_ATAPI_PROTOCOL UsbAtapiProtocol;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+ EFI_USB_ENDPOINT_DESCRIPTOR BulkInEndpointDescriptor;
+ EFI_USB_ENDPOINT_DESCRIPTOR BulkOutEndpointDescriptor;
+ EFI_USB_ENDPOINT_DESCRIPTOR InterruptEndpointDescriptor;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+} USB_CBI_DEVICE;
+
+#define USB_CBI_DEVICE_FROM_THIS(a) \
+ CR(a, USB_CBI_DEVICE, UsbAtapiProtocol, USB_CBI_DEVICE_SIGNATURE)
+
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/ComponentName.c
new file mode 100644
index 0000000000..3e139f9d9a
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/ComponentName.c
@@ -0,0 +1,215 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "keyboard.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+UsbKeyboardComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+UsbKeyboardComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gUsbKeyboardComponentName = {
+ UsbKeyboardComponentNameGetDriverName,
+ UsbKeyboardComponentNameGetControllerName,
+ "eng"
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mUsbKeyboardDriverNameTable[] = {
+ { "eng", (CHAR16 *) L"Usb Keyboard Driver" },
+ { NULL , NULL }
+};
+
+
+EFI_STATUS
+EFIAPI
+UsbKeyboardComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ Language - A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ DriverName - A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - DriverName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return LookupUnicodeString (
+ Language,
+ gUsbKeyboardComponentName.SupportedLanguages,
+ mUsbKeyboardDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UsbKeyboardComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ ControllerHandle - The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ ChildHandle - The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ ControllerName - A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language from the point of view of the driver specified
+ by This.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - ControllerName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB_KB_DEV *UsbKbDev;
+ EFI_SIMPLE_TEXT_IN_PROTOCOL *SimpleTxtIn;
+ EFI_USB_IO_PROTOCOL *UsbIoProtocol;
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check Controller's handle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIoProtocol,
+ gUsbKeyboardDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ gUsbKeyboardDriverBinding.DriverBindingHandle,
+ ControllerHandle
+ );
+
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Status != EFI_ALREADY_STARTED) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSimpleTextInProtocolGuid,
+ (VOID **) &SimpleTxtIn,
+ gUsbKeyboardDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UsbKbDev = USB_KB_DEV_FROM_THIS (SimpleTxtIn);
+
+ return LookupUnicodeString (
+ Language,
+ gUsbKeyboardComponentName.SupportedLanguages,
+ UsbKbDev->ControllerNameTable,
+ ControllerName
+ );
+
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.mbd b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.mbd
new file mode 100644
index 0000000000..ecb6af6c96
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.mbd
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>UsbKb</BaseName>
+ <Guid>2D2E62CF-9ECF-43b7-8219-94E7FC713DFE</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiRuntimeServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>EdkUsbLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.msa b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.msa
new file mode 100644
index 0000000000..0ff6464825
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.msa
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>UsbKb</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>2D2E62CF-9ECF-43b7-8219-94E7FC713DFE</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for UsbKb module</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">EdkUsbLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiRuntimeServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>efikey.h</Filename>
+ <Filename>keyboard.h</Filename>
+ <Filename>efikey.c</Filename>
+ <Filename>keyboard.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">DevicePath</Protocol>
+ <Protocol Usage="TO_START">UsbIo</Protocol>
+ <Protocol Usage="BY_START">SimpleTextIn</Protocol>
+ </Protocols>
+ <Guids>
+ <GuidEntry Usage="SOMETIMES_CONSUMED">
+ <C_Name>HotPlugDevice</C_Name>
+ </GuidEntry>
+ </Guids>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gUsbKeyboardDriverBinding</DriverBinding>
+ <ComponentName>gUsbKeyboardComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/build.xml b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/build.xml
new file mode 100644
index 0000000000..2608381d96
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
+<project basedir="." default="UsbKb"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Usb\UsbKb\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="UsbKb">
+ <GenBuild baseName="UsbKb" mbdFilename="${MODULE_DIR}\UsbKb.mbd" msaFilename="${MODULE_DIR}\UsbKb.msa"/>
+ </target>
+ <target depends="UsbKb_clean" name="clean"/>
+ <target depends="UsbKb_cleanall" name="cleanall"/>
+ <target name="UsbKb_clean">
+ <OutputDirSetup baseName="UsbKb" mbdFilename="${MODULE_DIR}\UsbKb.mbd" msaFilename="${MODULE_DIR}\UsbKb.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbKb_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbKb_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="UsbKb_cleanall">
+ <OutputDirSetup baseName="UsbKb" mbdFilename="${MODULE_DIR}\UsbKb.mbd" msaFilename="${MODULE_DIR}\UsbKb.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbKb_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbKb_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**UsbKb*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.c b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.c
new file mode 100644
index 0000000000..a9cdbc8760
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.c
@@ -0,0 +1,772 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiKey.c
+
+Abstract:
+
+ USB Keyboard Driver
+
+Revision History
+
+--*/
+
+#include "efikey.h"
+#include "keyboard.h"
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+EFI_STATUS
+EFIAPI
+USBKeyboardDriverBindingEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+EFI_STATUS
+EFIAPI
+USBKeyboardDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+USBKeyboardDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+USBKeyboardDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// Simple Text In Protocol Interface
+//
+STATIC
+EFI_STATUS
+EFIAPI
+USBKeyboardReset (
+ IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBKeyboardReadKeyStroke (
+ IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+ );
+
+STATIC
+VOID
+EFIAPI
+USBKeyboardWaitForKey (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+//
+// Helper functions
+//
+STATIC
+EFI_STATUS
+USBKeyboardCheckForKey (
+ IN USB_KB_DEV *UsbKeyboardDevice
+ );
+
+//
+// USB Keyboard Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding = {
+ USBKeyboardDriverBindingSupported,
+ USBKeyboardDriverBindingStart,
+ USBKeyboardDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+EFI_STATUS
+EFIAPI
+USBKeyboardDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Supported.
+
+ Arguments:
+ This - EFI_DRIVER_BINDING_PROTOCOL
+ Controller - Controller handle
+ RemainingDevicePath - EFI_DEVICE_PATH_PROTOCOL
+ Returns:
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS OpenStatus;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_STATUS Status;
+
+ //
+ // Check if USB_IO protocol is attached on the controller handle.
+ //
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (OpenStatus)) {
+ return OpenStatus;
+ }
+
+ //
+ // Use the USB I/O protocol interface to check whether the Controller is
+ // the Keyboard controller that can be managed by this driver.
+ //
+ Status = EFI_SUCCESS;
+
+ if (!IsUSBKeyboard (UsbIo)) {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+USBKeyboardDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Start.
+
+ Arguments:
+ This - EFI_DRIVER_BINDING_PROTOCOL
+ Controller - Controller handle
+ RemainingDevicePath - EFI_DEVICE_PATH_PROTOCOL
+ Returns:
+ EFI_SUCCESS - Success
+ EFI_OUT_OF_RESOURCES - Can't allocate memory
+ EFI_UNSUPPORTED - The Start routine fail
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ USB_KB_DEV *UsbKeyboardDevice;
+ UINT8 EndpointNumber;
+ EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+ UINT8 Index;
+ UINT8 EndpointAddr;
+ UINT8 PollingInterval;
+ UINT8 PacketSize;
+ BOOLEAN Found;
+
+ UsbKeyboardDevice = NULL;
+ Found = FALSE;
+
+ //
+ // Open USB_IO Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UsbKeyboardDevice = AllocateZeroPool (sizeof (USB_KB_DEV));
+ if (UsbKeyboardDevice == NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Get the Device Path Protocol on Controller's handle
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &UsbKeyboardDevice->DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (UsbKeyboardDevice);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+ //
+ // Report that the usb keyboard is being enabled
+ //
+ KbdReportStatusCode (
+ UsbKeyboardDevice->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE)
+ );
+
+ //
+ // This is pretty close to keyboard detection, so log progress
+ //
+ KbdReportStatusCode (
+ UsbKeyboardDevice->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT)
+ );
+
+ //
+ // Initialize UsbKeyboardDevice
+ //
+ UsbKeyboardDevice->UsbIo = UsbIo;
+
+ //
+ // Get interface & endpoint descriptor
+ //
+ UsbIo->UsbGetInterfaceDescriptor (
+ UsbIo,
+ &UsbKeyboardDevice->InterfaceDescriptor
+ );
+
+ EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints;
+
+ for (Index = 0; Index < EndpointNumber; Index++) {
+
+ UsbIo->UsbGetEndpointDescriptor (
+ UsbIo,
+ Index,
+ &EndpointDescriptor
+ );
+
+ if ((EndpointDescriptor.Attributes & 0x03) == 0x03) {
+ //
+ // We only care interrupt endpoint here
+ //
+ CopyMem (&UsbKeyboardDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof (EndpointDescriptor));
+ //UsbKeyboardDevice->IntEndpointDescriptor = EndpointDescriptor;
+ Found = TRUE;
+ }
+ }
+
+ if (!Found) {
+ //
+ // No interrupt endpoint found, then return unsupported.
+ //
+ gBS->FreePool (UsbKeyboardDevice);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_UNSUPPORTED;
+ }
+
+ UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;
+ UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;
+ UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;
+ Status = gBS->CreateEvent (
+ EFI_EVENT_NOTIFY_WAIT,
+ EFI_TPL_NOTIFY,
+ USBKeyboardWaitForKey,
+ UsbKeyboardDevice,
+ &(UsbKeyboardDevice->SimpleInput.WaitForKey)
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (UsbKeyboardDevice);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+
+ //
+ // Install simple txt in protocol interface
+ // for the usb keyboard device.
+ // Usb keyboard is a hot plug device, and expected to work immediately
+ // when plugging into system, so a HotPlugDeviceGuid is installed onto
+ // the usb keyboard device handle, to distinguish it from other conventional
+ // console devices.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ &UsbKeyboardDevice->SimpleInput,
+ &gEfiHotPlugDeviceGuid,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
+ gBS->FreePool (UsbKeyboardDevice);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+
+ //
+ // Reset USB Keyboard Device
+ //
+ Status = UsbKeyboardDevice->SimpleInput.Reset (
+ &UsbKeyboardDevice->SimpleInput,
+ TRUE
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ &UsbKeyboardDevice->SimpleInput,
+ &gEfiHotPlugDeviceGuid,
+ NULL,
+ NULL
+ );
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
+ gBS->FreePool (UsbKeyboardDevice);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+ //
+ // submit async interrupt transfer
+ //
+ EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress;
+ PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval;
+ PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
+
+ Status = UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ EndpointAddr,
+ TRUE,
+ PollingInterval,
+ PacketSize,
+ KeyboardHandler,
+ UsbKeyboardDevice
+ );
+
+ if (EFI_ERROR (Status)) {
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ &UsbKeyboardDevice->SimpleInput,
+ &gEfiHotPlugDeviceGuid,
+ NULL,
+ NULL
+ );
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);
+ gBS->FreePool (UsbKeyboardDevice);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+
+ UsbKeyboardDevice->ControllerNameTable = NULL;
+ AddUnicodeString (
+ "eng",
+ gUsbKeyboardComponentName.SupportedLanguages,
+ &UsbKeyboardDevice->ControllerNameTable,
+ (CHAR16 *) L"Generic Usb Keyboard"
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+USBKeyboardDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+ Stop.
+
+ Arguments:
+ This - EFI_DRIVER_BINDING_PROTOCOL
+ Controller - Controller handle
+ NumberOfChildren - Child handle number
+ ChildHandleBuffer - Child handle buffer
+ Returns:
+ EFI_SUCCESS - Success
+ EFI_UNSUPPORTED - Can't support
+--*/
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_TEXT_IN_PROTOCOL *SimpleInput;
+ USB_KB_DEV *UsbKeyboardDevice;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ (VOID **) &SimpleInput,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get USB_KB_DEV instance.
+ //
+ UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput);
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ UsbIo = UsbKeyboardDevice->UsbIo;
+ //
+ // Uninstall the Asyn Interrupt Transfer from this device
+ // will disable the key data input from this device
+ //
+ KbdReportStatusCode (
+ UsbKeyboardDevice->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE)
+ );
+
+ //
+ // Destroy asynchronous interrupt transfer
+ //
+ UsbKeyboardDevice->UsbIo->UsbAsyncInterruptTransfer (
+ UsbKeyboardDevice->UsbIo,
+ UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
+ FALSE,
+ UsbKeyboardDevice->IntEndpointDescriptor.Interval,
+ 0,
+ NULL,
+ NULL
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiSimpleTextInProtocolGuid,
+ &UsbKeyboardDevice->SimpleInput,
+ &gEfiHotPlugDeviceGuid,
+ NULL,
+ NULL
+ );
+ //
+ // free all the resources.
+ //
+ gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
+ gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
+ gBS->CloseEvent ((UsbKeyboardDevice->SimpleInput).WaitForKey);
+
+ if (UsbKeyboardDevice->ControllerNameTable != NULL) {
+ FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);
+ }
+
+ gBS->FreePool (UsbKeyboardDevice);
+
+ return Status;
+
+}
+
+
+EFI_STATUS
+EFIAPI
+USBKeyboardReset (
+ IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+ Routine Description:
+ Implements EFI_SIMPLE_TEXT_IN_PROTOCOL.Reset() function.
+
+ Arguments:
+ This The EFI_SIMPLE_TEXT_IN_PROTOCOL instance.
+ ExtendedVerification
+ Indicates that the driver may perform a more exhaustive
+ verification operation of the device during reset.
+
+ Returns:
+ EFI_SUCCESS - Success
+ EFI_DEVICE_ERROR - Hardware Error
+--*/
+{
+ EFI_STATUS Status;
+ USB_KB_DEV *UsbKeyboardDevice;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);
+
+ UsbIo = UsbKeyboardDevice->UsbIo;
+
+ KbdReportStatusCode (
+ UsbKeyboardDevice->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET)
+ );
+
+ //
+ // Non Exhaustive reset:
+ // only reset private data structures.
+ //
+ if (!ExtendedVerification) {
+ //
+ // Clear the key buffer of this Usb keyboard
+ //
+ KbdReportStatusCode (
+ UsbKeyboardDevice->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER)
+ );
+
+ InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));
+ UsbKeyboardDevice->CurKeyChar = 0;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Exhaustive reset
+ //
+ Status = InitUSBKeyboard (UsbKeyboardDevice);
+ UsbKeyboardDevice->CurKeyChar = 0;
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBKeyboardReadKeyStroke (
+ IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This,
+ OUT EFI_INPUT_KEY *Key
+ )
+/*++
+
+ Routine Description:
+ Implements EFI_SIMPLE_TEXT_IN_PROTOCOL.ReadKeyStroke() function.
+
+ Arguments:
+ This The EFI_SIMPLE_TEXT_IN_PROTOCOL instance.
+ Key A pointer to a buffer that is filled in with the keystroke
+ information for the key that was pressed.
+
+ Returns:
+ EFI_SUCCESS - Success
+--*/
+{
+ USB_KB_DEV *UsbKeyboardDevice;
+ EFI_STATUS Status;
+ UINT8 KeyChar;
+
+ UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);
+
+ //
+ // if there is no saved ASCII byte, fetch it
+ // by calling USBKeyboardCheckForKey().
+ //
+ if (UsbKeyboardDevice->CurKeyChar == 0) {
+ Status = USBKeyboardCheckForKey (UsbKeyboardDevice);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Key->UnicodeChar = 0;
+ Key->ScanCode = SCAN_NULL;
+
+ KeyChar = UsbKeyboardDevice->CurKeyChar;
+
+ UsbKeyboardDevice->CurKeyChar = 0;
+
+ //
+ // Translate saved ASCII byte into EFI_INPUT_KEY
+ //
+ Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, Key);
+
+ return Status;
+
+}
+
+STATIC
+VOID
+EFIAPI
+USBKeyboardWaitForKey (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+ Routine Description:
+ Handler function for WaitForKey event.
+
+ Arguments:
+ Event Event to be signaled when a key is pressed.
+ Context Points to USB_KB_DEV instance.
+
+ Returns:
+ VOID
+--*/
+{
+ USB_KB_DEV *UsbKeyboardDevice;
+
+ UsbKeyboardDevice = (USB_KB_DEV *) Context;
+
+ if (UsbKeyboardDevice->CurKeyChar == 0) {
+
+ if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice))) {
+ return ;
+ }
+ }
+ //
+ // If has key pending, signal the event.
+ //
+ gBS->SignalEvent (Event);
+}
+
+
+STATIC
+EFI_STATUS
+USBKeyboardCheckForKey (
+ IN USB_KB_DEV *UsbKeyboardDevice
+ )
+/*++
+
+ Routine Description:
+ Check whether there is key pending.
+
+ Arguments:
+ UsbKeyboardDevice The USB_KB_DEV instance.
+
+ Returns:
+ EFI_SUCCESS - Success
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 KeyChar;
+
+ //
+ // Fetch raw data from the USB keyboard input,
+ // and translate it into ASCII data.
+ //
+ Status = USBParseKey (UsbKeyboardDevice, &KeyChar);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UsbKeyboardDevice->CurKeyChar = KeyChar;
+ return EFI_SUCCESS;
+}
+
+VOID
+KbdReportStatusCode (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value
+ )
+/*++
+
+ Routine Description:
+ Report Status Code in Usb Bot Driver
+
+ Arguments:
+ DevicePath - Use this to get Device Path
+ CodeType - Status Code Type
+ CodeValue - Status Code Value
+
+ Returns:
+ None
+
+--*/
+{
+
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ CodeType,
+ Value,
+ DevicePath
+ );
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.h b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.h
new file mode 100644
index 0000000000..bf9f47732d
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.h
@@ -0,0 +1,118 @@
+/*++
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EfiKey.h
+
+Abstract:
+
+ Header file for USB Keyboard Driver's Data Structures
+
+Revision History
+--*/
+#ifndef _USB_KB_H
+#define _USB_KB_H
+
+
+#include <IndustryStandard/usb.h>
+
+#define MAX_KEY_ALLOWED 32
+
+#define HZ 1000 * 1000 * 10
+#define USBKBD_REPEAT_DELAY ((HZ) / 2)
+#define USBKBD_REPEAT_RATE ((HZ) / 50)
+
+#define CLASS_HID 3
+#define SUBCLASS_BOOT 1
+#define PROTOCOL_KEYBOARD 1
+
+#define BOOT_PROTOCOL 0
+#define REPORT_PROTOCOL 1
+
+typedef struct {
+ UINT8 Down;
+ UINT8 KeyCode;
+} USB_KEY;
+
+typedef struct {
+ USB_KEY buffer[MAX_KEY_ALLOWED + 1];
+ UINT8 bHead;
+ UINT8 bTail;
+} USB_KB_BUFFER;
+
+#define USB_KB_DEV_SIGNATURE EFI_SIGNATURE_32 ('u', 'k', 'b', 'd')
+typedef struct {
+ UINTN Signature;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_EVENT DelayedRecoveryEvent;
+ EFI_SIMPLE_TEXT_IN_PROTOCOL SimpleInput;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+ EFI_USB_ENDPOINT_DESCRIPTOR IntEndpointDescriptor;
+
+ USB_KB_BUFFER KeyboardBuffer;
+ UINT8 CtrlOn;
+ UINT8 AltOn;
+ UINT8 ShiftOn;
+ UINT8 NumLockOn;
+ UINT8 CapsOn;
+ UINT8 LastKeyCodeArray[8];
+ UINT8 CurKeyChar;
+
+ UINT8 RepeatKey;
+ EFI_EVENT RepeatTimer;
+
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+
+} USB_KB_DEV;
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gUsbKeyboardComponentName;
+extern EFI_GUID gEfiUsbKeyboardDriverGuid;
+
+VOID
+KbdReportStatusCode (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value
+ );
+
+#define USB_KB_DEV_FROM_THIS(a) \
+ CR(a, USB_KB_DEV, SimpleInput, USB_KB_DEV_SIGNATURE)
+
+#define MOD_CONTROL_L 0x01
+#define MOD_CONTROL_R 0x10
+#define MOD_SHIFT_L 0x02
+#define MOD_SHIFT_R 0x20
+#define MOD_ALT_L 0x04
+#define MOD_ALT_R 0x40
+#define MOD_WIN_L 0x08
+#define MOD_WIN_R 0x80
+
+typedef struct {
+ UINT8 Mask;
+ UINT8 Key;
+} KB_MODIFIER;
+
+#define USB_KEYCODE_MAX_MAKE 0x64
+
+#define USBKBD_VALID_KEYCODE(key) ((UINT8) (key) > 3)
+
+typedef struct {
+ UINT8 NumLock : 1;
+ UINT8 CapsLock : 1;
+ UINT8 Resrvd : 6;
+} LED_MAP;
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.c b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.c
new file mode 100644
index 0000000000..1328e6a098
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.c
@@ -0,0 +1,1150 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Keyboard.c
+
+Abstract:
+
+ Helper functions for USB Keyboard Driver
+
+Revision History
+
+--*/
+
+#include "keyboard.h"
+
+//
+// USB Key Code to Efi key mapping table
+// Format:<efi scan code>, <unicode without shift>, <unicode with shift>
+//
+STATIC
+UINT8 KeyConvertionTable[USB_KEYCODE_MAX_MAKE][3] = {
+ { SCAN_NULL, 'a', 'A' }, // 0x04
+ { SCAN_NULL, 'b', 'B' }, // 0x05
+ { SCAN_NULL, 'c', 'C' }, // 0x06
+ { SCAN_NULL, 'd', 'D' }, // 0x07
+ { SCAN_NULL, 'e', 'E' }, // 0x08
+ { SCAN_NULL, 'f', 'F' }, // 0x09
+ { SCAN_NULL, 'g', 'G' }, // 0x0A
+ { SCAN_NULL, 'h', 'H' }, // 0x0B
+ { SCAN_NULL, 'i', 'I' }, // 0x0C
+ { SCAN_NULL, 'j', 'J' }, // 0x0D
+ { SCAN_NULL, 'k', 'K' }, // 0x0E
+ { SCAN_NULL, 'l', 'L' }, // 0x0F
+ { SCAN_NULL, 'm', 'M' }, // 0x10
+ { SCAN_NULL, 'n', 'N' }, // 0x11
+ { SCAN_NULL, 'o', 'O' }, // 0x12
+ { SCAN_NULL, 'p', 'P' }, // 0x13
+ { SCAN_NULL, 'q', 'Q' }, // 0x14
+ { SCAN_NULL, 'r', 'R' }, // 0x15
+ { SCAN_NULL, 's', 'S' }, // 0x16
+ { SCAN_NULL, 't', 'T' }, // 0x17
+ { SCAN_NULL, 'u', 'U' }, // 0x18
+ { SCAN_NULL, 'v', 'V' }, // 0x19
+ { SCAN_NULL, 'w', 'W' }, // 0x1A
+ { SCAN_NULL, 'x', 'X' }, // 0x1B
+ { SCAN_NULL, 'y', 'Y' }, // 0x1C
+ { SCAN_NULL, 'z', 'Z' }, // 0x1D
+ { SCAN_NULL, '1', '!' }, // 0x1E
+ { SCAN_NULL, '2', '@' }, // 0x1F
+ { SCAN_NULL, '3', '#' }, // 0x20
+ { SCAN_NULL, '4', '$' }, // 0x21
+ { SCAN_NULL, '5', '%' }, // 0x22
+ { SCAN_NULL, '6', '^' }, // 0x23
+ { SCAN_NULL, '7', '&' }, // 0x24
+ { SCAN_NULL, '8', '*' }, // 0x25
+ { SCAN_NULL, '9', '(' }, // 0x26
+ { SCAN_NULL, '0', ')' }, // 0x27
+ { SCAN_NULL, 0x0d, 0x0d }, // 0x28 Enter
+ { SCAN_ESC, 0x00, 0x00 }, // 0x29 Esc
+ { SCAN_NULL, 0x08, 0x08 }, // 0x2A Backspace
+ { SCAN_NULL, 0x09, 0x09 }, // 0x2B Tab
+ { SCAN_NULL, ' ', ' ' }, // 0x2C Spacebar
+ { SCAN_NULL, '-', '_' }, // 0x2D
+ { SCAN_NULL, '=', '+' }, // 0x2E
+ { SCAN_NULL, '[', '{' }, // 0x2F
+ { SCAN_NULL, ']', '}' }, // 0x30
+ { SCAN_NULL, '\\', '|' }, // 0x31
+ { SCAN_NULL, '\\', '|' }, // 0x32 Keyboard US \ and |
+ { SCAN_NULL, ';', ':' }, // 0x33
+ { SCAN_NULL, '\'', '"' }, // 0x34
+ { SCAN_NULL, '`', '~' }, // 0x35 Keyboard Grave Accent and Tlide
+ { SCAN_NULL, ',', '<' }, // 0x36
+ { SCAN_NULL, '.', '>' }, // 0x37
+ { SCAN_NULL, '/', '?' }, // 0x38
+ { SCAN_NULL, 0x00, 0x00 }, // 0x39 CapsLock
+ { SCAN_F1, 0x00, 0x00 }, // 0x3A
+ { SCAN_F2, 0x00, 0x00 }, // 0x3B
+ { SCAN_F3, 0x00, 0x00 }, // 0x3C
+ { SCAN_F4, 0x00, 0x00 }, // 0x3D
+ { SCAN_F5, 0x00, 0x00 }, // 0x3E
+ { SCAN_F6, 0x00, 0x00 }, // 0x3F
+ { SCAN_F7, 0x00, 0x00 }, // 0x40
+ { SCAN_F8, 0x00, 0x00 }, // 0x41
+ { SCAN_F9, 0x00, 0x00 }, // 0x42
+ { SCAN_F10, 0x00, 0x00 }, // 0x43
+ { SCAN_NULL, 0x00, 0x00 }, // 0x44 F11
+ { SCAN_NULL, 0x00, 0x00 }, // 0x45 F12
+ { SCAN_NULL, 0x00, 0x00 }, // 0x46 PrintScreen
+ { SCAN_NULL, 0x00, 0x00 }, // 0x47 Scroll Lock
+ { SCAN_NULL, 0x00, 0x00 }, // 0x48 Pause
+ { SCAN_INSERT, 0x00, 0x00 }, // 0x49
+ { SCAN_HOME, 0x00, 0x00 }, // 0x4A
+ { SCAN_PAGE_UP, 0x00, 0x00 }, // 0x4B
+ { SCAN_DELETE, 0x00, 0x00 }, // 0x4C
+ { SCAN_END, 0x00, 0x00 }, // 0x4D
+ { SCAN_PAGE_DOWN, 0x00, 0x00 }, // 0x4E
+ { SCAN_RIGHT, 0x00, 0x00 }, // 0x4F
+ { SCAN_LEFT, 0x00, 0x00 }, // 0x50
+ { SCAN_DOWN, 0x00, 0x00 }, // 0x51
+ { SCAN_UP, 0x00, 0x00 }, // 0x52
+ { SCAN_NULL, 0x00, 0x00 }, // 0x53 NumLock
+ { SCAN_NULL, '/', '/' }, // 0x54
+ { SCAN_NULL, '*', '*' }, // 0x55
+ { SCAN_NULL, '-', '-' }, // 0x56
+ { SCAN_NULL, '+', '+' }, // 0x57
+ { SCAN_NULL, 0x0d, 0x0d }, // 0x58
+ { SCAN_END, '1', '1' }, // 0x59
+ { SCAN_DOWN, '2', '2' }, // 0x5A
+ { SCAN_PAGE_DOWN, '3', '3' }, // 0x5B
+ { SCAN_LEFT, '4', '4' }, // 0x5C
+ { SCAN_NULL, '5', '5' }, // 0x5D
+ { SCAN_RIGHT, '6', '6' }, // 0x5E
+ { SCAN_HOME, '7', '7' }, // 0x5F
+ { SCAN_UP, '8', '8' }, // 0x60
+ { SCAN_PAGE_UP, '9', '9' }, // 0x61
+ { SCAN_INSERT, '0', '0' }, // 0x62
+ { SCAN_DELETE, '.', '.' }, // 0x63
+ { SCAN_NULL, '\\', '|' }, // 0x64 Keyboard Non-US \ and |
+ { SCAN_NULL, 0x00, 0x00 }, // 0x65 Keyboard Application
+ { SCAN_NULL, 0x00, 0x00 }, // 0x66 Keyboard Power
+ { SCAN_NULL, '=' , '=' } // 0x67 Keypad =
+};
+
+STATIC KB_MODIFIER KB_Mod[8] = {
+ { MOD_CONTROL_L, 0xe0 }, // 11100000
+ { MOD_CONTROL_R, 0xe4 }, // 11100100
+ { MOD_SHIFT_L, 0xe1 }, // 11100001
+ { MOD_SHIFT_R, 0xe5 }, // 11100101
+ { MOD_ALT_L, 0xe2 }, // 11100010
+ { MOD_ALT_R, 0xe6 }, // 11100110
+ { MOD_WIN_L, 0xe3 }, // 11100011
+ { MOD_WIN_R, 0xe7 } // 11100111
+};
+
+
+BOOLEAN
+IsUSBKeyboard (
+ IN EFI_USB_IO_PROTOCOL *UsbIo
+ )
+/*++
+
+ Routine Description:
+ Uses USB I/O to check whether the device is a USB Keyboard device.
+
+ Arguments:
+ UsbIo: Points to a USB I/O protocol instance.
+
+ Returns:
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+
+ //
+ // Get the Default interface descriptor, currently we
+ // assume it is interface 1
+ //
+ Status = UsbIo->UsbGetInterfaceDescriptor (
+ UsbIo,
+ &InterfaceDescriptor
+ );
+
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ if (InterfaceDescriptor.InterfaceClass == CLASS_HID &&
+ InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT &&
+ InterfaceDescriptor.InterfaceProtocol == PROTOCOL_KEYBOARD
+ ) {
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+EFI_STATUS
+InitUSBKeyboard (
+ IN USB_KB_DEV *UsbKeyboardDevice
+ )
+/*++
+
+ Routine Description:
+ Initialize USB Keyboard device and all private data structures.
+
+ Arguments:
+ UsbKeyboardDevice The USB_KB_DEV instance.
+
+ Returns:
+ EFI_SUCCESS - Success
+ EFI_DEVICE_ERROR - Hardware Error
+--*/
+{
+ UINT8 ConfigValue;
+ UINT8 Protocol;
+ UINT8 ReportId;
+ UINT8 Duration;
+ EFI_STATUS Status;
+ UINT32 TransferResult;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ UsbIo = UsbKeyboardDevice->UsbIo;
+
+ KbdReportStatusCode (
+ UsbKeyboardDevice->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST)
+ );
+
+ InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));
+
+ //
+ // default configurations
+ //
+ ConfigValue = 0x01;
+
+ //
+ // Uses default configuration to configure the USB Keyboard device.
+ //
+ Status = UsbSetDeviceConfiguration (
+ UsbKeyboardDevice->UsbIo,
+ (UINT16) ConfigValue,
+ &TransferResult
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If configuration could not be set here, it means
+ // the keyboard interface has some errors and could
+ // not be initialized
+ //
+ KbdReportStatusCode (
+ UsbKeyboardDevice->DevicePath,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR)
+ );
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbGetProtocolRequest (
+ UsbKeyboardDevice->UsbIo,
+ UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
+ &Protocol
+ );
+ //
+ // Sets boot protocol for the USB Keyboard.
+ // This driver only supports boot protocol.
+ // !!BugBug: How about the device that does not support boot protocol?
+ //
+ if (Protocol != BOOT_PROTOCOL) {
+ UsbSetProtocolRequest (
+ UsbKeyboardDevice->UsbIo,
+ UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
+ BOOT_PROTOCOL
+ );
+ }
+ //
+ // the duration is indefinite, so the endpoint will inhibit reporting forever,
+ // and only reporting when a change is detected in the report data.
+ //
+
+ //
+ // idle value for all report ID
+ //
+ ReportId = 0;
+ //
+ // idle forever until there is a key pressed and released.
+ //
+ Duration = 0;
+ UsbSetIdleRequest (
+ UsbKeyboardDevice->UsbIo,
+ UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
+ ReportId,
+ Duration
+ );
+
+ UsbKeyboardDevice->CtrlOn = 0;
+ UsbKeyboardDevice->AltOn = 0;
+ UsbKeyboardDevice->ShiftOn = 0;
+ UsbKeyboardDevice->NumLockOn = 0;
+ UsbKeyboardDevice->CapsOn = 0;
+ ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8);
+
+ //
+ // Set a timer for repeat keys' generation.
+ //
+ if (UsbKeyboardDevice->RepeatTimer) {
+ gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);
+ UsbKeyboardDevice->RepeatTimer = 0;
+ }
+
+ Status = gBS->CreateEvent (
+ EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_NOTIFY,
+ USBKeyboardRepeatHandler,
+ UsbKeyboardDevice,
+ &UsbKeyboardDevice->RepeatTimer
+ );
+
+ if (UsbKeyboardDevice->DelayedRecoveryEvent) {
+ gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);
+ UsbKeyboardDevice->DelayedRecoveryEvent = 0;
+ }
+
+ Status = gBS->CreateEvent (
+ EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_NOTIFY,
+ USBKeyboardRecoveryHandler,
+ UsbKeyboardDevice,
+ &UsbKeyboardDevice->DelayedRecoveryEvent
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+KeyboardHandler (
+ IN VOID *Data,
+ IN UINTN DataLength,
+ IN VOID *Context,
+ IN UINT32 Result
+ )
+/*++
+
+ Routine Description:
+ Handler function for USB Keyboard's asynchronous interrupt transfer.
+
+ Arguments:
+ Data A pointer to a buffer that is filled with key data which is
+ retrieved via asynchronous interrupt transfer.
+ DataLength Indicates the size of the data buffer.
+ Context Pointing to USB_KB_DEV instance.
+ Result Indicates the result of the asynchronous interrupt transfer.
+
+ Returns:
+ EFI_SUCCESS - Success
+ EFI_DEVICE_ERROR - Hardware Error
+--*/
+{
+ USB_KB_DEV *UsbKeyboardDevice;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 *CurKeyCodeBuffer;
+ UINT8 *OldKeyCodeBuffer;
+ UINT8 CurModifierMap;
+ UINT8 OldModifierMap;
+ UINT8 Index;
+ UINT8 Index2;
+ BOOLEAN Down;
+ EFI_STATUS Status;
+ BOOLEAN KeyRelease;
+ BOOLEAN KeyPress;
+ UINT8 SavedTail;
+ USB_KEY UsbKey;
+ UINT8 NewRepeatKey;
+ UINT32 UsbStatus;
+ UINT8 *DataPtr;
+
+ ASSERT (Context);
+
+ NewRepeatKey = 0;
+ DataPtr = (UINT8 *) Data;
+ UsbKeyboardDevice = (USB_KB_DEV *) Context;
+ UsbIo = UsbKeyboardDevice->UsbIo;
+
+ //
+ // Analyzes the Result and performs corresponding action.
+ //
+ if (Result != EFI_USB_NOERROR) {
+ //
+ // Some errors happen during the process
+ //
+ KbdReportStatusCode (
+ UsbKeyboardDevice->DevicePath,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INPUT_ERROR)
+ );
+
+ //
+ // stop the repeat key generation if any
+ //
+ UsbKeyboardDevice->RepeatKey = 0;
+
+ gBS->SetTimer (
+ UsbKeyboardDevice->RepeatTimer,
+ TimerCancel,
+ USBKBD_REPEAT_RATE
+ );
+
+ if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
+ UsbClearEndpointHalt (
+ UsbIo,
+ UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
+ &UsbStatus
+ );
+ }
+
+ //
+ // Delete & Submit this interrupt again
+ //
+
+ Status = UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
+ FALSE,
+ 0,
+ 0,
+ NULL,
+ NULL
+ );
+
+ gBS->SetTimer (
+ UsbKeyboardDevice->DelayedRecoveryEvent,
+ TimerRelative,
+ EFI_USB_INTERRUPT_DELAY
+ );
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (DataLength == 0 || Data == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ CurKeyCodeBuffer = (UINT8 *) Data;
+ OldKeyCodeBuffer = UsbKeyboardDevice->LastKeyCodeArray;
+
+ //
+ // checks for new key stroke.
+ // if no new key got, return immediately.
+ //
+ for (Index = 0; Index < 8; Index++) {
+ if (OldKeyCodeBuffer[Index] != CurKeyCodeBuffer[Index]) {
+ break;
+ }
+ }
+
+ if (Index == 8) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Parse the modifier key
+ //
+ CurModifierMap = CurKeyCodeBuffer[0];
+ OldModifierMap = OldKeyCodeBuffer[0];
+
+ //
+ // handle modifier key's pressing or releasing situation.
+ //
+ for (Index = 0; Index < 8; Index++) {
+
+ if ((CurModifierMap & KB_Mod[Index].Mask) != (OldModifierMap & KB_Mod[Index].Mask)) {
+ //
+ // if current modifier key is up, then
+ // CurModifierMap & KB_Mod[Index].Mask = 0;
+ // otherwize it is a non-zero value.
+ // Inserts the pressed modifier key into key buffer.
+ //
+ Down = (UINT8) (CurModifierMap & KB_Mod[Index].Mask);
+ InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), KB_Mod[Index].Key, Down);
+ }
+ }
+
+ //
+ // handle normal key's releasing situation
+ //
+ KeyRelease = FALSE;
+ for (Index = 2; Index < 8; Index++) {
+
+ if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index])) {
+ continue;
+ }
+
+ KeyRelease = TRUE;
+ for (Index2 = 2; Index2 < 8; Index2++) {
+
+ if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index2])) {
+ continue;
+ }
+
+ if (OldKeyCodeBuffer[Index] == CurKeyCodeBuffer[Index2]) {
+ KeyRelease = FALSE;
+ break;
+ }
+ }
+
+ if (KeyRelease) {
+ InsertKeyCode (
+ &(UsbKeyboardDevice->KeyboardBuffer),
+ OldKeyCodeBuffer[Index],
+ 0
+ );
+ //
+ // the original reapeat key is released.
+ //
+ if (OldKeyCodeBuffer[Index] == UsbKeyboardDevice->RepeatKey) {
+ UsbKeyboardDevice->RepeatKey = 0;
+ }
+ }
+ }
+
+ //
+ // original repeat key is released, cancel the repeat timer
+ //
+ if (UsbKeyboardDevice->RepeatKey == 0) {
+ gBS->SetTimer (
+ UsbKeyboardDevice->RepeatTimer,
+ TimerCancel,
+ USBKBD_REPEAT_RATE
+ );
+ }
+
+ //
+ // handle normal key's pressing situation
+ //
+ KeyPress = FALSE;
+ for (Index = 2; Index < 8; Index++) {
+
+ if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index])) {
+ continue;
+ }
+
+ KeyPress = TRUE;
+ for (Index2 = 2; Index2 < 8; Index2++) {
+
+ if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index2])) {
+ continue;
+ }
+
+ if (CurKeyCodeBuffer[Index] == OldKeyCodeBuffer[Index2]) {
+ KeyPress = FALSE;
+ break;
+ }
+ }
+
+ if (KeyPress) {
+ InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), CurKeyCodeBuffer[Index], 1);
+ //
+ // NumLock pressed or CapsLock pressed
+ //
+ if (CurKeyCodeBuffer[Index] == 0x53 || CurKeyCodeBuffer[Index] == 0x39) {
+ UsbKeyboardDevice->RepeatKey = 0;
+ } else {
+ NewRepeatKey = CurKeyCodeBuffer[Index];
+ //
+ // do not repeat the original repeated key
+ //
+ UsbKeyboardDevice->RepeatKey = 0;
+ }
+ }
+ }
+
+ //
+ // Update LastKeycodeArray[] buffer in the
+ // Usb Keyboard Device data structure.
+ //
+ for (Index = 0; Index < 8; Index++) {
+ UsbKeyboardDevice->LastKeyCodeArray[Index] = CurKeyCodeBuffer[Index];
+ }
+
+ //
+ // pre-process KeyboardBuffer, pop out the ctrl,alt,del key in sequence
+ // and judge whether it will invoke reset event.
+ //
+ SavedTail = UsbKeyboardDevice->KeyboardBuffer.bTail;
+ Index = UsbKeyboardDevice->KeyboardBuffer.bHead;
+ while (Index != SavedTail) {
+ RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);
+
+ switch (UsbKey.KeyCode) {
+
+ case 0xe0:
+ case 0xe4:
+ if (UsbKey.Down) {
+ UsbKeyboardDevice->CtrlOn = 1;
+ } else {
+ UsbKeyboardDevice->CtrlOn = 0;
+ }
+ break;
+
+ case 0xe2:
+ case 0xe6:
+ if (UsbKey.Down) {
+ UsbKeyboardDevice->AltOn = 1;
+ } else {
+ UsbKeyboardDevice->AltOn = 0;
+ }
+ break;
+
+ //
+ // Del Key Code
+ //
+ case 0x4c:
+ case 0x63:
+ if (UsbKey.Down) {
+ if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) {
+ gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ //
+ // insert the key back to the buffer.
+ // so the key sequence will not be destroyed.
+ //
+ InsertKeyCode (
+ &(UsbKeyboardDevice->KeyboardBuffer),
+ UsbKey.KeyCode,
+ UsbKey.Down
+ );
+ Index = UsbKeyboardDevice->KeyboardBuffer.bHead;
+
+ }
+ //
+ // If have new key pressed, update the RepeatKey value, and set the
+ // timer to repeate delay timer
+ //
+ if (NewRepeatKey != 0) {
+ //
+ // sets trigger time to "Repeat Delay Time",
+ // to trigger the repeat timer when the key is hold long
+ // enough time.
+ //
+ gBS->SetTimer (
+ UsbKeyboardDevice->RepeatTimer,
+ TimerRelative,
+ USBKBD_REPEAT_DELAY
+ );
+ UsbKeyboardDevice->RepeatKey = NewRepeatKey;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+USBParseKey (
+ IN OUT USB_KB_DEV *UsbKeyboardDevice,
+ OUT UINT8 *KeyChar
+ )
+/*++
+
+ Routine Description:
+ Retrieves a key character after parsing the raw data in keyboard buffer.
+
+ Arguments:
+ UsbKeyboardDevice The USB_KB_DEV instance.
+ KeyChar Points to the Key character after key parsing.
+
+ Returns:
+ EFI_SUCCESS - Success
+ EFI_NOT_READY - Device is not ready
+--*/
+{
+ USB_KEY UsbKey;
+
+ *KeyChar = 0;
+
+ while (!IsUSBKeyboardBufferEmpty (&UsbKeyboardDevice->KeyboardBuffer)) {
+ //
+ // pops one raw data off.
+ //
+ RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey);
+
+ if (!UsbKey.Down) {
+ switch (UsbKey.KeyCode) {
+
+ case 0xe0:
+ case 0xe4:
+ UsbKeyboardDevice->CtrlOn = 0;
+ break;
+
+ case 0xe1:
+ case 0xe5:
+ UsbKeyboardDevice->ShiftOn = 0;
+ break;
+
+ case 0xe2:
+ case 0xe6:
+ UsbKeyboardDevice->AltOn = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ continue;
+ }
+
+ //
+ // Analyzes key pressing situation
+ //
+ switch (UsbKey.KeyCode) {
+
+ case 0xe0:
+ case 0xe4:
+ UsbKeyboardDevice->CtrlOn = 1;
+ continue;
+ break;
+
+ case 0xe1:
+ case 0xe5:
+ UsbKeyboardDevice->ShiftOn = 1;
+ continue;
+ break;
+
+ case 0xe2:
+ case 0xe6:
+ UsbKeyboardDevice->AltOn = 1;
+ continue;
+ break;
+
+ case 0xe3:
+ case 0xe7:
+ continue;
+ break;
+
+ case 0x53:
+ UsbKeyboardDevice->NumLockOn ^= 1;
+ SetKeyLED (UsbKeyboardDevice);
+ continue;
+ break;
+
+ case 0x39:
+ UsbKeyboardDevice->CapsOn ^= 1;
+ SetKeyLED (UsbKeyboardDevice);
+ continue;
+ break;
+
+ //
+ // F11,F12,PrintScreen,ScrollLock,Pause,Application,Power
+ // keys are not valid EFI key
+ //
+ case 0x44:
+ //
+ // fall through
+ //
+ case 0x45:
+ //
+ // fall through
+ //
+ case 0x46:
+ //
+ // fall through
+ //
+ case 0x47:
+ //
+ // fall through
+ //
+ case 0x48:
+ //
+ // fall through
+ //
+ case 0x65:
+ case 0x66:
+ continue;
+ break;
+
+ default:
+ break;
+ }
+
+ //
+ // When encountered Del Key...
+ //
+ if (UsbKey.KeyCode == 0x4c || UsbKey.KeyCode == 0x63) {
+ if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) {
+ gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+ }
+ }
+
+ *KeyChar = UsbKey.KeyCode;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_READY;
+
+}
+
+
+EFI_STATUS
+USBKeyCodeToEFIScanCode (
+ IN USB_KB_DEV *UsbKeyboardDevice,
+ IN UINT8 KeyChar,
+ OUT EFI_INPUT_KEY *Key
+ )
+/*++
+
+ Routine Description:
+ Converts USB Keyboard code to EFI Scan Code.
+
+ Arguments:
+ UsbKeyboardDevice The USB_KB_DEV instance.
+ KeyChar Indicates the key code that will be interpreted.
+ Key A pointer to a buffer that is filled in with
+ the keystroke information for the key that
+ was pressed.
+ Returns:
+ EFI_NOT_READY - Device is not ready
+ EFI_SUCCESS - Success
+--*/
+{
+ UINT8 Index;
+
+ if (!USBKBD_VALID_KEYCODE (KeyChar)) {
+ return EFI_NOT_READY;
+ }
+
+ //
+ // valid USB Key Code starts from 4
+ //
+ Index = (UINT8) (KeyChar - 4);
+
+ if (Index >= USB_KEYCODE_MAX_MAKE) {
+ return EFI_NOT_READY;
+ }
+
+ Key->ScanCode = KeyConvertionTable[Index][0];
+
+ if (UsbKeyboardDevice->ShiftOn) {
+
+ Key->UnicodeChar = KeyConvertionTable[Index][2];
+
+ } else {
+
+ Key->UnicodeChar = KeyConvertionTable[Index][1];
+ }
+
+ if (UsbKeyboardDevice->CapsOn) {
+
+ if (Key->UnicodeChar >= 'a' && Key->UnicodeChar <= 'z') {
+
+ Key->UnicodeChar = KeyConvertionTable[Index][2];
+
+ } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') {
+
+ Key->UnicodeChar = KeyConvertionTable[Index][1];
+
+ }
+ }
+
+ if (KeyChar >= 0x59 && KeyChar <= 0x63) {
+
+ if (UsbKeyboardDevice->NumLockOn && !UsbKeyboardDevice->ShiftOn) {
+
+ Key->ScanCode = SCAN_NULL;
+
+ } else {
+
+ Key->UnicodeChar = 0x00;
+ }
+ }
+
+ if (Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) {
+ return EFI_NOT_READY;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+
+EFI_STATUS
+InitUSBKeyBuffer (
+ IN OUT USB_KB_BUFFER *KeyboardBuffer
+ )
+/*++
+
+ Routine Description:
+ Resets USB Keyboard Buffer.
+
+ Arguments:
+ KeyboardBuffer - Points to the USB Keyboard Buffer.
+
+ Returns:
+ EFI_SUCCESS - Success
+--*/
+{
+ ZeroMem (KeyboardBuffer, sizeof (USB_KB_BUFFER));
+
+ KeyboardBuffer->bHead = KeyboardBuffer->bTail;
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsUSBKeyboardBufferEmpty (
+ IN USB_KB_BUFFER *KeyboardBuffer
+ )
+/*++
+
+ Routine Description:
+ Check whether USB Keyboard buffer is empty.
+
+ Arguments:
+ KeyboardBuffer - USB Keyboard Buffer.
+
+ Returns:
+
+--*/
+{
+ //
+ // meet FIFO empty condition
+ //
+ return (BOOLEAN) (KeyboardBuffer->bHead == KeyboardBuffer->bTail);
+}
+
+
+BOOLEAN
+IsUSBKeyboardBufferFull (
+ IN USB_KB_BUFFER *KeyboardBuffer
+ )
+/*++
+
+ Routine Description:
+ Check whether USB Keyboard buffer is full.
+
+ Arguments:
+ KeyboardBuffer - USB Keyboard Buffer.
+
+ Returns:
+
+--*/
+{
+ return (BOOLEAN)(((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1)) ==
+ KeyboardBuffer->bHead);
+}
+
+
+EFI_STATUS
+InsertKeyCode (
+ IN OUT USB_KB_BUFFER *KeyboardBuffer,
+ IN UINT8 Key,
+ IN UINT8 Down
+ )
+/*++
+
+ Routine Description:
+ Inserts a key code into keyboard buffer.
+
+ Arguments:
+ KeyboardBuffer - Points to the USB Keyboard Buffer.
+ Key - Key code
+ Down - Special key
+ Returns:
+ EFI_SUCCESS - Success
+--*/
+{
+ USB_KEY UsbKey;
+
+ //
+ // if keyboard buffer is full, throw the
+ // first key out of the keyboard buffer.
+ //
+ if (IsUSBKeyboardBufferFull (KeyboardBuffer)) {
+ RemoveKeyCode (KeyboardBuffer, &UsbKey);
+ }
+
+ KeyboardBuffer->buffer[KeyboardBuffer->bTail].KeyCode = Key;
+ KeyboardBuffer->buffer[KeyboardBuffer->bTail].Down = Down;
+
+ //
+ // adjust the tail pointer of the FIFO keyboard buffer.
+ //
+ KeyboardBuffer->bTail = (UINT8) ((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RemoveKeyCode (
+ IN OUT USB_KB_BUFFER *KeyboardBuffer,
+ OUT USB_KEY *UsbKey
+ )
+/*++
+
+ Routine Description:
+ Pops a key code off from keyboard buffer.
+
+ Arguments:
+ KeyboardBuffer - Points to the USB Keyboard Buffer.
+ UsbKey - Points to the buffer that contains a usb key code.
+
+ Returns:
+ EFI_SUCCESS - Success
+ EFI_DEVICE_ERROR - Hardware Error
+--*/
+{
+ if (IsUSBKeyboardBufferEmpty (KeyboardBuffer)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbKey->KeyCode = KeyboardBuffer->buffer[KeyboardBuffer->bHead].KeyCode;
+ UsbKey->Down = KeyboardBuffer->buffer[KeyboardBuffer->bHead].Down;
+
+ //
+ // adjust the head pointer of the FIFO keyboard buffer.
+ //
+ KeyboardBuffer->bHead = (UINT8) ((KeyboardBuffer->bHead + 1) % (MAX_KEY_ALLOWED + 1));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SetKeyLED (
+ IN USB_KB_DEV *UsbKeyboardDevice
+ )
+/*++
+
+ Routine Description:
+ Sets USB Keyboard LED state.
+
+ Arguments:
+ UsbKeyboardDevice - The USB_KB_DEV instance.
+
+ Returns:
+ EFI_SUCCESS - Success
+--*/
+{
+ LED_MAP Led;
+ UINT8 ReportId;
+
+ //
+ // Set each field in Led map.
+ //
+ Led.NumLock = (UINT8) UsbKeyboardDevice->NumLockOn;
+ Led.CapsLock = (UINT8) UsbKeyboardDevice->CapsOn;
+ Led.Resrvd = 0;
+
+ ReportId = 0;
+ //
+ // call Set Report Request to lighten the LED.
+ //
+ UsbSetReportRequest (
+ UsbKeyboardDevice->UsbIo,
+ UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber,
+ ReportId,
+ HID_OUTPUT_REPORT,
+ 1,
+ (UINT8 *) &Led
+ );
+
+ return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+USBKeyboardRepeatHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+ Routine Description:
+ Timer handler for Repeat Key timer.
+
+ Arguments:
+ Event - The Repeat Key event.
+ Context - Points to the USB_KB_DEV instance.
+
+ Returns:
+
+--*/
+{
+ USB_KB_DEV *UsbKeyboardDevice;
+
+ UsbKeyboardDevice = (USB_KB_DEV *) Context;
+
+ //
+ // Do nothing when there is no repeat key.
+ //
+ if (UsbKeyboardDevice->RepeatKey != 0) {
+ //
+ // Inserts one Repeat key into keyboard buffer,
+ //
+ InsertKeyCode (
+ &(UsbKeyboardDevice->KeyboardBuffer),
+ UsbKeyboardDevice->RepeatKey,
+ 1
+ );
+
+ //
+ // set repeate rate for repeat key generation.
+ //
+ gBS->SetTimer (
+ UsbKeyboardDevice->RepeatTimer,
+ TimerRelative,
+ USBKBD_REPEAT_RATE
+ );
+
+ }
+}
+
+VOID
+EFIAPI
+USBKeyboardRecoveryHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+ Routine Description:
+ Timer handler for Delayed Recovery timer.
+
+ Arguments:
+ Event - The Delayed Recovery event.
+ Context - Points to the USB_KB_DEV instance.
+
+ Returns:
+
+--*/
+{
+
+ USB_KB_DEV *UsbKeyboardDevice;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 PacketSize;
+
+ UsbKeyboardDevice = (USB_KB_DEV *) Context;
+
+ UsbIo = UsbKeyboardDevice->UsbIo;
+
+ PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize);
+
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress,
+ TRUE,
+ UsbKeyboardDevice->IntEndpointDescriptor.Interval,
+ PacketSize,
+ KeyboardHandler,
+ UsbKeyboardDevice
+ );
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.h b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.h
new file mode 100644
index 0000000000..a01fda3ca4
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.h
@@ -0,0 +1,106 @@
+/*++
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Keyboard.h
+
+Abstract:
+
+ Function prototype for USB Keyboard Driver
+
+Revision History
+--*/
+
+#ifndef _KEYBOARD_H
+#define _KEYBOARD_H
+
+#include "efikey.h"
+
+BOOLEAN
+IsUSBKeyboard (
+ IN EFI_USB_IO_PROTOCOL *UsbIo
+ );
+
+EFI_STATUS
+InitUSBKeyboard (
+ IN USB_KB_DEV *UsbKeyboardDevice
+ );
+
+EFI_STATUS
+EFIAPI
+KeyboardHandler (
+ IN VOID *Data,
+ IN UINTN DataLength,
+ IN VOID *Context,
+ IN UINT32 Result
+ );
+
+VOID
+EFIAPI
+USBKeyboardRecoveryHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+USBParseKey (
+ IN OUT USB_KB_DEV *UsbKeyboardDevice,
+ OUT UINT8 *KeyChar
+ );
+
+EFI_STATUS
+USBKeyCodeToEFIScanCode (
+ IN USB_KB_DEV *UsbKeyboardDevice,
+ IN UINT8 KeyChar,
+ OUT EFI_INPUT_KEY *Key
+ );
+
+EFI_STATUS
+InitUSBKeyBuffer (
+ IN OUT USB_KB_BUFFER *KeyboardBuffer
+ );
+
+BOOLEAN
+IsUSBKeyboardBufferEmpty (
+ IN USB_KB_BUFFER *KeyboardBuffer
+ );
+
+BOOLEAN
+IsUSBKeyboardBufferFull (
+ IN USB_KB_BUFFER *KeyboardBuffer
+ );
+
+EFI_STATUS
+InsertKeyCode (
+ IN OUT USB_KB_BUFFER *KeyboardBuffer,
+ IN UINT8 Key,
+ IN UINT8 Down
+ );
+
+EFI_STATUS
+RemoveKeyCode (
+ IN OUT USB_KB_BUFFER *KeyboardBuffer,
+ OUT USB_KEY *UsbKey
+ );
+
+VOID
+EFIAPI
+USBKeyboardRepeatHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+SetKeyLED (
+ IN USB_KB_DEV *UsbKeyboardDevice
+ );
+
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/ComponentName.c
new file mode 100644
index 0000000000..a021d95389
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/ComponentName.c
@@ -0,0 +1,154 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "UsbMassStorage.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+UsbMassStorageComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+UsbMassStorageComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gUsbMassStorageComponentName = {
+ UsbMassStorageComponentNameGetDriverName,
+ UsbMassStorageComponentNameGetControllerName,
+ "eng"
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mUsbMassStorageDriverNameTable[] = {
+ { "eng", (CHAR16 *) L"Generic USB Mass Storage Driver" },
+ { NULL , NULL }
+};
+
+EFI_STATUS
+EFIAPI
+UsbMassStorageComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ Language - A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ DriverName - A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - DriverName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return LookupUnicodeString (
+ Language,
+ gUsbMassStorageComponentName.SupportedLanguages,
+ mUsbMassStorageDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UsbMassStorageComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ ControllerHandle - The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ ChildHandle - The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ ControllerName - A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language from the point of view of the driver specified
+ by This.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - ControllerName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.c b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.c
new file mode 100644
index 0000000000..932b8c5ed9
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.c
@@ -0,0 +1,727 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ UsbMassStorage.c
+
+Abstract:
+
+ USB Mass Storage Driver
+
+Revision History
+
+--*/
+
+#include "UsbMassStorage.h"
+#include "UsbMassStorageHelper.h"
+
+extern EFI_COMPONENT_NAME_PROTOCOL gUsbMassStorageComponentName;
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+EFI_STATUS
+EFIAPI
+USBMassStorageDriverBindingEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+EFI_STATUS
+EFIAPI
+USBFloppyDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+USBFloppyDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+USBFloppyDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// Block I/O Protocol Interface
+//
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ );
+
+//
+// USB Floppy Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL gUSBFloppyDriverBinding = {
+ USBFloppyDriverBindingSupported,
+ USBFloppyDriverBindingStart,
+ USBFloppyDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+EFI_STATUS
+EFIAPI
+USBFloppyDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ that has UsbHcProtocol installed will be supported.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver supports this device.
+ EFI_UNSUPPORTED - This driver does not support this device.
+
+--*/
+{
+ EFI_STATUS OpenStatus;
+ EFI_USB_ATAPI_PROTOCOL *AtapiProtocol;
+
+ //
+ // check whether EFI_USB_ATAPI_PROTOCOL exists, if it does,
+ // then the controller must be a USB Mass Storage Controller
+ //
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ (VOID **) &AtapiProtocol,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (OpenStatus)) {
+ return OpenStatus;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+USBFloppyDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Starting the Usb Bus Driver
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver supports this device.
+ EFI_UNSUPPORTED - This driver does not support this device.
+ EFI_DEVICE_ERROR - This driver cannot be started due to device
+ Error
+ EFI_OUT_OF_RESOURCES- Can't allocate memory resources
+ EFI_ALREADY_STARTED - Thios driver has been started
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_ATAPI_PROTOCOL *AtapiProtocol;
+ USB_FLOPPY_DEV *UsbFloppyDevice;
+
+ UsbFloppyDevice = NULL;
+ //
+ // Check whether Usb Atapi Protocol attached on the controller handle.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ (VOID **) &AtapiProtocol,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (USB_FLOPPY_DEV),
+ (VOID **) &UsbFloppyDevice
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+
+ ZeroMem (UsbFloppyDevice, sizeof (USB_FLOPPY_DEV));
+
+ UsbFloppyDevice->Handle = Controller;
+ UsbFloppyDevice->BlkIo.Media = &UsbFloppyDevice->BlkMedia;
+ UsbFloppyDevice->Signature = USB_FLOPPY_DEV_SIGNATURE;
+ UsbFloppyDevice->BlkIo.Reset = USBFloppyReset;
+ UsbFloppyDevice->BlkIo.ReadBlocks = USBFloppyReadBlocks;
+ UsbFloppyDevice->BlkIo.WriteBlocks = USBFloppyWriteBlocks;
+ UsbFloppyDevice->BlkIo.FlushBlocks = USBFloppyFlushBlocks;
+ UsbFloppyDevice->AtapiProtocol = AtapiProtocol;
+
+ //
+ // Identify drive type and retrieve media information.
+ //
+ Status = USBFloppyIdentify (UsbFloppyDevice);
+ if (EFI_ERROR (Status)) {
+ if (UsbFloppyDevice->SenseData != NULL) {
+ gBS->FreePool (UsbFloppyDevice->SenseData);
+ }
+
+ gBS->FreePool (UsbFloppyDevice);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+ //
+ // Install Block I/O protocol for the usb floppy device.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiBlockIoProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &UsbFloppyDevice->BlkIo
+ );
+ if (EFI_ERROR (Status)) {
+ if (UsbFloppyDevice->SenseData != NULL) {
+ gBS->FreePool (UsbFloppyDevice->SenseData);
+ }
+
+ gBS->FreePool (UsbFloppyDevice);
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+
+EFI_STATUS
+EFIAPI
+USBFloppyDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to stop driver on
+ NumberOfChildren - Number of Children in the ChildHandleBuffer
+ ChildHandleBuffer - List of handles for the children we need to stop.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+ others
+
+--*/
+{
+ EFI_STATUS Status;
+ USB_FLOPPY_DEV *UsbFloppyDevice;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+
+ //
+ // First find USB_FLOPPY_DEV
+ //
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (BlkIo);
+
+ //
+ // Uninstall Block I/O protocol from the device handle
+ //
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ &UsbFloppyDevice->BlkIo
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Stop using EFI_USB_ATAPI_PROTOCOL
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbAtapiProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ if (UsbFloppyDevice->SenseData != NULL) {
+ gBS->FreePool (UsbFloppyDevice->SenseData);
+ }
+
+ gBS->FreePool (UsbFloppyDevice);
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+ Routine Description:
+ Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.
+
+ Arguments:
+ This The EFI_BLOCK_IO_PROTOCOL instance.
+ ExtendedVerification
+ Indicates that the driver may perform a more exhaustive
+ verification operation of the device during reset.
+ (This parameter is ingored in this driver.)
+
+ Returns:
+ EFI_SUCCESS - Success
+--*/
+{
+ USB_FLOPPY_DEV *UsbFloppyDevice;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ EFI_STATUS Status;
+
+ UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ //
+ // directly calling EFI_USB_ATAPI_PROTOCOL.Reset() to implement reset.
+ //
+ Status = UsbAtapiInterface->UsbAtapiReset (UsbAtapiInterface, TRUE);
+
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+ Routine Description:
+ Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.
+
+ Arguments:
+ This The EFI_BLOCK_IO_PROTOCOL instance.
+ MediaId The media id that the read request is for.
+ LBA The starting logical block address to read from on the device.
+ BufferSize
+ The size of the Buffer in bytes. This must be a multiple of
+ the intrinsic block size of the device.
+ Buffer A pointer to the destination buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ Returns:
+ EFI_INVALID_PARAMETER - Parameter is error
+ EFI_SUCCESS - Success
+ EFI_DEVICE_ERROR - Hardware Error
+ EFI_NO_MEDIA - No media
+ EFI_MEDIA_CHANGED - Media Change
+ EFI_BAD_BUFFER_SIZE - Buffer size is bad
+ --*/
+{
+ USB_FLOPPY_DEV *UsbFloppyDevice;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ BOOLEAN MediaChange;
+ EFI_TPL OldTpl;
+ UINT32 Retry;
+
+ OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
+ Status = EFI_SUCCESS;
+ MediaChange = FALSE;
+ Retry = 0;
+
+ UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);
+
+ //
+ // Check parameters
+ //
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ UsbFloppyTestUnitReady (UsbFloppyDevice);
+
+ Status = UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);
+ if (EFI_ERROR (Status)) {
+
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ if (MediaChange) {
+ gBS->RestoreTPL (OldTpl);
+ gBS->ReinstallProtocolInterface (
+ UsbFloppyDevice->Handle,
+ &gEfiBlockIoProtocolGuid,
+ &UsbFloppyDevice->BlkIo,
+ &UsbFloppyDevice->BlkIo
+ );
+ gBS->RaiseTPL (EFI_TPL_NOTIFY);
+ }
+
+ Media = UsbFloppyDevice->BlkIo.Media;
+ BlockSize = Media->BlockSize;
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ if (!(Media->MediaPresent)) {
+ Status = EFI_NO_MEDIA;
+ goto Done;
+ }
+
+ if (MediaId != Media->MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ goto Done;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto Done;
+ }
+
+ if (LBA > Media->LastBlock) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (!EFI_ERROR (Status)) {
+
+ Status = USBFloppyRead10 (UsbFloppyDevice, Buffer, LBA, 1);
+ if (EFI_ERROR (Status)) {
+ This->Reset (This, TRUE);
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ LBA += 1;
+ NumberOfBlocks -= 1;
+ Buffer = (UINT8 *) Buffer + This->Media->BlockSize;
+
+ if (NumberOfBlocks == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ Status = USBFloppyRead10 (UsbFloppyDevice, Buffer, LBA, NumberOfBlocks);
+ if (EFI_ERROR (Status)) {
+ This->Reset (This, TRUE);
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+Done:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+/*++
+
+ Routine Description:
+ Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.
+
+ Arguments:
+ This The EFI_BLOCK_IO_PROTOCOL instance.
+ MediaId The media id that the write request is for.
+ LBA The starting logical block address to be written.
+ The caller is responsible for writing to only
+ legitimate locations.
+ BufferSize
+ The size of the Buffer in bytes. This must be a multiple of
+ the intrinsic block size of the device.
+ Buffer A pointer to the source buffer for the data. The caller
+ is responsible for either having implicit or explicit ownership
+ of the buffer.
+
+ Returns:
+ EFI_INVALID_PARAMETER - Parameter is error
+ EFI_SUCCESS - Success
+ EFI_DEVICE_ERROR - Hardware Error
+ EFI_NO_MEDIA - No media
+ EFI_MEDIA_CHANGED - Media Change
+ EFI_BAD_BUFFER_SIZE - Buffer size is bad
+
+--*/
+{
+ USB_FLOPPY_DEV *UsbFloppyDevice;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ BOOLEAN MediaChange;
+ EFI_TPL OldTpl;
+ UINT32 Retry;
+
+ OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
+ Status = EFI_SUCCESS;
+ MediaChange = FALSE;
+ Retry = 0;
+
+ UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This);
+
+ //
+ // Check parameters
+ //
+ if (!Buffer) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (BufferSize == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ UsbFloppyTestUnitReady (UsbFloppyDevice);
+
+ Status = UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);
+ if (EFI_ERROR (Status)) {
+
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ if (MediaChange) {
+ gBS->RestoreTPL (OldTpl);
+ gBS->ReinstallProtocolInterface (
+ UsbFloppyDevice->Handle,
+ &gEfiBlockIoProtocolGuid,
+ &UsbFloppyDevice->BlkIo,
+ &UsbFloppyDevice->BlkIo
+ );
+ gBS->RaiseTPL (EFI_TPL_NOTIFY);
+ }
+
+ Media = UsbFloppyDevice->BlkIo.Media;
+ BlockSize = Media->BlockSize;
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ if (!(Media->MediaPresent)) {
+ Status = EFI_NO_MEDIA;
+ goto Done;
+ }
+
+ if (MediaId != Media->MediaId) {
+ Status = EFI_MEDIA_CHANGED;
+ goto Done;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto Done;
+ }
+
+ if (LBA > Media->LastBlock) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (UsbFloppyDevice->BlkMedia.ReadOnly) {
+ Status = EFI_WRITE_PROTECTED;
+ goto Done;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Status = USBFloppyWrite10 (UsbFloppyDevice, Buffer, LBA, 1);
+ if (EFI_ERROR (Status)) {
+ This->Reset (This, TRUE);
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ LBA += 1;
+ NumberOfBlocks -= 1;
+ Buffer = (UINT8 *) Buffer + This->Media->BlockSize;
+
+ if (NumberOfBlocks == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ Status = USBFloppyWrite10 (UsbFloppyDevice, Buffer, LBA, NumberOfBlocks);
+ if (EFI_ERROR (Status)) {
+ This->Reset (This, TRUE);
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+
+Done:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+USBFloppyFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+/*++
+
+ Routine Description:
+ Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.
+ (In this driver, this function just returns EFI_SUCCESS.)
+
+ Arguments:
+ This The EFI_BLOCK_IO_PROTOCOL instance.
+
+ Returns:
+ EFI_SUCCESS - Success
+--*/
+{
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.h b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.h
new file mode 100644
index 0000000000..4874bb08cc
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.h
@@ -0,0 +1,59 @@
+/*++
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ UsbMassStorage.h
+
+Abstract:
+
+ Header file for USB Mass Storage Driver's Data Structures
+
+Revision History
+--*/
+
+#ifndef _USB_FLP_H
+#define _USB_FLP_H
+
+
+#include <IndustryStandard/usb.h>
+#include "UsbMassStorageData.h"
+
+#define CLASS_MASSTORAGE 8
+#define SUBCLASS_UFI 4
+#define SUBCLASS_8070 5
+#define PROTOCOL_BOT 0x50
+#define PROTOCOL_CBI0 0
+#define PROTOCOL_CBI1 1
+
+#define USBFLOPPY 1
+#define USBFLOPPY2 2 // for those that use ReadCapacity(0x25) command to retrieve media capacity
+#define USBCDROM 3
+
+#define USB_FLOPPY_DEV_SIGNATURE EFI_SIGNATURE_32 ('u', 'f', 'l', 'p')
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE Handle;
+ EFI_BLOCK_IO_PROTOCOL BlkIo;
+ EFI_BLOCK_IO_MEDIA BlkMedia;
+ EFI_USB_ATAPI_PROTOCOL *AtapiProtocol;
+
+ REQUEST_SENSE_DATA *SenseData;
+ UINT8 SenseDataNumber;
+ UINT8 DeviceType;
+
+} USB_FLOPPY_DEV;
+
+#define USB_FLOPPY_DEV_FROM_THIS(a) \
+ CR(a, USB_FLOPPY_DEV, BlkIo, USB_FLOPPY_DEV_SIGNATURE)
+
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.mbd b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.mbd
new file mode 100644
index 0000000000..c9c9b5c73b
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.mbd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>UsbMassStorage</BaseName>
+ <Guid>A5C6D68B-E78A-4426-9278-A8F0D9EB4D8F</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>EdkUsbLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.msa b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.msa
new file mode 100644
index 0000000000..d071c9f656
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.msa
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>UsbMassStorage</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>A5C6D68B-E78A-4426-9278-A8F0D9EB4D8F</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for UsbMassStorage module</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">EdkUsbLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>UsbMassStorage.h</Filename>
+ <Filename>UsbMassStorageData.h</Filename>
+ <Filename>UsbMassStorageHelper.h</Filename>
+ <Filename>UsbMassStorage.c</Filename>
+ <Filename>UsbMassStorageHelper.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">UsbAtapi</Protocol>
+ <Protocol Usage="BY_START">BlockIo</Protocol>
+ </Protocols>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gUSBFloppyDriverBinding</DriverBinding>
+ <ComponentName>gUsbMassStorageComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageData.h b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageData.h
new file mode 100644
index 0000000000..598c82e220
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageData.h
@@ -0,0 +1,394 @@
+/*++
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ UsbMassStorageData.h
+
+Abstract:
+
+ Header file for USB Mass Storage Device related Data Structures
+
+Revision History
+--*/
+
+#ifndef _USB_FLP_DATA_H
+#define _USB_FLP_DATA_H
+
+//
+// bit definition
+//
+#define bit(a) 1 << (a)
+
+//
+// timeout unit is in millisecond.
+//
+#define USBFLPTIMEOUT 2000
+#define STALL_1_MILLI_SECOND 1000
+
+//
+// ATAPI Packet Command
+//
+#pragma pack(1)
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} TEST_UNIT_READY_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 page_code;
+ UINT8 reserved_3;
+ UINT8 allocation_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} INQUIRY_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 allocation_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} REQUEST_SENSE_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 page_code : 6;
+ UINT8 page_control : 2;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 parameter_list_length_hi;
+ UINT8 parameter_list_length_lo;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} MODE_SENSE_CMD_UFI;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 3;
+ UINT8 dbd : 1;
+ UINT8 reserved_2 : 1;
+ UINT8 lun : 3;
+ UINT8 page_code : 6;
+ UINT8 page_control : 2;
+ UINT8 reserved_3;
+ UINT8 allocation_length;
+ UINT8 control;
+} MODE_SENSE_CMD_SCSI;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 5;
+ UINT8 lun : 3;
+ UINT8 Lba0;
+ UINT8 Lba1;
+ UINT8 Lba2;
+ UINT8 Lba3;
+ UINT8 reserved_6;
+ UINT8 TranLen0;
+ UINT8 TranLen1;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} READ10_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 allocation_length_hi;
+ UINT8 allocation_length_lo;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} READ_FORMAT_CAP_CMD;
+
+typedef union {
+ UINT16 Data16[6];
+ TEST_UNIT_READY_CMD TestUnitReady;
+ READ10_CMD Read10;
+ REQUEST_SENSE_CMD RequestSense;
+ INQUIRY_CMD Inquiry;
+ MODE_SENSE_CMD_UFI ModeSenseUFI;
+ READ_FORMAT_CAP_CMD ReadFormatCapacity;
+ MODE_SENSE_CMD_SCSI ModeSenseSCSI;
+} ATAPI_PACKET_COMMAND;
+
+#pragma pack()
+//
+// Packet Command Code
+//
+#define TEST_UNIT_READY 0x00
+#define REZERO 0x01
+#define REQUEST_SENSE 0x03
+#define FORMAT_UNIT 0x04
+#define REASSIGN_BLOCKS 0x07
+#define INQUIRY 0x12
+#define START_STOP_UNIT 0x1B
+#define PREVENT_ALLOW_MEDIA_REMOVAL 0x1E
+#define READ_FORMAT_CAPACITY 0x23
+#define OLD_FORMAT_UNIT 0x24
+#define READ_CAPACITY 0x25
+#define READ_10 0x28
+#define WRITE_10 0x2A
+#define SEEK 0x2B
+#define SEND_DIAGNOSTICS 0x3D
+#define WRITE_VERIFY 0x2E
+#define VERIFY 0x2F
+#define READ_DEFECT_DATA 0x37
+#define WRITE_BUFFER 0x38
+#define READ_BUFFER 0x3C
+#define READ_LONG 0x3E
+#define WRITE_LONG 0x3F
+#define MODE_SELECT 0x55
+#define UFI_MODE_SENSE5A 0x5A
+#define SCSI_MODE_SENSE1A 0x1A
+#define READ_12 0xA8
+#define WRITE_12 0xAA
+#define MAX_ATAPI_BYTE_COUNT (0xfffe)
+
+//
+// Sense Key
+//
+#define REQUEST_SENSE_ERROR (0x70)
+#define SK_NO_SENSE (0x0)
+#define SK_RECOVERY_ERROR (0x1)
+#define SK_NOT_READY (0x2)
+#define SK_MEDIUM_ERROR (0x3)
+#define SK_HARDWARE_ERROR (0x4)
+#define SK_ILLEGAL_REQUEST (0x5)
+#define SK_UNIT_ATTENTION (0x6)
+#define SK_DATA_PROTECT (0x7)
+#define SK_BLANK_CHECK (0x8)
+#define SK_VENDOR_SPECIFIC (0x9)
+#define SK_RESERVED_A (0xA)
+#define SK_ABORT (0xB)
+#define SK_RESERVED_C (0xC)
+#define SK_OVERFLOW (0xD)
+#define SK_MISCOMPARE (0xE)
+#define SK_RESERVED_F (0xF)
+
+//
+// Additional Sense Codes
+//
+#define ASC_NOT_READY (0x04)
+#define ASC_MEDIA_ERR1 (0x10)
+#define ASC_MEDIA_ERR2 (0x11)
+#define ASC_MEDIA_ERR3 (0x14)
+#define ASC_MEDIA_ERR4 (0x30)
+#define ASC_MEDIA_UPSIDE_DOWN (0x06)
+#define ASC_INVALID_CMD (0x20)
+#define ASC_LBA_OUT_OF_RANGE (0x21)
+#define ASC_INVALID_FIELD (0x24)
+#define ASC_WRITE_PROTECTED (0x27)
+#define ASC_MEDIA_CHANGE (0x28)
+#define ASC_RESET (0x29) /* Power On Reset or Bus Reset occurred */
+#define ASC_ILLEGAL_FIELD (0x26)
+#define ASC_NO_MEDIA (0x3A)
+#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK (0x64)
+#define ASC_LOGICAL_UNIT_STATUS (0x08)
+
+//
+// Additional Sense Code Qualifier
+//
+#define ASCQ_IN_PROGRESS (0x01)
+#define ASCQ_DEVICE_BUSY (0xff)
+#define ASCQ_LOGICAL_UNIT_FAILURE (0x00)
+#define ASCQ_LOGICAL_UNIT_TIMEOUT (0x01)
+#define ASCQ_LOGICAL_UNIT_OVERRUN (0x80)
+
+#define SETFEATURE TRUE
+#define CLEARFEATURE FALSE
+
+//
+// ATAPI Data structure
+//
+#pragma pack(1)
+
+typedef struct {
+ UINT8 peripheral_type;
+ UINT8 RMB;
+ UINT8 version;
+ UINT8 response_data_format;
+ UINT8 addnl_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 vendor_info[8];
+ UINT8 product_id[12];
+ UINT8 eeprom_product_code[4];
+ UINT8 firmware_rev_level[4];
+} USB_INQUIRY_DATA;
+
+typedef struct {
+ UINT8 error_code : 7;
+ UINT8 valid : 1;
+ UINT8 reserved_1;
+ UINT8 sense_key : 4;
+ UINT8 reserved_21 : 1;
+ UINT8 ILI : 1;
+ UINT8 reserved_22 : 2;
+ UINT8 vendor_specific_3;
+ UINT8 vendor_specific_4;
+ UINT8 vendor_specific_5;
+ UINT8 vendor_specific_6;
+ UINT8 addnl_sense_length; // n - 7
+ UINT8 vendor_specific_8;
+ UINT8 vendor_specific_9;
+ UINT8 vendor_specific_10;
+ UINT8 vendor_specific_11;
+ UINT8 addnl_sense_code; // mandatory
+ UINT8 addnl_sense_code_qualifier; // mandatory
+ UINT8 field_replaceable_unit_code; // optional
+ UINT8 reserved_15;
+ UINT8 reserved_16;
+ UINT8 reserved_17;
+ //
+ // Followed by additional sense bytes : FIXME
+ //
+} REQUEST_SENSE_DATA;
+
+typedef struct {
+ UINT8 LastLba3;
+ UINT8 LastLba2;
+ UINT8 LastLba1;
+ UINT8 LastLba0;
+ UINT8 BlockSize3;
+ UINT8 BlockSize2;
+ UINT8 BlockSize1;
+ UINT8 BlockSize0;
+} READ_CAPACITY_DATA;
+
+typedef struct {
+ UINT8 reserved_0;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 Capacity_Length;
+ UINT8 LastLba3;
+ UINT8 LastLba2;
+ UINT8 LastLba1;
+ UINT8 LastLba0;
+ UINT8 DesCode : 2;
+ UINT8 reserved_9 : 6;
+ UINT8 BlockSize2;
+ UINT8 BlockSize1;
+ UINT8 BlockSize0;
+} READ_FORMAT_CAPACITY_DATA;
+
+typedef struct {
+ UINT8 mode_data_len_hi;
+ UINT8 mode_data_len_lo;
+ UINT8 media_type_code;
+ UINT8 reserved_3_0 : 4;
+ UINT8 dpofua : 1;
+ UINT8 reserved_3_1 : 2;
+ UINT8 write_protected : 1;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+} UFI_MODE_PARAMETER_HEADER;
+
+typedef struct {
+ UINT8 mode_data_len;
+ UINT8 media_type_code;
+ UINT8 speed : 4;
+ UINT8 buffered_mode : 3;
+ UINT8 write_protected : 1;
+ UINT8 block_descritptor_length;
+} SCSI_MODE_PARAMETER_HEADER6;
+
+typedef struct {
+ UINT8 page_code : 6;
+ UINT8 reserved_0 : 1;
+ UINT8 parameter_savable : 1;
+ UINT8 page_length;
+ UINT8 transfer_rate_msb;
+ UINT8 transfer_rate_lsb;
+ UINT8 number_of_heads;
+ UINT8 sectors_per_track;
+ UINT8 databytes_per_sector_msb;
+ UINT8 databytes_per_sector_lsb;
+ UINT8 number_of_cylinders_msb;
+ UINT8 number_of_cylinders_lsb;
+ UINT8 reserved_10_18[9];
+ UINT8 motor_on_delay;
+ UINT8 motor_off_delay;
+ UINT8 reserved_21_27[7];
+ UINT8 medium_rotation_rate_msb;
+ UINT8 medium_rotation_rate_lsb;
+ UINT8 reserved_30_31[2];
+} FLEXIBLE_DISK_PAGE;
+
+typedef struct {
+ UFI_MODE_PARAMETER_HEADER mode_param_header;
+ FLEXIBLE_DISK_PAGE flex_disk_page;
+} UFI_MODE_PARAMETER_PAGE_5;
+
+typedef struct {
+ UINT8 page_code : 6;
+ UINT8 reserved_0 : 1;
+ UINT8 parameter_savable : 1;
+ UINT8 page_length;
+ UINT8 reserved_2;
+ UINT8 inactive_time_multplier : 4;
+ UINT8 reserved_3 : 4;
+ UINT8 software_write_protect : 1;
+ UINT8 disable_media_access : 1;
+ UINT8 reserved_4 : 6;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+} TIMER_AND_PROTECT_PAGE;
+
+typedef struct {
+ UFI_MODE_PARAMETER_HEADER mode_param_header;
+ TIMER_AND_PROTECT_PAGE time_and_protect_page;
+} UFI_MODE_PARAMETER_PAGE_1C;
+
+#pragma pack()
+
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c
new file mode 100644
index 0000000000..b8ed813ea2
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c
@@ -0,0 +1,1653 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ UsbMassStorageHelper.c
+
+Abstract:
+
+ Helper functions for USB Mass Storage Driver
+
+Revision History
+
+--*/
+
+#include "UsbMassStorageHelper.h"
+
+STATIC
+BOOLEAN
+IsNoMedia (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ );
+
+STATIC
+BOOLEAN
+IsMediaError (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ );
+
+STATIC
+BOOLEAN
+IsMediaChange (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ );
+
+STATIC
+BOOLEAN
+IsDriveReady (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts,
+ OUT BOOLEAN *NeedRetry
+ );
+
+STATIC
+BOOLEAN
+IsMediaWriteProtected (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ );
+
+STATIC
+BOOLEAN
+IsLogicalUnitCommunicationOverRun (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ );
+
+EFI_STATUS
+USBFloppyPacketCommand (
+ USB_FLOPPY_DEV *UsbFloppyDevice,
+ VOID *Command,
+ UINT8 CommandSize,
+ VOID *DataBuffer,
+ UINT32 BufferLength,
+ EFI_USB_DATA_DIRECTION Direction,
+ UINT16 TimeOutInMilliSeconds
+ )
+/*++
+
+ Routine Description:
+ Sends Packet Command to USB Floppy Drive.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+ Command - A pointer to the command packet.
+ CommandSize - Indicates the size of the command packet.
+ DataBuffer - A pointer to the buffer for the data transfer
+ after the command packet.
+ BufferLength - Indicates the size of the Data Buffer.
+ Direction - Transfer Direction
+ TimeOutInMilliSeconds - Timeout Value
+ Returns:
+ EFI_SUCCESS - Success
+--*/
+{
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ EFI_STATUS Status;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+ //
+ // Directly calling EFI_USB_ATAPI_PROTOCOL.UsbAtapiPacketCmd()
+ // to perform the command request.
+ //
+ Status = UsbAtapiInterface->UsbAtapiPacketCmd (
+ UsbAtapiInterface,
+ Command,
+ CommandSize,
+ DataBuffer,
+ BufferLength,
+ Direction,
+ TimeOutInMilliSeconds
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+USBFloppyIdentify (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves device information to tell the device type.
+
+ Arguments:
+ UsbFloppyDevice The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+
+ EFI_STATUS Status;
+ USB_INQUIRY_DATA *Idata;
+ BOOLEAN MediaChange;
+
+ //
+ // Send Inquiry Packet Command to get INQUIRY data.
+ //
+ Status = USBFloppyInquiry (UsbFloppyDevice, &Idata);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get media removable info from INQUIRY data.
+ //
+ UsbFloppyDevice->BlkIo.Media->RemovableMedia = (UINT8) ((Idata->RMB & 0x80) == 0x80);
+
+ //
+ // Identify device type via INQUIRY data.
+ //
+ switch ((Idata->peripheral_type) & 0x1f) {
+ //
+ // Floppy
+ //
+ case 0x00:
+ UsbFloppyDevice->DeviceType = USBFLOPPY;
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
+ break;
+
+ //
+ // CD-ROM
+ //
+ case 0x05:
+ UsbFloppyDevice->DeviceType = USBCDROM;
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ UsbFloppyDevice->BlkIo.Media->BlockSize = 0x800;
+ UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
+ break;
+
+ default:
+ gBS->FreePool (Idata);
+ return EFI_DEVICE_ERROR;
+ };
+
+ //
+ // Initialize some device specific data.
+ //
+ //
+ // original sense data numbers
+ //
+ UsbFloppyDevice->SenseDataNumber = 6;
+
+ if (UsbFloppyDevice->SenseData != NULL) {
+ gBS->FreePool (UsbFloppyDevice->SenseData);
+ UsbFloppyDevice->SenseData = NULL;
+ }
+
+ UsbFloppyDevice->SenseData = AllocatePool (UsbFloppyDevice->SenseDataNumber * sizeof (REQUEST_SENSE_DATA));
+
+ if (UsbFloppyDevice->SenseData == NULL) {
+ gBS->FreePool (Idata);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get media information.
+ //
+ UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange);
+
+ gBS->FreePool (Idata);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+USBFloppyInquiry (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ OUT USB_INQUIRY_DATA **Idata
+ )
+/*++
+
+ Routine Description:
+ Send Inquiry Packet Command to device and retrieve Inquiry Data.
+
+ Arguments:
+ UsbFloppyDevice The USB_FLOPPY_DEV instance.
+ Idata A pointer pointing to the address of
+ Inquiry Data.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_STATUS Status;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ //
+ // prepare command packet for the Inquiry Packet Command.
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.Inquiry.opcode = INQUIRY;
+ Packet.Inquiry.page_code = 0;
+ Packet.Inquiry.allocation_length = sizeof (USB_INQUIRY_DATA);
+
+ *Idata = AllocateZeroPool (sizeof (USB_INQUIRY_DATA));
+ if (*Idata == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Send command packet and retrieve requested Inquiry Data.
+ //
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) (*Idata),
+ sizeof (USB_INQUIRY_DATA),
+ EfiUsbDataIn,
+ USBFLPTIMEOUT * 3
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (*Idata);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+USBFloppyRead10 (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+ Routine Description:
+ Sends Read10 Packet Command to device to perform data transfer
+ from device to host.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+ Buffer - A pointer to the destination buffer for the data.
+ The caller is responsible for either having implicit
+ or explicit ownership of the buffer.
+ Lba - The starting logical block address to read from
+ on the device.
+ NumberOfBlocks - Indicates the number of blocks that the read
+ operation requests.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ ATAPI_PACKET_COMMAND Packet;
+ READ10_CMD *Read10Packet;
+ UINT16 MaxBlock;
+ UINT16 BlocksRemaining;
+ UINT16 SectorCount;
+ UINT32 Lba32;
+ UINT32 BlockSize;
+ UINT32 ByteCount;
+ VOID *ptrBuffer;
+ EFI_STATUS Status;
+ UINT16 TimeOut;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ UINTN SenseCounts;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ //
+ // prepare command packet for the Inquiry Packet Command.
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Read10Packet = &Packet.Read10;
+ Lba32 = (UINT32) Lba;
+ ptrBuffer = Buffer;
+ BlockSize = UsbFloppyDevice->BlkIo.Media->BlockSize;
+
+ MaxBlock = (UINT16) (65536 / BlockSize);
+ BlocksRemaining = (UINT16) NumberOfBlocks;
+
+ Status = EFI_SUCCESS;
+ while (BlocksRemaining > 0) {
+ if (BlocksRemaining <= MaxBlock) {
+ SectorCount = BlocksRemaining;
+ } else {
+ SectorCount = MaxBlock;
+ }
+ //
+ // fill the Packet data structure
+ //
+ Read10Packet->opcode = READ_10;
+
+ //
+ // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
+ // Lba0 is MSB, Lba3 is LSB
+ //
+ Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
+ Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
+ Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
+ Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
+
+ //
+ // TranLen0 ~ TranLen1 specify the transfer length in block unit.
+ // TranLen0 is MSB, TranLen is LSB
+ //
+ Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
+ Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
+
+ ByteCount = SectorCount * BlockSize;
+
+ TimeOut = (UINT16) (SectorCount * USBFLPTIMEOUT);
+
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) ptrBuffer,
+ ByteCount,
+ EfiUsbDataIn,
+ TimeOut
+ );
+ if (EFI_ERROR (Status)) {
+
+ Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
+ if (!EFI_ERROR (Status)) {
+ if (IsLogicalUnitCommunicationOverRun (
+ UsbFloppyDevice->SenseData,
+ SenseCounts
+ )) {
+ Lba32 = (UINT32) Lba;
+ ptrBuffer = Buffer;
+ BlocksRemaining = (UINT16) NumberOfBlocks;
+ MaxBlock = (UINT16) (MaxBlock / 4);
+ if (MaxBlock < 1) {
+ MaxBlock = 1;
+ }
+
+ continue;
+ }
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // retry read10 command
+ //
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) ptrBuffer,
+ ByteCount,
+ EfiUsbDataIn,
+ TimeOut
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ Lba32 += SectorCount;
+ ptrBuffer = (UINT8 *) ptrBuffer + SectorCount * BlockSize;
+ BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+USBFloppyReadCapacity (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves media capacity information via
+ sending Read Capacity Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+
+ //
+ // used for capacity data returned from Usb Floppy
+ //
+ READ_CAPACITY_DATA Data;
+
+ ZeroMem (&Data, sizeof (Data));
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.Inquiry.opcode = READ_CAPACITY;
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) &Data,
+ sizeof (READ_CAPACITY_DATA),
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbFloppyDevice->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) |
+ (Data.LastLba2 << 16) |
+ (Data.LastLba1 << 8) |
+ Data.LastLba0;
+
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
+
+ UsbFloppyDevice->BlkIo.Media->BlockSize = 0x800;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+USBFloppyReadFormatCapacity (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves media capacity information via sending Read Format
+ Capacity Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+
+ //
+ // used for capacity data returned from Usb Floppy
+ //
+ READ_FORMAT_CAPACITY_DATA FormatData;
+
+ ZeroMem (&FormatData, sizeof (FormatData));
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.ReadFormatCapacity.opcode = READ_FORMAT_CAPACITY;
+ Packet.ReadFormatCapacity.allocation_length_lo = 12;
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) &FormatData,
+ sizeof (READ_FORMAT_CAPACITY_DATA),
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (FormatData.DesCode == 3) {
+ //
+ // Media is not present
+ //
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ } else {
+
+ UsbFloppyDevice->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) |
+ (FormatData.LastLba2 << 16) |
+ (FormatData.LastLba1 << 8) |
+ FormatData.LastLba0;
+
+ UsbFloppyDevice->BlkIo.Media->LastBlock--;
+
+ UsbFloppyDevice->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) |
+ (FormatData.BlockSize1 << 8) |
+ FormatData.BlockSize0;
+
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
+
+ UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
+
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+UsbFloppyRequestSense (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ OUT UINTN *SenseCounts
+ )
+/*++
+
+ Routine Description:
+ Retrieves Sense Data from device via
+ sending Request Sense Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+ SenseCounts - A pointer to the number of Sense Data returned.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ EFI_STATUS Status;
+ REQUEST_SENSE_DATA *Sense;
+ UINT8 *Ptr;
+ BOOLEAN SenseReq;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ *SenseCounts = 0;
+
+ ZeroMem (
+ UsbFloppyDevice->SenseData,
+ sizeof (REQUEST_SENSE_DATA) * (UsbFloppyDevice->SenseDataNumber)
+ );
+ //
+ // fill command packet for Request Sense Packet Command
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.RequestSense.opcode = REQUEST_SENSE;
+ Packet.RequestSense.allocation_length = sizeof (REQUEST_SENSE_DATA);
+
+ //
+ // initialize pointer
+ //
+ Ptr = (UINT8 *) (UsbFloppyDevice->SenseData);
+
+ //
+ // request sense data from device continuously
+ // until no sense data exists in the device.
+ //
+ for (SenseReq = TRUE; SenseReq;) {
+
+ Sense = (REQUEST_SENSE_DATA *) Ptr;
+
+ //
+ // send out Request Sense Packet Command and get one Sense
+ // data from device.
+ //
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) Ptr,
+ sizeof (REQUEST_SENSE_DATA),
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+ //
+ // failed to get Sense data
+ //
+ if (EFI_ERROR (Status)) {
+ //
+ // Recovery the device back to normal state.
+ //
+ UsbFloppyDevice->AtapiProtocol->UsbAtapiReset (
+ UsbFloppyDevice->AtapiProtocol,
+ TRUE
+ );
+
+ if (*SenseCounts == 0) {
+ //
+ // never retrieved any sense data from device,
+ // just return error.
+ //
+ return EFI_DEVICE_ERROR;
+ } else {
+ //
+ // has retrieved some sense data from device,
+ // so return success.
+ //
+ return EFI_SUCCESS;
+ }
+ }
+
+ if (Sense->sense_key != SK_NO_SENSE) {
+ //
+ // Ptr is byte based pointer
+ //
+ Ptr += sizeof (REQUEST_SENSE_DATA);
+
+ (*SenseCounts)++;
+
+ } else {
+ //
+ // when no sense key, skip out the loop
+ //
+ SenseReq = FALSE;
+ }
+
+ //
+ // If the sense key numbers exceed Sense Data Buffer size,
+ // just skip the loop and do not fetch the sense key in this function.
+ //
+ if (*SenseCounts == UsbFloppyDevice->SenseDataNumber) {
+ SenseReq = FALSE;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UsbFloppyTestUnitReady (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Sends Test Unit ReadyPacket Command to the device.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_STATUS Status;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ UINT32 RetryIndex;
+ UINT32 MaximumRetryTimes;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+ MaximumRetryTimes = 2;
+ //
+ // fill command packet
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.TestUnitReady.opcode = TEST_UNIT_READY;
+
+ //
+ // send command packet
+ //
+ Status = EFI_DEVICE_ERROR;
+
+ for (RetryIndex = 0; RetryIndex < MaximumRetryTimes && EFI_ERROR (Status); RetryIndex++) {
+
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ NULL,
+ 0,
+ EfiUsbNoData,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->Stall (100 * STALL_1_MILLI_SECOND);
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+USBFloppyWrite10 (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+ Routine Description:
+ Sends Write10 Packet Command to device to perform data transfer
+ from host to device.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+ Buffer - A pointer to the source buffer for the data.
+ The caller is responsible for either having implicit
+ or explicit ownership of the buffer.
+ Lba - The starting logical block address to written to
+ the device.
+ NumberOfBlocks - Indicates the number of blocks that the write
+ operation requests.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+--*/
+{
+ ATAPI_PACKET_COMMAND Packet;
+ READ10_CMD *Write10Packet;
+ UINT16 MaxBlock;
+ UINT16 BlocksRemaining;
+ UINT16 SectorCount;
+ UINT32 Lba32;
+ UINT32 BlockSize;
+ UINT32 ByteCount;
+ VOID *ptrBuffer;
+ EFI_STATUS Status;
+ UINT16 TimeOut;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ UINTN SenseCounts;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ //
+ // prepare command packet for the Write10 Packet Command.
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Write10Packet = &Packet.Read10;
+ Lba32 = (UINT32) Lba;
+ ptrBuffer = Buffer;
+ BlockSize = UsbFloppyDevice->BlkIo.Media->BlockSize;
+
+ MaxBlock = (UINT16) (65536 / BlockSize);
+ BlocksRemaining = (UINT16) NumberOfBlocks;
+
+ Status = EFI_SUCCESS;
+ while (BlocksRemaining > 0) {
+
+ if (BlocksRemaining <= MaxBlock) {
+
+ SectorCount = BlocksRemaining;
+ } else {
+
+ SectorCount = MaxBlock;
+ }
+ //
+ // fill the Packet data structure
+ //
+ Write10Packet->opcode = WRITE_10;
+
+ //
+ // Lba0 ~ Lba3 specify the start logical block address
+ // of the data transfer.
+ // Lba0 is MSB, Lba3 is LSB
+ //
+ Write10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
+ Write10Packet->Lba2 = (UINT8) (Lba32 >> 8);
+ Write10Packet->Lba1 = (UINT8) (Lba32 >> 16);
+ Write10Packet->Lba0 = (UINT8) (Lba32 >> 24);
+
+ //
+ // TranLen0 ~ TranLen1 specify the transfer length in block unit.
+ // TranLen0 is MSB, TranLen is LSB
+ //
+ Write10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
+ Write10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
+
+ ByteCount = SectorCount * BlockSize;
+
+ TimeOut = (UINT16) (SectorCount * USBFLPTIMEOUT);
+
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) ptrBuffer,
+ ByteCount,
+ EfiUsbDataOut,
+ TimeOut
+ );
+ if (EFI_ERROR (Status)) {
+ Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
+ if (!EFI_ERROR (Status)) {
+ if (IsLogicalUnitCommunicationOverRun (
+ UsbFloppyDevice->SenseData,
+ SenseCounts
+ )) {
+ Lba32 = (UINT32) Lba;
+ ptrBuffer = Buffer;
+ BlocksRemaining = (UINT16) NumberOfBlocks;
+ MaxBlock = (UINT16) (MaxBlock / 4);
+ if (MaxBlock < 1) {
+ MaxBlock = 1;
+ }
+
+ continue;
+ }
+ }
+ //
+ // retry write10 command
+ //
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) ptrBuffer,
+ ByteCount,
+ EfiUsbDataOut,
+ TimeOut
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ Lba32 += SectorCount;
+ ptrBuffer = (UINT8 *) ptrBuffer + SectorCount * BlockSize;
+ BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+UsbFloppyDetectMedia (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ OUT BOOLEAN *MediaChange
+ )
+/*++
+
+ Routine Description:
+ Retrieves media information.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+ MediaChange - Indicates whether media was changed.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+ EFI_INVALID_PARAMETER - Parameter is error
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS FloppyStatus;
+ //
+ // the following variables are used to record previous media information
+ //
+ EFI_BLOCK_IO_MEDIA OldMediaInfo;
+ UINTN SenseCounts;
+ UINTN RetryIndex;
+ UINTN RetryTimes;
+ UINTN MaximumRetryTimes;
+ BOOLEAN NeedRetry;
+
+ //
+ // a flag used to determine whether need to perform Read Capacity command.
+ //
+ BOOLEAN NeedReadCapacity;
+
+ REQUEST_SENSE_DATA *SensePtr;
+
+ //
+ // init
+ //
+ Status = EFI_SUCCESS;
+ FloppyStatus = EFI_SUCCESS;
+ CopyMem (&OldMediaInfo, UsbFloppyDevice->BlkIo.Media, sizeof (OldMediaInfo));
+ //OldMediaInfo = *UsbFloppyDevice->BlkIo.Media;
+ *MediaChange = FALSE;
+ NeedReadCapacity = TRUE;
+
+ //
+ // if there is no media present,or media not changed,
+ // the request sense command will detect faster than read capacity command.
+ // read capacity command can be bypassed, thus improve performance.
+ //
+ SenseCounts = 0;
+ Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
+
+ if (!EFI_ERROR (Status)) {
+
+ SensePtr = UsbFloppyDevice->SenseData;
+
+ //
+ // No Media
+ //
+ if (IsNoMedia (UsbFloppyDevice->SenseData, SenseCounts)) {
+
+ NeedReadCapacity = FALSE;
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ } else {
+ //
+ // Media Changed
+ //
+ if (IsMediaChange (UsbFloppyDevice->SenseData, SenseCounts)) {
+ UsbFloppyDevice->BlkIo.Media->MediaId++;
+ }
+
+ //
+ // Media Write-protected
+ //
+ if (IsMediaWriteProtected (UsbFloppyDevice->SenseData, SenseCounts)) {
+ UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
+ }
+
+ //
+ // Media Error
+ //
+ if (IsMediaError (UsbFloppyDevice->SenseData, SenseCounts)) {
+ //
+ // if media error encountered, make it look like no media present.
+ //
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ }
+
+ }
+
+ }
+
+ if (NeedReadCapacity) {
+ //
+ // at most retry 5 times
+ //
+ MaximumRetryTimes = 5;
+ //
+ // initial retry twice
+ //
+ RetryTimes = 2;
+
+ for (RetryIndex = 0; (RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes); RetryIndex++) {
+ //
+ // Using different command to retrieve media capacity.
+ //
+ switch (UsbFloppyDevice->DeviceType) {
+
+ case USBCDROM:
+ Status = USBFloppyReadCapacity (UsbFloppyDevice);
+ break;
+
+ case USBFLOPPY:
+ UsbMassStorageModeSense (UsbFloppyDevice);
+ Status = USBFloppyReadFormatCapacity (UsbFloppyDevice);
+ if (EFI_ERROR (Status) || !UsbFloppyDevice->BlkMedia.MediaPresent) {
+ //
+ // retry the ReadCapacity command
+ //
+ UsbFloppyDevice->DeviceType = USBFLOPPY2;
+ Status = EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case USBFLOPPY2:
+ UsbMassStorageModeSense (UsbFloppyDevice);
+ Status = USBFloppyReadCapacity (UsbFloppyDevice);
+ if (EFI_ERROR (Status)) {
+ //
+ // retry the ReadFormatCapacity command
+ //
+ UsbFloppyDevice->DeviceType = USBFLOPPY;
+ }
+ //
+ // force the BlockSize to be 0x200.
+ //
+ UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // skip the loop when read capacity succeeds.
+ //
+ break;
+ }
+
+ SenseCounts = 0;
+
+ FloppyStatus = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts);
+
+ //
+ // If Request Sense data failed,retry.
+ //
+ if (EFI_ERROR (FloppyStatus)) {
+ //
+ // retry once more
+ //
+ RetryTimes++;
+ continue;
+ }
+ //
+ // No Media
+ //
+ if (IsNoMedia (UsbFloppyDevice->SenseData, SenseCounts)) {
+
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ break;
+ }
+
+ if (IsMediaError (UsbFloppyDevice->SenseData, SenseCounts)) {
+ //
+ // if media error encountered, make it look like no media present.
+ //
+ UsbFloppyDevice->BlkIo.Media->MediaId = 0;
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE;
+ UsbFloppyDevice->BlkIo.Media->LastBlock = 0;
+ break;
+ }
+
+ if (IsMediaWriteProtected (UsbFloppyDevice->SenseData, SenseCounts)) {
+ UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE;
+ continue;
+ }
+
+ if (!IsDriveReady (UsbFloppyDevice->SenseData, SenseCounts, &NeedRetry)) {
+
+ //
+ // Drive not ready: if NeedRetry, then retry once more;
+ // else return error
+ //
+ if (NeedRetry) {
+ //
+ // Stall 0.1 second to wait for drive becoming ready
+ //
+ gBS->Stall (100 * STALL_1_MILLI_SECOND);
+ //
+ // reset retry variable to zero,
+ // to make it retry for "drive in progress of becoming ready".
+ //
+ RetryIndex = 0;
+ continue;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // if read capacity fail not for above reasons, retry once more
+ //
+ RetryTimes++;
+
+ }
+ //
+ // ENDFOR
+ //
+
+ //
+ // tell whether the readcapacity process is successful or not
+ // ("Status" variable record the latest status returned
+ // by ReadCapacity AND "FloppyStatus" record the latest status
+ // returned by RequestSense)
+ //
+ if (EFI_ERROR (Status) && EFI_ERROR (FloppyStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ }
+
+ if (UsbFloppyDevice->BlkIo.Media->MediaPresent != OldMediaInfo.MediaPresent) {
+
+ if (UsbFloppyDevice->BlkIo.Media->MediaPresent) {
+ UsbFloppyDevice->BlkIo.Media->MediaId = 1;
+ }
+
+ *MediaChange = TRUE;
+ }
+
+ if (UsbFloppyDevice->BlkIo.Media->ReadOnly != OldMediaInfo.ReadOnly) {
+ *MediaChange = TRUE;
+ UsbFloppyDevice->BlkIo.Media->MediaId += 1;
+ }
+
+ if (UsbFloppyDevice->BlkIo.Media->BlockSize != OldMediaInfo.BlockSize) {
+ *MediaChange = TRUE;
+ UsbFloppyDevice->BlkIo.Media->MediaId += 1;
+ }
+
+ if (UsbFloppyDevice->BlkIo.Media->LastBlock != OldMediaInfo.LastBlock) {
+ *MediaChange = TRUE;
+ UsbFloppyDevice->BlkIo.Media->MediaId += 1;
+ }
+
+ if (UsbFloppyDevice->BlkIo.Media->MediaId != OldMediaInfo.MediaId) {
+ *MediaChange = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+UsbFloppyModeSense5APage5 (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves media capacity information via sending Read Format
+ Capacity Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+
+--*/
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ UFI_MODE_PARAMETER_PAGE_5 ModePage5;
+ EFI_LBA LastBlock;
+ UINT32 SectorsPerTrack;
+ UINT32 NumberOfCylinders;
+ UINT32 NumberOfHeads;
+ UINT32 DataBytesPerSector;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ ZeroMem (&ModePage5, sizeof (UFI_MODE_PARAMETER_PAGE_5));
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
+ //
+ // Flexible Disk Page
+ //
+ Packet.ModeSenseUFI.page_code = 5;
+ //
+ // current values
+ //
+ Packet.ModeSenseUFI.page_control = 0;
+ Packet.ModeSenseUFI.parameter_list_length_hi = 0;
+ Packet.ModeSenseUFI.parameter_list_length_lo = sizeof (UFI_MODE_PARAMETER_PAGE_5);
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) &ModePage5,
+ sizeof (UFI_MODE_PARAMETER_PAGE_5),
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ NumberOfHeads = ModePage5.flex_disk_page.number_of_heads;
+ SectorsPerTrack = ModePage5.flex_disk_page.sectors_per_track;
+ NumberOfCylinders = ModePage5.flex_disk_page.number_of_cylinders_msb << 8 |
+ ModePage5.flex_disk_page.number_of_cylinders_lsb;
+
+ LastBlock = SectorsPerTrack * NumberOfHeads * NumberOfCylinders;
+ DataBytesPerSector = ModePage5.flex_disk_page.databytes_per_sector_msb << 8 |
+ ModePage5.flex_disk_page.databytes_per_sector_lsb;
+
+ UsbFloppyDevice->BlkIo.Media->LastBlock = LastBlock;
+
+ UsbFloppyDevice->BlkIo.Media->LastBlock--;
+
+ UsbFloppyDevice->BlkIo.Media->BlockSize = DataBytesPerSector;
+
+ UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE;
+
+ UsbFloppyDevice->BlkIo.Media->ReadOnly =
+ ModePage5.mode_param_header.write_protected;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+UsbFloppyModeSense5APage1C (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves media capacity information via sending Read Format
+ Capacity Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+
+--*/
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ UFI_MODE_PARAMETER_PAGE_1C ModePage1C;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ ZeroMem (&ModePage1C, sizeof (UFI_MODE_PARAMETER_PAGE_1C));
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
+ //
+ // Flexible Disk Page
+ //
+ Packet.ModeSenseUFI.page_code = 0x1C;
+ //
+ // current values
+ //
+ Packet.ModeSenseUFI.page_control = 0;
+ Packet.ModeSenseUFI.parameter_list_length_hi = 0;
+ Packet.ModeSenseUFI.parameter_list_length_lo = sizeof (UFI_MODE_PARAMETER_PAGE_1C);
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ (VOID *) &ModePage1C,
+ sizeof (UFI_MODE_PARAMETER_PAGE_1C),
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbFloppyDevice->BlkIo.Media->ReadOnly = ModePage1C.mode_param_header.write_protected;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+UsbMassStorageModeSense (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+{
+ if (UsbFloppyDevice->AtapiProtocol->CommandProtocol == EFI_USB_SUBCLASS_SCSI) {
+ return UsbSCSIModeSense1APage3F (UsbFloppyDevice);
+ } else {
+ return UsbFloppyModeSense5APage3F (UsbFloppyDevice);
+ }
+}
+
+EFI_STATUS
+UsbFloppyModeSense5APage3F (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves mode sense information via sending Mode Sense
+ Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+
+--*/
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ UFI_MODE_PARAMETER_HEADER Header;
+ UINT32 Size;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ Size = sizeof (UFI_MODE_PARAMETER_HEADER);
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A;
+ Packet.ModeSenseUFI.page_code = 0x3F;
+ Packet.ModeSenseUFI.page_control = 0;
+ Packet.ModeSenseUFI.parameter_list_length_hi = 0;
+ Packet.ModeSenseUFI.parameter_list_length_lo = (UINT8) Size;
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (ATAPI_PACKET_COMMAND),
+ &Header,
+ Size,
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbFloppyDevice->BlkIo.Media->ReadOnly = Header.write_protected;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+UsbSCSIModeSense1APage3F (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ )
+/*++
+
+ Routine Description:
+ Retrieves mode sense information via sending Mode Sense
+ Packet Command.
+
+ Arguments:
+ UsbFloppyDevice - The USB_FLOPPY_DEV instance.
+
+ Returns:
+ EFI_DEVICE_ERROR - Hardware error
+ EFI_SUCCESS - Success
+
+--*/
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface;
+ SCSI_MODE_PARAMETER_HEADER6 Header;
+ UINT32 Size;
+
+ UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol;
+
+ Size = sizeof (SCSI_MODE_PARAMETER_HEADER6);
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.ModeSenseSCSI.opcode = SCSI_MODE_SENSE1A;
+ Packet.ModeSenseSCSI.page_code = 0x3F;
+ Packet.ModeSenseSCSI.page_control = 0;
+ Packet.ModeSenseSCSI.allocation_length = (UINT8) Size;
+ Status = USBFloppyPacketCommand (
+ UsbFloppyDevice,
+ &Packet,
+ sizeof (MODE_SENSE_CMD_SCSI),
+ &Header,
+ Size,
+ EfiUsbDataIn,
+ USBFLPTIMEOUT
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ UsbFloppyDevice->BlkIo.Media->ReadOnly = Header.write_protected;
+ return EFI_SUCCESS;
+
+}
+
+/*++
+
+ The following functions are a set of helper functions,
+ which are used to parse sense key returned by the device.
+
+--*/
+BOOLEAN
+IsNoMedia (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+{
+ REQUEST_SENSE_DATA *SensePtr;
+ UINTN Index;
+ BOOLEAN NoMedia;
+
+ NoMedia = FALSE;
+
+ SensePtr = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+
+ if ((SensePtr->sense_key == SK_NOT_READY) &&
+ (SensePtr->addnl_sense_code == ASC_NO_MEDIA)) {
+
+ NoMedia = TRUE;
+ }
+
+ SensePtr++;
+ }
+
+ return NoMedia;
+}
+
+
+BOOLEAN
+IsMediaError (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+{
+ REQUEST_SENSE_DATA *SensePtr;
+ UINTN Index;
+ BOOLEAN IsError;
+
+ IsError = FALSE;
+ SensePtr = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+
+ switch (SensePtr->sense_key) {
+
+ //
+ // Medium error case
+ //
+ case SK_MEDIUM_ERROR:
+ switch (SensePtr->addnl_sense_code) {
+
+ case ASC_MEDIA_ERR1:
+ case ASC_MEDIA_ERR2:
+ case ASC_MEDIA_ERR3:
+ case ASC_MEDIA_ERR4:
+ IsError = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ //
+ // Medium upside-down case
+ //
+ case SK_NOT_READY:
+ switch (SensePtr->addnl_sense_code) {
+ case ASC_MEDIA_UPSIDE_DOWN:
+ IsError = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ SensePtr++;
+ }
+
+ return IsError;
+}
+
+BOOLEAN
+IsMediaChange (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+{
+ REQUEST_SENSE_DATA *SensePtr;
+ UINTN Index;
+ BOOLEAN MediaChanged;
+
+ MediaChanged = FALSE;
+ SensePtr = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+
+ if ((SensePtr->sense_key == SK_UNIT_ATTENTION) &&
+ (SensePtr->addnl_sense_code == ASC_MEDIA_CHANGE)) {
+
+ MediaChanged = TRUE;
+ }
+
+ SensePtr++;
+ }
+
+ return MediaChanged;
+}
+
+BOOLEAN
+IsDriveReady (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts,
+ OUT BOOLEAN *NeedRetry
+ )
+{
+ REQUEST_SENSE_DATA *SensePtr;
+ UINTN Index;
+ BOOLEAN IsReady;
+
+ IsReady = TRUE;
+ *NeedRetry = FALSE;
+ SensePtr = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+
+ if ((SensePtr->sense_key == SK_NOT_READY) &&
+ (SensePtr->addnl_sense_code == ASC_NOT_READY)) {
+
+ switch (SensePtr->addnl_sense_code_qualifier) {
+
+ case ASCQ_IN_PROGRESS:
+ case ASCQ_DEVICE_BUSY:
+ IsReady = FALSE;
+ *NeedRetry = TRUE;
+ break;
+
+ default:
+ //
+ // Drive is in error condition,
+ // no need to retry.
+ //
+ IsReady = FALSE;
+ *NeedRetry = FALSE;
+ break;
+ }
+ }
+
+ SensePtr++;
+ }
+
+ return IsReady;
+}
+
+BOOLEAN
+IsMediaWriteProtected (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+{
+ REQUEST_SENSE_DATA *SensePtr;
+ UINTN Index;
+ BOOLEAN IsWriteProtected;
+
+ IsWriteProtected = FALSE;
+ SensePtr = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+ //
+ // catch media write-protected condition.
+ //
+ if ((SensePtr->sense_key == SK_DATA_PROTECT) &&
+ (SensePtr->addnl_sense_code == ASC_WRITE_PROTECTED)) {
+
+ IsWriteProtected = TRUE;
+ }
+
+ SensePtr++;
+ }
+
+ return IsWriteProtected;
+}
+
+BOOLEAN
+IsLogicalUnitCommunicationOverRun (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+{
+ REQUEST_SENSE_DATA *SensePtr;
+ UINTN Index;
+ BOOLEAN IsOverRun;
+
+ IsOverRun = FALSE;
+ SensePtr = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+
+ if ((SensePtr->sense_key == SK_NOT_READY) &&
+ (SensePtr->addnl_sense_code == ASC_LOGICAL_UNIT_STATUS) &&
+ (SensePtr->addnl_sense_code_qualifier == ASCQ_LOGICAL_UNIT_OVERRUN)) {
+ IsOverRun = TRUE;
+ }
+
+ SensePtr++;
+ }
+
+ return IsOverRun;
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.h b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.h
new file mode 100644
index 0000000000..f41241adc4
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.h
@@ -0,0 +1,111 @@
+/*++
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ UsbMassStorageHelper.h
+
+Abstract:
+
+ Function prototype for USB Mass Storage Driver
+
+Revision History
+--*/
+#ifndef _USB_FLPHLP_H
+#define _USB_FLPHLP_H
+
+#include "UsbMassStorage.h"
+
+EFI_STATUS
+USBFloppyIdentify (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+USBFloppyPacketCommand (
+ USB_FLOPPY_DEV *UsbFloppyDevice,
+ VOID *Command,
+ UINT8 CommandSize,
+ VOID *DataBuffer,
+ UINT32 BufferLength,
+ EFI_USB_DATA_DIRECTION Direction,
+ UINT16 TimeOutInMilliSeconds
+ );
+
+EFI_STATUS
+USBFloppyInquiry (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ OUT USB_INQUIRY_DATA **Idata
+ );
+
+EFI_STATUS
+USBFloppyRead10 (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ );
+
+EFI_STATUS
+USBFloppyReadFormatCapacity (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+UsbFloppyRequestSense (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ OUT UINTN *SenseCounts
+ );
+
+EFI_STATUS
+UsbFloppyTestUnitReady (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+USBFloppyWrite10 (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ );
+
+EFI_STATUS
+UsbFloppyDetectMedia (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice,
+ OUT BOOLEAN *MediaChange
+ );
+
+EFI_STATUS
+UsbFloppyModeSense5APage5 (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+UsbFloppyModeSense5APage1C (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+UsbFloppyModeSense5APage3F (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+UsbSCSIModeSense1APage3F (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+EFI_STATUS
+UsbMassStorageModeSense (
+ IN USB_FLOPPY_DEV *UsbFloppyDevice
+ );
+
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/build.xml b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/build.xml
new file mode 100644
index 0000000000..d2e48d3027
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
+<project basedir="." default="UsbMassStorage"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Usb\UsbMassStorage\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="UsbMassStorage">
+ <GenBuild baseName="UsbMassStorage" mbdFilename="${MODULE_DIR}\UsbMassStorage.mbd" msaFilename="${MODULE_DIR}\UsbMassStorage.msa"/>
+ </target>
+ <target depends="UsbMassStorage_clean" name="clean"/>
+ <target depends="UsbMassStorage_cleanall" name="cleanall"/>
+ <target name="UsbMassStorage_clean">
+ <OutputDirSetup baseName="UsbMassStorage" mbdFilename="${MODULE_DIR}\UsbMassStorage.mbd" msaFilename="${MODULE_DIR}\UsbMassStorage.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbMassStorage_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbMassStorage_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="UsbMassStorage_cleanall">
+ <OutputDirSetup baseName="UsbMassStorage" mbdFilename="${MODULE_DIR}\UsbMassStorage.mbd" msaFilename="${MODULE_DIR}\UsbMassStorage.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbMassStorage_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbMassStorage_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**UsbMassStorage*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/ComponentName.c
new file mode 100644
index 0000000000..5b01cea9d4
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/ComponentName.c
@@ -0,0 +1,216 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "usbmouse.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+UsbMouseComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+UsbMouseComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gUsbMouseComponentName = {
+ UsbMouseComponentNameGetDriverName,
+ UsbMouseComponentNameGetControllerName,
+ "eng"
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mUsbMouseDriverNameTable[] = {
+ { "eng", (CHAR16 *) L"Usb Mouse Driver" },
+ { NULL , NULL }
+};
+
+
+EFI_STATUS
+EFIAPI
+UsbMouseComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ Language - A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ DriverName - A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - DriverName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return LookupUnicodeString (
+ Language,
+ gUsbMouseComponentName.SupportedLanguages,
+ mUsbMouseDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UsbMouseComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ ControllerHandle - The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ ChildHandle - The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ ControllerName - A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language from the point of view of the driver specified
+ by This.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - ControllerName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ EFI_STATUS Status;
+ USB_MOUSE_DEV *UsbMouseDev;
+ EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol;
+ EFI_USB_IO_PROTOCOL *UsbIoProtocol;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check Controller's handle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIoProtocol,
+ gUsbMouseDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ gUsbMouseDriverBinding.DriverBindingHandle,
+ ControllerHandle
+ );
+
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Status != EFI_ALREADY_STARTED) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSimplePointerProtocolGuid,
+ (VOID **) &SimplePointerProtocol,
+ gUsbMouseDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UsbMouseDev = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (SimplePointerProtocol);
+
+ return LookupUnicodeString (
+ Language,
+ gUsbMouseComponentName.SupportedLanguages,
+ UsbMouseDev->ControllerNameTable,
+ ControllerName
+ );
+
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.mbd b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.mbd
new file mode 100644
index 0000000000..88b3e47a97
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.mbd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>UsbMouse</BaseName>
+ <Guid>2D2E62AA-9ECF-43b7-8219-94E7FC713DFE</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>EdkUsbLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.msa b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.msa
new file mode 100644
index 0000000000..8d2e1a2999
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.msa
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>UsbMouse</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>2D2E62AA-9ECF-43b7-8219-94E7FC713DFE</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for UsbMouse module</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">EdkUsbLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>usbmouse.h</Filename>
+ <Filename>usbmouse.c</Filename>
+ <Filename>mousehid.h</Filename>
+ <Filename>mousehid.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">DevicePath</Protocol>
+ <Protocol Usage="TO_START">UsbIo</Protocol>
+ <Protocol Usage="BY_START">SimplePointer</Protocol>
+ </Protocols>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gUsbMouseDriverBinding</DriverBinding>
+ <ComponentName>gUsbMouseComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/build.xml b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/build.xml
new file mode 100644
index 0000000000..081a9e0582
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
+<project basedir="." default="UsbMouse"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Usb\UsbMouse\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="UsbMouse">
+ <GenBuild baseName="UsbMouse" mbdFilename="${MODULE_DIR}\UsbMouse.mbd" msaFilename="${MODULE_DIR}\UsbMouse.msa"/>
+ </target>
+ <target depends="UsbMouse_clean" name="clean"/>
+ <target depends="UsbMouse_cleanall" name="cleanall"/>
+ <target name="UsbMouse_clean">
+ <OutputDirSetup baseName="UsbMouse" mbdFilename="${MODULE_DIR}\UsbMouse.mbd" msaFilename="${MODULE_DIR}\UsbMouse.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbMouse_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbMouse_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="UsbMouse_cleanall">
+ <OutputDirSetup baseName="UsbMouse" mbdFilename="${MODULE_DIR}\UsbMouse.mbd" msaFilename="${MODULE_DIR}\UsbMouse.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\UsbMouse_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\UsbMouse_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**UsbMouse*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.c b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.c
new file mode 100644
index 0000000000..cbe0970484
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.c
@@ -0,0 +1,395 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Mousehid.c
+
+Abstract:
+ Parse mouse hid descriptor
+
+--*/
+
+#include "usbmouse.h"
+#include "mousehid.h"
+
+//
+// Get an item from report descriptor
+//
+STATIC
+UINT8 *
+GetNextItem (
+ IN UINT8 *StartPos,
+ IN UINT8 *EndPos,
+ OUT HID_ITEM *HidItem
+ )
+/*++
+
+Routine Description:
+
+ Get Next Item
+
+Arguments:
+
+ StartPos - Start Position
+ EndPos - End Position
+ HidItem - HidItem to return
+
+Returns:
+ Position
+
+--*/
+{
+ UINT8 Temp;
+
+ if ((EndPos - StartPos) <= 0) {
+ return NULL;
+ }
+
+ Temp = *StartPos;
+ StartPos++;
+ //
+ // bit 2,3
+ //
+ HidItem->Type = (UINT8) ((Temp >> 2) & 0x03);
+ //
+ // bit 4-7
+ //
+ HidItem->Tag = (UINT8) ((Temp >> 4) & 0x0F);
+
+ if (HidItem->Tag == HID_ITEM_TAG_LONG) {
+ //
+ // Long Items are not supported by HID rev1.0,
+ // although we try to parse it.
+ //
+ HidItem->Format = HID_ITEM_FORMAT_LONG;
+
+ if ((EndPos - StartPos) >= 2) {
+ HidItem->Size = *StartPos++;
+ HidItem->Tag = *StartPos++;
+
+ if ((EndPos - StartPos) >= HidItem->Size) {
+ HidItem->Data.LongData = StartPos;
+ StartPos += HidItem->Size;
+ return StartPos;
+ }
+ }
+ } else {
+ HidItem->Format = HID_ITEM_FORMAT_SHORT;
+ //
+ // bit 0, 1
+ //
+ HidItem->Size = (UINT8) (Temp & 0x03);
+ switch (HidItem->Size) {
+
+ case 0:
+ //
+ // No data
+ //
+ return StartPos;
+
+ case 1:
+ //
+ // One byte data
+ //
+ if ((EndPos - StartPos) >= 1) {
+ HidItem->Data.U8 = *StartPos++;
+ return StartPos;
+ }
+
+ case 2:
+ //
+ // Two byte data
+ //
+ if ((EndPos - StartPos) >= 2) {
+ CopyMem (&HidItem->Data.U16, StartPos, sizeof (UINT16));
+ StartPos += 2;
+ return StartPos;
+ }
+
+ case 3:
+ //
+ // 4 byte data, adjust size
+ //
+ HidItem->Size++;
+ if ((EndPos - StartPos) >= 4) {
+ CopyMem (&HidItem->Data.U32, StartPos, sizeof (UINT32));
+ StartPos += 4;
+ return StartPos;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+STATIC
+UINT32
+GetItemData (
+ IN HID_ITEM *HidItem
+ )
+/*++
+
+Routine Description:
+
+ Get Item Data
+
+Arguments:
+
+ HidItem - HID_ITEM
+
+Returns:
+ HidItem Data
+
+
+--*/
+{
+ //
+ // Get Data from HID_ITEM structure
+ //
+ switch (HidItem->Size) {
+
+ case 1:
+ return HidItem->Data.U8;
+
+ case 2:
+ return HidItem->Data.U16;
+
+ case 4:
+ return HidItem->Data.U32;
+ }
+
+ return 0;
+}
+
+STATIC
+VOID
+ParseLocalItem (
+ IN USB_MOUSE_DEV *UsbMouse,
+ IN HID_ITEM *LocalItem
+ )
+/*++
+
+Routine Description:
+
+ Parse Local Item
+
+Arguments:
+
+ UsbMouse - USB_MOUSE_DEV
+ LocalItem - Local Item
+
+Returns:
+
+--*/
+{
+ UINT32 Data;
+
+ if (LocalItem->Size == 0) {
+ //
+ // No expected data for local item
+ //
+ return ;
+ }
+
+ Data = GetItemData (LocalItem);
+
+ switch (LocalItem->Tag) {
+
+ case HID_LOCAL_ITEM_TAG_DELIMITER:
+ //
+ // we don't support delimiter here
+ //
+ return ;
+
+ case HID_LOCAL_ITEM_TAG_USAGE:
+ return ;
+
+ case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
+ if (UsbMouse->PrivateData.ButtonDetected) {
+ UsbMouse->PrivateData.ButtonMinIndex = (UINT8) Data;
+ }
+
+ return ;
+
+ case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
+ {
+ if (UsbMouse->PrivateData.ButtonDetected) {
+ UsbMouse->PrivateData.ButtonMaxIndex = (UINT8) Data;
+ }
+
+ return ;
+ }
+ }
+}
+
+STATIC
+VOID
+ParseGlobalItem (
+ IN USB_MOUSE_DEV *UsbMouse,
+ IN HID_ITEM *GlobalItem
+ )
+{
+ UINT8 UsagePage;
+
+ switch (GlobalItem->Tag) {
+ case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
+ {
+ UsagePage = (UINT8) GetItemData (GlobalItem);
+
+ //
+ // We only care Button Page here
+ //
+ if (UsagePage == 0x09) {
+ //
+ // Button Page
+ //
+ UsbMouse->PrivateData.ButtonDetected = TRUE;
+ return ;
+ }
+ break;
+ }
+
+ }
+}
+
+
+STATIC
+VOID
+ParseMainItem (
+ IN USB_MOUSE_DEV *UsbMouse,
+ IN HID_ITEM *MainItem
+ )
+/*++
+
+Routine Description:
+
+ Parse Main Item
+
+Arguments:
+
+ UsbMouse - TODO: add argument description
+ MainItem - HID_ITEM to parse
+
+Returns:
+
+ VOID
+
+--*/
+{
+ //
+ // we don't care any main items, just skip
+ //
+ return ;
+}
+
+STATIC
+VOID
+ParseHidItem (
+ IN USB_MOUSE_DEV *UsbMouse,
+ IN HID_ITEM *HidItem
+ )
+/*++
+
+Routine Description:
+
+ Parse Hid Item
+
+Arguments:
+
+ UsbMouse - USB_MOUSE_DEV
+ HidItem - HidItem to parse
+
+Returns:
+
+ VOID
+
+--*/
+{
+ switch (HidItem->Type) {
+
+ case HID_ITEM_TYPE_MAIN:
+ //
+ // For Main Item, parse main item
+ //
+ ParseMainItem (UsbMouse, HidItem);
+ break;
+
+ case HID_ITEM_TYPE_GLOBAL:
+ //
+ // For global Item, parse global item
+ //
+ ParseGlobalItem (UsbMouse, HidItem);
+ break;
+
+ case HID_ITEM_TYPE_LOCAL:
+ //
+ // For Local Item, parse local item
+ //
+ ParseLocalItem (UsbMouse, HidItem);
+ break;
+ }
+}
+//
+// A simple parse just read some field we are interested in
+//
+EFI_STATUS
+ParseMouseReportDescriptor (
+ IN USB_MOUSE_DEV *UsbMouse,
+ IN UINT8 *ReportDescriptor,
+ IN UINTN ReportSize
+ )
+/*++
+
+Routine Description:
+
+ Parse Mouse Report Descriptor
+
+Arguments:
+
+ UsbMouse - USB_MOUSE_DEV
+ ReportDescriptor - Report descriptor to parse
+ ReportSize - Report descriptor size
+
+Returns:
+
+ EFI_DEVICE_ERROR - Report descriptor error
+ EFI_SUCCESS - Success
+
+--*/
+{
+ UINT8 *DescriptorEnd;
+ UINT8 *ptr;
+ HID_ITEM HidItem;
+
+ DescriptorEnd = ReportDescriptor + ReportSize;
+
+ ptr = GetNextItem (ReportDescriptor, DescriptorEnd, &HidItem);
+
+ while (ptr != NULL) {
+ if (HidItem.Format != HID_ITEM_FORMAT_SHORT) {
+ //
+ // Long Format Item is not supported at current HID revision
+ //
+ return EFI_DEVICE_ERROR;
+ }
+
+ ParseHidItem (UsbMouse, &HidItem);
+
+ ptr = GetNextItem (ptr, DescriptorEnd, &HidItem);
+ }
+
+ UsbMouse->NumberOfButtons = (UINT8) (UsbMouse->PrivateData.ButtonMaxIndex - UsbMouse->PrivateData.ButtonMinIndex + 1);
+ UsbMouse->XLogicMax = UsbMouse->YLogicMax = 127;
+ UsbMouse->XLogicMin = UsbMouse->YLogicMin = -127;
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.h b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.h
new file mode 100644
index 0000000000..ccce8354ea
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.h
@@ -0,0 +1,84 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MouseHid.h
+
+Abstract:
+
+--*/
+
+#ifndef __MOUSE_HID_H
+#define __MOUSE_HID_H
+
+#include "usbmouse.h"
+
+//
+// HID Item general structure
+//
+typedef struct _hid_item {
+ UINT16 Format;
+ UINT8 Size;
+ UINT8 Type;
+ UINT8 Tag;
+ union {
+ UINT8 U8;
+ UINT16 U16;
+ UINT32 U32;
+ INT8 I8;
+ INT16 I16;
+ INT32 I32;
+ UINT8 *LongData;
+ } Data;
+} HID_ITEM;
+
+typedef struct {
+ UINT16 UsagePage;
+ INT32 LogicMin;
+ INT32 LogicMax;
+ INT32 PhysicalMin;
+ INT32 PhysicalMax;
+ UINT16 UnitExp;
+ UINT16 UINT;
+ UINT16 ReportId;
+ UINT16 ReportSize;
+ UINT16 ReportCount;
+} HID_GLOBAL;
+
+typedef struct {
+ UINT16 Usage[16]; /* usage array */
+ UINT16 UsageIndex;
+ UINT16 UsageMin;
+} HID_LOCAL;
+
+typedef struct {
+ UINT16 Type;
+ UINT16 Usage;
+} HID_COLLECTION;
+
+typedef struct {
+ HID_GLOBAL Global;
+ HID_GLOBAL GlobalStack[8];
+ UINT32 GlobalStackPtr;
+ HID_LOCAL Local;
+ HID_COLLECTION CollectionStack[8];
+ UINT32 CollectionStackPtr;
+} HID_PARSER;
+
+EFI_STATUS
+ParseMouseReportDescriptor (
+ IN USB_MOUSE_DEV *UsbMouse,
+ IN UINT8 *ReportDescriptor,
+ IN UINTN ReportSize
+ );
+
+#endif
diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.c b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.c
new file mode 100644
index 0000000000..81da0205a4
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.c
@@ -0,0 +1,1028 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name:
+
+ UsbMouse.c
+
+ Abstract:
+
+--*/
+
+#include "usbmouse.h"
+#include "mousehid.h"
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+EFI_STATUS
+EFIAPI
+USBMouseDriverBindingEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+EFI_STATUS
+EFIAPI
+USBMouseDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+USBMouseDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+USBMouseDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+
+EFI_DRIVER_BINDING_PROTOCOL gUsbMouseDriverBinding = {
+ USBMouseDriverBindingSupported,
+ USBMouseDriverBindingStart,
+ USBMouseDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+//
+// helper functions
+//
+STATIC
+BOOLEAN
+IsUsbMouse (
+ IN EFI_USB_IO_PROTOCOL *UsbIo
+ );
+
+STATIC
+EFI_STATUS
+InitializeUsbMouseDevice (
+ IN USB_MOUSE_DEV *UsbMouseDev
+ );
+
+STATIC
+VOID
+EFIAPI
+UsbMouseWaitForInput (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+//
+// Mouse interrupt handler
+//
+STATIC
+EFI_STATUS
+EFIAPI
+OnMouseInterruptComplete (
+ IN VOID *Data,
+ IN UINTN DataLength,
+ IN VOID *Context,
+ IN UINT32 Result
+ );
+
+//
+// Mouse Protocol
+//
+STATIC
+EFI_STATUS
+EFIAPI
+GetMouseState (
+ IN EFI_SIMPLE_POINTER_PROTOCOL *This,
+ OUT EFI_SIMPLE_POINTER_STATE *MouseState
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbMouseReset (
+ IN EFI_SIMPLE_POINTER_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+EFI_STATUS
+EFIAPI
+USBMouseDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ that has UsbHcProtocol installed will be supported.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver supports this device.
+ EFI_UNSUPPORTED - This driver does not support this device.
+
+--*/
+{
+ EFI_STATUS OpenStatus;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_STATUS Status;
+
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (OpenStatus == EFI_ALREADY_STARTED) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ //
+ // Use the USB I/O protocol interface to see the Controller is
+ // the Mouse controller that can be managed by this driver.
+ //
+ Status = EFI_SUCCESS;
+ if (!IsUsbMouse (UsbIo)) {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+USBMouseDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Starting the Usb Bus Driver
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver supports this device.
+ EFI_UNSUPPORTED - This driver does not support this device.
+ EFI_DEVICE_ERROR - This driver cannot be started due to device
+ Error
+ EFI_OUT_OF_RESOURCES- Can't allocate memory resources
+ EFI_ALREADY_STARTED - Thios driver has been started
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc;
+ USB_MOUSE_DEV *UsbMouseDevice;
+ UINT8 EndpointNumber;
+ UINT8 Index;
+ UINT8 EndpointAddr;
+ UINT8 PollingInterval;
+ UINT8 PacketSize;
+
+ UsbMouseDevice = NULL;
+ Status = EFI_SUCCESS;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ UsbMouseDevice = AllocateZeroPool (sizeof (USB_MOUSE_DEV));
+ if (UsbMouseDevice == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ UsbMouseDevice->UsbIo = UsbIo;
+
+ UsbMouseDevice->Signature = USB_MOUSE_DEV_SIGNATURE;
+
+ UsbMouseDevice->InterfaceDescriptor = AllocatePool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR));
+ if (UsbMouseDevice->InterfaceDescriptor == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ EndpointDesc = AllocatePool (sizeof (EFI_USB_ENDPOINT_DESCRIPTOR));
+ if (EndpointDesc == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+ //
+ // Get the Device Path Protocol on Controller's handle
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &UsbMouseDevice->DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+ //
+ // Get interface & endpoint descriptor
+ //
+ UsbIo->UsbGetInterfaceDescriptor (
+ UsbIo,
+ UsbMouseDevice->InterfaceDescriptor
+ );
+
+ EndpointNumber = UsbMouseDevice->InterfaceDescriptor->NumEndpoints;
+
+ for (Index = 0; Index < EndpointNumber; Index++) {
+ UsbIo->UsbGetEndpointDescriptor (
+ UsbIo,
+ Index,
+ EndpointDesc
+ );
+
+ if ((EndpointDesc->Attributes & 0x03) == 0x03) {
+
+ //
+ // We only care interrupt endpoint here
+ //
+ UsbMouseDevice->IntEndpointDescriptor = EndpointDesc;
+ }
+ }
+
+ if (UsbMouseDevice->IntEndpointDescriptor == NULL) {
+ //
+ // No interrupt endpoint, then error
+ //
+ Status = EFI_UNSUPPORTED;
+ goto ErrorExit;
+ }
+
+ Status = InitializeUsbMouseDevice (UsbMouseDevice);
+ if (EFI_ERROR (Status)) {
+ MouseReportStatusCode (
+ UsbMouseDevice->DevicePath,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_PERIPHERAL_MOUSE | EFI_P_EC_INTERFACE_ERROR)
+ );
+
+ goto ErrorExit;
+ }
+
+ UsbMouseDevice->SimplePointerProtocol.GetState = GetMouseState;
+ UsbMouseDevice->SimplePointerProtocol.Reset = UsbMouseReset;
+ UsbMouseDevice->SimplePointerProtocol.Mode = &UsbMouseDevice->Mode;
+
+ Status = gBS->CreateEvent (
+ EFI_EVENT_NOTIFY_WAIT,
+ EFI_TPL_NOTIFY,
+ UsbMouseWaitForInput,
+ UsbMouseDevice,
+ &((UsbMouseDevice->SimplePointerProtocol).WaitForInput)
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiSimplePointerProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &UsbMouseDevice->SimplePointerProtocol
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto ErrorExit;
+ }
+
+ //
+ // After Enabling Async Interrupt Transfer on this mouse Device
+ // we will be able to get key data from it. Thus this is deemed as
+ // the enable action of the mouse
+ //
+
+ MouseReportStatusCode (
+ UsbMouseDevice->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE)
+ );
+
+ //
+ // submit async interrupt transfer
+ //
+ EndpointAddr = UsbMouseDevice->IntEndpointDescriptor->EndpointAddress;
+ PollingInterval = UsbMouseDevice->IntEndpointDescriptor->Interval;
+ PacketSize = (UINT8) (UsbMouseDevice->IntEndpointDescriptor->MaxPacketSize);
+
+ Status = UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ EndpointAddr,
+ TRUE,
+ PollingInterval,
+ PacketSize,
+ OnMouseInterruptComplete,
+ UsbMouseDevice
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ UsbMouseDevice->ControllerNameTable = NULL;
+ AddUnicodeString (
+ "eng",
+ gUsbMouseComponentName.SupportedLanguages,
+ &UsbMouseDevice->ControllerNameTable,
+ (CHAR16 *) L"Generic Usb Mouse"
+ );
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If submit error, uninstall that interface
+ //
+ Status = EFI_DEVICE_ERROR;
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiSimplePointerProtocolGuid,
+ &UsbMouseDevice->SimplePointerProtocol
+ );
+
+ErrorExit:
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ if (UsbMouseDevice != NULL) {
+ if (UsbMouseDevice->InterfaceDescriptor != NULL) {
+ gBS->FreePool (UsbMouseDevice->InterfaceDescriptor);
+ }
+
+ if (UsbMouseDevice->IntEndpointDescriptor != NULL) {
+ gBS->FreePool (UsbMouseDevice->IntEndpointDescriptor);
+ }
+
+ if ((UsbMouseDevice->SimplePointerProtocol).WaitForInput != NULL) {
+ gBS->CloseEvent ((UsbMouseDevice->SimplePointerProtocol).WaitForInput);
+ }
+
+ gBS->FreePool (UsbMouseDevice);
+ UsbMouseDevice = NULL;
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+USBMouseDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to stop driver on
+ NumberOfChildren - Number of Children in the ChildHandleBuffer
+ ChildHandleBuffer - List of handles for the children we need to stop.
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+ others
+
+--*/
+{
+ EFI_STATUS Status;
+ USB_MOUSE_DEV *UsbMouseDevice;
+ EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ //
+ // Get our context back.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiSimplePointerProtocolGuid,
+ (VOID **) &SimplePointerProtocol,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ UsbMouseDevice = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (SimplePointerProtocol);
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiSimplePointerProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ UsbIo = UsbMouseDevice->UsbIo;
+
+ //
+ // Uninstall the Asyn Interrupt Transfer from this device
+ // will disable the mouse data input from this device
+ //
+ MouseReportStatusCode (
+ UsbMouseDevice->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE)
+ );
+
+ //
+ // Delete Mouse Async Interrupt Transfer
+ //
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ UsbMouseDevice->IntEndpointDescriptor->EndpointAddress,
+ FALSE,
+ UsbMouseDevice->IntEndpointDescriptor->Interval,
+ 0,
+ NULL,
+ NULL
+ );
+
+ gBS->CloseEvent (UsbMouseDevice->SimplePointerProtocol.WaitForInput);
+
+ if (UsbMouseDevice->DelayedRecoveryEvent) {
+ gBS->CloseEvent (UsbMouseDevice->DelayedRecoveryEvent);
+ UsbMouseDevice->DelayedRecoveryEvent = 0;
+ }
+
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiSimplePointerProtocolGuid,
+ &UsbMouseDevice->SimplePointerProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->FreePool (UsbMouseDevice->InterfaceDescriptor);
+ gBS->FreePool (UsbMouseDevice->IntEndpointDescriptor);
+
+ if (UsbMouseDevice->ControllerNameTable) {
+ FreeUnicodeStringTable (UsbMouseDevice->ControllerNameTable);
+ }
+
+ gBS->FreePool (UsbMouseDevice);
+
+ return EFI_SUCCESS;
+
+}
+
+BOOLEAN
+IsUsbMouse (
+ IN EFI_USB_IO_PROTOCOL *UsbIo
+ )
+/*++
+
+ Routine Description:
+ Tell if a Usb Controller is a mouse
+
+ Arguments:
+ UsbIo - Protocol instance pointer.
+
+ Returns:
+ TRUE - It is a mouse
+ FALSE - It is not a mouse
+--*/
+{
+ EFI_STATUS Status;
+ EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+
+ //
+ // Get the Default interface descriptor, now we only
+ // suppose it is interface 1
+ //
+ Status = UsbIo->UsbGetInterfaceDescriptor (
+ UsbIo,
+ &InterfaceDescriptor
+ );
+
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ if ((InterfaceDescriptor.InterfaceClass == CLASS_HID) &&
+ (InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT) &&
+ (InterfaceDescriptor.InterfaceProtocol == PROTOCOL_MOUSE)
+ ) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+STATIC
+EFI_STATUS
+InitializeUsbMouseDevice (
+ IN USB_MOUSE_DEV *UsbMouseDev
+ )
+/*++
+
+ Routine Description:
+ Initialize the Usb Mouse Device.
+
+ Arguments:
+ UsbMouseDev - Device instance to be initialized
+
+ Returns:
+ EFI_SUCCESS - Success
+ EFI_DEVICE_ERROR - Init error.
+ EFI_OUT_OF_RESOURCES- Can't allocate memory
+--*/
+{
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 Protocol;
+ EFI_STATUS Status;
+ EFI_USB_HID_DESCRIPTOR MouseHidDesc;
+ UINT8 *ReportDesc;
+
+ UsbIo = UsbMouseDev->UsbIo;
+
+ //
+ // Get HID descriptor
+ //
+ Status = UsbGetHidDescriptor (
+ UsbIo,
+ UsbMouseDev->InterfaceDescriptor->InterfaceNumber,
+ &MouseHidDesc
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get Report descriptor
+ //
+ if (MouseHidDesc.HidClassDesc[0].DescriptorType != 0x22) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ReportDesc = AllocateZeroPool (MouseHidDesc.HidClassDesc[0].DescriptorLength);
+ if (ReportDesc == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = UsbGetReportDescriptor (
+ UsbIo,
+ UsbMouseDev->InterfaceDescriptor->InterfaceNumber,
+ MouseHidDesc.HidClassDesc[0].DescriptorLength,
+ ReportDesc
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (ReportDesc);
+ return Status;
+ }
+
+ //
+ // Parse report descriptor
+ //
+ Status = ParseMouseReportDescriptor (
+ UsbMouseDev,
+ ReportDesc,
+ MouseHidDesc.HidClassDesc[0].DescriptorLength
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (ReportDesc);
+ return Status;
+ }
+
+ if (UsbMouseDev->NumberOfButtons >= 1) {
+ UsbMouseDev->Mode.LeftButton = TRUE;
+ }
+
+ if (UsbMouseDev->NumberOfButtons > 1) {
+ UsbMouseDev->Mode.RightButton = TRUE;
+ }
+
+ UsbMouseDev->Mode.ResolutionX = 8;
+ UsbMouseDev->Mode.ResolutionY = 8;
+ UsbMouseDev->Mode.ResolutionZ = 0;
+ //
+ // Here we just assume interface 0 is the mouse interface
+ //
+ UsbGetProtocolRequest (
+ UsbIo,
+ 0,
+ &Protocol
+ );
+
+ if (Protocol != BOOT_PROTOCOL) {
+ Status = UsbSetProtocolRequest (
+ UsbIo,
+ 0,
+ BOOT_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (ReportDesc);
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // Set indefinite Idle rate for USB Mouse
+ //
+ UsbSetIdleRequest (
+ UsbIo,
+ 0,
+ 0,
+ 0
+ );
+
+ gBS->FreePool (ReportDesc);
+
+ if (UsbMouseDev->DelayedRecoveryEvent) {
+ gBS->CloseEvent (UsbMouseDev->DelayedRecoveryEvent);
+ UsbMouseDev->DelayedRecoveryEvent = 0;
+ }
+
+ Status = gBS->CreateEvent (
+ EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_NOTIFY,
+ USBMouseRecoveryHandler,
+ UsbMouseDev,
+ &UsbMouseDev->DelayedRecoveryEvent
+ );
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+OnMouseInterruptComplete (
+ IN VOID *Data,
+ IN UINTN DataLength,
+ IN VOID *Context,
+ IN UINT32 Result
+ )
+/*++
+
+ Routine Description:
+ It is called whenever there is data received from async interrupt
+ transfer.
+
+ Arguments:
+ Data - Data received.
+ DataLength - Length of Data
+ Context - Passed in context
+ Result - Async Interrupt Transfer result
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+{
+ USB_MOUSE_DEV *UsbMouseDevice;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 EndpointAddr;
+ UINT32 UsbResult;
+
+ UsbMouseDevice = (USB_MOUSE_DEV *) Context;
+ UsbIo = UsbMouseDevice->UsbIo;
+
+ if (Result != EFI_USB_NOERROR) {
+ //
+ // Some errors happen during the process
+ //
+ MouseReportStatusCode (
+ UsbMouseDevice->DevicePath,
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_PERIPHERAL_MOUSE | EFI_P_EC_INPUT_ERROR)
+ );
+
+ if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
+ EndpointAddr = UsbMouseDevice->IntEndpointDescriptor->EndpointAddress;
+
+ UsbClearEndpointHalt (
+ UsbIo,
+ EndpointAddr,
+ &UsbResult
+ );
+ }
+
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ UsbMouseDevice->IntEndpointDescriptor->EndpointAddress,
+ FALSE,
+ 0,
+ 0,
+ NULL,
+ NULL
+ );
+
+ gBS->SetTimer (
+ UsbMouseDevice->DelayedRecoveryEvent,
+ TimerRelative,
+ EFI_USB_INTERRUPT_DELAY
+ );
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (DataLength == 0 || Data == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ UsbMouseDevice->StateChanged = TRUE;
+
+ //
+ // Check mouse Data
+ //
+ UsbMouseDevice->State.LeftButton = (BOOLEAN) (*(UINT8 *) Data & 0x01);
+ UsbMouseDevice->State.RightButton = (BOOLEAN) (*(UINT8 *) Data & 0x02);
+ UsbMouseDevice->State.RelativeMovementX += *((INT8 *) Data + 1);
+ UsbMouseDevice->State.RelativeMovementY += *((INT8 *) Data + 2);
+
+ if (DataLength > 3) {
+ UsbMouseDevice->State.RelativeMovementZ += *((INT8 *) Data + 3);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/*
+STATIC VOID
+PrintMouseState(
+ IN EFI_MOUSE_STATE *MouseState
+ )
+{
+ Aprint("(%x: %x, %x)\n",
+ MouseState->ButtonStates,
+ MouseState->dx,
+ MouseState->dy
+ );
+}
+*/
+STATIC
+EFI_STATUS
+EFIAPI
+GetMouseState (
+ IN EFI_SIMPLE_POINTER_PROTOCOL *This,
+ OUT EFI_SIMPLE_POINTER_STATE *MouseState
+ )
+/*++
+
+ Routine Description:
+ Get the mouse state, see SIMPLE POINTER PROTOCOL.
+
+ Arguments:
+ This - Protocol instance pointer.
+ MouseState - Current mouse state
+
+ Returns:
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+ EFI_NOT_READY
+
+--*/
+{
+ USB_MOUSE_DEV *MouseDev;
+
+ if (MouseState == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ MouseDev = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This);
+
+ if (!MouseDev->StateChanged) {
+ return EFI_NOT_READY;
+ }
+
+ CopyMem (
+ MouseState,
+ &MouseDev->State,
+ sizeof (EFI_SIMPLE_POINTER_STATE)
+ );
+
+ //
+ // Clear previous move state
+ //
+ MouseDev->State.RelativeMovementX = 0;
+ MouseDev->State.RelativeMovementY = 0;
+ MouseDev->State.RelativeMovementZ = 0;
+
+ MouseDev->StateChanged = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+EFIAPI
+UsbMouseReset (
+ IN EFI_SIMPLE_POINTER_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+ Routine Description:
+ Reset the mouse device, see SIMPLE POINTER PROTOCOL.
+
+ Arguments:
+ This - Protocol instance pointer.
+ ExtendedVerification - Ignored here/
+
+ Returns:
+ EFI_SUCCESS
+
+--*/
+{
+ USB_MOUSE_DEV *UsbMouseDevice;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ UsbMouseDevice = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This);
+
+ UsbIo = UsbMouseDevice->UsbIo;
+
+ MouseReportStatusCode (
+ UsbMouseDevice->DevicePath,
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET)
+ );
+
+ ZeroMem (
+ &UsbMouseDevice->State,
+ sizeof (EFI_SIMPLE_POINTER_STATE)
+ );
+ UsbMouseDevice->StateChanged = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+EFIAPI
+UsbMouseWaitForInput (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ Event notification function for SIMPLE_POINTER.WaitForInput event
+ Signal the event if there is input from mouse
+
+Arguments:
+ Event - Wait Event
+ Context - Passed parameter to event handler
+Returns:
+ VOID
+--*/
+{
+ USB_MOUSE_DEV *UsbMouseDev;
+
+ UsbMouseDev = (USB_MOUSE_DEV *) Context;
+
+ //
+ // Someone is waiting on the mouse event, if there's
+ // input from mouse, signal the event
+ //
+ if (UsbMouseDev->StateChanged) {
+ gBS->SignalEvent (Event);
+ }
+}
+
+VOID
+EFIAPI
+USBMouseRecoveryHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+ Routine Description:
+ Timer handler for Delayed Recovery timer.
+
+ Arguments:
+ Event - The Delayed Recovery event.
+ Context - Points to the USB_KB_DEV instance.
+
+ Returns:
+
+--*/
+{
+ USB_MOUSE_DEV *UsbMouseDev;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ UsbMouseDev = (USB_MOUSE_DEV *) Context;
+
+ UsbIo = UsbMouseDev->UsbIo;
+
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ UsbMouseDev->IntEndpointDescriptor->EndpointAddress,
+ TRUE,
+ UsbMouseDev->IntEndpointDescriptor->Interval,
+ UsbMouseDev->IntEndpointDescriptor->MaxPacketSize,
+ OnMouseInterruptComplete,
+ UsbMouseDev
+ );
+}
+
+VOID
+MouseReportStatusCode (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value
+ )
+/*++
+
+ Routine Description:
+ Report Status Code in Usb Bot Driver
+
+ Arguments:
+ DevicePath - Use this to get Device Path
+ CodeType - Status Code Type
+ CodeValue - Status Code Value
+
+ Returns:
+ None
+
+--*/
+{
+
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ CodeType,
+ Value,
+ DevicePath
+ );
+}
diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.h b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.h
new file mode 100644
index 0000000000..8a7dd753b1
--- /dev/null
+++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.h
@@ -0,0 +1,85 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name:
+
+ UsbMouse.h
+
+ Abstract:
+
+--*/
+
+#ifndef _USB_MOUSE_H
+#define _USB_MOUSE_H
+
+#include <IndustryStandard/usb.h>
+
+#define CLASS_HID 3
+#define SUBCLASS_BOOT 1
+#define PROTOCOL_MOUSE 2
+
+#define BOOT_PROTOCOL 0
+#define REPORT_PROTOCOL 1
+
+#define USB_MOUSE_DEV_SIGNATURE EFI_SIGNATURE_32 ('u', 'm', 'o', 'u')
+
+typedef struct {
+ BOOLEAN ButtonDetected;
+ UINT8 ButtonMinIndex;
+ UINT8 ButtonMaxIndex;
+ UINT8 Reserved;
+} PRIVATE_DATA;
+
+typedef struct {
+ UINTN Signature;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_EVENT DelayedRecoveryEvent;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor;
+ EFI_USB_ENDPOINT_DESCRIPTOR *IntEndpointDescriptor;
+ UINT8 NumberOfButtons;
+ INT32 XLogicMax;
+ INT32 XLogicMin;
+ INT32 YLogicMax;
+ INT32 YLogicMin;
+ EFI_SIMPLE_POINTER_PROTOCOL SimplePointerProtocol;
+ EFI_SIMPLE_POINTER_STATE State;
+ EFI_SIMPLE_POINTER_MODE Mode;
+ BOOLEAN StateChanged;
+ PRIVATE_DATA PrivateData;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+} USB_MOUSE_DEV;
+
+#define USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL(a) \
+ CR(a, USB_MOUSE_DEV, SimplePointerProtocol, USB_MOUSE_DEV_SIGNATURE)
+
+VOID
+EFIAPI
+USBMouseRecoveryHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gUsbMouseDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gUsbMouseComponentName;
+extern EFI_GUID gEfiUsbMouseDriverGuid;
+
+VOID
+MouseReportStatusCode (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_STATUS_CODE_TYPE CodeType,
+ IN EFI_STATUS_CODE_VALUE Value
+ );
+
+#endif