SDL_sysjoystick.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2014 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 <unistd.h>
  26. #include <fcntl.h>
  27. #include <sys/ioctl.h>
  28. #include <limits.h> /* For the definition of PATH_MAX */
  29. #include <linux/joystick.h>
  30. #include "SDL_assert.h"
  31. #include "SDL_joystick.h"
  32. #include "SDL_endian.h"
  33. #include "../SDL_sysjoystick.h"
  34. #include "../SDL_joystick_c.h"
  35. #include "SDL_sysjoystick_c.h"
  36. /* !!! FIXME: move this somewhere else. */
  37. #if !SDL_EVENTS_DISABLED
  38. #include "../../events/SDL_events_c.h"
  39. #endif
  40. /* This isn't defined in older Linux kernel headers */
  41. #ifndef SYN_DROPPED
  42. #define SYN_DROPPED 3
  43. #endif
  44. #include "../../core/linux/SDL_udev.h"
  45. static int MaybeAddDevice(const char *path);
  46. #if SDL_USE_LIBUDEV
  47. static int MaybeRemoveDevice(const char *path);
  48. void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
  49. #endif /* SDL_USE_LIBUDEV */
  50. /* A linked list of available joysticks */
  51. typedef struct SDL_joylist_item
  52. {
  53. int device_instance;
  54. char *path; /* "/dev/input/event2" or whatever */
  55. char *name; /* "SideWinder 3D Pro" or whatever */
  56. SDL_JoystickGUID guid;
  57. dev_t devnum;
  58. struct joystick_hwdata *hwdata;
  59. struct SDL_joylist_item *next;
  60. } SDL_joylist_item;
  61. static SDL_joylist_item *SDL_joylist = NULL;
  62. static SDL_joylist_item *SDL_joylist_tail = NULL;
  63. static int numjoysticks = 0;
  64. static int instance_counter = 0;
  65. #define test_bit(nr, addr) \
  66. (((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
  67. #define NBITS(x) ((((x)-1)/(sizeof(long) * 8))+1)
  68. static int
  69. IsJoystick(int fd, char *namebuf, const size_t namebuflen, SDL_JoystickGUID *guid)
  70. {
  71. struct input_id inpid;
  72. Uint16 *guid16 = (Uint16 *) ((char *) &guid->data);
  73. #if !SDL_USE_LIBUDEV
  74. /* When udev is enabled we only get joystick devices here, so there's no need to test them */
  75. unsigned long evbit[NBITS(EV_MAX)] = { 0 };
  76. unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
  77. unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
  78. if ((ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
  79. (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
  80. (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) {
  81. return (0);
  82. }
  83. if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) &&
  84. test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit))) {
  85. return 0;
  86. }
  87. #endif
  88. if (ioctl(fd, EVIOCGNAME(namebuflen), namebuf) < 0) {
  89. return 0;
  90. }
  91. if (ioctl(fd, EVIOCGID, &inpid) < 0) {
  92. return 0;
  93. }
  94. #ifdef DEBUG_JOYSTICK
  95. printf("Joystick: %s, bustype = %d, vendor = 0x%x, product = 0x%x, version = %d\n", namebuf, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
  96. #endif
  97. SDL_memset(guid->data, 0, sizeof(guid->data));
  98. /* We only need 16 bits for each of these; space them out to fill 128. */
  99. /* Byteswap so devices get same GUID on little/big endian platforms. */
  100. *(guid16++) = SDL_SwapLE16(inpid.bustype);
  101. *(guid16++) = 0;
  102. if (inpid.vendor && inpid.product && inpid.version) {
  103. *(guid16++) = SDL_SwapLE16(inpid.vendor);
  104. *(guid16++) = 0;
  105. *(guid16++) = SDL_SwapLE16(inpid.product);
  106. *(guid16++) = 0;
  107. *(guid16++) = SDL_SwapLE16(inpid.version);
  108. *(guid16++) = 0;
  109. } else {
  110. SDL_strlcpy((char*)guid16, namebuf, sizeof(guid->data) - 4);
  111. }
  112. return 1;
  113. }
  114. #if SDL_USE_LIBUDEV
  115. void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
  116. {
  117. if (devpath == NULL || !(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
  118. return;
  119. }
  120. switch( udev_type )
  121. {
  122. case SDL_UDEV_DEVICEADDED:
  123. MaybeAddDevice(devpath);
  124. break;
  125. case SDL_UDEV_DEVICEREMOVED:
  126. MaybeRemoveDevice(devpath);
  127. break;
  128. default:
  129. break;
  130. }
  131. }
  132. #endif /* SDL_USE_LIBUDEV */
  133. /* !!! FIXME: I would love to dump this code and use libudev instead. */
  134. static int
  135. MaybeAddDevice(const char *path)
  136. {
  137. struct stat sb;
  138. int fd = -1;
  139. int isstick = 0;
  140. char namebuf[128];
  141. SDL_JoystickGUID guid;
  142. SDL_joylist_item *item;
  143. #if !SDL_EVENTS_DISABLED
  144. SDL_Event event;
  145. #endif
  146. if (path == NULL) {
  147. return -1;
  148. }
  149. if (stat(path, &sb) == -1) {
  150. return -1;
  151. }
  152. /* Check to make sure it's not already in list. */
  153. for (item = SDL_joylist; item != NULL; item = item->next) {
  154. if (sb.st_rdev == item->devnum) {
  155. return -1; /* already have this one */
  156. }
  157. }
  158. fd = open(path, O_RDONLY, 0);
  159. if (fd < 0) {
  160. return -1;
  161. }
  162. #ifdef DEBUG_INPUT_EVENTS
  163. printf("Checking %s\n", path);
  164. #endif
  165. isstick = IsJoystick(fd, namebuf, sizeof (namebuf), &guid);
  166. close(fd);
  167. if (!isstick) {
  168. return -1;
  169. }
  170. item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
  171. if (item == NULL) {
  172. return -1;
  173. }
  174. SDL_zerop(item);
  175. item->devnum = sb.st_rdev;
  176. item->path = SDL_strdup(path);
  177. item->name = SDL_strdup(namebuf);
  178. item->guid = guid;
  179. if ( (item->path == NULL) || (item->name == NULL) ) {
  180. SDL_free(item->path);
  181. SDL_free(item->name);
  182. SDL_free(item);
  183. return -1;
  184. }
  185. item->device_instance = instance_counter++;
  186. if (SDL_joylist_tail == NULL) {
  187. SDL_joylist = SDL_joylist_tail = item;
  188. } else {
  189. SDL_joylist_tail->next = item;
  190. SDL_joylist_tail = item;
  191. }
  192. /* Need to increment the joystick count before we post the event */
  193. ++numjoysticks;
  194. /* !!! FIXME: Move this to an SDL_PrivateJoyDeviceAdded() function? */
  195. #if !SDL_EVENTS_DISABLED
  196. event.type = SDL_JOYDEVICEADDED;
  197. if (SDL_GetEventState(event.type) == SDL_ENABLE) {
  198. event.jdevice.which = (numjoysticks - 1);
  199. if ( (SDL_EventOK == NULL) ||
  200. (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
  201. SDL_PushEvent(&event);
  202. }
  203. }
  204. #endif /* !SDL_EVENTS_DISABLED */
  205. return numjoysticks;
  206. }
  207. #if SDL_USE_LIBUDEV
  208. /* !!! FIXME: I would love to dump this code and use libudev instead. */
  209. static int
  210. MaybeRemoveDevice(const char *path)
  211. {
  212. SDL_joylist_item *item;
  213. SDL_joylist_item *prev = NULL;
  214. #if !SDL_EVENTS_DISABLED
  215. SDL_Event event;
  216. #endif
  217. if (path == NULL) {
  218. return -1;
  219. }
  220. for (item = SDL_joylist; item != NULL; item = item->next) {
  221. /* found it, remove it. */
  222. if (SDL_strcmp(path, item->path) == 0) {
  223. const int retval = item->device_instance;
  224. if (item->hwdata) {
  225. item->hwdata->item = NULL;
  226. }
  227. if (prev != NULL) {
  228. prev->next = item->next;
  229. } else {
  230. SDL_assert(SDL_joylist == item);
  231. SDL_joylist = item->next;
  232. }
  233. if (item == SDL_joylist_tail) {
  234. SDL_joylist_tail = prev;
  235. }
  236. /* Need to decrement the joystick count before we post the event */
  237. --numjoysticks;
  238. /* !!! FIXME: Move this to an SDL_PrivateJoyDeviceRemoved() function? */
  239. #if !SDL_EVENTS_DISABLED
  240. event.type = SDL_JOYDEVICEREMOVED;
  241. if (SDL_GetEventState(event.type) == SDL_ENABLE) {
  242. event.jdevice.which = item->device_instance;
  243. if ( (SDL_EventOK == NULL) ||
  244. (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
  245. SDL_PushEvent(&event);
  246. }
  247. }
  248. #endif /* !SDL_EVENTS_DISABLED */
  249. SDL_free(item->path);
  250. SDL_free(item->name);
  251. SDL_free(item);
  252. return retval;
  253. }
  254. prev = item;
  255. }
  256. return -1;
  257. }
  258. #endif
  259. static int
  260. JoystickInitWithoutUdev(void)
  261. {
  262. int i;
  263. char path[PATH_MAX];
  264. /* !!! FIXME: only finds sticks if they're called /dev/input/event[0..31] */
  265. /* !!! FIXME: we could at least readdir() through /dev/input...? */
  266. /* !!! FIXME: (or delete this and rely on libudev?) */
  267. for (i = 0; i < 32; i++) {
  268. SDL_snprintf(path, SDL_arraysize(path), "/dev/input/event%d", i);
  269. MaybeAddDevice(path);
  270. }
  271. return numjoysticks;
  272. }
  273. #if SDL_USE_LIBUDEV
  274. static int
  275. JoystickInitWithUdev(void)
  276. {
  277. if (SDL_UDEV_Init() < 0) {
  278. return SDL_SetError("Could not initialize UDEV");
  279. }
  280. /* Set up the udev callback */
  281. if ( SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
  282. SDL_UDEV_Quit();
  283. return SDL_SetError("Could not set up joystick <-> udev callback");
  284. }
  285. /* Force a scan to build the initial device list */
  286. SDL_UDEV_Scan();
  287. return numjoysticks;
  288. }
  289. #endif
  290. int
  291. SDL_SYS_JoystickInit(void)
  292. {
  293. /* First see if the user specified one or more joysticks to use */
  294. if (SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL) {
  295. char *envcopy, *envpath, *delim;
  296. envcopy = SDL_strdup(SDL_getenv("SDL_JOYSTICK_DEVICE"));
  297. envpath = envcopy;
  298. while (envpath != NULL) {
  299. delim = SDL_strchr(envpath, ':');
  300. if (delim != NULL) {
  301. *delim++ = '\0';
  302. }
  303. MaybeAddDevice(envpath);
  304. envpath = delim;
  305. }
  306. SDL_free(envcopy);
  307. }
  308. #if SDL_USE_LIBUDEV
  309. return JoystickInitWithUdev();
  310. #endif
  311. return JoystickInitWithoutUdev();
  312. }
  313. int SDL_SYS_NumJoysticks()
  314. {
  315. return numjoysticks;
  316. }
  317. void SDL_SYS_JoystickDetect()
  318. {
  319. #if SDL_USE_LIBUDEV
  320. SDL_UDEV_Poll();
  321. #endif
  322. }
  323. SDL_bool SDL_SYS_JoystickNeedsPolling()
  324. {
  325. #if SDL_USE_LIBUDEV
  326. return SDL_TRUE;
  327. #endif
  328. return SDL_FALSE;
  329. }
  330. static SDL_joylist_item *
  331. JoystickByDevIndex(int device_index)
  332. {
  333. SDL_joylist_item *item = SDL_joylist;
  334. if ((device_index < 0) || (device_index >= numjoysticks)) {
  335. return NULL;
  336. }
  337. while (device_index > 0) {
  338. SDL_assert(item != NULL);
  339. device_index--;
  340. item = item->next;
  341. }
  342. return item;
  343. }
  344. /* Function to get the device-dependent name of a joystick */
  345. const char *
  346. SDL_SYS_JoystickNameForDeviceIndex(int device_index)
  347. {
  348. return JoystickByDevIndex(device_index)->name;
  349. }
  350. /* Function to perform the mapping from device index to the instance id for this index */
  351. SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
  352. {
  353. return JoystickByDevIndex(device_index)->device_instance;
  354. }
  355. static int
  356. allocate_hatdata(SDL_Joystick * joystick)
  357. {
  358. int i;
  359. joystick->hwdata->hats =
  360. (struct hwdata_hat *) SDL_malloc(joystick->nhats *
  361. sizeof(struct hwdata_hat));
  362. if (joystick->hwdata->hats == NULL) {
  363. return (-1);
  364. }
  365. for (i = 0; i < joystick->nhats; ++i) {
  366. joystick->hwdata->hats[i].axis[0] = 1;
  367. joystick->hwdata->hats[i].axis[1] = 1;
  368. }
  369. return (0);
  370. }
  371. static int
  372. allocate_balldata(SDL_Joystick * joystick)
  373. {
  374. int i;
  375. joystick->hwdata->balls =
  376. (struct hwdata_ball *) SDL_malloc(joystick->nballs *
  377. sizeof(struct hwdata_ball));
  378. if (joystick->hwdata->balls == NULL) {
  379. return (-1);
  380. }
  381. for (i = 0; i < joystick->nballs; ++i) {
  382. joystick->hwdata->balls[i].axis[0] = 0;
  383. joystick->hwdata->balls[i].axis[1] = 0;
  384. }
  385. return (0);
  386. }
  387. static void
  388. ConfigJoystick(SDL_Joystick * joystick, int fd)
  389. {
  390. int i, t;
  391. unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
  392. unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
  393. unsigned long relbit[NBITS(REL_MAX)] = { 0 };
  394. /* See if this device uses the new unified event API */
  395. if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
  396. (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) &&
  397. (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0)) {
  398. /* Get the number of buttons, axes, and other thingamajigs */
  399. for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
  400. if (test_bit(i, keybit)) {
  401. #ifdef DEBUG_INPUT_EVENTS
  402. printf("Joystick has button: 0x%x\n", i);
  403. #endif
  404. joystick->hwdata->key_map[i - BTN_MISC] = joystick->nbuttons;
  405. ++joystick->nbuttons;
  406. }
  407. }
  408. for (i = BTN_MISC; i < BTN_JOYSTICK; ++i) {
  409. if (test_bit(i, keybit)) {
  410. #ifdef DEBUG_INPUT_EVENTS
  411. printf("Joystick has button: 0x%x\n", i);
  412. #endif
  413. joystick->hwdata->key_map[i - BTN_MISC] = joystick->nbuttons;
  414. ++joystick->nbuttons;
  415. }
  416. }
  417. for (i = 0; i < ABS_MISC; ++i) {
  418. /* Skip hats */
  419. if (i == ABS_HAT0X) {
  420. i = ABS_HAT3Y;
  421. continue;
  422. }
  423. if (test_bit(i, absbit)) {
  424. struct input_absinfo absinfo;
  425. if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
  426. continue;
  427. }
  428. #ifdef DEBUG_INPUT_EVENTS
  429. printf("Joystick has absolute axis: 0x%.2x\n", i);
  430. printf("Values = { %d, %d, %d, %d, %d }\n",
  431. absinfo.value, absinfo.minimum, absinfo.maximum,
  432. absinfo.fuzz, absinfo.flat);
  433. #endif /* DEBUG_INPUT_EVENTS */
  434. joystick->hwdata->abs_map[i] = joystick->naxes;
  435. if (absinfo.minimum == absinfo.maximum) {
  436. joystick->hwdata->abs_correct[i].used = 0;
  437. } else {
  438. joystick->hwdata->abs_correct[i].used = 1;
  439. joystick->hwdata->abs_correct[i].coef[0] =
  440. (absinfo.maximum + absinfo.minimum) - 2 * absinfo.flat;
  441. joystick->hwdata->abs_correct[i].coef[1] =
  442. (absinfo.maximum + absinfo.minimum) + 2 * absinfo.flat;
  443. t = ((absinfo.maximum - absinfo.minimum) - 4 * absinfo.flat);
  444. if (t != 0) {
  445. joystick->hwdata->abs_correct[i].coef[2] =
  446. (1 << 28) / t;
  447. } else {
  448. joystick->hwdata->abs_correct[i].coef[2] = 0;
  449. }
  450. }
  451. ++joystick->naxes;
  452. }
  453. }
  454. for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
  455. if (test_bit(i, absbit) || test_bit(i + 1, absbit)) {
  456. struct input_absinfo absinfo;
  457. if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
  458. continue;
  459. }
  460. #ifdef DEBUG_INPUT_EVENTS
  461. printf("Joystick has hat %d\n", (i - ABS_HAT0X) / 2);
  462. printf("Values = { %d, %d, %d, %d, %d }\n",
  463. absinfo.value, absinfo.minimum, absinfo.maximum,
  464. absinfo.fuzz, absinfo.flat);
  465. #endif /* DEBUG_INPUT_EVENTS */
  466. ++joystick->nhats;
  467. }
  468. }
  469. if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) {
  470. ++joystick->nballs;
  471. }
  472. /* Allocate data to keep track of these thingamajigs */
  473. if (joystick->nhats > 0) {
  474. if (allocate_hatdata(joystick) < 0) {
  475. joystick->nhats = 0;
  476. }
  477. }
  478. if (joystick->nballs > 0) {
  479. if (allocate_balldata(joystick) < 0) {
  480. joystick->nballs = 0;
  481. }
  482. }
  483. }
  484. }
  485. /* Function to open a joystick for use.
  486. The joystick to open is specified by the index field of the joystick.
  487. This should fill the nbuttons and naxes fields of the joystick structure.
  488. It returns 0, or -1 if there is an error.
  489. */
  490. int
  491. SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
  492. {
  493. SDL_joylist_item *item = JoystickByDevIndex(device_index);
  494. char *fname = NULL;
  495. int fd = -1;
  496. if (item == NULL) {
  497. return SDL_SetError("No such device");
  498. }
  499. fname = item->path;
  500. fd = open(fname, O_RDONLY, 0);
  501. if (fd < 0) {
  502. return SDL_SetError("Unable to open %s", fname);
  503. }
  504. joystick->instance_id = item->device_instance;
  505. joystick->hwdata = (struct joystick_hwdata *)
  506. SDL_malloc(sizeof(*joystick->hwdata));
  507. if (joystick->hwdata == NULL) {
  508. close(fd);
  509. return SDL_OutOfMemory();
  510. }
  511. SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
  512. joystick->hwdata->item = item;
  513. joystick->hwdata->guid = item->guid;
  514. joystick->hwdata->fd = fd;
  515. joystick->hwdata->fname = SDL_strdup(item->path);
  516. if (joystick->hwdata->fname == NULL) {
  517. SDL_free(joystick->hwdata);
  518. joystick->hwdata = NULL;
  519. close(fd);
  520. return SDL_OutOfMemory();
  521. }
  522. SDL_assert(item->hwdata == NULL);
  523. item->hwdata = joystick->hwdata;
  524. /* Set the joystick to non-blocking read mode */
  525. fcntl(fd, F_SETFL, O_NONBLOCK);
  526. /* Get the number of buttons and axes on the joystick */
  527. ConfigJoystick(joystick, fd);
  528. /* mark joystick as fresh and ready */
  529. joystick->hwdata->fresh = 1;
  530. return (0);
  531. }
  532. /* Function to determine is this joystick is attached to the system right now */
  533. SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
  534. {
  535. return !joystick->closed && (joystick->hwdata->item != NULL);
  536. }
  537. static SDL_INLINE void
  538. HandleHat(SDL_Joystick * stick, Uint8 hat, int axis, int value)
  539. {
  540. struct hwdata_hat *the_hat;
  541. const Uint8 position_map[3][3] = {
  542. {SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP},
  543. {SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT},
  544. {SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN}
  545. };
  546. the_hat = &stick->hwdata->hats[hat];
  547. if (value < 0) {
  548. value = 0;
  549. } else if (value == 0) {
  550. value = 1;
  551. } else if (value > 0) {
  552. value = 2;
  553. }
  554. if (value != the_hat->axis[axis]) {
  555. the_hat->axis[axis] = value;
  556. SDL_PrivateJoystickHat(stick, hat,
  557. position_map[the_hat->
  558. axis[1]][the_hat->axis[0]]);
  559. }
  560. }
  561. static SDL_INLINE void
  562. HandleBall(SDL_Joystick * stick, Uint8 ball, int axis, int value)
  563. {
  564. stick->hwdata->balls[ball].axis[axis] += value;
  565. }
  566. static SDL_INLINE int
  567. AxisCorrect(SDL_Joystick * joystick, int which, int value)
  568. {
  569. struct axis_correct *correct;
  570. correct = &joystick->hwdata->abs_correct[which];
  571. if (correct->used) {
  572. value *= 2;
  573. if (value > correct->coef[0]) {
  574. if (value < correct->coef[1]) {
  575. return 0;
  576. }
  577. value -= correct->coef[1];
  578. } else {
  579. value -= correct->coef[0];
  580. }
  581. value *= correct->coef[2];
  582. value >>= 13;
  583. }
  584. /* Clamp and return */
  585. if (value < -32768)
  586. return -32768;
  587. if (value > 32767)
  588. return 32767;
  589. return value;
  590. }
  591. static SDL_INLINE void
  592. PollAllValues(SDL_Joystick * joystick)
  593. {
  594. struct input_absinfo absinfo;
  595. int a, b = 0;
  596. /* Poll all axis */
  597. for (a = ABS_X; b < ABS_MAX; a++) {
  598. switch (a) {
  599. case ABS_HAT0X:
  600. case ABS_HAT0Y:
  601. case ABS_HAT1X:
  602. case ABS_HAT1Y:
  603. case ABS_HAT2X:
  604. case ABS_HAT2Y:
  605. case ABS_HAT3X:
  606. case ABS_HAT3Y:
  607. /* ingore hats */
  608. break;
  609. default:
  610. if (joystick->hwdata->abs_correct[b].used) {
  611. if (ioctl(joystick->hwdata->fd, EVIOCGABS(a), &absinfo) >= 0) {
  612. absinfo.value = AxisCorrect(joystick, b, absinfo.value);
  613. #ifdef DEBUG_INPUT_EVENTS
  614. printf("Joystick : Re-read Axis %d (%d) val= %d\n",
  615. joystick->hwdata->abs_map[b], a, absinfo.value);
  616. #endif
  617. SDL_PrivateJoystickAxis(joystick,
  618. joystick->hwdata->abs_map[b],
  619. absinfo.value);
  620. }
  621. }
  622. b++;
  623. }
  624. }
  625. }
  626. static SDL_INLINE void
  627. HandleInputEvents(SDL_Joystick * joystick)
  628. {
  629. struct input_event events[32];
  630. int i, len;
  631. int code;
  632. if (joystick->hwdata->fresh) {
  633. PollAllValues(joystick);
  634. joystick->hwdata->fresh = 0;
  635. }
  636. while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
  637. len /= sizeof(events[0]);
  638. for (i = 0; i < len; ++i) {
  639. code = events[i].code;
  640. switch (events[i].type) {
  641. case EV_KEY:
  642. if (code >= BTN_MISC) {
  643. code -= BTN_MISC;
  644. SDL_PrivateJoystickButton(joystick,
  645. joystick->hwdata->key_map[code],
  646. events[i].value);
  647. }
  648. break;
  649. case EV_ABS:
  650. if (code >= ABS_MISC) {
  651. break;
  652. }
  653. switch (code) {
  654. case ABS_HAT0X:
  655. case ABS_HAT0Y:
  656. case ABS_HAT1X:
  657. case ABS_HAT1Y:
  658. case ABS_HAT2X:
  659. case ABS_HAT2Y:
  660. case ABS_HAT3X:
  661. case ABS_HAT3Y:
  662. code -= ABS_HAT0X;
  663. HandleHat(joystick, code / 2, code % 2, events[i].value);
  664. break;
  665. default:
  666. events[i].value =
  667. AxisCorrect(joystick, code, events[i].value);
  668. SDL_PrivateJoystickAxis(joystick,
  669. joystick->hwdata->abs_map[code],
  670. events[i].value);
  671. break;
  672. }
  673. break;
  674. case EV_REL:
  675. switch (code) {
  676. case REL_X:
  677. case REL_Y:
  678. code -= REL_X;
  679. HandleBall(joystick, code / 2, code % 2, events[i].value);
  680. break;
  681. default:
  682. break;
  683. }
  684. break;
  685. case EV_SYN:
  686. switch (code) {
  687. case SYN_DROPPED :
  688. #ifdef DEBUG_INPUT_EVENTS
  689. printf("Event SYN_DROPPED detected\n");
  690. #endif
  691. PollAllValues(joystick);
  692. break;
  693. default:
  694. break;
  695. }
  696. default:
  697. break;
  698. }
  699. }
  700. }
  701. }
  702. void
  703. SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
  704. {
  705. int i;
  706. HandleInputEvents(joystick);
  707. /* Deliver ball motion updates */
  708. for (i = 0; i < joystick->nballs; ++i) {
  709. int xrel, yrel;
  710. xrel = joystick->hwdata->balls[i].axis[0];
  711. yrel = joystick->hwdata->balls[i].axis[1];
  712. if (xrel || yrel) {
  713. joystick->hwdata->balls[i].axis[0] = 0;
  714. joystick->hwdata->balls[i].axis[1] = 0;
  715. SDL_PrivateJoystickBall(joystick, (Uint8) i, xrel, yrel);
  716. }
  717. }
  718. }
  719. /* Function to close a joystick after use */
  720. void
  721. SDL_SYS_JoystickClose(SDL_Joystick * joystick)
  722. {
  723. if (joystick->hwdata) {
  724. close(joystick->hwdata->fd);
  725. if (joystick->hwdata->item) {
  726. joystick->hwdata->item->hwdata = NULL;
  727. }
  728. SDL_free(joystick->hwdata->hats);
  729. SDL_free(joystick->hwdata->balls);
  730. SDL_free(joystick->hwdata->fname);
  731. SDL_free(joystick->hwdata);
  732. joystick->hwdata = NULL;
  733. }
  734. joystick->closed = 1;
  735. }
  736. /* Function to perform any system-specific joystick related cleanup */
  737. void
  738. SDL_SYS_JoystickQuit(void)
  739. {
  740. SDL_joylist_item *item = NULL;
  741. SDL_joylist_item *next = NULL;
  742. for (item = SDL_joylist; item; item = next) {
  743. next = item->next;
  744. SDL_free(item->path);
  745. SDL_free(item->name);
  746. SDL_free(item);
  747. }
  748. SDL_joylist = SDL_joylist_tail = NULL;
  749. numjoysticks = 0;
  750. instance_counter = 0;
  751. #if SDL_USE_LIBUDEV
  752. SDL_UDEV_DelCallback(joystick_udev_callback);
  753. SDL_UDEV_Quit();
  754. #endif
  755. }
  756. SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
  757. {
  758. return JoystickByDevIndex(device_index)->guid;
  759. }
  760. SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
  761. {
  762. return joystick->hwdata->guid;
  763. }
  764. #endif /* SDL_JOYSTICK_LINUX */
  765. /* vi: set ts=4 sw=4 expandtab: */