The SDL_HAPTIC_LEFTRIGHT effect should be preferred when available.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index eba8a959cb4..ce696f5b42f 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -185,14 +185,12 @@ static BOOL descriptor_add_haptic(struct sdl_device *impl) !(impl->sdl_haptic = pSDL_HapticOpenFromJoystick(impl->sdl_joystick))) impl->effect_support = 0; else - { impl->effect_support = pSDL_HapticQuery(impl->sdl_haptic); - if (pSDL_HapticRumbleSupported(impl->sdl_haptic)) - impl->effect_support |= WINE_SDL_HAPTIC_RUMBLE;
- pSDL_HapticStopAll(impl->sdl_haptic); - pSDL_HapticRumbleInit(impl->sdl_haptic); - } + if (!(impl->effect_support & EFFECT_SUPPORT_HAPTICS) && + pSDL_HapticRumbleSupported(impl->sdl_haptic) && + pSDL_HapticRumbleInit(impl->sdl_haptic) == 0) + impl->effect_support |= WINE_SDL_HAPTIC_RUMBLE;
if (!(impl->effect_support & EFFECT_SUPPORT_HAPTICS) && pSDL_JoystickRumble && !pSDL_JoystickRumble(impl->sdl_joystick, 0, 0, 0))
Instead of stopping them, then re-starting them when a new effect is requested.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index ce696f5b42f..0bddba2fe18 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -415,12 +415,15 @@ NTSTATUS sdl_device_haptics_start(struct unix_device *iface, UINT duration_ms, effect.leftright.large_magnitude = rumble_intensity; effect.leftright.small_magnitude = buzz_intensity;
- if (impl->effect_support & WINE_SDL_JOYSTICK_RUMBLE) - pSDL_JoystickRumble(impl->sdl_joystick, 0, 0, 0); - else if (impl->sdl_haptic) - pSDL_HapticStopAll(impl->sdl_haptic); if (!effect.leftright.large_magnitude && !effect.leftright.small_magnitude) + { + if (impl->effect_support & WINE_SDL_JOYSTICK_RUMBLE) + pSDL_JoystickRumble(impl->sdl_joystick, 0, 0, 0); + else if (impl->sdl_haptic) + pSDL_HapticStopAll(impl->sdl_haptic); + return STATUS_SUCCESS; + }
if (impl->effect_support & SDL_HAPTIC_LEFTRIGHT) {
Depending on the API the device supports, in preferred order.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/bus_sdl.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c index 0bddba2fe18..02757362bc7 100644 --- a/dlls/winebus.sys/bus_sdl.c +++ b/dlls/winebus.sys/bus_sdl.c @@ -100,6 +100,7 @@ MAKE_FUNCPTR(SDL_HapticPause); MAKE_FUNCPTR(SDL_HapticQuery); MAKE_FUNCPTR(SDL_HapticRumbleInit); MAKE_FUNCPTR(SDL_HapticRumblePlay); +MAKE_FUNCPTR(SDL_HapticRumbleStop); MAKE_FUNCPTR(SDL_HapticRumbleSupported); MAKE_FUNCPTR(SDL_HapticRunEffect); MAKE_FUNCPTR(SDL_HapticSetGain); @@ -417,10 +418,12 @@ NTSTATUS sdl_device_haptics_start(struct unix_device *iface, UINT duration_ms,
if (!effect.leftright.large_magnitude && !effect.leftright.small_magnitude) { - if (impl->effect_support & WINE_SDL_JOYSTICK_RUMBLE) - pSDL_JoystickRumble(impl->sdl_joystick, 0, 0, 0); - else if (impl->sdl_haptic) + if (impl->effect_support & SDL_HAPTIC_LEFTRIGHT) pSDL_HapticStopAll(impl->sdl_haptic); + else if (impl->effect_support & WINE_SDL_HAPTIC_RUMBLE) + pSDL_HapticRumbleStop(impl->sdl_haptic); + else if (impl->effect_support & WINE_SDL_JOYSTICK_RUMBLE) + pSDL_JoystickRumble(impl->sdl_joystick, 0, 0, 0);
return STATUS_SUCCESS; } @@ -997,6 +1000,7 @@ NTSTATUS sdl_bus_init(void *args) LOAD_FUNCPTR(SDL_HapticQuery); LOAD_FUNCPTR(SDL_HapticRumbleInit); LOAD_FUNCPTR(SDL_HapticRumblePlay); + LOAD_FUNCPTR(SDL_HapticRumbleStop); LOAD_FUNCPTR(SDL_HapticRumbleSupported); LOAD_FUNCPTR(SDL_HapticRunEffect); LOAD_FUNCPTR(SDL_HapticSetGain);
There's some inconsistencies between the HID 1.22 specification and HID usage names in Windows SDK headers. The headers use STOP for the 0x1001 usage name, and NULL for 0x1002, where the HID spec uses None for the 0x1001 usage name and Stop for 0x1002.
Both are implicit waveforms anyway, and the HID usages aren't really used anywhere, but their ordinal matters. The HID spec says that None has ordinal 1, and Stop ordinal 2, and that Stop waveform can be used to stop any previously started waveform. We are going to stick to that and ignore the HID usages, although the names won't match the usages.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winebus.sys/hid.c | 20 ++++++++------------ dlls/winebus.sys/unix_private.h | 24 +++++++++++++++--------- 2 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c index 3be2ca304d5..ec2250fbe80 100644 --- a/dlls/winebus.sys/hid.c +++ b/dlls/winebus.sys/hid.c @@ -323,26 +323,22 @@ BOOL hid_device_add_haptics(struct unix_device *iface)
USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_LIST), COLLECTION(1, NamedArray), - USAGE_PAGE(1, HID_USAGE_PAGE_ORDINAL), - USAGE(1, 3), /* HID_USAGE_HAPTICS_WAVEFORM_RUMBLE */ - USAGE(1, 4), /* HID_USAGE_HAPTICS_WAVEFORM_BUZZ */ + USAGE(4, (HID_USAGE_PAGE_ORDINAL<<16)|HAPTICS_WAVEFORM_RUMBLE_ORDINAL), /* HID_USAGE_HAPTICS_WAVEFORM_RUMBLE */ + USAGE(4, (HID_USAGE_PAGE_ORDINAL<<16)|HAPTICS_WAVEFORM_BUZZ_ORDINAL), /* HID_USAGE_HAPTICS_WAVEFORM_BUZZ */ REPORT_COUNT(1, 2), REPORT_SIZE(1, 16), FEATURE(1, Data|Var|Abs|Null), END_COLLECTION,
- USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS), USAGE(1, HID_USAGE_HAPTICS_DURATION_LIST), COLLECTION(1, NamedArray), - USAGE_PAGE(1, HID_USAGE_PAGE_ORDINAL), - USAGE(1, 3), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_RUMBLE) */ - USAGE(1, 4), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_BUZZ) */ + USAGE(4, (HID_USAGE_PAGE_ORDINAL<<16)|HAPTICS_WAVEFORM_RUMBLE_ORDINAL), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_RUMBLE) */ + USAGE(4, (HID_USAGE_PAGE_ORDINAL<<16)|HAPTICS_WAVEFORM_BUZZ_ORDINAL), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_BUZZ) */ REPORT_COUNT(1, 2), REPORT_SIZE(1, 16), FEATURE(1, Data|Var|Abs|Null), END_COLLECTION,
- USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS), USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME), UNIT(2, 0x1001), /* seconds */ UNIT_EXPONENT(1, -3), /* 10^-3 */ @@ -1042,18 +1038,18 @@ static void hid_device_set_output_report(struct unix_device *iface, HID_XFER_PAC if (packet->reportId == haptics->waveform_report) { struct hid_haptics_waveform *waveform = (struct hid_haptics_waveform *)(packet->reportBuffer + 1); - struct hid_haptics_waveform *rumble = haptics->waveforms + HAPTICS_WAVEFORM_RUMBLE_INDEX; - struct hid_haptics_waveform *buzz = haptics->waveforms + HAPTICS_WAVEFORM_BUZZ_INDEX; + struct hid_haptics_waveform *rumble = haptics->waveforms + HAPTICS_WAVEFORM_RUMBLE_ORDINAL; + struct hid_haptics_waveform *buzz = haptics->waveforms + HAPTICS_WAVEFORM_BUZZ_ORDINAL; ULONG duration_ms;
io->Information = sizeof(*waveform) + 1; assert(packet->reportBufferLen == io->Information);
- if (waveform->manual_trigger == 0 || waveform->manual_trigger > HAPTICS_WAVEFORM_LAST_INDEX) + if (waveform->manual_trigger == 0 || waveform->manual_trigger > HAPTICS_WAVEFORM_LAST_ORDINAL) io->Status = STATUS_INVALID_PARAMETER; else { - if (waveform->manual_trigger == HAPTICS_WAVEFORM_STOP_INDEX) + if (waveform->manual_trigger == HAPTICS_WAVEFORM_STOP_ORDINAL) memset(haptics->waveforms, 0, sizeof(haptics->waveforms)); else haptics->waveforms[waveform->manual_trigger] = *waveform; diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h index ff57e537ffe..74c1f4c092a 100644 --- a/dlls/winebus.sys/unix_private.h +++ b/dlls/winebus.sys/unix_private.h @@ -121,19 +121,25 @@ struct hid_report_descriptor BYTE next_report_id[3]; };
-enum haptics_waveform_index +/* HID spec uses None / Stop names for the first two implicit waveforms, + * where Windows SDK headers use STOP / NULL for the corresponding HID + * usage constants. We're not actually using the usages anyway are we + * stick to the HID spec here. + */ +enum haptics_waveform_ordinal { - HAPTICS_WAVEFORM_STOP_INDEX = 1, - HAPTICS_WAVEFORM_NULL_INDEX = 2, - HAPTICS_WAVEFORM_RUMBLE_INDEX = 3, - HAPTICS_WAVEFORM_BUZZ_INDEX = 4, - HAPTICS_WAVEFORM_LAST_INDEX = HAPTICS_WAVEFORM_BUZZ_INDEX, + HAPTICS_WAVEFORM_NONE_ORDINAL = 1, /* implicit, not included in waveform_list / duration_list */ + HAPTICS_WAVEFORM_STOP_ORDINAL = 2, /* implicit, not included in waveform_list / duration_list */ + HAPTICS_WAVEFORM_RUMBLE_ORDINAL = 3, + HAPTICS_WAVEFORM_BUZZ_ORDINAL = 4, + HAPTICS_WAVEFORM_FIRST_ORDINAL = HAPTICS_WAVEFORM_RUMBLE_ORDINAL, + HAPTICS_WAVEFORM_LAST_ORDINAL = HAPTICS_WAVEFORM_BUZZ_ORDINAL, };
struct hid_haptics_features { - WORD waveform_list[HAPTICS_WAVEFORM_LAST_INDEX - HAPTICS_WAVEFORM_NULL_INDEX]; - WORD duration_list[HAPTICS_WAVEFORM_LAST_INDEX - HAPTICS_WAVEFORM_NULL_INDEX]; + WORD waveform_list[HAPTICS_WAVEFORM_LAST_ORDINAL - HAPTICS_WAVEFORM_FIRST_ORDINAL + 1]; + WORD duration_list[HAPTICS_WAVEFORM_LAST_ORDINAL - HAPTICS_WAVEFORM_FIRST_ORDINAL + 1]; UINT waveform_cutoff_time_ms; };
@@ -146,7 +152,7 @@ struct hid_haptics_waveform struct hid_haptics { struct hid_haptics_features features; - struct hid_haptics_waveform waveforms[HAPTICS_WAVEFORM_LAST_INDEX + 1]; + struct hid_haptics_waveform waveforms[HAPTICS_WAVEFORM_LAST_ORDINAL + 1]; BYTE features_report; BYTE waveform_report; };
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/xinput1_3/main.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c index 7917b9f7af2..e669fa0af71 100644 --- a/dlls/xinput1_3/main.c +++ b/dlls/xinput1_3/main.c @@ -81,8 +81,8 @@ struct xinput_controller char *feature_report_buf;
BYTE haptics_report; - BYTE haptics_rumble_index; - BYTE haptics_buzz_index; + BYTE haptics_rumble_ordinal; + BYTE haptics_buzz_ordinal; } hid; };
@@ -244,21 +244,21 @@ static BOOL controller_check_caps(struct xinput_controller *controller, HANDLE d return TRUE; }
- controller->hid.haptics_buzz_index = 0; - controller->hid.haptics_rumble_index = 0; + controller->hid.haptics_buzz_ordinal = 0; + controller->hid.haptics_rumble_ordinal = 0; for (i = 3; status == HIDP_STATUS_SUCCESS; ++i) { ULONG waveform = 0; status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, i, &waveform, preparsed, report_buf, report_len); if (status != HIDP_STATUS_SUCCESS) WARN("HidP_GetUsageValue returned %#lx\n", status); - else if (waveform == HID_USAGE_HAPTICS_WAVEFORM_BUZZ) controller->hid.haptics_buzz_index = i; - else if (waveform == HID_USAGE_HAPTICS_WAVEFORM_RUMBLE) controller->hid.haptics_rumble_index = i; + else if (waveform == HID_USAGE_HAPTICS_WAVEFORM_BUZZ) controller->hid.haptics_buzz_ordinal = i; + else if (waveform == HID_USAGE_HAPTICS_WAVEFORM_RUMBLE) controller->hid.haptics_rumble_ordinal = i; }
- if (!controller->hid.haptics_buzz_index) WARN("haptics buzz not supported\n"); - if (!controller->hid.haptics_rumble_index) WARN("haptics rumble not supported\n"); - if (!controller->hid.haptics_rumble_index && !controller->hid.haptics_buzz_index) return TRUE; + if (!controller->hid.haptics_buzz_ordinal) WARN("haptics buzz not supported\n"); + if (!controller->hid.haptics_rumble_ordinal) WARN("haptics rumble not supported\n"); + if (!controller->hid.haptics_rumble_ordinal && !controller->hid.haptics_buzz_ordinal) return TRUE;
caps_count = 1; status = HidP_GetSpecificValueCaps(HidP_Output, HID_USAGE_PAGE_HAPTICS, 0, HID_USAGE_HAPTICS_MANUAL_TRIGGER, @@ -298,7 +298,7 @@ static DWORD HID_set_state(struct xinput_controller *controller, XINPUT_VIBRATIO state->wLeftMotorSpeed, preparsed, report_buf, report_len); if (status != HIDP_STATUS_SUCCESS) WARN("HidP_SetUsageValue INTENSITY returned %#lx\n", status); status = HidP_SetUsageValue(HidP_Output, HID_USAGE_PAGE_HAPTICS, 0, HID_USAGE_HAPTICS_MANUAL_TRIGGER, - controller->hid.haptics_rumble_index, preparsed, report_buf, report_len); + controller->hid.haptics_rumble_ordinal, preparsed, report_buf, report_len); if (status != HIDP_STATUS_SUCCESS) WARN("HidP_SetUsageValue MANUAL_TRIGGER returned %#lx\n", status); if (!HidD_SetOutputReport(controller->device, report_buf, report_len)) { @@ -313,7 +313,7 @@ static DWORD HID_set_state(struct xinput_controller *controller, XINPUT_VIBRATIO state->wRightMotorSpeed, preparsed, report_buf, report_len); if (status != HIDP_STATUS_SUCCESS) WARN("HidP_SetUsageValue INTENSITY returned %#lx\n", status); status = HidP_SetUsageValue(HidP_Output, HID_USAGE_PAGE_HAPTICS, 0, HID_USAGE_HAPTICS_MANUAL_TRIGGER, - controller->hid.haptics_buzz_index, preparsed, report_buf, report_len); + controller->hid.haptics_buzz_ordinal, preparsed, report_buf, report_len); if (status != HIDP_STATUS_SUCCESS) WARN("HidP_SetUsageValue MANUAL_TRIGGER returned %#lx\n", status); if (!HidD_SetOutputReport(controller->device, report_buf, report_len)) {