]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbMouseAbsolutePointerDxe / UsbMouseAbsolutePointer.c
index 2f3cf9aae213467ad434db316be18cc69d7cec40..ad5f066ec9ba51c0fda65ca09cdda43ef404eb1c 100644 (file)
@@ -1,20 +1,14 @@
 /** @file\r
   USB Mouse Driver that manages USB mouse and produces Absolute Pointer Protocol.\r
 \r
-Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "UsbMouseAbsolutePointer.h"\r
 \r
-EFI_DRIVER_BINDING_PROTOCOL gUsbMouseAbsolutePointerDriverBinding = {\r
+EFI_DRIVER_BINDING_PROTOCOL  gUsbMouseAbsolutePointerDriverBinding = {\r
   USBMouseAbsolutePointerDriverBindingSupported,\r
   USBMouseAbsolutePointerDriverBindingStart,\r
   USBMouseAbsolutePointerDriverBindingStop,\r
@@ -38,11 +32,11 @@ EFI_DRIVER_BINDING_PROTOCOL gUsbMouseAbsolutePointerDriverBinding = {
 EFI_STATUS\r
 EFIAPI\r
 USBMouseAbsolutePointerDriverBindingEntryPoint (\r
-  IN EFI_HANDLE           ImageHandle,\r
-  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
   )\r
 {\r
-  EFI_STATUS              Status;\r
+  EFI_STATUS  Status;\r
 \r
   Status = EfiLibInstallDriverBindingComponentName2 (\r
              ImageHandle,\r
@@ -57,7 +51,6 @@ USBMouseAbsolutePointerDriverBindingEntryPoint (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Check whether USB Mouse Absolute Pointer Driver supports this device.\r
 \r
@@ -72,18 +65,18 @@ USBMouseAbsolutePointerDriverBindingEntryPoint (
 EFI_STATUS\r
 EFIAPI\r
 USBMouseAbsolutePointerDriverBindingSupported (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
-  IN EFI_HANDLE                     Controller,\r
-  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
   )\r
 {\r
-  EFI_STATUS          Status;\r
-  EFI_USB_IO_PROTOCOL *UsbIo;\r
+  EFI_STATUS           Status;\r
+  EFI_USB_IO_PROTOCOL  *UsbIo;\r
 \r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
                   &gEfiUsbIoProtocolGuid,\r
-                  (VOID **) &UsbIo,\r
+                  (VOID **)&UsbIo,\r
                   This->DriverBindingHandle,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
@@ -91,7 +84,7 @@ USBMouseAbsolutePointerDriverBindingSupported (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  \r
+\r
   //\r
   // Use the USB I/O Protocol interface to check whether Controller is\r
   // a mouse device that can be managed by this driver.\r
@@ -100,22 +93,21 @@ USBMouseAbsolutePointerDriverBindingSupported (
   if (!IsUsbMouse (UsbIo)) {\r
     Status = EFI_UNSUPPORTED;\r
   }\r
-  \r
+\r
   gBS->CloseProtocol (\r
-        Controller,\r
-        &gEfiUsbIoProtocolGuid,\r
-        This->DriverBindingHandle,\r
-        Controller\r
-        );\r
-        \r
+         Controller,\r
+         &gEfiUsbIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Starts the mouse device with this driver.\r
 \r
-  This function consumes USB I/O Portocol, intializes USB mouse device,\r
+  This function consumes USB I/O Protocol, initializes USB mouse device,\r
   installs Absolute Pointer Protocol, and submits Asynchronous Interrupt\r
   Transfer to manage the USB mouse device.\r
 \r
@@ -134,22 +126,22 @@ USBMouseAbsolutePointerDriverBindingSupported (
 EFI_STATUS\r
 EFIAPI\r
 USBMouseAbsolutePointerDriverBindingStart (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
-  IN EFI_HANDLE                     Controller,\r
-  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
   )\r
 {\r
-  EFI_STATUS                     Status;\r
-  EFI_USB_IO_PROTOCOL            *UsbIo;\r
-  USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointerDevice;\r
-  UINT8                          EndpointNumber;\r
-  EFI_USB_ENDPOINT_DESCRIPTOR    EndpointDescriptor;\r
-  UINT8                          Index;\r
-  UINT8                          EndpointAddr;\r
-  UINT8                          PollingInterval;\r
-  UINT8                          PacketSize;\r
-  BOOLEAN                        Found;\r
-  EFI_TPL                        OldTpl;\r
+  EFI_STATUS                      Status;\r
+  EFI_USB_IO_PROTOCOL             *UsbIo;\r
+  USB_MOUSE_ABSOLUTE_POINTER_DEV  *UsbMouseAbsolutePointerDevice;\r
+  UINT8                           EndpointNumber;\r
+  EFI_USB_ENDPOINT_DESCRIPTOR     EndpointDescriptor;\r
+  UINT8                           Index;\r
+  UINT8                           EndpointAddr;\r
+  UINT8                           PollingInterval;\r
+  UINT8                           PacketSize;\r
+  BOOLEAN                         Found;\r
+  EFI_TPL                         OldTpl;\r
 \r
   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
   //\r
@@ -158,15 +150,15 @@ USBMouseAbsolutePointerDriverBindingStart (
   Status = gBS->OpenProtocol (\r
                   Controller,\r
                   &gEfiUsbIoProtocolGuid,\r
-                  (VOID **) &UsbIo,\r
+                  (VOID **)&UsbIo,\r
                   This->DriverBindingHandle,\r
                   Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER                  \r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
                   );\r
   if (EFI_ERROR (Status)) {\r
     goto ErrorExit1;\r
   }\r
-  \r
+\r
   UsbMouseAbsolutePointerDevice = AllocateZeroPool (sizeof (USB_MOUSE_ABSOLUTE_POINTER_DEV));\r
   ASSERT (UsbMouseAbsolutePointerDevice != NULL);\r
 \r
@@ -179,7 +171,7 @@ USBMouseAbsolutePointerDriverBindingStart (
   Status = gBS->OpenProtocol (\r
                   Controller,\r
                   &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &UsbMouseAbsolutePointerDevice->DevicePath,\r
+                  (VOID **)&UsbMouseAbsolutePointerDevice->DevicePath,\r
                   This->DriverBindingHandle,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
@@ -188,6 +180,16 @@ USBMouseAbsolutePointerDriverBindingStart (
   if (EFI_ERROR (Status)) {\r
     goto ErrorExit;\r
   }\r
+\r
+  //\r
+  // Report Status Code here since USB mouse will be detected next.\r
+  //\r
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+    EFI_PROGRESS_CODE,\r
+    (EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT),\r
+    UsbMouseAbsolutePointerDevice->DevicePath\r
+    );\r
+\r
   //\r
   // Get interface & endpoint descriptor\r
   //\r
@@ -199,7 +201,7 @@ USBMouseAbsolutePointerDriverBindingStart (
   EndpointNumber = UsbMouseAbsolutePointerDevice->InterfaceDescriptor.NumEndpoints;\r
 \r
   //\r
-  // Traverse endpoints to find interrupt endpoint\r
+  // Traverse endpoints to find interrupt endpoint IN\r
   //\r
   Found = FALSE;\r
   for (Index = 0; Index < EndpointNumber; Index++) {\r
@@ -209,11 +211,13 @@ USBMouseAbsolutePointerDriverBindingStart (
              &EndpointDescriptor\r
              );\r
 \r
-    if ((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) {\r
+    if (((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) &&\r
+        ((EndpointDescriptor.EndpointAddress & USB_ENDPOINT_DIR_IN) != 0))\r
+    {\r
       //\r
       // We only care interrupt endpoint here\r
       //\r
-      CopyMem (&UsbMouseAbsolutePointerDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));\r
+      CopyMem (&UsbMouseAbsolutePointerDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof (EndpointDescriptor));\r
       Found = TRUE;\r
       break;\r
     }\r
@@ -221,12 +225,28 @@ USBMouseAbsolutePointerDriverBindingStart (
 \r
   if (!Found) {\r
     //\r
+    // Report Status Code to indicate that there is no USB mouse\r
+    //\r
+    REPORT_STATUS_CODE (\r
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+      (EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED)\r
+      );\r
+    //\r
     // No interrupt endpoint found, then return unsupported.\r
     //\r
     Status = EFI_UNSUPPORTED;\r
     goto ErrorExit;\r
   }\r
 \r
+  //\r
+  // Report Status Code here since USB mouse has be detected.\r
+  //\r
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+    EFI_PROGRESS_CODE,\r
+    (EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED),\r
+    UsbMouseAbsolutePointerDevice->DevicePath\r
+    );\r
+\r
   Status = InitializeUsbMouseDevice (UsbMouseAbsolutePointerDevice);\r
   if (EFI_ERROR (Status)) {\r
     //\r
@@ -245,8 +265,8 @@ USBMouseAbsolutePointerDriverBindingStart (
   // Initialize and install EFI Absolute Pointer Protocol.\r
   //\r
   UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol.GetState = GetMouseAbsolutePointerState;\r
-  UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol.Reset   = UsbMouseAbsolutePointerReset;\r
-  UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol.Mode    = &UsbMouseAbsolutePointerDevice->Mode;\r
+  UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol.Reset    = UsbMouseAbsolutePointerReset;\r
+  UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol.Mode     = &UsbMouseAbsolutePointerDevice->Mode;\r
 \r
   Status = gBS->CreateEvent (\r
                   EVT_NOTIFY_WAIT,\r
@@ -286,7 +306,7 @@ USBMouseAbsolutePointerDriverBindingStart (
   //\r
   EndpointAddr    = UsbMouseAbsolutePointerDevice->IntEndpointDescriptor.EndpointAddress;\r
   PollingInterval = UsbMouseAbsolutePointerDevice->IntEndpointDescriptor.Interval;\r
-  PacketSize      = (UINT8) (UsbMouseAbsolutePointerDevice->IntEndpointDescriptor.MaxPacketSize);\r
+  PacketSize      = (UINT8)(UsbMouseAbsolutePointerDevice->IntEndpointDescriptor.MaxPacketSize);\r
 \r
   Status = UsbIo->UsbAsyncInterruptTransfer (\r
                     UsbIo,\r
@@ -316,8 +336,8 @@ USBMouseAbsolutePointerDriverBindingStart (
     gUsbMouseAbsolutePointerComponentName.SupportedLanguages,\r
     &UsbMouseAbsolutePointerDevice->ControllerNameTable,\r
     L"Generic Usb Mouse Absolute Pointer",\r
-      TRUE\r
-      );\r
+    TRUE\r
+    );\r
   AddUnicodeString2 (\r
     "en",\r
     gUsbMouseAbsolutePointerComponentName2.SupportedLanguages,\r
@@ -329,17 +349,17 @@ USBMouseAbsolutePointerDriverBindingStart (
   gBS->RestoreTPL (OldTpl);\r
   return EFI_SUCCESS;\r
 \r
-//\r
-// Error handler\r
-//\r
+  //\r
+  // Error handler\r
+  //\r
 ErrorExit:\r
   if (EFI_ERROR (Status)) {\r
     gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiUsbIoProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
+           Controller,\r
+           &gEfiUsbIoProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
 \r
     if (UsbMouseAbsolutePointerDevice != NULL) {\r
       if ((UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol).WaitForInput != NULL) {\r
@@ -357,7 +377,6 @@ ErrorExit1:
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Stop the USB mouse device handled by this driver.\r
 \r
@@ -374,10 +393,10 @@ ErrorExit1:
 EFI_STATUS\r
 EFIAPI\r
 USBMouseAbsolutePointerDriverBindingStop (\r
-  IN  EFI_DRIVER_BINDING_PROTOCOL   *This,\r
-  IN  EFI_HANDLE                    Controller,\r
-  IN  UINTN                         NumberOfChildren,\r
-  IN  EFI_HANDLE                    *ChildHandleBuffer\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   Controller,\r
+  IN  UINTN                        NumberOfChildren,\r
+  IN  EFI_HANDLE                   *ChildHandleBuffer\r
   )\r
 {\r
   EFI_STATUS                      Status;\r
@@ -388,7 +407,7 @@ USBMouseAbsolutePointerDriverBindingStop (
   Status = gBS->OpenProtocol (\r
                   Controller,\r
                   &gEfiAbsolutePointerProtocolGuid,\r
-                  (VOID **) &AbsolutePointerProtocol,\r
+                  (VOID **)&AbsolutePointerProtocol,\r
                   This->DriverBindingHandle,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
@@ -444,7 +463,7 @@ USBMouseAbsolutePointerDriverBindingStop (
   // Free all resources.\r
   //\r
   gBS->CloseEvent (UsbMouseAbsolutePointerDevice->AbsolutePointerProtocol.WaitForInput);\r
-  \r
+\r
   if (UsbMouseAbsolutePointerDevice->DelayedRecoveryEvent != NULL) {\r
     gBS->CloseEvent (UsbMouseAbsolutePointerDevice->DelayedRecoveryEvent);\r
     UsbMouseAbsolutePointerDevice->DelayedRecoveryEvent = NULL;\r
@@ -457,10 +476,8 @@ USBMouseAbsolutePointerDriverBindingStop (
   FreePool (UsbMouseAbsolutePointerDevice);\r
 \r
   return EFI_SUCCESS;\r
-\r
 }\r
 \r
-\r
 /**\r
   Uses USB I/O to check whether the device is a USB mouse device.\r
 \r
@@ -472,7 +489,7 @@ USBMouseAbsolutePointerDriverBindingStop (
 **/\r
 BOOLEAN\r
 IsUsbMouse (\r
-  IN  EFI_USB_IO_PROTOCOL     *UsbIo\r
+  IN  EFI_USB_IO_PROTOCOL  *UsbIo\r
   )\r
 {\r
   EFI_STATUS                    Status;\r
@@ -493,14 +510,14 @@ IsUsbMouse (
   if ((InterfaceDescriptor.InterfaceClass == CLASS_HID) &&\r
       (InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT) &&\r
       (InterfaceDescriptor.InterfaceProtocol == PROTOCOL_MOUSE)\r
-      ) {\r
+      )\r
+  {\r
     return TRUE;\r
   }\r
 \r
   return FALSE;\r
 }\r
 \r
-\r
 /**\r
   Initialize the USB mouse device.\r
 \r
@@ -518,49 +535,113 @@ IsUsbMouse (
 **/\r
 EFI_STATUS\r
 InitializeUsbMouseDevice (\r
-  IN  USB_MOUSE_ABSOLUTE_POINTER_DEV           *UsbMouseAbsolutePointerDev\r
+  IN  USB_MOUSE_ABSOLUTE_POINTER_DEV  *UsbMouseAbsolutePointerDev\r
   )\r
 {\r
-  EFI_USB_IO_PROTOCOL     *UsbIo;\r
-  UINT8                   Protocol;\r
-  EFI_STATUS              Status;\r
-  EFI_USB_HID_DESCRIPTOR  MouseHidDesc;\r
-  UINT8                   *ReportDesc;\r
-  UINT8                   ReportId;\r
-  UINT8                   Duration;\r
+  EFI_USB_IO_PROTOCOL        *UsbIo;\r
+  UINT8                      Protocol;\r
+  EFI_STATUS                 Status;\r
+  EFI_USB_HID_DESCRIPTOR     *MouseHidDesc;\r
+  UINT8                      *ReportDesc;\r
+  EFI_USB_CONFIG_DESCRIPTOR  ConfigDesc;\r
+  VOID                       *Buf;\r
+  UINT32                     TransferResult;\r
+  UINT16                     Total;\r
+  USB_DESC_HEAD              *Head;\r
+  BOOLEAN                    Start;\r
 \r
   UsbIo = UsbMouseAbsolutePointerDev->UsbIo;\r
 \r
   //\r
-  // Get HID descriptor\r
+  // Get the current configuration descriptor. Note that it doesn't include other descriptors.\r
+  //\r
+  Status = UsbIo->UsbGetConfigDescriptor (\r
+                    UsbIo,\r
+                    &ConfigDesc\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // By issuing Get_Descriptor(Configuration) request with total length, we get the Configuration descriptor,\r
+  // all Interface descriptors, all Endpoint descriptors, and the HID descriptor for each interface.\r
   //\r
-  Status = UsbGetHidDescriptor (\r
+  Buf = AllocateZeroPool (ConfigDesc.TotalLength);\r
+  if (Buf == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = UsbGetDescriptor (\r
              UsbIo,\r
-             UsbMouseAbsolutePointerDev->InterfaceDescriptor.InterfaceNumber,\r
-             &MouseHidDesc\r
+             (UINT16)((USB_DESC_TYPE_CONFIG << 8) | (ConfigDesc.ConfigurationValue - 1)),\r
+             0,\r
+             ConfigDesc.TotalLength,\r
+             Buf,\r
+             &TransferResult\r
              );\r
   if (EFI_ERROR (Status)) {\r
+    FreePool (Buf);\r
     return Status;\r
   }\r
 \r
+  Total        = 0;\r
+  Start        = FALSE;\r
+  Head         = (USB_DESC_HEAD *)Buf;\r
+  MouseHidDesc = NULL;\r
+\r
+  //\r
+  // Get HID descriptor from the receipt of Get_Descriptor(Configuration) request.\r
+  // This algorithm is based on the fact that the HID descriptor shall be interleaved\r
+  // between the interface and endpoint descriptors for HID interfaces.\r
+  //\r
+  while (Total < ConfigDesc.TotalLength) {\r
+    if (Head->Type == USB_DESC_TYPE_INTERFACE) {\r
+      if ((((USB_INTERFACE_DESCRIPTOR *)Head)->InterfaceNumber == UsbMouseAbsolutePointerDev->InterfaceDescriptor.InterfaceNumber) &&\r
+          (((USB_INTERFACE_DESCRIPTOR *)Head)->AlternateSetting == UsbMouseAbsolutePointerDev->InterfaceDescriptor.AlternateSetting))\r
+      {\r
+        Start = TRUE;\r
+      }\r
+    }\r
+\r
+    if (Start && (Head->Type == USB_DESC_TYPE_ENDPOINT)) {\r
+      break;\r
+    }\r
+\r
+    if (Start && (Head->Type == USB_DESC_TYPE_HID)) {\r
+      MouseHidDesc = (EFI_USB_HID_DESCRIPTOR *)Head;\r
+      break;\r
+    }\r
+\r
+    Total = Total + (UINT16)Head->Len;\r
+    Head  = (USB_DESC_HEAD *)((UINT8 *)Buf + Total);\r
+  }\r
+\r
+  if (MouseHidDesc == NULL) {\r
+    FreePool (Buf);\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   //\r
   // Get report descriptor\r
   //\r
-  if (MouseHidDesc.HidClassDesc[0].DescriptorType != USB_DESC_TYPE_REPORT) {\r
+  if (MouseHidDesc->HidClassDesc[0].DescriptorType != USB_DESC_TYPE_REPORT) {\r
+    FreePool (Buf);\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  ReportDesc = AllocateZeroPool (MouseHidDesc.HidClassDesc[0].DescriptorLength);\r
+  ReportDesc = AllocateZeroPool (MouseHidDesc->HidClassDesc[0].DescriptorLength);\r
   ASSERT (ReportDesc != NULL);\r
 \r
   Status = UsbGetReportDescriptor (\r
              UsbIo,\r
              UsbMouseAbsolutePointerDev->InterfaceDescriptor.InterfaceNumber,\r
-             MouseHidDesc.HidClassDesc[0].DescriptorLength,\r
+             MouseHidDesc->HidClassDesc[0].DescriptorLength,\r
              ReportDesc\r
              );\r
 \r
   if (EFI_ERROR (Status)) {\r
+    FreePool (Buf);\r
     FreePool (ReportDesc);\r
     return Status;\r
   }\r
@@ -571,10 +652,11 @@ InitializeUsbMouseDevice (
   Status = ParseMouseReportDescriptor (\r
              UsbMouseAbsolutePointerDev,\r
              ReportDesc,\r
-             MouseHidDesc.HidClassDesc[0].DescriptorLength\r
+             MouseHidDesc->HidClassDesc[0].DescriptorLength\r
              );\r
 \r
   if (EFI_ERROR (Status)) {\r
+    FreePool (Buf);\r
     FreePool (ReportDesc);\r
     return Status;\r
   }\r
@@ -586,7 +668,15 @@ InitializeUsbMouseDevice (
   UsbMouseAbsolutePointerDev->Mode.AbsoluteMinY = 0;\r
   UsbMouseAbsolutePointerDev->Mode.AbsoluteMinZ = 0;\r
   UsbMouseAbsolutePointerDev->Mode.Attributes   = 0x3;\r
-  \r
+\r
+  //\r
+  // Let the cursor's starting position is in the center of the screen.\r
+  //\r
+  UsbMouseAbsolutePointerDev->State.CurrentX =\r
+    DivU64x32 (UsbMouseAbsolutePointerDev->Mode.AbsoluteMaxX + UsbMouseAbsolutePointerDev->Mode.AbsoluteMinX, 2);\r
+  UsbMouseAbsolutePointerDev->State.CurrentY =\r
+    DivU64x32 (UsbMouseAbsolutePointerDev->Mode.AbsoluteMaxY + UsbMouseAbsolutePointerDev->Mode.AbsoluteMinY, 2);\r
+\r
   //\r
   // Set boot protocol for the USB mouse.\r
   // This driver only supports boot protocol.\r
@@ -599,33 +689,18 @@ InitializeUsbMouseDevice (
   if (Protocol != BOOT_PROTOCOL) {\r
     Status = UsbSetProtocolRequest (\r
                UsbIo,\r
-               0,\r
+               UsbMouseAbsolutePointerDev->InterfaceDescriptor.InterfaceNumber,\r
                BOOT_PROTOCOL\r
                );\r
 \r
     if (EFI_ERROR (Status)) {\r
+      FreePool (Buf);\r
       FreePool (ReportDesc);\r
       return Status;\r
     }\r
   }\r
 \r
-  //\r
-  // ReportId is zero, which means the idle rate applies to all input reports.\r
-  //\r
-  ReportId = 0;\r
-  //\r
-  // Duration is zero, which means the duration is infinite.\r
-  // so the endpoint will inhibit reporting forever,\r
-  // and only reporting when a change is detected in the report data.\r
-  //\r
-  Duration = 0;\r
-  UsbSetIdleRequest (\r
-    UsbIo,\r
-    UsbMouseAbsolutePointerDev->InterfaceDescriptor.InterfaceNumber,\r
-    ReportId,\r
-    Duration\r
-    );\r
-\r
+  FreePool (Buf);\r
   FreePool (ReportDesc);\r
 \r
   //\r
@@ -647,7 +722,6 @@ InitializeUsbMouseDevice (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Handler function for USB mouse's asynchronous interrupt transfer.\r
 \r
@@ -668,19 +742,19 @@ InitializeUsbMouseDevice (
 EFI_STATUS\r
 EFIAPI\r
 OnMouseInterruptComplete (\r
-  IN  VOID        *Data,\r
-  IN  UINTN       DataLength,\r
-  IN  VOID        *Context,\r
-  IN  UINT32      Result\r
+  IN  VOID    *Data,\r
+  IN  UINTN   DataLength,\r
+  IN  VOID    *Context,\r
+  IN  UINT32  Result\r
   )\r
 {\r
-  USB_MOUSE_ABSOLUTE_POINTER_DEV   *UsbMouseAbsolutePointerDevice;\r
-  EFI_USB_IO_PROTOCOL              *UsbIo;\r
-  UINT8                            EndpointAddr;\r
-  UINT32                           UsbResult;\r
+  USB_MOUSE_ABSOLUTE_POINTER_DEV  *UsbMouseAbsolutePointerDevice;\r
+  EFI_USB_IO_PROTOCOL             *UsbIo;\r
+  UINT8                           EndpointAddr;\r
+  UINT32                          UsbResult;\r
 \r
-  UsbMouseAbsolutePointerDevice  = (USB_MOUSE_ABSOLUTE_POINTER_DEV *) Context;\r
-  UsbIo                          = UsbMouseAbsolutePointerDevice->UsbIo;\r
+  UsbMouseAbsolutePointerDevice = (USB_MOUSE_ABSOLUTE_POINTER_DEV *)Context;\r
+  UsbIo                         = UsbMouseAbsolutePointerDevice->UsbIo;\r
 \r
   if (Result != EFI_USB_NOERROR) {\r
     //\r
@@ -704,7 +778,7 @@ OnMouseInterruptComplete (
 \r
     //\r
     // Delete & Submit this interrupt again\r
-    // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt. \r
+    // Handler of DelayedRecoveryEvent triggered by timer will re-submit the interrupt.\r
     //\r
     UsbIo->UsbAsyncInterruptTransfer (\r
              UsbIo,\r
@@ -729,12 +803,10 @@ OnMouseInterruptComplete (
   //\r
   // If no error and no data, just return EFI_SUCCESS.\r
   //\r
-  if (DataLength == 0 || Data == NULL) {\r
+  if ((DataLength == 0) || (Data == NULL)) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  UsbMouseAbsolutePointerDevice->StateChanged = TRUE;\r
-\r
   //\r
   // Check mouse Data\r
   // USB HID Specification specifies following data format:\r
@@ -747,13 +819,40 @@ OnMouseInterruptComplete (
   // 2       0 to 7  Y displacement\r
   // 3 to n  0 to 7  Device specific (optional)\r
   //\r
-  UsbMouseAbsolutePointerDevice->State.CurrentX += *((INT8 *) Data + 1);\r
-  UsbMouseAbsolutePointerDevice->State.CurrentY += *((INT8 *) Data + 2);\r
-  \r
+  if (DataLength < 3) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  UsbMouseAbsolutePointerDevice->StateChanged = TRUE;\r
+\r
+  UsbMouseAbsolutePointerDevice->State.ActiveButtons = *(UINT8 *)Data & (BIT0 | BIT1 | BIT2);\r
+\r
+  UsbMouseAbsolutePointerDevice->State.CurrentX =\r
+    MIN (\r
+      MAX (\r
+        (INT64)UsbMouseAbsolutePointerDevice->State.CurrentX + *((INT8 *)Data + 1),\r
+        (INT64)UsbMouseAbsolutePointerDevice->Mode.AbsoluteMinX\r
+        ),\r
+      (INT64)UsbMouseAbsolutePointerDevice->Mode.AbsoluteMaxX\r
+      );\r
+  UsbMouseAbsolutePointerDevice->State.CurrentY =\r
+    MIN (\r
+      MAX (\r
+        (INT64)UsbMouseAbsolutePointerDevice->State.CurrentY + *((INT8 *)Data + 2),\r
+        (INT64)UsbMouseAbsolutePointerDevice->Mode.AbsoluteMinY\r
+        ),\r
+      (INT64)UsbMouseAbsolutePointerDevice->Mode.AbsoluteMaxY\r
+      );\r
   if (DataLength > 3) {\r
-    UsbMouseAbsolutePointerDevice->State.CurrentZ += *((INT8 *) Data + 3);\r
+    UsbMouseAbsolutePointerDevice->State.CurrentZ =\r
+      MIN (\r
+        MAX (\r
+          (INT64)UsbMouseAbsolutePointerDevice->State.CurrentZ + *((INT8 *)Data + 1),\r
+          (INT64)UsbMouseAbsolutePointerDevice->Mode.AbsoluteMinZ\r
+          ),\r
+        (INT64)UsbMouseAbsolutePointerDevice->Mode.AbsoluteMaxZ\r
+        );\r
   }\r
-  UsbMouseAbsolutePointerDevice->State.ActiveButtons = *(UINT8 *) Data & (BIT0 | BIT1);\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -761,15 +860,15 @@ OnMouseInterruptComplete (
 /**\r
   Retrieves the current state of a pointer device.\r
 \r
-  @param  This                  A pointer to the EFI_ABSOLUTE_POINTER_PROTOCOL instance.                                   \r
+  @param  This                  A pointer to the EFI_ABSOLUTE_POINTER_PROTOCOL instance.\r
   @param  MouseState            A pointer to the state information on the pointer device.\r
 \r
   @retval EFI_SUCCESS           The state of the pointer device was returned in State.\r
   @retval EFI_NOT_READY         The state of the pointer device has not changed since the last call to\r
-                                GetState().                                                           \r
+                                GetState().\r
   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to retrieve the pointer device's\r
-                                current state.                                                           \r
-  @retval EFI_INVALID_PARAMETER State is NULL.                                                           \r
+                                current state.\r
+  @retval EFI_INVALID_PARAMETER State is NULL.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -779,7 +878,7 @@ GetMouseAbsolutePointerState (
   OUT  EFI_ABSOLUTE_POINTER_STATE     *State\r
   )\r
 {\r
-  USB_MOUSE_ABSOLUTE_POINTER_DEV *MouseAbsolutePointerDev;\r
+  USB_MOUSE_ABSOLUTE_POINTER_DEV  *MouseAbsolutePointerDev;\r
 \r
   if (State == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -801,20 +900,11 @@ GetMouseAbsolutePointerState (
     sizeof (EFI_ABSOLUTE_POINTER_STATE)\r
     );\r
 \r
-  //\r
-  // Clear previous move state\r
-  //\r
-  MouseAbsolutePointerDev->State.CurrentX      = 0;\r
-  MouseAbsolutePointerDev->State.CurrentY      = 0;\r
-  MouseAbsolutePointerDev->State.CurrentZ      = 0;\r
-  MouseAbsolutePointerDev->State.ActiveButtons = 0;\r
-\r
   MouseAbsolutePointerDev->StateChanged = FALSE;\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Resets the pointer device hardware.\r
 \r
@@ -833,9 +923,9 @@ UsbMouseAbsolutePointerReset (
   IN BOOLEAN                        ExtendedVerification\r
   )\r
 {\r
-  USB_MOUSE_ABSOLUTE_POINTER_DEV       *UsbMouseAbsolutePointerDevice;\r
+  USB_MOUSE_ABSOLUTE_POINTER_DEV  *UsbMouseAbsolutePointerDevice;\r
 \r
-  UsbMouseAbsolutePointerDevice  = USB_MOUSE_ABSOLUTE_POINTER_DEV_FROM_MOUSE_PROTOCOL (This);\r
+  UsbMouseAbsolutePointerDevice = USB_MOUSE_ABSOLUTE_POINTER_DEV_FROM_MOUSE_PROTOCOL (This);\r
 \r
   REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
     EFI_PROGRESS_CODE,\r
@@ -850,6 +940,15 @@ UsbMouseAbsolutePointerReset (
     &UsbMouseAbsolutePointerDevice->State,\r
     sizeof (EFI_ABSOLUTE_POINTER_STATE)\r
     );\r
+\r
+  //\r
+  // Let the cursor's starting position is in the center of the screen.\r
+  //\r
+  UsbMouseAbsolutePointerDevice->State.CurrentX =\r
+    DivU64x32 (UsbMouseAbsolutePointerDevice->Mode.AbsoluteMaxX + UsbMouseAbsolutePointerDevice->Mode.AbsoluteMinX, 2);\r
+  UsbMouseAbsolutePointerDevice->State.CurrentY =\r
+    DivU64x32 (UsbMouseAbsolutePointerDevice->Mode.AbsoluteMaxY + UsbMouseAbsolutePointerDevice->Mode.AbsoluteMinY, 2);\r
+\r
   UsbMouseAbsolutePointerDevice->StateChanged = FALSE;\r
 \r
   return EFI_SUCCESS;\r
@@ -865,13 +964,13 @@ UsbMouseAbsolutePointerReset (
 VOID\r
 EFIAPI\r
 UsbMouseAbsolutePointerWaitForInput (\r
-  IN  EFI_EVENT               Event,\r
-  IN  VOID                    *Context\r
+  IN  EFI_EVENT  Event,\r
+  IN  VOID       *Context\r
   )\r
 {\r
-  USB_MOUSE_ABSOLUTE_POINTER_DEV *UsbMouseAbsolutePointerDev;\r
+  USB_MOUSE_ABSOLUTE_POINTER_DEV  *UsbMouseAbsolutePointerDev;\r
 \r
-  UsbMouseAbsolutePointerDev = (USB_MOUSE_ABSOLUTE_POINTER_DEV *) Context;\r
+  UsbMouseAbsolutePointerDev = (USB_MOUSE_ABSOLUTE_POINTER_DEV *)Context;\r
 \r
   //\r
   // If there's input from mouse, signal the event.\r
@@ -897,16 +996,16 @@ UsbMouseAbsolutePointerWaitForInput (
 VOID\r
 EFIAPI\r
 USBMouseRecoveryHandler (\r
-  IN    EFI_EVENT    Event,\r
-  IN    VOID         *Context\r
+  IN    EFI_EVENT  Event,\r
+  IN    VOID       *Context\r
   )\r
 {\r
-  USB_MOUSE_ABSOLUTE_POINTER_DEV       *UsbMouseAbsolutePointerDev;\r
-  EFI_USB_IO_PROTOCOL                  *UsbIo;\r
+  USB_MOUSE_ABSOLUTE_POINTER_DEV  *UsbMouseAbsolutePointerDev;\r
+  EFI_USB_IO_PROTOCOL             *UsbIo;\r
 \r
-  UsbMouseAbsolutePointerDev = (USB_MOUSE_ABSOLUTE_POINTER_DEV *) Context;\r
+  UsbMouseAbsolutePointerDev = (USB_MOUSE_ABSOLUTE_POINTER_DEV *)Context;\r
 \r
-  UsbIo       = UsbMouseAbsolutePointerDev->UsbIo;\r
+  UsbIo = UsbMouseAbsolutePointerDev->UsbIo;\r
 \r
   //\r
   // Re-submit Asynchronous Interrupt Transfer for recovery.\r