Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 110 +++++++++++++++-------------- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 91 +----------------------- 2 files changed, 59 insertions(+), 142 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 301c367d37a..c11a5d66985 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -69,6 +69,7 @@ static NTSTATUS get_value_caps_range( WINE_HIDP_PREPARSED_DATA *preparsed, HIDP_ struct caps_filter { BOOLEAN buttons; + BOOLEAN values; USAGE usage_page; USHORT collection; USAGE usage; @@ -78,6 +79,7 @@ static BOOL match_value_caps( const struct hid_value_caps *caps, const struct ca { if (!caps->usage_min && !caps->usage_max) return FALSE; if (filter->buttons && !HID_VALUE_CAPS_IS_BUTTON( caps )) return FALSE; + if (filter->values && 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; @@ -247,6 +249,9 @@ NTSTATUS WINAPI HidP_GetCaps( PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *ca caps->NumberInputButtonCaps = preparsed->new_caps.NumberInputButtonCaps; caps->NumberOutputButtonCaps = preparsed->new_caps.NumberOutputButtonCaps; caps->NumberFeatureButtonCaps = preparsed->new_caps.NumberFeatureButtonCaps; + caps->NumberInputValueCaps = preparsed->new_caps.NumberInputValueCaps; + caps->NumberOutputValueCaps = preparsed->new_caps.NumberOutputValueCaps; + caps->NumberFeatureValueCaps = preparsed->new_caps.NumberFeatureValueCaps;
return HIDP_STATUS_SUCCESS; } @@ -701,68 +706,67 @@ NTSTATUS WINAPI HidP_GetSpecificButtonCaps( HIDP_REPORT_TYPE report_type, USAGE 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, - HIDP_VALUE_CAPS *ValueCaps, USHORT *ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData) +static NTSTATUS get_value_caps( const struct hid_value_caps *caps, void *user ) { - WINE_HIDP_PREPARSED_DATA *data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData; - WINE_HID_ELEMENT *elems = HID_ELEMS(data); - WINE_HID_REPORT *report = NULL; - USHORT v_count = 0, r_count = 0; - int i,j,u; - - TRACE("(%i, 0x%x, %i, 0x%x, %p %p %p)\n", ReportType, UsagePage, LinkCollection, - Usage, ValueCaps, ValueCapsLength, PreparsedData); - - if (data->magic != HID_MAGIC) - return HIDP_STATUS_INVALID_PREPARSED_DATA; - - switch(ReportType) + HIDP_VALUE_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 ); + dst->HasNull = HID_VALUE_CAPS_HAS_NULL( caps ); + dst->BitSize = caps->bit_size; + dst->ReportCount = caps->is_range ? 1 : caps->report_count; + dst->UnitsExp = caps->units_exp; + dst->Units = caps->units; + dst->LogicalMin = caps->logical_min; + dst->LogicalMax = caps->logical_max; + dst->PhysicalMin = caps->physical_min; + dst->PhysicalMax = caps->physical_max; + if (!(dst->IsRange = caps->is_range)) { - case HidP_Input: - v_count = data->caps.NumberInputValueCaps; - report = HID_INPUT_REPORTS(data); - break; - case HidP_Output: - v_count = data->caps.NumberOutputValueCaps; - report = HID_OUTPUT_REPORTS(data); - break; - case HidP_Feature: - v_count = data->caps.NumberFeatureValueCaps; - 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 || !v_count) + else { - *ValueCapsLength = 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; } - - v_count = min(v_count, *ValueCapsLength); - - u = 0; - for (j = 0; j < r_count && u < v_count; j++) + if (!(dst->IsStringRange = caps->is_string_range)) + dst->NotRange.StringIndex = caps->string_min; + else { - for (i = 0; i < report[j].elementCount && u < v_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 || Usage == elems[report[j].elementIdx + i].caps.NotRange.Usage)) - { - ValueCaps[u++] = elems[report[j].elementIdx + i].caps; - } - } + dst->Range.StringMin = caps->string_min; + dst->Range.StringMax = caps->string_max; } - TRACE("Matched %i usages\n", 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_GetSpecificValueCaps( HIDP_REPORT_TYPE report_type, USAGE usage_page, USHORT collection, + USAGE usage, HIDP_VALUE_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 = {.values = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage};
- *ValueCapsLength = u; + 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 HIDP_STATUS_SUCCESS; + return enum_value_caps( preparsed, report_type, &filter, get_value_caps, &caps, caps_count ); }
NTSTATUS WINAPI HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType, USHORT LinkCollection, USAGE_AND_PAGE *ButtonList, diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 11779daf684..3ce750728ec 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -1834,7 +1834,6 @@ static void test_hidp(HANDLE file, int report_id) check_member(caps, expect_hidp_caps[report_id], "%d", FeatureReportByteLength); check_member(caps, expect_hidp_caps[report_id], "%d", NumberLinkCollectionNodes); check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputButtonCaps); - todo_wine check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputValueCaps); todo_wine check_member(caps, expect_hidp_caps[report_id], "%d", NumberInputDataIndices); @@ -1934,15 +1933,12 @@ static void test_hidp(HANDLE file, int report_id)
count = ARRAY_SIZE(value_caps); status = HidP_GetValueCaps(HidP_Output, value_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetValueCaps returned %#x\n", status); status = HidP_GetValueCaps(HidP_Feature + 1, value_caps, &count, preparsed_data); ok(status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetValueCaps returned %#x\n", status); count = 0; status = HidP_GetValueCaps(HidP_Input, value_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetValueCaps returned %#x\n", status); - todo_wine ok(count == caps.NumberInputValueCaps, "HidP_GetValueCaps returned count %d, expected %d\n", count, caps.NumberInputValueCaps); count = ARRAY_SIZE(value_caps); @@ -1956,61 +1952,18 @@ static void test_hidp(HANDLE file, int report_id) for (i = 0; i < ARRAY_SIZE(expect_value_caps); ++i) { winetest_push_context("value_caps[%d]", i); - todo_wine_if(i == 3) - check_member(value_caps[i], expect_value_caps[i], "%04x", UsagePage); - check_member(value_caps[i], expect_value_caps[i], "%d", ReportID); - check_member(value_caps[i], expect_value_caps[i], "%d", IsAlias); - todo_wine_if(i == 2) - check_member(value_caps[i], expect_value_caps[i], "%d", BitField); - check_member(value_caps[i], expect_value_caps[i], "%d", LinkCollection); - check_member(value_caps[i], expect_value_caps[i], "%04x", LinkUsage); - check_member(value_caps[i], expect_value_caps[i], "%04x", LinkUsagePage); - todo_wine_if(i == 3) - check_member(value_caps[i], expect_value_caps[i], "%d", IsRange); - check_member(value_caps[i], expect_value_caps[i], "%d", IsStringRange); - check_member(value_caps[i], expect_value_caps[i], "%d", IsDesignatorRange); - todo_wine_if(i == 2) - check_member(value_caps[i], expect_value_caps[i], "%d", IsAbsolute); - todo_wine_if(i == 2) - check_member(value_caps[i], expect_value_caps[i], "%d", HasNull); - todo_wine_if(i >= 2) - check_member(value_caps[i], expect_value_caps[i], "%d", BitSize); - todo_wine_if(i == 2) - check_member(value_caps[i], expect_value_caps[i], "%d", ReportCount); - check_member(value_caps[i], expect_value_caps[i], "%d", UnitsExp); - check_member(value_caps[i], expect_value_caps[i], "%d", Units); - todo_wine_if(i >= 3) - check_member(value_caps[i], expect_value_caps[i], "%d", LogicalMin); - todo_wine_if(i >= 2) - check_member(value_caps[i], expect_value_caps[i], "%d", LogicalMax); - check_member(value_caps[i], expect_value_caps[i], "%d", PhysicalMin); - check_member(value_caps[i], expect_value_caps[i], "%d", PhysicalMax); - todo_wine - check_member(value_caps[i], expect_value_caps[i], "%04x", Range.UsageMin); - todo_wine - check_member(value_caps[i], expect_value_caps[i], "%04x", Range.UsageMax); - check_member(value_caps[i], expect_value_caps[i], "%d", Range.StringMin); - check_member(value_caps[i], expect_value_caps[i], "%d", Range.StringMax); - check_member(value_caps[i], expect_value_caps[i], "%d", Range.DesignatorMin); - check_member(value_caps[i], expect_value_caps[i], "%d", Range.DesignatorMax); - todo_wine_if(i >= 2) - check_member(value_caps[i], expect_value_caps[i], "%d", Range.DataIndexMin); - todo_wine_if(i >= 2) - check_member(value_caps[i], expect_value_caps[i], "%d", Range.DataIndexMax); + check_hidp_value_caps(&value_caps[i], &expect_value_caps[i]); winetest_pop_context(); }
count = ARRAY_SIZE(value_caps) - 4; status = HidP_GetSpecificValueCaps(HidP_Output, 0, 0, 0, value_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status); status = HidP_GetSpecificValueCaps(HidP_Feature + 1, 0, 0, 0, value_caps, &count, preparsed_data); ok(status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetSpecificValueCaps returned %#x\n", status); count = 0; status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0, 0, value_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetSpecificValueCaps returned %#x\n", status); - todo_wine ok(count == caps.NumberInputValueCaps, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, caps.NumberInputValueCaps); count = ARRAY_SIZE(value_caps) - 4; @@ -2031,58 +1984,18 @@ static void test_hidp(HANDLE file, int report_id) value_caps + 4, &count, preparsed_data); ok(status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificValueCaps returned %#x\n", status); ok(count == 1, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 1); - - todo_wine - check_member(value_caps[4], value_caps[3], "%04x", UsagePage); - check_member(value_caps[4], value_caps[3], "%d", ReportID); - check_member(value_caps[4], value_caps[3], "%d", IsAlias); - check_member(value_caps[4], value_caps[3], "%d", BitField); - check_member(value_caps[4], value_caps[3], "%d", LinkCollection); - check_member(value_caps[4], value_caps[3], "%04x", LinkUsage); - check_member(value_caps[4], value_caps[3], "%04x", LinkUsagePage); - todo_wine - check_member(value_caps[4], value_caps[3], "%d", IsRange); - check_member(value_caps[4], value_caps[3], "%d", IsStringRange); - check_member(value_caps[4], value_caps[3], "%d", IsDesignatorRange); - check_member(value_caps[4], value_caps[3], "%d", IsAbsolute); - check_member(value_caps[4], value_caps[3], "%d", HasNull); - todo_wine - check_member(value_caps[4], value_caps[3], "%d", BitSize); - check_member(value_caps[4], value_caps[3], "%d", ReportCount); - check_member(value_caps[4], value_caps[3], "%d", UnitsExp); - check_member(value_caps[4], value_caps[3], "%d", Units); - todo_wine - check_member(value_caps[4], value_caps[3], "%d", LogicalMin); - todo_wine - check_member(value_caps[4], value_caps[3], "%d", LogicalMax); - check_member(value_caps[4], value_caps[3], "%d", PhysicalMin); - check_member(value_caps[4], value_caps[3], "%d", PhysicalMax); - todo_wine - check_member(value_caps[4], value_caps[3], "%04x", Range.UsageMin); - todo_wine - check_member(value_caps[4], value_caps[3], "%04x", Range.UsageMax); - check_member(value_caps[4], value_caps[3], "%d", Range.StringMin); - check_member(value_caps[4], value_caps[3], "%d", Range.StringMax); - check_member(value_caps[4], value_caps[3], "%d", Range.DesignatorMin); - check_member(value_caps[4], value_caps[3], "%d", Range.DesignatorMax); - todo_wine - check_member(value_caps[4], value_caps[3], "%d", Range.DataIndexMin); - todo_wine - check_member(value_caps[4], value_caps[3], "%d", Range.DataIndexMax); + check_hidp_value_caps(&value_caps[4], &value_caps[3]);
count = 0xdead; status = HidP_GetSpecificValueCaps(HidP_Input, 0xfffe, 0, 0, value_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status); ok(count == 0, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 0); count = 0xdead; status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0xfffe, 0, value_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status); ok(count == 0, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 0); count = 0xdead; status = HidP_GetSpecificValueCaps(HidP_Input, 0, 0, 0xfffe, value_caps, &count, preparsed_data); - todo_wine ok(status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status); ok(count == 0, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 0);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 58 +++++++----------------------- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 4 --- 2 files changed, 12 insertions(+), 50 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index c11a5d66985..76b9ff5ee2c 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -524,56 +524,22 @@ NTSTATUS WINAPI HidP_InitializeReportForID( HIDP_REPORT_TYPE report_type, UCHAR return HIDP_STATUS_SUCCESS; }
-ULONG WINAPI HidP_MaxUsageListLength(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, PHIDP_PREPARSED_DATA PreparsedData) +static NTSTATUS get_usage_list_length( const struct hid_value_caps *caps, void *data ) { - PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData; - WINE_HID_ELEMENT *elems = HID_ELEMS(data); - WINE_HID_REPORT *report = NULL; - int r_count; - int i; - int count = 0; - - TRACE("(%i, %x, %p)\n", ReportType, UsagePage, PreparsedData); - - if (data->magic != HID_MAGIC) - return 0; - - switch(ReportType) - { - case HidP_Input: - report = HID_INPUT_REPORTS(data); - break; - case HidP_Output: - report = HID_OUTPUT_REPORTS(data); - break; - case HidP_Feature: - report = HID_FEATURE_REPORTS(data); - break; - default: - return HIDP_STATUS_INVALID_REPORT_TYPE; - } - r_count = data->reportCount[ReportType]; + *(ULONG *)data += caps->report_count; + return HIDP_STATUS_SUCCESS; +}
+ULONG WINAPI HidP_MaxUsageListLength( HIDP_REPORT_TYPE report_type, USAGE usage_page, PHIDP_PREPARSED_DATA preparsed_data ) +{ + WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page}; + USHORT limit = -1; + ULONG count = 0;
- if (!r_count) - return 0; + TRACE( "report_type %d, usage_page %x, preparsed_data %p.\n", report_type, usage_page, preparsed_data );
- for (i = 0; i < r_count; i++) - { - int j; - for (j = 0; j < report[i].elementCount; j++) - { - if (elems[report[i].elementIdx + j].caps.BitSize == 1 && - (UsagePage == 0 || elems[report[i].elementIdx + j].caps.UsagePage == UsagePage)) - { - if (elems[report[i].elementIdx + j].caps.IsRange) - count += (elems[report[i].elementIdx + j].caps.Range.UsageMax - - elems[report[i].elementIdx + j].caps.Range.UsageMin) + 1; - else - count++; - } - } - } + enum_value_caps( preparsed, report_type, &filter, get_usage_list_length, &count, &limit ); return count; }
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 3ce750728ec..8777880fd9d 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -2140,18 +2140,14 @@ static void test_hidp(HANDLE file, int report_id) ok(value == 0, "got value %x, expected %#x\n", value, 0);
value = HidP_MaxUsageListLength(HidP_Feature + 1, 0, preparsed_data); - todo_wine ok(value == 0, "HidP_MaxUsageListLength(HidP_Feature + 1, 0) returned %d, expected %d\n", value, 0); value = HidP_MaxUsageListLength(HidP_Input, 0, preparsed_data); - todo_wine ok(value == 42, "HidP_MaxUsageListLength(HidP_Input, 0) returned %d, expected %d\n", value, 42); value = HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON, preparsed_data); - todo_wine 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); ok(value == 8, "HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_LED) returned %d, expected %d\n", value, 8); value = HidP_MaxUsageListLength(HidP_Feature, HID_USAGE_PAGE_BUTTON, preparsed_data); - todo_wine ok(value == 8, "HidP_MaxUsageListLength(HidP_Feature, HID_USAGE_PAGE_BUTTON) returned %d, expected %d\n", value, 8); value = HidP_MaxUsageListLength(HidP_Feature, HID_USAGE_PAGE_LED, preparsed_data); ok(value == 0, "HidP_MaxUsageListLength(HidP_Feature, HID_USAGE_PAGE_LED) returned %d, expected %d\n", value, 0);
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=93032
Your paranoid android.
=== debiant2 (32 bit report) ===
hid: device: Timeout
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 71 ++++++++++++++++++++-------------- dlls/hidclass.sys/descriptor.c | 2 + include/wine/hid.h | 1 + 3 files changed, 45 insertions(+), 29 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 76b9ff5ee2c..6197e30c4da 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -73,6 +73,7 @@ struct caps_filter USAGE usage_page; USHORT collection; USAGE usage; + UCHAR report_id; };
static BOOL match_value_caps( const struct hid_value_caps *caps, const struct caps_filter *filter ) @@ -89,20 +90,22 @@ static BOOL match_value_caps( const struct hid_value_caps *caps, const struct ca 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 ) + ULONG report_len, 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 ); + for (status = get_value_caps_range( preparsed, report_type, report_len, &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 (filter->report_id && caps->report_id != filter->report_id) continue; + else if (remaining-- > 0) status = callback( caps, user ); }
+ if (status == HIDP_STATUS_NULL) status = HIDP_STATUS_SUCCESS; if (status != HIDP_STATUS_SUCCESS) return status;
*count -= remaining; @@ -539,7 +542,7 @@ ULONG WINAPI HidP_MaxUsageListLength( HIDP_REPORT_TYPE report_type, USAGE usage_
TRACE( "report_type %d, usage_page %x, preparsed_data %p.\n", report_type, usage_page, preparsed_data );
- enum_value_caps( preparsed, report_type, &filter, get_usage_list_length, &count, &limit ); + enum_value_caps( preparsed, report_type, 0, &filter, get_usage_list_length, &count, &limit ); return count; }
@@ -575,32 +578,42 @@ NTSTATUS WINAPI HidP_SetUsageValueArray( HIDP_REPORT_TYPE report_type, USAGE usa return HIDP_STATUS_NOT_IMPLEMENTED; }
-NTSTATUS WINAPI HidP_SetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, - PUSAGE UsageList, PULONG UsageLength, PHIDP_PREPARSED_DATA PreparsedData, - PCHAR Report, ULONG ReportLength) +struct set_usage_params { - WINE_HID_ELEMENT element; - NTSTATUS rc; - ULONG i; + USAGE usage; + char *report_buf; +};
- TRACE("(%i, %x, %i, %p, %p, %p, %p, %i)\n", ReportType, UsagePage, LinkCollection, UsageList, - UsageLength, PreparsedData, Report, ReportLength); +static NTSTATUS set_usage( const struct hid_value_caps *caps, void *user ) +{ + struct set_usage_params *params = user; + ULONG bit = caps->start_bit + params->usage - caps->usage_min; + params->report_buf[bit / 8] |= (1 << (bit % 8)); + return HIDP_STATUS_NULL; +}
- for (i = 0; i < *UsageLength; i++) - { - rc = find_usage(ReportType, UsagePage, LinkCollection, - UsageList[i], PreparsedData, Report, 1, &element); - if (rc == HIDP_STATUS_SUCCESS) - { - rc = set_report_data((BYTE*)Report, ReportLength, - element.valueStartBit, element.bitCount, -1); - } +NTSTATUS WINAPI HidP_SetUsages( 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 ) +{ + WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct set_usage_params params = {.report_buf = report_buf}; + struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection}; + NTSTATUS status; + USHORT limit = 1; + ULONG i, count = *usage_count;
- if (rc != HIDP_STATUS_SUCCESS) - { - *UsageLength = i; - return rc; - } + 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, set_usage, ¶ms, &limit ); + if (status != HIDP_STATUS_SUCCESS) return status; }
return HIDP_STATUS_SUCCESS; @@ -669,7 +682,7 @@ NTSTATUS WINAPI HidP_GetSpecificButtonCaps( HIDP_REPORT_TYPE report_type, 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 ); + return enum_value_caps( preparsed, report_type, 0, &filter, get_button_caps, &caps, caps_count ); }
static NTSTATUS get_value_caps( const struct hid_value_caps *caps, void *user ) @@ -732,7 +745,7 @@ NTSTATUS WINAPI HidP_GetSpecificValueCaps( HIDP_REPORT_TYPE report_type, USAGE u 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_value_caps, &caps, caps_count ); + return enum_value_caps( preparsed, report_type, 0, &filter, get_value_caps, &caps, caps_count ); }
NTSTATUS WINAPI HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType, USHORT LinkCollection, USAGE_AND_PAGE *ButtonList, diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c index e319519ca90..3b4455a0b88 100644 --- a/dlls/hidclass.sys/descriptor.c +++ b/dlls/hidclass.sys/descriptor.c @@ -481,6 +481,7 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY if (!*bit_size) *bit_size = 8; *bit_size += state->items.bit_size * state->items.report_count; *byte_size = max( *byte_size, (*bit_size + 7) / 8 ); + state->items.start_bit = *bit_size;
if (!state->items.report_count) { @@ -498,6 +499,7 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY state->items.report_count -= usages_size - 1; while (usages_size--) { + state->items.start_bit -= state->items.report_count * state->items.bit_size; 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]; diff --git a/include/wine/hid.h b/include/wine/hid.h index ceb07069b52..8d1d6d4d104 100644 --- a/include/wine/hid.h +++ b/include/wine/hid.h @@ -59,6 +59,7 @@ struct hid_value_caps USHORT bit_field; USHORT bit_size; USHORT report_count; + ULONG start_bit; LONG logical_min; LONG logical_max; LONG physical_min;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 98 ++++++++++-------------------- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 3 - 2 files changed, 33 insertions(+), 68 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 6197e30c4da..4889a1e4014 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -420,82 +420,50 @@ NTSTATUS WINAPI HidP_GetUsageValueArray(HIDP_REPORT_TYPE ReportType, USAGE Usage }
-NTSTATUS WINAPI HidP_GetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, - PUSAGE UsageList, PULONG UsageLength, PHIDP_PREPARSED_DATA PreparsedData, - PCHAR Report, ULONG ReportLength) +struct get_usage_params { - PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData; - WINE_HID_ELEMENT *elems = HID_ELEMS(data); - WINE_HID_REPORT *report = NULL; - BOOL found = FALSE; - USHORT b_count = 0, r_count = 0; - int i,uCount; + USAGE *usages; + USAGE *usages_end; + char *report_buf; +};
- TRACE("(%i, %x, %i, %p, %p, %p, %p, %i)\n", ReportType, UsagePage, LinkCollection, UsageList, - UsageLength, PreparsedData, Report, ReportLength); +static NTSTATUS get_usage( const struct hid_value_caps *caps, void *user ) +{ + struct get_usage_params *params = user; + ULONG bit, last;
- if (data->magic != HID_MAGIC) + for (bit = caps->start_bit, last = bit + caps->usage_max - caps->usage_min; bit <= last; ++bit) { - *UsageLength = 0; - return HIDP_STATUS_INVALID_PREPARSED_DATA; + if (!(params->report_buf[bit / 8] & (1 << (bit % 8)))) continue; + if (params->usages < params->usages_end) *params->usages = caps->usage_min + bit - caps->start_bit; + params->usages++; }
- switch(ReportType) - { - case HidP_Input: - b_count = data->caps.NumberInputButtonCaps; - break; - case HidP_Output: - b_count = data->caps.NumberOutputButtonCaps; - break; - case HidP_Feature: - b_count = data->caps.NumberFeatureButtonCaps; - break; - default: - return HIDP_STATUS_INVALID_REPORT_TYPE; - } - r_count = data->reportCount[ReportType]; - report = &data->reports[data->reportIdx[ReportType][(BYTE)Report[0]]]; - - if (!r_count || !b_count) - return HIDP_STATUS_USAGE_NOT_FOUND; + return HIDP_STATUS_SUCCESS; +}
- if (report->reportID && report->reportID != Report[0]) - return HIDP_STATUS_REPORT_DOES_NOT_EXIST; +NTSTATUS WINAPI HidP_GetUsages( HIDP_REPORT_TYPE report_type, USAGE usage_page, USHORT collection, USAGE *usages, + ULONG *usages_len, PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) +{ + WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct get_usage_params params = {.usages = usages, .usages_end = usages + *usages_len, .report_buf = report_buf}; + struct caps_filter filter = {.buttons = TRUE, .usage_page = usage_page, .collection = collection}; + NTSTATUS status; + USHORT limit = -1;
- uCount = 0; - for (i = 0; i < report->elementCount && uCount < *UsageLength; i++) - { - if (elems[report->elementIdx + i].caps.BitSize == 1 && - elems[report->elementIdx + i].caps.UsagePage == UsagePage) - { - int k; - WINE_HID_ELEMENT *element = &elems[report->elementIdx + i]; - 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; - found = TRUE; - if (v) - { - if (uCount == *UsageLength) - return HIDP_STATUS_BUFFER_TOO_SMALL; - UsageList[uCount] = element->caps.Range.UsageMin + k; - uCount++; - } - } - } - } + TRACE( "report_type %d, collection %d, usages %p, usages_len %p, preparsed_data %p, report_buf %p, report_len %u.\n", + report_type, collection, usages, usages_len, preparsed_data, report_buf, report_len );
- *UsageLength = uCount; + if (!report_len) return HIDP_STATUS_INVALID_REPORT_LENGTH;
- if (!found) - return HIDP_STATUS_USAGE_NOT_FOUND; + filter.report_id = report_buf[0]; + status = enum_value_caps( preparsed, report_type, report_len, &filter, get_usage, ¶ms, &limit ); + *usages_len = params.usages - usages; + if (status != HIDP_STATUS_SUCCESS) return status;
- return HIDP_STATUS_SUCCESS; + if (*usages_len == 0) return HIDP_STATUS_USAGE_NOT_FOUND; + if (params.usages > params.usages_end) return HIDP_STATUS_BUFFER_TOO_SMALL; + return status; }
NTSTATUS WINAPI HidP_GetValueCaps( HIDP_REPORT_TYPE report_type, HIDP_VALUE_CAPS *caps, USHORT *caps_count, diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 8777880fd9d..b455fe650f1 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -2190,7 +2190,6 @@ static void test_hidp(HANDLE file, int report_id) status = HidP_GetUsages(HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, preparsed_data, report, caps.InputReportByteLength); ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetUsages returned %#x\n", status); - todo_wine ok(value == 2, "got usage count %d, expected %d\n", value, 2); value = ARRAY_SIZE(usages); memset(usages, 0xcd, sizeof(usages)); @@ -2207,9 +2206,7 @@ static void test_hidp(HANDLE file, int report_id) report, caps.InputReportByteLength); ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsages returned %#x\n", status); ok(value == 2, "got usage count %d, expected %d\n", value, 2); - todo_wine ok(usages[0] == 6, "got usages[0] %x, expected %x\n", usages[0], 6); - todo_wine ok(usages[1] == 4, "got usages[1] %x, expected %x\n", usages[1], 4);
value = ARRAY_SIZE(usage_and_pages);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 101 +++++++++++------------------ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 2 - 2 files changed, 37 insertions(+), 66 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 4889a1e4014..8d893f6327d 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -716,81 +716,54 @@ NTSTATUS WINAPI HidP_GetSpecificValueCaps( HIDP_REPORT_TYPE report_type, USAGE u return enum_value_caps( preparsed, report_type, 0, &filter, get_value_caps, &caps, caps_count ); }
-NTSTATUS WINAPI HidP_GetUsagesEx(HIDP_REPORT_TYPE ReportType, USHORT LinkCollection, USAGE_AND_PAGE *ButtonList, - ULONG *UsageLength, PHIDP_PREPARSED_DATA PreparsedData, CHAR *Report, ULONG ReportLength) +struct get_usage_and_page_params { - 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,uCount = 0; - NTSTATUS rc; - - TRACE("(%i, %i, %p, %p(%i), %p, %p, %i)\n", ReportType, LinkCollection, ButtonList, - UsageLength, *UsageLength, PreparsedData, Report, ReportLength); - - if (data->magic != HID_MAGIC) - return HIDP_STATUS_INVALID_PREPARSED_DATA; - - switch(ReportType) - { - case HidP_Input: - b_count = data->caps.NumberInputButtonCaps; - break; - case HidP_Output: - b_count = data->caps.NumberOutputButtonCaps; - break; - case HidP_Feature: - b_count = data->caps.NumberFeatureButtonCaps; - break; - default: - return HIDP_STATUS_INVALID_REPORT_TYPE; - } - r_count = data->reportCount[ReportType]; - report = &data->reports[data->reportIdx[ReportType][(BYTE)Report[0]]]; - - if (!r_count || !b_count) - return HIDP_STATUS_USAGE_NOT_FOUND; + USAGE_AND_PAGE *usages; + USAGE_AND_PAGE *usages_end; + char *report_buf; +};
- if (report->reportID && report->reportID != Report[0]) - return HIDP_STATUS_REPORT_DOES_NOT_EXIST; +static NTSTATUS get_usage_and_page( const struct hid_value_caps *caps, void *user ) +{ + struct get_usage_and_page_params *params = user; + ULONG bit, last;
- for (i = 0; i < report->elementCount; i++) + for (bit = caps->start_bit, last = bit + caps->usage_max - caps->usage_min; bit <= last; bit++) { - if (elems[report->elementIdx + i].caps.BitSize == 1) + if (!(params->report_buf[bit / 8] & (1 << (bit % 8)))) continue; + if (params->usages < params->usages_end) { - int k; - WINE_HID_ELEMENT *element = &elems[report->elementIdx + i]; - 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 < *UsageLength) - { - ButtonList[uCount].Usage = element->caps.Range.UsageMin + k; - ButtonList[uCount].UsagePage = element->caps.UsagePage; - } - uCount++; - } - } + params->usages->UsagePage = caps->usage_page; + params->usages->Usage = caps->usage_min + bit - caps->start_bit; } + params->usages++; }
- TRACE("Returning %i usages\n", uCount); + return HIDP_STATUS_SUCCESS; +}
- if (*UsageLength < uCount) - rc = HIDP_STATUS_BUFFER_TOO_SMALL; - else - rc = HIDP_STATUS_SUCCESS; +NTSTATUS WINAPI HidP_GetUsagesEx( HIDP_REPORT_TYPE report_type, USHORT collection, USAGE_AND_PAGE *usages, + ULONG *usages_len, PHIDP_PREPARSED_DATA preparsed_data, char *report_buf, ULONG report_len ) +{ + struct get_usage_and_page_params params = {.usages = usages, .usages_end = usages + *usages_len, .report_buf = report_buf}; + WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct caps_filter filter = {.buttons = TRUE, .collection = collection}; + NTSTATUS status; + USHORT limit = -1;
- *UsageLength = uCount; + TRACE( "report_type %d, collection %d, usages %p, usages_len %p, preparsed_data %p, report_buf %p, report_len %u.\n", + report_type, collection, usages, usages_len, preparsed_data, report_buf, report_len );
- return rc; + if (!report_len) return HIDP_STATUS_INVALID_REPORT_LENGTH; + + filter.report_id = report_buf[0]; + status = enum_value_caps( preparsed, report_type, report_len, &filter, get_usage_and_page, ¶ms, &limit ); + *usages_len = params.usages - usages; + if (status != HIDP_STATUS_SUCCESS) return status; + + if (*usages_len == 0) return HIDP_STATUS_USAGE_NOT_FOUND; + if (params.usages > params.usages_end) return HIDP_STATUS_BUFFER_TOO_SMALL; + return status; }
ULONG WINAPI HidP_MaxDataListLength(HIDP_REPORT_TYPE ReportType, PHIDP_PREPARSED_DATA PreparsedData) diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index b455fe650f1..ca030599299 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -2227,10 +2227,8 @@ static void test_hidp(HANDLE file, int report_id) usage_and_pages[0].Usage, 4); ok(usage_and_pages[1].Usage == 6, "got usage_and_pages[1] Usage %x, expected %x\n", usage_and_pages[1].Usage, 6); - todo_wine ok(usage_and_pages[2].Usage == 6, "got usage_and_pages[2] Usage %x, expected %x\n", usage_and_pages[2].Usage, 6); - todo_wine ok(usage_and_pages[3].Usage == 4, "got usage_and_pages[3] Usage %x, expected %x\n", usage_and_pages[3].Usage, 4);
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=93035
Your paranoid android.
=== debiant2 (32 bit Japanese:Japan report) ===
ntoskrnl.exe: ntoskrnl: Timeout