hidclass.sys: Implement button array value caps.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2021-08-03 18:55:17 +02:00 committed by Alexandre Julliard
parent 26724c3ef4
commit 7096c26a2e
4 changed files with 75 additions and 15 deletions

View file

@ -286,6 +286,18 @@ static NTSTATUS get_usage( const struct hid_value_caps *caps, void *user )
{
struct get_usage_params *params = user;
ULONG bit, last;
BYTE index;
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)
{
if (!(index = params->report_buf[bit / 8])) continue;
if (params->usages < params->usages_end) *params->usages = caps->usage_min + index - caps->start_index;
params->usages++;
}
return HIDP_STATUS_SUCCESS;
}
for (bit = caps->start_bit, last = bit + caps->usage_max - caps->usage_min; bit <= last; ++bit)
{
@ -423,7 +435,22 @@ struct set_usage_params
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;
ULONG bit, 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)
{
if (params->report_buf[bit / 8]) continue;
params->report_buf[bit / 8] = caps->start_index + params->usage - caps->usage_min;
break;
}
if (bit > last) return HIDP_STATUS_BUFFER_TOO_SMALL;
return HIDP_STATUS_NULL;
}
bit = caps->start_bit + params->usage - caps->usage_min;
params->report_buf[bit / 8] |= (1 << (bit % 8));
return HIDP_STATUS_NULL;
}
@ -595,6 +622,22 @@ static NTSTATUS get_usage_and_page( const struct hid_value_caps *caps, void *use
{
struct get_usage_and_page_params *params = user;
ULONG bit, last;
BYTE index;
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)
{
if (!(index = params->report_buf[bit / 8])) continue;
if (params->usages < params->usages_end)
{
params->usages->UsagePage = caps->usage_page;
params->usages->Usage = caps->usage_min + index - caps->start_index;
}
params->usages++;
}
return HIDP_STATUS_SUCCESS;
}
for (bit = caps->start_bit, last = bit + caps->usage_max - caps->usage_min; bit <= last; bit++)
{
@ -667,9 +710,24 @@ static NTSTATUS find_all_data( const struct hid_value_caps *caps, void *user )
HIDP_DATA *data = params->data, *data_end = params->data_end;
ULONG bit, last, bit_count = caps->bit_size * caps->report_count;
char *report_buf = params->report_buf;
BYTE index;
if (!caps->bit_size) return HIDP_STATUS_SUCCESS;
if (caps->bit_size == 1)
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)
{
if (!(index = report_buf[bit / 8])) continue;
if (data < data_end)
{
data->DataIndex = caps->data_index_min + index - caps->start_index;
data->On = 1;
}
data++;
}
}
else if (HID_VALUE_CAPS_IS_BUTTON( caps ))
{
for (bit = caps->start_bit, last = bit + caps->usage_max - caps->usage_min; bit <= last; bit++)
{

View file

@ -460,6 +460,7 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY
USHORT *data_idx = state->data_idx[type];
ULONG *bit_size = &state->bit_size[type][state->items.report_id];
struct feature *feature;
BOOL is_array;
int j;
for (j = 0; j < state->items.report_count; j++)
@ -496,10 +497,14 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY
}
value = state->values[type] + *value_idx;
state->items.report_count -= usages_size - 1;
state->items.start_index = 0;
if (!(is_array = HID_VALUE_CAPS_IS_ARRAY( &state->items ))) state->items.report_count -= usages_size - 1;
else state->items.start_bit -= state->items.report_count * state->items.bit_size;
while (usages_size--)
{
state->items.start_bit -= state->items.report_count * state->items.bit_size;
if (!is_array) state->items.start_bit -= state->items.report_count * state->items.bit_size;
else state->items.start_index += 1;
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];
@ -508,7 +513,7 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY
if (state->items.usage_max || state->items.usage_min) *data_idx = state->items.data_index_max + 1;
*value++ = state->items;
*value_idx += 1;
state->items.report_count = 1;
if (!is_array) state->items.report_count = 1;
}
state->items.usage_page = usage_page;

View file

@ -2229,10 +2229,10 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
memcpy(buffer, report, caps.InputReportByteLength);
status = HidP_SetUsages(HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data,
report, caps.InputReportByteLength);
todo_wine ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_SetUsages returned %#x\n", status);
ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_SetUsages returned %#x\n", status);
buffer[6] = 2;
buffer[7] = 4;
todo_wine ok(!memcmp(buffer, report, caps.InputReportByteLength), "unexpected report data\n");
ok(!memcmp(buffer, report, caps.InputReportByteLength), "unexpected report data\n");
status = HidP_SetUsageValue(HidP_Input, HID_USAGE_PAGE_LED, 0, 6, 1,
preparsed_data, report, caps.InputReportByteLength);
@ -2272,7 +2272,7 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
status = HidP_GetUsagesEx(HidP_Input, 0, usage_and_pages, &value, preparsed_data, report,
caps.InputReportByteLength);
ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsagesEx returned %#x\n", status);
todo_wine ok(value == 6, "got usage count %d, expected %d\n", value, 4);
ok(value == 6, "got usage count %d, expected %d\n", value, 4);
ok(usage_and_pages[0].UsagePage == HID_USAGE_PAGE_BUTTON, "got usage_and_pages[0] UsagePage %x, expected %x\n",
usage_and_pages[0].UsagePage, HID_USAGE_PAGE_BUTTON);
ok(usage_and_pages[1].UsagePage == HID_USAGE_PAGE_BUTTON, "got usage_and_pages[1] UsagePage %x, expected %x\n",
@ -2281,7 +2281,6 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
usage_and_pages[2].UsagePage, HID_USAGE_PAGE_KEYBOARD);
ok(usage_and_pages[3].UsagePage == HID_USAGE_PAGE_KEYBOARD, "got usage_and_pages[3] UsagePage %x, expected %x\n",
usage_and_pages[3].UsagePage, HID_USAGE_PAGE_KEYBOARD);
todo_wine
ok(usage_and_pages[4].UsagePage == HID_USAGE_PAGE_LED, "got usage_and_pages[4] UsagePage %x, expected %x\n",
usage_and_pages[4].UsagePage, HID_USAGE_PAGE_LED);
ok(usage_and_pages[5].UsagePage == HID_USAGE_PAGE_LED, "got usage_and_pages[5] UsagePage %x, expected %x\n",
@ -2292,13 +2291,10 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
usage_and_pages[1].Usage, 6);
ok(usage_and_pages[2].Usage == 9, "got usage_and_pages[2] Usage %x, expected %x\n",
usage_and_pages[2].Usage, 9);
todo_wine
ok(usage_and_pages[3].Usage == 11, "got usage_and_pages[3] Usage %x, expected %x\n",
usage_and_pages[3].Usage, 11);
todo_wine
ok(usage_and_pages[4].Usage == 6, "got usage_and_pages[4] Usage %x, expected %x\n",
usage_and_pages[4].Usage, 6);
todo_wine
ok(usage_and_pages[5].Usage == 4, "got usage_and_pages[5] Usage %x, expected %x\n",
usage_and_pages[5].Usage, 4);
@ -2314,15 +2310,15 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
value = 1;
status = HidP_GetData(HidP_Input, data, &value, preparsed_data, report, caps.InputReportByteLength);
ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetData returned %#x\n", status);
todo_wine ok(value == 11, "got data count %d, expected %d\n", value, 11);
ok(value == 11, "got data count %d, expected %d\n", value, 11);
memset(data, 0, sizeof(data));
status = HidP_GetData(HidP_Input, data, &value, preparsed_data, report, caps.InputReportByteLength);
ok(status == HIDP_STATUS_SUCCESS, "HidP_GetData returned %#x\n", status);
for (i = 0; i < ARRAY_SIZE(expect_data); ++i)
{
winetest_push_context("data[%d]", i);
todo_wine_if(i >= 4) check_member(data[i], expect_data[i], "%d", DataIndex);
todo_wine_if(i >= 4) check_member(data[i], expect_data[i], "%d", RawValue);
check_member(data[i], expect_data[i], "%d", DataIndex);
check_member(data[i], expect_data[i], "%d", RawValue);
winetest_pop_context();
}

View file

@ -60,6 +60,7 @@ struct hid_value_caps
USHORT bit_size;
USHORT report_count;
ULONG start_bit;
ULONG start_index;
LONG logical_min;
LONG logical_max;
LONG physical_min;