From 6f9a01c72121bc0b0fc760d9fea6879fb85f6f02 Mon Sep 17 00:00:00 2001 From: Gabriel Laskar Date: Wed, 21 Jan 2015 23:35:27 +0100 Subject: [PATCH] ioctl: add decoding for parametrized command names Some ioctl commands from evdev, hiddev, mixer, uinput, spi, and joystick are parametrized by a size or a number that are variable. This change implements printing of these parametrized ioctl command names. * configure.ac (AC_CHECK_HEADERS): Add linux/input.h. * defs.h (ioctl_decode_number): New prototype. * io.c (sys_ioctl): Use ioctl_decode_number. * ioctl.c (ioctl_decode_number): New function. * xlat/evdev_abs.in: New file. * xlat/evdev_ev.in: New file. Signed-off-by: Gabriel Laskar --- configure.ac | 1 + defs.h | 1 + io.c | 17 +++--- ioctl.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++ xlat/evdev_abs.in | 41 +++++++++++++ xlat/evdev_ev.in | 12 ++++ 6 files changed, 210 insertions(+), 7 deletions(-) create mode 100644 xlat/evdev_abs.in create mode 100644 xlat/evdev_ev.in diff --git a/configure.ac b/configure.ac index c2e64f10..2359d49d 100644 --- a/configure.ac +++ b/configure.ac @@ -223,6 +223,7 @@ AC_CHECK_HEADERS(m4_normalize([ inttypes.h ioctls.h linux/falloc.h + linux/input.h linux/perf_event.h linux/ptrace.h linux/utsname.h diff --git a/defs.h b/defs.h index 33cdef03..8d654a59 100644 --- a/defs.h +++ b/defs.h @@ -735,6 +735,7 @@ extern const struct_ioctlent *ioctl_lookup(const unsigned int); extern const struct_ioctlent *ioctl_next_match(const struct_ioctlent *); extern void ioctl_print_code(const unsigned int); extern int ioctl_decode(struct tcb *, const unsigned int, long); +extern int ioctl_decode_command_number(const unsigned int); extern int block_ioctl(struct tcb *, const unsigned int, long); extern int loop_ioctl(struct tcb *, const unsigned int, long); extern int mtd_ioctl(struct tcb *, const unsigned int, long); diff --git a/io.c b/io.c index 2a36c000..6b24159a 100644 --- a/io.c +++ b/io.c @@ -398,13 +398,16 @@ sys_ioctl(struct tcb *tcp) if (entering(tcp)) { printfd(tcp, tcp->u_arg[0]); tprints(", "); - iop = ioctl_lookup(tcp->u_arg[1]); - if (iop) { - tprints(iop->symbol); - while ((iop = ioctl_next_match(iop))) - tprintf(" or %s", iop->symbol); - } else - ioctl_print_code(tcp->u_arg[1]); + if (!ioctl_decode_command_number(tcp->u_arg[1])) { + iop = ioctl_lookup(tcp->u_arg[1]); + if (iop) { + tprints(iop->symbol); + while ((iop = ioctl_next_match(iop))) + tprintf(" or %s", iop->symbol); + } else { + ioctl_print_code(tcp->u_arg[1]); + } + } ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2]); } else { diff --git a/ioctl.c b/ioctl.c index f9d570e8..65786647 100644 --- a/ioctl.c +++ b/ioctl.c @@ -32,6 +32,13 @@ #include #include "xlat/ioctl_dirs.h" +#ifdef HAVE_LINUX_INPUT_H +# include +#endif + +#include "xlat/evdev_abs.h" +#include "xlat/evdev_ev.h" + static int compare(const void *a, const void *b) { @@ -77,6 +84,144 @@ ioctl_print_code(const unsigned int code) _IOC_TYPE(code), _IOC_NR(code), _IOC_SIZE(code)); } +static int +evdev_decode_number(unsigned int arg) +{ + unsigned int nr = _IOC_NR(arg); + + if (_IOC_DIR(arg) == _IOC_WRITE) { + if (nr >= 0xc0 && nr <= 0xc0 + 0x3f) { + tprints("EVIOCSABS("); + printxval(evdev_abs, nr - 0xc0, "EV_???"); + tprints(")"); + return 1; + } + } + + if (_IOC_DIR(arg) != _IOC_READ) + return 0; + + if (nr >= 0x20 && nr <= 0x20 + 0x1f) { + tprints("EVIOCGBIT("); + printxval(evdev_ev, nr - 0x20, "EV_???"); + tprintf(", %u)", _IOC_SIZE(arg)); + return 1; + } else if (nr >= 0x40 && nr <= 0x40 + 0x3f) { + tprints("EVIOCGABS("); + printxval(evdev_abs, nr - 0x40, "ABS_???"); + tprints(")"); + return 1; + } + + switch (_IOC_NR(nr)) { + case 0x06: + tprintf("EVIOCGNAME(%u)", _IOC_SIZE(arg)); + return 1; + case 0x07: + tprintf("EVIOCGPHYS(%u)", _IOC_SIZE(arg)); + return 1; + case 0x08: + tprintf("EVIOCGUNIQ(%u)", _IOC_SIZE(arg)); + return 1; + case 0x09: + tprintf("EVIOCGPROP(%u)", _IOC_SIZE(arg)); + return 1; + case 0x0a: + tprintf("EVIOCGMTSLOTS(%u)", _IOC_SIZE(arg)); + return 1; + case 0x18: + tprintf("EVIOCGKEY(%u)", _IOC_SIZE(arg)); + return 1; + case 0x19: + tprintf("EVIOCGLED(%u)", _IOC_SIZE(arg)); + return 1; + case 0x1a: + tprintf("EVIOCGSND(%u)", _IOC_SIZE(arg)); + return 1; + case 0x1b: + tprintf("EVIOCGSW(%u)", _IOC_SIZE(arg)); + return 1; + default: + return 0; + } +} + +static int +hiddev_decode_number(unsigned int arg) +{ + if (_IOC_DIR(arg) == _IOC_READ) { + switch (_IOC_NR(arg)) { + case 0x04: + tprintf("HIDIOCGRAWNAME(%u)", _IOC_SIZE(arg)); + return 1; + case 0x05: + tprintf("HIDIOCGRAWPHYS(%u)", _IOC_SIZE(arg)); + return 1; + case 0x06: + tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(arg)); + return 1; + case 0x12: + tprintf("HIDIOCGPHYS(%u)", _IOC_SIZE(arg)); + return 1; + default: + return 0; + } + } else if (_IOC_DIR(arg) == (_IOC_READ | _IOC_WRITE)) { + switch (_IOC_NR(arg)) { + case 0x06: + tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(arg)); + return 1; + case 0x07: + tprintf("HIDIOCGFEATURE(%u)", _IOC_SIZE(arg)); + return 1; + default: + return 0; + } + } + + return 0; +} + +int +ioctl_decode_command_number(unsigned int arg) +{ + switch (_IOC_TYPE(arg)) { + case 'E': + return evdev_decode_number(arg); + case 'H': + return hiddev_decode_number(arg); + case 'M': + if (_IOC_DIR(arg) == _IOC_WRITE) { + tprintf("MIXER_WRITE(%u)", _IOC_NR(arg)); + return 1; + } else if (_IOC_DIR(arg) == _IOC_READ) { + tprintf("MIXER_READ(%u)", _IOC_NR(arg)); + return 1; + } + return 0; + case 'U': + if (_IOC_DIR(arg) == _IOC_READ && _IOC_NR(arg) == 0x2c) { + tprintf("UI_GET_SYSNAME(%u)", _IOC_SIZE(arg)); + return 1; + } + return 0; + case 'j': + if (_IOC_DIR(arg) == _IOC_READ && _IOC_NR(arg) == 0x13) { + tprintf("JSIOCGNAME(%u)", _IOC_SIZE(arg)); + return 1; + } + return 0; + case 'k': + if (_IOC_DIR(arg) == _IOC_WRITE && _IOC_NR(arg) == 0) { + tprintf("SPI_IOC_MESSAGE(%u)", _IOC_SIZE(arg)); + return 1; + } + return 0; + default: + return 0; + } +} + int ioctl_decode(struct tcb *tcp, unsigned int code, long arg) { diff --git a/xlat/evdev_abs.in b/xlat/evdev_abs.in new file mode 100644 index 00000000..ec8c2f43 --- /dev/null +++ b/xlat/evdev_abs.in @@ -0,0 +1,41 @@ +ABS_X +ABS_Y +ABS_Z +ABS_RX +ABS_RY +ABS_RZ +ABS_THROTTLE +ABS_RUDDER +ABS_WHEEL +ABS_GAS +ABS_BRAKE +ABS_HAT0X +ABS_HAT0Y +ABS_HAT1X +ABS_HAT1Y +ABS_HAT2X +ABS_HAT2Y +ABS_HAT3X +ABS_HAT3Y +ABS_PRESSURE +ABS_DISTANCE +ABS_TILT_X +ABS_TILT_Y +ABS_TOOL_WIDTH +ABS_VOLUME +ABS_MISC +ABS_MT_SLOT +ABS_MT_TOUCH_MAJOR +ABS_MT_TOUCH_MINOR +ABS_MT_WIDTH_MAJOR +ABS_MT_WIDTH_MINOR +ABS_MT_ORIENTATION +ABS_MT_POSITION_X +ABS_MT_POSITION_Y +ABS_MT_TOOL_TYPE +ABS_MT_BLOB_ID +ABS_MT_TRACKING_ID +ABS_MT_PRESSURE +ABS_MT_DISTANCE +ABS_MT_TOOL_X +ABS_MT_TOOL_Y diff --git a/xlat/evdev_ev.in b/xlat/evdev_ev.in new file mode 100644 index 00000000..0974b591 --- /dev/null +++ b/xlat/evdev_ev.in @@ -0,0 +1,12 @@ +EV_SYN +EV_KEY +EV_REL +EV_ABS +EV_MSC +EV_SW +EV_LED +EV_SND +EV_REP +EV_FF +EV_PWR +EV_FF_STATUS -- 2.40.0