Rémi Bernon : winebus.sys: Send PID effect state reports for SDL devices.
Alexandre Julliard
julliard at winehq.org
Thu Dec 2 15:30:16 CST 2021
Module: wine
Branch: master
Commit: 3ed121bffa3d1a4394277a532edb150c6b4bebfd
URL: https://source.winehq.org/git/wine.git/?a=commit;h=3ed121bffa3d1a4394277a532edb150c6b4bebfd
Author: Rémi Bernon <rbernon at codeweavers.com>
Date: Thu Dec 2 10:47:48 2021 +0100
winebus.sys: Send PID effect state reports for SDL devices.
Checking for effect state updates periodically, as well as whenever the
device state changes but not more than once every 10ms.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52062
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/winebus.sys/bus_sdl.c | 62 +++++++++++++++++++++++++++++++++++++----
dlls/winebus.sys/hid.c | 8 ++++++
dlls/winebus.sys/unix_private.h | 2 ++
3 files changed, 66 insertions(+), 6 deletions(-)
diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c
index 254971e1185..76d90ab7912 100644
--- a/dlls/winebus.sys/bus_sdl.c
+++ b/dlls/winebus.sys/bus_sdl.c
@@ -78,7 +78,7 @@ MAKE_FUNCPTR(SDL_JoystickInstanceID);
MAKE_FUNCPTR(SDL_JoystickName);
MAKE_FUNCPTR(SDL_JoystickNumAxes);
MAKE_FUNCPTR(SDL_JoystickOpen);
-MAKE_FUNCPTR(SDL_WaitEvent);
+MAKE_FUNCPTR(SDL_WaitEventTimeout);
MAKE_FUNCPTR(SDL_JoystickNumButtons);
MAKE_FUNCPTR(SDL_JoystickNumBalls);
MAKE_FUNCPTR(SDL_JoystickNumHats);
@@ -93,6 +93,7 @@ MAKE_FUNCPTR(SDL_GameControllerOpen);
MAKE_FUNCPTR(SDL_GameControllerEventState);
MAKE_FUNCPTR(SDL_HapticClose);
MAKE_FUNCPTR(SDL_HapticDestroyEffect);
+MAKE_FUNCPTR(SDL_HapticGetEffectStatus);
MAKE_FUNCPTR(SDL_HapticNewEffect);
MAKE_FUNCPTR(SDL_HapticOpenFromJoystick);
MAKE_FUNCPTR(SDL_HapticPause);
@@ -110,6 +111,7 @@ MAKE_FUNCPTR(SDL_JoystickIsHaptic);
MAKE_FUNCPTR(SDL_GameControllerAddMapping);
MAKE_FUNCPTR(SDL_RegisterEvents);
MAKE_FUNCPTR(SDL_PushEvent);
+MAKE_FUNCPTR(SDL_GetTicks);
static int (*pSDL_JoystickRumble)(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
static Uint16 (*pSDL_JoystickGetProduct)(SDL_Joystick * joystick);
static Uint16 (*pSDL_JoystickGetProductVersion)(SDL_Joystick * joystick);
@@ -136,6 +138,8 @@ struct sdl_device
SDL_Haptic *sdl_haptic;
int haptic_effect_id;
int effect_ids[256];
+ int effect_state[256];
+ LONG effect_flags;
};
static inline struct sdl_device *impl_from_unix_device(struct unix_device *iface)
@@ -453,9 +457,11 @@ static NTSTATUS sdl_device_physical_device_control(struct unix_device *iface, US
{
case PID_USAGE_DC_ENABLE_ACTUATORS:
pSDL_HapticSetGain(impl->sdl_haptic, 100);
+ InterlockedOr(&impl->effect_flags, EFFECT_STATE_ACTUATORS_ENABLED);
return STATUS_SUCCESS;
case PID_USAGE_DC_DISABLE_ACTUATORS:
pSDL_HapticSetGain(impl->sdl_haptic, 0);
+ InterlockedAnd(&impl->effect_flags, ~EFFECT_STATE_ACTUATORS_ENABLED);
return STATUS_SUCCESS;
case PID_USAGE_DC_STOP_ALL_EFFECTS:
pSDL_HapticStopAll(impl->sdl_haptic);
@@ -471,9 +477,11 @@ static NTSTATUS sdl_device_physical_device_control(struct unix_device *iface, US
return STATUS_SUCCESS;
case PID_USAGE_DC_DEVICE_PAUSE:
pSDL_HapticPause(impl->sdl_haptic);
+ InterlockedOr(&impl->effect_flags, EFFECT_STATE_DEVICE_PAUSED);
return STATUS_SUCCESS;
case PID_USAGE_DC_DEVICE_CONTINUE:
pSDL_HapticUnpause(impl->sdl_haptic);
+ InterlockedAnd(&impl->effect_flags, ~EFFECT_STATE_DEVICE_PAUSED);
return STATUS_SUCCESS;
}
@@ -686,6 +694,42 @@ static const struct hid_device_vtbl sdl_device_vtbl =
sdl_device_physical_effect_update,
};
+static void check_device_effects_state(struct sdl_device *impl)
+{
+ struct unix_device *iface = &impl->unix_device;
+ struct hid_effect_state *effect_state = &iface->hid_physical.effect_state;
+ ULONG effect_flags = InterlockedOr(&impl->effect_flags, 0);
+ unsigned int i, ret;
+
+ if (!impl->sdl_haptic) return;
+ if (!(impl->effect_support & SDL_HAPTIC_STATUS)) return;
+
+ for (i = 0; i < ARRAY_SIZE(impl->effect_ids); ++i)
+ {
+ if (impl->effect_ids[i] == -1) continue;
+ ret = pSDL_HapticGetEffectStatus(impl->sdl_haptic, impl->effect_ids[i]);
+ if (impl->effect_state[i] == ret) continue;
+ impl->effect_state[i] = ret;
+ hid_device_set_effect_state(iface, i, effect_flags | (ret == 1 ? EFFECT_STATE_EFFECT_PLAYING : 0));
+ bus_event_queue_input_report(&event_queue, iface, effect_state->report_buf, effect_state->report_len);
+ }
+}
+
+static void check_all_devices_effects_state(void)
+{
+ static UINT last_ticks = 0;
+ UINT ticks = pSDL_GetTicks();
+ struct sdl_device *impl;
+
+ if (ticks - last_ticks < 10) return;
+ last_ticks = ticks;
+
+ pthread_mutex_lock(&sdl_cs);
+ LIST_FOR_EACH_ENTRY(impl, &device_list, struct sdl_device, unix_device.entry)
+ check_device_effects_state(impl);
+ pthread_mutex_unlock(&sdl_cs);
+}
+
static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *event)
{
struct unix_device *iface = &impl->unix_device;
@@ -693,7 +737,7 @@ static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *e
if (impl->sdl_controller) return TRUE; /* use controller events instead */
- switch(event->type)
+ switch (event->type)
{
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
@@ -732,6 +776,8 @@ static BOOL set_report_from_joystick_event(struct sdl_device *impl, SDL_Event *e
default:
ERR("TODO: Process Report (0x%x)\n",event->type);
}
+
+ check_device_effects_state(impl);
return FALSE;
}
@@ -740,7 +786,7 @@ static BOOL set_report_from_controller_event(struct sdl_device *impl, SDL_Event
struct unix_device *iface = &impl->unix_device;
struct hid_device_state *state = &iface->hid_device_state;
- switch(event->type)
+ switch (event->type)
{
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
@@ -786,6 +832,8 @@ static BOOL set_report_from_controller_event(struct sdl_device *impl, SDL_Event
default:
ERR("TODO: Process Report (%x)\n",event->type);
}
+
+ check_device_effects_state(impl);
return FALSE;
}
@@ -924,7 +972,7 @@ NTSTATUS sdl_bus_init(void *args)
LOAD_FUNCPTR(SDL_JoystickName);
LOAD_FUNCPTR(SDL_JoystickNumAxes);
LOAD_FUNCPTR(SDL_JoystickOpen);
- LOAD_FUNCPTR(SDL_WaitEvent);
+ LOAD_FUNCPTR(SDL_WaitEventTimeout);
LOAD_FUNCPTR(SDL_JoystickNumButtons);
LOAD_FUNCPTR(SDL_JoystickNumBalls);
LOAD_FUNCPTR(SDL_JoystickNumHats);
@@ -939,6 +987,7 @@ NTSTATUS sdl_bus_init(void *args)
LOAD_FUNCPTR(SDL_GameControllerEventState);
LOAD_FUNCPTR(SDL_HapticClose);
LOAD_FUNCPTR(SDL_HapticDestroyEffect);
+ LOAD_FUNCPTR(SDL_HapticGetEffectStatus);
LOAD_FUNCPTR(SDL_HapticNewEffect);
LOAD_FUNCPTR(SDL_HapticOpenFromJoystick);
LOAD_FUNCPTR(SDL_HapticPause);
@@ -956,6 +1005,7 @@ NTSTATUS sdl_bus_init(void *args)
LOAD_FUNCPTR(SDL_GameControllerAddMapping);
LOAD_FUNCPTR(SDL_RegisterEvents);
LOAD_FUNCPTR(SDL_PushEvent);
+ LOAD_FUNCPTR(SDL_GetTicks);
#undef LOAD_FUNCPTR
pSDL_JoystickRumble = dlsym(sdl_handle, "SDL_JoystickRumble");
pSDL_JoystickGetProduct = dlsym(sdl_handle, "SDL_JoystickGetProduct");
@@ -1013,8 +1063,8 @@ NTSTATUS sdl_bus_wait(void *args)
do
{
if (bus_event_queue_pop(&event_queue, result)) return STATUS_PENDING;
- if (pSDL_WaitEvent(&event) != 0) process_device_event(&event);
- else WARN("SDL_WaitEvent failed: %s\n", pSDL_GetError());
+ if (pSDL_WaitEventTimeout(&event, 10) != 0) process_device_event(&event);
+ else check_all_devices_effects_state();
} while (event.type != quit_event);
TRACE("SDL main loop exiting\n");
diff --git a/dlls/winebus.sys/hid.c b/dlls/winebus.sys/hid.c
index 29d5debcfe2..8680f8a088c 100644
--- a/dlls/winebus.sys/hid.c
+++ b/dlls/winebus.sys/hid.c
@@ -1405,3 +1405,11 @@ void hid_device_drop_report(struct unix_device *iface)
{
iface->hid_device_state.dropped = TRUE;
}
+
+void hid_device_set_effect_state(struct unix_device *iface, BYTE index, BYTE flags)
+{
+ struct hid_effect_state *state = &iface->hid_physical.effect_state;
+ struct pid_effect_state *report = (struct pid_effect_state *)(state->report_buf + 1);
+ report->index = index;
+ report->flags = flags;
+}
diff --git a/dlls/winebus.sys/unix_private.h b/dlls/winebus.sys/unix_private.h
index 564fec9fc3a..efecf6cdbe3 100644
--- a/dlls/winebus.sys/unix_private.h
+++ b/dlls/winebus.sys/unix_private.h
@@ -262,6 +262,8 @@ extern BOOL hid_device_set_hatswitch_y(struct unix_device *iface, ULONG index, L
extern BOOL hid_device_sync_report(struct unix_device *iface) DECLSPEC_HIDDEN;
extern void hid_device_drop_report(struct unix_device *iface) DECLSPEC_HIDDEN;
+extern void hid_device_set_effect_state(struct unix_device *iface, BYTE index, BYTE flags) DECLSPEC_HIDDEN;
+
BOOL is_xbox_gamepad(WORD vid, WORD pid) DECLSPEC_HIDDEN;
BOOL is_dualshock4_gamepad(WORD vid, WORD pid) DECLSPEC_HIDDEN;
More information about the wine-cvs
mailing list