zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_evdev.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_INPUT_LINUXEV
24 
25 /* This is based on the linux joystick driver */
26 /* References: https://www.kernel.org/doc/Documentation/input/input.txt
27  * https://www.kernel.org/doc/Documentation/input/event-codes.txt
28  * /usr/include/linux/input.h
29  * The evtest application is also useful to debug the protocol
30  */
31 
32 
33 #include "SDL_evdev.h"
34 #define _THIS SDL_EVDEV_PrivateData *_this
35 static _THIS = NULL;
36 
37 #include <sys/stat.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 #include <sys/ioctl.h>
41 #include <limits.h> /* For the definition of PATH_MAX */
42 
43 
44 #include "SDL.h"
45 #include "SDL_assert.h"
46 #include "SDL_endian.h"
47 #include "../../core/linux/SDL_udev.h"
48 #include "SDL_scancode.h"
49 #include "../../events/SDL_events_c.h"
50 
51 /* This isn't defined in older Linux kernel headers */
52 #ifndef SYN_DROPPED
53 #define SYN_DROPPED 3
54 #endif
55 
56 static SDL_Scancode SDL_EVDEV_translate_keycode(int keycode);
57 static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item);
58 static int SDL_EVDEV_device_removed(const char *devpath);
59 
60 #if SDL_USE_LIBUDEV
61 static int SDL_EVDEV_device_added(const SDL_UDEV_deviceclass devclass, const char *devpath);
62 void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, SDL_UDEV_deviceclass udev_class, const char *devpath);
63 #endif /* SDL_USE_LIBUDEV */
64 
65 static SDL_Scancode EVDEV_Keycodes[] = {
66  SDL_SCANCODE_UNKNOWN, /* KEY_RESERVED 0 */
67  SDL_SCANCODE_ESCAPE, /* KEY_ESC 1 */
68  SDL_SCANCODE_1, /* KEY_1 2 */
69  SDL_SCANCODE_2, /* KEY_2 3 */
70  SDL_SCANCODE_3, /* KEY_3 4 */
71  SDL_SCANCODE_4, /* KEY_4 5 */
72  SDL_SCANCODE_5, /* KEY_5 6 */
73  SDL_SCANCODE_6, /* KEY_6 7 */
74  SDL_SCANCODE_7, /* KEY_7 8 */
75  SDL_SCANCODE_8, /* KEY_8 9 */
76  SDL_SCANCODE_9, /* KEY_9 10 */
77  SDL_SCANCODE_0, /* KEY_0 11 */
78  SDL_SCANCODE_MINUS, /* KEY_MINUS 12 */
79  SDL_SCANCODE_EQUALS, /* KEY_EQUAL 13 */
80  SDL_SCANCODE_BACKSPACE, /* KEY_BACKSPACE 14 */
81  SDL_SCANCODE_TAB, /* KEY_TAB 15 */
82  SDL_SCANCODE_Q, /* KEY_Q 16 */
83  SDL_SCANCODE_W, /* KEY_W 17 */
84  SDL_SCANCODE_E, /* KEY_E 18 */
85  SDL_SCANCODE_R, /* KEY_R 19 */
86  SDL_SCANCODE_T, /* KEY_T 20 */
87  SDL_SCANCODE_Y, /* KEY_Y 21 */
88  SDL_SCANCODE_U, /* KEY_U 22 */
89  SDL_SCANCODE_I, /* KEY_I 23 */
90  SDL_SCANCODE_O, /* KEY_O 24 */
91  SDL_SCANCODE_P, /* KEY_P 25 */
92  SDL_SCANCODE_LEFTBRACKET, /* KEY_LEFTBRACE 26 */
93  SDL_SCANCODE_RIGHTBRACKET, /* KEY_RIGHTBRACE 27 */
94  SDL_SCANCODE_RETURN, /* KEY_ENTER 28 */
95  SDL_SCANCODE_LCTRL, /* KEY_LEFTCTRL 29 */
96  SDL_SCANCODE_A, /* KEY_A 30 */
97  SDL_SCANCODE_S, /* KEY_S 31 */
98  SDL_SCANCODE_D, /* KEY_D 32 */
99  SDL_SCANCODE_F, /* KEY_F 33 */
100  SDL_SCANCODE_G, /* KEY_G 34 */
101  SDL_SCANCODE_H, /* KEY_H 35 */
102  SDL_SCANCODE_J, /* KEY_J 36 */
103  SDL_SCANCODE_K, /* KEY_K 37 */
104  SDL_SCANCODE_L, /* KEY_L 38 */
105  SDL_SCANCODE_SEMICOLON, /* KEY_SEMICOLON 39 */
106  SDL_SCANCODE_APOSTROPHE, /* KEY_APOSTROPHE 40 */
107  SDL_SCANCODE_GRAVE, /* KEY_GRAVE 41 */
108  SDL_SCANCODE_LSHIFT, /* KEY_LEFTSHIFT 42 */
109  SDL_SCANCODE_BACKSLASH, /* KEY_BACKSLASH 43 */
110  SDL_SCANCODE_Z, /* KEY_Z 44 */
111  SDL_SCANCODE_X, /* KEY_X 45 */
112  SDL_SCANCODE_C, /* KEY_C 46 */
113  SDL_SCANCODE_V, /* KEY_V 47 */
114  SDL_SCANCODE_B, /* KEY_B 48 */
115  SDL_SCANCODE_N, /* KEY_N 49 */
116  SDL_SCANCODE_M, /* KEY_M 50 */
117  SDL_SCANCODE_COMMA, /* KEY_COMMA 51 */
118  SDL_SCANCODE_PERIOD, /* KEY_DOT 52 */
119  SDL_SCANCODE_SLASH, /* KEY_SLASH 53 */
120  SDL_SCANCODE_RSHIFT, /* KEY_RIGHTSHIFT 54 */
121  SDL_SCANCODE_KP_MULTIPLY, /* KEY_KPASTERISK 55 */
122  SDL_SCANCODE_LALT, /* KEY_LEFTALT 56 */
123  SDL_SCANCODE_SPACE, /* KEY_SPACE 57 */
124  SDL_SCANCODE_CAPSLOCK, /* KEY_CAPSLOCK 58 */
125  SDL_SCANCODE_F1, /* KEY_F1 59 */
126  SDL_SCANCODE_F2, /* KEY_F2 60 */
127  SDL_SCANCODE_F3, /* KEY_F3 61 */
128  SDL_SCANCODE_F4, /* KEY_F4 62 */
129  SDL_SCANCODE_F5, /* KEY_F5 63 */
130  SDL_SCANCODE_F6, /* KEY_F6 64 */
131  SDL_SCANCODE_F7, /* KEY_F7 65 */
132  SDL_SCANCODE_F8, /* KEY_F8 66 */
133  SDL_SCANCODE_F9, /* KEY_F9 67 */
134  SDL_SCANCODE_F10, /* KEY_F10 68 */
135  SDL_SCANCODE_NUMLOCKCLEAR, /* KEY_NUMLOCK 69 */
136  SDL_SCANCODE_SCROLLLOCK, /* KEY_SCROLLLOCK 70 */
137  SDL_SCANCODE_KP_7, /* KEY_KP7 71 */
138  SDL_SCANCODE_KP_8, /* KEY_KP8 72 */
139  SDL_SCANCODE_KP_9, /* KEY_KP9 73 */
140  SDL_SCANCODE_KP_MINUS, /* KEY_KPMINUS 74 */
141  SDL_SCANCODE_KP_4, /* KEY_KP4 75 */
142  SDL_SCANCODE_KP_5, /* KEY_KP5 76 */
143  SDL_SCANCODE_KP_6, /* KEY_KP6 77 */
144  SDL_SCANCODE_KP_PLUS, /* KEY_KPPLUS 78 */
145  SDL_SCANCODE_KP_1, /* KEY_KP1 79 */
146  SDL_SCANCODE_KP_2, /* KEY_KP2 80 */
147  SDL_SCANCODE_KP_3, /* KEY_KP3 81 */
148  SDL_SCANCODE_KP_0, /* KEY_KP0 82 */
149  SDL_SCANCODE_KP_PERIOD, /* KEY_KPDOT 83 */
150  SDL_SCANCODE_UNKNOWN, /* 84 */
151  SDL_SCANCODE_LANG5, /* KEY_ZENKAKUHANKAKU 85 */
152  SDL_SCANCODE_UNKNOWN, /* KEY_102ND 86 */
153  SDL_SCANCODE_F11, /* KEY_F11 87 */
154  SDL_SCANCODE_F12, /* KEY_F12 88 */
155  SDL_SCANCODE_UNKNOWN, /* KEY_RO 89 */
156  SDL_SCANCODE_LANG3, /* KEY_KATAKANA 90 */
157  SDL_SCANCODE_LANG4, /* KEY_HIRAGANA 91 */
158  SDL_SCANCODE_UNKNOWN, /* KEY_HENKAN 92 */
159  SDL_SCANCODE_LANG3, /* KEY_KATAKANAHIRAGANA 93 */
160  SDL_SCANCODE_UNKNOWN, /* KEY_MUHENKAN 94 */
161  SDL_SCANCODE_KP_COMMA, /* KEY_KPJPCOMMA 95 */
162  SDL_SCANCODE_KP_ENTER, /* KEY_KPENTER 96 */
163  SDL_SCANCODE_RCTRL, /* KEY_RIGHTCTRL 97 */
164  SDL_SCANCODE_KP_DIVIDE, /* KEY_KPSLASH 98 */
165  SDL_SCANCODE_SYSREQ, /* KEY_SYSRQ 99 */
166  SDL_SCANCODE_RALT, /* KEY_RIGHTALT 100 */
167  SDL_SCANCODE_UNKNOWN, /* KEY_LINEFEED 101 */
168  SDL_SCANCODE_HOME, /* KEY_HOME 102 */
169  SDL_SCANCODE_UP, /* KEY_UP 103 */
170  SDL_SCANCODE_PAGEUP, /* KEY_PAGEUP 104 */
171  SDL_SCANCODE_LEFT, /* KEY_LEFT 105 */
172  SDL_SCANCODE_RIGHT, /* KEY_RIGHT 106 */
173  SDL_SCANCODE_END, /* KEY_END 107 */
174  SDL_SCANCODE_DOWN, /* KEY_DOWN 108 */
175  SDL_SCANCODE_PAGEDOWN, /* KEY_PAGEDOWN 109 */
176  SDL_SCANCODE_INSERT, /* KEY_INSERT 110 */
177  SDL_SCANCODE_DELETE, /* KEY_DELETE 111 */
178  SDL_SCANCODE_UNKNOWN, /* KEY_MACRO 112 */
179  SDL_SCANCODE_MUTE, /* KEY_MUTE 113 */
180  SDL_SCANCODE_VOLUMEDOWN, /* KEY_VOLUMEDOWN 114 */
181  SDL_SCANCODE_VOLUMEUP, /* KEY_VOLUMEUP 115 */
182  SDL_SCANCODE_POWER, /* KEY_POWER 116 SC System Power Down */
183  SDL_SCANCODE_KP_EQUALS, /* KEY_KPEQUAL 117 */
184  SDL_SCANCODE_KP_MINUS, /* KEY_KPPLUSMINUS 118 */
185  SDL_SCANCODE_PAUSE, /* KEY_PAUSE 119 */
186  SDL_SCANCODE_UNKNOWN, /* KEY_SCALE 120 AL Compiz Scale (Expose) */
187  SDL_SCANCODE_KP_COMMA, /* KEY_KPCOMMA 121 */
188  SDL_SCANCODE_LANG1, /* KEY_HANGEUL,KEY_HANGUEL 122 */
189  SDL_SCANCODE_LANG2, /* KEY_HANJA 123 */
190  SDL_SCANCODE_INTERNATIONAL3,/* KEY_YEN 124 */
191  SDL_SCANCODE_LGUI, /* KEY_LEFTMETA 125 */
192  SDL_SCANCODE_RGUI, /* KEY_RIGHTMETA 126 */
193  SDL_SCANCODE_APPLICATION, /* KEY_COMPOSE 127 */
194  SDL_SCANCODE_STOP, /* KEY_STOP 128 AC Stop */
195  SDL_SCANCODE_AGAIN, /* KEY_AGAIN 129 */
196  SDL_SCANCODE_UNKNOWN, /* KEY_PROPS 130 AC Properties */
197  SDL_SCANCODE_UNDO, /* KEY_UNDO 131 AC Undo */
198  SDL_SCANCODE_UNKNOWN, /* KEY_FRONT 132 */
199  SDL_SCANCODE_COPY, /* KEY_COPY 133 AC Copy */
200  SDL_SCANCODE_UNKNOWN, /* KEY_OPEN 134 AC Open */
201  SDL_SCANCODE_PASTE, /* KEY_PASTE 135 AC Paste */
202  SDL_SCANCODE_FIND, /* KEY_FIND 136 AC Search */
203  SDL_SCANCODE_CUT, /* KEY_CUT 137 AC Cut */
204  SDL_SCANCODE_HELP, /* KEY_HELP 138 AL Integrated Help Center */
205  SDL_SCANCODE_MENU, /* KEY_MENU 139 Menu (show menu) */
206  SDL_SCANCODE_CALCULATOR, /* KEY_CALC 140 AL Calculator */
207  SDL_SCANCODE_UNKNOWN, /* KEY_SETUP 141 */
208  SDL_SCANCODE_SLEEP, /* KEY_SLEEP 142 SC System Sleep */
209  SDL_SCANCODE_UNKNOWN, /* KEY_WAKEUP 143 System Wake Up */
210  SDL_SCANCODE_UNKNOWN, /* KEY_FILE 144 AL Local Machine Browser */
211  SDL_SCANCODE_UNKNOWN, /* KEY_SENDFILE 145 */
212  SDL_SCANCODE_UNKNOWN, /* KEY_DELETEFILE 146 */
213  SDL_SCANCODE_UNKNOWN, /* KEY_XFER 147 */
214  SDL_SCANCODE_APP1, /* KEY_PROG1 148 */
215  SDL_SCANCODE_APP1, /* KEY_PROG2 149 */
216  SDL_SCANCODE_WWW, /* KEY_WWW 150 AL Internet Browser */
217  SDL_SCANCODE_UNKNOWN, /* KEY_MSDOS 151 */
218  SDL_SCANCODE_UNKNOWN, /* KEY_COFFEE,KEY_SCREENLOCK 152 AL Terminal Lock/Screensaver */
219  SDL_SCANCODE_UNKNOWN, /* KEY_DIRECTION 153 */
220  SDL_SCANCODE_UNKNOWN, /* KEY_CYCLEWINDOWS 154 */
221  SDL_SCANCODE_MAIL, /* KEY_MAIL 155 */
222  SDL_SCANCODE_AC_BOOKMARKS, /* KEY_BOOKMARKS 156 AC Bookmarks */
223  SDL_SCANCODE_COMPUTER, /* KEY_COMPUTER 157 */
224  SDL_SCANCODE_AC_BACK, /* KEY_BACK 158 AC Back */
225  SDL_SCANCODE_AC_FORWARD, /* KEY_FORWARD 159 AC Forward */
226  SDL_SCANCODE_UNKNOWN, /* KEY_CLOSECD 160 */
227  SDL_SCANCODE_EJECT, /* KEY_EJECTCD 161 */
228  SDL_SCANCODE_UNKNOWN, /* KEY_EJECTCLOSECD 162 */
229  SDL_SCANCODE_AUDIONEXT, /* KEY_NEXTSONG 163 */
230  SDL_SCANCODE_AUDIOPLAY, /* KEY_PLAYPAUSE 164 */
231  SDL_SCANCODE_AUDIOPREV, /* KEY_PREVIOUSSONG 165 */
232  SDL_SCANCODE_AUDIOSTOP, /* KEY_STOPCD 166 */
233  SDL_SCANCODE_UNKNOWN, /* KEY_RECORD 167 */
234  SDL_SCANCODE_UNKNOWN, /* KEY_REWIND 168 */
235  SDL_SCANCODE_UNKNOWN, /* KEY_PHONE 169 Media Select Telephone */
236  SDL_SCANCODE_UNKNOWN, /* KEY_ISO 170 */
237  SDL_SCANCODE_UNKNOWN, /* KEY_CONFIG 171 AL Consumer Control Configuration */
238  SDL_SCANCODE_AC_HOME, /* KEY_HOMEPAGE 172 AC Home */
239  SDL_SCANCODE_AC_REFRESH, /* KEY_REFRESH 173 AC Refresh */
240  SDL_SCANCODE_UNKNOWN, /* KEY_EXIT 174 AC Exit */
241  SDL_SCANCODE_UNKNOWN, /* KEY_MOVE 175 */
242  SDL_SCANCODE_UNKNOWN, /* KEY_EDIT 176 */
243  SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLUP 177 */
244  SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLDOWN 178 */
245  SDL_SCANCODE_KP_LEFTPAREN, /* KEY_KPLEFTPAREN 179 */
246  SDL_SCANCODE_KP_RIGHTPAREN, /* KEY_KPRIGHTPAREN 180 */
247  SDL_SCANCODE_UNKNOWN, /* KEY_NEW 181 AC New */
248  SDL_SCANCODE_AGAIN, /* KEY_REDO 182 AC Redo/Repeat */
249  SDL_SCANCODE_F13, /* KEY_F13 183 */
250  SDL_SCANCODE_F14, /* KEY_F14 184 */
251  SDL_SCANCODE_F15, /* KEY_F15 185 */
252  SDL_SCANCODE_F16, /* KEY_F16 186 */
253  SDL_SCANCODE_F17, /* KEY_F17 187 */
254  SDL_SCANCODE_F18, /* KEY_F18 188 */
255  SDL_SCANCODE_F19, /* KEY_F19 189 */
256  SDL_SCANCODE_F20, /* KEY_F20 190 */
257  SDL_SCANCODE_F21, /* KEY_F21 191 */
258  SDL_SCANCODE_F22, /* KEY_F22 192 */
259  SDL_SCANCODE_F23, /* KEY_F23 193 */
260  SDL_SCANCODE_F24, /* KEY_F24 194 */
261  SDL_SCANCODE_UNKNOWN, /* 195 */
262  SDL_SCANCODE_UNKNOWN, /* 196 */
263  SDL_SCANCODE_UNKNOWN, /* 197 */
264  SDL_SCANCODE_UNKNOWN, /* 198 */
265  SDL_SCANCODE_UNKNOWN, /* 199 */
266  SDL_SCANCODE_UNKNOWN, /* KEY_PLAYCD 200 */
267  SDL_SCANCODE_UNKNOWN, /* KEY_PAUSECD 201 */
268  SDL_SCANCODE_UNKNOWN, /* KEY_PROG3 202 */
269  SDL_SCANCODE_UNKNOWN, /* KEY_PROG4 203 */
270  SDL_SCANCODE_UNKNOWN, /* KEY_DASHBOARD 204 AL Dashboard */
271  SDL_SCANCODE_UNKNOWN, /* KEY_SUSPEND 205 */
272  SDL_SCANCODE_UNKNOWN, /* KEY_CLOSE 206 AC Close */
273  SDL_SCANCODE_UNKNOWN, /* KEY_PLAY 207 */
274  SDL_SCANCODE_UNKNOWN, /* KEY_FASTFORWARD 208 */
275  SDL_SCANCODE_UNKNOWN, /* KEY_BASSBOOST 209 */
276  SDL_SCANCODE_UNKNOWN, /* KEY_PRINT 210 AC Print */
277  SDL_SCANCODE_UNKNOWN, /* KEY_HP 211 */
278  SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA 212 */
279  SDL_SCANCODE_UNKNOWN, /* KEY_SOUND 213 */
280  SDL_SCANCODE_UNKNOWN, /* KEY_QUESTION 214 */
281  SDL_SCANCODE_UNKNOWN, /* KEY_EMAIL 215 */
282  SDL_SCANCODE_UNKNOWN, /* KEY_CHAT 216 */
283  SDL_SCANCODE_UNKNOWN, /* KEY_SEARCH 217 */
284  SDL_SCANCODE_UNKNOWN, /* KEY_CONNECT 218 */
285  SDL_SCANCODE_UNKNOWN, /* KEY_FINANCE 219 AL Checkbook/Finance */
286  SDL_SCANCODE_UNKNOWN, /* KEY_SPORT 220 */
287  SDL_SCANCODE_UNKNOWN, /* KEY_SHOP 221 */
288  SDL_SCANCODE_UNKNOWN, /* KEY_ALTERASE 222 */
289  SDL_SCANCODE_UNKNOWN, /* KEY_CANCEL 223 AC Cancel */
290  SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESSDOWN 224 */
291  SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESSUP 225 */
292  SDL_SCANCODE_UNKNOWN, /* KEY_MEDIA 226 */
293  SDL_SCANCODE_UNKNOWN, /* KEY_SWITCHVIDEOMODE 227 Cycle between available video outputs (Monitor/LCD/TV-out/etc) */
294  SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMTOGGLE 228 */
295  SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMDOWN 229 */
296  SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMUP 230 */
297  SDL_SCANCODE_UNKNOWN, /* KEY_SEND 231 AC Send */
298  SDL_SCANCODE_UNKNOWN, /* KEY_REPLY 232 AC Reply */
299  SDL_SCANCODE_UNKNOWN, /* KEY_FORWARDMAIL 233 AC Forward Msg */
300  SDL_SCANCODE_UNKNOWN, /* KEY_SAVE 234 AC Save */
301  SDL_SCANCODE_UNKNOWN, /* KEY_DOCUMENTS 235 */
302  SDL_SCANCODE_UNKNOWN, /* KEY_BATTERY 236 */
303  SDL_SCANCODE_UNKNOWN, /* KEY_BLUETOOTH 237 */
304  SDL_SCANCODE_UNKNOWN, /* KEY_WLAN 238 */
305  SDL_SCANCODE_UNKNOWN, /* KEY_UWB 239 */
306  SDL_SCANCODE_UNKNOWN, /* KEY_UNKNOWN 240 */
307  SDL_SCANCODE_UNKNOWN, /* KEY_VIDEO_NEXT 241 drive next video source */
308  SDL_SCANCODE_UNKNOWN, /* KEY_VIDEO_PREV 242 drive previous video source */
309  SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_CYCLE 243 brightness up, after max is min */
310  SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_ZERO 244 brightness off, use ambient */
311  SDL_SCANCODE_UNKNOWN, /* KEY_DISPLAY_OFF 245 display device to off state */
312  SDL_SCANCODE_UNKNOWN, /* KEY_WIMAX 246 */
313  SDL_SCANCODE_UNKNOWN, /* KEY_RFKILL 247 Key that controls all radios */
314  SDL_SCANCODE_UNKNOWN, /* KEY_MICMUTE 248 Mute / unmute the microphone */
315 };
316 
317 static Uint8 EVDEV_MouseButtons[] = {
318  SDL_BUTTON_LEFT, /* BTN_LEFT 0x110 */
319  SDL_BUTTON_RIGHT, /* BTN_RIGHT 0x111 */
320  SDL_BUTTON_MIDDLE, /* BTN_MIDDLE 0x112 */
321  SDL_BUTTON_X1, /* BTN_SIDE 0x113 */
322  SDL_BUTTON_X2, /* BTN_EXTRA 0x114 */
323  SDL_BUTTON_X2 + 1, /* BTN_FORWARD 0x115 */
324  SDL_BUTTON_X2 + 2, /* BTN_BACK 0x116 */
325  SDL_BUTTON_X2 + 3 /* BTN_TASK 0x117 */
326 };
327 
328 int
329 SDL_EVDEV_Init(void)
330 {
331  int retval = 0;
332 
333  if (_this == NULL) {
334  _this = (SDL_EVDEV_PrivateData *) SDL_calloc(1, sizeof(*_this));
335  if(_this == NULL) {
336  return SDL_OutOfMemory();
337  }
338 
339 #if SDL_USE_LIBUDEV
340  if (SDL_UDEV_Init() < 0) {
341  SDL_free(_this);
342  _this = NULL;
343  return -1;
344  }
345 
346  /* Set up the udev callback */
347  if ( SDL_UDEV_AddCallback(SDL_EVDEV_udev_callback) < 0) {
348  SDL_EVDEV_Quit();
349  return -1;
350  }
351 
352  /* Force a scan to build the initial device list */
353  SDL_UDEV_Scan();
354 #else
355  /* TODO: Scan the devices manually, like a caveman */
356 #endif /* SDL_USE_LIBUDEV */
357 
358  }
359 
360  _this->ref_count += 1;
361 
362  return retval;
363 }
364 
365 void
366 SDL_EVDEV_Quit(void)
367 {
368  if (_this == NULL) {
369  return;
370  }
371 
372  _this->ref_count -= 1;
373 
374  if (_this->ref_count < 1) {
375 
376 #if SDL_USE_LIBUDEV
377  SDL_UDEV_DelCallback(SDL_EVDEV_udev_callback);
378  SDL_UDEV_Quit();
379 #endif /* SDL_USE_LIBUDEV */
380 
381  /* Remove existing devices */
382  while(_this->first != NULL) {
383  SDL_EVDEV_device_removed(_this->first->path);
384  }
385 
386  SDL_assert(_this->first == NULL);
387  SDL_assert(_this->last == NULL);
388  SDL_assert(_this->numdevices == 0);
389 
390  SDL_free(_this);
391  _this = NULL;
392  }
393 }
394 
395 #if SDL_USE_LIBUDEV
396 void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, SDL_UDEV_deviceclass udev_class, const char *devpath)
397 {
398  SDL_EVDEV_deviceclass devclass;
399 
400  if (devpath == NULL) {
401  return;
402  }
403 
404  switch( udev_class )
405  {
406  case SDL_UDEV_DEVICE_MOUSE:
407  devclass = SDL_EVDEV_DEVICE_MOUSE;
408  break;
409 
410  case SDL_UDEV_DEVICE_KEYBOARD:
411  devclass = SDL_EVDEV_DEVICE_KEYBOARD;
412  break;
413 
414  default:
415  return;
416  }
417 
418  switch( udev_type )
419  {
420  case SDL_UDEV_DEVICEADDED:
421  SDL_EVDEV_device_added(devclass, devpath);
422  break;
423 
424  case SDL_UDEV_DEVICEREMOVED:
425  SDL_EVDEV_device_removed(devpath);
426  break;
427 
428  default:
429  break;
430 
431  }
432 
433 }
434 
435 #endif /* SDL_USE_LIBUDEV */
436 
437 void
438 SDL_EVDEV_Poll(void)
439 {
440  struct input_event events[32];
441  int i, len;
442  SDL_evdevlist_item *item;
443  SDL_Scancode scan_code;
444  int mouse_button;
445  SDL_Mouse *mouse;
446 
447 #if SDL_USE_LIBUDEV
448  SDL_UDEV_Poll();
449 #endif
450 
451  for (item = _this->first; item != NULL; item = item->next) {
452  while ((len = read(item->fd, events, (sizeof events))) > 0) {
453  len /= sizeof(events[0]);
454  for (i = 0; i < len; ++i) {
455  switch(item->devclass) {
456  case SDL_EVDEV_DEVICE_KEYBOARD:
457  switch (events[i].type) {
458  case EV_KEY:
459  scan_code = SDL_EVDEV_translate_keycode(events[i].code);
460  if (scan_code != SDL_SCANCODE_UNKNOWN) {
461  if (events[i].value == 0) {
462  SDL_SendKeyboardKey(SDL_RELEASED, scan_code);
463  }
464  else if (events[i].value == 1) {
465  SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
466  }
467  else if (events[i].value == 2) {
468  /* Key repeated */
469  SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
470  }
471  }
472  break;
473 
474  default:
475  break;
476  }
477  break; /* SDL_EVDEV_DEVICE_KEYBOARD */
478 
479  case SDL_EVDEV_DEVICE_MOUSE:
480  mouse = SDL_GetMouse();
481  switch (events[i].type) {
482  case EV_KEY:
483  mouse_button = events[i].code - BTN_MOUSE;
484  if (mouse_button >= 0 && mouse_button < SDL_arraysize(EVDEV_MouseButtons)) {
485  if (events[i].value == 0) {
486  SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]);
487  }
488  else if (events[i].value == 1) {
489  SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]);
490  }
491  }
492  break;
493  case EV_ABS:
494  switch(events[i].code) {
495  case ABS_X:
496  SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
497  break;
498  case ABS_Y:
499  SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
500  break;
501  default:
502  break;
503  }
504  break;
505  case EV_REL:
506  switch(events[i].code) {
507  case REL_X:
508  SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, events[i].value, 0);
509  break;
510  case REL_Y:
511  SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, 0, events[i].value);
512  break;
513  case REL_WHEEL:
514  SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value);
515  break;
516  case REL_HWHEEL:
517  SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0);
518  break;
519  default:
520  break;
521  }
522  break;
523  default:
524  break;
525  }
526  break; /* SDL_EVDEV_DEVICE_MOUSE */
527 
528  default:
529  break;
530  }
531 
532 
533  /* Handle events not specific to any type of device */
534  switch (events[i].type) {
535  case EV_SYN:
536  switch (events[i].code) {
537  case SYN_DROPPED :
538  SDL_EVDEV_sync_device(item);
539  break;
540  default:
541  break;
542  }
543  }
544 
545  }
546  }
547  }
548 }
549 
550 static SDL_Scancode
551 SDL_EVDEV_translate_keycode(int keycode)
552 {
554 
555  if (keycode < SDL_arraysize(EVDEV_Keycodes)) {
556  scancode = EVDEV_Keycodes[keycode];
557  }
558  if (scancode == SDL_SCANCODE_UNKNOWN) {
559  SDL_Log("The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list <sdl@libsdl.org> EVDEV KeyCode %d \n", keycode);
560  }
561  return scancode;
562 }
563 
564 static void
565 SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
566 {
567  /* TODO: get full state of device and report whatever is required */
568 }
569 
570 #if SDL_USE_LIBUDEV
571 static int
572 SDL_EVDEV_device_added(const SDL_UDEV_deviceclass devclass, const char *devpath)
573 {
574  SDL_evdevlist_item *item;
575 
576  /* Check to make sure it's not already in list. */
577  for (item = _this->first; item != NULL; item = item->next) {
578  if (strcmp(devpath, item->path) == 0) {
579  return -1; /* already have this one */
580  }
581  }
582 
583  item = (SDL_evdevlist_item *) SDL_calloc(1, sizeof (SDL_evdevlist_item));
584  if (item == NULL) {
585  return SDL_OutOfMemory();
586  }
587 
588  item->devclass = devclass;
589 
590 
591  item->fd = open(devpath, O_RDONLY, 0);
592  if (item->fd < 0) {
593  SDL_free(item);
594  return SDL_SetError("Unable to open %s", devpath);
595  }
596 
597  item->path = SDL_strdup(devpath);
598  if (item->path == NULL) {
599  close(item->fd);
600  SDL_free(item);
601  return SDL_OutOfMemory();
602  }
603 
604  /* Non blocking read mode */
605  fcntl(item->fd, F_SETFL, O_NONBLOCK);
606 
607  if (_this->last == NULL) {
608  _this->first = _this->last = item;
609  } else {
610  _this->last->next = item;
611  _this->last = item;
612  }
613 
614  SDL_EVDEV_sync_device(item);
615 
616  return _this->numdevices++;
617 }
618 #endif /* SDL_USE_LIBUDEV */
619 
620 static int
621 SDL_EVDEV_device_removed(const char *devpath)
622 {
623  SDL_evdevlist_item *item;
624  SDL_evdevlist_item *prev = NULL;
625 
626  for (item = _this->first; item != NULL; item = item->next) {
627  /* found it, remove it. */
628  if ( strcmp(devpath, item->path) ==0 ) {
629  if (prev != NULL) {
630  prev->next = item->next;
631  } else {
632  SDL_assert(_this->first == item);
633  _this->first = item->next;
634  }
635  if (item == _this->last) {
636  _this->last = prev;
637  }
638  close(item->fd);
639  SDL_free(item->path);
640  SDL_free(item);
641  _this->numdevices--;
642  return 0;
643  }
644  prev = item;
645  }
646 
647  return -1;
648 }
649 
650 
651 #endif /* SDL_INPUT_LINUXEV */
652 
653 /* vi: set ts=4 sw=4 expandtab: */
SDL_Mouse * SDL_GetMouse(void)
Definition: SDL_mouse.c:62
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
DECLSPEC void *SDLCALL SDL_calloc(size_t nmemb, size_t size)
#define NULL
Definition: ftobjs.h:61
SDL_Window * focus
Definition: SDL_mouse_c.h:61
#define SDL_BUTTON_RIGHT
Definition: SDL_mouse.h:206
DECLSPEC void SDLCALL SDL_free(void *mem)
#define SDL_BUTTON_X1
Definition: SDL_mouse.h:207
GLenum GLsizei len
Definition: glew.h:7035
SDL_MouseID mouseID
Definition: SDL_mouse_c.h:60
int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
Definition: SDL_keyboard.c:650
static SDL_VideoDevice * _this
Definition: SDL_video.c:92
int SDL_SendMouseMotion(SDL_Window *window, SDL_MouseID mouseID, int relative, int x, int y)
Definition: SDL_mouse.c:178
#define SDL_BUTTON_LEFT
Definition: SDL_mouse.h:204
#define _THIS
DECLSPEC char *SDLCALL SDL_strdup(const char *str)
Definition: SDL_string.c:511
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
#define SDL_BUTTON_MIDDLE
Definition: SDL_mouse.h:205
#define SDL_assert(condition)
Definition: SDL_assert.h:159
Definition: inftrees.h:24
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:83
DECLSPEC void SDLCALL SDL_Log(const char *fmt,...)
Log a message with SDL_LOG_CATEGORY_APPLICATION and SDL_LOG_PRIORITY_INFO.
Definition: SDL_log.c:173
EGLSurface EGLint void ** value
Definition: eglext.h:301
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:129
int SDL_SendMouseWheel(SDL_Window *window, SDL_MouseID mouseID, int x, int y)
Definition: SDL_mouse.c:332
#define SDL_PRESSED
Definition: SDL_events.h:50
int i
Definition: pngrutil.c:1377
#define SDL_BUTTON_X2
Definition: SDL_mouse.h:208
#define SDL_RELEASED
Definition: SDL_events.h:49
int SDL_SendMouseButton(SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
Definition: SDL_mouse.c:276
SDL_Scancode
The SDL keyboard scancode representation.
Definition: SDL_scancode.h:43