~ubuntu-branches/ubuntu/vivid/libsdl2/vivid

« back to all changes in this revision

Viewing changes to src/joystick/linux/SDL_sysjoystick.c

  • Committer: Package Import Robot
  • Author(s): Manuel A. Fernandez Montecelo, Felix Geyer
  • Date: 2013-12-28 12:31:19 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20131228123119-e0k27gckmnzskfgb
Tags: 2.0.1+dfsg1-1
* New upstream release (Closes: #728974)
  - Remove patch applied upstream:
    bug-723797-false_positives_in_mouse_wheel_code.patch
* Bump Standards-Version to 3.9.5, no changes needed.

[ Felix Geyer ]
* Import upstream gpg key for uscan to verify the orig tarball.

Show diffs side-by-side

added added

removed removed

Lines of Context:
52
52
#define SYN_DROPPED 3
53
53
#endif
54
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
 
55
#include "../../core/linux/SDL_udev.h"
 
56
 
 
57
static int MaybeAddDevice(const char *path);
 
58
#if SDL_USE_LIBUDEV
 
59
static int MaybeRemoveDevice(const char *path);
 
60
void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
 
61
#endif /* SDL_USE_LIBUDEV */
173
62
 
174
63
 
175
64
/* A linked list of available joysticks */
246
135
    return 1;
247
136
}
248
137
 
 
138
#if SDL_USE_LIBUDEV
 
139
void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
 
140
{
 
141
    if (devpath == NULL || !(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
 
142
        return;
 
143
    }
 
144
    
 
145
    switch( udev_type )
 
146
    {
 
147
        case SDL_UDEV_DEVICEADDED:
 
148
            MaybeAddDevice(devpath);
 
149
            break;
 
150
            
 
151
        case SDL_UDEV_DEVICEREMOVED:
 
152
            MaybeRemoveDevice(devpath);
 
153
            break;
 
154
            
 
155
        default:
 
156
            break;
 
157
    }
 
158
    
 
159
}
 
160
#endif /* SDL_USE_LIBUDEV */
 
161
 
249
162
 
250
163
/* !!! FIXME: I would love to dump this code and use libudev instead. */
251
164
static int
257
170
    char namebuf[128];
258
171
    SDL_JoystickGUID guid;
259
172
    SDL_joylist_item *item;
 
173
#if !SDL_EVENTS_DISABLED
 
174
    SDL_Event event;
 
175
#endif
260
176
 
261
177
    if (path == NULL) {
262
178
        return -1;
314
230
        SDL_joylist_tail = item;
315
231
    }
316
232
 
 
233
    /* !!! FIXME: Move this to an SDL_PrivateJoyDeviceAdded() function? */
 
234
#if !SDL_EVENTS_DISABLED
 
235
    event.type = SDL_JOYDEVICEADDED;
 
236
 
 
237
    if (SDL_GetEventState(event.type) == SDL_ENABLE) {
 
238
        event.jdevice.which = numjoysticks;
 
239
        if ( (SDL_EventOK == NULL) ||
 
240
             (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
 
241
            SDL_PushEvent(&event);
 
242
        }
 
243
    }
 
244
#endif /* !SDL_EVENTS_DISABLED */
 
245
 
317
246
    return numjoysticks++;
318
247
}
319
248
 
324
253
{
325
254
    SDL_joylist_item *item;
326
255
    SDL_joylist_item *prev = NULL;
 
256
#if !SDL_EVENTS_DISABLED
 
257
    SDL_Event event;
 
258
#endif
327
259
 
328
260
    if (path == NULL) {
329
261
        return -1;
345
277
            if (item == SDL_joylist_tail) {
346
278
                SDL_joylist_tail = prev;
347
279
            }
 
280
 
 
281
            /* !!! FIXME: Move this to an SDL_PrivateJoyDeviceRemoved() function? */
 
282
#if !SDL_EVENTS_DISABLED
 
283
            event.type = SDL_JOYDEVICEREMOVED;
 
284
 
 
285
            if (SDL_GetEventState(event.type) == SDL_ENABLE) {
 
286
                event.jdevice.which = item->device_instance;
 
287
                if ( (SDL_EventOK == NULL) ||
 
288
                     (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
 
289
                    SDL_PushEvent(&event);
 
290
                }
 
291
            }
 
292
#endif /* !SDL_EVENTS_DISABLED */
 
293
 
348
294
            SDL_free(item->path);
349
295
            SDL_free(item->name);
350
296
            SDL_free(item);
380
326
static int
381
327
JoystickInitWithUdev(void)
382
328
{
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);
 
329
 
 
330
    if (SDL_UDEV_Init() < 0) {
 
331
        return SDL_SetError("Could not initialize UDEV");
 
332
    }
 
333
 
 
334
    /* Set up the udev callback */
 
335
    if ( SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
 
336
        SDL_UDEV_Quit();
 
337
        return SDL_SetError("Could not set up joystick <-> udev callback");
 
338
    }
 
339
    
 
340
    /* Force a scan to build the initial device list */
 
341
    SDL_UDEV_Scan();
417
342
 
418
343
    return numjoysticks;
419
344
}
439
364
    }
440
365
 
441
366
#if SDL_USE_LIBUDEV
442
 
    if (LoadUDEVLibrary() == 0) {   /* okay if this fails, FOR NOW. */
443
 
        return JoystickInitWithUdev();
444
 
    }
 
367
    return JoystickInitWithUdev();
445
368
#endif
446
369
 
447
370
    return JoystickInitWithoutUdev();
452
375
    return numjoysticks;
453
376
}
454
377
 
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
378
void SDL_SYS_JoystickDetect()
478
379
{
479
380
#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
 
    }
 
381
    SDL_UDEV_Poll();
535
382
#endif
 
383
    
536
384
}
537
385
 
538
386
SDL_bool SDL_SYS_JoystickNeedsPolling()
539
387
{
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();
 
388
#if SDL_USE_LIBUDEV
 
389
    return SDL_TRUE;
 
390
#endif
 
391
    
 
392
    return SDL_FALSE;
548
393
}
549
394
 
550
395
static SDL_joylist_item *
772
617
    return !joystick->closed && (joystick->hwdata->item != NULL);
773
618
}
774
619
 
775
 
static __inline__ void
 
620
static SDL_INLINE void
776
621
HandleHat(SDL_Joystick * stick, Uint8 hat, int axis, int value)
777
622
{
778
623
    struct hwdata_hat *the_hat;
798
643
    }
799
644
}
800
645
 
801
 
static __inline__ void
 
646
static SDL_INLINE void
802
647
HandleBall(SDL_Joystick * stick, Uint8 ball, int axis, int value)
803
648
{
804
649
    stick->hwdata->balls[ball].axis[axis] += value;
805
650
}
806
651
 
807
652
 
808
 
static __inline__ int
 
653
static SDL_INLINE int
809
654
AxisCorrect(SDL_Joystick * joystick, int which, int value)
810
655
{
811
656
    struct axis_correct *correct;
834
679
    return value;
835
680
}
836
681
 
837
 
static __inline__ void
 
682
static SDL_INLINE void
838
683
PollAllValues(SDL_Joystick * joystick)
839
684
{
840
685
    struct input_absinfo absinfo;
872
717
    }
873
718
}
874
719
 
875
 
static __inline__ void
 
720
static SDL_INLINE void
876
721
HandleInputEvents(SDL_Joystick * joystick)
877
722
{
878
723
    struct input_event events[32];
1011
856
    instance_counter = 0;
1012
857
 
1013
858
#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();
 
859
    SDL_UDEV_DelCallback(joystick_udev_callback);
 
860
    SDL_UDEV_Quit();
1023
861
#endif
1024
862
}
1025
863