zenilib: zenilib/jni/external/sdl/src/joystick/linux/SDL_sysjoystick.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_sysjoystick.c
Go to the documentation of this file.
1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2013 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_config.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 system specific header for 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 /* !!! FIXME: move this somewhere else. */
46 #if !SDL_EVENTS_DISABLED
47 #include "../../events/SDL_events_c.h"
48 #endif
49
50 /* This isn't defined in older Linux kernel headers */
51 #ifndef SYN_DROPPED
52 #define SYN_DROPPED 3
53 #endif
54
55 /*
56 * !!! FIXME: move all the udev stuff to src/core/linux, so I can reuse it
57 * !!! FIXME: for audio hardware disconnects.
58 */
59 #ifdef HAVE_LIBUDEV_H
60 #define SDL_USE_LIBUDEV 1
61 #include "SDL_loadso.h"
62 #include <libudev.h>
63 #include <sys/time.h>
64 #include <sys/types.h>
65
66 /* we never link directly to libudev. */
67 /* !!! FIXME: can we generalize this? ALSA, etc, do the same things. */
68 static const char *udev_library = "libudev.so.0";
69 static void *udev_handle = NULL;
70
71 /* !!! FIXME: this is kinda ugly. */
72 static SDL_bool
73 load_udev_sym(const char *fn, void **addr)
74 {
75 *addr = SDL_LoadFunction(udev_handle, fn);
76 if (*addr == NULL) {
77 /* Don't call SDL_SetError(): SDL_LoadFunction already did. */
78 return SDL_FALSE;
79 }
80
81 return SDL_TRUE;
82 }
83
84 /* libudev entry points... */
85 static const char *(*UDEV_udev_device_get_action)(struct udev_device *) = NULL;
86 static const char *(*UDEV_udev_device_get_devnode)(struct udev_device *) = NULL;
87 static const char *(*UDEV_udev_device_get_property_value)(struct udev_device *, const char *) = NULL;
88 static struct udev_device *(*UDEV_udev_device_new_from_syspath)(struct udev *, const char *) = NULL;
89 static void (*UDEV_udev_device_unref)(struct udev_device *) = NULL;
90 static int (*UDEV_udev_enumerate_add_match_property)(struct udev_enumerate *, const char *, const char *) = NULL;
91 static int (*UDEV_udev_enumerate_add_match_subsystem)(struct udev_enumerate *, const char *) = NULL;
92 static struct udev_list_entry *(*UDEV_udev_enumerate_get_list_entry)(struct udev_enumerate *) = NULL;
93 static struct udev_enumerate *(*UDEV_udev_enumerate_new)(struct udev *) = NULL;
94 static int (*UDEV_udev_enumerate_scan_devices)(struct udev_enumerate *) = NULL;
95 static void (*UDEV_udev_enumerate_unref)(struct udev_enumerate *) = NULL;
96 static const char *(*UDEV_udev_list_entry_get_name)(struct udev_list_entry *) = NULL;
97 static struct udev_list_entry *(*UDEV_udev_list_entry_get_next)(struct udev_list_entry *) = NULL;
98 static int (*UDEV_udev_monitor_enable_receiving)(struct udev_monitor *) = NULL;
99 static int (*UDEV_udev_monitor_filter_add_match_subsystem_devtype)(struct udev_monitor *, const char *, const char *) = NULL;
100 static int (*UDEV_udev_monitor_get_fd)(struct udev_monitor *) = NULL;
101 static struct udev_monitor *(*UDEV_udev_monitor_new_from_netlink)(struct udev *, const char *) = NULL;
102 static struct udev_device *(*UDEV_udev_monitor_receive_device)(struct udev_monitor *) = NULL;
103 static void (*UDEV_udev_monitor_unref)(struct udev_monitor *) = NULL;
104 static struct udev *(*UDEV_udev_new)(void) = NULL;
105 static void (*UDEV_udev_unref)(struct udev *) = NULL;
106
107 static int
108 load_udev_syms(void)
109 {
110 /* cast funcs to char* first, to please GCC's strict aliasing rules. */
111 #define SDL_UDEV_SYM(x) \
112 if (!load_udev_sym(#x, (void **) (char *) &UDEV_##x)) return -1
113
114 SDL_UDEV_SYM(udev_device_get_action);
115 SDL_UDEV_SYM(udev_device_get_devnode);
116 SDL_UDEV_SYM(udev_device_get_property_value);
117 SDL_UDEV_SYM(udev_device_new_from_syspath);
118 SDL_UDEV_SYM(udev_device_unref);
119 SDL_UDEV_SYM(udev_enumerate_add_match_property);
120 SDL_UDEV_SYM(udev_enumerate_add_match_subsystem);
121 SDL_UDEV_SYM(udev_enumerate_get_list_entry);
122 SDL_UDEV_SYM(udev_enumerate_new);
123 SDL_UDEV_SYM(udev_enumerate_scan_devices);
124 SDL_UDEV_SYM(udev_enumerate_unref);
125 SDL_UDEV_SYM(udev_list_entry_get_name);
126 SDL_UDEV_SYM(udev_list_entry_get_next);
127 SDL_UDEV_SYM(udev_monitor_enable_receiving);
128 SDL_UDEV_SYM(udev_monitor_filter_add_match_subsystem_devtype);
129 SDL_UDEV_SYM(udev_monitor_get_fd);
130 SDL_UDEV_SYM(udev_monitor_new_from_netlink);
131 SDL_UDEV_SYM(udev_monitor_receive_device);
132 SDL_UDEV_SYM(udev_monitor_unref);
133 SDL_UDEV_SYM(udev_new);
134 SDL_UDEV_SYM(udev_unref);
135
136 #undef SDL_UDEV_SYM
137
138 return 0;
139 }
140
141 static void
142 UnloadUDEVLibrary(void)
143 {
144 if (udev_handle != NULL) {
145 SDL_UnloadObject(udev_handle);
146 udev_handle = NULL;
147 }
148 }
149
150 static int
151 LoadUDEVLibrary(void)
152 {
153 int retval = 0;
154 if (udev_handle == NULL) {
155 udev_handle = SDL_LoadObject(udev_library);
156 if (udev_handle == NULL) {
157 retval = -1;
158 /* Don't call SDL_SetError(): SDL_LoadObject already did. */
159 } else {
160 retval = load_udev_syms();
161 if (retval < 0) {
162 UnloadUDEVLibrary();
163 }
164 }
165 }
166
167 return retval;
168 }
169
170 static struct udev *udev = NULL;
171 static struct udev_monitor *udev_mon = NULL;
172 #endif
173
174
175 /* A linked list of available joysticks */
176 typedef struct SDL_joylist_item
177 {
178 int device_instance;
179 char *path; /* "/dev/input/event2" or whatever */
180 char *name; /* "SideWinder 3D Pro" or whatever */
181 SDL_JoystickGUID guid;
182 dev_t devnum;
183 struct joystick_hwdata *hwdata;
184 struct SDL_joylist_item *next;
185 } SDL_joylist_item;
186
187 static SDL_joylist_item *SDL_joylist = NULL;
188 static SDL_joylist_item *SDL_joylist_tail = NULL;
189 static int numjoysticks = 0;
190 static int instance_counter = 0;
191
192 #define test_bit(nr, addr) \
193 (((1UL << ((nr) % (sizeof(long) * 8))) & ((addr)[(nr) / (sizeof(long) * 8)])) != 0)
194 #define NBITS(x) ((((x)-1)/(sizeof(long) * 8))+1)
195
196 static int
197 IsJoystick(int fd, char *namebuf, const size_t namebuflen, SDL_JoystickGUID *guid)
198 {
199 unsigned long evbit[NBITS(EV_MAX)] = { 0 };
200 unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
201 unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
202 struct input_id inpid;
203 Uint16 *guid16 = (Uint16 *) ((char *) &guid->data);
204
205 if ((ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
206 (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
207 (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) {
208 return (0);
209 }
210
211 if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) &&
212 test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit))) {
213 return 0;
214 }
215
216 if (ioctl(fd, EVIOCGNAME(namebuflen), namebuf) < 0) {
217 return 0;
218 }
219
220 if (ioctl(fd, EVIOCGID, &inpid) < 0) {
221 return 0;
222 }
223
224 #ifdef DEBUG_JOYSTICK
225 printf("Joystick: %s, bustype = %d, vendor = 0x%x, product = 0x%x, version = %d\n", namebuf, inpid.bustype, inpid.vendor, inpid.product, inpid.version);
226 #endif
227
228 SDL_memset(guid->data, 0, sizeof(guid->data));
229
230 /* We only need 16 bits for each of these; space them out to fill 128. */
231 /* Byteswap so devices get same GUID on little/big endian platforms. */
232 *(guid16++) = SDL_SwapLE16(inpid.bustype);
233 *(guid16++) = 0;
234
235 if (inpid.vendor && inpid.product && inpid.version) {
236 *(guid16++) = SDL_SwapLE16(inpid.vendor);
237 *(guid16++) = 0;
238 *(guid16++) = SDL_SwapLE16(inpid.product);
239 *(guid16++) = 0;
240 *(guid16++) = SDL_SwapLE16(inpid.version);
241 *(guid16++) = 0;
242 } else {
243 SDL_strlcpy((char*)guid16, namebuf, sizeof(guid->data) - 4);
244 }
245
246 return 1;
247 }
248
249
250 /* !!! FIXME: I would love to dump this code and use libudev instead. */
251 static int
252 MaybeAddDevice(const char *path)
253 {
254 struct stat sb;
255 int fd = -1;
256 int isstick = 0;
257 char namebuf[128];
258 SDL_JoystickGUID guid;
259 SDL_joylist_item *item;
260
261 if (path == NULL) {
262 return -1;
263 }
264
265 if (stat(path, &sb) == -1) {
266 return -1;
267 }
268
269 /* Check to make sure it's not already in list. */
270 for (item = SDL_joylist; item != NULL; item = item->next) {
271 if (sb.st_rdev == item->devnum) {
272 return -1; /* already have this one */
273 }
274 }
275
276 fd = open(path, O_RDONLY, 0);
277 if (fd < 0) {
278 return -1;
279 }
280
281 #ifdef DEBUG_INPUT_EVENTS
282 printf("Checking %s\n", path);
283 #endif
284
285 isstick = IsJoystick(fd, namebuf, sizeof (namebuf), &guid);
286 close(fd);
287 if (!isstick) {
288 return -1;
289 }
290
291 item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
292 if (item == NULL) {
293 return -1;
294 }
295
296 SDL_zerop(item);
297 item->devnum = sb.st_rdev;
298 item->path = SDL_strdup(path);
299 item->name = SDL_strdup(namebuf);
300 item->guid = guid;
301
302 if ( (item->path == NULL) || (item->name == NULL) ) {
303 SDL_free(item->path);
304 SDL_free(item->name);
305 SDL_free(item);
306 return -1;
307 }
308
309 item->device_instance = instance_counter++;
310 if (SDL_joylist_tail == NULL) {
311 SDL_joylist = SDL_joylist_tail = item;
312 } else {
313 SDL_joylist_tail->next = item;
314 SDL_joylist_tail = item;
315 }
316
317 return numjoysticks++;
318 }
319
320 #if SDL_USE_LIBUDEV
321 /* !!! FIXME: I would love to dump this code and use libudev instead. */
322 static int
323 MaybeRemoveDevice(const char *path)
324 {
325 SDL_joylist_item *item;
326 SDL_joylist_item *prev = NULL;
327
328 if (path == NULL) {
329 return -1;
330 }
331
332 for (item = SDL_joylist; item != NULL; item = item->next) {
333 /* found it, remove it. */
334 if (SDL_strcmp(path, item->path) == 0) {
335 const int retval = item->device_instance;
336 if (item->hwdata) {
337 item->hwdata->item = NULL;
338 }
339 if (prev != NULL) {
340 prev->next = item->next;
341 } else {
342 SDL_assert(SDL_joylist == item);
343 SDL_joylist = item->next;
344 }
345 if (item == SDL_joylist_tail) {
346 SDL_joylist_tail = prev;
347 }
348 SDL_free(item->path);
349 SDL_free(item->name);
350 SDL_free(item);
351 numjoysticks--;
352 return retval;
353 }
354 prev = item;
355 }
356
357 return -1;
358 }
359 #endif
360
361 static int
362 JoystickInitWithoutUdev(void)
363 {
364 int i;
365 char path[PATH_MAX];
366
367 /* !!! FIXME: only finds sticks if they're called /dev/input/event[0..31] */
368 /* !!! FIXME: we could at least readdir() through /dev/input...? */
369 /* !!! FIXME: (or delete this and rely on libudev?) */
370 for (i = 0; i < 32; i++) {
371 SDL_snprintf(path, SDL_arraysize(path), "/dev/input/event%d", i);
372 MaybeAddDevice(path);
373 }
374
375 return numjoysticks;
376 }
377
378
379 #if SDL_USE_LIBUDEV
380 static int
381 JoystickInitWithUdev(void)
382 {
383 struct udev_enumerate *enumerate = NULL;
384 struct udev_list_entry *devs = NULL;
385 struct udev_list_entry *item = NULL;
386
387 SDL_assert(udev == NULL);
388 udev = UDEV_udev_new();
389 if (udev == NULL) {
390 return SDL_SetError("udev_new() failed");
391 }
392
393 udev_mon = UDEV_udev_monitor_new_from_netlink(udev, "udev");
394 if (udev_mon != NULL) { /* okay if it's NULL, we just lose hotplugging. */
395 UDEV_udev_monitor_filter_add_match_subsystem_devtype(udev_mon,
396 "input", NULL);
397 UDEV_udev_monitor_enable_receiving(udev_mon);
398 }
399
400 enumerate = UDEV_udev_enumerate_new(udev);
401 if (enumerate == NULL) {
402 return SDL_SetError("udev_enumerate_new() failed");
403 }
404
405 UDEV_udev_enumerate_add_match_subsystem(enumerate, "input");
406 UDEV_udev_enumerate_add_match_property(enumerate, "ID_INPUT_JOYSTICK", "1");
407 UDEV_udev_enumerate_scan_devices(enumerate);
408 devs = UDEV_udev_enumerate_get_list_entry(enumerate);
409 for (item = devs; item; item = UDEV_udev_list_entry_get_next(item)) {
410 const char *path = UDEV_udev_list_entry_get_name(item);
411 struct udev_device *dev = UDEV_udev_device_new_from_syspath(udev, path);
412 MaybeAddDevice(UDEV_udev_device_get_devnode(dev));
413 UDEV_udev_device_unref(dev);
414 }
415
416 UDEV_udev_enumerate_unref(enumerate);
417
418 return numjoysticks;
419 }
420 #endif
421
422 int
423 SDL_SYS_JoystickInit(void)
424 {
425 /* First see if the user specified one or more joysticks to use */
426 if (SDL_getenv("SDL_JOYSTICK_DEVICE") != NULL) {
427 char *envcopy, *envpath, *delim;
428 envcopy = SDL_strdup(SDL_getenv("SDL_JOYSTICK_DEVICE"));
429 envpath = envcopy;
430 while (envpath != NULL) {
431 delim = SDL_strchr(envpath, ':');
432 if (delim != NULL) {
433 *delim++ = '\0';
434 }
435 MaybeAddDevice(envpath);
436 envpath = delim;
437 }
438 SDL_free(envcopy);
439 }
440
441 #if SDL_USE_LIBUDEV
442 if (LoadUDEVLibrary() == 0) { /* okay if this fails, FOR NOW. */
443 return JoystickInitWithUdev();
444 }
445 #endif
446
447 return JoystickInitWithoutUdev();
448 }
449
450 int SDL_SYS_NumJoysticks()
451 {
452 return numjoysticks;
453 }
454
455 static SDL_bool
456 HotplugUpdateAvailable(void)
457 {
458 #if SDL_USE_LIBUDEV
459 if (udev_mon != NULL) {
460 const int fd = UDEV_udev_monitor_get_fd(udev_mon);
461 fd_set fds;
462 struct timeval tv;
463
464 FD_ZERO(&fds);
465 FD_SET(fd, &fds);
466 tv.tv_sec = 0;
467 tv.tv_usec = 0;
468 if ((select(fd+1, &fds, NULL, NULL, &tv) > 0) && (FD_ISSET(fd, &fds))) {
469 return SDL_TRUE;
470 }
471 }
472 #endif
473
474 return SDL_FALSE;
475 }
476
477 void SDL_SYS_JoystickDetect()
478 {
479 #if SDL_USE_LIBUDEV
480 struct udev_device *dev = NULL;
481 const char *devnode = NULL;
482 const char *action = NULL;
483 const char *val = NULL;
484
485 while (HotplugUpdateAvailable()) {
486 dev = UDEV_udev_monitor_receive_device(udev_mon);
487 if (dev == NULL) {
488 break;
489 }
490 val = UDEV_udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK");
491 if ((!val) || (SDL_strcmp(val, "1") != 0)) {
492 continue;
493 }
494
495 action = UDEV_udev_device_get_action(dev);
496 devnode = UDEV_udev_device_get_devnode(dev);
497
498 if (SDL_strcmp(action, "add") == 0) {
499 const int device_index = MaybeAddDevice(devnode);
500 if (device_index != -1) {
501 /* !!! FIXME: Move this to an SDL_PrivateJoyDeviceAdded() function? */
502 #if !SDL_EVENTS_DISABLED
503 SDL_Event event;
504 event.type = SDL_JOYDEVICEADDED;
505
506 if (SDL_GetEventState(event.type) == SDL_ENABLE) {
507 event.jdevice.which = device_index;
508 if ( (SDL_EventOK == NULL) ||
509 (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
510 SDL_PushEvent(&event);
511 }
512 }
513 #endif /* !SDL_EVENTS_DISABLED */
514 }
515 } else if (SDL_strcmp(action, "remove") == 0) {
516 const int inst = MaybeRemoveDevice(devnode);
517 if (inst != -1) {
518 /* !!! FIXME: Move this to an SDL_PrivateJoyDeviceRemoved() function? */
519 #if !SDL_EVENTS_DISABLED
520 SDL_Event event;
521 event.type = SDL_JOYDEVICEREMOVED;
522
523 if (SDL_GetEventState(event.type) == SDL_ENABLE) {
524 event.jdevice.which = inst;
525 if ( (SDL_EventOK == NULL) ||
526 (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
527 SDL_PushEvent(&event);
528 }
529 }
530 #endif /* !SDL_EVENTS_DISABLED */
531 }
532 }
533 UDEV_udev_device_unref(dev);
534 }
535 #endif
536 }
537
538 SDL_bool SDL_SYS_JoystickNeedsPolling()
539 {
540 /*
541 * This results in a select() call, so technically we're polling to
542 * decide if we should poll, but I think this function is here because
543 * Windows has to do an enormous amount of work to detect new sticks,
544 * whereas libudev just needs to see if there's more data available on
545 * a socket...so this should be acceptable, I hope.
546 */
547 return HotplugUpdateAvailable();
548 }
549
550 static SDL_joylist_item *
551 JoystickByDevIndex(int device_index)
552 {
553 SDL_joylist_item *item = SDL_joylist;
554
555 if ((device_index < 0) || (device_index >= numjoysticks)) {
556 return NULL;
557 }
558
559 while (device_index > 0) {
560 SDL_assert(item != NULL);
561 device_index--;
562 item = item->next;
563 }
564
565 return item;
566 }
567
568 /* Function to get the device-dependent name of a joystick */
569 const char *
570 SDL_SYS_JoystickNameForDeviceIndex(int device_index)
571 {
572 return JoystickByDevIndex(device_index)->name;
573 }
574
575 /* Function to perform the mapping from device index to the instance id for this index */
576 SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
577 {
578 return JoystickByDevIndex(device_index)->device_instance;
579 }
580
581 static int
582 allocate_hatdata(SDL_Joystick * joystick)
583 {
584 int i;
585
586 joystick->hwdata->hats =
587 (struct hwdata_hat *) SDL_malloc(joystick->nhats *
588 sizeof(struct hwdata_hat));
589 if (joystick->hwdata->hats == NULL) {
590 return (-1);
591 }
592 for (i = 0; i < joystick->nhats; ++i) {
593 joystick->hwdata->hats[i].axis[0] = 1;
594 joystick->hwdata->hats[i].axis[1] = 1;
595 }
596 return (0);
597 }
598
599 static int
600 allocate_balldata(SDL_Joystick * joystick)
601 {
602 int i;
603
604 joystick->hwdata->balls =
605 (struct hwdata_ball *) SDL_malloc(joystick->nballs *
606 sizeof(struct hwdata_ball));
607 if (joystick->hwdata->balls == NULL) {
608 return (-1);
609 }
610 for (i = 0; i < joystick->nballs; ++i) {
611 joystick->hwdata->balls[i].axis[0] = 0;
612 joystick->hwdata->balls[i].axis[1] = 0;
613 }
614 return (0);
615 }
616
617 static void
618 ConfigJoystick(SDL_Joystick * joystick, int fd)
619 {
620 int i, t;
621 unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
622 unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
623 unsigned long relbit[NBITS(REL_MAX)] = { 0 };
624
625 /* See if this device uses the new unified event API */
626 if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
627 (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) &&
628 (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0)) {
629
630 /* Get the number of buttons, axes, and other thingamajigs */
631 for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
632 if (test_bit(i, keybit)) {
633 #ifdef DEBUG_INPUT_EVENTS
634 printf("Joystick has button: 0x%x\n", i);
635 #endif
636 joystick->hwdata->key_map[i - BTN_MISC] = joystick->nbuttons;
637 ++joystick->nbuttons;
638 }
639 }
640 for (i = BTN_MISC; i < BTN_JOYSTICK; ++i) {
641 if (test_bit(i, keybit)) {
642 #ifdef DEBUG_INPUT_EVENTS
643 printf("Joystick has button: 0x%x\n", i);
644 #endif
645 joystick->hwdata->key_map[i - BTN_MISC] = joystick->nbuttons;
646 ++joystick->nbuttons;
647 }
648 }
649 for (i = 0; i < ABS_MISC; ++i) {
650 /* Skip hats */
651 if (i == ABS_HAT0X) {
652 i = ABS_HAT3Y;
653 continue;
654 }
655 if (test_bit(i, absbit)) {
656 struct input_absinfo absinfo;
657
658 if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0)
659 continue;
660 #ifdef DEBUG_INPUT_EVENTS
661 printf("Joystick has absolute axis: %x\n", i);
662 printf("Values = { %d, %d, %d, %d, %d }\n",
663 absinfo.value, absinfo.minimum, absinfo.maximum,
664 absinfo.fuzz, absinfo.flat);
665 #endif /* DEBUG_INPUT_EVENTS */
666 joystick->hwdata->abs_map[i] = joystick->naxes;
667 if (absinfo.minimum == absinfo.maximum) {
668 joystick->hwdata->abs_correct[i].used = 0;
669 } else {
670 joystick->hwdata->abs_correct[i].used = 1;
671 joystick->hwdata->abs_correct[i].coef[0] =
672 (absinfo.maximum + absinfo.minimum) - 2 * absinfo.flat;
673 joystick->hwdata->abs_correct[i].coef[1] =
674 (absinfo.maximum + absinfo.minimum) + 2 * absinfo.flat;
675 t = ((absinfo.maximum - absinfo.minimum) - 4 * absinfo.flat);
676 if (t != 0) {
677 joystick->hwdata->abs_correct[i].coef[2] =
678 (1 << 28) / t;
679 } else {
680 joystick->hwdata->abs_correct[i].coef[2] = 0;
681 }
682 }
683 ++joystick->naxes;
684 }
685 }
686 for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
687 if (test_bit(i, absbit) || test_bit(i + 1, absbit)) {
688 #ifdef DEBUG_INPUT_EVENTS
689 printf("Joystick has hat %d\n", (i - ABS_HAT0X) / 2);
690 #endif
691 ++joystick->nhats;
692 }
693 }
694 if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) {
695 ++joystick->nballs;
696 }
697
698 /* Allocate data to keep track of these thingamajigs */
699 if (joystick->nhats > 0) {
700 if (allocate_hatdata(joystick) < 0) {
701 joystick->nhats = 0;
702 }
703 }
704 if (joystick->nballs > 0) {
705 if (allocate_balldata(joystick) < 0) {
706 joystick->nballs = 0;
707 }
708 }
709 }
710 }
711
712
713 /* Function to open a joystick for use.
714 The joystick to open is specified by the index field of the joystick.
715 This should fill the nbuttons and naxes fields of the joystick structure.
716 It returns 0, or -1 if there is an error.
717 */
718 int
719 SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
720 {
721 SDL_joylist_item *item = JoystickByDevIndex(device_index);
722 char *fname = NULL;
723 int fd = -1;
724
725 if (item == NULL) {
726 return SDL_SetError("No such device");
727 }
728
729 fname = item->path;
730 fd = open(fname, O_RDONLY, 0);
731 if (fd < 0) {
732 return SDL_SetError("Unable to open %s", fname);
733 }
734
735 joystick->instance_id = item->device_instance;
736 joystick->hwdata = (struct joystick_hwdata *)
737 SDL_malloc(sizeof(*joystick->hwdata));
738 if (joystick->hwdata == NULL) {
739 close(fd);
740 return SDL_OutOfMemory();
741 }
742 SDL_memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
743 joystick->hwdata->item = item;
744 joystick->hwdata->guid = item->guid;
745 joystick->hwdata->fd = fd;
746 joystick->hwdata->fname = SDL_strdup(item->path);
747 if (joystick->hwdata->fname == NULL) {
748 SDL_free(joystick->hwdata);
749 joystick->hwdata = NULL;
750 close(fd);
751 return SDL_OutOfMemory();
752 }
753
754 SDL_assert(item->hwdata == NULL);
755 item->hwdata = joystick->hwdata;
756
757 /* Set the joystick to non-blocking read mode */
758 fcntl(fd, F_SETFL, O_NONBLOCK);
759
760 /* Get the number of buttons and axes on the joystick */
761 ConfigJoystick(joystick, fd);
762
763 /* mark joystick as fresh and ready */
764 joystick->hwdata->fresh = 1;
765
766 return (0);
767 }
768
769 /* Function to determine is this joystick is attached to the system right now */
770 SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
771 {
772 return !joystick->closed && (joystick->hwdata->item != NULL);
773 }
774
775 static __inline__ void
776 HandleHat(SDL_Joystick * stick, Uint8 hat, int axis, int value)
777 {
778 struct hwdata_hat *the_hat;
779 const Uint8 position_map[3][3] = {
780 {SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP},
781 {SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT},
782 {SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN}
783 };
784
785 the_hat = &stick->hwdata->hats[hat];
786 if (value < 0) {
787 value = 0;
788 } else if (value == 0) {
789 value = 1;
790 } else if (value > 0) {
791 value = 2;
792 }
793 if (value != the_hat->axis[axis]) {
794 the_hat->axis[axis] = value;
795 SDL_PrivateJoystickHat(stick, hat,
796 position_map[the_hat->
797 axis[1]][the_hat->axis[0]]);
798 }
799 }
800
801 static __inline__ void
802 HandleBall(SDL_Joystick * stick, Uint8 ball, int axis, int value)
803 {
804 stick->hwdata->balls[ball].axis[axis] += value;
805 }
806
807
808 static __inline__ int
809 AxisCorrect(SDL_Joystick * joystick, int which, int value)
810 {
811 struct axis_correct *correct;
812
813 correct = &joystick->hwdata->abs_correct[which];
814 if (correct->used) {
815 value *= 2;
816 if (value > correct->coef[0]) {
817 if (value < correct->coef[1]) {
818 return 0;
819 }
820 value -= correct->coef[1];
821 } else {
822 value -= correct->coef[0];
823 }
824 value *= correct->coef[2];
825 value >>= 13;
826 }
827
828 /* Clamp and return */
829 if (value < -32768)
830 return -32768;
831 if (value > 32767)
832 return 32767;
833
834 return value;
835 }
836
837 static __inline__ void
838 PollAllValues(SDL_Joystick * joystick)
839 {
840 struct input_absinfo absinfo;
841 int a, b = 0;
842
843 /* Poll all axis */
844 for (a = ABS_X; b < ABS_MAX; a++) {
845 switch (a) {
846 case ABS_HAT0X:
847 case ABS_HAT0Y:
848 case ABS_HAT1X:
849 case ABS_HAT1Y:
850 case ABS_HAT2X:
851 case ABS_HAT2Y:
852 case ABS_HAT3X:
853 case ABS_HAT3Y:
854 /* ingore hats */
855 break;
856 default:
857 if (joystick->hwdata->abs_correct[b].used) {
858 if (ioctl(joystick->hwdata->fd, EVIOCGABS(a), &absinfo) >= 0) {
859 absinfo.value = AxisCorrect(joystick, b, absinfo.value);
860
861 #ifdef DEBUG_INPUT_EVENTS
862 printf("Joystick : Re-read Axis %d (%d) val= %d\n",
863 joystick->hwdata->abs_map[b], a, absinfo.value);
864 #endif
865 SDL_PrivateJoystickAxis(joystick,
866 joystick->hwdata->abs_map[b],
867 absinfo.value);
868 }
869 }
870 b++;
871 }
872 }
873 }
874
875 static __inline__ void
876 HandleInputEvents(SDL_Joystick * joystick)
877 {
878 struct input_event events[32];
879 int i, len;
880 int code;
881
882 if (joystick->hwdata->fresh) {
883 PollAllValues(joystick);
884 joystick->hwdata->fresh = 0;
885 }
886
887 while ((len = read(joystick->hwdata->fd, events, (sizeof events))) > 0) {
888 len /= sizeof(events[0]);
889 for (i = 0; i < len; ++i) {
890 code = events[i].code;
891 switch (events[i].type) {
892 case EV_KEY:
893 if (code >= BTN_MISC) {
894 code -= BTN_MISC;
895 SDL_PrivateJoystickButton(joystick,
896 joystick->hwdata->key_map[code],
897 events[i].value);
898 }
899 break;
900 case EV_ABS:
901 if (code >= ABS_MISC) {
902 break;
903 }
904
905 switch (code) {
906 case ABS_HAT0X:
907 case ABS_HAT0Y:
908 case ABS_HAT1X:
909 case ABS_HAT1Y:
910 case ABS_HAT2X:
911 case ABS_HAT2Y:
912 case ABS_HAT3X:
913 case ABS_HAT3Y:
914 code -= ABS_HAT0X;
915 HandleHat(joystick, code / 2, code % 2, events[i].value);
916 break;
917 default:
918 events[i].value =
919 AxisCorrect(joystick, code, events[i].value);
920 SDL_PrivateJoystickAxis(joystick,
921 joystick->hwdata->abs_map[code],
922 events[i].value);
923 break;
924 }
925 break;
926 case EV_REL:
927 switch (code) {
928 case REL_X:
929 case REL_Y:
930 code -= REL_X;
931 HandleBall(joystick, code / 2, code % 2, events[i].value);
932 break;
933 default:
934 break;
935 }
936 break;
937 case EV_SYN:
938 switch (code) {
939 case SYN_DROPPED :
940 #ifdef DEBUG_INPUT_EVENTS
941 printf("Event SYN_DROPPED detected\n");
942 #endif
943 PollAllValues(joystick);
944 break;
945 default:
946 break;
947 }
948 default:
949 break;
950 }
951 }
952 }
953 }
954
955 void
956 SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
957 {
958 int i;
959
960 HandleInputEvents(joystick);
961
962 /* Deliver ball motion updates */
963 for (i = 0; i < joystick->nballs; ++i) {
964 int xrel, yrel;
965
966 xrel = joystick->hwdata->balls[i].axis[0];
967 yrel = joystick->hwdata->balls[i].axis[1];
968 if (xrel || yrel) {
969 joystick->hwdata->balls[i].axis[0] = 0;
970 joystick->hwdata->balls[i].axis[1] = 0;
971 SDL_PrivateJoystickBall(joystick, (Uint8) i, xrel, yrel);
972 }
973 }
974 }
975
976 /* Function to close a joystick after use */
977 void
978 SDL_SYS_JoystickClose(SDL_Joystick * joystick)
979 {
980 if (joystick->hwdata) {
981 close(joystick->hwdata->fd);
982 if (joystick->hwdata->item) {
983 joystick->hwdata->item->hwdata = NULL;
984 }
985 SDL_free(joystick->hwdata->hats);
986 SDL_free(joystick->hwdata->balls);
987 SDL_free(joystick->hwdata->fname);
988 SDL_free(joystick->hwdata);
989 joystick->hwdata = NULL;
990 }
991 joystick->closed = 1;
992 }
993
994 /* Function to perform any system-specific joystick related cleanup */
995 void
996 SDL_SYS_JoystickQuit(void)
997 {
998 SDL_joylist_item *item = NULL;
999 SDL_joylist_item *next = NULL;
1000
1001 for (item = SDL_joylist; item; item = next) {
1002 next = item->next;
1003 SDL_free(item->path);
1004 SDL_free(item->name);
1005 SDL_free(item);
1006 }
1007
1008 SDL_joylist = SDL_joylist_tail = NULL;
1009
1010 numjoysticks = 0;
1011 instance_counter = 0;
1012
1013 #if SDL_USE_LIBUDEV
1014 if (udev_mon != NULL) {
1015 UDEV_udev_monitor_unref(udev_mon);
1016 udev_mon = NULL;
1017 }
1018 if (udev != NULL) {
1019 UDEV_udev_unref(udev);
1020 udev = NULL;
1021 }
1022 UnloadUDEVLibrary();
1023 #endif
1024 }
1025
1026 SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
1027 {
1028 return JoystickByDevIndex(device_index)->guid;
1029 }
1030
1031 SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
1032 {
1033 return joystick->hwdata->guid;
1034 }
1035
1036 #endif /* SDL_JOYSTICK_LINUX */
1037
1038 /* vi: set ts=4 sw=4 expandtab: */
SDL_HAT_LEFTDOWN
#define SDL_HAT_LEFTDOWN
Definition: SDL_joystick.h:199
joystick_hwdata::fresh
int fresh
Definition: SDL_sysjoystick_c.h:54
joystick_hwdata::axis_correct::used
int used
Definition: SDL_sysjoystick_c.h:50
joystick_hwdata::balls
struct joystick_hwdata::hwdata_ball * balls
__inline__
#define __inline__
Definition: begin_code.h:119
val
GLuint const GLfloat * val
Definition: glew.h:2715
SDL_PushEvent
DECLSPEC int SDLCALL SDL_PushEvent(SDL_Event *event)
Add an event to the event queue.
Definition: SDL_events.c:457
joystick_hwdata::guid
SDL_JoystickGUID guid
Definition: SDL_sysjoystick_c.h:82
SDL_joystick.h
EVIOCGID
#define EVIOCGID
Definition: SDL_config_linux.h:367
type
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
void
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1824
SDL_PrivateJoystickHat
int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
Definition: SDL_joystick.c:536
SDL_SYS_NumJoysticks
int SDL_SYS_NumJoysticks()
Definition: SDL_sysjoystick.m:43
NULL
#define NULL
Definition: ftobjs.h:61
SDL_snprintf
DECLSPEC int SDLCALL SDL_snprintf(char *text, size_t maxlen, const char *fmt,...)
Definition: SDL_string.c:1277
addr
GLenum GLvoid * addr
Definition: glew.h:10667
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:116
SDL_JOYDEVICEADDED
Definition: SDL_events.h:110
SDL_HAT_RIGHTUP
#define SDL_HAT_RIGHTUP
Definition: SDL_joystick.h:196
SDL_JoystickID
Sint32 SDL_JoystickID
Definition: SDL_joystick.h:72
SDL_TRUE
Definition: SDL_stdinc.h:119
t
GLdouble GLdouble t
Definition: glew.h:1384
SDL_free
DECLSPEC void SDLCALL SDL_free(void *mem)
SDL_PrivateJoystickButton
int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
Definition: SDL_joystick.c:610
SDL_ENABLE
#define SDL_ENABLE
Definition: SDL_events.h:688
a
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:8736
name
EGLImageKHR EGLint * name
Definition: eglext.h:284
len
GLenum GLsizei len
Definition: glew.h:7035
SDL_SYS_JoystickQuit
void SDL_SYS_JoystickQuit(void)
Definition: SDL_sysjoystick.m:129
SDL_JoystickGUID::data
Uint8 data[16]
Definition: SDL_joystick.h:69
SDL_strchr
DECLSPEC char *SDLCALL SDL_strchr(const char *str, int c)
Definition: SDL_string.c:575
SDL_FALSE
Definition: SDL_stdinc.h:118
path
GLsizei const GLchar *const * path
Definition: glew.h:5828
SDL_config.h
_SDL_Joystick::hwdata
struct joystick_hwdata * hwdata
Definition: SDL_sysjoystick.h:49
SDL_PrivateJoystickAxis
int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
Definition: SDL_joystick.c:496
_SDL_Joystick::nballs
int nballs
Definition: SDL_sysjoystick.h:40
joystick_hwdata
Definition: SDL_sysjoystick_c.h:58
SDL_JOYDEVICEREMOVED
Definition: SDL_events.h:111
SDL_HAT_RIGHT
#define SDL_HAT_RIGHT
Definition: SDL_joystick.h:193
SDL_PrivateJoystickBall
int SDL_PrivateJoystickBall(SDL_Joystick *joystick, Uint8 ball, Sint16 xrel, Sint16 yrel)
Definition: SDL_joystick.c:574
SDL_HAT_RIGHTDOWN
#define SDL_HAT_RIGHTDOWN
Definition: SDL_joystick.h:197
SDL_GetEventState
#define SDL_GetEventState(type)
Definition: SDL_events.h:701
int
int
Definition: SDL_systhread.c:37
SDL_HAT_LEFT
#define SDL_HAT_LEFT
Definition: SDL_joystick.h:195
SDL_strdup
DECLSPEC char *SDLCALL SDL_strdup(const char *str)
Definition: SDL_string.c:511
SDL_SYS_JoystickAttached
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
Definition: SDL_sysjoystick.m:87
SDL_EventOK
SDL_EventFilter SDL_EventOK
Definition: SDL_events.c:40
SDL_LoadObject
DECLSPEC void *SDLCALL SDL_LoadObject(const char *sofile)
SDL_strlcpy
DECLSPEC size_t SDLCALL SDL_strlcpy(char *dst, const char *src, size_t maxlen)
Definition: SDL_string.c:448
joystick_hwdata::axis_correct::coef
int coef[3]
Definition: SDL_sysjoystick_c.h:51
SDL_memset
DECLSPEC void *SDLCALL SDL_memset(void *dst, int c, size_t len)
Definition: SDL_string.c:261
SDL_SYS_JoystickDetect
void SDL_SYS_JoystickDetect()
Definition: SDL_sysjoystick.m:48
SDL_UnloadObject
DECLSPEC void SDLCALL SDL_UnloadObject(void *handle)
SDL_SetError
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
SDL_malloc
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
SDL_SYS_JoystickNameForDeviceIndex
const char * SDL_SYS_JoystickNameForDeviceIndex(int device_index)
Definition: SDL_sysjoystick.m:59
SDL_strcmp
DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2)
Definition: SDL_string.c:910
joystick_hwdata::hats
long hats
Definition: SDL_sysjoystick_c.h:71
joystick_hwdata::item
struct SDL_joylist_item * item
Definition: SDL_sysjoystick_c.h:30
SDL_SYS_JoystickUpdate
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
Definition: SDL_sysjoystick.m:98
SDL_SYS_JoystickGetGUID
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick *joystick)
Definition: SDL_sysjoystick.m:143
SDL_endian.h
SDL_SYS_JoystickNeedsPolling
SDL_bool SDL_SYS_JoystickNeedsPolling()
Definition: SDL_sysjoystick.m:52
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:159
SDL_SYS_JoystickInit
int SDL_SYS_JoystickInit(void)
Definition: SDL_sysjoystick.m:38
SDL_EventOKParam
void * SDL_EventOKParam
Definition: SDL_events.c:41
code
Definition: inftrees.h:24
PATH_MAX
#define PATH_MAX
Definition: hrtf.c:34
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:83
joystick_hwdata::key_map
Uint8 key_map[KEY_MAX-BTN_MISC]
Definition: SDL_sysjoystick_c.h:46
value
EGLSurface EGLint void ** value
Definition: eglext.h:301
SDL_loadso.h
Uint8
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
SDL_HAT_LEFTUP
#define SDL_HAT_LEFTUP
Definition: SDL_joystick.h:198
SDL_JoystickGUID
Definition: SDL_joystick.h:68
SDL_zerop
#define SDL_zerop(x)
Definition: SDL_stdinc.h:255
_SDL_Joystick
Definition: SDL_sysjoystick.h:29
SDL_SYS_GetInstanceIdOfDeviceIndex
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
Definition: SDL_sysjoystick.m:65
b
GLdouble GLdouble GLdouble b
Definition: glew.h:8383
SDL_SYS_JoystickOpen
int SDL_SYS_JoystickOpen(SDL_Joystick *joystick, int device_index)
Definition: SDL_sysjoystick.m:76
Uint16
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:137
SDL_Event
General event structure.
Definition: SDL_events.h:495
joystick_hwdata::abs_correct
struct joystick_hwdata::axis_correct abs_correct[ABS_MAX]
SDL_getenv
DECLSPEC char *SDLCALL SDL_getenv(const char *name)
Definition: SDL_getenv.c:179
_SDL_Joystick::nbuttons
int nbuttons
Definition: SDL_sysjoystick.h:46
joystick_hwdata::fd
int fd
Definition: SDL_sysjoystick_c.h:29
types.h
_SDL_Joystick::closed
Uint8 closed
Definition: SDL_sysjoystick.h:53
i
int i
Definition: pngrutil.c:1377
joystick_hwdata::fname
char * fname
Definition: SDL_sysjoystick_c.h:32
SDL_HAT_CENTERED
#define SDL_HAT_CENTERED
Definition: SDL_joystick.h:191
SDL_LoadFunction
DECLSPEC void *SDLCALL SDL_LoadFunction(void *handle, const char *name)
SDL_SYS_JoystickClose
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
Definition: SDL_sysjoystick.m:119
SDL_SwapLE16
#define SDL_SwapLE16(X)
Definition: SDL_endian.h:211
joystick_hwdata::abs_map
Uint8 abs_map[ABS_MAX]
Definition: SDL_sysjoystick_c.h:47
joystick_hwdata::hwdata_ball::axis
int axis[2]
Definition: SDL_sysjoystick_c.h:42
SDL_HAT_UP
#define SDL_HAT_UP
Definition: SDL_joystick.h:192
SDL_HAT_DOWN
#define SDL_HAT_DOWN
Definition: SDL_joystick.h:194
_SDL_Joystick::naxes
int naxes
Definition: SDL_sysjoystick.h:34
_SDL_Joystick::instance_id
SDL_JoystickID instance_id
Definition: SDL_sysjoystick.h:31
SDL_SYS_JoystickGetDeviceGUID
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int device_index)
Definition: SDL_sysjoystick.m:133
SDL_Event::type
Uint32 type
Definition: SDL_events.h:497
SDL_assert.h
_SDL_Joystick::nhats
int nhats
Definition: SDL_sysjoystick.h:37
event
cl_event event
Definition: glew.h:3556