Skip to content

Commit 220895d

Browse files
Lawstorantslouken
authored andcommitted
[SDL2] Add SDL_HINT_JOYSTICK_HAPTIC_AXES
Allows users to overwrite the number of haptic axes defined for a given joystick. Also supports a "wildcard" VID:PID of 0xFFFF/0xFFFF (cherry picked from commit 0809be4)
1 parent 282f7a8 commit 220895d

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed

include/SDL_hints.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,6 +1423,27 @@ extern "C" {
14231423
*/
14241424
#define SDL_HINT_JOYSTICK_DEVICE "SDL_JOYSTICK_DEVICE"
14251425

1426+
1427+
/**
1428+
* A variable containing a list of devices and their desired number of haptic
1429+
* (force feedback) enabled axis.
1430+
*
1431+
* The format of the string is a comma separated list of USB VID/PID pairs in
1432+
* hexadecimal form plus the number of desired axes, e.g.
1433+
*
1434+
* `0xAAAA/0xBBBB/1,0xCCCC/0xDDDD/3`
1435+
*
1436+
* This hint supports a "wildcard" device that will set the number of haptic
1437+
* axes on all initialized haptic devices which were not defined explicitly
1438+
* in this hint.
1439+
*
1440+
* `0xFFFF/0xFFFF/1`
1441+
*
1442+
* This hint should be set before a controller is opened. The number of
1443+
* haptic axes won't exceed the number of real axes found on the device.
1444+
*/
1445+
#define SDL_HINT_JOYSTICK_HAPTIC_AXES "SDL_JOYSTICK_HAPTIC_AXES"
1446+
14261447
/**
14271448
* A variable controlling whether joysticks on Linux will always treat 'hat'
14281449
* axis inputs (ABS_HAT0X - ABS_HAT3Y) as 8-way digital hats without checking

src/haptic/SDL_haptic.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,85 @@
2323
#include "SDL_syshaptic.h"
2424
#include "SDL_haptic_c.h"
2525
#include "../joystick/SDL_joystick_c.h" /* For SDL_PrivateJoystickValid */
26+
#include "SDL_hints.h"
27+
#include "../SDL_hints_c.h"
28+
29+
typedef struct SDL_Haptic_VIDPID_Naxes {
30+
Uint16 vid;
31+
Uint16 pid;
32+
Uint16 naxes;
33+
} SDL_Haptic_VIDPID_Naxes;
34+
35+
static void SDL_HapticLoadAxesList(SDL_Haptic_VIDPID_Naxes **entries, int *num_entries)
36+
{
37+
SDL_Haptic_VIDPID_Naxes entry;
38+
const char *spot;
39+
int length = 0;
40+
41+
spot = SDL_GetHint(SDL_HINT_JOYSTICK_HAPTIC_AXES);
42+
if (!spot)
43+
return;
44+
45+
while (SDL_sscanf(spot, "0x%hx/0x%hx/%hu%n", &entry.vid, &entry.pid, &entry.naxes, &length) == 3) {
46+
SDL_assert(length > 0);
47+
spot += length;
48+
length = 0;
49+
50+
if ((*num_entries % 8) == 0) {
51+
int new_max = *num_entries + 8;
52+
SDL_Haptic_VIDPID_Naxes *new_entries =
53+
(SDL_Haptic_VIDPID_Naxes *)SDL_realloc(*entries, new_max * sizeof(**entries));
54+
55+
// Out of memory, go with what we have already
56+
if (!new_entries)
57+
break;
58+
59+
*entries = new_entries;
60+
}
61+
(*entries)[(*num_entries)++] = entry;
62+
63+
if (spot[0] == ',')
64+
spot++;
65+
}
66+
}
67+
68+
// /* Return -1 if not found */
69+
static int SDL_HapticNaxesListIndex(struct SDL_Haptic_VIDPID_Naxes *entries, int num_entries, Uint16 vid, Uint16 pid)
70+
{
71+
int i;
72+
if (!entries)
73+
return -1;
74+
75+
for (i = 0; i < num_entries; ++i) {
76+
if (entries[i].vid == vid && entries[i].pid == pid)
77+
return i;
78+
}
79+
80+
return -1;
81+
}
82+
83+
// Check if device needs a custom number of naxes
84+
static int SDL_HapticGetNaxes(Uint16 vid, Uint16 pid)
85+
{
86+
int num_entries = 0, index = 0, naxes = -1;
87+
SDL_Haptic_VIDPID_Naxes *naxes_list = NULL;
88+
89+
SDL_HapticLoadAxesList(&naxes_list, &num_entries);
90+
if (!num_entries || !naxes_list)
91+
return -1;
92+
93+
// Perform "wildcard" pass
94+
index = SDL_HapticNaxesListIndex(naxes_list, num_entries, 0xffff, 0xffff);
95+
if (index >= 0)
96+
naxes = naxes_list[index].naxes;
97+
98+
index = SDL_HapticNaxesListIndex(naxes_list, num_entries, vid, pid);
99+
if (index >= 0)
100+
naxes = naxes_list[index].naxes;
101+
102+
SDL_free(naxes_list);
103+
return naxes;
104+
}
26105

27106
/* Global for SDL_windowshaptic.c */
28107
#if defined(SDL_HAPTIC_DINPUT) || defined(SDL_HAPTIC_XINPUT)
@@ -258,6 +337,8 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick)
258337
{
259338
SDL_Haptic *haptic;
260339
SDL_Haptic *hapticlist;
340+
int naxes, general_axes;
341+
Uint16 vid, pid;
261342

262343
/* Make sure there is room. */
263344
if (SDL_NumHaptics() <= 0) {
@@ -314,6 +395,18 @@ SDL_Haptic *SDL_HapticOpenFromJoystick(SDL_Joystick *joystick)
314395
}
315396
SDL_UnlockJoysticks();
316397

398+
vid = SDL_JoystickGetVendor(joystick);
399+
pid = SDL_JoystickGetProduct(joystick);
400+
general_axes = SDL_JoystickNumAxes(joystick);
401+
402+
naxes = SDL_HapticGetNaxes(vid, pid);
403+
if (naxes > 0)
404+
haptic->naxes = naxes;
405+
406+
// Limit to the actual number of axes found on the device
407+
if (general_axes >= 0 && naxes > general_axes)
408+
haptic->naxes = general_axes;
409+
317410
/* Add haptic to list */
318411
++haptic->ref_count;
319412
/* Link the haptic in the list */

0 commit comments

Comments
 (0)