Rémi Bernon : winebus.sys: Compute offsets while building the report descriptor.

Alexandre Julliard julliard at winehq.org
Wed Sep 22 16:04:38 CDT 2021


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

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Wed Sep 22 10:30:43 2021 +0200

winebus.sys: Compute offsets while building the report descriptor.

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

---

 dlls/winebus.sys/hid.c          | 83 +++++++++++++++++++++++++++++++++++++++++
 dlls/winebus.sys/unix_private.h | 14 +++++++
 2 files changed, 97 insertions(+)

diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c
index 98eb5341a2e..6d3dae5690d 100644
--- a/dlls/winebus.sys/hid.c
+++ b/dlls/winebus.sys/hid.c
@@ -32,8 +32,12 @@
 #include "hidusage.h"
 #include "ddk/wdm.h"
 
+#include "wine/debug.h"
+
 #include "unix_private.h"
 
+WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
+
 static BOOL hid_report_descriptor_append(struct hid_report_descriptor *desc, const BYTE *buffer, SIZE_T size)
 {
     BYTE *tmp = desc->data;
@@ -93,6 +97,25 @@ BOOL hid_device_end_report_descriptor(struct unix_device *iface)
     return hid_report_descriptor_append(desc, template, sizeof(template));
 }
 
+static BOOL hid_device_add_button_count(struct unix_device *iface, BYTE count)
+{
+    USHORT offset = iface->hid_device_state.bit_size / 8;
+
+    if ((iface->hid_device_state.bit_size % 8) && !iface->hid_device_state.button_count)
+        ERR("buttons should start byte aligned, missing padding!\n");
+    else if (iface->hid_device_state.bit_size + count > 0x80000)
+        ERR("report size overflow, too many elements!\n");
+    else
+    {
+        if (!iface->hid_device_state.button_count) iface->hid_device_state.button_start = offset;
+        iface->hid_device_state.button_count += count;
+        iface->hid_device_state.bit_size += count;
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
 BOOL hid_device_add_buttons(struct unix_device *iface, USAGE usage_page, USAGE usage_min, USAGE usage_max)
 {
     struct hid_report_descriptor *desc = &iface->hid_report_descriptor;
@@ -117,6 +140,9 @@ BOOL hid_device_add_buttons(struct unix_device *iface, USAGE usage_page, USAGE u
         INPUT(1, Cnst|Var|Abs),
     };
 
+    if (!hid_device_add_button_count(iface, usage_max - usage_min + 1))
+        return FALSE;
+
     if (!hid_report_descriptor_append(desc, template, sizeof(template)))
         return FALSE;
 
@@ -126,6 +152,27 @@ BOOL hid_device_add_buttons(struct unix_device *iface, USAGE usage_page, USAGE u
     return TRUE;
 }
 
+static BOOL hid_device_add_hatswitch_count(struct unix_device *iface, BYTE count)
+{
+    USHORT offset = iface->hid_device_state.bit_size / 8;
+
+    if (iface->hid_device_state.button_count)
+        ERR("hatswitches should be added before buttons!\n");
+    else if ((iface->hid_device_state.bit_size % 8))
+        ERR("hatswitches should be byte aligned, missing padding!\n");
+    else if (iface->hid_device_state.bit_size + 8 * count > 0x80000)
+        ERR("report size overflow, too many elements!\n");
+    else
+    {
+        if (!iface->hid_device_state.hatswitch_count) iface->hid_device_state.hatswitch_start = offset;
+        iface->hid_device_state.hatswitch_count += count;
+        iface->hid_device_state.bit_size += 8 * count;
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
 BOOL hid_device_add_hatswitch(struct unix_device *iface, INT count)
 {
     struct hid_report_descriptor *desc = &iface->hid_report_descriptor;
@@ -143,9 +190,42 @@ BOOL hid_device_add_hatswitch(struct unix_device *iface, INT count)
         INPUT(1, Data|Var|Abs|Null),
     };
 
+    if (!hid_device_add_hatswitch_count(iface, count))
+        return FALSE;
+
     return hid_report_descriptor_append(desc, template, sizeof(template));
 }
 
+static BOOL hid_device_add_axis_count(struct unix_device *iface, BOOL rel, BYTE count)
+{
+    USHORT offset = iface->hid_device_state.bit_size / 8;
+
+    if (!rel && iface->hid_device_state.rel_axis_count)
+        ERR("absolute axes should be added before relative axes!\n");
+    else if (iface->hid_device_state.button_count || iface->hid_device_state.hatswitch_count)
+        ERR("axes should be added before buttons or hatswitches!\n");
+    else if ((iface->hid_device_state.bit_size % 8))
+        ERR("axes should be byte aligned, missing padding!\n");
+    else if (iface->hid_device_state.bit_size + 32 * count > 0x80000)
+        ERR("report size overflow, too many elements!\n");
+    else if (rel)
+    {
+        if (!iface->hid_device_state.rel_axis_count) iface->hid_device_state.rel_axis_start = offset;
+        iface->hid_device_state.rel_axis_count += count;
+        iface->hid_device_state.bit_size += 32 * count;
+        return TRUE;
+    }
+    else
+    {
+        if (!iface->hid_device_state.abs_axis_count) iface->hid_device_state.abs_axis_start = offset;
+        iface->hid_device_state.abs_axis_count += count;
+        iface->hid_device_state.bit_size += 32 * count;
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
 BOOL hid_device_add_axes(struct unix_device *iface, BYTE count, USAGE usage_page,
                          const USAGE *usages, BOOL rel, LONG min, LONG max)
 {
@@ -171,6 +251,9 @@ BOOL hid_device_add_axes(struct unix_device *iface, BYTE count, USAGE usage_page
     };
     int i;
 
+    if (!hid_device_add_axis_count(iface, rel, count))
+        return FALSE;
+
     if (!hid_report_descriptor_append(desc, template_begin, sizeof(template_begin)))
         return FALSE;
 
diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h
index d1d48737e67..acb2f45aca3 100644
--- a/dlls/winebus.sys/unix_private.h
+++ b/dlls/winebus.sys/unix_private.h
@@ -57,6 +57,19 @@ struct hid_report_descriptor
     SIZE_T max_size;
 };
 
+struct hid_device_state
+{
+    ULONG bit_size;
+    USHORT abs_axis_start;
+    USHORT abs_axis_count;
+    USHORT rel_axis_start;
+    USHORT rel_axis_count;
+    USHORT hatswitch_start;
+    USHORT hatswitch_count;
+    USHORT button_start;
+    USHORT button_count;
+};
+
 struct unix_device
 {
     const struct raw_device_vtbl *vtbl;
@@ -65,6 +78,7 @@ struct unix_device
 
     const struct hid_device_vtbl *hid_vtbl;
     struct hid_report_descriptor hid_report_descriptor;
+    struct hid_device_state hid_device_state;
 };
 
 extern void *raw_device_create(const struct raw_device_vtbl *vtbl, SIZE_T size) DECLSPEC_HIDDEN;




More information about the wine-cvs mailing list