[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
This commit is contained in:
Johannes Anderwald 2012-10-22 21:18:30 +00:00
parent 77520445a8
commit ed3d75f9de
7 changed files with 272 additions and 32 deletions

View file

@ -306,6 +306,38 @@ HidP_GetScaledUsageValue(
return HidParser_GetScaledUsageValue(&Parser, PreparsedData, ReportType, UsagePage, LinkCollection, Usage, UsageValue, Report, ReportLength); 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 HIDAPI
NTSTATUS NTSTATUS
NTAPI NTAPI
@ -405,24 +437,6 @@ HidP_GetLinkCollectionNodes(
return STATUS_NOT_IMPLEMENTED; 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 NTSTATUS
NTAPI NTAPI
HidP_SysPowerEvent ( HidP_SysPowerEvent (

View file

@ -37,6 +37,7 @@ MouHid_GetButtonMove(
OUT PLONG LastY) OUT PLONG LastY)
{ {
NTSTATUS Status; NTSTATUS Status;
ULONG ValueX, ValueY;
/* init result */ /* init result */
*LastX = 0; *LastX = 0;
@ -44,17 +45,50 @@ MouHid_GetButtonMove(
/* get scaled usage value x */ /* 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); 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 */ if (Status != HIDP_STATUS_SUCCESS)
ASSERT(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 */ /* 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); 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 */ if (Status != HIDP_STATUS_SUCCESS)
ASSERT(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 VOID
MouHid_GetButtonFlags( MouHid_GetButtonFlags(
IN PMOUHID_DEVICE_EXTENSION DeviceExtension, IN PMOUHID_DEVICE_EXTENSION DeviceExtension,
@ -132,6 +166,12 @@ MouHid_GetButtonFlags(
TempList = DeviceExtension->CurrentUsageList; TempList = DeviceExtension->CurrentUsageList;
DeviceExtension->CurrentUsageList = DeviceExtension->PreviousUsageList; DeviceExtension->CurrentUsageList = DeviceExtension->PreviousUsageList;
DeviceExtension->PreviousUsageList = TempList; DeviceExtension->PreviousUsageList = TempList;
if (DeviceExtension->MouseAbsolute)
{
// mouse operates absolute
*ButtonFlags |= MOUSE_MOVE_ABSOLUTE;
}
} }
VOID VOID
@ -195,12 +235,12 @@ MouHid_ReadCompletion(
return STATUS_MORE_PROCESSING_REQUIRED; return STATUS_MORE_PROCESSING_REQUIRED;
} }
/* get mouse change flags */
MouHid_GetButtonFlags(DeviceExtension, &ButtonFlags);
/* get mouse change */ /* get mouse change */
MouHid_GetButtonMove(DeviceExtension, &LastX, &LastY); MouHid_GetButtonMove(DeviceExtension, &LastX, &LastY);
/* get mouse change flags */
MouHid_GetButtonFlags(DeviceExtension, &ButtonFlags);
/* init input data */ /* init input data */
RtlZeroMemory(&MouseInputData, sizeof(MOUSE_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); DPRINT("[MOUHID] LastX %ld LastY %ld Flags %x ButtonData %x\n", MouseInputData.LastX, MouseInputData.LastY, MouseInputData.ButtonFlags, MouseInputData.ButtonData);
/* dispatch mouse action */ /* dispatch mouse action */
@ -700,10 +746,10 @@ MouHid_StartDevice(
DeviceExtension->PreparsedData = PreparsedData; DeviceExtension->PreparsedData = PreparsedData;
ValueCapsLength = 1; 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; 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 */ /* now check for wheel mouse support */
ValueCapsLength = 1; ValueCapsLength = 1;

View file

@ -109,6 +109,22 @@ typedef struct
// //
UCHAR StopReadReport; 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; }MOUHID_DEVICE_EXTENSION, *PMOUHID_DEVICE_EXTENSION;
#define WHEEL_DELTA 120 #define WHEEL_DELTA 120

View 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_STATUS
HidParser_GetScaledUsageValueWithReport( HidParser_GetScaledUsageValueWithReport(
@ -652,11 +749,18 @@ HidParser_GetScaledUsageValueWithReport(
// //
// logical boundaries are signed values // logical boundaries are signed values
// //
// FIXME: scale with physical min/max
if ((Data & ~(ReportItem->Mask >> 1)) != 0) if ((Data & ~(ReportItem->Mask >> 1)) != 0)
{ {
Data |= ~ReportItem->Mask; Data |= ~ReportItem->Mask;
} }
} }
else
{
// HACK: logical boundaries are absolute values
return HIDPARSER_STATUS_BAD_LOG_PHY_VALUES;
}
// //
// store result // store result

View file

@ -34,6 +34,8 @@ TranslateHidParserStatus(
return HIDP_STATUS_I8042_TRANS_UNKNOWN; return HIDP_STATUS_I8042_TRANS_UNKNOWN;
case HIDPARSER_STATUS_COLLECTION_NOT_FOUND: case HIDPARSER_STATUS_COLLECTION_NOT_FOUND:
return HIDP_STATUS_NOT_IMPLEMENTED; //FIXME 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); DPRINT1("TranslateHidParserStatus Status %ld not implemented\n", Status);
return HIDP_STATUS_NOT_IMPLEMENTED; return HIDP_STATUS_NOT_IMPLEMENTED;
@ -952,9 +954,54 @@ HidParser_GetUsageValue(
IN PCHAR Report, IN PCHAR Report,
IN ULONG ReportLength) IN ULONG ReportLength)
{ {
UNIMPLEMENTED HIDPARSER_STATUS ParserStatus;
ASSERT(FALSE);
return STATUS_NOT_IMPLEMENTED; //
// 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 NTSTATUS

View file

@ -48,7 +48,8 @@ typedef enum
HIDPARSER_STATUS_INVALID_REPORT_TYPE = -6, HIDPARSER_STATUS_INVALID_REPORT_TYPE = -6,
HIDPARSER_STATUS_BUFFER_TOO_SMALL = -7, HIDPARSER_STATUS_BUFFER_TOO_SMALL = -7,
HIDPARSER_STATUS_USAGE_NOT_FOUND = -8, 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; }HIDPARSER_STATUS_CODES;
typedef struct typedef struct
@ -200,6 +201,7 @@ HidParser_GetLinkCollectionNodes(
OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes, OUT PHIDP_LINK_COLLECTION_NODE LinkCollectionNodes,
IN OUT PULONG LinkCollectionNodesLength); IN OUT PULONG LinkCollectionNodesLength);
HIDAPI HIDAPI
NTSTATUS NTSTATUS
NTAPI NTAPI

View file

@ -327,6 +327,17 @@ HidParser_GetScaledUsageValueWithReport(
IN PCHAR ReportDescriptor, IN PCHAR ReportDescriptor,
IN ULONG ReportDescriptorLength); 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 */ /* parser.c */
HIDPARSER_STATUS HIDPARSER_STATUS