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