diff --git a/dlls/hid/hid.spec b/dlls/hid/hid.spec index fe8002efa50..cbae14c8cf5 100644 --- a/dlls/hid/hid.spec +++ b/dlls/hid/hid.spec @@ -20,7 +20,7 @@ @ stdcall HidD_SetOutputReport(long ptr long) @ stdcall HidP_GetButtonCaps(long ptr ptr ptr) @ stdcall HidP_GetCaps(ptr ptr) -@ stub HidP_GetData +@ stdcall HidP_GetData(long ptr ptr ptr ptr long) @ stub HidP_GetExtendedAttributes @ stub HidP_GetLinkCollectionNodes @ stdcall HidP_GetScaledUsageValue(long long long long ptr ptr ptr long) diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index da57665ad80..d6d143e899e 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -783,3 +783,98 @@ ULONG WINAPI HidP_MaxDataListLength(HIDP_REPORT_TYPE ReportType, PHIDP_PREPARSED return 0; } } + +NTSTATUS WINAPI HidP_GetData(HIDP_REPORT_TYPE ReportType, HIDP_DATA *DataList, ULONG *DataLength, + PHIDP_PREPARSED_DATA PreparsedData,CHAR *Report, ULONG ReportLength) +{ + WINE_HIDP_PREPARSED_DATA *data = (WINE_HIDP_PREPARSED_DATA*)PreparsedData; + WINE_HID_REPORT *report = NULL; + USHORT r_count = 0; + int i,uCount = 0; + NTSTATUS rc; + + TRACE("(%i, %p, %p(%i), %p, %p, %i)\n", ReportType, DataList, DataLength, + DataLength?*DataLength:0, PreparsedData, Report, ReportLength); + + 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: + 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); + } + + if (i == r_count) + return HIDP_STATUS_REPORT_DOES_NOT_EXIST; + + for (i = 0; i < report->elementCount; i++) + { + WINE_HID_ELEMENT *element = &report->Elements[i]; + if (element->ElementType == ButtonElement) + { + int k; + for (k=0; k < element->bitCount; k++) + { + UINT v = 0; + NTSTATUS rc = get_report_data((BYTE*)Report, ReportLength, + element->valueStartBit + k, 1, &v); + if (rc != HIDP_STATUS_SUCCESS) + return rc; + if (v) + { + if (uCount < *DataLength) + { + DataList[uCount].DataIndex = element->caps.button.u.Range.DataIndexMin + k; + DataList[uCount].u.On = v; + } + uCount++; + } + } + } + else + { + if (uCount < *DataLength) + { + UINT v; + NTSTATUS rc = get_report_data((BYTE*)Report, ReportLength, + element->valueStartBit, element->bitCount, &v); + if (rc != HIDP_STATUS_SUCCESS) + return rc; + if (element->caps.value.BitSize == 16) + v = (short)v; + DataList[uCount].DataIndex = element->caps.value.u.NotRange.DataIndex; + DataList[uCount].u.RawValue = v; + } + uCount++; + } + } + + if (*DataLength < uCount) + rc = HIDP_STATUS_BUFFER_TOO_SMALL; + else + rc = HIDP_STATUS_SUCCESS; + + *DataLength = uCount; + + return rc; +} diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c index c20e51d90c6..8064e3464e9 100644 --- a/dlls/hidclass.sys/descriptor.c +++ b/dlls/hidclass.sys/descriptor.c @@ -694,7 +694,7 @@ static inline void new_report(WINE_HID_REPORT *wine_report, struct feature* feat wine_report->elementCount = 0; } -static void build_elements(WINE_HID_REPORT *wine_report, struct feature* feature, DWORD *bitOffset) +static void build_elements(WINE_HID_REPORT *wine_report, struct feature* feature, DWORD *bitOffset, unsigned int *data_index) { unsigned int i; @@ -729,6 +729,9 @@ static void build_elements(WINE_HID_REPORT *wine_report, struct feature* feature wine_element->caps.button.u.Range.StringMax = feature->caps.u.Range.StringMax; wine_element->caps.button.u.Range.DesignatorMin = feature->caps.u.Range.DesignatorMin; wine_element->caps.button.u.Range.DesignatorMax = feature->caps.u.Range.DesignatorMax; + wine_element->caps.button.u.Range.DataIndexMin = *data_index; + wine_element->caps.button.u.Range.DataIndexMax = *data_index + wine_element->bitCount - 1; + *data_index = *data_index + wine_element->bitCount; } else { @@ -737,6 +740,8 @@ static void build_elements(WINE_HID_REPORT *wine_report, struct feature* feature wine_element->caps.button.u.NotRange.Usage = feature->caps.u.NotRange.Usage[i]; wine_element->caps.button.u.NotRange.StringIndex = feature->caps.u.NotRange.StringIndex; wine_element->caps.button.u.NotRange.DesignatorIndex = feature->caps.u.NotRange.DesignatorIndex; + wine_element->caps.button.u.NotRange.DataIndex = *data_index; + *data_index = *data_index + 1; } } else @@ -776,12 +781,21 @@ static void build_elements(WINE_HID_REPORT *wine_report, struct feature* feature wine_element->caps.value.u.Range.StringMax = feature->caps.u.Range.StringMax; wine_element->caps.value.u.Range.DesignatorMin = feature->caps.u.Range.DesignatorMin; wine_element->caps.value.u.Range.DesignatorMax = feature->caps.u.Range.DesignatorMax; + wine_element->caps.value.u.Range.DataIndexMin = *data_index; + wine_element->caps.value.u.Range.DataIndexMax = *data_index + + (wine_element->caps.value.u.Range.UsageMax - + wine_element->caps.value.u.Range.UsageMin); + *data_index = *data_index + + (wine_element->caps.value.u.Range.UsageMax - + wine_element->caps.value.u.Range.UsageMin) + 1; } else { wine_element->caps.value.u.NotRange.Usage = feature->caps.u.NotRange.Usage[i]; wine_element->caps.value.u.NotRange.StringIndex = feature->caps.u.NotRange.StringIndex; wine_element->caps.value.u.NotRange.DesignatorIndex = feature->caps.u.NotRange.DesignatorIndex; + wine_element->caps.value.u.NotRange.DataIndex = *data_index; + *data_index = *data_index + 1; } } @@ -821,6 +835,7 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData( unsigned int i; unsigned int element_count; unsigned int size = 0; + unsigned int data_index; if (features[0]->caps.ReportID != 0) { @@ -915,6 +930,7 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData( wine_report = data->InputReports; if (i_count) { + data_index = 0; bitLength = 0; new_report(wine_report, input_features[0]); data->dwInputReportCount++; @@ -933,17 +949,19 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData( bitLength = max(bitOffset, bitLength); bitOffset = 8; } - build_elements(wine_report, input_features[i], &bitOffset); + 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; @@ -962,17 +980,19 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData( bitLength = max(bitOffset, bitLength); bitOffset = 8; } - build_elements(wine_report, output_features[i], &bitOffset); + 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; @@ -991,12 +1011,13 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData( bitLength = max(bitOffset, bitLength); bitOffset = 8; } - build_elements(wine_report, feature_features[i], &bitOffset); + 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; } return data; diff --git a/include/ddk/hidpi.h b/include/ddk/hidpi.h index 902fa79bc8a..0f69a03a646 100644 --- a/include/ddk/hidpi.h +++ b/include/ddk/hidpi.h @@ -166,6 +166,15 @@ typedef struct _USAGE_AND_PAGE { USAGE UsagePage; } USAGE_AND_PAGE, *PUSAGE_AND_PAGE; +typedef struct _HIDP_DATA { + USHORT DataIndex; + USHORT Reserved; + union { + ULONG RawValue; + BOOLEAN On; + } DUMMYUNIONNAME; +} HIDP_DATA, *PHIDP_DATA; + typedef BOOLEAN (NTAPI *PHIDP_INSERT_SCANCODES) (VOID *Context, CHAR *NewScanCodes, ULONG Length); @@ -182,6 +191,7 @@ NTSTATUS WINAPI HidP_GetSpecificButtonCaps(HIDP_REPORT_TYPE ReportType, USAGE Us NTSTATUS WINAPI HidP_GetSpecificValueCaps(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, HIDP_VALUE_CAPS *ValueCaps, USHORT *ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData); NTSTATUS WINAPI HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType, USHORT LinkCollection, USAGE_AND_PAGE *ButtonList, ULONG *UsageLength, PHIDP_PREPARSED_DATA PreparsedData, CHAR *Report, ULONG ReportLength); ULONG WINAPI HidP_MaxDataListLength(HIDP_REPORT_TYPE ReportType, PHIDP_PREPARSED_DATA PreparsedData); +NTSTATUS WINAPI HidP_GetData(HIDP_REPORT_TYPE ReportType, HIDP_DATA *DataList, ULONG *DataLength, PHIDP_PREPARSED_DATA PreparsedData, CHAR *Report, ULONG ReportLength); #ifndef FACILITY_HID_ERROR_CODE #define FACILITY_HID_ERROR_CODE 0x11