SDL_sysjoystick.c 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2020 Sam Lantinga <[email protected]>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "../../SDL_internal.h"
  19. #ifdef SDL_JOYSTICK_LINUX
  20. #ifndef SDL_INPUT_LINUXEV
  21. #error SDL now requires a Linux 2.4+ kernel with /dev/input/event support.
  22. #endif
  23. /* This is the Linux implementation of the SDL joystick API */
  24. #include <sys/stat.h>
  25. #include <errno.h> /* errno, strerror */
  26. #include <fcntl.h>
  27. #include <limits.h> /* For the definition of PATH_MAX */
  28. #include <sys/inotify.h>
  29. #include <sys/ioctl.h>
  30. #include <unistd.h>
  31. #include <dirent.h>
  32. #include <linux/joystick.h>
  33. #include "SDL_assert.h"
  34. #include "SDL_hints.h"
  35. #include "SDL_joystick.h"
  36. #include "SDL_log.h"
  37. #include "SDL_endian.h"
  38. #include "SDL_timer.h"
  39. #include "../../events/SDL_events_c.h"
  40. #include "../SDL_sysjoystick.h"
  41. #include "../SDL_joystick_c.h"
  42. #include "../steam/SDL_steamcontroller.h"
  43. #include "SDL_sysjoystick_c.h"
  44. #include "../hidapi/SDL_hidapijoystick_c.h"
  45. /* This isn't defined in older Linux kernel headers */
  46. #ifndef SYN_DROPPED
  47. #define SYN_DROPPED 3
  48. #endif
  49. #ifndef BTN_SOUTH
  50. #define BTN_SOUTH 0x130
  51. #endif
  52. #ifndef BTN_EAST
  53. #define BTN_EAST 0x131
  54. #endif
  55. #ifndef BTN_NORTH
  56. #define BTN_NORTH 0x133
  57. #endif
  58. #ifndef BTN_WEST
  59. #define BTN_WEST 0x134
  60. #endif
  61. #ifndef BTN_DPAD_UP
  62. #define BTN_DPAD_UP 0x220
  63. #endif
  64. #ifndef BTN_DPAD_DOWN
  65. #define BTN_DPAD_DOWN 0x221
  66. #endif
  67. #ifndef BTN_DPAD_LEFT
  68. #define BTN_DPAD_LEFT 0x222
  69. #endif
  70. #ifndef BTN_DPAD_RIGHT
  71. #define BTN_DPAD_RIGHT 0x223
  72. #endif
  73. #include "../../core/linux/SDL_evdev_capabilities.h"
  74. #include "../../core/linux/SDL_udev.h"
  75. #if 0
  76. #define DEBUG_INPUT_EVENTS 1
  77. #endif
  78. typedef enum
  79. {
  80. ENUMERATION_UNSET,
  81. ENUMERATION_LIBUDEV,
  82. ENUMERATION_FALLBACK
  83. } EnumerationMethod;
  84. static EnumerationMethod enumeration_method = ENUMERATION_UNSET;
  85. static int MaybeAddDevice(const char *path);
  86. static int MaybeRemoveDevice(const char *path);
  87. /* A linked list of available joysticks */
  88. typedef struct SDL_joylist_item
  89. {
  90. int device_instance;
  91. char *path; /* "/dev/input/event2" or whatever */
  92. char *name; /* "SideWinder 3D Pro" or whatever */
  93. SDL_JoystickGUID guid;
  94. dev_t devnum;
  95. struct joystick_hwdata *hwdata;
  96. struct SDL_joylist_item *next;
  97. /* Steam Controller support */
  98. SDL_bool m_bSteamController;
  99. } SDL_joylist_item;
  100. static SDL_joylist_item *SDL_joylist = NULL;
  101. static SDL_joylist_item *SDL_joylist_tail = NULL;
  102. static int numjoysticks = 0;
  103. static int inotify_fd = -1;
  104. static Uint32 last_joy_detect_time;
  105. static time_t last_input_dir_mtime;
  106. static void
  107. FixupDeviceInfoForMapping(int fd, struct input_id *inpid)
  108. {
  109. if (inpid->vendor == 0x045e && inpid->product == 0x0b05 && inpid->version == 0x0903) {
  110. /* This is a Microsoft Xbox One Elite Series 2 controller */
  111. unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
  112. /* The first version of the firmware duplicated all the inputs */
  113. if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
  114. test_bit(0x2c0, keybit)) {
  115. /* Change the version to 0x0902, so we can map it differently */
  116. inpid->version = 0x0902;
  117. }
  118. }
  119. }
  120. #ifdef SDL_JOYSTICK_HIDAPI
  121. static SDL_bool
  122. IsVirtualJoystick(Uint16 vendor, Uint16 product, Uint16 version, const char *name)
  123. {
  124. if (vendor == USB_VENDOR_MICROSOFT && product == USB_PRODUCT_XBOX_ONE_S && version == 0 &&
  125. SDL_strcmp(name, "Xbox One S Controller") == 0) {
  126. /* This is the virtual device created by the xow driver */
  127. return SDL_TRUE;
  128. }
  129. return SDL_FALSE;
  130. }
  131. #endif /* SDL_JOYSTICK_HIDAPI */
  132. static int
  133. GuessIsJoystick(int fd)
  134. {
  135. unsigned long evbit[NBITS(EV_MAX)] = { 0 };
  136. unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
  137. unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
  138. unsigned long relbit[NBITS(REL_MAX)] = { 0 };
  139. int devclass;
  140. if ((ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
  141. (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
  142. (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) < 0) ||
  143. (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) {
  144. return (0);
  145. }
  146. devclass = SDL_EVDEV_GuessDeviceClass(evbit, absbit, keybit, relbit);
  147. if (devclass & SDL_UDEV_DEVICE_JOYSTICK) {
  148. return 1;
  149. }
  150. return 0;
  151. }
  152. static int
  153. IsJoystick(int fd, char **name_return, SDL_JoystickGUID *guid)
  154. {
  155. struct input_id inpid;
  156. Uint16 *guid16 = (Uint16 *)guid->data;
  157. char *name;
  158. char product_string[128];
  159. /* When udev is enabled we only get joystick devices here, so there's no need to test them */
  160. if (enumeration_method != ENUMERATION_LIBUDEV && !GuessIsJoystick(fd)) {
  161. return 0;
  162. }
  163. if (ioctl(fd, EVIOCGID, &inpid) < 0) {
  164. return 0;
  165. }
  166. if (ioctl(fd, EVIOCGNAME(sizeof(product_string)), product_string) < 0) {
  167. return 0;
  168. }
  169. name = SDL_CreateJoystickName(inpid.vendor, inpid.product, NULL, product_string);
  170. if (!name) {
  171. return 0;
  172. }
  173. #ifdef SDL_JOYSTICK_HIDAPI
  174. if (!IsVirtualJoystick(inpid.vendor, inpid.product, inpid.version, name) &&
  175. HIDAPI_IsDevicePresent(inpid.vendor, inpid.product, inpid.version, name)) {
  176. /* The HIDAPI driver is taking care of this device */
  177. SDL_free(name);
  178. return 0;
  179. }
  180. #endif
  181. FixupDeviceInfoForMapping(fd, &inpid);
  182. #ifdef DEBUG_JOYSTICK
  183. printf("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", name, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
  184. #endif
  185. SDL_memset(guid->data, 0, sizeof(guid->data));
  186. /* We only need 16 bits for each of these; space them out to fill 128. */
  187. /* Byteswap so devices get same GUID on little/big endian platforms. */
  188. *guid16++ = SDL_SwapLE16(inpid.bustype);
  189. *guid16++ = 0;
  190. if (inpid.vendor && inpid.product) {
  191. *guid16++ = SDL_SwapLE16(inpid.vendor);
  192. *guid16++ = 0;
  193. *guid16++ = SDL_SwapLE16(inpid.product);
  194. *guid16++ = 0;
  195. *guid16++ = SDL_SwapLE16(inpid.version);
  196. *guid16++ = 0;
  197. } else {
  198. SDL_strlcpy((char*)guid16, name, sizeof(guid->data) - 4);
  199. }
  200. if (SDL_ShouldIgnoreJoystick(name, *guid)) {
  201. SDL_free(name);
  202. return 0;
  203. }
  204. *name_return = name;
  205. return 1;
  206. }
  207. #if SDL_USE_LIBUDEV
  208. static void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
  209. {
  210. if (devpath == NULL) {
  211. return;
  212. }
  213. switch (udev_type) {
  214. case SDL_UDEV_DEVICEADDED:
  215. if (!(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
  216. return;
  217. }
  218. MaybeAddDevice(devpath);
  219. break;
  220. case SDL_UDEV_DEVICEREMOVED:
  221. MaybeRemoveDevice(devpath);
  222. break;
  223. default:
  224. break;
  225. }
  226. }
  227. #endif /* SDL_USE_LIBUDEV */
  228. static int
  229. MaybeAddDevice(const char *path)
  230. {
  231. struct stat sb;
  232. int fd = -1;
  233. int isstick = 0;
  234. char *name = NULL;
  235. SDL_JoystickGUID guid;
  236. SDL_joylist_item *item;
  237. if (path == NULL) {
  238. return -1;
  239. }
  240. if (stat(path, &sb) == -1) {
  241. return -1;
  242. }
  243. /* Check to make sure it's not already in list. */
  244. for (item = SDL_joylist; item != NULL; item = item->next) {
  245. if (sb.st_rdev == item->devnum) {
  246. return -1; /* already have this one */
  247. }
  248. }
  249. fd = open(path, O_RDONLY, 0);
  250. if (fd < 0) {
  251. return -1;
  252. }
  253. #ifdef DEBUG_INPUT_EVENTS
  254. printf("Checking %s\n", path);
  255. #endif
  256. isstick = IsJoystick(fd, &name, &guid);
  257. close(fd);
  258. if (!isstick) {
  259. return -1;
  260. }
  261. item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
  262. if (item == NULL) {
  263. return -1;
  264. }
  265. SDL_zerop(item);
  266. item->devnum = sb.st_rdev;
  267. item->path = SDL_strdup(path);
  268. item->name = name;
  269. item->guid = guid;
  270. if ((item->path == NULL) || (item->name == NULL)) {
  271. SDL_free(item->path);
  272. SDL_free(item->name);
  273. SDL_free(item);
  274. return -1;
  275. }
  276. item->device_instance = SDL_GetNextJoystickInstanceID();
  277. if (SDL_joylist_tail == NULL) {
  278. SDL_joylist = SDL_joylist_tail = item;
  279. } else {
  280. SDL_joylist_tail->next = item;
  281. SDL_joylist_tail = item;
  282. }
  283. /* Need to increment the joystick count before we post the event */
  284. ++numjoysticks;
  285. SDL_PrivateJoystickAdded(item->device_instance);
  286. return numjoysticks;
  287. }
  288. #if SDL_USE_LIBUDEV
  289. static int
  290. MaybeRemoveDevice(const char *path)
  291. {
  292. SDL_joylist_item *item;
  293. SDL_joylist_item *prev = NULL;
  294. if (path == NULL) {
  295. return -1;
  296. }
  297. for (item = SDL_joylist; item != NULL; item = item->next) {
  298. /* found it, remove it. */
  299. if (SDL_strcmp(path, item->path) == 0) {
  300. const int retval = item->device_instance;
  301. if (item->hwdata) {
  302. item->hwdata->item = NULL;
  303. }
  304. if (prev != NULL) {
  305. prev->next = item->next;
  306. } else {
  307. SDL_assert(SDL_joylist == item);
  308. SDL_joylist = item->next;
  309. }
  310. if (item == SDL_joylist_tail) {
  311. SDL_joylist_tail = prev;
  312. }
  313. /* Need to decrement the joystick count before we post the event */
  314. --numjoysticks;
  315. SDL_PrivateJoystickRemoved(item->device_instance);
  316. SDL_free(item->path);
  317. SDL_free(item->name);
  318. SDL_free(item);
  319. return retval;
  320. }
  321. prev = item;
  322. }
  323. return -1;
  324. }
  325. #endif
  326. static void
  327. HandlePendingRemovals(void)
  328. {
  329. SDL_joylist_item *prev = NULL;
  330. SDL_joylist_item *item = SDL_joylist;
  331. while (item != NULL) {
  332. if (item->hwdata && item->hwdata->gone) {
  333. item->hwdata->item = NULL;
  334. if (prev != NULL) {
  335. prev->next = item->next;
  336. } else {
  337. SDL_assert(SDL_joylist == item);
  338. SDL_joylist = item->next;
  339. }
  340. if (item == SDL_joylist_tail) {
  341. SDL_joylist_tail = prev;
  342. }
  343. /* Need to decrement the joystick count before we post the event */
  344. --numjoysticks;
  345. SDL_PrivateJoystickRemoved(item->device_instance);
  346. SDL_free(item->path);
  347. SDL_free(item->name);
  348. SDL_free(item);
  349. if (prev != NULL) {
  350. item = prev->next;
  351. } else {
  352. item = SDL_joylist;
  353. }
  354. } else {
  355. prev = item;
  356. item = item->next;
  357. }
  358. }
  359. }
  360. static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
  361. {
  362. SDL_joylist_item *item;
  363. item = (SDL_joylist_item *) SDL_calloc(1, sizeof (SDL_joylist_item));
  364. if (item == NULL) {
  365. return SDL_FALSE;
  366. }
  367. item->path = SDL_strdup("");
  368. item->name = SDL_strdup(name);
  369. item->guid = guid;
  370. item->m_bSteamController = SDL_TRUE;
  371. if ((item->path == NULL) || (item->name == NULL)) {
  372. SDL_free(item->path);
  373. SDL_free(item->name);
  374. SDL_free(item);
  375. return SDL_FALSE;
  376. }
  377. *device_instance = item->device_instance = SDL_GetNextJoystickInstanceID();
  378. if (SDL_joylist_tail == NULL) {
  379. SDL_joylist = SDL_joylist_tail = item;
  380. } else {
  381. SDL_joylist_tail->next = item;
  382. SDL_joylist_tail = item;
  383. }
  384. /* Need to increment the joystick count before we post the event */
  385. ++numjoysticks;
  386. SDL_PrivateJoystickAdded(item->device_instance);
  387. return SDL_TRUE;
  388. }
  389. static void SteamControllerDisconnectedCallback(int device_instance)
  390. {
  391. SDL_joylist_item *item;
  392. SDL_joylist_item *prev = NULL;
  393. for (item = SDL_joylist; item != NULL; item = item->next) {
  394. /* found it, remove it. */
  395. if (item->device_instance == device_instance) {
  396. if (item->hwdata) {
  397. item->hwdata->item = NULL;
  398. }
  399. if (prev != NULL) {
  400. prev->next = item->next;
  401. } else {
  402. SDL_assert(SDL_joylist == item);
  403. SDL_joylist = item->next;
  404. }
  405. if (item == SDL_joylist_tail) {
  406. SDL_joylist_tail = prev;
  407. }
  408. /* Need to decrement the joystick count before we post the event */
  409. --numjoysticks;
  410. SDL_PrivateJoystickRemoved(item->device_instance);
  411. SDL_free(item->name);
  412. SDL_free(item);
  413. return;
  414. }
  415. prev = item;
  416. }
  417. }
  418. static int
  419. StrHasPrefix(const char *string, const char *prefix)
  420. {
  421. return (SDL_strncmp(string, prefix, SDL_strlen(prefix)) == 0);
  422. }
  423. static int
  424. StrIsInteger(const char *string)
  425. {
  426. const char *p;
  427. if (*string == '\0') {
  428. return 0;
  429. }
  430. for (p = string; *p != '\0'; p++) {
  431. if (*p < '0' || *p > '9') {
  432. return 0;
  433. }
  434. }
  435. return 1;
  436. }
  437. static void
  438. LINUX_InotifyJoystickDetect(void)
  439. {
  440. union
  441. {
  442. struct inotify_event event;
  443. char storage[4096];
  444. char enough_for_inotify[sizeof (struct inotify_event) + NAME_MAX + 1];
  445. } buf;
  446. ssize_t bytes;
  447. size_t remain = 0;
  448. size_t len;
  449. bytes = read(inotify_fd, &buf, sizeof (buf));
  450. if (bytes > 0) {
  451. remain = (size_t) bytes;
  452. }
  453. while (remain > 0) {
  454. if (buf.event.len > 0) {
  455. if (StrHasPrefix(buf.event.name, "event") &&
  456. StrIsInteger(buf.event.name + strlen ("event"))) {
  457. char path[PATH_MAX];
  458. SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", buf.event.name);
  459. if (buf.event.mask & (IN_CREATE | IN_MOVED_TO | IN_ATTRIB)) {
  460. MaybeAddDevice(path);
  461. }
  462. else if (buf.event.mask & (IN_DELETE | IN_MOVED_FROM)) {
  463. MaybeRemoveDevice(path);
  464. }
  465. }
  466. }
  467. len = sizeof (struct inotify_event) + buf.event.len;
  468. remain -= len;
  469. if (remain != 0) {
  470. memmove (&buf.storage[0], &buf.storage[len], remain);
  471. }
  472. }
  473. }
  474. static void
  475. LINUX_FallbackJoystickDetect(void)
  476. {
  477. const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */
  478. Uint32 now = SDL_GetTicks();
  479. if (!last_joy_detect_time || SDL_TICKS_PASSED(now, last_joy_detect_time + SDL_JOY_DETECT_INTERVAL_MS)) {
  480. struct stat sb;
  481. /* Opening input devices can generate synchronous device I/O, so avoid it if we can */
  482. if (stat("/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) {
  483. DIR *folder;
  484. struct dirent *dent;
  485. folder = opendir("/dev/input");
  486. if (folder) {
  487. while ((dent = readdir(folder))) {
  488. int len = SDL_strlen(dent->d_name);
  489. if (len > 5 && SDL_strncmp(dent->d_name, "event", 5) == 0) {
  490. char path[PATH_MAX];
  491. SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", dent->d_name);
  492. MaybeAddDevice(path);
  493. }
  494. }
  495. closedir(folder);
  496. }
  497. last_input_dir_mtime = sb.st_mtime;
  498. }
  499. last_joy_detect_time = now;
  500. }
  501. }
  502. static void
  503. LINUX_JoystickDetect(void)
  504. {
  505. #if SDL_USE_LIBUDEV
  506. if (enumeration_method == ENUMERATION_LIBUDEV) {
  507. SDL_UDEV_Poll();
  508. }
  509. else
  510. #endif
  511. if (inotify_fd >= 0) {
  512. LINUX_InotifyJoystickDetect();
  513. }
  514. else {
  515. LINUX_FallbackJoystickDetect();
  516. }
  517. HandlePendingRemovals();
  518. SDL_UpdateSteamControllers();
  519. }
  520. static int
  521. LINUX_JoystickInit(void)
  522. {
  523. #if SDL_USE_LIBUDEV
  524. if (enumeration_method == ENUMERATION_UNSET) {
  525. if (SDL_getenv("SDL_JOYSTICK_DISABLE_UDEV") != NULL) {
  526. enumeration_method = ENUMERATION_FALLBACK;
  527. }
  528. else {
  529. enumeration_method = ENUMERATION_LIBUDEV;
  530. }
  531. }
  532. #endif
  533. /* First see if the user specified one or more joysticks to use */
  534. if (SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL) {
  535. char *envcopy, *envpath, *delim;
  536. envcopy = SDL_strdup(SDL_getenv("SDL_JOYSTICK_DEVICE"));
  537. envpath = envcopy;
  538. while (envpath != NULL) {
  539. delim = SDL_strchr(envpath, ':');
  540. if (delim != NULL) {
  541. *delim++ = '\0';
  542. }
  543. MaybeAddDevice(envpath);
  544. envpath = delim;
  545. }
  546. SDL_free(envcopy);
  547. }
  548. SDL_InitSteamControllers(SteamControllerConnectedCallback,
  549. SteamControllerDisconnectedCallback);
  550. /* Force immediate joystick detection if using fallback */
  551. last_joy_detect_time = 0;
  552. last_input_dir_mtime = 0;
  553. #if SDL_USE_LIBUDEV
  554. if (enumeration_method == ENUMERATION_LIBUDEV) {
  555. if (SDL_UDEV_Init() < 0) {
  556. return SDL_SetError("Could not initialize UDEV");
  557. }
  558. /* Set up the udev callback */
  559. if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
  560. SDL_UDEV_Quit();
  561. return SDL_SetError("Could not set up joystick <-> udev callback");
  562. }
  563. /* Force a scan to build the initial device list */
  564. SDL_UDEV_Scan();
  565. }
  566. else
  567. #endif
  568. {
  569. inotify_fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
  570. if (inotify_fd < 0) {
  571. SDL_LogWarn(SDL_LOG_CATEGORY_INPUT,
  572. "Unable to initialize inotify, falling back to polling: %s",
  573. strerror (errno));
  574. }
  575. else {
  576. /* We need to watch for attribute changes in addition to
  577. * creation, because when a device is first created, it has
  578. * permissions that we can't read. When udev chmods it to
  579. * something that we maybe *can* read, we'll get an
  580. * IN_ATTRIB event to tell us. */
  581. if (inotify_add_watch(inotify_fd, "/dev/input",
  582. IN_CREATE | IN_DELETE | IN_MOVE | IN_ATTRIB) < 0) {
  583. close(inotify_fd);
  584. inotify_fd = -1;
  585. SDL_LogWarn(SDL_LOG_CATEGORY_INPUT,
  586. "Unable to add inotify watch, falling back to polling: %s",
  587. strerror (errno));
  588. }
  589. }
  590. /* Report all devices currently present */
  591. LINUX_JoystickDetect();
  592. }
  593. return 0;
  594. }
  595. static int
  596. LINUX_JoystickGetCount(void)
  597. {
  598. return numjoysticks;
  599. }
  600. static SDL_joylist_item *
  601. JoystickByDevIndex(int device_index)
  602. {
  603. SDL_joylist_item *item = SDL_joylist;
  604. if ((device_index < 0) || (device_index >= numjoysticks)) {
  605. return NULL;
  606. }
  607. while (device_index > 0) {
  608. SDL_assert(item != NULL);
  609. device_index--;
  610. item = item->next;
  611. }
  612. return item;
  613. }
  614. /* Function to get the device-dependent name of a joystick */
  615. static const char *
  616. LINUX_JoystickGetDeviceName(int device_index)
  617. {
  618. return JoystickByDevIndex(device_index)->name;
  619. }
  620. static int
  621. LINUX_JoystickGetDevicePlayerIndex(int device_index)
  622. {
  623. return -1;
  624. }
  625. static void
  626. LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index)
  627. {
  628. }
  629. static SDL_JoystickGUID
  630. LINUX_JoystickGetDeviceGUID( int device_index )
  631. {
  632. return JoystickByDevIndex(device_index)->guid;
  633. }
  634. /* Function to perform the mapping from device index to the instance id for this index */
  635. static SDL_JoystickID
  636. LINUX_JoystickGetDeviceInstanceID(int device_index)
  637. {
  638. return JoystickByDevIndex(device_index)->device_instance;
  639. }
  640. static int
  641. allocate_hatdata(SDL_Joystick * joystick)
  642. {
  643. int i;
  644. joystick->hwdata->hats =
  645. (struct hwdata_hat *) SDL_malloc(joystick->nhats *
  646. sizeof(struct hwdata_hat));
  647. if (joystick->hwdata->hats == NULL) {
  648. return (-1);
  649. }
  650. for (i = 0; i < joystick->nhats; ++i) {
  651. joystick->hwdata->hats[i].axis[0] = 1;
  652. joystick->hwdata->hats[i].axis[1] = 1;
  653. }
  654. return (0);
  655. }
  656. static int
  657. allocate_balldata(SDL_Joystick * joystick)
  658. {
  659. int i;
  660. joystick->hwdata->balls =
  661. (struct hwdata_ball *) SDL_malloc(joystick->nballs *
  662. sizeof(struct hwdata_ball));
  663. if (joystick->hwdata->balls == NULL) {
  664. return (-1);
  665. }
  666. for (i = 0; i < joystick->nballs; ++i) {
  667. joystick->hwdata->balls[i].axis[0] = 0;
  668. joystick->hwdata->balls[i].axis[1] = 0;
  669. }
  670. return (0);
  671. }
  672. static void
  673. ConfigJoystick(SDL_Joystick * joystick, int fd)
  674. {
  675. int i, t;
  676. unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
  677. unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
  678. unsigned long relbit[NBITS(REL_MAX)] = { 0 };
  679. unsigned long ffbit[NBITS(FF_MAX)] = { 0 };
  680. /* See if this device uses the new unified event API */
  681. if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
  682. (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) &&
  683. (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0)) {
  684. /* Get the number of buttons, axes, and other thingamajigs */
  685. for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
  686. if (test_bit(i, keybit)) {
  687. #ifdef DEBUG_INPUT_EVENTS
  688. printf("Joystick has button: 0x%x\n", i);
  689. #endif
  690. joystick->hwdata->key_map[i] = joystick->nbuttons;
  691. joystick->hwdata->has_key[i] = SDL_TRUE;
  692. ++joystick->nbuttons;
  693. }
  694. }
  695. for (i = 0; i < BTN_JOYSTICK; ++i) {
  696. if (test_bit(i, keybit)) {
  697. #ifdef DEBUG_INPUT_EVENTS
  698. printf("Joystick has button: 0x%x\n", i);
  699. #endif
  700. joystick->hwdata->key_map[i] = joystick->nbuttons;
  701. joystick->hwdata->has_key[i] = SDL_TRUE;
  702. ++joystick->nbuttons;
  703. }
  704. }
  705. for (i = 0; i < ABS_MAX; ++i) {
  706. /* Skip hats */
  707. if (i == ABS_HAT0X) {
  708. i = ABS_HAT3Y;
  709. continue;
  710. }
  711. if (test_bit(i, absbit)) {
  712. struct input_absinfo absinfo;
  713. SDL_bool hint_used = SDL_GetHintBoolean(SDL_HINT_LINUX_JOYSTICK_DEADZONES, SDL_TRUE);
  714. if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
  715. continue;
  716. }
  717. #ifdef DEBUG_INPUT_EVENTS
  718. printf("Joystick has absolute axis: 0x%.2x\n", i);
  719. printf("Values = { %d, %d, %d, %d, %d }\n",
  720. absinfo.value, absinfo.minimum, absinfo.maximum,
  721. absinfo.fuzz, absinfo.flat);
  722. #endif /* DEBUG_INPUT_EVENTS */
  723. joystick->hwdata->abs_map[i] = joystick->naxes;
  724. joystick->hwdata->has_abs[i] = SDL_TRUE;
  725. if (absinfo.minimum == absinfo.maximum) {
  726. joystick->hwdata->abs_correct[i].used = 0;
  727. } else {
  728. joystick->hwdata->abs_correct[i].used = hint_used;
  729. joystick->hwdata->abs_correct[i].coef[0] =
  730. (absinfo.maximum + absinfo.minimum) - 2 * absinfo.flat;
  731. joystick->hwdata->abs_correct[i].coef[1] =
  732. (absinfo.maximum + absinfo.minimum) + 2 * absinfo.flat;
  733. t = ((absinfo.maximum - absinfo.minimum) - 4 * absinfo.flat);
  734. if (t != 0) {
  735. joystick->hwdata->abs_correct[i].coef[2] =
  736. (1 << 28) / t;
  737. } else {
  738. joystick->hwdata->abs_correct[i].coef[2] = 0;
  739. }
  740. }
  741. ++joystick->naxes;
  742. }
  743. }
  744. for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
  745. if (test_bit(i, absbit) || test_bit(i + 1, absbit)) {
  746. struct input_absinfo absinfo;
  747. int hat_index = (i - ABS_HAT0X) / 2;
  748. if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
  749. continue;
  750. }
  751. #ifdef DEBUG_INPUT_EVENTS
  752. printf("Joystick has hat %d\n", hat_index);
  753. printf("Values = { %d, %d, %d, %d, %d }\n",
  754. absinfo.value, absinfo.minimum, absinfo.maximum,
  755. absinfo.fuzz, absinfo.flat);
  756. #endif /* DEBUG_INPUT_EVENTS */
  757. joystick->hwdata->hats_indices[hat_index] = joystick->nhats++;
  758. joystick->hwdata->has_hat[hat_index] = SDL_TRUE;
  759. }
  760. }
  761. if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) {
  762. ++joystick->nballs;
  763. }
  764. /* Allocate data to keep track of these thingamajigs */
  765. if (joystick->nhats > 0) {
  766. if (allocate_hatdata(joystick) < 0) {
  767. joystick->nhats = 0;
  768. }
  769. }
  770. if (joystick->nballs > 0) {
  771. if (allocate_balldata(joystick) < 0) {
  772. joystick->nballs = 0;
  773. }
  774. }
  775. }
  776. if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(ffbit)), ffbit) >= 0) {
  777. if (test_bit(FF_RUMBLE, ffbit)) {
  778. joystick->hwdata->ff_rumble = SDL_TRUE;
  779. }
  780. if (test_bit(FF_SINE, ffbit)) {
  781. joystick->hwdata->ff_sine = SDL_TRUE;
  782. }
  783. }
  784. }
  785. /* Function to open a joystick for use.
  786. The joystick to open is specified by the device index.
  787. This should fill the nbuttons and naxes fields of the joystick structure.
  788. It returns 0, or -1 if there is an error.
  789. */
  790. static int
  791. LINUX_JoystickOpen(SDL_Joystick * joystick, int device_index)
  792. {
  793. SDL_joylist_item *item = JoystickByDevIndex(device_index);
  794. if (item == NULL) {
  795. return SDL_SetError("No such device");
  796. }
  797. joystick->instance_id = item->device_instance;
  798. joystick->hwdata = (struct joystick_hwdata *)
  799. SDL_calloc(1, sizeof(*joystick->hwdata));
  800. if (joystick->hwdata == NULL) {
  801. return SDL_OutOfMemory();
  802. }
  803. joystick->hwdata->item = item;
  804. joystick->hwdata->guid = item->guid;
  805. joystick->hwdata->effect.id = -1;
  806. joystick->hwdata->m_bSteamController = item->m_bSteamController;
  807. SDL_memset(joystick->hwdata->abs_map, 0xFF, sizeof(joystick->hwdata->abs_map));
  808. if (item->m_bSteamController) {
  809. joystick->hwdata->fd = -1;
  810. SDL_GetSteamControllerInputs(&joystick->nbuttons,
  811. &joystick->naxes,
  812. &joystick->nhats);
  813. } else {
  814. int fd = open(item->path, O_RDWR, 0);
  815. if (fd < 0) {
  816. SDL_free(joystick->hwdata);
  817. joystick->hwdata = NULL;
  818. return SDL_SetError("Unable to open %s", item->path);
  819. }
  820. joystick->hwdata->fd = fd;
  821. joystick->hwdata->fname = SDL_strdup(item->path);
  822. if (joystick->hwdata->fname == NULL) {
  823. SDL_free(joystick->hwdata);
  824. joystick->hwdata = NULL;
  825. close(fd);
  826. return SDL_OutOfMemory();
  827. }
  828. /* Set the joystick to non-blocking read mode */
  829. fcntl(fd, F_SETFL, O_NONBLOCK);
  830. /* Get the number of buttons and axes on the joystick */
  831. ConfigJoystick(joystick, fd);
  832. }
  833. SDL_assert(item->hwdata == NULL);
  834. item->hwdata = joystick->hwdata;
  835. /* mark joystick as fresh and ready */
  836. joystick->hwdata->fresh = SDL_TRUE;
  837. return (0);
  838. }
  839. static int
  840. LINUX_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
  841. {
  842. struct input_event event;
  843. if (joystick->hwdata->ff_rumble) {
  844. struct ff_effect *effect = &joystick->hwdata->effect;
  845. effect->type = FF_RUMBLE;
  846. effect->replay.length = SDL_MAX_RUMBLE_DURATION_MS;
  847. effect->u.rumble.strong_magnitude = low_frequency_rumble;
  848. effect->u.rumble.weak_magnitude = high_frequency_rumble;
  849. } else if (joystick->hwdata->ff_sine) {
  850. /* Scale and average the two rumble strengths */
  851. Sint16 magnitude = (Sint16)(((low_frequency_rumble / 2) + (high_frequency_rumble / 2)) / 2);
  852. struct ff_effect *effect = &joystick->hwdata->effect;
  853. effect->type = FF_PERIODIC;
  854. effect->replay.length = SDL_MAX_RUMBLE_DURATION_MS;
  855. effect->u.periodic.waveform = FF_SINE;
  856. effect->u.periodic.magnitude = magnitude;
  857. } else {
  858. return SDL_Unsupported();
  859. }
  860. if (ioctl(joystick->hwdata->fd, EVIOCSFF, &joystick->hwdata->effect) < 0) {
  861. /* The kernel may have lost this effect, try to allocate a new one */
  862. joystick->hwdata->effect.id = -1;
  863. if (ioctl(joystick->hwdata->fd, EVIOCSFF, &joystick->hwdata->effect) < 0) {
  864. return SDL_SetError("Couldn't update rumble effect: %s", strerror(errno));
  865. }
  866. }
  867. event.type = EV_FF;
  868. event.code = joystick->hwdata->effect.id;
  869. event.value = 1;
  870. if (write(joystick->hwdata->fd, &event, sizeof(event)) < 0) {
  871. return SDL_SetError("Couldn't start rumble effect: %s", strerror(errno));
  872. }
  873. return 0;
  874. }
  875. static int
  876. LINUX_JoystickRumbleTriggers(SDL_Joystick * joystick, Uint16 left_rumble, Uint16 right_rumble)
  877. {
  878. return SDL_Unsupported();
  879. }
  880. static SDL_bool
  881. LINUX_JoystickHasLED(SDL_Joystick * joystick)
  882. {
  883. return SDL_FALSE;
  884. }
  885. static int
  886. LINUX_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
  887. {
  888. return SDL_Unsupported();
  889. }
  890. static SDL_INLINE void
  891. HandleHat(SDL_Joystick * stick, Uint8 hat, int axis, int value)
  892. {
  893. struct hwdata_hat *the_hat;
  894. const Uint8 position_map[3][3] = {
  895. {SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP},
  896. {SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT},
  897. {SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN}
  898. };
  899. the_hat = &stick->hwdata->hats[hat];
  900. if (value < 0) {
  901. value = 0;
  902. } else if (value == 0) {
  903. value = 1;
  904. } else if (value > 0) {
  905. value = 2;
  906. }
  907. if (value != the_hat->axis[axis]) {
  908. the_hat->axis[axis] = value;
  909. SDL_PrivateJoystickHat(stick, hat,
  910. position_map[the_hat->axis[1]][the_hat->axis[0]]);
  911. }
  912. }
  913. static SDL_INLINE void
  914. HandleBall(SDL_Joystick * stick, Uint8 ball, int axis, int value)
  915. {
  916. stick->hwdata->balls[ball].axis[axis] += value;
  917. }
  918. static SDL_INLINE int
  919. AxisCorrect(SDL_Joystick * joystick, int which, int value)
  920. {
  921. struct axis_correct *correct;
  922. correct = &joystick->hwdata->abs_correct[which];
  923. if (correct->used) {
  924. value *= 2;
  925. if (value > correct->coef[0]) {
  926. if (value < correct->coef[1]) {
  927. return 0;
  928. }
  929. value -= correct->coef[1];
  930. } else {
  931. value -= correct->coef[0];
  932. }
  933. value *= correct->coef[2];
  934. value >>= 13;
  935. }
  936. /* Clamp and return */
  937. if (value < -32768)
  938. return -32768;
  939. if (value > 32767)
  940. return 32767;
  941. return value;
  942. }
  943. static SDL_INLINE void
  944. PollAllValues(SDL_Joystick * joystick)
  945. {
  946. struct input_absinfo absinfo;
  947. unsigned long keyinfo[NBITS(KEY_MAX)];
  948. int i;
  949. /* Poll all axis */
  950. for (i = ABS_X; i < ABS_MAX; i++) {
  951. if (i == ABS_HAT0X) { /* we handle hats in the next loop, skip them for now. */
  952. i = ABS_HAT3Y;
  953. continue;
  954. }
  955. if (joystick->hwdata->abs_correct[i].used) {
  956. if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
  957. absinfo.value = AxisCorrect(joystick, i, absinfo.value);
  958. #ifdef DEBUG_INPUT_EVENTS
  959. printf("Joystick : Re-read Axis %d (%d) val= %d\n",
  960. joystick->hwdata->abs_map[i], i, absinfo.value);
  961. #endif
  962. SDL_PrivateJoystickAxis(joystick,
  963. joystick->hwdata->abs_map[i],
  964. absinfo.value);
  965. }
  966. }
  967. }
  968. /* Poll all hats */
  969. for (i = ABS_HAT0X; i <= ABS_HAT3Y; i++) {
  970. const int baseaxis = i - ABS_HAT0X;
  971. const int hatidx = baseaxis / 2;
  972. SDL_assert(hatidx < SDL_arraysize(joystick->hwdata->has_hat));
  973. if (joystick->hwdata->has_hat[hatidx]) {
  974. if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
  975. const int hataxis = baseaxis % 2;
  976. HandleHat(joystick, joystick->hwdata->hats_indices[hatidx], hataxis, absinfo.value);
  977. }
  978. }
  979. }
  980. /* Poll all buttons */
  981. SDL_zeroa(keyinfo);
  982. if (ioctl(joystick->hwdata->fd, EVIOCGKEY(sizeof (keyinfo)), keyinfo) >= 0) {
  983. for (i = 0; i < KEY_MAX; i++) {
  984. if (joystick->hwdata->has_key[i]) {
  985. const Uint8 value = test_bit(i, keyinfo) ? SDL_PRESSED : SDL_RELEASED;
  986. #ifdef DEBUG_INPUT_EVENTS
  987. printf("Joystick : Re-read Button %d (%d) val= %d\n",
  988. joystick->hwdata->key_map[i], i, value);
  989. #endif
  990. SDL_PrivateJoystickButton(joystick,
  991. joystick->hwdata->key_map[i], value);
  992. }
  993. }
  994. }
  995. /* Joyballs are relative input, so there's no poll state. Events only! */
  996. }
  997. static SDL_INLINE void
  998. HandleInputEvents(SDL_Joystick * joystick)
  999. {
  1000. struct input_event events[32];
  1001. int i, len;
  1002. int code;
  1003. if (joystick->hwdata->fresh) {
  1004. PollAllValues(joystick);
  1005. joystick->hwdata->fresh = SDL_FALSE;
  1006. }
  1007. while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
  1008. len /= sizeof(events[0]);
  1009. for (i = 0; i < len; ++i) {
  1010. code = events[i].code;
  1011. /* If the kernel sent a SYN_DROPPED, we are supposed to ignore the
  1012. rest of the packet (the end of it signified by a SYN_REPORT) */
  1013. if ( joystick->hwdata->recovering_from_dropped &&
  1014. ((events[i].type != EV_SYN) || (code != SYN_REPORT)) ) {
  1015. continue;
  1016. }
  1017. switch (events[i].type) {
  1018. case EV_KEY:
  1019. SDL_PrivateJoystickButton(joystick,
  1020. joystick->hwdata->key_map[code],
  1021. events[i].value);
  1022. break;
  1023. case EV_ABS:
  1024. switch (code) {
  1025. case ABS_HAT0X:
  1026. case ABS_HAT0Y:
  1027. case ABS_HAT1X:
  1028. case ABS_HAT1Y:
  1029. case ABS_HAT2X:
  1030. case ABS_HAT2Y:
  1031. case ABS_HAT3X:
  1032. case ABS_HAT3Y:
  1033. code -= ABS_HAT0X;
  1034. HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value);
  1035. break;
  1036. default:
  1037. if (joystick->hwdata->abs_map[code] != 0xFF) {
  1038. events[i].value =
  1039. AxisCorrect(joystick, code, events[i].value);
  1040. SDL_PrivateJoystickAxis(joystick,
  1041. joystick->hwdata->abs_map[code],
  1042. events[i].value);
  1043. }
  1044. break;
  1045. }
  1046. break;
  1047. case EV_REL:
  1048. switch (code) {
  1049. case REL_X:
  1050. case REL_Y:
  1051. code -= REL_X;
  1052. HandleBall(joystick, code / 2, code % 2, events[i].value);
  1053. break;
  1054. default:
  1055. break;
  1056. }
  1057. break;
  1058. case EV_SYN:
  1059. switch (code) {
  1060. case SYN_DROPPED :
  1061. #ifdef DEBUG_INPUT_EVENTS
  1062. printf("Event SYN_DROPPED detected\n");
  1063. #endif
  1064. joystick->hwdata->recovering_from_dropped = SDL_TRUE;
  1065. break;
  1066. case SYN_REPORT :
  1067. if (joystick->hwdata->recovering_from_dropped) {
  1068. joystick->hwdata->recovering_from_dropped = SDL_FALSE;
  1069. PollAllValues(joystick); /* try to sync up to current state now */
  1070. }
  1071. break;
  1072. default:
  1073. break;
  1074. }
  1075. default:
  1076. break;
  1077. }
  1078. }
  1079. }
  1080. if (errno == ENODEV) {
  1081. /* We have to wait until the JoystickDetect callback to remove this */
  1082. joystick->hwdata->gone = SDL_TRUE;
  1083. }
  1084. }
  1085. static void
  1086. LINUX_JoystickUpdate(SDL_Joystick * joystick)
  1087. {
  1088. int i;
  1089. if (joystick->hwdata->m_bSteamController) {
  1090. SDL_UpdateSteamController(joystick);
  1091. return;
  1092. }
  1093. HandleInputEvents(joystick);
  1094. /* Deliver ball motion updates */
  1095. for (i = 0; i < joystick->nballs; ++i) {
  1096. int xrel, yrel;
  1097. xrel = joystick->hwdata->balls[i].axis[0];
  1098. yrel = joystick->hwdata->balls[i].axis[1];
  1099. if (xrel || yrel) {
  1100. joystick->hwdata->balls[i].axis[0] = 0;
  1101. joystick->hwdata->balls[i].axis[1] = 0;
  1102. SDL_PrivateJoystickBall(joystick, (Uint8) i, xrel, yrel);
  1103. }
  1104. }
  1105. }
  1106. /* Function to close a joystick after use */
  1107. static void
  1108. LINUX_JoystickClose(SDL_Joystick * joystick)
  1109. {
  1110. if (joystick->hwdata) {
  1111. if (joystick->hwdata->effect.id >= 0) {
  1112. ioctl(joystick->hwdata->fd, EVIOCRMFF, joystick->hwdata->effect.id);
  1113. joystick->hwdata->effect.id = -1;
  1114. }
  1115. if (joystick->hwdata->fd >= 0) {
  1116. close(joystick->hwdata->fd);
  1117. }
  1118. if (joystick->hwdata->item) {
  1119. joystick->hwdata->item->hwdata = NULL;
  1120. }
  1121. SDL_free(joystick->hwdata->hats);
  1122. SDL_free(joystick->hwdata->balls);
  1123. SDL_free(joystick->hwdata->fname);
  1124. SDL_free(joystick->hwdata);
  1125. }
  1126. }
  1127. /* Function to perform any system-specific joystick related cleanup */
  1128. static void
  1129. LINUX_JoystickQuit(void)
  1130. {
  1131. SDL_joylist_item *item = NULL;
  1132. SDL_joylist_item *next = NULL;
  1133. close(inotify_fd);
  1134. inotify_fd = -1;
  1135. for (item = SDL_joylist; item; item = next) {
  1136. next = item->next;
  1137. SDL_free(item->path);
  1138. SDL_free(item->name);
  1139. SDL_free(item);
  1140. }
  1141. SDL_joylist = SDL_joylist_tail = NULL;
  1142. numjoysticks = 0;
  1143. #if SDL_USE_LIBUDEV
  1144. if (enumeration_method == ENUMERATION_LIBUDEV) {
  1145. SDL_UDEV_DelCallback(joystick_udev_callback);
  1146. SDL_UDEV_Quit();
  1147. }
  1148. #endif
  1149. SDL_QuitSteamControllers();
  1150. }
  1151. /*
  1152. This is based on the Linux Gamepad Specification
  1153. available at: https://www.kernel.org/doc/html/v4.15/input/gamepad.html
  1154. */
  1155. static SDL_bool
  1156. LINUX_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
  1157. {
  1158. SDL_Joystick * joystick;
  1159. joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1);
  1160. if (joystick == NULL) {
  1161. SDL_OutOfMemory();
  1162. return SDL_FALSE;
  1163. }
  1164. /* We temporarily open the device to check how it's configured. */
  1165. if (LINUX_JoystickOpen(joystick, device_index) < 0) {
  1166. SDL_free(joystick);
  1167. return SDL_FALSE;
  1168. }
  1169. if (!joystick->hwdata->has_key[BTN_GAMEPAD]) {
  1170. /* Not a gamepad according to the specs. */
  1171. LINUX_JoystickClose(joystick);
  1172. SDL_free(joystick);
  1173. return SDL_FALSE;
  1174. }
  1175. /* We have a gamepad, start filling out the mappings */
  1176. if (joystick->hwdata->has_key[BTN_SOUTH]) {
  1177. out->a.kind = EMappingKind_Button;
  1178. out->a.target = joystick->hwdata->key_map[BTN_SOUTH];
  1179. }
  1180. if (joystick->hwdata->has_key[BTN_EAST]) {
  1181. out->b.kind = EMappingKind_Button;
  1182. out->b.target = joystick->hwdata->key_map[BTN_EAST];
  1183. }
  1184. if (joystick->hwdata->has_key[BTN_NORTH]) {
  1185. out->y.kind = EMappingKind_Button;
  1186. out->y.target = joystick->hwdata->key_map[BTN_NORTH];
  1187. }
  1188. if (joystick->hwdata->has_key[BTN_WEST]) {
  1189. out->x.kind = EMappingKind_Button;
  1190. out->x.target = joystick->hwdata->key_map[BTN_WEST];
  1191. }
  1192. if (joystick->hwdata->has_key[BTN_SELECT]) {
  1193. out->back.kind = EMappingKind_Button;
  1194. out->back.target = joystick->hwdata->key_map[BTN_SELECT];
  1195. }
  1196. if (joystick->hwdata->has_key[BTN_START]) {
  1197. out->start.kind = EMappingKind_Button;
  1198. out->start.target = joystick->hwdata->key_map[BTN_START];
  1199. }
  1200. if (joystick->hwdata->has_key[BTN_THUMBL]) {
  1201. out->leftstick.kind = EMappingKind_Button;
  1202. out->leftstick.target = joystick->hwdata->key_map[BTN_THUMBL];
  1203. }
  1204. if (joystick->hwdata->has_key[BTN_THUMBR]) {
  1205. out->rightstick.kind = EMappingKind_Button;
  1206. out->rightstick.target = joystick->hwdata->key_map[BTN_THUMBR];
  1207. }
  1208. if (joystick->hwdata->has_key[BTN_MODE]) {
  1209. out->guide.kind = EMappingKind_Button;
  1210. out->guide.target = joystick->hwdata->key_map[BTN_MODE];
  1211. }
  1212. /*
  1213. According to the specs the D-Pad, the shoulder buttons and the triggers
  1214. can be digital, or analog, or both at the same time.
  1215. */
  1216. /* Prefer digital shoulder buttons, but settle for analog if missing. */
  1217. if (joystick->hwdata->has_key[BTN_TL]) {
  1218. out->leftshoulder.kind = EMappingKind_Button;
  1219. out->leftshoulder.target = joystick->hwdata->key_map[BTN_TL];
  1220. }
  1221. if (joystick->hwdata->has_key[BTN_TR]) {
  1222. out->rightshoulder.kind = EMappingKind_Button;
  1223. out->rightshoulder.target = joystick->hwdata->key_map[BTN_TR];
  1224. }
  1225. if (joystick->hwdata->has_hat[1] && /* Check if ABS_HAT1{X, Y} is available. */
  1226. (!joystick->hwdata->has_key[BTN_TL] || !joystick->hwdata->has_key[BTN_TR])) {
  1227. int hat = joystick->hwdata->hats_indices[1] << 4;
  1228. out->leftshoulder.kind = EMappingKind_Hat;
  1229. out->rightshoulder.kind = EMappingKind_Hat;
  1230. out->leftshoulder.target = hat | 0x4;
  1231. out->rightshoulder.target = hat | 0x2;
  1232. }
  1233. /* Prefer analog triggers, but settle for digital if missing. */
  1234. if (joystick->hwdata->has_hat[2]) { /* Check if ABS_HAT2{X,Y} is available. */
  1235. int hat = joystick->hwdata->hats_indices[2] << 4;
  1236. out->lefttrigger.kind = EMappingKind_Hat;
  1237. out->righttrigger.kind = EMappingKind_Hat;
  1238. out->lefttrigger.target = hat | 0x4;
  1239. out->righttrigger.target = hat | 0x2;
  1240. } else {
  1241. if (joystick->hwdata->has_key[BTN_TL2]) {
  1242. out->lefttrigger.kind = EMappingKind_Button;
  1243. out->lefttrigger.target = joystick->hwdata->key_map[BTN_TL2];
  1244. }
  1245. if (joystick->hwdata->has_key[BTN_TR2]) {
  1246. out->righttrigger.kind = EMappingKind_Button;
  1247. out->righttrigger.target = joystick->hwdata->key_map[BTN_TR2];
  1248. }
  1249. }
  1250. /* Prefer digital D-Pad, but settle for analog if missing. */
  1251. if (joystick->hwdata->has_key[BTN_DPAD_UP]) {
  1252. out->dpup.kind = EMappingKind_Button;
  1253. out->dpup.target = joystick->hwdata->key_map[BTN_DPAD_UP];
  1254. }
  1255. if (joystick->hwdata->has_key[BTN_DPAD_DOWN]) {
  1256. out->dpdown.kind = EMappingKind_Button;
  1257. out->dpdown.target = joystick->hwdata->key_map[BTN_DPAD_DOWN];
  1258. }
  1259. if (joystick->hwdata->has_key[BTN_DPAD_LEFT]) {
  1260. out->dpleft.kind = EMappingKind_Button;
  1261. out->dpleft.target = joystick->hwdata->key_map[BTN_DPAD_LEFT];
  1262. }
  1263. if (joystick->hwdata->has_key[BTN_DPAD_RIGHT]) {
  1264. out->dpright.kind = EMappingKind_Button;
  1265. out->dpright.target = joystick->hwdata->key_map[BTN_DPAD_RIGHT];
  1266. }
  1267. if (joystick->hwdata->has_hat[0] && /* Check if ABS_HAT0{X,Y} is available. */
  1268. (!joystick->hwdata->has_key[BTN_DPAD_LEFT] || !joystick->hwdata->has_key[BTN_DPAD_RIGHT] ||
  1269. !joystick->hwdata->has_key[BTN_DPAD_UP] || !joystick->hwdata->has_key[BTN_DPAD_DOWN])) {
  1270. int hat = joystick->hwdata->hats_indices[0] << 4;
  1271. out->dpleft.kind = EMappingKind_Hat;
  1272. out->dpright.kind = EMappingKind_Hat;
  1273. out->dpup.kind = EMappingKind_Hat;
  1274. out->dpdown.kind = EMappingKind_Hat;
  1275. out->dpleft.target = hat | 0x8;
  1276. out->dpright.target = hat | 0x2;
  1277. out->dpup.target = hat | 0x1;
  1278. out->dpdown.target = hat | 0x4;
  1279. }
  1280. if (joystick->hwdata->has_abs[ABS_X] && joystick->hwdata->has_abs[ABS_Y]) {
  1281. out->leftx.kind = EMappingKind_Axis;
  1282. out->lefty.kind = EMappingKind_Axis;
  1283. out->leftx.target = joystick->hwdata->abs_map[ABS_X];
  1284. out->lefty.target = joystick->hwdata->abs_map[ABS_Y];
  1285. }
  1286. if (joystick->hwdata->has_abs[ABS_RX] && joystick->hwdata->has_abs[ABS_RY]) {
  1287. out->rightx.kind = EMappingKind_Axis;
  1288. out->righty.kind = EMappingKind_Axis;
  1289. out->rightx.target = joystick->hwdata->abs_map[ABS_RX];
  1290. out->righty.target = joystick->hwdata->abs_map[ABS_RY];
  1291. }
  1292. LINUX_JoystickClose(joystick);
  1293. SDL_free(joystick);
  1294. return SDL_TRUE;
  1295. }
  1296. SDL_JoystickDriver SDL_LINUX_JoystickDriver =
  1297. {
  1298. LINUX_JoystickInit,
  1299. LINUX_JoystickGetCount,
  1300. LINUX_JoystickDetect,
  1301. LINUX_JoystickGetDeviceName,
  1302. LINUX_JoystickGetDevicePlayerIndex,
  1303. LINUX_JoystickSetDevicePlayerIndex,
  1304. LINUX_JoystickGetDeviceGUID,
  1305. LINUX_JoystickGetDeviceInstanceID,
  1306. LINUX_JoystickOpen,
  1307. LINUX_JoystickRumble,
  1308. LINUX_JoystickRumbleTriggers,
  1309. LINUX_JoystickHasLED,
  1310. LINUX_JoystickSetLED,
  1311. LINUX_JoystickUpdate,
  1312. LINUX_JoystickClose,
  1313. LINUX_JoystickQuit,
  1314. LINUX_JoystickGetGamepadMapping
  1315. };
  1316. #endif /* SDL_JOYSTICK_LINUX */
  1317. /* vi: set ts=4 sw=4 expandtab: */