From ed3d75f9deb7c80b4041ac43475ff9e17bf0c4ab Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Mon, 22 Oct 2012 21:18:30 +0000 Subject: [PATCH] [HIDPARSE][HIDPARSER] - 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 | 50 +++++++---- reactos/drivers/hid/mouhid/mouhid.c | 66 +++++++++++--- reactos/drivers/hid/mouhid/mouhid.h | 16 ++++ reactos/lib/drivers/hidparser/api.c | 104 ++++++++++++++++++++++ reactos/lib/drivers/hidparser/hidparser.c | 53 ++++++++++- reactos/lib/drivers/hidparser/hidparser.h | 4 +- reactos/lib/drivers/hidparser/parser.h | 11 +++ 7 files changed, 272 insertions(+), 32 deletions(-) diff --git a/reactos/drivers/hid/hidparse/hidparse.c b/reactos/drivers/hid/hidparse/hidparse.c index d44310630d8..4254fd7c633 100644 --- a/reactos/drivers/hid/hidparse/hidparse.c +++ b/reactos/drivers/hid/hidparse/hidparse.c @@ -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 ( diff --git a/reactos/drivers/hid/mouhid/mouhid.c b/reactos/drivers/hid/mouhid/mouhid.c index b713b70f3dc..6ba3007048f 100644 --- a/reactos/drivers/hid/mouhid/mouhid.c +++ b/reactos/drivers/hid/mouhid/mouhid.c @@ -37,6 +37,7 @@ MouHid_GetButtonMove( OUT PLONG LastY) { NTSTATUS Status; + ULONG ValueX, ValueY; /* init result */ *LastX = 0; @@ -44,17 +45,50 @@ 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, @@ -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; diff --git a/reactos/drivers/hid/mouhid/mouhid.h b/reactos/drivers/hid/mouhid/mouhid.h index 78048fdce5d..e177a2ff985 100644 --- a/reactos/drivers/hid/mouhid/mouhid.h +++ b/reactos/drivers/hid/mouhid/mouhid.h @@ -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 diff --git a/reactos/lib/drivers/hidparser/api.c b/reactos/lib/drivers/hidparser/api.c index 1420da7ffb7..ee77899ae21 100644 --- a/reactos/lib/drivers/hidparser/api.c +++ b/reactos/lib/drivers/hidparser/api.c @@ -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 diff --git a/reactos/lib/drivers/hidparser/hidparser.c b/reactos/lib/drivers/hidparser/hidparser.c index c38b8e1c978..cc27cd8c10c 100644 --- a/reactos/lib/drivers/hidparser/hidparser.c +++ b/reactos/lib/drivers/hidparser/hidparser.c @@ -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 diff --git a/reactos/lib/drivers/hidparser/hidparser.h b/reactos/lib/drivers/hidparser/hidparser.h index 425c20899e1..ed7a616b638 100644 --- a/reactos/lib/drivers/hidparser/hidparser.h +++ b/reactos/lib/drivers/hidparser/hidparser.h @@ -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 diff --git a/reactos/lib/drivers/hidparser/parser.h b/reactos/lib/drivers/hidparser/parser.h index ef0d7f3e421..a7126df678d 100644 --- a/reactos/lib/drivers/hidparser/parser.h +++ b/reactos/lib/drivers/hidparser/parser.h @@ -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