diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 772ee092c83..bcdfd7a9c15 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -444,6 +444,14 @@ static NTSTATUS sdl_device_physical_device_control(struct unix_device *iface, US return STATUS_NOT_SUPPORTED; } +static NTSTATUS sdl_device_physical_effect_control(struct unix_device *iface, BYTE index, + USAGE control, BYTE iterations) +{ + FIXME("iface %p, index %u, control %04x, iterations %u stub!\n", iface, index, control, iterations); + + return STATUS_NOT_IMPLEMENTED; +} + static const struct hid_device_vtbl sdl_device_vtbl = { sdl_device_destroy, @@ -451,6 +459,7 @@ static const struct hid_device_vtbl sdl_device_vtbl = sdl_device_stop, sdl_device_haptics_start, sdl_device_physical_device_control, + sdl_device_physical_effect_control, }; static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *event) diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 454ab3ea870..5eca64e8317 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -868,6 +868,14 @@ static NTSTATUS lnxev_device_physical_device_control(struct unix_device *iface, return STATUS_NOT_SUPPORTED; } +static NTSTATUS lnxev_device_physical_effect_control(struct unix_device *iface, BYTE index, + USAGE control, BYTE iterations) +{ + FIXME("iface %p, index %u, control %04x, iterations %u stub!\n", iface, index, control, iterations); + + return STATUS_NOT_IMPLEMENTED; +} + static const struct hid_device_vtbl lnxev_device_vtbl = { lnxev_device_destroy, @@ -875,6 +883,7 @@ static const struct hid_device_vtbl lnxev_device_vtbl = lnxev_device_stop, lnxev_device_haptics_start, lnxev_device_physical_device_control, + lnxev_device_physical_effect_control, }; #endif /* HAS_PROPER_INPUT_HEADER */ diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index 12db1706ede..4ddee27cff9 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -411,6 +411,21 @@ static const USAGE pid_device_control_usages[] = PID_USAGE_DC_DEVICE_PAUSE, PID_USAGE_DC_DEVICE_CONTINUE, }; + +struct pid_effect_control +{ + BYTE index; + BYTE control_index; + BYTE iterations; +}; + +static const USAGE pid_effect_control_usages[] = +{ + 0, /* HID nary collection indexes start at 1 */ + PID_USAGE_OP_EFFECT_START, + PID_USAGE_OP_EFFECT_START_SOLO, + PID_USAGE_OP_EFFECT_STOP, +}; #include "poppack.h" BOOL hid_device_add_physical(struct unix_device *iface) @@ -437,6 +452,42 @@ BOOL hid_device_add_physical(struct unix_device *iface) END_COLLECTION, END_COLLECTION, }; + + const BYTE effect_control_report = ++desc->next_report_id[HidP_Output]; + const BYTE effect_control_header[] = + { + /* Control effect state */ + USAGE(1, PID_USAGE_EFFECT_OPERATION_REPORT), + COLLECTION(1, Logical), + REPORT_ID(1, effect_control_report), + + USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX), + LOGICAL_MAXIMUM(1, 0x7f), + LOGICAL_MINIMUM(1, 0x00), + REPORT_SIZE(1, 8), + REPORT_COUNT(1, 1), + OUTPUT(1, Data|Var|Abs), + + USAGE(1, PID_USAGE_EFFECT_OPERATION), + COLLECTION(1, Logical), + }; + const BYTE effect_control_footer[] = + { + LOGICAL_MINIMUM(1, 1), + LOGICAL_MAXIMUM(1, 3), + REPORT_SIZE(1, 8), + REPORT_COUNT(1, 1), + OUTPUT(1, Data|Ary|Abs), + END_COLLECTION, + + USAGE(1, PID_USAGE_LOOP_COUNT), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(2, 0x00ff), + REPORT_SIZE(1, 8), + REPORT_COUNT(1, 1), + OUTPUT(1, Data|Var|Abs), + END_COLLECTION, + }; ULONG i; if (!hid_report_descriptor_append(desc, device_control_header, sizeof(device_control_header))) @@ -449,7 +500,18 @@ BOOL hid_device_add_physical(struct unix_device *iface) if (!hid_report_descriptor_append(desc, device_control_footer, sizeof(device_control_footer))) return FALSE; + if (!hid_report_descriptor_append(desc, effect_control_header, sizeof(effect_control_header))) + return FALSE; + for (i = 1; i < ARRAY_SIZE(pid_effect_control_usages); ++i) + { + if (!hid_report_descriptor_append_usage(desc, pid_effect_control_usages[i])) + return FALSE; + } + if (!hid_report_descriptor_append(desc, effect_control_footer, sizeof(effect_control_footer))) + return FALSE; + iface->hid_physical.device_control_report = device_control_report; + iface->hid_physical.effect_control_report = effect_control_report; return TRUE; } @@ -525,6 +587,21 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC else io->Status = iface->hid_vtbl->physical_device_control(iface, control); } + else if (packet->reportId == physical->effect_control_report) + { + struct pid_effect_control *report = (struct pid_effect_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_effect_control_usages)) + io->Status = STATUS_INVALID_PARAMETER; + else if (!(control = pid_effect_control_usages[report->control_index])) + io->Status = STATUS_INVALID_PARAMETER; + else + io->Status = iface->hid_vtbl->physical_effect_control(iface, report->index, control, report->iterations); + } else { io->Information = 0; diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index c62e4c9d0ab..2446b8de4a7 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -48,6 +48,7 @@ struct hid_device_vtbl 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); + NTSTATUS (*physical_effect_control)(struct unix_device *iface, BYTE index, USAGE control, BYTE iterations); }; struct hid_report_descriptor @@ -91,6 +92,7 @@ struct hid_haptics struct hid_physical { BYTE device_control_report; + BYTE effect_control_report; }; struct hid_device_state diff --git a/dlls/winebus.sys/unixlib.c b/dlls/winebus.sys/unixlib.c index 49a42ea04ad..177b8f5ba70 100644 --- a/dlls/winebus.sys/unixlib.c +++ b/dlls/winebus.sys/unixlib.c @@ -93,6 +93,12 @@ static NTSTATUS mouse_physical_device_control(struct unix_device *iface, USAGE c return STATUS_NOT_SUPPORTED; } +static NTSTATUS mouse_physical_effect_control(struct unix_device *iface, BYTE index, + USAGE control, BYTE iterations) +{ + return STATUS_NOT_SUPPORTED; +} + static const struct hid_device_vtbl mouse_vtbl = { mouse_destroy, @@ -100,6 +106,7 @@ static const struct hid_device_vtbl mouse_vtbl = mouse_stop, mouse_haptics_start, mouse_physical_device_control, + mouse_physical_effect_control, }; static const struct device_desc mouse_device_desc = @@ -156,6 +163,12 @@ static NTSTATUS keyboard_physical_device_control(struct unix_device *iface, USAG return STATUS_NOT_SUPPORTED; } +static NTSTATUS keyboard_physical_effect_control(struct unix_device *iface, BYTE index, + USAGE control, BYTE iterations) +{ + return STATUS_NOT_SUPPORTED; +} + static const struct hid_device_vtbl keyboard_vtbl = { keyboard_destroy, @@ -163,6 +176,7 @@ static const struct hid_device_vtbl keyboard_vtbl = keyboard_stop, keyboard_haptics_start, keyboard_physical_device_control, + keyboard_physical_effect_control, }; static const struct device_desc keyboard_device_desc =