• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
38 typedef 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 
63 static void
decode_envelope(void * const data)64 decode_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 
78 static int
ff_effect_ioctl(struct tcb * const tcp,const kernel_ulong_t arg)79 ff_effect_ioctl(struct tcb *const tcp, const kernel_ulong_t 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(ptr_to_kulong(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 
156 static int
abs_ioctl(struct tcb * const tcp,const kernel_ulong_t arg)157 abs_ioctl(struct tcb *const tcp, const kernel_ulong_t 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 
190 static int
keycode_ioctl(struct tcb * const tcp,const kernel_ulong_t arg)191 keycode_ioctl(struct tcb *const tcp, const kernel_ulong_t 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
207 static int
keycode_V2_ioctl(struct tcb * const tcp,const kernel_ulong_t arg)208 keycode_V2_ioctl(struct tcb *const tcp, const kernel_ulong_t 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 
244 static int
getid_ioctl(struct tcb * const tcp,const kernel_ulong_t arg)245 getid_ioctl(struct tcb *const tcp, const kernel_ulong_t 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 
264 static int
decode_bitset(struct tcb * const tcp,const kernel_ulong_t arg,const struct xlat decode_nr[],const unsigned int max_nr,const char * const dflt)265 decode_bitset(struct tcb *const tcp, const kernel_ulong_t arg,
266 	      const struct xlat decode_nr[], const unsigned int max_nr,
267 	      const char *const dflt)
268 {
269 	tprints(", ");
270 
271 	unsigned int size;
272 	if ((kernel_ulong_t) tcp->u_rval > max_nr)
273 		size = max_nr;
274 	else
275 		size = tcp->u_rval;
276 	char decoded_arg[size];
277 
278 	if (umove_or_printaddr(tcp, arg, &decoded_arg))
279 		return 1;
280 
281 	tprints("[");
282 
283 	int bit_displayed = 0;
284 	int i = next_set_bit(decoded_arg, 0, size);
285 	if (i < 0) {
286 		tprints(" 0 ");
287 	} else {
288 		printxval(decode_nr, i, dflt);
289 
290 		while ((i = next_set_bit(decoded_arg, i + 1, size)) > 0) {
291 			if (abbrev(tcp) && bit_displayed >= 3) {
292 				tprints(", ...");
293 				break;
294 			}
295 			tprints(", ");
296 			printxval(decode_nr, i, dflt);
297 			bit_displayed++;
298 		}
299 	}
300 
301 	tprints("]");
302 
303 	return 1;
304 }
305 
306 # ifdef EVIOCGMTSLOTS
307 static int
mtslots_ioctl(struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg)308 mtslots_ioctl(struct tcb *const tcp, const unsigned int code,
309 	      const kernel_ulong_t arg)
310 {
311 	tprints(", ");
312 
313 	const size_t size = _IOC_SIZE(code) / sizeof(int);
314 	if (!size) {
315 		printaddr(arg);
316 		return 1;
317 	}
318 
319 	int buffer[size];
320 
321 	if (umove_or_printaddr(tcp, arg, &buffer))
322 		return 1;
323 
324 	tprints("{code=");
325 	printxval(evdev_mtslots, buffer[0], "ABS_MT_???");
326 
327 	tprints(", values=[");
328 
329 	unsigned int i;
330 	for (i = 1; i < ARRAY_SIZE(buffer); i++)
331 		tprintf("%s%d", i > 1 ? ", " : "", buffer[i]);
332 
333 	tprints("]}");
334 
335 	return 1;
336 }
337 # endif /* EVIOCGMTSLOTS */
338 
339 # if defined EVIOCGREP || defined EVIOCSREP
340 static int
repeat_ioctl(struct tcb * const tcp,const kernel_ulong_t arg)341 repeat_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
342 {
343 	tprints(", ");
344 	printpair_int(tcp, arg, "%u");
345 	return 1;
346 }
347 # endif /* EVIOCGREP || EVIOCSREP */
348 
349 static int
bit_ioctl(struct tcb * const tcp,const unsigned int ev_nr,const kernel_ulong_t arg)350 bit_ioctl(struct tcb *const tcp, const unsigned int ev_nr,
351 	  const kernel_ulong_t arg)
352 {
353 	switch (ev_nr) {
354 		case EV_SYN:
355 			return decode_bitset(tcp, arg, evdev_sync,
356 					     SYN_MAX, "SYN_???");
357 		case EV_KEY:
358 			return decode_bitset(tcp, arg, evdev_keycode,
359 					     KEY_MAX, "KEY_???");
360 		case EV_REL:
361 			return decode_bitset(tcp, arg, evdev_relative_axes,
362 					     REL_MAX, "REL_???");
363 		case EV_ABS:
364 			return decode_bitset(tcp, arg, evdev_abs,
365 					     ABS_MAX, "ABS_???");
366 		case EV_MSC:
367 			return decode_bitset(tcp, arg, evdev_misc,
368 					     MSC_MAX, "MSC_???");
369 # ifdef EV_SW
370 		case EV_SW:
371 			return decode_bitset(tcp, arg, evdev_switch,
372 					     SW_MAX, "SW_???");
373 # endif
374 		case EV_LED:
375 			return decode_bitset(tcp, arg, evdev_leds,
376 					     LED_MAX, "LED_???");
377 		case EV_SND:
378 			return decode_bitset(tcp, arg, evdev_snd,
379 					     SND_MAX, "SND_???");
380 		case EV_REP:
381 			return decode_bitset(tcp, arg, evdev_autorepeat,
382 					     REP_MAX, "REP_???");
383 		case EV_FF:
384 			return decode_bitset(tcp, arg, evdev_ff_types,
385 					     FF_MAX, "FF_???");
386 		case EV_PWR:
387 			tprints(", ");
388 			printnum_int(tcp, arg, "%d");
389 			return 1;
390 		case EV_FF_STATUS:
391 			return decode_bitset(tcp, arg, evdev_ff_status,
392 					     FF_STATUS_MAX, "FF_STATUS_???");
393 		default:
394 			tprints(", ");
395 			printaddr(arg);
396 			return 1;
397 	}
398 }
399 
400 static int
evdev_read_ioctl(struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg)401 evdev_read_ioctl(struct tcb *const tcp, const unsigned int code,
402 		 const kernel_ulong_t arg)
403 {
404 	/* fixed-number fixed-length commands */
405 	switch (code) {
406 		case EVIOCGVERSION:
407 			tprints(", ");
408 			printnum_int(tcp, arg, "%#x");
409 			return 1;
410 		case EVIOCGEFFECTS:
411 			tprints(", ");
412 			printnum_int(tcp, arg, "%u");
413 			return 1;
414 		case EVIOCGID:
415 			return getid_ioctl(tcp, arg);
416 # ifdef EVIOCGREP
417 		case EVIOCGREP:
418 			return repeat_ioctl(tcp, arg);
419 # endif
420 		case EVIOCGKEYCODE:
421 			return keycode_ioctl(tcp, arg);
422 # ifdef EVIOCGKEYCODE_V2
423 		case EVIOCGKEYCODE_V2:
424 			return keycode_V2_ioctl(tcp, arg);
425 # endif
426 	}
427 
428 	/* fixed-number variable-length commands */
429 	switch (_IOC_NR(code)) {
430 # ifdef EVIOCGMTSLOTS
431 		case _IOC_NR(EVIOCGMTSLOTS(0)):
432 			return mtslots_ioctl(tcp, code, arg);
433 # endif
434 		case _IOC_NR(EVIOCGNAME(0)):
435 		case _IOC_NR(EVIOCGPHYS(0)):
436 		case _IOC_NR(EVIOCGUNIQ(0)):
437 			tprints(", ");
438 			if (syserror(tcp))
439 				printaddr(arg);
440 			else
441 				printstrn(tcp, arg, tcp->u_rval);
442 			return 1;
443 # ifdef EVIOCGPROP
444 		case _IOC_NR(EVIOCGPROP(0)):
445 			return decode_bitset(tcp, arg, evdev_prop,
446 					     INPUT_PROP_MAX, "PROP_???");
447 # endif
448 		case _IOC_NR(EVIOCGSND(0)):
449 			return decode_bitset(tcp, arg, evdev_snd,
450 					     SND_MAX, "SND_???");
451 # ifdef EVIOCGSW
452 		case _IOC_NR(EVIOCGSW(0)):
453 			return decode_bitset(tcp, arg, evdev_switch,
454 					     SW_MAX, "SW_???");
455 # endif
456 		case _IOC_NR(EVIOCGKEY(0)):
457 			return decode_bitset(tcp, arg, evdev_keycode,
458 					     KEY_MAX, "KEY_???");
459 		case _IOC_NR(EVIOCGLED(0)):
460 			return decode_bitset(tcp, arg, evdev_leds,
461 					     LED_MAX, "LED_???");
462 	}
463 
464 	/* multi-number fixed-length commands */
465 	if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0)))
466 		return abs_ioctl(tcp, arg);
467 
468 	/* multi-number variable-length commands */
469 	if ((_IOC_NR(code) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
470 		return bit_ioctl(tcp, _IOC_NR(code) & EV_MAX, arg);
471 
472 	return 0;
473 }
474 
475 static int
evdev_write_ioctl(struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg)476 evdev_write_ioctl(struct tcb *const tcp, const unsigned int code,
477 		  const kernel_ulong_t arg)
478 {
479 	/* fixed-number fixed-length commands */
480 	switch (code) {
481 # ifdef EVIOCSREP
482 		case EVIOCSREP:
483 			return repeat_ioctl(tcp, arg);
484 # endif
485 		case EVIOCSKEYCODE:
486 			return keycode_ioctl(tcp, arg);
487 # ifdef EVIOCSKEYCODE_V2
488 		case EVIOCSKEYCODE_V2:
489 			return keycode_V2_ioctl(tcp, arg);
490 # endif
491 		case EVIOCSFF:
492 			return ff_effect_ioctl(tcp, arg);
493 		case EVIOCRMFF:
494 			tprintf(", %d", (int) arg);
495 			return 1;
496 		case EVIOCGRAB:
497 # ifdef EVIOCREVOKE
498 		case EVIOCREVOKE:
499 # endif
500 			tprintf(", %" PRI_klu, arg);
501 			return 1;
502 # ifdef EVIOCSCLOCKID
503 		case EVIOCSCLOCKID:
504 			tprints(", ");
505 			printnum_int(tcp, arg, "%u");
506 			return 1;
507 # endif
508 	}
509 
510 	/* multi-number fixed-length commands */
511 	if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0)))
512 		return abs_ioctl(tcp, arg);
513 
514 	return 0;
515 }
516 
MPERS_PRINTER_DECL(int,evdev_ioctl,struct tcb * const tcp,const unsigned int code,const kernel_ulong_t arg)517 MPERS_PRINTER_DECL(int, evdev_ioctl, struct tcb *const tcp,
518 		   const unsigned int code, const kernel_ulong_t arg)
519 {
520 	switch (_IOC_DIR(code)) {
521 		case _IOC_READ:
522 			if (entering(tcp))
523 				return 0;
524 			return evdev_read_ioctl(tcp, code, arg);
525 		case _IOC_WRITE:
526 			return evdev_write_ioctl(tcp, code, arg) | RVAL_DECODED;
527 		default:
528 			return RVAL_DECODED;
529 	}
530 }
531 
532 #endif /* HAVE_LINUX_INPUT_H */
533