hid: Change format of preparsed data.
Advantages of this format: - all table elements have constant size, that makes iterating table easier - allow report lookup by report ID in O(1) time - doesn't sort reports, it makes it possible to preserve original order of elements making output of functions more similar to native - preparsed data is created from collection, this will allow to add support for multiple top-most collections Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Aric Stewart <aric@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
421c83cd7b
commit
395d268565
237
dlls/hid/hidp.c
237
dlls/hid/hidp.c
|
@ -123,6 +123,7 @@ NTSTATUS WINAPI HidP_GetButtonCaps(HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAP
|
|||
PUSHORT ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData)
|
||||
{
|
||||
PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
|
||||
WINE_HID_ELEMENT *elems = HID_ELEMS(data);
|
||||
WINE_HID_REPORT *report = NULL;
|
||||
USHORT b_count = 0, r_count = 0;
|
||||
int i,j,u;
|
||||
|
@ -136,24 +137,22 @@ NTSTATUS WINAPI HidP_GetButtonCaps(HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAP
|
|||
{
|
||||
case HidP_Input:
|
||||
b_count = data->caps.NumberInputButtonCaps;
|
||||
r_count = data->dwInputReportCount;
|
||||
report = HID_INPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Output:
|
||||
b_count = data->caps.NumberOutputButtonCaps;
|
||||
r_count = data->dwOutputReportCount;
|
||||
report = HID_OUTPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Feature:
|
||||
b_count = data->caps.NumberFeatureButtonCaps;
|
||||
r_count = data->dwFeatureReportCount;
|
||||
report = HID_FEATURE_REPORTS(data);
|
||||
break;
|
||||
default:
|
||||
return HIDP_STATUS_INVALID_REPORT_TYPE;
|
||||
}
|
||||
r_count = data->reportCount[ReportType];
|
||||
|
||||
if (!r_count || !b_count || !report)
|
||||
if (!r_count || !b_count)
|
||||
{
|
||||
*ButtonCapsLength = 0;
|
||||
return HIDP_STATUS_SUCCESS;
|
||||
|
@ -164,12 +163,11 @@ NTSTATUS WINAPI HidP_GetButtonCaps(HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAP
|
|||
u = 0;
|
||||
for (j = 0; j < r_count && u < b_count; j++)
|
||||
{
|
||||
for (i = 0; i < report->elementCount && u < b_count; i++)
|
||||
for (i = 0; i < report[j].elementCount && u < b_count; i++)
|
||||
{
|
||||
if (report->Elements[i].ElementType == ButtonElement)
|
||||
ButtonCaps[u++] = report->Elements[i].caps.button;
|
||||
if (elems[report[j].elementIdx + i].ElementType == ButtonElement)
|
||||
ButtonCaps[u++] = elems[report[j].elementIdx + i].caps.button;
|
||||
}
|
||||
report = HID_NEXT_REPORT(data, report);
|
||||
}
|
||||
|
||||
*ButtonCapsLength = b_count;
|
||||
|
@ -197,6 +195,7 @@ static NTSTATUS find_value(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT
|
|||
WINE_HID_ELEMENT *element)
|
||||
{
|
||||
PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
|
||||
WINE_HID_ELEMENT *elems = HID_ELEMS(data);
|
||||
WINE_HID_REPORT *report = NULL;
|
||||
USHORT v_count = 0, r_count = 0;
|
||||
int i;
|
||||
|
@ -210,54 +209,43 @@ static NTSTATUS find_value(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT
|
|||
{
|
||||
case HidP_Input:
|
||||
v_count = data->caps.NumberInputValueCaps;
|
||||
r_count = data->dwInputReportCount;
|
||||
report = HID_INPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Output:
|
||||
v_count = data->caps.NumberOutputValueCaps;
|
||||
r_count = data->dwOutputReportCount;
|
||||
report = HID_OUTPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Feature:
|
||||
v_count = data->caps.NumberFeatureValueCaps;
|
||||
r_count = data->dwFeatureReportCount;
|
||||
report = HID_FEATURE_REPORTS(data);
|
||||
break;
|
||||
default:
|
||||
return HIDP_STATUS_INVALID_REPORT_TYPE;
|
||||
}
|
||||
r_count = data->reportCount[ReportType];
|
||||
report = &data->reports[data->reportIdx[ReportType][(BYTE)Report[0]]];
|
||||
|
||||
if (!r_count || !v_count || !report)
|
||||
if (!r_count || !v_count)
|
||||
return HIDP_STATUS_USAGE_NOT_FOUND;
|
||||
|
||||
for (i = 0; i < r_count; i++)
|
||||
{
|
||||
if (!report->reportID || report->reportID == Report[0])
|
||||
break;
|
||||
report = HID_NEXT_REPORT(data, report);
|
||||
}
|
||||
|
||||
if (i == r_count)
|
||||
if (report->reportID && report->reportID != Report[0])
|
||||
return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
|
||||
|
||||
for (i = 0; i < report->elementCount; i++)
|
||||
{
|
||||
HIDP_VALUE_CAPS *value = &report->Elements[i].caps.value;
|
||||
HIDP_VALUE_CAPS *value = &elems[report->elementIdx + i].caps.value;
|
||||
|
||||
if (report->Elements[i].ElementType != ValueElement ||
|
||||
if (elems[report->elementIdx + i].ElementType != ValueElement ||
|
||||
value->UsagePage != UsagePage)
|
||||
continue;
|
||||
|
||||
if (value->IsRange && value->u.Range.UsageMin <= Usage && Usage <= value->u.Range.UsageMax)
|
||||
{
|
||||
*element = report->Elements[i];
|
||||
*element = elems[report->elementIdx + i];
|
||||
element->valueStartBit += value->BitSize * (Usage - value->u.Range.UsageMin);
|
||||
element->bitCount = value->BitSize;
|
||||
return HIDP_STATUS_SUCCESS;
|
||||
}
|
||||
else if (report->Elements[i].caps.value.u.NotRange.Usage == Usage)
|
||||
else if (value->u.NotRange.Usage == Usage)
|
||||
{
|
||||
*element = report->Elements[i];
|
||||
*element = elems[report->elementIdx + i];
|
||||
element->bitCount = value->BitSize;
|
||||
return HIDP_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -343,6 +331,7 @@ NTSTATUS WINAPI HidP_GetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USH
|
|||
PCHAR Report, ULONG ReportLength)
|
||||
{
|
||||
PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
|
||||
WINE_HID_ELEMENT *elems = HID_ELEMS(data);
|
||||
WINE_HID_REPORT *report = NULL;
|
||||
BOOL found = FALSE;
|
||||
USHORT b_count = 0, r_count = 0;
|
||||
|
@ -361,44 +350,33 @@ NTSTATUS WINAPI HidP_GetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USH
|
|||
{
|
||||
case HidP_Input:
|
||||
b_count = data->caps.NumberInputButtonCaps;
|
||||
r_count = data->dwInputReportCount;
|
||||
report = HID_INPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Output:
|
||||
b_count = data->caps.NumberOutputButtonCaps;
|
||||
r_count = data->dwOutputReportCount;
|
||||
report = HID_OUTPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Feature:
|
||||
b_count = data->caps.NumberFeatureButtonCaps;
|
||||
r_count = data->dwFeatureReportCount;
|
||||
report = HID_FEATURE_REPORTS(data);
|
||||
break;
|
||||
default:
|
||||
return HIDP_STATUS_INVALID_REPORT_TYPE;
|
||||
}
|
||||
r_count = data->reportCount[ReportType];
|
||||
report = &data->reports[data->reportIdx[ReportType][(BYTE)Report[0]]];
|
||||
|
||||
if (!r_count || !b_count || !report)
|
||||
if (!r_count || !b_count)
|
||||
return HIDP_STATUS_USAGE_NOT_FOUND;
|
||||
|
||||
for (i = 0; i < r_count; i++)
|
||||
{
|
||||
if (!report->reportID || report->reportID == Report[0])
|
||||
break;
|
||||
report = HID_NEXT_REPORT(data, report);
|
||||
}
|
||||
|
||||
if (i == r_count)
|
||||
if (report->reportID && report->reportID != Report[0])
|
||||
return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
|
||||
|
||||
uCount = 0;
|
||||
for (i = 0; i < report->elementCount && uCount < *UsageLength; i++)
|
||||
{
|
||||
if (report->Elements[i].ElementType == ButtonElement &&
|
||||
report->Elements[i].caps.button.UsagePage == UsagePage)
|
||||
if (elems[report->elementIdx + i].ElementType == ButtonElement &&
|
||||
elems[report->elementIdx + i].caps.button.UsagePage == UsagePage)
|
||||
{
|
||||
int k;
|
||||
WINE_HID_ELEMENT *element = &report->Elements[i];
|
||||
WINE_HID_ELEMENT *element = &elems[report->elementIdx + i];
|
||||
for (k=0; k < element->bitCount; k++)
|
||||
{
|
||||
UINT v = 0;
|
||||
|
@ -431,6 +409,7 @@ NTSTATUS WINAPI HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS
|
|||
PUSHORT ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData)
|
||||
{
|
||||
PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
|
||||
WINE_HID_ELEMENT *elems = HID_ELEMS(data);
|
||||
WINE_HID_REPORT *report = NULL;
|
||||
USHORT v_count = 0, r_count = 0;
|
||||
int i,j,u;
|
||||
|
@ -444,24 +423,22 @@ NTSTATUS WINAPI HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS
|
|||
{
|
||||
case HidP_Input:
|
||||
v_count = data->caps.NumberInputValueCaps;
|
||||
r_count = data->dwInputReportCount;
|
||||
report = HID_INPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Output:
|
||||
v_count = data->caps.NumberOutputValueCaps;
|
||||
r_count = data->dwOutputReportCount;
|
||||
report = HID_OUTPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Feature:
|
||||
v_count = data->caps.NumberFeatureValueCaps;
|
||||
r_count = data->dwFeatureReportCount;
|
||||
report = HID_FEATURE_REPORTS(data);
|
||||
break;
|
||||
default:
|
||||
return HIDP_STATUS_INVALID_REPORT_TYPE;
|
||||
}
|
||||
r_count = data->reportCount[ReportType];
|
||||
|
||||
if (!r_count || !v_count || !report)
|
||||
if (!r_count || !v_count)
|
||||
{
|
||||
*ValueCapsLength = 0;
|
||||
return HIDP_STATUS_SUCCESS;
|
||||
|
@ -472,12 +449,11 @@ NTSTATUS WINAPI HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS
|
|||
u = 0;
|
||||
for (j = 0; j < r_count && u < v_count; j++)
|
||||
{
|
||||
for (i = 0; i < report->elementCount && u < v_count; i++)
|
||||
for (i = 0; i < report[j].elementCount && u < v_count; i++)
|
||||
{
|
||||
if (report->Elements[i].ElementType == ValueElement)
|
||||
ValueCaps[u++] = report->Elements[i].caps.value;
|
||||
if (elems[report->elementIdx + i].ElementType == ValueElement)
|
||||
ValueCaps[u++] = elems[report->elementIdx + i].caps.value;
|
||||
}
|
||||
report = HID_NEXT_REPORT(data, report);
|
||||
}
|
||||
|
||||
*ValueCapsLength = v_count;
|
||||
|
@ -491,9 +467,7 @@ NTSTATUS WINAPI HidP_InitializeReportForID(HIDP_REPORT_TYPE ReportType, UCHAR Re
|
|||
int size;
|
||||
PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
|
||||
WINE_HID_REPORT *report = NULL;
|
||||
BOOL found=FALSE;
|
||||
int r_count;
|
||||
int i;
|
||||
|
||||
TRACE("(%i, %i, %p, %p, %i)\n",ReportType, ReportID, PreparsedData, Report, ReportLength);
|
||||
|
||||
|
@ -504,52 +478,37 @@ NTSTATUS WINAPI HidP_InitializeReportForID(HIDP_REPORT_TYPE ReportType, UCHAR Re
|
|||
{
|
||||
case HidP_Input:
|
||||
size = data->caps.InputReportByteLength;
|
||||
report = HID_INPUT_REPORTS(data);
|
||||
r_count = data->dwInputReportCount;
|
||||
break;
|
||||
case HidP_Output:
|
||||
size = data->caps.OutputReportByteLength;
|
||||
report = HID_OUTPUT_REPORTS(data);
|
||||
r_count = data->dwOutputReportCount;
|
||||
break;
|
||||
case HidP_Feature:
|
||||
size = data->caps.FeatureReportByteLength;
|
||||
report = HID_FEATURE_REPORTS(data);
|
||||
r_count = data->dwFeatureReportCount;
|
||||
break;
|
||||
default:
|
||||
return HIDP_STATUS_INVALID_REPORT_TYPE;
|
||||
}
|
||||
r_count = data->reportCount[ReportType];
|
||||
report = &data->reports[data->reportIdx[ReportType][(BYTE)Report[0]]];
|
||||
|
||||
if (!r_count || !size || !report)
|
||||
if (!r_count || !size)
|
||||
return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
|
||||
|
||||
if (size != ReportLength)
|
||||
return HIDP_STATUS_INVALID_REPORT_LENGTH;
|
||||
|
||||
ZeroMemory(Report, size);
|
||||
|
||||
for (i = 0; i < r_count; i++)
|
||||
{
|
||||
if (report->reportID == ReportID)
|
||||
{
|
||||
found = TRUE;
|
||||
if (report->reportID)
|
||||
Report[0] = ReportID;
|
||||
/* TODO: Handle null and default values */
|
||||
}
|
||||
report = HID_NEXT_REPORT(data, report);
|
||||
}
|
||||
|
||||
if (!found)
|
||||
if (report->reportID && report->reportID != Report[0])
|
||||
return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
|
||||
|
||||
ZeroMemory(Report, size);
|
||||
Report[0] = ReportID;
|
||||
return HIDP_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ULONG WINAPI HidP_MaxUsageListLength(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, PHIDP_PREPARSED_DATA PreparsedData)
|
||||
{
|
||||
PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
|
||||
WINE_HID_ELEMENT *elems = HID_ELEMS(data);
|
||||
WINE_HID_REPORT *report = NULL;
|
||||
int r_count;
|
||||
int i;
|
||||
|
@ -564,39 +523,37 @@ ULONG WINAPI HidP_MaxUsageListLength(HIDP_REPORT_TYPE ReportType, USAGE UsagePag
|
|||
{
|
||||
case HidP_Input:
|
||||
report = HID_INPUT_REPORTS(data);
|
||||
r_count = data->dwInputReportCount;
|
||||
break;
|
||||
case HidP_Output:
|
||||
report = HID_OUTPUT_REPORTS(data);
|
||||
r_count = data->dwOutputReportCount;
|
||||
break;
|
||||
case HidP_Feature:
|
||||
report = HID_FEATURE_REPORTS(data);
|
||||
r_count = data->dwFeatureReportCount;
|
||||
break;
|
||||
default:
|
||||
return HIDP_STATUS_INVALID_REPORT_TYPE;
|
||||
}
|
||||
r_count = data->reportCount[ReportType];
|
||||
|
||||
if (!r_count || !report)
|
||||
|
||||
if (!r_count)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < r_count; i++)
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < report->elementCount; j++)
|
||||
for (j = 0; j < report[i].elementCount; j++)
|
||||
{
|
||||
if (report->Elements[j].ElementType == ButtonElement &&
|
||||
(UsagePage == 0 || report->Elements[j].caps.button.UsagePage == UsagePage))
|
||||
if (elems[report[i].elementIdx + j].ElementType == ButtonElement &&
|
||||
(UsagePage == 0 || elems[report[i].elementIdx + j].caps.button.UsagePage == UsagePage))
|
||||
{
|
||||
if (report->Elements[j].caps.button.IsRange)
|
||||
count += (report->Elements[j].caps.button.u.Range.UsageMax -
|
||||
report->Elements[j].caps.button.u.Range.UsageMin) + 1;
|
||||
if (elems[report[i].elementIdx + j].caps.button.IsRange)
|
||||
count += (elems[report[i].elementIdx + j].caps.button.u.Range.UsageMax -
|
||||
elems[report[i].elementIdx + j].caps.button.u.Range.UsageMin) + 1;
|
||||
else
|
||||
count++;
|
||||
}
|
||||
}
|
||||
report = HID_NEXT_REPORT(data, report);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -671,6 +628,7 @@ NTSTATUS WINAPI HidP_GetSpecificButtonCaps(HIDP_REPORT_TYPE ReportType,
|
|||
HIDP_BUTTON_CAPS *ButtonCaps, USHORT *ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData)
|
||||
{
|
||||
WINE_HIDP_PREPARSED_DATA *data = (WINE_HIDP_PREPARSED_DATA*)PreparsedData;
|
||||
WINE_HID_ELEMENT *elems = HID_ELEMS(data);
|
||||
WINE_HID_REPORT *report = NULL;
|
||||
USHORT b_count = 0, r_count = 0;
|
||||
int i,j,u;
|
||||
|
@ -685,24 +643,22 @@ NTSTATUS WINAPI HidP_GetSpecificButtonCaps(HIDP_REPORT_TYPE ReportType,
|
|||
{
|
||||
case HidP_Input:
|
||||
b_count = data->caps.NumberInputButtonCaps;
|
||||
r_count = data->dwInputReportCount;
|
||||
report = HID_INPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Output:
|
||||
b_count = data->caps.NumberOutputButtonCaps;
|
||||
r_count = data->dwOutputReportCount;
|
||||
report = HID_OUTPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Feature:
|
||||
b_count = data->caps.NumberFeatureButtonCaps;
|
||||
r_count = data->dwFeatureReportCount;
|
||||
report = HID_FEATURE_REPORTS(data);
|
||||
break;
|
||||
default:
|
||||
return HIDP_STATUS_INVALID_REPORT_TYPE;
|
||||
}
|
||||
r_count = data->reportCount[ReportType];
|
||||
|
||||
if (!r_count || !b_count || !report)
|
||||
if (!r_count || !b_count)
|
||||
{
|
||||
*ButtonCapsLength = 0;
|
||||
return HIDP_STATUS_SUCCESS;
|
||||
|
@ -713,22 +669,21 @@ NTSTATUS WINAPI HidP_GetSpecificButtonCaps(HIDP_REPORT_TYPE ReportType,
|
|||
u = 0;
|
||||
for (j = 0; j < r_count && u < b_count; j++)
|
||||
{
|
||||
for (i = 0; i < report->elementCount && u < b_count; i++)
|
||||
for (i = 0; i < report[j].elementCount && u < b_count; i++)
|
||||
{
|
||||
if (report->Elements[i].ElementType == ButtonElement &&
|
||||
(UsagePage == 0 || UsagePage == report->Elements[i].caps.button.UsagePage) &&
|
||||
(LinkCollection == 0 || LinkCollection == report->Elements[i].caps.button.LinkCollection) &&
|
||||
if (elems[report[j].elementIdx + i].ElementType == ButtonElement &&
|
||||
(UsagePage == 0 || UsagePage == elems[report[j].elementIdx + i].caps.button.UsagePage) &&
|
||||
(LinkCollection == 0 || LinkCollection == elems[report[j].elementIdx + i].caps.button.LinkCollection) &&
|
||||
(Usage == 0 || (
|
||||
(!report->Elements[i].caps.button.IsRange &&
|
||||
Usage == report->Elements[i].caps.button.u.NotRange.Usage)) ||
|
||||
(report->Elements[i].caps.button.IsRange &&
|
||||
Usage >=report->Elements[i].caps.button.u.Range.UsageMin &&
|
||||
Usage <= report->Elements[i].caps.button.u.Range.UsageMax)))
|
||||
(!elems[report[j].elementIdx + i].caps.button.IsRange &&
|
||||
Usage == elems[report[j].elementIdx + i].caps.button.u.NotRange.Usage)) ||
|
||||
(elems[report[j].elementIdx + i].caps.button.IsRange &&
|
||||
Usage >= elems[report[j].elementIdx + i].caps.button.u.Range.UsageMin &&
|
||||
Usage <= elems[report[j].elementIdx + i].caps.button.u.Range.UsageMax)))
|
||||
{
|
||||
ButtonCaps[u++] = report->Elements[i].caps.button;
|
||||
ButtonCaps[u++] = elems[report[j].elementIdx + i].caps.button;
|
||||
}
|
||||
}
|
||||
report = HID_NEXT_REPORT(data, report);
|
||||
}
|
||||
TRACE("Matched %i usages\n", u);
|
||||
|
||||
|
@ -743,6 +698,7 @@ NTSTATUS WINAPI HidP_GetSpecificValueCaps(HIDP_REPORT_TYPE ReportType,
|
|||
HIDP_VALUE_CAPS *ValueCaps, USHORT *ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData)
|
||||
{
|
||||
WINE_HIDP_PREPARSED_DATA *data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData;
|
||||
WINE_HID_ELEMENT *elems = HID_ELEMS(data);
|
||||
WINE_HID_REPORT *report = NULL;
|
||||
USHORT v_count = 0, r_count = 0;
|
||||
int i,j,u;
|
||||
|
@ -757,24 +713,22 @@ NTSTATUS WINAPI HidP_GetSpecificValueCaps(HIDP_REPORT_TYPE ReportType,
|
|||
{
|
||||
case HidP_Input:
|
||||
v_count = data->caps.NumberInputValueCaps;
|
||||
r_count = data->dwInputReportCount;
|
||||
report = HID_INPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Output:
|
||||
v_count = data->caps.NumberOutputValueCaps;
|
||||
r_count = data->dwOutputReportCount;
|
||||
report = HID_OUTPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Feature:
|
||||
v_count = data->caps.NumberFeatureValueCaps;
|
||||
r_count = data->dwFeatureReportCount;
|
||||
report = HID_FEATURE_REPORTS(data);
|
||||
break;
|
||||
default:
|
||||
return HIDP_STATUS_INVALID_REPORT_TYPE;
|
||||
}
|
||||
r_count = data->reportCount[ReportType];
|
||||
|
||||
if (!r_count || !v_count || !report)
|
||||
if (!r_count || !v_count)
|
||||
{
|
||||
*ValueCapsLength = 0;
|
||||
return HIDP_STATUS_SUCCESS;
|
||||
|
@ -785,17 +739,16 @@ NTSTATUS WINAPI HidP_GetSpecificValueCaps(HIDP_REPORT_TYPE ReportType,
|
|||
u = 0;
|
||||
for (j = 0; j < r_count && u < v_count; j++)
|
||||
{
|
||||
for (i = 0; i < report->elementCount && u < v_count; i++)
|
||||
for (i = 0; i < report[j].elementCount && u < v_count; i++)
|
||||
{
|
||||
if (report->Elements[i].ElementType == ValueElement &&
|
||||
(UsagePage == 0 || UsagePage == report->Elements[i].caps.value.UsagePage) &&
|
||||
(LinkCollection == 0 || LinkCollection == report->Elements[i].caps.value.LinkCollection) &&
|
||||
(Usage == 0 || Usage == report->Elements[i].caps.value.u.NotRange.Usage))
|
||||
if (elems[report[j].elementIdx + i].ElementType == ValueElement &&
|
||||
(UsagePage == 0 || UsagePage == elems[report[j].elementIdx + i].caps.value.UsagePage) &&
|
||||
(LinkCollection == 0 || LinkCollection == elems[report[j].elementIdx + i].caps.value.LinkCollection) &&
|
||||
(Usage == 0 || Usage == elems[report[j].elementIdx + i].caps.value.u.NotRange.Usage))
|
||||
{
|
||||
ValueCaps[u++] = report->Elements[i].caps.value;
|
||||
ValueCaps[u++] = elems[report[j].elementIdx + i].caps.value;
|
||||
}
|
||||
}
|
||||
report = HID_NEXT_REPORT(data, report);
|
||||
}
|
||||
TRACE("Matched %i usages\n", u);
|
||||
|
||||
|
@ -808,6 +761,7 @@ NTSTATUS WINAPI HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType, USHORT LinkCollect
|
|||
ULONG *UsageLength, PHIDP_PREPARSED_DATA PreparsedData, CHAR *Report, ULONG ReportLength)
|
||||
{
|
||||
WINE_HIDP_PREPARSED_DATA *data = (WINE_HIDP_PREPARSED_DATA*)PreparsedData;
|
||||
WINE_HID_ELEMENT *elems = HID_ELEMS(data);
|
||||
WINE_HID_REPORT *report = NULL;
|
||||
USHORT b_count = 0, r_count = 0;
|
||||
int i,uCount = 0;
|
||||
|
@ -823,42 +777,31 @@ NTSTATUS WINAPI HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType, USHORT LinkCollect
|
|||
{
|
||||
case HidP_Input:
|
||||
b_count = data->caps.NumberInputButtonCaps;
|
||||
r_count = data->dwInputReportCount;
|
||||
report = HID_INPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Output:
|
||||
b_count = data->caps.NumberOutputButtonCaps;
|
||||
r_count = data->dwOutputReportCount;
|
||||
report = HID_OUTPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Feature:
|
||||
b_count = data->caps.NumberFeatureButtonCaps;
|
||||
r_count = data->dwFeatureReportCount;
|
||||
report = HID_FEATURE_REPORTS(data);
|
||||
break;
|
||||
default:
|
||||
return HIDP_STATUS_INVALID_REPORT_TYPE;
|
||||
}
|
||||
r_count = data->reportCount[ReportType];
|
||||
report = &data->reports[data->reportIdx[ReportType][(BYTE)Report[0]]];
|
||||
|
||||
if (!r_count || !b_count || !report)
|
||||
if (!r_count || !b_count)
|
||||
return HIDP_STATUS_USAGE_NOT_FOUND;
|
||||
|
||||
for (i = 0; i < r_count; i++)
|
||||
{
|
||||
if (!report->reportID || report->reportID == Report[0])
|
||||
break;
|
||||
report = HID_NEXT_REPORT(data, report);
|
||||
}
|
||||
|
||||
if (i == r_count)
|
||||
if (report->reportID && report->reportID != Report[0])
|
||||
return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
|
||||
|
||||
for (i = 0; i < report->elementCount; i++)
|
||||
{
|
||||
if (report->Elements[i].ElementType == ButtonElement)
|
||||
if (elems[report->elementIdx + i].ElementType == ButtonElement)
|
||||
{
|
||||
int k;
|
||||
WINE_HID_ELEMENT *element = &report->Elements[i];
|
||||
WINE_HID_ELEMENT *element = &elems[report->elementIdx + i];
|
||||
for (k=0; k < element->bitCount; k++)
|
||||
{
|
||||
UINT v = 0;
|
||||
|
@ -915,6 +858,7 @@ NTSTATUS WINAPI HidP_GetData(HIDP_REPORT_TYPE ReportType, HIDP_DATA *DataList, U
|
|||
PHIDP_PREPARSED_DATA PreparsedData,CHAR *Report, ULONG ReportLength)
|
||||
{
|
||||
WINE_HIDP_PREPARSED_DATA *data = (WINE_HIDP_PREPARSED_DATA*)PreparsedData;
|
||||
WINE_HID_ELEMENT *elems = HID_ELEMS(data);
|
||||
WINE_HID_REPORT *report = NULL;
|
||||
USHORT r_count = 0;
|
||||
int i,uCount = 0;
|
||||
|
@ -926,37 +870,18 @@ NTSTATUS WINAPI HidP_GetData(HIDP_REPORT_TYPE ReportType, HIDP_DATA *DataList, U
|
|||
if (data->magic != HID_MAGIC)
|
||||
return 0;
|
||||
|
||||
switch(ReportType)
|
||||
{
|
||||
case HidP_Input:
|
||||
r_count = data->dwInputReportCount;
|
||||
report = HID_INPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Output:
|
||||
r_count = data->dwOutputReportCount;
|
||||
report = HID_OUTPUT_REPORTS(data);
|
||||
break;
|
||||
case HidP_Feature:
|
||||
r_count = data->dwFeatureReportCount;
|
||||
report = HID_FEATURE_REPORTS(data);
|
||||
break;
|
||||
default:
|
||||
if (ReportType != HidP_Input && ReportType != HidP_Output && ReportType != HidP_Feature)
|
||||
return HIDP_STATUS_INVALID_REPORT_TYPE;
|
||||
}
|
||||
|
||||
for (i = 0; i < r_count; i++)
|
||||
{
|
||||
if (!report->reportID || report->reportID == Report[0])
|
||||
break;
|
||||
report = HID_NEXT_REPORT(data, report);
|
||||
}
|
||||
r_count = data->reportCount[ReportType];
|
||||
report = &data->reports[data->reportIdx[ReportType][(BYTE)Report[0]]];
|
||||
|
||||
if (i == r_count)
|
||||
if (!r_count || (report->reportID && report->reportID != Report[0]))
|
||||
return HIDP_STATUS_REPORT_DOES_NOT_EXIST;
|
||||
|
||||
for (i = 0; i < report->elementCount; i++)
|
||||
{
|
||||
WINE_HID_ELEMENT *element = &report->Elements[i];
|
||||
WINE_HID_ELEMENT *element = &elems[report->elementIdx + i];
|
||||
if (element->ElementType == ButtonElement)
|
||||
{
|
||||
int k;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Internal HID structures
|
||||
* Wine internal HID structures
|
||||
*
|
||||
* Copyright 2015 Aric Stewart
|
||||
*
|
||||
|
@ -18,18 +18,18 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __HID_PARSE_H
|
||||
#define __HID_PARSE_H
|
||||
#ifndef __WINE_PARSE_H
|
||||
#define __WINE_PARSE_H
|
||||
|
||||
#define HID_MAGIC 0x8491759
|
||||
|
||||
typedef enum {
|
||||
typedef enum __WINE_ELEMENT_TYPE {
|
||||
UnknownElement = 0,
|
||||
ButtonElement,
|
||||
ValueElement,
|
||||
} WINE_ELEMENT_TYPE;
|
||||
|
||||
typedef struct
|
||||
typedef struct __WINE_ELEMENT
|
||||
{
|
||||
WINE_ELEMENT_TYPE ElementType;
|
||||
UINT valueStartBit;
|
||||
|
@ -40,33 +40,30 @@ typedef struct
|
|||
} caps;
|
||||
} WINE_HID_ELEMENT;
|
||||
|
||||
typedef struct
|
||||
typedef struct __WINE_HID_REPORT
|
||||
{
|
||||
UCHAR reportID;
|
||||
DWORD dwSize;
|
||||
DWORD bitSize;
|
||||
DWORD elementCount;
|
||||
WINE_HID_ELEMENT Elements[1];
|
||||
DWORD elementIdx;
|
||||
} WINE_HID_REPORT;
|
||||
|
||||
typedef struct
|
||||
typedef struct __WINE_HIDP_PREPARSED_DATA
|
||||
{
|
||||
DWORD magic;
|
||||
DWORD dwSize;
|
||||
HIDP_CAPS caps;
|
||||
|
||||
DWORD dwInputReportCount;
|
||||
DWORD dwOutputReportCount;
|
||||
DWORD dwFeatureReportCount;
|
||||
DWORD elementOffset;
|
||||
DWORD reportCount[3];
|
||||
BYTE reportIdx[3][256];
|
||||
|
||||
DWORD dwOutputReportOffset;
|
||||
DWORD dwFeatureReportOffset;
|
||||
|
||||
WINE_HID_REPORT InputReports[1];
|
||||
WINE_HID_REPORT reports[1];
|
||||
} WINE_HIDP_PREPARSED_DATA, *PWINE_HIDP_PREPARSED_DATA;
|
||||
|
||||
#define HID_NEXT_REPORT(d,r) ((r)?(WINE_HID_REPORT*)(((BYTE*)(r))+(r)->dwSize):(d)->InputReports)
|
||||
#define HID_INPUT_REPORTS(d) ((d)->InputReports)
|
||||
#define HID_OUTPUT_REPORTS(d) ((WINE_HID_REPORT*)(((BYTE*)(d)->InputReports)+(d)->dwOutputReportOffset))
|
||||
#define HID_FEATURE_REPORTS(d) ((WINE_HID_REPORT*)(((BYTE*)(d)->InputReports)+(d)->dwFeatureReportOffset))
|
||||
#define HID_INPUT_REPORTS(d) ((d)->reports)
|
||||
#define HID_OUTPUT_REPORTS(d) ((d)->reports + (d)->reportCount[0])
|
||||
#define HID_FEATURE_REPORTS(d) ((d)->reports + (d)->reportCount[0] + (d)->reportCount[1])
|
||||
#define HID_ELEMS(d) ((WINE_HID_ELEMENT*)((BYTE*)(d) + (d)->elementOffset))
|
||||
|
||||
#endif /* __HID_PARSE_H */
|
||||
#endif /* __WINE_PARSE_H */
|
||||
|
|
|
@ -214,7 +214,9 @@ static void debugstr_caps(const char* type, struct caps *caps)
|
|||
{
|
||||
if (!caps)
|
||||
return;
|
||||
TRACE("(%s Caps: UsagePage 0x%x; LogicalMin %i; LogicalMax %i; PhysicalMin %i; PhysicalMax %i; UnitsExp %i; Units %i; BitSize %i; ReportID %i; ReportCount %i; Usage %s; StringIndex %s; DesignatorIndex %s; Delim %i;)\n",
|
||||
TRACE("(%s Caps: UsagePage 0x%x; LogicalMin %i; LogicalMax %i; PhysicalMin %i; "
|
||||
"PhysicalMax %i; UnitsExp %i; Units %i; BitSize %i; ReportID %i; ReportCount %i; "
|
||||
"Usage %s; StringIndex %s; DesignatorIndex %s; Delim %i;)\n",
|
||||
type,
|
||||
caps->UsagePage,
|
||||
caps->LogicalMin,
|
||||
|
@ -258,7 +260,9 @@ static void debug_collection(struct collection *collection)
|
|||
struct collection *centry;
|
||||
if (TRACE_ON(hid))
|
||||
{
|
||||
TRACE("START Collection %i <<< %s, parent: %p, %i features, %i collections\n", collection->index, collection_string[collection->type], collection->parent, list_count(&collection->features), list_count(&collection->collections));
|
||||
TRACE("START Collection %i <<< %s, parent: %p, %i features, %i collections\n",
|
||||
collection->index, collection_string[collection->type], collection->parent,
|
||||
list_count(&collection->features), list_count(&collection->collections));
|
||||
debugstr_caps("Collection", &collection->caps);
|
||||
LIST_FOR_EACH_ENTRY(fentry, &collection->features, struct feature, col_entry)
|
||||
debug_feature(fentry);
|
||||
|
@ -319,26 +323,38 @@ static void debug_print_element(const CHAR* type, WINE_HID_ELEMENT *wine_element
|
|||
TRACE("%s: UNKNOWN\n", type);
|
||||
}
|
||||
|
||||
static void debug_print_report(const char* type, WINE_HID_REPORT *report)
|
||||
static void debug_print_report(const char* type, WINE_HIDP_PREPARSED_DATA *data,
|
||||
WINE_HID_REPORT *report)
|
||||
{
|
||||
WINE_HID_ELEMENT *elem = HID_ELEMS(data);
|
||||
unsigned int i;
|
||||
TRACE("START Report %i <<< %s report : dwSize: %i elementCount: %i\n",
|
||||
TRACE("START Report %i <<< %s report : bitSize: %i elementCount: %i\n",
|
||||
report->reportID,
|
||||
type,
|
||||
report->dwSize,
|
||||
report->bitSize,
|
||||
report->elementCount);
|
||||
for (i = 0; i < report->elementCount; i++)
|
||||
debug_print_element(type, &report->Elements[i]);
|
||||
{
|
||||
debug_print_element(type, &elem[report->elementIdx + i]);
|
||||
}
|
||||
TRACE(">>> END Report %i\n",report->reportID);
|
||||
}
|
||||
|
||||
static void debug_print_preparsed(WINE_HIDP_PREPARSED_DATA *data)
|
||||
{
|
||||
unsigned int i;
|
||||
WINE_HID_REPORT *r;
|
||||
unsigned int i, end;
|
||||
if (TRACE_ON(hid))
|
||||
{
|
||||
TRACE("START PREPARSED Data <<< dwSize: %i Usage: %i, UsagePage: %i, InputReportByteLength: %i, tOutputReportByteLength: %i, FeatureReportByteLength: %i, NumberLinkCollectionNodes: %i, NumberInputButtonCaps: %i, NumberInputValueCaps: %i,NumberInputDataIndices: %i, NumberOutputButtonCaps: %i, NumberOutputValueCaps: %i, NumberOutputDataIndices: %i, NumberFeatureButtonCaps: %i, NumberFeatureValueCaps: %i, NumberFeatureDataIndices: %i, dwInputReportCount: %i, dwOutputReportCount: %i, dwFeatureReportCount: %i, dwOutputReportOffset: %i, dwFeatureReportOffset: %i\n",
|
||||
TRACE("START PREPARSED Data <<< dwSize: %i Usage: %i, UsagePage: %i, "
|
||||
"InputReportByteLength: %i, tOutputReportByteLength: %i, "
|
||||
"FeatureReportByteLength: %i, NumberLinkCollectionNodes: %i, "
|
||||
"NumberInputButtonCaps: %i, NumberInputValueCaps: %i, "
|
||||
"NumberInputDataIndices: %i, NumberOutputButtonCaps: %i, "
|
||||
"NumberOutputValueCaps: %i, NumberOutputDataIndices: %i, "
|
||||
"NumberFeatureButtonCaps: %i, NumberFeatureValueCaps: %i, "
|
||||
"NumberFeatureDataIndices: %i, reportCount[HidP_Input]: %i, "
|
||||
"reportCount[HidP_Output]: %i, reportCount[HidP_Feature]: %i, "
|
||||
"elementOffset: %i\n",
|
||||
data->dwSize,
|
||||
data->caps.Usage,
|
||||
data->caps.UsagePage,
|
||||
|
@ -355,29 +371,25 @@ static void debug_print_preparsed(WINE_HIDP_PREPARSED_DATA *data)
|
|||
data->caps.NumberFeatureButtonCaps,
|
||||
data->caps.NumberFeatureValueCaps,
|
||||
data->caps.NumberFeatureDataIndices,
|
||||
data->dwInputReportCount,
|
||||
data->dwOutputReportCount,
|
||||
data->dwFeatureReportCount,
|
||||
data->dwOutputReportOffset,
|
||||
data->dwFeatureReportOffset);
|
||||
data->reportCount[HidP_Input],
|
||||
data->reportCount[HidP_Output],
|
||||
data->reportCount[HidP_Feature],
|
||||
data->elementOffset);
|
||||
|
||||
r = HID_INPUT_REPORTS(data);
|
||||
for (i = 0; i < data->dwInputReportCount; i++)
|
||||
end = data->reportCount[HidP_Input];
|
||||
for (i = 0; i < end; i++)
|
||||
{
|
||||
debug_print_report("INPUT", r);
|
||||
r = HID_NEXT_REPORT(data, r);
|
||||
debug_print_report("INPUT", data, &data->reports[i]);
|
||||
}
|
||||
r = HID_OUTPUT_REPORTS(data);
|
||||
for (i = 0; i < data->dwOutputReportCount; i++)
|
||||
end += data->reportCount[HidP_Output];
|
||||
for (; i < end; i++)
|
||||
{
|
||||
debug_print_report("OUTPUT", r);
|
||||
r = HID_NEXT_REPORT(data, r);
|
||||
debug_print_report("OUTPUT", data, &data->reports[i]);
|
||||
}
|
||||
r = HID_FEATURE_REPORTS(data);
|
||||
for (i = 0; i < data->dwFeatureReportCount; i++)
|
||||
end += data->reportCount[HidP_Feature];
|
||||
for (i = 0; i < end; i++)
|
||||
{
|
||||
debug_print_report("FEATURE", r);
|
||||
r = HID_NEXT_REPORT(data, r);
|
||||
debug_print_report("FEATURE", data, &data->reports[i]);
|
||||
}
|
||||
TRACE(">>> END Preparsed Data\n");
|
||||
}
|
||||
|
@ -685,28 +697,22 @@ static int parse_descriptor(BYTE *descriptor, unsigned int index, unsigned int l
|
|||
return i;
|
||||
}
|
||||
|
||||
static inline void new_report(WINE_HID_REPORT *wine_report, struct feature* feature)
|
||||
{
|
||||
wine_report->reportID = feature->caps.ReportID;
|
||||
wine_report->dwSize = sizeof(*wine_report) - sizeof(WINE_HID_ELEMENT);
|
||||
wine_report->elementCount = 0;
|
||||
}
|
||||
|
||||
static void build_elements(WINE_HID_REPORT *wine_report, struct feature* feature, DWORD *bitOffset, unsigned int *data_index)
|
||||
static void build_elements(WINE_HID_REPORT *wine_report, WINE_HID_ELEMENT *elems,
|
||||
struct feature* feature, USHORT *data_index)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (!feature->isData)
|
||||
{
|
||||
*bitOffset = *bitOffset + (feature->caps.BitSize * feature->caps.ReportCount);
|
||||
wine_report->bitSize += feature->caps.BitSize * feature->caps.ReportCount;
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < feature->caps.usage_count; i++)
|
||||
{
|
||||
WINE_HID_ELEMENT *wine_element = &wine_report->Elements[wine_report->elementCount];
|
||||
WINE_HID_ELEMENT *wine_element = elems + wine_report->elementIdx + wine_report->elementCount;
|
||||
|
||||
wine_element->valueStartBit = *bitOffset;
|
||||
wine_element->valueStartBit = wine_report->bitSize;
|
||||
if (feature->caps.BitSize == 1)
|
||||
{
|
||||
wine_element->ElementType = ButtonElement;
|
||||
|
@ -723,7 +729,7 @@ static void build_elements(WINE_HID_REPORT *wine_report, struct feature* feature
|
|||
if (wine_element->caps.button.IsRange)
|
||||
{
|
||||
wine_element->bitCount = (feature->caps.u.Range.UsageMax - feature->caps.u.Range.UsageMin) + 1;
|
||||
*bitOffset = *bitOffset + wine_element->bitCount;
|
||||
wine_report->bitSize += wine_element->bitCount;
|
||||
wine_element->caps.button.u.Range.UsageMin = feature->caps.u.Range.UsageMin;
|
||||
wine_element->caps.button.u.Range.UsageMax = feature->caps.u.Range.UsageMax;
|
||||
wine_element->caps.button.u.Range.StringMin = feature->caps.u.Range.StringMin;
|
||||
|
@ -736,7 +742,7 @@ static void build_elements(WINE_HID_REPORT *wine_report, struct feature* feature
|
|||
}
|
||||
else
|
||||
{
|
||||
*bitOffset = *bitOffset + 1;
|
||||
wine_report->bitSize++;
|
||||
wine_element->bitCount = 1;
|
||||
wine_element->caps.button.u.NotRange.Usage = feature->caps.u.NotRange.Usage[i];
|
||||
wine_element->caps.button.u.NotRange.Reserved1 = feature->caps.u.NotRange.Usage[i];
|
||||
|
@ -774,7 +780,7 @@ static void build_elements(WINE_HID_REPORT *wine_report, struct feature* feature
|
|||
else
|
||||
wine_element->caps.value.ReportCount = feature->caps.ReportCount;
|
||||
wine_element->bitCount = (feature->caps.BitSize * wine_element->caps.value.ReportCount);
|
||||
*bitOffset = *bitOffset + wine_element->bitCount;
|
||||
wine_report->bitSize += wine_element->bitCount;
|
||||
wine_element->caps.value.UnitsExp = feature->caps.UnitsExp;
|
||||
wine_element->caps.value.Units = feature->caps.Units;
|
||||
wine_element->caps.value.LogicalMin = feature->caps.LogicalMin;
|
||||
|
@ -833,204 +839,113 @@ static void count_elements(struct feature* feature, USHORT *buttons, USHORT *val
|
|||
}
|
||||
}
|
||||
|
||||
static WINE_HIDP_PREPARSED_DATA* build_PreparseData(
|
||||
struct feature **features, int feature_count,
|
||||
struct feature **input_features, int i_count,
|
||||
struct feature **output_features, int o_count,
|
||||
struct feature **feature_features, int f_count,
|
||||
struct collection *base_collection)
|
||||
struct preparse_ctx
|
||||
{
|
||||
int report_count[3];
|
||||
int elem_count;
|
||||
int report_elem_count[3][256];
|
||||
|
||||
int elem_alloc;
|
||||
BOOL report_created[3][256];
|
||||
};
|
||||
|
||||
static void create_preparse_ctx(const struct collection *base, struct preparse_ctx *ctx)
|
||||
{
|
||||
struct feature *f;
|
||||
struct collection *c;
|
||||
|
||||
LIST_FOR_EACH_ENTRY(f, &base->features, struct feature, col_entry)
|
||||
{
|
||||
ctx->elem_count += f->caps.usage_count;
|
||||
ctx->report_elem_count[f->type][f->caps.ReportID] += f->caps.usage_count;
|
||||
if (ctx->report_elem_count[f->type][f->caps.ReportID] != f->caps.usage_count)
|
||||
continue;
|
||||
ctx->report_count[f->type]++;
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_ENTRY(c, &base->collections, struct collection, entry)
|
||||
create_preparse_ctx(c, ctx);
|
||||
}
|
||||
|
||||
static void preparse_collection(const struct collection *base,
|
||||
WINE_HIDP_PREPARSED_DATA *data, struct preparse_ctx *ctx)
|
||||
{
|
||||
WINE_HID_ELEMENT *elem = HID_ELEMS(data);
|
||||
struct feature *f;
|
||||
struct collection *c;
|
||||
|
||||
LIST_FOR_EACH_ENTRY(f, &base->features, struct feature, col_entry)
|
||||
{
|
||||
WINE_HID_REPORT *report;
|
||||
|
||||
if (!ctx->report_created[f->type][f->caps.ReportID])
|
||||
{
|
||||
ctx->report_created[f->type][f->caps.ReportID] = TRUE;
|
||||
data->reportIdx[f->type][f->caps.ReportID] = data->reportCount[f->type]++;
|
||||
if (f->type > 0) data->reportIdx[f->type][f->caps.ReportID] += ctx->report_count[0];
|
||||
if (f->type > 1) data->reportIdx[f->type][f->caps.ReportID] += ctx->report_count[1];
|
||||
|
||||
report = &data->reports[data->reportIdx[f->type][f->caps.ReportID]];
|
||||
report->reportID = f->caps.ReportID;
|
||||
/* Room for the reportID */
|
||||
report->bitSize = 8;
|
||||
report->elementIdx = ctx->elem_alloc;
|
||||
ctx->elem_alloc += ctx->report_elem_count[f->type][f->caps.ReportID];
|
||||
}
|
||||
|
||||
report = &data->reports[data->reportIdx[f->type][f->caps.ReportID]];
|
||||
switch (f->type)
|
||||
{
|
||||
case HidP_Input:
|
||||
build_elements(report, elem, f, &data->caps.NumberInputDataIndices);
|
||||
count_elements(f, &data->caps.NumberInputButtonCaps, &data->caps.NumberInputValueCaps);
|
||||
data->caps.InputReportByteLength =
|
||||
max(data->caps.InputReportByteLength, (report->bitSize + 7) / 8);
|
||||
break;
|
||||
case HidP_Output:
|
||||
build_elements(report, elem, f, &data->caps.NumberOutputDataIndices);
|
||||
count_elements(f, &data->caps.NumberOutputButtonCaps, &data->caps.NumberOutputValueCaps);
|
||||
data->caps.OutputReportByteLength =
|
||||
max(data->caps.OutputReportByteLength, (report->bitSize + 7) / 8);
|
||||
break;
|
||||
case HidP_Feature:
|
||||
build_elements(report, elem, f, &data->caps.NumberFeatureDataIndices);
|
||||
count_elements(f, &data->caps.NumberFeatureButtonCaps, &data->caps.NumberFeatureValueCaps);
|
||||
data->caps.FeatureReportByteLength =
|
||||
max(data->caps.FeatureReportByteLength, (report->bitSize + 7) / 8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_ENTRY(c, &base->collections, struct collection, entry)
|
||||
preparse_collection(c, data, ctx);
|
||||
}
|
||||
|
||||
static WINE_HIDP_PREPARSED_DATA* build_PreparseData(struct collection *base_collection)
|
||||
{
|
||||
WINE_HIDP_PREPARSED_DATA *data;
|
||||
WINE_HID_REPORT *wine_report = NULL;
|
||||
DWORD bitOffset, bitLength;
|
||||
unsigned int report_count = 1;
|
||||
unsigned int i;
|
||||
unsigned int element_count;
|
||||
unsigned int size = 0;
|
||||
unsigned int data_index;
|
||||
unsigned int report_count;
|
||||
unsigned int size;
|
||||
|
||||
if (features[0]->caps.ReportID != 0)
|
||||
{
|
||||
unsigned int *report_ids;
|
||||
unsigned int cnt = i_count + o_count + f_count;
|
||||
report_ids = HeapAlloc(GetProcessHeap(), 0 , sizeof(*report_ids) * cnt);
|
||||
struct preparse_ctx ctx;
|
||||
unsigned int element_off;
|
||||
|
||||
if (i_count)
|
||||
{
|
||||
report_ids[0] = input_features[0]->caps.ReportID;
|
||||
for (i = 1; i < i_count; i++)
|
||||
{
|
||||
unsigned int j;
|
||||
unsigned int found = FALSE;
|
||||
for (j = 0; !found && j < i_count; j++)
|
||||
{
|
||||
if (report_ids[j] == input_features[i]->caps.ReportID)
|
||||
found = TRUE;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
report_ids[report_count] = input_features[i]->caps.ReportID;
|
||||
report_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o_count)
|
||||
{
|
||||
report_count++;
|
||||
report_ids[0] = output_features[0]->caps.ReportID;
|
||||
for (i = 1; i < o_count; i++)
|
||||
{
|
||||
unsigned int j;
|
||||
unsigned int found = FALSE;
|
||||
for (j = 0; !found && j < o_count; j++)
|
||||
{
|
||||
if (report_ids[j] == output_features[i]->caps.ReportID)
|
||||
found = TRUE;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
report_ids[report_count] = output_features[i]->caps.ReportID;
|
||||
report_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (f_count)
|
||||
{
|
||||
report_count++;
|
||||
report_ids[0] = feature_features[0]->caps.ReportID;
|
||||
for (i = 1; i < f_count; i++)
|
||||
{
|
||||
unsigned int j;
|
||||
unsigned int found = FALSE;
|
||||
for (j = 0; !found && j < f_count; j++)
|
||||
{
|
||||
if (report_ids[j] == feature_features[i]->caps.ReportID)
|
||||
found = TRUE;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
report_ids[report_count] = feature_features[i]->caps.ReportID;
|
||||
report_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, report_ids);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (o_count) report_count++;
|
||||
if (f_count) report_count++;
|
||||
}
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
create_preparse_ctx(base_collection, &ctx);
|
||||
|
||||
element_count = 0;
|
||||
for (i = 0; i < feature_count; i++)
|
||||
element_count += features[i]->caps.usage_count;
|
||||
|
||||
size = sizeof(WINE_HIDP_PREPARSED_DATA) +
|
||||
(element_count * sizeof(WINE_HID_ELEMENT)) +
|
||||
(report_count * sizeof(WINE_HID_REPORT));
|
||||
|
||||
TRACE("%i reports %i elements -> size %i\n",report_count, element_count, size);
|
||||
report_count = ctx.report_count[HidP_Input] + ctx.report_count[HidP_Output]
|
||||
+ ctx.report_count[HidP_Feature];
|
||||
element_off = FIELD_OFFSET(WINE_HIDP_PREPARSED_DATA, reports[report_count]);
|
||||
size = element_off + (ctx.elem_count * sizeof(WINE_HID_ELEMENT));
|
||||
|
||||
data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
|
||||
data->magic = HID_MAGIC;
|
||||
data->dwSize = size;
|
||||
data->caps.Usage = base_collection->caps.u.NotRange.Usage[0];
|
||||
data->caps.UsagePage = base_collection->caps.UsagePage;
|
||||
data->elementOffset = element_off;
|
||||
|
||||
wine_report = data->InputReports;
|
||||
if (i_count)
|
||||
{
|
||||
data_index = 0;
|
||||
bitLength = 0;
|
||||
new_report(wine_report, input_features[0]);
|
||||
data->dwInputReportCount++;
|
||||
|
||||
/* Room for the reportID */
|
||||
bitOffset = 8;
|
||||
|
||||
for (i = 0; i < i_count; i++)
|
||||
{
|
||||
if (input_features[i]->caps.ReportID != wine_report->reportID)
|
||||
{
|
||||
wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
|
||||
wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
|
||||
new_report(wine_report, input_features[i]);
|
||||
data->dwInputReportCount++;
|
||||
bitLength = max(bitOffset, bitLength);
|
||||
bitOffset = 8;
|
||||
}
|
||||
build_elements(wine_report, input_features[i], &bitOffset, &data_index);
|
||||
count_elements(input_features[i], &data->caps.NumberInputButtonCaps,
|
||||
&data->caps.NumberInputValueCaps);
|
||||
}
|
||||
wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
|
||||
bitLength = max(bitOffset, bitLength);
|
||||
data->caps.InputReportByteLength = ((bitLength + 7) & ~7)/8;
|
||||
data->caps.NumberInputDataIndices = data_index;
|
||||
}
|
||||
|
||||
if (o_count)
|
||||
{
|
||||
data_index = 0;
|
||||
bitLength = 0;
|
||||
wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
|
||||
data->dwOutputReportOffset = (BYTE*)wine_report - (BYTE*)data->InputReports;
|
||||
new_report(wine_report, output_features[0]);
|
||||
data->dwOutputReportCount++;
|
||||
bitOffset = 8;
|
||||
|
||||
for (i = 0; i < o_count; i++)
|
||||
{
|
||||
if (output_features[i]->caps.ReportID != wine_report->reportID)
|
||||
{
|
||||
wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
|
||||
wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
|
||||
new_report(wine_report, output_features[i]);
|
||||
data->dwOutputReportCount++;
|
||||
bitLength = max(bitOffset, bitLength);
|
||||
bitOffset = 8;
|
||||
}
|
||||
build_elements(wine_report, output_features[i], &bitOffset, &data_index);
|
||||
count_elements(output_features[i], &data->caps.NumberOutputButtonCaps,
|
||||
&data->caps.NumberOutputValueCaps);
|
||||
}
|
||||
wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
|
||||
bitLength = max(bitOffset, bitLength);
|
||||
data->caps.OutputReportByteLength = ((bitLength + 7) & ~7)/8;
|
||||
data->caps.NumberOutputDataIndices = data_index;
|
||||
}
|
||||
|
||||
if (f_count)
|
||||
{
|
||||
data_index = 0;
|
||||
bitLength = 0;
|
||||
wine_report = (WINE_HID_REPORT*)(((BYTE*)wine_report)+wine_report->dwSize);
|
||||
data->dwFeatureReportOffset = (BYTE*)wine_report - (BYTE*)data->InputReports;
|
||||
new_report(wine_report, feature_features[0]);
|
||||
data->dwFeatureReportCount++;
|
||||
bitOffset = 8;
|
||||
|
||||
for (i = 0; i < f_count; i++)
|
||||
{
|
||||
if (feature_features[i]->caps.ReportID != wine_report->reportID)
|
||||
{
|
||||
wine_report->dwSize += (sizeof(WINE_HID_ELEMENT) * wine_report->elementCount);
|
||||
wine_report = (WINE_HID_REPORT*)((BYTE*)wine_report+wine_report->dwSize);
|
||||
new_report(wine_report, feature_features[i]);
|
||||
data->dwFeatureReportCount++;
|
||||
bitLength = max(bitOffset, bitLength);
|
||||
bitOffset = 8;
|
||||
}
|
||||
build_elements(wine_report, feature_features[i], &bitOffset, &data_index);
|
||||
count_elements(feature_features[i], &data->caps.NumberFeatureButtonCaps,
|
||||
&data->caps.NumberFeatureValueCaps);
|
||||
}
|
||||
bitLength = max(bitOffset, bitLength);
|
||||
data->caps.FeatureReportByteLength = ((bitLength + 7) & ~7)/8;
|
||||
data->caps.NumberFeatureDataIndices = data_index;
|
||||
}
|
||||
|
||||
preparse_collection(base_collection, data, &ctx);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -1051,15 +966,6 @@ static void free_collection(struct collection *collection)
|
|||
HeapFree(GetProcessHeap(), 0, collection);
|
||||
}
|
||||
|
||||
static int compare_reports(const void *a, const void* b)
|
||||
{
|
||||
struct feature *f1 = *(struct feature **)a;
|
||||
struct feature *f2 = *(struct feature **)b;
|
||||
int c = (f1->caps.ReportID - f2->caps.ReportID);
|
||||
if (c) return c;
|
||||
return (f1->index - f2->index);
|
||||
}
|
||||
|
||||
WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length)
|
||||
{
|
||||
WINE_HIDP_PREPARSED_DATA *data = NULL;
|
||||
|
@ -1109,77 +1015,8 @@ WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length)
|
|||
}
|
||||
}
|
||||
|
||||
cidx = 2;
|
||||
if (feature_count)
|
||||
{
|
||||
struct feature *entry;
|
||||
struct feature** sorted_features;
|
||||
struct feature** input_features;
|
||||
struct feature** output_features;
|
||||
struct feature** feature_features;
|
||||
unsigned int i_count, o_count, f_count;
|
||||
unsigned int i;
|
||||
|
||||
i_count = o_count = f_count = 0;
|
||||
|
||||
sorted_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*sorted_features) * feature_count);
|
||||
input_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*input_features) * feature_count);
|
||||
output_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*output_features) * feature_count);
|
||||
feature_features = HeapAlloc(GetProcessHeap(), 0, sizeof(*feature_features) * feature_count);
|
||||
|
||||
i = 0;
|
||||
LIST_FOR_EACH_ENTRY(entry, &features, struct feature, entry)
|
||||
sorted_features[i++] = entry;
|
||||
|
||||
/* Sort features base on report if there are multiple reports */
|
||||
if (sorted_features[0]->caps.ReportID != 0)
|
||||
qsort(sorted_features, feature_count, sizeof(struct feature*), compare_reports);
|
||||
|
||||
for (i = 0; i < feature_count; i++)
|
||||
{
|
||||
switch (sorted_features[i]->type)
|
||||
{
|
||||
case HidP_Input:
|
||||
input_features[i_count] = sorted_features[i];
|
||||
i_count++;
|
||||
break;
|
||||
case HidP_Output:
|
||||
output_features[o_count] = sorted_features[i];
|
||||
o_count++;
|
||||
break;
|
||||
case HidP_Feature:
|
||||
feature_features[f_count] = sorted_features[i];
|
||||
f_count++;
|
||||
break;
|
||||
default:
|
||||
ERR("Unknown type %i\n",sorted_features[i]->type);
|
||||
}
|
||||
}
|
||||
|
||||
if (TRACE_ON(hid))
|
||||
{
|
||||
TRACE("DUMP FEATURES:\n");
|
||||
TRACE("----INPUT----\n");
|
||||
for (cidx = 0; cidx < i_count; cidx++)
|
||||
debug_feature(input_features[cidx]);
|
||||
TRACE("----OUTPUT----\n");
|
||||
for (cidx = 0; cidx < o_count; cidx++)
|
||||
debug_feature(output_features[cidx]);
|
||||
TRACE("----FEATURE----\n");
|
||||
for (cidx = 0; cidx < f_count; cidx++)
|
||||
debug_feature(feature_features[cidx]);
|
||||
}
|
||||
|
||||
data = build_PreparseData(sorted_features, feature_count, input_features, i_count, output_features, o_count, feature_features, f_count, base);
|
||||
|
||||
data = build_PreparseData(base);
|
||||
debug_print_preparsed(data);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, sorted_features);
|
||||
HeapFree(GetProcessHeap(), 0, input_features);
|
||||
HeapFree(GetProcessHeap(), 0, output_features);
|
||||
HeapFree(GetProcessHeap(), 0, feature_features);
|
||||
}
|
||||
|
||||
free_collection(base);
|
||||
/* We do not have to free the list as free_collection does all the work */
|
||||
|
||||
|
|
|
@ -353,7 +353,7 @@ static DWORD CALLBACK hid_device_thread(void *args)
|
|||
if (!exit_now && irp->IoStatus.u.Status == STATUS_SUCCESS)
|
||||
{
|
||||
packet->reportBufferLen = irp->IoStatus.Information;
|
||||
if (ext->preparseData->InputReports[0].reportID)
|
||||
if (ext->preparseData->reports[0].reportID)
|
||||
packet->reportId = packet->reportBuffer[0];
|
||||
else
|
||||
packet->reportId = 0;
|
||||
|
@ -590,7 +590,7 @@ NTSTATUS WINAPI HID_Device_ioctl(DEVICE_OBJECT *device, IRP *irp)
|
|||
|
||||
packet = HeapAlloc(GetProcessHeap(), 0, packet_size);
|
||||
|
||||
if (extension->preparseData->InputReports[0].reportID)
|
||||
if (extension->preparseData->reports[0].reportID)
|
||||
packet->reportId = buffer[0];
|
||||
else
|
||||
packet->reportId = 0;
|
||||
|
|
|
@ -43,9 +43,9 @@ typedef struct __WINE_ELEMENT
|
|||
typedef struct __WINE_HID_REPORT
|
||||
{
|
||||
UCHAR reportID;
|
||||
DWORD dwSize;
|
||||
DWORD bitSize;
|
||||
DWORD elementCount;
|
||||
WINE_HID_ELEMENT Elements[1];
|
||||
DWORD elementIdx;
|
||||
} WINE_HID_REPORT;
|
||||
|
||||
typedef struct __WINE_HIDP_PREPARSED_DATA
|
||||
|
@ -54,19 +54,16 @@ typedef struct __WINE_HIDP_PREPARSED_DATA
|
|||
DWORD dwSize;
|
||||
HIDP_CAPS caps;
|
||||
|
||||
DWORD dwInputReportCount;
|
||||
DWORD dwOutputReportCount;
|
||||
DWORD dwFeatureReportCount;
|
||||
DWORD elementOffset;
|
||||
DWORD reportCount[3];
|
||||
BYTE reportIdx[3][256];
|
||||
|
||||
DWORD dwOutputReportOffset;
|
||||
DWORD dwFeatureReportOffset;
|
||||
WINE_HID_REPORT reports[1];
|
||||
} WINE_HIDP_PREPARSED_DATA, *PWINE_HIDP_PREPARSED_DATA;
|
||||
|
||||
WINE_HID_REPORT InputReports[1];
|
||||
} WINE_HIDP_PREPARSED_DATA;
|
||||
|
||||
#define HID_NEXT_REPORT(d,r) ((r)?(WINE_HID_REPORT*)(((BYTE*)(r))+(r)->dwSize):(d)->InputReports)
|
||||
#define HID_INPUT_REPORTS(d) ((d)->InputReports)
|
||||
#define HID_OUTPUT_REPORTS(d) (WINE_HID_REPORT*)(((BYTE*)(d)->InputReports)+(d)->dwOutputReportOffset)
|
||||
#define HID_FEATURE_REPORTS(d) (WINE_HID_REPORT*)(((BYTE*)(d)->InputReports)+(d)->dwFeatureReportOffset)
|
||||
#define HID_INPUT_REPORTS(d) ((d)->reports)
|
||||
#define HID_OUTPUT_REPORTS(d) ((d)->reports + (d)->reportCount[0])
|
||||
#define HID_FEATURE_REPORTS(d) ((d)->reports + (d)->reportCount[0] + (d)->reportCount[1])
|
||||
#define HID_ELEMS(d) ((WINE_HID_ELEMENT*)((BYTE*)(d) + (d)->elementOffset))
|
||||
|
||||
#endif /* __WINE_PARSE_H */
|
||||
|
|
Loading…
Reference in New Issue