Advertising support of the periodic effect types only for now.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 20 ++++- dlls/winebus.sys/bus_udev.c | 19 +++- dlls/winebus.sys/hid.c | 151 +++++++++++++++++++++++++++++++- dlls/winebus.sys/unix_private.h | 21 ++++- dlls/winebus.sys/unixlib.c | 14 +++ 5 files changed, 220 insertions(+), 5 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 33386a80a34..9c2112f8e56 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -174,7 +174,8 @@ static void set_hat_value(struct unix_device *iface, int index, int value)
static BOOL descriptor_add_haptic(struct sdl_device *impl) { - USHORT i; + USHORT i, count = 0; + USAGE usages[16];
if (!pSDL_JoystickIsHaptic(impl->sdl_joystick) || !(impl->sdl_haptic = pSDL_HapticOpenFromJoystick(impl->sdl_joystick))) @@ -200,7 +201,13 @@ static BOOL descriptor_add_haptic(struct sdl_device *impl)
if ((impl->effect_support & EFFECT_SUPPORT_PHYSICAL)) { - if (!hid_device_add_physical(&impl->unix_device)) + /* SDL_HAPTIC_SQUARE doesn't exist */ + if (impl->effect_support & SDL_HAPTIC_SINE) usages[count++] = PID_USAGE_ET_SINE; + 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 (!hid_device_add_physical(&impl->unix_device, usages, count)) return FALSE; }
@@ -471,6 +478,14 @@ static NTSTATUS sdl_device_physical_effect_control(struct unix_device *iface, BY return STATUS_SUCCESS; }
+static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYTE index, + struct effect_params *params) +{ + FIXME("iface %p, index %u, params %p stub!\n", iface, index, params); + + return STATUS_NOT_IMPLEMENTED; +} + static const struct hid_device_vtbl sdl_device_vtbl = { sdl_device_destroy, @@ -479,6 +494,7 @@ static const struct hid_device_vtbl sdl_device_vtbl = sdl_device_haptics_start, sdl_device_physical_device_control, sdl_device_physical_effect_control, + sdl_device_physical_effect_update, };
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 3db261b2404..d63c9aab589 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -567,6 +567,8 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d BYTE ffbits[(FF_MAX+7)/8]; struct ff_effect effect; USAGE_AND_PAGE usage; + USHORT count = 0; + USAGE usages[16]; INT i, button_count, abs_count, rel_count, hat_count; const BYTE *device_usage = what_am_I(dev); struct lnxev_device *impl = lnxev_impl_from_unix_device(iface); @@ -664,7 +666,13 @@ static NTSTATUS build_report_descriptor(struct unix_device *iface, struct udev_d for (i = 0; i < FF_MAX; ++i) if (test_bit(ffbits, i)) break; if (i != FF_MAX) { - if (!hid_device_add_physical(iface)) + if (test_bit(ffbits, FF_SINE)) usages[count++] = PID_USAGE_ET_SINE; + if (test_bit(ffbits, FF_SQUARE)) usages[count++] = PID_USAGE_ET_SQUARE; + 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 (!hid_device_add_physical(iface, usages, count)) return STATUS_NO_MEMORY; }
@@ -916,6 +924,14 @@ static NTSTATUS lnxev_device_physical_effect_control(struct unix_device *iface, return STATUS_SUCCESS; }
+static NTSTATUS lnxev_device_physical_effect_update(struct unix_device *iface, BYTE index, + struct effect_params *params) +{ + FIXME("iface %p, index %u, params %p stub!\n", iface, index, params); + + return STATUS_NOT_IMPLEMENTED; +} + static const struct hid_device_vtbl lnxev_device_vtbl = { lnxev_device_destroy, @@ -924,6 +940,7 @@ static const struct hid_device_vtbl lnxev_device_vtbl = lnxev_device_haptics_start, lnxev_device_physical_device_control, lnxev_device_physical_effect_control, + lnxev_device_physical_effect_update, }; #endif /* HAS_PROPER_INPUT_HEADER */
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index 4ddee27cff9..72d358e6ad7 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -426,12 +426,27 @@ static const USAGE pid_effect_control_usages[] = PID_USAGE_OP_EFFECT_START_SOLO, PID_USAGE_OP_EFFECT_STOP, }; + +struct pid_effect_update +{ + BYTE index; + BYTE type_index; + UINT16 duration; + UINT16 trigger_repeat_interval; + UINT16 sample_period; + UINT16 start_delay; + BYTE gain; + BYTE trigger_button; + BYTE enable_bits; + BYTE direction[2]; +}; #include "poppack.h"
-BOOL hid_device_add_physical(struct unix_device *iface) +BOOL hid_device_add_physical(struct unix_device *iface, USAGE *usages, USHORT count) { struct hid_report_descriptor *desc = &iface->hid_report_descriptor; const BYTE device_control_report = ++desc->next_report_id[HidP_Output]; + struct hid_device_state *state = &iface->hid_device_state; const BYTE device_control_header[] = { USAGE_PAGE(1, HID_USAGE_PAGE_PID), @@ -488,6 +503,95 @@ BOOL hid_device_add_physical(struct unix_device *iface) OUTPUT(1, Data|Var|Abs), END_COLLECTION, }; + + const BYTE effect_update_report = ++desc->next_report_id[HidP_Output]; + const BYTE effect_update_header[] = + { + /* Set effect properties */ + USAGE(1, PID_USAGE_SET_EFFECT_REPORT), + COLLECTION(1, Logical), + REPORT_ID(1, effect_update_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_TYPE), + COLLECTION(1, Logical), + }; + const BYTE effect_update_footer[] = + { + LOGICAL_MINIMUM(1, 1), + LOGICAL_MAXIMUM(1, count), + REPORT_SIZE(1, 8), + OUTPUT(1, Data|Ary|Abs), + END_COLLECTION, + + USAGE(1, PID_USAGE_DURATION), + USAGE(1, PID_USAGE_TRIGGER_REPEAT_INTERVAL), + USAGE(1, PID_USAGE_SAMPLE_PERIOD), + USAGE(1, PID_USAGE_START_DELAY), + UNIT(2, 0x1003), /* Eng Lin:Time */ + 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_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), + REPORT_COUNT(1, 1), + OUTPUT(1, Data|Var|Abs|Null), + + USAGE(1, PID_USAGE_AXES_ENABLE), + 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_MAXIMUM(1, 1), + REPORT_SIZE(1, 1), + REPORT_COUNT(1, 2), + OUTPUT(1, Data|Var|Abs), + END_COLLECTION, + USAGE(1, PID_USAGE_DIRECTION_ENABLE), + REPORT_COUNT(1, 1), + OUTPUT(1, Data|Var|Abs), + REPORT_COUNT(1, 5), + OUTPUT(1, Cnst|Var|Abs), /* 5-bit pad */ + + USAGE(1, PID_USAGE_DIRECTION), + COLLECTION(1, Logical), + USAGE(4, (HID_USAGE_PAGE_ORDINAL<<16)|1), + USAGE(4, (HID_USAGE_PAGE_ORDINAL<<16)|2), + 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), + 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, + }; ULONG i;
if (!hid_report_descriptor_append(desc, device_control_header, sizeof(device_control_header))) @@ -510,8 +614,22 @@ BOOL hid_device_add_physical(struct unix_device *iface) if (!hid_report_descriptor_append(desc, effect_control_footer, sizeof(effect_control_footer))) return FALSE;
+ if (!hid_report_descriptor_append(desc, effect_update_header, sizeof(effect_update_header))) + return FALSE; + for (i = 0; i < count; ++i) + { + if (!hid_report_descriptor_append_usage(desc, usages[i])) + return FALSE; + } + if (!hid_report_descriptor_append(desc, effect_update_footer, sizeof(effect_update_footer))) + return FALSE; + + /* HID nary collection indexes start at 1 */ + memcpy(iface->hid_physical.effect_types + 1, usages, count * sizeof(*usages)); + iface->hid_physical.device_control_report = device_control_report; iface->hid_physical.effect_control_report = effect_control_report; + iface->hid_physical.effect_update_report = effect_update_report; return TRUE; }
@@ -602,6 +720,37 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC else io->Status = iface->hid_vtbl->physical_effect_control(iface, report->index, control, report->iterations); } + else if (packet->reportId == physical->effect_update_report) + { + struct pid_effect_update *report = (struct pid_effect_update *)(packet->reportBuffer + 1); + struct effect_params *params = iface->hid_physical.effect_params + report->index; + USAGE effect_type; + + io->Information = sizeof(*report) + 1; + if (packet->reportBufferLen < io->Information) + io->Status = STATUS_BUFFER_TOO_SMALL; + else if (report->type_index >= ARRAY_SIZE(iface->hid_physical.effect_types)) + io->Status = STATUS_INVALID_PARAMETER; + else if (!(effect_type = iface->hid_physical.effect_types[report->type_index])) + io->Status = STATUS_INVALID_PARAMETER; + else + { + params->effect_type = effect_type; + params->duration = report->duration; + 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; + params->direction_enabled = (report->enable_bits & 4) != 0; + params->direction[0] = report->direction[0]; + params->direction[1] = report->direction[1]; + + io->Status = iface->hid_vtbl->physical_effect_update(iface, report->index, params); + } + } else { io->Information = 0; diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index 2446b8de4a7..125ee600eb6 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -29,6 +29,20 @@
#include "wine/list.h"
+struct effect_params +{ + USAGE effect_type; + UINT16 duration; + UINT16 trigger_repeat_interval; + UINT16 sample_period; + UINT16 start_delay; + BYTE gain; + BYTE trigger_button; + BOOL axis_enabled[2]; + BOOL direction_enabled; + BYTE direction[2]; +}; + struct raw_device_vtbl { void (*destroy)(struct unix_device *iface); @@ -49,6 +63,7 @@ struct hid_device_vtbl 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); + NTSTATUS (*physical_effect_update)(struct unix_device *iface, BYTE index, struct effect_params *params); };
struct hid_report_descriptor @@ -91,8 +106,12 @@ struct hid_haptics
struct hid_physical { + USAGE effect_types[32]; + struct effect_params effect_params[256]; + BYTE device_control_report; BYTE effect_control_report; + BYTE effect_update_report; };
struct hid_device_state @@ -161,7 +180,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_add_physical(struct unix_device *iface, USAGE *usages, USHORT count) 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; diff --git a/dlls/winebus.sys/unixlib.c b/dlls/winebus.sys/unixlib.c index 29537170df7..c9d5fa5fd43 100644 --- a/dlls/winebus.sys/unixlib.c +++ b/dlls/winebus.sys/unixlib.c @@ -99,6 +99,12 @@ static NTSTATUS mouse_physical_effect_control(struct unix_device *iface, BYTE in return STATUS_NOT_SUPPORTED; }
+static NTSTATUS mouse_physical_effect_update(struct unix_device *iface, BYTE index, + struct effect_params *params) +{ + return STATUS_NOT_SUPPORTED; +} + static const struct hid_device_vtbl mouse_vtbl = { mouse_destroy, @@ -107,6 +113,7 @@ static const struct hid_device_vtbl mouse_vtbl = mouse_haptics_start, mouse_physical_device_control, mouse_physical_effect_control, + mouse_physical_effect_update, };
static const struct device_desc mouse_device_desc = @@ -169,6 +176,12 @@ static NTSTATUS keyboard_physical_effect_control(struct unix_device *iface, BYTE return STATUS_NOT_SUPPORTED; }
+static NTSTATUS keyboard_physical_effect_update(struct unix_device *iface, BYTE index, + struct effect_params *params) +{ + return STATUS_NOT_SUPPORTED; +} + static const struct hid_device_vtbl keyboard_vtbl = { keyboard_destroy, @@ -177,6 +190,7 @@ static const struct hid_device_vtbl keyboard_vtbl = keyboard_haptics_start, keyboard_physical_device_control, keyboard_physical_effect_control, + keyboard_physical_effect_update, };
static const struct device_desc keyboard_device_desc =
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 43 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 95ee04d9e82..ba968ec516d 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -85,6 +85,19 @@ struct pid_control_report ULONG control_coll; };
+struct pid_effect_update +{ + BYTE id; + ULONG collection; + ULONG type_coll; + struct hid_value_caps *duration_caps; + struct hid_value_caps *gain_caps; + struct hid_value_caps *sample_period_caps; + struct hid_value_caps *start_delay_caps; + struct hid_value_caps *trigger_button_caps; + struct hid_value_caps *trigger_repeat_interval_caps; +}; + #define DEVICE_STATE_MAX_SIZE 1024
struct hid_joystick @@ -115,6 +128,7 @@ struct hid_joystick struct list effect_list; struct pid_control_report pid_device_control; struct pid_control_report pid_effect_control; + struct pid_effect_update pid_effect_update; };
static inline struct hid_joystick *impl_from_IDirectInputDevice8W( IDirectInputDevice8W *iface ) @@ -1589,6 +1603,7 @@ static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps * { struct pid_control_report *device_control = &impl->pid_device_control; struct pid_control_report *effect_control = &impl->pid_effect_control; + struct pid_effect_update *effect_update = &impl->pid_effect_update;
#define SET_COLLECTION( rep ) \ do \ @@ -1613,9 +1628,14 @@ static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps * { case PID_USAGE_DEVICE_CONTROL_REPORT: SET_COLLECTION( device_control ); break; case PID_USAGE_EFFECT_OPERATION_REPORT: SET_COLLECTION( effect_control ); break; + case PID_USAGE_SET_EFFECT_REPORT: SET_COLLECTION( effect_update ); break;
case PID_USAGE_DEVICE_CONTROL: SET_SUB_COLLECTION( device_control, control_coll ); break; case PID_USAGE_EFFECT_OPERATION: SET_SUB_COLLECTION( effect_control, control_coll ); break; + case PID_USAGE_EFFECT_TYPE: + if (instance->wCollectionNumber == effect_update->collection) + SET_SUB_COLLECTION( effect_update, type_coll ); + break; } }
@@ -1630,6 +1650,7 @@ static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *cap { struct pid_control_report *device_control = &impl->pid_device_control; struct pid_control_report *effect_control = &impl->pid_effect_control; + struct pid_effect_update *effect_update = &impl->pid_effect_update;
if (!(instance->dwType & DIDFT_OUTPUT)) return DIENUM_CONTINUE;
@@ -1646,6 +1667,24 @@ static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *cap SET_REPORT_ID( device_control ); if (instance->wCollectionNumber == effect_control->control_coll) SET_REPORT_ID( effect_control ); + if (instance->wCollectionNumber == effect_update->type_coll) + SET_REPORT_ID( effect_update ); + if (instance->wCollectionNumber == effect_update->collection) + { + SET_REPORT_ID( effect_update ); + if (instance->wUsage == PID_USAGE_DURATION) + effect_update->duration_caps = caps; + if (instance->wUsage == PID_USAGE_GAIN) + effect_update->gain_caps = caps; + if (instance->wUsage == PID_USAGE_SAMPLE_PERIOD) + effect_update->sample_period_caps = caps; + if (instance->wUsage == PID_USAGE_START_DELAY) + effect_update->start_delay_caps = caps; + if (instance->wUsage == PID_USAGE_TRIGGER_BUTTON) + effect_update->trigger_button_caps = caps; + if (instance->wUsage == PID_USAGE_TRIGGER_REPEAT_INTERVAL) + effect_update->trigger_repeat_interval_caps = caps; + }
#undef SET_REPORT_ID
@@ -1750,10 +1789,14 @@ static HRESULT hid_joystick_create_device( IDirectInputImpl *dinput, const GUID TRACE( "device control id %u, coll %u, control coll %u\n", impl->pid_device_control.id, impl->pid_device_control.collection, impl->pid_device_control.control_coll ); TRACE( "effect control id %u, coll %u\n", impl->pid_effect_control.id, impl->pid_effect_control.collection ); + TRACE( "effect update id %u, coll %u, type_coll %u\n", impl->pid_effect_update.id, + impl->pid_effect_update.collection, impl->pid_effect_update.type_coll );
if (impl->pid_device_control.id) { impl->dev_caps.dwFlags |= DIDC_FORCEFEEDBACK; + if (impl->pid_effect_update.start_delay_caps) + impl->dev_caps.dwFlags |= DIDC_STARTDELAY; impl->dev_caps.dwFFSamplePeriod = 1000000; impl->dev_caps.dwFFMinTimeResolution = 1000000; impl->dev_caps.dwHardwareRevision = 1;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 93 +++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 9c2112f8e56..de1aa2363fd 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -106,6 +106,7 @@ MAKE_FUNCPTR(SDL_HapticSetGain); MAKE_FUNCPTR(SDL_HapticStopAll); MAKE_FUNCPTR(SDL_HapticStopEffect); MAKE_FUNCPTR(SDL_HapticUnpause); +MAKE_FUNCPTR(SDL_HapticUpdateEffect); MAKE_FUNCPTR(SDL_JoystickIsHaptic); MAKE_FUNCPTR(SDL_GameControllerAddMapping); MAKE_FUNCPTR(SDL_RegisterEvents); @@ -478,12 +479,99 @@ static NTSTATUS sdl_device_physical_effect_control(struct unix_device *iface, BY return STATUS_SUCCESS; }
+static NTSTATUS set_effect_type_from_usage(SDL_HapticEffect *effect, USAGE type) +{ + switch (type) + { + case PID_USAGE_ET_SINE: + effect->type = SDL_HAPTIC_SINE; + return STATUS_SUCCESS; + case PID_USAGE_ET_TRIANGLE: + effect->type = SDL_HAPTIC_TRIANGLE; + return STATUS_SUCCESS; + case PID_USAGE_ET_SAWTOOTH_UP: + effect->type = SDL_HAPTIC_SAWTOOTHUP; + return STATUS_SUCCESS; + case PID_USAGE_ET_SAWTOOTH_DOWN: + effect->type = SDL_HAPTIC_SAWTOOTHDOWN; + return STATUS_SUCCESS; + case PID_USAGE_ET_SPRING: + effect->type = SDL_HAPTIC_SPRING; + return STATUS_SUCCESS; + case PID_USAGE_ET_DAMPER: + effect->type = SDL_HAPTIC_DAMPER; + return STATUS_SUCCESS; + case PID_USAGE_ET_INERTIA: + effect->type = SDL_HAPTIC_INERTIA; + return STATUS_SUCCESS; + case PID_USAGE_ET_FRICTION: + effect->type = SDL_HAPTIC_FRICTION; + return STATUS_SUCCESS; + case PID_USAGE_ET_CONSTANT_FORCE: + effect->type = SDL_HAPTIC_CONSTANT; + return STATUS_SUCCESS; + case PID_USAGE_ET_RAMP: + effect->type = SDL_HAPTIC_RAMP; + return STATUS_SUCCESS; + case PID_USAGE_ET_CUSTOM_FORCE_DATA: + effect->type = SDL_HAPTIC_CUSTOM; + return STATUS_SUCCESS; + default: + return STATUS_NOT_SUPPORTED; + } +} + static NTSTATUS sdl_device_physical_effect_update(struct unix_device *iface, BYTE index, struct effect_params *params) { - FIXME("iface %p, index %u, params %p stub!\n", iface, index, params); + struct sdl_device *impl = impl_from_unix_device(iface); + int id = impl->effect_ids[index]; + SDL_HapticEffect effect = {0}; + NTSTATUS status;
- return STATUS_NOT_IMPLEMENTED; + TRACE("iface %p, index %u, params %p.\n", iface, index, params); + + if ((status = set_effect_type_from_usage(&effect, params->effect_type))) return status; + + switch (params->effect_type) + { + case PID_USAGE_ET_SINE: + case PID_USAGE_ET_SQUARE: + case PID_USAGE_ET_TRIANGLE: + case PID_USAGE_ET_SAWTOOTH_UP: + case PID_USAGE_ET_SAWTOOTH_DOWN: + FIXME("periodic effect semi-stub!"); + effect.periodic.length = params->duration; + effect.periodic.delay = params->start_delay; + 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; + break; + + case PID_USAGE_ET_SPRING: + case PID_USAGE_ET_DAMPER: + case PID_USAGE_ET_INERTIA: + case PID_USAGE_ET_FRICTION: + FIXME("not implemented!"); + break; + + case PID_USAGE_ET_CONSTANT_FORCE: + FIXME("not implemented!"); + break; + case PID_USAGE_ET_RAMP: + FIXME("not implemented!"); + break; + case PID_USAGE_ET_CUSTOM_FORCE_DATA: + FIXME("not implemented!"); + break; + } + + if (id < 0) impl->effect_ids[index] = pSDL_HapticNewEffect(impl->sdl_haptic, &effect); + else pSDL_HapticUpdateEffect(impl->sdl_haptic, id, &effect); + + return STATUS_SUCCESS; }
static const struct hid_device_vtbl sdl_device_vtbl = @@ -758,6 +846,7 @@ NTSTATUS sdl_bus_init(void *args) LOAD_FUNCPTR(SDL_HapticStopAll); LOAD_FUNCPTR(SDL_HapticStopEffect); LOAD_FUNCPTR(SDL_HapticUnpause); + LOAD_FUNCPTR(SDL_HapticUpdateEffect); LOAD_FUNCPTR(SDL_JoystickIsHaptic); LOAD_FUNCPTR(SDL_GameControllerAddMapping); LOAD_FUNCPTR(SDL_RegisterEvents);
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_udev.c | 103 +++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-)
diff --git a/dlls/winebus.sys/bus_udev.c b/dlls/winebus.sys/bus_udev.c index d63c9aab589..08ca8435d31 100644 --- a/dlls/winebus.sys/bus_udev.c +++ b/dlls/winebus.sys/bus_udev.c @@ -924,12 +924,111 @@ static NTSTATUS lnxev_device_physical_effect_control(struct unix_device *iface, return STATUS_SUCCESS; }
+static NTSTATUS set_effect_type_from_usage(struct ff_effect *effect, USAGE type) +{ + switch (type) + { + case PID_USAGE_ET_SINE: + effect->type = FF_PERIODIC; + effect->u.periodic.waveform = FF_SINE; + return STATUS_SUCCESS; + case PID_USAGE_ET_SQUARE: + effect->type = FF_PERIODIC; + effect->u.periodic.waveform = FF_SQUARE; + return STATUS_SUCCESS; + case PID_USAGE_ET_TRIANGLE: + effect->type = FF_PERIODIC; + effect->u.periodic.waveform = FF_TRIANGLE; + return STATUS_SUCCESS; + case PID_USAGE_ET_SAWTOOTH_UP: + effect->type = FF_PERIODIC; + effect->u.periodic.waveform = FF_SAW_UP; + return STATUS_SUCCESS; + case PID_USAGE_ET_SAWTOOTH_DOWN: + effect->type = FF_PERIODIC; + effect->u.periodic.waveform = FF_SAW_DOWN; + return STATUS_SUCCESS; + case PID_USAGE_ET_SPRING: + effect->type = FF_SPRING; + return STATUS_SUCCESS; + case PID_USAGE_ET_DAMPER: + effect->type = FF_DAMPER; + return STATUS_SUCCESS; + case PID_USAGE_ET_INERTIA: + effect->type = FF_INERTIA; + return STATUS_SUCCESS; + case PID_USAGE_ET_FRICTION: + effect->type = FF_FRICTION; + return STATUS_SUCCESS; + case PID_USAGE_ET_CONSTANT_FORCE: + effect->type = FF_CONSTANT; + return STATUS_SUCCESS; + case PID_USAGE_ET_RAMP: + effect->type = FF_RAMP; + return STATUS_SUCCESS; + case PID_USAGE_ET_CUSTOM_FORCE_DATA: + effect->type = FF_CUSTOM; + return STATUS_SUCCESS; + default: + return STATUS_NOT_SUPPORTED; + } +} + static NTSTATUS lnxev_device_physical_effect_update(struct unix_device *iface, BYTE index, struct effect_params *params) { - FIXME("iface %p, index %u, params %p stub!\n", iface, index, params); + struct lnxev_device *impl = lnxev_impl_from_unix_device(iface); + struct ff_effect effect = {.id = impl->effect_ids[index]}; + NTSTATUS status;
- return STATUS_NOT_IMPLEMENTED; + TRACE("iface %p, index %u, params %p.\n", iface, index, params); + + if ((status = set_effect_type_from_usage(&effect, params->effect_type))) return status; + + effect.replay.length = params->duration; + effect.replay.delay = params->start_delay; + 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; + + switch (params->effect_type) + { + case PID_USAGE_ET_SINE: + case PID_USAGE_ET_SQUARE: + case PID_USAGE_ET_TRIANGLE: + case PID_USAGE_ET_SAWTOOTH_UP: + case PID_USAGE_ET_SAWTOOTH_DOWN: + FIXME("periodic effect semi-stub!"); + break; + + case PID_USAGE_ET_SPRING: + case PID_USAGE_ET_DAMPER: + case PID_USAGE_ET_INERTIA: + case PID_USAGE_ET_FRICTION: + FIXME("not implemented!"); + break; + + case PID_USAGE_ET_CONSTANT_FORCE: + FIXME("not implemented!"); + break; + case PID_USAGE_ET_RAMP: + FIXME("not implemented!"); + break; + case PID_USAGE_ET_CUSTOM_FORCE_DATA: + FIXME("not implemented!"); + break; + } + + if (ioctl(impl->base.device_fd, EVIOCSFF, &effect) != -1) + impl->effect_ids[index] = effect.id; + else + { + WARN("couldn't create effect, EVIOCSFF ioctl failed: %d %s\n", errno, strerror(errno)); + return STATUS_UNSUCCESSFUL; + } + + return STATUS_SUCCESS; }
static const struct hid_device_vtbl lnxev_device_vtbl =
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 124 ++++++++++++++++++++++++++++++++++++- dlls/dinput8/tests/hid.c | 8 +-- 2 files changed, 124 insertions(+), 8 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index ba968ec516d..946a5c73d74 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -175,6 +175,52 @@ static const GUID *object_usage_to_guid( USAGE usage_page, USAGE usage ) return &GUID_Unknown; }
+static inline USAGE effect_guid_to_usage( const GUID *guid ) +{ + if (IsEqualGUID( guid, &GUID_CustomForce )) return PID_USAGE_ET_CUSTOM_FORCE_DATA; + if (IsEqualGUID( guid, &GUID_ConstantForce )) return PID_USAGE_ET_CONSTANT_FORCE; + if (IsEqualGUID( guid, &GUID_RampForce )) return PID_USAGE_ET_RAMP; + if (IsEqualGUID( guid, &GUID_Square )) return PID_USAGE_ET_SQUARE; + if (IsEqualGUID( guid, &GUID_Sine )) return PID_USAGE_ET_SINE; + if (IsEqualGUID( guid, &GUID_Triangle )) return PID_USAGE_ET_TRIANGLE; + if (IsEqualGUID( guid, &GUID_SawtoothUp )) return PID_USAGE_ET_SAWTOOTH_UP; + if (IsEqualGUID( guid, &GUID_SawtoothDown )) return PID_USAGE_ET_SAWTOOTH_DOWN; + if (IsEqualGUID( guid, &GUID_Spring )) return PID_USAGE_ET_SPRING; + if (IsEqualGUID( guid, &GUID_Damper )) return PID_USAGE_ET_DAMPER; + if (IsEqualGUID( guid, &GUID_Inertia )) return PID_USAGE_ET_INERTIA; + if (IsEqualGUID( guid, &GUID_Friction )) return PID_USAGE_ET_FRICTION; + return 0; +} + +static const WCHAR *effect_guid_to_string( const GUID *guid ) +{ + static const WCHAR guid_customforce_w[] = {'G','U','I','D','_','C','u','s','t','o','m','F','o','r','c','e',0}; + static const WCHAR guid_constantforce_w[] = {'G','U','I','D','_','C','o','n','s','t','a','n','t','F','o','r','c','e',0}; + static const WCHAR guid_rampforce_w[] = {'G','U','I','D','_','R','a','m','p','F','o','r','c','e',0}; + static const WCHAR guid_square_w[] = {'G','U','I','D','_','S','q','u','a','r','e',0}; + static const WCHAR guid_sine_w[] = {'G','U','I','D','_','S','i','n','e',0}; + static const WCHAR guid_triangle_w[] = {'G','U','I','D','_','T','r','i','a','n','g','l','e',0}; + static const WCHAR guid_sawtoothup_w[] = {'G','U','I','D','_','S','a','w','t','o','o','t','h','U','p',0}; + static const WCHAR guid_sawtoothdown_w[] = {'G','U','I','D','_','S','a','w','t','o','o','t','h','D','o','w','n',0}; + static const WCHAR guid_spring_w[] = {'G','U','I','D','_','S','p','r','i','n','g',0}; + static const WCHAR guid_damper_w[] = {'G','U','I','D','_','D','a','m','p','e','r',0}; + static const WCHAR guid_inertia_w[] = {'G','U','I','D','_','I','n','e','r','t','i','a',0}; + static const WCHAR guid_friction_w[] = {'G','U','I','D','_','F','r','i','c','t','i','o','n',0}; + if (IsEqualGUID( guid, &GUID_CustomForce )) return guid_customforce_w; + if (IsEqualGUID( guid, &GUID_ConstantForce )) return guid_constantforce_w; + if (IsEqualGUID( guid, &GUID_RampForce )) return guid_rampforce_w; + if (IsEqualGUID( guid, &GUID_Square )) return guid_square_w; + if (IsEqualGUID( guid, &GUID_Sine )) return guid_sine_w; + if (IsEqualGUID( guid, &GUID_Triangle )) return guid_triangle_w; + if (IsEqualGUID( guid, &GUID_SawtoothUp )) return guid_sawtoothup_w; + if (IsEqualGUID( guid, &GUID_SawtoothDown )) return guid_sawtoothdown_w; + if (IsEqualGUID( guid, &GUID_Spring )) return guid_spring_w; + if (IsEqualGUID( guid, &GUID_Damper )) return guid_damper_w; + if (IsEqualGUID( guid, &GUID_Inertia )) return guid_inertia_w; + if (IsEqualGUID( guid, &GUID_Friction )) return guid_friction_w; + return NULL; +} + typedef BOOL (*enum_object_callback)( struct hid_joystick *impl, struct hid_value_caps *caps, DIDEVICEOBJECTINSTANCEW *instance, void *data );
@@ -964,12 +1010,86 @@ static HRESULT WINAPI hid_joystick_EnumEffects( IDirectInputDevice8W *iface, LPD static HRESULT WINAPI hid_joystick_GetEffectInfo( IDirectInputDevice8W *iface, DIEFFECTINFOW *info, const GUID *guid ) { - FIXME( "iface %p, info %p, guid %s stub!\n", iface, info, debugstr_guid( guid ) ); + struct hid_joystick *impl = impl_from_IDirectInputDevice8W( iface ); + struct pid_effect_update *effect_update = &impl->pid_effect_update; + PHIDP_PREPARSED_DATA preparsed = impl->preparsed; + HIDP_BUTTON_CAPS button; + ULONG type, collection; + NTSTATUS status; + USAGE usage = 0; + USHORT count; + + TRACE( "iface %p, info %p, guid %s.\n", iface, info, debugstr_guid( guid ) );
if (!info) return E_POINTER; if (info->dwSize != sizeof(DIEFFECTINFOW)) return DIERR_INVALIDPARAM; + if (!(impl->dev_caps.dwFlags & DIDC_FORCEFEEDBACK)) return DIERR_DEVICENOTREG;
- return DIERR_DEVICENOTREG; + switch ((usage = effect_guid_to_usage( guid ))) + { + case PID_USAGE_ET_SQUARE: + case PID_USAGE_ET_SINE: + case PID_USAGE_ET_TRIANGLE: + case PID_USAGE_ET_SAWTOOTH_UP: + case PID_USAGE_ET_SAWTOOTH_DOWN: + type = DIEFT_PERIODIC; + break; + case PID_USAGE_ET_SPRING: + case PID_USAGE_ET_DAMPER: + case PID_USAGE_ET_INERTIA: + case PID_USAGE_ET_FRICTION: + type = DIEFT_CONDITION; + break; + case PID_USAGE_ET_CONSTANT_FORCE: + type = DIEFT_CONSTANTFORCE; + break; + case PID_USAGE_ET_RAMP: + type = DIEFT_RAMPFORCE; + break; + case PID_USAGE_ET_CUSTOM_FORCE_DATA: + type = DIEFT_CUSTOMFORCE; + break; + default: + return DIERR_DEVICENOTREG; + } + + if (!(collection = effect_update->collection)) return DIERR_DEVICENOTREG; + + if (effect_update->duration_caps) info->dwDynamicParams |= DIEP_DURATION; + if (effect_update->gain_caps) info->dwDynamicParams |= DIEP_GAIN; + if (effect_update->sample_period_caps) info->dwDynamicParams |= DIEP_SAMPLEPERIOD; + if (effect_update->start_delay_caps) + { + type |= DIEFT_STARTDELAY; + info->dwDynamicParams |= DIEP_STARTDELAY; + } + if (effect_update->trigger_button_caps) info->dwDynamicParams |= DIEP_TRIGGERBUTTON; + if (effect_update->trigger_repeat_interval_caps) info->dwDynamicParams |= DIEP_TRIGGERREPEATINTERVAL; + + if (!(collection = effect_update->type_coll)) return DIERR_DEVICENOTREG; + else + { + count = 1; + status = HidP_GetSpecificButtonCaps( HidP_Output, HID_USAGE_PAGE_PID, collection, + usage, &button, &count, preparsed ); + if (status != HIDP_STATUS_SUCCESS) + { + WARN( "HidP_GetSpecificValueCaps %#x returned %#x\n", usage, status ); + return DIERR_DEVICENOTREG; + } + else if (!count) + { + WARN( "effect usage %#x not found\n", usage ); + return DIERR_DEVICENOTREG; + } + } + + info->guid = *guid; + info->dwEffType = type; + info->dwStaticParams = info->dwDynamicParams; + lstrcpynW( info->tszName, effect_guid_to_string( guid ), MAX_PATH ); + + return DI_OK; }
static HRESULT WINAPI hid_joystick_GetForceFeedbackState( IDirectInputDevice8W *iface, DWORD *out ) diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index ab70a7c7b76..59f5f6ff29d 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -3363,7 +3363,9 @@ static BOOL CALLBACK check_effects( const DIEFFECTINFOW *effect, void *args ) check_member( *effect, *exp, "%u", dwSize ); check_member_guid( *effect, *exp, guid ); check_member( *effect, *exp, "%#x", dwEffType ); + todo_wine check_member( *effect, *exp, "%#x", dwStaticParams ); + todo_wine check_member( *effect, *exp, "%#x", dwDynamicParams ); check_member_wstr( *effect, *exp, tszName );
@@ -5728,27 +5730,21 @@ static void test_force_feedback_joystick( void ) res = 0; hr = IDirectInputDevice8_EnumEffects( device, check_effect_count, &res, DIEFT_PERIODIC ); ok( hr == DI_OK, "IDirectInputDevice8_EnumEffects returned %#x\n", hr ); - todo_wine ok( res == 1, "got %u expected %u\n", res, 1 ); hr = IDirectInputDevice8_EnumEffects( device, check_effects, &check_effects_params, DIEFT_ALL ); ok( hr == DI_OK, "IDirectInputDevice8_EnumEffects returned %#x\n", hr ); - todo_wine ok( check_effects_params.index >= check_effects_params.expect_count, "missing %u effects\n", check_effects_params.expect_count - check_effects_params.index );
effectinfo.dwSize = sizeof(DIEFFECTINFOW); hr = IDirectInputDevice8_GetEffectInfo( device, &effectinfo, &GUID_Sine ); - todo_wine ok( hr == DI_OK, "IDirectInputDevice8_GetEffectInfo returned %#x\n", hr ); - todo_wine check_member_guid( effectinfo, expect_effects[0], guid ); - todo_wine check_member( effectinfo, expect_effects[0], "%#x", dwEffType ); todo_wine check_member( effectinfo, expect_effects[0], "%#x", dwStaticParams ); todo_wine check_member( effectinfo, expect_effects[0], "%#x", dwDynamicParams ); - todo_wine check_member_wstr( effectinfo, expect_effects[0], tszName );
hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 16 +++++++++++++++- dlls/dinput8/tests/hid.c | 4 ---- 2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 946a5c73d74..1a22c7c8baa 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -90,6 +90,9 @@ struct pid_effect_update BYTE id; ULONG collection; ULONG type_coll; + ULONG axes_coll; + ULONG axis_count; + struct hid_value_caps *axis_caps[6]; struct hid_value_caps *duration_caps; struct hid_value_caps *gain_caps; struct hid_value_caps *sample_period_caps; @@ -1055,6 +1058,8 @@ static HRESULT WINAPI hid_joystick_GetEffectInfo( IDirectInputDevice8W *iface, D
if (!(collection = effect_update->collection)) return DIERR_DEVICENOTREG;
+ info->dwDynamicParams = DIEP_TYPESPECIFICPARAMS; + if (effect_update->axis_count) info->dwDynamicParams |= DIEP_AXES; if (effect_update->duration_caps) info->dwDynamicParams |= DIEP_DURATION; if (effect_update->gain_caps) info->dwDynamicParams |= DIEP_GAIN; if (effect_update->sample_period_caps) info->dwDynamicParams |= DIEP_SAMPLEPERIOD; @@ -1065,7 +1070,8 @@ static HRESULT WINAPI hid_joystick_GetEffectInfo( IDirectInputDevice8W *iface, D } if (effect_update->trigger_button_caps) info->dwDynamicParams |= DIEP_TRIGGERBUTTON; if (effect_update->trigger_repeat_interval_caps) info->dwDynamicParams |= DIEP_TRIGGERREPEATINTERVAL; - + if (effect_update->axes_coll) info->dwDynamicParams |= DIEP_AXES; + if (!(collection = effect_update->type_coll)) return DIERR_DEVICENOTREG; else { @@ -1756,6 +1762,7 @@ static BOOL init_pid_reports( struct hid_joystick *impl, struct hid_value_caps * if (instance->wCollectionNumber == effect_update->collection) SET_SUB_COLLECTION( effect_update, type_coll ); break; + case PID_USAGE_AXES_ENABLE: SET_SUB_COLLECTION( effect_update, axes_coll ); break; } }
@@ -1805,6 +1812,13 @@ static BOOL init_pid_caps( struct hid_joystick *impl, struct hid_value_caps *cap if (instance->wUsage == PID_USAGE_TRIGGER_REPEAT_INTERVAL) effect_update->trigger_repeat_interval_caps = caps; } + if (instance->wCollectionNumber == effect_update->axes_coll) + { + SET_REPORT_ID( effect_update ); + if (effect_update->axis_count >= 6) FIXME( "more than 6 PID axes detected\n" ); + else effect_update->axis_caps[effect_update->axis_count] = caps; + effect_update->axis_count++; + }
#undef SET_REPORT_ID
diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index 59f5f6ff29d..f4e180a85f3 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -3363,9 +3363,7 @@ static BOOL CALLBACK check_effects( const DIEFFECTINFOW *effect, void *args ) check_member( *effect, *exp, "%u", dwSize ); check_member_guid( *effect, *exp, guid ); check_member( *effect, *exp, "%#x", dwEffType ); - todo_wine check_member( *effect, *exp, "%#x", dwStaticParams ); - todo_wine check_member( *effect, *exp, "%#x", dwDynamicParams ); check_member_wstr( *effect, *exp, tszName );
@@ -5741,9 +5739,7 @@ static void test_force_feedback_joystick( void ) ok( hr == DI_OK, "IDirectInputDevice8_GetEffectInfo returned %#x\n", hr ); check_member_guid( effectinfo, expect_effects[0], guid ); check_member( effectinfo, expect_effects[0], "%#x", dwEffType ); - todo_wine check_member( effectinfo, expect_effects[0], "%#x", dwStaticParams ); - todo_wine check_member( effectinfo, expect_effects[0], "%#x", dwDynamicParams ); check_member_wstr( effectinfo, expect_effects[0], tszName );
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/joystick_hid.c | 18 ++++++++++++++++++ dlls/dinput8/tests/hid.c | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c index 1a22c7c8baa..7c212797ec1 100644 --- a/dlls/dinput/joystick_hid.c +++ b/dlls/dinput/joystick_hid.c @@ -255,6 +255,23 @@ static BOOL enum_object( struct hid_joystick *impl, const DIPROPHEADER *filter, return DIENUM_CONTINUE; }
+static void check_pid_effect_axis_caps( struct hid_joystick *impl, DIDEVICEOBJECTINSTANCEW *instance ) +{ + struct pid_effect_update *effect_update = &impl->pid_effect_update; + ULONG i; + + for (i = 0; i < effect_update->axis_count; ++i) + { + if (effect_update->axis_caps[i]->usage_page != instance->wUsagePage) continue; + if (effect_update->axis_caps[i]->usage_min > instance->wUsage) continue; + if (effect_update->axis_caps[i]->usage_max >= instance->wUsage) break; + } + + if (i == effect_update->axis_count) return; + instance->dwType |= DIDFT_FFACTUATOR; + instance->dwFlags |= DIDOI_FFACTUATOR; +} + static void set_axis_type( DIDEVICEOBJECTINSTANCEW *instance, BOOL *seen, DWORD i, DWORD *count ) { if (!seen[i]) instance->dwType = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( i ); @@ -326,6 +343,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, instance.dwFlags = DIDOI_ASPECTPOSITION; break; } + check_pid_effect_axis_caps( impl, &instance ); instance.wUsagePage = caps->usage_page; instance.wUsage = j; instance.guidType = *object_usage_to_guid( instance.wUsagePage, instance.wUsage ); diff --git a/dlls/dinput8/tests/hid.c b/dlls/dinput8/tests/hid.c index f4e180a85f3..cddb5aa1aac 100644 --- a/dlls/dinput8/tests/hid.c +++ b/dlls/dinput8/tests/hid.c @@ -5590,7 +5590,7 @@ static void test_force_feedback_joystick( void ) const struct check_objects_todos objects_todos[ARRAY_SIZE(expect_objects)] = { {}, - {.type = TRUE, .flags = TRUE}, + {}, {.type = TRUE, .flags = TRUE}, {.type = TRUE, .flags = TRUE}, };
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=99365
Your paranoid android.
=== debiant2 (32 bit report) ===
dinput8: hid.c:3318: Test failed: obj[1]: got dwType 0x2, expected 0x1000002 hid.c:3320: Test failed: obj[1]: got dwFlags 0x100, expected 0x101
=== debiant2 (32 bit Arabic:Morocco report) ===
dinput8: hid.c:3318: Test failed: obj[1]: got dwType 0x2, expected 0x1000002 hid.c:3320: Test failed: obj[1]: got dwFlags 0x100, expected 0x101
=== debiant2 (32 bit German report) ===
dinput8: hid.c:3318: Test failed: obj[1]: got dwType 0x2, expected 0x1000002 hid.c:3320: Test failed: obj[1]: got dwFlags 0x100, expected 0x101
=== debiant2 (32 bit French report) ===
dinput8: hid.c:3318: Test failed: obj[1]: got dwType 0x2, expected 0x1000002 hid.c:3320: Test failed: obj[1]: got dwFlags 0x100, expected 0x101
=== debiant2 (32 bit Hebrew:Israel report) ===
dinput8: hid.c:3318: Test failed: obj[1]: got dwType 0x2, expected 0x1000002 hid.c:3320: Test failed: obj[1]: got dwFlags 0x100, expected 0x101
=== debiant2 (32 bit Hindi:India report) ===
dinput8: hid.c:3318: Test failed: obj[1]: got dwType 0x2, expected 0x1000002 hid.c:3320: Test failed: obj[1]: got dwFlags 0x100, expected 0x101
=== debiant2 (32 bit Japanese:Japan report) ===
dinput8: hid.c:3318: Test failed: obj[1]: got dwType 0x2, expected 0x1000002 hid.c:3320: Test failed: obj[1]: got dwFlags 0x100, expected 0x101
=== debiant2 (32 bit Chinese:China report) ===
dinput8: hid.c:3318: Test failed: obj[1]: got dwType 0x2, expected 0x1000002 hid.c:3320: Test failed: obj[1]: got dwFlags 0x100, expected 0x101
=== debiant2 (64 bit WoW report) ===
dinput8: hid.c:3318: Test failed: obj[1]: got dwType 0x2, expected 0x1000002 hid.c:3320: Test failed: obj[1]: got dwFlags 0x100, expected 0x101
On 10/5/21 9:17 AM, Marvin wrote:
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=99365
Your paranoid android.
=== debiant2 (32 bit report) ===
dinput8: hid.c:3318: Test failed: obj[1]: got dwType 0x2, expected 0x1000002 hid.c:3320: Test failed: obj[1]: got dwFlags 0x100, expected 0x101
I may have missed something in a rebase, please ignore that last patch I'll figure it out and resend it later.