Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 160 +++++++++++++++++------------ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 41 +------- include/wine/hid.h | 30 ------ 3 files changed, 95 insertions(+), 136 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index bdf03a652f4..301c367d37a 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -66,6 +66,49 @@ static NTSTATUS get_value_caps_range( WINE_HIDP_PREPARSED_DATA *preparsed, HIDP_ return HIDP_STATUS_SUCCESS; }
+struct caps_filter +{ + BOOLEAN buttons; + USAGE usage_page; + USHORT collection; + USAGE usage; +}; + +static BOOL match_value_caps( const struct hid_value_caps *caps, const struct caps_filter *filter ) +{ + if (!caps->usage_min && !caps->usage_max) return FALSE; + if (filter->buttons && !HID_VALUE_CAPS_IS_BUTTON( caps )) return FALSE; + if (filter->usage_page && filter->usage_page != caps->usage_page) return FALSE; + if (filter->collection && filter->collection != caps->link_collection) return FALSE; + if (!filter->usage) return TRUE; + return caps->usage_min <= filter->usage && caps->usage_max >= filter->usage; +} + +typedef NTSTATUS (*enum_value_caps_callback)( const struct hid_value_caps *caps, void *user ); + +static NTSTATUS enum_value_caps( WINE_HIDP_PREPARSED_DATA *preparsed, HIDP_REPORT_TYPE report_type, + const struct caps_filter *filter, enum_value_caps_callback callback, + void *user, USHORT *count ) +{ + const struct hid_value_caps *caps, *caps_end; + NTSTATUS status; + LONG remaining = *count; + + for (status = get_value_caps_range( preparsed, report_type, 0, &caps, &caps_end ); + status == HIDP_STATUS_SUCCESS && caps != caps_end; caps++) + { + if (!match_value_caps( caps, filter )) continue; + if (remaining-- > 0) status = callback( caps, user ); + } + + if (status != HIDP_STATUS_SUCCESS) return status; + + *count -= remaining; + if (*count == 0) return HIDP_STATUS_USAGE_NOT_FOUND; + if (remaining < 0) return HIDP_STATUS_BUFFER_TOO_SMALL; + return HIDP_STATUS_SUCCESS; +} + static NTSTATUS get_report_data(BYTE *report, INT reportLength, INT startBit, INT valueSize, PULONG value) {
@@ -192,17 +235,18 @@ NTSTATUS WINAPI HidP_GetButtonCaps( HIDP_REPORT_TYPE report_type, HIDP_BUTTON_CA return HidP_GetSpecificButtonCaps( report_type, 0, 0, 0, caps, caps_count, preparsed_data ); }
-NTSTATUS WINAPI HidP_GetCaps(PHIDP_PREPARSED_DATA PreparsedData, - PHIDP_CAPS Capabilities) +NTSTATUS WINAPI HidP_GetCaps( PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *caps ) { - PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData; + WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data;
- TRACE("(%p, %p)\n",PreparsedData, Capabilities); + TRACE( "preparsed_data %p, caps %p.\n", preparsed_data, caps );
- if (data->magic != HID_MAGIC) - return HIDP_STATUS_INVALID_PREPARSED_DATA; + if (preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA;
- *Capabilities = data->caps; + *caps = preparsed->caps; + caps->NumberInputButtonCaps = preparsed->new_caps.NumberInputButtonCaps; + caps->NumberOutputButtonCaps = preparsed->new_caps.NumberOutputButtonCaps; + caps->NumberFeatureButtonCaps = preparsed->new_caps.NumberFeatureButtonCaps;
return HIDP_STATUS_SUCCESS; } @@ -603,75 +647,59 @@ NTSTATUS WINAPI HidP_TranslateUsagesToI8042ScanCodes(USAGE *ChangedUsageList, return STATUS_NOT_IMPLEMENTED; }
-NTSTATUS WINAPI HidP_GetSpecificButtonCaps(HIDP_REPORT_TYPE ReportType, - USAGE UsagePage, USHORT LinkCollection, USAGE Usage, - HIDP_BUTTON_CAPS *ButtonCaps, USHORT *ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData) +static NTSTATUS get_button_caps( const struct hid_value_caps *caps, void *user ) { - 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; - - TRACE("(%i, 0x%x, %i, 0x%x, %p %p %p)\n", ReportType, UsagePage, LinkCollection, - Usage, ButtonCaps, ButtonCapsLength, PreparsedData); - - if (data->magic != HID_MAGIC) - return HIDP_STATUS_INVALID_PREPARSED_DATA; - - switch(ReportType) + HIDP_BUTTON_CAPS **iter = user, *dst = *iter; + dst->UsagePage = caps->usage_page; + dst->ReportID = caps->report_id; + dst->LinkCollection = caps->link_collection; + dst->LinkUsagePage = caps->link_usage_page; + dst->LinkUsage = caps->link_usage; + dst->BitField = caps->bit_field; + dst->IsAlias = FALSE; + dst->IsAbsolute = HID_VALUE_CAPS_IS_ABSOLUTE( caps ); + if (!(dst->IsRange = caps->is_range)) { - case HidP_Input: - b_count = data->caps.NumberInputButtonCaps; - report = HID_INPUT_REPORTS(data); - break; - case HidP_Output: - b_count = data->caps.NumberOutputButtonCaps; - report = HID_OUTPUT_REPORTS(data); - break; - case HidP_Feature: - b_count = data->caps.NumberFeatureButtonCaps; - report = HID_FEATURE_REPORTS(data); - break; - default: - return HIDP_STATUS_INVALID_REPORT_TYPE; + dst->NotRange.Usage = caps->usage_min; + dst->NotRange.DataIndex = caps->data_index_min; } - r_count = data->reportCount[ReportType]; - - if (!r_count || !b_count) + else { - *ButtonCapsLength = 0; - return HIDP_STATUS_SUCCESS; + dst->Range.UsageMin = caps->usage_min; + dst->Range.UsageMax = caps->usage_max; + dst->Range.DataIndexMin = caps->data_index_min; + dst->Range.DataIndexMax = caps->data_index_max; } - - b_count = min(b_count, *ButtonCapsLength); - - u = 0; - for (j = 0; j < r_count && u < b_count; j++) + if (!(dst->IsStringRange = caps->is_string_range)) + dst->NotRange.StringIndex = caps->string_min; + else { - for (i = 0; i < report[j].elementCount && u < b_count; i++) - { - if (elems[report[j].elementIdx + i].caps.BitSize == 1 && - (UsagePage == 0 || UsagePage == elems[report[j].elementIdx + i].caps.UsagePage) && - (LinkCollection == 0 || LinkCollection == elems[report[j].elementIdx + i].caps.LinkCollection) && - (Usage == 0 || ( - (!elems[report[j].elementIdx + i].caps.IsRange && - Usage == elems[report[j].elementIdx + i].caps.NotRange.Usage)) || - (elems[report[j].elementIdx + i].caps.IsRange && - Usage >= elems[report[j].elementIdx + i].caps.Range.UsageMin && - Usage <= elems[report[j].elementIdx + i].caps.Range.UsageMax))) - { - ButtonCaps[u++] = *(HIDP_BUTTON_CAPS *)&elems[report[j].elementIdx + i].caps; - } - } + dst->Range.StringMin = caps->string_min; + dst->Range.StringMax = caps->string_max; } - TRACE("Matched %i usages\n", u); - - *ButtonCapsLength = u; - + if ((dst->IsDesignatorRange = caps->is_designator_range)) + dst->NotRange.DesignatorIndex = caps->designator_min; + else + { + dst->Range.DesignatorMin = caps->designator_min; + dst->Range.DesignatorMax = caps->designator_max; + } + *iter += 1; return HIDP_STATUS_SUCCESS; }
+NTSTATUS WINAPI HidP_GetSpecificButtonCaps( HIDP_REPORT_TYPE report_type, USAGE usage_page, USHORT collection, + USAGE usage, HIDP_BUTTON_CAPS *caps, USHORT *caps_count, + PHIDP_PREPARSED_DATA preparsed_data ) +{ + WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + const struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage}; + + TRACE( "report_type %d, usage_page %x, collection %d, usage %x, caps %p, caps_count %p, preparsed_data %p.\n", + report_type, usage_page, collection, usage, caps, caps_count, preparsed_data ); + + return enum_value_caps( preparsed, report_type, &filter, get_button_caps, &caps, caps_count ); +}
NTSTATUS WINAPI HidP_GetSpecificValueCaps(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index ff3749569ff..11779daf684 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1833,7 +1833,6 @@ static void test_hidp(HANDLE file, int report_id) check_member(caps, expect_hidp_caps[report_id], "%d", OutputReportByteLength); check_member(caps, expect_hidp_caps[report_id], "%d", FeatureReportByteLength); check_member(caps, expect_hidp_caps[report_id], "%d", NumberLinkCollectionNodes); - todo_wine check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputButtonCaps); todo_wine check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputValueCaps); @@ -1870,15 +1869,12 @@ static void test_hidp(HANDLE file, int report_id)
count = ARRAY_SIZE(button_caps); status = HidP_GetButtonCaps(HidP_Output, button_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetButtonCaps returned %#x\n", status); status = HidP_GetButtonCaps(HidP_Feature + 1, button_caps, &count, preparsed_data); ok(status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetButtonCaps returned %#x\n", status); count = 0; status = HidP_GetButtonCaps(HidP_Input, button_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetButtonCaps returned %#x\n", status); - todo_wine ok(count == caps.NumberInputButtonCaps, "HidP_GetButtonCaps returned count %d, expected %d\n", count, caps.NumberInputButtonCaps); count = ARRAY_SIZE(button_caps); @@ -1893,50 +1889,18 @@ static void test_hidp(HANDLE file, int report_id) for (i = 0; i < ARRAY_SIZE(expect_button_caps); ++i) { winetest_push_context("button_caps[%d]", i); - todo_wine_if(i >= 2) - check_member(button_caps[i], expect_button_caps[i], "%04x", UsagePage); - check_member(button_caps[i], expect_button_caps[i], "%d", ReportID); - check_member(button_caps[i], expect_button_caps[i], "%d", IsAlias); - todo_wine_if(i == 1 || i == 2) - check_member(button_caps[i], expect_button_caps[i], "%d", BitField); - todo_wine_if(i >= 2) - check_member(button_caps[i], expect_button_caps[i], "%d", LinkCollection); - todo_wine_if(i >= (report_id ? 2 : 3)) - check_member(button_caps[i], expect_button_caps[i], "%04x", LinkUsage); - todo_wine_if(i >= (report_id ? 2 : 3)) - check_member(button_caps[i], expect_button_caps[i], "%04x", LinkUsagePage); - todo_wine_if(i >= 1 && i <= (report_id ? 2 : 1)) - check_member(button_caps[i], expect_button_caps[i], "%d", IsRange); - check_member(button_caps[i], expect_button_caps[i], "%d", IsStringRange); - check_member(button_caps[i], expect_button_caps[i], "%d", IsDesignatorRange); - todo_wine_if(i == 2) - check_member(button_caps[i], expect_button_caps[i], "%d", IsAbsolute); - todo_wine_if(i >= 1) - check_member(button_caps[i], expect_button_caps[i], "%04x", Range.UsageMin); - todo_wine_if(i >= 1) - check_member(button_caps[i], expect_button_caps[i], "%04x", Range.UsageMax); - check_member(button_caps[i], expect_button_caps[i], "%d", Range.StringMin); - check_member(button_caps[i], expect_button_caps[i], "%d", Range.StringMax); - check_member(button_caps[i], expect_button_caps[i], "%d", Range.DesignatorMin); - check_member(button_caps[i], expect_button_caps[i], "%d", Range.DesignatorMax); - todo_wine_if(i >= 1) - check_member(button_caps[i], expect_button_caps[i], "%d", Range.DataIndexMin); - todo_wine_if(i >= 1) - check_member(button_caps[i], expect_button_caps[i], "%d", Range.DataIndexMax); + check_hidp_button_caps(&button_caps[i], &expect_button_caps[i]); winetest_pop_context(); }
count = ARRAY_SIZE(button_caps) - 1; status = HidP_GetSpecificButtonCaps(HidP_Output, 0, 0, 0, button_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status); status = HidP_GetSpecificButtonCaps(HidP_Feature + 1, 0, 0, 0, button_caps, &count, preparsed_data); ok(status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetSpecificButtonCaps returned %#x\n", status); count = 0; status = HidP_GetSpecificButtonCaps(HidP_Input, 0, 0, 0, button_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetSpecificButtonCaps returned %#x\n", status); - todo_wine ok(count == caps.NumberInputButtonCaps, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, caps.NumberInputButtonCaps); count = ARRAY_SIZE(button_caps) - 1; @@ -1957,17 +1921,14 @@ static void test_hidp(HANDLE file, int report_id)
count = 0xbeef; status = HidP_GetSpecificButtonCaps(HidP_Input, 0xfffe, 0, 0, button_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status); ok(count == 0, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, 0); count = 0xbeef; status = HidP_GetSpecificButtonCaps(HidP_Input, 0, 0xfffe, 0, button_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status); ok(count == 0, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, 0); count = 0xbeef; status = HidP_GetSpecificButtonCaps(HidP_Input, 0, 0, 0xfffe, button_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status); ok(count == 0, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, 0);
diff --git a/include/wine/hid.h b/include/wine/hid.h index 5609adec11f..ceb07069b52 100644 --- a/include/wine/hid.h +++ b/include/wine/hid.h @@ -38,36 +38,6 @@ typedef struct __WINE_ELEMENT HIDP_VALUE_CAPS caps; } WINE_HID_ELEMENT;
-/* make sure HIDP_BUTTON_CAPS is a subset of HIDP_VALUE_CAPS */ -C_ASSERT( sizeof(HIDP_BUTTON_CAPS) == sizeof(HIDP_VALUE_CAPS) ); - -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, UsagePage) == offsetof(HIDP_VALUE_CAPS, UsagePage) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, ReportID) == offsetof(HIDP_VALUE_CAPS, ReportID) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, IsAlias) == offsetof(HIDP_VALUE_CAPS, IsAlias) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, BitField) == offsetof(HIDP_VALUE_CAPS, BitField) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, LinkCollection) == offsetof(HIDP_VALUE_CAPS, LinkCollection) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, LinkUsage) == offsetof(HIDP_VALUE_CAPS, LinkUsage) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, LinkUsagePage) == offsetof(HIDP_VALUE_CAPS, LinkUsagePage) ); - -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, IsRange) == offsetof(HIDP_VALUE_CAPS, IsRange) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, IsStringRange) == offsetof(HIDP_VALUE_CAPS, IsStringRange) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, IsDesignatorRange) == offsetof(HIDP_VALUE_CAPS, IsDesignatorRange) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, IsAbsolute) == offsetof(HIDP_VALUE_CAPS, IsAbsolute) ); - -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, Range.UsageMin) == offsetof(HIDP_VALUE_CAPS, Range.UsageMin) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, Range.UsageMax) == offsetof(HIDP_VALUE_CAPS, Range.UsageMax) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, Range.StringMin) == offsetof(HIDP_VALUE_CAPS, Range.StringMin) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, Range.StringMax) == offsetof(HIDP_VALUE_CAPS, Range.StringMax) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, Range.DesignatorMin) == offsetof(HIDP_VALUE_CAPS, Range.DesignatorMin) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, Range.DesignatorMax) == offsetof(HIDP_VALUE_CAPS, Range.DesignatorMax) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, Range.DataIndexMin) == offsetof(HIDP_VALUE_CAPS, Range.DataIndexMin) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, Range.DataIndexMax) == offsetof(HIDP_VALUE_CAPS, Range.DataIndexMax) ); - -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, NotRange.Usage) == offsetof(HIDP_VALUE_CAPS, NotRange.Usage) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, NotRange.StringIndex) == offsetof(HIDP_VALUE_CAPS, NotRange.StringIndex) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, NotRange.DesignatorIndex) == offsetof(HIDP_VALUE_CAPS, NotRange.DesignatorIndex) ); -C_ASSERT( offsetof(HIDP_BUTTON_CAPS, NotRange.DataIndex) == offsetof(HIDP_VALUE_CAPS, NotRange.DataIndex) ); - struct hid_value_caps { USAGE usage_page;