From c263fea14fa13273763a1518f48561157f30b880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Fri, 8 Oct 2021 09:50:24 +0200 Subject: [PATCH] winebus.sys: Add a PID set condition output report. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RĂ©mi Bernon Signed-off-by: Alexandre Julliard --- dlls/winebus.sys/bus_sdl.c | 30 ++++++++++- dlls/winebus.sys/bus_udev.c | 23 ++++++++- dlls/winebus.sys/hid.c | 91 +++++++++++++++++++++++++++++++++ dlls/winebus.sys/unix_private.h | 13 +++++ 4 files changed, 155 insertions(+), 2 deletions(-) diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 78de600fda6..36efd5cc850 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -208,6 +208,10 @@ static BOOL descriptor_add_haptic(struct sdl_device *impl) if (impl->effect_support & SDL_HAPTIC_TRIANGLE) usages[count++] = PID_USAGE_ET_TRIANGLE; if (impl->effect_support & SDL_HAPTIC_SAWTOOTHUP) usages[count++] = PID_USAGE_ET_SAWTOOTH_UP; if (impl->effect_support & SDL_HAPTIC_SAWTOOTHDOWN) usages[count++] = PID_USAGE_ET_SAWTOOTH_DOWN; + if (impl->effect_support & SDL_HAPTIC_SPRING) usages[count++] = PID_USAGE_ET_SPRING; + 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 (!hid_device_add_physical(&impl->unix_device, usages, count)) return FALSE; @@ -562,7 +566,31 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT case PID_USAGE_ET_DAMPER: case PID_USAGE_ET_INERTIA: case PID_USAGE_ET_FRICTION: - FIXME("not implemented!"); + effect.condition.length = params->duration; + effect.condition.delay = params->start_delay; + effect.condition.button = params->trigger_button; + effect.condition.interval = params->trigger_repeat_interval; + effect.condition.direction.type = SDL_HAPTIC_SPHERICAL; + effect.condition.direction.dir[0] = params->direction[0] * 36000 / 256; + effect.condition.direction.dir[1] = params->direction[1] * 36000 / 256; + if (params->condition_count >= 1) + { + effect.condition.right_sat[0] = params->condition[0].positive_saturation; + effect.condition.left_sat[0] = params->condition[0].negative_saturation; + effect.condition.right_coeff[0] = params->condition[0].positive_coefficient; + effect.condition.left_coeff[0] = params->condition[0].negative_coefficient; + effect.condition.deadband[0] = params->condition[0].dead_band; + effect.condition.center[0] = params->condition[0].center_point_offset; + } + if (params->condition_count >= 2) + { + effect.condition.right_sat[1] = params->condition[1].positive_saturation; + effect.condition.left_sat[1] = params->condition[1].negative_saturation; + effect.condition.right_coeff[1] = params->condition[1].positive_coefficient; + effect.condition.left_coeff[1] = params->condition[1].negative_coefficient; + effect.condition.deadband[1] = params->condition[1].dead_band; + effect.condition.center[1] = params->condition[1].center_point_offset; + } break; case PID_USAGE_ET_CONSTANT_FORCE: diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index 8a47b232148..251c74574af 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -672,6 +672,10 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d if (test_bit(ffbits, FF_TRIANGLE)) usages[count++] = PID_USAGE_ET_TRIANGLE; if (test_bit(ffbits, FF_SAW_UP)) usages[count++] = PID_USAGE_ET_SAWTOOTH_UP; if (test_bit(ffbits, FF_SAW_DOWN)) usages[count++] = PID_USAGE_ET_SAWTOOTH_DOWN; + if (test_bit(ffbits, FF_SPRING)) usages[count++] = PID_USAGE_ET_SPRING; + 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 (!hid_device_add_physical(iface, usages, count)) return STATUS_NO_MEMORY; @@ -1014,7 +1018,24 @@ static NTSTATUS lnxev_device_physical_effect_update(struct unix_device *iface, B case PID_USAGE_ET_DAMPER: case PID_USAGE_ET_INERTIA: case PID_USAGE_ET_FRICTION: - FIXME("not implemented!"); + if (params->condition_count >= 1) + { + effect.u.condition[0].right_saturation = params->condition[0].positive_saturation; + effect.u.condition[0].left_saturation = params->condition[0].negative_saturation; + effect.u.condition[0].right_coeff = params->condition[0].positive_coefficient; + effect.u.condition[0].left_coeff = params->condition[0].negative_coefficient; + effect.u.condition[0].deadband = params->condition[0].dead_band; + effect.u.condition[0].center = params->condition[0].center_point_offset; + } + if (params->condition_count >= 2) + { + effect.u.condition[1].right_saturation = params->condition[1].positive_saturation; + effect.u.condition[1].left_saturation = params->condition[1].negative_saturation; + effect.u.condition[1].right_coeff = params->condition[1].positive_coefficient; + effect.u.condition[1].left_coeff = params->condition[1].negative_coefficient; + effect.u.condition[1].deadband = params->condition[1].dead_band; + effect.u.condition[1].center = params->condition[1].center_point_offset; + } break; case PID_USAGE_ET_CONSTANT_FORCE: diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index c25558a5ac4..1cd9cf82d68 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -458,6 +458,18 @@ struct pid_set_envelope UINT16 attack_time; UINT16 fade_time; }; + +struct pid_set_condition +{ + BYTE index; + BYTE condition_index; + BYTE center_point_offset; + BYTE positive_coefficient; + BYTE negative_coefficient; + BYTE positive_saturation; + BYTE negative_saturation; + BYTE dead_band; +}; #include "poppack.h" static BOOL hid_descriptor_add_set_periodic(struct unix_device *iface) @@ -577,6 +589,52 @@ static BOOL hid_descriptor_add_set_envelope(struct unix_device *iface) return hid_report_descriptor_append(desc, template, sizeof(template)); } +static BOOL hid_descriptor_add_set_condition(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[] = + { + /* Condition Report Definition */ + USAGE(1, PID_USAGE_SET_CONDITION_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_CP_OFFSET), + USAGE(1, PID_USAGE_POSITIVE_COEFFICIENT), + USAGE(1, PID_USAGE_NEGATIVE_COEFFICIENT), + LOGICAL_MINIMUM(1, -128), + LOGICAL_MAXIMUM(1, +127), + PHYSICAL_MINIMUM(2, -10000), + PHYSICAL_MAXIMUM(2, +10000), + REPORT_SIZE(1, 8), + REPORT_COUNT(1, 3), + OUTPUT(1, Data|Var|Abs), + + USAGE(1, PID_USAGE_POSITIVE_SATURATION), + USAGE(1, PID_USAGE_NEGATIVE_SATURATION), + USAGE(1, PID_USAGE_DEAD_BAND), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(2, 0x00ff), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(2, +10000), + REPORT_SIZE(1, 8), + REPORT_COUNT(1, 3), + OUTPUT(1, Data|Var|Abs), + END_COLLECTION, + }; + + iface->hid_physical.set_condition_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; @@ -729,6 +787,7 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co }; BOOL periodic = FALSE; BOOL envelope = FALSE; + BOOL condition = FALSE; ULONG i; if (!hid_report_descriptor_append(desc, device_control_header, sizeof(device_control_header))) @@ -769,12 +828,19 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co usages[i] == PID_USAGE_ET_SAWTOOTH_UP || usages[i] == PID_USAGE_ET_SAWTOOTH_DOWN) periodic = envelope = TRUE; + if (usages[i] == PID_USAGE_ET_SPRING || + usages[i] == PID_USAGE_ET_DAMPER || + usages[i] == PID_USAGE_ET_INERTIA || + usages[i] == PID_USAGE_ET_FRICTION) + condition = TRUE; } if (periodic && !hid_descriptor_add_set_periodic(iface)) return FALSE; if (envelope && !hid_descriptor_add_set_envelope(iface)) return FALSE; + if (condition && !hid_descriptor_add_set_condition(iface)) + return FALSE; /* HID nary collection indexes start at 1 */ memcpy(iface->hid_physical.effect_types + 1, usages, count * sizeof(*usages)); @@ -901,6 +967,8 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC params->direction[1] = report->direction[1]; io->Status = iface->hid_vtbl->physical_effect_update(iface, report->index, params); + + params->condition_count = 0; } } else if (packet->reportId == physical->set_periodic_report) @@ -935,6 +1003,29 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC params->envelope.fade_time = report->fade_time; } } + else if (packet->reportId == physical->set_condition_report) + { + struct pid_set_condition *report = (struct pid_set_condition *)(packet->reportBuffer + 1); + struct effect_params *params = iface->hid_physical.effect_params + report->index; + struct effect_condition *condition; + UINT index; + + io->Information = sizeof(*report) + 1; + if (packet->reportBufferLen < io->Information) + io->Status = STATUS_BUFFER_TOO_SMALL; + else if ((index = params->condition_count++) >= ARRAY_SIZE(params->condition)) + io->Status = STATUS_INVALID_PARAMETER; + else + { + condition = params->condition + index; + condition->center_point_offset = report->center_point_offset; + condition->positive_coefficient = report->positive_coefficient; + condition->negative_coefficient = report->negative_coefficient; + condition->positive_saturation = report->positive_saturation; + condition->negative_saturation = report->negative_saturation; + condition->dead_band = report->dead_band; + } + } else { io->Information = 0; diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index 71e6716c7fa..f8c27a73b73 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -45,6 +45,16 @@ struct effect_envelope UINT16 fade_time; }; +struct effect_condition +{ + BYTE center_point_offset; + BYTE positive_coefficient; + BYTE negative_coefficient; + BYTE positive_saturation; + BYTE negative_saturation; + BYTE dead_band; +}; + struct effect_params { USAGE effect_type; @@ -57,11 +67,13 @@ struct effect_params BOOL axis_enabled[2]; BOOL direction_enabled; BYTE direction[2]; + BYTE condition_count; /* only for periodic, constant or ramp forces */ struct effect_envelope envelope; union { struct effect_periodic periodic; + struct effect_condition condition[2]; }; }; @@ -136,6 +148,7 @@ struct hid_physical BYTE effect_update_report; BYTE set_periodic_report; BYTE set_envelope_report; + BYTE set_condition_report; }; struct hid_device_state