[PATCH 3/5] winebus.sys: Use report ids in crafted HID reports.

Rémi Bernon rbernon at codeweavers.com
Thu Sep 23 01:55:28 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/winebus.sys/bus_sdl.c      | 18 +++++++-
 dlls/winebus.sys/bus_udev.c     |  6 +++
 dlls/winebus.sys/hid.c          | 80 +++++++++++++++++++++++++--------
 dlls/winebus.sys/unix_private.h |  6 ++-
 dlls/xinput1_3/main.c           |  2 +-
 5 files changed, 89 insertions(+), 23 deletions(-)

diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c
index 7af5f13bcee..72cdf8ae605 100644
--- a/dlls/winebus.sys/bus_sdl.c
+++ b/dlls/winebus.sys/bus_sdl.c
@@ -46,6 +46,7 @@
 #include "winternl.h"
 #include "ddk/wdm.h"
 #include "ddk/hidtypes.h"
+#include "ddk/hidsdi.h"
 #include "wine/debug.h"
 #include "wine/unicode.h"
 #include "hidusage.h"
@@ -119,6 +120,7 @@ struct sdl_device
 
     SDL_Haptic *sdl_haptic;
     int haptic_effect_id;
+    BYTE vendor_rumble_report_id;
 };
 
 static inline struct sdl_device *impl_from_unix_device(struct unix_device *iface)
@@ -166,7 +168,7 @@ static BOOL descriptor_add_haptic(struct sdl_device *impl)
         {
             pSDL_HapticStopAll(impl->sdl_haptic);
             pSDL_HapticRumbleInit(impl->sdl_haptic);
-            if (!hid_device_add_haptics(&impl->unix_device))
+            if (!hid_device_add_haptics(&impl->unix_device, &impl->vendor_rumble_report_id))
                 return FALSE;
             impl->haptic_effect_id = -1;
         }
@@ -217,6 +219,9 @@ static NTSTATUS build_joystick_report_descriptor(struct unix_device *iface)
     if (!hid_device_begin_report_descriptor(iface, HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_JOYSTICK))
         return STATUS_NO_MEMORY;
 
+    if (!hid_device_begin_input_report(iface))
+        return STATUS_NO_MEMORY;
+
     if (axis_count && !hid_device_add_axes(iface, axis_count, HID_USAGE_PAGE_GENERIC,
                                            joystick_usages, FALSE, -32768, 32767))
         return STATUS_NO_MEMORY;
@@ -231,6 +236,9 @@ static NTSTATUS build_joystick_report_descriptor(struct unix_device *iface)
     if (button_count && !hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, button_count))
         return STATUS_NO_MEMORY;
 
+    if (!hid_device_end_input_report(iface))
+        return STATUS_NO_MEMORY;
+
     if (!descriptor_add_haptic(impl))
         return STATUS_NO_MEMORY;
 
@@ -258,6 +266,9 @@ static NTSTATUS build_controller_report_descriptor(struct unix_device *iface)
     if (!hid_device_begin_report_descriptor(iface, HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_GAMEPAD))
         return STATUS_NO_MEMORY;
 
+    if (!hid_device_begin_input_report(iface))
+        return STATUS_NO_MEMORY;
+
     if (!hid_device_add_axes(iface, 2, HID_USAGE_PAGE_GENERIC, left_axis_usages,
                              FALSE, -32768, 32767))
         return STATUS_NO_MEMORY;
@@ -276,6 +287,9 @@ static NTSTATUS build_controller_report_descriptor(struct unix_device *iface)
     if (!hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, button_count))
         return STATUS_NO_MEMORY;
 
+    if (!hid_device_end_input_report(iface))
+        return STATUS_NO_MEMORY;
+
     if (!descriptor_add_haptic(impl))
         return STATUS_NO_MEMORY;
 
@@ -325,7 +339,7 @@ static void sdl_device_set_output_report(struct unix_device *iface, HID_XFER_PAC
 {
     struct sdl_device *impl = impl_from_unix_device(iface);
 
-    if (impl->sdl_haptic && packet->reportId == 0)
+    if (impl->sdl_haptic && packet->reportId == impl->vendor_rumble_report_id)
     {
         WORD left = packet->reportBuffer[2] * 128;
         WORD right = packet->reportBuffer[3] * 128;
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c
index f4d27090109..508614d2c04 100644
--- a/dlls/winebus.sys/bus_udev.c
+++ b/dlls/winebus.sys/bus_udev.c
@@ -391,6 +391,9 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d
     if (!hid_device_begin_report_descriptor(iface, device_usage[0], device_usage[1]))
         return STATUS_NO_MEMORY;
 
+    if (!hid_device_begin_input_report(iface))
+        return STATUS_NO_MEMORY;
+
     abs_count = 0;
     for (i = 0; i < HID_ABS_MAX; i++)
     {
@@ -437,6 +440,9 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d
     if (button_count && !hid_device_add_buttons(iface, HID_USAGE_PAGE_BUTTON, 1, button_count))
         return STATUS_NO_MEMORY;
 
+    if (!hid_device_end_input_report(iface))
+        return STATUS_NO_MEMORY;
+
     if (!hid_device_end_report_descriptor(iface))
         return STATUS_NO_MEMORY;
 
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c
index 4a4295b9aa8..92d572355c2 100644
--- a/dlls/winebus.sys/hid.c
+++ b/dlls/winebus.sys/hid.c
@@ -31,6 +31,7 @@
 #include "winioctl.h"
 #include "hidusage.h"
 #include "ddk/wdm.h"
+#include "ddk/hidsdi.h"
 
 #include "wine/debug.h"
 
@@ -87,6 +88,39 @@ BOOL hid_device_begin_report_descriptor(struct unix_device *iface, USAGE usage_p
 }
 
 BOOL hid_device_end_report_descriptor(struct unix_device *iface)
+{
+    struct hid_report_descriptor *desc = &iface->hid_report_descriptor;
+    static const BYTE template[] =
+    {
+        END_COLLECTION,
+    };
+
+    return hid_report_descriptor_append(desc, template, sizeof(template));
+}
+
+BOOL hid_device_begin_input_report(struct unix_device *iface)
+{
+    struct hid_report_descriptor *desc = &iface->hid_report_descriptor;
+    struct hid_device_state *state = &iface->hid_device_state;
+    const BYTE report_id = ++desc->next_report_id[HidP_Input];
+    const BYTE template[] =
+    {
+        COLLECTION(1, Report),
+            REPORT_ID(1, report_id),
+    };
+
+    if (state->report_len)
+    {
+        ERR("input report already created\n");
+        return FALSE;
+    }
+
+    state->id = report_id;
+    state->bit_size += 8;
+    return hid_report_descriptor_append(desc, template, sizeof(template));
+}
+
+BOOL hid_device_end_input_report(struct unix_device *iface)
 {
     struct hid_report_descriptor *desc = &iface->hid_report_descriptor;
     struct hid_device_state *state = &iface->hid_device_state;
@@ -98,6 +132,9 @@ BOOL hid_device_end_report_descriptor(struct unix_device *iface)
     state->report_len = (state->bit_size + 7) / 8;
     if (!(state->report_buf = calloc(1, state->report_len))) return FALSE;
     if (!(state->last_report_buf = calloc(1, state->report_len))) return FALSE;
+
+    state->report_buf[0] = state->id;
+    state->last_report_buf[0] = state->id;
     return hid_report_descriptor_append(desc, template, sizeof(template));
 }
 
@@ -276,31 +313,36 @@ BOOL hid_device_add_axes(struct unix_device *iface, BYTE count, USAGE usage_page
     return TRUE;
 }
 
-BOOL hid_device_add_haptics(struct unix_device *iface)
+BOOL hid_device_add_haptics(struct unix_device *iface, BYTE *id)
 {
     struct hid_report_descriptor *desc = &iface->hid_report_descriptor;
-    static const BYTE template[] =
+    const BYTE report_id = ++desc->next_report_id[HidP_Output];
+    const BYTE template[] =
     {
         USAGE_PAGE(2, HID_USAGE_PAGE_VENDOR_DEFINED_BEGIN),
-        USAGE(1, 0x01),
-        /* padding */
-        REPORT_COUNT(1, 0x02),
-        REPORT_SIZE(1, 0x08),
-        OUTPUT(1, Data|Var|Abs),
-        /* actuators */
-        LOGICAL_MINIMUM(1, 0x00),
-        LOGICAL_MAXIMUM(1, 0xff),
-        PHYSICAL_MINIMUM(1, 0x00),
-        PHYSICAL_MAXIMUM(1, 0xff),
-        REPORT_SIZE(1, 0x08),
-        REPORT_COUNT(1, 0x02),
-        OUTPUT(1, Data|Var|Abs),
-        /* padding */
-        REPORT_COUNT(1, 0x02),
-        REPORT_SIZE(1, 0x08),
-        OUTPUT(1, Data|Var|Abs),
+        COLLECTION(1, Report),
+            REPORT_ID(1, report_id),
+            /* padding */
+            REPORT_COUNT(1, 0x02),
+            REPORT_SIZE(1, 0x08),
+            OUTPUT(1, Data|Var|Abs),
+            /* actuators */
+            USAGE(1, 0x01),
+            LOGICAL_MINIMUM(1, 0x00),
+            LOGICAL_MAXIMUM(1, 0xff),
+            PHYSICAL_MINIMUM(1, 0x00),
+            PHYSICAL_MAXIMUM(1, 0xff),
+            REPORT_SIZE(1, 0x08),
+            REPORT_COUNT(1, 0x02),
+            OUTPUT(1, Data|Var|Abs),
+            /* padding */
+            REPORT_COUNT(1, 0x02),
+            REPORT_SIZE(1, 0x08),
+            OUTPUT(1, Data|Var|Abs),
+        END_COLLECTION,
     };
 
+    *id = report_id;
     return hid_report_descriptor_append(desc, template, sizeof(template));
 }
 
diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h
index 543bfda9d79..b44bf503b45 100644
--- a/dlls/winebus.sys/unix_private.h
+++ b/dlls/winebus.sys/unix_private.h
@@ -55,6 +55,7 @@ struct hid_report_descriptor
     BYTE *data;
     SIZE_T size;
     SIZE_T max_size;
+    BYTE next_report_id[3];
 };
 
 struct hid_device_state
@@ -72,6 +73,7 @@ struct hid_device_state
     BYTE *report_buf;
     BYTE *last_report_buf;
     BOOL dropped;
+    BYTE id;
 };
 
 struct unix_device
@@ -111,13 +113,15 @@ extern BOOL bus_event_queue_pop(struct list *queue, struct bus_event *event) DEC
 extern BOOL hid_device_begin_report_descriptor(struct unix_device *iface, USAGE usage_page, USAGE usage) DECLSPEC_HIDDEN;
 extern BOOL hid_device_end_report_descriptor(struct unix_device *iface) DECLSPEC_HIDDEN;
 
+extern BOOL hid_device_begin_input_report(struct unix_device *iface) DECLSPEC_HIDDEN;
+extern BOOL hid_device_end_input_report(struct unix_device *iface) DECLSPEC_HIDDEN;
 extern BOOL hid_device_add_buttons(struct unix_device *iface, USAGE usage_page,
                                    USAGE usage_min, USAGE usage_max) DECLSPEC_HIDDEN;
 extern BOOL hid_device_add_hatswitch(struct unix_device *iface, INT count) DECLSPEC_HIDDEN;
 extern BOOL hid_device_add_axes(struct unix_device *iface, BYTE count, USAGE usage_page,
                                 const USAGE *usages, BOOL rel, LONG min, LONG max) DECLSPEC_HIDDEN;
 
-extern BOOL hid_device_add_haptics(struct unix_device *iface) DECLSPEC_HIDDEN;
+extern BOOL hid_device_add_haptics(struct unix_device *iface, BYTE *id) DECLSPEC_HIDDEN;
 
 extern BOOL hid_device_set_abs_axis(struct unix_device *iface, ULONG index, LONG value) DECLSPEC_HIDDEN;
 extern BOOL hid_device_set_rel_axis(struct unix_device *iface, ULONG index, LONG value) DECLSPEC_HIDDEN;
diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c
index 44493ddb2a1..d601c23f6f1 100644
--- a/dlls/xinput1_3/main.c
+++ b/dlls/xinput1_3/main.c
@@ -233,7 +233,7 @@ static DWORD HID_set_state(struct xinput_controller *controller, XINPUT_VIBRATIO
         if (controller->enabled)
         {
             memset(output_report_buf, 0, output_report_len);
-            output_report_buf[0] = /* report id */ 0;
+            output_report_buf[0] = 1;
             output_report_buf[1] = 0x8;
             output_report_buf[3] = (BYTE)(state->wLeftMotorSpeed / 256);
             output_report_buf[4] = (BYTE)(state->wRightMotorSpeed / 256);
-- 
2.33.0




More information about the wine-devel mailing list