21 #include "../../SDL_internal.h"
23 #ifdef SDL_JOYSTICK_LINUX
25 #ifndef SDL_INPUT_LINUXEV
26 #error SDL now requires a Linux 2.4+ kernel with /dev/input/event support.
36 #include <sys/inotify.h>
38 #include <sys/ioctl.h>
41 #include <linux/joystick.h>
48 #include "../../events/SDL_events_c.h"
49 #include "../SDL_sysjoystick.h"
50 #include "../SDL_joystick_c.h"
51 #include "../steam/SDL_steamcontroller.h"
52 #include "SDL_sysjoystick_c.h"
53 #include "../hidapi/SDL_hidapijoystick_c.h"
60 #define BTN_SOUTH 0x130
63 #define BTN_EAST 0x131
66 #define BTN_NORTH 0x133
69 #define BTN_WEST 0x134
72 #define BTN_DPAD_UP 0x220
75 #define BTN_DPAD_DOWN 0x221
78 #define BTN_DPAD_LEFT 0x222
80 #ifndef BTN_DPAD_RIGHT
81 #define BTN_DPAD_RIGHT 0x223
84 #include "../../core/linux/SDL_evdev_capabilities.h"
85 #include "../../core/linux/SDL_udev.h"
88 #define DEBUG_INPUT_EVENTS 1
98 static EnumerationMethod enumeration_method = ENUMERATION_UNSET;
100 static int MaybeAddDevice(
const char *
path);
101 static int MaybeRemoveDevice(
const char *
path);
104 typedef struct SDL_joylist_item
112 struct SDL_joylist_item *next;
118 static SDL_joylist_item *SDL_joylist =
NULL;
119 static SDL_joylist_item *SDL_joylist_tail =
NULL;
121 static int inotify_fd = -1;
123 static Uint32 last_joy_detect_time;
124 static time_t last_input_dir_mtime;
127 FixupDeviceInfoForMapping(
int fd,
struct input_id *inpid)
129 if (inpid->vendor == 0x045e && inpid->product == 0x0b05 && inpid->version == 0x0903) {
131 unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
134 if ((ioctl(
fd, EVIOCGBIT(EV_KEY,
sizeof(keybit)), keybit) >= 0) &&
135 test_bit(0x2c0, keybit)) {
137 inpid->version = 0x0902;
142 #ifdef SDL_JOYSTICK_HIDAPI
156 GuessIsJoystick(
int fd)
158 unsigned long evbit[NBITS(EV_MAX)] = { 0 };
159 unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
160 unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
161 unsigned long relbit[NBITS(REL_MAX)] = { 0 };
164 if ((ioctl(
fd, EVIOCGBIT(0,
sizeof(evbit)), evbit) < 0) ||
165 (ioctl(
fd, EVIOCGBIT(EV_KEY,
sizeof(keybit)), keybit) < 0) ||
166 (ioctl(
fd, EVIOCGBIT(EV_REL,
sizeof(relbit)), relbit) < 0) ||
167 (ioctl(
fd, EVIOCGBIT(EV_ABS,
sizeof(absbit)), absbit) < 0)) {
171 devclass = SDL_EVDEV_GuessDeviceClass(evbit, absbit, keybit, relbit);
173 if (devclass & SDL_UDEV_DEVICE_JOYSTICK) {
183 struct input_id inpid;
186 char product_string[128];
189 if (enumeration_method != ENUMERATION_LIBUDEV && !GuessIsJoystick(
fd)) {
193 if (ioctl(
fd, EVIOCGID, &inpid) < 0) {
197 if (ioctl(
fd, EVIOCGNAME(
sizeof(product_string)), product_string) < 0) {
206 #ifdef SDL_JOYSTICK_HIDAPI
207 if (!IsVirtualJoystick(inpid.vendor, inpid.product, inpid.version,
name) &&
215 FixupDeviceInfoForMapping(
fd, &inpid);
217 #ifdef DEBUG_JOYSTICK
218 printf(
"Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n",
name, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
228 if (inpid.vendor && inpid.product) {
248 static void joystick_udev_callback(SDL_UDEV_deviceevent udev_type,
int udev_class,
const char *devpath)
250 if (devpath ==
NULL) {
255 case SDL_UDEV_DEVICEADDED:
256 if (!(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
259 MaybeAddDevice(devpath);
262 case SDL_UDEV_DEVICEREMOVED:
263 MaybeRemoveDevice(devpath);
274 MaybeAddDevice(
const char *
path)
281 SDL_joylist_item *item;
287 if (stat(
path, &sb) == -1) {
292 for (item = SDL_joylist; item !=
NULL; item = item->next) {
293 if (sb.st_rdev == item->devnum) {
298 fd = open(
path, O_RDONLY, 0);
303 #ifdef DEBUG_INPUT_EVENTS
304 printf(
"Checking %s\n",
path);
307 isstick = IsJoystick(
fd, &
name, &guid);
313 item = (SDL_joylist_item *)
SDL_malloc(
sizeof (SDL_joylist_item));
319 item->devnum = sb.st_rdev;
324 if ((item->path ==
NULL) || (item->name ==
NULL)) {
332 if (SDL_joylist_tail ==
NULL) {
333 SDL_joylist = SDL_joylist_tail = item;
335 SDL_joylist_tail->next = item;
336 SDL_joylist_tail = item;
348 MaybeRemoveDevice(
const char *
path)
350 SDL_joylist_item *item;
351 SDL_joylist_item *prev =
NULL;
357 for (item = SDL_joylist; item !=
NULL; item = item->next) {
360 const int retval = item->device_instance;
362 item->hwdata->item =
NULL;
365 prev->next = item->next;
368 SDL_joylist = item->next;
370 if (item == SDL_joylist_tail) {
371 SDL_joylist_tail = prev;
391 HandlePendingRemovals(
void)
393 SDL_joylist_item *prev =
NULL;
394 SDL_joylist_item *item = SDL_joylist;
396 while (item !=
NULL) {
397 if (item->hwdata && item->hwdata->gone) {
398 item->hwdata->item =
NULL;
401 prev->next = item->next;
404 SDL_joylist = item->next;
406 if (item == SDL_joylist_tail) {
407 SDL_joylist_tail = prev;
433 SDL_joylist_item *item;
435 item = (SDL_joylist_item *)
SDL_calloc(1,
sizeof (SDL_joylist_item));
443 item->m_bSteamController =
SDL_TRUE;
445 if ((item->path ==
NULL) || (item->name ==
NULL)) {
453 if (SDL_joylist_tail ==
NULL) {
454 SDL_joylist = SDL_joylist_tail = item;
456 SDL_joylist_tail->next = item;
457 SDL_joylist_tail = item;
468 static void SteamControllerDisconnectedCallback(
int device_instance)
470 SDL_joylist_item *item;
471 SDL_joylist_item *prev =
NULL;
473 for (item = SDL_joylist; item !=
NULL; item = item->next) {
475 if (item->device_instance == device_instance) {
477 item->hwdata->item =
NULL;
480 prev->next = item->next;
483 SDL_joylist = item->next;
485 if (item == SDL_joylist_tail) {
486 SDL_joylist_tail = prev;
503 #ifdef HAVE_INOTIFY_INIT1
504 static int SDL_inotify_init1(
void) {
505 return inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
508 static int SDL_inotify_init1(
void) {
509 int fd = inotify_init();
510 if (
fd < 0)
return -1;
511 fcntl(
fd, F_SETFL, O_NONBLOCK);
512 fcntl(
fd, F_SETFD, FD_CLOEXEC);
518 StrHasPrefix(
const char *
string,
const char *prefix)
524 StrIsInteger(
const char *
string)
528 if (*
string ==
'\0') {
532 for (
p =
string; *
p !=
'\0';
p++) {
542 LINUX_InotifyJoystickDetect(
void)
546 struct inotify_event
event;
548 char enough_for_inotify[
sizeof (
struct inotify_event) + NAME_MAX + 1];
554 bytes = read(inotify_fd, &
buf,
sizeof (
buf));
561 if (
buf.event.len > 0) {
562 if (StrHasPrefix(
buf.event.name,
"event") &&
563 StrIsInteger(
buf.event.name + strlen (
"event"))) {
568 if (
buf.event.mask & (IN_CREATE | IN_MOVED_TO | IN_ATTRIB)) {
569 MaybeAddDevice(
path);
571 else if (
buf.event.mask & (IN_DELETE | IN_MOVED_FROM)) {
572 MaybeRemoveDevice(
path);
592 LINUX_FallbackJoystickDetect(
void)
594 const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000;
597 if (!last_joy_detect_time ||
SDL_TICKS_PASSED(now, last_joy_detect_time + SDL_JOY_DETECT_INTERVAL_MS)) {
601 if (stat(
"/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) {
605 folder = opendir(
"/dev/input");
607 while ((dent = readdir(folder))) {
612 MaybeAddDevice(
path);
619 last_input_dir_mtime = sb.st_mtime;
622 last_joy_detect_time = now;
627 LINUX_JoystickDetect(
void)
630 if (enumeration_method == ENUMERATION_LIBUDEV) {
636 if (inotify_fd >= 0 && last_joy_detect_time != 0) {
637 LINUX_InotifyJoystickDetect();
642 LINUX_FallbackJoystickDetect();
645 HandlePendingRemovals();
651 LINUX_JoystickInit(
void)
654 if (enumeration_method == ENUMERATION_UNSET) {
657 "udev disabled by SDL_JOYSTICK_DISABLE_UDEV");
658 enumeration_method = ENUMERATION_FALLBACK;
660 else if (
access(
"/.flatpak-info", F_OK) == 0
661 ||
access(
"/run/pressure-vessel", F_OK) == 0) {
663 "Container detected, disabling udev integration");
664 enumeration_method = ENUMERATION_FALLBACK;
668 "Using udev for joystick device discovery");
669 enumeration_method = ENUMERATION_LIBUDEV;
676 char *envcopy, *envpath, *delim;
679 while (envpath !=
NULL) {
684 MaybeAddDevice(envpath);
691 SteamControllerDisconnectedCallback);
694 last_joy_detect_time = 0;
695 last_input_dir_mtime = 0;
698 if (enumeration_method == ENUMERATION_LIBUDEV) {
699 if (SDL_UDEV_Init() < 0) {
704 if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
706 return SDL_SetError(
"Could not set up joystick <-> udev callback");
715 #if defined(HAVE_INOTIFY)
716 inotify_fd = SDL_inotify_init1();
718 if (inotify_fd < 0) {
720 "Unable to initialize inotify, falling back to polling: %s",
728 if (inotify_add_watch(inotify_fd,
"/dev/input",
729 IN_CREATE | IN_DELETE | IN_MOVE | IN_ATTRIB) < 0) {
733 "Unable to add inotify watch, falling back to polling: %s",
740 LINUX_JoystickDetect();
747 LINUX_JoystickGetCount(
void)
752 static SDL_joylist_item *
753 JoystickByDevIndex(
int device_index)
755 SDL_joylist_item *item = SDL_joylist;
757 if ((device_index < 0) || (device_index >=
numjoysticks)) {
761 while (device_index > 0) {
772 LINUX_JoystickGetDeviceName(
int device_index)
774 return JoystickByDevIndex(device_index)->name;
778 LINUX_JoystickGetDevicePlayerIndex(
int device_index)
784 LINUX_JoystickSetDevicePlayerIndex(
int device_index,
int player_index)
789 LINUX_JoystickGetDeviceGUID(
int device_index )
791 return JoystickByDevIndex(device_index)->guid;
796 LINUX_JoystickGetDeviceInstanceID(
int device_index)
798 return JoystickByDevIndex(device_index)->device_instance;
802 allocate_hatdata(SDL_Joystick *
joystick)
808 sizeof(
struct hwdata_hat));
820 allocate_balldata(SDL_Joystick *
joystick)
826 sizeof(
struct hwdata_ball));
838 ConfigJoystick(SDL_Joystick *
joystick,
int fd)
841 unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
842 unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
843 unsigned long relbit[NBITS(REL_MAX)] = { 0 };
844 unsigned long ffbit[NBITS(FF_MAX)] = { 0 };
848 if ((ioctl(
fd, EVIOCGBIT(EV_KEY,
sizeof(keybit)), keybit) >= 0) &&
849 (ioctl(
fd, EVIOCGBIT(EV_ABS,
sizeof(absbit)), absbit) >= 0) &&
850 (ioctl(
fd, EVIOCGBIT(EV_REL,
sizeof(relbit)), relbit) >= 0)) {
853 for (
i = BTN_JOYSTICK;
i < KEY_MAX; ++
i) {
854 if (test_bit(
i, keybit)) {
855 #ifdef DEBUG_INPUT_EVENTS
856 printf(
"Joystick has button: 0x%x\n",
i);
863 for (
i = 0;
i < BTN_JOYSTICK; ++
i) {
864 if (test_bit(
i, keybit)) {
865 #ifdef DEBUG_INPUT_EVENTS
866 printf(
"Joystick has button: 0x%x\n",
i);
873 for (
i = 0;
i < ABS_MAX; ++
i) {
875 if (
i == ABS_HAT0X) {
879 if (test_bit(
i, absbit)) {
880 struct input_absinfo absinfo;
881 struct axis_correct *correct = &
joystick->hwdata->abs_correct[
i];
883 if (ioctl(
fd, EVIOCGABS(
i), &absinfo) < 0) {
886 #ifdef DEBUG_INPUT_EVENTS
887 printf(
"Joystick has absolute axis: 0x%.2x\n",
i);
888 printf(
"Values = { %d, %d, %d, %d, %d }\n",
889 absinfo.value, absinfo.minimum, absinfo.maximum,
890 absinfo.fuzz, absinfo.flat);
895 correct->minimum = absinfo.minimum;
896 correct->maximum = absinfo.maximum;
897 if (correct->minimum != correct->maximum) {
900 correct->coef[0] = (absinfo.maximum + absinfo.minimum) - 2 * absinfo.flat;
901 correct->coef[1] = (absinfo.maximum + absinfo.minimum) + 2 * absinfo.flat;
902 t = ((absinfo.maximum - absinfo.minimum) - 4 * absinfo.flat);
904 correct->coef[2] = (1 << 28) /
t;
906 correct->coef[2] = 0;
909 float value_range = (correct->maximum - correct->minimum);
912 correct->scale = (output_range / value_range);
918 for (
i = ABS_HAT0X;
i <= ABS_HAT3Y;
i += 2) {
919 if (test_bit(
i, absbit) || test_bit(
i + 1, absbit)) {
920 struct input_absinfo absinfo;
921 int hat_index = (
i - ABS_HAT0X) / 2;
923 if (ioctl(
fd, EVIOCGABS(
i), &absinfo) < 0) {
926 #ifdef DEBUG_INPUT_EVENTS
927 printf(
"Joystick has hat %d\n", hat_index);
928 printf(
"Values = { %d, %d, %d, %d, %d }\n",
929 absinfo.value, absinfo.minimum, absinfo.maximum,
930 absinfo.fuzz, absinfo.flat);
936 if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) {
942 if (allocate_hatdata(
joystick) < 0) {
947 if (allocate_balldata(
joystick) < 0) {
953 if (ioctl(
fd, EVIOCGBIT(EV_FF,
sizeof(ffbit)), ffbit) >= 0) {
954 if (test_bit(FF_RUMBLE, ffbit)) {
957 if (test_bit(FF_SINE, ffbit)) {
970 LINUX_JoystickOpen(SDL_Joystick *
joystick,
int device_index)
972 SDL_joylist_item *item = JoystickByDevIndex(device_index);
978 joystick->instance_id = item->device_instance;
987 joystick->hwdata->m_bSteamController =
item->m_bSteamController;
990 if (
item->m_bSteamController) {
996 int fd = open(
item->path, O_RDWR, 0);
1013 fcntl(
fd, F_SETFL, O_NONBLOCK);
1029 LINUX_JoystickRumble(SDL_Joystick *
joystick,
Uint16 low_frequency_rumble,
Uint16 high_frequency_rumble)
1031 struct input_event
event;
1034 struct ff_effect *effect = &
joystick->hwdata->effect;
1036 effect->type = FF_RUMBLE;
1038 effect->u.rumble.strong_magnitude = low_frequency_rumble;
1039 effect->u.rumble.weak_magnitude = high_frequency_rumble;
1040 }
else if (
joystick->hwdata->ff_sine) {
1042 Sint16 magnitude = (
Sint16)(((low_frequency_rumble / 2) + (high_frequency_rumble / 2)) / 2);
1043 struct ff_effect *effect = &
joystick->hwdata->effect;
1045 effect->type = FF_PERIODIC;
1047 effect->u.periodic.waveform = FF_SINE;
1048 effect->u.periodic.magnitude = magnitude;
1053 if (ioctl(
joystick->hwdata->fd, EVIOCSFF, &
joystick->hwdata->effect) < 0) {
1056 if (ioctl(
joystick->hwdata->fd, EVIOCSFF, &
joystick->hwdata->effect) < 0) {
1057 return SDL_SetError(
"Couldn't update rumble effect: %s", strerror(errno));
1062 event.code =
joystick->hwdata->effect.id;
1065 return SDL_SetError(
"Couldn't start rumble effect: %s", strerror(errno));
1077 LINUX_JoystickHasLED(SDL_Joystick *
joystick)
1097 struct hwdata_hat *the_hat;
1098 const Uint8 position_map[3][3] = {
1104 the_hat = &stick->hwdata->hats[hat];
1107 }
else if (
value == 0) {
1109 }
else if (
value > 0) {
1115 position_map[the_hat->axis[1]][the_hat->axis[0]]);
1122 stick->hwdata->balls[ball].axis[
axis] +=
value;
1129 struct axis_correct *correct;
1131 correct = &
joystick->hwdata->abs_correct[which];
1132 if (correct->minimum != correct->maximum) {
1133 if (correct->use_deadzones) {
1135 if (
value > correct->coef[0]) {
1139 value -= correct->coef[1];
1141 value -= correct->coef[0];
1143 value *= correct->coef[2];
1161 PollAllValues(SDL_Joystick *
joystick)
1163 struct input_absinfo absinfo;
1164 unsigned long keyinfo[NBITS(KEY_MAX)];
1168 for (
i = ABS_X;
i < ABS_MAX;
i++) {
1169 if (
i == ABS_HAT0X) {
1174 if (ioctl(
joystick->hwdata->fd, EVIOCGABS(
i), &absinfo) >= 0) {
1175 absinfo.value = AxisCorrect(
joystick,
i, absinfo.value);
1177 #ifdef DEBUG_INPUT_EVENTS
1178 printf(
"Joystick : Re-read Axis %d (%d) val= %d\n",
1179 joystick->hwdata->abs_map[
i],
i, absinfo.value);
1189 for (
i = ABS_HAT0X;
i <= ABS_HAT3Y;
i++) {
1190 const int baseaxis =
i - ABS_HAT0X;
1191 const int hatidx = baseaxis / 2;
1193 if (
joystick->hwdata->has_hat[hatidx]) {
1194 if (ioctl(
joystick->hwdata->fd, EVIOCGABS(
i), &absinfo) >= 0) {
1195 const int hataxis = baseaxis % 2;
1196 HandleHat(
joystick,
joystick->hwdata->hats_indices[hatidx], hataxis, absinfo.value);
1203 if (ioctl(
joystick->hwdata->fd, EVIOCGKEY(
sizeof (keyinfo)), keyinfo) >= 0) {
1204 for (
i = 0;
i < KEY_MAX;
i++) {
1207 #ifdef DEBUG_INPUT_EVENTS
1208 printf(
"Joystick : Re-read Button %d (%d) val= %d\n",
1221 HandleInputEvents(SDL_Joystick *
joystick)
1223 struct input_event
events[32];
1234 for (
i = 0;
i <
len; ++
i) {
1239 if (
joystick->hwdata->recovering_from_dropped &&
1240 ((
events[
i].
type != EV_SYN) || (code != SYN_REPORT)) ) {
1264 if (
joystick->hwdata->abs_map[code] != 0xFF) {
1288 #ifdef DEBUG_INPUT_EVENTS
1289 printf(
"Event SYN_DROPPED detected\n");
1294 if (
joystick->hwdata->recovering_from_dropped) {
1308 if (errno == ENODEV) {
1315 LINUX_JoystickUpdate(SDL_Joystick *
joystick)
1319 if (
joystick->hwdata->m_bSteamController) {
1330 xrel =
joystick->hwdata->balls[
i].axis[0];
1331 yrel =
joystick->hwdata->balls[
i].axis[1];
1342 LINUX_JoystickClose(SDL_Joystick *
joystick)
1345 if (
joystick->hwdata->effect.id >= 0) {
1364 LINUX_JoystickQuit(
void)
1366 SDL_joylist_item *item =
NULL;
1367 SDL_joylist_item *next =
NULL;
1369 if (inotify_fd >= 0) {
1374 for (item = SDL_joylist; item; item = next) {
1381 SDL_joylist = SDL_joylist_tail =
NULL;
1386 if (enumeration_method == ENUMERATION_LIBUDEV) {
1387 SDL_UDEV_DelCallback(joystick_udev_callback);
1411 if (LINUX_JoystickOpen(
joystick, device_index) < 0) {
1416 if (!
joystick->hwdata->has_key[BTN_GAMEPAD]) {
1425 if (
joystick->hwdata->has_key[BTN_SOUTH]) {
1430 if (
joystick->hwdata->has_key[BTN_EAST]) {
1435 if (
joystick->hwdata->has_key[BTN_NORTH]) {
1440 if (
joystick->hwdata->has_key[BTN_WEST]) {
1445 if (
joystick->hwdata->has_key[BTN_SELECT]) {
1450 if (
joystick->hwdata->has_key[BTN_START]) {
1455 if (
joystick->hwdata->has_key[BTN_THUMBL]) {
1460 if (
joystick->hwdata->has_key[BTN_THUMBR]) {
1465 if (
joystick->hwdata->has_key[BTN_MODE]) {
1476 if (
joystick->hwdata->has_key[BTN_TL]) {
1481 if (
joystick->hwdata->has_key[BTN_TR]) {
1486 if (
joystick->hwdata->has_hat[1] &&
1487 (!
joystick->hwdata->has_key[BTN_TL] || !
joystick->hwdata->has_key[BTN_TR])) {
1488 int hat =
joystick->hwdata->hats_indices[1] << 4;
1496 if (
joystick->hwdata->has_hat[2]) {
1497 int hat =
joystick->hwdata->hats_indices[2] << 4;
1503 if (
joystick->hwdata->has_key[BTN_TL2]) {
1508 if (
joystick->hwdata->has_key[BTN_TR2]) {
1515 if (
joystick->hwdata->has_key[BTN_DPAD_UP]) {
1520 if (
joystick->hwdata->has_key[BTN_DPAD_DOWN]) {
1525 if (
joystick->hwdata->has_key[BTN_DPAD_LEFT]) {
1530 if (
joystick->hwdata->has_key[BTN_DPAD_RIGHT]) {
1535 if (
joystick->hwdata->has_hat[0] &&
1536 (!
joystick->hwdata->has_key[BTN_DPAD_LEFT] || !
joystick->hwdata->has_key[BTN_DPAD_RIGHT] ||
1537 !
joystick->hwdata->has_key[BTN_DPAD_UP] || !
joystick->hwdata->has_key[BTN_DPAD_DOWN])) {
1538 int hat =
joystick->hwdata->hats_indices[0] << 4;
1549 if (
joystick->hwdata->has_abs[ABS_X] &&
joystick->hwdata->has_abs[ABS_Y]) {
1556 if (
joystick->hwdata->has_abs[ABS_RX] &&
joystick->hwdata->has_abs[ABS_RY]) {
1572 LINUX_JoystickGetCount,
1573 LINUX_JoystickDetect,
1574 LINUX_JoystickGetDeviceName,
1575 LINUX_JoystickGetDevicePlayerIndex,
1576 LINUX_JoystickSetDevicePlayerIndex,
1577 LINUX_JoystickGetDeviceGUID,
1578 LINUX_JoystickGetDeviceInstanceID,
1580 LINUX_JoystickRumble,
1581 LINUX_JoystickRumbleTriggers,
1582 LINUX_JoystickHasLED,
1583 LINUX_JoystickSetLED,
1584 LINUX_JoystickSetSensorsEnabled,
1585 LINUX_JoystickUpdate,
1586 LINUX_JoystickClose,
1588 LINUX_JoystickGetGamepadMapping
#define SDL_assert(condition)
#define SDL_GetHintBoolean
#define SDL_OutOfMemory()
#define SDL_Unsupported()
SDL_bool HIDAPI_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
#define SDL_HINT_LINUX_JOYSTICK_DEADZONES
A variable controlling whether joysticks on Linux adhere to their HID-defined deadzones or return unf...
int SDL_PrivateJoystickBall(SDL_Joystick *joystick, Uint8 ball, Sint16 xrel, Sint16 yrel)
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
SDL_bool SDL_ShouldIgnoreJoystick(const char *name, SDL_JoystickGUID guid)
void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
SDL_JoystickID SDL_GetNextJoystickInstanceID()
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
char * SDL_CreateJoystickName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name)
#define SDL_JOYSTICK_AXIS_MIN
#define SDL_HAT_RIGHTDOWN
#define SDL_JOYSTICK_AXIS_MAX
GLuint GLuint GLsizei GLenum type
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLuint const GLchar * name
GLuint GLint GLboolean GLint GLenum access
GLenum GLuint GLenum GLsizei const GLchar * buf
GLsizei const GLchar *const * path
GLsizei const GLfloat * value
#define SDL_arraysize(array)
void SDL_InitSteamControllers(SteamControllerConnectedCallback_t connectedCallback, SteamControllerDisconnectedCallback_t disconnectedCallback)
void SDL_GetSteamControllerInputs(int *nbuttons, int *naxes, int *nhats)
void SDL_UpdateSteamControllers(void)
void SDL_UpdateSteamController(SDL_Joystick *joystick)
void SDL_QuitSteamControllers(void)
#define SDL_MAX_RUMBLE_DURATION_MS
SDL_JoystickDriver SDL_LINUX_JoystickDriver
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
SDL_InputMapping rightshoulder
SDL_InputMapping righttrigger
SDL_InputMapping rightstick
SDL_InputMapping leftshoulder
SDL_InputMapping lefttrigger
SDL_InputMapping leftstick
struct SDL_joylist_item * item
static SDL_Event events[EVENT_BUF_SIZE]
static SDL_Joystick * joystick
#define USB_PRODUCT_XBOX_ONE_S
#define USB_VENDOR_MICROSOFT
typedef int(__stdcall *FARPROC)()