Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
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;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 31 ++++++++++++++++++++----------- dlls/hidparse.sys/main.c | 34 +++++++++++++++++----------------- include/wine/hid.h | 8 +++++--- 3 files changed, 42 insertions(+), 31 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index a94e7b637ae..547f935f850 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -95,16 +95,17 @@ static NTSTATUS enum_value_caps( struct hid_preparsed_data *preparsed, HIDP_REPO enum_value_caps_callback callback, void *user, USHORT *count ) { const struct hid_value_caps *caps, *caps_end; - NTSTATUS status; - BOOL incompatible = FALSE; + BOOL is_range, incompatible = FALSE; LONG remaining = *count; + NTSTATUS status;
for (status = get_value_caps_range( preparsed, report_type, report_len, &caps, &caps_end ); status == HIDP_STATUS_SUCCESS && caps != caps_end; caps++) { + is_range = caps->flags & HID_VALUE_CAPS_IS_RANGE; if (!match_value_caps( caps, filter )) continue; if (filter->report_id && caps->report_id != filter->report_id) incompatible = TRUE; - else if (filter->array && (caps->is_range || caps->report_count <= 1)) return HIDP_STATUS_NOT_VALUE_ARRAY; + else if (filter->array && (is_range || caps->report_count <= 1)) return HIDP_STATUS_NOT_VALUE_ARRAY; else if (remaining-- > 0) status = callback( caps, user ); }
@@ -634,7 +635,8 @@ static NTSTATUS get_button_caps( const struct hid_value_caps *caps, void *user ) dst->BitField = caps->bit_field; dst->IsAlias = FALSE; dst->IsAbsolute = HID_VALUE_CAPS_IS_ABSOLUTE( caps ); - if (!(dst->IsRange = caps->is_range)) + dst->IsRange = (caps->flags & HID_VALUE_CAPS_IS_RANGE) ? 1 : 0; + if (!dst->IsRange) { dst->NotRange.Usage = caps->usage_min; dst->NotRange.DataIndex = caps->data_index_min; @@ -646,14 +648,16 @@ static NTSTATUS get_button_caps( const struct hid_value_caps *caps, void *user ) dst->Range.DataIndexMin = caps->data_index_min; dst->Range.DataIndexMax = caps->data_index_max; } - if (!(dst->IsStringRange = caps->is_string_range)) + dst->IsStringRange = (caps->flags & HID_VALUE_CAPS_IS_STRING_RANGE) ? 1 : 0; + if (!dst->IsStringRange) dst->NotRange.StringIndex = caps->string_min; else { dst->Range.StringMin = caps->string_min; dst->Range.StringMax = caps->string_max; } - if ((dst->IsDesignatorRange = caps->is_designator_range)) + dst->IsDesignatorRange = (caps->flags & HID_VALUE_CAPS_IS_DESIGNATOR_RANGE) ? 1 : 0; + if (!dst->IsDesignatorRange) dst->NotRange.DesignatorIndex = caps->designator_min; else { @@ -690,33 +694,37 @@ static NTSTATUS get_value_caps( const struct hid_value_caps *caps, void *user ) 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)) + dst->IsRange = (caps->flags & HID_VALUE_CAPS_IS_RANGE) ? 1 : 0; + if (!dst->IsRange) { + dst->ReportCount = caps->report_count; dst->NotRange.Usage = caps->usage_min; dst->NotRange.DataIndex = caps->data_index_min; } else { + dst->ReportCount = 1; 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; } - if (!(dst->IsStringRange = caps->is_string_range)) + dst->IsStringRange = (caps->flags & HID_VALUE_CAPS_IS_STRING_RANGE) ? 1 : 0; + if (!dst->IsStringRange) dst->NotRange.StringIndex = caps->string_min; else { dst->Range.StringMin = caps->string_min; dst->Range.StringMax = caps->string_max; } - if ((dst->IsDesignatorRange = caps->is_designator_range)) + dst->IsDesignatorRange = (caps->flags & HID_VALUE_CAPS_IS_DESIGNATOR_RANGE) ? 1 : 0; + if (!dst->IsDesignatorRange) dst->NotRange.DesignatorIndex = caps->designator_min; else { @@ -810,7 +818,8 @@ NTSTATUS WINAPI HidP_GetUsagesEx( HIDP_REPORT_TYPE report_type, USHORT collectio
static NTSTATUS count_data( const struct hid_value_caps *caps, void *user ) { - if (caps->is_range || HID_VALUE_CAPS_IS_BUTTON( caps )) *(ULONG *)user += caps->report_count; + BOOL is_range = caps->flags & HID_VALUE_CAPS_IS_RANGE; + if (is_range || HID_VALUE_CAPS_IS_BUTTON( caps )) *(ULONG *)user += caps->report_count; else *(ULONG *)user += 1; return HIDP_STATUS_SUCCESS; } diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index b7326f9fe4a..73b9858f741 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -102,11 +102,11 @@ enum static inline const char *debugstr_hid_value_caps( struct hid_value_caps *caps ) { if (!caps) return "(null)"; - return wine_dbg_sprintf( "RId %d, Usg %02x:%02x-%02x Dat %02x-%02x (%d), Str %d-%d (%d), Des %d-%d (%d), " - "Bits %02x, LCol %d LUsg %02x:%02x, BitSz %d, RCnt %d, Unit %x E%+d, Log %+d-%+d, Phy %+d-%+d", - caps->report_id, caps->usage_page, caps->usage_min, caps->usage_max, caps->data_index_min, caps->data_index_max, caps->is_range, - caps->string_min, caps->string_max, caps->is_string_range, caps->designator_min, caps->designator_max, caps->is_designator_range, - caps->bit_field, caps->link_collection, caps->link_usage_page, caps->link_usage, caps->bit_size, caps->report_count, + return wine_dbg_sprintf( "RId %d, Usg %02x:%02x-%02x Dat %02x-%02x, Str %d-%d, Des %d-%d, " + "Bits %02x Flags %#x, LCol %d LUsg %02x:%02x, BitSz %d, RCnt %d, Unit %x E%+d, Log %+d-%+d, Phy %+d-%+d", + caps->report_id, caps->usage_page, caps->usage_min, caps->usage_max, caps->data_index_min, caps->data_index_max, + caps->string_min, caps->string_max, caps->designator_min, caps->designator_max, caps->bit_field, caps->flags, + caps->link_collection, caps->link_usage_page, caps->link_usage, caps->bit_size, caps->report_count, caps->units, caps->units_exp, caps->logical_min, caps->logical_max, caps->physical_min, caps->physical_max ); }
@@ -243,13 +243,13 @@ static BOOL parse_global_pop( struct hid_parser_state *state ) static BOOL parse_local_usage( struct hid_parser_state *state, USAGE usage_page, USAGE usage ) { if (!usage_page) usage_page = state->items.usage_page; - if (state->items.is_range) state->usages_size = 0; + if (state->items.flags & HID_VALUE_CAPS_IS_RANGE) state->usages_size = 0; state->usages_page[state->usages_size] = usage_page; state->usages_min[state->usages_size] = usage; state->usages_max[state->usages_size] = usage; state->items.usage_min = usage; state->items.usage_max = usage; - state->items.is_range = FALSE; + state->items.flags &= ~HID_VALUE_CAPS_IS_RANGE; if (state->usages_size++ == 255) ERR( "HID parser usages stack overflow!\n" ); return state->usages_size <= 255; } @@ -257,22 +257,22 @@ static BOOL parse_local_usage( struct hid_parser_state *state, USAGE usage_page, static void parse_local_usage_min( struct hid_parser_state *state, USAGE usage_page, USAGE usage ) { if (!usage_page) usage_page = state->items.usage_page; - if (!state->items.is_range) state->usages_max[0] = 0; + if (!(state->items.flags & HID_VALUE_CAPS_IS_RANGE)) state->usages_max[0] = 0; state->usages_page[0] = usage_page; state->usages_min[0] = usage; state->items.usage_min = usage; - state->items.is_range = TRUE; + state->items.flags |= HID_VALUE_CAPS_IS_RANGE; state->usages_size = 1; }
static void parse_local_usage_max( struct hid_parser_state *state, USAGE usage_page, USAGE usage ) { if (!usage_page) usage_page = state->items.usage_page; - if (!state->items.is_range) state->usages_min[0] = 0; + if (!(state->items.flags & HID_VALUE_CAPS_IS_RANGE)) state->usages_min[0] = 0; state->usages_page[0] = usage_page; state->usages_max[0] = usage; state->items.usage_max = usage; - state->items.is_range = TRUE; + state->items.flags |= HID_VALUE_CAPS_IS_RANGE; state->usages_size = 1; }
@@ -579,27 +579,27 @@ struct hid_preparsed_data *parse_descriptor( BYTE *descriptor, unsigned int leng break; case SHORT_ITEM( TAG_LOCAL_DESIGNATOR_INDEX, TAG_TYPE_LOCAL ): state->items.designator_min = state->items.designator_max = value; - state->items.is_designator_range = FALSE; + state->items.flags &= ~HID_VALUE_CAPS_IS_DESIGNATOR_RANGE; break; case SHORT_ITEM( TAG_LOCAL_DESIGNATOR_MINIMUM, TAG_TYPE_LOCAL ): state->items.designator_min = value; - state->items.is_designator_range = TRUE; + state->items.flags |= HID_VALUE_CAPS_IS_DESIGNATOR_RANGE; break; case SHORT_ITEM( TAG_LOCAL_DESIGNATOR_MAXIMUM, TAG_TYPE_LOCAL ): state->items.designator_max = value; - state->items.is_designator_range = TRUE; + state->items.flags |= HID_VALUE_CAPS_IS_DESIGNATOR_RANGE; break; case SHORT_ITEM( TAG_LOCAL_STRING_INDEX, TAG_TYPE_LOCAL ): state->items.string_min = state->items.string_max = value; - state->items.is_string_range = FALSE; + state->items.flags &= ~HID_VALUE_CAPS_IS_STRING_RANGE; break; case SHORT_ITEM( TAG_LOCAL_STRING_MINIMUM, TAG_TYPE_LOCAL ): state->items.string_min = value; - state->items.is_string_range = TRUE; + state->items.flags |= HID_VALUE_CAPS_IS_STRING_RANGE; break; case SHORT_ITEM( TAG_LOCAL_STRING_MAXIMUM, TAG_TYPE_LOCAL ): state->items.string_max = value; - state->items.is_string_range = TRUE; + state->items.flags |= HID_VALUE_CAPS_IS_STRING_RANGE; break; case SHORT_ITEM( TAG_LOCAL_DELIMITER, TAG_TYPE_LOCAL ): FIXME( "delimiter %d not implemented!\n", value ); diff --git a/include/wine/hid.h b/include/wine/hid.h index 8e33745ddc4..4f388404885 100644 --- a/include/wine/hid.h +++ b/include/wine/hid.h @@ -42,9 +42,7 @@ struct hid_value_caps USHORT string_max; USHORT designator_min; USHORT designator_max; - BOOLEAN is_range; - BOOLEAN is_string_range; - BOOLEAN is_designator_range; + ULONG flags; UCHAR report_id; USHORT link_collection; USAGE link_usage_page; @@ -63,6 +61,10 @@ struct hid_value_caps ULONG units_exp; };
+#define HID_VALUE_CAPS_IS_RANGE 0x10 +#define HID_VALUE_CAPS_IS_STRING_RANGE 0x40 +#define HID_VALUE_CAPS_IS_DESIGNATOR_RANGE 0x80 + #define HID_VALUE_CAPS_IS_ABSOLUTE(x) (((x)->bit_field & 0x04) == 0) #define HID_VALUE_CAPS_HAS_NULL(x) (((x)->bit_field & 0x40) != 0) #define HID_VALUE_CAPS_IS_ARRAY(c) (((c)->bit_field & 2) == 0)
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 52 +++++++++++++++++++++++++++++----------- dlls/hidparse.sys/main.c | 4 ++-- include/wine/hid.h | 3 ++- 3 files changed, 42 insertions(+), 17 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 547f935f850..4a1771e586c 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -293,19 +293,24 @@ struct get_usage_params
static NTSTATUS get_usage( const struct hid_value_caps *caps, void *user ) { + const struct hid_value_caps *end = caps; + ULONG index_min, index_max, bit, last; 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 )) { + while (end->flags & HID_VALUE_CAPS_ARRAY_HAS_MORE) end++; + index_min = end - caps + 1; + index_max = index_min + caps->usage_max - caps->usage_min; + 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 (params->usages < params->usages_end) *params->usages = caps->usage_min + index - caps->start_index; + if (!(index = report_buf[bit / 8]) || index < index_min || index > index_max) continue; + if (params->usages < params->usages_end) *params->usages = caps->usage_min + index - index_min; params->usages++; } return HIDP_STATUS_SUCCESS; @@ -499,18 +504,22 @@ struct set_usage_params
static NTSTATUS set_usage( const struct hid_value_caps *caps, void *user ) { + const struct hid_value_caps *end = caps; struct set_usage_params *params = user; + ULONG index_min, bit, last; unsigned char *report_buf; - ULONG bit, last;
report_buf = (unsigned char *)params->report_buf + caps->start_byte;
if (HID_VALUE_CAPS_IS_ARRAY( caps )) { + while (end->flags & HID_VALUE_CAPS_ARRAY_HAS_MORE) end++; + index_min = end - caps + 1; + for (bit = caps->start_bit, last = bit + caps->report_count * caps->bit_size - 1; bit <= last; bit += 8) { if (report_buf[bit / 8]) continue; - report_buf[bit / 8] = caps->start_index + params->usage - caps->usage_min; + report_buf[bit / 8] = index_min + params->usage - caps->usage_min; break; }
@@ -559,18 +568,22 @@ struct unset_usage_params
static NTSTATUS unset_usage( const struct hid_value_caps *caps, void *user ) { + ULONG index, index_min, index_max, bit, last; + const struct hid_value_caps *end = caps; 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 )) { + while (end->flags & HID_VALUE_CAPS_ARRAY_HAS_MORE) end++; + index_min = end - caps + 1; + index_max = index_min + caps->usage_max - caps->usage_min; + 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 (report_buf[bit / 8] != index) continue; + if (!(index = report_buf[bit / 8]) || index < index_min || index > index_max) continue; report_buf[bit / 8] = 0; params->found = TRUE; break; @@ -758,21 +771,26 @@ 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; + const struct hid_value_caps *end = caps; + ULONG index_min, index_max, bit, last; 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 )) { + while (end->flags & HID_VALUE_CAPS_ARRAY_HAS_MORE) end++; + index_min = end - caps + 1; + index_max = index_min + caps->usage_max - caps->usage_min; + 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 (!(index = report_buf[bit / 8]) || index < index_min || index > index_max) 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->Usage = caps->usage_min + index - index_min; } params->usages++; } @@ -848,7 +866,8 @@ 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; + ULONG index_min, index_max, bit, last, bit_count; + const struct hid_value_caps *end = caps; unsigned char *report_buf; BYTE index;
@@ -858,12 +877,16 @@ static NTSTATUS find_all_data( const struct hid_value_caps *caps, void *user )
if (HID_VALUE_CAPS_IS_ARRAY( caps )) { + while (end->flags & HID_VALUE_CAPS_ARRAY_HAS_MORE) end++; + index_min = end - caps + 1; + index_max = index_min + caps->usage_max - caps->usage_min; + 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 (!(index = report_buf[bit / 8]) || index < index_min || index > index_max) continue; if (data < data_end) { - data->DataIndex = caps->data_index_min + index - caps->start_index; + data->DataIndex = caps->data_index_min + index - index_min; data->On = 1; } data++; @@ -888,6 +911,7 @@ static NTSTATUS find_all_data( const struct hid_value_caps *caps, void *user ) { data->DataIndex = caps->data_index_min; data->RawValue = 0; + bit_count = caps->bit_size * caps->report_count; if ((bit_count + 7) / 8 > sizeof(data->RawValue)) return HIDP_STATUS_BUFFER_TOO_SMALL; copy_bits( (void *)&data->RawValue, report_buf, bit_count, -caps->start_bit ); } diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index 73b9858f741..2f7f417a7aa 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -354,13 +354,14 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY } value = state->values[type] + *value_idx;
- state->items.start_index = usages_size; if (!(is_array = HID_VALUE_CAPS_IS_ARRAY( &state->items ))) state->items.report_count -= usages_size - 1; else start_bit -= state->items.report_count * state->items.bit_size;
while (usages_size--) { if (!is_array) start_bit -= state->items.report_count * state->items.bit_size; + else if (usages_size) state->items.flags |= HID_VALUE_CAPS_ARRAY_HAS_MORE; + else state->items.flags &= ~HID_VALUE_CAPS_ARRAY_HAS_MORE; state->items.start_byte = start_bit / 8; state->items.start_bit = start_bit % 8; state->items.usage_page = state->usages_page[usages_size]; @@ -372,7 +373,6 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY *value++ = state->items; *value_idx += 1; if (!is_array) state->items.report_count = 1; - else state->items.start_index -= 1; }
state->items.usage_page = usage_page; diff --git a/include/wine/hid.h b/include/wine/hid.h index 4f388404885..a6c585b2ff4 100644 --- a/include/wine/hid.h +++ b/include/wine/hid.h @@ -52,7 +52,6 @@ struct hid_value_caps USHORT report_count; UCHAR start_bit; USHORT start_byte; - ULONG start_index; LONG logical_min; LONG logical_max; LONG physical_min; @@ -61,6 +60,8 @@ struct hid_value_caps ULONG units_exp; };
+/* named array continues on next caps */ +#define HID_VALUE_CAPS_ARRAY_HAS_MORE 0x01 #define HID_VALUE_CAPS_IS_RANGE 0x10 #define HID_VALUE_CAPS_IS_STRING_RANGE 0x40 #define HID_VALUE_CAPS_IS_DESIGNATOR_RANGE 0x80
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 4 ++-- dlls/hidparse.sys/main.c | 3 +++ include/wine/hid.h | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 4a1771e586c..662d3da9d58 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -647,7 +647,7 @@ static NTSTATUS get_button_caps( const struct hid_value_caps *caps, void *user ) dst->LinkUsage = caps->link_usage; dst->BitField = caps->bit_field; dst->IsAlias = FALSE; - dst->IsAbsolute = HID_VALUE_CAPS_IS_ABSOLUTE( caps ); + dst->IsAbsolute = (caps->flags & HID_VALUE_CAPS_IS_ABSOLUTE) ? 1 : 0; dst->IsRange = (caps->flags & HID_VALUE_CAPS_IS_RANGE) ? 1 : 0; if (!dst->IsRange) { @@ -704,7 +704,7 @@ static NTSTATUS get_value_caps( const struct hid_value_caps *caps, void *user ) dst->LinkUsage = caps->link_usage; dst->BitField = caps->bit_field; dst->IsAlias = FALSE; - dst->IsAbsolute = HID_VALUE_CAPS_IS_ABSOLUTE( caps ); + dst->IsAbsolute = (caps->flags & HID_VALUE_CAPS_IS_ABSOLUTE) ? 1 : 0; dst->HasNull = HID_VALUE_CAPS_HAS_NULL( caps ); dst->BitSize = caps->bit_size; dst->UnitsExp = caps->units_exp; diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index 2f7f417a7aa..ea4d84a6e81 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -357,6 +357,9 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY if (!(is_array = HID_VALUE_CAPS_IS_ARRAY( &state->items ))) state->items.report_count -= usages_size - 1; else start_bit -= state->items.report_count * state->items.bit_size;
+ if (!(state->items.bit_field & INPUT_ABS_REL)) state->items.flags |= HID_VALUE_CAPS_IS_ABSOLUTE; + if (state->items.bit_field & INPUT_DATA_CONST) state->items.flags |= HID_VALUE_CAPS_IS_CONSTANT; + while (usages_size--) { if (!is_array) start_bit -= state->items.report_count * state->items.bit_size; diff --git a/include/wine/hid.h b/include/wine/hid.h index a6c585b2ff4..7661850efc6 100644 --- a/include/wine/hid.h +++ b/include/wine/hid.h @@ -62,11 +62,12 @@ struct hid_value_caps
/* named array continues on next caps */ #define HID_VALUE_CAPS_ARRAY_HAS_MORE 0x01 +#define HID_VALUE_CAPS_IS_CONSTANT 0x02 +#define HID_VALUE_CAPS_IS_ABSOLUTE 0x08 #define HID_VALUE_CAPS_IS_RANGE 0x10 #define HID_VALUE_CAPS_IS_STRING_RANGE 0x40 #define HID_VALUE_CAPS_IS_DESIGNATOR_RANGE 0x80
-#define HID_VALUE_CAPS_IS_ABSOLUTE(x) (((x)->bit_field & 0x04) == 0) #define HID_VALUE_CAPS_HAS_NULL(x) (((x)->bit_field & 0x40) != 0) #define HID_VALUE_CAPS_IS_ARRAY(c) (((c)->bit_field & 2) == 0) #define HID_VALUE_CAPS_IS_BUTTON(c) ((c)->bit_size == 1 || HID_VALUE_CAPS_IS_ARRAY(c))
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/hid/hidp.c | 9 +++++---- dlls/hidparse.sys/main.c | 7 ++++--- include/wine/hid.h | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 662d3da9d58..a1cdb951fd4 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -80,8 +80,8 @@ struct caps_filter 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->values && HID_VALUE_CAPS_IS_BUTTON( caps )) return FALSE; + if (filter->buttons && !(caps->flags & HID_VALUE_CAPS_IS_BUTTON)) return FALSE; + if (filter->values && (caps->flags & HID_VALUE_CAPS_IS_BUTTON)) 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; @@ -836,8 +836,9 @@ NTSTATUS WINAPI HidP_GetUsagesEx( HIDP_REPORT_TYPE report_type, USHORT collectio
static NTSTATUS count_data( const struct hid_value_caps *caps, void *user ) { + BOOL is_button = caps->flags & HID_VALUE_CAPS_IS_BUTTON; BOOL is_range = caps->flags & HID_VALUE_CAPS_IS_RANGE; - if (is_range || HID_VALUE_CAPS_IS_BUTTON( caps )) *(ULONG *)user += caps->report_count; + if (is_range || is_button) *(ULONG *)user += caps->report_count; else *(ULONG *)user += 1; return HIDP_STATUS_SUCCESS; } @@ -892,7 +893,7 @@ static NTSTATUS find_all_data( const struct hid_value_caps *caps, void *user ) data++; } } - else if (HID_VALUE_CAPS_IS_BUTTON( caps )) + else if (caps->flags & HID_VALUE_CAPS_IS_BUTTON) { for (bit = caps->start_bit, last = bit + caps->usage_max - caps->usage_min; bit <= last; bit++) { diff --git a/dlls/hidparse.sys/main.c b/dlls/hidparse.sys/main.c index ea4d84a6e81..3170abc50b5 100644 --- a/dlls/hidparse.sys/main.c +++ b/dlls/hidparse.sys/main.c @@ -359,6 +359,7 @@ static BOOL parse_new_value_caps( struct hid_parser_state *state, HIDP_REPORT_TY
if (!(state->items.bit_field & INPUT_ABS_REL)) state->items.flags |= HID_VALUE_CAPS_IS_ABSOLUTE; if (state->items.bit_field & INPUT_DATA_CONST) state->items.flags |= HID_VALUE_CAPS_IS_CONSTANT; + if (state->items.bit_size == 1 || is_array) state->items.flags |= HID_VALUE_CAPS_IS_BUTTON;
while (usages_size--) { @@ -437,7 +438,7 @@ static struct hid_preparsed_data *build_preparsed_data( struct hid_parser_state for (i = 0, button = 0, filler = 0; i < data->caps.NumberInputValueCaps; ++i) { if (!caps[i].usage_min && !caps[i].usage_max) filler++; - else if (HID_VALUE_CAPS_IS_BUTTON( caps + i )) button++; + else if (caps[i].flags & HID_VALUE_CAPS_IS_BUTTON) button++; } data->caps.NumberInputButtonCaps = button; data->caps.NumberInputValueCaps -= filler + button; @@ -447,7 +448,7 @@ static struct hid_preparsed_data *build_preparsed_data( struct hid_parser_state for (i = 0, button = 0, filler = 0; i < data->caps.NumberOutputValueCaps; ++i) { if (!caps[i].usage_min && !caps[i].usage_max) filler++; - else if (HID_VALUE_CAPS_IS_BUTTON( caps + i )) button++; + else if (caps[i].flags & HID_VALUE_CAPS_IS_BUTTON) button++; } caps += data->caps.NumberOutputValueCaps; data->caps.NumberOutputButtonCaps = button; @@ -458,7 +459,7 @@ static struct hid_preparsed_data *build_preparsed_data( struct hid_parser_state for (i = 0, button = 0, filler = 0; i < data->caps.NumberFeatureValueCaps; ++i) { if (!caps[i].usage_min && !caps[i].usage_max) filler++; - else if (HID_VALUE_CAPS_IS_BUTTON( caps + i )) button++; + else if (caps[i].flags & HID_VALUE_CAPS_IS_BUTTON) button++; } caps += data->caps.NumberFeatureValueCaps; data->caps.NumberFeatureButtonCaps = button; diff --git a/include/wine/hid.h b/include/wine/hid.h index 7661850efc6..43f881bcc52 100644 --- a/include/wine/hid.h +++ b/include/wine/hid.h @@ -63,6 +63,7 @@ struct hid_value_caps /* named array continues on next caps */ #define HID_VALUE_CAPS_ARRAY_HAS_MORE 0x01 #define HID_VALUE_CAPS_IS_CONSTANT 0x02 +#define HID_VALUE_CAPS_IS_BUTTON 0x04 #define HID_VALUE_CAPS_IS_ABSOLUTE 0x08 #define HID_VALUE_CAPS_IS_RANGE 0x10 #define HID_VALUE_CAPS_IS_STRING_RANGE 0x40 @@ -70,7 +71,6 @@ struct hid_value_caps
#define HID_VALUE_CAPS_HAS_NULL(x) (((x)->bit_field & 0x40) != 0) #define HID_VALUE_CAPS_IS_ARRAY(c) (((c)->bit_field & 2) == 0) -#define HID_VALUE_CAPS_IS_BUTTON(c) ((c)->bit_size == 1 || HID_VALUE_CAPS_IS_ARRAY(c))
struct hid_preparsed_data {