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