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