2 * Copyright (c) 2015 Etienne Gemsa <etienne.gemsa@lse.epita.fr>
3 * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org>
4 * Copyright (c) 2015-2019 The strace developers.
7 * SPDX-License-Identifier: LGPL-2.1-or-later
12 #include "xlat/evdev_abs.h"
13 #include "xlat/evdev_ev.h"
15 #ifdef HAVE_LINUX_INPUT_H
17 # include <linux/ioctl.h>
18 # include <linux/input.h>
20 # include "xlat/evdev_autorepeat.h"
21 # include "xlat/evdev_ff_status.h"
22 # include "xlat/evdev_ff_types.h"
23 # include "xlat/evdev_keycode.h"
24 # include "xlat/evdev_leds.h"
25 # include "xlat/evdev_misc.h"
26 # include "xlat/evdev_mtslots.h"
27 # include "xlat/evdev_prop.h"
28 # include "xlat/evdev_relative_axes.h"
29 # include "xlat/evdev_snd.h"
30 # include "xlat/evdev_switch.h"
37 abs_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
41 struct input_absinfo absinfo;
43 if (!umove_or_printaddr(tcp, arg, &absinfo)) {
56 # ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION
57 tprintf(", resolution=%u",
67 return RVAL_IOCTL_DECODED;
71 keycode_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
75 unsigned int keycode[2];
77 if (!umove_or_printaddr(tcp, arg, &keycode)) {
78 tprintf("[%u, ", keycode[0]);
79 printxval(evdev_keycode, keycode[1], "KEY_???");
83 return RVAL_IOCTL_DECODED;
86 # ifdef EVIOCGKEYCODE_V2
88 keycode_V2_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
92 struct input_keymap_entry ike;
94 if (umove_or_printaddr(tcp, arg, &ike))
95 return RVAL_IOCTL_DECODED;
97 tprintf("{flags=%" PRIu8
105 tprintf("index=%" PRIu16 ", keycode=", ike.index);
106 printxval(evdev_keycode, ike.keycode, "KEY_???");
107 tprints(", scancode=[");
108 for (i = 0; i < ARRAY_SIZE(ike.scancode); i++) {
111 tprintf("%" PRIx8, ike.scancode[i]);
120 return RVAL_IOCTL_DECODED;
122 # endif /* EVIOCGKEYCODE_V2 */
125 getid_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
131 if (!umove_or_printaddr(tcp, arg, &id))
132 tprintf("{ID_BUS=%" PRIu16
133 ", ID_VENDOR=%" PRIu16
134 ", ID_PRODUCT=%" PRIu16
135 ", ID_VERSION=%" PRIu16 "}",
141 return RVAL_IOCTL_DECODED;
145 decode_bitset(struct tcb *const tcp, const kernel_ulong_t arg,
146 const struct xlat *decode_nr, const unsigned int max_nr,
147 const char *const dflt)
152 unsigned int size_bits;
154 if ((kernel_ulong_t) tcp->u_rval > max_nr / 8)
157 size_bits = tcp->u_rval * 8;
159 size = ROUNDUP(ROUNDUP_DIV(size_bits, 8), current_wordsize);
161 if (syserror(tcp) || !size) {
164 return RVAL_IOCTL_DECODED;
167 char decoded_arg[size];
169 if (umove_or_printaddr(tcp, arg, &decoded_arg))
170 return RVAL_IOCTL_DECODED;
172 if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_RAW) {
175 int bit_displayed = 0;
176 int i = next_set_bit(decoded_arg, 0, size_bits);
180 printxval(decode_nr, i, dflt);
182 while ((i = next_set_bit(decoded_arg, i + 1,
184 if (abbrev(tcp) && bit_displayed >= 3) {
189 printxval(decode_nr, i, dflt);
197 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
200 if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV) {
203 print_local_array(tcp, decoded_arg, size / current_wordsize,
204 &elem, current_wordsize,
205 print_xlong_array_member, NULL, 0);
208 if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
211 return RVAL_IOCTL_DECODED;
214 # ifdef EVIOCGMTSLOTS
216 mtslots_ioctl(struct tcb *const tcp, const unsigned int code,
217 const kernel_ulong_t arg)
221 const size_t size = _IOC_SIZE(code) / sizeof(int);
224 return RVAL_IOCTL_DECODED;
229 if (umove_or_printaddr(tcp, arg, &buffer))
230 return RVAL_IOCTL_DECODED;
233 printxval(evdev_mtslots, buffer[0], "ABS_MT_???");
235 tprints(", values=[");
238 for (i = 1; i < ARRAY_SIZE(buffer); i++)
239 tprintf("%s%d", i > 1 ? ", " : "", buffer[i]);
243 return RVAL_IOCTL_DECODED;
245 # endif /* EVIOCGMTSLOTS */
247 # if defined EVIOCGREP || defined EVIOCSREP
249 repeat_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
252 printpair_int(tcp, arg, "%u");
253 return RVAL_IOCTL_DECODED;
255 # endif /* EVIOCGREP || EVIOCSREP */
258 bit_ioctl(struct tcb *const tcp, const unsigned int ev_nr,
259 const kernel_ulong_t arg)
263 return decode_bitset(tcp, arg, evdev_ev,
266 return decode_bitset(tcp, arg, evdev_keycode,
269 return decode_bitset(tcp, arg, evdev_relative_axes,
272 return decode_bitset(tcp, arg, evdev_abs,
275 return decode_bitset(tcp, arg, evdev_misc,
278 return decode_bitset(tcp, arg, evdev_switch,
281 return decode_bitset(tcp, arg, evdev_leds,
284 return decode_bitset(tcp, arg, evdev_snd,
287 return decode_bitset(tcp, arg, evdev_autorepeat,
290 return decode_bitset(tcp, arg, evdev_ff_types,
294 printnum_int(tcp, arg, "%d");
295 return RVAL_IOCTL_DECODED;
297 return decode_bitset(tcp, arg, evdev_ff_status,
298 FF_STATUS_MAX, "FF_STATUS_???");
302 return RVAL_IOCTL_DECODED;
307 evdev_read_ioctl(struct tcb *const tcp, const unsigned int code,
308 const kernel_ulong_t arg)
310 /* fixed-number fixed-length commands */
314 printnum_int(tcp, arg, "%#x");
315 return RVAL_IOCTL_DECODED;
318 printnum_int(tcp, arg, "%u");
319 return RVAL_IOCTL_DECODED;
321 return getid_ioctl(tcp, arg);
324 return repeat_ioctl(tcp, arg);
327 return keycode_ioctl(tcp, arg);
328 # ifdef EVIOCGKEYCODE_V2
329 case EVIOCGKEYCODE_V2:
330 return keycode_V2_ioctl(tcp, arg);
334 /* fixed-number variable-length commands */
335 switch (_IOC_NR(code)) {
336 # ifdef EVIOCGMTSLOTS
337 case _IOC_NR(EVIOCGMTSLOTS(0)):
338 return mtslots_ioctl(tcp, code, arg);
340 case _IOC_NR(EVIOCGNAME(0)):
341 case _IOC_NR(EVIOCGPHYS(0)):
342 case _IOC_NR(EVIOCGUNIQ(0)):
347 printstrn(tcp, arg, tcp->u_rval);
348 return RVAL_IOCTL_DECODED;
350 case _IOC_NR(EVIOCGPROP(0)):
351 return decode_bitset(tcp, arg, evdev_prop,
352 INPUT_PROP_MAX, "PROP_???");
354 case _IOC_NR(EVIOCGSND(0)):
355 return decode_bitset(tcp, arg, evdev_snd,
358 case _IOC_NR(EVIOCGSW(0)):
359 return decode_bitset(tcp, arg, evdev_switch,
362 case _IOC_NR(EVIOCGKEY(0)):
363 return decode_bitset(tcp, arg, evdev_keycode,
365 case _IOC_NR(EVIOCGLED(0)):
366 return decode_bitset(tcp, arg, evdev_leds,
370 /* multi-number fixed-length commands */
371 if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0)))
372 return abs_ioctl(tcp, arg);
374 /* multi-number variable-length commands */
375 if ((_IOC_NR(code) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
376 return bit_ioctl(tcp, _IOC_NR(code) & EV_MAX, arg);
382 evdev_write_ioctl(struct tcb *const tcp, const unsigned int code,
383 const kernel_ulong_t arg)
385 /* fixed-number fixed-length commands */
389 return repeat_ioctl(tcp, arg);
392 return keycode_ioctl(tcp, arg);
393 # ifdef EVIOCSKEYCODE_V2
394 case EVIOCSKEYCODE_V2:
395 return keycode_V2_ioctl(tcp, arg);
398 tprintf(", %d", (int) arg);
399 return RVAL_IOCTL_DECODED;
404 tprintf(", %" PRI_klu, arg);
405 return RVAL_IOCTL_DECODED;
406 # ifdef EVIOCSCLOCKID
409 printnum_int(tcp, arg, "%u");
410 return RVAL_IOCTL_DECODED;
413 int rc = evdev_write_ioctl_mpers(tcp, code, arg);
415 if (rc != RVAL_DECODED)
420 /* multi-number fixed-length commands */
421 if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0)))
422 return abs_ioctl(tcp, arg);
428 print_evdev_ff_type(const kernel_ulong_t val)
430 printxval(evdev_ff_types, val, "FF_???");
434 evdev_ioctl(struct tcb *const tcp,
435 const unsigned int code, const kernel_ulong_t arg)
437 switch (_IOC_DIR(code)) {
441 return evdev_read_ioctl(tcp, code, arg);
443 return evdev_write_ioctl(tcp, code, arg) | RVAL_DECODED;
449 #endif /* HAVE_LINUX_INPUT_H */