[HIDPARSE][HIDPARSER]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Mon, 22 Oct 2012 21:18:30 +0000 (21:18 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Mon, 22 Oct 2012 21:18:30 +0000 (21:18 +0000)
- Implement HidP_GetUsageValue
- Add hack to HidParser_GetScaledUsageValueWithReport
[MOUHID]
- Add partial support for absolute pointing devices
- Tested in VBOX 4.1.22 with absolute pointing devices
- Needs more work in win32k
- Core 6553

svn path=/trunk/; revision=57595

reactos/drivers/hid/hidparse/hidparse.c
reactos/drivers/hid/mouhid/mouhid.c
reactos/drivers/hid/mouhid/mouhid.h
reactos/lib/drivers/hidparser/api.c
reactos/lib/drivers/hidparser/hidparser.c
reactos/lib/drivers/hidparser/hidparser.h
reactos/lib/drivers/hidparser/parser.h

index d443106..4254fd7 100644 (file)
@@ -306,6 +306,38 @@ HidP_GetScaledUsageValue(
     return HidParser_GetScaledUsageValue(&Parser, PreparsedData, ReportType, UsagePage, LinkCollection, Usage, UsageValue, Report, ReportLength);
 }
 
+HIDAPI
+NTSTATUS
+NTAPI
+HidP_GetUsageValue(
+  IN HIDP_REPORT_TYPE  ReportType,
+  IN USAGE  UsagePage,
+  IN USHORT  LinkCollection,
+  IN USAGE  Usage,
+  OUT PULONG  UsageValue,
+  IN PHIDP_PREPARSED_DATA  PreparsedData,
+  IN PCHAR  Report,
+  IN ULONG  ReportLength)
+{
+    HID_PARSER Parser;
+
+    //
+    // sanity check
+    //
+    ASSERT(ReportType == HidP_Input || ReportType == HidP_Output || ReportType == HidP_Feature);
+
+    //
+    // init parser
+    //
+    HidParser_InitParser(AllocFunction, FreeFunction, ZeroFunction, CopyFunction, DebugFunction, &Parser);
+
+    //
+    // get scaled usage value
+    //
+    return HidParser_GetUsageValue(&Parser, PreparsedData, ReportType, UsagePage, LinkCollection, Usage, UsageValue, Report, ReportLength);
+}
+
+
 HIDAPI
 NTSTATUS
 NTAPI
@@ -405,24 +437,6 @@ HidP_GetLinkCollectionNodes(
     return STATUS_NOT_IMPLEMENTED;
 }
 
-HIDAPI
-NTSTATUS
-NTAPI
-HidP_GetUsageValue(
-  IN HIDP_REPORT_TYPE  ReportType,
-  IN USAGE  UsagePage,
-  IN USHORT  LinkCollection,
-  IN USAGE  Usage,
-  OUT PULONG  UsageValue,
-  IN PHIDP_PREPARSED_DATA  PreparsedData,
-  IN PCHAR  Report,
-  IN ULONG  ReportLength)
-{
-    UNIMPLEMENTED
-    ASSERT(FALSE);
-    return STATUS_NOT_IMPLEMENTED;
-}
-
 NTSTATUS
 NTAPI
 HidP_SysPowerEvent (
index b713b70..6ba3007 100644 (file)
@@ -37,6 +37,7 @@ MouHid_GetButtonMove(
     OUT PLONG LastY)
 {
     NTSTATUS Status;
+    ULONG ValueX, ValueY;
 
     /* init result */
     *LastX = 0;
@@ -44,16 +45,49 @@ 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(
@@ -132,6 +166,12 @@ MouHid_GetButtonFlags(
     TempList = DeviceExtension->CurrentUsageList;
     DeviceExtension->CurrentUsageList = DeviceExtension->PreviousUsageList;
     DeviceExtension->PreviousUsageList = TempList;
+
+    if (DeviceExtension->MouseAbsolute)
+    {
+        // mouse operates absolute
+        *ButtonFlags |= MOUSE_MOVE_ABSOLUTE;
+    }
 }
 
 VOID
@@ -195,12 +235,12 @@ 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);
+
     /* init input data */
     RtlZeroMemory(&MouseInputData, sizeof(MOUSE_INPUT_DATA));
 
@@ -227,6 +267,12 @@ MouHid_ReadCompletion(
         }
     }
 
+    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 */
@@ -700,10 +746,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;
index 78048fd..e177a2f 100644 (file)
@@ -109,6 +109,22 @@ typedef struct
     //
     UCHAR StopReadReport;
 
+    //
+    // mouse absolute
+    //
+    UCHAR MouseAbsolute;
+
+    //
+    // value caps x
+    //
+    HIDP_VALUE_CAPS ValueCapsX;
+
+    //
+    // value caps y button
+    //
+    HIDP_VALUE_CAPS ValueCapsY;
+
+
 }MOUHID_DEVICE_EXTENSION, *PMOUHID_DEVICE_EXTENSION;
 
 #define WHEEL_DELTA 120
index 1420da7..ee77899 100644 (file)
@@ -563,6 +563,103 @@ HidParser_UsesReportId(
 
 }
 
+HIDPARSER_STATUS
+HidParser_GetUsageValueWithReport(
+    IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType,
+    IN USAGE UsagePage,
+    IN USAGE  Usage,
+    OUT PULONG UsageValue,
+    IN PCHAR ReportDescriptor,
+    IN ULONG ReportDescriptorLength)
+{
+    ULONG Index;
+    PHID_REPORT Report;
+    USHORT CurrentUsagePage;
+    PHID_REPORT_ITEM ReportItem;
+    ULONG Data;
+
+    //
+    // get report
+    //
+    Report = HidParser_GetReportInCollection(CollectionContext, ReportType);
+    if (!Report)
+    {
+        //
+        // no such report
+        //
+        return HIDPARSER_STATUS_REPORT_NOT_FOUND;
+    }
+
+    if (Report->ReportSize / 8 != (ReportDescriptorLength - 1))
+    {
+        //
+        // invalid report descriptor length
+        //
+        return HIDPARSER_STATUS_INVALID_REPORT_LENGTH;
+    }
+
+    for(Index = 0; Index < Report->ItemCount; Index++)
+    {
+        //
+        // get report item
+        //
+        ReportItem = &Report->Items[Index];
+
+        //
+        // check usage page
+        //
+        CurrentUsagePage = (ReportItem->UsageMinimum >> 16);
+
+        //
+        // does usage page match
+        //
+        if (UsagePage != CurrentUsagePage)
+            continue;
+
+        //
+        // does the usage match
+        //
+        if (Usage != (ReportItem->UsageMinimum & 0xFFFF))
+            continue;
+
+        //
+        // check if the specified usage is activated
+        //
+        ASSERT(ReportItem->ByteOffset < ReportDescriptorLength);
+
+        //
+        // one extra shift for skipping the prepended report id
+        //
+        Data = 0;
+        Parser->Copy(&Data, &ReportDescriptor[ReportItem->ByteOffset +1], min(sizeof(ULONG), ReportDescriptorLength - (ReportItem->ByteOffset + 1)));
+        //Data = ReportDescriptor[ReportItem->ByteOffset + 1];
+
+        //
+        // shift data
+        //
+        Data >>= ReportItem->Shift;
+
+        //
+        // clear unwanted bits
+        //
+        Data &= ReportItem->Mask;
+
+        //
+        // store result
+        //
+        *UsageValue = Data;
+        return HIDPARSER_STATUS_SUCCESS;
+    }
+
+    //
+    // usage not found
+    //
+    return HIDPARSER_STATUS_USAGE_NOT_FOUND;
+}
+
+
 
 HIDPARSER_STATUS
 HidParser_GetScaledUsageValueWithReport(
@@ -652,11 +749,18 @@ HidParser_GetScaledUsageValueWithReport(
             //
             // logical boundaries are signed values
             //
+
+            // FIXME: scale with physical min/max
             if ((Data & ~(ReportItem->Mask >> 1)) != 0)
             {
                 Data |= ~ReportItem->Mask;
             }
         }
+        else
+        {
+            // HACK: logical boundaries are absolute values
+            return HIDPARSER_STATUS_BAD_LOG_PHY_VALUES;
+        }
 
         //
         // store result
index c38b8e1..cc27cd8 100644 (file)
@@ -34,6 +34,8 @@ TranslateHidParserStatus(
             return HIDP_STATUS_I8042_TRANS_UNKNOWN;
         case HIDPARSER_STATUS_COLLECTION_NOT_FOUND:
             return HIDP_STATUS_NOT_IMPLEMENTED; //FIXME
+        case HIDPARSER_STATUS_BAD_LOG_PHY_VALUES:
+            return HIDP_STATUS_BAD_LOG_PHY_VALUES;
     }
     DPRINT1("TranslateHidParserStatus Status %ld not implemented\n", Status);
     return HIDP_STATUS_NOT_IMPLEMENTED;
@@ -952,9 +954,54 @@ HidParser_GetUsageValue(
     IN PCHAR  Report,
     IN ULONG  ReportLength)
 {
-    UNIMPLEMENTED
-    ASSERT(FALSE);
-    return STATUS_NOT_IMPLEMENTED;
+    HIDPARSER_STATUS ParserStatus;
+
+    //
+    // FIXME: implement searching in specific collection
+    //
+    ASSERT(LinkCollection == HIDP_LINK_COLLECTION_UNSPECIFIED);
+
+    if (ReportType == HidP_Input)
+    {
+        //
+        // input report
+        //
+        ParserStatus = HidParser_GetUsageValueWithReport(Parser, CollectionContext, HID_REPORT_TYPE_INPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
+    }
+    else if (ReportType == HidP_Output)
+    {
+        //
+        // input report
+        //
+        ParserStatus = HidParser_GetUsageValueWithReport(Parser, CollectionContext, HID_REPORT_TYPE_OUTPUT, UsagePage, Usage, UsageValue, Report, ReportLength);
+    }
+    else if (ReportType == HidP_Feature)
+    {
+        //
+        // input report
+        //
+        ParserStatus = HidParser_GetUsageValueWithReport(Parser, CollectionContext, HID_REPORT_TYPE_FEATURE,  UsagePage, Usage, UsageValue, Report, ReportLength);
+    }
+    else
+    {
+        //
+        // invalid report type
+        //
+        return HIDP_STATUS_INVALID_REPORT_TYPE;
+    }
+
+    if (ParserStatus == HIDPARSER_STATUS_SUCCESS)
+    {
+        //
+        // success
+        //
+        return HIDP_STATUS_SUCCESS;
+    }
+
+    //
+    // translate error
+    //
+    return TranslateHidParserStatus(ParserStatus);
 }
 
 NTSTATUS
index 425c208..ed7a616 100644 (file)
@@ -48,7 +48,8 @@ typedef enum
     HIDPARSER_STATUS_INVALID_REPORT_TYPE = -6,
     HIDPARSER_STATUS_BUFFER_TOO_SMALL = -7,
     HIDPARSER_STATUS_USAGE_NOT_FOUND = -8,
-    HIDPARSER_STATUS_I8042_TRANS_UNKNOWN = -9
+    HIDPARSER_STATUS_I8042_TRANS_UNKNOWN = -9,
+    HIDPARSER_STATUS_BAD_LOG_PHY_VALUES = -10
 }HIDPARSER_STATUS_CODES;
 
 typedef struct
@@ -200,6 +201,7 @@ HidParser_GetLinkCollectionNodes(
     OUT PHIDP_LINK_COLLECTION_NODE  LinkCollectionNodes,
     IN OUT PULONG  LinkCollectionNodesLength);
 
+
 HIDAPI
 NTSTATUS
 NTAPI
index ef0d7f3..a7126df 100644 (file)
@@ -327,6 +327,17 @@ HidParser_GetScaledUsageValueWithReport(
     IN PCHAR ReportDescriptor,
     IN ULONG ReportDescriptorLength);
 
+HIDPARSER_STATUS
+HidParser_GetUsageValueWithReport(
+    IN PHID_PARSER Parser,
+    IN PVOID CollectionContext,
+    IN UCHAR ReportType,
+    IN USAGE UsagePage,
+    IN USAGE  Usage,
+    OUT PULONG UsageValue,
+    IN PCHAR ReportDescriptor,
+    IN ULONG ReportDescriptorLength);
+
 /* parser.c */
 
 HIDPARSER_STATUS