Skip to content

Latest commit

 

History

History
761 lines (664 loc) · 26.8 KB

SDL_evdev.c

File metadata and controls

761 lines (664 loc) · 26.8 KB
 
1
2
/*
Simple DirectMedia Layer
Jan 5, 2019
Jan 5, 2019
3
Copyright (C) 1997-2019 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
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"
Jan 9, 2017
Jan 9, 2017
33
#include "SDL_evdev_kbd.h"
34
35
36
37
38
39
40
41
42
43
44
45
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/input.h>
#include "SDL.h"
#include "SDL_assert.h"
#include "SDL_endian.h"
#include "SDL_scancode.h"
#include "../../events/SDL_events_c.h"
Oct 1, 2016
Oct 1, 2016
46
#include "../../events/scancodes_linux.h" /* adds linux_scancode_table */
Jan 9, 2017
Jan 9, 2017
47
#include "../../core/linux/SDL_udev.h"
Jan 8, 2017
Jan 8, 2017
49
/* These are not defined in older Linux kernel headers */
50
51
52
#ifndef SYN_DROPPED
#define SYN_DROPPED 3
#endif
Nov 1, 2016
Nov 1, 2016
53
54
55
56
57
#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
Jan 15, 2019
Jan 15, 2019
58
#define ABS_MT_PRESSURE 0x3a
Nov 1, 2016
Nov 1, 2016
59
60
#endif
Oct 1, 2016
Oct 1, 2016
61
62
63
64
typedef struct SDL_evdevlist_item
{
char *path;
int fd;
Jan 9, 2017
Jan 9, 2017
65
Oct 1, 2016
Oct 1, 2016
66
67
/* TODO: use this for every device, not just touchscreen */
int out_of_sync;
Jan 9, 2017
Jan 9, 2017
68
Oct 1, 2016
Oct 1, 2016
69
70
71
72
73
74
/* 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;
Jan 9, 2017
Jan 9, 2017
75
Oct 1, 2016
Oct 1, 2016
76
77
int min_x, max_x, range_x;
int min_y, max_y, range_y;
Jan 15, 2019
Jan 15, 2019
78
int min_pressure, max_pressure, range_pressure;
Jan 9, 2017
Jan 9, 2017
79
Oct 1, 2016
Oct 1, 2016
80
81
82
83
84
85
86
87
88
89
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;
Jan 15, 2019
Jan 15, 2019
90
int x, y, pressure;
Oct 1, 2016
Oct 1, 2016
91
} * slots;
Jan 15, 2019
Jan 15, 2019
92
Oct 1, 2016
Oct 1, 2016
93
} * touchscreen_data;
Jan 9, 2017
Jan 9, 2017
94
Oct 1, 2016
Oct 1, 2016
95
96
97
98
99
struct SDL_evdevlist_item *next;
} SDL_evdevlist_item;
typedef struct SDL_EVDEV_PrivateData
{
Jan 9, 2017
Jan 9, 2017
100
101
int ref_count;
int num_devices;
Oct 1, 2016
Oct 1, 2016
102
103
SDL_evdevlist_item *first;
SDL_evdevlist_item *last;
Jan 9, 2017
Jan 9, 2017
104
SDL_EVDEV_keyboard_state *kbd;
Oct 1, 2016
Oct 1, 2016
105
106
} SDL_EVDEV_PrivateData;
Aug 29, 2018
Aug 29, 2018
107
#undef _THIS
Oct 1, 2016
Oct 1, 2016
108
109
110
#define _THIS SDL_EVDEV_PrivateData *_this
static _THIS = NULL;
111
112
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
113
static int SDL_EVDEV_device_removed(const char *dev_path);
114
115
#if SDL_USE_LIBUDEV
Oct 1, 2016
Oct 1, 2016
116
static int SDL_EVDEV_device_added(const char *dev_path, int udev_class);
Jun 11, 2017
Jun 11, 2017
117
static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class,
Oct 1, 2016
Oct 1, 2016
118
const char *dev_path);
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#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 */
};
int
SDL_EVDEV_Init(void)
{
Oct 1, 2016
Oct 1, 2016
135
136
137
if (_this == NULL) {
_this = (SDL_EVDEV_PrivateData*)SDL_calloc(1, sizeof(*_this));
if (_this == NULL) {
138
139
140
141
return SDL_OutOfMemory();
}
#if SDL_USE_LIBUDEV
Oct 1, 2016
Oct 1, 2016
142
143
if (SDL_UDEV_Init() < 0) {
SDL_free(_this);
144
145
146
147
148
_this = NULL;
return -1;
}
/* Set up the udev callback */
Jun 25, 2015
Jun 25, 2015
149
if (SDL_UDEV_AddCallback(SDL_EVDEV_udev_callback) < 0) {
Oct 1, 2016
Oct 1, 2016
150
SDL_UDEV_Quit();
Oct 1, 2016
Oct 1, 2016
151
SDL_free(_this);
Oct 1, 2016
Oct 1, 2016
152
_this = NULL;
Jan 9, 2017
Jan 9, 2017
155
156
157
158
159
160
/* 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 8, 2017
Jan 8, 2017
161
Jan 9, 2017
Jan 9, 2017
162
_this->kbd = SDL_EVDEV_kbd_init();
Jan 9, 2017
Jan 9, 2017
164
165
_this->ref_count += 1;
Jan 9, 2017
Jan 9, 2017
166
Oct 1, 2016
Oct 1, 2016
167
return 0;
168
169
170
171
172
}
void
SDL_EVDEV_Quit(void)
{
Oct 1, 2016
Oct 1, 2016
173
if (_this == NULL) {
Jan 9, 2017
Jan 9, 2017
176
177
_this->ref_count -= 1;
Jan 9, 2017
Jan 9, 2017
178
Oct 1, 2016
Oct 1, 2016
179
if (_this->ref_count < 1) {
Oct 1, 2016
Oct 1, 2016
181
SDL_UDEV_DelCallback(SDL_EVDEV_udev_callback);
182
183
SDL_UDEV_Quit();
#endif /* SDL_USE_LIBUDEV */
Jan 9, 2017
Jan 9, 2017
184
185
186
SDL_EVDEV_kbd_quit(_this->kbd);
187
188
/* Remove existing devices */
while(_this->first != NULL) {
Oct 1, 2016
Oct 1, 2016
189
SDL_EVDEV_device_removed(_this->first->path);
Jan 9, 2017
Jan 9, 2017
191
Oct 1, 2016
Oct 1, 2016
192
193
194
SDL_assert(_this->first == NULL);
SDL_assert(_this->last == NULL);
SDL_assert(_this->num_devices == 0);
Jan 9, 2017
Jan 9, 2017
195
Oct 1, 2016
Oct 1, 2016
196
SDL_free(_this);
197
198
199
200
201
_this = NULL;
}
}
#if SDL_USE_LIBUDEV
Jun 11, 2017
Jun 11, 2017
202
static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_class,
Oct 1, 2016
Oct 1, 2016
203
const char* dev_path)
Oct 1, 2016
Oct 1, 2016
205
if (dev_path == NULL) {
Jan 9, 2017
Jan 9, 2017
208
Oct 1, 2016
Oct 1, 2016
209
switch(udev_event) {
210
case SDL_UDEV_DEVICEADDED:
Oct 1, 2016
Oct 1, 2016
211
212
if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_KEYBOARD |
SDL_UDEV_DEVICE_TOUCHSCREEN)))
Jun 25, 2015
Jun 25, 2015
213
return;
Oct 1, 2016
Oct 1, 2016
214
Oct 1, 2016
Oct 1, 2016
215
SDL_EVDEV_device_added(dev_path, udev_class);
Oct 1, 2016
Oct 1, 2016
216
break;
217
case SDL_UDEV_DEVICEREMOVED:
Oct 1, 2016
Oct 1, 2016
218
SDL_EVDEV_device_removed(dev_path);
219
220
221
222
223
224
225
226
227
228
229
break;
default:
break;
}
}
#endif /* SDL_USE_LIBUDEV */
void
SDL_EVDEV_Poll(void)
{
struct input_event events[32];
Oct 1, 2016
Oct 1, 2016
230
int i, j, len;
231
232
233
234
SDL_evdevlist_item *item;
SDL_Scancode scan_code;
int mouse_button;
SDL_Mouse *mouse;
Jan 15, 2019
Jan 15, 2019
235
float norm_x, norm_y, norm_pressure;
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
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
251
252
/* special handling for touchscreen, that should eventually be
used for all devices */
Oct 1, 2016
Oct 1, 2016
253
254
if (item->out_of_sync && item->is_touchscreen &&
events[i].type == EV_SYN && events[i].code != SYN_REPORT) {
Oct 1, 2016
Oct 1, 2016
255
256
break;
}
Jan 9, 2017
Jan 9, 2017
257
258
259
260
261
262
263
264
265
266
267
268
269
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;
}
Jan 15, 2019
Jan 15, 2019
270
271
272
/* BTH_TOUCH event value 1 indicates there is contact with
a touchscreen or trackpad (earlist finger's current
position is sent in EV_ABS ABS_X/ABS_Y, switching to
Apr 4, 2019
Apr 4, 2019
273
next finger after earlist is released) */
Jan 15, 2019
Jan 15, 2019
274
275
276
277
if (item->is_touchscreen && events[i].code == BTN_TOUCH) {
break;
}
278
279
280
281
282
/* 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
283
} else if (events[i].value == 1 || events[i].value == 2 /* key repeated */) {
284
285
286
SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
}
}
Jan 9, 2017
Jan 9, 2017
287
SDL_EVDEV_kbd_keycode(_this->kbd, events[i].code, events[i].value);
288
289
290
break;
case EV_ABS:
switch(events[i].code) {
Oct 1, 2016
Oct 1, 2016
291
case ABS_MT_SLOT:
Oct 1, 2016
Oct 1, 2016
292
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
293
294
295
296
break;
item->touchscreen_data->current_slot = events[i].value;
break;
case ABS_MT_TRACKING_ID:
Oct 1, 2016
Oct 1, 2016
297
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
298
break;
Oct 1, 2016
Oct 1, 2016
299
if (events[i].value >= 0) {
Oct 1, 2016
Oct 1, 2016
300
301
302
303
304
305
306
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
307
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
308
309
break;
item->touchscreen_data->slots[item->touchscreen_data->current_slot].x = events[i].value;
Oct 1, 2016
Oct 1, 2016
310
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
Oct 1, 2016
Oct 1, 2016
311
312
313
314
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
315
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
316
317
break;
item->touchscreen_data->slots[item->touchscreen_data->current_slot].y = events[i].value;
Oct 1, 2016
Oct 1, 2016
318
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
Oct 1, 2016
Oct 1, 2016
319
320
321
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
}
break;
Jan 15, 2019
Jan 15, 2019
322
323
324
325
326
327
328
329
case ABS_MT_PRESSURE:
if (!item->is_touchscreen) /* FIXME: temp hack */
break;
item->touchscreen_data->slots[item->touchscreen_data->current_slot].pressure = events[i].value;
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
}
break;
Oct 1, 2016
Oct 1, 2016
331
if (item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
332
break;
333
334
335
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
break;
case ABS_Y:
Oct 1, 2016
Oct 1, 2016
336
if (item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
337
break;
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
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
364
case SYN_REPORT:
Oct 1, 2016
Oct 1, 2016
365
if (!item->is_touchscreen) /* FIXME: temp hack */
Oct 1, 2016
Oct 1, 2016
366
break;
Jan 9, 2017
Jan 9, 2017
367
Oct 1, 2016
Oct 1, 2016
368
for(j = 0; j < item->touchscreen_data->max_slots; j++) {
Oct 1, 2016
Oct 1, 2016
369
370
371
372
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;
Jan 9, 2017
Jan 9, 2017
373
Jan 15, 2019
Jan 15, 2019
374
375
376
377
378
379
380
381
if (item->touchscreen_data->range_pressure > 0) {
norm_pressure = (float)(item->touchscreen_data->slots[j].pressure - item->touchscreen_data->min_pressure) /
(float)item->touchscreen_data->range_pressure;
} else {
/* This touchscreen does not support pressure */
norm_pressure = 1.0f;
}
Oct 1, 2016
Oct 1, 2016
382
switch(item->touchscreen_data->slots[j].delta) {
Oct 1, 2016
Oct 1, 2016
383
case EVDEV_TOUCH_SLOTDELTA_DOWN:
Jan 15, 2019
Jan 15, 2019
384
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_TRUE, norm_x, norm_y, norm_pressure);
Oct 1, 2016
Oct 1, 2016
385
386
387
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
break;
case EVDEV_TOUCH_SLOTDELTA_UP:
Jan 15, 2019
Jan 15, 2019
388
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_FALSE, norm_x, norm_y, norm_pressure);
Oct 1, 2016
Oct 1, 2016
389
390
391
392
item->touchscreen_data->slots[j].tracking_id = -1;
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
break;
case EVDEV_TOUCH_SLOTDELTA_MOVE:
Jan 15, 2019
Jan 15, 2019
393
SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, norm_x, norm_y, norm_pressure);
Oct 1, 2016
Oct 1, 2016
394
395
396
397
398
399
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
break;
default:
break;
}
}
Jan 9, 2017
Jan 9, 2017
400
Oct 1, 2016
Oct 1, 2016
401
if (item->out_of_sync)
Oct 1, 2016
Oct 1, 2016
402
403
item->out_of_sync = 0;
break;
Oct 1, 2016
Oct 1, 2016
405
if (item->is_touchscreen)
Oct 1, 2016
Oct 1, 2016
406
item->out_of_sync = 1;
407
408
409
410
411
412
413
414
415
416
417
418
419
SDL_EVDEV_sync_device(item);
break;
default:
break;
}
break;
}
}
}
}
}
static SDL_Scancode
Oct 1, 2016
Oct 1, 2016
420
SDL_EVDEV_translate_keycode(int keycode)
421
422
423
{
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
Oct 1, 2016
Oct 1, 2016
424
if (keycode < SDL_arraysize(linux_scancode_table))
Oct 1, 2016
Oct 1, 2016
425
426
scancode = linux_scancode_table[keycode];
Oct 1, 2016
Oct 1, 2016
427
if (scancode == SDL_SCANCODE_UNKNOWN) {
Jan 15, 2019
Jan 15, 2019
428
429
430
431
432
433
434
435
436
/* BTN_TOUCH is handled elsewhere, but we might still end up here if
you get an unexpected BTN_TOUCH from something SDL believes is not
a touch device. In this case, we'd rather not get a misleading
SDL_Log message about an unknown key. */
if (keycode != BTN_TOUCH) {
SDL_Log("The key you just pressed is not recognized by SDL. To help "
"get this fixed, please report this to the SDL forums/mailing list "
"<https://discourse.libsdl.org/> EVDEV KeyCode %d", keycode);
}
Oct 1, 2016
Oct 1, 2016
438
439
440
441
return scancode;
}
Oct 1, 2016
Oct 1, 2016
442
#ifdef SDL_USE_LIBUDEV
Oct 1, 2016
Oct 1, 2016
443
static int
Oct 1, 2016
Oct 1, 2016
444
445
SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
{
Oct 1, 2016
Oct 1, 2016
446
447
448
int ret, i;
char name[64];
struct input_absinfo abs_info;
Jan 9, 2017
Jan 9, 2017
449
Oct 1, 2016
Oct 1, 2016
450
if (!item->is_touchscreen)
Oct 1, 2016
Oct 1, 2016
451
return 0;
Jan 9, 2017
Jan 9, 2017
452
Oct 1, 2016
Oct 1, 2016
453
454
item->touchscreen_data = SDL_calloc(1, sizeof(*item->touchscreen_data));
if (item->touchscreen_data == NULL)
Oct 1, 2016
Oct 1, 2016
455
return SDL_OutOfMemory();
Jan 9, 2017
Jan 9, 2017
456
Oct 1, 2016
Oct 1, 2016
457
458
459
460
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
461
}
Jan 9, 2017
Jan 9, 2017
462
Oct 1, 2016
Oct 1, 2016
463
464
465
item->touchscreen_data->name = SDL_strdup(name);
if (item->touchscreen_data->name == NULL) {
SDL_free(item->touchscreen_data);
Oct 1, 2016
Oct 1, 2016
466
467
return SDL_OutOfMemory();
}
Jan 9, 2017
Jan 9, 2017
468
Oct 1, 2016
Oct 1, 2016
469
470
471
472
473
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
474
475
476
477
}
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;
Jan 9, 2017
Jan 9, 2017
478
Oct 1, 2016
Oct 1, 2016
479
480
481
482
483
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
484
485
486
487
}
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;
Jan 9, 2017
Jan 9, 2017
488
Jan 15, 2019
Jan 15, 2019
489
490
491
492
493
494
495
496
497
498
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_PRESSURE), &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");
}
item->touchscreen_data->min_pressure = abs_info.minimum;
item->touchscreen_data->max_pressure = abs_info.maximum;
item->touchscreen_data->range_pressure = abs_info.maximum - abs_info.minimum;
Oct 1, 2016
Oct 1, 2016
499
500
501
502
503
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
504
505
}
item->touchscreen_data->max_slots = abs_info.maximum + 1;
Jan 9, 2017
Jan 9, 2017
506
Oct 1, 2016
Oct 1, 2016
507
508
item->touchscreen_data->slots = SDL_calloc(
item->touchscreen_data->max_slots,
Oct 1, 2016
Oct 1, 2016
509
510
511
512
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
513
514
return SDL_OutOfMemory();
}
Jan 9, 2017
Jan 9, 2017
515
Oct 1, 2016
Oct 1, 2016
516
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
Oct 1, 2016
Oct 1, 2016
517
518
item->touchscreen_data->slots[i].tracking_id = -1;
}
Jan 9, 2017
Jan 9, 2017
519
Oct 1, 2016
Oct 1, 2016
520
ret = SDL_AddTouch(item->fd, /* I guess our fd is unique enough */
Nov 10, 2018
Nov 10, 2018
521
SDL_TOUCH_DEVICE_DIRECT,
Oct 1, 2016
Oct 1, 2016
522
523
524
525
526
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
527
528
return ret;
}
Jan 9, 2017
Jan 9, 2017
529
Oct 1, 2016
Oct 1, 2016
530
531
return 0;
}
Oct 1, 2016
Oct 1, 2016
532
#endif /* SDL_USE_LIBUDEV */
Oct 1, 2016
Oct 1, 2016
533
534
static void
Oct 1, 2016
Oct 1, 2016
535
536
SDL_EVDEV_destroy_touchscreen(SDL_evdevlist_item* item) {
if (!item->is_touchscreen)
Oct 1, 2016
Oct 1, 2016
537
return;
Jan 9, 2017
Jan 9, 2017
538
Oct 1, 2016
Oct 1, 2016
539
540
541
542
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
543
544
}
545
546
547
static void
SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
{
Oct 1, 2016
Oct 1, 2016
548
#ifdef EVIOCGMTSLOTS
Oct 1, 2016
Oct 1, 2016
549
550
551
552
553
554
555
556
557
558
559
560
561
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;
Jan 9, 2017
Jan 9, 2017
562
Oct 1, 2016
Oct 1, 2016
563
/* TODO: sync devices other than touchscreen */
Oct 1, 2016
Oct 1, 2016
564
if (!item->is_touchscreen)
Oct 1, 2016
Oct 1, 2016
565
return;
Jan 9, 2017
Jan 9, 2017
566
Oct 1, 2016
Oct 1, 2016
567
568
mt_req_size = sizeof(*mt_req_code) +
sizeof(*mt_req_values) * item->touchscreen_data->max_slots;
Jan 9, 2017
Jan 9, 2017
569
Oct 1, 2016
Oct 1, 2016
570
571
mt_req_code = SDL_calloc(1, mt_req_size);
if (mt_req_code == NULL) {
Oct 1, 2016
Oct 1, 2016
572
573
return;
}
Jan 9, 2017
Jan 9, 2017
574
Oct 1, 2016
Oct 1, 2016
575
mt_req_values = (__s32*)mt_req_code + 1;
Jan 9, 2017
Jan 9, 2017
576
Oct 1, 2016
Oct 1, 2016
577
*mt_req_code = ABS_MT_TRACKING_ID;
Oct 1, 2016
Oct 1, 2016
578
579
580
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
581
582
return;
}
Oct 1, 2016
Oct 1, 2016
583
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
Oct 1, 2016
Oct 1, 2016
584
585
586
587
588
589
590
591
592
/*
* 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
593
594
if (item->touchscreen_data->slots[i].tracking_id < 0 &&
mt_req_values[i] >= 0) {
Oct 1, 2016
Oct 1, 2016
595
596
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
597
598
} else if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
mt_req_values[i] < 0) {
Oct 1, 2016
Oct 1, 2016
599
600
601
602
item->touchscreen_data->slots[i].tracking_id = -1;
item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_UP;
}
}
Jan 9, 2017
Jan 9, 2017
603
Oct 1, 2016
Oct 1, 2016
604
*mt_req_code = ABS_MT_POSITION_X;
Oct 1, 2016
Oct 1, 2016
605
606
607
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
608
609
return;
}
Oct 1, 2016
Oct 1, 2016
610
611
612
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
613
item->touchscreen_data->slots[i].x = mt_req_values[i];
Oct 1, 2016
Oct 1, 2016
614
615
if (item->touchscreen_data->slots[i].delta ==
EVDEV_TOUCH_SLOTDELTA_NONE) {
Oct 1, 2016
Oct 1, 2016
616
617
618
619
620
item->touchscreen_data->slots[i].delta =
EVDEV_TOUCH_SLOTDELTA_MOVE;
}
}
}
Jan 9, 2017
Jan 9, 2017
621
Oct 1, 2016
Oct 1, 2016
622
*mt_req_code = ABS_MT_POSITION_Y;
Oct 1, 2016
Oct 1, 2016
623
624
625
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
626
627
return;
}
Oct 1, 2016
Oct 1, 2016
628
629
630
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
631
item->touchscreen_data->slots[i].y = mt_req_values[i];
Oct 1, 2016
Oct 1, 2016
632
633
if (item->touchscreen_data->slots[i].delta ==
EVDEV_TOUCH_SLOTDELTA_NONE) {
Oct 1, 2016
Oct 1, 2016
634
635
636
637
638
item->touchscreen_data->slots[i].delta =
EVDEV_TOUCH_SLOTDELTA_MOVE;
}
}
}
Jan 9, 2017
Jan 9, 2017
639
Jan 15, 2019
Jan 15, 2019
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
*mt_req_code = ABS_MT_PRESSURE;
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
if (ret < 0) {
SDL_free(mt_req_code);
return;
}
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
item->touchscreen_data->slots[i].pressure != mt_req_values[i]) {
item->touchscreen_data->slots[i].pressure = mt_req_values[i];
if (item->touchscreen_data->slots[i].delta ==
EVDEV_TOUCH_SLOTDELTA_NONE) {
item->touchscreen_data->slots[i].delta =
EVDEV_TOUCH_SLOTDELTA_MOVE;
}
}
}
Oct 1, 2016
Oct 1, 2016
658
659
660
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
if (ret < 0) {
SDL_free(mt_req_code);
Oct 1, 2016
Oct 1, 2016
661
662
663
return;
}
item->touchscreen_data->current_slot = abs_info.value;
Jan 9, 2017
Jan 9, 2017
664
Oct 1, 2016
Oct 1, 2016
665
SDL_free(mt_req_code);
Oct 1, 2016
Oct 1, 2016
666
667
#endif /* EVIOCGMTSLOTS */
668
669
670
671
}
#if SDL_USE_LIBUDEV
static int
Oct 1, 2016
Oct 1, 2016
672
SDL_EVDEV_device_added(const char *dev_path, int udev_class)
Oct 1, 2016
Oct 1, 2016
674
int ret;
675
676
677
678
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
679
if (SDL_strcmp(dev_path, item->path) == 0) {
680
681
682
return -1; /* already have this one */
}
}
Jan 9, 2017
Jan 9, 2017
683
684
685
686
687
688
item = (SDL_evdevlist_item *) SDL_calloc(1, sizeof (SDL_evdevlist_item));
if (item == NULL) {
return SDL_OutOfMemory();
}
Oct 1, 2016
Oct 1, 2016
689
item->fd = open(dev_path, O_RDONLY | O_NONBLOCK);
690
691
if (item->fd < 0) {
SDL_free(item);
Oct 1, 2016
Oct 1, 2016
692
return SDL_SetError("Unable to open %s", dev_path);
Jan 9, 2017
Jan 9, 2017
694
Oct 1, 2016
Oct 1, 2016
695
item->path = SDL_strdup(dev_path);
696
697
698
699
700
if (item->path == NULL) {
close(item->fd);
SDL_free(item);
return SDL_OutOfMemory();
}
Jan 9, 2017
Jan 9, 2017
701
Oct 1, 2016
Oct 1, 2016
702
if (udev_class & SDL_UDEV_DEVICE_TOUCHSCREEN) {
Oct 1, 2016
Oct 1, 2016
703
item->is_touchscreen = 1;
Jan 9, 2017
Jan 9, 2017
704
Oct 1, 2016
Oct 1, 2016
705
if ((ret = SDL_EVDEV_init_touchscreen(item)) < 0) {
Oct 1, 2016
Oct 1, 2016
706
707
708
709
710
close(item->fd);
SDL_free(item);
return ret;
}
}
Jan 9, 2017
Jan 9, 2017
711
712
713
714
715
716
717
if (_this->last == NULL) {
_this->first = _this->last = item;
} else {
_this->last->next = item;
_this->last = item;
}
Jan 9, 2017
Jan 9, 2017
718
719
SDL_EVDEV_sync_device(item);
Jan 9, 2017
Jan 9, 2017
720
Oct 1, 2016
Oct 1, 2016
721
return _this->num_devices++;
722
723
724
725
}
#endif /* SDL_USE_LIBUDEV */
static int
Oct 1, 2016
Oct 1, 2016
726
SDL_EVDEV_device_removed(const char *dev_path)
727
728
729
730
731
732
{
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
733
if (SDL_strcmp(dev_path, item->path) == 0) {
734
735
736
737
738
739
740
741
742
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
743
744
if (item->is_touchscreen) {
SDL_EVDEV_destroy_touchscreen(item);
Oct 1, 2016
Oct 1, 2016
745
}
746
747
748
close(item->fd);
SDL_free(item->path);
SDL_free(item);
Oct 1, 2016
Oct 1, 2016
749
_this->num_devices--;
750
751
752
753
754
755
756
757
758
759
760
761
return 0;
}
prev = item;
}
return -1;
}
#endif /* SDL_INPUT_LINUXEV */
/* vi: set ts=4 sw=4 expandtab: */