blob: 983bf1488681dc8f3ab01c412c66e87688d4370f [file] [log] [blame]
Etienne Gemsa4f750b92015-02-20 17:14:10 +01001/*
2 * Copyright (c) 2015 Etienne Gemsa <etienne.gemsa@lse.epita.fr>
Dmitry V. Levin43c8a5d2016-05-27 00:49:08 +00003 * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org>
Etienne Gemsa4f750b92015-02-20 17:14:10 +01004 * 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
Etienne Gemsa4f750b92015-02-20 17:14:10 +010032
Dmitry V. Levin43c8a5d2016-05-27 00:49:08 +000033#include DEF_MPERS_TYPE(struct_ff_effect)
34
Dmitry V. Levin8d85c232016-05-27 00:39:33 +000035# include <linux/ioctl.h>
36# include <linux/input.h>
Dmitry V. Levin43c8a5d2016-05-27 00:49:08 +000037
38typedef struct ff_effect struct_ff_effect;
39
Dmitry V. Levin7af5e652016-08-15 21:08:16 +000040#endif /* HAVE_LINUX_INPUT_H */
Dmitry V. Levin43c8a5d2016-05-27 00:49:08 +000041
42#include MPERS_DEFS
43
44#ifdef HAVE_LINUX_INPUT_H
45
Dmitry V. Levin8d85c232016-05-27 00:39:33 +000046# 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
Dmitry V. Levin19dadf92015-02-22 02:50:33 +030062
Etienne Gemsa4f750b92015-02-20 17:14:10 +010063static void
Dmitry V. Levin43c8a5d2016-05-27 00:49:08 +000064decode_envelope(void *const data)
Etienne Gemsa4f750b92015-02-20 17:14:10 +010065{
Dmitry V. Levin43c8a5d2016-05-27 00:49:08 +000066 const struct ff_envelope *const envelope = data;
67
Dmitry V. Levinc758ed02016-05-27 00:40:53 +000068 tprintf(", envelope={attack_length=%" PRIu16
69 ", attack_level=%" PRIu16
70 ", fade_length=%" PRIu16
71 ", fade_level=%#x}",
Etienne Gemsa4f750b92015-02-20 17:14:10 +010072 envelope->attack_length,
73 envelope->attack_level,
74 envelope->fade_length,
75 envelope->fade_level);
76}
77
78static int
Elliott Hughesd35df492017-02-15 15:19:05 -080079ff_effect_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +010080{
Dmitry V. Levin3a45eb32016-05-27 00:41:02 +000081 tprints(", ");
82
Dmitry V. Levin43c8a5d2016-05-27 00:49:08 +000083 struct_ff_effect ffe;
Etienne Gemsa4f750b92015-02-20 17:14:10 +010084
Dmitry V. Levin3a45eb32016-05-27 00:41:02 +000085 if (umove_or_printaddr(tcp, arg, &ffe))
86 return 1;
Etienne Gemsa4f750b92015-02-20 17:14:10 +010087
Dmitry V. Levin3a45eb32016-05-27 00:41:02 +000088 tprints("{type=");
Etienne Gemsa4f750b92015-02-20 17:14:10 +010089 printxval(evdev_ff_types, ffe.type, "FF_???");
Dmitry V. Levin3a45eb32016-05-27 00:41:02 +000090 tprintf(", id=%" PRIu16
91 ", direction=%" PRIu16 ", ",
92 ffe.id,
93 ffe.direction);
Etienne Gemsa4f750b92015-02-20 17:14:10 +010094
Dmitry V. Levin3a45eb32016-05-27 00:41:02 +000095 if (abbrev(tcp)) {
96 tprints("...}");
97 return 1;
Etienne Gemsa4f750b92015-02-20 17:14:10 +010098 }
99
Dmitry V. Levin3a45eb32016-05-27 00:41:02 +0000100 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);
Dmitry V. Levin484326d2016-06-11 01:28:21 +0000136 tprintf(", custom_len=%u, custom_data=",
137 ffe.u.periodic.custom_len);
Elliott Hughesd35df492017-02-15 15:19:05 -0800138 printaddr(ptr_to_kulong(ffe.u.periodic.custom_data));
Dmitry V. Levin484326d2016-06-11 01:28:21 +0000139 tprints("}");
Dmitry V. Levin3a45eb32016-05-27 00:41:02 +0000140 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
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100153 return 1;
154}
155
156static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800157abs_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100158{
Dmitry V. Levine1670062016-05-27 00:41:14 +0000159 tprints(", ");
160
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100161 struct input_absinfo absinfo;
162
Dmitry V. Levine1670062016-05-27 00:41:14 +0000163 if (!umove_or_printaddr(tcp, arg, &absinfo)) {
164 tprintf("{value=%u"
165 ", minimum=%u, ",
166 absinfo.value,
167 absinfo.minimum);
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100168
Dmitry V. Levine1670062016-05-27 00:41:14 +0000169 if (!abbrev(tcp)) {
170 tprintf("maximum=%u"
171 ", fuzz=%u"
172 ", flat=%u",
173 absinfo.maximum,
174 absinfo.fuzz,
175 absinfo.flat);
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000176# ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION
Dmitry V. Levine1670062016-05-27 00:41:14 +0000177 tprintf(", resolution=%u",
178 absinfo.resolution);
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000179# endif
Dmitry V. Levine1670062016-05-27 00:41:14 +0000180 } else {
181 tprints("...");
182 }
183
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100184 tprints("}");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100185 }
Dmitry V. Levine1670062016-05-27 00:41:14 +0000186
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100187 return 1;
188}
189
190static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800191keycode_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100192{
Dmitry V. Levin7954e2a2016-05-27 00:41:25 +0000193 tprints(", ");
194
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100195 unsigned int keycode[2];
196
Dmitry V. Levin7954e2a2016-05-27 00:41:25 +0000197 if (!umove_or_printaddr(tcp, arg, &keycode)) {
198 tprintf("[%u, ", keycode[0]);
199 printxval(evdev_keycode, keycode[1], "KEY_???");
200 tprints("]");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100201 }
202
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100203 return 1;
204}
205
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000206# ifdef EVIOCGKEYCODE_V2
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100207static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800208keycode_V2_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100209{
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000210 tprints(", ");
211
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100212 struct input_keymap_entry ike;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100213
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000214 if (umove_or_printaddr(tcp, arg, &ike))
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100215 return 1;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100216
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000217 tprintf("{flags=%" PRIu8
218 ", len=%" PRIu8 ", ",
219 ike.flags,
220 ike.len);
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100221
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100222 if (!abbrev(tcp)) {
Dmitry V. Levin7d8b41a2015-02-21 23:05:26 +0000223 unsigned int i;
224
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000225 tprintf("index=%" PRIu16 ", keycode=", ike.index);
Dmitry V. Levin7d8b41a2015-02-21 23:05:26 +0000226 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 }
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000233 tprints("]");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100234 } else {
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000235 tprints("...");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100236 }
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000237
238 tprints("}");
239
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100240 return 1;
241}
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000242# endif /* EVIOCGKEYCODE_V2 */
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100243
244static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800245getid_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100246{
Dmitry V. Levine54f98a2016-05-27 00:41:43 +0000247 tprints(", ");
248
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100249 struct input_id id;
250
Dmitry V. Levine54f98a2016-05-27 00:41:43 +0000251 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);
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100260
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100261 return 1;
262}
263
264static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800265decode_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)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100268{
Dmitry V. Levin14a810e2016-05-27 00:41:51 +0000269 tprints(", ");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100270
271 unsigned int size;
Elliott Hughesd35df492017-02-15 15:19:05 -0800272 if ((kernel_ulong_t) tcp->u_rval > max_nr)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100273 size = max_nr;
274 else
275 size = tcp->u_rval;
276 char decoded_arg[size];
277
Dmitry V. Levin14a810e2016-05-27 00:41:51 +0000278 if (umove_or_printaddr(tcp, arg, &decoded_arg))
279 return 1;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100280
Dmitry V. Levin14a810e2016-05-27 00:41:51 +0000281 tprints("[");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100282
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
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000306# ifdef EVIOCGMTSLOTS
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100307static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800308mtslots_ioctl(struct tcb *const tcp, const unsigned int code,
309 const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100310{
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000311 tprints(", ");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100312
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000313 const size_t size = _IOC_SIZE(code) / sizeof(int);
314 if (!size) {
315 printaddr(arg);
316 return 1;
317 }
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100318
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000319 int buffer[size];
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100320
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000321 if (umove_or_printaddr(tcp, arg, &buffer))
322 return 1;
323
324 tprints("{code=");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100325 printxval(evdev_mtslots, buffer[0], "ABS_MT_???");
326
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100327 tprints(", values=[");
328
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000329 unsigned int i;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100330 for (i = 1; i < ARRAY_SIZE(buffer); i++)
331 tprintf("%s%d", i > 1 ? ", " : "", buffer[i]);
332
333 tprints("]}");
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000334
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100335 return 1;
336}
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000337# endif /* EVIOCGMTSLOTS */
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100338
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000339# if defined EVIOCGREP || defined EVIOCSREP
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100340static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800341repeat_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100342{
Dmitry V. Levinb6795082015-07-06 22:33:39 +0000343 tprints(", ");
344 printpair_int(tcp, arg, "%u");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100345 return 1;
346}
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000347# endif /* EVIOCGREP || EVIOCSREP */
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100348
349static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800350bit_ioctl(struct tcb *const tcp, const unsigned int ev_nr,
351 const kernel_ulong_t arg)
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000352{
353 switch (ev_nr) {
354 case EV_SYN:
355 return decode_bitset(tcp, arg, evdev_sync,
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000356 SYN_MAX, "SYN_???");
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000357 case EV_KEY:
358 return decode_bitset(tcp, arg, evdev_keycode,
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000359 KEY_MAX, "KEY_???");
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000360 case EV_REL:
361 return decode_bitset(tcp, arg, evdev_relative_axes,
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000362 REL_MAX, "REL_???");
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000363 case EV_ABS:
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000364 return decode_bitset(tcp, arg, evdev_abs,
365 ABS_MAX, "ABS_???");
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000366 case EV_MSC:
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000367 return decode_bitset(tcp, arg, evdev_misc,
368 MSC_MAX, "MSC_???");
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000369# ifdef EV_SW
370 case EV_SW:
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000371 return decode_bitset(tcp, arg, evdev_switch,
372 SW_MAX, "SW_???");
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000373# endif
374 case EV_LED:
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000375 return decode_bitset(tcp, arg, evdev_leds,
376 LED_MAX, "LED_???");
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000377 case EV_SND:
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000378 return decode_bitset(tcp, arg, evdev_snd,
379 SND_MAX, "SND_???");
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000380 case EV_REP:
381 return decode_bitset(tcp, arg, evdev_autorepeat,
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000382 REP_MAX, "REP_???");
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000383 case EV_FF:
384 return decode_bitset(tcp, arg, evdev_ff_types,
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000385 FF_MAX, "FF_???");
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000386 case EV_PWR:
Dmitry V. Levin47be9f22016-05-28 00:12:01 +0000387 tprints(", ");
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000388 printnum_int(tcp, arg, "%d");
389 return 1;
390 case EV_FF_STATUS:
391 return decode_bitset(tcp, arg, evdev_ff_status,
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000392 FF_STATUS_MAX, "FF_STATUS_???");
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000393 default:
Dmitry V. Levinaa21c072016-05-28 00:49:17 +0000394 tprints(", ");
395 printaddr(arg);
396 return 1;
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000397 }
398}
399
400static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800401evdev_read_ioctl(struct tcb *const tcp, const unsigned int code,
402 const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100403{
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000404 /* fixed-number fixed-length commands */
405 switch (code) {
406 case EVIOCGVERSION:
407 tprints(", ");
Dmitry V. Levinb29569a2016-05-27 00:42:07 +0000408 printnum_int(tcp, arg, "%#x");
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000409 return 1;
410 case EVIOCGEFFECTS:
411 tprints(", ");
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000412 printnum_int(tcp, arg, "%u");
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000413 return 1;
414 case EVIOCGID:
415 return getid_ioctl(tcp, arg);
416# ifdef EVIOCGREP
417 case EVIOCGREP:
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000418 return repeat_ioctl(tcp, arg);
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000419# 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(", ");
Dmitry V. Levin10de2eb2016-05-27 00:42:18 +0000438 if (syserror(tcp))
439 printaddr(arg);
440 else
Elliott Hughesd35df492017-02-15 15:19:05 -0800441 printstrn(tcp, arg, tcp->u_rval);
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000442 return 1;
443# ifdef EVIOCGPROP
444 case _IOC_NR(EVIOCGPROP(0)):
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000445 return decode_bitset(tcp, arg, evdev_prop,
446 INPUT_PROP_MAX, "PROP_???");
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000447# endif
448 case _IOC_NR(EVIOCGSND(0)):
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000449 return decode_bitset(tcp, arg, evdev_snd,
450 SND_MAX, "SND_???");
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000451# ifdef EVIOCGSW
452 case _IOC_NR(EVIOCGSW(0)):
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000453 return decode_bitset(tcp, arg, evdev_switch,
454 SW_MAX, "SW_???");
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000455# endif
456 case _IOC_NR(EVIOCGKEY(0)):
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000457 return decode_bitset(tcp, arg, evdev_keycode,
458 KEY_MAX, "KEY_???");
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000459 case _IOC_NR(EVIOCGLED(0)):
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000460 return decode_bitset(tcp, arg, evdev_leds,
461 LED_MAX, "LED_???");
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000462 }
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 */
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000469 if ((_IOC_NR(code) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
470 return bit_ioctl(tcp, _IOC_NR(code) & EV_MAX, arg);
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100471
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000472 return 0;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100473}
474
475static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800476evdev_write_ioctl(struct tcb *const tcp, const unsigned int code,
477 const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100478{
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000479 /* fixed-number fixed-length commands */
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100480 switch (code) {
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000481# ifdef EVIOCSREP
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100482 case EVIOCSREP:
483 return repeat_ioctl(tcp, arg);
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000484# endif
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100485 case EVIOCSKEYCODE:
486 return keycode_ioctl(tcp, arg);
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000487# ifdef EVIOCSKEYCODE_V2
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100488 case EVIOCSKEYCODE_V2:
489 return keycode_V2_ioctl(tcp, arg);
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000490# endif
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100491 case EVIOCSFF:
492 return ff_effect_ioctl(tcp, arg);
493 case EVIOCRMFF:
Dmitry V. Levin00394242016-05-27 00:40:27 +0000494 tprintf(", %d", (int) arg);
495 return 1;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100496 case EVIOCGRAB:
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000497# ifdef EVIOCREVOKE
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100498 case EVIOCREVOKE:
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000499# endif
Elliott Hughesd35df492017-02-15 15:19:05 -0800500 tprintf(", %" PRI_klu, arg);
Dmitry V. Levin9635df42016-05-27 00:40:45 +0000501 return 1;
502# ifdef EVIOCSCLOCKID
503 case EVIOCSCLOCKID:
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100504 tprints(", ");
505 printnum_int(tcp, arg, "%u");
506 return 1;
Dmitry V. Levin9635df42016-05-27 00:40:45 +0000507# endif
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100508 }
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000509
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;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100515}
516
Elliott Hughesd35df492017-02-15 15:19:05 -0800517MPERS_PRINTER_DECL(int, evdev_ioctl, struct tcb *const tcp,
518 const unsigned int code, const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100519{
Elliott Hughesdc75b012017-07-05 13:54:44 -0700520 switch (_IOC_DIR(code)) {
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100521 case _IOC_READ:
Dmitry V. Levin2114e082016-05-27 00:40:02 +0000522 if (entering(tcp))
523 return 0;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100524 return evdev_read_ioctl(tcp, code, arg);
525 case _IOC_WRITE:
Dmitry V. Levin2114e082016-05-27 00:40:02 +0000526 return evdev_write_ioctl(tcp, code, arg) | RVAL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100527 default:
Dmitry V. Levin2114e082016-05-27 00:40:02 +0000528 return RVAL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100529 }
530}
531
532#endif /* HAVE_LINUX_INPUT_H */