1 /* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 5 * Copyright (c) 1996-2001 Wichert Akkerman <wichert (at) cistron.nl> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "defs.h" 32 #include <linux/ioctl.h> 33 #include "xlat/ioctl_dirs.h" 34 35 #ifdef HAVE_LINUX_INPUT_H 36 # include <linux/input.h> 37 #endif 38 39 #include "xlat/evdev_abs.h" 40 #include "xlat/evdev_ev.h" 41 42 static int 43 compare(const void *a, const void *b) 44 { 45 const unsigned int code1 = (const unsigned long) a; 46 const unsigned int code2 = ((struct_ioctlent *) b)->code; 47 return (code1 > code2) ? 1 : (code1 < code2) ? -1 : 0; 48 } 49 50 const struct_ioctlent * 51 ioctl_lookup(const unsigned int code) 52 { 53 struct_ioctlent *iop; 54 55 iop = bsearch((const void *) (const unsigned long) code, ioctlent, 56 nioctlents, sizeof(ioctlent[0]), compare); 57 while (iop > ioctlent) { 58 iop--; 59 if (iop->code != code) { 60 iop++; 61 break; 62 } 63 } 64 return iop; 65 } 66 67 const struct_ioctlent * 68 ioctl_next_match(const struct_ioctlent *iop) 69 { 70 const unsigned int code = iop->code; 71 iop++; 72 if (iop < ioctlent + nioctlents && iop->code == code) 73 return iop; 74 return NULL; 75 } 76 77 void 78 ioctl_print_code(const unsigned int code) 79 { 80 tprints("_IOC("); 81 printflags(ioctl_dirs, _IOC_DIR(code), "_IOC_???"); 82 tprintf(", 0x%02x, 0x%02x, 0x%02x)", 83 _IOC_TYPE(code), _IOC_NR(code), _IOC_SIZE(code)); 84 } 85 86 static int 87 evdev_decode_number(unsigned int arg) 88 { 89 unsigned int nr = _IOC_NR(arg); 90 91 if (_IOC_DIR(arg) == _IOC_WRITE) { 92 if (nr >= 0xc0 && nr <= 0xc0 + 0x3f) { 93 tprints("EVIOCSABS("); 94 printxval(evdev_abs, nr - 0xc0, "EV_???"); 95 tprints(")"); 96 return 1; 97 } 98 } 99 100 if (_IOC_DIR(arg) != _IOC_READ) 101 return 0; 102 103 if (nr >= 0x20 && nr <= 0x20 + 0x1f) { 104 tprints("EVIOCGBIT("); 105 printxval(evdev_ev, nr - 0x20, "EV_???"); 106 tprintf(", %u)", _IOC_SIZE(arg)); 107 return 1; 108 } else if (nr >= 0x40 && nr <= 0x40 + 0x3f) { 109 tprints("EVIOCGABS("); 110 printxval(evdev_abs, nr - 0x40, "ABS_???"); 111 tprints(")"); 112 return 1; 113 } 114 115 switch (_IOC_NR(nr)) { 116 case 0x06: 117 tprintf("EVIOCGNAME(%u)", _IOC_SIZE(arg)); 118 return 1; 119 case 0x07: 120 tprintf("EVIOCGPHYS(%u)", _IOC_SIZE(arg)); 121 return 1; 122 case 0x08: 123 tprintf("EVIOCGUNIQ(%u)", _IOC_SIZE(arg)); 124 return 1; 125 case 0x09: 126 tprintf("EVIOCGPROP(%u)", _IOC_SIZE(arg)); 127 return 1; 128 case 0x0a: 129 tprintf("EVIOCGMTSLOTS(%u)", _IOC_SIZE(arg)); 130 return 1; 131 case 0x18: 132 tprintf("EVIOCGKEY(%u)", _IOC_SIZE(arg)); 133 return 1; 134 case 0x19: 135 tprintf("EVIOCGLED(%u)", _IOC_SIZE(arg)); 136 return 1; 137 case 0x1a: 138 tprintf("EVIOCGSND(%u)", _IOC_SIZE(arg)); 139 return 1; 140 case 0x1b: 141 tprintf("EVIOCGSW(%u)", _IOC_SIZE(arg)); 142 return 1; 143 default: 144 return 0; 145 } 146 } 147 148 static int 149 hiddev_decode_number(unsigned int arg) 150 { 151 if (_IOC_DIR(arg) == _IOC_READ) { 152 switch (_IOC_NR(arg)) { 153 case 0x04: 154 tprintf("HIDIOCGRAWNAME(%u)", _IOC_SIZE(arg)); 155 return 1; 156 case 0x05: 157 tprintf("HIDIOCGRAWPHYS(%u)", _IOC_SIZE(arg)); 158 return 1; 159 case 0x06: 160 tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(arg)); 161 return 1; 162 case 0x12: 163 tprintf("HIDIOCGPHYS(%u)", _IOC_SIZE(arg)); 164 return 1; 165 default: 166 return 0; 167 } 168 } else if (_IOC_DIR(arg) == (_IOC_READ | _IOC_WRITE)) { 169 switch (_IOC_NR(arg)) { 170 case 0x06: 171 tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(arg)); 172 return 1; 173 case 0x07: 174 tprintf("HIDIOCGFEATURE(%u)", _IOC_SIZE(arg)); 175 return 1; 176 default: 177 return 0; 178 } 179 } 180 181 return 0; 182 } 183 184 int 185 ioctl_decode_command_number(unsigned int arg) 186 { 187 switch (_IOC_TYPE(arg)) { 188 case 'E': 189 return evdev_decode_number(arg); 190 case 'H': 191 return hiddev_decode_number(arg); 192 case 'M': 193 if (_IOC_DIR(arg) == _IOC_WRITE) { 194 tprintf("MIXER_WRITE(%u)", _IOC_NR(arg)); 195 return 1; 196 } else if (_IOC_DIR(arg) == _IOC_READ) { 197 tprintf("MIXER_READ(%u)", _IOC_NR(arg)); 198 return 1; 199 } 200 return 0; 201 case 'U': 202 if (_IOC_DIR(arg) == _IOC_READ && _IOC_NR(arg) == 0x2c) { 203 tprintf("UI_GET_SYSNAME(%u)", _IOC_SIZE(arg)); 204 return 1; 205 } 206 return 0; 207 case 'j': 208 if (_IOC_DIR(arg) == _IOC_READ && _IOC_NR(arg) == 0x13) { 209 tprintf("JSIOCGNAME(%u)", _IOC_SIZE(arg)); 210 return 1; 211 } 212 return 0; 213 case 'k': 214 if (_IOC_DIR(arg) == _IOC_WRITE && _IOC_NR(arg) == 0) { 215 tprintf("SPI_IOC_MESSAGE(%u)", _IOC_SIZE(arg)); 216 return 1; 217 } 218 return 0; 219 default: 220 return 0; 221 } 222 } 223 224 int 225 ioctl_decode(struct tcb *tcp, unsigned int code, long arg) 226 { 227 switch (_IOC_TYPE(code)) { 228 #if defined(ALPHA) || defined(POWERPC) 229 case 'f': case 't': case 'T': 230 #else /* !ALPHA */ 231 case 0x54: 232 #endif /* !ALPHA */ 233 return term_ioctl(tcp, code, arg); 234 case 0x89: 235 return sock_ioctl(tcp, code, arg); 236 case 'p': 237 return rtc_ioctl(tcp, code, arg); 238 case 0x03: 239 case 0x12: 240 case 'X': 241 return block_ioctl(tcp, code, arg); 242 #ifdef HAVE_SCSI_SG_H 243 case 0x22: 244 return scsi_ioctl(tcp, code, arg); 245 #endif 246 case 'L': 247 return loop_ioctl(tcp, code, arg); 248 case 'M': 249 return mtd_ioctl(tcp, code, arg); 250 case 'o': 251 case 'O': 252 return ubi_ioctl(tcp, code, arg); 253 case 'V': 254 return v4l2_ioctl(tcp, code, arg); 255 case '=': 256 return ptp_ioctl(tcp, code, arg); 257 #ifdef HAVE_LINUX_INPUT_H 258 case 'E': 259 return evdev_ioctl(tcp, code, arg); 260 #endif 261 default: 262 break; 263 } 264 return 0; 265 } 266 267 /* 268 * Registry of ioctl characters, culled from 269 * @(#)ioccom.h 1.7 89/06/16 SMI; from UCB ioctl.h 7.1 6/4/86 270 * 271 * char file where defined notes 272 * ---- ------------------ ----- 273 * F sun/fbio.h 274 * G sun/gpio.h 275 * H vaxif/if_hy.h 276 * M sundev/mcpcmd.h *overlap* 277 * M sys/modem.h *overlap* 278 * S sys/stropts.h 279 * T sys/termio.h -no overlap- 280 * T sys/termios.h -no overlap- 281 * V sundev/mdreg.h 282 * a vaxuba/adreg.h 283 * d sun/dkio.h -no overlap with sys/des.h- 284 * d sys/des.h (possible overlap) 285 * d vax/dkio.h (possible overlap) 286 * d vaxuba/rxreg.h (possible overlap) 287 * f sys/filio.h 288 * g sunwindow/win_ioctl.h -no overlap- 289 * g sunwindowdev/winioctl.c !no manifest constant! -no overlap- 290 * h sundev/hrc_common.h 291 * i sys/sockio.h *overlap* 292 * i vaxuba/ikreg.h *overlap* 293 * k sundev/kbio.h 294 * m sundev/msio.h (possible overlap) 295 * m sundev/msreg.h (possible overlap) 296 * m sys/mtio.h (possible overlap) 297 * n sun/ndio.h 298 * p net/nit_buf.h (possible overlap) 299 * p net/nit_if.h (possible overlap) 300 * p net/nit_pf.h (possible overlap) 301 * p sundev/fpareg.h (possible overlap) 302 * p sys/sockio.h (possible overlap) 303 * p vaxuba/psreg.h (possible overlap) 304 * q sun/sqz.h 305 * r sys/sockio.h 306 * s sys/sockio.h 307 * t sys/ttold.h (possible overlap) 308 * t sys/ttycom.h (possible overlap) 309 * v sundev/vuid_event.h *overlap* 310 * v sys/vcmd.h *overlap* 311 * V linux/videodev2.h 312 * 313 * End of Registry 314 */ 315