]> granicus.if.org Git - strace/blob - evdev.c
Change the license of strace to LGPL-2.1-or-later
[strace] / evdev.c
1 /*
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-2018 The strace developers.
5  * All rights reserved.
6  *
7  * SPDX-License-Identifier: LGPL-2.1-or-later
8  */
9
10 #include "defs.h"
11
12 #include "xlat/evdev_abs.h"
13 #include "xlat/evdev_ev.h"
14
15 #ifdef HAVE_LINUX_INPUT_H
16
17 # include <linux/ioctl.h>
18 # include <linux/input.h>
19
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"
31
32 # ifndef SYN_MAX
33 #  define SYN_MAX 0xf
34 # endif
35
36 const size_t evdev_abs_size = ARRAY_SIZE(evdev_abs) - 1;
37
38 static int
39 abs_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
40 {
41         tprints(", ");
42
43         struct input_absinfo absinfo;
44
45         if (!umove_or_printaddr(tcp, arg, &absinfo)) {
46                 tprintf("{value=%u"
47                         ", minimum=%u, ",
48                         absinfo.value,
49                         absinfo.minimum);
50
51                 if (!abbrev(tcp)) {
52                         tprintf("maximum=%u"
53                                 ", fuzz=%u"
54                                 ", flat=%u",
55                                 absinfo.maximum,
56                                 absinfo.fuzz,
57                                 absinfo.flat);
58 # ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION
59                         tprintf(", resolution=%u",
60                                 absinfo.resolution);
61 # endif
62                 } else {
63                         tprints("...");
64                 }
65
66                 tprints("}");
67         }
68
69         return RVAL_IOCTL_DECODED;
70 }
71
72 static int
73 keycode_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
74 {
75         tprints(", ");
76
77         unsigned int keycode[2];
78
79         if (!umove_or_printaddr(tcp, arg, &keycode)) {
80                 tprintf("[%u, ", keycode[0]);
81                 printxval_index(evdev_keycode, keycode[1], "KEY_???");
82                 tprints("]");
83         }
84
85         return RVAL_IOCTL_DECODED;
86 }
87
88 # ifdef EVIOCGKEYCODE_V2
89 static int
90 keycode_V2_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
91 {
92         tprints(", ");
93
94         struct input_keymap_entry ike;
95
96         if (umove_or_printaddr(tcp, arg, &ike))
97                 return RVAL_IOCTL_DECODED;
98
99         tprintf("{flags=%" PRIu8
100                 ", len=%" PRIu8 ", ",
101                 ike.flags,
102                 ike.len);
103
104         if (!abbrev(tcp)) {
105                 unsigned int i;
106
107                 tprintf("index=%" PRIu16 ", keycode=", ike.index);
108                 printxval_index(evdev_keycode, ike.keycode, "KEY_???");
109                 tprints(", scancode=[");
110                 for (i = 0; i < ARRAY_SIZE(ike.scancode); i++) {
111                         if (i > 0)
112                                 tprints(", ");
113                         tprintf("%" PRIx8, ike.scancode[i]);
114                 }
115                 tprints("]");
116         } else {
117                 tprints("...");
118         }
119
120         tprints("}");
121
122         return RVAL_IOCTL_DECODED;
123 }
124 # endif /* EVIOCGKEYCODE_V2 */
125
126 static int
127 getid_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
128 {
129         tprints(", ");
130
131         struct input_id id;
132
133         if (!umove_or_printaddr(tcp, arg, &id))
134                 tprintf("{ID_BUS=%" PRIu16
135                         ", ID_VENDOR=%" PRIu16
136                         ", ID_PRODUCT=%" PRIu16
137                         ", ID_VERSION=%" PRIu16 "}",
138                         id.bustype,
139                         id.vendor,
140                         id.product,
141                         id.version);
142
143         return RVAL_IOCTL_DECODED;
144 }
145
146 static int
147 decode_bitset_(struct tcb *const tcp, const kernel_ulong_t arg,
148                const struct xlat decode_nr[], const unsigned int max_nr,
149                const char *const dflt, size_t decode_nr_size, enum xlat_type xt)
150 {
151         tprints(", ");
152
153         unsigned int size;
154         if ((kernel_ulong_t) tcp->u_rval > max_nr / 8)
155                 size = max_nr;
156         else
157                 size = tcp->u_rval * 8;
158         char decoded_arg[size];
159
160         if (umove_or_printaddr(tcp, arg, &decoded_arg))
161                 return RVAL_IOCTL_DECODED;
162
163         tprints("[");
164
165         int bit_displayed = 0;
166         int i = next_set_bit(decoded_arg, 0, size);
167         if (i < 0) {
168                 tprints(" 0 ");
169         } else {
170                 printxval_dispatch(decode_nr, decode_nr_size, i, dflt, xt);
171
172                 while ((i = next_set_bit(decoded_arg, i + 1, size)) > 0) {
173                         if (abbrev(tcp) && bit_displayed >= 3) {
174                                 tprints(", ...");
175                                 break;
176                         }
177                         tprints(", ");
178                         printxval_dispatch(decode_nr, decode_nr_size, i, dflt,
179                                            xt);
180                         bit_displayed++;
181                 }
182         }
183
184         tprints("]");
185
186         return RVAL_IOCTL_DECODED;
187 }
188
189 #define decode_bitset(tcp_, arg_, decode_nr_, max_nr_, dflt_, xt_) \
190         decode_bitset_((tcp_), (arg_), (decode_nr_), (max_nr_), \
191                        (dflt_), ARRAY_SIZE(decode_nr_), (xt_))
192
193 # ifdef EVIOCGMTSLOTS
194 static int
195 mtslots_ioctl(struct tcb *const tcp, const unsigned int code,
196               const kernel_ulong_t arg)
197 {
198         tprints(", ");
199
200         const size_t size = _IOC_SIZE(code) / sizeof(int);
201         if (!size) {
202                 printaddr(arg);
203                 return RVAL_IOCTL_DECODED;
204         }
205
206         int buffer[size];
207
208         if (umove_or_printaddr(tcp, arg, &buffer))
209                 return RVAL_IOCTL_DECODED;
210
211         tprints("{code=");
212         printxval(evdev_mtslots, buffer[0], "ABS_MT_???");
213
214         tprints(", values=[");
215
216         unsigned int i;
217         for (i = 1; i < ARRAY_SIZE(buffer); i++)
218                 tprintf("%s%d", i > 1 ? ", " : "", buffer[i]);
219
220         tprints("]}");
221
222         return RVAL_IOCTL_DECODED;
223 }
224 # endif /* EVIOCGMTSLOTS */
225
226 # if defined EVIOCGREP || defined EVIOCSREP
227 static int
228 repeat_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
229 {
230         tprints(", ");
231         printpair_int(tcp, arg, "%u");
232         return RVAL_IOCTL_DECODED;
233 }
234 # endif /* EVIOCGREP || EVIOCSREP */
235
236 static int
237 bit_ioctl(struct tcb *const tcp, const unsigned int ev_nr,
238           const kernel_ulong_t arg)
239 {
240         switch (ev_nr) {
241                 case 0:
242                         return decode_bitset(tcp, arg, evdev_ev,
243                                              EV_MAX, "EV_???", XT_SORTED);
244                 case EV_KEY:
245                         return decode_bitset(tcp, arg, evdev_keycode,
246                                              KEY_MAX, "KEY_???", XT_INDEXED);
247                 case EV_REL:
248                         return decode_bitset(tcp, arg, evdev_relative_axes,
249                                              REL_MAX, "REL_???", XT_INDEXED);
250                 case EV_ABS:
251                         return decode_bitset(tcp, arg, evdev_abs,
252                                              ABS_MAX, "ABS_???", XT_INDEXED);
253                 case EV_MSC:
254                         return decode_bitset(tcp, arg, evdev_misc,
255                                              MSC_MAX, "MSC_???", XT_INDEXED);
256                 case EV_SW:
257                         return decode_bitset(tcp, arg, evdev_switch,
258                                              SW_MAX, "SW_???", XT_INDEXED);
259                 case EV_LED:
260                         return decode_bitset(tcp, arg, evdev_leds,
261                                              LED_MAX, "LED_???", XT_INDEXED);
262                 case EV_SND:
263                         return decode_bitset(tcp, arg, evdev_snd,
264                                              SND_MAX, "SND_???", XT_INDEXED);
265                 case EV_REP:
266                         return decode_bitset(tcp, arg, evdev_autorepeat,
267                                              REP_MAX, "REP_???", XT_INDEXED);
268                 case EV_FF:
269                         return decode_bitset(tcp, arg, evdev_ff_types,
270                                              FF_MAX, "FF_???", XT_SORTED);
271                 case EV_PWR:
272                         tprints(", ");
273                         printnum_int(tcp, arg, "%d");
274                         return RVAL_IOCTL_DECODED;
275                 case EV_FF_STATUS:
276                         return decode_bitset(tcp, arg, evdev_ff_status,
277                                              FF_STATUS_MAX, "FF_STATUS_???",
278                                              XT_INDEXED);
279                 default:
280                         tprints(", ");
281                         printaddr(arg);
282                         return RVAL_IOCTL_DECODED;
283         }
284 }
285
286 static int
287 evdev_read_ioctl(struct tcb *const tcp, const unsigned int code,
288                  const kernel_ulong_t arg)
289 {
290         /* fixed-number fixed-length commands */
291         switch (code) {
292                 case EVIOCGVERSION:
293                         tprints(", ");
294                         printnum_int(tcp, arg, "%#x");
295                         return RVAL_IOCTL_DECODED;
296                 case EVIOCGEFFECTS:
297                         tprints(", ");
298                         printnum_int(tcp, arg, "%u");
299                         return RVAL_IOCTL_DECODED;
300                 case EVIOCGID:
301                         return getid_ioctl(tcp, arg);
302 # ifdef EVIOCGREP
303                 case EVIOCGREP:
304                         return repeat_ioctl(tcp, arg);
305 # endif
306                 case EVIOCGKEYCODE:
307                         return keycode_ioctl(tcp, arg);
308 # ifdef EVIOCGKEYCODE_V2
309                 case EVIOCGKEYCODE_V2:
310                         return keycode_V2_ioctl(tcp, arg);
311 # endif
312         }
313
314         /* fixed-number variable-length commands */
315         switch (_IOC_NR(code)) {
316 # ifdef EVIOCGMTSLOTS
317                 case _IOC_NR(EVIOCGMTSLOTS(0)):
318                         return mtslots_ioctl(tcp, code, arg);
319 # endif
320                 case _IOC_NR(EVIOCGNAME(0)):
321                 case _IOC_NR(EVIOCGPHYS(0)):
322                 case _IOC_NR(EVIOCGUNIQ(0)):
323                         tprints(", ");
324                         if (syserror(tcp))
325                                 printaddr(arg);
326                         else
327                                 printstrn(tcp, arg, tcp->u_rval);
328                         return RVAL_IOCTL_DECODED;
329 # ifdef EVIOCGPROP
330                 case _IOC_NR(EVIOCGPROP(0)):
331                         return decode_bitset(tcp, arg, evdev_prop,
332                                              INPUT_PROP_MAX, "PROP_???",
333                                              XT_INDEXED);
334 # endif
335                 case _IOC_NR(EVIOCGSND(0)):
336                         return decode_bitset(tcp, arg, evdev_snd,
337                                              SND_MAX, "SND_???", XT_INDEXED);
338 # ifdef EVIOCGSW
339                 case _IOC_NR(EVIOCGSW(0)):
340                         return decode_bitset(tcp, arg, evdev_switch,
341                                              SW_MAX, "SW_???", XT_INDEXED);
342 # endif
343                 case _IOC_NR(EVIOCGKEY(0)):
344                         return decode_bitset(tcp, arg, evdev_keycode,
345                                              KEY_MAX, "KEY_???", XT_INDEXED);
346                 case _IOC_NR(EVIOCGLED(0)):
347                         return decode_bitset(tcp, arg, evdev_leds,
348                                              LED_MAX, "LED_???", XT_INDEXED);
349         }
350
351         /* multi-number fixed-length commands */
352         if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0)))
353                 return abs_ioctl(tcp, arg);
354
355         /* multi-number variable-length commands */
356         if ((_IOC_NR(code) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
357                 return bit_ioctl(tcp, _IOC_NR(code) & EV_MAX, arg);
358
359         return 0;
360 }
361
362 static int
363 evdev_write_ioctl(struct tcb *const tcp, const unsigned int code,
364                   const kernel_ulong_t arg)
365 {
366         /* fixed-number fixed-length commands */
367         switch (code) {
368 # ifdef EVIOCSREP
369                 case EVIOCSREP:
370                         return repeat_ioctl(tcp, arg);
371 # endif
372                 case EVIOCSKEYCODE:
373                         return keycode_ioctl(tcp, arg);
374 # ifdef EVIOCSKEYCODE_V2
375                 case EVIOCSKEYCODE_V2:
376                         return keycode_V2_ioctl(tcp, arg);
377 # endif
378                 case EVIOCRMFF:
379                         tprintf(", %d", (int) arg);
380                         return RVAL_IOCTL_DECODED;
381                 case EVIOCGRAB:
382 # ifdef EVIOCREVOKE
383                 case EVIOCREVOKE:
384 # endif
385                         tprintf(", %" PRI_klu, arg);
386                         return RVAL_IOCTL_DECODED;
387 # ifdef EVIOCSCLOCKID
388                 case EVIOCSCLOCKID:
389                         tprints(", ");
390                         printnum_int(tcp, arg, "%u");
391                         return RVAL_IOCTL_DECODED;
392 # endif
393                 default: {
394                         int rc = evdev_write_ioctl_mpers(tcp, code, arg);
395
396                         if (rc != RVAL_DECODED)
397                                 return rc;
398                 }
399         }
400
401         /* multi-number fixed-length commands */
402         if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0)))
403                 return abs_ioctl(tcp, arg);
404
405         return 0;
406 }
407
408 void
409 print_evdev_ff_type(const kernel_ulong_t val)
410 {
411         printxval(evdev_ff_types, val, "FF_???");
412 }
413
414 int
415 evdev_ioctl(struct tcb *const tcp,
416             const unsigned int code, const kernel_ulong_t arg)
417 {
418         switch (_IOC_DIR(code)) {
419                 case _IOC_READ:
420                         if (entering(tcp))
421                                 return 0;
422                         return evdev_read_ioctl(tcp, code, arg);
423                 case _IOC_WRITE:
424                         return evdev_write_ioctl(tcp, code, arg) | RVAL_DECODED;
425                 default:
426                         return RVAL_DECODED;
427         }
428 }
429
430 #endif /* HAVE_LINUX_INPUT_H */