summaryrefslogtreecommitdiff
path: root/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe
diff options
context:
space:
mode:
Diffstat (limited to 'Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe')
-rw-r--r--Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/ComponentName.c224
-rw-r--r--Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/MouseHid.c281
-rw-r--r--Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.c995
-rw-r--r--Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.h471
-rw-r--r--Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf72
-rw-r--r--Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.unibin0 -> 3736 bytes
-rw-r--r--Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxeExtra.unibin0 -> 1392 bytes
7 files changed, 2043 insertions, 0 deletions
diff --git a/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/ComponentName.c b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/ComponentName.c
new file mode 100644
index 0000000000..4b79a0f07e
--- /dev/null
+++ b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/ComponentName.c
@@ -0,0 +1,224 @@
+/** @file
+ UEFI Component Name(2) protocol implementation for USB Mouse Absolute Pointer Driver.
+
+Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "UsbMouseAbsolutePointer.h"
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gUsbMouseAbsolutePointerComponentName = {
+ UsbMouseAbsolutePointerComponentNameGetDriverName,
+ UsbMouseAbsolutePointerComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gUsbMouseAbsolutePointerComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) UsbMouseAbsolutePointerComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) UsbMouseAbsolutePointerComponentNameGetControllerName,
+ "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mUsbMouseAbsolutePointerDriverNameTable[] = {
+ { "eng;en", L"Usb Mouse Absolute Pointer Driver" },
+ { NULL , NULL }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name 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. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+ @param 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.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbMouseAbsolutePointerComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mUsbMouseAbsolutePointerDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gUsbMouseAbsolutePointerComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param 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.
+ @param 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.
+ @param Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name 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. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+ @param 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.
+
+ @retval 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.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbMouseAbsolutePointerComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointerDev;
+ EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointerProtocol;
+ 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,
+ gUsbMouseAbsolutePointerDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiUsbIoProtocolGuid,
+ gUsbMouseAbsolutePointerDriverBinding.DriverBindingHandle,
+ ControllerHandle
+ );
+
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Status != EFI_ALREADY_STARTED) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiAbsolutePointerProtocolGuid,
+ (VOID **) &AbsolutePointerProtocol,
+ gUsbMouseAbsolutePointerDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UsbMouseAbsolutePointerDev = USB_MOUSE_ABSOLUTE_POINTER_DEV_FROM_MOUSE_PROTOCOL (AbsolutePointerProtocol);
+
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ UsbMouseAbsolutePointerDev->ControllerNameTable,
+ ControllerName,
+ (BOOLEAN)(This == &gUsbMouseAbsolutePointerComponentName)
+ );
+
+}
diff --git a/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/MouseHid.c b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/MouseHid.c
new file mode 100644
index 0000000000..92ce18f425
--- /dev/null
+++ b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/MouseHid.c
@@ -0,0 +1,281 @@
+/** @file
+ Helper functions to parse HID report descriptor and items.
+
+Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UsbMouseAbsolutePointer.h"
+
+
+/**
+ Get next HID item from report descriptor.
+
+ This function retrieves next HID item from report descriptor, according to
+ the start position.
+ According to USB HID Specification, An item is piece of information
+ about the device. All items have a one-byte prefix that contains
+ the item tag, item type, and item size.
+ There are two basic types of items: short items and long items.
+ If the item is a short item, its optional data size may be 0, 1, 2, or 4 bytes.
+ Only short item is supported here.
+
+ @param StartPos Start position of the HID item to get.
+ @param EndPos End position of the range to get the the next HID item.
+ @param HidItem Buffer for the HID Item to return.
+
+ @return Pointer to end of the HID item returned.
+ NULL if no HID item retrieved.
+
+**/
+UINT8 *
+GetNextHidItem (
+ IN UINT8 *StartPos,
+ IN UINT8 *EndPos,
+ OUT HID_ITEM *HidItem
+ )
+{
+ UINT8 Temp;
+
+ if (EndPos <= StartPos) {
+ return NULL;
+ }
+
+ Temp = *StartPos;
+ StartPos++;
+
+ //
+ // Bit format of prefix byte:
+ // Bits 0-1: Size
+ // Bits 2-3: Type
+ // Bits 4-7: Tag
+ //
+ HidItem->Type = BitFieldRead8 (Temp, 2, 3);
+ HidItem->Tag = BitFieldRead8 (Temp, 4, 7);
+
+ if (HidItem->Tag == HID_ITEM_TAG_LONG) {
+ //
+ // Long Items are not supported, 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;
+ HidItem->Size = BitFieldRead8 (Temp, 0, 1);
+
+ switch (HidItem->Size) {
+ case 0:
+ //
+ // No data
+ //
+ return StartPos;
+
+ case 1:
+ //
+ // 1-byte data
+ //
+ if ((EndPos - StartPos) >= 1) {
+ HidItem->Data.Uint8 = *StartPos++;
+ return StartPos;
+ }
+
+ case 2:
+ //
+ // 2-byte data
+ //
+ if ((EndPos - StartPos) >= 2) {
+ CopyMem (&HidItem->Data.Uint16, StartPos, sizeof (UINT16));
+ StartPos += 2;
+ return StartPos;
+ }
+
+ case 3:
+ //
+ // 4-byte data, adjust size
+ //
+ HidItem->Size = 4;
+ if ((EndPos - StartPos) >= 4) {
+ CopyMem (&HidItem->Data.Uint32, StartPos, sizeof (UINT32));
+ StartPos += 4;
+ return StartPos;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ Get data from HID item.
+
+ This function retrieves data from HID item.
+ It only supports short items, which has 4 types of data:
+ 0, 1, 2, or 4 bytes.
+
+ @param HidItem Pointer to the HID item.
+
+ @return The data of HID item.
+
+**/
+UINT32
+GetItemData (
+ IN HID_ITEM *HidItem
+ )
+{
+ //
+ // Get data from HID item.
+ //
+ switch (HidItem->Size) {
+ case 1:
+ return HidItem->Data.Uint8;
+ case 2:
+ return HidItem->Data.Uint16;
+ case 4:
+ return HidItem->Data.Uint32;
+ }
+ return 0;
+}
+
+/**
+ Parse HID item from report descriptor.
+
+ There are three item types: Main, Global, and Local.
+ This function parses these types of HID items according
+ to tag info.
+
+ @param UsbMouse The instance of USB_MOUSE_ABSOLUTE_POINTER_DEV
+ @param HidItem The HID item to parse
+
+**/
+VOID
+ParseHidItem (
+ IN USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouse,
+ IN HID_ITEM *HidItem
+ )
+{
+ UINT8 Data;
+
+ switch (HidItem->Type) {
+
+ case HID_ITEM_TYPE_MAIN:
+ //
+ // we don't care any main items, just skip
+ //
+ return ;
+
+ case HID_ITEM_TYPE_GLOBAL:
+ //
+ // For global items, we only care Usage Page tag for Button Page here
+ //
+ if (HidItem->Tag == HID_GLOBAL_ITEM_TAG_USAGE_PAGE) {
+ Data = (UINT8) GetItemData (HidItem);
+ if (Data == 0x09) {
+ //
+ // Button Page
+ //
+ UsbMouse->PrivateData.ButtonDetected = TRUE;
+ }
+ }
+ return;
+
+ case HID_ITEM_TYPE_LOCAL:
+ if (HidItem->Size == 0) {
+ //
+ // No expected data for local item
+ //
+ return ;
+ }
+
+ Data = (UINT8) GetItemData (HidItem);
+
+ switch (HidItem->Tag) {
+ case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
+ if (UsbMouse->PrivateData.ButtonDetected) {
+ UsbMouse->PrivateData.ButtonMinIndex = Data;
+ }
+ return ;
+
+ case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
+ {
+ if (UsbMouse->PrivateData.ButtonDetected) {
+ UsbMouse->PrivateData.ButtonMaxIndex = Data;
+ }
+ return ;
+ }
+
+ default:
+ return ;
+ }
+ }
+}
+
+
+/**
+ Parse Mouse Report Descriptor.
+
+ According to USB HID Specification, report descriptors are
+ composed of pieces of information. Each piece of information
+ is called an Item. This function retrieves each item from
+ the report descriptor and updates USB_MOUSE_ABSOLUTE_POINTER_DEV.
+
+ @param UsbMouseAbsolutePointer The instance of USB_MOUSE_ABSOLUTE_POINTER_DEV
+ @param ReportDescriptor Report descriptor to parse
+ @param ReportSize Report descriptor size
+
+ @retval EFI_SUCCESS Report descriptor successfully parsed.
+ @retval EFI_UNSUPPORTED Report descriptor contains long item.
+
+**/
+EFI_STATUS
+ParseMouseReportDescriptor (
+ OUT USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointer,
+ IN UINT8 *ReportDescriptor,
+ IN UINTN ReportSize
+ )
+{
+ UINT8 *DescriptorEnd;
+ UINT8 *Ptr;
+ HID_ITEM HidItem;
+
+ DescriptorEnd = ReportDescriptor + ReportSize;
+
+ Ptr = GetNextHidItem (ReportDescriptor, DescriptorEnd, &HidItem);
+ while (Ptr != NULL) {
+ if (HidItem.Format != HID_ITEM_FORMAT_SHORT) {
+ //
+ // Long Item is not supported at current HID revision
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ ParseHidItem (UsbMouseAbsolutePointer, &HidItem);
+
+ Ptr = GetNextHidItem (Ptr, DescriptorEnd, &HidItem);
+ }
+
+ UsbMouseAbsolutePointer->NumberOfButtons = (UINT8) (UsbMouseAbsolutePointer->PrivateData.ButtonMaxIndex - UsbMouseAbsolutePointer->PrivateData.ButtonMinIndex + 1);
+ UsbMouseAbsolutePointer->XLogicMax = 1023;
+ UsbMouseAbsolutePointer->YLogicMax = 1023;
+ UsbMouseAbsolutePointer->XLogicMin = -1023;
+ UsbMouseAbsolutePointer->YLogicMin = -1023;
+
+ return EFI_SUCCESS;
+}
diff --git a/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.c b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.c
new file mode 100644
index 0000000000..42e696fcc9
--- /dev/null
+++ b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.c
@@ -0,0 +1,995 @@
+/** @file
+ USB Mouse Driver that manages USB mouse and produces Absolute Pointer Protocol.
+
+Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UsbMouseAbsolutePointer.h"
+
+EFI_DRIVER_BINDING_PROTOCOL gUsbMouseAbsolutePointerDriverBinding = {
+ USBMouseAbsolutePointerDriverBindingSupported,
+ USBMouseAbsolutePointerDriverBindingStart,
+ USBMouseAbsolutePointerDriverBindingStop,
+ 0x1,
+ NULL,
+ NULL
+};
+
+/**
+ Entrypoint of USB Mouse Absolute Pointer Driver.
+
+ This function is the entrypoint of USB Mouse Driver. It installs Driver Binding
+ Protocols together with Component Name Protocols.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+USBMouseAbsolutePointerDriverBindingEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gUsbMouseAbsolutePointerDriverBinding,
+ ImageHandle,
+ &gUsbMouseAbsolutePointerComponentName,
+ &gUsbMouseAbsolutePointerComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Check whether USB Mouse Absolute Pointer Driver supports this device.
+
+ @param This The driver binding protocol.
+ @param Controller The controller handle to check.
+ @param RemainingDevicePath The remaining device path.
+
+ @retval EFI_SUCCESS The driver supports this controller.
+ @retval other This device isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+USBMouseAbsolutePointerDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Use the USB I/O Protocol interface to check whether Controller is
+ // a mouse device 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;
+}
+
+
+/**
+ Starts the mouse device with this driver.
+
+ This function consumes USB I/O Portocol, intializes USB mouse device,
+ installs Absolute Pointer Protocol, and submits Asynchronous Interrupt
+ Transfer to manage the USB mouse device.
+
+ @param This The driver binding instance.
+ @param Controller Handle of device to bind driver to.
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
+ @retval EFI_ALREADY_STARTED This driver has been started.
+
+**/
+EFI_STATUS
+EFIAPI
+USBMouseAbsolutePointerDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointerDevice;
+ UINT8 EndpointNumber;
+ EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
+ UINT8 Index;
+ UINT8 EndpointAddr;
+ UINT8 PollingInterval;
+ UINT8 PacketSize;
+ BOOLEAN Found;
+ EFI_TPL OldTpl;
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+ //
+ // Open USB I/O Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ (VOID **) &UsbIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit1;
+ }
+
+ UsbMouseAbsolutePointerDevice = AllocateZeroPool (sizeof (USB_MOUSE_ABSOLUTE_POINTER_DEV));
+ ASSERT (UsbMouseAbsolutePointerDevice != NULL);
+
+ UsbMouseAbsolutePointerDevice->UsbIo = UsbIo;
+ UsbMouseAbsolutePointerDevice->Signature = USB_MOUSE_ABSOLUTE_POINTER_DEV_SIGNATURE;
+
+ //
+ // Get the Device Path Protocol on Controller's handle
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &UsbMouseAbsolutePointerDevice->DevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ //
+ // Report Status Code here since USB mouse will be detected next.
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT),
+ UsbMouseAbsolutePointerDevice->DevicePath
+ );
+
+ //
+ // Get interface & endpoint descriptor
+ //
+ UsbIo->UsbGetInterfaceDescriptor (
+ UsbIo,
+ &UsbMouseAbsolutePointerDevice->InterfaceDescriptor
+ );
+
+ EndpointNumber = UsbMouseAbsolutePointerDevice->InterfaceDescriptor.NumEndpoints;
+
+ //
+ // Traverse endpoints to find interrupt endpoint
+ //
+ Found = FALSE;
+ for (Index = 0; Index < EndpointNumber; Index++) {
+ UsbIo->UsbGetEndpointDescriptor (
+ UsbIo,
+ Index,
+ &EndpointDescriptor
+ );
+
+ if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) {
+ //
+ // We only care interrupt endpoint here
+ //
+ CopyMem (&UsbMouseAbsolutePointerDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));
+ Found = TRUE;
+ break;
+ }
+ }
+
+ if (!Found) {
+ //
+ // Report Status Code to indicate that there is no USB mouse
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED)
+ );
+ //
+ // No interrupt endpoint found, then return unsupported.
+ //
+ Status = EFI_UNSUPPORTED;
+ goto ErrorExit;
+ }
+
+ //
+ // Report Status Code here since USB mouse has be detected.
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED),
+ UsbMouseAbsolutePointerDevice->DevicePath
+ );
+
+ Status = InitializeUsbMouseDevice (UsbMouseAbsolutePointerDevice);
+ if (EFI_ERROR (Status)) {
+ //
+ // Fail to initialize USB mouse device.
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_PERIPHERAL_MOUSE | EFI_P_EC_INTERFACE_ERROR),
+ UsbMouseAbsolutePointerDevice->DevicePath
+ );
+
+ goto ErrorExit;
+ }
+
+ //
+ // Initialize and install EFI Absolute Pointer Protocol.
+ //
+ UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol.GetState = GetMouseAbsolutePointerState;
+ UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol.Reset = UsbMouseAbsolutePointerReset;
+ UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol.Mode = &UsbMouseAbsolutePointerDevice->Mode;
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_WAIT,
+ TPL_NOTIFY,
+ UsbMouseAbsolutePointerWaitForInput,
+ UsbMouseAbsolutePointerDevice,
+ &((UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol).WaitForInput)
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiAbsolutePointerProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ //
+ // The next step would be submitting Asynchronous Interrupt Transfer on this mouse device.
+ // After that we will be able to get key data from it. Thus this is deemed as
+ // the enable action of the mouse, so report status code accordingly.
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE),
+ UsbMouseAbsolutePointerDevice->DevicePath
+ );
+
+ //
+ // Submit Asynchronous Interrupt Transfer to manage this device.
+ //
+ EndpointAddr = UsbMouseAbsolutePointerDevice->IntEndpointDescriptor.EndpointAddress;
+ PollingInterval = UsbMouseAbsolutePointerDevice->IntEndpointDescriptor.Interval;
+ PacketSize = (UINT8) (UsbMouseAbsolutePointerDevice->IntEndpointDescriptor.MaxPacketSize);
+
+ Status = UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ EndpointAddr,
+ TRUE,
+ PollingInterval,
+ PacketSize,
+ OnMouseInterruptComplete,
+ UsbMouseAbsolutePointerDevice
+ );
+
+ if (EFI_ERROR (Status)) {
+ //
+ // If submit error, uninstall that interface
+ //
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiAbsolutePointerProtocolGuid,
+ &UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol
+ );
+ goto ErrorExit;
+ }
+
+ UsbMouseAbsolutePointerDevice->ControllerNameTable = NULL;
+ AddUnicodeString2 (
+ "eng",
+ gUsbMouseAbsolutePointerComponentName.SupportedLanguages,
+ &UsbMouseAbsolutePointerDevice->ControllerNameTable,
+ L"Generic Usb Mouse Absolute Pointer",
+ TRUE
+ );
+ AddUnicodeString2 (
+ "en",
+ gUsbMouseAbsolutePointerComponentName2.SupportedLanguages,
+ &UsbMouseAbsolutePointerDevice->ControllerNameTable,
+ L"Generic Usb Mouse Absolute Pointer",
+ FALSE
+ );
+
+ gBS->RestoreTPL (OldTpl);
+ return EFI_SUCCESS;
+
+//
+// Error handler
+//
+ErrorExit:
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ if (UsbMouseAbsolutePointerDevice != NULL) {
+ if ((UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol).WaitForInput != NULL) {
+ gBS->CloseEvent ((UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol).WaitForInput);
+ }
+
+ FreePool (UsbMouseAbsolutePointerDevice);
+ UsbMouseAbsolutePointerDevice = NULL;
+ }
+ }
+
+ErrorExit1:
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+
+/**
+ Stop the USB mouse device handled by this driver.
+
+ @param This The driver binding protocol.
+ @param Controller The controller to release.
+ @param NumberOfChildren The number of handles in ChildHandleBuffer.
+ @param ChildHandleBuffer The array of child handle.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_UNSUPPORTED Absolute Pointer Protocol is not installed on Controller.
+ @retval Others Fail to uninstall protocols attached on the device.
+
+**/
+EFI_STATUS
+EFIAPI
+USBMouseAbsolutePointerDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointerDevice;
+ EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointerProtocol;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiAbsolutePointerProtocolGuid,
+ (VOID **) &AbsolutePointerProtocol,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ UsbMouseAbsolutePointerDevice = USB_MOUSE_ABSOLUTE_POINTER_DEV_FROM_MOUSE_PROTOCOL (AbsolutePointerProtocol);
+
+ UsbIo = UsbMouseAbsolutePointerDevice->UsbIo;
+
+ //
+ // The key data input from this device will be disabled.
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE),
+ UsbMouseAbsolutePointerDevice->DevicePath
+ );
+
+ //
+ // Delete the Asynchronous Interrupt Transfer from this device
+ //
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ UsbMouseAbsolutePointerDevice->IntEndpointDescriptor.EndpointAddress,
+ FALSE,
+ UsbMouseAbsolutePointerDevice->IntEndpointDescriptor.Interval,
+ 0,
+ NULL,
+ NULL
+ );
+
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiAbsolutePointerProtocolGuid,
+ &UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsbIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Free all resources.
+ //
+ gBS->CloseEvent (UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol.WaitForInput);
+
+ if (UsbMouseAbsolutePointerDevice->DelayedRecoveryEvent != NULL) {
+ gBS->CloseEvent (UsbMouseAbsolutePointerDevice->DelayedRecoveryEvent);
+ UsbMouseAbsolutePointerDevice->DelayedRecoveryEvent = NULL;
+ }
+
+ if (UsbMouseAbsolutePointerDevice->ControllerNameTable != NULL) {
+ FreeUnicodeStringTable (UsbMouseAbsolutePointerDevice->ControllerNameTable);
+ }
+
+ FreePool (UsbMouseAbsolutePointerDevice);
+
+ return EFI_SUCCESS;
+
+}
+
+
+/**
+ Uses USB I/O to check whether the device is a USB mouse device.
+
+ @param UsbIo Pointer to a USB I/O protocol instance.
+
+ @retval TRUE Device is a USB mouse device.
+ @retval FALSE Device is a not USB mouse device.
+
+**/
+BOOLEAN
+IsUsbMouse (
+ IN EFI_USB_IO_PROTOCOL *UsbIo
+ )
+{
+ EFI_STATUS Status;
+ EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
+
+ //
+ // Get the default interface descriptor
+ //
+ 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;
+}
+
+
+/**
+ Initialize the USB mouse device.
+
+ This function retrieves and parses HID report descriptor, and
+ initializes state of USB_MOUSE_ABSOLUTE_POINTER_DEV. Then it sets indefinite idle
+ rate for the device. Finally it creates event for delayed recovery,
+ which deals with device error.
+
+ @param UsbMouseAbsolutePointerDev Device instance to be initialized.
+
+ @retval EFI_SUCCESS USB mouse device successfully initialized.
+ @retval EFI_UNSUPPORTED HID descriptor type is not report descriptor.
+ @retval Other USB mouse device was not initialized successfully.
+
+**/
+EFI_STATUS
+InitializeUsbMouseDevice (
+ IN USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointerDev
+ )
+{
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 Protocol;
+ EFI_STATUS Status;
+ EFI_USB_HID_DESCRIPTOR *MouseHidDesc;
+ UINT8 *ReportDesc;
+ EFI_USB_CONFIG_DESCRIPTOR ConfigDesc;
+ VOID *Buf;
+ UINT32 TransferResult;
+ UINT16 Total;
+ USB_DESC_HEAD *Head;
+ BOOLEAN Start;
+
+ UsbIo = UsbMouseAbsolutePointerDev->UsbIo;
+
+ //
+ // Get the current configuration descriptor. Note that it doesn't include other descriptors.
+ //
+ Status = UsbIo->UsbGetConfigDescriptor (
+ UsbIo,
+ &ConfigDesc
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // By issuing Get_Descriptor(Configuration) request with total length, we get the Configuration descriptor,
+ // all Interface descriptors, all Endpoint descriptors, and the HID descriptor for each interface.
+ //
+ Buf = AllocateZeroPool (ConfigDesc.TotalLength);
+ if (Buf == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = UsbGetDescriptor (
+ UsbIo,
+ (UINT16)((USB_DESC_TYPE_CONFIG << 8) | (ConfigDesc.ConfigurationValue - 1)),
+ 0,
+ ConfigDesc.TotalLength,
+ Buf,
+ &TransferResult
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Buf);
+ return Status;
+ }
+
+ Total = 0;
+ Start = FALSE;
+ Head = (USB_DESC_HEAD *)Buf;
+ MouseHidDesc = NULL;
+
+ //
+ // Get HID descriptor from the receipt of Get_Descriptor(Configuration) request.
+ // This algorithm is based on the fact that the HID descriptor shall be interleaved
+ // between the interface and endpoint descriptors for HID interfaces.
+ //
+ while (Total < ConfigDesc.TotalLength) {
+ if (Head->Type == USB_DESC_TYPE_INTERFACE) {
+ if ((((USB_INTERFACE_DESCRIPTOR *)Head)->InterfaceNumber == UsbMouseAbsolutePointerDev->InterfaceDescriptor.InterfaceNumber) &&
+ (((USB_INTERFACE_DESCRIPTOR *)Head)->AlternateSetting == UsbMouseAbsolutePointerDev->InterfaceDescriptor.AlternateSetting)) {
+ Start = TRUE;
+ }
+ }
+ if (Start && (Head->Type == USB_DESC_TYPE_ENDPOINT)) {
+ break;
+ }
+ if (Start && (Head->Type == USB_DESC_TYPE_HID)) {
+ MouseHidDesc = (EFI_USB_HID_DESCRIPTOR *)Head;
+ break;
+ }
+ Total = Total + (UINT16)Head->Len;
+ Head = (USB_DESC_HEAD*)((UINT8 *)Buf + Total);
+ }
+
+ if (MouseHidDesc == NULL) {
+ FreePool (Buf);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get report descriptor
+ //
+ if (MouseHidDesc->HidClassDesc[0].DescriptorType != USB_DESC_TYPE_REPORT) {
+ FreePool (Buf);
+ return EFI_UNSUPPORTED;
+ }
+
+ ReportDesc = AllocateZeroPool (MouseHidDesc->HidClassDesc[0].DescriptorLength);
+ ASSERT (ReportDesc != NULL);
+
+ Status = UsbGetReportDescriptor (
+ UsbIo,
+ UsbMouseAbsolutePointerDev->InterfaceDescriptor.InterfaceNumber,
+ MouseHidDesc->HidClassDesc[0].DescriptorLength,
+ ReportDesc
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Buf);
+ FreePool (ReportDesc);
+ return Status;
+ }
+
+ //
+ // Parse report descriptor
+ //
+ Status = ParseMouseReportDescriptor (
+ UsbMouseAbsolutePointerDev,
+ ReportDesc,
+ MouseHidDesc->HidClassDesc[0].DescriptorLength
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Buf);
+ FreePool (ReportDesc);
+ return Status;
+ }
+
+ UsbMouseAbsolutePointerDev->Mode.AbsoluteMaxX = 1024;
+ UsbMouseAbsolutePointerDev->Mode.AbsoluteMaxY = 1024;
+ UsbMouseAbsolutePointerDev->Mode.AbsoluteMaxZ = 0;
+ UsbMouseAbsolutePointerDev->Mode.AbsoluteMinX = 0;
+ UsbMouseAbsolutePointerDev->Mode.AbsoluteMinY = 0;
+ UsbMouseAbsolutePointerDev->Mode.AbsoluteMinZ = 0;
+ UsbMouseAbsolutePointerDev->Mode.Attributes = 0x3;
+
+ //
+ // Set boot protocol for the USB mouse.
+ // This driver only supports boot protocol.
+ //
+ UsbGetProtocolRequest (
+ UsbIo,
+ UsbMouseAbsolutePointerDev->InterfaceDescriptor.InterfaceNumber,
+ &Protocol
+ );
+ if (Protocol != BOOT_PROTOCOL) {
+ Status = UsbSetProtocolRequest (
+ UsbIo,
+ UsbMouseAbsolutePointerDev->InterfaceDescriptor.InterfaceNumber,
+ BOOT_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Buf);
+ FreePool (ReportDesc);
+ return Status;
+ }
+ }
+
+ FreePool (Buf);
+ FreePool (ReportDesc);
+
+ //
+ // Create event for delayed recovery, which deals with device error.
+ //
+ if (UsbMouseAbsolutePointerDev->DelayedRecoveryEvent != NULL) {
+ gBS->CloseEvent (UsbMouseAbsolutePointerDev->DelayedRecoveryEvent);
+ UsbMouseAbsolutePointerDev->DelayedRecoveryEvent = 0;
+ }
+
+ gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ USBMouseRecoveryHandler,
+ UsbMouseAbsolutePointerDev,
+ &UsbMouseAbsolutePointerDev->DelayedRecoveryEvent
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Handler function for USB mouse's asynchronous interrupt transfer.
+
+ This function is the handler function for USB mouse's asynchronous interrupt transfer
+ to manage the mouse. It parses data returned from asynchronous interrupt transfer, and
+ get button and movement state.
+
+ @param Data A pointer to a buffer that is filled with key data which is
+ retrieved via asynchronous interrupt transfer.
+ @param DataLength Indicates the size of the data buffer.
+ @param Context Pointing to USB_KB_DEV instance.
+ @param Result Indicates the result of the asynchronous interrupt transfer.
+
+ @retval EFI_SUCCESS Asynchronous interrupt transfer is handled successfully.
+ @retval EFI_DEVICE_ERROR Hardware error occurs.
+
+**/
+EFI_STATUS
+EFIAPI
+OnMouseInterruptComplete (
+ IN VOID *Data,
+ IN UINTN DataLength,
+ IN VOID *Context,
+ IN UINT32 Result
+ )
+{
+ USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointerDevice;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ UINT8 EndpointAddr;
+ UINT32 UsbResult;
+
+ UsbMouseAbsolutePointerDevice = (USB_MOUSE_ABSOLUTE_POINTER_DEV *) Context;
+ UsbIo = UsbMouseAbsolutePointerDevice->UsbIo;
+
+ if (Result != EFI_USB_NOERROR) {
+ //
+ // Some errors happen during the process
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_PERIPHERAL_MOUSE | EFI_P_EC_INPUT_ERROR),
+ UsbMouseAbsolutePointerDevice->DevicePath
+ );
+
+ if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) {
+ EndpointAddr = UsbMouseAbsolutePointerDevice->IntEndpointDescriptor.EndpointAddress;
+
+ UsbClearEndpointHalt (
+ UsbIo,
+ EndpointAddr,
+ &UsbResult
+ );
+ }
+
+ //
+ // Delete & Submit this interrupt again
+ // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt.
+ //
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ UsbMouseAbsolutePointerDevice->IntEndpointDescriptor.EndpointAddress,
+ FALSE,
+ 0,
+ 0,
+ NULL,
+ NULL
+ );
+ //
+ // EFI_USB_INTERRUPT_DELAY is defined in USB standard for error handling.
+ //
+ gBS->SetTimer (
+ UsbMouseAbsolutePointerDevice->DelayedRecoveryEvent,
+ TimerRelative,
+ EFI_USB_INTERRUPT_DELAY
+ );
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // If no error and no data, just return EFI_SUCCESS.
+ //
+ if (DataLength == 0 || Data == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ UsbMouseAbsolutePointerDevice->StateChanged = TRUE;
+
+ //
+ // Check mouse Data
+ // USB HID Specification specifies following data format:
+ // Byte Bits Description
+ // 0 0 Button 1
+ // 1 Button 2
+ // 2 Button 3
+ // 4 to 7 Device-specific
+ // 1 0 to 7 X displacement
+ // 2 0 to 7 Y displacement
+ // 3 to n 0 to 7 Device specific (optional)
+ //
+ UsbMouseAbsolutePointerDevice->State.CurrentX += *((INT8 *) Data + 1);
+ UsbMouseAbsolutePointerDevice->State.CurrentY += *((INT8 *) Data + 2);
+
+ if (DataLength > 3) {
+ UsbMouseAbsolutePointerDevice->State.CurrentZ += *((INT8 *) Data + 3);
+ }
+ UsbMouseAbsolutePointerDevice->State.ActiveButtons = *(UINT8 *) Data & (BIT0 | BIT1);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Retrieves the current state of a pointer device.
+
+ @param This A pointer to the EFI_ABSOLUTE_POINTER_PROTOCOL instance.
+ @param MouseState A pointer to the state information on the pointer device.
+
+ @retval EFI_SUCCESS The state of the pointer device was returned in State.
+ @retval EFI_NOT_READY The state of the pointer device has not changed since the last call to
+ GetState().
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to retrieve the pointer device's
+ current state.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+GetMouseAbsolutePointerState (
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
+ OUT EFI_ABSOLUTE_POINTER_STATE *State
+ )
+{
+ USB_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev;
+
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ MouseAbsolutePointerDev = USB_MOUSE_ABSOLUTE_POINTER_DEV_FROM_MOUSE_PROTOCOL (This);
+
+ if (!MouseAbsolutePointerDev->StateChanged) {
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Retrieve mouse state from USB_MOUSE_ABSOLUTE_POINTER_DEV,
+ // which was filled by OnMouseInterruptComplete()
+ //
+ CopyMem (
+ State,
+ &MouseAbsolutePointerDev->State,
+ sizeof (EFI_ABSOLUTE_POINTER_STATE)
+ );
+
+ //
+ // Clear previous move state
+ //
+ MouseAbsolutePointerDev->State.CurrentX = 0;
+ MouseAbsolutePointerDev->State.CurrentY = 0;
+ MouseAbsolutePointerDev->State.CurrentZ = 0;
+ MouseAbsolutePointerDev->State.ActiveButtons = 0;
+
+ MouseAbsolutePointerDev->StateChanged = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Resets the pointer device hardware.
+
+ @param This A pointer to the EFI_ABSOLUTE_POINTER_PROTOCOL instance.
+ @param ExtendedVerification Indicates that the driver may perform a more exhaustive
+ verification operation of the device during reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbMouseAbsolutePointerReset (
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointerDevice;
+
+ UsbMouseAbsolutePointerDevice = USB_MOUSE_ABSOLUTE_POINTER_DEV_FROM_MOUSE_PROTOCOL (This);
+
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET),
+ UsbMouseAbsolutePointerDevice->DevicePath
+ );
+
+ //
+ // Clear mouse state.
+ //
+ ZeroMem (
+ &UsbMouseAbsolutePointerDevice->State,
+ sizeof (EFI_ABSOLUTE_POINTER_STATE)
+ );
+ UsbMouseAbsolutePointerDevice->StateChanged = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Event notification function for EFI_ABSOLUTE_POINTER_PROTOCOL.WaitForInput event.
+
+ @param Event Event to be signaled when there's input from mouse.
+ @param Context Points to USB_MOUSE_ABSOLUTE_POINTER_DEV instance.
+
+**/
+VOID
+EFIAPI
+UsbMouseAbsolutePointerWaitForInput (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointerDev;
+
+ UsbMouseAbsolutePointerDev = (USB_MOUSE_ABSOLUTE_POINTER_DEV *) Context;
+
+ //
+ // If there's input from mouse, signal the event.
+ //
+ if (UsbMouseAbsolutePointerDev->StateChanged) {
+ gBS->SignalEvent (Event);
+ }
+}
+
+/**
+ Handler for Delayed Recovery event.
+
+ This function is the handler for Delayed Recovery event triggered
+ by timer.
+ After a device error occurs, the event would be triggered
+ with interval of EFI_USB_INTERRUPT_DELAY. EFI_USB_INTERRUPT_DELAY
+ is defined in USB standard for error handling.
+
+ @param Event The Delayed Recovery event.
+ @param Context Points to the USB_MOUSE_ABSOLUTE_POINTER_DEV instance.
+
+**/
+VOID
+EFIAPI
+USBMouseRecoveryHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointerDev;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+
+ UsbMouseAbsolutePointerDev = (USB_MOUSE_ABSOLUTE_POINTER_DEV *) Context;
+
+ UsbIo = UsbMouseAbsolutePointerDev->UsbIo;
+
+ //
+ // Re-submit Asynchronous Interrupt Transfer for recovery.
+ //
+ UsbIo->UsbAsyncInterruptTransfer (
+ UsbIo,
+ UsbMouseAbsolutePointerDev->IntEndpointDescriptor.EndpointAddress,
+ TRUE,
+ UsbMouseAbsolutePointerDev->IntEndpointDescriptor.Interval,
+ UsbMouseAbsolutePointerDev->IntEndpointDescriptor.MaxPacketSize,
+ OnMouseInterruptComplete,
+ UsbMouseAbsolutePointerDev
+ );
+}
diff --git a/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.h b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.h
new file mode 100644
index 0000000000..08b8d56dd8
--- /dev/null
+++ b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.h
@@ -0,0 +1,471 @@
+/** @file
+ Helper routine and corresponding data struct used by USB Mouse Absolute Pointer Driver.
+
+Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _USB_MOUSE_ABSOLUTE_POINTER_H_
+#define _USB_MOUSE_ABSOLUTE_POINTER_H_
+
+
+#include <Uefi.h>
+
+#include <Protocol/AbsolutePointer.h>
+#include <Protocol/UsbIo.h>
+#include <Protocol/DevicePath.h>
+
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiUsbLib.h>
+#include <Library/DebugLib.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_ABSOLUTE_POINTER_DEV_SIGNATURE SIGNATURE_32 ('u', 'm', 's', 't')
+
+//
+// A common header for usb standard descriptor.
+// Each stand descriptor has a length and type.
+//
+#pragma pack(1)
+typedef struct {
+ UINT8 Len;
+ UINT8 Type;
+} USB_DESC_HEAD;
+#pragma pack()
+
+///
+/// Button range and status
+///
+typedef struct {
+ BOOLEAN ButtonDetected;
+ UINT8 ButtonMinIndex;
+ UINT8 ButtonMaxIndex;
+ UINT8 Reserved;
+} USB_MOUSE_BUTTON_DATA;
+
+///
+/// Device instance of USB mouse.
+///
+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_ABSOLUTE_POINTER_PROTOCOL AbsolutePointerProtocol;
+ EFI_ABSOLUTE_POINTER_STATE State;
+ EFI_ABSOLUTE_POINTER_MODE Mode;
+ BOOLEAN StateChanged;
+ USB_MOUSE_BUTTON_DATA PrivateData;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+} USB_MOUSE_ABSOLUTE_POINTER_DEV;
+
+///
+/// General HID Item structure
+///
+
+typedef union {
+ UINT8 Uint8;
+ UINT16 Uint16;
+ UINT32 Uint32;
+ INT8 Int8;
+ INT16 Int16;
+ INT32 Int32;
+ UINT8 *LongData;
+} HID_DATA;
+
+typedef struct {
+ UINT16 Format;
+ UINT8 Size;
+ UINT8 Type;
+ UINT8 Tag;
+ HID_DATA Data;
+} HID_ITEM;
+
+#define USB_MOUSE_ABSOLUTE_POINTER_DEV_FROM_MOUSE_PROTOCOL(a) \
+ CR(a, USB_MOUSE_ABSOLUTE_POINTER_DEV, AbsolutePointerProtocol, USB_MOUSE_ABSOLUTE_POINTER_DEV_SIGNATURE)
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gUsbMouseAbsolutePointerDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gUsbMouseAbsolutePointerComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gUsbMouseAbsolutePointerComponentName2;
+
+//
+// Functions of Driver Binding Protocol
+//
+
+/**
+ Check whether USB Mouse Absolute Pointer Driver supports this device.
+
+ @param This The driver binding protocol.
+ @param Controller The controller handle to check.
+ @param RemainingDevicePath The remaining device path.
+
+ @retval EFI_SUCCESS The driver supports this controller.
+ @retval other This device isn't supported.
+
+**/
+EFI_STATUS
+EFIAPI
+USBMouseAbsolutePointerDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Starts the mouse device with this driver.
+
+ This function consumes USB I/O Portocol, intializes USB mouse device,
+ installs Absolute Pointer Protocol, and submits Asynchronous Interrupt
+ Transfer to manage the USB mouse device.
+
+ @param This The driver binding instance.
+ @param Controller Handle of device to bind driver to.
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS This driver supports this device.
+ @retval EFI_UNSUPPORTED This driver does not support this device.
+ @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
+ @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
+ @retval EFI_ALREADY_STARTED This driver has been started.
+
+**/
+EFI_STATUS
+EFIAPI
+USBMouseAbsolutePointerDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+/**
+ Stop the USB mouse device handled by this driver.
+
+ @param This The driver binding protocol.
+ @param Controller The controller to release.
+ @param NumberOfChildren The number of handles in ChildHandleBuffer.
+ @param ChildHandleBuffer The array of child handle.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_UNSUPPORTED Absolute Pointer Protocol is not installed on Controller.
+ @retval Others Fail to uninstall protocols attached on the device.
+
+**/
+EFI_STATUS
+EFIAPI
+USBMouseAbsolutePointerDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// EFI Component Name Functions
+//
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name 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. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+ @param 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.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbMouseAbsolutePointerComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param 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.
+ @param 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.
+ @param Language A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name 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. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+ @param 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.
+
+ @retval 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.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbMouseAbsolutePointerComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// Functions of EFI_ABSOLUTE_POINTER_PROTOCOL
+//
+
+/**
+ Retrieves the current state of a pointer device.
+
+ @param This A pointer to the EFI_ABSOLUTE_POINTER_PROTOCOL instance.
+ @param MouseState A pointer to the state information on the pointer device.
+
+ @retval EFI_SUCCESS The state of the pointer device was returned in State.
+ @retval EFI_NOT_READY The state of the pointer device has not changed since the last call to
+ GetState().
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to retrieve the pointer device's
+ current state.
+ @retval EFI_INVALID_PARAMETER State is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+GetMouseAbsolutePointerState (
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
+ OUT EFI_ABSOLUTE_POINTER_STATE *State
+ );
+
+/**
+ Resets the pointer device hardware.
+
+ @param This A pointer to the EFI_ABSOLUTE_POINTER_PROTOCOL instance.
+ @param ExtendedVerification Indicates that the driver may perform a more exhaustive
+ verification operation of the device during reset.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbMouseAbsolutePointerReset (
+ IN EFI_ABSOLUTE_POINTER_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Event notification function for EFI_ABSOLUTE_POINTER_PROTOCOL.WaitForInput event.
+
+ @param Event Event to be signaled when there's input from mouse.
+ @param Context Points to USB_MOUSE_ABSOLUTE_POINTER_DEV instance.
+
+**/
+VOID
+EFIAPI
+UsbMouseAbsolutePointerWaitForInput (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+//
+// Internal worker functions
+//
+
+/**
+ Uses USB I/O to check whether the device is a USB mouse device.
+
+ @param UsbIo Pointer to a USB I/O protocol instance.
+
+ @retval TRUE Device is a USB mouse device.
+ @retval FALSE Device is a not USB mouse device.
+
+**/
+BOOLEAN
+IsUsbMouse (
+ IN EFI_USB_IO_PROTOCOL *UsbIo
+ );
+
+/**
+ Initialize the USB mouse device.
+
+ This function retrieves and parses HID report descriptor, and
+ initializes state of USB_MOUSE_ABSOLUTE_POINTER_DEV. Then it sets indefinite idle
+ rate for the device. Finally it creates event for delayed recovery,
+ which deals with device error.
+
+ @param UsbMouseAbsolutePointerDev Device instance to be initialized.
+
+ @retval EFI_SUCCESS USB mouse device successfully initialized.
+ @retval EFI_UNSUPPORTED HID descriptor type is not report descriptor.
+ @retval Other USB mouse device was not initialized successfully.
+
+**/
+EFI_STATUS
+InitializeUsbMouseDevice (
+ IN USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointerDev
+ );
+
+/**
+ Handler function for USB mouse's asynchronous interrupt transfer.
+
+ This function is the handler function for USB mouse's asynchronous interrupt transfer
+ to manage the mouse. It parses data returned from asynchronous interrupt transfer, and
+ get button and movement state.
+
+ @param Data A pointer to a buffer that is filled with key data which is
+ retrieved via asynchronous interrupt transfer.
+ @param DataLength Indicates the size of the data buffer.
+ @param Context Pointing to USB_KB_DEV instance.
+ @param Result Indicates the result of the asynchronous interrupt transfer.
+
+ @retval EFI_SUCCESS Asynchronous interrupt transfer is handled successfully.
+ @retval EFI_DEVICE_ERROR Hardware error occurs.
+
+**/
+EFI_STATUS
+EFIAPI
+OnMouseInterruptComplete (
+ IN VOID *Data,
+ IN UINTN DataLength,
+ IN VOID *Context,
+ IN UINT32 Result
+ );
+
+/**
+ Handler for Delayed Recovery event.
+
+ This function is the handler for Delayed Recovery event triggered
+ by timer.
+ After a device error occurs, the event would be triggered
+ with interval of EFI_USB_INTERRUPT_DELAY. EFI_USB_INTERRUPT_DELAY
+ is defined in USB standard for error handling.
+
+ @param Event The Delayed Recovery event.
+ @param Context Points to the USB_MOUSE_ABSOLUTE_POINTER_DEV instance.
+
+**/
+VOID
+EFIAPI
+USBMouseRecoveryHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Parse Mouse Report Descriptor.
+
+ According to USB HID Specification, report descriptors are
+ composed of pieces of information. Each piece of information
+ is called an Item. This function retrieves each item from
+ the report descriptor and updates USB_MOUSE_ABSOLUTE_POINTER_DEV.
+
+ @param UsbMouseAbsolutePointer The instance of USB_MOUSE_ABSOLUTE_POINTER_DEV
+ @param ReportDescriptor Report descriptor to parse
+ @param ReportSize Report descriptor size
+
+ @retval EFI_SUCCESS Report descriptor successfully parsed.
+ @retval EFI_UNSUPPORTED Report descriptor contains long item.
+
+**/
+EFI_STATUS
+ParseMouseReportDescriptor (
+ OUT USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointer,
+ IN UINT8 *ReportDescriptor,
+ IN UINTN ReportSize
+ );
+
+#endif
diff --git a/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf
new file mode 100644
index 0000000000..af10382d52
--- /dev/null
+++ b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.inf
@@ -0,0 +1,72 @@
+## @file
+# USB Mouse Driver that manages USB mouse and produces Absolute Pointer Protocol.
+#
+# USB Mouse Driver consumes USB I/O Protocol and Device Path Protocol, and produces
+# Absolute Pointer Protocol on USB mouse devices.
+# It manages the USB mouse device via Asynchronous Interrupt Transfer of USB I/O Protocol,
+# and parses the data according to USB HID Specification.
+# This module refers to following specifications:
+# 1. Universal Serial Bus HID Firmware Specification, ver 1.11
+# 2. UEFI Specification, v2.1
+#
+# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UsbMouseAbsolutePointerDxe
+ MODULE_UNI_FILE = UsbMouseAbsolutePointerDxe.uni
+ FILE_GUID = 4EA43463-747C-46eb-97FB-B0E5C5F05306
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = USBMouseAbsolutePointerDriverBindingEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gUsbMouseAbsolutePointerDriverBinding
+# COMPONENT_NAME = gUsbMouseAbsolutePointerComponentName
+# COMPONENT_NAME2 = gUsbMouseAbsolutePointerComponentName2
+#
+
+[Sources]
+ ComponentName.c
+ MouseHid.c
+ UsbMouseAbsolutePointer.c
+ UsbMouseAbsolutePointer.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ BaseMemoryLib
+ ReportStatusCodeLib
+ UefiUsbLib
+
+[Protocols]
+ gEfiUsbIoProtocolGuid ## TO_START
+ gEfiDevicePathProtocolGuid ## TO_START
+ gEfiAbsolutePointerProtocolGuid ## BY_START
+
+# [Event]
+# EVENT_TYPE_RELATIVE_TIMER ## CONSUMES
+#
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ UsbMouseAbsolutePointerDxeExtra.uni
diff --git a/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.uni b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.uni
new file mode 100644
index 0000000000..628d6933c0
--- /dev/null
+++ b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxe.uni
Binary files differ
diff --git a/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxeExtra.uni b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxeExtra.uni
new file mode 100644
index 0000000000..763dcaed03
--- /dev/null
+++ b/Core/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointerDxeExtra.uni
Binary files differ