Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/ntoskrnl.exe/tests/driver_hid.c | 12 ++++++- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 49 ++++++++++++++++++++++------ 2 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/driver_hid.c b/dlls/ntoskrnl.exe/tests/driver_hid.c index 8111af23c06..ce942815dcb 100644 --- a/dlls/ntoskrnl.exe/tests/driver_hid.c +++ b/dlls/ntoskrnl.exe/tests/driver_hid.c @@ -299,6 +299,16 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) REPORT_COUNT(1, 8), REPORT_SIZE(1, 1), INPUT(1, Data|Var|Abs), + + USAGE(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8c), + USAGE(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8d), + USAGE(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8e), + USAGE(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8f), + LOGICAL_MINIMUM(1, 1), + LOGICAL_MAXIMUM(1, 16), + REPORT_COUNT(1, 2), + REPORT_SIZE(1, 8), + INPUT(1, Data|Ary|Abs), END_COLLECTION,
USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS), @@ -477,7 +487,7 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
case IOCTL_HID_READ_REPORT: { - ULONG expected_size = 23; + ULONG expected_size = 25; ok(!in_size, "got input size %u\n", in_size); ok(out_size == expected_size, "got output size %u\n", out_size);
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index f11dce1cc93..a7a67f298ab 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1684,13 +1684,13 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled { .Usage = HID_USAGE_GENERIC_JOYSTICK, .UsagePage = HID_USAGE_PAGE_GENERIC, - .InputReportByteLength = 24, + .InputReportByteLength = 26, .OutputReportByteLength = 3, .FeatureReportByteLength = 18, .NumberLinkCollectionNodes = 10, - .NumberInputButtonCaps = 13, + .NumberInputButtonCaps = 17, .NumberInputValueCaps = 7, - .NumberInputDataIndices = 43, + .NumberInputDataIndices = 47, .NumberFeatureButtonCaps = 1, .NumberFeatureValueCaps = 5, .NumberFeatureDataIndices = 7, @@ -1699,13 +1699,13 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled { .Usage = HID_USAGE_GENERIC_JOYSTICK, .UsagePage = HID_USAGE_PAGE_GENERIC, - .InputReportByteLength = 23, + .InputReportByteLength = 25, .OutputReportByteLength = 2, .FeatureReportByteLength = 17, .NumberLinkCollectionNodes = 10, - .NumberInputButtonCaps = 13, + .NumberInputButtonCaps = 17, .NumberInputValueCaps = 7, - .NumberInputDataIndices = 43, + .NumberInputDataIndices = 47, .NumberFeatureButtonCaps = 1, .NumberFeatureValueCaps = 5, .NumberFeatureDataIndices = 7, @@ -1872,12 +1872,12 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled HIDP_LINK_COLLECTION_NODE collections[16]; PHIDP_PREPARSED_DATA preparsed_data; USAGE_AND_PAGE usage_and_pages[16]; - HIDP_BUTTON_CAPS button_caps[16]; + HIDP_BUTTON_CAPS button_caps[32]; HIDP_VALUE_CAPS value_caps[16]; char buffer[200], report[200]; DWORD collection_count; DWORD waveform_list; - HIDP_DATA data[32]; + HIDP_DATA data[64]; USAGE usages[16]; NTSTATUS status; HIDP_CAPS caps; @@ -2186,7 +2186,7 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled value = HidP_MaxUsageListLength(HidP_Feature + 1, 0, preparsed_data); ok(value == 0, "HidP_MaxUsageListLength(HidP_Feature + 1, 0) returned %d, expected %d\n", value, 0); value = HidP_MaxUsageListLength(HidP_Input, 0, preparsed_data); - ok(value == 42, "HidP_MaxUsageListLength(HidP_Input, 0) returned %d, expected %d\n", value, 42); + ok(value == 50, "HidP_MaxUsageListLength(HidP_Input, 0) returned %d, expected %d\n", value, 50); value = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON, preparsed_data); ok(value == 32, "HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON) returned %d, expected %d\n", value, 32); value = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_LED, preparsed_data); @@ -2307,7 +2307,7 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled value = HidP_MaxDataListLength(HidP_Feature + 1, preparsed_data); ok(value == 0, "HidP_MaxDataListLength(HidP_Feature + 1) returned %d, expected %d\n", value, 0); value = HidP_MaxDataListLength(HidP_Input, preparsed_data); - ok(value == 50, "HidP_MaxDataListLength(HidP_Input) returned %d, expected %d\n", value, 50); + ok(value == 58, "HidP_MaxDataListLength(HidP_Input) returned %d, expected %d\n", value, 58); value = HidP_MaxDataListLength(HidP_Output, preparsed_data); ok(value == 0, "HidP_MaxDataListLength(HidP_Output) returned %d, expected %d\n", value, 0); value = HidP_MaxDataListLength(HidP_Feature, preparsed_data); @@ -2328,6 +2328,35 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled winetest_pop_context(); }
+ /* HID nary usage collections are set with 1-based usage index in their declaration order */ + + memset(report, 0, caps.InputReportByteLength); + status = HidP_InitializeReportForID(HidP_Input, report_id, preparsed_data, report, + caps.InputReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status); + value = 2; + usages[0] = 0x8e; + usages[1] = 0x8f; + status = HidP_SetUsages(HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data, + report, caps.InputReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status); + todo_wine + ok(report[caps.InputReportByteLength - 2] == 3, "unexpected usage index %d, expected 3\n", + report[caps.InputReportByteLength - 2]); + todo_wine + ok(report[caps.InputReportByteLength - 1] == 4, "unexpected usage index %d, expected 4\n", + report[caps.InputReportByteLength - 1]); + report[caps.InputReportByteLength - 2] = 0; + report[caps.InputReportByteLength - 1] = 0; + value = 1; + usages[0] = 0x8c; + status = HidP_SetUsages(HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data, + report, caps.InputReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status); + todo_wine + ok(report[caps.InputReportByteLength - 2] == 1, "unexpected usage index %d, expected 1\n", + report[caps.InputReportByteLength - 2]); + memset(report, 0xcd, sizeof(report)); status = HidP_InitializeReportForID(HidP_Feature, 3, preparsed_data, report, caps.FeatureReportByteLength); ok(status == HIDP_STATUS_REPORT_DOES_NOT_EXIST, "HidP_InitializeReportForID returned %#x\n", status);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hidparse.sys/main.c | 4 ++-- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index 185cefbb3e5..3a57c338165 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -354,14 +354,13 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY } value = state->values[type] + *value_idx;
- state->items.start_index = 0; + state->items.start_index = usages_size; if (!(is_array = HID_VALUE_CAPS_IS_ARRAY( &state->items ))) state->items.report_count -= usages_size - 1; else state->items.start_bit -= state->items.report_count * state->items.bit_size;
while (usages_size--) { if (!is_array) state->items.start_bit -= state->items.report_count * state->items.bit_size; - else state->items.start_index += 1; state->items.usage_page = state->usages_page[usages_size]; state->items.usage_min = state->usages_min[usages_size]; state->items.usage_max = state->usages_max[usages_size]; @@ -371,6 +370,7 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY *value++ = state->items; *value_idx += 1; if (!is_array) state->items.report_count = 1; + else state->items.start_index -= 1; }
state->items.usage_page = usage_page; diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index a7a67f298ab..7f4874d1f9e 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -2340,10 +2340,8 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled status = HidP_SetUsages(HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data, report, caps.InputReportByteLength); ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status); - todo_wine ok(report[caps.InputReportByteLength - 2] == 3, "unexpected usage index %d, expected 3\n", report[caps.InputReportByteLength - 2]); - todo_wine ok(report[caps.InputReportByteLength - 1] == 4, "unexpected usage index %d, expected 4\n", report[caps.InputReportByteLength - 1]); report[caps.InputReportByteLength - 2] = 0; @@ -2353,7 +2351,6 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled status = HidP_SetUsages(HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data, report, caps.InputReportByteLength); ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status); - todo_wine ok(report[caps.InputReportByteLength - 2] == 1, "unexpected usage index %d, expected 1\n", report[caps.InputReportByteLength - 2]);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hid.spec | 2 +- dlls/hid/hidp.c | 59 ++++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 12 +++++- include/ddk/hidpi.h | 1 + 4 files changed, 71 insertions(+), 3 deletions(-)
diff --git a/dlls/hid/hid.spec b/dlls/hid/hid.spec index edfdb004fd0..5d4706e3727 100644 --- a/dlls/hid/hid.spec +++ b/dlls/hid/hid.spec @@ -40,5 +40,5 @@ @ stdcall HidP_SetUsageValueArray(long long long long ptr long ptr ptr long) @ stdcall HidP_SetUsages(long long long ptr ptr ptr ptr long) @ stdcall HidP_TranslateUsagesToI8042ScanCodes(ptr long long ptr ptr ptr) -@ stub HidP_UnsetUsages +@ stdcall HidP_UnsetUsages(long long long ptr ptr ptr ptr long) @ stub HidP_UsageListDifference diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 31f1b85f14a..8c43d27f252 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -481,6 +481,65 @@ NTSTATUS WINAPI HidP_SetUsages( HIDP_REPORT_TYPE report_type, USAGE usage_page, return HIDP_STATUS_SUCCESS; }
+struct unset_usage_params +{ + USAGE usage; + char *report_buf; + BOOL found; +}; + +static NTSTATUS unset_usage( const struct hid_value_caps *caps, void *user ) +{ + struct unset_usage_params *params = user; + ULONG bit, index, last; + + if (HID_VALUE_CAPS_IS_ARRAY( caps )) + { + for (bit = caps->start_bit, last = bit + caps->report_count * caps->bit_size - 1; bit <= last; bit += 8) + { + index = caps->start_index + params->usage - caps->usage_min; + if (params->report_buf[bit / 8] != index) continue; + params->report_buf[bit / 8] = 0; + params->found = TRUE; + break; + } + + return HIDP_STATUS_NULL; + } + + bit = caps->start_bit + params->usage - caps->usage_min; + if (params->report_buf[bit / 8] & (1 << (bit % 8))) params->found = TRUE; + params->report_buf[bit / 8] &= ~(1 << (bit % 8)); + return HIDP_STATUS_NULL; +} + +NTSTATUS WINAPI HidP_UnsetUsages( HIDP_REPORT_TYPE report_type, USAGE usage_page, USHORT collection, USAGE *usages, + ULONG *usage_count, PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) +{ + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; + struct unset_usage_params params = {.report_buf = report_buf, .found = FALSE}; + struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection}; + NTSTATUS status; + USHORT limit = 1; + ULONG i, count = *usage_count; + + TRACE( "report_type %d, usage_page %x, collection %d, usages %p, usage_count %p, preparsed_data %p, " + "report_buf %p, report_len %u.\n", + report_type, usage_page, collection, usages, usage_count, preparsed_data, report_buf, report_len ); + + if (!report_len) return HIDP_STATUS_INVALID_REPORT_LENGTH; + + filter.report_id = report_buf[0]; + for (i = 0; i < count; ++i) + { + params.usage = filter.usage = usages[i]; + status = enum_value_caps( preparsed, report_type, report_len, &filter, unset_usage, ¶ms, &limit ); + if (status != HIDP_STATUS_SUCCESS) return status; + } + + if (!params.found) return HIDP_STATUS_BUTTON_NOT_PRESSED; + return HIDP_STATUS_SUCCESS; +}
NTSTATUS WINAPI HidP_TranslateUsagesToI8042ScanCodes(USAGE *ChangedUsageList, ULONG UsageListLength, HIDP_KEYBOARD_DIRECTION KeyAction, diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 7f4874d1f9e..34491500423 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -2344,8 +2344,16 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled report[caps.InputReportByteLength - 2]); ok(report[caps.InputReportByteLength - 1] == 4, "unexpected usage index %d, expected 4\n", report[caps.InputReportByteLength - 1]); - report[caps.InputReportByteLength - 2] = 0; - report[caps.InputReportByteLength - 1] = 0; + status = HidP_UnsetUsages(HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data, + report, caps.InputReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_UnsetUsages returned %#x\n", status); + ok(report[caps.InputReportByteLength - 2] == 0, "unexpected usage index %d, expected 0\n", + report[caps.InputReportByteLength - 2]); + ok(report[caps.InputReportByteLength - 1] == 0, "unexpected usage index %d, expected 0\n", + report[caps.InputReportByteLength - 1]); + status = HidP_UnsetUsages(HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data, + report, caps.InputReportByteLength); + ok(status == HIDP_STATUS_BUTTON_NOT_PRESSED, "HidP_UnsetUsages returned %#x\n", status); value = 1; usages[0] = 0x8c; status = HidP_SetUsages(HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data, diff --git a/include/ddk/hidpi.h b/include/ddk/hidpi.h index 6dfe5919b4f..305c38a95d3 100644 --- a/include/ddk/hidpi.h +++ b/include/ddk/hidpi.h @@ -209,6 +209,7 @@ NTSTATUS WINAPI HidP_SetUsageValueArray( HIDP_REPORT_TYPE ReportType, USAGE Usag NTSTATUS WINAPI HidP_SetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, PUSAGE UsageList, PULONG UsageLength, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength); +NTSTATUS WINAPI HidP_UnsetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, PUSAGE UsageList, PULONG UsageLength, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength); NTSTATUS WINAPI HidP_TranslateUsagesToI8042ScanCodes(USAGE *ChangedUsageList, ULONG UsageListLength, HIDP_KEYBOARD_DIRECTION KeyAction, HIDP_KEYBOARD_MODIFIER_STATE *ModifierState, PHIDP_INSERT_SCANCODES InsertCodesProcedure, VOID *InsertCodesContext); NTSTATUS WINAPI HidP_GetSpecificButtonCaps(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, HIDP_BUTTON_CAPS *ButtonCaps, USHORT *ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData); NTSTATUS WINAPI HidP_GetSpecificValueCaps(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, HIDP_VALUE_CAPS *ValueCaps, USHORT *ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=96288
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
ntoskrnl.exe: driver.c:902: Test failed: got 0 driver.c:903: Test failed: DPC was called.
The function seems to actually do overflows and rounding errors.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
It's so nasty that I'm not even sure anymore that I'll use it, but here we go anyway.
dlls/hid/hid.spec | 2 +- dlls/hid/hidp.c | 47 +++++++++++++++ dlls/ntoskrnl.exe/tests/driver_hid.c | 10 ++++ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 86 +++++++++++++++++++++++++--- include/ddk/hidpi.h | 1 + 5 files changed, 138 insertions(+), 8 deletions(-)
diff --git a/dlls/hid/hid.spec b/dlls/hid/hid.spec index 5d4706e3727..37dfdbce307 100644 --- a/dlls/hid/hid.spec +++ b/dlls/hid/hid.spec @@ -35,7 +35,7 @@ @ stdcall HidP_MaxDataListLength(long ptr) @ stdcall HidP_MaxUsageListLength(long long ptr) @ stub HidP_SetData -@ stub HidP_SetScaledUsageValue +@ stdcall HidP_SetScaledUsageValue(long long long long long ptr ptr long) @ stdcall HidP_SetUsageValue(long long long long long ptr ptr long) @ stdcall HidP_SetUsageValueArray(long long long long ptr long ptr ptr long) @ stdcall HidP_SetUsages(long long long ptr ptr ptr ptr long) diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 8c43d27f252..cd9de2148c2 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -380,6 +380,53 @@ ULONG WINAPI HidP_MaxUsageListLength( HIDP_REPORT_TYPE report_type, USAGE usage_ return count; }
+static NTSTATUS set_scaled_usage_value( const struct hid_value_caps *caps, void *user ) +{ + ULONG bit_count = caps->bit_size * caps->report_count; + struct usage_value_params *params = user; + LONG value, log_range, phy_range; + + if (caps->logical_min > caps->logical_max) return HIDP_STATUS_BAD_LOG_PHY_VALUES; + if (caps->physical_min > caps->physical_max) return HIDP_STATUS_BAD_LOG_PHY_VALUES; + + if ((bit_count + 7) / 8 > sizeof(value)) return HIDP_STATUS_BUFFER_TOO_SMALL; + if (sizeof(LONG) > params->value_len) return HIDP_STATUS_BUFFER_TOO_SMALL; + value = *(LONG *)params->value_buf; + + if (caps->physical_min || caps->physical_max) + { + /* testing shows that this is what the function does, including all + * the overflows and rounding errors... */ + log_range = (caps->logical_max - caps->logical_min + 1) / 2; + phy_range = (caps->physical_max - caps->physical_min + 1) / 2; + value = value - caps->physical_min; + value = (log_range * value) / phy_range; + value = caps->logical_min + value; + } + + copy_bits( params->report_buf, (unsigned char *)&value, bit_count, caps->start_bit ); + + return HIDP_STATUS_NULL; +} + +NTSTATUS WINAPI HidP_SetScaledUsageValue( HIDP_REPORT_TYPE report_type, USAGE usage_page, USHORT collection, + USAGE usage, LONG value, PHIDP_PREPARSED_DATA preparsed_data, + char *report_buf, ULONG report_len ) +{ + struct usage_value_params params = {.value_buf = &value, .value_len = sizeof(value), .report_buf = report_buf}; + struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data; + struct caps_filter filter = {.values = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage }; + USHORT count = 1; + + TRACE( "report_type %d, usage_page %x, collection %d, usage %x, value %d, preparsed_data %p, report_buf %p, report_len %u.\n", + report_type, usage_page, collection, usage, value, preparsed_data, report_buf, report_len ); + + if (!report_len) return HIDP_STATUS_INVALID_REPORT_LENGTH; + + filter.report_id = report_buf[0]; + return enum_value_caps( preparsed, report_type, report_len, &filter, set_scaled_usage_value, ¶ms, &count ); +} + static NTSTATUS set_usage_value( const struct hid_value_caps *caps, void *user ) { struct usage_value_params *params = user; diff --git a/dlls/ntoskrnl.exe/tests/driver_hid.c b/dlls/ntoskrnl.exe/tests/driver_hid.c index ce942815dcb..ed0767877ac 100644 --- a/dlls/ntoskrnl.exe/tests/driver_hid.c +++ b/dlls/ntoskrnl.exe/tests/driver_hid.c @@ -356,6 +356,16 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) /* reset global items */ UNIT(1, 0), /* None */ UNIT_EXPONENT(1, 0), + + USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), + USAGE(1, HID_USAGE_GENERIC_Z), + LOGICAL_MINIMUM(4, 0x0000), + LOGICAL_MAXIMUM(4, 0x7fff), + PHYSICAL_MINIMUM(4, 0xfff90000), + PHYSICAL_MAXIMUM(4, 0x0003ffff), + REPORT_SIZE(1, 32), + REPORT_COUNT(1, 1), + FEATURE(1, Data|Var|Abs), END_COLLECTION,
USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC), diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 34491500423..84711f75b33 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1686,14 +1686,14 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled .UsagePage = HID_USAGE_PAGE_GENERIC, .InputReportByteLength = 26, .OutputReportByteLength = 3, - .FeatureReportByteLength = 18, + .FeatureReportByteLength = 22, .NumberLinkCollectionNodes = 10, .NumberInputButtonCaps = 17, .NumberInputValueCaps = 7, .NumberInputDataIndices = 47, .NumberFeatureButtonCaps = 1, - .NumberFeatureValueCaps = 5, - .NumberFeatureDataIndices = 7, + .NumberFeatureValueCaps = 6, + .NumberFeatureDataIndices = 8, }, /* with report id */ { @@ -1701,14 +1701,14 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled .UsagePage = HID_USAGE_PAGE_GENERIC, .InputReportByteLength = 25, .OutputReportByteLength = 2, - .FeatureReportByteLength = 17, + .FeatureReportByteLength = 21, .NumberLinkCollectionNodes = 10, .NumberInputButtonCaps = 17, .NumberInputValueCaps = 7, .NumberInputDataIndices = 47, .NumberFeatureButtonCaps = 1, - .NumberFeatureValueCaps = 5, - .NumberFeatureDataIndices = 7, + .NumberFeatureValueCaps = 6, + .NumberFeatureDataIndices = 8, }, }; const HIDP_BUTTON_CAPS expect_button_caps[] = @@ -2182,6 +2182,10 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled (LONG *)&value, preparsed_data, report, caps.InputReportByteLength); ok(status == HIDP_STATUS_BAD_LOG_PHY_VALUES, "HidP_GetScaledUsageValue returned %#x\n", status); ok(value == 0, "got value %x, expected %#x\n", value, 0); + status = HidP_SetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY, + 0, preparsed_data, report, caps.InputReportByteLength); + ok(status == HIDP_STATUS_BAD_LOG_PHY_VALUES, "HidP_GetScaledUsageValue returned %#x\n", status); + ok(value == 0, "got value %x, expected %#x\n", value, 0);
value = HidP_MaxUsageListLength(HidP_Feature + 1, 0, preparsed_data); ok(value == 0, "HidP_MaxUsageListLength(HidP_Feature + 1, 0) returned %d, expected %d\n", value, 0); @@ -2311,7 +2315,7 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled value = HidP_MaxDataListLength(HidP_Output, preparsed_data); ok(value == 0, "HidP_MaxDataListLength(HidP_Output) returned %d, expected %d\n", value, 0); value = HidP_MaxDataListLength(HidP_Feature, preparsed_data); - ok(value == 13, "HidP_MaxDataListLength(HidP_Feature) returned %d, expected %d\n", value, 13); + ok(value == 14, "HidP_MaxDataListLength(HidP_Feature) returned %d, expected %d\n", value, 14);
value = 1; status = HidP_GetData(HidP_Input, data, &value, preparsed_data, report, caps.InputReportByteLength); @@ -2474,6 +2478,74 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled ok(!memcmp(buffer, buffer + 16, 16), "unexpected report value\n");
+ value = 0x7fffffff; + status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + value, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status); + value = 0xdeadbeef; + status = HidP_GetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + (LONG *)&value, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_VALUE_OUT_OF_RANGE, "HidP_GetScaledUsageValue returned %#x\n", status); + ok(value == 0, "got value %x, expected %#x\n", value, 0); + value = 0xdeadbeef; + status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + &value, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status); + ok(value == 0x7fffffff, "got value %x, expected %#x\n", value, 0x7fffffff); + + value = 0x7fff; + status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + value, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status); + value = 0xdeadbeef; + status = HidP_GetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + (LONG *)&value, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status); + ok(value == 0x0003ffff, "got value %x, expected %#x\n", value, 0x0003ffff); + + value = 0; + status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + value, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status); + value = 0xdeadbeef; + status = HidP_GetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + (LONG *)&value, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status); + ok(value == 0xfff90000, "got value %x, expected %#x\n", value, 0xfff90000); + status = HidP_SetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + 0x1000, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status); + value = 0; + status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + &value, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status); + ok(value == 0xfffff518, "got value %x, expected %#x\n", value, 0xfffff518); + status = HidP_SetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + 0, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status); + value = 0; + status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + &value, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status); + ok(value == 0xfffff45e, "got value %x, expected %#x\n", value, 0xfffff45e); + status = HidP_SetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + 0xdead, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status); + value = 0; + status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + &value, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status); + ok(value == 0xfffffe7d, "got value %x, expected %#x\n", value, 0xfffffe7d); + status = HidP_SetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + 0xbeef, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status); + value = 0; + status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, + &value, preparsed_data, report, caps.FeatureReportByteLength); + ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status); + ok(value == 0xfffffd0b, "got value %x, expected %#x\n", value, 0xfffffd0b); + + memset(report, 0xcd, sizeof(report)); status = HidP_InitializeReportForID(HidP_Input, report_id, preparsed_data, report, caps.InputReportByteLength); ok(status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status); diff --git a/include/ddk/hidpi.h b/include/ddk/hidpi.h index 305c38a95d3..e2e2bd2229b 100644 --- a/include/ddk/hidpi.h +++ b/include/ddk/hidpi.h @@ -202,6 +202,7 @@ NTSTATUS WINAPI HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS NTSTATUS WINAPI HidP_InitializeReportForID(HIDP_REPORT_TYPE ReportType, UCHAR ReportID, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength); ULONG WINAPI HidP_MaxUsageListLength(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, PHIDP_PREPARSED_DATA PreparsedData); NTSTATUS WINAPI HidP_GetScaledUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, PLONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength); +NTSTATUS WINAPI HidP_SetScaledUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, LONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength); NTSTATUS WINAPI HidP_SetUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, ULONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData, CHAR *Report, ULONG ReportLength); NTSTATUS WINAPI HidP_SetUsageValueArray( HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, PCHAR UsageValue, USHORT UsageValueByteLength,