[PATCH 4/5] winebus.sys: Use HID descriptor helpers in bus_udev.c.

Rémi Bernon rbernon at codeweavers.com
Thu Aug 12 03:26:57 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/winebus.sys/bus_udev.c   | 147 +++++++++-------------------------
 dlls/winebus.sys/controller.h |   5 ++
 dlls/winebus.sys/hid.c        | 121 ++++++++++++++++++++++++++++
 3 files changed, 162 insertions(+), 111 deletions(-)

diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
index 261d24d011b..f9469399202 100644
--- a/dlls/winebus.sys/bus_udev.c
+++ b/dlls/winebus.sys/bus_udev.c
@@ -112,25 +112,6 @@ static inline struct platform_private *impl_from_DEVICE_OBJECT(DEVICE_OBJECT *de
 
 #ifdef HAS_PROPER_INPUT_HEADER
 
-#include "psh_hid_macros.h"
-
-static const BYTE REPORT_ABS_AXIS_TAIL[] = {
-    LOGICAL_MINIMUM(4, /* placeholder */ 0x00000000),
-    LOGICAL_MAXIMUM(4, /* placeholder */ 0x000000ff),
-    PHYSICAL_MINIMUM(4, /* placeholder */ 0x00000000),
-    PHYSICAL_MAXIMUM(4, /* placeholder */ 0x000000ff),
-    REPORT_SIZE(1, 32),
-    REPORT_COUNT(1, /* placeholder */ 0),
-    INPUT(1, Data|Var|Abs),
-};
-#define IDX_ABS_LOG_MINIMUM 1
-#define IDX_ABS_LOG_MAXIMUM 6
-#define IDX_ABS_PHY_MINIMUM 11
-#define IDX_ABS_PHY_MAXIMUM 16
-#define IDX_ABS_AXIS_COUNT 23
-
-#include "pop_hid_macros.h"
-
 static const BYTE ABS_TO_HID_MAP[][2] = {
     {HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_X},              /*ABS_X*/
     {HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_Y},              /*ABS_Y*/
@@ -199,8 +180,7 @@ struct wine_input_private {
     BYTE *current_report_buffer;
     enum { FIRST, NORMAL, DROPPED } report_state;
 
-    int report_descriptor_size;
-    BYTE *report_descriptor;
+    struct hid_descriptor desc;
 
     int button_start;
     BYTE button_map[KEY_MAX];
@@ -212,40 +192,6 @@ struct wine_input_private {
 
 #define test_bit(arr,bit) (((BYTE*)(arr))[(bit)>>3]&(1<<((bit)&7)))
 
-static BYTE *add_axis_block(BYTE *report_ptr, BYTE count, BYTE page, BYTE *usages, BOOL absolute, const struct wine_input_absinfo *absinfo)
-{
-    int i;
-    memcpy(report_ptr, REPORT_AXIS_HEADER, sizeof(REPORT_AXIS_HEADER));
-    report_ptr[IDX_AXIS_PAGE] = page;
-    report_ptr += sizeof(REPORT_AXIS_HEADER);
-    for (i = 0; i < count; i++)
-    {
-        memcpy(report_ptr, REPORT_AXIS_USAGE, sizeof(REPORT_AXIS_USAGE));
-        report_ptr[IDX_AXIS_USAGE] = usages[i];
-        report_ptr += sizeof(REPORT_AXIS_USAGE);
-    }
-    if (absolute)
-    {
-        memcpy(report_ptr, REPORT_ABS_AXIS_TAIL, sizeof(REPORT_ABS_AXIS_TAIL));
-        if (absinfo)
-        {
-            *((int*)&report_ptr[IDX_ABS_LOG_MINIMUM]) = LE_DWORD(absinfo->info.minimum);
-            *((int*)&report_ptr[IDX_ABS_LOG_MAXIMUM]) = LE_DWORD(absinfo->info.maximum);
-            *((int*)&report_ptr[IDX_ABS_PHY_MINIMUM]) = LE_DWORD(absinfo->info.minimum);
-            *((int*)&report_ptr[IDX_ABS_PHY_MAXIMUM]) = LE_DWORD(absinfo->info.maximum);
-        }
-        report_ptr[IDX_ABS_AXIS_COUNT] = count;
-        report_ptr += sizeof(REPORT_ABS_AXIS_TAIL);
-    }
-    else
-    {
-        memcpy(report_ptr, REPORT_REL_AXIS_TAIL, sizeof(REPORT_REL_AXIS_TAIL));
-        report_ptr[IDX_REL_AXIS_COUNT] = count;
-        report_ptr += sizeof(REPORT_REL_AXIS_TAIL);
-    }
-    return report_ptr;
-}
-
 static const BYTE* what_am_I(struct udev_device *dev)
 {
     static const BYTE Unknown[2]     = {HID_USAGE_PAGE_GENERIC, 0};
@@ -408,8 +354,7 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
     int rel_pages[TOP_REL_PAGE][HID_REL_MAX+1];
     BYTE absbits[(ABS_MAX+7)/8];
     BYTE relbits[(REL_MAX+7)/8];
-    BYTE *report_ptr;
-    INT i, descript_size;
+    INT i;
     INT report_size;
     INT button_count, abs_count, rel_count, hat_count;
     const BYTE *device_usage = what_am_I(dev);
@@ -425,7 +370,6 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
         return FALSE;
     }
 
-    descript_size = sizeof(REPORT_HEADER) + sizeof(REPORT_TAIL);
     report_size = 0;
 
     abs_count = 0;
@@ -443,7 +387,6 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
         if (abs_pages[i][0] > 0)
         {
             int j;
-            descript_size += sizeof(REPORT_AXIS_USAGE) * abs_pages[i][0];
             for (j = 1; j <= abs_pages[i][0]; j++)
             {
                 ext->abs_map[abs_pages[i][j]].report_index = report_size;
@@ -451,8 +394,6 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
             }
             abs_count++;
         }
-    descript_size += sizeof(REPORT_AXIS_HEADER) * abs_count;
-    descript_size += sizeof(REPORT_ABS_AXIS_TAIL) * abs_count;
 
     rel_count = 0;
     memset(rel_pages, 0, sizeof(rel_pages));
@@ -467,7 +408,6 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
         if (rel_pages[i][0] > 0)
         {
             int j;
-            descript_size += sizeof(REPORT_AXIS_USAGE) * rel_pages[i][0];
             for (j = 1; j <= rel_pages[i][0]; j++)
             {
                 ext->rel_map[rel_pages[i][j]] = report_size;
@@ -475,17 +415,12 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
             }
             rel_count++;
         }
-    descript_size += sizeof(REPORT_AXIS_HEADER) * rel_count;
-    descript_size += sizeof(REPORT_REL_AXIS_TAIL) * rel_count;
 
     /* For now lump all buttons just into incremental usages, Ignore Keys */
     ext->button_start = report_size;
     button_count = count_buttons(ext->base.device_fd, ext->button_map);
     if (button_count)
     {
-        descript_size += sizeof(REPORT_BUTTONS);
-        if (button_count % 8)
-            descript_size += sizeof(REPORT_PADDING);
         report_size += (button_count + 7) / 8;
     }
 
@@ -499,35 +434,26 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
             report_size++;
             hat_count++;
         }
-    if (hat_count > 0)
-        descript_size += sizeof(REPORT_HATSWITCH);
 
-    TRACE("Report Descriptor will be %i bytes\n", descript_size);
     TRACE("Report will be %i bytes\n", report_size);
 
-    ext->report_descriptor = HeapAlloc(GetProcessHeap(), 0, descript_size);
-    if (!ext->report_descriptor)
-    {
-        ERR("Failed to alloc report descriptor\n");
+    if (!hid_descriptor_begin(&ext->desc, device_usage[0], device_usage[1]))
         return FALSE;
-    }
-    report_ptr = ext->report_descriptor;
 
-    memcpy(report_ptr, REPORT_HEADER, sizeof(REPORT_HEADER));
-    report_ptr[IDX_HEADER_PAGE] = device_usage[0];
-    report_ptr[IDX_HEADER_USAGE] = device_usage[1];
-    report_ptr += sizeof(REPORT_HEADER);
     if (abs_count)
     {
         for (i = 1; i < TOP_ABS_PAGE; i++)
         {
             if (abs_pages[i][0])
             {
-                BYTE usages[HID_ABS_MAX];
+                USAGE usages[HID_ABS_MAX];
                 int j;
                 for (j = 0; j < abs_pages[i][0]; j++)
                     usages[j] = ABS_TO_HID_MAP[abs_pages[i][j+1]][1];
-                report_ptr = add_axis_block(report_ptr, abs_pages[i][0], i, usages, TRUE, &ext->abs_map[abs_pages[i][1]]);
+                if (!hid_descriptor_add_axes(&ext->desc, abs_pages[i][0], i, usages, FALSE, 32,
+                                             LE_DWORD(ext->abs_map[abs_pages[i][1]].info.minimum),
+                                             LE_DWORD(ext->abs_map[abs_pages[i][1]].info.maximum)))
+                    return FALSE;
             }
         }
     }
@@ -537,45 +463,41 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
         {
             if (rel_pages[i][0])
             {
-                BYTE usages[HID_REL_MAX];
+                USAGE usages[HID_REL_MAX];
                 int j;
                 for (j = 0; j < rel_pages[i][0]; j++)
                     usages[j] = REL_TO_HID_MAP[rel_pages[i][j+1]][1];
-                report_ptr = add_axis_block(report_ptr, rel_pages[i][0], i, usages, FALSE, NULL);
+                if (!hid_descriptor_add_axes(&ext->desc, rel_pages[i][0], i, usages, TRUE, 8, 0x81, 0x7f))
+                    return FALSE;
             }
         }
     }
     if (button_count)
     {
-        report_ptr = add_button_block(report_ptr, 1, button_count);
+        if (!hid_descriptor_add_buttons(&ext->desc, HID_USAGE_PAGE_BUTTON, 1, button_count))
+            return FALSE;
+
         if (button_count % 8)
         {
             BYTE padding = 8 - (button_count % 8);
-            report_ptr = add_padding_block(report_ptr, padding);
+            if (!hid_descriptor_add_padding(&ext->desc, padding))
+                return FALSE;
         }
     }
     if (hat_count)
-        report_ptr = add_hatswitch(report_ptr, hat_count);
-
-    memcpy(report_ptr, REPORT_TAIL, sizeof(REPORT_TAIL));
-
-    ext->report_descriptor_size = descript_size;
-    ext->buffer_length = report_size;
-    ext->current_report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, report_size);
-    if (ext->current_report_buffer == NULL)
     {
-        ERR("Failed to alloc report buffer\n");
-        HeapFree(GetProcessHeap(), 0, ext->report_descriptor);
-        return FALSE;
+        if (!hid_descriptor_add_hatswitch(&ext->desc, hat_count))
+            return FALSE;
     }
-    ext->last_report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, report_size);
-    if (ext->last_report_buffer == NULL)
-    {
-        ERR("Failed to alloc report buffer\n");
-        HeapFree(GetProcessHeap(), 0, ext->report_descriptor);
-        HeapFree(GetProcessHeap(), 0, ext->current_report_buffer);
+
+    if (!hid_descriptor_end(&ext->desc))
         return FALSE;
-    }
+
+    ext->buffer_length = report_size;
+    if (!(ext->current_report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, report_size)))
+        goto failed;
+    if (!(ext->last_report_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, report_size)))
+        goto failed;
     ext->report_state = FIRST;
 
     /* Initialize axis in the report */
@@ -584,6 +506,12 @@ static BOOL build_report_descriptor(struct wine_input_private *ext, struct udev_
             set_abs_axis_value(ext, i, ext->abs_map[i].info.value);
 
     return TRUE;
+
+failed:
+    HeapFree(GetProcessHeap(), 0, ext->current_report_buffer);
+    HeapFree(GetProcessHeap(), 0, ext->last_report_buffer);
+    hid_descriptor_free(&ext->desc);
+    return FALSE;
 }
 
 static BOOL set_report_from_event(struct wine_input_private *ext, struct input_event *ie)
@@ -972,7 +900,7 @@ static void lnxev_free_device(DEVICE_OBJECT *device)
 
     HeapFree(GetProcessHeap(), 0, ext->current_report_buffer);
     HeapFree(GetProcessHeap(), 0, ext->last_report_buffer);
-    HeapFree(GetProcessHeap(), 0, ext->report_descriptor);
+    hid_descriptor_free(&ext->desc);
 
     close(ext->base.device_fd);
     udev_device_unref(ext->base.udev_device);
@@ -982,13 +910,10 @@ static NTSTATUS lnxev_get_reportdescriptor(DEVICE_OBJECT *device, BYTE *buffer,
 {
     struct wine_input_private *ext = input_impl_from_DEVICE_OBJECT(device);
 
-    *out_length = ext->report_descriptor_size;
-
-    if (length < ext->report_descriptor_size)
-        return STATUS_BUFFER_TOO_SMALL;
-
-    memcpy(buffer, ext->report_descriptor, ext->report_descriptor_size);
+    *out_length = ext->desc.size;
+    if (length < ext->desc.size) return STATUS_BUFFER_TOO_SMALL;
 
+    memcpy(buffer, ext->desc.data, ext->desc.size);
     return STATUS_SUCCESS;
 }
 
diff --git a/dlls/winebus.sys/controller.h b/dlls/winebus.sys/controller.h
index aa838129ce2..b03338841e8 100644
--- a/dlls/winebus.sys/controller.h
+++ b/dlls/winebus.sys/controller.h
@@ -34,9 +34,14 @@ struct hid_descriptor
 extern BOOL hid_descriptor_append(struct hid_descriptor *desc, const BYTE *buffer, SIZE_T size) DECLSPEC_HIDDEN;
 extern BOOL hid_descriptor_begin(struct hid_descriptor *desc, USAGE usage_page, USAGE usage) DECLSPEC_HIDDEN;
 extern BOOL hid_descriptor_end(struct hid_descriptor *desc) DECLSPEC_HIDDEN;
+extern void hid_descriptor_free(struct hid_descriptor *desc) DECLSPEC_HIDDEN;
 
 extern BOOL hid_descriptor_add_buttons(struct hid_descriptor *desc, USAGE usage_page,
                                        USAGE usage_min, USAGE usage_max) DECLSPEC_HIDDEN;
+extern BOOL hid_descriptor_add_padding(struct hid_descriptor *desc, BYTE bitcount) DECLSPEC_HIDDEN;
+extern BOOL hid_descriptor_add_hatswitch(struct hid_descriptor *desc, INT count) DECLSPEC_HIDDEN;
+extern BOOL hid_descriptor_add_axes(struct hid_descriptor *desc, BYTE count, USAGE usage_page,
+                                    const USAGE *usages, BOOL rel, INT size, LONG min, LONG max) DECLSPEC_HIDDEN;
 
 /* Blocks of data for building HID device descriptions */
 
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c
index 052037ec19e..86c27d3eded 100644
--- a/dlls/winebus.sys/hid.c
+++ b/dlls/winebus.sys/hid.c
@@ -44,6 +44,16 @@ BOOL hid_descriptor_append(struct hid_descriptor *desc, const BYTE *buffer, SIZE
 
 #include "psh_hid_macros.h"
 
+static BOOL hid_descriptor_append_usage(struct hid_descriptor *desc, USAGE usage)
+{
+    const BYTE template[] =
+    {
+        USAGE(2, usage),
+    };
+
+    return hid_descriptor_append(desc, template, sizeof(template));
+}
+
 BOOL hid_descriptor_begin(struct hid_descriptor *desc, USAGE usage_page, USAGE usage)
 {
     const BYTE template[] =
@@ -68,6 +78,11 @@ BOOL hid_descriptor_end(struct hid_descriptor *desc)
     return hid_descriptor_append(desc, template, sizeof(template));
 }
 
+void hid_descriptor_free(struct hid_descriptor *desc)
+{
+    HeapFree(GetProcessHeap(), 0, desc->data);
+}
+
 BOOL hid_descriptor_add_buttons(struct hid_descriptor *desc, USAGE usage_page,
                                 USAGE usage_min, USAGE usage_max)
 {
@@ -88,4 +103,110 @@ BOOL hid_descriptor_add_buttons(struct hid_descriptor *desc, USAGE usage_page,
     return hid_descriptor_append(desc, template, sizeof(template));
 }
 
+BOOL hid_descriptor_add_padding(struct hid_descriptor *desc, BYTE bitcount)
+{
+    const BYTE template[] =
+    {
+        REPORT_COUNT(1, bitcount),
+        REPORT_SIZE(1, 1),
+        INPUT(1, Cnst|Var|Abs),
+    };
+
+    return hid_descriptor_append(desc, template, sizeof(template));
+}
+
+BOOL hid_descriptor_add_hatswitch(struct hid_descriptor *desc, INT count)
+{
+    const BYTE template[] =
+    {
+        USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
+        USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
+        LOGICAL_MINIMUM(1, 1),
+        LOGICAL_MAXIMUM(1, 8),
+        PHYSICAL_MINIMUM(1, 0),
+        PHYSICAL_MAXIMUM(2, 8),
+        REPORT_SIZE(1, 4),
+        REPORT_COUNT(4, count),
+        UNIT(1, 0x0e /* none */),
+        INPUT(1, Data|Var|Abs|Null),
+    };
+
+    return hid_descriptor_append(desc, template, sizeof(template));
+}
+
+BOOL hid_descriptor_add_axes(struct hid_descriptor *desc, BYTE count, USAGE usage_page,
+                             const USAGE *usages, BOOL rel, INT size, LONG min, LONG max)
+{
+    const BYTE template_begin[] =
+    {
+        USAGE_PAGE(1, usage_page),
+        COLLECTION(1, Physical),
+    };
+    const BYTE template_end[] =
+    {
+        END_COLLECTION,
+    };
+    const BYTE template_1[] =
+    {
+        LOGICAL_MINIMUM(1, min),
+        LOGICAL_MAXIMUM(1, max),
+        PHYSICAL_MINIMUM(1, min),
+        PHYSICAL_MAXIMUM(1, max),
+        REPORT_SIZE(1, size),
+        REPORT_COUNT(1, count),
+        INPUT(1, Data|Var|(rel ? Rel : Abs)),
+    };
+    const BYTE template_2[] =
+    {
+        LOGICAL_MINIMUM(2, min),
+        LOGICAL_MAXIMUM(2, max),
+        PHYSICAL_MINIMUM(2, min),
+        PHYSICAL_MAXIMUM(2, max),
+        REPORT_SIZE(1, size),
+        REPORT_COUNT(1, count),
+        INPUT(1, Data|Var|(rel ? Rel : Abs)),
+    };
+    const BYTE template_4[] =
+    {
+        LOGICAL_MINIMUM(4, min),
+        LOGICAL_MAXIMUM(4, max),
+        PHYSICAL_MINIMUM(4, min),
+        PHYSICAL_MAXIMUM(4, max),
+        REPORT_SIZE(1, size),
+        REPORT_COUNT(1, count),
+        INPUT(1, Data|Var|(rel ? Rel : Abs)),
+    };
+    int i;
+
+    if (!hid_descriptor_append(desc, template_begin, sizeof(template_begin)))
+        return FALSE;
+
+    for (i = 0; i < count; i++)
+    {
+        if (!hid_descriptor_append_usage(desc, usages[i]))
+            return FALSE;
+    }
+
+    if (size >= 16)
+    {
+        if (!hid_descriptor_append(desc, template_4, sizeof(template_4)))
+            return FALSE;
+    }
+    else if (size >= 8)
+    {
+        if (!hid_descriptor_append(desc, template_2, sizeof(template_2)))
+            return FALSE;
+    }
+    else
+    {
+        if (!hid_descriptor_append(desc, template_1, sizeof(template_1)))
+            return FALSE;
+    }
+
+    if (!hid_descriptor_append(desc, template_end, sizeof(template_end)))
+        return FALSE;
+
+    return TRUE;
+}
+
 #include "pop_hid_macros.h"
-- 
2.32.0




More information about the wine-devel mailing list