Skip to content

Latest commit

 

History

History
828 lines (712 loc) · 27.7 KB

SDL_evdev.c

File metadata and controls

828 lines (712 loc) · 27.7 KB
 
1
2
/*
Simple DirectMedia Layer
Jan 2, 2017
Jan 2, 2017
3
Copyright (C) 1997-2017 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
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;
Jan 7, 2017
Jan 7, 2017
110
int old_kb_mode;
Oct 1, 2016
Oct 1, 2016
111
112
113
114
115
} 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
#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 */
};
Oct 1, 2016
Oct 1, 2016
137
static int SDL_EVDEV_is_console(int fd) {
Jan 6, 2017
Jan 6, 2017
138
char type;
Oct 1, 2016
Oct 1, 2016
140
141
return isatty(fd) && ioctl(fd, KDGKBTYPE, &type) == 0 &&
(type == KB_101 || type == KB_84);
142
143
144
}
/* Prevent keystrokes from reaching the tty */
Oct 1, 2016
Oct 1, 2016
145
static int SDL_EVDEV_mute_keyboard(int tty_fd, int* old_kb_mode)
Oct 1, 2016
Oct 1, 2016
147
148
if (!SDL_EVDEV_is_console(tty_fd)) {
return SDL_SetError("Tried to mute an invalid tty");
Oct 1, 2016
Oct 1, 2016
149
}
Oct 1, 2016
Oct 1, 2016
151
152
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
154
Oct 1, 2016
Oct 1, 2016
155
156
if (ioctl(tty_fd, KDSKBMODE, K_OFF) < 0) {
return SDL_SetError("Failed to set keyboard mode during muting");
157
158
159
160
161
162
}
return 0;
}
/* Restore the keyboard mode for given tty */
Jan 7, 2017
Jan 7, 2017
163
static void SDL_EVDEV_unmute_keyboard(int tty_fd, int old_kb_mode)
Jan 7, 2017
Jan 7, 2017
165
166
if (ioctl(tty_fd, KDSKBMODE, old_kb_mode) < 0) {
SDL_Log("Failed to set keyboard mode");
167
168
169
170
171
172
}
}
int
SDL_EVDEV_Init(void)
{
Oct 1, 2016
Oct 1, 2016
173
174
175
if (_this == NULL) {
_this = (SDL_EVDEV_PrivateData*)SDL_calloc(1, sizeof(*_this));
if (_this == NULL) {
176
177
178
179
return SDL_OutOfMemory();
}
#if SDL_USE_LIBUDEV
Oct 1, 2016
Oct 1, 2016
180
181
if (SDL_UDEV_Init() < 0) {
SDL_free(_this);
182
183
184
185
186
_this = NULL;
return -1;
}
/* Set up the udev callback */
Jun 25, 2015
Jun 25, 2015
187
if (SDL_UDEV_AddCallback(SDL_EVDEV_udev_callback) < 0) {
Oct 1, 2016
Oct 1, 2016
188
SDL_UDEV_Quit();
Oct 1, 2016
Oct 1, 2016
189
SDL_free(_this);
Oct 1, 2016
Oct 1, 2016
190
_this = NULL;
191
192
193
194
195
196
197
198
199
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 */
Jan 7, 2017
Jan 7, 2017
200
201
202
203
_this->console_fd = open("/dev/tty", O_RDONLY);
if( _this->console_fd < 0 ) {
return SDL_SetError("Failed to open /dev/tty");
}
Oct 1, 2016
Oct 1, 2016
205
206
/* Mute the keyboard so keystrokes only generate evdev events and do not
leak through to the console */
Jan 7, 2017
Jan 7, 2017
207
SDL_EVDEV_mute_keyboard(_this->console_fd, &_this->old_kb_mode);
208
209
210
211
}
_this->ref_count += 1;
Oct 1, 2016
Oct 1, 2016
212
return 0;
213
214
215
216
217
}
void
SDL_EVDEV_Quit(void)
{
Oct 1, 2016
Oct 1, 2016
218
if (_this == NULL) {
219
220
221
222
223
return;
}
_this->ref_count -= 1;
Oct 1, 2016
Oct 1, 2016
224
if (_this->ref_count < 1) {
Oct 1, 2016
Oct 1, 2016
226
SDL_UDEV_DelCallback(SDL_EVDEV_udev_callback);
227
228
229
SDL_UDEV_Quit();
#endif /* SDL_USE_LIBUDEV */
Oct 1, 2016
Oct 1, 2016
230
if (_this->console_fd >= 0) {
Jan 7, 2017
Jan 7, 2017
231
SDL_EVDEV_unmute_keyboard(_this->console_fd, _this->old_kb_mode);
Oct 1, 2016
Oct 1, 2016
232
close(_this->console_fd);
233
234
235
236
}
/* Remove existing devices */
while(_this->first != NULL) {
Oct 1, 2016
Oct 1, 2016
237
SDL_EVDEV_device_removed(_this->first->path);
Oct 1, 2016
Oct 1, 2016
240
241
242
SDL_assert(_this->first == NULL);
SDL_assert(_this->last == NULL);
SDL_assert(_this->num_devices == 0);
Oct 1, 2016
Oct 1, 2016
244
SDL_free(_this);
245
246
247
248
249
_this = NULL;
}
}
#if SDL_USE_LIBUDEV
Oct 1, 2016
Oct 1, 2016
250
251
void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_class,
const char* dev_path)
Oct 1, 2016
Oct 1, 2016
253
if (dev_path == NULL) {
Oct 1, 2016
Oct 1, 2016
257
switch(udev_event) {
258
case SDL_UDEV_DEVICEADDED:
Oct 1, 2016
Oct 1, 2016
259
260
if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_KEYBOARD |
SDL_UDEV_DEVICE_TOUCHSCREEN)))
Jun 25, 2015
Jun 25, 2015
261
return;
Oct 1, 2016
Oct 1, 2016
262
Oct 1, 2016
Oct 1, 2016
263
SDL_EVDEV_device_added(dev_path, udev_class);
Oct 1, 2016
Oct 1, 2016
264
break;
265
case SDL_UDEV_DEVICEREMOVED:
Oct 1, 2016
Oct 1, 2016
266
SDL_EVDEV_device_removed(dev_path);
267
268
269
270
271
272
273
break;
default:
break;
}
}
#endif /* SDL_USE_LIBUDEV */
Oct 1, 2016
Oct 1, 2016
274
275
276
#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
277
static void SDL_EVDEV_do_text_input(unsigned short keycode) {
Oct 1, 2016
Oct 1, 2016
278
279
280
281
282
283
char shift_state;
int locks_state;
struct kbentry kbe;
unsigned char type;
char text[2] = { 0 };
Oct 1, 2016
Oct 1, 2016
284
if (_this->console_fd < 0)
Oct 1, 2016
Oct 1, 2016
285
286
287
return;
shift_state = TIOCL_GETSHIFTSTATE;
Oct 1, 2016
Oct 1, 2016
288
if (ioctl(_this->console_fd, TIOCLINUX, &shift_state) < 0) {
Oct 1, 2016
Oct 1, 2016
289
290
291
292
293
294
295
/* TODO: error */
return;
}
kbe.kb_table = shift_state;
kbe.kb_index = keycode;
Oct 1, 2016
Oct 1, 2016
296
if (ioctl(_this->console_fd, KDGKBENT, &kbe) < 0) {
Oct 1, 2016
Oct 1, 2016
297
298
299
300
/* TODO: error */
return;
}
Oct 1, 2016
Oct 1, 2016
301
type = KTYP(kbe.kb_value);
Oct 1, 2016
Oct 1, 2016
302
Oct 1, 2016
Oct 1, 2016
303
if (type < 0xf0) {
Oct 1, 2016
Oct 1, 2016
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
/*
* 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
323
if (type == KT_LETTER) {
Oct 1, 2016
Oct 1, 2016
324
325
type = KT_LATIN;
Oct 1, 2016
Oct 1, 2016
326
if (ioctl(_this->console_fd, KDGKBLED, &locks_state) < 0) {
Oct 1, 2016
Oct 1, 2016
327
328
329
330
/* TODO: error */
return;
}
Oct 1, 2016
Oct 1, 2016
331
332
if (locks_state & K_CAPSLOCK) {
kbe.kb_table = shift_state ^ (1 << KG_SHIFT);
Oct 1, 2016
Oct 1, 2016
333
Oct 1, 2016
Oct 1, 2016
334
if (ioctl(_this->console_fd, KDGKBENT, &kbe) < 0) {
Oct 1, 2016
Oct 1, 2016
335
336
337
338
339
340
341
/* TODO: error */
return;
}
}
}
/* TODO: convert values >= 0x80 from ISO-8859-1? to UTF-8 */
Oct 1, 2016
Oct 1, 2016
342
if (type != KT_LATIN || KVAL(kbe.kb_value) >= 0x80)
Oct 1, 2016
Oct 1, 2016
343
344
return;
Oct 1, 2016
Oct 1, 2016
345
346
*text = KVAL(kbe.kb_value);
SDL_SendKeyboardText(text);
Oct 1, 2016
Oct 1, 2016
347
348
349
}
#endif /* SDL_INPUT_LINUXKD */
350
351
352
353
void
SDL_EVDEV_Poll(void)
{
struct input_event events[32];
Oct 1, 2016
Oct 1, 2016
354
int i, j, len;
355
356
357
358
SDL_evdevlist_item *item;
SDL_Scancode scan_code;
int mouse_button;
SDL_Mouse *mouse;
Oct 1, 2016
Oct 1, 2016
359
float norm_x, norm_y;
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
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
375
376
/* special handling for touchscreen, that should eventually be
used for all devices */
Oct 1, 2016
Oct 1, 2016
377
378
if (item->out_of_sync && item->is_touchscreen &&
events[i].type == EV_SYN && events[i].code != SYN_REPORT) {
Oct 1, 2016
Oct 1, 2016
379
380
381
break;
}
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
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
399
} else if (events[i].value == 1 || events[i].value == 2 /* key repeated */) {
400
401
SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
#ifdef SDL_INPUT_LINUXKD
Oct 1, 2016
Oct 1, 2016
402
SDL_EVDEV_do_text_input(events[i].code);
403
404
405
406
407
408
#endif /* SDL_INPUT_LINUXKD */
}
}
break;
case EV_ABS:
switch(events[i].code) {
Oct 1, 2016
Oct 1, 2016
409
case ABS_MT_SLOT:
Oct 1, 2016
Oct 1, 2016
410
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
411
412
413
414
break;
item->touchscreen_data->current_slot = events[i].value;
break;
case ABS_MT_TRACKING_ID:
Oct 1, 2016
Oct 1, 2016
415
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
416
break;
Oct 1, 2016
Oct 1, 2016
417
if (events[i].value >= 0) {
Oct 1, 2016
Oct 1, 2016
418
419
420
421
422
423
424
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
425
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
426
427
break;
item->touchscreen_data->slots[item->touchscreen_data->current_slot].x = events[i].value;
Oct 1, 2016
Oct 1, 2016
428
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
Oct 1, 2016
Oct 1, 2016
429
430
431
432
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
433
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
434
435
break;
item->touchscreen_data->slots[item->touchscreen_data->current_slot].y = events[i].value;
Oct 1, 2016
Oct 1, 2016
436
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
Oct 1, 2016
Oct 1, 2016
437
438
439
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
}
break;
Oct 1, 2016
Oct 1, 2016
441
if (item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
442
break;
443
444
445
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
break;
case ABS_Y:
Oct 1, 2016
Oct 1, 2016
446
if (item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
447
break;
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
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
474
case SYN_REPORT:
Oct 1, 2016
Oct 1, 2016
475
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
476
477
break;
Oct 1, 2016
Oct 1, 2016
478
for(j = 0; j < item->touchscreen_data->max_slots; j++) {
Oct 1, 2016
Oct 1, 2016
479
480
481
482
483
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
484
switch(item->touchscreen_data->slots[j].delta) {
Oct 1, 2016
Oct 1, 2016
485
case EVDEV_TOUCH_SLOTDELTA_DOWN:
Oct 1, 2016
Oct 1, 2016
486
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
487
488
489
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
break;
case EVDEV_TOUCH_SLOTDELTA_UP:
Oct 1, 2016
Oct 1, 2016
490
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
491
492
493
494
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
495
SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, norm_x, norm_y, 1.0f);
Oct 1, 2016
Oct 1, 2016
496
497
498
499
500
501
502
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
break;
default:
break;
}
}
Oct 1, 2016
Oct 1, 2016
503
if (item->out_of_sync)
Oct 1, 2016
Oct 1, 2016
504
505
item->out_of_sync = 0;
break;
Oct 1, 2016
Oct 1, 2016
507
if (item->is_touchscreen)
Oct 1, 2016
Oct 1, 2016
508
item->out_of_sync = 1;
509
510
511
512
513
514
515
516
517
518
519
520
521
SDL_EVDEV_sync_device(item);
break;
default:
break;
}
break;
}
}
}
}
}
static SDL_Scancode
Oct 1, 2016
Oct 1, 2016
522
SDL_EVDEV_translate_keycode(int keycode)
523
524
525
{
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
Oct 1, 2016
Oct 1, 2016
526
if (keycode < SDL_arraysize(linux_scancode_table))
Oct 1, 2016
Oct 1, 2016
527
528
scancode = linux_scancode_table[keycode];
Oct 1, 2016
Oct 1, 2016
529
530
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
531
"get this fixed, please report this to the SDL mailing list "
Oct 1, 2016
Oct 1, 2016
532
"<sdl@libsdl.org> EVDEV KeyCode %d\n", keycode);
Oct 1, 2016
Oct 1, 2016
534
535
536
537
return scancode;
}
Oct 1, 2016
Oct 1, 2016
538
#ifdef SDL_USE_LIBUDEV
Oct 1, 2016
Oct 1, 2016
539
static int
Oct 1, 2016
Oct 1, 2016
540
541
SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
{
Oct 1, 2016
Oct 1, 2016
542
543
544
545
int ret, i;
char name[64];
struct input_absinfo abs_info;
Oct 1, 2016
Oct 1, 2016
546
if (!item->is_touchscreen)
Oct 1, 2016
Oct 1, 2016
547
548
return 0;
Oct 1, 2016
Oct 1, 2016
549
550
item->touchscreen_data = SDL_calloc(1, sizeof(*item->touchscreen_data));
if (item->touchscreen_data == NULL)
Oct 1, 2016
Oct 1, 2016
551
552
return SDL_OutOfMemory();
Oct 1, 2016
Oct 1, 2016
553
554
555
556
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
557
558
}
Oct 1, 2016
Oct 1, 2016
559
560
561
item->touchscreen_data->name = SDL_strdup(name);
if (item->touchscreen_data->name == NULL) {
SDL_free(item->touchscreen_data);
Oct 1, 2016
Oct 1, 2016
562
563
564
return SDL_OutOfMemory();
}
Oct 1, 2016
Oct 1, 2016
565
566
567
568
569
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
570
571
572
573
574
}
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
575
576
577
578
579
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
580
581
582
583
584
}
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
585
586
587
588
589
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
590
591
592
593
594
}
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
595
596
597
598
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
599
600
601
return SDL_OutOfMemory();
}
Oct 1, 2016
Oct 1, 2016
602
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
Oct 1, 2016
Oct 1, 2016
603
604
605
item->touchscreen_data->slots[i].tracking_id = -1;
}
Oct 1, 2016
Oct 1, 2016
606
607
608
609
610
611
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
612
613
614
615
616
return ret;
}
return 0;
}
Oct 1, 2016
Oct 1, 2016
617
#endif /* SDL_USE_LIBUDEV */
Oct 1, 2016
Oct 1, 2016
618
619
static void
Oct 1, 2016
Oct 1, 2016
620
621
SDL_EVDEV_destroy_touchscreen(SDL_evdevlist_item* item) {
if (!item->is_touchscreen)
Oct 1, 2016
Oct 1, 2016
622
623
return;
Oct 1, 2016
Oct 1, 2016
624
625
626
627
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
628
629
}
630
631
632
static void
SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
{
Oct 1, 2016
Oct 1, 2016
633
#ifdef EVIOCGMTSLOTS
Oct 1, 2016
Oct 1, 2016
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
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
649
if (!item->is_touchscreen)
Oct 1, 2016
Oct 1, 2016
650
651
return;
Oct 1, 2016
Oct 1, 2016
652
653
mt_req_size = sizeof(*mt_req_code) +
sizeof(*mt_req_values) * item->touchscreen_data->max_slots;
Oct 1, 2016
Oct 1, 2016
654
Oct 1, 2016
Oct 1, 2016
655
656
mt_req_code = SDL_calloc(1, mt_req_size);
if (mt_req_code == NULL) {
Oct 1, 2016
Oct 1, 2016
657
658
659
660
661
662
return;
}
mt_req_values = (__s32*)mt_req_code + 1;
*mt_req_code = ABS_MT_TRACKING_ID;
Oct 1, 2016
Oct 1, 2016
663
664
665
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
666
667
return;
}
Oct 1, 2016
Oct 1, 2016
668
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
Oct 1, 2016
Oct 1, 2016
669
670
671
672
673
674
675
676
677
/*
* 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
678
679
if (item->touchscreen_data->slots[i].tracking_id < 0 &&
mt_req_values[i] >= 0) {
Oct 1, 2016
Oct 1, 2016
680
681
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
682
683
} else if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
mt_req_values[i] < 0) {
Oct 1, 2016
Oct 1, 2016
684
685
686
687
688
689
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
690
691
692
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
693
694
return;
}
Oct 1, 2016
Oct 1, 2016
695
696
697
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
698
item->touchscreen_data->slots[i].x = mt_req_values[i];
Oct 1, 2016
Oct 1, 2016
699
700
if (item->touchscreen_data->slots[i].delta ==
EVDEV_TOUCH_SLOTDELTA_NONE) {
Oct 1, 2016
Oct 1, 2016
701
702
703
704
705
706
707
item->touchscreen_data->slots[i].delta =
EVDEV_TOUCH_SLOTDELTA_MOVE;
}
}
}
*mt_req_code = ABS_MT_POSITION_Y;
Oct 1, 2016
Oct 1, 2016
708
709
710
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
711
712
return;
}
Oct 1, 2016
Oct 1, 2016
713
714
715
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
716
item->touchscreen_data->slots[i].y = mt_req_values[i];
Oct 1, 2016
Oct 1, 2016
717
718
if (item->touchscreen_data->slots[i].delta ==
EVDEV_TOUCH_SLOTDELTA_NONE) {
Oct 1, 2016
Oct 1, 2016
719
720
721
722
723
724
item->touchscreen_data->slots[i].delta =
EVDEV_TOUCH_SLOTDELTA_MOVE;
}
}
}
Oct 1, 2016
Oct 1, 2016
725
726
727
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
if (ret < 0) {
SDL_free(mt_req_code);
Oct 1, 2016
Oct 1, 2016
728
729
730
731
return;
}
item->touchscreen_data->current_slot = abs_info.value;
Oct 1, 2016
Oct 1, 2016
732
SDL_free(mt_req_code);
Oct 1, 2016
Oct 1, 2016
733
734
#endif /* EVIOCGMTSLOTS */
735
736
737
738
}
#if SDL_USE_LIBUDEV
static int
Oct 1, 2016
Oct 1, 2016
739
SDL_EVDEV_device_added(const char *dev_path, int udev_class)
Oct 1, 2016
Oct 1, 2016
741
int ret;
742
743
744
745
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
746
if (SDL_strcmp(dev_path, item->path) == 0) {
747
748
749
750
751
752
753
754
755
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
756
item->fd = open(dev_path, O_RDONLY | O_NONBLOCK);
757
758
if (item->fd < 0) {
SDL_free(item);
Oct 1, 2016
Oct 1, 2016
759
return SDL_SetError("Unable to open %s", dev_path);
Oct 1, 2016
Oct 1, 2016
762
item->path = SDL_strdup(dev_path);
763
764
765
766
767
768
if (item->path == NULL) {
close(item->fd);
SDL_free(item);
return SDL_OutOfMemory();
}
Oct 1, 2016
Oct 1, 2016
769
if (udev_class & SDL_UDEV_DEVICE_TOUCHSCREEN) {
Oct 1, 2016
Oct 1, 2016
770
771
item->is_touchscreen = 1;
Oct 1, 2016
Oct 1, 2016
772
if ((ret = SDL_EVDEV_init_touchscreen(item)) < 0) {
Oct 1, 2016
Oct 1, 2016
773
774
775
776
777
close(item->fd);
SDL_free(item);
return ret;
}
}
778
779
780
781
782
783
784
785
786
787
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
788
return _this->num_devices++;
789
790
791
792
}
#endif /* SDL_USE_LIBUDEV */
static int
Oct 1, 2016
Oct 1, 2016
793
SDL_EVDEV_device_removed(const char *dev_path)
794
795
796
797
798
799
{
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
800
if (SDL_strcmp(dev_path, item->path) == 0) {
801
802
803
804
805
806
807
808
809
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
810
811
if (item->is_touchscreen) {
SDL_EVDEV_destroy_touchscreen(item);
Oct 1, 2016
Oct 1, 2016
812
}
813
814
815
close(item->fd);
SDL_free(item->path);
SDL_free(item);
Oct 1, 2016
Oct 1, 2016
816
_this->num_devices--;
817
818
819
820
821
822
823
824
825
826
827
828
return 0;
}
prev = item;
}
return -1;
}
#endif /* SDL_INPUT_LINUXEV */
/* vi: set ts=4 sw=4 expandtab: */