evdev.c revision 7af5e6593f95d0bcb2618c91884bd7349148e918
1/*
2 * Copyright (c) 2015 Etienne Gemsa <etienne.gemsa@lse.epita.fr>
3 * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "defs.h"
30
31#ifdef HAVE_LINUX_INPUT_H
32
33#include DEF_MPERS_TYPE(struct_ff_effect)
34
35# include <linux/ioctl.h>
36# include <linux/input.h>
37
38typedef struct ff_effect struct_ff_effect;
39
40#endif /* HAVE_LINUX_INPUT_H */
41
42#include MPERS_DEFS
43
44#ifdef HAVE_LINUX_INPUT_H
45
46# include "xlat/evdev_autorepeat.h"
47# include "xlat/evdev_ff_status.h"
48# include "xlat/evdev_ff_types.h"
49# include "xlat/evdev_keycode.h"
50# include "xlat/evdev_leds.h"
51# include "xlat/evdev_misc.h"
52# include "xlat/evdev_mtslots.h"
53# include "xlat/evdev_prop.h"
54# include "xlat/evdev_relative_axes.h"
55# include "xlat/evdev_snd.h"
56# include "xlat/evdev_switch.h"
57# include "xlat/evdev_sync.h"
58
59# ifndef SYN_MAX
60#  define SYN_MAX 0xf
61# endif
62
63static void
64decode_envelope(void *const data)
65{
66	const struct ff_envelope *const envelope = data;
67
68	tprintf(", envelope={attack_length=%" PRIu16
69		", attack_level=%" PRIu16
70		", fade_length=%" PRIu16
71		", fade_level=%#x}",
72		envelope->attack_length,
73		envelope->attack_level,
74		envelope->fade_length,
75		envelope->fade_level);
76}
77
78static int
79ff_effect_ioctl(struct tcb *tcp, long arg)
80{
81	tprints(", ");
82
83	struct_ff_effect ffe;
84
85	if (umove_or_printaddr(tcp, arg, &ffe))
86		return 1;
87
88	tprints("{type=");
89	printxval(evdev_ff_types, ffe.type, "FF_???");
90	tprintf(", id=%" PRIu16
91		", direction=%" PRIu16 ", ",
92		ffe.id,
93		ffe.direction);
94
95	if (abbrev(tcp)) {
96		tprints("...}");
97		return 1;
98	}
99
100	tprintf("trigger={button=%" PRIu16
101		", interval=%" PRIu16 "}"
102		", replay={length=%" PRIu16
103		", delay=%" PRIu16 "}",
104		ffe.trigger.button,
105		ffe.trigger.interval,
106		ffe.replay.length,
107		ffe.replay.delay);
108
109	switch (ffe.type) {
110		case FF_CONSTANT:
111			tprintf(", constant={level=%" PRId16,
112				ffe.u.constant.level);
113			decode_envelope(&ffe.u.constant.envelope);
114			tprints("}");
115			break;
116		case FF_RAMP:
117			tprintf(", ramp={start_level=%" PRId16
118				", end_level=%" PRId16,
119				ffe.u.ramp.start_level,
120				ffe.u.ramp.end_level);
121			decode_envelope(&ffe.u.ramp.envelope);
122			tprints("}");
123			break;
124		case FF_PERIODIC:
125			tprintf(", periodic={waveform=%" PRIu16
126				", period=%" PRIu16
127				", magnitude=%" PRId16
128				", offset=%" PRId16
129				", phase=%" PRIu16,
130				ffe.u.periodic.waveform,
131				ffe.u.periodic.period,
132				ffe.u.periodic.magnitude,
133				ffe.u.periodic.offset,
134				ffe.u.periodic.phase);
135			decode_envelope(&ffe.u.periodic.envelope);
136			tprintf(", custom_len=%u, custom_data=",
137				ffe.u.periodic.custom_len);
138			printaddr((unsigned long) ffe.u.periodic.custom_data);
139			tprints("}");
140			break;
141		case FF_RUMBLE:
142			tprintf(", rumble={strong_magnitude=%" PRIu16
143				", weak_magnitude=%" PRIu16 "}",
144				ffe.u.rumble.strong_magnitude,
145				ffe.u.rumble.weak_magnitude);
146			break;
147		default:
148			break;
149	}
150
151	tprints("}");
152
153	return 1;
154}
155
156static int
157abs_ioctl(struct tcb *tcp, long arg)
158{
159	tprints(", ");
160
161	struct input_absinfo absinfo;
162
163	if (!umove_or_printaddr(tcp, arg, &absinfo)) {
164		tprintf("{value=%u"
165			", minimum=%u, ",
166			absinfo.value,
167			absinfo.minimum);
168
169		if (!abbrev(tcp)) {
170			tprintf("maximum=%u"
171				", fuzz=%u"
172				", flat=%u",
173				absinfo.maximum,
174				absinfo.fuzz,
175				absinfo.flat);
176# ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION
177			tprintf(", resolution=%u",
178				absinfo.resolution);
179# endif
180		} else {
181			tprints("...");
182		}
183
184		tprints("}");
185	}
186
187	return 1;
188}
189
190static int
191keycode_ioctl(struct tcb *tcp, long arg)
192{
193	tprints(", ");
194
195	unsigned int keycode[2];
196
197	if (!umove_or_printaddr(tcp, arg, &keycode)) {
198		tprintf("[%u, ", keycode[0]);
199		printxval(evdev_keycode, keycode[1], "KEY_???");
200		tprints("]");
201	}
202
203	return 1;
204}
205
206# ifdef EVIOCGKEYCODE_V2
207static int
208keycode_V2_ioctl(struct tcb *tcp, long arg)
209{
210	tprints(", ");
211
212	struct input_keymap_entry ike;
213
214	if (umove_or_printaddr(tcp, arg, &ike))
215		return 1;
216
217	tprintf("{flags=%" PRIu8
218		", len=%" PRIu8 ", ",
219		ike.flags,
220		ike.len);
221
222	if (!abbrev(tcp)) {
223		unsigned int i;
224
225		tprintf("index=%" PRIu16 ", keycode=", ike.index);
226		printxval(evdev_keycode, ike.keycode, "KEY_???");
227		tprints(", scancode=[");
228		for (i = 0; i < ARRAY_SIZE(ike.scancode); i++) {
229			if (i > 0)
230				tprints(", ");
231			tprintf("%" PRIx8, ike.scancode[i]);
232		}
233		tprints("]");
234	} else {
235		tprints("...");
236	}
237
238	tprints("}");
239
240	return 1;
241}
242# endif /* EVIOCGKEYCODE_V2 */
243
244static int
245getid_ioctl(struct tcb *tcp, long arg)
246{
247	tprints(", ");
248
249	struct input_id id;
250
251	if (!umove_or_printaddr(tcp, arg, &id))
252		tprintf("{ID_BUS=%" PRIu16
253			", ID_VENDOR=%" PRIu16
254			", ID_PRODUCT=%" PRIu16
255			", ID_VERSION=%" PRIu16 "}",
256			id.bustype,
257			id.vendor,
258			id.product,
259			id.version);
260
261	return 1;
262}
263
264static int
265decode_bitset(struct tcb *tcp, long arg, const struct xlat decode_nr[],
266	      const unsigned int max_nr, const char *dflt)
267{
268	tprints(", ");
269
270	unsigned int size;
271	if ((unsigned long) tcp->u_rval > max_nr)
272		size = max_nr;
273	else
274		size = tcp->u_rval;
275	char decoded_arg[size];
276
277	if (umove_or_printaddr(tcp, arg, &decoded_arg))
278		return 1;
279
280	tprints("[");
281
282	int bit_displayed = 0;
283	int i = next_set_bit(decoded_arg, 0, size);
284	if (i < 0) {
285		tprints(" 0 ");
286	} else {
287		printxval(decode_nr, i, dflt);
288
289		while ((i = next_set_bit(decoded_arg, i + 1, size)) > 0) {
290			if (abbrev(tcp) && bit_displayed >= 3) {
291				tprints(", ...");
292				break;
293			}
294			tprints(", ");
295			printxval(decode_nr, i, dflt);
296			bit_displayed++;
297		}
298	}
299
300	tprints("]");
301
302	return 1;
303}
304
305# ifdef EVIOCGMTSLOTS
306static int
307mtslots_ioctl(struct tcb *tcp, const unsigned int code, long arg)
308{
309	tprints(", ");
310
311	const size_t size = _IOC_SIZE(code) / sizeof(int);
312	if (!size) {
313		printaddr(arg);
314		return 1;
315	}
316
317	int buffer[size];
318
319	if (umove_or_printaddr(tcp, arg, &buffer))
320		return 1;
321
322	tprints("{code=");
323	printxval(evdev_mtslots, buffer[0], "ABS_MT_???");
324
325	tprints(", values=[");
326
327	unsigned int i;
328	for (i = 1; i < ARRAY_SIZE(buffer); i++)
329		tprintf("%s%d", i > 1 ? ", " : "", buffer[i]);
330
331	tprints("]}");
332
333	return 1;
334}
335# endif /* EVIOCGMTSLOTS */
336
337# if defined EVIOCGREP || defined EVIOCSREP
338static int
339repeat_ioctl(struct tcb *tcp, long arg)
340{
341	tprints(", ");
342	printpair_int(tcp, arg, "%u");
343	return 1;
344}
345# endif /* EVIOCGREP || EVIOCSREP */
346
347static int
348bit_ioctl(struct tcb *tcp, const unsigned int ev_nr, const long arg)
349{
350	switch (ev_nr) {
351		case EV_SYN:
352			return decode_bitset(tcp, arg, evdev_sync,
353					     SYN_MAX, "SYN_???");
354		case EV_KEY:
355			return decode_bitset(tcp, arg, evdev_keycode,
356					     KEY_MAX, "KEY_???");
357		case EV_REL:
358			return decode_bitset(tcp, arg, evdev_relative_axes,
359					     REL_MAX, "REL_???");
360		case EV_ABS:
361			return decode_bitset(tcp, arg, evdev_abs,
362					     ABS_MAX, "ABS_???");
363		case EV_MSC:
364			return decode_bitset(tcp, arg, evdev_misc,
365					     MSC_MAX, "MSC_???");
366# ifdef EV_SW
367		case EV_SW:
368			return decode_bitset(tcp, arg, evdev_switch,
369					     SW_MAX, "SW_???");
370# endif
371		case EV_LED:
372			return decode_bitset(tcp, arg, evdev_leds,
373					     LED_MAX, "LED_???");
374		case EV_SND:
375			return decode_bitset(tcp, arg, evdev_snd,
376					     SND_MAX, "SND_???");
377		case EV_REP:
378			return decode_bitset(tcp, arg, evdev_autorepeat,
379					     REP_MAX, "REP_???");
380		case EV_FF:
381			return decode_bitset(tcp, arg, evdev_ff_types,
382					     FF_MAX, "FF_???");
383		case EV_PWR:
384			tprints(", ");
385			printnum_int(tcp, arg, "%d");
386			return 1;
387		case EV_FF_STATUS:
388			return decode_bitset(tcp, arg, evdev_ff_status,
389					     FF_STATUS_MAX, "FF_STATUS_???");
390		default:
391			tprints(", ");
392			printaddr(arg);
393			return 1;
394	}
395}
396
397static int
398evdev_read_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
399{
400	/* fixed-number fixed-length commands */
401	switch (code) {
402		case EVIOCGVERSION:
403			tprints(", ");
404			printnum_int(tcp, arg, "%#x");
405			return 1;
406		case EVIOCGEFFECTS:
407			tprints(", ");
408			printnum_int(tcp, arg, "%u");
409			return 1;
410		case EVIOCGID:
411			return getid_ioctl(tcp, arg);
412# ifdef EVIOCGREP
413		case EVIOCGREP:
414			return repeat_ioctl(tcp, arg);
415# endif
416		case EVIOCGKEYCODE:
417			return keycode_ioctl(tcp, arg);
418# ifdef EVIOCGKEYCODE_V2
419		case EVIOCGKEYCODE_V2:
420			return keycode_V2_ioctl(tcp, arg);
421# endif
422	}
423
424	/* fixed-number variable-length commands */
425	switch (_IOC_NR(code)) {
426# ifdef EVIOCGMTSLOTS
427		case _IOC_NR(EVIOCGMTSLOTS(0)):
428			return mtslots_ioctl(tcp, code, arg);
429# endif
430		case _IOC_NR(EVIOCGNAME(0)):
431		case _IOC_NR(EVIOCGPHYS(0)):
432		case _IOC_NR(EVIOCGUNIQ(0)):
433			tprints(", ");
434			if (syserror(tcp))
435				printaddr(arg);
436			else
437				printstr(tcp, arg, tcp->u_rval);
438			return 1;
439# ifdef EVIOCGPROP
440		case _IOC_NR(EVIOCGPROP(0)):
441			return decode_bitset(tcp, arg, evdev_prop,
442					     INPUT_PROP_MAX, "PROP_???");
443# endif
444		case _IOC_NR(EVIOCGSND(0)):
445			return decode_bitset(tcp, arg, evdev_snd,
446					     SND_MAX, "SND_???");
447# ifdef EVIOCGSW
448		case _IOC_NR(EVIOCGSW(0)):
449			return decode_bitset(tcp, arg, evdev_switch,
450					     SW_MAX, "SW_???");
451# endif
452		case _IOC_NR(EVIOCGKEY(0)):
453			return decode_bitset(tcp, arg, evdev_keycode,
454					     KEY_MAX, "KEY_???");
455		case _IOC_NR(EVIOCGLED(0)):
456			return decode_bitset(tcp, arg, evdev_leds,
457					     LED_MAX, "LED_???");
458	}
459
460	/* multi-number fixed-length commands */
461	if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0)))
462		return abs_ioctl(tcp, arg);
463
464	/* multi-number variable-length commands */
465	if ((_IOC_NR(code) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
466		return bit_ioctl(tcp, _IOC_NR(code) & EV_MAX, arg);
467
468	return 0;
469}
470
471static int
472evdev_write_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
473{
474	/* fixed-number fixed-length commands */
475	switch (code) {
476# ifdef EVIOCSREP
477		case EVIOCSREP:
478			return repeat_ioctl(tcp, arg);
479# endif
480		case EVIOCSKEYCODE:
481			return keycode_ioctl(tcp, arg);
482# ifdef EVIOCSKEYCODE_V2
483		case EVIOCSKEYCODE_V2:
484			return keycode_V2_ioctl(tcp, arg);
485# endif
486		case EVIOCSFF:
487			return ff_effect_ioctl(tcp, arg);
488		case EVIOCRMFF:
489			tprintf(", %d", (int) arg);
490			return 1;
491		case EVIOCGRAB:
492# ifdef EVIOCREVOKE
493		case EVIOCREVOKE:
494# endif
495			tprintf(", %lu", arg);
496			return 1;
497# ifdef EVIOCSCLOCKID
498		case EVIOCSCLOCKID:
499			tprints(", ");
500			printnum_int(tcp, arg, "%u");
501			return 1;
502# endif
503	}
504
505	/* multi-number fixed-length commands */
506	if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0)))
507		return abs_ioctl(tcp, arg);
508
509	return 0;
510}
511
512MPERS_PRINTER_DECL(int, evdev_ioctl, struct tcb *tcp,
513		   const unsigned int code, const long arg)
514{
515	switch(_IOC_DIR(code)) {
516		case _IOC_READ:
517			if (entering(tcp))
518				return 0;
519			return evdev_read_ioctl(tcp, code, arg);
520		case _IOC_WRITE:
521			return evdev_write_ioctl(tcp, code, arg) | RVAL_DECODED;
522		default:
523			return RVAL_DECODED;
524	}
525}
526
527#endif /* HAVE_LINUX_INPUT_H */
528