winebus.sys: Add a PID device control output report.

And include it in the HID report descriptor when SDL device has support
for any haptic effect, or when UDEV lnxev device has any FF bit set.

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-10-01 09:31:00 +02:00 committed by Alexandre Julliard
parent b33bece87e
commit 903c7ea75d
5 changed files with 128 additions and 3 deletions

View File

@ -115,6 +115,9 @@ static Uint16 (*pSDL_JoystickGetVendor)(SDL_Joystick * joystick);
#define WINE_SDL_HAPTIC_RUMBLE 0x80000000 /* using SDL_HapticRumble API */
#define EFFECT_SUPPORT_HAPTICS (SDL_HAPTIC_LEFTRIGHT|WINE_SDL_HAPTIC_RUMBLE|WINE_SDL_JOYSTICK_RUMBLE)
#define EFFECT_SUPPORT_PHYSICAL (SDL_HAPTIC_CONSTANT|SDL_HAPTIC_RAMP|SDL_HAPTIC_SINE|SDL_HAPTIC_TRIANGLE| \
SDL_HAPTIC_SAWTOOTHUP|SDL_HAPTIC_SAWTOOTHDOWN|SDL_HAPTIC_SPRING|SDL_HAPTIC_DAMPER|SDL_HAPTIC_INERTIA| \
SDL_HAPTIC_FRICTION|SDL_HAPTIC_CUSTOM)
struct sdl_device
{
@ -165,14 +168,12 @@ static void set_hat_value(struct unix_device *iface, int index, int value)
static BOOL descriptor_add_haptic(struct sdl_device *impl)
{
unsigned int haptics_mask = SDL_HAPTIC_LEFTRIGHT;
if (!pSDL_JoystickIsHaptic(impl->sdl_joystick) ||
!(impl->sdl_haptic = pSDL_HapticOpenFromJoystick(impl->sdl_joystick)))
impl->effect_support = 0;
else
{
impl->effect_support = pSDL_HapticQuery(impl->sdl_haptic) & haptics_mask;
impl->effect_support = pSDL_HapticQuery(impl->sdl_haptic);
if (pSDL_HapticRumbleSupported(impl->sdl_haptic))
impl->effect_support |= WINE_SDL_HAPTIC_RUMBLE;
@ -189,6 +190,12 @@ static BOOL descriptor_add_haptic(struct sdl_device *impl)
return FALSE;
}
if ((impl->effect_support & EFFECT_SUPPORT_PHYSICAL))
{
if (!hid_device_add_physical(&impl->unix_device))
return FALSE;
}
impl->haptic_effect_id = -1;
return TRUE;
}
@ -391,12 +398,20 @@ NTSTATUS sdl_device_haptics_start(struct unix_device *iface, DWORD duration_ms,
return STATUS_SUCCESS;
}
static NTSTATUS sdl_device_physical_device_control(struct unix_device *iface, USAGE control)
{
FIXME("iface %p, control %#04x stub\n", iface, control);
return STATUS_NOT_SUPPORTED;
}
static const struct hid_device_vtbl sdl_device_vtbl =
{
sdl_device_destroy,
sdl_device_start,
sdl_device_stop,
sdl_device_haptics_start,
sdl_device_physical_device_control,
};
static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *event)

View File

@ -658,6 +658,13 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d
impl->haptic_effect_id = effect.id;
}
for (i = 0; i < FF_MAX; ++i) if (test_bit(ffbits, i)) break;
if (i != FF_MAX)
{
if (!hid_device_add_physical(iface))
return STATUS_NO_MEMORY;
}
if (!hid_device_end_report_descriptor(iface))
return STATUS_NO_MEMORY;
@ -802,12 +809,20 @@ static NTSTATUS lnxev_device_haptics_start(struct unix_device *iface, DWORD dura
return STATUS_SUCCESS;
}
static NTSTATUS lnxev_device_physical_device_control(struct unix_device *iface, USAGE control)
{
FIXME("iface %p, control %#04x stub!\n", iface, control);
return STATUS_NOT_IMPLEMENTED;
}
static const struct hid_device_vtbl lnxev_device_vtbl =
{
lnxev_device_destroy,
lnxev_device_start,
lnxev_device_stop,
lnxev_device_haptics_start,
lnxev_device_physical_device_control,
};
#endif /* HAS_PROPER_INPUT_HEADER */

View File

@ -35,6 +35,7 @@
#include "ddk/hidsdi.h"
#include "wine/debug.h"
#include "wine/hid.h"
#include "unix_private.h"
@ -394,6 +395,64 @@ BOOL hid_device_add_haptics(struct unix_device *iface)
return hid_report_descriptor_append(desc, haptics_template, sizeof(haptics_template));
}
#include "pshpack1.h"
struct pid_device_control
{
BYTE control_index;
};
static const USAGE pid_device_control_usages[] =
{
0, /* HID nary collection indexes start at 1 */
PID_USAGE_DC_ENABLE_ACTUATORS,
PID_USAGE_DC_DISABLE_ACTUATORS,
PID_USAGE_DC_STOP_ALL_EFFECTS,
PID_USAGE_DC_DEVICE_RESET,
PID_USAGE_DC_DEVICE_PAUSE,
PID_USAGE_DC_DEVICE_CONTINUE,
};
#include "poppack.h"
BOOL hid_device_add_physical(struct unix_device *iface)
{
struct hid_report_descriptor *desc = &iface->hid_report_descriptor;
const BYTE device_control_report = ++desc->next_report_id[HidP_Output];
const BYTE device_control_header[] =
{
USAGE_PAGE(1, HID_USAGE_PAGE_PID),
USAGE(1, PID_USAGE_DEVICE_CONTROL_REPORT),
COLLECTION(1, Logical),
REPORT_ID(1, device_control_report),
USAGE(1, PID_USAGE_DEVICE_CONTROL),
COLLECTION(1, Logical),
};
const BYTE device_control_footer[] =
{
LOGICAL_MINIMUM(1, 1),
LOGICAL_MAXIMUM(1, 6),
REPORT_SIZE(1, 8),
REPORT_COUNT(1, 1),
OUTPUT(1, Data|Ary|Abs),
END_COLLECTION,
END_COLLECTION,
};
ULONG i;
if (!hid_report_descriptor_append(desc, device_control_header, sizeof(device_control_header)))
return FALSE;
for (i = 1; i < ARRAY_SIZE(pid_device_control_usages); ++i)
{
if (!hid_report_descriptor_append_usage(desc, pid_device_control_usages[i]))
return FALSE;
}
if (!hid_report_descriptor_append(desc, device_control_footer, sizeof(device_control_footer)))
return FALSE;
iface->hid_physical.device_control_report = device_control_report;
return TRUE;
}
#include "pop_hid_macros.h"
static void hid_device_destroy(struct unix_device *iface)
@ -425,6 +484,7 @@ NTSTATUS hid_device_get_report_descriptor(struct unix_device *iface, BYTE *buffe
static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PACKET *packet, IO_STATUS_BLOCK *io)
{
struct hid_physical *physical = &iface->hid_physical;
struct hid_haptics *haptics = &iface->hid_haptics;
if (packet->reportId == haptics->waveform_report)
@ -450,6 +510,21 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC
io->Status = iface->hid_vtbl->haptics_start(iface, duration_ms, rumble->intensity, buzz->intensity);
}
}
else if (packet->reportId == physical->device_control_report)
{
struct pid_device_control *report = (struct pid_device_control *)(packet->reportBuffer + 1);
USAGE control;
io->Information = sizeof(*report) + 1;
if (packet->reportBufferLen < io->Information)
io->Status = STATUS_BUFFER_TOO_SMALL;
else if (report->control_index >= ARRAY_SIZE(pid_device_control_usages))
io->Status = STATUS_INVALID_PARAMETER;
else if (!(control = pid_device_control_usages[report->control_index]))
io->Status = STATUS_INVALID_PARAMETER;
else
io->Status = iface->hid_vtbl->physical_device_control(iface, control);
}
else
{
io->Information = 0;

View File

@ -47,6 +47,7 @@ struct hid_device_vtbl
void (*stop)(struct unix_device *iface);
NTSTATUS (*haptics_start)(struct unix_device *iface, DWORD duration_ms,
USHORT rumble_intensity, USHORT buzz_intensity);
NTSTATUS (*physical_device_control)(struct unix_device *iface, USAGE control);
};
struct hid_report_descriptor
@ -87,6 +88,11 @@ struct hid_haptics
BYTE waveform_report;
};
struct hid_physical
{
BYTE device_control_report;
};
struct hid_device_state
{
ULONG bit_size;
@ -115,6 +121,7 @@ struct unix_device
struct hid_report_descriptor hid_report_descriptor;
struct hid_device_state hid_device_state;
struct hid_haptics hid_haptics;
struct hid_physical hid_physical;
};
extern void *raw_device_create(const struct raw_device_vtbl *vtbl, SIZE_T size) DECLSPEC_HIDDEN;
@ -152,6 +159,7 @@ extern BOOL hid_device_add_axes(struct unix_device *iface, BYTE count, USAGE usa
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_physical(struct unix_device *iface) 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

@ -88,12 +88,18 @@ static NTSTATUS mouse_haptics_start(struct unix_device *iface, DWORD duration,
return STATUS_NOT_SUPPORTED;
}
static NTSTATUS mouse_physical_device_control(struct unix_device *iface, USAGE control)
{
return STATUS_NOT_SUPPORTED;
}
static const struct hid_device_vtbl mouse_vtbl =
{
mouse_destroy,
mouse_start,
mouse_stop,
mouse_haptics_start,
mouse_physical_device_control,
};
static const struct device_desc mouse_device_desc =
@ -145,12 +151,18 @@ static NTSTATUS keyboard_haptics_start(struct unix_device *iface, DWORD duration
return STATUS_NOT_SUPPORTED;
}
static NTSTATUS keyboard_physical_device_control(struct unix_device *iface, USAGE control)
{
return STATUS_NOT_SUPPORTED;
}
static const struct hid_device_vtbl keyboard_vtbl =
{
keyboard_destroy,
keyboard_start,
keyboard_stop,
keyboard_haptics_start,
keyboard_physical_device_control,
};
static const struct device_desc keyboard_device_desc =