[PATCH 1/5] hidparse.sys: Split struct hid_value_caps start_bit into start_byte / start_bit.

Rémi Bernon rbernon at codeweavers.com
Fri Sep 17 02:18:54 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at 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;
-- 
2.33.0




More information about the wine-devel mailing list