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