From: "Rémi Bernon" Subject: [PATCH 1/5] hidparse.sys: Split struct hid_value_caps start_bit into start_byte / start_bit. Message-Id: <20210917071858.3316554-1-rbernon@codeweavers.com> Date: Fri, 17 Sep 2021 09:18:54 +0200 Signed-off-by: Rémi Bernon --- This is the first part of a series to make Wine internal HID structures compatible (enough) with native. dlls/hid/hidp.c | 63 +++++++++++++++++++++++++++++----------- dlls/hidparse.sys/main.c | 16 +++++----- include/wine/hid.h | 3 +- 3 files changed, 57 insertions(+), 25 deletions(-) diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index cd9de2148c2..a94e7b637ae 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -192,10 +192,13 @@ static NTSTATUS get_scaled_usage_value( const struct hid_value_caps *caps, void struct usage_value_params *params = user; ULONG unsigned_value = 0, bit_count = caps->bit_size * caps->report_count; LONG signed_value, *value = params->value_buf; + unsigned char *report_buf; if ((bit_count + 7) / 8 > sizeof(unsigned_value)) return HIDP_STATUS_BUFFER_TOO_SMALL; if (sizeof(LONG) > params->value_len) return HIDP_STATUS_BUFFER_TOO_SMALL; - copy_bits( (unsigned char *)&unsigned_value, params->report_buf, bit_count, -caps->start_bit ); + + report_buf = (unsigned char *)params->report_buf + caps->start_byte; + copy_bits( (unsigned char *)&unsigned_value, report_buf, bit_count, -caps->start_bit ); signed_value = sign_extend( unsigned_value, caps ); if (caps->logical_min > caps->logical_max || caps->physical_min > caps->physical_max) @@ -232,9 +235,14 @@ static NTSTATUS get_usage_value( const struct hid_value_caps *caps, void *user ) { struct usage_value_params *params = user; ULONG bit_count = caps->bit_size * caps->report_count; + unsigned char *report_buf; + if ((bit_count + 7) / 8 > params->value_len) return HIDP_STATUS_BUFFER_TOO_SMALL; memset( params->value_buf, 0, params->value_len ); - copy_bits( params->value_buf, params->report_buf, bit_count, -caps->start_bit ); + + report_buf = (unsigned char *)params->report_buf + caps->start_byte; + copy_bits( params->value_buf, report_buf, bit_count, -caps->start_bit ); + return HIDP_STATUS_NULL; } @@ -285,14 +293,17 @@ struct get_usage_params static NTSTATUS get_usage( const struct hid_value_caps *caps, void *user ) { struct get_usage_params *params = user; + unsigned char *report_buf; ULONG bit, last; BYTE index; + report_buf = (unsigned char *)params->report_buf + caps->start_byte; + 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 (!(index = report_buf[bit / 8])) continue; if (params->usages < params->usages_end) *params->usages = caps->usage_min + index - caps->start_index; params->usages++; } @@ -301,7 +312,7 @@ static NTSTATUS get_usage( const struct hid_value_caps *caps, void *user ) for (bit = caps->start_bit, last = bit + caps->usage_max - caps->usage_min; bit <= last; ++bit) { - if (!(params->report_buf[bit / 8] & (1 << (bit % 8)))) continue; + if (!(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++; } @@ -384,6 +395,7 @@ static NTSTATUS set_scaled_usage_value( const struct hid_value_caps *caps, void { ULONG bit_count = caps->bit_size * caps->report_count; struct usage_value_params *params = user; + unsigned char *report_buf; LONG value, log_range, phy_range; if (caps->logical_min > caps->logical_max) return HIDP_STATUS_BAD_LOG_PHY_VALUES; @@ -404,7 +416,8 @@ static NTSTATUS set_scaled_usage_value( const struct hid_value_caps *caps, void value = caps->logical_min + value; } - copy_bits( params->report_buf, (unsigned char *)&value, bit_count, caps->start_bit ); + report_buf = (unsigned char *)params->report_buf + caps->start_byte; + copy_bits( report_buf, (unsigned char *)&value, bit_count, caps->start_bit ); return HIDP_STATUS_NULL; } @@ -431,8 +444,13 @@ static NTSTATUS set_usage_value( const struct hid_value_caps *caps, void *user ) { struct usage_value_params *params = user; ULONG bit_count = caps->bit_size * caps->report_count; + unsigned char *report_buf; + if ((bit_count + 7) / 8 > params->value_len) return HIDP_STATUS_BUFFER_TOO_SMALL; - copy_bits( params->report_buf, params->value_buf, bit_count, caps->start_bit ); + + report_buf = (unsigned char *)params->report_buf + caps->start_byte; + copy_bits( report_buf, params->value_buf, bit_count, caps->start_bit ); + return HIDP_STATUS_NULL; } @@ -481,14 +499,17 @@ struct set_usage_params static NTSTATUS set_usage( const struct hid_value_caps *caps, void *user ) { struct set_usage_params *params = user; + unsigned char *report_buf; ULONG bit, last; + report_buf = (unsigned char *)params->report_buf + caps->start_byte; + 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; + if (report_buf[bit / 8]) continue; + report_buf[bit / 8] = caps->start_index + params->usage - caps->usage_min; break; } @@ -497,7 +518,7 @@ static NTSTATUS set_usage( const struct hid_value_caps *caps, void *user ) } bit = caps->start_bit + params->usage - caps->usage_min; - params->report_buf[bit / 8] |= (1 << (bit % 8)); + report_buf[bit / 8] |= (1 << (bit % 8)); return HIDP_STATUS_NULL; } @@ -538,15 +559,18 @@ struct unset_usage_params static NTSTATUS unset_usage( const struct hid_value_caps *caps, void *user ) { struct unset_usage_params *params = user; + unsigned char *report_buf; ULONG bit, index, last; + report_buf = (unsigned char *)params->report_buf + caps->start_byte; + 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; + if (report_buf[bit / 8] != index) continue; + report_buf[bit / 8] = 0; params->found = TRUE; break; } @@ -555,8 +579,8 @@ static NTSTATUS unset_usage( const struct hid_value_caps *caps, void *user ) } 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)); + if (report_buf[bit / 8] & (1 << (bit % 8))) params->found = TRUE; + report_buf[bit / 8] &= ~(1 << (bit % 8)); return HIDP_STATUS_NULL; } @@ -726,14 +750,17 @@ struct get_usage_and_page_params static NTSTATUS get_usage_and_page( const struct hid_value_caps *caps, void *user ) { struct get_usage_and_page_params *params = user; + unsigned char *report_buf; ULONG bit, last; BYTE index; + report_buf = (unsigned char *)params->report_buf + caps->start_byte; + 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 (!(index = report_buf[bit / 8])) continue; if (params->usages < params->usages_end) { params->usages->UsagePage = caps->usage_page; @@ -746,7 +773,7 @@ static NTSTATUS get_usage_and_page( const struct hid_value_caps *caps, void *use for (bit = caps->start_bit, last = bit + caps->usage_max - caps->usage_min; bit <= last; bit++) { - if (!(params->report_buf[bit / 8] & (1 << (bit % 8)))) continue; + if (!(report_buf[bit / 8] & (1 << (bit % 8)))) continue; if (params->usages < params->usages_end) { params->usages->UsagePage = caps->usage_page; @@ -813,11 +840,13 @@ static NTSTATUS find_all_data( const struct hid_value_caps *caps, void *user ) struct find_all_data_params *params = 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; + unsigned char *report_buf; BYTE index; if (!caps->bit_size) return HIDP_STATUS_SUCCESS; + report_buf = (unsigned char *)params->report_buf + caps->start_byte; + 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) @@ -851,7 +880,7 @@ static NTSTATUS find_all_data( const struct hid_value_caps *caps, void *user ) data->DataIndex = caps->data_index_min; data->RawValue = 0; if ((bit_count + 7) / 8 > sizeof(data->RawValue)) return HIDP_STATUS_BUFFER_TOO_SMALL; - copy_bits( (void *)&data->RawValue, (void *)report_buf, bit_count, -caps->start_bit ); + copy_bits( (void *)&data->RawValue, report_buf, bit_count, -caps->start_bit ); } data++; } diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index 3a57c338165..b7326f9fe4a 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -333,13 +333,13 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY USHORT *byte_size = state->byte_size[type]; USHORT *value_idx = state->value_idx[type]; USHORT *data_idx = state->data_idx[type]; - ULONG *bit_size = &state->bit_size[type][state->items.report_id]; + ULONG start_bit, *bit_size = &state->bit_size[type][state->items.report_id]; BOOL is_array; 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; + start_bit = *bit_size; if (!state->items.report_count) { @@ -356,11 +356,13 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY state->items.start_index = usages_size; 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; + else start_bit -= state->items.report_count * state->items.bit_size; while (usages_size--) { - if (!is_array) state->items.start_bit -= state->items.report_count * state->items.bit_size; + if (!is_array) start_bit -= state->items.report_count * state->items.bit_size; + state->items.start_byte = start_bit / 8; + state->items.start_bit = start_bit % 8; 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]; @@ -652,7 +654,7 @@ NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_de caps_end = caps + preparsed->value_caps_count[HidP_Input]; for (; caps != caps_end; ++caps) { - len = caps->start_bit + caps->bit_size * caps->report_count; + len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count; if (!input_len[caps->report_id]) report_count++; input_len[caps->report_id] = max(input_len[caps->report_id], len); } @@ -661,7 +663,7 @@ NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_de caps_end = caps + preparsed->value_caps_count[HidP_Output]; for (; caps != caps_end; ++caps) { - len = caps->start_bit + caps->bit_size * caps->report_count; + len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count; if (!input_len[caps->report_id] && !output_len[caps->report_id]) report_count++; output_len[caps->report_id] = max(output_len[caps->report_id], len); } @@ -670,7 +672,7 @@ NTSTATUS WINAPI HidP_GetCollectionDescription( PHIDP_REPORT_DESCRIPTOR report_de caps_end = caps + preparsed->value_caps_count[HidP_Feature]; for (; caps != caps_end; ++caps) { - len = caps->start_bit + caps->bit_size * caps->report_count; + len = caps->start_byte * 8 + caps->start_bit + caps->bit_size * caps->report_count; if (!input_len[caps->report_id] && !output_len[caps->report_id] && !feature_len[caps->report_id]) report_count++; feature_len[caps->report_id] = max(feature_len[caps->report_id], len); } diff --git a/include/wine/hid.h b/include/wine/hid.h index e76676ac8c2..8e33745ddc4 100644 --- a/include/wine/hid.h +++ b/include/wine/hid.h @@ -52,7 +52,8 @@ struct hid_value_caps USHORT bit_field; USHORT bit_size; USHORT report_count; - ULONG start_bit; + UCHAR start_bit; + USHORT start_byte; ULONG start_index; LONG logical_min; LONG logical_max; -- 2.33.0