30 #ifdef SDL_USE_LIBUDEV
32 #include <linux/input.h>
37 #include "../unix/SDL_poll.h"
39 static const char *SDL_UDEV_LIBS[] = {
40 #ifdef SDL_UDEV_DYNAMIC
48 #define _THIS SDL_UDEV_PrivateData *_this
51 static SDL_bool SDL_UDEV_load_sym(
const char *fn,
void **
addr);
52 static int SDL_UDEV_load_syms(
void);
53 static SDL_bool SDL_UDEV_hotplug_update_available(
void);
54 static void device_event(SDL_UDEV_deviceevent
type,
struct udev_device *dev);
57 SDL_UDEV_load_sym(
const char *fn,
void **
addr)
69 SDL_UDEV_load_syms(
void)
72 #define SDL_UDEV_SYM(x) \
73 if (!SDL_UDEV_load_sym(#x, (void **) (char *) & _this->x)) return -1
75 SDL_UDEV_SYM(udev_device_get_action);
76 SDL_UDEV_SYM(udev_device_get_devnode);
77 SDL_UDEV_SYM(udev_device_get_subsystem);
78 SDL_UDEV_SYM(udev_device_get_parent_with_subsystem_devtype);
79 SDL_UDEV_SYM(udev_device_get_property_value);
80 SDL_UDEV_SYM(udev_device_get_sysattr_value);
81 SDL_UDEV_SYM(udev_device_new_from_syspath);
82 SDL_UDEV_SYM(udev_device_unref);
83 SDL_UDEV_SYM(udev_enumerate_add_match_property);
84 SDL_UDEV_SYM(udev_enumerate_add_match_subsystem);
85 SDL_UDEV_SYM(udev_enumerate_get_list_entry);
86 SDL_UDEV_SYM(udev_enumerate_new);
87 SDL_UDEV_SYM(udev_enumerate_scan_devices);
88 SDL_UDEV_SYM(udev_enumerate_unref);
89 SDL_UDEV_SYM(udev_list_entry_get_name);
90 SDL_UDEV_SYM(udev_list_entry_get_next);
91 SDL_UDEV_SYM(udev_monitor_enable_receiving);
92 SDL_UDEV_SYM(udev_monitor_filter_add_match_subsystem_devtype);
93 SDL_UDEV_SYM(udev_monitor_get_fd);
94 SDL_UDEV_SYM(udev_monitor_new_from_netlink);
95 SDL_UDEV_SYM(udev_monitor_receive_device);
96 SDL_UDEV_SYM(udev_monitor_unref);
97 SDL_UDEV_SYM(udev_new);
98 SDL_UDEV_SYM(udev_unref);
99 SDL_UDEV_SYM(udev_device_new_from_devnum);
100 SDL_UDEV_SYM(udev_device_get_devnum);
107 SDL_UDEV_hotplug_update_available(
void)
110 const int fd =
_this->udev_monitor_get_fd(
_this->udev_mon);
130 retval = SDL_UDEV_LoadLibrary();
146 _this->udev_mon =
_this->udev_monitor_new_from_netlink(
_this->udev,
"udev");
149 return SDL_SetError(
"udev_monitor_new_from_netlink() failed");
152 _this->udev_monitor_filter_add_match_subsystem_devtype(
_this->udev_mon,
"input",
NULL);
153 _this->udev_monitor_filter_add_match_subsystem_devtype(
_this->udev_mon,
"sound",
NULL);
154 _this->udev_monitor_enable_receiving(
_this->udev_mon);
161 _this->ref_count += 1;
169 SDL_UDEV_CallbackList *item;
175 _this->ref_count -= 1;
177 if (
_this->ref_count < 1) {
195 SDL_UDEV_UnloadLibrary();
204 struct udev_enumerate *enumerate =
NULL;
205 struct udev_list_entry *devs =
NULL;
206 struct udev_list_entry *item =
NULL;
212 enumerate =
_this->udev_enumerate_new(
_this->udev);
213 if (enumerate ==
NULL) {
219 _this->udev_enumerate_add_match_subsystem(enumerate,
"input");
220 _this->udev_enumerate_add_match_subsystem(enumerate,
"sound");
222 _this->udev_enumerate_scan_devices(enumerate);
223 devs =
_this->udev_enumerate_get_list_entry(enumerate);
224 for (item = devs; item; item =
_this->udev_list_entry_get_next(item)) {
225 const char *
path =
_this->udev_list_entry_get_name(item);
226 struct udev_device *dev =
_this->udev_device_new_from_syspath(
_this->udev, path);
228 device_event(SDL_UDEV_DEVICEADDED, dev);
229 _this->udev_device_unref(dev);
233 _this->udev_enumerate_unref(enumerate);
238 SDL_UDEV_UnloadLibrary(
void)
251 SDL_UDEV_LoadLibrary(
void)
260 if (SDL_UDEV_load_syms() == 0) {
268 retval = SDL_UDEV_load_syms();
270 SDL_UDEV_UnloadLibrary();
287 #define BITS_PER_LONG (sizeof(unsigned long) * 8)
288 #define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
289 #define OFF(x) ((x)%BITS_PER_LONG)
290 #define LONG(x) ((x)/BITS_PER_LONG)
291 #define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
293 static void get_caps(
struct udev_device *dev,
struct udev_device *pdev,
const char *attr,
unsigned long *bitmask,
size_t bitmask_len)
301 SDL_memset(bitmask, 0, bitmask_len*
sizeof(*bitmask));
302 value =
_this->udev_device_get_sysattr_value(pdev, attr);
311 if (i < bitmask_len) {
318 if (i < bitmask_len) {
324 guess_device_class(
struct udev_device *dev)
327 struct udev_device *pdev;
328 unsigned long bitmask_ev[NBITS(EV_MAX)];
329 unsigned long bitmask_abs[NBITS(ABS_MAX)];
330 unsigned long bitmask_key[NBITS(KEY_MAX)];
331 unsigned long bitmask_rel[NBITS(REL_MAX)];
332 unsigned long keyboard_mask;
337 while (pdev && !
_this->udev_device_get_sysattr_value(pdev,
"capabilities/ev")) {
338 pdev =
_this->udev_device_get_parent_with_subsystem_devtype(pdev,
"input",
NULL);
344 get_caps(dev, pdev,
"capabilities/ev", bitmask_ev,
SDL_arraysize(bitmask_ev));
345 get_caps(dev, pdev,
"capabilities/abs", bitmask_abs,
SDL_arraysize(bitmask_abs));
346 get_caps(dev, pdev,
"capabilities/rel", bitmask_rel,
SDL_arraysize(bitmask_rel));
347 get_caps(dev, pdev,
"capabilities/key", bitmask_key,
SDL_arraysize(bitmask_key));
349 if (test_bit(EV_ABS, bitmask_ev) &&
350 test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs)) {
351 if (test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key)) {
353 }
else if (test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key)) {
355 }
else if (test_bit(BTN_MOUSE, bitmask_key)) {
356 devclass |= SDL_UDEV_DEVICE_MOUSE;
357 }
else if (test_bit(BTN_TOUCH, bitmask_key)) {
360 devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN;
363 if (test_bit(BTN_TRIGGER, bitmask_key) ||
364 test_bit(BTN_A, bitmask_key) ||
365 test_bit(BTN_1, bitmask_key) ||
366 test_bit(ABS_RX, bitmask_abs) ||
367 test_bit(ABS_RY, bitmask_abs) ||
368 test_bit(ABS_RZ, bitmask_abs) ||
369 test_bit(ABS_THROTTLE, bitmask_abs) ||
370 test_bit(ABS_RUDDER, bitmask_abs) ||
371 test_bit(ABS_WHEEL, bitmask_abs) ||
372 test_bit(ABS_GAS, bitmask_abs) ||
373 test_bit(ABS_BRAKE, bitmask_abs)) {
374 devclass |= SDL_UDEV_DEVICE_JOYSTICK;
378 if (test_bit(EV_REL, bitmask_ev) &&
379 test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel) &&
380 test_bit(BTN_MOUSE, bitmask_key)) {
381 devclass |= SDL_UDEV_DEVICE_MOUSE;
386 keyboard_mask = 0xFFFFFFFE;
387 if ((bitmask_key[0] & keyboard_mask) != 0)
388 devclass |= SDL_UDEV_DEVICE_KEYBOARD;
394 device_event(SDL_UDEV_deviceevent
type,
struct udev_device *dev)
396 const char *subsystem;
400 SDL_UDEV_CallbackList *item;
402 path =
_this->udev_device_get_devnode(dev);
407 subsystem =
_this->udev_device_get_subsystem(dev);
409 devclass = SDL_UDEV_DEVICE_SOUND;
410 }
else if (
SDL_strcmp(subsystem,
"input") == 0) {
413 val =
_this->udev_device_get_property_value(dev,
"ID_INPUT_JOYSTICK");
415 devclass |= SDL_UDEV_DEVICE_JOYSTICK;
418 val =
_this->udev_device_get_property_value(dev,
"ID_INPUT_MOUSE");
420 devclass |= SDL_UDEV_DEVICE_MOUSE;
423 val =
_this->udev_device_get_property_value(dev,
"ID_INPUT_TOUCHSCREEN");
425 devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN;
434 val =
_this->udev_device_get_property_value(dev,
"ID_INPUT_KEY");
436 devclass |= SDL_UDEV_DEVICE_KEYBOARD;
441 val =
_this->udev_device_get_property_value(dev,
"ID_CLASS");
444 devclass = SDL_UDEV_DEVICE_JOYSTICK;
446 devclass = SDL_UDEV_DEVICE_MOUSE;
448 devclass = SDL_UDEV_DEVICE_KEYBOARD;
454 devclass = guess_device_class(dev);
462 for (item =
_this->first; item !=
NULL; item = item->next) {
463 item->callback(type, devclass, path);
470 struct udev_device *dev =
NULL;
471 const char *action =
NULL;
477 while (SDL_UDEV_hotplug_update_available()) {
478 dev =
_this->udev_monitor_receive_device(
_this->udev_mon);
482 action =
_this->udev_device_get_action(dev);
488 device_event(SDL_UDEV_DEVICEADDED, dev);
489 }
else if (
SDL_strcmp(action,
"remove") == 0) {
490 device_event(SDL_UDEV_DEVICEREMOVED, dev);
493 _this->udev_device_unref(dev);
498 SDL_UDEV_AddCallback(SDL_UDEV_Callback cb)
500 SDL_UDEV_CallbackList *item;
501 item = (SDL_UDEV_CallbackList *)
SDL_calloc(1,
sizeof (SDL_UDEV_CallbackList));
511 _this->last->next = item;
519 SDL_UDEV_DelCallback(SDL_UDEV_Callback cb)
521 SDL_UDEV_CallbackList *item;
522 SDL_UDEV_CallbackList *prev =
NULL;
524 for (item =
_this->first; item !=
NULL; item = item->next) {
526 if (item->callback == cb) {
528 prev->next = item->next;
531 _this->first = item->next;
533 if (item ==
_this->last) {
int SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS)
static SDL_VideoDevice * _this
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)
void * SDL_calloc(size_t nmemb, size_t size)
GLsizei const GLfloat * value
#define SDL_assert(condition)
#define SDL_OutOfMemory()
static char text[MAX_TEXT_LENGTH]
GLuint GLuint GLsizei GLenum type
#define SDL_arraysize(array)
GLsizei const GLchar *const * path
void * SDL_LoadFunction(void *handle, const char *name)