mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[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:
parent
77520445a8
commit
ed3d75f9de
7 changed files with 272 additions and 32 deletions
|
@ -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 (
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue