From: Ivo Ivanov logos128@gmail.com
Fixes improper interpretation of the condition output reports.
Signed-off-by: Ivo Ivanov logos128@gmail.com Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/hid.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index 6f22e0e81d8..d9523324ae1 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -625,6 +625,13 @@ static BOOL hid_descriptor_add_set_condition(struct unix_device *iface) REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs),
+ USAGE(1, PID_USAGE_PARAMETER_BLOCK_OFFSET), + LOGICAL_MINIMUM(1, 0x00), + LOGICAL_MAXIMUM(1, 0x01), + 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),
Instead of packet length, which may be larger than the last report buffer.
Based on a patch from Ivo Ivanov logos128@gmail.com.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/main.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/dlls/winebus.sys/main.c b/dlls/winebus.sys/main.c index c9a18313853..d805f887a6f 100644 --- a/dlls/winebus.sys/main.c +++ b/dlls/winebus.sys/main.c @@ -82,7 +82,7 @@ struct device_extension ULONG report_desc_length; HIDP_DEVICE_DESC collection_desc;
- BYTE *last_reports[256]; + struct hid_report *last_reports[256]; struct list reports; IRP *pending_read;
@@ -432,7 +432,7 @@ static void process_hid_report(DEVICE_OBJECT *device, BYTE *report_buf, DWORD re { struct device_extension *ext = (struct device_extension *)device->DeviceExtension; ULONG size = offsetof(struct hid_report, buffer[report_len]); - struct hid_report *report; + struct hid_report *report, *last_report; IRP *irp;
if (!(report = RtlAllocateHeap(GetProcessHeap(), 0, size))) return; @@ -442,8 +442,11 @@ static void process_hid_report(DEVICE_OBJECT *device, BYTE *report_buf, DWORD re RtlEnterCriticalSection(&ext->cs); list_add_tail(&ext->reports, &report->entry);
- if (!ext->collection_desc.ReportIDs[0].ReportID) memcpy(ext->last_reports[0], report_buf, report_len); - else memcpy(ext->last_reports[report_buf[0]], report_buf, report_len); + if (!ext->collection_desc.ReportIDs[0].ReportID) last_report = ext->last_reports[0]; + else last_report = ext->last_reports[report_buf[0]]; + + last_report->length = report_len; + memcpy(last_report->buffer, report_buf, report_len);
if ((irp = pop_pending_read(ext))) { @@ -857,6 +860,7 @@ static NTSTATUS pdo_pnp_dispatch(DEVICE_OBJECT *device, IRP *irp) for (i = 0; i < ext->collection_desc.ReportIDsLength; ++i) { if (!(size = reports[i].InputLength)) continue; + size = offsetof( struct hid_report, buffer[size] ); if (!(ext->last_reports[reports[i].ReportID] = RtlAllocateHeap(GetProcessHeap(), 0, size))) status = STATUS_NO_MEMORY; } if (!status) ext->state = DEVICE_STATE_STARTED; @@ -1035,7 +1039,9 @@ static NTSTATUS WINAPI hid_internal_dispatch(DEVICE_OBJECT *device, IRP *irp) case IOCTL_HID_GET_INPUT_REPORT: { HID_XFER_PACKET *packet = (HID_XFER_PACKET *)irp->UserBuffer; - memcpy(packet->reportBuffer, ext->last_reports[packet->reportId], packet->reportBufferLen); + struct hid_report *last_report = ext->last_reports[packet->reportId]; + memcpy(packet->reportBuffer, last_report->buffer, last_report->length); + packet->reportBufferLen = last_report->length; irp->IoStatus.Information = packet->reportBufferLen; irp->IoStatus.Status = STATUS_SUCCESS; if (TRACE_ON(hid))
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/hid.c | 8 -------- dlls/winebus.sys/unix_private.h | 1 - 2 files changed, 9 deletions(-)
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index d9523324ae1..89bc4904fac 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -440,7 +440,6 @@ struct pid_effect_update UINT16 trigger_repeat_interval; UINT16 sample_period; UINT16 start_delay; - BYTE gain; BYTE trigger_button; BYTE enable_bits; BYTE direction[2]; @@ -851,12 +850,6 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co UNIT_EXPONENT(1, 0), UNIT(1, 0), /* None */
- USAGE(1, PID_USAGE_GAIN), - LOGICAL_MAXIMUM(1, 0x7f), - REPORT_SIZE(1, 8), - REPORT_COUNT(1, 1), - OUTPUT(1, Data|Var|Abs), - USAGE(1, PID_USAGE_TRIGGER_BUTTON), LOGICAL_MAXIMUM(2, state->button_count), REPORT_SIZE(1, 8), @@ -1093,7 +1086,6 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC params->trigger_repeat_interval = report->trigger_repeat_interval; params->sample_period = report->sample_period; params->start_delay = report->start_delay; - params->gain = report->gain; params->trigger_button = report->trigger_button == 0xff ? 0 : report->trigger_button; params->axis_enabled[0] = (report->enable_bits & 1) != 0; params->axis_enabled[1] = (report->enable_bits & 2) != 0; diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index ef574e48cee..0315deca35d 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -73,7 +73,6 @@ struct effect_params UINT16 trigger_repeat_interval; UINT16 sample_period; UINT16 start_delay; - BYTE gain; BYTE trigger_button; BOOL axis_enabled[2]; BOOL direction_enabled;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 70c761267f7..11ba9867623 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -676,8 +676,12 @@ static void set_report_value( struct hid_joystick *impl, char *report_buf, phy_min = caps->physical_min; phy_max = caps->physical_max;
- if (value > phy_max || value < phy_min) value = -1; - else value = log_min + (value - phy_min) * (log_max - log_min) / (phy_max - phy_min); + if (phy_max || phy_min) + { + if (value > phy_max || value < phy_min) value = -1; + else value = log_min + (value - phy_min) * (log_max - log_min) / (phy_max - phy_min); + } + status = HidP_SetUsageValue( HidP_Output, caps->usage_page, caps->link_collection, caps->usage_min, value, preparsed, report_buf, report_len ); if (status != HIDP_STATUS_SUCCESS) WARN( "HidP_SetUsageValue %04x:%04x returned %#x\n",
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 24 +++--- dlls/winebus.sys/bus_udev.c | 12 +-- dlls/winebus.sys/hid.c | 142 +++++++++++++++----------------- dlls/winebus.sys/unix_private.h | 32 +++---- dlls/winebus.sys/unixlib.c | 4 +- 5 files changed, 104 insertions(+), 110 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 220e360d78f..e3932e31ff5 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -480,13 +480,13 @@ static NTSTATUS sdl_device_physical_device_control(struct unix_device *iface, US return STATUS_NOT_SUPPORTED; }
-static NTSTATUS sdl_device_physical_device_set_gain(struct unix_device *iface, BYTE value) +static NTSTATUS sdl_device_physical_device_set_gain(struct unix_device *iface, BYTE percent) { struct sdl_device *impl = impl_from_unix_device(iface);
- TRACE("iface %p, value %#x.\n", iface, value); + TRACE("iface %p, percent %#x.\n", iface, percent);
- pSDL_HapticSetGain(impl->sdl_haptic, value * 100 / 255); + pSDL_HapticSetGain(impl->sdl_haptic, percent);
return STATUS_SUCCESS; } @@ -583,10 +583,10 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT effect.periodic.button = params->trigger_button; effect.periodic.interval = params->trigger_repeat_interval; effect.periodic.direction.type = SDL_HAPTIC_SPHERICAL; - effect.periodic.direction.dir[0] = params->direction[0] * 36000 / 256; - effect.periodic.direction.dir[1] = params->direction[1] * 36000 / 256; + effect.periodic.direction.dir[0] = params->direction[0]; + effect.periodic.direction.dir[1] = params->direction[1]; effect.periodic.period = params->periodic.period; - effect.periodic.magnitude = params->periodic.magnitude * 128; + effect.periodic.magnitude = params->periodic.magnitude; effect.periodic.offset = params->periodic.offset; effect.periodic.phase = params->periodic.phase; effect.periodic.attack_length = params->envelope.attack_time; @@ -604,8 +604,8 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT 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; + effect.condition.direction.dir[0] = params->direction[0]; + effect.condition.direction.dir[1] = params->direction[1]; if (params->condition_count >= 1) { effect.condition.right_sat[0] = params->condition[0].positive_saturation; @@ -632,8 +632,8 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT 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.direction.dir[0] = params->direction[0]; + effect.constant.direction.dir[1] = params->direction[1]; effect.constant.level = params->constant_force.magnitude; effect.constant.attack_length = params->envelope.attack_time; effect.constant.attack_level = params->envelope.attack_level; @@ -647,8 +647,8 @@ static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYT effect.ramp.button = params->trigger_button; effect.ramp.interval = params->trigger_repeat_interval; effect.ramp.direction.type = SDL_HAPTIC_SPHERICAL; - effect.ramp.direction.dir[0] = params->direction[0] * 36000 / 256; - effect.ramp.direction.dir[1] = params->direction[1] * 36000 / 256; + effect.ramp.direction.dir[0] = params->direction[0]; + effect.ramp.direction.dir[1] = params->direction[1]; effect.ramp.start = params->ramp_force.ramp_start; effect.ramp.end = params->ramp_force.ramp_end; effect.ramp.attack_length = params->envelope.attack_time; diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index d7bbd5ba79d..3a7a5db723d 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -924,17 +924,17 @@ static NTSTATUS lnxev_device_physical_device_control(struct unix_device *iface, return STATUS_NOT_SUPPORTED; }
-static NTSTATUS lnxev_device_physical_device_set_gain(struct unix_device *iface, BYTE value) +static NTSTATUS lnxev_device_physical_device_set_gain(struct unix_device *iface, BYTE percent) { struct lnxev_device *impl = lnxev_impl_from_unix_device(iface); struct input_event ie = { .type = EV_FF, .code = FF_GAIN, - .value = value * 100 / 255, + .value = percent, };
- TRACE("iface %p, value %#x.\n", iface, value); + TRACE("iface %p, percent %#x.\n", iface, percent);
if (write(impl->base.device_fd, &ie, sizeof(ie)) == -1) WARN("write failed %d %s\n", errno, strerror(errno)); @@ -1031,7 +1031,7 @@ static NTSTATUS lnxev_device_physical_effect_update(struct unix_device *iface, B effect.trigger.button = params->trigger_button; effect.trigger.interval = params->trigger_repeat_interval; /* only supports polar with one direction angle */ - effect.direction = params->direction[0] * 256; + effect.direction = params->direction[0] * 0x800 / 1125;
switch (params->effect_type) { @@ -1041,9 +1041,9 @@ static NTSTATUS lnxev_device_physical_effect_update(struct unix_device *iface, B case PID_USAGE_ET_SAWTOOTH_UP: case PID_USAGE_ET_SAWTOOTH_DOWN: effect.u.periodic.period = params->periodic.period; - effect.u.periodic.magnitude = params->periodic.magnitude * 128; + effect.u.periodic.magnitude = params->periodic.magnitude; effect.u.periodic.offset = params->periodic.offset; - effect.u.periodic.phase = params->periodic.phase; + effect.u.periodic.phase = params->periodic.phase * 0x800 / 1125; effect.u.periodic.envelope.attack_length = params->envelope.attack_time; effect.u.periodic.envelope.attack_level = params->envelope.attack_level; effect.u.periodic.envelope.fade_length = params->envelope.fade_time; diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index 89bc4904fac..56f30338481 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -170,8 +170,6 @@ BOOL hid_device_add_buttons(struct unix_device *iface, USAGE usage_page, USAGE u USAGE_MAXIMUM(2, usage_max), LOGICAL_MINIMUM(1, 0), LOGICAL_MAXIMUM(1, 1), - PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(1, 1), REPORT_COUNT(2, count), REPORT_SIZE(1, 1), INPUT(1, Data|Var|Abs), @@ -225,8 +223,6 @@ BOOL hid_device_add_hatswitch(struct unix_device *iface, INT count) USAGE(1, HID_USAGE_GENERIC_HATSWITCH), LOGICAL_MINIMUM(1, 1), LOGICAL_MAXIMUM(1, 8), - PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(2, 8), REPORT_SIZE(1, 8), REPORT_COUNT(4, count), UNIT(1, 0x0e /* none */), @@ -286,8 +282,6 @@ BOOL hid_device_add_axes(struct unix_device *iface, BYTE count, USAGE usage_page { LOGICAL_MINIMUM(4, min), LOGICAL_MAXIMUM(4, max), - PHYSICAL_MINIMUM(4, min), - PHYSICAL_MAXIMUM(4, max), REPORT_SIZE(1, 32), REPORT_COUNT(1, count), INPUT(1, Data|Var|(rel ? Rel : Abs)), @@ -354,8 +348,6 @@ BOOL hid_device_add_haptics(struct unix_device *iface) UNIT_EXPONENT(1, -3), /* 10^-3 */ LOGICAL_MINIMUM(4, 0x00000000), LOGICAL_MAXIMUM(4, 0x7fffffff), - PHYSICAL_MINIMUM(4, 0x00000000), - PHYSICAL_MAXIMUM(4, 0x7fffffff), REPORT_SIZE(1, 32), REPORT_COUNT(1, 1), FEATURE(1, Data|Var|Abs), @@ -367,8 +359,6 @@ BOOL hid_device_add_haptics(struct unix_device *iface) USAGE(1, HID_USAGE_HAPTICS_MANUAL_TRIGGER), LOGICAL_MINIMUM(1, 1), LOGICAL_MAXIMUM(1, 4), - PHYSICAL_MINIMUM(1, 1), - PHYSICAL_MAXIMUM(1, 4), REPORT_SIZE(1, 16), REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs), @@ -376,8 +366,6 @@ BOOL hid_device_add_haptics(struct unix_device *iface) USAGE(1, HID_USAGE_HAPTICS_INTENSITY), LOGICAL_MINIMUM(4, 0x00000000), LOGICAL_MAXIMUM(4, 0x0000ffff), - PHYSICAL_MINIMUM(4, 0x00000000), - PHYSICAL_MAXIMUM(4, 0x0000ffff), REPORT_SIZE(1, 16), REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs), @@ -442,23 +430,23 @@ struct pid_effect_update UINT16 start_delay; BYTE trigger_button; BYTE enable_bits; - BYTE direction[2]; + UINT16 direction[2]; };
struct pid_set_periodic { BYTE index; - BYTE magnitude; - BYTE offset; - BYTE phase; + UINT16 magnitude; + INT16 offset; + UINT16 phase; UINT16 period; };
struct pid_set_envelope { BYTE index; - BYTE attack_level; - BYTE fade_level; + UINT16 attack_level; + UINT16 fade_level; UINT16 attack_time; UINT16 fade_time; }; @@ -467,25 +455,25 @@ 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; + INT16 center_point_offset; + INT16 positive_coefficient; + INT16 negative_coefficient; + UINT16 positive_saturation; + UINT16 negative_saturation; + UINT16 dead_band; };
struct pid_set_constant_force { BYTE index; - UINT16 magnitude; + INT16 magnitude; };
struct pid_set_ramp_force { BYTE index; - BYTE ramp_start; - BYTE ramp_end; + INT16 ramp_start; + INT16 ramp_end; }; #include "poppack.h"
@@ -501,38 +489,40 @@ static BOOL hid_descriptor_add_set_periodic(struct unix_device *iface) REPORT_ID(1, report_id),
USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX), + LOGICAL_MINIMUM(1, 0), 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(1, 0), - LOGICAL_MAXIMUM(2, 0x00ff), + LOGICAL_MAXIMUM(2, 0x7fff), PHYSICAL_MINIMUM(1, 0), PHYSICAL_MAXIMUM(2, 10000), - REPORT_SIZE(1, 8), + REPORT_SIZE(1, 16), REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 0),
USAGE(1, PID_USAGE_OFFSET), - LOGICAL_MINIMUM(1, 0x80), - LOGICAL_MAXIMUM(1, 0x7f), + LOGICAL_MINIMUM(2, 0x8000), + LOGICAL_MAXIMUM(2, 0x7fff), PHYSICAL_MINIMUM(2, -10000), - PHYSICAL_MAXIMUM(2, 10000), - REPORT_SIZE(1, 8), + PHYSICAL_MAXIMUM(2, +10000), + REPORT_SIZE(1, 16), REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 0),
USAGE(1, PID_USAGE_PHASE), UNIT(1, 0x14), /* Eng Rot:Angular Pos */ UNIT_EXPONENT(1, -2), LOGICAL_MINIMUM(1, 0), - LOGICAL_MAXIMUM(2, 0xff), - PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(4, 36000), - REPORT_SIZE(1, 8), + LOGICAL_MAXIMUM(4, 36000), + REPORT_SIZE(1, 16), REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs),
@@ -541,13 +531,10 @@ static BOOL hid_descriptor_add_set_periodic(struct unix_device *iface) UNIT_EXPONENT(1, -3), /* 10^-3 */ LOGICAL_MINIMUM(1, 0), LOGICAL_MAXIMUM(2, 0x7fff), - PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(2, 0x7fff), REPORT_SIZE(1, 16), REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs),
- PHYSICAL_MAXIMUM(1, 0), UNIT_EXPONENT(1, 0), UNIT(1, 0), /* None */ END_COLLECTION, @@ -569,30 +556,30 @@ static BOOL hid_descriptor_add_set_envelope(struct unix_device *iface) REPORT_ID(1, report_id),
USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX), + LOGICAL_MINIMUM(1, 0), 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_ATTACK_LEVEL), USAGE(1, PID_USAGE_FADE_LEVEL), - LOGICAL_MINIMUM(1, 0x00), - LOGICAL_MAXIMUM(2, 0x00ff), + LOGICAL_MINIMUM(1, 0), + LOGICAL_MAXIMUM(2, 0x7fff), PHYSICAL_MINIMUM(1, 0), PHYSICAL_MAXIMUM(2, 10000), - REPORT_SIZE(1, 8), + REPORT_SIZE(1, 16), REPORT_COUNT(1, 2), OUTPUT(1, Data|Var|Abs), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 0),
USAGE(1, PID_USAGE_ATTACK_TIME), USAGE(1, PID_USAGE_FADE_TIME), UNIT(2, 0x1003), /* Eng Lin:Time */ UNIT_EXPONENT(1, -3), - LOGICAL_MINIMUM(1, 0x00), + LOGICAL_MINIMUM(1, 0), LOGICAL_MAXIMUM(2, 0x7fff), - PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(2, 0x7fff), REPORT_SIZE(1, 16), REPORT_COUNT(1, 2), OUTPUT(1, Data|Var|Abs), @@ -618,8 +605,8 @@ static BOOL hid_descriptor_add_set_condition(struct unix_device *iface) REPORT_ID(1, report_id),
USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX), + LOGICAL_MINIMUM(1, 0), LOGICAL_MAXIMUM(1, 0x7f), - LOGICAL_MINIMUM(1, 0x00), REPORT_SIZE(1, 8), REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs), @@ -634,24 +621,28 @@ static BOOL hid_descriptor_add_set_condition(struct unix_device *iface) 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), + LOGICAL_MINIMUM(2, 0x8000), + LOGICAL_MAXIMUM(2, 0x7fff), PHYSICAL_MINIMUM(2, -10000), PHYSICAL_MAXIMUM(2, +10000), - REPORT_SIZE(1, 8), + REPORT_SIZE(1, 16), REPORT_COUNT(1, 3), OUTPUT(1, Data|Var|Abs), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 0),
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), + LOGICAL_MAXIMUM(2, 0x7fff), PHYSICAL_MINIMUM(1, 0), PHYSICAL_MAXIMUM(2, +10000), - REPORT_SIZE(1, 8), + REPORT_SIZE(1, 16), REPORT_COUNT(1, 3), OUTPUT(1, Data|Var|Abs), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 0), END_COLLECTION, };
@@ -671,20 +662,22 @@ static BOOL hid_descriptor_add_set_constant_force(struct unix_device *iface) REPORT_ID(1, report_id),
USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX), + LOGICAL_MINIMUM(1, 0), 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), + LOGICAL_MINIMUM(2, 0x8000), + LOGICAL_MAXIMUM(2, 0x7fff), + PHYSICAL_MINIMUM(2, -10000), + PHYSICAL_MAXIMUM(2, +10000), REPORT_SIZE(1, 16), REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 0), END_COLLECTION, };
@@ -704,21 +697,23 @@ static BOOL hid_descriptor_add_set_ramp_force(struct unix_device *iface) REPORT_ID(1, report_id),
USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX), + LOGICAL_MINIMUM(1, 0), 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_RAMP_START), USAGE(1, PID_USAGE_RAMP_END), - LOGICAL_MINIMUM(1, 0x80), - LOGICAL_MAXIMUM(1, 0x7f), + LOGICAL_MINIMUM(2, 0x8000), + LOGICAL_MAXIMUM(2, 0x7fff), PHYSICAL_MINIMUM(2, -10000), PHYSICAL_MAXIMUM(2, +10000), - REPORT_SIZE(1, 8), + REPORT_SIZE(1, 16), REPORT_COUNT(1, 2), OUTPUT(1, Data|Var|Abs), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 0), END_COLLECTION, };
@@ -762,12 +757,14 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co
USAGE(1, PID_USAGE_DEVICE_GAIN), LOGICAL_MINIMUM(1, 0), - LOGICAL_MAXIMUM(2, 0x00ff), + LOGICAL_MAXIMUM(1, 100), PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(2, 0x2710), + PHYSICAL_MAXIMUM(2, 10000), REPORT_SIZE(1, 8), REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs), + PHYSICAL_MINIMUM(1, 0), + PHYSICAL_MAXIMUM(1, 0), END_COLLECTION, };
@@ -780,8 +777,8 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co REPORT_ID(1, effect_control_report),
USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX), + LOGICAL_MINIMUM(1, 0), LOGICAL_MAXIMUM(1, 0x7f), - LOGICAL_MINIMUM(1, 0x00), REPORT_SIZE(1, 8), REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs), @@ -816,8 +813,8 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co REPORT_ID(1, effect_update_report),
USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX), + LOGICAL_MINIMUM(1, 0), LOGICAL_MAXIMUM(1, 0x7f), - LOGICAL_MINIMUM(1, 0x00), REPORT_SIZE(1, 8), REPORT_COUNT(1, 1), OUTPUT(1, Data|Var|Abs), @@ -841,16 +838,14 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co UNIT_EXPONENT(1, -3), /* 10^-3 */ LOGICAL_MINIMUM(1, 0), LOGICAL_MAXIMUM(2, 0x7fff), - PHYSICAL_MINIMUM(1, 0), - PHYSICAL_MAXIMUM(2, 0x7fff), REPORT_SIZE(1, 16), REPORT_COUNT(1, 4), OUTPUT(1, Data|Var|Abs), - PHYSICAL_MAXIMUM(1, 0), UNIT_EXPONENT(1, 0), UNIT(1, 0), /* None */
USAGE(1, PID_USAGE_TRIGGER_BUTTON), + LOGICAL_MINIMUM(1, 0), LOGICAL_MAXIMUM(2, state->button_count), REPORT_SIZE(1, 8), REPORT_COUNT(1, 1), @@ -860,6 +855,7 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co COLLECTION(1, Logical), USAGE(4, (HID_USAGE_PAGE_GENERIC<<16)|HID_USAGE_GENERIC_X), USAGE(4, (HID_USAGE_PAGE_GENERIC<<16)|HID_USAGE_GENERIC_Y), + LOGICAL_MINIMUM(1, 0), LOGICAL_MAXIMUM(1, 1), REPORT_SIZE(1, 1), REPORT_COUNT(1, 2), @@ -878,13 +874,11 @@ BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT co UNIT(1, 0x14), /* Eng Rot:Angular Pos */ UNIT_EXPONENT(1, -2), LOGICAL_MINIMUM(1, 0), - LOGICAL_MAXIMUM(2, 0x00ff), - PHYSICAL_MAXIMUM(4, 36000), - REPORT_SIZE(1, 8), + LOGICAL_MAXIMUM(4, 36000), + REPORT_SIZE(1, 16), REPORT_COUNT(1, 2), OUTPUT(1, Data|Var|Abs), END_COLLECTION, - PHYSICAL_MAXIMUM(1, 0), UNIT_EXPONENT(1, 0), UNIT(1, 0), /* None */ END_COLLECTION, diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index 0315deca35d..10784652a2b 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -31,39 +31,39 @@
struct effect_periodic { - BYTE magnitude; - BYTE offset; - BYTE phase; + UINT16 magnitude; + INT16 offset; + UINT16 phase; UINT16 period; };
struct effect_envelope { - BYTE attack_level; - BYTE fade_level; + UINT16 attack_level; + UINT16 fade_level; UINT16 attack_time; 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; + INT16 center_point_offset; + INT16 positive_coefficient; + INT16 negative_coefficient; + UINT16 positive_saturation; + UINT16 negative_saturation; + UINT16 dead_band; };
struct effect_constant_force { - UINT16 magnitude; + INT16 magnitude; };
struct effect_ramp_force { - BYTE ramp_start; - BYTE ramp_end; + INT16 ramp_start; + INT16 ramp_end; };
struct effect_params @@ -76,7 +76,7 @@ struct effect_params BYTE trigger_button; BOOL axis_enabled[2]; BOOL direction_enabled; - BYTE direction[2]; + UINT16 direction[2]; BYTE condition_count; /* only for periodic, constant or ramp forces */ struct effect_envelope envelope; @@ -108,7 +108,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_device_set_gain)(struct unix_device *iface, BYTE value); + NTSTATUS (*physical_device_set_gain)(struct unix_device *iface, BYTE percent); NTSTATUS (*physical_effect_control)(struct unix_device *iface, BYTE index, USAGE control, BYTE iterations); NTSTATUS (*physical_effect_update)(struct unix_device *iface, BYTE index, struct effect_params *params); }; diff --git a/dlls/winebus.sys/unixlib.c b/dlls/winebus.sys/unixlib.c index 9d819bab7e3..1269ae05c2b 100644 --- a/dlls/winebus.sys/unixlib.c +++ b/dlls/winebus.sys/unixlib.c @@ -106,7 +106,7 @@ static NTSTATUS mouse_physical_device_control(struct unix_device *iface, USAGE c return STATUS_NOT_SUPPORTED; }
-static NTSTATUS mouse_physical_device_set_gain(struct unix_device *iface, BYTE value) +static NTSTATUS mouse_physical_device_set_gain(struct unix_device *iface, BYTE percent) { return STATUS_NOT_SUPPORTED; } @@ -189,7 +189,7 @@ static NTSTATUS keyboard_physical_device_control(struct unix_device *iface, USAG return STATUS_NOT_SUPPORTED; }
-static NTSTATUS keyboard_physical_device_set_gain(struct unix_device *iface, BYTE value) +static NTSTATUS keyboard_physical_device_set_gain(struct unix_device *iface, BYTE percent) { return STATUS_NOT_SUPPORTED; }
From: Ivo Ivanov logos128@gmail.com
To correctly scale angle values and warn about unexpected units.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 11ba9867623..fb83d173bda 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -2596,6 +2596,18 @@ static void set_parameter_value( struct hid_joystick_effect *impl, char *report_ return set_report_value( impl->joystick, report_buf, caps, value ); }
+static void set_parameter_value_angle( struct hid_joystick_effect *impl, char *report_buf, + struct hid_value_caps *caps, LONG value ) +{ + LONG exp; + if (!caps) return; + exp = caps->units_exp; + if (caps->units != 0x14) WARN( "unknown angle unit caps %x\n", caps->units ); + else if (exp < -2) while (exp++ < -2) value *= 10; + else if (exp > -2) while (exp-- > -2) value /= 10; + set_parameter_value( impl, report_buf, caps, value ); +} + static void set_parameter_value_us( struct hid_joystick_effect *impl, char *report_buf, struct hid_value_caps *caps, LONG value ) { @@ -2766,7 +2778,7 @@ static HRESULT WINAPI hid_joystick_effect_Download( IDirectInputEffect *iface ) { tmp = directions[i] + (i == 0 ? 9000 : 0); caps = effect_update->direction_caps[effect_update->direction_count - i - 1]; - set_parameter_value( impl, impl->effect_update_buf, caps, tmp % 36000 ); + set_parameter_value_angle( impl, impl->effect_update_buf, caps, tmp % 36000 ); }
status = HidP_SetUsageValue( HidP_Output, HID_USAGE_PAGE_PID, 0, PID_USAGE_TRIGGER_BUTTON,
From: Ivo Ivanov logos128@gmail.com
What the tests show is actually that the direction should be set only if the corresponding axis is in the axis list.
Signed-off-by: Ivo Ivanov logos128@gmail.com Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 10 ++++---- dlls/dinput8/tests/hid.c | 48 +++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 8 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index fb83d173bda..0910c870762 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -1631,7 +1631,7 @@ static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *cap { SET_REPORT_ID( effect_update ); caps->physical_min = 0; - caps->physical_max = 36000 - 36000 / (caps->logical_max - caps->logical_min); + caps->physical_max = 35900; if (effect_update->direction_count >= 6) FIXME( "more than 6 PID directions detected\n" ); else effect_update->direction_caps[effect_update->direction_count] = caps; effect_update->direction_count++; @@ -1650,7 +1650,7 @@ static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *cap if (instance->wUsage == PID_USAGE_PHASE) { caps->physical_min = 0; - caps->physical_max = 36000 - 36000 / (caps->logical_max - caps->logical_min); + caps->physical_max = 35900; set_periodic->phase_caps = caps; } if (instance->wUsage == PID_USAGE_OFFSET) @@ -2078,11 +2078,12 @@ static void convert_directions_to_spherical( const DIEFFECT *in, DIEFFECT *out ) out->cAxes = in->cAxes; break; case DIEFF_SPHERICAL: - for (i = 0; i < in->cAxes; ++i) + for (i = 0; i < in->cAxes - 1; ++i) { out->rglDirection[i] = in->rglDirection[i] % 36000; if (out->rglDirection[i] < 0) out->rglDirection[i] += 36000; } + out->rglDirection[i] = 0; out->cAxes = in->cAxes; break; } @@ -2773,8 +2774,7 @@ static HRESULT WINAPI hid_joystick_effect_Download( IDirectInputEffect *iface ) spherical.rglDirection = directions; convert_directions_to_spherical( &impl->params, &spherical );
- if (!effect_update->direction_count) WARN( "no PID effect direction caps found\n" ); - else for (i = 0; i < spherical.cAxes - 1; ++i) + for (i = 0; i < min( effect_update->direction_count, spherical.cAxes ); ++i) { tmp = directions[i] + (i == 0 ? 9000 : 0); caps = effect_update->direction_caps[effect_update->direction_count - i - 1]; diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 9e21ccdb713..5d7416b0e4c 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -6461,10 +6461,27 @@ static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file, DW .code = IOCTL_HID_WRITE_REPORT, .report_id = 3, .report_len = 11, - .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x00,0x00}, + .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x3f,0x00}, }, }; struct hid_expect expect_create_2[] = + { + /* set condition */ + { + .code = IOCTL_HID_WRITE_REPORT, + .report_id = 7, + .report_len = 8, + .report_buf = {0x07,0x00,0x4c,0x3f,0xcc,0x4c,0x33,0x19}, + }, + /* update effect */ + { + .code = IOCTL_HID_WRITE_REPORT, + .report_id = 3, + .report_len = 11, + .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0xf1}, + }, + }; + struct hid_expect expect_create_3[] = { /* set condition */ { @@ -6488,10 +6505,11 @@ static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file, DW .report_len = 4, .report_buf = {0x02, 0x01, 0x03, 0x00}, }; - static const DWORD expect_axes[3] = { + static const DWORD expect_axes[3] = + { + DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFACTUATOR, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR, DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ) | DIDFT_FFACTUATOR, - DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFACTUATOR, }; static const LONG expect_directions[3] = { +3000, @@ -6642,6 +6660,10 @@ static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file, DW
desc = expect_desc; desc.cAxes = 3; + desc.rglDirection = directions; + desc.rglDirection[0] = +3000; + desc.rglDirection[1] = -2000; + desc.rglDirection[2] = +1000; desc.cbTypeSpecificParams = 1 * sizeof(DICONDITION); desc.lpvTypeSpecificParams = (void *)&expect_condition[1]; set_hid_expect( file, expect_create_2, sizeof(expect_create_2) ); @@ -6653,6 +6675,26 @@ static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file, DW ref = IDirectInputEffect_Release( effect ); ok( ref == 0, "Release returned %d\n", ref ); set_hid_expect( file, NULL, 0 ); + + desc = expect_desc; + desc.cAxes = 2; + desc.rgdwAxes = axes; + desc.rgdwAxes[0] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ) | DIDFT_FFACTUATOR; + desc.rgdwAxes[1] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR; + desc.rglDirection = directions; + desc.rglDirection[0] = +3000; + desc.rglDirection[1] = -2000; + desc.cbTypeSpecificParams = 1 * sizeof(DICONDITION); + desc.lpvTypeSpecificParams = (void *)&expect_condition[1]; + set_hid_expect( file, expect_create_3, sizeof(expect_create_3) ); + hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &desc, &effect, NULL ); + ok( hr == DI_OK, "CreateEffect returned %#x\n", hr ); + set_hid_expect( file, NULL, 0 ); + + set_hid_expect( file, &expect_destroy, sizeof(expect_destroy) ); + ref = IDirectInputEffect_Release( effect ); + ok( ref == 0, "Release returned %d\n", ref ); + set_hid_expect( file, NULL, 0 ); }
static void test_force_feedback_joystick( DWORD version )
From: Ivo Ivanov logos128@gmail.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51873 Signed-off-by: Ivo Ivanov logos128@gmail.com Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/joy.cpl/main.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/dlls/joy.cpl/main.c b/dlls/joy.cpl/main.c index c96efb17aa3..a1308606f98 100644 --- a/dlls/joy.cpl/main.c +++ b/dlls/joy.cpl/main.c @@ -790,6 +790,7 @@ static BOOL CALLBACK ff_effects_callback(const DIEFFECTINFOW *pdei, void *pvRef) DIEFFECT dieffect; DWORD axes[2] = {DIJOFS_X, DIJOFS_Y}; int direction[2] = {0, 0}; + int num_axes = 2; struct Joystick *joystick = pvRef; DIRAMPFORCE rforce; DICONSTANTFORCE cforce; @@ -811,8 +812,8 @@ static BOOL CALLBACK ff_effects_callback(const DIEFFECTINFOW *pdei, void *pvRef) dieffect.dwSize = sizeof(dieffect); dieffect.dwFlags = DIEFF_CARTESIAN|DIEFF_OBJECTOFFSETS; dieffect.dwDuration = FF_PLAY_TIME; + dieffect.dwGain = DI_FFNOMINALMAX;
- dieffect.cAxes = 2; dieffect.rgdwAxes = axes; dieffect.rglDirection = direction;
@@ -865,8 +866,14 @@ static BOOL CALLBACK ff_effects_callback(const DIEFFECTINFOW *pdei, void *pvRef) dieffect.dwFlags |= DIEP_TYPESPECIFICPARAMS; }
- hr = IDirectInputDevice2_CreateEffect( - joystick->device, &pdei->guid, &dieffect, &joystick->effects[joystick->cur_effect].effect, NULL); + do + { + dieffect.cAxes = num_axes--; + hr = IDirectInputDevice2_CreateEffect( + joystick->device, &pdei->guid, &dieffect, &joystick->effects[joystick->cur_effect].effect, NULL); + } + while (FAILED(hr) && num_axes); + if (FAILED(hr)) { FIXME("Failed to create effect with type %s, hr %#x\n", debugstr_guid(&pdei->guid), hr);