From 03f8528315fa46c95991a34f3325d7b33ae5538c Mon Sep 17 00:00:00 2001
From: Edward Rudd <urkle@outoforder.cc>
Date: Sat, 02 May 2020 21:48:36 +0000
Subject: [PATCH] Update source to SDL2 2.0.12
---
source/src/joystick/linux/SDL_sysjoystick.c | 404 +++++++++++++++++++++++++++++----------------------------
1 files changed, 206 insertions(+), 198 deletions(-)
diff --git a/source/src/joystick/linux/SDL_sysjoystick.c b/source/src/joystick/linux/SDL_sysjoystick.c
index 06a2d9a..fcfc0f3 100644
--- a/source/src/joystick/linux/SDL_sysjoystick.c
+++ b/source/src/joystick/linux/SDL_sysjoystick.c
@@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
- Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+ Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -34,11 +34,13 @@
#include <limits.h> /* For the definition of PATH_MAX */
#include <sys/ioctl.h>
#include <unistd.h>
+#include <dirent.h>
#include <linux/joystick.h>
#include "SDL_assert.h"
#include "SDL_joystick.h"
#include "SDL_endian.h"
+#include "SDL_timer.h"
#include "../../events/SDL_events_c.h"
#include "../SDL_sysjoystick.h"
#include "../SDL_joystick_c.h"
@@ -56,9 +58,7 @@
static int MaybeAddDevice(const char *path);
#if SDL_USE_LIBUDEV
static int MaybeRemoveDevice(const char *path);
-static void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
#endif /* SDL_USE_LIBUDEV */
-
/* A linked list of available joysticks */
typedef struct SDL_joylist_item
@@ -79,110 +79,53 @@
static SDL_joylist_item *SDL_joylist_tail = NULL;
static int numjoysticks = 0;
+#if !SDL_USE_LIBUDEV
+static Uint32 last_joy_detect_time;
+static time_t last_input_dir_mtime;
+#endif
#define test_bit(nr, addr) \
(((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
#define NBITS(x) ((((x)-1)/(sizeof(long) * 8))+1)
static int
+PrefixMatch(const char *a, const char *b)
+{
+ int matchlen = 0;
+ while (*a && *b) {
+ if (*a++ == *b++) {
+ ++matchlen;
+ } else {
+ break;
+ }
+ }
+ return matchlen;
+}
+
+static void
+FixupDeviceInfoForMapping(int fd, struct input_id *inpid)
+{
+ if (inpid->vendor == 0x045e && inpid->product == 0x0b05 && inpid->version == 0x0903) {
+ /* This is a Microsoft Xbox One Elite Series 2 controller */
+ unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
+
+ /* The first version of the firmware duplicated all the inputs */
+ if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
+ test_bit(0x2c0, keybit)) {
+ /* Change the version to 0x0902, so we can map it differently */
+ inpid->version = 0x0902;
+ }
+ }
+}
+
+
+static int
IsJoystick(int fd, char *namebuf, const size_t namebuflen, SDL_JoystickGUID *guid)
{
- /* This list is taken from:
- https://raw.githubusercontent.com/denilsonsa/udev-joystick-blacklist/master/generate_rules.py
- */
- static Uint32 joystick_blacklist[] = {
- /* Microsoft Microsoft Wireless Optical Desktop® 2.10 */
- /* Microsoft Wireless Desktop - Comfort Edition */
- MAKE_VIDPID(0x045e, 0x009d),
-
- /* Microsoft Microsoft® Digital Media Pro Keyboard */
- /* Microsoft Corp. Digital Media Pro Keyboard */
- MAKE_VIDPID(0x045e, 0x00b0),
-
- /* Microsoft Microsoft® Digital Media Keyboard */
- /* Microsoft Corp. Digital Media Keyboard 1.0A */
- MAKE_VIDPID(0x045e, 0x00b4),
-
- /* Microsoft Microsoft® Digital Media Keyboard 3000 */
- MAKE_VIDPID(0x045e, 0x0730),
-
- /* Microsoft Microsoft® 2.4GHz Transceiver v6.0 */
- /* Microsoft Microsoft® 2.4GHz Transceiver v8.0 */
- /* Microsoft Corp. Nano Transceiver v1.0 for Bluetooth */
- /* Microsoft Wireless Mobile Mouse 1000 */
- /* Microsoft Wireless Desktop 3000 */
- MAKE_VIDPID(0x045e, 0x0745),
-
- /* Microsoft® SideWinder(TM) 2.4GHz Transceiver */
- MAKE_VIDPID(0x045e, 0x0748),
-
- /* Microsoft Corp. Wired Keyboard 600 */
- MAKE_VIDPID(0x045e, 0x0750),
-
- /* Microsoft Corp. Sidewinder X4 keyboard */
- MAKE_VIDPID(0x045e, 0x0768),
-
- /* Microsoft Corp. Arc Touch Mouse Transceiver */
- MAKE_VIDPID(0x045e, 0x0773),
-
- /* Microsoft® 2.4GHz Transceiver v9.0 */
- /* Microsoft® Nano Transceiver v2.1 */
- /* Microsoft Sculpt Ergonomic Keyboard (5KV-00001) */
- MAKE_VIDPID(0x045e, 0x07a5),
-
- /* Microsoft® Nano Transceiver v1.0 */
- /* Microsoft Wireless Keyboard 800 */
- MAKE_VIDPID(0x045e, 0x07b2),
-
- /* Microsoft® Nano Transceiver v2.0 */
- MAKE_VIDPID(0x045e, 0x0800),
-
- /* List of Wacom devices at: http://linuxwacom.sourceforge.net/wiki/index.php/Device_IDs */
- MAKE_VIDPID(0x056a, 0x0010), /* Wacom ET-0405 Graphire */
- MAKE_VIDPID(0x056a, 0x0011), /* Wacom ET-0405A Graphire2 (4x5) */
- MAKE_VIDPID(0x056a, 0x0012), /* Wacom ET-0507A Graphire2 (5x7) */
- MAKE_VIDPID(0x056a, 0x0013), /* Wacom CTE-430 Graphire3 (4x5) */
- MAKE_VIDPID(0x056a, 0x0014), /* Wacom CTE-630 Graphire3 (6x8) */
- MAKE_VIDPID(0x056a, 0x0015), /* Wacom CTE-440 Graphire4 (4x5) */
- MAKE_VIDPID(0x056a, 0x0016), /* Wacom CTE-640 Graphire4 (6x8) */
- MAKE_VIDPID(0x056a, 0x0017), /* Wacom CTE-450 Bamboo Fun (4x5) */
- MAKE_VIDPID(0x056a, 0x0016), /* Wacom CTE-640 Graphire 4 6x8 */
- MAKE_VIDPID(0x056a, 0x0017), /* Wacom CTE-450 Bamboo Fun 4x5 */
- MAKE_VIDPID(0x056a, 0x0018), /* Wacom CTE-650 Bamboo Fun 6x8 */
- MAKE_VIDPID(0x056a, 0x0019), /* Wacom CTE-631 Bamboo One */
- MAKE_VIDPID(0x056a, 0x00d1), /* Wacom Bamboo Pen and Touch CTH-460 */
-
- MAKE_VIDPID(0x09da, 0x054f), /* A4 Tech Co., G7 750 mouse */
- MAKE_VIDPID(0x09da, 0x3043), /* A4 Tech Co., Ltd Bloody R8A Gaming Mouse */
- MAKE_VIDPID(0x09da, 0x31b5), /* A4 Tech Co., Ltd Bloody TL80 Terminator Laser Gaming Mouse */
- MAKE_VIDPID(0x09da, 0x3997), /* A4 Tech Co., Ltd Bloody RT7 Terminator Wireless */
- MAKE_VIDPID(0x09da, 0x3f8b), /* A4 Tech Co., Ltd Bloody V8 mouse */
- MAKE_VIDPID(0x09da, 0x51f4), /* Modecom MC-5006 Keyboard */
- MAKE_VIDPID(0x09da, 0x5589), /* A4 Tech Co., Ltd Terminator TL9 Laser Gaming Mouse */
- MAKE_VIDPID(0x09da, 0x7b22), /* A4 Tech Co., Ltd Bloody V5 */
- MAKE_VIDPID(0x09da, 0x7f2d), /* A4 Tech Co., Ltd Bloody R3 mouse */
- MAKE_VIDPID(0x09da, 0x8090), /* A4 Tech Co., Ltd X-718BK Oscar Optical Gaming Mouse */
- MAKE_VIDPID(0x09da, 0x9066), /* A4 Tech Co., Sharkoon Fireglider Optical */
- MAKE_VIDPID(0x09da, 0x9090), /* A4 Tech Co., Ltd XL-730K / XL-750BK / XL-755BK Laser Mouse */
- MAKE_VIDPID(0x09da, 0x90c0), /* A4 Tech Co., Ltd X7 G800V keyboard */
- MAKE_VIDPID(0x09da, 0xf012), /* A4 Tech Co., Ltd Bloody V7 mouse */
- MAKE_VIDPID(0x09da, 0xf32a), /* A4 Tech Co., Ltd Bloody B540 keyboard */
- MAKE_VIDPID(0x09da, 0xf613), /* A4 Tech Co., Ltd Bloody V2 mouse */
- MAKE_VIDPID(0x09da, 0xf624), /* A4 Tech Co., Ltd Bloody B120 Keyboard */
-
- MAKE_VIDPID(0x1d57, 0xad03), /* [T3] 2.4GHz and IR Air Mouse Remote Control */
-
- MAKE_VIDPID(0x1e7d, 0x2e4a), /* Roccat Tyon Mouse */
-
- MAKE_VIDPID(0x20a0, 0x422d), /* Winkeyless.kr Keyboards */
-
- MAKE_VIDPID(0x2516, 0x001f), /* Cooler Master Storm Mizar Mouse */
- MAKE_VIDPID(0x2516, 0x0028), /* Cooler Master Storm Alcor Mouse */
- };
struct input_id inpid;
- int i;
- Uint32 id;
Uint16 *guid16 = (Uint16 *)guid->data;
+ const char *name;
+ const char *spot;
#if !SDL_USE_LIBUDEV
/* When udev is enabled we only get joystick devices here, so there's no need to test them */
@@ -202,28 +145,36 @@
}
#endif
- if (ioctl(fd, EVIOCGNAME(namebuflen), namebuf) < 0) {
- return 0;
- }
-
if (ioctl(fd, EVIOCGID, &inpid) < 0) {
return 0;
}
+ name = SDL_GetCustomJoystickName(inpid.vendor, inpid.product);
+ if (name) {
+ SDL_strlcpy(namebuf, name, namebuflen);
+ } else {
+ if (ioctl(fd, EVIOCGNAME(namebuflen), namebuf) < 0) {
+ return 0;
+ }
+
+ /* Remove duplicate manufacturer in the name */
+ for (spot = namebuf + 1; *spot; ++spot) {
+ int matchlen = PrefixMatch(namebuf, spot);
+ if (matchlen > 0 && spot[matchlen - 1] == ' ') {
+ SDL_memmove(namebuf, spot, SDL_strlen(spot)+1);
+ break;
+ }
+ }
+ }
+
#ifdef SDL_JOYSTICK_HIDAPI
- if (HIDAPI_IsDevicePresent(inpid.vendor, inpid.product, inpid.version)) {
+ if (HIDAPI_IsDevicePresent(inpid.vendor, inpid.product, inpid.version, namebuf)) {
/* The HIDAPI driver is taking care of this device */
return 0;
}
#endif
- /* Check the joystick blacklist */
- id = MAKE_VIDPID(inpid.vendor, inpid.product);
- for (i = 0; i < SDL_arraysize(joystick_blacklist); ++i) {
- if (id == joystick_blacklist[i]) {
- return 0;
- }
- }
+ FixupDeviceInfoForMapping(fd, &inpid);
#ifdef DEBUG_JOYSTICK
printf("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", namebuf, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
@@ -279,8 +230,6 @@
}
#endif /* SDL_USE_LIBUDEV */
-
-/* !!! FIXME: I would love to dump this code and use libudev instead. */
static int
MaybeAddDevice(const char *path)
{
@@ -356,7 +305,6 @@
}
#if SDL_USE_LIBUDEV
-/* !!! FIXME: I would love to dump this code and use libudev instead. */
static int
MaybeRemoveDevice(const char *path)
{
@@ -401,45 +349,46 @@
}
#endif
-#if ! SDL_USE_LIBUDEV
-static int
-JoystickInitWithoutUdev(void)
+static void
+HandlePendingRemovals(void)
{
- int i;
- char path[PATH_MAX];
+ SDL_joylist_item *prev = NULL;
+ SDL_joylist_item *item = SDL_joylist;
- /* !!! FIXME: only finds sticks if they're called /dev/input/event[0..31] */
- /* !!! FIXME: we could at least readdir() through /dev/input...? */
- /* !!! FIXME: (or delete this and rely on libudev?) */
- for (i = 0; i < 32; i++) {
- SDL_snprintf(path, SDL_arraysize(path), "/dev/input/event%d", i);
- MaybeAddDevice(path);
+ while (item != NULL) {
+ if (item->hwdata && item->hwdata->gone) {
+ item->hwdata->item = NULL;
+
+ if (prev != NULL) {
+ prev->next = item->next;
+ } else {
+ SDL_assert(SDL_joylist == item);
+ SDL_joylist = item->next;
+ }
+ if (item == SDL_joylist_tail) {
+ SDL_joylist_tail = prev;
+ }
+
+ /* Need to decrement the joystick count before we post the event */
+ --numjoysticks;
+
+ SDL_PrivateJoystickRemoved(item->device_instance);
+
+ SDL_free(item->path);
+ SDL_free(item->name);
+ SDL_free(item);
+
+ if (prev != NULL) {
+ item = prev->next;
+ } else {
+ item = SDL_joylist;
+ }
+ } else {
+ prev = item;
+ item = item->next;
+ }
}
-
- return 0;
}
-#endif
-
-#if SDL_USE_LIBUDEV
-static int
-JoystickInitWithUdev(void)
-{
- if (SDL_UDEV_Init() < 0) {
- return SDL_SetError("Could not initialize UDEV");
- }
-
- /* Set up the udev callback */
- if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
- SDL_UDEV_Quit();
- return SDL_SetError("Could not set up joystick <-> udev callback");
- }
-
- /* Force a scan to build the initial device list */
- SDL_UDEV_Scan();
-
- return 0;
-}
-#endif
static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
{
@@ -512,6 +461,49 @@
}
}
+static void
+LINUX_JoystickDetect(void)
+{
+#if SDL_USE_LIBUDEV
+ SDL_UDEV_Poll();
+#else
+ const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */
+ Uint32 now = SDL_GetTicks();
+
+ if (!last_joy_detect_time || SDL_TICKS_PASSED(now, last_joy_detect_time + SDL_JOY_DETECT_INTERVAL_MS)) {
+ struct stat sb;
+
+ /* Opening input devices can generate synchronous device I/O, so avoid it if we can */
+ if (stat("/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) {
+ DIR *folder;
+ struct dirent *dent;
+
+ folder = opendir("/dev/input");
+ if (folder) {
+ while ((dent = readdir(folder))) {
+ int len = SDL_strlen(dent->d_name);
+ if (len > 5 && SDL_strncmp(dent->d_name, "event", 5) == 0) {
+ char path[PATH_MAX];
+ SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", dent->d_name);
+ MaybeAddDevice(path);
+ }
+ }
+
+ closedir(folder);
+ }
+
+ last_input_dir_mtime = sb.st_mtime;
+ }
+
+ last_joy_detect_time = now;
+ }
+#endif
+
+ HandlePendingRemovals();
+
+ SDL_UpdateSteamControllers();
+}
+
static int
LINUX_JoystickInit(void)
{
@@ -535,26 +527,34 @@
SteamControllerDisconnectedCallback);
#if SDL_USE_LIBUDEV
- return JoystickInitWithUdev();
-#else
- return JoystickInitWithoutUdev();
+ if (SDL_UDEV_Init() < 0) {
+ return SDL_SetError("Could not initialize UDEV");
+ }
+
+ /* Set up the udev callback */
+ if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
+ SDL_UDEV_Quit();
+ return SDL_SetError("Could not set up joystick <-> udev callback");
+ }
+
+ /* Force a scan to build the initial device list */
+ SDL_UDEV_Scan();
+#else
+ /* Force immediate joystick detection */
+ last_joy_detect_time = 0;
+ last_input_dir_mtime = 0;
+
+ /* Report all devices currently present */
+ LINUX_JoystickDetect();
#endif
+
+ return 0;
}
static int
LINUX_JoystickGetCount(void)
{
return numjoysticks;
-}
-
-static void
-LINUX_JoystickDetect(void)
-{
-#if SDL_USE_LIBUDEV
- SDL_UDEV_Poll();
-#endif
-
- SDL_UpdateSteamControllers();
}
static SDL_joylist_item *
@@ -586,6 +586,11 @@
LINUX_JoystickGetDevicePlayerIndex(int device_index)
{
return -1;
+}
+
+static void
+LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index)
+{
}
static SDL_JoystickGUID
@@ -711,17 +716,18 @@
for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
if (test_bit(i, absbit) || test_bit(i + 1, absbit)) {
struct input_absinfo absinfo;
+ int hat_index = (i - ABS_HAT0X) / 2;
if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
continue;
}
#ifdef DEBUG_INPUT_EVENTS
- printf("Joystick has hat %d\n", (i - ABS_HAT0X) / 2);
+ printf("Joystick has hat %d\n", hat_index);
printf("Values = { %d, %d, %d, %d, %d }\n",
absinfo.value, absinfo.minimum, absinfo.maximum,
absinfo.fuzz, absinfo.flat);
#endif /* DEBUG_INPUT_EVENTS */
- ++joystick->nhats;
+ joystick->hwdata->hats_indices[hat_index] = joystick->nhats++;
}
}
if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) {
@@ -776,6 +782,7 @@
joystick->hwdata->guid = item->guid;
joystick->hwdata->effect.id = -1;
joystick->hwdata->m_bSteamController = item->m_bSteamController;
+ SDL_memset(joystick->hwdata->abs_map, 0xFF, sizeof(joystick->hwdata->abs_map));
if (item->m_bSteamController) {
joystick->hwdata->fd = -1;
@@ -816,7 +823,7 @@
}
static int
-LINUX_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
+LINUX_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{
struct input_event event;
@@ -824,7 +831,7 @@
struct ff_effect *effect = &joystick->hwdata->effect;
effect->type = FF_RUMBLE;
- effect->replay.length = SDL_min(duration_ms, 32767);
+ effect->replay.length = SDL_MAX_RUMBLE_DURATION_MS;
effect->u.rumble.strong_magnitude = low_frequency_rumble;
effect->u.rumble.weak_magnitude = high_frequency_rumble;
} else if (joystick->hwdata->ff_sine) {
@@ -833,7 +840,7 @@
struct ff_effect *effect = &joystick->hwdata->effect;
effect->type = FF_PERIODIC;
- effect->replay.length = SDL_min(duration_ms, 32767);
+ effect->replay.length = SDL_MAX_RUMBLE_DURATION_MS;
effect->u.periodic.waveform = FF_SINE;
effect->u.periodic.magnitude = magnitude;
} else {
@@ -841,7 +848,11 @@
}
if (ioctl(joystick->hwdata->fd, EVIOCSFF, &joystick->hwdata->effect) < 0) {
- return SDL_SetError("Couldn't update rumble effect: %s", strerror(errno));
+ /* The kernel may have lost this effect, try to allocate a new one */
+ joystick->hwdata->effect.id = -1;
+ if (ioctl(joystick->hwdata->fd, EVIOCSFF, &joystick->hwdata->effect) < 0) {
+ return SDL_SetError("Couldn't update rumble effect: %s", strerror(errno));
+ }
}
event.type = EV_FF;
@@ -874,8 +885,7 @@
if (value != the_hat->axis[axis]) {
the_hat->axis[axis] = value;
SDL_PrivateJoystickHat(stick, hat,
- position_map[the_hat->
- axis[1]][the_hat->axis[0]]);
+ position_map[the_hat->axis[1]][the_hat->axis[0]]);
}
}
@@ -919,36 +929,26 @@
PollAllValues(SDL_Joystick * joystick)
{
struct input_absinfo absinfo;
- int a, b = 0;
+ int i;
/* Poll all axis */
- for (a = ABS_X; b < ABS_MAX; a++) {
- switch (a) {
- case ABS_HAT0X:
- case ABS_HAT0Y:
- case ABS_HAT1X:
- case ABS_HAT1Y:
- case ABS_HAT2X:
- case ABS_HAT2Y:
- case ABS_HAT3X:
- case ABS_HAT3Y:
- /* ingore hats */
- break;
- default:
- if (joystick->hwdata->abs_correct[b].used) {
- if (ioctl(joystick->hwdata->fd, EVIOCGABS(a), &absinfo) >= 0) {
- absinfo.value = AxisCorrect(joystick, b, absinfo.value);
+ for (i = ABS_X; i < ABS_MAX; i++) {
+ if (i == ABS_HAT0X) {
+ i = ABS_HAT3Y;
+ continue;
+ }
+ if (joystick->hwdata->abs_correct[i].used) {
+ if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
+ absinfo.value = AxisCorrect(joystick, i, absinfo.value);
#ifdef DEBUG_INPUT_EVENTS
- printf("Joystick : Re-read Axis %d (%d) val= %d\n",
- joystick->hwdata->abs_map[b], a, absinfo.value);
+ printf("Joystick : Re-read Axis %d (%d) val= %d\n",
+ joystick->hwdata->abs_map[i], i, absinfo.value);
#endif
- SDL_PrivateJoystickAxis(joystick,
- joystick->hwdata->abs_map[b],
- absinfo.value);
- }
+ SDL_PrivateJoystickAxis(joystick,
+ joystick->hwdata->abs_map[i],
+ absinfo.value);
}
- b++;
}
}
}
@@ -986,14 +986,16 @@
case ABS_HAT3X:
case ABS_HAT3Y:
code -= ABS_HAT0X;
- HandleHat(joystick, code / 2, code % 2, events[i].value);
+ HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value);
break;
default:
- events[i].value =
- AxisCorrect(joystick, code, events[i].value);
- SDL_PrivateJoystickAxis(joystick,
- joystick->hwdata->abs_map[code],
- events[i].value);
+ if (joystick->hwdata->abs_map[code] != 0xFF) {
+ events[i].value =
+ AxisCorrect(joystick, code, events[i].value);
+ SDL_PrivateJoystickAxis(joystick,
+ joystick->hwdata->abs_map[code],
+ events[i].value);
+ }
break;
}
break;
@@ -1023,6 +1025,11 @@
break;
}
}
+ }
+
+ if (errno == ENODEV) {
+ /* We have to wait until the JoystickDetect callback to remove this */
+ joystick->hwdata->gone = SDL_TRUE;
}
}
@@ -1107,6 +1114,7 @@
LINUX_JoystickDetect,
LINUX_JoystickGetDeviceName,
LINUX_JoystickGetDevicePlayerIndex,
+ LINUX_JoystickSetDevicePlayerIndex,
LINUX_JoystickGetDeviceGUID,
LINUX_JoystickGetDeviceInstanceID,
LINUX_JoystickOpen,
--
Gitblit v1.9.3