[PATCH 3/4] hid: Implement HidP_UnsetUsages.

Rémi Bernon rbernon at codeweavers.com
Wed Aug 25 11:08:32 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at 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, &params, &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);
-- 
2.33.0




More information about the wine-devel mailing list