Rémi Bernon : hidparse.sys: Replace start_index with HID_VALUE_CAPS_ARRAY_HAS_MORE flag.

Alexandre Julliard julliard at winehq.org
Mon Sep 20 16:26:21 CDT 2021


Module: wine
Branch: master
Commit: 8eb6180d6ccb9239c31992731ef0501b37fed534
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=8eb6180d6ccb9239c31992731ef0501b37fed534

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Fri Sep 17 09:18:56 2021 +0200

hidparse.sys: Replace start_index with HID_VALUE_CAPS_ARRAY_HAS_MORE flag.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 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




More information about the wine-cvs mailing list