1 /*- 2 * Copyright (c) 1994-1995 Søren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 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 "opt_compat.h" 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/sysproto.h> 37 #include <sys/capsicum.h> 38 #include <sys/cdio.h> 39 #include <sys/dvdio.h> 40 #include <sys/conf.h> 41 #include <sys/disk.h> 42 #include <sys/consio.h> 43 #include <sys/ctype.h> 44 #include <sys/fcntl.h> 45 #include <sys/file.h> 46 #include <sys/filedesc.h> 47 #include <sys/filio.h> 48 #include <sys/jail.h> 49 #include <sys/kbio.h> 50 #include <sys/kernel.h> 51 #include <sys/linker_set.h> 52 #include <sys/lock.h> 53 #include <sys/malloc.h> 54 #include <sys/proc.h> 55 #include <sys/sbuf.h> 56 #include <sys/socket.h> 57 #include <sys/sockio.h> 58 #include <sys/soundcard.h> 59 #include <sys/stdint.h> 60 #include <sys/sx.h> 61 #include <sys/sysctl.h> 62 #include <sys/tty.h> 63 #include <sys/uio.h> 64 #include <sys/types.h> 65 #include <sys/mman.h> 66 #include <sys/resourcevar.h> 67 68 #include <net/if.h> 69 #include <net/if_var.h> 70 #include <net/if_dl.h> 71 #include <net/if_types.h> 72 73 #include <dev/evdev/input.h> 74 #include <dev/usb/usb_ioctl.h> 75 76 #ifdef COMPAT_LINUX32 77 #include <machine/../linux32/linux.h> 78 #include <machine/../linux32/linux32_proto.h> 79 #else 80 #include <machine/../linux/linux.h> 81 #include <machine/../linux/linux_proto.h> 82 #endif 83 84 #include <compat/linux/linux_ioctl.h> 85 #include <compat/linux/linux_mib.h> 86 #include <compat/linux/linux_socket.h> 87 #include <compat/linux/linux_timer.h> 88 #include <compat/linux/linux_util.h> 89 90 #include <contrib/v4l/videodev.h> 91 #include <compat/linux/linux_videodev_compat.h> 92 93 #include <contrib/v4l/videodev2.h> 94 #include <compat/linux/linux_videodev2_compat.h> 95 96 #include <cam/scsi/scsi_sg.h> 97 98 CTASSERT(LINUX_IFNAMSIZ == IFNAMSIZ); 99 100 static linux_ioctl_function_t linux_ioctl_cdrom; 101 static linux_ioctl_function_t linux_ioctl_vfat; 102 static linux_ioctl_function_t linux_ioctl_console; 103 static linux_ioctl_function_t linux_ioctl_hdio; 104 static linux_ioctl_function_t linux_ioctl_disk; 105 static linux_ioctl_function_t linux_ioctl_socket; 106 static linux_ioctl_function_t linux_ioctl_sound; 107 static linux_ioctl_function_t linux_ioctl_termio; 108 static linux_ioctl_function_t linux_ioctl_private; 109 static linux_ioctl_function_t linux_ioctl_drm; 110 static linux_ioctl_function_t linux_ioctl_sg; 111 static linux_ioctl_function_t linux_ioctl_v4l; 112 static linux_ioctl_function_t linux_ioctl_v4l2; 113 static linux_ioctl_function_t linux_ioctl_special; 114 static linux_ioctl_function_t linux_ioctl_fbsd_usb; 115 static linux_ioctl_function_t linux_ioctl_evdev; 116 117 static struct linux_ioctl_handler cdrom_handler = 118 { linux_ioctl_cdrom, LINUX_IOCTL_CDROM_MIN, LINUX_IOCTL_CDROM_MAX }; 119 static struct linux_ioctl_handler vfat_handler = 120 { linux_ioctl_vfat, LINUX_IOCTL_VFAT_MIN, LINUX_IOCTL_VFAT_MAX }; 121 static struct linux_ioctl_handler console_handler = 122 { linux_ioctl_console, LINUX_IOCTL_CONSOLE_MIN, LINUX_IOCTL_CONSOLE_MAX }; 123 static struct linux_ioctl_handler hdio_handler = 124 { linux_ioctl_hdio, LINUX_IOCTL_HDIO_MIN, LINUX_IOCTL_HDIO_MAX }; 125 static struct linux_ioctl_handler disk_handler = 126 { linux_ioctl_disk, LINUX_IOCTL_DISK_MIN, LINUX_IOCTL_DISK_MAX }; 127 static struct linux_ioctl_handler socket_handler = 128 { linux_ioctl_socket, LINUX_IOCTL_SOCKET_MIN, LINUX_IOCTL_SOCKET_MAX }; 129 static struct linux_ioctl_handler sound_handler = 130 { linux_ioctl_sound, LINUX_IOCTL_SOUND_MIN, LINUX_IOCTL_SOUND_MAX }; 131 static struct linux_ioctl_handler termio_handler = 132 { linux_ioctl_termio, LINUX_IOCTL_TERMIO_MIN, LINUX_IOCTL_TERMIO_MAX }; 133 static struct linux_ioctl_handler private_handler = 134 { linux_ioctl_private, LINUX_IOCTL_PRIVATE_MIN, LINUX_IOCTL_PRIVATE_MAX }; 135 static struct linux_ioctl_handler drm_handler = 136 { linux_ioctl_drm, LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX }; 137 static struct linux_ioctl_handler sg_handler = 138 { linux_ioctl_sg, LINUX_IOCTL_SG_MIN, LINUX_IOCTL_SG_MAX }; 139 static struct linux_ioctl_handler video_handler = 140 { linux_ioctl_v4l, LINUX_IOCTL_VIDEO_MIN, LINUX_IOCTL_VIDEO_MAX }; 141 static struct linux_ioctl_handler video2_handler = 142 { linux_ioctl_v4l2, LINUX_IOCTL_VIDEO2_MIN, LINUX_IOCTL_VIDEO2_MAX }; 143 static struct linux_ioctl_handler fbsd_usb = 144 { linux_ioctl_fbsd_usb, FBSD_LUSB_MIN, FBSD_LUSB_MAX }; 145 static struct linux_ioctl_handler evdev_handler = 146 { linux_ioctl_evdev, LINUX_IOCTL_EVDEV_MIN, LINUX_IOCTL_EVDEV_MAX }; 147 148 DATA_SET(linux_ioctl_handler_set, cdrom_handler); 149 DATA_SET(linux_ioctl_handler_set, vfat_handler); 150 DATA_SET(linux_ioctl_handler_set, console_handler); 151 DATA_SET(linux_ioctl_handler_set, hdio_handler); 152 DATA_SET(linux_ioctl_handler_set, disk_handler); 153 DATA_SET(linux_ioctl_handler_set, socket_handler); 154 DATA_SET(linux_ioctl_handler_set, sound_handler); 155 DATA_SET(linux_ioctl_handler_set, termio_handler); 156 DATA_SET(linux_ioctl_handler_set, private_handler); 157 DATA_SET(linux_ioctl_handler_set, drm_handler); 158 DATA_SET(linux_ioctl_handler_set, sg_handler); 159 DATA_SET(linux_ioctl_handler_set, video_handler); 160 DATA_SET(linux_ioctl_handler_set, video2_handler); 161 DATA_SET(linux_ioctl_handler_set, fbsd_usb); 162 DATA_SET(linux_ioctl_handler_set, evdev_handler); 163 164 struct handler_element 165 { 166 TAILQ_ENTRY(handler_element) list; 167 int (*func)(struct thread *, struct linux_ioctl_args *); 168 int low, high, span; 169 }; 170 171 static TAILQ_HEAD(, handler_element) handlers = 172 TAILQ_HEAD_INITIALIZER(handlers); 173 static struct sx linux_ioctl_sx; 174 SX_SYSINIT(linux_ioctl, &linux_ioctl_sx, "linux ioctl handlers"); 175 176 /* 177 * hdio related ioctls for VMWare support 178 */ 179 180 struct linux_hd_geometry { 181 u_int8_t heads; 182 u_int8_t sectors; 183 u_int16_t cylinders; 184 u_int32_t start; 185 }; 186 187 struct linux_hd_big_geometry { 188 u_int8_t heads; 189 u_int8_t sectors; 190 u_int32_t cylinders; 191 u_int32_t start; 192 }; 193 194 static int 195 linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args) 196 { 197 cap_rights_t rights; 198 struct file *fp; 199 int error; 200 u_int sectorsize, fwcylinders, fwheads, fwsectors; 201 off_t mediasize, bytespercyl; 202 203 error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); 204 if (error != 0) 205 return (error); 206 switch (args->cmd & 0xffff) { 207 case LINUX_HDIO_GET_GEO: 208 case LINUX_HDIO_GET_GEO_BIG: 209 error = fo_ioctl(fp, DIOCGMEDIASIZE, 210 (caddr_t)&mediasize, td->td_ucred, td); 211 if (!error) 212 error = fo_ioctl(fp, DIOCGSECTORSIZE, 213 (caddr_t)§orsize, td->td_ucred, td); 214 if (!error) 215 error = fo_ioctl(fp, DIOCGFWHEADS, 216 (caddr_t)&fwheads, td->td_ucred, td); 217 if (!error) 218 error = fo_ioctl(fp, DIOCGFWSECTORS, 219 (caddr_t)&fwsectors, td->td_ucred, td); 220 /* 221 * XXX: DIOCGFIRSTOFFSET is not yet implemented, so 222 * so pretend that GEOM always says 0. This is NOT VALID 223 * for slices or partitions, only the per-disk raw devices. 224 */ 225 226 fdrop(fp, td); 227 if (error) 228 return (error); 229 /* 230 * 1. Calculate the number of bytes in a cylinder, 231 * given the firmware's notion of heads and sectors 232 * per cylinder. 233 * 2. Calculate the number of cylinders, given the total 234 * size of the media. 235 * All internal calculations should have 64-bit precision. 236 */ 237 bytespercyl = (off_t) sectorsize * fwheads * fwsectors; 238 fwcylinders = mediasize / bytespercyl; 239 #if defined(DEBUG) 240 linux_msg(td, "HDIO_GET_GEO: mediasize %jd, c/h/s %d/%d/%d, " 241 "bpc %jd", 242 (intmax_t)mediasize, fwcylinders, fwheads, fwsectors, 243 (intmax_t)bytespercyl); 244 #endif 245 if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO) { 246 struct linux_hd_geometry hdg; 247 248 hdg.cylinders = fwcylinders; 249 hdg.heads = fwheads; 250 hdg.sectors = fwsectors; 251 hdg.start = 0; 252 error = copyout(&hdg, (void *)args->arg, sizeof(hdg)); 253 } else if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO_BIG) { 254 struct linux_hd_big_geometry hdbg; 255 256 hdbg.cylinders = fwcylinders; 257 hdbg.heads = fwheads; 258 hdbg.sectors = fwsectors; 259 hdbg.start = 0; 260 error = copyout(&hdbg, (void *)args->arg, sizeof(hdbg)); 261 } 262 return (error); 263 break; 264 default: 265 /* XXX */ 266 linux_msg(td, 267 "ioctl fd=%d, cmd=0x%x ('%c',%d) is not implemented", 268 args->fd, (int)(args->cmd & 0xffff), 269 (int)(args->cmd & 0xff00) >> 8, 270 (int)(args->cmd & 0xff)); 271 break; 272 } 273 fdrop(fp, td); 274 return (ENOIOCTL); 275 } 276 277 static int 278 linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args) 279 { 280 cap_rights_t rights; 281 struct file *fp; 282 int error; 283 u_int sectorsize; 284 off_t mediasize; 285 286 error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); 287 if (error != 0) 288 return (error); 289 switch (args->cmd & 0xffff) { 290 case LINUX_BLKGETSIZE: 291 error = fo_ioctl(fp, DIOCGSECTORSIZE, 292 (caddr_t)§orsize, td->td_ucred, td); 293 if (!error) 294 error = fo_ioctl(fp, DIOCGMEDIASIZE, 295 (caddr_t)&mediasize, td->td_ucred, td); 296 fdrop(fp, td); 297 if (error) 298 return (error); 299 sectorsize = mediasize / sectorsize; 300 /* 301 * XXX: How do we know we return the right size of integer ? 302 */ 303 return (copyout(§orsize, (void *)args->arg, 304 sizeof(sectorsize))); 305 break; 306 case LINUX_BLKSSZGET: 307 error = fo_ioctl(fp, DIOCGSECTORSIZE, 308 (caddr_t)§orsize, td->td_ucred, td); 309 fdrop(fp, td); 310 if (error) 311 return (error); 312 return (copyout(§orsize, (void *)args->arg, 313 sizeof(sectorsize))); 314 break; 315 } 316 fdrop(fp, td); 317 return (ENOIOCTL); 318 } 319 320 /* 321 * termio related ioctls 322 */ 323 324 struct linux_termio { 325 unsigned short c_iflag; 326 unsigned short c_oflag; 327 unsigned short c_cflag; 328 unsigned short c_lflag; 329 unsigned char c_line; 330 unsigned char c_cc[LINUX_NCC]; 331 }; 332 333 struct linux_termios { 334 unsigned int c_iflag; 335 unsigned int c_oflag; 336 unsigned int c_cflag; 337 unsigned int c_lflag; 338 unsigned char c_line; 339 unsigned char c_cc[LINUX_NCCS]; 340 }; 341 342 struct linux_winsize { 343 unsigned short ws_row, ws_col; 344 unsigned short ws_xpixel, ws_ypixel; 345 }; 346 347 struct speedtab { 348 int sp_speed; /* Speed. */ 349 int sp_code; /* Code. */ 350 }; 351 352 static struct speedtab sptab[] = { 353 { B0, LINUX_B0 }, { B50, LINUX_B50 }, 354 { B75, LINUX_B75 }, { B110, LINUX_B110 }, 355 { B134, LINUX_B134 }, { B150, LINUX_B150 }, 356 { B200, LINUX_B200 }, { B300, LINUX_B300 }, 357 { B600, LINUX_B600 }, { B1200, LINUX_B1200 }, 358 { B1800, LINUX_B1800 }, { B2400, LINUX_B2400 }, 359 { B4800, LINUX_B4800 }, { B9600, LINUX_B9600 }, 360 { B19200, LINUX_B19200 }, { B38400, LINUX_B38400 }, 361 { B57600, LINUX_B57600 }, { B115200, LINUX_B115200 }, 362 {-1, -1 } 363 }; 364 365 struct linux_serial_struct { 366 int type; 367 int line; 368 int port; 369 int irq; 370 int flags; 371 int xmit_fifo_size; 372 int custom_divisor; 373 int baud_base; 374 unsigned short close_delay; 375 char reserved_char[2]; 376 int hub6; 377 unsigned short closing_wait; 378 unsigned short closing_wait2; 379 int reserved[4]; 380 }; 381 382 static int 383 linux_to_bsd_speed(int code, struct speedtab *table) 384 { 385 for ( ; table->sp_code != -1; table++) 386 if (table->sp_code == code) 387 return (table->sp_speed); 388 return -1; 389 } 390 391 static int 392 bsd_to_linux_speed(int speed, struct speedtab *table) 393 { 394 for ( ; table->sp_speed != -1; table++) 395 if (table->sp_speed == speed) 396 return (table->sp_code); 397 return -1; 398 } 399 400 static void 401 bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios) 402 { 403 int i; 404 405 #ifdef DEBUG 406 if (ldebug(ioctl)) { 407 printf("LINUX: BSD termios structure (input):\n"); 408 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", 409 bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag, 410 bios->c_ispeed, bios->c_ospeed); 411 printf("c_cc "); 412 for (i=0; i<NCCS; i++) 413 printf("%02x ", bios->c_cc[i]); 414 printf("\n"); 415 } 416 #endif 417 418 lios->c_iflag = 0; 419 if (bios->c_iflag & IGNBRK) 420 lios->c_iflag |= LINUX_IGNBRK; 421 if (bios->c_iflag & BRKINT) 422 lios->c_iflag |= LINUX_BRKINT; 423 if (bios->c_iflag & IGNPAR) 424 lios->c_iflag |= LINUX_IGNPAR; 425 if (bios->c_iflag & PARMRK) 426 lios->c_iflag |= LINUX_PARMRK; 427 if (bios->c_iflag & INPCK) 428 lios->c_iflag |= LINUX_INPCK; 429 if (bios->c_iflag & ISTRIP) 430 lios->c_iflag |= LINUX_ISTRIP; 431 if (bios->c_iflag & INLCR) 432 lios->c_iflag |= LINUX_INLCR; 433 if (bios->c_iflag & IGNCR) 434 lios->c_iflag |= LINUX_IGNCR; 435 if (bios->c_iflag & ICRNL) 436 lios->c_iflag |= LINUX_ICRNL; 437 if (bios->c_iflag & IXON) 438 lios->c_iflag |= LINUX_IXON; 439 if (bios->c_iflag & IXANY) 440 lios->c_iflag |= LINUX_IXANY; 441 if (bios->c_iflag & IXOFF) 442 lios->c_iflag |= LINUX_IXOFF; 443 if (bios->c_iflag & IMAXBEL) 444 lios->c_iflag |= LINUX_IMAXBEL; 445 446 lios->c_oflag = 0; 447 if (bios->c_oflag & OPOST) 448 lios->c_oflag |= LINUX_OPOST; 449 if (bios->c_oflag & ONLCR) 450 lios->c_oflag |= LINUX_ONLCR; 451 if (bios->c_oflag & TAB3) 452 lios->c_oflag |= LINUX_XTABS; 453 454 lios->c_cflag = bsd_to_linux_speed(bios->c_ispeed, sptab); 455 lios->c_cflag |= (bios->c_cflag & CSIZE) >> 4; 456 if (bios->c_cflag & CSTOPB) 457 lios->c_cflag |= LINUX_CSTOPB; 458 if (bios->c_cflag & CREAD) 459 lios->c_cflag |= LINUX_CREAD; 460 if (bios->c_cflag & PARENB) 461 lios->c_cflag |= LINUX_PARENB; 462 if (bios->c_cflag & PARODD) 463 lios->c_cflag |= LINUX_PARODD; 464 if (bios->c_cflag & HUPCL) 465 lios->c_cflag |= LINUX_HUPCL; 466 if (bios->c_cflag & CLOCAL) 467 lios->c_cflag |= LINUX_CLOCAL; 468 if (bios->c_cflag & CRTSCTS) 469 lios->c_cflag |= LINUX_CRTSCTS; 470 471 lios->c_lflag = 0; 472 if (bios->c_lflag & ISIG) 473 lios->c_lflag |= LINUX_ISIG; 474 if (bios->c_lflag & ICANON) 475 lios->c_lflag |= LINUX_ICANON; 476 if (bios->c_lflag & ECHO) 477 lios->c_lflag |= LINUX_ECHO; 478 if (bios->c_lflag & ECHOE) 479 lios->c_lflag |= LINUX_ECHOE; 480 if (bios->c_lflag & ECHOK) 481 lios->c_lflag |= LINUX_ECHOK; 482 if (bios->c_lflag & ECHONL) 483 lios->c_lflag |= LINUX_ECHONL; 484 if (bios->c_lflag & NOFLSH) 485 lios->c_lflag |= LINUX_NOFLSH; 486 if (bios->c_lflag & TOSTOP) 487 lios->c_lflag |= LINUX_TOSTOP; 488 if (bios->c_lflag & ECHOCTL) 489 lios->c_lflag |= LINUX_ECHOCTL; 490 if (bios->c_lflag & ECHOPRT) 491 lios->c_lflag |= LINUX_ECHOPRT; 492 if (bios->c_lflag & ECHOKE) 493 lios->c_lflag |= LINUX_ECHOKE; 494 if (bios->c_lflag & FLUSHO) 495 lios->c_lflag |= LINUX_FLUSHO; 496 if (bios->c_lflag & PENDIN) 497 lios->c_lflag |= LINUX_PENDIN; 498 if (bios->c_lflag & IEXTEN) 499 lios->c_lflag |= LINUX_IEXTEN; 500 501 for (i=0; i<LINUX_NCCS; i++) 502 lios->c_cc[i] = LINUX_POSIX_VDISABLE; 503 lios->c_cc[LINUX_VINTR] = bios->c_cc[VINTR]; 504 lios->c_cc[LINUX_VQUIT] = bios->c_cc[VQUIT]; 505 lios->c_cc[LINUX_VERASE] = bios->c_cc[VERASE]; 506 lios->c_cc[LINUX_VKILL] = bios->c_cc[VKILL]; 507 lios->c_cc[LINUX_VEOF] = bios->c_cc[VEOF]; 508 lios->c_cc[LINUX_VEOL] = bios->c_cc[VEOL]; 509 lios->c_cc[LINUX_VMIN] = bios->c_cc[VMIN]; 510 lios->c_cc[LINUX_VTIME] = bios->c_cc[VTIME]; 511 lios->c_cc[LINUX_VEOL2] = bios->c_cc[VEOL2]; 512 lios->c_cc[LINUX_VSUSP] = bios->c_cc[VSUSP]; 513 lios->c_cc[LINUX_VSTART] = bios->c_cc[VSTART]; 514 lios->c_cc[LINUX_VSTOP] = bios->c_cc[VSTOP]; 515 lios->c_cc[LINUX_VREPRINT] = bios->c_cc[VREPRINT]; 516 lios->c_cc[LINUX_VDISCARD] = bios->c_cc[VDISCARD]; 517 lios->c_cc[LINUX_VWERASE] = bios->c_cc[VWERASE]; 518 lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT]; 519 520 for (i=0; i<LINUX_NCCS; i++) { 521 if (i != LINUX_VMIN && i != LINUX_VTIME && 522 lios->c_cc[i] == _POSIX_VDISABLE) 523 lios->c_cc[i] = LINUX_POSIX_VDISABLE; 524 } 525 lios->c_line = 0; 526 527 #ifdef DEBUG 528 if (ldebug(ioctl)) { 529 printf("LINUX: LINUX termios structure (output):\n"); 530 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", 531 lios->c_iflag, lios->c_oflag, lios->c_cflag, 532 lios->c_lflag, (int)lios->c_line); 533 printf("c_cc "); 534 for (i=0; i<LINUX_NCCS; i++) 535 printf("%02x ", lios->c_cc[i]); 536 printf("\n"); 537 } 538 #endif 539 } 540 541 static void 542 linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios) 543 { 544 int i; 545 546 #ifdef DEBUG 547 if (ldebug(ioctl)) { 548 printf("LINUX: LINUX termios structure (input):\n"); 549 printf("i=%08x o=%08x c=%08x l=%08x line=%d\n", 550 lios->c_iflag, lios->c_oflag, lios->c_cflag, 551 lios->c_lflag, (int)lios->c_line); 552 printf("c_cc "); 553 for (i=0; i<LINUX_NCCS; i++) 554 printf("%02x ", lios->c_cc[i]); 555 printf("\n"); 556 } 557 #endif 558 559 bios->c_iflag = 0; 560 if (lios->c_iflag & LINUX_IGNBRK) 561 bios->c_iflag |= IGNBRK; 562 if (lios->c_iflag & LINUX_BRKINT) 563 bios->c_iflag |= BRKINT; 564 if (lios->c_iflag & LINUX_IGNPAR) 565 bios->c_iflag |= IGNPAR; 566 if (lios->c_iflag & LINUX_PARMRK) 567 bios->c_iflag |= PARMRK; 568 if (lios->c_iflag & LINUX_INPCK) 569 bios->c_iflag |= INPCK; 570 if (lios->c_iflag & LINUX_ISTRIP) 571 bios->c_iflag |= ISTRIP; 572 if (lios->c_iflag & LINUX_INLCR) 573 bios->c_iflag |= INLCR; 574 if (lios->c_iflag & LINUX_IGNCR) 575 bios->c_iflag |= IGNCR; 576 if (lios->c_iflag & LINUX_ICRNL) 577 bios->c_iflag |= ICRNL; 578 if (lios->c_iflag & LINUX_IXON) 579 bios->c_iflag |= IXON; 580 if (lios->c_iflag & LINUX_IXANY) 581 bios->c_iflag |= IXANY; 582 if (lios->c_iflag & LINUX_IXOFF) 583 bios->c_iflag |= IXOFF; 584 if (lios->c_iflag & LINUX_IMAXBEL) 585 bios->c_iflag |= IMAXBEL; 586 587 bios->c_oflag = 0; 588 if (lios->c_oflag & LINUX_OPOST) 589 bios->c_oflag |= OPOST; 590 if (lios->c_oflag & LINUX_ONLCR) 591 bios->c_oflag |= ONLCR; 592 if (lios->c_oflag & LINUX_XTABS) 593 bios->c_oflag |= TAB3; 594 595 bios->c_cflag = (lios->c_cflag & LINUX_CSIZE) << 4; 596 if (lios->c_cflag & LINUX_CSTOPB) 597 bios->c_cflag |= CSTOPB; 598 if (lios->c_cflag & LINUX_CREAD) 599 bios->c_cflag |= CREAD; 600 if (lios->c_cflag & LINUX_PARENB) 601 bios->c_cflag |= PARENB; 602 if (lios->c_cflag & LINUX_PARODD) 603 bios->c_cflag |= PARODD; 604 if (lios->c_cflag & LINUX_HUPCL) 605 bios->c_cflag |= HUPCL; 606 if (lios->c_cflag & LINUX_CLOCAL) 607 bios->c_cflag |= CLOCAL; 608 if (lios->c_cflag & LINUX_CRTSCTS) 609 bios->c_cflag |= CRTSCTS; 610 611 bios->c_lflag = 0; 612 if (lios->c_lflag & LINUX_ISIG) 613 bios->c_lflag |= ISIG; 614 if (lios->c_lflag & LINUX_ICANON) 615 bios->c_lflag |= ICANON; 616 if (lios->c_lflag & LINUX_ECHO) 617 bios->c_lflag |= ECHO; 618 if (lios->c_lflag & LINUX_ECHOE) 619 bios->c_lflag |= ECHOE; 620 if (lios->c_lflag & LINUX_ECHOK) 621 bios->c_lflag |= ECHOK; 622 if (lios->c_lflag & LINUX_ECHONL) 623 bios->c_lflag |= ECHONL; 624 if (lios->c_lflag & LINUX_NOFLSH) 625 bios->c_lflag |= NOFLSH; 626 if (lios->c_lflag & LINUX_TOSTOP) 627 bios->c_lflag |= TOSTOP; 628 if (lios->c_lflag & LINUX_ECHOCTL) 629 bios->c_lflag |= ECHOCTL; 630 if (lios->c_lflag & LINUX_ECHOPRT) 631 bios->c_lflag |= ECHOPRT; 632 if (lios->c_lflag & LINUX_ECHOKE) 633 bios->c_lflag |= ECHOKE; 634 if (lios->c_lflag & LINUX_FLUSHO) 635 bios->c_lflag |= FLUSHO; 636 if (lios->c_lflag & LINUX_PENDIN) 637 bios->c_lflag |= PENDIN; 638 if (lios->c_lflag & LINUX_IEXTEN) 639 bios->c_lflag |= IEXTEN; 640 641 for (i=0; i<NCCS; i++) 642 bios->c_cc[i] = _POSIX_VDISABLE; 643 bios->c_cc[VINTR] = lios->c_cc[LINUX_VINTR]; 644 bios->c_cc[VQUIT] = lios->c_cc[LINUX_VQUIT]; 645 bios->c_cc[VERASE] = lios->c_cc[LINUX_VERASE]; 646 bios->c_cc[VKILL] = lios->c_cc[LINUX_VKILL]; 647 bios->c_cc[VEOF] = lios->c_cc[LINUX_VEOF]; 648 bios->c_cc[VEOL] = lios->c_cc[LINUX_VEOL]; 649 bios->c_cc[VMIN] = lios->c_cc[LINUX_VMIN]; 650 bios->c_cc[VTIME] = lios->c_cc[LINUX_VTIME]; 651 bios->c_cc[VEOL2] = lios->c_cc[LINUX_VEOL2]; 652 bios->c_cc[VSUSP] = lios->c_cc[LINUX_VSUSP]; 653 bios->c_cc[VSTART] = lios->c_cc[LINUX_VSTART]; 654 bios->c_cc[VSTOP] = lios->c_cc[LINUX_VSTOP]; 655 bios->c_cc[VREPRINT] = lios->c_cc[LINUX_VREPRINT]; 656 bios->c_cc[VDISCARD] = lios->c_cc[LINUX_VDISCARD]; 657 bios->c_cc[VWERASE] = lios->c_cc[LINUX_VWERASE]; 658 bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT]; 659 660 for (i=0; i<NCCS; i++) { 661 if (i != VMIN && i != VTIME && 662 bios->c_cc[i] == LINUX_POSIX_VDISABLE) 663 bios->c_cc[i] = _POSIX_VDISABLE; 664 } 665 666 bios->c_ispeed = bios->c_ospeed = 667 linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab); 668 669 #ifdef DEBUG 670 if (ldebug(ioctl)) { 671 printf("LINUX: BSD termios structure (output):\n"); 672 printf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n", 673 bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag, 674 bios->c_ispeed, bios->c_ospeed); 675 printf("c_cc "); 676 for (i=0; i<NCCS; i++) 677 printf("%02x ", bios->c_cc[i]); 678 printf("\n"); 679 } 680 #endif 681 } 682 683 static void 684 bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio) 685 { 686 struct linux_termios lios; 687 688 bsd_to_linux_termios(bios, &lios); 689 lio->c_iflag = lios.c_iflag; 690 lio->c_oflag = lios.c_oflag; 691 lio->c_cflag = lios.c_cflag; 692 lio->c_lflag = lios.c_lflag; 693 lio->c_line = lios.c_line; 694 memcpy(lio->c_cc, lios.c_cc, LINUX_NCC); 695 } 696 697 static void 698 linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios) 699 { 700 struct linux_termios lios; 701 int i; 702 703 lios.c_iflag = lio->c_iflag; 704 lios.c_oflag = lio->c_oflag; 705 lios.c_cflag = lio->c_cflag; 706 lios.c_lflag = lio->c_lflag; 707 for (i=LINUX_NCC; i<LINUX_NCCS; i++) 708 lios.c_cc[i] = LINUX_POSIX_VDISABLE; 709 memcpy(lios.c_cc, lio->c_cc, LINUX_NCC); 710 linux_to_bsd_termios(&lios, bios); 711 } 712 713 static int 714 linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args) 715 { 716 struct termios bios; 717 struct linux_termios lios; 718 struct linux_termio lio; 719 cap_rights_t rights; 720 struct file *fp; 721 int error; 722 723 error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); 724 if (error != 0) 725 return (error); 726 727 switch (args->cmd & 0xffff) { 728 729 case LINUX_TCGETS: 730 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred, 731 td); 732 if (error) 733 break; 734 bsd_to_linux_termios(&bios, &lios); 735 error = copyout(&lios, (void *)args->arg, sizeof(lios)); 736 break; 737 738 case LINUX_TCSETS: 739 error = copyin((void *)args->arg, &lios, sizeof(lios)); 740 if (error) 741 break; 742 linux_to_bsd_termios(&lios, &bios); 743 error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred, 744 td)); 745 break; 746 747 case LINUX_TCSETSW: 748 error = copyin((void *)args->arg, &lios, sizeof(lios)); 749 if (error) 750 break; 751 linux_to_bsd_termios(&lios, &bios); 752 error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred, 753 td)); 754 break; 755 756 case LINUX_TCSETSF: 757 error = copyin((void *)args->arg, &lios, sizeof(lios)); 758 if (error) 759 break; 760 linux_to_bsd_termios(&lios, &bios); 761 error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred, 762 td)); 763 break; 764 765 case LINUX_TCGETA: 766 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred, 767 td); 768 if (error) 769 break; 770 bsd_to_linux_termio(&bios, &lio); 771 error = (copyout(&lio, (void *)args->arg, sizeof(lio))); 772 break; 773 774 case LINUX_TCSETA: 775 error = copyin((void *)args->arg, &lio, sizeof(lio)); 776 if (error) 777 break; 778 linux_to_bsd_termio(&lio, &bios); 779 error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred, 780 td)); 781 break; 782 783 case LINUX_TCSETAW: 784 error = copyin((void *)args->arg, &lio, sizeof(lio)); 785 if (error) 786 break; 787 linux_to_bsd_termio(&lio, &bios); 788 error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred, 789 td)); 790 break; 791 792 case LINUX_TCSETAF: 793 error = copyin((void *)args->arg, &lio, sizeof(lio)); 794 if (error) 795 break; 796 linux_to_bsd_termio(&lio, &bios); 797 error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred, 798 td)); 799 break; 800 801 /* LINUX_TCSBRK */ 802 803 case LINUX_TCXONC: { 804 switch (args->arg) { 805 case LINUX_TCOOFF: 806 args->cmd = TIOCSTOP; 807 break; 808 case LINUX_TCOON: 809 args->cmd = TIOCSTART; 810 break; 811 case LINUX_TCIOFF: 812 case LINUX_TCION: { 813 int c; 814 struct write_args wr; 815 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, 816 td->td_ucred, td); 817 if (error) 818 break; 819 fdrop(fp, td); 820 c = (args->arg == LINUX_TCIOFF) ? VSTOP : VSTART; 821 c = bios.c_cc[c]; 822 if (c != _POSIX_VDISABLE) { 823 wr.fd = args->fd; 824 wr.buf = &c; 825 wr.nbyte = sizeof(c); 826 return (sys_write(td, &wr)); 827 } else 828 return (0); 829 } 830 default: 831 fdrop(fp, td); 832 return (EINVAL); 833 } 834 args->arg = 0; 835 error = (sys_ioctl(td, (struct ioctl_args *)args)); 836 break; 837 } 838 839 case LINUX_TCFLSH: { 840 int val; 841 switch (args->arg) { 842 case LINUX_TCIFLUSH: 843 val = FREAD; 844 break; 845 case LINUX_TCOFLUSH: 846 val = FWRITE; 847 break; 848 case LINUX_TCIOFLUSH: 849 val = FREAD | FWRITE; 850 break; 851 default: 852 fdrop(fp, td); 853 return (EINVAL); 854 } 855 error = (fo_ioctl(fp,TIOCFLUSH,(caddr_t)&val,td->td_ucred,td)); 856 break; 857 } 858 859 case LINUX_TIOCEXCL: 860 args->cmd = TIOCEXCL; 861 error = (sys_ioctl(td, (struct ioctl_args *)args)); 862 break; 863 864 case LINUX_TIOCNXCL: 865 args->cmd = TIOCNXCL; 866 error = (sys_ioctl(td, (struct ioctl_args *)args)); 867 break; 868 869 case LINUX_TIOCSCTTY: 870 args->cmd = TIOCSCTTY; 871 error = (sys_ioctl(td, (struct ioctl_args *)args)); 872 break; 873 874 case LINUX_TIOCGPGRP: 875 args->cmd = TIOCGPGRP; 876 error = (sys_ioctl(td, (struct ioctl_args *)args)); 877 break; 878 879 case LINUX_TIOCSPGRP: 880 args->cmd = TIOCSPGRP; 881 error = (sys_ioctl(td, (struct ioctl_args *)args)); 882 break; 883 884 /* LINUX_TIOCOUTQ */ 885 /* LINUX_TIOCSTI */ 886 887 case LINUX_TIOCGWINSZ: 888 args->cmd = TIOCGWINSZ; 889 error = (sys_ioctl(td, (struct ioctl_args *)args)); 890 break; 891 892 case LINUX_TIOCSWINSZ: 893 args->cmd = TIOCSWINSZ; 894 error = (sys_ioctl(td, (struct ioctl_args *)args)); 895 break; 896 897 case LINUX_TIOCMGET: 898 args->cmd = TIOCMGET; 899 error = (sys_ioctl(td, (struct ioctl_args *)args)); 900 break; 901 902 case LINUX_TIOCMBIS: 903 args->cmd = TIOCMBIS; 904 error = (sys_ioctl(td, (struct ioctl_args *)args)); 905 break; 906 907 case LINUX_TIOCMBIC: 908 args->cmd = TIOCMBIC; 909 error = (sys_ioctl(td, (struct ioctl_args *)args)); 910 break; 911 912 case LINUX_TIOCMSET: 913 args->cmd = TIOCMSET; 914 error = (sys_ioctl(td, (struct ioctl_args *)args)); 915 break; 916 917 /* TIOCGSOFTCAR */ 918 /* TIOCSSOFTCAR */ 919 920 case LINUX_FIONREAD: /* LINUX_TIOCINQ */ 921 args->cmd = FIONREAD; 922 error = (sys_ioctl(td, (struct ioctl_args *)args)); 923 break; 924 925 /* LINUX_TIOCLINUX */ 926 927 case LINUX_TIOCCONS: 928 args->cmd = TIOCCONS; 929 error = (sys_ioctl(td, (struct ioctl_args *)args)); 930 break; 931 932 case LINUX_TIOCGSERIAL: { 933 struct linux_serial_struct lss; 934 935 bzero(&lss, sizeof(lss)); 936 lss.type = LINUX_PORT_16550A; 937 lss.flags = 0; 938 lss.close_delay = 0; 939 error = copyout(&lss, (void *)args->arg, sizeof(lss)); 940 break; 941 } 942 943 case LINUX_TIOCSSERIAL: { 944 struct linux_serial_struct lss; 945 error = copyin((void *)args->arg, &lss, sizeof(lss)); 946 if (error) 947 break; 948 /* XXX - It really helps to have an implementation that 949 * does nothing. NOT! 950 */ 951 error = 0; 952 break; 953 } 954 955 case LINUX_TIOCPKT: 956 args->cmd = TIOCPKT; 957 error = (sys_ioctl(td, (struct ioctl_args *)args)); 958 break; 959 960 case LINUX_FIONBIO: 961 args->cmd = FIONBIO; 962 error = (sys_ioctl(td, (struct ioctl_args *)args)); 963 break; 964 965 case LINUX_TIOCNOTTY: 966 args->cmd = TIOCNOTTY; 967 error = (sys_ioctl(td, (struct ioctl_args *)args)); 968 break; 969 970 case LINUX_TIOCSETD: { 971 int line; 972 switch (args->arg) { 973 case LINUX_N_TTY: 974 line = TTYDISC; 975 break; 976 case LINUX_N_SLIP: 977 line = SLIPDISC; 978 break; 979 case LINUX_N_PPP: 980 line = PPPDISC; 981 break; 982 default: 983 fdrop(fp, td); 984 return (EINVAL); 985 } 986 error = (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, td->td_ucred, 987 td)); 988 break; 989 } 990 991 case LINUX_TIOCGETD: { 992 int linux_line; 993 int bsd_line = TTYDISC; 994 error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line, 995 td->td_ucred, td); 996 if (error) 997 break; 998 switch (bsd_line) { 999 case TTYDISC: 1000 linux_line = LINUX_N_TTY; 1001 break; 1002 case SLIPDISC: 1003 linux_line = LINUX_N_SLIP; 1004 break; 1005 case PPPDISC: 1006 linux_line = LINUX_N_PPP; 1007 break; 1008 default: 1009 fdrop(fp, td); 1010 return (EINVAL); 1011 } 1012 error = (copyout(&linux_line, (void *)args->arg, sizeof(int))); 1013 break; 1014 } 1015 1016 /* LINUX_TCSBRKP */ 1017 /* LINUX_TIOCTTYGSTRUCT */ 1018 1019 case LINUX_FIONCLEX: 1020 args->cmd = FIONCLEX; 1021 error = (sys_ioctl(td, (struct ioctl_args *)args)); 1022 break; 1023 1024 case LINUX_FIOCLEX: 1025 args->cmd = FIOCLEX; 1026 error = (sys_ioctl(td, (struct ioctl_args *)args)); 1027 break; 1028 1029 case LINUX_FIOASYNC: 1030 args->cmd = FIOASYNC; 1031 error = (sys_ioctl(td, (struct ioctl_args *)args)); 1032 break; 1033 1034 /* LINUX_TIOCSERCONFIG */ 1035 /* LINUX_TIOCSERGWILD */ 1036 /* LINUX_TIOCSERSWILD */ 1037 /* LINUX_TIOCGLCKTRMIOS */ 1038 /* LINUX_TIOCSLCKTRMIOS */ 1039 1040 case LINUX_TIOCSBRK: 1041 args->cmd = TIOCSBRK; 1042 error = (sys_ioctl(td, (struct ioctl_args *)args)); 1043 break; 1044 1045 case LINUX_TIOCCBRK: 1046 args->cmd = TIOCCBRK; 1047 error = (sys_ioctl(td, (struct ioctl_args *)args)); 1048 break; 1049 case LINUX_TIOCGPTN: { 1050 int nb; 1051 1052 error = fo_ioctl(fp, TIOCGPTN, (caddr_t)&nb, td->td_ucred, td); 1053 if (!error) 1054 error = copyout(&nb, (void *)args->arg, 1055 sizeof(int)); 1056 break; 1057 } 1058 case LINUX_TIOCSPTLCK: 1059 /* Our unlockpt() does nothing. */ 1060 error = 0; 1061 break; 1062 default: 1063 error = ENOIOCTL; 1064 break; 1065 } 1066 1067 fdrop(fp, td); 1068 return (error); 1069 } 1070 1071 /* 1072 * CDROM related ioctls 1073 */ 1074 1075 struct linux_cdrom_msf 1076 { 1077 u_char cdmsf_min0; 1078 u_char cdmsf_sec0; 1079 u_char cdmsf_frame0; 1080 u_char cdmsf_min1; 1081 u_char cdmsf_sec1; 1082 u_char cdmsf_frame1; 1083 }; 1084 1085 struct linux_cdrom_tochdr 1086 { 1087 u_char cdth_trk0; 1088 u_char cdth_trk1; 1089 }; 1090 1091 union linux_cdrom_addr 1092 { 1093 struct { 1094 u_char minute; 1095 u_char second; 1096 u_char frame; 1097 } msf; 1098 int lba; 1099 }; 1100 1101 struct linux_cdrom_tocentry 1102 { 1103 u_char cdte_track; 1104 u_char cdte_adr:4; 1105 u_char cdte_ctrl:4; 1106 u_char cdte_format; 1107 union linux_cdrom_addr cdte_addr; 1108 u_char cdte_datamode; 1109 }; 1110 1111 struct linux_cdrom_subchnl 1112 { 1113 u_char cdsc_format; 1114 u_char cdsc_audiostatus; 1115 u_char cdsc_adr:4; 1116 u_char cdsc_ctrl:4; 1117 u_char cdsc_trk; 1118 u_char cdsc_ind; 1119 union linux_cdrom_addr cdsc_absaddr; 1120 union linux_cdrom_addr cdsc_reladdr; 1121 }; 1122 1123 struct l_cdrom_read_audio { 1124 union linux_cdrom_addr addr; 1125 u_char addr_format; 1126 l_int nframes; 1127 u_char *buf; 1128 }; 1129 1130 struct l_dvd_layer { 1131 u_char book_version:4; 1132 u_char book_type:4; 1133 u_char min_rate:4; 1134 u_char disc_size:4; 1135 u_char layer_type:4; 1136 u_char track_path:1; 1137 u_char nlayers:2; 1138 u_char track_density:4; 1139 u_char linear_density:4; 1140 u_char bca:1; 1141 u_int32_t start_sector; 1142 u_int32_t end_sector; 1143 u_int32_t end_sector_l0; 1144 }; 1145 1146 struct l_dvd_physical { 1147 u_char type; 1148 u_char layer_num; 1149 struct l_dvd_layer layer[4]; 1150 }; 1151 1152 struct l_dvd_copyright { 1153 u_char type; 1154 u_char layer_num; 1155 u_char cpst; 1156 u_char rmi; 1157 }; 1158 1159 struct l_dvd_disckey { 1160 u_char type; 1161 l_uint agid:2; 1162 u_char value[2048]; 1163 }; 1164 1165 struct l_dvd_bca { 1166 u_char type; 1167 l_int len; 1168 u_char value[188]; 1169 }; 1170 1171 struct l_dvd_manufact { 1172 u_char type; 1173 u_char layer_num; 1174 l_int len; 1175 u_char value[2048]; 1176 }; 1177 1178 typedef union { 1179 u_char type; 1180 struct l_dvd_physical physical; 1181 struct l_dvd_copyright copyright; 1182 struct l_dvd_disckey disckey; 1183 struct l_dvd_bca bca; 1184 struct l_dvd_manufact manufact; 1185 } l_dvd_struct; 1186 1187 typedef u_char l_dvd_key[5]; 1188 typedef u_char l_dvd_challenge[10]; 1189 1190 struct l_dvd_lu_send_agid { 1191 u_char type; 1192 l_uint agid:2; 1193 }; 1194 1195 struct l_dvd_host_send_challenge { 1196 u_char type; 1197 l_uint agid:2; 1198 l_dvd_challenge chal; 1199 }; 1200 1201 struct l_dvd_send_key { 1202 u_char type; 1203 l_uint agid:2; 1204 l_dvd_key key; 1205 }; 1206 1207 struct l_dvd_lu_send_challenge { 1208 u_char type; 1209 l_uint agid:2; 1210 l_dvd_challenge chal; 1211 }; 1212 1213 struct l_dvd_lu_send_title_key { 1214 u_char type; 1215 l_uint agid:2; 1216 l_dvd_key title_key; 1217 l_int lba; 1218 l_uint cpm:1; 1219 l_uint cp_sec:1; 1220 l_uint cgms:2; 1221 }; 1222 1223 struct l_dvd_lu_send_asf { 1224 u_char type; 1225 l_uint agid:2; 1226 l_uint asf:1; 1227 }; 1228 1229 struct l_dvd_host_send_rpcstate { 1230 u_char type; 1231 u_char pdrc; 1232 }; 1233 1234 struct l_dvd_lu_send_rpcstate { 1235 u_char type:2; 1236 u_char vra:3; 1237 u_char ucca:3; 1238 u_char region_mask; 1239 u_char rpc_scheme; 1240 }; 1241 1242 typedef union { 1243 u_char type; 1244 struct l_dvd_lu_send_agid lsa; 1245 struct l_dvd_host_send_challenge hsc; 1246 struct l_dvd_send_key lsk; 1247 struct l_dvd_lu_send_challenge lsc; 1248 struct l_dvd_send_key hsk; 1249 struct l_dvd_lu_send_title_key lstk; 1250 struct l_dvd_lu_send_asf lsasf; 1251 struct l_dvd_host_send_rpcstate hrpcs; 1252 struct l_dvd_lu_send_rpcstate lrpcs; 1253 } l_dvd_authinfo; 1254 1255 static void 1256 bsd_to_linux_msf_lba(u_char af, union msf_lba *bp, union linux_cdrom_addr *lp) 1257 { 1258 if (af == CD_LBA_FORMAT) 1259 lp->lba = bp->lba; 1260 else { 1261 lp->msf.minute = bp->msf.minute; 1262 lp->msf.second = bp->msf.second; 1263 lp->msf.frame = bp->msf.frame; 1264 } 1265 } 1266 1267 static void 1268 set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba) 1269 { 1270 if (format == LINUX_CDROM_MSF) { 1271 addr->msf.frame = lba % 75; 1272 lba /= 75; 1273 lba += 2; 1274 addr->msf.second = lba % 60; 1275 addr->msf.minute = lba / 60; 1276 } else 1277 addr->lba = lba; 1278 } 1279 1280 static int 1281 linux_to_bsd_dvd_struct(l_dvd_struct *lp, struct dvd_struct *bp) 1282 { 1283 bp->format = lp->type; 1284 switch (bp->format) { 1285 case DVD_STRUCT_PHYSICAL: 1286 if (bp->layer_num >= 4) 1287 return (EINVAL); 1288 bp->layer_num = lp->physical.layer_num; 1289 break; 1290 case DVD_STRUCT_COPYRIGHT: 1291 bp->layer_num = lp->copyright.layer_num; 1292 break; 1293 case DVD_STRUCT_DISCKEY: 1294 bp->agid = lp->disckey.agid; 1295 break; 1296 case DVD_STRUCT_BCA: 1297 case DVD_STRUCT_MANUFACT: 1298 break; 1299 default: 1300 return (EINVAL); 1301 } 1302 return (0); 1303 } 1304 1305 static int 1306 bsd_to_linux_dvd_struct(struct dvd_struct *bp, l_dvd_struct *lp) 1307 { 1308 switch (bp->format) { 1309 case DVD_STRUCT_PHYSICAL: { 1310 struct dvd_layer *blp = (struct dvd_layer *)bp->data; 1311 struct l_dvd_layer *llp = &lp->physical.layer[bp->layer_num]; 1312 memset(llp, 0, sizeof(*llp)); 1313 llp->book_version = blp->book_version; 1314 llp->book_type = blp->book_type; 1315 llp->min_rate = blp->max_rate; 1316 llp->disc_size = blp->disc_size; 1317 llp->layer_type = blp->layer_type; 1318 llp->track_path = blp->track_path; 1319 llp->nlayers = blp->nlayers; 1320 llp->track_density = blp->track_density; 1321 llp->linear_density = blp->linear_density; 1322 llp->bca = blp->bca; 1323 llp->start_sector = blp->start_sector; 1324 llp->end_sector = blp->end_sector; 1325 llp->end_sector_l0 = blp->end_sector_l0; 1326 break; 1327 } 1328 case DVD_STRUCT_COPYRIGHT: 1329 lp->copyright.cpst = bp->cpst; 1330 lp->copyright.rmi = bp->rmi; 1331 break; 1332 case DVD_STRUCT_DISCKEY: 1333 memcpy(lp->disckey.value, bp->data, sizeof(lp->disckey.value)); 1334 break; 1335 case DVD_STRUCT_BCA: 1336 lp->bca.len = bp->length; 1337 memcpy(lp->bca.value, bp->data, sizeof(lp->bca.value)); 1338 break; 1339 case DVD_STRUCT_MANUFACT: 1340 lp->manufact.len = bp->length; 1341 memcpy(lp->manufact.value, bp->data, 1342 sizeof(lp->manufact.value)); 1343 /* lp->manufact.layer_num is unused in linux (redhat 7.0) */ 1344 break; 1345 default: 1346 return (EINVAL); 1347 } 1348 return (0); 1349 } 1350 1351 static int 1352 linux_to_bsd_dvd_authinfo(l_dvd_authinfo *lp, int *bcode, 1353 struct dvd_authinfo *bp) 1354 { 1355 switch (lp->type) { 1356 case LINUX_DVD_LU_SEND_AGID: 1357 *bcode = DVDIOCREPORTKEY; 1358 bp->format = DVD_REPORT_AGID; 1359 bp->agid = lp->lsa.agid; 1360 break; 1361 case LINUX_DVD_HOST_SEND_CHALLENGE: 1362 *bcode = DVDIOCSENDKEY; 1363 bp->format = DVD_SEND_CHALLENGE; 1364 bp->agid = lp->hsc.agid; 1365 memcpy(bp->keychal, lp->hsc.chal, 10); 1366 break; 1367 case LINUX_DVD_LU_SEND_KEY1: 1368 *bcode = DVDIOCREPORTKEY; 1369 bp->format = DVD_REPORT_KEY1; 1370 bp->agid = lp->lsk.agid; 1371 break; 1372 case LINUX_DVD_LU_SEND_CHALLENGE: 1373 *bcode = DVDIOCREPORTKEY; 1374 bp->format = DVD_REPORT_CHALLENGE; 1375 bp->agid = lp->lsc.agid; 1376 break; 1377 case LINUX_DVD_HOST_SEND_KEY2: 1378 *bcode = DVDIOCSENDKEY; 1379 bp->format = DVD_SEND_KEY2; 1380 bp->agid = lp->hsk.agid; 1381 memcpy(bp->keychal, lp->hsk.key, 5); 1382 break; 1383 case LINUX_DVD_LU_SEND_TITLE_KEY: 1384 *bcode = DVDIOCREPORTKEY; 1385 bp->format = DVD_REPORT_TITLE_KEY; 1386 bp->agid = lp->lstk.agid; 1387 bp->lba = lp->lstk.lba; 1388 break; 1389 case LINUX_DVD_LU_SEND_ASF: 1390 *bcode = DVDIOCREPORTKEY; 1391 bp->format = DVD_REPORT_ASF; 1392 bp->agid = lp->lsasf.agid; 1393 break; 1394 case LINUX_DVD_INVALIDATE_AGID: 1395 *bcode = DVDIOCREPORTKEY; 1396 bp->format = DVD_INVALIDATE_AGID; 1397 bp->agid = lp->lsa.agid; 1398 break; 1399 case LINUX_DVD_LU_SEND_RPC_STATE: 1400 *bcode = DVDIOCREPORTKEY; 1401 bp->format = DVD_REPORT_RPC; 1402 break; 1403 case LINUX_DVD_HOST_SEND_RPC_STATE: 1404 *bcode = DVDIOCSENDKEY; 1405 bp->format = DVD_SEND_RPC; 1406 bp->region = lp->hrpcs.pdrc; 1407 break; 1408 default: 1409 return (EINVAL); 1410 } 1411 return (0); 1412 } 1413 1414 static int 1415 bsd_to_linux_dvd_authinfo(struct dvd_authinfo *bp, l_dvd_authinfo *lp) 1416 { 1417 switch (lp->type) { 1418 case LINUX_DVD_LU_SEND_AGID: 1419 lp->lsa.agid = bp->agid; 1420 break; 1421 case LINUX_DVD_HOST_SEND_CHALLENGE: 1422 lp->type = LINUX_DVD_LU_SEND_KEY1; 1423 break; 1424 case LINUX_DVD_LU_SEND_KEY1: 1425 memcpy(lp->lsk.key, bp->keychal, sizeof(lp->lsk.key)); 1426 break; 1427 case LINUX_DVD_LU_SEND_CHALLENGE: 1428 memcpy(lp->lsc.chal, bp->keychal, sizeof(lp->lsc.chal)); 1429 break; 1430 case LINUX_DVD_HOST_SEND_KEY2: 1431 lp->type = LINUX_DVD_AUTH_ESTABLISHED; 1432 break; 1433 case LINUX_DVD_LU_SEND_TITLE_KEY: 1434 memcpy(lp->lstk.title_key, bp->keychal, 1435 sizeof(lp->lstk.title_key)); 1436 lp->lstk.cpm = bp->cpm; 1437 lp->lstk.cp_sec = bp->cp_sec; 1438 lp->lstk.cgms = bp->cgms; 1439 break; 1440 case LINUX_DVD_LU_SEND_ASF: 1441 lp->lsasf.asf = bp->asf; 1442 break; 1443 case LINUX_DVD_INVALIDATE_AGID: 1444 break; 1445 case LINUX_DVD_LU_SEND_RPC_STATE: 1446 lp->lrpcs.type = bp->reg_type; 1447 lp->lrpcs.vra = bp->vend_rsts; 1448 lp->lrpcs.ucca = bp->user_rsts; 1449 lp->lrpcs.region_mask = bp->region; 1450 lp->lrpcs.rpc_scheme = bp->rpc_scheme; 1451 break; 1452 case LINUX_DVD_HOST_SEND_RPC_STATE: 1453 break; 1454 default: 1455 return (EINVAL); 1456 } 1457 return (0); 1458 } 1459 1460 static int 1461 linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args) 1462 { 1463 cap_rights_t rights; 1464 struct file *fp; 1465 int error; 1466 1467 error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); 1468 if (error != 0) 1469 return (error); 1470 switch (args->cmd & 0xffff) { 1471 1472 case LINUX_CDROMPAUSE: 1473 args->cmd = CDIOCPAUSE; 1474 error = (sys_ioctl(td, (struct ioctl_args *)args)); 1475 break; 1476 1477 case LINUX_CDROMRESUME: 1478 args->cmd = CDIOCRESUME; 1479 error = (sys_ioctl(td, (struct ioctl_args *)args)); 1480 break; 1481 1482 case LINUX_CDROMPLAYMSF: 1483 args->cmd = CDIOCPLAYMSF; 1484 error = (sys_ioctl(td, (struct ioctl_args *)args)); 1485 break; 1486 1487 case LINUX_CDROMPLAYTRKIND: 1488 args->cmd = CDIOCPLAYTRACKS; 1489 error = (sys_ioctl(td, (struct ioctl_args *)args)); 1490 break; 1491 1492 case LINUX_CDROMREADTOCHDR: { 1493 struct ioc_toc_header th; 1494 struct linux_cdrom_tochdr lth; 1495 error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th, 1496 td->td_ucred, td); 1497 if (!error) { 1498 lth.cdth_trk0 = th.starting_track; 1499 lth.cdth_trk1 = th.ending_track; 1500 copyout(<h, (void *)args->arg, sizeof(lth)); 1501 } 1502 break; 1503 } 1504 1505 case LINUX_CDROMREADTOCENTRY: { 1506 struct linux_cdrom_tocentry lte; 1507 struct ioc_read_toc_single_entry irtse; 1508 1509 error = copyin((void *)args->arg, <e, sizeof(lte)); 1510 if (error) 1511 break; 1512 irtse.address_format = lte.cdte_format; 1513 irtse.track = lte.cdte_track; 1514 error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse, 1515 td->td_ucred, td); 1516 if (!error) { 1517 lte.cdte_ctrl = irtse.entry.control; 1518 lte.cdte_adr = irtse.entry.addr_type; 1519 bsd_to_linux_msf_lba(irtse.address_format, 1520 &irtse.entry.addr, <e.cdte_addr); 1521 error = copyout(<e, (void *)args->arg, sizeof(lte)); 1522 } 1523 break; 1524 } 1525 1526 case LINUX_CDROMSTOP: 1527 args->cmd = CDIOCSTOP; 1528 error = (sys_ioctl(td, (struct ioctl_args *)args)); 1529 break; 1530 1531 case LINUX_CDROMSTART: 1532 args->cmd = CDIOCSTART; 1533 error = (sys_ioctl(td, (struct ioctl_args *)args)); 1534 break; 1535 1536 case LINUX_CDROMEJECT: 1537 args->cmd = CDIOCEJECT; 1538 error = (sys_ioctl(td, (struct ioctl_args *)args)); 1539 break; 1540 1541 /* LINUX_CDROMVOLCTRL */ 1542 1543 case LINUX_CDROMSUBCHNL: { 1544 struct linux_cdrom_subchnl sc; 1545 struct ioc_read_subchannel bsdsc; 1546 struct cd_sub_channel_info bsdinfo; 1547 1548 bsdsc.address_format = CD_LBA_FORMAT; 1549 bsdsc.data_format = CD_CURRENT_POSITION; 1550 bsdsc.track = 0; 1551 bsdsc.data_len = sizeof(bsdinfo); 1552 bsdsc.data = &bsdinfo; 1553 error = fo_ioctl(fp, CDIOCREADSUBCHANNEL_SYSSPACE, 1554 (caddr_t)&bsdsc, td->td_ucred, td); 1555 if (error) 1556 break; 1557 error = copyin((void *)args->arg, &sc, sizeof(sc)); 1558 if (error) 1559 break; 1560 sc.cdsc_audiostatus = bsdinfo.header.audio_status; 1561 sc.cdsc_adr = bsdinfo.what.position.addr_type; 1562 sc.cdsc_ctrl = bsdinfo.what.position.control; 1563 sc.cdsc_trk = bsdinfo.what.position.track_number; 1564 sc.cdsc_ind = bsdinfo.what.position.index_number; 1565 set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format, 1566 bsdinfo.what.position.absaddr.lba); 1567 set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format, 1568 bsdinfo.what.position.reladdr.lba); 1569 error = copyout(&sc, (void *)args->arg, sizeof(sc)); 1570 break; 1571 } 1572 1573 /* LINUX_CDROMREADMODE2 */ 1574 /* LINUX_CDROMREADMODE1 */ 1575 /* LINUX_CDROMREADAUDIO */ 1576 /* LINUX_CDROMEJECT_SW */ 1577 /* LINUX_CDROMMULTISESSION */ 1578 /* LINUX_CDROM_GET_UPC */ 1579 1580 case LINUX_CDROMRESET: 1581 args->cmd = CDIOCRESET; 1582 error = (sys_ioctl(td, (struct ioctl_args *)args)); 1583 break; 1584 1585 /* LINUX_CDROMVOLREAD */ 1586 /* LINUX_CDROMREADRAW */ 1587 /* LINUX_CDROMREADCOOKED */ 1588 /* LINUX_CDROMSEEK */ 1589 /* LINUX_CDROMPLAYBLK */ 1590 /* LINUX_CDROMREADALL */ 1591 /* LINUX_CDROMCLOSETRAY */ 1592 /* LINUX_CDROMLOADFROMSLOT */ 1593 /* LINUX_CDROMGETSPINDOWN */ 1594 /* LINUX_CDROMSETSPINDOWN */ 1595 /* LINUX_CDROM_SET_OPTIONS */ 1596 /* LINUX_CDROM_CLEAR_OPTIONS */ 1597 /* LINUX_CDROM_SELECT_SPEED */ 1598 /* LINUX_CDROM_SELECT_DISC */ 1599 /* LINUX_CDROM_MEDIA_CHANGED */ 1600 /* LINUX_CDROM_DRIVE_STATUS */ 1601 /* LINUX_CDROM_DISC_STATUS */ 1602 /* LINUX_CDROM_CHANGER_NSLOTS */ 1603 /* LINUX_CDROM_LOCKDOOR */ 1604 /* LINUX_CDROM_DEBUG */ 1605 /* LINUX_CDROM_GET_CAPABILITY */ 1606 /* LINUX_CDROMAUDIOBUFSIZ */ 1607 1608 case LINUX_DVD_READ_STRUCT: { 1609 l_dvd_struct *lds; 1610 struct dvd_struct *bds; 1611 1612 lds = malloc(sizeof(*lds), M_LINUX, M_WAITOK); 1613 bds = malloc(sizeof(*bds), M_LINUX, M_WAITOK); 1614 error = copyin((void *)args->arg, lds, sizeof(*lds)); 1615 if (error) 1616 goto out; 1617 error = linux_to_bsd_dvd_struct(lds, bds); 1618 if (error) 1619 goto out; 1620 error = fo_ioctl(fp, DVDIOCREADSTRUCTURE, (caddr_t)bds, 1621 td->td_ucred, td); 1622 if (error) 1623 goto out; 1624 error = bsd_to_linux_dvd_struct(bds, lds); 1625 if (error) 1626 goto out; 1627 error = copyout(lds, (void *)args->arg, sizeof(*lds)); 1628 out: 1629 free(bds, M_LINUX); 1630 free(lds, M_LINUX); 1631 break; 1632 } 1633 1634 /* LINUX_DVD_WRITE_STRUCT */ 1635 1636 case LINUX_DVD_AUTH: { 1637 l_dvd_authinfo lda; 1638 struct dvd_authinfo bda; 1639 int bcode; 1640 1641 error = copyin((void *)args->arg, &lda, sizeof(lda)); 1642 if (error) 1643 break; 1644 error = linux_to_bsd_dvd_authinfo(&lda, &bcode, &bda); 1645 if (error) 1646 break; 1647 error = fo_ioctl(fp, bcode, (caddr_t)&bda, td->td_ucred, 1648 td); 1649 if (error) { 1650 if (lda.type == LINUX_DVD_HOST_SEND_KEY2) { 1651 lda.type = LINUX_DVD_AUTH_FAILURE; 1652 copyout(&lda, (void *)args->arg, sizeof(lda)); 1653 } 1654 break; 1655 } 1656 error = bsd_to_linux_dvd_authinfo(&bda, &lda); 1657 if (error) 1658 break; 1659 error = copyout(&lda, (void *)args->arg, sizeof(lda)); 1660 break; 1661 } 1662 1663 case LINUX_SCSI_GET_BUS_NUMBER: 1664 { 1665 struct sg_scsi_id id; 1666 1667 error = fo_ioctl(fp, SG_GET_SCSI_ID, (caddr_t)&id, 1668 td->td_ucred, td); 1669 if (error) 1670 break; 1671 error = copyout(&id.channel, (void *)args->arg, sizeof(int)); 1672 break; 1673 } 1674 1675 case LINUX_SCSI_GET_IDLUN: 1676 { 1677 struct sg_scsi_id id; 1678 struct scsi_idlun idl; 1679 1680 error = fo_ioctl(fp, SG_GET_SCSI_ID, (caddr_t)&id, 1681 td->td_ucred, td); 1682 if (error) 1683 break; 1684 idl.dev_id = (id.scsi_id & 0xff) + ((id.lun & 0xff) << 8) + 1685 ((id.channel & 0xff) << 16) + ((id.host_no & 0xff) << 24); 1686 idl.host_unique_id = id.host_no; 1687 error = copyout(&idl, (void *)args->arg, sizeof(idl)); 1688 break; 1689 } 1690 1691 /* LINUX_CDROM_SEND_PACKET */ 1692 /* LINUX_CDROM_NEXT_WRITABLE */ 1693 /* LINUX_CDROM_LAST_WRITTEN */ 1694 1695 default: 1696 error = ENOIOCTL; 1697 break; 1698 } 1699 1700 fdrop(fp, td); 1701 return (error); 1702 } 1703 1704 static int 1705 linux_ioctl_vfat(struct thread *td, struct linux_ioctl_args *args) 1706 { 1707 1708 return (ENOTTY); 1709 } 1710 1711 /* 1712 * Sound related ioctls 1713 */ 1714 1715 struct linux_old_mixer_info { 1716 char id[16]; 1717 char name[32]; 1718 }; 1719 1720 static u_int32_t dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT }; 1721 1722 #define SETDIR(c) (((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30]) 1723 1724 static int 1725 linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args) 1726 { 1727 1728 switch (args->cmd & 0xffff) { 1729 1730 case LINUX_SOUND_MIXER_WRITE_VOLUME: 1731 args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME); 1732 return (sys_ioctl(td, (struct ioctl_args *)args)); 1733 1734 case LINUX_SOUND_MIXER_WRITE_BASS: 1735 args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS); 1736 return (sys_ioctl(td, (struct ioctl_args *)args)); 1737 1738 case LINUX_SOUND_MIXER_WRITE_TREBLE: 1739 args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE); 1740 return (sys_ioctl(td, (struct ioctl_args *)args)); 1741 1742 case LINUX_SOUND_MIXER_WRITE_SYNTH: 1743 args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH); 1744 return (sys_ioctl(td, (struct ioctl_args *)args)); 1745 1746 case LINUX_SOUND_MIXER_WRITE_PCM: 1747 args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM); 1748 return (sys_ioctl(td, (struct ioctl_args *)args)); 1749 1750 case LINUX_SOUND_MIXER_WRITE_SPEAKER: 1751 args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER); 1752 return (sys_ioctl(td, (struct ioctl_args *)args)); 1753 1754 case LINUX_SOUND_MIXER_WRITE_LINE: 1755 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE); 1756 return (sys_ioctl(td, (struct ioctl_args *)args)); 1757 1758 case LINUX_SOUND_MIXER_WRITE_MIC: 1759 args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC); 1760 return (sys_ioctl(td, (struct ioctl_args *)args)); 1761 1762 case LINUX_SOUND_MIXER_WRITE_CD: 1763 args->cmd = SETDIR(SOUND_MIXER_WRITE_CD); 1764 return (sys_ioctl(td, (struct ioctl_args *)args)); 1765 1766 case LINUX_SOUND_MIXER_WRITE_IMIX: 1767 args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX); 1768 return (sys_ioctl(td, (struct ioctl_args *)args)); 1769 1770 case LINUX_SOUND_MIXER_WRITE_ALTPCM: 1771 args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM); 1772 return (sys_ioctl(td, (struct ioctl_args *)args)); 1773 1774 case LINUX_SOUND_MIXER_WRITE_RECLEV: 1775 args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV); 1776 return (sys_ioctl(td, (struct ioctl_args *)args)); 1777 1778 case LINUX_SOUND_MIXER_WRITE_IGAIN: 1779 args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN); 1780 return (sys_ioctl(td, (struct ioctl_args *)args)); 1781 1782 case LINUX_SOUND_MIXER_WRITE_OGAIN: 1783 args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN); 1784 return (sys_ioctl(td, (struct ioctl_args *)args)); 1785 1786 case LINUX_SOUND_MIXER_WRITE_LINE1: 1787 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1); 1788 return (sys_ioctl(td, (struct ioctl_args *)args)); 1789 1790 case LINUX_SOUND_MIXER_WRITE_LINE2: 1791 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2); 1792 return (sys_ioctl(td, (struct ioctl_args *)args)); 1793 1794 case LINUX_SOUND_MIXER_WRITE_LINE3: 1795 args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3); 1796 return (sys_ioctl(td, (struct ioctl_args *)args)); 1797 1798 case LINUX_SOUND_MIXER_INFO: { 1799 /* Key on encoded length */ 1800 switch ((args->cmd >> 16) & 0x1fff) { 1801 case 0x005c: { /* SOUND_MIXER_INFO */ 1802 args->cmd = SOUND_MIXER_INFO; 1803 return (sys_ioctl(td, (struct ioctl_args *)args)); 1804 } 1805 case 0x0030: { /* SOUND_OLD_MIXER_INFO */ 1806 struct linux_old_mixer_info info; 1807 bzero(&info, sizeof(info)); 1808 strncpy(info.id, "OSS", sizeof(info.id) - 1); 1809 strncpy(info.name, "FreeBSD OSS Mixer", sizeof(info.name) - 1); 1810 copyout(&info, (void *)args->arg, sizeof(info)); 1811 return (0); 1812 } 1813 default: 1814 return (ENOIOCTL); 1815 } 1816 break; 1817 } 1818 1819 case LINUX_OSS_GETVERSION: { 1820 int version = linux_get_oss_version(td); 1821 return (copyout(&version, (void *)args->arg, sizeof(int))); 1822 } 1823 1824 case LINUX_SOUND_MIXER_READ_STEREODEVS: 1825 args->cmd = SOUND_MIXER_READ_STEREODEVS; 1826 return (sys_ioctl(td, (struct ioctl_args *)args)); 1827 1828 case LINUX_SOUND_MIXER_READ_CAPS: 1829 args->cmd = SOUND_MIXER_READ_CAPS; 1830 return (sys_ioctl(td, (struct ioctl_args *)args)); 1831 1832 case LINUX_SOUND_MIXER_READ_RECMASK: 1833 args->cmd = SOUND_MIXER_READ_RECMASK; 1834 return (sys_ioctl(td, (struct ioctl_args *)args)); 1835 1836 case LINUX_SOUND_MIXER_READ_DEVMASK: 1837 args->cmd = SOUND_MIXER_READ_DEVMASK; 1838 return (sys_ioctl(td, (struct ioctl_args *)args)); 1839 1840 case LINUX_SOUND_MIXER_WRITE_RECSRC: 1841 args->cmd = SETDIR(SOUND_MIXER_WRITE_RECSRC); 1842 return (sys_ioctl(td, (struct ioctl_args *)args)); 1843 1844 case LINUX_SNDCTL_DSP_RESET: 1845 args->cmd = SNDCTL_DSP_RESET; 1846 return (sys_ioctl(td, (struct ioctl_args *)args)); 1847 1848 case LINUX_SNDCTL_DSP_SYNC: 1849 args->cmd = SNDCTL_DSP_SYNC; 1850 return (sys_ioctl(td, (struct ioctl_args *)args)); 1851 1852 case LINUX_SNDCTL_DSP_SPEED: 1853 args->cmd = SNDCTL_DSP_SPEED; 1854 return (sys_ioctl(td, (struct ioctl_args *)args)); 1855 1856 case LINUX_SNDCTL_DSP_STEREO: 1857 args->cmd = SNDCTL_DSP_STEREO; 1858 return (sys_ioctl(td, (struct ioctl_args *)args)); 1859 1860 case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */ 1861 args->cmd = SNDCTL_DSP_GETBLKSIZE; 1862 return (sys_ioctl(td, (struct ioctl_args *)args)); 1863 1864 case LINUX_SNDCTL_DSP_SETFMT: 1865 args->cmd = SNDCTL_DSP_SETFMT; 1866 return (sys_ioctl(td, (struct ioctl_args *)args)); 1867 1868 case LINUX_SOUND_PCM_WRITE_CHANNELS: 1869 args->cmd = SOUND_PCM_WRITE_CHANNELS; 1870 return (sys_ioctl(td, (struct ioctl_args *)args)); 1871 1872 case LINUX_SOUND_PCM_WRITE_FILTER: 1873 args->cmd = SOUND_PCM_WRITE_FILTER; 1874 return (sys_ioctl(td, (struct ioctl_args *)args)); 1875 1876 case LINUX_SNDCTL_DSP_POST: 1877 args->cmd = SNDCTL_DSP_POST; 1878 return (sys_ioctl(td, (struct ioctl_args *)args)); 1879 1880 case LINUX_SNDCTL_DSP_SUBDIVIDE: 1881 args->cmd = SNDCTL_DSP_SUBDIVIDE; 1882 return (sys_ioctl(td, (struct ioctl_args *)args)); 1883 1884 case LINUX_SNDCTL_DSP_SETFRAGMENT: 1885 args->cmd = SNDCTL_DSP_SETFRAGMENT; 1886 return (sys_ioctl(td, (struct ioctl_args *)args)); 1887 1888 case LINUX_SNDCTL_DSP_GETFMTS: 1889 args->cmd = SNDCTL_DSP_GETFMTS; 1890 return (sys_ioctl(td, (struct ioctl_args *)args)); 1891 1892 case LINUX_SNDCTL_DSP_GETOSPACE: 1893 args->cmd = SNDCTL_DSP_GETOSPACE; 1894 return (sys_ioctl(td, (struct ioctl_args *)args)); 1895 1896 case LINUX_SNDCTL_DSP_GETISPACE: 1897 args->cmd = SNDCTL_DSP_GETISPACE; 1898 return (sys_ioctl(td, (struct ioctl_args *)args)); 1899 1900 case LINUX_SNDCTL_DSP_NONBLOCK: 1901 args->cmd = SNDCTL_DSP_NONBLOCK; 1902 return (sys_ioctl(td, (struct ioctl_args *)args)); 1903 1904 case LINUX_SNDCTL_DSP_GETCAPS: 1905 args->cmd = SNDCTL_DSP_GETCAPS; 1906 return (sys_ioctl(td, (struct ioctl_args *)args)); 1907 1908 case LINUX_SNDCTL_DSP_SETTRIGGER: /* LINUX_SNDCTL_GETTRIGGER */ 1909 args->cmd = SNDCTL_DSP_SETTRIGGER; 1910 return (sys_ioctl(td, (struct ioctl_args *)args)); 1911 1912 case LINUX_SNDCTL_DSP_GETIPTR: 1913 args->cmd = SNDCTL_DSP_GETIPTR; 1914 return (sys_ioctl(td, (struct ioctl_args *)args)); 1915 1916 case LINUX_SNDCTL_DSP_GETOPTR: 1917 args->cmd = SNDCTL_DSP_GETOPTR; 1918 return (sys_ioctl(td, (struct ioctl_args *)args)); 1919 1920 case LINUX_SNDCTL_DSP_SETDUPLEX: 1921 args->cmd = SNDCTL_DSP_SETDUPLEX; 1922 return (sys_ioctl(td, (struct ioctl_args *)args)); 1923 1924 case LINUX_SNDCTL_DSP_GETODELAY: 1925 args->cmd = SNDCTL_DSP_GETODELAY; 1926 return (sys_ioctl(td, (struct ioctl_args *)args)); 1927 1928 case LINUX_SNDCTL_SEQ_RESET: 1929 args->cmd = SNDCTL_SEQ_RESET; 1930 return (sys_ioctl(td, (struct ioctl_args *)args)); 1931 1932 case LINUX_SNDCTL_SEQ_SYNC: 1933 args->cmd = SNDCTL_SEQ_SYNC; 1934 return (sys_ioctl(td, (struct ioctl_args *)args)); 1935 1936 case LINUX_SNDCTL_SYNTH_INFO: 1937 args->cmd = SNDCTL_SYNTH_INFO; 1938 return (sys_ioctl(td, (struct ioctl_args *)args)); 1939 1940 case LINUX_SNDCTL_SEQ_CTRLRATE: 1941 args->cmd = SNDCTL_SEQ_CTRLRATE; 1942 return (sys_ioctl(td, (struct ioctl_args *)args)); 1943 1944 case LINUX_SNDCTL_SEQ_GETOUTCOUNT: 1945 args->cmd = SNDCTL_SEQ_GETOUTCOUNT; 1946 return (sys_ioctl(td, (struct ioctl_args *)args)); 1947 1948 case LINUX_SNDCTL_SEQ_GETINCOUNT: 1949 args->cmd = SNDCTL_SEQ_GETINCOUNT; 1950 return (sys_ioctl(td, (struct ioctl_args *)args)); 1951 1952 case LINUX_SNDCTL_SEQ_PERCMODE: 1953 args->cmd = SNDCTL_SEQ_PERCMODE; 1954 return (sys_ioctl(td, (struct ioctl_args *)args)); 1955 1956 case LINUX_SNDCTL_FM_LOAD_INSTR: 1957 args->cmd = SNDCTL_FM_LOAD_INSTR; 1958 return (sys_ioctl(td, (struct ioctl_args *)args)); 1959 1960 case LINUX_SNDCTL_SEQ_TESTMIDI: 1961 args->cmd = SNDCTL_SEQ_TESTMIDI; 1962 return (sys_ioctl(td, (struct ioctl_args *)args)); 1963 1964 case LINUX_SNDCTL_SEQ_RESETSAMPLES: 1965 args->cmd = SNDCTL_SEQ_RESETSAMPLES; 1966 return (sys_ioctl(td, (struct ioctl_args *)args)); 1967 1968 case LINUX_SNDCTL_SEQ_NRSYNTHS: 1969 args->cmd = SNDCTL_SEQ_NRSYNTHS; 1970 return (sys_ioctl(td, (struct ioctl_args *)args)); 1971 1972 case LINUX_SNDCTL_SEQ_NRMIDIS: 1973 args->cmd = SNDCTL_SEQ_NRMIDIS; 1974 return (sys_ioctl(td, (struct ioctl_args *)args)); 1975 1976 case LINUX_SNDCTL_MIDI_INFO: 1977 args->cmd = SNDCTL_MIDI_INFO; 1978 return (sys_ioctl(td, (struct ioctl_args *)args)); 1979 1980 case LINUX_SNDCTL_SEQ_TRESHOLD: 1981 args->cmd = SNDCTL_SEQ_TRESHOLD; 1982 return (sys_ioctl(td, (struct ioctl_args *)args)); 1983 1984 case LINUX_SNDCTL_SYNTH_MEMAVL: 1985 args->cmd = SNDCTL_SYNTH_MEMAVL; 1986 return (sys_ioctl(td, (struct ioctl_args *)args)); 1987 1988 } 1989 1990 return (ENOIOCTL); 1991 } 1992 1993 /* 1994 * Console related ioctls 1995 */ 1996 1997 static int 1998 linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args) 1999 { 2000 cap_rights_t rights; 2001 struct file *fp; 2002 int error; 2003 2004 error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); 2005 if (error != 0) 2006 return (error); 2007 switch (args->cmd & 0xffff) { 2008 2009 case LINUX_KIOCSOUND: 2010 args->cmd = KIOCSOUND; 2011 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2012 break; 2013 2014 case LINUX_KDMKTONE: 2015 args->cmd = KDMKTONE; 2016 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2017 break; 2018 2019 case LINUX_KDGETLED: 2020 args->cmd = KDGETLED; 2021 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2022 break; 2023 2024 case LINUX_KDSETLED: 2025 args->cmd = KDSETLED; 2026 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2027 break; 2028 2029 case LINUX_KDSETMODE: 2030 args->cmd = KDSETMODE; 2031 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2032 break; 2033 2034 case LINUX_KDGETMODE: 2035 args->cmd = KDGETMODE; 2036 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2037 break; 2038 2039 case LINUX_KDGKBMODE: 2040 args->cmd = KDGKBMODE; 2041 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2042 break; 2043 2044 case LINUX_KDSKBMODE: { 2045 int kbdmode; 2046 switch (args->arg) { 2047 case LINUX_KBD_RAW: 2048 kbdmode = K_RAW; 2049 break; 2050 case LINUX_KBD_XLATE: 2051 kbdmode = K_XLATE; 2052 break; 2053 case LINUX_KBD_MEDIUMRAW: 2054 kbdmode = K_RAW; 2055 break; 2056 default: 2057 fdrop(fp, td); 2058 return (EINVAL); 2059 } 2060 error = (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode, 2061 td->td_ucred, td)); 2062 break; 2063 } 2064 2065 case LINUX_VT_OPENQRY: 2066 args->cmd = VT_OPENQRY; 2067 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2068 break; 2069 2070 case LINUX_VT_GETMODE: 2071 args->cmd = VT_GETMODE; 2072 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2073 break; 2074 2075 case LINUX_VT_SETMODE: { 2076 struct vt_mode mode; 2077 if ((error = copyin((void *)args->arg, &mode, sizeof(mode)))) 2078 break; 2079 if (LINUX_SIG_VALID(mode.relsig)) 2080 mode.relsig = linux_to_bsd_signal(mode.relsig); 2081 else 2082 mode.relsig = 0; 2083 if (LINUX_SIG_VALID(mode.acqsig)) 2084 mode.acqsig = linux_to_bsd_signal(mode.acqsig); 2085 else 2086 mode.acqsig = 0; 2087 /* XXX. Linux ignores frsig and set it to 0. */ 2088 mode.frsig = 0; 2089 if ((error = copyout(&mode, (void *)args->arg, sizeof(mode)))) 2090 break; 2091 args->cmd = VT_SETMODE; 2092 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2093 break; 2094 } 2095 2096 case LINUX_VT_GETSTATE: 2097 args->cmd = VT_GETACTIVE; 2098 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2099 break; 2100 2101 case LINUX_VT_RELDISP: 2102 args->cmd = VT_RELDISP; 2103 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2104 break; 2105 2106 case LINUX_VT_ACTIVATE: 2107 args->cmd = VT_ACTIVATE; 2108 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2109 break; 2110 2111 case LINUX_VT_WAITACTIVE: 2112 args->cmd = VT_WAITACTIVE; 2113 error = (sys_ioctl(td, (struct ioctl_args *)args)); 2114 break; 2115 2116 default: 2117 error = ENOIOCTL; 2118 break; 2119 } 2120 2121 fdrop(fp, td); 2122 return (error); 2123 } 2124 2125 /* 2126 * Criteria for interface name translation 2127 */ 2128 #define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER) 2129 2130 /* 2131 * Translate a Linux interface name to a FreeBSD interface name, 2132 * and return the associated ifnet structure 2133 * bsdname and lxname need to be least IFNAMSIZ bytes long, but 2134 * can point to the same buffer. 2135 */ 2136 2137 static struct ifnet * 2138 ifname_linux_to_bsd(struct thread *td, const char *lxname, char *bsdname) 2139 { 2140 struct ifnet *ifp; 2141 int len, unit; 2142 char *ep; 2143 int is_eth, index; 2144 2145 for (len = 0; len < LINUX_IFNAMSIZ; ++len) 2146 if (!isalpha(lxname[len])) 2147 break; 2148 if (len == 0 || len == LINUX_IFNAMSIZ) 2149 return (NULL); 2150 unit = (int)strtoul(lxname + len, &ep, 10); 2151 if (ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ) 2152 return (NULL); 2153 index = 0; 2154 is_eth = (len == 3 && !strncmp(lxname, "eth", len)) ? 1 : 0; 2155 CURVNET_SET(TD_TO_VNET(td)); 2156 IFNET_RLOCK(); 2157 TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 2158 /* 2159 * Allow Linux programs to use FreeBSD names. Don't presume 2160 * we never have an interface named "eth", so don't make 2161 * the test optional based on is_eth. 2162 */ 2163 if (strncmp(ifp->if_xname, lxname, LINUX_IFNAMSIZ) == 0) 2164 break; 2165 if (is_eth && IFP_IS_ETH(ifp) && unit == index++) 2166 break; 2167 } 2168 IFNET_RUNLOCK(); 2169 CURVNET_RESTORE(); 2170 if (ifp != NULL) 2171 strlcpy(bsdname, ifp->if_xname, IFNAMSIZ); 2172 return (ifp); 2173 } 2174 2175 /* 2176 * Implement the SIOCGIFNAME ioctl 2177 */ 2178 2179 static int 2180 linux_ioctl_ifname(struct thread *td, struct l_ifreq *uifr) 2181 { 2182 struct l_ifreq ifr; 2183 struct ifnet *ifp; 2184 int error, ethno, index; 2185 2186 error = copyin(uifr, &ifr, sizeof(ifr)); 2187 if (error != 0) 2188 return (error); 2189 2190 CURVNET_SET(TD_TO_VNET(curthread)); 2191 IFNET_RLOCK(); 2192 index = 1; /* ifr.ifr_ifindex starts from 1 */ 2193 ethno = 0; 2194 error = ENODEV; 2195 TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 2196 if (ifr.ifr_ifindex == index) { 2197 if (IFP_IS_ETH(ifp)) 2198 snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, 2199 "eth%d", ethno); 2200 else 2201 strlcpy(ifr.ifr_name, ifp->if_xname, 2202 LINUX_IFNAMSIZ); 2203 error = 0; 2204 break; 2205 } 2206 if (IFP_IS_ETH(ifp)) 2207 ethno++; 2208 index++; 2209 } 2210 IFNET_RUNLOCK(); 2211 if (error == 0) 2212 error = copyout(&ifr, uifr, sizeof(ifr)); 2213 CURVNET_RESTORE(); 2214 2215 return (error); 2216 } 2217 2218 /* 2219 * Implement the SIOCGIFCONF ioctl 2220 */ 2221 2222 static int 2223 linux_ifconf(struct thread *td, struct ifconf *uifc) 2224 { 2225 #ifdef COMPAT_LINUX32 2226 struct l_ifconf ifc; 2227 #else 2228 struct ifconf ifc; 2229 #endif 2230 struct l_ifreq ifr; 2231 struct ifnet *ifp; 2232 struct ifaddr *ifa; 2233 struct sbuf *sb; 2234 int error, ethno, full = 0, valid_len, max_len; 2235 2236 error = copyin(uifc, &ifc, sizeof(ifc)); 2237 if (error != 0) 2238 return (error); 2239 2240 max_len = MAXPHYS - 1; 2241 2242 CURVNET_SET(TD_TO_VNET(td)); 2243 /* handle the 'request buffer size' case */ 2244 if ((l_uintptr_t)ifc.ifc_buf == PTROUT(NULL)) { 2245 ifc.ifc_len = 0; 2246 IFNET_RLOCK(); 2247 TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 2248 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 2249 struct sockaddr *sa = ifa->ifa_addr; 2250 if (sa->sa_family == AF_INET) 2251 ifc.ifc_len += sizeof(ifr); 2252 } 2253 } 2254 IFNET_RUNLOCK(); 2255 error = copyout(&ifc, uifc, sizeof(ifc)); 2256 CURVNET_RESTORE(); 2257 return (error); 2258 } 2259 2260 if (ifc.ifc_len <= 0) { 2261 CURVNET_RESTORE(); 2262 return (EINVAL); 2263 } 2264 2265 again: 2266 /* Keep track of eth interfaces */ 2267 ethno = 0; 2268 if (ifc.ifc_len <= max_len) { 2269 max_len = ifc.ifc_len; 2270 full = 1; 2271 } 2272 sb = sbuf_new(NULL, NULL, max_len + 1, SBUF_FIXEDLEN); 2273 max_len = 0; 2274 valid_len = 0; 2275 2276 /* Return all AF_INET addresses of all interfaces */ 2277 IFNET_RLOCK(); 2278 TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 2279 int addrs = 0; 2280 2281 bzero(&ifr, sizeof(ifr)); 2282 if (IFP_IS_ETH(ifp)) 2283 snprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "eth%d", 2284 ethno++); 2285 else 2286 strlcpy(ifr.ifr_name, ifp->if_xname, LINUX_IFNAMSIZ); 2287 2288 /* Walk the address list */ 2289 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 2290 struct sockaddr *sa = ifa->ifa_addr; 2291 2292 if (sa->sa_family == AF_INET) { 2293 ifr.ifr_addr.sa_family = LINUX_AF_INET; 2294 memcpy(ifr.ifr_addr.sa_data, sa->sa_data, 2295 sizeof(ifr.ifr_addr.sa_data)); 2296 sbuf_bcat(sb, &ifr, sizeof(ifr)); 2297 max_len += sizeof(ifr); 2298 addrs++; 2299 } 2300 2301 if (sbuf_error(sb) == 0) 2302 valid_len = sbuf_len(sb); 2303 } 2304 if (addrs == 0) { 2305 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 2306 sbuf_bcat(sb, &ifr, sizeof(ifr)); 2307 max_len += sizeof(ifr); 2308 2309 if (sbuf_error(sb) == 0) 2310 valid_len = sbuf_len(sb); 2311 } 2312 } 2313 IFNET_RUNLOCK(); 2314 2315 if (valid_len != max_len && !full) { 2316 sbuf_delete(sb); 2317 goto again; 2318 } 2319 2320 ifc.ifc_len = valid_len; 2321 sbuf_finish(sb); 2322 error = copyout(sbuf_data(sb), PTRIN(ifc.ifc_buf), ifc.ifc_len); 2323 if (error == 0) 2324 error = copyout(&ifc, uifc, sizeof(ifc)); 2325 sbuf_delete(sb); 2326 CURVNET_RESTORE(); 2327 2328 return (error); 2329 } 2330 2331 static int 2332 linux_gifflags(struct thread *td, struct ifnet *ifp, struct l_ifreq *ifr) 2333 { 2334 l_short flags; 2335 2336 flags = (ifp->if_flags | ifp->if_drv_flags) & 0xffff; 2337 /* these flags have no Linux equivalent */ 2338 flags &= ~(IFF_DRV_OACTIVE|IFF_SIMPLEX| 2339 IFF_LINK0|IFF_LINK1|IFF_LINK2); 2340 /* Linux' multicast flag is in a different bit */ 2341 if (flags & IFF_MULTICAST) { 2342 flags &= ~IFF_MULTICAST; 2343 flags |= 0x1000; 2344 } 2345 2346 return (copyout(&flags, &ifr->ifr_flags, sizeof(flags))); 2347 } 2348 2349 #define ARPHRD_ETHER 1 2350 #define ARPHRD_LOOPBACK 772 2351 2352 static int 2353 linux_gifhwaddr(struct ifnet *ifp, struct l_ifreq *ifr) 2354 { 2355 struct ifaddr *ifa; 2356 struct sockaddr_dl *sdl; 2357 struct l_sockaddr lsa; 2358 2359 if (ifp->if_type == IFT_LOOP) { 2360 bzero(&lsa, sizeof(lsa)); 2361 lsa.sa_family = ARPHRD_LOOPBACK; 2362 return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof(lsa))); 2363 } 2364 2365 if (ifp->if_type != IFT_ETHER) 2366 return (ENOENT); 2367 2368 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 2369 sdl = (struct sockaddr_dl*)ifa->ifa_addr; 2370 if (sdl != NULL && (sdl->sdl_family == AF_LINK) && 2371 (sdl->sdl_type == IFT_ETHER)) { 2372 bzero(&lsa, sizeof(lsa)); 2373 lsa.sa_family = ARPHRD_ETHER; 2374 bcopy(LLADDR(sdl), lsa.sa_data, LINUX_IFHWADDRLEN); 2375 return (copyout(&lsa, &ifr->ifr_hwaddr, sizeof(lsa))); 2376 } 2377 } 2378 2379 return (ENOENT); 2380 } 2381 2382 2383 /* 2384 * If we fault in bsd_to_linux_ifreq() then we will fault when we call 2385 * the native ioctl(). Thus, we don't really need to check the return 2386 * value of this function. 2387 */ 2388 static int 2389 bsd_to_linux_ifreq(struct ifreq *arg) 2390 { 2391 struct ifreq ifr; 2392 size_t ifr_len = sizeof(struct ifreq); 2393 int error; 2394 2395 if ((error = copyin(arg, &ifr, ifr_len))) 2396 return (error); 2397 2398 *(u_short *)&ifr.ifr_addr = ifr.ifr_addr.sa_family; 2399 2400 error = copyout(&ifr, arg, ifr_len); 2401 2402 return (error); 2403 } 2404 2405 /* 2406 * Socket related ioctls 2407 */ 2408 2409 static int 2410 linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args) 2411 { 2412 char lifname[LINUX_IFNAMSIZ], ifname[IFNAMSIZ]; 2413 cap_rights_t rights; 2414 struct ifnet *ifp; 2415 struct file *fp; 2416 int error, type; 2417 2418 ifp = NULL; 2419 error = 0; 2420 2421 error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); 2422 if (error != 0) 2423 return (error); 2424 type = fp->f_type; 2425 fdrop(fp, td); 2426 if (type != DTYPE_SOCKET) { 2427 /* not a socket - probably a tap / vmnet device */ 2428 switch (args->cmd) { 2429 case LINUX_SIOCGIFADDR: 2430 case LINUX_SIOCSIFADDR: 2431 case LINUX_SIOCGIFFLAGS: 2432 return (linux_ioctl_special(td, args)); 2433 default: 2434 return (ENOIOCTL); 2435 } 2436 } 2437 2438 switch (args->cmd & 0xffff) { 2439 2440 case LINUX_FIOGETOWN: 2441 case LINUX_FIOSETOWN: 2442 case LINUX_SIOCADDMULTI: 2443 case LINUX_SIOCATMARK: 2444 case LINUX_SIOCDELMULTI: 2445 case LINUX_SIOCGIFNAME: 2446 case LINUX_SIOCGIFCONF: 2447 case LINUX_SIOCGPGRP: 2448 case LINUX_SIOCSPGRP: 2449 case LINUX_SIOCGIFCOUNT: 2450 /* these ioctls don't take an interface name */ 2451 #ifdef DEBUG 2452 printf("%s(): ioctl %d\n", __func__, 2453 args->cmd & 0xffff); 2454 #endif 2455 break; 2456 2457 case LINUX_SIOCGIFFLAGS: 2458 case LINUX_SIOCGIFADDR: 2459 case LINUX_SIOCSIFADDR: 2460 case LINUX_SIOCGIFDSTADDR: 2461 case LINUX_SIOCGIFBRDADDR: 2462 case LINUX_SIOCGIFNETMASK: 2463 case LINUX_SIOCSIFNETMASK: 2464 case LINUX_SIOCGIFMTU: 2465 case LINUX_SIOCSIFMTU: 2466 case LINUX_SIOCSIFNAME: 2467 case LINUX_SIOCGIFHWADDR: 2468 case LINUX_SIOCSIFHWADDR: 2469 case LINUX_SIOCDEVPRIVATE: 2470 case LINUX_SIOCDEVPRIVATE+1: 2471 case LINUX_SIOCGIFINDEX: 2472 /* copy in the interface name and translate it. */ 2473 error = copyin((void *)args->arg, lifname, LINUX_IFNAMSIZ); 2474 if (error != 0) 2475 return (error); 2476 #ifdef DEBUG 2477 printf("%s(): ioctl %d on %.*s\n", __func__, 2478 args->cmd & 0xffff, LINUX_IFNAMSIZ, lifname); 2479 #endif 2480 ifp = ifname_linux_to_bsd(td, lifname, ifname); 2481 if (ifp == NULL) 2482 return (EINVAL); 2483 /* 2484 * We need to copy it back out in case we pass the 2485 * request on to our native ioctl(), which will expect 2486 * the ifreq to be in user space and have the correct 2487 * interface name. 2488 */ 2489 error = copyout(ifname, (void *)args->arg, IFNAMSIZ); 2490 if (error != 0) 2491 return (error); 2492 #ifdef DEBUG 2493 printf("%s(): %s translated to %s\n", __func__, 2494 lifname, ifname); 2495 #endif 2496 break; 2497 2498 default: 2499 return (ENOIOCTL); 2500 } 2501 2502 switch (args->cmd & 0xffff) { 2503 2504 case LINUX_FIOSETOWN: 2505 args->cmd = FIOSETOWN; 2506 error = sys_ioctl(td, (struct ioctl_args *)args); 2507 break; 2508 2509 case LINUX_SIOCSPGRP: 2510 args->cmd = SIOCSPGRP; 2511 error = sys_ioctl(td, (struct ioctl_args *)args); 2512 break; 2513 2514 case LINUX_FIOGETOWN: 2515 args->cmd = FIOGETOWN; 2516 error = sys_ioctl(td, (struct ioctl_args *)args); 2517 break; 2518 2519 case LINUX_SIOCGPGRP: 2520 args->cmd = SIOCGPGRP; 2521 error = sys_ioctl(td, (struct ioctl_args *)args); 2522 break; 2523 2524 case LINUX_SIOCATMARK: 2525 args->cmd = SIOCATMARK; 2526 error = sys_ioctl(td, (struct ioctl_args *)args); 2527 break; 2528 2529 /* LINUX_SIOCGSTAMP */ 2530 2531 case LINUX_SIOCGIFNAME: 2532 error = linux_ioctl_ifname(td, (struct l_ifreq *)args->arg); 2533 break; 2534 2535 case LINUX_SIOCGIFCONF: 2536 error = linux_ifconf(td, (struct ifconf *)args->arg); 2537 break; 2538 2539 case LINUX_SIOCGIFFLAGS: 2540 args->cmd = SIOCGIFFLAGS; 2541 error = linux_gifflags(td, ifp, (struct l_ifreq *)args->arg); 2542 break; 2543 2544 case LINUX_SIOCGIFADDR: 2545 args->cmd = SIOCGIFADDR; 2546 error = sys_ioctl(td, (struct ioctl_args *)args); 2547 bsd_to_linux_ifreq((struct ifreq *)args->arg); 2548 break; 2549 2550 case LINUX_SIOCSIFADDR: 2551 /* XXX probably doesn't work, included for completeness */ 2552 args->cmd = SIOCSIFADDR; 2553 error = sys_ioctl(td, (struct ioctl_args *)args); 2554 break; 2555 2556 case LINUX_SIOCGIFDSTADDR: 2557 args->cmd = SIOCGIFDSTADDR; 2558 error = sys_ioctl(td, (struct ioctl_args *)args); 2559 bsd_to_linux_ifreq((struct ifreq *)args->arg); 2560 break; 2561 2562 case LINUX_SIOCGIFBRDADDR: 2563 args->cmd = SIOCGIFBRDADDR; 2564 error = sys_ioctl(td, (struct ioctl_args *)args); 2565 bsd_to_linux_ifreq((struct ifreq *)args->arg); 2566 break; 2567 2568 case LINUX_SIOCGIFNETMASK: 2569 args->cmd = SIOCGIFNETMASK; 2570 error = sys_ioctl(td, (struct ioctl_args *)args); 2571 bsd_to_linux_ifreq((struct ifreq *)args->arg); 2572 break; 2573 2574 case LINUX_SIOCSIFNETMASK: 2575 error = ENOIOCTL; 2576 break; 2577 2578 case LINUX_SIOCGIFMTU: 2579 args->cmd = SIOCGIFMTU; 2580 error = sys_ioctl(td, (struct ioctl_args *)args); 2581 break; 2582 2583 case LINUX_SIOCSIFMTU: 2584 args->cmd = SIOCSIFMTU; 2585 error = sys_ioctl(td, (struct ioctl_args *)args); 2586 break; 2587 2588 case LINUX_SIOCSIFNAME: 2589 error = ENOIOCTL; 2590 break; 2591 2592 case LINUX_SIOCGIFHWADDR: 2593 error = linux_gifhwaddr(ifp, (struct l_ifreq *)args->arg); 2594 break; 2595 2596 case LINUX_SIOCSIFHWADDR: 2597 error = ENOIOCTL; 2598 break; 2599 2600 case LINUX_SIOCADDMULTI: 2601 args->cmd = SIOCADDMULTI; 2602 error = sys_ioctl(td, (struct ioctl_args *)args); 2603 break; 2604 2605 case LINUX_SIOCDELMULTI: 2606 args->cmd = SIOCDELMULTI; 2607 error = sys_ioctl(td, (struct ioctl_args *)args); 2608 break; 2609 2610 case LINUX_SIOCGIFINDEX: 2611 args->cmd = SIOCGIFINDEX; 2612 error = sys_ioctl(td, (struct ioctl_args *)args); 2613 break; 2614 2615 case LINUX_SIOCGIFCOUNT: 2616 error = 0; 2617 break; 2618 2619 /* 2620 * XXX This is slightly bogus, but these ioctls are currently 2621 * XXX only used by the aironet (if_an) network driver. 2622 */ 2623 case LINUX_SIOCDEVPRIVATE: 2624 args->cmd = SIOCGPRIVATE_0; 2625 error = sys_ioctl(td, (struct ioctl_args *)args); 2626 break; 2627 2628 case LINUX_SIOCDEVPRIVATE+1: 2629 args->cmd = SIOCGPRIVATE_1; 2630 error = sys_ioctl(td, (struct ioctl_args *)args); 2631 break; 2632 } 2633 2634 if (ifp != NULL) 2635 /* restore the original interface name */ 2636 copyout(lifname, (void *)args->arg, LINUX_IFNAMSIZ); 2637 2638 #ifdef DEBUG 2639 printf("%s(): returning %d\n", __func__, error); 2640 #endif 2641 return (error); 2642 } 2643 2644 /* 2645 * Device private ioctl handler 2646 */ 2647 static int 2648 linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args) 2649 { 2650 cap_rights_t rights; 2651 struct file *fp; 2652 int error, type; 2653 2654 error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); 2655 if (error != 0) 2656 return (error); 2657 type = fp->f_type; 2658 fdrop(fp, td); 2659 if (type == DTYPE_SOCKET) 2660 return (linux_ioctl_socket(td, args)); 2661 return (ENOIOCTL); 2662 } 2663 2664 /* 2665 * DRM ioctl handler (sys/dev/drm) 2666 */ 2667 static int 2668 linux_ioctl_drm(struct thread *td, struct linux_ioctl_args *args) 2669 { 2670 args->cmd = SETDIR(args->cmd); 2671 return sys_ioctl(td, (struct ioctl_args *)args); 2672 } 2673 2674 #ifdef COMPAT_LINUX32 2675 #define CP(src,dst,fld) do { (dst).fld = (src).fld; } while (0) 2676 #define PTRIN_CP(src,dst,fld) \ 2677 do { (dst).fld = PTRIN((src).fld); } while (0) 2678 #define PTROUT_CP(src,dst,fld) \ 2679 do { (dst).fld = PTROUT((src).fld); } while (0) 2680 2681 static int 2682 linux_ioctl_sg_io(struct thread *td, struct linux_ioctl_args *args) 2683 { 2684 struct sg_io_hdr io; 2685 struct sg_io_hdr32 io32; 2686 cap_rights_t rights; 2687 struct file *fp; 2688 int error; 2689 2690 error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); 2691 if (error != 0) { 2692 printf("sg_linux_ioctl: fget returned %d\n", error); 2693 return (error); 2694 } 2695 2696 if ((error = copyin((void *)args->arg, &io32, sizeof(io32))) != 0) 2697 goto out; 2698 2699 CP(io32, io, interface_id); 2700 CP(io32, io, dxfer_direction); 2701 CP(io32, io, cmd_len); 2702 CP(io32, io, mx_sb_len); 2703 CP(io32, io, iovec_count); 2704 CP(io32, io, dxfer_len); 2705 PTRIN_CP(io32, io, dxferp); 2706 PTRIN_CP(io32, io, cmdp); 2707 PTRIN_CP(io32, io, sbp); 2708 CP(io32, io, timeout); 2709 CP(io32, io, flags); 2710 CP(io32, io, pack_id); 2711 PTRIN_CP(io32, io, usr_ptr); 2712 CP(io32, io, status); 2713 CP(io32, io, masked_status); 2714 CP(io32, io, msg_status); 2715 CP(io32, io, sb_len_wr); 2716 CP(io32, io, host_status); 2717 CP(io32, io, driver_status); 2718 CP(io32, io, resid); 2719 CP(io32, io, duration); 2720 CP(io32, io, info); 2721 2722 if ((error = fo_ioctl(fp, SG_IO, (caddr_t)&io, td->td_ucred, td)) != 0) 2723 goto out; 2724 2725 CP(io, io32, interface_id); 2726 CP(io, io32, dxfer_direction); 2727 CP(io, io32, cmd_len); 2728 CP(io, io32, mx_sb_len); 2729 CP(io, io32, iovec_count); 2730 CP(io, io32, dxfer_len); 2731 PTROUT_CP(io, io32, dxferp); 2732 PTROUT_CP(io, io32, cmdp); 2733 PTROUT_CP(io, io32, sbp); 2734 CP(io, io32, timeout); 2735 CP(io, io32, flags); 2736 CP(io, io32, pack_id); 2737 PTROUT_CP(io, io32, usr_ptr); 2738 CP(io, io32, status); 2739 CP(io, io32, masked_status); 2740 CP(io, io32, msg_status); 2741 CP(io, io32, sb_len_wr); 2742 CP(io, io32, host_status); 2743 CP(io, io32, driver_status); 2744 CP(io, io32, resid); 2745 CP(io, io32, duration); 2746 CP(io, io32, info); 2747 2748 error = copyout(&io32, (void *)args->arg, sizeof(io32)); 2749 2750 out: 2751 fdrop(fp, td); 2752 return (error); 2753 } 2754 #endif 2755 2756 static int 2757 linux_ioctl_sg(struct thread *td, struct linux_ioctl_args *args) 2758 { 2759 2760 switch (args->cmd) { 2761 case LINUX_SG_GET_VERSION_NUM: 2762 args->cmd = SG_GET_VERSION_NUM; 2763 break; 2764 case LINUX_SG_SET_TIMEOUT: 2765 args->cmd = SG_SET_TIMEOUT; 2766 break; 2767 case LINUX_SG_GET_TIMEOUT: 2768 args->cmd = SG_GET_TIMEOUT; 2769 break; 2770 case LINUX_SG_IO: 2771 args->cmd = SG_IO; 2772 #ifdef COMPAT_LINUX32 2773 return (linux_ioctl_sg_io(td, args)); 2774 #endif 2775 break; 2776 case LINUX_SG_GET_RESERVED_SIZE: 2777 args->cmd = SG_GET_RESERVED_SIZE; 2778 break; 2779 case LINUX_SG_GET_SCSI_ID: 2780 args->cmd = SG_GET_SCSI_ID; 2781 break; 2782 case LINUX_SG_GET_SG_TABLESIZE: 2783 args->cmd = SG_GET_SG_TABLESIZE; 2784 break; 2785 default: 2786 return (ENODEV); 2787 } 2788 return (sys_ioctl(td, (struct ioctl_args *)args)); 2789 } 2790 2791 /* 2792 * Video4Linux (V4L) ioctl handler 2793 */ 2794 static int 2795 linux_to_bsd_v4l_tuner(struct l_video_tuner *lvt, struct video_tuner *vt) 2796 { 2797 vt->tuner = lvt->tuner; 2798 strlcpy(vt->name, lvt->name, LINUX_VIDEO_TUNER_NAME_SIZE); 2799 vt->rangelow = lvt->rangelow; /* possible long size conversion */ 2800 vt->rangehigh = lvt->rangehigh; /* possible long size conversion */ 2801 vt->flags = lvt->flags; 2802 vt->mode = lvt->mode; 2803 vt->signal = lvt->signal; 2804 return (0); 2805 } 2806 2807 static int 2808 bsd_to_linux_v4l_tuner(struct video_tuner *vt, struct l_video_tuner *lvt) 2809 { 2810 lvt->tuner = vt->tuner; 2811 strlcpy(lvt->name, vt->name, LINUX_VIDEO_TUNER_NAME_SIZE); 2812 lvt->rangelow = vt->rangelow; /* possible long size conversion */ 2813 lvt->rangehigh = vt->rangehigh; /* possible long size conversion */ 2814 lvt->flags = vt->flags; 2815 lvt->mode = vt->mode; 2816 lvt->signal = vt->signal; 2817 return (0); 2818 } 2819 2820 #ifdef COMPAT_LINUX_V4L_CLIPLIST 2821 static int 2822 linux_to_bsd_v4l_clip(struct l_video_clip *lvc, struct video_clip *vc) 2823 { 2824 vc->x = lvc->x; 2825 vc->y = lvc->y; 2826 vc->width = lvc->width; 2827 vc->height = lvc->height; 2828 vc->next = PTRIN(lvc->next); /* possible pointer size conversion */ 2829 return (0); 2830 } 2831 #endif 2832 2833 static int 2834 linux_to_bsd_v4l_window(struct l_video_window *lvw, struct video_window *vw) 2835 { 2836 vw->x = lvw->x; 2837 vw->y = lvw->y; 2838 vw->width = lvw->width; 2839 vw->height = lvw->height; 2840 vw->chromakey = lvw->chromakey; 2841 vw->flags = lvw->flags; 2842 vw->clips = PTRIN(lvw->clips); /* possible pointer size conversion */ 2843 vw->clipcount = lvw->clipcount; 2844 return (0); 2845 } 2846 2847 static int 2848 bsd_to_linux_v4l_window(struct video_window *vw, struct l_video_window *lvw) 2849 { 2850 lvw->x = vw->x; 2851 lvw->y = vw->y; 2852 lvw->width = vw->width; 2853 lvw->height = vw->height; 2854 lvw->chromakey = vw->chromakey; 2855 lvw->flags = vw->flags; 2856 lvw->clips = PTROUT(vw->clips); /* possible pointer size conversion */ 2857 lvw->clipcount = vw->clipcount; 2858 return (0); 2859 } 2860 2861 static int 2862 linux_to_bsd_v4l_buffer(struct l_video_buffer *lvb, struct video_buffer *vb) 2863 { 2864 vb->base = PTRIN(lvb->base); /* possible pointer size conversion */ 2865 vb->height = lvb->height; 2866 vb->width = lvb->width; 2867 vb->depth = lvb->depth; 2868 vb->bytesperline = lvb->bytesperline; 2869 return (0); 2870 } 2871 2872 static int 2873 bsd_to_linux_v4l_buffer(struct video_buffer *vb, struct l_video_buffer *lvb) 2874 { 2875 lvb->base = PTROUT(vb->base); /* possible pointer size conversion */ 2876 lvb->height = vb->height; 2877 lvb->width = vb->width; 2878 lvb->depth = vb->depth; 2879 lvb->bytesperline = vb->bytesperline; 2880 return (0); 2881 } 2882 2883 static int 2884 linux_to_bsd_v4l_code(struct l_video_code *lvc, struct video_code *vc) 2885 { 2886 strlcpy(vc->loadwhat, lvc->loadwhat, LINUX_VIDEO_CODE_LOADWHAT_SIZE); 2887 vc->datasize = lvc->datasize; 2888 vc->data = PTRIN(lvc->data); /* possible pointer size conversion */ 2889 return (0); 2890 } 2891 2892 #ifdef COMPAT_LINUX_V4L_CLIPLIST 2893 static int 2894 linux_v4l_clip_copy(void *lvc, struct video_clip **ppvc) 2895 { 2896 int error; 2897 struct video_clip vclip; 2898 struct l_video_clip l_vclip; 2899 2900 error = copyin(lvc, &l_vclip, sizeof(l_vclip)); 2901 if (error) return (error); 2902 linux_to_bsd_v4l_clip(&l_vclip, &vclip); 2903 /* XXX: If there can be no concurrency: s/M_NOWAIT/M_WAITOK/ */ 2904 if ((*ppvc = malloc(sizeof(**ppvc), M_LINUX, M_NOWAIT)) == NULL) 2905 return (ENOMEM); /* XXX: linux has no ENOMEM here */ 2906 memcpy(*ppvc, &vclip, sizeof(vclip)); 2907 (*ppvc)->next = NULL; 2908 return (0); 2909 } 2910 2911 static int 2912 linux_v4l_cliplist_free(struct video_window *vw) 2913 { 2914 struct video_clip **ppvc; 2915 struct video_clip **ppvc_next; 2916 2917 for (ppvc = &(vw->clips); *ppvc != NULL; ppvc = ppvc_next) { 2918 ppvc_next = &((*ppvc)->next); 2919 free(*ppvc, M_LINUX); 2920 } 2921 vw->clips = NULL; 2922 2923 return (0); 2924 } 2925 2926 static int 2927 linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw) 2928 { 2929 int error; 2930 int clipcount; 2931 void *plvc; 2932 struct video_clip **ppvc; 2933 2934 /* 2935 * XXX: The cliplist is used to pass in a list of clipping 2936 * rectangles or, if clipcount == VIDEO_CLIP_BITMAP, a 2937 * clipping bitmap. Some Linux apps, however, appear to 2938 * leave cliplist and clips uninitialized. In any case, 2939 * the cliplist is not used by pwc(4), at the time of 2940 * writing, FreeBSD's only V4L driver. When a driver 2941 * that uses the cliplist is developed, this code may 2942 * need re-examiniation. 2943 */ 2944 error = 0; 2945 clipcount = vw->clipcount; 2946 if (clipcount == VIDEO_CLIP_BITMAP) { 2947 /* 2948 * In this case, the pointer (clips) is overloaded 2949 * to be a "void *" to a bitmap, therefore there 2950 * is no struct video_clip to copy now. 2951 */ 2952 } else if (clipcount > 0 && clipcount <= 16384) { 2953 /* 2954 * Clips points to list of clip rectangles, so 2955 * copy the list. 2956 * 2957 * XXX: Upper limit of 16384 was used here to try to 2958 * avoid cases when clipcount and clips pointer 2959 * are uninitialized and therefore have high random 2960 * values, as is the case in the Linux Skype 2961 * application. The value 16384 was chosen as that 2962 * is what is used in the Linux stradis(4) MPEG 2963 * decoder driver, the only place we found an 2964 * example of cliplist use. 2965 */ 2966 plvc = PTRIN(lvw->clips); 2967 vw->clips = NULL; 2968 ppvc = &(vw->clips); 2969 while (clipcount-- > 0) { 2970 if (plvc == NULL) { 2971 error = EFAULT; 2972 break; 2973 } else { 2974 error = linux_v4l_clip_copy(plvc, ppvc); 2975 if (error) { 2976 linux_v4l_cliplist_free(vw); 2977 break; 2978 } 2979 } 2980 ppvc = &((*ppvc)->next); 2981 plvc = PTRIN(((struct l_video_clip *) plvc)->next); 2982 } 2983 } else { 2984 /* 2985 * clipcount == 0 or negative (but not VIDEO_CLIP_BITMAP) 2986 * Force cliplist to null. 2987 */ 2988 vw->clipcount = 0; 2989 vw->clips = NULL; 2990 } 2991 return (error); 2992 } 2993 #endif 2994 2995 static int 2996 linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) 2997 { 2998 cap_rights_t rights; 2999 struct file *fp; 3000 int error; 3001 struct video_tuner vtun; 3002 struct video_window vwin; 3003 struct video_buffer vbuf; 3004 struct video_code vcode; 3005 struct l_video_tuner l_vtun; 3006 struct l_video_window l_vwin; 3007 struct l_video_buffer l_vbuf; 3008 struct l_video_code l_vcode; 3009 3010 switch (args->cmd & 0xffff) { 3011 case LINUX_VIDIOCGCAP: args->cmd = VIDIOCGCAP; break; 3012 case LINUX_VIDIOCGCHAN: args->cmd = VIDIOCGCHAN; break; 3013 case LINUX_VIDIOCSCHAN: args->cmd = VIDIOCSCHAN; break; 3014 3015 case LINUX_VIDIOCGTUNER: 3016 error = fget(td, args->fd, 3017 cap_rights_init(&rights, CAP_IOCTL), &fp); 3018 if (error != 0) 3019 return (error); 3020 error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun)); 3021 if (error) { 3022 fdrop(fp, td); 3023 return (error); 3024 } 3025 linux_to_bsd_v4l_tuner(&l_vtun, &vtun); 3026 error = fo_ioctl(fp, VIDIOCGTUNER, &vtun, td->td_ucred, td); 3027 if (!error) { 3028 bsd_to_linux_v4l_tuner(&vtun, &l_vtun); 3029 error = copyout(&l_vtun, (void *) args->arg, 3030 sizeof(l_vtun)); 3031 } 3032 fdrop(fp, td); 3033 return (error); 3034 3035 case LINUX_VIDIOCSTUNER: 3036 error = fget(td, args->fd, 3037 cap_rights_init(&rights, CAP_IOCTL), &fp); 3038 if (error != 0) 3039 return (error); 3040 error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun)); 3041 if (error) { 3042 fdrop(fp, td); 3043 return (error); 3044 } 3045 linux_to_bsd_v4l_tuner(&l_vtun, &vtun); 3046 error = fo_ioctl(fp, VIDIOCSTUNER, &vtun, td->td_ucred, td); 3047 fdrop(fp, td); 3048 return (error); 3049 3050 case LINUX_VIDIOCGPICT: args->cmd = VIDIOCGPICT; break; 3051 case LINUX_VIDIOCSPICT: args->cmd = VIDIOCSPICT; break; 3052 case LINUX_VIDIOCCAPTURE: args->cmd = VIDIOCCAPTURE; break; 3053 3054 case LINUX_VIDIOCGWIN: 3055 error = fget(td, args->fd, 3056 cap_rights_init(&rights, CAP_IOCTL), &fp); 3057 if (error != 0) 3058 return (error); 3059 error = fo_ioctl(fp, VIDIOCGWIN, &vwin, td->td_ucred, td); 3060 if (!error) { 3061 bsd_to_linux_v4l_window(&vwin, &l_vwin); 3062 error = copyout(&l_vwin, (void *) args->arg, 3063 sizeof(l_vwin)); 3064 } 3065 fdrop(fp, td); 3066 return (error); 3067 3068 case LINUX_VIDIOCSWIN: 3069 error = fget(td, args->fd, 3070 cap_rights_init(&rights, CAP_IOCTL), &fp); 3071 if (error != 0) 3072 return (error); 3073 error = copyin((void *) args->arg, &l_vwin, sizeof(l_vwin)); 3074 if (error) { 3075 fdrop(fp, td); 3076 return (error); 3077 } 3078 linux_to_bsd_v4l_window(&l_vwin, &vwin); 3079 #ifdef COMPAT_LINUX_V4L_CLIPLIST 3080 error = linux_v4l_cliplist_copy(&l_vwin, &vwin); 3081 if (error) { 3082 fdrop(fp, td); 3083 return (error); 3084 } 3085 #endif 3086 error = fo_ioctl(fp, VIDIOCSWIN, &vwin, td->td_ucred, td); 3087 fdrop(fp, td); 3088 #ifdef COMPAT_LINUX_V4L_CLIPLIST 3089 linux_v4l_cliplist_free(&vwin); 3090 #endif 3091 return (error); 3092 3093 case LINUX_VIDIOCGFBUF: 3094 error = fget(td, args->fd, 3095 cap_rights_init(&rights, CAP_IOCTL), &fp); 3096 if (error != 0) 3097 return (error); 3098 error = fo_ioctl(fp, VIDIOCGFBUF, &vbuf, td->td_ucred, td); 3099 if (!error) { 3100 bsd_to_linux_v4l_buffer(&vbuf, &l_vbuf); 3101 error = copyout(&l_vbuf, (void *) args->arg, 3102 sizeof(l_vbuf)); 3103 } 3104 fdrop(fp, td); 3105 return (error); 3106 3107 case LINUX_VIDIOCSFBUF: 3108 error = fget(td, args->fd, 3109 cap_rights_init(&rights, CAP_IOCTL), &fp); 3110 if (error != 0) 3111 return (error); 3112 error = copyin((void *) args->arg, &l_vbuf, sizeof(l_vbuf)); 3113 if (error) { 3114 fdrop(fp, td); 3115 return (error); 3116 } 3117 linux_to_bsd_v4l_buffer(&l_vbuf, &vbuf); 3118 error = fo_ioctl(fp, VIDIOCSFBUF, &vbuf, td->td_ucred, td); 3119 fdrop(fp, td); 3120 return (error); 3121 3122 case LINUX_VIDIOCKEY: args->cmd = VIDIOCKEY; break; 3123 case LINUX_VIDIOCGFREQ: args->cmd = VIDIOCGFREQ; break; 3124 case LINUX_VIDIOCSFREQ: args->cmd = VIDIOCSFREQ; break; 3125 case LINUX_VIDIOCGAUDIO: args->cmd = VIDIOCGAUDIO; break; 3126 case LINUX_VIDIOCSAUDIO: args->cmd = VIDIOCSAUDIO; break; 3127 case LINUX_VIDIOCSYNC: args->cmd = VIDIOCSYNC; break; 3128 case LINUX_VIDIOCMCAPTURE: args->cmd = VIDIOCMCAPTURE; break; 3129 case LINUX_VIDIOCGMBUF: args->cmd = VIDIOCGMBUF; break; 3130 case LINUX_VIDIOCGUNIT: args->cmd = VIDIOCGUNIT; break; 3131 case LINUX_VIDIOCGCAPTURE: args->cmd = VIDIOCGCAPTURE; break; 3132 case LINUX_VIDIOCSCAPTURE: args->cmd = VIDIOCSCAPTURE; break; 3133 case LINUX_VIDIOCSPLAYMODE: args->cmd = VIDIOCSPLAYMODE; break; 3134 case LINUX_VIDIOCSWRITEMODE: args->cmd = VIDIOCSWRITEMODE; break; 3135 case LINUX_VIDIOCGPLAYINFO: args->cmd = VIDIOCGPLAYINFO; break; 3136 3137 case LINUX_VIDIOCSMICROCODE: 3138 error = fget(td, args->fd, 3139 cap_rights_init(&rights, CAP_IOCTL), &fp); 3140 if (error != 0) 3141 return (error); 3142 error = copyin((void *) args->arg, &l_vcode, sizeof(l_vcode)); 3143 if (error) { 3144 fdrop(fp, td); 3145 return (error); 3146 } 3147 linux_to_bsd_v4l_code(&l_vcode, &vcode); 3148 error = fo_ioctl(fp, VIDIOCSMICROCODE, &vcode, td->td_ucred, td); 3149 fdrop(fp, td); 3150 return (error); 3151 3152 case LINUX_VIDIOCGVBIFMT: args->cmd = VIDIOCGVBIFMT; break; 3153 case LINUX_VIDIOCSVBIFMT: args->cmd = VIDIOCSVBIFMT; break; 3154 default: return (ENOIOCTL); 3155 } 3156 3157 error = sys_ioctl(td, (struct ioctl_args *)args); 3158 return (error); 3159 } 3160 3161 /* 3162 * Special ioctl handler 3163 */ 3164 static int 3165 linux_ioctl_special(struct thread *td, struct linux_ioctl_args *args) 3166 { 3167 int error; 3168 3169 switch (args->cmd) { 3170 case LINUX_SIOCGIFADDR: 3171 args->cmd = SIOCGIFADDR; 3172 error = sys_ioctl(td, (struct ioctl_args *)args); 3173 break; 3174 case LINUX_SIOCSIFADDR: 3175 args->cmd = SIOCSIFADDR; 3176 error = sys_ioctl(td, (struct ioctl_args *)args); 3177 break; 3178 case LINUX_SIOCGIFFLAGS: 3179 args->cmd = SIOCGIFFLAGS; 3180 error = sys_ioctl(td, (struct ioctl_args *)args); 3181 break; 3182 default: 3183 error = ENOIOCTL; 3184 } 3185 3186 return (error); 3187 } 3188 3189 static int 3190 linux_to_bsd_v4l2_standard(struct l_v4l2_standard *lvstd, struct v4l2_standard *vstd) 3191 { 3192 vstd->index = lvstd->index; 3193 vstd->id = lvstd->id; 3194 CTASSERT(sizeof(vstd->name) == sizeof(lvstd->name)); 3195 memcpy(vstd->name, lvstd->name, sizeof(vstd->name)); 3196 vstd->frameperiod = lvstd->frameperiod; 3197 vstd->framelines = lvstd->framelines; 3198 CTASSERT(sizeof(vstd->reserved) == sizeof(lvstd->reserved)); 3199 memcpy(vstd->reserved, lvstd->reserved, sizeof(vstd->reserved)); 3200 return (0); 3201 } 3202 3203 static int 3204 bsd_to_linux_v4l2_standard(struct v4l2_standard *vstd, struct l_v4l2_standard *lvstd) 3205 { 3206 lvstd->index = vstd->index; 3207 lvstd->id = vstd->id; 3208 CTASSERT(sizeof(vstd->name) == sizeof(lvstd->name)); 3209 memcpy(lvstd->name, vstd->name, sizeof(lvstd->name)); 3210 lvstd->frameperiod = vstd->frameperiod; 3211 lvstd->framelines = vstd->framelines; 3212 CTASSERT(sizeof(vstd->reserved) == sizeof(lvstd->reserved)); 3213 memcpy(lvstd->reserved, vstd->reserved, sizeof(lvstd->reserved)); 3214 return (0); 3215 } 3216 3217 static int 3218 linux_to_bsd_v4l2_buffer(struct l_v4l2_buffer *lvb, struct v4l2_buffer *vb) 3219 { 3220 vb->index = lvb->index; 3221 vb->type = lvb->type; 3222 vb->bytesused = lvb->bytesused; 3223 vb->flags = lvb->flags; 3224 vb->field = lvb->field; 3225 vb->timestamp.tv_sec = lvb->timestamp.tv_sec; 3226 vb->timestamp.tv_usec = lvb->timestamp.tv_usec; 3227 memcpy(&vb->timecode, &lvb->timecode, sizeof (lvb->timecode)); 3228 vb->sequence = lvb->sequence; 3229 vb->memory = lvb->memory; 3230 if (lvb->memory == V4L2_MEMORY_USERPTR) 3231 /* possible pointer size conversion */ 3232 vb->m.userptr = (unsigned long)PTRIN(lvb->m.userptr); 3233 else 3234 vb->m.offset = lvb->m.offset; 3235 vb->length = lvb->length; 3236 vb->input = lvb->input; 3237 vb->reserved = lvb->reserved; 3238 return (0); 3239 } 3240 3241 static int 3242 bsd_to_linux_v4l2_buffer(struct v4l2_buffer *vb, struct l_v4l2_buffer *lvb) 3243 { 3244 lvb->index = vb->index; 3245 lvb->type = vb->type; 3246 lvb->bytesused = vb->bytesused; 3247 lvb->flags = vb->flags; 3248 lvb->field = vb->field; 3249 lvb->timestamp.tv_sec = vb->timestamp.tv_sec; 3250 lvb->timestamp.tv_usec = vb->timestamp.tv_usec; 3251 memcpy(&lvb->timecode, &vb->timecode, sizeof (vb->timecode)); 3252 lvb->sequence = vb->sequence; 3253 lvb->memory = vb->memory; 3254 if (vb->memory == V4L2_MEMORY_USERPTR) 3255 /* possible pointer size conversion */ 3256 lvb->m.userptr = PTROUT(vb->m.userptr); 3257 else 3258 lvb->m.offset = vb->m.offset; 3259 lvb->length = vb->length; 3260 lvb->input = vb->input; 3261 lvb->reserved = vb->reserved; 3262 return (0); 3263 } 3264 3265 static int 3266 linux_to_bsd_v4l2_format(struct l_v4l2_format *lvf, struct v4l2_format *vf) 3267 { 3268 vf->type = lvf->type; 3269 if (lvf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY 3270 #ifdef V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY 3271 || lvf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY 3272 #endif 3273 ) 3274 /* 3275 * XXX TODO - needs 32 -> 64 bit conversion: 3276 * (unused by webcams?) 3277 */ 3278 return EINVAL; 3279 memcpy(&vf->fmt, &lvf->fmt, sizeof(vf->fmt)); 3280 return 0; 3281 } 3282 3283 static int 3284 bsd_to_linux_v4l2_format(struct v4l2_format *vf, struct l_v4l2_format *lvf) 3285 { 3286 lvf->type = vf->type; 3287 if (vf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY 3288 #ifdef V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY 3289 || vf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY 3290 #endif 3291 ) 3292 /* 3293 * XXX TODO - needs 32 -> 64 bit conversion: 3294 * (unused by webcams?) 3295 */ 3296 return EINVAL; 3297 memcpy(&lvf->fmt, &vf->fmt, sizeof(vf->fmt)); 3298 return 0; 3299 } 3300 static int 3301 linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args) 3302 { 3303 cap_rights_t rights; 3304 struct file *fp; 3305 int error; 3306 struct v4l2_format vformat; 3307 struct l_v4l2_format l_vformat; 3308 struct v4l2_standard vstd; 3309 struct l_v4l2_standard l_vstd; 3310 struct l_v4l2_buffer l_vbuf; 3311 struct v4l2_buffer vbuf; 3312 struct v4l2_input vinp; 3313 3314 switch (args->cmd & 0xffff) { 3315 case LINUX_VIDIOC_RESERVED: 3316 case LINUX_VIDIOC_LOG_STATUS: 3317 if ((args->cmd & IOC_DIRMASK) != LINUX_IOC_VOID) 3318 return ENOIOCTL; 3319 args->cmd = (args->cmd & 0xffff) | IOC_VOID; 3320 break; 3321 3322 case LINUX_VIDIOC_OVERLAY: 3323 case LINUX_VIDIOC_STREAMON: 3324 case LINUX_VIDIOC_STREAMOFF: 3325 case LINUX_VIDIOC_S_STD: 3326 case LINUX_VIDIOC_S_TUNER: 3327 case LINUX_VIDIOC_S_AUDIO: 3328 case LINUX_VIDIOC_S_AUDOUT: 3329 case LINUX_VIDIOC_S_MODULATOR: 3330 case LINUX_VIDIOC_S_FREQUENCY: 3331 case LINUX_VIDIOC_S_CROP: 3332 case LINUX_VIDIOC_S_JPEGCOMP: 3333 case LINUX_VIDIOC_S_PRIORITY: 3334 case LINUX_VIDIOC_DBG_S_REGISTER: 3335 case LINUX_VIDIOC_S_HW_FREQ_SEEK: 3336 case LINUX_VIDIOC_SUBSCRIBE_EVENT: 3337 case LINUX_VIDIOC_UNSUBSCRIBE_EVENT: 3338 args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_IN; 3339 break; 3340 3341 case LINUX_VIDIOC_QUERYCAP: 3342 case LINUX_VIDIOC_G_STD: 3343 case LINUX_VIDIOC_G_AUDIO: 3344 case LINUX_VIDIOC_G_INPUT: 3345 case LINUX_VIDIOC_G_OUTPUT: 3346 case LINUX_VIDIOC_G_AUDOUT: 3347 case LINUX_VIDIOC_G_JPEGCOMP: 3348 case LINUX_VIDIOC_QUERYSTD: 3349 case LINUX_VIDIOC_G_PRIORITY: 3350 case LINUX_VIDIOC_QUERY_DV_PRESET: 3351 args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_OUT; 3352 break; 3353 3354 case LINUX_VIDIOC_ENUM_FMT: 3355 case LINUX_VIDIOC_REQBUFS: 3356 case LINUX_VIDIOC_G_PARM: 3357 case LINUX_VIDIOC_S_PARM: 3358 case LINUX_VIDIOC_G_CTRL: 3359 case LINUX_VIDIOC_S_CTRL: 3360 case LINUX_VIDIOC_G_TUNER: 3361 case LINUX_VIDIOC_QUERYCTRL: 3362 case LINUX_VIDIOC_QUERYMENU: 3363 case LINUX_VIDIOC_S_INPUT: 3364 case LINUX_VIDIOC_S_OUTPUT: 3365 case LINUX_VIDIOC_ENUMOUTPUT: 3366 case LINUX_VIDIOC_G_MODULATOR: 3367 case LINUX_VIDIOC_G_FREQUENCY: 3368 case LINUX_VIDIOC_CROPCAP: 3369 case LINUX_VIDIOC_G_CROP: 3370 case LINUX_VIDIOC_ENUMAUDIO: 3371 case LINUX_VIDIOC_ENUMAUDOUT: 3372 case LINUX_VIDIOC_G_SLICED_VBI_CAP: 3373 #ifdef VIDIOC_ENUM_FRAMESIZES 3374 case LINUX_VIDIOC_ENUM_FRAMESIZES: 3375 case LINUX_VIDIOC_ENUM_FRAMEINTERVALS: 3376 case LINUX_VIDIOC_ENCODER_CMD: 3377 case LINUX_VIDIOC_TRY_ENCODER_CMD: 3378 #endif 3379 case LINUX_VIDIOC_DBG_G_REGISTER: 3380 case LINUX_VIDIOC_DBG_G_CHIP_IDENT: 3381 case LINUX_VIDIOC_ENUM_DV_PRESETS: 3382 case LINUX_VIDIOC_S_DV_PRESET: 3383 case LINUX_VIDIOC_G_DV_PRESET: 3384 case LINUX_VIDIOC_S_DV_TIMINGS: 3385 case LINUX_VIDIOC_G_DV_TIMINGS: 3386 args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_INOUT; 3387 break; 3388 3389 case LINUX_VIDIOC_G_FMT: 3390 case LINUX_VIDIOC_S_FMT: 3391 case LINUX_VIDIOC_TRY_FMT: 3392 error = copyin((void *)args->arg, &l_vformat, sizeof(l_vformat)); 3393 if (error) 3394 return (error); 3395 error = fget(td, args->fd, 3396 cap_rights_init(&rights, CAP_IOCTL), &fp); 3397 if (error) 3398 return (error); 3399 if (linux_to_bsd_v4l2_format(&l_vformat, &vformat) != 0) 3400 error = EINVAL; 3401 else if ((args->cmd & 0xffff) == LINUX_VIDIOC_G_FMT) 3402 error = fo_ioctl(fp, VIDIOC_G_FMT, &vformat, 3403 td->td_ucred, td); 3404 else if ((args->cmd & 0xffff) == LINUX_VIDIOC_S_FMT) 3405 error = fo_ioctl(fp, VIDIOC_S_FMT, &vformat, 3406 td->td_ucred, td); 3407 else 3408 error = fo_ioctl(fp, VIDIOC_TRY_FMT, &vformat, 3409 td->td_ucred, td); 3410 bsd_to_linux_v4l2_format(&vformat, &l_vformat); 3411 copyout(&l_vformat, (void *)args->arg, sizeof(l_vformat)); 3412 fdrop(fp, td); 3413 return (error); 3414 3415 case LINUX_VIDIOC_ENUMSTD: 3416 error = copyin((void *)args->arg, &l_vstd, sizeof(l_vstd)); 3417 if (error) 3418 return (error); 3419 linux_to_bsd_v4l2_standard(&l_vstd, &vstd); 3420 error = fget(td, args->fd, 3421 cap_rights_init(&rights, CAP_IOCTL), &fp); 3422 if (error) 3423 return (error); 3424 error = fo_ioctl(fp, VIDIOC_ENUMSTD, (caddr_t)&vstd, 3425 td->td_ucred, td); 3426 if (error) { 3427 fdrop(fp, td); 3428 return (error); 3429 } 3430 bsd_to_linux_v4l2_standard(&vstd, &l_vstd); 3431 error = copyout(&l_vstd, (void *)args->arg, sizeof(l_vstd)); 3432 fdrop(fp, td); 3433 return (error); 3434 3435 case LINUX_VIDIOC_ENUMINPUT: 3436 /* 3437 * The Linux struct l_v4l2_input differs only in size, 3438 * it has no padding at the end. 3439 */ 3440 error = copyin((void *)args->arg, &vinp, 3441 sizeof(struct l_v4l2_input)); 3442 if (error != 0) 3443 return (error); 3444 error = fget(td, args->fd, 3445 cap_rights_init(&rights, CAP_IOCTL), &fp); 3446 if (error != 0) 3447 return (error); 3448 error = fo_ioctl(fp, VIDIOC_ENUMINPUT, (caddr_t)&vinp, 3449 td->td_ucred, td); 3450 if (error) { 3451 fdrop(fp, td); 3452 return (error); 3453 } 3454 error = copyout(&vinp, (void *)args->arg, 3455 sizeof(struct l_v4l2_input)); 3456 fdrop(fp, td); 3457 return (error); 3458 3459 case LINUX_VIDIOC_QUERYBUF: 3460 case LINUX_VIDIOC_QBUF: 3461 case LINUX_VIDIOC_DQBUF: 3462 error = copyin((void *)args->arg, &l_vbuf, sizeof(l_vbuf)); 3463 if (error) 3464 return (error); 3465 error = fget(td, args->fd, 3466 cap_rights_init(&rights, CAP_IOCTL), &fp); 3467 if (error) 3468 return (error); 3469 linux_to_bsd_v4l2_buffer(&l_vbuf, &vbuf); 3470 if ((args->cmd & 0xffff) == LINUX_VIDIOC_QUERYBUF) 3471 error = fo_ioctl(fp, VIDIOC_QUERYBUF, &vbuf, 3472 td->td_ucred, td); 3473 else if ((args->cmd & 0xffff) == LINUX_VIDIOC_QBUF) 3474 error = fo_ioctl(fp, VIDIOC_QBUF, &vbuf, 3475 td->td_ucred, td); 3476 else 3477 error = fo_ioctl(fp, VIDIOC_DQBUF, &vbuf, 3478 td->td_ucred, td); 3479 bsd_to_linux_v4l2_buffer(&vbuf, &l_vbuf); 3480 copyout(&l_vbuf, (void *)args->arg, sizeof(l_vbuf)); 3481 fdrop(fp, td); 3482 return (error); 3483 3484 /* 3485 * XXX TODO - these need 32 -> 64 bit conversion: 3486 * (are any of them needed for webcams?) 3487 */ 3488 case LINUX_VIDIOC_G_FBUF: 3489 case LINUX_VIDIOC_S_FBUF: 3490 3491 case LINUX_VIDIOC_G_EXT_CTRLS: 3492 case LINUX_VIDIOC_S_EXT_CTRLS: 3493 case LINUX_VIDIOC_TRY_EXT_CTRLS: 3494 3495 case LINUX_VIDIOC_DQEVENT: 3496 3497 default: return (ENOIOCTL); 3498 } 3499 3500 error = sys_ioctl(td, (struct ioctl_args *)args); 3501 return (error); 3502 } 3503 3504 /* 3505 * Support for emulators/linux-libusb. This port uses FBSD_LUSB* macros 3506 * instead of USB* ones. This lets us to provide correct values for cmd. 3507 * 0xffffffe0 -- 0xffffffff range seemed to be the least collision-prone. 3508 */ 3509 static int 3510 linux_ioctl_fbsd_usb(struct thread *td, struct linux_ioctl_args *args) 3511 { 3512 int error; 3513 3514 error = 0; 3515 switch (args->cmd) { 3516 case FBSD_LUSB_DEVICEENUMERATE: 3517 args->cmd = USB_DEVICEENUMERATE; 3518 break; 3519 case FBSD_LUSB_DEV_QUIRK_ADD: 3520 args->cmd = USB_DEV_QUIRK_ADD; 3521 break; 3522 case FBSD_LUSB_DEV_QUIRK_GET: 3523 args->cmd = USB_DEV_QUIRK_GET; 3524 break; 3525 case FBSD_LUSB_DEV_QUIRK_REMOVE: 3526 args->cmd = USB_DEV_QUIRK_REMOVE; 3527 break; 3528 case FBSD_LUSB_DO_REQUEST: 3529 args->cmd = USB_DO_REQUEST; 3530 break; 3531 case FBSD_LUSB_FS_CLEAR_STALL_SYNC: 3532 args->cmd = USB_FS_CLEAR_STALL_SYNC; 3533 break; 3534 case FBSD_LUSB_FS_CLOSE: 3535 args->cmd = USB_FS_CLOSE; 3536 break; 3537 case FBSD_LUSB_FS_COMPLETE: 3538 args->cmd = USB_FS_COMPLETE; 3539 break; 3540 case FBSD_LUSB_FS_INIT: 3541 args->cmd = USB_FS_INIT; 3542 break; 3543 case FBSD_LUSB_FS_OPEN: 3544 args->cmd = USB_FS_OPEN; 3545 break; 3546 case FBSD_LUSB_FS_START: 3547 args->cmd = USB_FS_START; 3548 break; 3549 case FBSD_LUSB_FS_STOP: 3550 args->cmd = USB_FS_STOP; 3551 break; 3552 case FBSD_LUSB_FS_UNINIT: 3553 args->cmd = USB_FS_UNINIT; 3554 break; 3555 case FBSD_LUSB_GET_CONFIG: 3556 args->cmd = USB_GET_CONFIG; 3557 break; 3558 case FBSD_LUSB_GET_DEVICEINFO: 3559 args->cmd = USB_GET_DEVICEINFO; 3560 break; 3561 case FBSD_LUSB_GET_DEVICE_DESC: 3562 args->cmd = USB_GET_DEVICE_DESC; 3563 break; 3564 case FBSD_LUSB_GET_FULL_DESC: 3565 args->cmd = USB_GET_FULL_DESC; 3566 break; 3567 case FBSD_LUSB_GET_IFACE_DRIVER: 3568 args->cmd = USB_GET_IFACE_DRIVER; 3569 break; 3570 case FBSD_LUSB_GET_PLUGTIME: 3571 args->cmd = USB_GET_PLUGTIME; 3572 break; 3573 case FBSD_LUSB_GET_POWER_MODE: 3574 args->cmd = USB_GET_POWER_MODE; 3575 break; 3576 case FBSD_LUSB_GET_REPORT_DESC: 3577 args->cmd = USB_GET_REPORT_DESC; 3578 break; 3579 case FBSD_LUSB_GET_REPORT_ID: 3580 args->cmd = USB_GET_REPORT_ID; 3581 break; 3582 case FBSD_LUSB_GET_TEMPLATE: 3583 args->cmd = USB_GET_TEMPLATE; 3584 break; 3585 case FBSD_LUSB_IFACE_DRIVER_ACTIVE: 3586 args->cmd = USB_IFACE_DRIVER_ACTIVE; 3587 break; 3588 case FBSD_LUSB_IFACE_DRIVER_DETACH: 3589 args->cmd = USB_IFACE_DRIVER_DETACH; 3590 break; 3591 case FBSD_LUSB_QUIRK_NAME_GET: 3592 args->cmd = USB_QUIRK_NAME_GET; 3593 break; 3594 case FBSD_LUSB_READ_DIR: 3595 args->cmd = USB_READ_DIR; 3596 break; 3597 case FBSD_LUSB_SET_ALTINTERFACE: 3598 args->cmd = USB_SET_ALTINTERFACE; 3599 break; 3600 case FBSD_LUSB_SET_CONFIG: 3601 args->cmd = USB_SET_CONFIG; 3602 break; 3603 case FBSD_LUSB_SET_IMMED: 3604 args->cmd = USB_SET_IMMED; 3605 break; 3606 case FBSD_LUSB_SET_POWER_MODE: 3607 args->cmd = USB_SET_POWER_MODE; 3608 break; 3609 case FBSD_LUSB_SET_TEMPLATE: 3610 args->cmd = USB_SET_TEMPLATE; 3611 break; 3612 case FBSD_LUSB_FS_OPEN_STREAM: 3613 args->cmd = USB_FS_OPEN_STREAM; 3614 break; 3615 case FBSD_LUSB_GET_DEV_PORT_PATH: 3616 args->cmd = USB_GET_DEV_PORT_PATH; 3617 break; 3618 case FBSD_LUSB_GET_POWER_USAGE: 3619 args->cmd = USB_GET_POWER_USAGE; 3620 break; 3621 default: 3622 error = ENOIOCTL; 3623 } 3624 if (error != ENOIOCTL) 3625 error = sys_ioctl(td, (struct ioctl_args *)args); 3626 return (error); 3627 } 3628 3629 /* 3630 * Some evdev ioctls must be translated. 3631 * - EVIOCGMTSLOTS is a IOC_READ ioctl on Linux although it has input data 3632 * (must be IOC_INOUT on FreeBSD). 3633 * - On Linux, EVIOCGRAB, EVIOCREVOKE and EVIOCRMFF are defined as _IOW with 3634 * an int argument. You don't pass an int pointer to the ioctl(), however, 3635 * but just the int directly. On FreeBSD, they are defined as _IOWINT for 3636 * this to work. 3637 */ 3638 static int 3639 linux_ioctl_evdev(struct thread *td, struct linux_ioctl_args *args) 3640 { 3641 cap_rights_t rights; 3642 struct file *fp; 3643 clockid_t clock; 3644 int error; 3645 3646 args->cmd = SETDIR(args->cmd); 3647 3648 switch (args->cmd) { 3649 case (EVIOCGRAB & ~IOC_DIRMASK) | IOC_IN: 3650 args->cmd = EVIOCGRAB; 3651 break; 3652 case (EVIOCREVOKE & ~IOC_DIRMASK) | IOC_IN: 3653 args->cmd = EVIOCREVOKE; 3654 break; 3655 case (EVIOCRMFF & ~IOC_DIRMASK) | IOC_IN: 3656 args->cmd = EVIOCRMFF; 3657 break; 3658 case EVIOCSCLOCKID: { 3659 error = copyin(PTRIN(args->arg), &clock, sizeof(clock)); 3660 if (error != 0) 3661 return (error); 3662 if (clock & ~(LINUX_IOCTL_EVDEV_CLK)) 3663 return (EINVAL); 3664 error = linux_to_native_clockid(&clock, clock); 3665 if (error != 0) 3666 return (error); 3667 3668 error = fget(td, args->fd, 3669 cap_rights_init(&rights, CAP_IOCTL), &fp); 3670 if (error != 0) 3671 return (error); 3672 3673 error = fo_ioctl(fp, EVIOCSCLOCKID, &clock, td->td_ucred, td); 3674 fdrop(fp, td); 3675 return (error); 3676 } 3677 default: 3678 break; 3679 } 3680 3681 if (IOCBASECMD(args->cmd) == 3682 ((EVIOCGMTSLOTS(0) & ~IOC_DIRMASK) | IOC_OUT)) 3683 args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_INOUT; 3684 3685 return (sys_ioctl(td, (struct ioctl_args *)args)); 3686 } 3687 3688 /* 3689 * main ioctl syscall function 3690 */ 3691 3692 int 3693 linux_ioctl(struct thread *td, struct linux_ioctl_args *args) 3694 { 3695 cap_rights_t rights; 3696 struct file *fp; 3697 struct handler_element *he; 3698 int error, cmd; 3699 3700 #ifdef DEBUG 3701 if (ldebug(ioctl)) 3702 printf(ARGS(ioctl, "%d, %04lx, *"), args->fd, 3703 (unsigned long)args->cmd); 3704 #endif 3705 3706 error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp); 3707 if (error != 0) 3708 return (error); 3709 if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 3710 fdrop(fp, td); 3711 return (EBADF); 3712 } 3713 3714 /* Iterate over the ioctl handlers */ 3715 cmd = args->cmd & 0xffff; 3716 sx_slock(&linux_ioctl_sx); 3717 mtx_lock(&Giant); 3718 TAILQ_FOREACH(he, &handlers, list) { 3719 if (cmd >= he->low && cmd <= he->high) { 3720 error = (*he->func)(td, args); 3721 if (error != ENOIOCTL) { 3722 mtx_unlock(&Giant); 3723 sx_sunlock(&linux_ioctl_sx); 3724 fdrop(fp, td); 3725 return (error); 3726 } 3727 } 3728 } 3729 mtx_unlock(&Giant); 3730 sx_sunlock(&linux_ioctl_sx); 3731 fdrop(fp, td); 3732 3733 switch (args->cmd & 0xffff) { 3734 case LINUX_BTRFS_IOC_CLONE: 3735 return (ENOTSUP); 3736 3737 default: 3738 linux_msg(td, "ioctl fd=%d, cmd=0x%x ('%c',%d) is not implemented", 3739 args->fd, (int)(args->cmd & 0xffff), 3740 (int)(args->cmd & 0xff00) >> 8, (int)(args->cmd & 0xff)); 3741 break; 3742 } 3743 3744 return (EINVAL); 3745 } 3746 3747 int 3748 linux_ioctl_register_handler(struct linux_ioctl_handler *h) 3749 { 3750 struct handler_element *he, *cur; 3751 3752 if (h == NULL || h->func == NULL) 3753 return (EINVAL); 3754 3755 /* 3756 * Reuse the element if the handler is already on the list, otherwise 3757 * create a new element. 3758 */ 3759 sx_xlock(&linux_ioctl_sx); 3760 TAILQ_FOREACH(he, &handlers, list) { 3761 if (he->func == h->func) 3762 break; 3763 } 3764 if (he == NULL) { 3765 he = malloc(sizeof(*he), 3766 M_LINUX, M_WAITOK); 3767 he->func = h->func; 3768 } else 3769 TAILQ_REMOVE(&handlers, he, list); 3770 3771 /* Initialize range information. */ 3772 he->low = h->low; 3773 he->high = h->high; 3774 he->span = h->high - h->low + 1; 3775 3776 /* Add the element to the list, sorted on span. */ 3777 TAILQ_FOREACH(cur, &handlers, list) { 3778 if (cur->span > he->span) { 3779 TAILQ_INSERT_BEFORE(cur, he, list); 3780 sx_xunlock(&linux_ioctl_sx); 3781 return (0); 3782 } 3783 } 3784 TAILQ_INSERT_TAIL(&handlers, he, list); 3785 sx_xunlock(&linux_ioctl_sx); 3786 3787 return (0); 3788 } 3789 3790 int 3791 linux_ioctl_unregister_handler(struct linux_ioctl_handler *h) 3792 { 3793 struct handler_element *he; 3794 3795 if (h == NULL || h->func == NULL) 3796 return (EINVAL); 3797 3798 sx_xlock(&linux_ioctl_sx); 3799 TAILQ_FOREACH(he, &handlers, list) { 3800 if (he->func == h->func) { 3801 TAILQ_REMOVE(&handlers, he, list); 3802 sx_xunlock(&linux_ioctl_sx); 3803 free(he, M_LINUX); 3804 return (0); 3805 } 3806 } 3807 sx_xunlock(&linux_ioctl_sx); 3808 3809 return (EINVAL); 3810 } 3811