Sync with trunk r58740.
[reactos.git] / drivers / hid / mouhid / mouhid.c
index b61af2f..3163b87 100644 (file)
@@ -37,6 +37,7 @@ MouHid_GetButtonMove(
     OUT PLONG LastY)
 {
     NTSTATUS Status;
+    ULONG ValueX, ValueY;
 
     /* init result */
     *LastX = 0;
@@ -44,21 +45,55 @@ MouHid_GetButtonMove(
 
     /* get scaled usage value x */
     Status =  HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, (PLONG)LastX, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
-    /* FIXME handle error */
-    ASSERT(Status == HIDP_STATUS_SUCCESS);
+    if (Status != HIDP_STATUS_SUCCESS)
+    {
+        /* FIXME: handle more errors */
+        if (Status == HIDP_STATUS_BAD_LOG_PHY_VALUES)
+        {
+            /* FIXME: assume it operates in absolute mode */
+            DeviceExtension->MouseAbsolute = TRUE;
+
+            /* get unscaled value */
+            Status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, (PULONG)&ValueX, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
+
+            /* FIXME handle error */
+            ASSERT(Status == HIDP_STATUS_SUCCESS);
+
+            /* absolute pointing devices values need be in range 0 - 0xffff */
+            ASSERT(DeviceExtension->ValueCapsX.LogicalMax > 0);
+
+            *LastX = (ValueX * 0xFFFF) / DeviceExtension->ValueCapsX.LogicalMax;
+        }
+    }
 
     /* get scaled usage value y */
     Status =  HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, (PLONG)LastY, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
-    /* FIXME handle error */
-    ASSERT(Status == HIDP_STATUS_SUCCESS);
+    if (Status != HIDP_STATUS_SUCCESS)
+    {
+        // FIXME: handle more errors
+        if (Status == HIDP_STATUS_BAD_LOG_PHY_VALUES)
+        {
+            // assume it operates in absolute mode
+            DeviceExtension->MouseAbsolute = TRUE;
 
-}
+            // get unscaled value
+            Status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, (PULONG)&ValueY, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
 
+            /* FIXME handle error */
+            ASSERT(Status == HIDP_STATUS_SUCCESS);
+
+            /* absolute pointing devices values need be in range 0 - 0xffff */
+            ASSERT(DeviceExtension->ValueCapsY.LogicalMax);
+            *LastY = (ValueY * 0xFFFF) / DeviceExtension->ValueCapsY.LogicalMax;
+        }
+    }
+}
 
 VOID
 MouHid_GetButtonFlags(
     IN PMOUHID_DEVICE_EXTENSION DeviceExtension,
-    OUT PUSHORT ButtonFlags)
+    OUT PUSHORT ButtonFlags,
+    OUT PUSHORT Flags)
 {
     NTSTATUS Status;
     USAGE Usage;
@@ -68,6 +103,7 @@ MouHid_GetButtonFlags(
 
     /* init flags */
     *ButtonFlags = 0;
+    *Flags = 0;
 
     /* get usages */
     CurrentUsageListLength = DeviceExtension->UsageListLength;
@@ -132,6 +168,12 @@ MouHid_GetButtonFlags(
     TempList = DeviceExtension->CurrentUsageList;
     DeviceExtension->CurrentUsageList = DeviceExtension->PreviousUsageList;
     DeviceExtension->PreviousUsageList = TempList;
+
+    if (DeviceExtension->MouseAbsolute)
+    {
+        // mouse operates absolute
+        *Flags |= MOUSE_MOVE_ABSOLUTE;
+    }
 }
 
 VOID
@@ -172,6 +214,7 @@ MouHid_ReadCompletion(
     NTSTATUS Status;
     LONG LastX, LastY;
     MOUSE_INPUT_DATA MouseInputData;
+    USHORT Flags;
 
     /* get device extension */
     DeviceExtension = (PMOUHID_DEVICE_EXTENSION)Context;
@@ -195,17 +238,18 @@ MouHid_ReadCompletion(
         return STATUS_MORE_PROCESSING_REQUIRED;
     }
 
-    /* get mouse change flags */
-    MouHid_GetButtonFlags(DeviceExtension, &ButtonFlags);
-
     /* get mouse change */
     MouHid_GetButtonMove(DeviceExtension, &LastX, &LastY);
 
+    /* get mouse change flags */
+    MouHid_GetButtonFlags(DeviceExtension, &ButtonFlags, &Flags);
+
     /* init input data */
     RtlZeroMemory(&MouseInputData, sizeof(MOUSE_INPUT_DATA));
 
     /* init input data */
     MouseInputData.ButtonFlags = ButtonFlags;
+    MouseInputData.Flags = Flags;
     MouseInputData.LastX = LastX;
     MouseInputData.LastY = LastY;
 
@@ -215,19 +259,25 @@ MouHid_ReadCompletion(
         /* get usage */
         UsageValue = 0;
         Status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_WHEEL, &UsageValue, DeviceExtension->PreparsedData, DeviceExtension->Report, DeviceExtension->ReportLength);
-        if (Status == HIDP_STATUS_SUCCESS)
+        if (Status == HIDP_STATUS_SUCCESS && UsageValue != 0)
         {
             /* store wheel status */
             MouseInputData.ButtonFlags |= MOUSE_WHEEL;
-            MouseInputData.ButtonData = (USHORT)UsageValue; /* FIXME */
+            MouseInputData.ButtonData = (USHORT)(UsageValue * WHEEL_DELTA);
         }
         else
         {
-            DPRINT1("[MOUHID] failed to get wheel status with %x\n", Status);
+            DPRINT("[MOUHID] failed to get wheel status with %x\n", Status);
         }
     }
 
-    DPRINT1("[MOUHID] LastX %ld LastY %ld Flags %x ButtonData %x\n", MouseInputData.LastX, MouseInputData.LastY, MouseInputData.ButtonFlags, MouseInputData.ButtonData);
+    DPRINT("[MOUHID] ReportData %02x %02x %02x %02x %02x %02x %02x\n",
+        DeviceExtension->Report[0] & 0xFF,
+        DeviceExtension->Report[1] & 0xFF, DeviceExtension->Report[2] & 0xFF,
+        DeviceExtension->Report[3] & 0xFF, DeviceExtension->Report[4] & 0xFF,
+        DeviceExtension->Report[5] & 0xFF, DeviceExtension->Report[6] & 0xFF);
+
+    DPRINT("[MOUHID] LastX %ld LastY %ld Flags %x ButtonData %x\n", MouseInputData.LastX, MouseInputData.LastY, MouseInputData.ButtonFlags, MouseInputData.ButtonData);
 
     /* dispatch mouse action */
     MouHid_DispatchInputData(DeviceExtension, &MouseInputData);
@@ -298,7 +348,7 @@ MouHid_Create(
     KEVENT Event;
     PMOUHID_DEVICE_EXTENSION DeviceExtension;
 
-    DPRINT1("MOUHID: IRP_MJ_CREATE\n");
+    DPRINT("MOUHID: IRP_MJ_CREATE\n");
 
     /* get device extension */
     DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
@@ -347,7 +397,7 @@ MouHid_Create(
 
              /* initiating read */
              Status = MouHid_InitiateRead(DeviceExtension);
-             DPRINT1("[MOUHID] MouHid_InitiateRead: status %x\n", Status);
+             DPRINT("[MOUHID] MouHid_InitiateRead: status %x\n", Status);
              if (Status == STATUS_PENDING)
              {
                  /* report irp is pending */
@@ -414,7 +464,7 @@ MouHid_InternalDeviceControl(
     /* get current stack location */
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
-    DPRINT1("[MOUHID] InternalDeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
+    DPRINT("[MOUHID] InternalDeviceControl %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
 
     /* get device extension */
     DeviceExtension = (PMOUHID_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
@@ -447,10 +497,10 @@ MouHid_InternalDeviceControl(
          /* queue length */
          Attributes->InputDataQueueLength = 2;
 
-         DPRINT1("[MOUHID] MouseIdentifier %x\n", Attributes->MouseIdentifier);
-         DPRINT1("[MOUHID] NumberOfButtons %x\n", Attributes->NumberOfButtons);
-         DPRINT1("[MOUHID] SampleRate %x\n", Attributes->SampleRate);
-         DPRINT1("[MOUHID] InputDataQueueLength %x\n", Attributes->InputDataQueueLength);
+         DPRINT("[MOUHID] MouseIdentifier %x\n", Attributes->MouseIdentifier);
+         DPRINT("[MOUHID] NumberOfButtons %x\n", Attributes->NumberOfButtons);
+         DPRINT("[MOUHID] SampleRate %x\n", Attributes->SampleRate);
+         DPRINT("[MOUHID] InputDataQueueLength %x\n", Attributes->InputDataQueueLength);
 
          /* complete request */
          Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
@@ -645,10 +695,10 @@ MouHid_StartDevice(
         return Status;
     }
 
-    DPRINT1("[MOUHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength);
+    DPRINT("[MOUHID] Usage %x UsagePage %x InputReportLength %lu\n", Capabilities.Usage, Capabilities.UsagePage, Capabilities.InputReportByteLength);
 
     /* verify capabilities */
-    if (Capabilities.Usage != HID_USAGE_GENERIC_POINTER && Capabilities.Usage != HID_USAGE_GENERIC_MOUSE || Capabilities.UsagePage != HID_USAGE_PAGE_GENERIC)
+    if ((Capabilities.Usage != HID_USAGE_GENERIC_POINTER && Capabilities.Usage != HID_USAGE_GENERIC_MOUSE) || Capabilities.UsagePage != HID_USAGE_PAGE_GENERIC)
     {
         /* not supported */
         ExFreePool(PreparsedData);
@@ -658,7 +708,7 @@ MouHid_StartDevice(
     /* init input report*/
     DeviceExtension->ReportLength = Capabilities.InputReportByteLength;
     ASSERT(DeviceExtension->ReportLength);
-    DeviceExtension->Report = (PUCHAR)ExAllocatePool(NonPagedPool, DeviceExtension->ReportLength);
+    DeviceExtension->Report = (PCHAR)ExAllocatePool(NonPagedPool, DeviceExtension->ReportLength);
     ASSERT(DeviceExtension->Report);
     RtlZeroMemory(DeviceExtension->Report, DeviceExtension->ReportLength);
 
@@ -671,7 +721,7 @@ MouHid_StartDevice(
 
     /* get max number of buttons */
     Buttons = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON, PreparsedData);
-    DPRINT1("[MOUHID] Buttons %lu\n", Buttons);
+    DPRINT("[MOUHID] Buttons %lu\n", Buttons);
     ASSERT(Buttons > 0);
 
     /* now allocate an array for those buttons */
@@ -700,10 +750,10 @@ MouHid_StartDevice(
     DeviceExtension->PreparsedData = PreparsedData;
 
     ValueCapsLength = 1;
-    HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, &ValueCaps, &ValueCapsLength, PreparsedData);
+    HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_X, &DeviceExtension->ValueCapsX, &ValueCapsLength, PreparsedData);
 
     ValueCapsLength = 1;
-    HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, &ValueCaps, &ValueCapsLength, PreparsedData);
+    HidP_GetSpecificValueCaps(HidP_Input, HID_USAGE_PAGE_GENERIC, HIDP_LINK_COLLECTION_UNSPECIFIED, HID_USAGE_GENERIC_Y, &DeviceExtension->ValueCapsY, &ValueCapsLength, PreparsedData);
 
     /* now check for wheel mouse support */
     ValueCapsLength = 1;
@@ -713,7 +763,7 @@ MouHid_StartDevice(
         /* mouse has wheel support */
         DeviceExtension->MouseIdentifier = WHEELMOUSE_HID_HARDWARE;
         DeviceExtension->WheelUsagePage = ValueCaps.UsagePage;
-        DPRINT1("[MOUHID] mouse wheel support detected\n", Status);
+        DPRINT("[MOUHID] mouse wheel support detected\n", Status);
     }
     else
     {
@@ -725,7 +775,7 @@ MouHid_StartDevice(
             /* wheel support */
             DeviceExtension->MouseIdentifier = WHEELMOUSE_HID_HARDWARE;
             DeviceExtension->WheelUsagePage = ValueCaps.UsagePage;
-            DPRINT1("[MOUHID] mouse wheel support detected with z-axis\n", Status);
+            DPRINT("[MOUHID] mouse wheel support detected with z-axis\n", Status);
         }
     }
 
@@ -786,9 +836,13 @@ MouHid_Pnp(
 
     /* get current irp stack */
     IoStack = IoGetCurrentIrpStackLocation(Irp);
-    DPRINT1("[MOUHID] IRP_MJ_PNP Request: %x\n", IoStack->MinorFunction);
+    DPRINT("[MOUHID] IRP_MJ_PNP Request: %x\n", IoStack->MinorFunction);
 
-    if (IoStack->MinorFunction == IRP_MN_STOP_DEVICE || IoStack->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE || IoStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE || IoStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE)
+    if (IoStack->MinorFunction == IRP_MN_STOP_DEVICE ||
+        IoStack->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE ||
+        IoStack->MinorFunction == IRP_MN_QUERY_STOP_DEVICE ||
+        IoStack->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE ||
+        IoStack->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE)
     {
         /* indicate success */
         Irp->IoStatus.Status = STATUS_SUCCESS;
@@ -803,6 +857,9 @@ MouHid_Pnp(
     {
         /* FIXME synchronization */
 
+        /* request stop */
+        DeviceExtension->StopReadReport = TRUE;
+
         /* cancel irp */
         IoCancelIrp(DeviceExtension->Irp);
 
@@ -815,9 +872,19 @@ MouHid_Pnp(
         /* dispatch to lower device */
         Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
 
+        /* wait for completion of stop event */
+        KeWaitForSingleObject(&DeviceExtension->ReadCompletionEvent, Executive, KernelMode, FALSE, NULL);
+
+        /* free irp */
         IoFreeIrp(DeviceExtension->Irp);
+
+        /* detach device */
         IoDetachDevice(DeviceExtension->NextDeviceObject);
+
+        /* delete device */
         IoDeleteDevice(DeviceObject);
+
+        /* done */
         return Status;
     }
     else if (IoStack->MinorFunction == IRP_MN_START_DEVICE)
@@ -850,7 +917,7 @@ MouHid_Pnp(
 
         /* lets start the device */
         Status = MouHid_StartDevice(DeviceObject);
-        DPRINT1("MouHid_StartDevice %x\n", Status);
+        DPRINT("MouHid_StartDevice %x\n", Status);
 
         /* complete request */
         Irp->IoStatus.Status = Status;