]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouse.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Usb / UsbMouseDxe / UsbMouse.c
index d81eaf7eae07e36211845a131a1bd6f92cf5589c..677815a8ade3de3a298b8326679d1e65e8d0218a 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   USB Mouse Driver that manages USB mouse and produces Simple 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
@@ -188,6 +182,16 @@ USBMouseDriverBindingStart (
   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
+    UsbMouseDevice->DevicePath\r
+    );\r
+\r
   //\r
   // Get interface & endpoint descriptor\r
   //\r
@@ -221,12 +225,28 @@ USBMouseDriverBindingStart (
 \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
+    UsbMouseDevice->DevicePath\r
+    );\r
+\r
   Status = InitializeUsbMouseDevice (UsbMouseDevice);\r
   if (EFI_ERROR (Status)) {\r
     //\r
@@ -309,7 +329,7 @@ USBMouseDriverBindingStart (
            );\r
     goto ErrorExit;\r
   }\r
-  \r
+\r
   UsbMouseDevice->ControllerNameTable = NULL;\r
   AddUnicodeString2 (\r
     "eng",\r
@@ -521,46 +541,106 @@ InitializeUsbMouseDevice (
   IN OUT USB_MOUSE_DEV           *UsbMouseDev\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 = UsbMouseDev->UsbIo;\r
 \r
   //\r
-  // Get HID descriptor\r
+  // Get the current configuration descriptor. Note that it doesn't include other descriptors.\r
   //\r
-  Status = UsbGetHidDescriptor (\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
+  Buf = AllocateZeroPool (ConfigDesc.TotalLength);\r
+  if (Buf == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = UsbGetDescriptor (\r
              UsbIo,\r
-             UsbMouseDev->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 == UsbMouseDev->InterfaceDescriptor.InterfaceNumber) &&\r
+        (((USB_INTERFACE_DESCRIPTOR *)Head)->AlternateSetting == UsbMouseDev->InterfaceDescriptor.AlternateSetting)) {\r
+        Start = TRUE;\r
+      }\r
+    }\r
+    if (Start && (Head->Type == USB_DESC_TYPE_ENDPOINT)) {\r
+      break;\r
+    }\r
+    if (Start && (Head->Type == USB_DESC_TYPE_HID)) {\r
+      MouseHidDesc = (EFI_USB_HID_DESCRIPTOR *)Head;\r
+      break;\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
              UsbMouseDev->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 +651,11 @@ InitializeUsbMouseDevice (
   Status = ParseMouseReportDescriptor (\r
              UsbMouseDev,\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
@@ -610,28 +691,13 @@ InitializeUsbMouseDevice (
                );\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
-    UsbMouseDev->InterfaceDescriptor.InterfaceNumber,\r
-    ReportId,\r
-    Duration\r
-    );\r
-\r
+  FreePool (Buf);\r
   FreePool (ReportDesc);\r
 \r
   //\r
@@ -710,7 +776,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
@@ -739,8 +805,6 @@ OnMouseInterruptComplete (
     return EFI_SUCCESS;\r
   }\r
 \r
-  UsbMouseDevice->StateChanged = TRUE;\r
-\r
   //\r
   // Check mouse Data\r
   // USB HID Specification specifies following data format:\r
@@ -753,6 +817,12 @@ OnMouseInterruptComplete (
   // 2       0 to 7  Y displacement\r
   // 3 to n  0 to 7  Device specific (optional)\r
   //\r
+  if (DataLength < 3) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  UsbMouseDevice->StateChanged = TRUE;\r
+\r
   UsbMouseDevice->State.LeftButton  = (BOOLEAN) ((*(UINT8 *) Data & BIT0) != 0);\r
   UsbMouseDevice->State.RightButton = (BOOLEAN) ((*(UINT8 *) Data & BIT1) != 0);\r
   UsbMouseDevice->State.RelativeMovementX += *((INT8 *) Data + 1);\r
@@ -767,16 +837,16 @@ OnMouseInterruptComplete (
 \r
 /**\r
   Retrieves the current state of a pointer device.\r
-    \r
-  @param  This                  A pointer to the EFI_SIMPLE_POINTER_PROTOCOL instance.                                   \r
+\r
+  @param  This                  A pointer to the EFI_SIMPLE_POINTER_PROTOCOL instance.\r
   @param  MouseState            A pointer to the state information on the pointer device.\r
-                                \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 MouseState is NULL.                                                           \r
+                                current state.\r
+  @retval EFI_INVALID_PARAMETER MouseState is NULL.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -820,13 +890,13 @@ GetMouseState (
 }\r
 \r
 \r
-/**                                                                 \r
+/**\r
   Resets the pointer device hardware.\r
-  \r
+\r
   @param  This                  A pointer to the EFI_SIMPLE_POINTER_PROTOCOL instance.\r
   @param  ExtendedVerification  Indicates that the driver may perform a more exhaustive\r
                                 verification operation of the device during reset.\r
-                                \r
+\r
   @retval EFI_SUCCESS           The device was reset.\r
   @retval EFI_DEVICE_ERROR      The device is not functioning correctly and could not be reset.\r
 \r
@@ -865,7 +935,7 @@ UsbMouseReset (
 \r
   @param  Event        Event to be signaled when there's input from mouse.\r
   @param  Context      Points to USB_MOUSE_DEV instance.\r
\r
+\r
 **/\r
 VOID\r
 EFIAPI\r