| Summary: | Wired Switch Pro controller inconsistently rumbles in SDL 2.0.12 | ||
|---|---|---|---|
| Product: | SDL | Reporter: | RustyM <rustym> |
| Component: | haptic | Assignee: | Ryan C. Gordon <icculus> |
| Status: | NEW --- | QA Contact: | Sam Lantinga <slouken> |
| Severity: | major | ||
| Priority: | P2 | ||
| Version: | 2.0.12 | ||
| Hardware: | All | ||
| OS: | All | ||
|
Description
RustyM
2020-03-15 18:02:25 UTC
I’ve been working on this more lately since this bug is preventing me from moving to 2.0.12
Just discovered this issue ONLY happens when a Switch Pro controller is wired. Over Bluetooth I haven’t seen it happen on Windows or Mac. With that in mind, I started looking into “changeset 13765”:
Don't send rumble packets too quickly to Nintendo Switch Pro controllers over Bluetooth
https://hg.libsdl.org/SDL/rev/0b12c0e43e6c
This change happened 4 weeks after I found this bug, so it’s not the cause. Moreover, I think it provides a clue to a partial solution:
/* How often you have to refresh a long duration rumble to keep the motors running */
#define RUMBLE_REFRESH_FREQUENCY_MS 40
I’m guessing this rumble refresh timer was figured out over Bluetooth. So I split this into two defines:
/* How often you have to refresh a long duration rumble to keep the motors running */
#define RUMBLE_REFRESH_FREQUENCY_MS_BLUETOOTH 40
/* Wired controllers require a longer refresh duration or they'll sometimes continue to rumble beyond the stop call */
#define RUMBLE_REFRESH_FREQUENCY_MS_WIRED 1000
Through experimentation I found the 1000 ms wired refresh rate. 1050 ms wasn’t enough to keep a long rumble going over a Wired connection. Then later on in the code I added a check for m_bUsingBluetooth:
SDL_TICKS_PASSED(SDL_GetTicks(), ctx->m_unRumbleSent + (ctx->m_bUsingBluetooth ? RUMBLE_REFRESH_FREQUENCY_MS_BLUETOOTH : RUMBLE_REFRESH_FREQUENCY_MS_WIRED))) {
These two changes to "SDK_hidapi_switch.c" fix the inconsistent rumble in many cases. I haven’t been able to replicate the issue in “testgamecontroller” anymore. Unfortunately it still happens in my own code, though far less frequently.
I can’t yet get it to happen consistently, but I think it has something to do with complex uses of SDL_GameControllerRumble(). Perhaps when I tell a long rumble to stop, and then soon after start a new rumble, the wires get crossed somewhere? Like it queues up a call to stop a rumble or refresh a rumble and it gets confused or some buffer doesn’t get cleared? The results of the bug is what I listed in my original post: Sometimes a rumble told to “stop”, doesn’t actually stop and continues longer than it should. And then sometimes just after this a surprisingly strong rumble happens.
|