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