There are a number of poorly behaved HID devices that time out on attempts to
read various strings. Rather than end up on an endless treadmill of blacklisting
broken devices, reduce our risk by only querying devices that are gamepads.
SDL_hidapijoystick.c already checks these same usages, so we shouldn't
exclude any working HID devices (caveat below).
This also makes HidP_GetPreparsedData() and HidP_GetCaps() failure skip
the device entirely, but that seems desired. If a device can't even return basic
top-level collection data properly, we want nothing to do with that broken device.
If we do find devices that work with HIDAPI joystick and fail these calls, we can
add an exception via VID+PID matching.
bluenaxela+sdl
The HORI Wireless Switch Pad does not properly connect via bluetooth. I did some debugging and found that the code that tries to control the Home LED causes this controller to disconnect.
This results in a dlsym() call, which causes Emscripten to panic if the game
wasn't explicitly built dlopen support. eglGetProcAddress works just fine on
this platform, so just let that codepath handle it.
Eric Jing
When the project directory path contains spaces, CMake butchers the include path for the hidapi files.
I traced the problem to the cmake/sdlchecks.cmake file at line 1091, which sets flags for the build process. I surrounded the problem flag with double quotes, shown below, and CMake works with spaces in the project directory path.
This is a multi-part fix, and is the 2nd attempt at a fix for Bug 5034. Here
are the problems being addressed:
1. On macOS 10.14.x and earlier, trying to call IOHIDDeviceUnscheduleFromRunLoop
without a prior, paired call to IOHIDDeviceScheduleWithRunLoop, appears to
lead to a crash. A per-device flag has been added to make sure that these
calls are paired.
2. DARWIN_JoystickDetect was free'ing its SDL_joystick's hwdata field
(via FreeDevice) without setting it to NULL, and DARWIN_JoystickRumble wasn't
checking for a NULL hwdata. FreeDevice will now set hwdata to NULL and
DARWIN_JoystickRumble will check for a NULL hwdata.
meyraud705
Added Linux implementation, otherwise you get "Unsupported direction type" error.
Added documentation to explain why one would use SDL_HAPTIC_FIRST_AXIS.
Mathieu Laurendeau
Consider a device supporting effects on multiple axes.
There's currently no way to play effects against a single-axis direction.
A device supporting effects against X and Y may not allow to play effects with a two-axis direction coordinate, even if one of the coordinates is null.
My current (ugly) work around for this is to add a direction type SDL_HAPTIC_X_FORCE to play effects against a X-axis only direction (patch attached).
This issue impacted two GIMX users using the following wheels:
- Leo Bodnar SimSteering force feedback wheel
- Accuforce direct drive wheel
Playing constant/spring/damper effects against a X-axis direction worked well for the first wheel, but not for the second one.
A better strategy seems to play the effects against the first axis reported by the DirectInput enumeration.
This strategy also works with Logitech wheels (at least the DFGT).
It's been more than a year that I have the latest patch (playing effects against the first axis only) in the GIMX software. It's being used by thousands of people, mostly for adapting their FFB wheel to the PS4. I had no report that proves this strategy to be wrong.
Jimb Esser
Add new RawInput controller API, and improved correlation with XInput/WGI
Reorder joystick init so drivers can ask the others if they handle a device reliably
Do not poll disconnected XInput devices (major perf issue)
Fix various cases where incorrect correlation could happen
Simple mechanism for propagating unhandled Guide button presses even before guaranteed correlation
Correlate by axis motion as well as button presses
Fix failing to zero other trigger
Fix SDL_HINT_JOYSTICK_HIDAPI not working if set before calling SDL_Init()
Add missing device to device names
Disable RawInput if we have a mismatch of XInput-capable but not RawInput-capable devices
Updated to SDL 2.0.13 code with the following notes:
New HID driver: xbox360w - no idea what that is, hopefully urelated
SDL_hidapijoystick.c had been refactored to couple data handling logic with device opening logic and device lists caused some problems, yields slightly uglier integration than previously when the 360 HID device driver was just handling the data.
SDL_hidapijoystick.c now often pulls the device off of the joystick_hwdata structure for some rumble logic, but it appears that code path is never reached, so probably not a problem.
Looks like joystick_hwdata was refactored to not include a mutex in other drivers, maintainers may want to do the same refactor here if that's useful for some reason.
Something changed in how devices get names, so getting generic names.
Had to fix a (new?) bug where removing an XInput controller caused existing controllers (that moved to a new XInput index) to get identified as 0x045e/0x02fd ("it's probably Bluetooth" in code), rendering the existing HIDAPI_IsDevicePresent and new RAWINPUT_IsDevicePresent unreliable.
Jimb Esser
Add new RawInput controller API, and improved correlation with XInput/WGI
Reorder joystick init so drivers can ask the others if they handle a device reliably
Do not poll disconnected XInput devices (major perf issue)
Fix various cases where incorrect correlation could happen
Simple mechanism for propagating unhandled Guide button presses even before guaranteed correlation
Correlate by axis motion as well as button presses
Fix failing to zero other trigger
Fix SDL_HINT_JOYSTICK_HIDAPI not working if set before calling SDL_Init()
Add missing device to device names
Disable RawInput if we have a mismatch of XInput-capable but not RawInput-capable devices
Updated to SDL 2.0.13 code with the following notes:
New HID driver: xbox360w - no idea what that is, hopefully urelated
SDL_hidapijoystick.c had been refactored to couple data handling logic with device opening logic and device lists caused some problems, yields slightly uglier integration than previously when the 360 HID device driver was just handling the data.
SDL_hidapijoystick.c now often pulls the device off of the joystick_hwdata structure for some rumble logic, but it appears that code path is never reached, so probably not a problem.
Looks like joystick_hwdata was refactored to not include a mutex in other drivers, maintainers may want to do the same refactor here if that's useful for some reason.
Something changed in how devices get names, so getting generic names.
Had to fix a (new?) bug where removing an XInput controller caused existing controllers (that moved to a new XInput index) to get identified as 0x045e/0x02fd ("it's probably Bluetooth" in code), rendering the existing HIDAPI_IsDevicePresent and new RAWINPUT_IsDevicePresent unreliable.
Malte Kie?ling
I get a build error in SDL_sysjoystick.c:74 for the merged patch, but its nothing to sweat about, just -Werror=declaration-after-statement doing its usual stuff.
David Ludwig
I have created a new driver for SDL's Joystick and Game-Controller subsystem: a Virtual driver. This driver allows one to create a software-based joystick, which to SDL applications will look and react like a real joystick, but whose state can be set programmatically. A primary use case for this is to help enable developers to add touch-screen joysticks to their apps.
The driver comes with a set of new, public APIs, with functions to attach and detach joysticks, set virtual-joystick state, and to determine if a joystick is a virtual-one.
Use of virtual joysticks goes as such:
1. Attach one or more virtual joysticks by calling SDL_JoystickAttachVirtual. If successful, this returns the virtual-device's joystick-index.
2. Open the virtual joysticks (using indicies returned by SDL_JoystickAttachVirtual).
3. Call any of the SDL_JoystickSetVirtual* functions when joystick-state changes. Please note that virtual-joystick state will only get applied on the next call to SDL_JoystickUpdate, or when pumping or polling for SDL events (via SDL_PumpEvents or SDL_PollEvent).
Here is a listing of the new, public APIs, at present and subject to change:
------------------------------------------------------------
/**
* Attaches a new virtual joystick.
* Returns the joystick's device index, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type, int naxes, int nballs, int nbuttons, int nhats);
/**
* Detaches a virtual joystick
* Returns 0 on success, or -1 if an error occurred.
*/
extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
/**
* Indicates whether or not a virtual-joystick is at a given device index.
*/
extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
/**
* Set values on an opened, virtual-joystick's controls.
* Returns 0 on success, -1 on error.
*/
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick * joystick, int axis, Sint16 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualBall(SDL_Joystick * joystick, int ball, Sint16 xrel, Sint16 yrel);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick * joystick, int button, Uint8 value);
extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick * joystick, int hat, Uint8 value);
------------------------------------------------------------
Miscellaneous notes on the initial patch, which are also subject to change:
1. no test code is present in SDL, yet. This should, perhaps, change. Initial development was done with an ImGui-based app, which potentially is too thick for use in SDL-official. If tests are to be added, what kind of tests? Automated? Graphical?
2. virtual game controllers can be created by calling SDL_JoystickAttachVirtual with a joystick-type of SDL_JOYSTICK_TYPE_GAME_CONTROLLER, with naxes (num axes) set to SDL_CONTROLLER_AXIS_MAX, and with nbuttons (num buttons) set to SDL_CONTROLLER_BUTTON_MAX. When updating their state, values of type SDL_GameControllerAxis or SDL_GameControllerButton can be casted to an int and used for the control-index (in calls to SDL_JoystickSetVirtual* functions).
3. virtual joysticks' guids are mostly all-zeros with the exception of the last two bytes, the first of which is a 'v', to indicate that the guid is a virtual one, and the second of which is a SDL_JoystickType that has been converted into a Uint8.
4. virtual joysticks are ONLY turned into virtual game-controllers if and when their joystick-type is set to SDL_JOYSTICK_TYPE_GAMECONTROLLER. This is controlled by having SDL's default list of game-controllers have a single entry for a virtual game controller (of guid, "00000000000000000000000000007601", which is subject to the guid-encoding described above).
5. regarding having to call SDL_JoystickUpdate, either directly or indirectly via SDL_PumpEvents or SDL_PollEvents, before new virtual-joystick state becomes active (as specified via SDL_JoystickSetVirtual* function-calls), this was done to match behavior found in SDL's other joystick drivers, almost all of which will only update SDL-state during SDL_JoystickUpdate.
6. the initial patch is based off of SDL 2.0.12
7. the virtual joystick subsystem is disabled by default. It should be possible to enable it by building with SDL_JOYSTICK_VIRTUAL=1
Questions, comments, suggestions, or bug reports very welcome!