evdev.c revision 484326dbd8f8e02983e37498b4b5fa990d16b536
1/* 2 * Copyright (c) 2015 Etienne Gemsa <etienne.gemsa@lse.epita.fr> 3 * Copyright (c) 2015-2016 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 33#include DEF_MPERS_TYPE(struct_ff_effect) 34 35# include <linux/ioctl.h> 36# include <linux/input.h> 37 38typedef struct ff_effect struct_ff_effect; 39 40#endif /* HAVE_LINUX_BTRFS_H */ 41 42#include MPERS_DEFS 43 44#ifdef HAVE_LINUX_INPUT_H 45 46# 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 62 63static void 64decode_envelope(void *const data) 65{ 66 const struct ff_envelope *const envelope = data; 67 68 tprintf(", envelope={attack_length=%" PRIu16 69 ", attack_level=%" PRIu16 70 ", fade_length=%" PRIu16 71 ", fade_level=%#x}", 72 envelope->attack_length, 73 envelope->attack_level, 74 envelope->fade_length, 75 envelope->fade_level); 76} 77 78static int 79ff_effect_ioctl(struct tcb *tcp, long arg) 80{ 81 tprints(", "); 82 83 struct_ff_effect ffe; 84 85 if (umove_or_printaddr(tcp, arg, &ffe)) 86 return 1; 87 88 tprints("{type="); 89 printxval(evdev_ff_types, ffe.type, "FF_???"); 90 tprintf(", id=%" PRIu16 91 ", direction=%" PRIu16 ", ", 92 ffe.id, 93 ffe.direction); 94 95 if (abbrev(tcp)) { 96 tprints("...}"); 97 return 1; 98 } 99 100 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); 136 tprintf(", custom_len=%u, custom_data=", 137 ffe.u.periodic.custom_len); 138 printaddr((unsigned long) ffe.u.periodic.custom_data); 139 tprints("}"); 140 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 153 return 1; 154} 155 156static int 157abs_ioctl(struct tcb *tcp, long arg) 158{ 159 tprints(", "); 160 161 struct input_absinfo absinfo; 162 163 if (!umove_or_printaddr(tcp, arg, &absinfo)) { 164 tprintf("{value=%u" 165 ", minimum=%u, ", 166 absinfo.value, 167 absinfo.minimum); 168 169 if (!abbrev(tcp)) { 170 tprintf("maximum=%u" 171 ", fuzz=%u" 172 ", flat=%u", 173 absinfo.maximum, 174 absinfo.fuzz, 175 absinfo.flat); 176# ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION 177 tprintf(", resolution=%u", 178 absinfo.resolution); 179# endif 180 } else { 181 tprints("..."); 182 } 183 184 tprints("}"); 185 } 186 187 return 1; 188} 189 190static int 191keycode_ioctl(struct tcb *tcp, long arg) 192{ 193 tprints(", "); 194 195 unsigned int keycode[2]; 196 197 if (!umove_or_printaddr(tcp, arg, &keycode)) { 198 tprintf("[%u, ", keycode[0]); 199 printxval(evdev_keycode, keycode[1], "KEY_???"); 200 tprints("]"); 201 } 202 203 return 1; 204} 205 206# ifdef EVIOCGKEYCODE_V2 207static int 208keycode_V2_ioctl(struct tcb *tcp, long arg) 209{ 210 tprints(", "); 211 212 struct input_keymap_entry ike; 213 214 if (umove_or_printaddr(tcp, arg, &ike)) 215 return 1; 216 217 tprintf("{flags=%" PRIu8 218 ", len=%" PRIu8 ", ", 219 ike.flags, 220 ike.len); 221 222 if (!abbrev(tcp)) { 223 unsigned int i; 224 225 tprintf("index=%" PRIu16 ", keycode=", ike.index); 226 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 } 233 tprints("]"); 234 } else { 235 tprints("..."); 236 } 237 238 tprints("}"); 239 240 return 1; 241} 242# endif /* EVIOCGKEYCODE_V2 */ 243 244static int 245getid_ioctl(struct tcb *tcp, long arg) 246{ 247 tprints(", "); 248 249 struct input_id id; 250 251 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); 260 261 return 1; 262} 263 264static int 265decode_bitset(struct tcb *tcp, long arg, const struct xlat decode_nr[], 266 const unsigned int max_nr, const char *dflt) 267{ 268 tprints(", "); 269 270 unsigned int size; 271 if ((unsigned long) tcp->u_rval > max_nr) 272 size = max_nr; 273 else 274 size = tcp->u_rval; 275 char decoded_arg[size]; 276 277 if (umove_or_printaddr(tcp, arg, &decoded_arg)) 278 return 1; 279 280 tprints("["); 281 282 int bit_displayed = 0; 283 int i = next_set_bit(decoded_arg, 0, size); 284 if (i < 0) { 285 tprints(" 0 "); 286 } else { 287 printxval(decode_nr, i, dflt); 288 289 while ((i = next_set_bit(decoded_arg, i + 1, size)) > 0) { 290 if (abbrev(tcp) && bit_displayed >= 3) { 291 tprints(", ..."); 292 break; 293 } 294 tprints(", "); 295 printxval(decode_nr, i, dflt); 296 bit_displayed++; 297 } 298 } 299 300 tprints("]"); 301 302 return 1; 303} 304 305# ifdef EVIOCGMTSLOTS 306static int 307mtslots_ioctl(struct tcb *tcp, const unsigned int code, long arg) 308{ 309 tprints(", "); 310 311 const size_t size = _IOC_SIZE(code) / sizeof(int); 312 if (!size) { 313 printaddr(arg); 314 return 1; 315 } 316 317 int buffer[size]; 318 319 if (umove_or_printaddr(tcp, arg, &buffer)) 320 return 1; 321 322 tprints("{code="); 323 printxval(evdev_mtslots, buffer[0], "ABS_MT_???"); 324 325 tprints(", values=["); 326 327 unsigned int i; 328 for (i = 1; i < ARRAY_SIZE(buffer); i++) 329 tprintf("%s%d", i > 1 ? ", " : "", buffer[i]); 330 331 tprints("]}"); 332 333 return 1; 334} 335# endif /* EVIOCGMTSLOTS */ 336 337# if defined EVIOCGREP || defined EVIOCSREP 338static int 339repeat_ioctl(struct tcb *tcp, long arg) 340{ 341 tprints(", "); 342 printpair_int(tcp, arg, "%u"); 343 return 1; 344} 345# endif /* EVIOCGREP || EVIOCSREP */ 346 347static int 348bit_ioctl(struct tcb *tcp, const unsigned int ev_nr, const long arg) 349{ 350 switch (ev_nr) { 351 case EV_SYN: 352 return decode_bitset(tcp, arg, evdev_sync, 353 SYN_MAX, "SYN_???"); 354 case EV_KEY: 355 return decode_bitset(tcp, arg, evdev_keycode, 356 KEY_MAX, "KEY_???"); 357 case EV_REL: 358 return decode_bitset(tcp, arg, evdev_relative_axes, 359 REL_MAX, "REL_???"); 360 case EV_ABS: 361 return decode_bitset(tcp, arg, evdev_abs, 362 ABS_MAX, "ABS_???"); 363 case EV_MSC: 364 return decode_bitset(tcp, arg, evdev_misc, 365 MSC_MAX, "MSC_???"); 366# ifdef EV_SW 367 case EV_SW: 368 return decode_bitset(tcp, arg, evdev_switch, 369 SW_MAX, "SW_???"); 370# endif 371 case EV_LED: 372 return decode_bitset(tcp, arg, evdev_leds, 373 LED_MAX, "LED_???"); 374 case EV_SND: 375 return decode_bitset(tcp, arg, evdev_snd, 376 SND_MAX, "SND_???"); 377 case EV_REP: 378 return decode_bitset(tcp, arg, evdev_autorepeat, 379 REP_MAX, "REP_???"); 380 case EV_FF: 381 return decode_bitset(tcp, arg, evdev_ff_types, 382 FF_MAX, "FF_???"); 383 case EV_PWR: 384 tprints(", "); 385 printnum_int(tcp, arg, "%d"); 386 return 1; 387 case EV_FF_STATUS: 388 return decode_bitset(tcp, arg, evdev_ff_status, 389 FF_STATUS_MAX, "FF_STATUS_???"); 390 default: 391 tprints(", "); 392 printaddr(arg); 393 return 1; 394 } 395} 396 397static int 398evdev_read_ioctl(struct tcb *tcp, const unsigned int code, const long arg) 399{ 400 /* fixed-number fixed-length commands */ 401 switch (code) { 402 case EVIOCGVERSION: 403 tprints(", "); 404 printnum_int(tcp, arg, "%#x"); 405 return 1; 406 case EVIOCGEFFECTS: 407 tprints(", "); 408 printnum_int(tcp, arg, "%u"); 409 return 1; 410 case EVIOCGID: 411 return getid_ioctl(tcp, arg); 412# ifdef EVIOCGREP 413 case EVIOCGREP: 414 return repeat_ioctl(tcp, arg); 415# endif 416 case EVIOCGKEYCODE: 417 return keycode_ioctl(tcp, arg); 418# ifdef EVIOCGKEYCODE_V2 419 case EVIOCGKEYCODE_V2: 420 return keycode_V2_ioctl(tcp, arg); 421# endif 422 } 423 424 /* fixed-number variable-length commands */ 425 switch (_IOC_NR(code)) { 426# ifdef EVIOCGMTSLOTS 427 case _IOC_NR(EVIOCGMTSLOTS(0)): 428 return mtslots_ioctl(tcp, code, arg); 429# endif 430 case _IOC_NR(EVIOCGNAME(0)): 431 case _IOC_NR(EVIOCGPHYS(0)): 432 case _IOC_NR(EVIOCGUNIQ(0)): 433 tprints(", "); 434 if (syserror(tcp)) 435 printaddr(arg); 436 else 437 printstr(tcp, arg, tcp->u_rval); 438 return 1; 439# ifdef EVIOCGPROP 440 case _IOC_NR(EVIOCGPROP(0)): 441 return decode_bitset(tcp, arg, evdev_prop, 442 INPUT_PROP_MAX, "PROP_???"); 443# endif 444 case _IOC_NR(EVIOCGSND(0)): 445 return decode_bitset(tcp, arg, evdev_snd, 446 SND_MAX, "SND_???"); 447# ifdef EVIOCGSW 448 case _IOC_NR(EVIOCGSW(0)): 449 return decode_bitset(tcp, arg, evdev_switch, 450 SW_MAX, "SW_???"); 451# endif 452 case _IOC_NR(EVIOCGKEY(0)): 453 return decode_bitset(tcp, arg, evdev_keycode, 454 KEY_MAX, "KEY_???"); 455 case _IOC_NR(EVIOCGLED(0)): 456 return decode_bitset(tcp, arg, evdev_leds, 457 LED_MAX, "LED_???"); 458 } 459 460 /* multi-number fixed-length commands */ 461 if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) 462 return abs_ioctl(tcp, arg); 463 464 /* multi-number variable-length commands */ 465 if ((_IOC_NR(code) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) 466 return bit_ioctl(tcp, _IOC_NR(code) & EV_MAX, arg); 467 468 return 0; 469} 470 471static int 472evdev_write_ioctl(struct tcb *tcp, const unsigned int code, const long arg) 473{ 474 /* fixed-number fixed-length commands */ 475 switch (code) { 476# ifdef EVIOCSREP 477 case EVIOCSREP: 478 return repeat_ioctl(tcp, arg); 479# endif 480 case EVIOCSKEYCODE: 481 return keycode_ioctl(tcp, arg); 482# ifdef EVIOCSKEYCODE_V2 483 case EVIOCSKEYCODE_V2: 484 return keycode_V2_ioctl(tcp, arg); 485# endif 486 case EVIOCSFF: 487 return ff_effect_ioctl(tcp, arg); 488 case EVIOCRMFF: 489 tprintf(", %d", (int) arg); 490 return 1; 491 case EVIOCGRAB: 492# ifdef EVIOCREVOKE 493 case EVIOCREVOKE: 494# endif 495 tprintf(", %lu", arg); 496 return 1; 497# ifdef EVIOCSCLOCKID 498 case EVIOCSCLOCKID: 499 tprints(", "); 500 printnum_int(tcp, arg, "%u"); 501 return 1; 502# endif 503 } 504 505 /* multi-number fixed-length commands */ 506 if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) 507 return abs_ioctl(tcp, arg); 508 509 return 0; 510} 511 512MPERS_PRINTER_DECL(int, evdev_ioctl, struct tcb *tcp, 513 const unsigned int code, const long arg) 514{ 515 switch(_IOC_DIR(code)) { 516 case _IOC_READ: 517 if (entering(tcp)) 518 return 0; 519 return evdev_read_ioctl(tcp, code, arg); 520 case _IOC_WRITE: 521 return evdev_write_ioctl(tcp, code, arg) | RVAL_DECODED; 522 default: 523 return RVAL_DECODED; 524 } 525} 526 527#endif /* HAVE_LINUX_INPUT_H */ 528