Skip to content

Latest commit

 

History

History
881 lines (757 loc) · 29 KB

SDL_evdev.c

File metadata and controls

881 lines (757 loc) · 29 KB
 
1
2
/*
Simple DirectMedia Layer
Jan 2, 2016
Jan 2, 2016
3
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#ifdef SDL_INPUT_LINUXEV
/* This is based on the linux joystick driver */
/* References: https://www.kernel.org/doc/Documentation/input/input.txt
* https://www.kernel.org/doc/Documentation/input/event-codes.txt
* /usr/include/linux/input.h
* The evtest application is also useful to debug the protocol
*/
#include "SDL_evdev.h"
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <limits.h> /* For the definition of PATH_MAX */
#include <linux/input.h>
#ifdef SDL_INPUT_LINUXKD
#include <linux/kd.h>
#include <linux/keyboard.h>
Oct 1, 2016
Oct 1, 2016
43
44
#include <linux/vt.h>
#include <linux/tiocl.h> /* for TIOCL_GETSHIFTSTATE */
45
46
47
48
49
50
51
52
#endif
#include "SDL.h"
#include "SDL_assert.h"
#include "SDL_endian.h"
#include "../../core/linux/SDL_udev.h"
#include "SDL_scancode.h"
#include "../../events/SDL_events_c.h"
Oct 1, 2016
Oct 1, 2016
53
#include "../../events/scancodes_linux.h" /* adds linux_scancode_table */
54
55
56
57
58
59
/* This isn't defined in older Linux kernel headers */
#ifndef SYN_DROPPED
#define SYN_DROPPED 3
#endif
Nov 1, 2016
Nov 1, 2016
60
61
62
63
64
65
66
67
/* These are not defined in older Linux kernel headers */
#ifndef ABS_MT_SLOT
#define ABS_MT_SLOT 0x2f
#define ABS_MT_POSITION_X 0x35
#define ABS_MT_POSITION_Y 0x36
#define ABS_MT_TRACKING_ID 0x39
#endif
Oct 1, 2016
Oct 1, 2016
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
typedef struct SDL_evdevlist_item
{
char *path;
int fd;
/* TODO: use this for every device, not just touchscreen */
int out_of_sync;
/* TODO: expand on this to have data for every possible class (mouse,
keyboard, touchpad, etc.). Also there's probably some things in here we
can pull out to the SDL_evdevlist_item i.e. name */
int is_touchscreen;
struct {
char* name;
int min_x, max_x, range_x;
int min_y, max_y, range_y;
int max_slots;
int current_slot;
struct {
enum {
EVDEV_TOUCH_SLOTDELTA_NONE = 0,
EVDEV_TOUCH_SLOTDELTA_DOWN,
EVDEV_TOUCH_SLOTDELTA_UP,
EVDEV_TOUCH_SLOTDELTA_MOVE
} delta;
int tracking_id;
int x, y;
} * slots;
} * touchscreen_data;
struct SDL_evdevlist_item *next;
} SDL_evdevlist_item;
typedef struct SDL_EVDEV_PrivateData
{
SDL_evdevlist_item *first;
SDL_evdevlist_item *last;
int num_devices;
int ref_count;
int console_fd;
int kb_mode;
} SDL_EVDEV_PrivateData;
#define _THIS SDL_EVDEV_PrivateData *_this
static _THIS = NULL;
116
117
static SDL_Scancode SDL_EVDEV_translate_keycode(int keycode);
static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item);
Oct 1, 2016
Oct 1, 2016
118
static int SDL_EVDEV_device_removed(const char *dev_path);
119
120
#if SDL_USE_LIBUDEV
Oct 1, 2016
Oct 1, 2016
121
122
123
static int SDL_EVDEV_device_added(const char *dev_path, int udev_class);
void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class,
const char *dev_path);
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#endif /* SDL_USE_LIBUDEV */
static Uint8 EVDEV_MouseButtons[] = {
SDL_BUTTON_LEFT, /* BTN_LEFT 0x110 */
SDL_BUTTON_RIGHT, /* BTN_RIGHT 0x111 */
SDL_BUTTON_MIDDLE, /* BTN_MIDDLE 0x112 */
SDL_BUTTON_X1, /* BTN_SIDE 0x113 */
SDL_BUTTON_X2, /* BTN_EXTRA 0x114 */
SDL_BUTTON_X2 + 1, /* BTN_FORWARD 0x115 */
SDL_BUTTON_X2 + 2, /* BTN_BACK 0x116 */
SDL_BUTTON_X2 + 3 /* BTN_TASK 0x117 */
};
static const char* EVDEV_consoles[] = {
Oct 1, 2016
Oct 1, 2016
138
/* "/proc/self/fd/0",
Oct 1, 2016
Oct 1, 2016
140
"/dev/tty0", */ /* the tty ioctl's prohibit these */
141
142
143
144
145
146
"/dev/tty1",
"/dev/tty2",
"/dev/tty3",
"/dev/tty4",
"/dev/tty5",
"/dev/tty6",
Oct 1, 2016
Oct 1, 2016
147
"/dev/tty7", /* usually X is spawned in tty7 */
148
149
150
151
"/dev/vc/0",
"/dev/console"
};
Oct 1, 2016
Oct 1, 2016
152
static int SDL_EVDEV_is_console(int fd) {
Oct 1, 2016
Oct 1, 2016
153
int type;
Oct 1, 2016
Oct 1, 2016
155
156
return isatty(fd) && ioctl(fd, KDGKBTYPE, &type) == 0 &&
(type == KB_101 || type == KB_84);
157
158
159
}
/* Prevent keystrokes from reaching the tty */
Oct 1, 2016
Oct 1, 2016
160
static int SDL_EVDEV_mute_keyboard(int tty_fd, int* old_kb_mode)
Oct 1, 2016
Oct 1, 2016
162
163
if (!SDL_EVDEV_is_console(tty_fd)) {
return SDL_SetError("Tried to mute an invalid tty");
Oct 1, 2016
Oct 1, 2016
164
}
Oct 1, 2016
Oct 1, 2016
166
167
if (ioctl(tty_fd, KDGKBMODE, old_kb_mode) < 0) {
return SDL_SetError("Failed to get keyboard mode during muting");
Oct 1, 2016
Oct 1, 2016
169
170
171
172
/* FIXME: atm this absolutely ruins the vt, and KDSKBMUTE isn't implemented
in the kernel */
/*
Oct 1, 2016
Oct 1, 2016
173
174
if (ioctl(tty_fd, KDSKBMODE, K_OFF) < 0) {
return SDL_SetError("Failed to set keyboard mode during muting");
Oct 1, 2016
Oct 1, 2016
176
*/
177
178
179
180
181
return 0;
}
/* Restore the keyboard mode for given tty */
Oct 1, 2016
Oct 1, 2016
182
static void SDL_EVDEV_unmute_keyboard(int tty_fd, int kb_mode)
Oct 1, 2016
Oct 1, 2016
184
185
/* read above */
/*
Oct 1, 2016
Oct 1, 2016
186
187
if (ioctl(tty_fd, KDSKBMODE, kb_mode) < 0) {
SDL_Log("Failed to unmute keyboard");
Oct 1, 2016
Oct 1, 2016
189
*/
190
191
192
}
static int SDL_EVDEV_get_active_tty()
Oct 1, 2016
Oct 1, 2016
193
194
195
196
197
{
int i, fd, ret, tty = 0;
char tiocl;
struct vt_stat vt_state;
char path[PATH_MAX + 1];
Oct 1, 2016
Oct 1, 2016
199
200
for(i = 0; i < SDL_arraysize(EVDEV_consoles); i++) {
fd = open(EVDEV_consoles[i], O_RDONLY);
Oct 1, 2016
Oct 1, 2016
201
Oct 1, 2016
Oct 1, 2016
202
if (fd < 0 && !SDL_EVDEV_is_console(fd))
Oct 1, 2016
Oct 1, 2016
203
204
205
break;
tiocl = TIOCL_GETFGCONSOLE;
Oct 1, 2016
Oct 1, 2016
206
if ((ret = ioctl(fd, TIOCLINUX, &tiocl)) >= 0)
Oct 1, 2016
Oct 1, 2016
207
tty = ret + 1;
Oct 1, 2016
Oct 1, 2016
208
else if (ioctl(fd, VT_GETSTATE, &vt_state) == 0)
Oct 1, 2016
Oct 1, 2016
209
210
tty = vt_state.v_active;
Oct 1, 2016
Oct 1, 2016
211
close(fd);
Oct 1, 2016
Oct 1, 2016
212
Oct 1, 2016
Oct 1, 2016
213
214
215
216
if (tty) {
sprintf(path, "/dev/tty%u", tty);
fd = open(path, O_RDONLY);
if (fd >= 0 && SDL_EVDEV_is_console(fd))
Oct 1, 2016
Oct 1, 2016
217
218
return fd;
}
Oct 1, 2016
Oct 1, 2016
221
return SDL_SetError("Failed to determine active tty");
222
223
224
225
226
}
int
SDL_EVDEV_Init(void)
{
Oct 1, 2016
Oct 1, 2016
227
228
229
if (_this == NULL) {
_this = (SDL_EVDEV_PrivateData*)SDL_calloc(1, sizeof(*_this));
if (_this == NULL) {
230
231
232
233
return SDL_OutOfMemory();
}
#if SDL_USE_LIBUDEV
Oct 1, 2016
Oct 1, 2016
234
235
if (SDL_UDEV_Init() < 0) {
SDL_free(_this);
236
237
238
239
240
_this = NULL;
return -1;
}
/* Set up the udev callback */
Jun 25, 2015
Jun 25, 2015
241
if (SDL_UDEV_AddCallback(SDL_EVDEV_udev_callback) < 0) {
Oct 1, 2016
Oct 1, 2016
242
SDL_UDEV_Quit();
Oct 1, 2016
Oct 1, 2016
243
SDL_free(_this);
Oct 1, 2016
Oct 1, 2016
244
_this = NULL;
245
246
247
248
249
250
251
252
253
return -1;
}
/* Force a scan to build the initial device list */
SDL_UDEV_Scan();
#else
/* TODO: Scan the devices manually, like a caveman */
#endif /* SDL_USE_LIBUDEV */
Oct 1, 2016
Oct 1, 2016
254
255
256
/* We need a physical terminal (not PTS) to be able to translate key
code to symbols via the kernel tables */
_this->console_fd = SDL_EVDEV_get_active_tty();
Oct 1, 2016
Oct 1, 2016
258
259
/* Mute the keyboard so keystrokes only generate evdev events and do not
leak through to the console */
Oct 1, 2016
Oct 1, 2016
260
SDL_EVDEV_mute_keyboard(_this->console_fd, &_this->kb_mode);
261
262
263
264
}
_this->ref_count += 1;
Oct 1, 2016
Oct 1, 2016
265
return 0;
266
267
268
269
270
}
void
SDL_EVDEV_Quit(void)
{
Oct 1, 2016
Oct 1, 2016
271
if (_this == NULL) {
272
273
274
275
276
return;
}
_this->ref_count -= 1;
Oct 1, 2016
Oct 1, 2016
277
if (_this->ref_count < 1) {
Oct 1, 2016
Oct 1, 2016
279
SDL_UDEV_DelCallback(SDL_EVDEV_udev_callback);
280
281
282
SDL_UDEV_Quit();
#endif /* SDL_USE_LIBUDEV */
Oct 1, 2016
Oct 1, 2016
283
284
285
if (_this->console_fd >= 0) {
SDL_EVDEV_unmute_keyboard(_this->console_fd, _this->kb_mode);
close(_this->console_fd);
286
287
288
289
}
/* Remove existing devices */
while(_this->first != NULL) {
Oct 1, 2016
Oct 1, 2016
290
SDL_EVDEV_device_removed(_this->first->path);
Oct 1, 2016
Oct 1, 2016
293
294
295
SDL_assert(_this->first == NULL);
SDL_assert(_this->last == NULL);
SDL_assert(_this->num_devices == 0);
Oct 1, 2016
Oct 1, 2016
297
SDL_free(_this);
298
299
300
301
302
_this = NULL;
}
}
#if SDL_USE_LIBUDEV
Oct 1, 2016
Oct 1, 2016
303
304
void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_class,
const char* dev_path)
Oct 1, 2016
Oct 1, 2016
306
if (dev_path == NULL) {
Oct 1, 2016
Oct 1, 2016
310
switch(udev_event) {
311
case SDL_UDEV_DEVICEADDED:
Oct 1, 2016
Oct 1, 2016
312
313
if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_KEYBOARD |
SDL_UDEV_DEVICE_TOUCHSCREEN)))
Jun 25, 2015
Jun 25, 2015
314
return;
Oct 1, 2016
Oct 1, 2016
315
Oct 1, 2016
Oct 1, 2016
316
SDL_EVDEV_device_added(dev_path, udev_class);
Oct 1, 2016
Oct 1, 2016
317
break;
318
case SDL_UDEV_DEVICEREMOVED:
Oct 1, 2016
Oct 1, 2016
319
SDL_EVDEV_device_removed(dev_path);
320
321
322
323
324
325
326
break;
default:
break;
}
}
#endif /* SDL_USE_LIBUDEV */
Oct 1, 2016
Oct 1, 2016
327
328
329
#ifdef SDL_INPUT_LINUXKD
/* this logic is pulled from kbd_keycode() in drivers/tty/vt/keyboard.c in the
Linux kernel source */
Oct 1, 2016
Oct 1, 2016
330
static void SDL_EVDEV_do_text_input(unsigned short keycode) {
Oct 1, 2016
Oct 1, 2016
331
332
333
334
335
336
char shift_state;
int locks_state;
struct kbentry kbe;
unsigned char type;
char text[2] = { 0 };
Oct 1, 2016
Oct 1, 2016
337
if (_this->console_fd < 0)
Oct 1, 2016
Oct 1, 2016
338
339
340
return;
shift_state = TIOCL_GETSHIFTSTATE;
Oct 1, 2016
Oct 1, 2016
341
if (ioctl(_this->console_fd, TIOCLINUX, &shift_state) < 0) {
Oct 1, 2016
Oct 1, 2016
342
343
344
345
346
347
348
/* TODO: error */
return;
}
kbe.kb_table = shift_state;
kbe.kb_index = keycode;
Oct 1, 2016
Oct 1, 2016
349
if (ioctl(_this->console_fd, KDGKBENT, &kbe) < 0) {
Oct 1, 2016
Oct 1, 2016
350
351
352
353
/* TODO: error */
return;
}
Oct 1, 2016
Oct 1, 2016
354
type = KTYP(kbe.kb_value);
Oct 1, 2016
Oct 1, 2016
355
Oct 1, 2016
Oct 1, 2016
356
if (type < 0xf0) {
Oct 1, 2016
Oct 1, 2016
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
/*
* FIXME: keysyms with a type below 0xf0 represent a unicode character
* which requires special handling due to dead characters, diacritics,
* etc. For perfect input a proper way to deal with such characters
* should be implemented.
*
* For reference, the only place I was able to find out about this
* special 0xf0 value was in an unused? couple of patches listed below.
*
* http://ftp.tc.edu.tw/pub/docs/Unicode/utf8/linux-2.3.12-keyboard.diff
* http://ftp.tc.edu.tw/pub/docs/Unicode/utf8/linux-2.3.12-console.diff
*/
return;
}
type -= 0xf0;
/* if type is KT_LETTER then it can be affected by Caps Lock */
Oct 1, 2016
Oct 1, 2016
376
if (type == KT_LETTER) {
Oct 1, 2016
Oct 1, 2016
377
378
type = KT_LATIN;
Oct 1, 2016
Oct 1, 2016
379
if (ioctl(_this->console_fd, KDGKBLED, &locks_state) < 0) {
Oct 1, 2016
Oct 1, 2016
380
381
382
383
/* TODO: error */
return;
}
Oct 1, 2016
Oct 1, 2016
384
385
if (locks_state & K_CAPSLOCK) {
kbe.kb_table = shift_state ^ (1 << KG_SHIFT);
Oct 1, 2016
Oct 1, 2016
386
Oct 1, 2016
Oct 1, 2016
387
if (ioctl(_this->console_fd, KDGKBENT, &kbe) < 0) {
Oct 1, 2016
Oct 1, 2016
388
389
390
391
392
393
394
/* TODO: error */
return;
}
}
}
/* TODO: convert values >= 0x80 from ISO-8859-1? to UTF-8 */
Oct 1, 2016
Oct 1, 2016
395
if (type != KT_LATIN || KVAL(kbe.kb_value) >= 0x80)
Oct 1, 2016
Oct 1, 2016
396
397
return;
Oct 1, 2016
Oct 1, 2016
398
399
*text = KVAL(kbe.kb_value);
SDL_SendKeyboardText(text);
Oct 1, 2016
Oct 1, 2016
400
401
402
}
#endif /* SDL_INPUT_LINUXKD */
403
404
405
406
void
SDL_EVDEV_Poll(void)
{
struct input_event events[32];
Oct 1, 2016
Oct 1, 2016
407
int i, j, len;
408
409
410
411
SDL_evdevlist_item *item;
SDL_Scancode scan_code;
int mouse_button;
SDL_Mouse *mouse;
Oct 1, 2016
Oct 1, 2016
412
float norm_x, norm_y;
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
if (!_this) {
return;
}
#if SDL_USE_LIBUDEV
SDL_UDEV_Poll();
#endif
mouse = SDL_GetMouse();
for (item = _this->first; item != NULL; item = item->next) {
while ((len = read(item->fd, events, (sizeof events))) > 0) {
len /= sizeof(events[0]);
for (i = 0; i < len; ++i) {
Oct 1, 2016
Oct 1, 2016
428
429
/* special handling for touchscreen, that should eventually be
used for all devices */
Oct 1, 2016
Oct 1, 2016
430
431
if (item->out_of_sync && item->is_touchscreen &&
events[i].type == EV_SYN && events[i].code != SYN_REPORT) {
Oct 1, 2016
Oct 1, 2016
432
433
434
break;
}
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
switch (events[i].type) {
case EV_KEY:
if (events[i].code >= BTN_MOUSE && events[i].code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) {
mouse_button = events[i].code - BTN_MOUSE;
if (events[i].value == 0) {
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]);
} else if (events[i].value == 1) {
SDL_SendMouseButton(mouse->focus, mouse->mouseID, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]);
}
break;
}
/* Probably keyboard */
scan_code = SDL_EVDEV_translate_keycode(events[i].code);
if (scan_code != SDL_SCANCODE_UNKNOWN) {
if (events[i].value == 0) {
SDL_SendKeyboardKey(SDL_RELEASED, scan_code);
Oct 1, 2016
Oct 1, 2016
452
} else if (events[i].value == 1 || events[i].value == 2 /* key repeated */) {
453
454
SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
#ifdef SDL_INPUT_LINUXKD
Oct 1, 2016
Oct 1, 2016
455
SDL_EVDEV_do_text_input(events[i].code);
456
457
458
459
460
461
#endif /* SDL_INPUT_LINUXKD */
}
}
break;
case EV_ABS:
switch(events[i].code) {
Oct 1, 2016
Oct 1, 2016
462
case ABS_MT_SLOT:
Oct 1, 2016
Oct 1, 2016
463
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
464
465
466
467
break;
item->touchscreen_data->current_slot = events[i].value;
break;
case ABS_MT_TRACKING_ID:
Oct 1, 2016
Oct 1, 2016
468
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
469
break;
Oct 1, 2016
Oct 1, 2016
470
if (events[i].value >= 0) {
Oct 1, 2016
Oct 1, 2016
471
472
473
474
475
476
477
item->touchscreen_data->slots[item->touchscreen_data->current_slot].tracking_id = events[i].value;
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
} else {
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_UP;
}
break;
case ABS_MT_POSITION_X:
Oct 1, 2016
Oct 1, 2016
478
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
479
480
break;
item->touchscreen_data->slots[item->touchscreen_data->current_slot].x = events[i].value;
Oct 1, 2016
Oct 1, 2016
481
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
Oct 1, 2016
Oct 1, 2016
482
483
484
485
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
}
break;
case ABS_MT_POSITION_Y:
Oct 1, 2016
Oct 1, 2016
486
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
487
488
break;
item->touchscreen_data->slots[item->touchscreen_data->current_slot].y = events[i].value;
Oct 1, 2016
Oct 1, 2016
489
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
Oct 1, 2016
Oct 1, 2016
490
491
492
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
}
break;
Oct 1, 2016
Oct 1, 2016
494
if (item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
495
break;
496
497
498
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
break;
case ABS_Y:
Oct 1, 2016
Oct 1, 2016
499
if (item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
500
break;
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
break;
default:
break;
}
break;
case EV_REL:
switch(events[i].code) {
case REL_X:
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, events[i].value, 0);
break;
case REL_Y:
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_TRUE, 0, events[i].value);
break;
case REL_WHEEL:
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, 0, events[i].value, SDL_MOUSEWHEEL_NORMAL);
break;
case REL_HWHEEL:
SDL_SendMouseWheel(mouse->focus, mouse->mouseID, events[i].value, 0, SDL_MOUSEWHEEL_NORMAL);
break;
default:
break;
}
break;
case EV_SYN:
switch (events[i].code) {
Oct 1, 2016
Oct 1, 2016
527
case SYN_REPORT:
Oct 1, 2016
Oct 1, 2016
528
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
529
530
break;
Oct 1, 2016
Oct 1, 2016
531
for(j = 0; j < item->touchscreen_data->max_slots; j++) {
Oct 1, 2016
Oct 1, 2016
532
533
534
535
536
norm_x = (float)(item->touchscreen_data->slots[j].x - item->touchscreen_data->min_x) /
(float)item->touchscreen_data->range_x;
norm_y = (float)(item->touchscreen_data->slots[j].y - item->touchscreen_data->min_y) /
(float)item->touchscreen_data->range_y;
Oct 1, 2016
Oct 1, 2016
537
switch(item->touchscreen_data->slots[j].delta) {
Oct 1, 2016
Oct 1, 2016
538
case EVDEV_TOUCH_SLOTDELTA_DOWN:
Oct 1, 2016
Oct 1, 2016
539
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_TRUE, norm_x, norm_y, 1.0f);
Oct 1, 2016
Oct 1, 2016
540
541
542
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
break;
case EVDEV_TOUCH_SLOTDELTA_UP:
Oct 1, 2016
Oct 1, 2016
543
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_FALSE, norm_x, norm_y, 1.0f);
Oct 1, 2016
Oct 1, 2016
544
545
546
547
item->touchscreen_data->slots[j].tracking_id = -1;
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
break;
case EVDEV_TOUCH_SLOTDELTA_MOVE:
Oct 1, 2016
Oct 1, 2016
548
SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, norm_x, norm_y, 1.0f);
Oct 1, 2016
Oct 1, 2016
549
550
551
552
553
554
555
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
break;
default:
break;
}
}
Oct 1, 2016
Oct 1, 2016
556
if (item->out_of_sync)
Oct 1, 2016
Oct 1, 2016
557
558
item->out_of_sync = 0;
break;
Oct 1, 2016
Oct 1, 2016
560
if (item->is_touchscreen)
Oct 1, 2016
Oct 1, 2016
561
item->out_of_sync = 1;
562
563
564
565
566
567
568
569
570
571
572
573
574
SDL_EVDEV_sync_device(item);
break;
default:
break;
}
break;
}
}
}
}
}
static SDL_Scancode
Oct 1, 2016
Oct 1, 2016
575
SDL_EVDEV_translate_keycode(int keycode)
576
577
578
{
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
Oct 1, 2016
Oct 1, 2016
579
if (keycode < SDL_arraysize(linux_scancode_table))
Oct 1, 2016
Oct 1, 2016
580
581
scancode = linux_scancode_table[keycode];
Oct 1, 2016
Oct 1, 2016
582
583
if (scancode == SDL_SCANCODE_UNKNOWN) {
SDL_Log("The key you just pressed is not recognized by SDL. To help "
Oct 1, 2016
Oct 1, 2016
584
"get this fixed, please report this to the SDL mailing list "
Oct 1, 2016
Oct 1, 2016
585
"<sdl@libsdl.org> EVDEV KeyCode %d\n", keycode);
Oct 1, 2016
Oct 1, 2016
587
588
589
590
return scancode;
}
Oct 1, 2016
Oct 1, 2016
591
#ifdef SDL_USE_LIBUDEV
Oct 1, 2016
Oct 1, 2016
592
static int
Oct 1, 2016
Oct 1, 2016
593
594
SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
{
Oct 1, 2016
Oct 1, 2016
595
596
597
598
int ret, i;
char name[64];
struct input_absinfo abs_info;
Oct 1, 2016
Oct 1, 2016
599
if (!item->is_touchscreen)
Oct 1, 2016
Oct 1, 2016
600
601
return 0;
Oct 1, 2016
Oct 1, 2016
602
603
item->touchscreen_data = SDL_calloc(1, sizeof(*item->touchscreen_data));
if (item->touchscreen_data == NULL)
Oct 1, 2016
Oct 1, 2016
604
605
return SDL_OutOfMemory();
Oct 1, 2016
Oct 1, 2016
606
607
608
609
ret = ioctl(item->fd, EVIOCGNAME(sizeof(name)), name);
if (ret < 0) {
SDL_free(item->touchscreen_data);
return SDL_SetError("Failed to get evdev touchscreen name");
Oct 1, 2016
Oct 1, 2016
610
611
}
Oct 1, 2016
Oct 1, 2016
612
613
614
item->touchscreen_data->name = SDL_strdup(name);
if (item->touchscreen_data->name == NULL) {
SDL_free(item->touchscreen_data);
Oct 1, 2016
Oct 1, 2016
615
616
617
return SDL_OutOfMemory();
}
Oct 1, 2016
Oct 1, 2016
618
619
620
621
622
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_X), &abs_info);
if (ret < 0) {
SDL_free(item->touchscreen_data->name);
SDL_free(item->touchscreen_data);
return SDL_SetError("Failed to get evdev touchscreen limits");
Oct 1, 2016
Oct 1, 2016
623
624
625
626
627
}
item->touchscreen_data->min_x = abs_info.minimum;
item->touchscreen_data->max_x = abs_info.maximum;
item->touchscreen_data->range_x = abs_info.maximum - abs_info.minimum;
Oct 1, 2016
Oct 1, 2016
628
629
630
631
632
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_Y), &abs_info);
if (ret < 0) {
SDL_free(item->touchscreen_data->name);
SDL_free(item->touchscreen_data);
return SDL_SetError("Failed to get evdev touchscreen limits");
Oct 1, 2016
Oct 1, 2016
633
634
635
636
637
}
item->touchscreen_data->min_y = abs_info.minimum;
item->touchscreen_data->max_y = abs_info.maximum;
item->touchscreen_data->range_y = abs_info.maximum - abs_info.minimum;
Oct 1, 2016
Oct 1, 2016
638
639
640
641
642
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
if (ret < 0) {
SDL_free(item->touchscreen_data->name);
SDL_free(item->touchscreen_data);
return SDL_SetError("Failed to get evdev touchscreen limits");
Oct 1, 2016
Oct 1, 2016
643
644
645
646
647
}
item->touchscreen_data->max_slots = abs_info.maximum + 1;
item->touchscreen_data->slots = SDL_calloc(
item->touchscreen_data->max_slots,
Oct 1, 2016
Oct 1, 2016
648
649
650
651
sizeof(*item->touchscreen_data->slots));
if (item->touchscreen_data->slots == NULL) {
SDL_free(item->touchscreen_data->name);
SDL_free(item->touchscreen_data);
Oct 1, 2016
Oct 1, 2016
652
653
654
return SDL_OutOfMemory();
}
Oct 1, 2016
Oct 1, 2016
655
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
Oct 1, 2016
Oct 1, 2016
656
657
658
item->touchscreen_data->slots[i].tracking_id = -1;
}
Oct 1, 2016
Oct 1, 2016
659
660
661
662
663
664
ret = SDL_AddTouch(item->fd, /* I guess our fd is unique enough */
item->touchscreen_data->name);
if (ret < 0) {
SDL_free(item->touchscreen_data->slots);
SDL_free(item->touchscreen_data->name);
SDL_free(item->touchscreen_data);
Oct 1, 2016
Oct 1, 2016
665
666
667
668
669
return ret;
}
return 0;
}
Oct 1, 2016
Oct 1, 2016
670
#endif /* SDL_USE_LIBUDEV */
Oct 1, 2016
Oct 1, 2016
671
672
static void
Oct 1, 2016
Oct 1, 2016
673
674
SDL_EVDEV_destroy_touchscreen(SDL_evdevlist_item* item) {
if (!item->is_touchscreen)
Oct 1, 2016
Oct 1, 2016
675
676
return;
Oct 1, 2016
Oct 1, 2016
677
678
679
680
SDL_DelTouch(item->fd);
SDL_free(item->touchscreen_data->slots);
SDL_free(item->touchscreen_data->name);
SDL_free(item->touchscreen_data);
Oct 1, 2016
Oct 1, 2016
681
682
}
683
684
685
static void
SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
{
Oct 1, 2016
Oct 1, 2016
686
#ifdef EVIOCGMTSLOTS
Oct 1, 2016
Oct 1, 2016
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
int i, ret;
struct input_absinfo abs_info;
/*
* struct input_mt_request_layout {
* __u32 code;
* __s32 values[num_slots];
* };
*
* this is the structure we're trying to emulate
*/
__u32* mt_req_code;
__s32* mt_req_values;
size_t mt_req_size;
/* TODO: sync devices other than touchscreen */
Oct 1, 2016
Oct 1, 2016
702
if (!item->is_touchscreen)
Oct 1, 2016
Oct 1, 2016
703
704
return;
Oct 1, 2016
Oct 1, 2016
705
706
mt_req_size = sizeof(*mt_req_code) +
sizeof(*mt_req_values) * item->touchscreen_data->max_slots;
Oct 1, 2016
Oct 1, 2016
707
Oct 1, 2016
Oct 1, 2016
708
709
mt_req_code = SDL_calloc(1, mt_req_size);
if (mt_req_code == NULL) {
Oct 1, 2016
Oct 1, 2016
710
711
712
713
714
715
return;
}
mt_req_values = (__s32*)mt_req_code + 1;
*mt_req_code = ABS_MT_TRACKING_ID;
Oct 1, 2016
Oct 1, 2016
716
717
718
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
if (ret < 0) {
SDL_free(mt_req_code);
Oct 1, 2016
Oct 1, 2016
719
720
return;
}
Oct 1, 2016
Oct 1, 2016
721
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
Oct 1, 2016
Oct 1, 2016
722
723
724
725
726
727
728
729
730
/*
* This doesn't account for the very edge case of the user removing their
* finger and replacing it on the screen during the time we're out of sync,
* which'll mean that we're not going from down -> up or up -> down, we're
* going from down -> down but with a different tracking id, meaning we'd
* have to tell SDL of the two events, but since we wait till SYN_REPORT in
* SDL_EVDEV_Poll to tell SDL, the current structure of this code doesn't
* allow it. Lets just pray to God it doesn't happen.
*/
Oct 1, 2016
Oct 1, 2016
731
732
if (item->touchscreen_data->slots[i].tracking_id < 0 &&
mt_req_values[i] >= 0) {
Oct 1, 2016
Oct 1, 2016
733
734
item->touchscreen_data->slots[i].tracking_id = mt_req_values[i];
item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
Oct 1, 2016
Oct 1, 2016
735
736
} else if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
mt_req_values[i] < 0) {
Oct 1, 2016
Oct 1, 2016
737
738
739
740
741
742
item->touchscreen_data->slots[i].tracking_id = -1;
item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_UP;
}
}
*mt_req_code = ABS_MT_POSITION_X;
Oct 1, 2016
Oct 1, 2016
743
744
745
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
if (ret < 0) {
SDL_free(mt_req_code);
Oct 1, 2016
Oct 1, 2016
746
747
return;
}
Oct 1, 2016
Oct 1, 2016
748
749
750
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
item->touchscreen_data->slots[i].x != mt_req_values[i]) {
Oct 1, 2016
Oct 1, 2016
751
item->touchscreen_data->slots[i].x = mt_req_values[i];
Oct 1, 2016
Oct 1, 2016
752
753
if (item->touchscreen_data->slots[i].delta ==
EVDEV_TOUCH_SLOTDELTA_NONE) {
Oct 1, 2016
Oct 1, 2016
754
755
756
757
758
759
760
item->touchscreen_data->slots[i].delta =
EVDEV_TOUCH_SLOTDELTA_MOVE;
}
}
}
*mt_req_code = ABS_MT_POSITION_Y;
Oct 1, 2016
Oct 1, 2016
761
762
763
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
if (ret < 0) {
SDL_free(mt_req_code);
Oct 1, 2016
Oct 1, 2016
764
765
return;
}
Oct 1, 2016
Oct 1, 2016
766
767
768
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
item->touchscreen_data->slots[i].y != mt_req_values[i]) {
Oct 1, 2016
Oct 1, 2016
769
item->touchscreen_data->slots[i].y = mt_req_values[i];
Oct 1, 2016
Oct 1, 2016
770
771
if (item->touchscreen_data->slots[i].delta ==
EVDEV_TOUCH_SLOTDELTA_NONE) {
Oct 1, 2016
Oct 1, 2016
772
773
774
775
776
777
item->touchscreen_data->slots[i].delta =
EVDEV_TOUCH_SLOTDELTA_MOVE;
}
}
}
Oct 1, 2016
Oct 1, 2016
778
779
780
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
if (ret < 0) {
SDL_free(mt_req_code);
Oct 1, 2016
Oct 1, 2016
781
782
783
784
return;
}
item->touchscreen_data->current_slot = abs_info.value;
Oct 1, 2016
Oct 1, 2016
785
SDL_free(mt_req_code);
Oct 1, 2016
Oct 1, 2016
786
787
#endif /* EVIOCGMTSLOTS */
788
789
790
791
}
#if SDL_USE_LIBUDEV
static int
Oct 1, 2016
Oct 1, 2016
792
SDL_EVDEV_device_added(const char *dev_path, int udev_class)
Oct 1, 2016
Oct 1, 2016
794
int ret;
795
796
797
798
SDL_evdevlist_item *item;
/* Check to make sure it's not already in list. */
for (item = _this->first; item != NULL; item = item->next) {
Oct 1, 2016
Oct 1, 2016
799
if (SDL_strcmp(dev_path, item->path) == 0) {
800
801
802
803
804
805
806
807
808
return -1; /* already have this one */
}
}
item = (SDL_evdevlist_item *) SDL_calloc(1, sizeof (SDL_evdevlist_item));
if (item == NULL) {
return SDL_OutOfMemory();
}
Oct 1, 2016
Oct 1, 2016
809
item->fd = open(dev_path, O_RDONLY | O_NONBLOCK);
810
811
if (item->fd < 0) {
SDL_free(item);
Oct 1, 2016
Oct 1, 2016
812
return SDL_SetError("Unable to open %s", dev_path);
Oct 1, 2016
Oct 1, 2016
815
item->path = SDL_strdup(dev_path);
816
817
818
819
820
821
if (item->path == NULL) {
close(item->fd);
SDL_free(item);
return SDL_OutOfMemory();
}
Oct 1, 2016
Oct 1, 2016
822
if (udev_class & SDL_UDEV_DEVICE_TOUCHSCREEN) {
Oct 1, 2016
Oct 1, 2016
823
824
item->is_touchscreen = 1;
Oct 1, 2016
Oct 1, 2016
825
if ((ret = SDL_EVDEV_init_touchscreen(item)) < 0) {
Oct 1, 2016
Oct 1, 2016
826
827
828
829
830
close(item->fd);
SDL_free(item);
return ret;
}
}
831
832
833
834
835
836
837
838
839
840
if (_this->last == NULL) {
_this->first = _this->last = item;
} else {
_this->last->next = item;
_this->last = item;
}
SDL_EVDEV_sync_device(item);
Oct 1, 2016
Oct 1, 2016
841
return _this->num_devices++;
842
843
844
845
}
#endif /* SDL_USE_LIBUDEV */
static int
Oct 1, 2016
Oct 1, 2016
846
SDL_EVDEV_device_removed(const char *dev_path)
847
848
849
850
851
852
{
SDL_evdevlist_item *item;
SDL_evdevlist_item *prev = NULL;
for (item = _this->first; item != NULL; item = item->next) {
/* found it, remove it. */
Oct 1, 2016
Oct 1, 2016
853
if (SDL_strcmp(dev_path, item->path) == 0) {
854
855
856
857
858
859
860
861
862
if (prev != NULL) {
prev->next = item->next;
} else {
SDL_assert(_this->first == item);
_this->first = item->next;
}
if (item == _this->last) {
_this->last = prev;
}
Oct 1, 2016
Oct 1, 2016
863
864
if (item->is_touchscreen) {
SDL_EVDEV_destroy_touchscreen(item);
Oct 1, 2016
Oct 1, 2016
865
}
866
867
868
close(item->fd);
SDL_free(item->path);
SDL_free(item);
Oct 1, 2016
Oct 1, 2016
869
_this->num_devices--;
870
871
872
873
874
875
876
877
878
879
880
881
return 0;
}
prev = item;
}
return -1;
}
#endif /* SDL_INPUT_LINUXEV */
/* vi: set ts=4 sw=4 expandtab: */