SDL_sysjoystick.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
  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/ioctl.h>
  29. #include <unistd.h>
  30. #include <dirent.h>
  31. #include <linux/joystick.h>
  32. #include "SDL_assert.h"
  33. #include "SDL_joystick.h"
  34. #include "SDL_endian.h"
  35. #include "SDL_timer.h"
  36. #include "../../events/SDL_events_c.h"
  37. #include "../SDL_sysjoystick.h"
  38. #include "../SDL_joystick_c.h"
  39. #include "../steam/SDL_steamcontroller.h"
  40. #include "SDL_sysjoystick_c.h"
  41. #include "../hidapi/SDL_hidapijoystick_c.h"
  42. /* This isn't defined in older Linux kernel headers */
  43. #ifndef SYN_DROPPED
  44. #define SYN_DROPPED 3
  45. #endif
  46. #include "../../core/linux/SDL_udev.h"
  47. static int MaybeAddDevice(const char *path);
  48. #if SDL_USE_LIBUDEV
  49. static int MaybeRemoveDevice(const char *path);
  50. #endif /* SDL_USE_LIBUDEV */
  51. /* A linked list of available joysticks */
  52. typedef struct SDL_joylist_item
  53. {
  54. int device_instance;
  55. char *path; /* "/dev/input/event2" or whatever */
  56. char *name; /* "SideWinder 3D Pro" or whatever */
  57. SDL_JoystickGUID guid;
  58. dev_t devnum;
  59. struct joystick_hwdata *hwdata;
  60. struct SDL_joylist_item *next;
  61. /* Steam Controller support */
  62. SDL_bool m_bSteamController;
  63. } SDL_joylist_item;
  64. static SDL_joylist_item *SDL_joylist = NULL;
  65. static SDL_joylist_item *SDL_joylist_tail = NULL;
  66. static int numjoysticks = 0;
  67. #if !SDL_USE_LIBUDEV
  68. static Uint32 last_joy_detect_time;
  69. static time_t last_input_dir_mtime;
  70. #endif
  71. #define test_bit(nr, addr) \
  72. (((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
  73. #define NBITS(x) ((((x)-1)/(sizeof(long) * 8))+1)
  74. static int
  75. PrefixMatch(const char *a, const char *b)
  76. {
  77. int matchlen = 0;
  78. while (*a && *b) {
  79. if (*a++ == *b++) {
  80. ++matchlen;
  81. } else {
  82. break;
  83. }
  84. }
  85. return matchlen;
  86. }
  87. static int
  88. IsJoystick(int fd, char *namebuf, const size_t namebuflen, SDL_JoystickGUID *guid)
  89. {
  90. struct input_id inpid;
  91. Uint16 *guid16 = (Uint16 *)guid->data;
  92. const char *name;
  93. const char *spot;
  94. #if !SDL_USE_LIBUDEV
  95. /* When udev is enabled we only get joystick devices here, so there's no need to test them */
  96. unsigned long evbit[NBITS(EV_MAX)] = { 0 };
  97. unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
  98. unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
  99. if ((ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
  100. (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
  101. (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) {
  102. return (0);
  103. }
  104. if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) &&
  105. test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit))) {
  106. return 0;
  107. }
  108. #endif
  109. if (ioctl(fd, EVIOCGID, &inpid) < 0) {
  110. return 0;
  111. }
  112. name = SDL_GetCustomJoystickName(inpid.vendor, inpid.product);
  113. if (name) {
  114. SDL_strlcpy(namebuf, name, namebuflen);
  115. } else {
  116. if (ioctl(fd, EVIOCGNAME(namebuflen), namebuf) < 0) {
  117. return 0;
  118. }
  119. /* Remove duplicate manufacturer in the name */
  120. for (spot = namebuf + 1; *spot; ++spot) {
  121. int matchlen = PrefixMatch(namebuf, spot);
  122. if (matchlen > 0 && spot[matchlen - 1] == ' ') {
  123. SDL_memmove(namebuf, spot, SDL_strlen(spot)+1);
  124. break;
  125. }
  126. }
  127. }
  128. #ifdef SDL_JOYSTICK_HIDAPI
  129. if (HIDAPI_IsDevicePresent(inpid.vendor, inpid.product, inpid.version, namebuf)) {
  130. /* The HIDAPI driver is taking care of this device */
  131. return 0;
  132. }
  133. #endif
  134. #ifdef DEBUG_JOYSTICK
  135. printf("Joystick: %s, bustype = %d, vendor = 0x%.4x, product = 0x%.4x, version = %d\n", namebuf, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
  136. #endif
  137. SDL_memset(guid->data, 0, sizeof(guid->data));
  138. /* We only need 16 bits for each of these; space them out to fill 128. */
  139. /* Byteswap so devices get same GUID on little/big endian platforms. */
  140. *guid16++ = SDL_SwapLE16(inpid.bustype);
  141. *guid16++ = 0;
  142. if (inpid.vendor && inpid.product) {
  143. *guid16++ = SDL_SwapLE16(inpid.vendor);
  144. *guid16++ = 0;
  145. *guid16++ = SDL_SwapLE16(inpid.product);
  146. *guid16++ = 0;
  147. *guid16++ = SDL_SwapLE16(inpid.version);
  148. *guid16++ = 0;
  149. } else {
  150. SDL_strlcpy((char*)guid16, namebuf, sizeof(guid->data) - 4);
  151. }
  152. if (SDL_ShouldIgnoreJoystick(namebuf, *guid)) {
  153. return 0;
  154. }
  155. return 1;
  156. }
  157. #if SDL_USE_LIBUDEV
  158. static void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
  159. {
  160. if (devpath == NULL) {
  161. return;
  162. }
  163. switch (udev_type) {
  164. case SDL_UDEV_DEVICEADDED:
  165. if (!(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
  166. return;
  167. }
  168. MaybeAddDevice(devpath);
  169. break;
  170. case SDL_UDEV_DEVICEREMOVED:
  171. MaybeRemoveDevice(devpath);
  172. break;
  173. default:
  174. break;
  175. }
  176. }
  177. #endif /* SDL_USE_LIBUDEV */
  178. static int
  179. MaybeAddDevice(const char *path)
  180. {
  181. struct stat sb;
  182. int fd = -1;
  183. int isstick = 0;
  184. char namebuf[128];
  185. SDL_JoystickGUID guid;
  186. SDL_joylist_item *item;
  187. if (path == NULL) {
  188. return -1;
  189. }
  190. if (stat(path, &sb) == -1) {
  191. return -1;
  192. }
  193. /* Check to make sure it's not already in list. */
  194. for (item = SDL_joylist; item != NULL; item = item->next) {
  195. if (sb.st_rdev == item->devnum) {
  196. return -1; /* already have this one */
  197. }
  198. }
  199. fd = open(path, O_RDONLY, 0);
  200. if (fd < 0) {
  201. return -1;
  202. }
  203. #ifdef DEBUG_INPUT_EVENTS
  204. printf("Checking %s\n", path);
  205. #endif
  206. isstick = IsJoystick(fd, namebuf, sizeof (namebuf), &guid);
  207. close(fd);
  208. if (!isstick) {
  209. return -1;
  210. }
  211. item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
  212. if (item == NULL) {
  213. return -1;
  214. }
  215. SDL_zerop(item);
  216. item->devnum = sb.st_rdev;
  217. item->path = SDL_strdup(path);
  218. item->name = SDL_strdup(namebuf);
  219. item->guid = guid;
  220. if ((item->path == NULL) || (item->name == NULL)) {
  221. SDL_free(item->path);
  222. SDL_free(item->name);
  223. SDL_free(item);
  224. return -1;
  225. }
  226. item->device_instance = SDL_GetNextJoystickInstanceID();
  227. if (SDL_joylist_tail == NULL) {
  228. SDL_joylist = SDL_joylist_tail = item;
  229. } else {
  230. SDL_joylist_tail->next = item;
  231. SDL_joylist_tail = item;
  232. }
  233. /* Need to increment the joystick count before we post the event */
  234. ++numjoysticks;
  235. SDL_PrivateJoystickAdded(item->device_instance);
  236. return numjoysticks;
  237. }
  238. #if SDL_USE_LIBUDEV
  239. static int
  240. MaybeRemoveDevice(const char *path)
  241. {
  242. SDL_joylist_item *item;
  243. SDL_joylist_item *prev = NULL;
  244. if (path == NULL) {
  245. return -1;
  246. }
  247. for (item = SDL_joylist; item != NULL; item = item->next) {
  248. /* found it, remove it. */
  249. if (SDL_strcmp(path, item->path) == 0) {
  250. const int retval = item->device_instance;
  251. if (item->hwdata) {
  252. item->hwdata->item = NULL;
  253. }
  254. if (prev != NULL) {
  255. prev->next = item->next;
  256. } else {
  257. SDL_assert(SDL_joylist == item);
  258. SDL_joylist = item->next;
  259. }
  260. if (item == SDL_joylist_tail) {
  261. SDL_joylist_tail = prev;
  262. }
  263. /* Need to decrement the joystick count before we post the event */
  264. --numjoysticks;
  265. SDL_PrivateJoystickRemoved(item->device_instance);
  266. SDL_free(item->path);
  267. SDL_free(item->name);
  268. SDL_free(item);
  269. return retval;
  270. }
  271. prev = item;
  272. }
  273. return -1;
  274. }
  275. #endif
  276. static void
  277. HandlePendingRemovals(void)
  278. {
  279. SDL_joylist_item *prev = NULL;
  280. SDL_joylist_item *item = SDL_joylist;
  281. while (item != NULL) {
  282. if (item->hwdata && item->hwdata->gone) {
  283. item->hwdata->item = NULL;
  284. if (prev != NULL) {
  285. prev->next = item->next;
  286. } else {
  287. SDL_assert(SDL_joylist == item);
  288. SDL_joylist = item->next;
  289. }
  290. if (item == SDL_joylist_tail) {
  291. SDL_joylist_tail = prev;
  292. }
  293. /* Need to decrement the joystick count before we post the event */
  294. --numjoysticks;
  295. SDL_PrivateJoystickRemoved(item->device_instance);
  296. SDL_free(item->path);
  297. SDL_free(item->name);
  298. SDL_free(item);
  299. if (prev != NULL) {
  300. item = prev->next;
  301. } else {
  302. item = SDL_joylist;
  303. }
  304. } else {
  305. prev = item;
  306. item = item->next;
  307. }
  308. }
  309. }
  310. static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickGUID guid, int *device_instance)
  311. {
  312. SDL_joylist_item *item;
  313. item = (SDL_joylist_item *) SDL_calloc(1, sizeof (SDL_joylist_item));
  314. if (item == NULL) {
  315. return SDL_FALSE;
  316. }
  317. item->path = SDL_strdup("");
  318. item->name = SDL_strdup(name);
  319. item->guid = guid;
  320. item->m_bSteamController = SDL_TRUE;
  321. if ((item->path == NULL) || (item->name == NULL)) {
  322. SDL_free(item->path);
  323. SDL_free(item->name);
  324. SDL_free(item);
  325. return SDL_FALSE;
  326. }
  327. *device_instance = item->device_instance = SDL_GetNextJoystickInstanceID();
  328. if (SDL_joylist_tail == NULL) {
  329. SDL_joylist = SDL_joylist_tail = item;
  330. } else {
  331. SDL_joylist_tail->next = item;
  332. SDL_joylist_tail = item;
  333. }
  334. /* Need to increment the joystick count before we post the event */
  335. ++numjoysticks;
  336. SDL_PrivateJoystickAdded(item->device_instance);
  337. return SDL_TRUE;
  338. }
  339. static void SteamControllerDisconnectedCallback(int device_instance)
  340. {
  341. SDL_joylist_item *item;
  342. SDL_joylist_item *prev = NULL;
  343. for (item = SDL_joylist; item != NULL; item = item->next) {
  344. /* found it, remove it. */
  345. if (item->device_instance == device_instance) {
  346. if (item->hwdata) {
  347. item->hwdata->item = NULL;
  348. }
  349. if (prev != NULL) {
  350. prev->next = item->next;
  351. } else {
  352. SDL_assert(SDL_joylist == item);
  353. SDL_joylist = item->next;
  354. }
  355. if (item == SDL_joylist_tail) {
  356. SDL_joylist_tail = prev;
  357. }
  358. /* Need to decrement the joystick count before we post the event */
  359. --numjoysticks;
  360. SDL_PrivateJoystickRemoved(item->device_instance);
  361. SDL_free(item->name);
  362. SDL_free(item);
  363. return;
  364. }
  365. prev = item;
  366. }
  367. }
  368. static void
  369. LINUX_JoystickDetect(void)
  370. {
  371. #if SDL_USE_LIBUDEV
  372. SDL_UDEV_Poll();
  373. #else
  374. const Uint32 SDL_JOY_DETECT_INTERVAL_MS = 3000; /* Update every 3 seconds */
  375. Uint32 now = SDL_GetTicks();
  376. if (!last_joy_detect_time || SDL_TICKS_PASSED(now, last_joy_detect_time + SDL_JOY_DETECT_INTERVAL_MS)) {
  377. struct stat sb;
  378. /* Opening input devices can generate synchronous device I/O, so avoid it if we can */
  379. if (stat("/dev/input", &sb) == 0 && sb.st_mtime != last_input_dir_mtime) {
  380. DIR *folder;
  381. struct dirent *dent;
  382. folder = opendir("/dev/input");
  383. if (folder) {
  384. while ((dent = readdir(folder))) {
  385. int len = SDL_strlen(dent->d_name);
  386. if (len > 5 && SDL_strncmp(dent->d_name, "event", 5) == 0) {
  387. char path[PATH_MAX];
  388. SDL_snprintf(path, SDL_arraysize(path), "/dev/input/%s", dent->d_name);
  389. MaybeAddDevice(path);
  390. }
  391. }
  392. closedir(folder);
  393. }
  394. last_input_dir_mtime = sb.st_mtime;
  395. }
  396. last_joy_detect_time = now;
  397. }
  398. #endif
  399. HandlePendingRemovals();
  400. SDL_UpdateSteamControllers();
  401. }
  402. static int
  403. LINUX_JoystickInit(void)
  404. {
  405. /* First see if the user specified one or more joysticks to use */
  406. if (SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL) {
  407. char *envcopy, *envpath, *delim;
  408. envcopy = SDL_strdup(SDL_getenv("SDL_JOYSTICK_DEVICE"));
  409. envpath = envcopy;
  410. while (envpath != NULL) {
  411. delim = SDL_strchr(envpath, ':');
  412. if (delim != NULL) {
  413. *delim++ = '\0';
  414. }
  415. MaybeAddDevice(envpath);
  416. envpath = delim;
  417. }
  418. SDL_free(envcopy);
  419. }
  420. SDL_InitSteamControllers(SteamControllerConnectedCallback,
  421. SteamControllerDisconnectedCallback);
  422. #if SDL_USE_LIBUDEV
  423. if (SDL_UDEV_Init() < 0) {
  424. return SDL_SetError("Could not initialize UDEV");
  425. }
  426. /* Set up the udev callback */
  427. if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
  428. SDL_UDEV_Quit();
  429. return SDL_SetError("Could not set up joystick <-> udev callback");
  430. }
  431. /* Force a scan to build the initial device list */
  432. SDL_UDEV_Scan();
  433. #else
  434. /* Force immediate joystick detection */
  435. last_joy_detect_time = 0;
  436. last_input_dir_mtime = 0;
  437. /* Report all devices currently present */
  438. LINUX_JoystickDetect();
  439. #endif
  440. return 0;
  441. }
  442. static int
  443. LINUX_JoystickGetCount(void)
  444. {
  445. return numjoysticks;
  446. }
  447. static SDL_joylist_item *
  448. JoystickByDevIndex(int device_index)
  449. {
  450. SDL_joylist_item *item = SDL_joylist;
  451. if ((device_index < 0) || (device_index >= numjoysticks)) {
  452. return NULL;
  453. }
  454. while (device_index > 0) {
  455. SDL_assert(item != NULL);
  456. device_index--;
  457. item = item->next;
  458. }
  459. return item;
  460. }
  461. /* Function to get the device-dependent name of a joystick */
  462. static const char *
  463. LINUX_JoystickGetDeviceName(int device_index)
  464. {
  465. return JoystickByDevIndex(device_index)->name;
  466. }
  467. static int
  468. LINUX_JoystickGetDevicePlayerIndex(int device_index)
  469. {
  470. return -1;
  471. }
  472. static void
  473. LINUX_JoystickSetDevicePlayerIndex(int device_index, int player_index)
  474. {
  475. }
  476. static SDL_JoystickGUID
  477. LINUX_JoystickGetDeviceGUID( int device_index )
  478. {
  479. return JoystickByDevIndex(device_index)->guid;
  480. }
  481. /* Function to perform the mapping from device index to the instance id for this index */
  482. static SDL_JoystickID
  483. LINUX_JoystickGetDeviceInstanceID(int device_index)
  484. {
  485. return JoystickByDevIndex(device_index)->device_instance;
  486. }
  487. static int
  488. allocate_hatdata(SDL_Joystick * joystick)
  489. {
  490. int i;
  491. joystick->hwdata->hats =
  492. (struct hwdata_hat *) SDL_malloc(joystick->nhats *
  493. sizeof(struct hwdata_hat));
  494. if (joystick->hwdata->hats == NULL) {
  495. return (-1);
  496. }
  497. for (i = 0; i < joystick->nhats; ++i) {
  498. joystick->hwdata->hats[i].axis[0] = 1;
  499. joystick->hwdata->hats[i].axis[1] = 1;
  500. }
  501. return (0);
  502. }
  503. static int
  504. allocate_balldata(SDL_Joystick * joystick)
  505. {
  506. int i;
  507. joystick->hwdata->balls =
  508. (struct hwdata_ball *) SDL_malloc(joystick->nballs *
  509. sizeof(struct hwdata_ball));
  510. if (joystick->hwdata->balls == NULL) {
  511. return (-1);
  512. }
  513. for (i = 0; i < joystick->nballs; ++i) {
  514. joystick->hwdata->balls[i].axis[0] = 0;
  515. joystick->hwdata->balls[i].axis[1] = 0;
  516. }
  517. return (0);
  518. }
  519. static void
  520. ConfigJoystick(SDL_Joystick * joystick, int fd)
  521. {
  522. int i, t;
  523. unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
  524. unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
  525. unsigned long relbit[NBITS(REL_MAX)] = { 0 };
  526. unsigned long ffbit[NBITS(FF_MAX)] = { 0 };
  527. /* See if this device uses the new unified event API */
  528. if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
  529. (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) &&
  530. (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0)) {
  531. /* Get the number of buttons, axes, and other thingamajigs */
  532. for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
  533. if (test_bit(i, keybit)) {
  534. #ifdef DEBUG_INPUT_EVENTS
  535. printf("Joystick has button: 0x%x\n", i);
  536. #endif
  537. joystick->hwdata->key_map[i] = joystick->nbuttons;
  538. ++joystick->nbuttons;
  539. }
  540. }
  541. for (i = 0; i < BTN_JOYSTICK; ++i) {
  542. if (test_bit(i, keybit)) {
  543. #ifdef DEBUG_INPUT_EVENTS
  544. printf("Joystick has button: 0x%x\n", i);
  545. #endif
  546. joystick->hwdata->key_map[i] = joystick->nbuttons;
  547. ++joystick->nbuttons;
  548. }
  549. }
  550. for (i = 0; i < ABS_MAX; ++i) {
  551. /* Skip hats */
  552. if (i == ABS_HAT0X) {
  553. i = ABS_HAT3Y;
  554. continue;
  555. }
  556. if (test_bit(i, absbit)) {
  557. struct input_absinfo absinfo;
  558. if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
  559. continue;
  560. }
  561. #ifdef DEBUG_INPUT_EVENTS
  562. printf("Joystick has absolute axis: 0x%.2x\n", i);
  563. printf("Values = { %d, %d, %d, %d, %d }\n",
  564. absinfo.value, absinfo.minimum, absinfo.maximum,
  565. absinfo.fuzz, absinfo.flat);
  566. #endif /* DEBUG_INPUT_EVENTS */
  567. joystick->hwdata->abs_map[i] = joystick->naxes;
  568. if (absinfo.minimum == absinfo.maximum) {
  569. joystick->hwdata->abs_correct[i].used = 0;
  570. } else {
  571. joystick->hwdata->abs_correct[i].used = 1;
  572. joystick->hwdata->abs_correct[i].coef[0] =
  573. (absinfo.maximum + absinfo.minimum) - 2 * absinfo.flat;
  574. joystick->hwdata->abs_correct[i].coef[1] =
  575. (absinfo.maximum + absinfo.minimum) + 2 * absinfo.flat;
  576. t = ((absinfo.maximum - absinfo.minimum) - 4 * absinfo.flat);
  577. if (t != 0) {
  578. joystick->hwdata->abs_correct[i].coef[2] =
  579. (1 << 28) / t;
  580. } else {
  581. joystick->hwdata->abs_correct[i].coef[2] = 0;
  582. }
  583. }
  584. ++joystick->naxes;
  585. }
  586. }
  587. for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
  588. if (test_bit(i, absbit) || test_bit(i + 1, absbit)) {
  589. struct input_absinfo absinfo;
  590. int hat_index = (i - ABS_HAT0X) / 2;
  591. if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
  592. continue;
  593. }
  594. #ifdef DEBUG_INPUT_EVENTS
  595. printf("Joystick has hat %d\n", hat_index);
  596. printf("Values = { %d, %d, %d, %d, %d }\n",
  597. absinfo.value, absinfo.minimum, absinfo.maximum,
  598. absinfo.fuzz, absinfo.flat);
  599. #endif /* DEBUG_INPUT_EVENTS */
  600. joystick->hwdata->hats_indices[joystick->nhats++] = hat_index;
  601. }
  602. }
  603. if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) {
  604. ++joystick->nballs;
  605. }
  606. /* Allocate data to keep track of these thingamajigs */
  607. if (joystick->nhats > 0) {
  608. if (allocate_hatdata(joystick) < 0) {
  609. joystick->nhats = 0;
  610. }
  611. }
  612. if (joystick->nballs > 0) {
  613. if (allocate_balldata(joystick) < 0) {
  614. joystick->nballs = 0;
  615. }
  616. }
  617. }
  618. if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(ffbit)), ffbit) >= 0) {
  619. if (test_bit(FF_RUMBLE, ffbit)) {
  620. joystick->hwdata->ff_rumble = SDL_TRUE;
  621. }
  622. if (test_bit(FF_SINE, ffbit)) {
  623. joystick->hwdata->ff_sine = SDL_TRUE;
  624. }
  625. }
  626. }
  627. /* Function to open a joystick for use.
  628. The joystick to open is specified by the device index.
  629. This should fill the nbuttons and naxes fields of the joystick structure.
  630. It returns 0, or -1 if there is an error.
  631. */
  632. static int
  633. LINUX_JoystickOpen(SDL_Joystick * joystick, int device_index)
  634. {
  635. SDL_joylist_item *item = JoystickByDevIndex(device_index);
  636. if (item == NULL) {
  637. return SDL_SetError("No such device");
  638. }
  639. joystick->instance_id = item->device_instance;
  640. joystick->hwdata = (struct joystick_hwdata *)
  641. SDL_calloc(1, sizeof(*joystick->hwdata));
  642. if (joystick->hwdata == NULL) {
  643. return SDL_OutOfMemory();
  644. }
  645. joystick->hwdata->item = item;
  646. joystick->hwdata->guid = item->guid;
  647. joystick->hwdata->effect.id = -1;
  648. joystick->hwdata->m_bSteamController = item->m_bSteamController;
  649. SDL_memset(joystick->hwdata->abs_map, 0xFF, sizeof(joystick->hwdata->abs_map));
  650. if (item->m_bSteamController) {
  651. joystick->hwdata->fd = -1;
  652. SDL_GetSteamControllerInputs(&joystick->nbuttons,
  653. &joystick->naxes,
  654. &joystick->nhats);
  655. } else {
  656. int fd = open(item->path, O_RDWR, 0);
  657. if (fd < 0) {
  658. SDL_free(joystick->hwdata);
  659. joystick->hwdata = NULL;
  660. return SDL_SetError("Unable to open %s", item->path);
  661. }
  662. joystick->hwdata->fd = fd;
  663. joystick->hwdata->fname = SDL_strdup(item->path);
  664. if (joystick->hwdata->fname == NULL) {
  665. SDL_free(joystick->hwdata);
  666. joystick->hwdata = NULL;
  667. close(fd);
  668. return SDL_OutOfMemory();
  669. }
  670. /* Set the joystick to non-blocking read mode */
  671. fcntl(fd, F_SETFL, O_NONBLOCK);
  672. /* Get the number of buttons and axes on the joystick */
  673. ConfigJoystick(joystick, fd);
  674. }
  675. SDL_assert(item->hwdata == NULL);
  676. item->hwdata = joystick->hwdata;
  677. /* mark joystick as fresh and ready */
  678. joystick->hwdata->fresh = 1;
  679. return (0);
  680. }
  681. static int
  682. LINUX_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms)
  683. {
  684. struct input_event event;
  685. if (joystick->hwdata->ff_rumble) {
  686. struct ff_effect *effect = &joystick->hwdata->effect;
  687. effect->type = FF_RUMBLE;
  688. effect->replay.length = SDL_min(duration_ms, 32767);
  689. effect->u.rumble.strong_magnitude = low_frequency_rumble;
  690. effect->u.rumble.weak_magnitude = high_frequency_rumble;
  691. } else if (joystick->hwdata->ff_sine) {
  692. /* Scale and average the two rumble strengths */
  693. Sint16 magnitude = (Sint16)(((low_frequency_rumble / 2) + (high_frequency_rumble / 2)) / 2);
  694. struct ff_effect *effect = &joystick->hwdata->effect;
  695. effect->type = FF_PERIODIC;
  696. effect->replay.length = SDL_min(duration_ms, 32767);
  697. effect->u.periodic.waveform = FF_SINE;
  698. effect->u.periodic.magnitude = magnitude;
  699. } else {
  700. return SDL_Unsupported();
  701. }
  702. if (ioctl(joystick->hwdata->fd, EVIOCSFF, &joystick->hwdata->effect) < 0) {
  703. return SDL_SetError("Couldn't update rumble effect: %s", strerror(errno));
  704. }
  705. event.type = EV_FF;
  706. event.code = joystick->hwdata->effect.id;
  707. event.value = 1;
  708. if (write(joystick->hwdata->fd, &event, sizeof(event)) < 0) {
  709. return SDL_SetError("Couldn't start rumble effect: %s", strerror(errno));
  710. }
  711. return 0;
  712. }
  713. static SDL_INLINE void
  714. HandleHat(SDL_Joystick * stick, Uint8 hat, int axis, int value)
  715. {
  716. struct hwdata_hat *the_hat;
  717. const Uint8 position_map[3][3] = {
  718. {SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP},
  719. {SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT},
  720. {SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN}
  721. };
  722. the_hat = &stick->hwdata->hats[hat];
  723. if (value < 0) {
  724. value = 0;
  725. } else if (value == 0) {
  726. value = 1;
  727. } else if (value > 0) {
  728. value = 2;
  729. }
  730. if (value != the_hat->axis[axis]) {
  731. the_hat->axis[axis] = value;
  732. SDL_PrivateJoystickHat(stick, hat,
  733. position_map[the_hat->axis[1]][the_hat->axis[0]]);
  734. }
  735. }
  736. static SDL_INLINE void
  737. HandleBall(SDL_Joystick * stick, Uint8 ball, int axis, int value)
  738. {
  739. stick->hwdata->balls[ball].axis[axis] += value;
  740. }
  741. static SDL_INLINE int
  742. AxisCorrect(SDL_Joystick * joystick, int which, int value)
  743. {
  744. struct axis_correct *correct;
  745. correct = &joystick->hwdata->abs_correct[which];
  746. if (correct->used) {
  747. value *= 2;
  748. if (value > correct->coef[0]) {
  749. if (value < correct->coef[1]) {
  750. return 0;
  751. }
  752. value -= correct->coef[1];
  753. } else {
  754. value -= correct->coef[0];
  755. }
  756. value *= correct->coef[2];
  757. value >>= 13;
  758. }
  759. /* Clamp and return */
  760. if (value < -32768)
  761. return -32768;
  762. if (value > 32767)
  763. return 32767;
  764. return value;
  765. }
  766. static SDL_INLINE void
  767. PollAllValues(SDL_Joystick * joystick)
  768. {
  769. struct input_absinfo absinfo;
  770. int i;
  771. /* Poll all axis */
  772. for (i = ABS_X; i < ABS_MAX; i++) {
  773. if (i == ABS_HAT0X) {
  774. i = ABS_HAT3Y;
  775. continue;
  776. }
  777. if (joystick->hwdata->abs_correct[i].used) {
  778. if (ioctl(joystick->hwdata->fd, EVIOCGABS(i), &absinfo) >= 0) {
  779. absinfo.value = AxisCorrect(joystick, i, absinfo.value);
  780. #ifdef DEBUG_INPUT_EVENTS
  781. printf("Joystick : Re-read Axis %d (%d) val= %d\n",
  782. joystick->hwdata->abs_map[i], i, absinfo.value);
  783. #endif
  784. SDL_PrivateJoystickAxis(joystick,
  785. joystick->hwdata->abs_map[i],
  786. absinfo.value);
  787. }
  788. }
  789. }
  790. }
  791. static SDL_INLINE void
  792. HandleInputEvents(SDL_Joystick * joystick)
  793. {
  794. struct input_event events[32];
  795. int i, len;
  796. int code;
  797. if (joystick->hwdata->fresh) {
  798. PollAllValues(joystick);
  799. joystick->hwdata->fresh = 0;
  800. }
  801. while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
  802. len /= sizeof(events[0]);
  803. for (i = 0; i < len; ++i) {
  804. code = events[i].code;
  805. switch (events[i].type) {
  806. case EV_KEY:
  807. SDL_PrivateJoystickButton(joystick,
  808. joystick->hwdata->key_map[code],
  809. events[i].value);
  810. break;
  811. case EV_ABS:
  812. switch (code) {
  813. case ABS_HAT0X:
  814. case ABS_HAT0Y:
  815. case ABS_HAT1X:
  816. case ABS_HAT1Y:
  817. case ABS_HAT2X:
  818. case ABS_HAT2Y:
  819. case ABS_HAT3X:
  820. case ABS_HAT3Y:
  821. code -= ABS_HAT0X;
  822. HandleHat(joystick, joystick->hwdata->hats_indices[code / 2], code % 2, events[i].value);
  823. break;
  824. default:
  825. if (joystick->hwdata->abs_map[code] != 0xFF) {
  826. events[i].value =
  827. AxisCorrect(joystick, code, events[i].value);
  828. SDL_PrivateJoystickAxis(joystick,
  829. joystick->hwdata->abs_map[code],
  830. events[i].value);
  831. }
  832. break;
  833. }
  834. break;
  835. case EV_REL:
  836. switch (code) {
  837. case REL_X:
  838. case REL_Y:
  839. code -= REL_X;
  840. HandleBall(joystick, code / 2, code % 2, events[i].value);
  841. break;
  842. default:
  843. break;
  844. }
  845. break;
  846. case EV_SYN:
  847. switch (code) {
  848. case SYN_DROPPED :
  849. #ifdef DEBUG_INPUT_EVENTS
  850. printf("Event SYN_DROPPED detected\n");
  851. #endif
  852. PollAllValues(joystick);
  853. break;
  854. default:
  855. break;
  856. }
  857. default:
  858. break;
  859. }
  860. }
  861. }
  862. if (errno == ENODEV) {
  863. /* We have to wait until the JoystickDetect callback to remove this */
  864. joystick->hwdata->gone = SDL_TRUE;
  865. }
  866. }
  867. static void
  868. LINUX_JoystickUpdate(SDL_Joystick * joystick)
  869. {
  870. int i;
  871. if (joystick->hwdata->m_bSteamController) {
  872. SDL_UpdateSteamController(joystick);
  873. return;
  874. }
  875. HandleInputEvents(joystick);
  876. /* Deliver ball motion updates */
  877. for (i = 0; i < joystick->nballs; ++i) {
  878. int xrel, yrel;
  879. xrel = joystick->hwdata->balls[i].axis[0];
  880. yrel = joystick->hwdata->balls[i].axis[1];
  881. if (xrel || yrel) {
  882. joystick->hwdata->balls[i].axis[0] = 0;
  883. joystick->hwdata->balls[i].axis[1] = 0;
  884. SDL_PrivateJoystickBall(joystick, (Uint8) i, xrel, yrel);
  885. }
  886. }
  887. }
  888. /* Function to close a joystick after use */
  889. static void
  890. LINUX_JoystickClose(SDL_Joystick * joystick)
  891. {
  892. if (joystick->hwdata) {
  893. if (joystick->hwdata->effect.id >= 0) {
  894. ioctl(joystick->hwdata->fd, EVIOCRMFF, joystick->hwdata->effect.id);
  895. joystick->hwdata->effect.id = -1;
  896. }
  897. if (joystick->hwdata->fd >= 0) {
  898. close(joystick->hwdata->fd);
  899. }
  900. if (joystick->hwdata->item) {
  901. joystick->hwdata->item->hwdata = NULL;
  902. }
  903. SDL_free(joystick->hwdata->hats);
  904. SDL_free(joystick->hwdata->balls);
  905. SDL_free(joystick->hwdata->fname);
  906. SDL_free(joystick->hwdata);
  907. }
  908. }
  909. /* Function to perform any system-specific joystick related cleanup */
  910. static void
  911. LINUX_JoystickQuit(void)
  912. {
  913. SDL_joylist_item *item = NULL;
  914. SDL_joylist_item *next = NULL;
  915. for (item = SDL_joylist; item; item = next) {
  916. next = item->next;
  917. SDL_free(item->path);
  918. SDL_free(item->name);
  919. SDL_free(item);
  920. }
  921. SDL_joylist = SDL_joylist_tail = NULL;
  922. numjoysticks = 0;
  923. #if SDL_USE_LIBUDEV
  924. SDL_UDEV_DelCallback(joystick_udev_callback);
  925. SDL_UDEV_Quit();
  926. #endif
  927. SDL_QuitSteamControllers();
  928. }
  929. SDL_JoystickDriver SDL_LINUX_JoystickDriver =
  930. {
  931. LINUX_JoystickInit,
  932. LINUX_JoystickGetCount,
  933. LINUX_JoystickDetect,
  934. LINUX_JoystickGetDeviceName,
  935. LINUX_JoystickGetDevicePlayerIndex,
  936. LINUX_JoystickSetDevicePlayerIndex,
  937. LINUX_JoystickGetDeviceGUID,
  938. LINUX_JoystickGetDeviceInstanceID,
  939. LINUX_JoystickOpen,
  940. LINUX_JoystickRumble,
  941. LINUX_JoystickUpdate,
  942. LINUX_JoystickClose,
  943. LINUX_JoystickQuit,
  944. };
  945. #endif /* SDL_JOYSTICK_LINUX */
  946. /* vi: set ts=4 sw=4 expandtab: */