[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