/
SDL_evdev.c
761 lines (664 loc) · 26.8 KB
1
2
/*
Simple DirectMedia Layer
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"
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"
46
#include "../../events/scancodes_linux.h" /* adds linux_scancode_table */
47
#include "../../core/linux/SDL_udev.h"
48
49
/* These are not defined in older Linux kernel headers */
50
51
52
#ifndef SYN_DROPPED
#define SYN_DROPPED 3
#endif
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
58
#define ABS_MT_PRESSURE 0x3a
59
60
#endif
61
62
63
64
typedef struct SDL_evdevlist_item
{
char *path;
int fd;
65
66
67
/* TODO: use this for every device, not just touchscreen */
int out_of_sync;
68
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;
75
76
77
int min_x, max_x, range_x;
int min_y, max_y, range_y;
78
int min_pressure, max_pressure, range_pressure;
79
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;
90
int x, y, pressure;
91
} * slots;
92
93
} * touchscreen_data;
94
95
96
97
98
99
struct SDL_evdevlist_item *next;
} SDL_evdevlist_item;
typedef struct SDL_EVDEV_PrivateData
{
100
101
int ref_count;
int num_devices;
102
103
SDL_evdevlist_item *first;
SDL_evdevlist_item *last;
104
SDL_EVDEV_keyboard_state *kbd;
105
106
} SDL_EVDEV_PrivateData;
107
#undef _THIS
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);
113
static int SDL_EVDEV_device_removed(const char *dev_path);
114
115
#if SDL_USE_LIBUDEV
116
static int SDL_EVDEV_device_added(const char *dev_path, int udev_class);
117
static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class,
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)
{
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
142
143
if (SDL_UDEV_Init() < 0) {
SDL_free(_this);
144
145
146
147
148
_this = NULL;
return -1;
}
/* Set up the udev callback */
149
if (SDL_UDEV_AddCallback(SDL_EVDEV_udev_callback) < 0) {
150
SDL_UDEV_Quit();
151
SDL_free(_this);
152
_this = NULL;
153
154
return -1;
}
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 */
161
162
_this->kbd = SDL_EVDEV_kbd_init();
163
}
164
165
_this->ref_count += 1;
166
167
return 0;
168
169
170
171
172
}
void
SDL_EVDEV_Quit(void)
{
173
if (_this == NULL) {
174
175
return;
}
176
177
_this->ref_count -= 1;
178
179
if (_this->ref_count < 1) {
180
#if SDL_USE_LIBUDEV
181
SDL_UDEV_DelCallback(SDL_EVDEV_udev_callback);
182
183
SDL_UDEV_Quit();
#endif /* SDL_USE_LIBUDEV */
184
185
186
SDL_EVDEV_kbd_quit(_this->kbd);
187
188
/* Remove existing devices */
while(_this->first != NULL) {
189
SDL_EVDEV_device_removed(_this->first->path);
190
}
191
192
193
194
SDL_assert(_this->first == NULL);
SDL_assert(_this->last == NULL);
SDL_assert(_this->num_devices == 0);
195
196
SDL_free(_this);
197
198
199
200
201
_this = NULL;
}
}
#if SDL_USE_LIBUDEV
202
static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_class,
203
const char* dev_path)
204
{
205
if (dev_path == NULL) {
206
207
return;
}
208
209
switch(udev_event) {
210
case SDL_UDEV_DEVICEADDED:
211
212
if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_KEYBOARD |
SDL_UDEV_DEVICE_TOUCHSCREEN)))
213
return;
214
215
SDL_EVDEV_device_added(dev_path, udev_class);
216
break;
217
case SDL_UDEV_DEVICEREMOVED:
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];
230
int i, j, len;
231
232
233
234
SDL_evdevlist_item *item;
SDL_Scancode scan_code;
int mouse_button;
SDL_Mouse *mouse;
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) {
251
252
/* special handling for touchscreen, that should eventually be
used for all devices */
253
254
if (item->out_of_sync && item->is_touchscreen &&
events[i].type == EV_SYN && events[i].code != SYN_REPORT) {
255
256
break;
}
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;
}
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
273
next finger after earlist is released) */
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);
283
} else if (events[i].value == 1 || events[i].value == 2 /* key repeated */) {
284
285
286
SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
}
}
287
SDL_EVDEV_kbd_keycode(_this->kbd, events[i].code, events[i].value);
288
289
290
break;
case EV_ABS:
switch(events[i].code) {
291
case ABS_MT_SLOT:
292
if (!item->is_touchscreen) /* FIXME: temp hack */
293
294
295
296
break;
item->touchscreen_data->current_slot = events[i].value;
break;
case ABS_MT_TRACKING_ID:
297
if (!item->is_touchscreen) /* FIXME: temp hack */
298
break;
299
if (events[i].value >= 0) {
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:
307
if (!item->is_touchscreen) /* FIXME: temp hack */
308
309
break;
item->touchscreen_data->slots[item->touchscreen_data->current_slot].x = events[i].value;
310
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
311
312
313
314
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
}
break;
case ABS_MT_POSITION_Y:
315
if (!item->is_touchscreen) /* FIXME: temp hack */
316
317
break;
item->touchscreen_data->slots[item->touchscreen_data->current_slot].y = events[i].value;
318
if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
319
320
321
item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
}
break;
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;
330
case ABS_X:
331
if (item->is_touchscreen) /* FIXME: temp hack */
332
break;
333
334
335
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
break;
case ABS_Y:
336
if (item->is_touchscreen) /* FIXME: temp hack */
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) {
364
case SYN_REPORT:
365
if (!item->is_touchscreen) /* FIXME: temp hack */
366
break;
367
368
for(j = 0; j < item->touchscreen_data->max_slots; j++) {
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;
373
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;
}
382
switch(item->touchscreen_data->slots[j].delta) {
383
case EVDEV_TOUCH_SLOTDELTA_DOWN:
384
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_TRUE, norm_x, norm_y, norm_pressure);
385
386
387
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
break;
case EVDEV_TOUCH_SLOTDELTA_UP:
388
SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_FALSE, norm_x, norm_y, norm_pressure);
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:
393
SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, norm_x, norm_y, norm_pressure);
394
395
396
397
398
399
item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
break;
default:
break;
}
}
400
401
if (item->out_of_sync)
402
403
item->out_of_sync = 0;
break;
404
case SYN_DROPPED:
405
if (item->is_touchscreen)
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
420
SDL_EVDEV_translate_keycode(int keycode)
421
422
423
{
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
424
if (keycode < SDL_arraysize(linux_scancode_table))
425
426
scancode = linux_scancode_table[keycode];
427
if (scancode == SDL_SCANCODE_UNKNOWN) {
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);
}
437
}
438
439
440
441
return scancode;
}
442
#ifdef SDL_USE_LIBUDEV
443
static int
444
445
SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
{
446
447
448
int ret, i;
char name[64];
struct input_absinfo abs_info;
449
450
if (!item->is_touchscreen)
451
return 0;
452
453
454
item->touchscreen_data = SDL_calloc(1, sizeof(*item->touchscreen_data));
if (item->touchscreen_data == NULL)
455
return SDL_OutOfMemory();
456
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");
461
}
462
463
464
465
item->touchscreen_data->name = SDL_strdup(name);
if (item->touchscreen_data->name == NULL) {
SDL_free(item->touchscreen_data);
466
467
return SDL_OutOfMemory();
}
468
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");
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;
478
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");
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;
488
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;
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");
504
505
}
item->touchscreen_data->max_slots = abs_info.maximum + 1;
506
507
508
item->touchscreen_data->slots = SDL_calloc(
item->touchscreen_data->max_slots,
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);
513
514
return SDL_OutOfMemory();
}
515
516
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
517
518
item->touchscreen_data->slots[i].tracking_id = -1;
}
519
520
ret = SDL_AddTouch(item->fd, /* I guess our fd is unique enough */
521
SDL_TOUCH_DEVICE_DIRECT,
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);
527
528
return ret;
}
529
530
531
return 0;
}
532
#endif /* SDL_USE_LIBUDEV */
533
534
static void
535
536
SDL_EVDEV_destroy_touchscreen(SDL_evdevlist_item* item) {
if (!item->is_touchscreen)
537
return;
538
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);
543
544
}
545
546
547
static void
SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
{
548
#ifdef EVIOCGMTSLOTS
549
550
551
552
553
554
555
556
557
558
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
*/
559
560
Uint32* mt_req_code;
Sint32* mt_req_values;
561
size_t mt_req_size;
562
563
/* TODO: sync devices other than touchscreen */
564
if (!item->is_touchscreen)
565
return;
566
567
568
mt_req_size = sizeof(*mt_req_code) +
sizeof(*mt_req_values) * item->touchscreen_data->max_slots;
569
570
571
mt_req_code = SDL_calloc(1, mt_req_size);
if (mt_req_code == NULL) {
572
573
return;
}
574
575
mt_req_values = (Sint32*)mt_req_code + 1;
576
577
*mt_req_code = ABS_MT_TRACKING_ID;
578
579
580
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
if (ret < 0) {
SDL_free(mt_req_code);
581
582
return;
}
583
for(i = 0; i < item->touchscreen_data->max_slots; i++) {
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.
*/
593
594
if (item->touchscreen_data->slots[i].tracking_id < 0 &&
mt_req_values[i] >= 0) {
595
596
item->touchscreen_data->slots[i].tracking_id = mt_req_values[i];
item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
597
598
} else if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
mt_req_values[i] < 0) {
599
600
601
602
item->touchscreen_data->slots[i].tracking_id = -1;
item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_UP;
}
}
603
604
*mt_req_code = ABS_MT_POSITION_X;
605
606
607
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
if (ret < 0) {
SDL_free(mt_req_code);
608
609
return;
}
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]) {
613
item->touchscreen_data->slots[i].x = mt_req_values[i];
614
615
if (item->touchscreen_data->slots[i].delta ==
EVDEV_TOUCH_SLOTDELTA_NONE) {
616
617
618
619
620
item->touchscreen_data->slots[i].delta =
EVDEV_TOUCH_SLOTDELTA_MOVE;
}
}
}
621
622
*mt_req_code = ABS_MT_POSITION_Y;
623
624
625
ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
if (ret < 0) {
SDL_free(mt_req_code);
626
627
return;
}
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]) {
631
item->touchscreen_data->slots[i].y = mt_req_values[i];
632
633
if (item->touchscreen_data->slots[i].delta ==
EVDEV_TOUCH_SLOTDELTA_NONE) {
634
635
636
637
638
item->touchscreen_data->slots[i].delta =
EVDEV_TOUCH_SLOTDELTA_MOVE;
}
}
}
639
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;
}
}
}
658
659
660
ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
if (ret < 0) {
SDL_free(mt_req_code);
661
662
663
return;
}
item->touchscreen_data->current_slot = abs_info.value;
664
665
SDL_free(mt_req_code);
666
667
#endif /* EVIOCGMTSLOTS */
668
669
670
671
}
#if SDL_USE_LIBUDEV
static int
672
SDL_EVDEV_device_added(const char *dev_path, int udev_class)
673
{
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) {
679
if (SDL_strcmp(dev_path, item->path) == 0) {
680
681
682
return -1; /* already have this one */
}
}
683
684
685
686
687
688
item = (SDL_evdevlist_item *) SDL_calloc(1, sizeof (SDL_evdevlist_item));
if (item == NULL) {
return SDL_OutOfMemory();
}
689
item->fd = open(dev_path, O_RDONLY | O_NONBLOCK);
690
691
if (item->fd < 0) {
SDL_free(item);
692
return SDL_SetError("Unable to open %s", dev_path);
693
}
694
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();
}
701
702
if (udev_class & SDL_UDEV_DEVICE_TOUCHSCREEN) {
703
item->is_touchscreen = 1;
704
705
if ((ret = SDL_EVDEV_init_touchscreen(item)) < 0) {
706
707
708
709
710
close(item->fd);
SDL_free(item);
return ret;
}
}
711
712
713
714
715
716
717
if (_this->last == NULL) {
_this->first = _this->last = item;
} else {
_this->last->next = item;
_this->last = item;
}
718
719
SDL_EVDEV_sync_device(item);
720
721
return _this->num_devices++;
722
723
724
725
}
#endif /* SDL_USE_LIBUDEV */
static int
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. */
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;
}
743
744
if (item->is_touchscreen) {
SDL_EVDEV_destroy_touchscreen(item);
745
}
746
747
748
close(item->fd);
SDL_free(item->path);
SDL_free(item);
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: */