Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 15 ++++++++- dlls/winebus.sys/bus_udev.c | 8 ++++- dlls/winebus.sys/hid.c | 56 +++++++++++++++++++++++++++++++++ dlls/winebus.sys/unix_private.h | 7 +++++ 4 files changed, 84 insertions(+), 2 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 36efd5cc850..14546467863 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -212,6 +212,7 @@ static BOOL descriptor_add_haptic(struct sdl_device *impl) if (impl->effect_support & SDL_HAPTIC_DAMPER) usages[count++] = PID_USAGE_ET_DAMPER; if (impl->effect_support & SDL_HAPTIC_INERTIA) usages[count++] = PID_USAGE_ET_INERTIA; if (impl->effect_support & SDL_HAPTIC_FRICTION) usages[count++] = PID_USAGE_ET_FRICTION; + if (impl->effect_support & SDL_HAPTIC_CONSTANT) usages[count++] = PID_USAGE_ET_CONSTANT_FORCE;
if (!hid_device_add_physical(&impl->unix_device, usages, count)) return FALSE; @@ -594,8 +595,20 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT break;
case PID_USAGE_ET_CONSTANT_FORCE: - FIXME("not implemented!"); + effect.constant.length = params->duration; + effect.constant.delay = params->start_delay; + effect.constant.button = params->trigger_button; + effect.constant.interval = params->trigger_repeat_interval; + effect.constant.direction.type = SDL_HAPTIC_SPHERICAL; + effect.constant.direction.dir[0] = params->direction[0] * 36000 / 256; + effect.constant.direction.dir[1] = params->direction[1] * 36000 / 256; + effect.constant.level = params->constant_force.magnitude; + effect.constant.attack_length = params->envelope.attack_time; + effect.constant.attack_level = params->envelope.attack_level; + effect.constant.fade_length = params->envelope.fade_time; + effect.constant.fade_level = params->envelope.fade_level; break; + case PID_USAGE_ET_RAMP: FIXME("not implemented!"); break; diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 251c74574af..6067500117c 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -676,6 +676,7 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d if (test_bit(ffbits, FF_DAMPER)) usages[count++] = PID_USAGE_ET_DAMPER; if (test_bit(ffbits, FF_INERTIA)) usages[count++] = PID_USAGE_ET_INERTIA; if (test_bit(ffbits, FF_FRICTION)) usages[count++] = PID_USAGE_ET_FRICTION; + if (test_bit(ffbits, FF_CONSTANT)) usages[count++] = PID_USAGE_ET_CONSTANT_FORCE;
if (!hid_device_add_physical(iface, usages, count)) return STATUS_NO_MEMORY; @@ -1039,8 +1040,13 @@ static NTSTATUS lnxev_device_physical_effect_update(struct unix_device *iface, B break;
case PID_USAGE_ET_CONSTANT_FORCE: - FIXME("not implemented!"); + effect.u.constant.level = params->constant_force.magnitude; + effect.u.constant.envelope.attack_length = params->envelope.attack_time; + effect.u.constant.envelope.attack_level = params->envelope.attack_level; + effect.u.constant.envelope.fade_length = params->envelope.fade_time; + effect.u.constant.envelope.fade_level = params->envelope.fade_level; break; + case PID_USAGE_ET_RAMP: FIXME("not implemented!"); break; diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index 1cd9cf82d68..4c55367e78d 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -470,6 +470,13 @@ struct pid_set_condition BYTE negative_saturation; BYTE dead_band; }; + +struct pid_set_constant_force +{ + BYTE index; + UINT16 magnitude; +}; + #include "poppack.h"
static BOOL hid_descriptor_add_set_periodic(struct unix_device *iface) @@ -635,6 +642,39 @@ static BOOL hid_descriptor_add_set_condition(struct unix_device *iface) return hid_report_descriptor_append(desc, template, sizeof(template)); }
+static BOOL hid_descriptor_add_set_constant_force(struct unix_device *iface) +{ + struct hid_report_descriptor *desc = &iface->hid_report_descriptor; + const BYTE report_id = ++desc->next_report_id[HidP_Output]; + const BYTE template[] = + { + /* Constant Force Report Definition */ + USAGE(1, PID_USAGE_SET_CONSTANT_FORCE_REPORT), + COLLECTION(1, Logical), + REPORT_ID(1, report_id), + + 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_MAGNITUDE), + LOGICAL_MINIMUM(2, 0xff01), + LOGICAL_MAXIMUM(2, 0x00ff), + PHYSICAL_MINIMUM(2, -1000), + PHYSICAL_MAXIMUM(2, 1000), + REPORT_SIZE(1, 16), + REPORT_COUNT(1, 1), + OUTPUT(1, Data|Var|Abs), + END_COLLECTION, + }; + + iface->hid_physical.set_constant_force_report = report_id; + return hid_report_descriptor_append(desc, template, sizeof(template)); +} + BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT count) { struct hid_report_descriptor *desc = &iface->hid_report_descriptor; @@ -788,6 +828,7 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co BOOL periodic = FALSE; BOOL envelope = FALSE; BOOL condition = FALSE; + BOOL constant_force = FALSE; ULONG i;
if (!hid_report_descriptor_append(desc, device_control_header, sizeof(device_control_header))) @@ -833,6 +874,8 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co usages[i] == PID_USAGE_ET_INERTIA || usages[i] == PID_USAGE_ET_FRICTION) condition = TRUE; + if (usages[i] == PID_USAGE_ET_CONSTANT_FORCE) + envelope = constant_force = TRUE; }
if (periodic && !hid_descriptor_add_set_periodic(iface)) @@ -841,6 +884,8 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co return FALSE; if (condition && !hid_descriptor_add_set_condition(iface)) return FALSE; + if (constant_force && !hid_descriptor_add_set_constant_force(iface)) + return FALSE;
/* HID nary collection indexes start at 1 */ memcpy(iface->hid_physical.effect_types + 1, usages, count * sizeof(*usages)); @@ -1026,6 +1071,17 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC condition->dead_band = report->dead_band; } } + else if (packet->reportId == physical->set_constant_force_report) + { + struct pid_set_constant_force *report = (struct pid_set_constant_force *)(packet->reportBuffer + 1); + struct effect_params *params = iface->hid_physical.effect_params + report->index; + + io->Information = sizeof(*report) + 1; + if (packet->reportBufferLen < io->Information) + io->Status = STATUS_BUFFER_TOO_SMALL; + else + params->constant_force.magnitude = report->magnitude; + } else { io->Information = 0; diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index f8c27a73b73..bd0e3272593 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -55,6 +55,11 @@ struct effect_condition BYTE dead_band; };
+struct effect_constant_force +{ + UINT16 magnitude; +}; + struct effect_params { USAGE effect_type; @@ -74,6 +79,7 @@ struct effect_params { struct effect_periodic periodic; struct effect_condition condition[2]; + struct effect_constant_force constant_force; }; };
@@ -149,6 +155,7 @@ struct hid_physical BYTE set_periodic_report; BYTE set_envelope_report; BYTE set_condition_report; + BYTE set_constant_force_report; };
struct hid_device_state