1 /*
2  * Copyright 2014-2020, Björn Ståhl
3  * License: 3-Clause BSD, see COPYING file in arcan source repository.
4  * Reference: http://arcan-fe.com
5  */
6 
7 #include <stdlib.h>
8 #include <stdint.h>
9 #include <stdbool.h>
10 #include <assert.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <inttypes.h>
15 #include <stdio.h>
16 #include <errno.h>
17 #include <poll.h>
18 #include <glob.h>
19 
20 #include <sys/types.h>
21 #include <sys/param.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 
25 #include <linux/input.h>
26 
27 #include "arcan_shmif.h"
28 #include "arcan_math.h"
29 #include "arcan_general.h"
30 #include "arcan_event.h"
31 #include "arcan_led.h"
32 #include "arcan_video.h"
33 #include "arcan_videoint.h"
34 #include "keycode_xlate.h"
35 
36 #ifndef __FreeBSD__
37 #include <sys/inotify.h>
38 #endif
39 
40 #ifdef HAVE_XKBCOMMON
41 #include <xkbcommon/xkbcommon.h>
42 #include <xkbcommon/xkbcommon-keysyms.h>
43 #include <xkbcommon/xkbcommon-compose.h>
44 /*
45  * shared between all event queues
46  */
47 static struct xkb_context* xkb_context;
48 #endif
49 
50 #ifdef _DEBUG
51 #define DEBUG 1
52 #else
53 #define DEBUG 0
54 #endif
55 
56 #define debug_print(fmt, ...) \
57             do { if (DEBUG) arcan_warning("[%lld]%s:%d:%s(): " fmt "\n", \
58 						arcan_timemillis(), "evdev:", __LINE__, __func__,##__VA_ARGS__); \
59 						} while (0)
60 
61 #define verbose_print
62 
63 /*
64  * scan / probe a node- dir (ENVV overridable)
65  */
66 #ifndef NOTIFY_SCAN_DIR
67 #define NOTIFY_SCAN_DIR "/dev/input"
68 #endif
69 
70 static char* notify_scan_dir;
71 
72 /*
73  * In happy-fun everything is user-space land, we face the policy problem of
74  * device nodes not being created with the desired permissions in an atomic
75  * manner. Combine with inotify and we may beat some deaemon to the races and
76  * there we go. For EACCES we go the 'retry a little later' route.
77  */
78 static const int default_eacces_tries = 8;
79 static const int default_eacces_delay = 1000;
80 
81 static struct {
82 	char* path;
83 	int tries;
84 	int64_t last_ts;
85 } pending[8];
86 
87 static struct {
88 	bool mute, init;
89 	int tty, notify;
90 	int pending;
91 }
92 gstate = {
93 
94 	.notify = -1,
95 };
96 
97 static const char* envopts[] = {
98 	"scandir=path/to/folder", "Directory to monitor for device node hotplug "
99 		"(Default: "NOTIFY_SCAN_DIR")",
100 	"disable_ttyswap", "Disable tty- swapping signal handler",
101 	"[evdev_type=label]", "suffix evdev_type with _n for (n = 2, 3, ...)",
102 	"evdev_keyboard=label", "Force device matching 'label' as a keyboard",
103 	"evdev_game=label", "Force device matching 'label' as a game device",
104 	"evdev_mouse=label", "Force device matching 'label' as a mouse",
105 #ifdef HAVE_XKBCOMMON
106 	"", "",
107 	"[XKB-ARGUMENTS]", "[these are ENV- only (fwd to libxkbcommon)]",
108 	"XKB_DEFAULT_LAYOUT=lang", "enable XKB translation maps for keyboards",
109 	"XKB_DEFAULT_VARIANT=variant", "define XKB layout variant",
110 	"XKB_DEFAULT_MODEL=pc101", "define XKB keyboard model",
111 #endif
112 	NULL
113 };
114 
115 /*
116  * need a reasonable limit on the amount of allowed devices, should this become
117  * a problem -- whitelist. See lookup_devnode for an explanation on the problem
118  * with devid-.
119  */
120 #define MAX_DEVICES 256
121 
122 struct devnode;
123 #include "device_db.h"
124 
125 struct axis_opts {
126 /* none, avg, drop */
127 	enum ARCAN_ANALOGFILTER_KIND mode;
128 	enum ARCAN_ANALOGFILTER_KIND oldmode;
129 
130 	int lower, upper, deadzone;
131 
132 /* we won't get access to a good range distribution if we don't emit the first
133  * / last sample that got into the drop range */
134 	bool inlzone, inuzone, indzone;
135 
136 	int kernel_sz;
137 	int kernel_ofs;
138 	int32_t flt_kernel[64];
139 };
140 
141 static struct {
142 	size_t n_devs, sz_nodes;
143 
144 /* repeat is currently enforced uniformly across all keyboards, might be
145  * usecases where this is not preferable but there is no higher-level api
146  * that provides this granularity. */
147 	unsigned period, delay;
148 
149 	unsigned short mouseid;
150 	struct devnode* nodes;
151 
152 	struct pollfd* pollset;
153 } iodev = {0};
154 
155 struct devnode {
156 	int handle;
157 
158 /* NULL&size terminated, with chain-block set of the previous one could not
159  * handle. This is to cover devices that could expose themselves as being
160  * aggregated KEY/DEV/etc. */
161 	struct evhandler hnd;
162 
163 	char label[256];
164 	char* path;
165 	unsigned short devnum;
166 	size_t button_count;
167 
168 	enum devnode_type type;
169 	union {
170 		struct {
171 			struct axis_opts data;
172 		} sensor;
173 		struct {
174 			unsigned short axes;
175 			unsigned short buttons;
176 			unsigned short relofs;
177 			char hats[16];
178 			struct axis_opts* adata;
179 		} game;
180 		struct {
181 			uint16_t mx;
182 			uint16_t my;
183 			struct axis_opts flt[2];
184 		} cursor;
185 		struct {
186 			unsigned state;
187 #ifdef HAVE_XKBCOMMON
188 			struct xkb_keymap* xkb_layout;
189 			struct xkb_state* xkb_state;
190 #endif
191 		} keyboard;
192 	};
193 /* because in this universe, pretty much any normal input device can
194  * also have a touch display. */
195 	struct {
196 		bool active;
197 		bool pending;
198 		int x;
199 		int y;
200 		int pressure;
201 		int size;
202 		int ind;
203 	} touch;
204 
205 /* and also possible act as a LED controller */
206 	struct {
207 		bool gotled;
208 		int ctrlid;
209 		int ind;
210 		int fds[2];
211 	} led;
212 };
213 
214 static void got_device(struct arcan_evctx* ctx, int fd, const char*);
215 
216 /* for other platforms and legacy, devid used to be allocated sequentially
217  * and swept linear, even though this platform do not work like that and we
218  * have a dynamic set of devices. For this reason, we split the 16 bit space
219  * into < MAX_DEVICES and >= MAX_DEVICES and a device a can be accessed by
220  * either id */
lookup_devnode(int devid)221 static struct devnode* lookup_devnode(int devid)
222 {
223 	if (devid <= 0)
224 		devid = iodev.mouseid;
225 
226 	if (devid < iodev.sz_nodes){
227 		verbose_print("lookup(%d) => %"PRIxPTR, devid, &iodev.nodes[devid]);
228 		return &iodev.nodes[devid];
229 	}
230 
231 	for (size_t i = 0; i < iodev.sz_nodes; i++){
232 		if (iodev.nodes[i].devnum == devid){
233 			verbose_print("lookup(%d:%zu) => %"PRIxPTR, devid, i, &iodev.nodes[i]);
234 			return &iodev.nodes[i];
235 		}
236 	}
237 
238 	verbose_print("%zu => %d", devid, -1);
239 	return NULL;
240 }
241 
242 /* another option to this mess (as the hashing thing doesn't seem to work out
243  * is to move identification/etc. to another level and just let whatever device
244  * node generator is active populate with coherent names. and use a hash of that
245  * name as the ID */
identify(int fd,const char * path,char * label,size_t label_sz,unsigned short * dnum)246 static bool identify(int fd, const char* path,
247 	char* label, size_t label_sz, unsigned short* dnum)
248 {
249 	if (-1 == ioctl(fd, EVIOCGNAME(label_sz), label)){
250 		debug_print("input/identify: bad EVIOCGNAME, setting unknown\n");
251 		snprintf(label, label_sz, "unknown");
252 	}
253 	else
254 		verbose_print(
255 			"input/identify(%d): %s name resolved to %s", fd, path, label);
256 
257 	struct input_id nodeid;
258 	if (-1 == ioctl(fd, EVIOCGID, &nodeid)){
259 		debug_print(
260 			"input/identify(%d): no EVIOCGID, reason:%s", fd, strerror(errno));
261 		return false;
262 	}
263 
264 /*
265  * first, check if any other subsystem knows about this one and ignore if so
266  */
267 	if (arcan_led_known(nodeid.vendor, nodeid.product)){
268 		debug_print(
269 			"led subsys know %d, %d\n", (int)nodeid.vendor, (int)nodeid.product);
270 		arcan_led_init();
271 		return false;
272 	}
273 
274 /* didn't find much on how unique eviocguniq actually was, nor common lengths
275  * or what not so just mix them in a buffer, hash and let unsigned overflow
276  * modulo take us down to 16bit */
277 	size_t bpl = sizeof(long) * 8;
278 	size_t nbits = ((EV_MAX)-1) / bpl + 1;
279 
280 	char buf[12 + nbits * sizeof(long)];
281 	char bbuf[sizeof(buf)];
282 	memset(buf, '\0', sizeof(buf));
283 	memset(bbuf, '\0', sizeof(bbuf));
284 
285 /* some test devices here answered to the ioctl and returned full empty UNIQs,
286  * do something to lower the likelihood of collisions */
287 	unsigned long hash = 5381;
288 
289 	if (-1 == ioctl(fd, EVIOCGUNIQ(sizeof(buf)), buf) ||
290 		memcmp(buf, bbuf, sizeof(buf)) == 0){
291 
292 		size_t llen = strlen(label);
293 		for (size_t i = 0; i < llen; i++)
294 			hash = ((hash << 5) + hash) + label[i];
295 
296 		llen = strlen(path);
297 		for (size_t i = 0; i < llen; i++)
298 			hash  = ((hash << 5) + hash) + path[i];
299 
300 		buf[11] ^= nodeid.vendor >> 8;
301 		buf[10] ^= nodeid.vendor;
302 		buf[9] ^= nodeid.product >> 8;
303 		buf[8] ^= nodeid.product;
304 		buf[7] ^= nodeid.version >> 8;
305 		buf[6] ^= nodeid.version;
306 
307 /* even this point has a few collisions, particularly some keyboards and mice
308  * that don't respond to CGUNIQ and expose multiple- subdevices but with
309  * different button/axis count */
310 		ioctl(fd, EVIOCGBIT(0, EV_MAX), &buf);
311 	}
312 
313 	for (size_t i = 0; i < sizeof(buf); i++)
314 		hash = ((hash << 5) + hash) + buf[i];
315 
316 /* 16-bit clamp is legacy in the scripting layer, also leave the highest
317  * bit unset as that is reserved for synthetic devices */
318 	hash &= 0xfffe;
319 	if (hash < MAX_DEVICES)
320 		hash += MAX_DEVICES;
321 
322 /* scan for collisions, if there is one, random and repeat. We lose
323  * repeatability but don't risk collision-disconnect spam */
324 	for (ssize_t i = 0; i < iodev.sz_nodes; i++){
325 		while (hash == iodev.nodes[i].devnum){
326 			uint16_t rv;
327 			arcan_random((uint8_t*)&rv, 2);
328 			hash = rv & (uint16_t) 0xfffe;
329 			if (hash < MAX_DEVICES)
330 				hash += MAX_DEVICES;
331 			if (i)
332 				i -= 1;
333 			continue;
334 		}
335 	}
336 
337 	*dnum = hash;
338 
339 	return true;
340 }
341 
process_axis(struct arcan_evctx * ctx,struct axis_opts * daxis,int16_t samplev,int16_t * outv)342 static inline bool process_axis(struct arcan_evctx* ctx,
343 	struct axis_opts* daxis, int16_t samplev, int16_t* outv)
344 {
345 	if (daxis->mode == ARCAN_ANALOGFILTER_NONE)
346 		return false;
347 
348 	if (daxis->mode == ARCAN_ANALOGFILTER_PASS)
349 		goto accept_sample;
350 
351 /* quickfilter deadzone */
352 	if (abs(samplev) < daxis->deadzone){
353 		if (!daxis->indzone){
354 			samplev = 0;
355 			daxis->indzone = true;
356 		}
357 		else
358 			return false;
359 	}
360 	else
361 		daxis->indzone = false;
362 
363 /* quickfilter out controller edgenoise */
364 	if (samplev < daxis->lower){
365 		if (!daxis->inlzone){
366 			samplev = daxis->lower;
367 			daxis->inlzone = true;
368 			daxis->inuzone = false;
369 		}
370 		else
371 			return false;
372 	}
373 	else if (samplev > daxis->upper){
374 		if (!daxis->inuzone){
375 			samplev = daxis->upper;
376 			daxis->inuzone = true;
377 			daxis->inlzone = false;
378 		}
379 		else
380 			return false;
381 	}
382 	else
383 		daxis->inlzone = daxis->inuzone = false;
384 
385 	daxis->flt_kernel[ daxis->kernel_ofs++ ] = samplev;
386 
387 /* don't proceed until the kernel is filled */
388 	if (daxis->kernel_ofs < daxis->kernel_sz)
389 		return false;
390 
391 	if (daxis->kernel_sz > 1){
392 		int32_t tot = 0;
393 
394 		if (daxis->mode == ARCAN_ANALOGFILTER_ALAST){
395 			samplev = daxis->flt_kernel[daxis->kernel_sz - 1];
396 		}
397 		else {
398 			for (int i = 0; i < daxis->kernel_sz; i++)
399 				tot += daxis->flt_kernel[i];
400 
401 			samplev = tot != 0 ? tot / daxis->kernel_sz : 0;
402 		}
403 
404 	}
405 	else;
406 	daxis->kernel_ofs = 0;
407 
408 accept_sample:
409 	*outv = samplev;
410 	return true;
411 }
412 
set_analogstate(struct axis_opts * dst,int lower_bound,int upper_bound,int deadzone,int kernel_size,enum ARCAN_ANALOGFILTER_KIND mode)413 static void set_analogstate(struct axis_opts* dst,
414 	int lower_bound, int upper_bound, int deadzone,
415 	int kernel_size, enum ARCAN_ANALOGFILTER_KIND mode)
416 {
417 	dst->lower = lower_bound;
418 	dst->upper = upper_bound;
419 	dst->deadzone = deadzone;
420 	dst->kernel_sz = kernel_size;
421 	dst->mode = mode;
422 
423 	dst->kernel_ofs = 0;
424 }
425 
find_axis(int devid,unsigned axisid,bool * outn)426 static struct axis_opts* find_axis(int devid, unsigned axisid, bool* outn)
427 {
428 	struct devnode* node = lookup_devnode(devid);
429 	*outn = node != NULL;
430 
431 	if (!node)
432 		return NULL;
433 
434 	switch(node->type){
435 	case DEVNODE_SENSOR:
436 		return axisid == 0 ? &node->sensor.data : NULL;
437 	break;
438 
439 	case DEVNODE_GAME:
440 		if (axisid < node->game.axes)
441 			return &node->game.adata[axisid];
442 	break;
443 
444 	case DEVNODE_MOUSE:
445 		if (axisid == 0)
446 			return &node->cursor.flt[0];
447 		else if (axisid == 1)
448 			return &node->cursor.flt[1];
449 	break;
450 
451 	default:
452 	break;
453 	}
454 
455 	return NULL;
456 }
457 
platform_event_analogstate(int devid,int axisid,int * lower_bound,int * upper_bound,int * deadzone,int * kernel_size,enum ARCAN_ANALOGFILTER_KIND * mode)458 arcan_errc platform_event_analogstate(int devid, int axisid,
459 	int* lower_bound, int* upper_bound, int* deadzone,
460 	int* kernel_size, enum ARCAN_ANALOGFILTER_KIND* mode)
461 {
462 	bool gotnode;
463 	struct axis_opts* axis = find_axis(devid, axisid, &gotnode);
464 
465 	if (!axis)
466 		return gotnode ?
467 			ARCAN_ERRC_BAD_RESOURCE : ARCAN_ERRC_NO_SUCH_OBJECT;
468 
469 	*lower_bound = axis->lower;
470 	*upper_bound = axis->upper;
471 	*deadzone = axis->deadzone;
472 	*kernel_size = axis->kernel_sz;
473 	*mode = axis->mode;
474 
475 	return ARCAN_OK;
476 }
477 
platform_event_analogall(bool enable,bool mouse)478 void platform_event_analogall(bool enable, bool mouse)
479 {
480 	struct devnode* node = lookup_devnode(iodev.mouseid);
481 	if (!node)
482 		return;
483 
484 /*
485  * FIXME sweep all devices and all axes (or just mouseid) if (enable) then set
486  * whatever the previous mode was, else store current mode and set NONE
487  */
488 }
489 
490 static void disconnect(struct arcan_evctx* ctx, struct devnode* node);
platform_event_analogfilter(int devid,int axisid,int lower_bound,int upper_bound,int deadzone,int buffer_sz,enum ARCAN_ANALOGFILTER_KIND kind)491 void platform_event_analogfilter(int devid,
492 	int axisid, int lower_bound, int upper_bound, int deadzone,
493 	int buffer_sz, enum ARCAN_ANALOGFILTER_KIND kind)
494 {
495 /* this was added here rather than a separate entry-point to deal with backward
496  * and forward compatiblity from an API angle */
497 	if (kind == ARCAN_ANALOGFILTER_FORGET){
498 		struct devnode* node = lookup_devnode(devid);
499 
500 /* this is also a piece of legacy, other functions operate on an explicit
501  * context, but there is really only one */
502 		if (node)
503 			disconnect(arcan_event_defaultctx(), node);
504 		return;
505 	}
506 
507 	bool node;
508 	struct axis_opts* axis = find_axis(devid, axisid, &node);
509 	if (!axis)
510 		return;
511 
512 	int kernel_lim = sizeof(axis->flt_kernel) / sizeof(axis->flt_kernel[0]);
513 
514 	if (buffer_sz > kernel_lim)
515 		buffer_sz = kernel_lim;
516 
517 	if (buffer_sz <= 0)
518 		buffer_sz = 1;
519 
520 	set_analogstate(axis,lower_bound, upper_bound, deadzone, buffer_sz, kind);
521 }
522 
discovered(struct arcan_evctx * ctx,const char * name,size_t name_len,bool nopending)523 static bool discovered(struct arcan_evctx* ctx,
524 	const char* name, size_t name_len, bool nopending)
525 {
526 	char buffer[name_len+sizeof(notify_scan_dir)];
527 	char outbuffer[MAXPATHLEN];
528 
529 /* need to resolve a symlink if there is one as the platform_device_open
530  * has a whitelist that is rather picky about which devices it will open */
531 	snprintf(buffer, sizeof(buffer), "%s/%.*s", notify_scan_dir, (int)name_len, name);
532 
533 	TRACE_MARK_ENTER("event", "open-device", TRACE_SYS_DEFAULT, 0, 0, name);
534 
535 	int fd = platform_device_open(
536 		readlink(buffer, outbuffer, sizeof(outbuffer)) > 0 ?
537 			outbuffer : buffer, O_NONBLOCK| O_RDWR);
538 
539 	TRACE_MARK_EXIT("event", "open-device", TRACE_SYS_DEFAULT, 0, fd, name);
540 
541 	verbose_print("input: trying to add %s/%.*s",
542 		notify_scan_dir, (int)name_len, name);
543 
544 	if (-1 == fd && errno == EACCES){
545 		if (gstate.pending >= COUNT_OF(pending)){
546 			debug_print(
547 				"input: pending queue limit exceeded, possibly something wrong"
548 				" with monitored folder (%s) and permissions.", notify_scan_dir
549 			);
550 			return false;
551 		}
552 
553 /* already know about this one */
554 		if (nopending)
555 			return false;
556 
557 /* sign that someone is impatient and plugging / unplugging while pending */
558 		size_t i;
559 		ssize_t j = -1;
560 		for (i = 0; i < COUNT_OF(pending); i++){
561 			if (!pending[i].path && j == -1)
562 				j = i;
563 			if (pending[i].path && strcmp(name, pending[i].path) == 0)
564 				return false;
565 		}
566 /* name comes from inotify which does not have to terminate */
567 		gstate.pending++;
568 		pending[j].path = malloc(name_len + 1);
569 		sprintf(pending[j].path, "%.*s", (int)name_len, name);
570 		pending[j].tries = default_eacces_tries;
571 		pending[j].last_ts = arcan_frametime();
572 		return false;
573 	}
574 
575 /* even if we can access it and it is of the right type, it is not certain
576  * that we can actually identify and use it according with evdev */
577 	if (-1 != fd){
578 		got_device(ctx, fd, name);
579 		return true;
580 	}
581 	else
582 		arcan_warning("input: couldn't open new device (%s), reason: %s\n",
583 			name, strerror(errno));
584 	return false;
585 }
586 
process_pending(struct arcan_evctx * ctx)587 static void process_pending(struct arcan_evctx* ctx)
588 {
589 	for (size_t i = 0; i < COUNT_OF(pending); i++){
590 		if (!pending[i].path)
591 			continue;
592 
593 /* wait a little longer for each failed attempt */
594 		if (arcan_frametime() - pending[i].last_ts < (default_eacces_tries -
595 			pending[i].tries + 1) * default_eacces_delay)
596 			continue;
597 
598 		pending[i].last_ts = arcan_frametime();
599 
600 		if (discovered(ctx, pending[i].path, strlen(pending[i].path), true)){
601 			free(pending[i].path);
602 			pending[i].path = NULL;
603 			gstate.pending--;
604 		}
605 		else{
606 			pending[i].tries--;
607 			if (pending[i].tries <= 0){
608 				arcan_warning("input(eperm): device(%s) retry count"
609 					"exceeded\n", pending[i].path);
610 				free(pending[i].path);
611 				pending[i].path = NULL;
612 				gstate.pending--;
613 			}
614 		}
615 	}
616 }
617 
disconnect(struct arcan_evctx * ctx,struct devnode * node)618 static void disconnect(struct arcan_evctx* ctx, struct devnode* node)
619 {
620 	struct arcan_event addev = {
621 		.category = EVENT_IO,
622 		.io.kind = EVENT_IO_STATUS,
623 		.io.devid = node->devnum,
624 		.io.devkind = EVENT_IDEVKIND_STATUS,
625 		.io.input.status.devkind = node->type,
626 		.io.input.status.action = EVENT_IDEV_REMOVED
627 	};
628 	snprintf((char*) &addev.io.label, sizeof(addev.io.label) /
629 		sizeof(addev.io.label[0]), "%s", node->label);
630 	arcan_event_enqueue(ctx, &addev);
631 
632 	for (size_t i = 0; i < iodev.sz_nodes; i++)
633 		if (node->devnum == iodev.nodes[i].devnum){
634 			close(node->handle);
635 			free(node->path);
636 			node->path = NULL;
637 			node->handle = -1;
638 			iodev.pollset[i].events = iodev.pollset[i].revents = 0;
639 			iodev.pollset[i].fd = -1;
640 			if (node->led.gotled){
641 				iodev.pollset[i+iodev.sz_nodes].fd = -1;
642 				iodev.pollset[i+iodev.sz_nodes].events =
643 					iodev.pollset[i+iodev.sz_nodes].revents = 0;
644 				node->led.gotled = false;
645 				arcan_led_remove(node->led.ctrlid);
646 				close(node->led.fds[0]);
647 				close(node->led.fds[1]);
648 				node->led.fds[0] = -1;
649 				node->led.fds[1] = -1;
650 			}
651 #ifdef HAVE_XKBCOMMON
652 			if (node->type == DEVNODE_KEYBOARD && node->keyboard.xkb_state){
653 				xkb_state_unref(node->keyboard.xkb_state);
654 				xkb_keymap_unref(node->keyboard.xkb_layout);
655 				node->keyboard.xkb_state = NULL;
656 				node->keyboard.xkb_layout = NULL;
657 			}
658 #endif
659 			iodev.n_devs--;
660 		}
661 }
662 
do_led(struct devnode * node)663 static void do_led(struct devnode* node)
664 {
665 	if (!node->led.gotled){
666 		arcan_warning("evdev(), pollset corruption? POLLIN on node without LED\n");
667 		return;
668 	}
669 
670 	uint8_t buf[2];
671 	bool set = false;
672 
673 	while (2 == read(node->led.fds[0], buf, 2)){
674 		switch (tolower(buf[0])){
675 		case 'A': node->led.ind = -1; break;
676 		case 'a': node->led.ind = buf[1]; break;
677 /* not registered as a RGB led */
678 		case 'r': break;
679 		case 'g': break;
680 		case 'b': break;
681 		case 'i': set = buf[1] > 0; break;
682 		case 'c':
683 			if (node->led.ind == -1){
684 				for (size_t i = 0; i < LED_MAX; i++)
685 					if (-1 == write(node->handle, &(struct input_event){.type = EV_LED,
686 						.code = i, .value = set}, sizeof(struct input_event)))
687 						arcan_warning("platform/evdev: failed to write to led device\n");
688 			}
689 			else {
690 				if (-1 == write(node->handle, &(struct input_event){.type = EV_LED,
691 					.code = node->led.ind, .value = set}, sizeof(struct input_event)))
692 					arcan_warning("platform/evdev: failed to write to led device\n");
693 			}
694 		break;
695 		}
696 	}
697 }
698 
platform_event_process(struct arcan_evctx * ctx)699 void platform_event_process(struct arcan_evctx* ctx)
700 {
701 /* lovely little variable length field at end of struct here /sarcasm,
702  * could get away with running the notify polling less often than once
703  * every frame, somewhat excessive. */
704 #ifdef __FreeBSD__
705 #else
706 	if (-1 != gstate.notify){
707 		char inbuf[1024];
708 		ssize_t nr = read(gstate.notify, inbuf, sizeof(inbuf));
709 		off_t ofs = 0;
710 
711 		if (-1 != nr)
712 			while (nr - ofs > sizeof(struct inotify_event)){
713 				struct inotify_event cur;
714 				memcpy(&cur, &inbuf[ofs], sizeof(struct inotify_event));
715 				ofs += sizeof(struct inotify_event);
716 
717 				if ((cur.mask & IN_CREATE) && !(cur.mask & IN_ISDIR)){
718 					discovered(ctx, &inbuf[ofs], cur.len, false);
719 					ofs += cur.len;
720 				}
721 			}
722 	}
723 #endif
724 	TRACE_MARK_ENTER("event", "flush-pending-in", TRACE_SYS_DEFAULT, 0, 0, "flush-in");
725 
726 	if (gstate.pending)
727 		process_pending(ctx);
728 
729 	int nr = poll(iodev.pollset, iodev.sz_nodes * 2, 0);
730 	if (nr <= 0){
731 		TRACE_MARK_EXIT("event", "flush-pending-in", TRACE_SYS_FAST, 0, 0, "flush-in");
732 		return;
733 	}
734 
735 	for (size_t i = 0; i < iodev.sz_nodes; i++){
736 /* recall, sz_nodes is half the count, i + sz_nodes = alt-dev index */
737 		if (iodev.pollset[i+iodev.sz_nodes].revents & POLLIN){
738 			do_led(&iodev.nodes[i]);
739 		}
740 
741 		if (iodev.pollset[i].fd == -1 || 0 == iodev.pollset[i].revents)
742 			continue;
743 
744 /* !POLLIN, then something is wrong, remove the node */
745 		if (0 == (iodev.pollset[i].revents & POLLIN)){
746 			disconnect(ctx, &iodev.nodes[i]);
747 			continue;
748 		}
749 /* some nodes may get a null handler temporarily or permanently assiged,
750  * drain those for evdev structures */
751 		else {
752 			if (iodev.nodes[i].hnd.handler)
753 				iodev.nodes[i].hnd.handler(ctx, &iodev.nodes[i]);
754 			else{
755 				char dump[256];
756 				size_t nr __attribute__((unused));
757 				nr = read(iodev.nodes[i].handle, dump, 256);
758 			}
759 		}
760 	}
761 	TRACE_MARK_EXIT("event", "flush-pending-in", TRACE_SYS_DEFAULT, 0, 0, "flush-in");
762 }
763 
platform_event_samplebase(int devid,float xyz[3])764 void platform_event_samplebase(int devid, float xyz[3])
765 {
766 	struct devnode* node = lookup_devnode(devid);
767 	if (!node || node->type != DEVNODE_MOUSE)
768 		return;
769 
770 	node->cursor.mx = xyz[0];
771 	node->cursor.my = xyz[1];
772 }
773 
platform_event_keyrepeat(struct arcan_evctx * ctx,int * period,int * delay)774 void platform_event_keyrepeat(struct arcan_evctx* ctx, int* period, int* delay)
775 {
776 	bool upd = false;
777 
778 	if (*period < 0){
779 		*period = iodev.period;
780 	}
781 	else{
782 		int tmp = *period;
783 		*period = iodev.period;
784 		iodev.period = tmp;
785 		upd = true;
786 	}
787 
788 	if (*delay < 0){
789 		*delay = iodev.delay;
790 	}
791 	else {
792 		int tmp = *delay;
793 		*delay = iodev.delay;
794 		iodev.delay = tmp;
795 		upd = true;
796 	}
797 
798 	if (!upd)
799 		return;
800 
801 	for (size_t i = 0; i < iodev.sz_nodes; i++)
802 		if (iodev.nodes[i].type == DEVNODE_KEYBOARD){
803 			struct input_event ev = {
804 				.type = EV_REP,
805 				.code = REP_DELAY,
806 				.value = *delay
807 			};
808 			if (-1 == write(iodev.nodes[i].handle,&ev,sizeof(struct input_event)))
809 				verbose_print("linux/event: keydelay fail (%s)\n", strerror(errno));
810 
811 			ev.code = REP_PERIOD;
812 			ev.value = *period;
813 			if (-1 == write(iodev.nodes[i].handle,&ev,sizeof(struct input_event)))
814 				verbose_print("linux/event: keyrepeat fail (%s)\n", strerror(errno));
815 		}
816 }
817 
lookup_type(int val)818 static const char* lookup_type(int val)
819 {
820 	switch(val){
821 	case DEVNODE_GAME:
822 		return "game";
823 	case DEVNODE_MOUSE:
824 		return "mouse";
825 	case DEVNODE_SENSOR:
826 		return "sensor";
827 	case DEVNODE_KEYBOARD:
828 		return "keyboard";
829 	break;
830 	default:
831 	return "unknown";
832 	}
833 }
834 
835 #define bit_longn(x) ( (x) / (sizeof(long)*8) )
836 #define bit_ofs(x) ( (x) % (sizeof(long)*8) )
837 #define bit_isset(ary, bit) (( ary[bit_longn(bit)] >> bit_ofs(bit)) & 1)
838 #define bit_count(x) ( ((x) - 1 ) / (sizeof(long) * 8 ) + 1 )
839 
button_count(int fd,size_t bitn,bool * got_mouse,bool * got_joy)840 static size_t button_count(int fd, size_t bitn, bool* got_mouse, bool* got_joy)
841 {
842 	size_t count = 0;
843 
844 	unsigned long bits[ bit_count(KEY_MAX) ];
845 
846 	if (-1 == ioctl(fd, EVIOCGBIT(bitn, KEY_MAX), bits))
847 		return false;
848 
849 	for (size_t i = 0; i < KEY_MAX; i++){
850 		if (bit_isset(bits, i)){
851 			count++;
852 		}
853 	}
854 
855 	*got_mouse = (bit_isset(bits, BTN_MOUSE) || bit_isset(bits, BTN_LEFT) ||
856 		bit_isset(bits, BTN_RIGHT) || bit_isset(bits, BTN_MIDDLE));
857 
858 	*got_joy = (bit_isset(bits, BTN_JOYSTICK) || bit_isset(bits, BTN_GAMEPAD) ||
859 		bit_isset(bits, BTN_WHEEL));
860 
861 	return count;
862 }
863 
check_mouse_axis(int fd,size_t bitn)864 static bool check_mouse_axis(int fd, size_t bitn)
865 {
866 	unsigned long bits[ bit_count(KEY_MAX) ];
867 	if (-1 == ioctl(fd, EVIOCGBIT(bitn, KEY_MAX), bits))
868 		return false;
869 
870 /* uncertain if other (REL_Z, REL_RX, REL_RY, REL_RZ, REL_DIAL, REL_MISC)
871  * should be used as a failing criteria */
872 	return bit_isset(bits, REL_X) && bit_isset(bits, REL_Y);
873 }
874 
to_utf8(uint16_t utf16,uint8_t out[4])875 static char* to_utf8(uint16_t utf16, uint8_t out[4])
876 {
877 	int count = 1, ofs = 0;
878 	uint32_t mask = 0x800;
879 
880 	if (utf16 >= 0x80)
881 		count++;
882 
883 	for(size_t i=0; i < 5; i++){
884 		if ( (uint32_t) utf16 >= mask )
885 			count++;
886 
887 		mask <<= 5;
888 	}
889 
890 	if (count == 1){
891 		out[0] = (char) utf16;
892 		out[1] = 0x00;
893 	}
894 	else {
895 		for (int i = (count-1 > 4 ? 4 : count - 1); i >= 0; i--){
896 			unsigned char ch = ( utf16 >> (6 * i)) & 0x3f;
897 			ch |= 0x80;
898 			if (i == count-1)
899 				ch |= 0xff << (8-count);
900 			out[ofs++] = ch;
901 		}
902 		out[ofs++] = 0x00;
903 	}
904 
905 	return (char*) out;
906 }
907 
map_axes(int fd,size_t bitn,struct devnode * node)908 static void map_axes(int fd, size_t bitn, struct devnode* node)
909 {
910 	unsigned long bits[ bit_count(ABS_MAX) ];
911 	unsigned long rel_bits[ bit_count(REL_MAX) ];
912 
913 	assert(node->type == DEVNODE_GAME);
914 	if (node->game.adata)
915 		return;
916 	node->game.axes = 0;
917 
918 	if (-1 != ioctl(fd, EVIOCGBIT(bitn, ABS_MAX), bits)){
919 		for (size_t i = 0; i < ABS_MAX; i++){
920 			if (bit_isset(bits, i))
921 				node->game.axes++;
922 		}
923 	}
924 
925 	node->game.relofs = node->game.axes;
926 	if (-1 != ioctl(fd, EVIOCGBIT(bitn, REL_MAX), rel_bits)){
927 		for (size_t i = 0; i < REL_MAX; i++){
928 			if (bit_isset(bits, i)){
929 				node->game.axes++;
930 			}
931 		}
932 	}
933 
934 	if (node->game.axes == 0)
935 		return;
936 
937 	node->game.adata = arcan_alloc_mem(
938 		sizeof(struct axis_opts) * node->game.axes,
939 		ARCAN_MEM_BINDING, ARCAN_MEM_BZERO, ARCAN_MEMALIGN_NATURAL
940 	);
941 
942 	size_t ac = 0;
943 
944 	for (size_t i = 0; i < ABS_MAX; i++)
945 		if (bit_isset(bits, i)){
946 			struct input_absinfo ainf;
947 			struct axis_opts* ax = &node->game.adata[ac++];
948 
949 			memset(ax, '\0', sizeof(struct axis_opts));
950 			ax->mode = ax->oldmode = ARCAN_ANALOGFILTER_AVG;
951 			ax->lower = -32768;
952 			ax->upper = 32767;
953 
954 			if (-1 == ioctl(fd, EVIOCGABS(i), &ainf))
955 				continue;
956 
957 			ax->upper = ainf.maximum;
958 			ax->lower = ainf.minimum;
959 		}
960 }
961 
962 /*
963  * setup/register/prepare led- controller handler
964  */
setup_led(struct devnode * dst,size_t bitn,int fd)965 static void setup_led(struct devnode* dst, size_t bitn, int fd)
966 {
967 	unsigned long bits[ bit_count(LED_MAX) ];
968 	if (-1 == ioctl(fd, EVIOCGBIT(bitn, LED_MAX), bits))
969 		return;
970 
971 	size_t count = 0;
972 	for (size_t i = 0; i < LED_MAX; i++){
973 		if (bit_isset(bits, i))
974 			count++;
975 	}
976 
977 	if (!count)
978 		return;
979 
980 	if (pipe(dst->led.fds) == -1)
981 		return;
982 
983 	for (size_t i = 0; i < 2; i++){
984 		int flags = fcntl(dst->led.fds[i], F_GETFL);
985 		if (-1 != flags)
986 			fcntl(dst->led.fds[i], F_SETFL, flags | O_NONBLOCK);
987 		flags = fcntl(dst->led.fds[i], F_GETFD);
988 		if (-1 != flags)
989 			fcntl(dst->led.fds[i], F_SETFD, flags | FD_CLOEXEC);
990 	}
991 
992 	char ledname[16];
993 	snprintf(ledname, 16, "%d_led", dst->devnum);
994 	dst->led.ctrlid = arcan_led_register(dst->led.fds[1], dst->devnum, ledname,
995 		(struct led_capabilities){ .nleds = LED_MAX,
996 			.variable_brightness = false, .rgb = false }
997 	);
998 	if (-1 == dst->led.ctrlid){
999 		close(dst->led.fds[0]);
1000 		close(dst->led.fds[1]);
1001 		dst->led.fds[0] = dst->led.fds[1] = -1;
1002 		return;
1003 	}
1004 	dst->led.gotled = true;
1005 /* reset */
1006 	for (size_t i = 0; i < LED_MAX; i++){
1007 		if (-1 == write(dst->handle, &(struct input_event){.type = EV_LED,
1008 			.code = i, .value = 0}, sizeof(struct input_event)))
1009 			arcan_warning("platform/evdev(), error sending reset to led device\n");
1010 	}
1011 }
1012 
alloc_node_slot(const char * path)1013 static int alloc_node_slot(const char* path)
1014 {
1015 /* pre-existing? close old node and replace with this one, happens
1016  * when we race and the device appears and reappears and we just need
1017  * to reference a new inode */
1018 	int hole = -1;
1019 
1020 	for (size_t i = 0; i < iodev.sz_nodes; i++){
1021 		if (-1 == hole && iodev.nodes[i].handle < 0){
1022 			hole = i;
1023 			continue;
1024 		}
1025 
1026 /* or collision with existing? we use file-path for this. index
1027  * stays the same and got_device will still register so don't have
1028  * to consider leak for ledset */
1029 		if (iodev.nodes[i].path && strcmp(iodev.nodes[i].path, path) == 0){
1030 			close(iodev.nodes[i].handle);
1031 			iodev.n_devs--;
1032 			return i;
1033 		}
1034 	}
1035 
1036 /* no empty slot, grow pollsets and node tracking */
1037 	if (hole == -1){
1038 		size_t new_cnt = iodev.sz_nodes + 8;
1039 		struct devnode* nn = realloc(
1040 			iodev.nodes, sizeof(struct devnode) * new_cnt);
1041 		if (!nn)
1042 			return -1;
1043 		iodev.nodes = nn;
1044 		memset(nn + iodev.sz_nodes, '\0', sizeof(struct devnode) * 8);
1045 		for (size_t i = iodev.sz_nodes; i < new_cnt; i++){
1046 			iodev.nodes[i].handle = BADFD;
1047 			iodev.nodes[i].led.fds[0] = iodev.nodes[i].led.fds[1] = BADFD;
1048 		}
1049 
1050 /* pollset size is actually twice the number of nodes to allow a
1051  * 'mirror address' for a possible led- or other special device ref.
1052  * (say sound...) */
1053 		struct pollfd* newset = malloc(2 * sizeof(struct pollfd) * new_cnt);
1054 		if (!newset)
1055 			return -1;
1056 
1057 		free(iodev.pollset);
1058 		for (size_t i = 0; i < new_cnt; i++){
1059 			memset(&newset[i], '\0', sizeof(struct pollfd));
1060 			memset(&newset[i+new_cnt], '\0', sizeof(struct pollfd));
1061 			newset[i].events = POLLIN | POLLERR | POLLHUP;
1062 			newset[i].fd = iodev.nodes[i].handle;
1063 			newset[i+new_cnt].events = POLLIN;
1064 			newset[i+new_cnt].fd = iodev.nodes[i].led.fds[0];
1065 		}
1066 
1067 /* update pointers, set hole to the first new entry */
1068 		iodev.pollset = newset;
1069 		hole = iodev.sz_nodes;
1070 		iodev.sz_nodes = new_cnt;
1071 	}
1072 
1073 	return hole;
1074 }
1075 
send_device_added(struct arcan_evctx * ctx,struct devnode * node)1076 static void send_device_added(struct arcan_evctx* ctx, struct devnode* node)
1077 {
1078 	struct arcan_event addev = {
1079 		.category = EVENT_IO,
1080 		.io.kind = EVENT_IO_STATUS,
1081 		.io.devkind = EVENT_IDEVKIND_STATUS,
1082 		.io.devid = node->devnum,
1083 		.io.input.status.devkind = node->type,
1084 		.io.input.status.action = EVENT_IDEV_ADDED
1085 	};
1086 	snprintf((char*) &addev.io.label, sizeof(addev.io.label) /
1087 		sizeof(addev.io.label[0]), "%s", node->label);
1088 	arcan_event_enqueue(ctx, &addev);
1089 }
1090 
platform_event_translation(int devid,int action,const char ** arg,const char ** err)1091 bool platform_event_translation(
1092 	int devid, int action, const char** arg, const char** err)
1093 {
1094 	struct devnode* node = NULL;
1095 
1096 /* find the n'th device on a negative id */
1097 	if (devid < 0){
1098 		devid *= -1;
1099 
1100 		for (size_t i = 0; i < iodev.sz_nodes; i++){
1101 			if (iodev.nodes[i].type == DEVNODE_KEYBOARD){
1102 				devid--;
1103 				if (!devid){
1104 					node = &iodev.nodes[i];
1105 					break;
1106 				}
1107 			}
1108 		}
1109 	}
1110 	else
1111 		node = lookup_devnode(devid);
1112 
1113 	if (!node || node->type != DEVNODE_KEYBOARD){
1114 		*err = "No such device";
1115 		return false;
1116 	}
1117 
1118 #ifdef HAVE_XKBCOMMON
1119 	char* rules = NULL;
1120 	char* model = NULL;
1121 	char* variant = NULL;
1122 	char* options = NULL;
1123 	char* layout = NULL;
1124 
1125 	struct xkb_rule_names names = {0};
1126 
1127 	if (!xkb_context){
1128 		*err = "Missing XKB context";
1129 		return false;
1130 	}
1131 
1132 /* Config takes priority - Then explicitly fill with environment,
1133  *
1134  * An omitted path here is to incrementally index keyboards and allow multiple
1135  * slots so different keyboards can get different layouts from the start. The
1136  * problem with this is the usual one of persistant IDs across instances as
1137  * anyone with a multiple keyboard setup that calls for different layouts
1138  * already have very .. exotic tastes.
1139  */
1140 	if (action == EVENT_TRANSLATION_CLEAR){
1141 		uintptr_t tag;
1142 		cfg_lookup_fun get_config = platform_config_lookup(&tag);
1143 		get_config("event_xkb_rules", 0, &rules, tag);
1144 		get_config("event_xkb_variant", 0, &variant, tag);
1145 		get_config("event_xkb_model", 0, &model, tag);
1146 		get_config("event_xkb_options", 0, &options, tag);
1147 		get_config("event_xkb_layout", 0, &layout, tag);
1148 
1149 		names.rules = rules ? rules : getenv("XKB_DEFAULT_RULES");
1150 		names.model = model ? model : getenv("XKB_DEFAULT_MODEL");
1151 		names.variant = variant ? variant : getenv("XKB_DEFAULT_VARIANT");
1152 		names.options = options ? options : getenv("XKB_DEFAULT_OPTIONS");
1153 		names.layout = layout ? options : getenv("XKB_DEFAULT_LAYOUT");
1154 	}
1155 /* just fill struct from arg */
1156 	else if (action == EVENT_TRANSLATION_SET){
1157 		names.layout = arg[0];
1158 		if (names.layout)
1159 			names.model = arg[1];
1160 		if (names.model)
1161 			names.variant = arg[2];
1162 		if (names.variant)
1163 			names.options = arg[3];
1164 	}
1165 	else {
1166 		*err = "Unsupported action";
1167 		return false;
1168 	}
1169 
1170 	if (node->keyboard.xkb_layout){
1171 		if (node->keyboard.xkb_state)
1172 			xkb_state_unref(node->keyboard.xkb_state);
1173 		xkb_keymap_unref(node->keyboard.xkb_layout);
1174 		node->keyboard.xkb_state = NULL;
1175 		node->keyboard.xkb_layout = NULL;
1176 	}
1177 
1178 /* Disable xkb translation entirely */
1179 	if (!names.rules && !names.model &&
1180 		!names.variant && !names.options && !names.layout)
1181 		return false;
1182 
1183 	node->keyboard.xkb_layout =
1184 		xkb_keymap_new_from_names(xkb_context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
1185 
1186 	if (node->keyboard.xkb_layout)
1187 		node->keyboard.xkb_state = xkb_state_new(node->keyboard.xkb_layout);
1188 
1189 	free(rules);
1190 	free(model);
1191 	free(variant);
1192 	free(options);
1193 
1194 	return true;
1195 #endif
1196 
1197 	*err = "Engine built without libxkbcommon support";
1198 	return false;
1199 }
1200 
platform_event_device_request(int space,const char * path)1201 int platform_event_device_request(int space, const char* path)
1202 {
1203 	return -EINVAL;
1204 }
1205 
got_device(struct arcan_evctx * ctx,int fd,const char * path)1206 static void got_device(struct arcan_evctx* ctx, int fd, const char* path)
1207 {
1208 	struct devnode node = {
1209 		.handle = fd,
1210 		.led.fds = {BADFD, BADFD}
1211 	};
1212 
1213 	struct stat fdstat;
1214 	if (-1 == fstat(fd, &fdstat)){
1215 			verbose_print(
1216 				"input: couldn't stat node to identify (%s)", strerror(errno));
1217 		return;
1218 	}
1219 
1220 	if ((fdstat.st_mode & (S_IFCHR | S_IFBLK)) == 0){
1221 			verbose_print(
1222 				"input: ignoring %s, not a character or block device", path);
1223 		return;
1224 	}
1225 
1226 	if (!identify(fd, path, node.label, sizeof(node.label), &node.devnum)){
1227 			verbose_print(
1228 				"input: identify failed on %s, ignoring unknown.", path);
1229 		close(fd);
1230 		return;
1231 	}
1232 
1233 	if (iodev.n_devs >= MAX_DEVICES){
1234 		arcan_warning("input: device limit reached, ignoring %s.", path);
1235 		close(fd);
1236 	}
1237 
1238 /* figure out what kind of a device this is from the exposed capabilities,
1239  * heuristic nonsense rather than an interface exposing what the driver should
1240  * know or decide, fantastic.
1241  *
1242  * keyboards typically have longer key masks (and we can check for a few common
1243  * ones) no REL/ABS (don't know if those built-in trackball ones expose as two
1244  * devices or not these days), but also a ton of .. keys
1245  */
1246 	struct evhandler eh = lookup_dev_handler(node.label);
1247 
1248 /* [eh] may contain overrides, but we still need to probe the driver state for
1249  * axes etc. and allocate accordingly */
1250 	node.type = DEVNODE_GAME;
1251 
1252 	bool mouse_ax = false;
1253 	bool mouse_btn = false;
1254 	bool joystick_btn = false;
1255 	int add_led = -1;
1256 
1257 	size_t bpl = sizeof(long) * 8;
1258 	size_t nbits = ((EV_MAX)-1) / bpl + 1;
1259 	long prop[ nbits ];
1260 
1261 	if (-1 == ioctl(fd, EVIOCGBIT(0, EV_MAX), &prop)){
1262 		verbose_print(
1263 			"input: probing %s failed, %s", path, strerror(errno));
1264 		close(fd);
1265 		return;
1266 	}
1267 
1268 	for (size_t bit = 0; bit < EV_MAX; bit++)
1269 		if ( 1ul & (prop[bit/bpl]) >> (bit & (bpl - 1)) )
1270 		switch(bit){
1271 		case EV_KEY:
1272 			node.button_count = button_count(fd, bit, &mouse_btn, &joystick_btn);
1273 		break;
1274 
1275 		case EV_REL:
1276 			mouse_ax = check_mouse_axis(fd, bit);
1277 		break;
1278 
1279 		case EV_ABS:
1280 			map_axes(fd, bit, &node);
1281 		break;
1282 
1283 		case EV_SW:
1284 		break;
1285 
1286 /* useless for the time being */
1287 		case EV_MSC:
1288 		break;
1289 		case EV_SYN:
1290 		break;
1291 		case EV_LED:
1292 			add_led = bit;
1293 		break;
1294 		case EV_SND:
1295 		break;
1296 		case EV_REP:
1297 		break;
1298 		case EV_PWR:
1299 		break;
1300 		case EV_FF:
1301 		case EV_FF_STATUS:
1302 		break;
1303 		}
1304 
1305 	if (!eh.handler){
1306 		if (mouse_ax && mouse_btn){
1307 			node.type = DEVNODE_MOUSE;
1308 			node.cursor.flt[0].mode = ARCAN_ANALOGFILTER_PASS;
1309 			node.cursor.flt[1].mode = ARCAN_ANALOGFILTER_PASS;
1310 
1311 			if (!iodev.mouseid)
1312 				iodev.mouseid = node.devnum;
1313 		}
1314 /* not particularly pretty and rather arbitrary */
1315 		else if (!mouse_btn && !joystick_btn && node.button_count > 84){
1316 			node.type = DEVNODE_KEYBOARD;
1317 			node.keyboard.state = 0;
1318 
1319 /* FIX: query current LED states and set corresponding states in the devnode,
1320  * this does not save / restore the built-in repeats */
1321 			unsigned rep[2] = {0, 0};
1322 			ioctl(node.handle, EVIOCSREP, rep);
1323 		}
1324 
1325 		node.hnd.handler = defhandlers[node.type];
1326 	}
1327 	else{
1328 		node.hnd = eh;
1329 		node.type = eh.type;
1330 	}
1331 
1332 /* finally added */
1333 	int hole = alloc_node_slot(path);
1334 	if (-1 == hole){
1335 		verbose_print(
1336 			"input: dropped %s due to errors during scan.", path);
1337 		close(fd);
1338 		return;
1339 	}
1340 
1341 	iodev.n_devs++;
1342 	node.path = strdup(path);
1343 	iodev.pollset[hole].fd = fd;
1344 	iodev.pollset[hole].events = POLLIN | POLLERR | POLLHUP;
1345 	iodev.pollset[hole + iodev.sz_nodes].fd = BADFD;
1346 	send_device_added(ctx, &node);
1347 
1348 /* had to defer led device creation until now because we didn't
1349  * know if there's a slot for it or not, the pollset actually is
1350  * twice the expected size, one for the main device and one for
1351  * the possible led controller */
1352 	if (add_led != -1){
1353 		setup_led(&node, add_led, fd);
1354 		if (node.led.gotled){
1355 			iodev.pollset[hole+iodev.sz_nodes].fd = node.led.fds[0];
1356 		}
1357 	}
1358 	iodev.nodes[hole] = node;
1359 
1360 	if (node.type == DEVNODE_KEYBOARD){
1361 		const char* err;
1362 		platform_event_translation(node.devnum, EVENT_TRANSLATION_CLEAR, NULL, &err);
1363 	}
1364 
1365 	verbose_print("input: (%s:%s) added as type: %s",
1366 		path, node.label, lookup_type(node.type));
1367 
1368 	return;
1369 }
1370 
1371 #undef bit_isset
1372 #undef bit_ofs
1373 #undef bit_longn
1374 #undef bit_count
1375 
platform_event_rescan_idev(struct arcan_evctx * ctx)1376 void platform_event_rescan_idev(struct arcan_evctx* ctx)
1377 {
1378 	char ibuf [strlen(notify_scan_dir) + sizeof("/*")];
1379 	glob_t res = {0};
1380 	snprintf(ibuf, sizeof(ibuf), "%s/*", notify_scan_dir);
1381 
1382 	if (glob(ibuf, 0, NULL, &res) == 0){
1383 		char** beg = res.gl_pathv;
1384 
1385 		while(*beg){
1386 			int fd = platform_device_open(*beg, O_NONBLOCK | O_RDWR);
1387 			if (-1 != fd)
1388 				got_device(ctx, fd, *beg);
1389 			beg++;
1390 		}
1391 
1392 		globfree(&res);
1393 	}
1394 
1395 	verbose_print("input: couldn't scan %s", notify_scan_dir);
1396 }
1397 
update_state(int code,bool state,unsigned * statev)1398 static void update_state(int code, bool state, unsigned* statev)
1399 {
1400 	int modifier = 0;
1401 
1402 	switch (klut[code]){
1403 	case K_LSHIFT:
1404 		modifier = ARKMOD_LSHIFT;
1405 	break;
1406 	case K_RSHIFT:
1407 		modifier = ARKMOD_RSHIFT;
1408 	break;
1409 	case K_LALT:
1410 		modifier = ARKMOD_LALT;
1411 	break;
1412 	case K_RALT:
1413 		modifier = ARKMOD_RALT;
1414 	break;
1415 	case K_LCTRL:
1416 		modifier = ARKMOD_LCTRL;
1417 	break;
1418 	case K_RCTRL:
1419 		modifier = ARKMOD_RCTRL;
1420 	break;
1421 	case K_LMETA:
1422 		modifier = ARKMOD_LMETA;
1423 	break;
1424 	case K_RMETA:
1425 		modifier = ARKMOD_RMETA;
1426 	break;
1427 	case K_CAPSLOCK:
1428 		modifier = ARKMOD_CAPS;
1429 	break;
1430 	case K_COMPOSE:
1431 		modifier = ARKMOD_MODE;
1432 	break;
1433 	default:
1434 		return;
1435 	}
1436 
1437 	if (state)
1438 		*statev |= modifier;
1439 	else
1440 		*statev &= ~modifier;
1441 }
1442 
defhandler_kbd(struct arcan_evctx * out,struct devnode * node)1443 static void defhandler_kbd(
1444 	struct arcan_evctx* out, struct devnode* node)
1445 {
1446 	struct input_event inev[64];
1447 	ssize_t evs = read(node->handle, &inev, sizeof(inev));
1448 
1449 	if (-1 == evs){
1450 		if (errno != EINTR && errno != EAGAIN)
1451 			disconnect(out, node);
1452 	}
1453 
1454 	if (evs < 0 || evs < sizeof(struct input_event))
1455 		return;
1456 
1457 	arcan_event newev = {
1458 		.category = EVENT_IO,
1459 		.io = {
1460 			.kind = EVENT_IO_BUTTON,
1461 			.devid = node->devnum,
1462 			.datatype = EVENT_IDATATYPE_TRANSLATED,
1463 			.devkind = EVENT_IDEVKIND_KEYBOARD,
1464 		}
1465 	};
1466 
1467 	for (size_t i = 0; i < evs / sizeof(struct input_event); i++){
1468 		switch(inev[i].type){
1469 		case EV_KEY:
1470 		newev.io.input.translated.scancode = inev[i].code;
1471 		newev.io.input.translated.keysym = lookup_keycode(inev[i].code);
1472 		newev.io.input.translated.modifiers = node->keyboard.state;
1473 		update_state(inev[i].code, inev[i].value != 0, &node->keyboard.state);
1474 /* possible checkpoint for adding other keyboard layout support here */
1475 		newev.io.subid = inev[i].code;
1476 
1477 /* default 'fallback' translation */
1478 		uint16_t code = lookup_character(inev[i].code, node->keyboard.state, true);
1479 		if (code)
1480 			to_utf8(code, newev.io.input.translated.utf8);
1481 
1482 /* virtual terminal switching for press on LCTRL+LALT+Fn. should possibly have
1483  * more advanced config here to limit # of eligible devices and change
1484  * combination, and option to disable the thing entirely because it is
1485  * just terrible */
1486 		if ((node->keyboard.state == (ARKMOD_LALT | ARKMOD_LCTRL)) &&
1487 			inev[i].code >= KEY_F1 && inev[i].code <= KEY_F10 && inev[i].value != 0){
1488 			platform_device_release("TTY", inev[i].code - KEY_F1 + 1);
1489 		}
1490 
1491 /* Feed layout statemachine, try to get a translation out of it. Since we
1492  * don't have support for xkeyboard symbols, we either make due with the normal
1493  * kernel keycode to SDL keysym or go with the keyboard layout and try to
1494  * translate that into SDL. */
1495 #ifdef HAVE_XKBCOMMON
1496 		if (node->keyboard.xkb_state){
1497 			memset(newev.io.input.translated.utf8, '\0', 5);
1498 			if (inev[i].value == 0){
1499 				xkb_state_update_key(
1500 					node->keyboard.xkb_state, inev[i].code + 8, XKB_KEY_UP);
1501 			}
1502 			else if (inev[i].value == 1 || (inev[i].value == 2 && xkb_keymap_key_repeats(
1503 				node->keyboard.xkb_layout, inev[i].code+8))){
1504 				xkb_state_key_get_utf8(node->keyboard.xkb_state,
1505 					inev[i].code + 8, (char*) newev.io.input.translated.utf8, 5);
1506 				xkb_state_update_key(
1507 					node->keyboard.xkb_state, inev[i].code + 8, XKB_KEY_DOWN);
1508 			}
1509 		}
1510 #endif
1511 
1512 /* auto-repeat, may get even if we are not in this state because of broken
1513  * drivers or failed mode-setting. */
1514 		if (inev[i].value == 2){
1515 			if (iodev.period){
1516 				newev.io.input.translated.modifiers |= ARKMOD_REPEAT;
1517 				newev.io.input.translated.active = false;
1518 				arcan_event_enqueue(out, &newev);
1519 				newev.io.input.translated.active = true;
1520 				arcan_event_enqueue(out, &newev);
1521 			}
1522 		}
1523 		else{
1524 			newev.io.input.translated.active = inev[i].value != 0;
1525 			arcan_event_enqueue(out, &newev);
1526 		}
1527 
1528 		break;
1529 
1530 		default:
1531 		break;
1532 		}
1533 
1534 	}
1535 }
1536 
flush_pending(struct arcan_evctx * ctx,struct devnode * node)1537 static void flush_pending(
1538 	struct arcan_evctx* ctx, struct devnode* node)
1539 {
1540 	arcan_event newev = {
1541 		.category = EVENT_IO,
1542 		.io = {
1543 		.label = "touch",
1544 		.devid = node->devnum,
1545 		.subid = node->touch.ind + 128,
1546 		.kind = EVENT_IO_TOUCH,
1547 		.devkind = EVENT_IDEVKIND_TOUCHDISP,
1548 		.datatype = EVENT_IDATATYPE_TOUCH
1549 		}
1550 	};
1551 
1552 	verbose_print("kind=touch:device=%d:base=%d", node->devnum, node->touch.ind);
1553 
1554 	newev.io.input.touch.active = node->touch.active;
1555 	newev.io.input.touch.x = node->touch.x;
1556 	newev.io.input.touch.y = node->touch.y;
1557 	newev.io.input.touch.pressure = node->touch.pressure;
1558 	newev.io.input.touch.size = node->touch.size;
1559 
1560 	arcan_event_enqueue(ctx, &newev);
1561 	node->touch.pending = false;
1562 	node->touch.active = true;
1563 }
1564 
decode_mt(struct arcan_evctx * ctx,struct devnode * node,int code,int val)1565 static void decode_mt(struct arcan_evctx* ctx,
1566 	struct devnode* node, int code, int val)
1567 {
1568 /* there are multiple protocols and mappings for this that we don't
1569  * account for here, move it to a toch event with the basic information
1570  * and let higher layers deal with it */
1571 	int newind = -1;
1572 
1573 	switch(code){
1574 	case ABS_X:
1575 		if (node->touch.ind != 0 && node->touch.pending)
1576 			flush_pending(ctx, node);
1577 
1578 		node->touch.ind = 0;
1579 		node->touch.x = val;
1580 		node->touch.pending = true;
1581 	break;
1582 	case ABS_Y:
1583 		if (node->touch.ind != 0 && node->touch.pending)
1584 			flush_pending(ctx, node);
1585 
1586 		node->touch.ind = 0;
1587 		node->touch.y = val;
1588 		node->touch.pending = true;
1589 	break;
1590 	case ABS_MT_PRESSURE:
1591 		node->touch.pressure = val;
1592 	break;
1593 	case ABS_MT_POSITION_X:
1594 		node->touch.x = val;
1595 		node->touch.pending = true;
1596 	break;
1597 	case ABS_MT_POSITION_Y:
1598 		node->touch.y = val;
1599 		node->touch.pending = true;
1600 	break;
1601 	case ABS_DISTANCE:
1602 		node->touch.pressure = val;
1603 	break;
1604 	case ABS_MT_TRACKING_ID:
1605 		if (-1 == val){
1606 			node->touch.active = false;
1607 			node->touch.pending = true;
1608 			flush_pending(ctx, node);
1609 		}
1610 		else
1611 			; /* we don't distingush between IDs, only SLOTs */
1612 	break;
1613 	case ABS_MT_SLOT:
1614 		if (node->touch.pending && node->touch.ind != val)
1615 			flush_pending(ctx, node);
1616 		node->touch.ind = val;
1617 	break;
1618 	default:
1619 		verbose_print("dev=%d:type=multitouch:code=%d"
1620 			":status=unknown", (int) node->devnum, code);
1621 	break;
1622 	}
1623 }
1624 
decode_hat(struct arcan_evctx * ctx,struct devnode * node,int ind,int val)1625 static void decode_hat(struct arcan_evctx* ctx,
1626 	struct devnode* node, int ind, int val)
1627 {
1628 	arcan_event newev = {
1629 		.category = EVENT_IO,
1630 		.io = {
1631 			.label = "gamepad",
1632 			.kind = EVENT_IO_BUTTON,
1633 			.devkind = EVENT_IDEVKIND_GAMEDEV,
1634 			.datatype = EVENT_IDATATYPE_DIGITAL
1635 		}
1636 	};
1637 
1638 	ind *= 2;
1639 	const int base = 64;
1640 
1641 	newev.io.devid = node->devnum;
1642 
1643 /* clamp */
1644 	if (val < 0)
1645 		val = -1;
1646 	else if (val > 0)
1647 		val = 1;
1648 	else {
1649 /* which of the two possibilities was released? */
1650 		newev.io.input.digital.active = false;
1651 
1652 		if (node->game.hats[ind] != 0){
1653 			newev.io.subid = base + ind;
1654 			node->game.hats[ind] = 0;
1655 			arcan_event_enqueue(ctx, &newev);
1656 		}
1657 
1658 		if (node->game.hats[ind+1] != 0){
1659 			newev.io.subid = base + ind + 1;
1660 			node->game.hats[ind+1] = 0;
1661 			arcan_event_enqueue(ctx, &newev);
1662 		}
1663 
1664 		return;
1665 	}
1666 
1667 	if (val > 0)
1668 		ind++;
1669 
1670 	node->game.hats[ind] = val;
1671 	newev.io.input.digital.active = true;
1672 	newev.io.subid = base + ind;
1673 	arcan_event_enqueue(ctx, &newev);
1674 }
1675 
defhandler_game(struct arcan_evctx * ctx,struct devnode * node)1676 static void defhandler_game(struct arcan_evctx* ctx, struct devnode* node)
1677 {
1678 	struct input_event inev[64];
1679 	ssize_t evs = read(node->handle, &inev, sizeof(inev));
1680 
1681 	if (-1 == evs){
1682 		if (errno != EINTR && errno != EAGAIN)
1683 			disconnect(ctx, node);
1684 	}
1685 
1686 	if (evs < 0 || evs < sizeof(struct input_event))
1687 		return;
1688 
1689 	arcan_event newev = {
1690 		.category = EVENT_IO,
1691 		.io = {
1692 			.label = "gamepad",
1693 			.devkind = EVENT_IDEVKIND_GAMEDEV
1694 		}
1695 	};
1696 
1697 	short samplev;
1698 
1699 	for (size_t i = 0; i < evs / sizeof(struct input_event); i++){
1700 		switch(inev[i].type){
1701 		case EV_KEY:
1702 			if (inev[i].code >= BTN_TOUCH)
1703 				inev[i].code -= BTN_TOUCH;
1704 			else if (inev[i].code >= BTN_JOYSTICK)
1705 				inev[i].code -= BTN_JOYSTICK;
1706 			else if (inev[i].code >= BTN_MOUSE)
1707 				inev[i].code -= BTN_MOUSE - 1;
1708 			if (node->hnd.button_mask && inev[i].code <= 64 &&
1709 				( (node->hnd.button_mask >> inev[i].code) & 1) )
1710 				continue;
1711 
1712 			newev.io.kind = EVENT_IO_BUTTON;
1713 			newev.io.datatype = EVENT_IDATATYPE_DIGITAL;
1714 			newev.io.input.digital.active = inev[i].value;
1715 			newev.io.subid = inev[i].code;
1716 			newev.io.devid = node->devnum;
1717 			arcan_event_enqueue(ctx, &newev);
1718 		break;
1719 
1720 		case EV_SW:
1721 			newev.io.kind = EVENT_IO_BUTTON;
1722 			newev.io.datatype = EVENT_IDATATYPE_DIGITAL;
1723 			newev.io.input.digital.active = inev[i].value;
1724 			newev.io.subid = inev[i].code;
1725 			newev.io.devid = node->devnum;
1726 			arcan_event_enqueue(ctx, &newev);
1727 		break;
1728 
1729 		case EV_REL:
1730 		case EV_ABS:
1731 /* is the axis currently masked? */
1732 			if (node->hnd.axis_mask && inev[i].code <= 64 &&
1733 				( (node->hnd.axis_mask >> inev[i].code) & 1) ){
1734 				continue;
1735 			}
1736 			verbose_print("rel? %d - %d\n", inev[i].type, inev[i].code);
1737 
1738 			if (inev[i].code >= ABS_HAT0X && inev[i].code <= ABS_HAT3Y){
1739 				decode_hat(ctx, node, inev[i].code - ABS_HAT0X, inev[i].value);
1740 			}
1741 			else if (inev[i].code < node->game.axes &&
1742 				process_axis(ctx,
1743 				&node->game.adata[inev[i].code], inev[i].value, &samplev)){
1744 				newev.io.kind = EVENT_IO_AXIS_MOVE;
1745 				newev.io.datatype = EVENT_IDATATYPE_ANALOG;
1746 				newev.io.input.analog.gotrel = inev[i].type == EV_REL;
1747 				newev.io.subid = inev[i].code;
1748 				newev.io.devid = node->devnum;
1749 				newev.io.input.analog.axisval[0] = samplev;
1750 				newev.io.input.analog.nvalues = 2;
1751 				arcan_event_enqueue(ctx, &newev);
1752 			}
1753 			else if ((inev[i].code >= ABS_X && inev[i].code <= ABS_Y) ||
1754 				(inev[i].code >= ABS_MT_SLOT && inev[i].code <= ABS_MT_TOOL_Y)){
1755 				decode_mt(ctx, node, inev[i].code, inev[i].value);
1756 			}
1757 /* though we do reserve axis slots for the relative bits, there is no actual
1758  * filter set to them other than the the mask used above */
1759 			else if (
1760 				inev[i].code == REL_X ||
1761 				inev[i].code == REL_Y ||
1762 				inev[i].code == REL_DIAL ||
1763 				inev[i].code == REL_Z ||
1764 				inev[i].code == REL_RZ ||
1765 				inev[i].code == REL_RX ||
1766 				inev[i].code == REL_RY)
1767 			{
1768 				newev.io.kind = EVENT_IO_AXIS_MOVE;
1769 				newev.io.datatype = EVENT_IDATATYPE_ANALOG;
1770 				newev.io.input.analog.gotrel = true;
1771 				newev.io.subid = inev[i].code;
1772 				newev.io.devid = node->devnum;
1773 				newev.io.input.analog.axisval[0] = inev[i].value;
1774 				newev.io.input.analog.nvalues = 1;
1775 				arcan_event_enqueue(ctx, &newev);
1776 			}
1777 			else {
1778 				verbose_print("kind=game:device=%d:rel:code=%d:status=unknown", node->devnum, inev[i].code);
1779 			}
1780 		break;
1781 
1782 		case EV_SYN:
1783 		case EV_REP:
1784 			if (node->touch.pending)
1785 				flush_pending(ctx, node);
1786 		break;
1787 
1788 		default:
1789 			verbose_print("kind=game:device=%d:type=%d:status=unknown", node->devnum, inev[i].type);
1790 		break;
1791 		}
1792 	}
1793 
1794 }
1795 
code_to_mouse(int code)1796 static inline short code_to_mouse(int code)
1797 {
1798 	return (code < BTN_MOUSE || code >= BTN_JOYSTICK) ?
1799 		-1 : (code - BTN_MOUSE + 1);
1800 }
1801 
defhandler_mouse(struct arcan_evctx * ctx,struct devnode * node)1802 static void defhandler_mouse(struct arcan_evctx* ctx,
1803 	struct devnode* node)
1804 {
1805 	struct input_event inev[64];
1806 
1807 	ssize_t evs = read(node->handle, &inev, sizeof(inev));
1808 
1809 	if (-1 == evs){
1810 		if (errno != EINTR && errno != EAGAIN)
1811 			disconnect(ctx, node);
1812 	}
1813 
1814 	if (evs < 0 || evs < sizeof(struct input_event))
1815 		return;
1816 
1817 	arcan_event newev = {
1818 		.category = EVENT_IO,
1819 		.io = {
1820 			.label = "mouse",
1821 			.devkind = EVENT_IDEVKIND_MOUSE,
1822 		}
1823 	};
1824 
1825 	short samplev;
1826 	newev.io.devid = node->devnum;
1827 
1828 	for (size_t i = 0; i < evs / sizeof(struct input_event); i++){
1829 		int vofs = 0;
1830 
1831 		switch(inev[i].type){
1832 		case EV_KEY:
1833 			samplev = code_to_mouse(inev[i].code);
1834 			if (samplev < 0)
1835 				continue;
1836 
1837 			newev.io.kind = EVENT_IO_BUTTON;
1838 			newev.io.datatype = EVENT_IDATATYPE_DIGITAL;
1839 			newev.io.input.digital.active = inev[i].value;
1840 			newev.io.subid = samplev;
1841 
1842 			arcan_event_enqueue(ctx, &newev);
1843 		break;
1844 		case EV_REL:
1845 			switch (inev[i].code){
1846 			case REL_HWHEEL:
1847 				vofs += 2;
1848 			case REL_WHEEL:
1849 				newev.io.kind = EVENT_IO_BUTTON;
1850 				newev.io.datatype = EVENT_IDATATYPE_DIGITAL;
1851 				newev.io.input.digital.active = 1;
1852 				newev.io.subid = vofs + (inev[i].value > 0 ? 256 : 257);
1853 				arcan_event_enqueue(ctx, &newev);
1854 				newev.io.input.digital.active = 0;
1855 				arcan_event_enqueue(ctx, &newev);
1856 			break;
1857 
1858 			case REL_X:
1859 				if (process_axis(ctx, &node->cursor.flt[0], inev[i].value, &samplev)){
1860 					samplev = inev[i].value;
1861 
1862 					node->cursor.mx = ((int)node->cursor.mx + samplev < 0) ?
1863 						0 : node->cursor.mx + samplev;
1864 
1865 					newev.io.kind = EVENT_IO_AXIS_MOVE;
1866 					newev.io.datatype = EVENT_IDATATYPE_ANALOG;
1867 					newev.io.input.analog.gotrel = true;
1868 					newev.io.subid = 0;
1869 					newev.io.input.analog.axisval[0] = samplev;
1870 					newev.io.input.analog.axisval[1] = node->cursor.mx;
1871 					newev.io.input.analog.nvalues = 2;
1872 
1873 					arcan_event_enqueue(ctx, &newev);
1874 				}
1875 			break;
1876 			case REL_Y:
1877 				if (process_axis(ctx, &node->cursor.flt[1], inev[i].value, &samplev)){
1878 					node->cursor.my = ((int)node->cursor.my + samplev < 0) ?
1879 						0 : node->cursor.my + samplev;
1880 
1881 					newev.io.kind = EVENT_IO_AXIS_MOVE;
1882 					newev.io.datatype = EVENT_IDATATYPE_ANALOG;
1883 					newev.io.input.analog.gotrel = true;
1884 					newev.io.subid = 1;
1885 					newev.io.input.analog.axisval[0] = samplev;
1886 					newev.io.input.analog.axisval[1] = node->cursor.my;
1887 					newev.io.input.analog.nvalues = 2;
1888 
1889 					arcan_event_enqueue(ctx, &newev);
1890 				}
1891 			break;
1892 			default:
1893 			break;
1894 			}
1895 		break;
1896 		case EV_ABS:
1897 		break;
1898 		}
1899 	}
1900 }
1901 
defhandler_null(struct arcan_evctx * out,struct devnode * node)1902 static void defhandler_null(struct arcan_evctx* out,
1903 	struct devnode* node)
1904 {
1905 	char nbuf[256];
1906 	ssize_t evs = read(node->handle, nbuf, sizeof(nbuf));
1907 	if (-1 == evs){
1908 		if (errno != EINTR && errno != EAGAIN)
1909 			disconnect(out, node);
1910 	}
1911 }
1912 
platform_event_devlabel(int devid)1913 const char* platform_event_devlabel(int devid)
1914 {
1915 	struct devnode* node = lookup_devnode(devid);
1916 	if (!node)
1917 		return NULL;
1918 
1919 	return node->label;
1920 }
1921 
1922 /*
1923  * note, this do not currently save/restore individual options between
1924  * init/deinit sessions, which is needed for virtual terminal switching
1925  * and external_launch.
1926  */
platform_event_reset(struct arcan_evctx * ctx)1927 void platform_event_reset(struct arcan_evctx* ctx)
1928 {
1929 
1930 }
1931 
platform_event_deinit(struct arcan_evctx * ctx)1932 void platform_event_deinit(struct arcan_evctx* ctx)
1933 {
1934 	platform_device_release("TTY", -1);
1935 
1936 /* note, we purposely leak (let it disappear on close) to avoid the races and
1937  * interactions that come from TTY switching -> deinit -> signal -> init */
1938 
1939 	if (gstate.notify != -1){
1940 		close(gstate.notify);
1941 		gstate.notify = -1;
1942 	}
1943 
1944 /* note, for VT switching this means that the state of devices when it comes
1945  * to filtering etc. do not persist between external launches, should rework
1946  * this */
1947 	for (size_t i = 0; i < iodev.n_devs; i++){
1948 		if (iodev.nodes[i].handle > 0){
1949 			verbose_print("closing %zu:%d", i, iodev.nodes[i].handle);
1950 			close(iodev.nodes[i].handle);
1951 			memset(&iodev.nodes[i], '\0', sizeof(struct devnode));
1952 			iodev.nodes[i].handle = -1;
1953 		}
1954 	}
1955 
1956 	iodev.n_devs = 0;
1957 	gstate.init = false;
1958 }
1959 
platform_device_lock(int devind,bool state)1960 void platform_device_lock(int devind, bool state)
1961 {
1962 	struct devnode* node = lookup_devnode(devind);
1963 	if (!node || !node->handle)
1964 		return;
1965 
1966 	ioctl(node->handle, EVIOCGRAB, state? 1 : 0);
1967 
1968 /*
1969  * doesn't make sense outside some window systems, might be useful to propagate
1970  * further to device locking on systems that are less forgiving.
1971  */
1972 }
1973 
platform_event_capabilities(const char ** out)1974 enum PLATFORM_EVENT_CAPABILITIES platform_event_capabilities(const char** out)
1975 {
1976 	enum PLATFORM_EVENT_CAPABILITIES rv = 0;
1977 	if (out)
1978 		*out = "evdev";
1979 
1980 	for (size_t i = 0; i < iodev.n_devs; i++){
1981 		if (iodev.nodes[i].handle)
1982 			switch(iodev.nodes[i].type){
1983 /* don't have better granularity in this step at the moment */
1984 			case DEVNODE_SENSOR:
1985 				rv |= ACAP_POSITION | ACAP_ORIENTATION;
1986 			break;
1987 			case DEVNODE_MOUSE:
1988 				rv |= ACAP_MOUSE;
1989 			break;
1990 			case DEVNODE_GAME:
1991 				rv |= ACAP_GAMING;
1992 			break;
1993 			case DEVNODE_KEYBOARD:
1994 				rv |= ACAP_TRANSLATED;
1995 			break;
1996 			case DEVNODE_TOUCH:
1997 				rv |= ACAP_TOUCH;
1998 			break;
1999 			default:
2000 			break;
2001 		}
2002 	}
2003 
2004 	return rv;
2005 }
2006 
platform_event_envopts()2007 const char** platform_event_envopts()
2008 {
2009 	return (const char**) envopts;
2010 }
2011 
2012 /*
2013  * most of this is done priv-side, it is just the actual tty device to use and
2014  * control that is of importance as the privilege side keeps track of the first
2015  * TTY marked device that was opened as use that for the special 'TTY' name
2016  * later on release requests.
2017  */
find_tty()2018 static void find_tty()
2019 {
2020 /* first, check if the env. defines a specific TTY device to use and try that */
2021 	const char* newtty = NULL;
2022 	int tty = -1;
2023 	bool scantty = true;
2024 
2025 	uintptr_t tag;
2026 	cfg_lookup_fun get_config = platform_config_lookup(&tag);
2027 	char* ttydev;
2028 	if (get_config("event_tty_override", 0, &ttydev, tag) && ttydev){
2029 		int fd = platform_device_open(ttydev, O_RDWR);
2030 		scantty = false;
2031 		if (-1 == fd)
2032 			arcan_warning("couldn't open TTYOVERRIDE %s, reason: %s\n",
2033 				newtty, strerror(errno));
2034 		else
2035 			tty = fd;
2036 		free(ttydev);
2037 	}
2038 
2039 /* Failing that, try and find what tty we might be on -- some might redirect
2040  * stdin to something else and then it is not a valid tty to work on. Which,
2041  * of course, brings us back to the special kid in the class, sysfs. */
2042 	if (!isatty(tty) && scantty){
2043 		FILE* fpek = fopen("/sys/class/tty/tty0/active", "r");
2044 		if (fpek){
2045 			char line[32] = "/dev/";
2046 			if (fgets(line+5, 32-5, fpek)){
2047 				char* endl = strrchr(line, '\n');
2048 				if (endl)
2049 					*endl = '\0';
2050 				tty = platform_device_open(line, O_RDWR);
2051 			}
2052 			fclose(fpek);
2053 		}
2054 	}
2055 }
2056 
platform_event_preinit()2057 void platform_event_preinit()
2058 {
2059 }
2060 
platform_event_init(arcan_evctx * ctx)2061 void platform_event_init(arcan_evctx* ctx)
2062 {
2063 	uintptr_t tag;
2064 
2065 	cfg_lookup_fun get_config = platform_config_lookup(&tag);
2066 
2067 #ifdef __LINUX
2068 	gstate.notify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
2069 #endif
2070 
2071 	init_keyblut();
2072 #ifdef HAVE_XKBCOMMON
2073 	xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
2074 #endif
2075 
2076 	if (!notify_scan_dir)
2077 		notify_scan_dir = strdup(NOTIFY_SCAN_DIR);
2078 
2079 	find_tty();
2080 
2081 	char* newsd;
2082 	if (get_config("event_scandir", 0, &newsd, tag) && newsd){
2083 		free(notify_scan_dir);
2084 		notify_scan_dir = newsd;
2085 	}
2086 
2087 /* chances are the CREATE events are actually racey, but with the
2088  * _device_open refactor this won't really matter as the suid part
2089  * allows us access anyway */
2090 #ifdef __LINUX
2091 	if (-1 == gstate.notify || inotify_add_watch(
2092 		gstate.notify, notify_scan_dir, IN_CREATE) == -1){
2093 		arcan_warning("inotify initialization failure (%s),"
2094 			"	device discovery disabled.", strerror(errno));
2095 
2096 		if (-1 != gstate.notify){
2097 			close(gstate.notify);
2098 			gstate.notify = -1;
2099 		}
2100 	}
2101 #elif __FreeBSD__
2102 /* there is a way to get devd to cooperate */
2103 #else
2104 #endif
2105 
2106 	platform_event_rescan_idev(ctx);
2107 }
2108