[PATCH 3/5] hid: Rewrite HidP_SetUsages using enum_value_caps.
Rémi Bernon
rbernon at codeweavers.com
Thu Jun 24 03:05:57 CDT 2021
Signed-off-by: Rémi Bernon <rbernon at 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;
--
2.32.0
More information about the wine-devel
mailing list