evdev.c revision 19dadf94015523c6b8b7a2a0a8daff4151dafb07
1/*
2 * Copyright (c) 2015 Etienne Gemsa <etienne.gemsa@lse.epita.fr>
3 * Copyright (c) 2015 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#include <linux/input.h>
33#include "xlat/evdev_abs.h"
34#include "xlat/evdev_autorepeat.h"
35#include "xlat/evdev_ff_status.h"
36#include "xlat/evdev_ff_types.h"
37#include "xlat/evdev_keycode.h"
38#include "xlat/evdev_leds.h"
39#include "xlat/evdev_misc.h"
40#include "xlat/evdev_mtslots.h"
41#include "xlat/evdev_prop.h"
42#include "xlat/evdev_relative_axes.h"
43#include "xlat/evdev_snd.h"
44#include "xlat/evdev_switch.h"
45#include "xlat/evdev_sync.h"
46
47#ifndef SYN_MAX
48# define SYN_MAX 0xf
49#endif
50
51static void
52decode_envelope(struct ff_envelope *envelope)
53{
54	tprintf(", envelope={attack_length=%" PRIu16 ", attack_level=%" PRIu16
55		", fade_length=%" PRIu16 ", fade_level=%" PRIx32 "}",
56		envelope->attack_length,
57		envelope->attack_level,
58		envelope->fade_length,
59		envelope->fade_level);
60}
61
62static int
63ff_effect_ioctl(struct tcb *tcp, long arg)
64{
65	struct ff_effect ffe;
66
67	if (!verbose(tcp) || umove(tcp, arg, &ffe) < 0)
68		return 0;
69
70	tprints(", {type=");
71	printxval(evdev_ff_types, ffe.type, "FF_???");
72	tprintf(", id=%" PRIu16 ", direction=%" PRIu16,
73		ffe.id, ffe.direction);
74
75	if (!abbrev(tcp)) {
76		tprintf(", trigger={button=%" PRIu16 ", interval=%" PRIu16 "}",
77			ffe.trigger.button, ffe.trigger.interval);
78		tprintf(", replay={lenght=%" PRIu16 ", delay=%" PRIu16 "}",
79			ffe.replay.length, ffe.replay.delay);
80		switch (ffe.type) {
81			case FF_CONSTANT:
82				tprintf(", constant_ef={%" PRIi16,
83					ffe.u.constant.level);
84				decode_envelope(&ffe.u.constant.envelope);
85				tprints("}");
86				return 1;
87			case FF_RAMP:
88				tprintf(", ramp={start_level=%" PRIi16
89					", end_level=%" PRIi16,
90					ffe.u.ramp.start_level,
91					ffe.u.ramp.end_level);
92				decode_envelope(&ffe.u.ramp.envelope);
93				tprints("}");
94				return 1;
95			case FF_PERIODIC:
96				tprintf(", periodic_ef={waveform=%" PRIu16
97					", period=%" PRIu16
98					", magnitude=%" PRIi16
99					", offset=%" PRIi16
100					", phase=%" PRIu16,
101					ffe.u.periodic.waveform,
102					ffe.u.periodic.period,
103					ffe.u.periodic.magnitude,
104					ffe.u.periodic.offset,
105					ffe.u.periodic.phase);
106				decode_envelope(&ffe.u.periodic.envelope);
107				tprintf(", custom_len=%" PRIu32
108					", *custom_data=%#lx}",
109					ffe.u.periodic.custom_len,
110					(unsigned long)ffe.u.periodic.custom_data);
111				return 1;
112			case FF_RUMBLE:
113				tprintf(", rumble={strong_magnitude=%" PRIu16
114					", weak_magnitude=%" PRIu16 "}",
115					ffe.u.rumble.strong_magnitude,
116					ffe.u.rumble.weak_magnitude);
117				return 1;
118			case FF_SPRING:
119			case FF_FRICTION:
120			case FF_DAMPER:
121			case FF_INERTIA:
122			case FF_CUSTOM:
123				break;
124			default :
125				break;
126		}
127	}
128
129	tprints(", ...}");
130	return 1;
131}
132
133static int
134abs_ioctl(struct tcb *tcp, long arg)
135{
136	struct input_absinfo absinfo;
137
138	if (!verbose(tcp) || umove(tcp, arg, &absinfo) < 0)
139		return 0;
140
141	tprintf(", {value=%" PRIu32 ", minimum=%" PRIu32,
142		absinfo.value, absinfo.minimum);
143	if (!abbrev(tcp)) {
144		tprintf(", maximum=%" PRIu32 ", fuzz=%" PRIu32,
145			absinfo.maximum, absinfo.fuzz);
146		tprintf(", flat=%" PRIu32, absinfo.flat);
147#ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION
148		tprintf(", resolution=%" PRIu32, absinfo.resolution);
149#endif
150		tprints("}");
151	} else {
152		tprints(", ...}");
153	}
154	return 1;
155}
156
157static int
158keycode_ioctl(struct tcb *tcp, long arg)
159{
160	unsigned int keycode[2];
161
162	if (!arg) {
163		tprints(", NULL");
164		return 1;
165	}
166
167	if (!verbose(tcp) || umove(tcp, arg, &keycode) < 0)
168		return 0;
169
170	tprintf(", [%u, ", keycode[0]);
171	printxval(evdev_keycode, keycode[1], "KEY_???");
172	tprints("]");
173	return 1;
174}
175
176#ifdef EVIOCGKEYCODE_V2
177static int
178keycode_V2_ioctl(struct tcb *tcp, long arg)
179{
180	struct input_keymap_entry ike;
181	unsigned i;
182
183	if (!arg) {
184		tprints(", NULL");
185		return 1;
186	}
187
188	if (!verbose(tcp) || umove(tcp, arg, &ike) < 0)
189		return 0;
190
191	tprintf(", {flags=%" PRIu8 ", len=%" PRIu8,
192		ike.flags, ike.len);
193	if (!abbrev(tcp)) {
194		tprintf(", index=%" PRIu16 ", keycode=%" PRIu32,
195			ike.index, ike.keycode);
196		tprints(", scancode={");
197		for (i = 0; i < ARRAY_SIZE(ike.scancode); i++)
198			tprintf(" %" PRIx8, ike.scancode[i]);
199		tprints("}}");
200	} else {
201		tprints(", ...}");
202	}
203	return 1;
204}
205#endif /* EVIOCGKEYCODE_V2 */
206
207static int
208getid_ioctl(struct tcb *tcp, long arg)
209{
210	struct input_id id;
211
212	if (!verbose(tcp) || umove(tcp, arg, &id) < 0)
213		return 0;
214
215	tprintf(", {ID_BUS=%" PRIu16 ", ID_VENDOR=%" PRIu16,
216		id.bustype, id.vendor);
217	if (!abbrev(tcp)) {
218		tprintf(", ID_PRODUCT=%" PRIu16 ", ID_VERSION=%" PRIu16 "}",
219			id.product, id.version);
220	} else {
221		tprints(", ...}");
222	}
223	return 1;
224}
225
226static int
227decode_bitset(struct tcb *tcp, long arg, const struct xlat decode_nr[],
228	      const unsigned int max_nr, const char *dflt)
229{
230	if (!verbose(tcp))
231		return 0;
232
233	unsigned int size;
234	if ((unsigned long) tcp->u_rval > max_nr)
235		size = max_nr;
236	else
237		size = tcp->u_rval;
238	char decoded_arg[size];
239
240	if (umoven(tcp, arg, size, decoded_arg) < 0)
241		return 0;
242
243	tprints(", [");
244
245	int bit_displayed = 0;
246	int i = next_set_bit(decoded_arg, 0, size);
247	if (i < 0) {
248		tprints(" 0 ");
249	} else {
250		printxval(decode_nr, i, dflt);
251
252		while ((i = next_set_bit(decoded_arg, i + 1, size)) > 0) {
253			if (abbrev(tcp) && bit_displayed >= 3) {
254				tprints(", ...");
255				break;
256			}
257			tprints(", ");
258			printxval(decode_nr, i, dflt);
259			bit_displayed++;
260		}
261	}
262
263	tprints("]");
264
265	return 1;
266}
267
268#ifdef EVIOCGMTSLOTS
269static int
270mtslots_ioctl(struct tcb *tcp, const unsigned int code, long arg)
271{
272	const size_t size = _IOC_SIZE(code) / sizeof(int32_t);
273	if (!size)
274		return 0;
275
276	int32_t buffer[size];
277
278	if (!verbose(tcp) || umove(tcp, arg, &buffer) < 0)
279		return 0;
280
281	tprints(", {code=");
282	printxval(evdev_mtslots, buffer[0], "ABS_MT_???");
283
284	unsigned int i;
285	tprints(", values=[");
286
287	for (i = 1; i < ARRAY_SIZE(buffer); i++)
288		tprintf("%s%d", i > 1 ? ", " : "", buffer[i]);
289
290	tprints("]}");
291	return 1;
292}
293#endif /* EVIOCGMTSLOTS */
294
295#ifdef EVIOCGREP
296static int
297repeat_ioctl(struct tcb *tcp, long arg)
298{
299	unsigned int val[2];
300
301	if (!verbose(tcp) || umove(tcp, arg, &val) < 0)
302		return 0;
303
304	tprintf(", [%" PRIu32 " %" PRIu32 "]", val[0], val[1]);
305	return 1;
306}
307#endif /* EVIOCGREP */
308
309static int
310evdev_read_ioctl(struct tcb *tcp, const unsigned int code, long arg)
311{
312	if (entering(tcp))
313		return 1;
314
315	if (syserror(tcp))
316		return 0;
317
318	if ((_IOC_NR(code) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) {
319		switch (_IOC_NR(code) - 0x20) {
320			case EV_SYN:
321				return decode_bitset(tcp, arg, evdev_sync,
322						SYN_MAX, "SYN_???");
323			case EV_KEY:
324				return decode_bitset(tcp, arg, evdev_keycode,
325						KEY_MAX, "KEY_???");
326			case EV_REL:
327				return decode_bitset(tcp, arg, evdev_relative_axes,
328						REL_MAX, "REL_???");
329			case EV_ABS:
330				return decode_bitset(tcp, arg,
331						evdev_abs, ABS_MAX, "ABS_???");
332			case EV_MSC:
333				return decode_bitset(tcp, arg,
334						evdev_misc, MSC_MAX, "MSC_???");
335#ifdef EV_SW
336			case EV_SW:
337				return decode_bitset(tcp, arg,
338						evdev_switch, SW_MAX, "SW_???");
339#endif
340			case EV_LED:
341				return decode_bitset(tcp, arg,
342						evdev_leds, LED_MAX, "LED_???");
343			case EV_SND:
344				return decode_bitset(tcp, arg,
345						evdev_snd, SND_MAX, "SND_???");
346			case EV_REP:
347				return decode_bitset(tcp, arg, evdev_autorepeat,
348						REP_MAX, "REP_???");
349			case EV_FF:
350				return decode_bitset(tcp, arg, evdev_ff_types,
351						FF_MAX, "FF_???");
352			case EV_PWR:
353				printnum_int(tcp, arg, "%d");
354				return 1;
355			case EV_FF_STATUS:
356				return decode_bitset(tcp, arg, evdev_ff_status,
357						FF_STATUS_MAX, "FF_STATUS_???");
358			default:
359				return 0;
360		}
361	}
362
363	if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0)))
364		return abs_ioctl(tcp, arg);
365
366	switch (code) {
367		case EVIOCGVERSION:
368			tprints(", ");
369			printnum_int(tcp, arg, "%" PRIx32);
370			return 1;
371		case EVIOCGEFFECTS:
372			tprints(", ");
373			printnum_int(tcp, arg, "%" PRIu32);
374			return 1;
375		case EVIOCGID:
376			return getid_ioctl(tcp, arg);
377#ifdef EVIOCGREP
378		case EVIOCGREP:
379			return repeat_ioctl(tcp, arg);;
380#endif
381		case EVIOCGKEYCODE:
382			return keycode_ioctl(tcp, arg);
383#ifdef EVIOCGKEYCODE_V2
384		case EVIOCGKEYCODE_V2:
385			return keycode_V2_ioctl(tcp, arg);
386#endif
387	}
388
389	switch (_IOC_NR(code)) {
390#ifdef EVIOCGMTSLOTS
391		case _IOC_NR(EVIOCGMTSLOTS(0)):
392			return mtslots_ioctl(tcp, code, arg);
393#endif
394		case _IOC_NR(EVIOCGNAME(0)):
395		case _IOC_NR(EVIOCGPHYS(0)):
396		case _IOC_NR(EVIOCGUNIQ(0)):
397			tprints(", ");
398			printstr(tcp, arg, tcp->u_rval - 1);
399			return 1;
400#ifdef EVIOCGPROP
401		case _IOC_NR(EVIOCGPROP(0)):
402			return decode_bitset(tcp, arg,
403					evdev_prop, INPUT_PROP_MAX, "PROP_???");
404#endif
405		case _IOC_NR(EVIOCGSND(0)):
406			return decode_bitset(tcp, arg,
407					evdev_snd, SND_MAX, "SND_???");
408#ifdef EVIOCGSW
409		case _IOC_NR(EVIOCGSW(0)):
410			return decode_bitset(tcp, arg,
411					evdev_switch, SW_MAX, "SW_???");
412#endif
413		case _IOC_NR(EVIOCGKEY(0)):
414			return decode_bitset(tcp, arg,
415					evdev_keycode, KEY_MAX, "KEY_???");
416		case _IOC_NR(EVIOCGLED(0)):
417			return decode_bitset(tcp, arg,
418					evdev_leds, LED_MAX, "LED_???");
419		default:
420			return 0;
421	}
422}
423
424static int
425evdev_write_ioctl(struct tcb *tcp, const unsigned int code, long arg)
426{
427	if (exiting(tcp))
428		return 1;
429
430	if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0)))
431		return abs_ioctl(tcp, arg);
432
433	switch (code) {
434#ifdef EVIOCSREP
435		case EVIOCSREP:
436			return repeat_ioctl(tcp, arg);
437#endif
438		case EVIOCSKEYCODE:
439			return keycode_ioctl(tcp, arg);
440#ifdef EVIOCSKEYCODE_V2
441		case EVIOCSKEYCODE_V2:
442			return keycode_V2_ioctl(tcp, arg);
443#endif
444		case EVIOCSFF:
445			return ff_effect_ioctl(tcp, arg);
446		case EVIOCRMFF:
447#ifdef EVIOCSCLOCKID
448		case EVIOCSCLOCKID:
449#endif
450		case EVIOCGRAB:
451#ifdef EVIOCREVOKE
452		case EVIOCREVOKE:
453#endif
454			tprints(", ");
455			printnum_int(tcp, arg, "%u");
456			return 1;
457		default:
458			return 0;
459	}
460}
461
462int
463evdev_ioctl(struct tcb *tcp, const unsigned int code, long arg)
464{
465	switch(_IOC_DIR(code)) {
466		case _IOC_READ:
467			return evdev_read_ioctl(tcp, code, arg);
468		case _IOC_WRITE:
469			if (!evdev_write_ioctl(tcp, code, arg))
470				tprintf(", %lx", arg);
471			return 1;
472		default:
473			return 0;
474	}
475}
476
477#endif /* HAVE_LINUX_INPUT_H */
478