1 /* $NetBSD: linux32_termios.c,v 1.1 2006/02/15 09:31:17 manu Exp $ */ 2 3 /*- 4 * Copyright (c) 1995-2006 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Frank van der Linden, Eric Haszlakiewicz, and Emmanuel Dreyfus. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: linux32_termios.c,v 1.1 2006/02/15 09:31:17 manu Exp $"); 41 42 #include "opt_compat_linux32.h" 43 44 #include <sys/types.h> 45 #include <sys/param.h> 46 #include <sys/time.h> 47 #include <sys/ucred.h> 48 #include <sys/proc.h> 49 #include <sys/lwp.h> 50 #include <sys/file.h> 51 #include <sys/filedesc.h> 52 #include <sys/fcntl.h> 53 #include <sys/termios.h> 54 55 #include <compat/netbsd32/netbsd32.h> 56 #include <compat/netbsd32/netbsd32_syscallargs.h> 57 58 #include <compat/linux32/common/linux32_types.h> 59 #include <compat/linux32/common/linux32_signal.h> 60 #include <compat/linux32/common/linux32_ioctl.h> 61 #include <compat/linux32/common/linux32_machdep.h> 62 #include <compat/linux32/common/linux32_termios.h> 63 #include <compat/linux32/linux32_syscallargs.h> 64 65 #include <compat/linux/common/linux_types.h> 66 #include <compat/linux/common/linux_signal.h> 67 #include <compat/linux/common/linux_util.h> 68 #include <compat/linux/common/linux_termios.h> 69 #include <compat/linux/linux_syscallargs.h> 70 71 int 72 linux32_ioctl_termios(l, uap, retval) 73 struct lwp *l; 74 struct linux32_sys_ioctl_args /* { 75 syscallarg(int) fd; 76 syscallarg(netbsd32_u_long) com; 77 syscallarg(netbsd32_charp) data; 78 } */ *uap; 79 register_t *retval; 80 { 81 struct file *fp; 82 struct filedesc *fdp; 83 u_long com; 84 struct linux32_termio tmplt; 85 struct linux32_termios tmplts; 86 struct termios tmpbts; 87 int idat; 88 struct sys_ioctl_args ia; 89 int error; 90 char tioclinux; 91 int (*bsdioctl)(struct file *, u_long, void *, struct lwp *); 92 93 fdp = l->l_proc->p_fd; 94 if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL) 95 return (EBADF); 96 97 if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 98 error = EBADF; 99 goto out; 100 } 101 102 FILE_USE(fp); 103 104 bsdioctl = fp->f_ops->fo_ioctl; 105 com = SCARG(uap, com); 106 retval[0] = 0; 107 108 switch (com & 0xffff) { 109 case LINUX32_TCGETS: 110 error = (*bsdioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, l); 111 if (error) 112 goto out; 113 bsd_termios_to_linux32_termios(&tmpbts, &tmplts); 114 error = copyout(&tmplts, 115 NETBSD32PTR64(SCARG(uap, data)), 116 sizeof tmplts); 117 goto out; 118 case LINUX32_TCSETS: 119 case LINUX32_TCSETSW: 120 case LINUX32_TCSETSF: 121 /* 122 * First fill in all fields, so that we keep the current 123 * values for fields that Linux doesn't know about. 124 */ 125 error = (*bsdioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, l); 126 if (error) 127 goto out; 128 if ((error = copyin(NETBSD32PTR64(SCARG(uap, data)), 129 &tmplts, sizeof tmplts)) != 0) 130 goto out; 131 linux32_termios_to_bsd_termios(&tmplts, &tmpbts); 132 switch (com) { 133 case LINUX32_TCSETS: 134 com = TIOCSETA; 135 break; 136 case LINUX32_TCSETSW: 137 com = TIOCSETAW; 138 break; 139 case LINUX32_TCSETSF: 140 com = TIOCSETAF; 141 break; 142 } 143 error = (*bsdioctl)(fp, com, (caddr_t)&tmpbts, l); 144 goto out; 145 case LINUX32_TCGETA: 146 error = (*bsdioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, l); 147 if (error) 148 goto out; 149 bsd_termios_to_linux32_termio(&tmpbts, &tmplt); 150 error = copyout(&tmplt, 151 NETBSD32PTR64(SCARG(uap, data)), 152 sizeof tmplt); 153 goto out; 154 case LINUX32_TCSETA: 155 case LINUX32_TCSETAW: 156 case LINUX32_TCSETAF: 157 /* 158 * First fill in all fields, so that we keep the current 159 * values for fields that Linux doesn't know about. 160 */ 161 error = (*bsdioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, l); 162 if (error) 163 goto out; 164 if ((error = copyin(NETBSD32PTR64(SCARG(uap, data)), 165 &tmplt, sizeof tmplt)) != 0) 166 goto out; 167 linux32_termio_to_bsd_termios(&tmplt, &tmpbts); 168 switch (com) { 169 case LINUX32_TCSETA: 170 com = TIOCSETA; 171 break; 172 case LINUX32_TCSETAW: 173 com = TIOCSETAW; 174 break; 175 case LINUX32_TCSETAF: 176 com = TIOCSETAF; 177 break; 178 } 179 error = (*bsdioctl)(fp, com, (caddr_t)&tmpbts, l); 180 goto out; 181 case LINUX32_TCFLSH: 182 switch((u_long)NETBSD32PTR64(SCARG(uap, data))) { 183 case 0: 184 idat = FREAD; 185 break; 186 case 1: 187 idat = FWRITE; 188 break; 189 case 2: 190 idat = 0; 191 break; 192 default: 193 error = EINVAL; 194 goto out; 195 } 196 error = (*bsdioctl)(fp, TIOCFLUSH, (caddr_t)&idat, l); 197 goto out; 198 case LINUX32_TIOCGETD: 199 error = (*bsdioctl)(fp, TIOCGETD, (caddr_t)&idat, l); 200 if (error) 201 goto out; 202 switch (idat) { 203 case TTYDISC: 204 idat = LINUX_N_TTY; 205 break; 206 case SLIPDISC: 207 idat = LINUX_N_SLIP; 208 break; 209 case PPPDISC: 210 idat = LINUX_N_PPP; 211 break; 212 case STRIPDISC: 213 idat = LINUX_N_STRIP; 214 break; 215 /* 216 * Linux does not have the tablet line discipline. 217 */ 218 case TABLDISC: 219 default: 220 idat = -1; /* XXX What should this be? */ 221 break; 222 } 223 error = copyout(&idat, 224 NETBSD32PTR64(SCARG(uap, data)), sizeof idat); 225 goto out; 226 case LINUX32_TIOCSETD: 227 if ((error = copyin(NETBSD32PTR64(SCARG(uap, data)), 228 &idat, sizeof idat)) != 0) 229 goto out; 230 switch (idat) { 231 case LINUX_N_TTY: 232 idat = TTYDISC; 233 break; 234 case LINUX_N_SLIP: 235 idat = SLIPDISC; 236 break; 237 case LINUX_N_PPP: 238 idat = PPPDISC; 239 break; 240 case LINUX_N_STRIP: 241 idat = STRIPDISC; 242 break; 243 /* 244 * We can't handle the mouse line discipline Linux has. 245 */ 246 case LINUX_N_MOUSE: 247 case LINUX_N_AX25: 248 case LINUX_N_X25: 249 case LINUX_N_6PACK: 250 default: 251 error = EINVAL; 252 goto out; 253 } 254 error = (*bsdioctl)(fp, TIOCSETD, (caddr_t)&idat, l); 255 goto out; 256 case LINUX32_TIOCLINUX: 257 if ((error = copyin(NETBSD32PTR64(SCARG(uap, data)), 258 &tioclinux, sizeof tioclinux)) != 0) 259 goto out; 260 switch (tioclinux) { 261 case LINUX_TIOCLINUX_KERNMSG: 262 /* 263 * XXX needed to not fail for some things. Could 264 * try to use TIOCCONS, but the char argument 265 * specifies the VT #, not an fd. 266 */ 267 error = 0; 268 goto out; 269 case LINUX_TIOCLINUX_COPY: 270 case LINUX_TIOCLINUX_PASTE: 271 case LINUX_TIOCLINUX_UNBLANK: 272 case LINUX_TIOCLINUX_LOADLUT: 273 case LINUX_TIOCLINUX_READSHIFT: 274 case LINUX_TIOCLINUX_READMOUSE: 275 case LINUX_TIOCLINUX_VESABLANK: 276 case LINUX_TIOCLINUX_CURCONS: /* could use VT_GETACTIVE */ 277 error = EINVAL; 278 goto out; 279 } 280 break; 281 case LINUX32_TIOCGWINSZ: 282 SCARG(&ia, com) = TIOCGWINSZ; 283 break; 284 case LINUX32_TIOCSWINSZ: 285 SCARG(&ia, com) = TIOCSWINSZ; 286 break; 287 case LINUX32_TIOCGPGRP: 288 SCARG(&ia, com) = TIOCGPGRP; 289 break; 290 case LINUX32_TIOCSPGRP: 291 SCARG(&ia, com) = TIOCSPGRP; 292 break; 293 case LINUX32_FIONREAD: 294 SCARG(&ia, com) = FIONREAD; 295 break; 296 case LINUX32_FIONBIO: 297 SCARG(&ia, com) = FIONBIO; 298 break; 299 case LINUX32_FIOASYNC: 300 SCARG(&ia, com) = FIOASYNC; 301 break; 302 case LINUX32_TIOCEXCL: 303 SCARG(&ia, com) = TIOCEXCL; 304 break; 305 case LINUX32_TIOCNXCL: 306 SCARG(&ia, com) = TIOCNXCL; 307 break; 308 case LINUX32_TIOCCONS: 309 SCARG(&ia, com) = TIOCCONS; 310 break; 311 case LINUX32_TIOCNOTTY: 312 SCARG(&ia, com) = TIOCNOTTY; 313 break; 314 case LINUX32_TCSBRK: 315 SCARG(&ia, com) = 316 NETBSD32PTR64(SCARG(uap, data)) ? TIOCDRAIN : TIOCSBRK; 317 break; 318 case LINUX32_TIOCMGET: 319 SCARG(&ia, com) = TIOCMGET; 320 break; 321 case LINUX32_TIOCMSET: 322 SCARG(&ia, com) = TIOCMSET; 323 break; 324 case LINUX32_TIOCMBIC: 325 SCARG(&ia, com) = TIOCMBIC; 326 break; 327 case LINUX32_TIOCMBIS: 328 SCARG(&ia, com) = TIOCMBIS; 329 break; 330 #ifdef LINUX32_TIOCGPTN 331 case LINUX32_TIOCGPTN: 332 #ifndef NO_DEV_PTM 333 { 334 caddr_t sg = stackgap_init(l->l_proc, 0); 335 struct ptmget ptm; 336 struct ptmget *ptmp = stackgap_alloc(l->l_proc, &sg, 337 sizeof(*ptmp)); 338 339 SCARG(&ia, fd) = SCARG(uap, fd); 340 SCARG(&ia, com) = TIOCPTSNAME; 341 SCARG(&ia, data) = ptmp; 342 343 if ((error = sys_ioctl(curlwp, &ia, retval)) != 0) 344 goto out; 345 346 if ((error = copyin(ptmp, &ptm, sizeof(ptm))) != 0) 347 printf("copyin %d\n", error); 348 349 error = copyout(&ptm.sfd, 350 NETBSD32PTR64(SCARG(uap, data)), 351 sizeof(ptm.sfd)); 352 goto out; 353 } 354 #endif /* NO_DEV_PTM */ 355 #endif /* LINUX32_TIOCGPTN */ 356 default: 357 error = EINVAL; 358 goto out; 359 } 360 361 SCARG(&ia, fd) = SCARG(uap, fd); 362 SCARG(&ia, data) = NETBSD32PTR64(SCARG(uap, data)); 363 /* XXX NJWLWP */ 364 error = netbsd32_ioctl(curlwp, &ia, retval); 365 out: 366 FILE_UNUSE(fp, l); 367 return error; 368 } 369