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