blob: cae2ef154ace862b3668a9b0d20e9e2439707735 [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>
Elliott Hughes28e98bc2018-06-14 16:59:04 -07004 * Copyright (c) 2015-2018 The strace developers.
Etienne Gemsa4f750b92015-02-20 17:14:10 +01005 * 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
Elliott Hughes03a418e2018-06-15 13:11:40 -070032#include "xlat/evdev_abs.h"
Elliott Hughesc1873762018-12-19 15:13:36 -080033#include "xlat/evdev_ev.h"
Elliott Hughes03a418e2018-06-15 13:11:40 -070034
Etienne Gemsa4f750b92015-02-20 17:14:10 +010035#ifdef HAVE_LINUX_INPUT_H
Etienne Gemsa4f750b92015-02-20 17:14:10 +010036
Dmitry V. Levin8d85c232016-05-27 00:39:33 +000037# include <linux/ioctl.h>
38# include <linux/input.h>
Dmitry V. Levin43c8a5d2016-05-27 00:49:08 +000039
Dmitry V. Levin8d85c232016-05-27 00:39:33 +000040# include "xlat/evdev_autorepeat.h"
41# include "xlat/evdev_ff_status.h"
42# include "xlat/evdev_ff_types.h"
43# include "xlat/evdev_keycode.h"
44# include "xlat/evdev_leds.h"
45# include "xlat/evdev_misc.h"
46# include "xlat/evdev_mtslots.h"
47# include "xlat/evdev_prop.h"
48# include "xlat/evdev_relative_axes.h"
49# include "xlat/evdev_snd.h"
50# include "xlat/evdev_switch.h"
Dmitry V. Levin8d85c232016-05-27 00:39:33 +000051
52# ifndef SYN_MAX
53# define SYN_MAX 0xf
54# endif
Dmitry V. Levin19dadf92015-02-22 02:50:33 +030055
Elliott Hughes03a418e2018-06-15 13:11:40 -070056const size_t evdev_abs_size = ARRAY_SIZE(evdev_abs) - 1;
57
Etienne Gemsa4f750b92015-02-20 17:14:10 +010058static int
Elliott Hughesd35df492017-02-15 15:19:05 -080059abs_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +010060{
Dmitry V. Levine1670062016-05-27 00:41:14 +000061 tprints(", ");
62
Etienne Gemsa4f750b92015-02-20 17:14:10 +010063 struct input_absinfo absinfo;
64
Dmitry V. Levine1670062016-05-27 00:41:14 +000065 if (!umove_or_printaddr(tcp, arg, &absinfo)) {
66 tprintf("{value=%u"
67 ", minimum=%u, ",
68 absinfo.value,
69 absinfo.minimum);
Etienne Gemsa4f750b92015-02-20 17:14:10 +010070
Dmitry V. Levine1670062016-05-27 00:41:14 +000071 if (!abbrev(tcp)) {
72 tprintf("maximum=%u"
73 ", fuzz=%u"
74 ", flat=%u",
75 absinfo.maximum,
76 absinfo.fuzz,
77 absinfo.flat);
Dmitry V. Levin8d85c232016-05-27 00:39:33 +000078# ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION
Dmitry V. Levine1670062016-05-27 00:41:14 +000079 tprintf(", resolution=%u",
80 absinfo.resolution);
Dmitry V. Levin8d85c232016-05-27 00:39:33 +000081# endif
Dmitry V. Levine1670062016-05-27 00:41:14 +000082 } else {
83 tprints("...");
84 }
85
Etienne Gemsa4f750b92015-02-20 17:14:10 +010086 tprints("}");
Etienne Gemsa4f750b92015-02-20 17:14:10 +010087 }
Dmitry V. Levine1670062016-05-27 00:41:14 +000088
Elliott Hughes77c3ff82017-09-08 17:11:00 -070089 return RVAL_IOCTL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +010090}
91
92static int
Elliott Hughesd35df492017-02-15 15:19:05 -080093keycode_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +010094{
Dmitry V. Levin7954e2a2016-05-27 00:41:25 +000095 tprints(", ");
96
Etienne Gemsa4f750b92015-02-20 17:14:10 +010097 unsigned int keycode[2];
98
Dmitry V. Levin7954e2a2016-05-27 00:41:25 +000099 if (!umove_or_printaddr(tcp, arg, &keycode)) {
100 tprintf("[%u, ", keycode[0]);
Elliott Hughes03a418e2018-06-15 13:11:40 -0700101 printxval_index(evdev_keycode, keycode[1], "KEY_???");
Dmitry V. Levin7954e2a2016-05-27 00:41:25 +0000102 tprints("]");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100103 }
104
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700105 return RVAL_IOCTL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100106}
107
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000108# ifdef EVIOCGKEYCODE_V2
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100109static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800110keycode_V2_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100111{
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000112 tprints(", ");
113
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100114 struct input_keymap_entry ike;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100115
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000116 if (umove_or_printaddr(tcp, arg, &ike))
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700117 return RVAL_IOCTL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100118
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000119 tprintf("{flags=%" PRIu8
120 ", len=%" PRIu8 ", ",
121 ike.flags,
122 ike.len);
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100123
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100124 if (!abbrev(tcp)) {
Dmitry V. Levin7d8b41a2015-02-21 23:05:26 +0000125 unsigned int i;
126
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000127 tprintf("index=%" PRIu16 ", keycode=", ike.index);
Elliott Hughes03a418e2018-06-15 13:11:40 -0700128 printxval_index(evdev_keycode, ike.keycode, "KEY_???");
Dmitry V. Levin7d8b41a2015-02-21 23:05:26 +0000129 tprints(", scancode=[");
130 for (i = 0; i < ARRAY_SIZE(ike.scancode); i++) {
131 if (i > 0)
132 tprints(", ");
133 tprintf("%" PRIx8, ike.scancode[i]);
134 }
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000135 tprints("]");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100136 } else {
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000137 tprints("...");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100138 }
Dmitry V. Levin13f8e8f2016-05-27 00:41:34 +0000139
140 tprints("}");
141
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700142 return RVAL_IOCTL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100143}
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000144# endif /* EVIOCGKEYCODE_V2 */
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100145
146static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800147getid_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100148{
Dmitry V. Levine54f98a2016-05-27 00:41:43 +0000149 tprints(", ");
150
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100151 struct input_id id;
152
Dmitry V. Levine54f98a2016-05-27 00:41:43 +0000153 if (!umove_or_printaddr(tcp, arg, &id))
154 tprintf("{ID_BUS=%" PRIu16
155 ", ID_VENDOR=%" PRIu16
156 ", ID_PRODUCT=%" PRIu16
157 ", ID_VERSION=%" PRIu16 "}",
158 id.bustype,
159 id.vendor,
160 id.product,
161 id.version);
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100162
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700163 return RVAL_IOCTL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100164}
165
166static int
Elliott Hughes03a418e2018-06-15 13:11:40 -0700167decode_bitset_(struct tcb *const tcp, const kernel_ulong_t arg,
168 const struct xlat decode_nr[], const unsigned int max_nr,
169 const char *const dflt, size_t decode_nr_size, enum xlat_type xt)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100170{
Dmitry V. Levin14a810e2016-05-27 00:41:51 +0000171 tprints(", ");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100172
173 unsigned int size;
Elliott Hughesc1873762018-12-19 15:13:36 -0800174 if ((kernel_ulong_t) tcp->u_rval > max_nr / 8)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100175 size = max_nr;
176 else
Elliott Hughesc1873762018-12-19 15:13:36 -0800177 size = tcp->u_rval * 8;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100178 char decoded_arg[size];
179
Dmitry V. Levin14a810e2016-05-27 00:41:51 +0000180 if (umove_or_printaddr(tcp, arg, &decoded_arg))
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700181 return RVAL_IOCTL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100182
Dmitry V. Levin14a810e2016-05-27 00:41:51 +0000183 tprints("[");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100184
185 int bit_displayed = 0;
186 int i = next_set_bit(decoded_arg, 0, size);
187 if (i < 0) {
188 tprints(" 0 ");
189 } else {
Elliott Hughes03a418e2018-06-15 13:11:40 -0700190 printxval_dispatch(decode_nr, decode_nr_size, i, dflt, xt);
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100191
192 while ((i = next_set_bit(decoded_arg, i + 1, size)) > 0) {
193 if (abbrev(tcp) && bit_displayed >= 3) {
194 tprints(", ...");
195 break;
196 }
197 tprints(", ");
Elliott Hughes03a418e2018-06-15 13:11:40 -0700198 printxval_dispatch(decode_nr, decode_nr_size, i, dflt,
199 xt);
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100200 bit_displayed++;
201 }
202 }
203
204 tprints("]");
205
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700206 return RVAL_IOCTL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100207}
208
Elliott Hughes03a418e2018-06-15 13:11:40 -0700209#define decode_bitset(tcp_, arg_, decode_nr_, max_nr_, dflt_, xt_) \
210 decode_bitset_((tcp_), (arg_), (decode_nr_), (max_nr_), \
211 (dflt_), ARRAY_SIZE(decode_nr_), (xt_))
212
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000213# ifdef EVIOCGMTSLOTS
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100214static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800215mtslots_ioctl(struct tcb *const tcp, const unsigned int code,
216 const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100217{
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000218 tprints(", ");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100219
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000220 const size_t size = _IOC_SIZE(code) / sizeof(int);
221 if (!size) {
222 printaddr(arg);
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700223 return RVAL_IOCTL_DECODED;
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000224 }
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100225
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000226 int buffer[size];
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100227
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000228 if (umove_or_printaddr(tcp, arg, &buffer))
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700229 return RVAL_IOCTL_DECODED;
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000230
231 tprints("{code=");
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100232 printxval(evdev_mtslots, buffer[0], "ABS_MT_???");
233
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100234 tprints(", values=[");
235
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000236 unsigned int i;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100237 for (i = 1; i < ARRAY_SIZE(buffer); i++)
238 tprintf("%s%d", i > 1 ? ", " : "", buffer[i]);
239
240 tprints("]}");
Dmitry V. Levin563f0ce2016-05-27 00:41:59 +0000241
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700242 return RVAL_IOCTL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100243}
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000244# endif /* EVIOCGMTSLOTS */
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100245
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000246# if defined EVIOCGREP || defined EVIOCSREP
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100247static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800248repeat_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100249{
Dmitry V. Levinb6795082015-07-06 22:33:39 +0000250 tprints(", ");
251 printpair_int(tcp, arg, "%u");
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700252 return RVAL_IOCTL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100253}
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000254# endif /* EVIOCGREP || EVIOCSREP */
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100255
256static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800257bit_ioctl(struct tcb *const tcp, const unsigned int ev_nr,
258 const kernel_ulong_t arg)
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000259{
260 switch (ev_nr) {
Elliott Hughesc1873762018-12-19 15:13:36 -0800261 case 0:
262 return decode_bitset(tcp, arg, evdev_ev,
263 EV_MAX, "EV_???", XT_SORTED);
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000264 case EV_KEY:
265 return decode_bitset(tcp, arg, evdev_keycode,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700266 KEY_MAX, "KEY_???", XT_INDEXED);
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000267 case EV_REL:
268 return decode_bitset(tcp, arg, evdev_relative_axes,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700269 REL_MAX, "REL_???", XT_INDEXED);
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000270 case EV_ABS:
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000271 return decode_bitset(tcp, arg, evdev_abs,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700272 ABS_MAX, "ABS_???", XT_INDEXED);
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000273 case EV_MSC:
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000274 return decode_bitset(tcp, arg, evdev_misc,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700275 MSC_MAX, "MSC_???", XT_INDEXED);
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000276 case EV_SW:
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000277 return decode_bitset(tcp, arg, evdev_switch,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700278 SW_MAX, "SW_???", XT_INDEXED);
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000279 case EV_LED:
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000280 return decode_bitset(tcp, arg, evdev_leds,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700281 LED_MAX, "LED_???", XT_INDEXED);
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000282 case EV_SND:
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000283 return decode_bitset(tcp, arg, evdev_snd,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700284 SND_MAX, "SND_???", XT_INDEXED);
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000285 case EV_REP:
286 return decode_bitset(tcp, arg, evdev_autorepeat,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700287 REP_MAX, "REP_???", XT_INDEXED);
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000288 case EV_FF:
289 return decode_bitset(tcp, arg, evdev_ff_types,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700290 FF_MAX, "FF_???", XT_SORTED);
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000291 case EV_PWR:
Dmitry V. Levin47be9f22016-05-28 00:12:01 +0000292 tprints(", ");
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000293 printnum_int(tcp, arg, "%d");
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700294 return RVAL_IOCTL_DECODED;
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000295 case EV_FF_STATUS:
296 return decode_bitset(tcp, arg, evdev_ff_status,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700297 FF_STATUS_MAX, "FF_STATUS_???",
298 XT_INDEXED);
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000299 default:
Dmitry V. Levinaa21c072016-05-28 00:49:17 +0000300 tprints(", ");
301 printaddr(arg);
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700302 return RVAL_IOCTL_DECODED;
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000303 }
304}
305
306static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800307evdev_read_ioctl(struct tcb *const tcp, const unsigned int code,
308 const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100309{
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000310 /* fixed-number fixed-length commands */
311 switch (code) {
312 case EVIOCGVERSION:
313 tprints(", ");
Dmitry V. Levinb29569a2016-05-27 00:42:07 +0000314 printnum_int(tcp, arg, "%#x");
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700315 return RVAL_IOCTL_DECODED;
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000316 case EVIOCGEFFECTS:
317 tprints(", ");
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000318 printnum_int(tcp, arg, "%u");
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700319 return RVAL_IOCTL_DECODED;
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000320 case EVIOCGID:
321 return getid_ioctl(tcp, arg);
322# ifdef EVIOCGREP
323 case EVIOCGREP:
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000324 return repeat_ioctl(tcp, arg);
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000325# endif
326 case EVIOCGKEYCODE:
327 return keycode_ioctl(tcp, arg);
328# ifdef EVIOCGKEYCODE_V2
329 case EVIOCGKEYCODE_V2:
330 return keycode_V2_ioctl(tcp, arg);
331# endif
332 }
333
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);
339# endif
340 case _IOC_NR(EVIOCGNAME(0)):
341 case _IOC_NR(EVIOCGPHYS(0)):
342 case _IOC_NR(EVIOCGUNIQ(0)):
343 tprints(", ");
Dmitry V. Levin10de2eb2016-05-27 00:42:18 +0000344 if (syserror(tcp))
345 printaddr(arg);
346 else
Elliott Hughesd35df492017-02-15 15:19:05 -0800347 printstrn(tcp, arg, tcp->u_rval);
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700348 return RVAL_IOCTL_DECODED;
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000349# ifdef EVIOCGPROP
350 case _IOC_NR(EVIOCGPROP(0)):
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000351 return decode_bitset(tcp, arg, evdev_prop,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700352 INPUT_PROP_MAX, "PROP_???",
353 XT_INDEXED);
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000354# endif
355 case _IOC_NR(EVIOCGSND(0)):
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000356 return decode_bitset(tcp, arg, evdev_snd,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700357 SND_MAX, "SND_???", XT_INDEXED);
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000358# ifdef EVIOCGSW
359 case _IOC_NR(EVIOCGSW(0)):
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000360 return decode_bitset(tcp, arg, evdev_switch,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700361 SW_MAX, "SW_???", XT_INDEXED);
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000362# endif
363 case _IOC_NR(EVIOCGKEY(0)):
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000364 return decode_bitset(tcp, arg, evdev_keycode,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700365 KEY_MAX, "KEY_???", XT_INDEXED);
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000366 case _IOC_NR(EVIOCGLED(0)):
Dmitry V. Levin3f23c0c2016-05-27 00:42:25 +0000367 return decode_bitset(tcp, arg, evdev_leds,
Elliott Hughes03a418e2018-06-15 13:11:40 -0700368 LED_MAX, "LED_???", XT_INDEXED);
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000369 }
370
371 /* multi-number fixed-length commands */
372 if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0)))
373 return abs_ioctl(tcp, arg);
374
375 /* multi-number variable-length commands */
Dmitry V. Levin53767d82016-05-27 00:40:18 +0000376 if ((_IOC_NR(code) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
377 return bit_ioctl(tcp, _IOC_NR(code) & EV_MAX, arg);
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100378
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000379 return 0;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100380}
381
382static int
Elliott Hughesd35df492017-02-15 15:19:05 -0800383evdev_write_ioctl(struct tcb *const tcp, const unsigned int code,
384 const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100385{
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000386 /* fixed-number fixed-length commands */
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100387 switch (code) {
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000388# ifdef EVIOCSREP
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100389 case EVIOCSREP:
390 return repeat_ioctl(tcp, arg);
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000391# endif
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100392 case EVIOCSKEYCODE:
393 return keycode_ioctl(tcp, arg);
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000394# ifdef EVIOCSKEYCODE_V2
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100395 case EVIOCSKEYCODE_V2:
396 return keycode_V2_ioctl(tcp, arg);
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000397# endif
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100398 case EVIOCRMFF:
Dmitry V. Levin00394242016-05-27 00:40:27 +0000399 tprintf(", %d", (int) arg);
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700400 return RVAL_IOCTL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100401 case EVIOCGRAB:
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000402# ifdef EVIOCREVOKE
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100403 case EVIOCREVOKE:
Dmitry V. Levin8d85c232016-05-27 00:39:33 +0000404# endif
Elliott Hughesd35df492017-02-15 15:19:05 -0800405 tprintf(", %" PRI_klu, arg);
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700406 return RVAL_IOCTL_DECODED;
Dmitry V. Levin9635df42016-05-27 00:40:45 +0000407# ifdef EVIOCSCLOCKID
408 case EVIOCSCLOCKID:
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100409 tprints(", ");
410 printnum_int(tcp, arg, "%u");
Elliott Hughes77c3ff82017-09-08 17:11:00 -0700411 return RVAL_IOCTL_DECODED;
Dmitry V. Levin9635df42016-05-27 00:40:45 +0000412# endif
Elliott Hughes28e98bc2018-06-14 16:59:04 -0700413 default: {
414 int rc = evdev_write_ioctl_mpers(tcp, code, arg);
415
416 if (rc != RVAL_DECODED)
417 return rc;
418 }
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100419 }
Dmitry V. Levin8a18f802016-05-27 00:40:10 +0000420
421 /* multi-number fixed-length commands */
422 if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0)))
423 return abs_ioctl(tcp, arg);
424
425 return 0;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100426}
427
Elliott Hughes28e98bc2018-06-14 16:59:04 -0700428void
429print_evdev_ff_type(const kernel_ulong_t val)
430{
431 printxval(evdev_ff_types, val, "FF_???");
432}
433
434int
435evdev_ioctl(struct tcb *const tcp,
436 const unsigned int code, const kernel_ulong_t arg)
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100437{
Elliott Hughesdc75b012017-07-05 13:54:44 -0700438 switch (_IOC_DIR(code)) {
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100439 case _IOC_READ:
Dmitry V. Levin2114e082016-05-27 00:40:02 +0000440 if (entering(tcp))
441 return 0;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100442 return evdev_read_ioctl(tcp, code, arg);
443 case _IOC_WRITE:
Dmitry V. Levin2114e082016-05-27 00:40:02 +0000444 return evdev_write_ioctl(tcp, code, arg) | RVAL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100445 default:
Dmitry V. Levin2114e082016-05-27 00:40:02 +0000446 return RVAL_DECODED;
Etienne Gemsa4f750b92015-02-20 17:14:10 +0100447 }
448}
449
450#endif /* HAVE_LINUX_INPUT_H */