winebus.sys: Use report ids in crafted HID reports.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2021-09-23 08:55:28 +02:00 committed by Alexandre Julliard
parent 9cf1e8353c
commit 04b19a969b
5 changed files with 89 additions and 23 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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));
}

View File

@ -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;

View File

@ -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);