From 3b40a032675fdf3cc24e1b207896aa4c8cadc8cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Wed, 25 Aug 2021 18:08:32 +0200 Subject: [PATCH] hid: Implement HidP_UnsetUsages. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RĂ©mi Bernon Signed-off-by: Alexandre Julliard --- 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 2f5c2cd81cc..115032dbb52 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);