1 /* $NetBSD: linux32_termios.c,v 1.8 2007/05/13 15:38:14 dsl 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.8 2007/05/13 15:38:14 dsl 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 netbsd32_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) { 109 case LINUX32_TCGETS: 110 error = (*bsdioctl)(fp, TIOCGETA, (void *)&tmpbts, l); 111 if (error) 112 goto out; 113 bsd_termios_to_linux32_termios(&tmpbts, &tmplts); 114 error = copyout(&tmplts, SCARG_P32(uap, data), sizeof tmplts); 115 goto out; 116 case LINUX32_TCSETS: 117 case LINUX32_TCSETSW: 118 case LINUX32_TCSETSF: 119 /* 120 * First fill in all fields, so that we keep the current 121 * values for fields that Linux doesn't know about. 122 */ 123 error = (*bsdioctl)(fp, TIOCGETA, (void *)&tmpbts, l); 124 if (error) 125 goto out; 126 if ((error = copyin(SCARG_P32(uap, data), 127 &tmplts, sizeof tmplts)) != 0) 128 goto out; 129 linux32_termios_to_bsd_termios(&tmplts, &tmpbts); 130 switch (com) { 131 case LINUX32_TCSETS: 132 com = TIOCSETA; 133 break; 134 case LINUX32_TCSETSW: 135 com = TIOCSETAW; 136 break; 137 case LINUX32_TCSETSF: 138 com = TIOCSETAF; 139 break; 140 } 141 error = (*bsdioctl)(fp, com, (void *)&tmpbts, l); 142 goto out; 143 case LINUX32_TCGETA: 144 error = (*bsdioctl)(fp, TIOCGETA, (void *)&tmpbts, l); 145 if (error) 146 goto out; 147 bsd_termios_to_linux32_termio(&tmpbts, &tmplt); 148 error = copyout(&tmplt, SCARG_P32(uap, data), sizeof tmplt); 149 goto out; 150 case LINUX32_TCSETA: 151 case LINUX32_TCSETAW: 152 case LINUX32_TCSETAF: 153 /* 154 * First fill in all fields, so that we keep the current 155 * values for fields that Linux doesn't know about. 156 */ 157 error = (*bsdioctl)(fp, TIOCGETA, (void *)&tmpbts, l); 158 if (error) 159 goto out; 160 if ((error = copyin(SCARG_P32(uap, data), 161 &tmplt, sizeof tmplt)) != 0) 162 goto out; 163 linux32_termio_to_bsd_termios(&tmplt, &tmpbts); 164 switch (com) { 165 case LINUX32_TCSETA: 166 com = TIOCSETA; 167 break; 168 case LINUX32_TCSETAW: 169 com = TIOCSETAW; 170 break; 171 case LINUX32_TCSETAF: 172 com = TIOCSETAF; 173 break; 174 } 175 error = (*bsdioctl)(fp, com, (void *)&tmpbts, l); 176 goto out; 177 case LINUX32_TCFLSH: 178 switch((u_long)SCARG_P32(uap, data)) { 179 case 0: 180 idat = FREAD; 181 break; 182 case 1: 183 idat = FWRITE; 184 break; 185 case 2: 186 idat = 0; 187 break; 188 default: 189 error = EINVAL; 190 goto out; 191 } 192 error = (*bsdioctl)(fp, TIOCFLUSH, (void *)&idat, l); 193 goto out; 194 case LINUX32_TIOCGETD: 195 error = (*bsdioctl)(fp, TIOCGETD, (void *)&idat, l); 196 if (error) 197 goto out; 198 switch (idat) { 199 case TTYDISC: 200 idat = LINUX_N_TTY; 201 break; 202 case SLIPDISC: 203 idat = LINUX_N_SLIP; 204 break; 205 case PPPDISC: 206 idat = LINUX_N_PPP; 207 break; 208 case STRIPDISC: 209 idat = LINUX_N_STRIP; 210 break; 211 /* 212 * Linux does not have the tablet line discipline. 213 */ 214 case TABLDISC: 215 default: 216 idat = -1; /* XXX What should this be? */ 217 break; 218 } 219 error = copyout(&idat, SCARG_P32(uap, data), sizeof idat); 220 goto out; 221 case LINUX32_TIOCSETD: 222 if ((error = copyin(SCARG_P32(uap, data), 223 &idat, sizeof idat)) != 0) 224 goto out; 225 switch (idat) { 226 case LINUX_N_TTY: 227 idat = TTYDISC; 228 break; 229 case LINUX_N_SLIP: 230 idat = SLIPDISC; 231 break; 232 case LINUX_N_PPP: 233 idat = PPPDISC; 234 break; 235 case LINUX_N_STRIP: 236 idat = STRIPDISC; 237 break; 238 /* 239 * We can't handle the mouse line discipline Linux has. 240 */ 241 case LINUX_N_MOUSE: 242 case LINUX_N_AX25: 243 case LINUX_N_X25: 244 case LINUX_N_6PACK: 245 default: 246 error = EINVAL; 247 goto out; 248 } 249 error = (*bsdioctl)(fp, TIOCSETD, (void *)&idat, l); 250 goto out; 251 case LINUX32_TIOCLINUX: 252 if ((error = copyin(SCARG_P32(uap, data), 253 &tioclinux, sizeof tioclinux)) != 0) 254 goto out; 255 switch (tioclinux) { 256 case LINUX_TIOCLINUX_KERNMSG: 257 /* 258 * XXX needed to not fail for some things. Could 259 * try to use TIOCCONS, but the char argument 260 * specifies the VT #, not an fd. 261 */ 262 error = 0; 263 goto out; 264 case LINUX_TIOCLINUX_COPY: 265 case LINUX_TIOCLINUX_PASTE: 266 case LINUX_TIOCLINUX_UNBLANK: 267 case LINUX_TIOCLINUX_LOADLUT: 268 case LINUX_TIOCLINUX_READSHIFT: 269 case LINUX_TIOCLINUX_READMOUSE: 270 case LINUX_TIOCLINUX_VESABLANK: 271 case LINUX_TIOCLINUX_CURCONS: /* could use VT_GETACTIVE */ 272 error = EINVAL; 273 goto out; 274 } 275 break; 276 case LINUX32_TIOCGWINSZ: 277 SCARG(&ia, com) = TIOCGWINSZ; 278 break; 279 case LINUX32_TIOCSWINSZ: 280 SCARG(&ia, com) = TIOCSWINSZ; 281 break; 282 case LINUX32_TIOCGPGRP: 283 SCARG(&ia, com) = TIOCGPGRP; 284 break; 285 case LINUX32_TIOCSPGRP: 286 SCARG(&ia, com) = TIOCSPGRP; 287 break; 288 case LINUX32_FIONREAD: 289 SCARG(&ia, com) = FIONREAD; 290 break; 291 case LINUX32_FIONBIO: 292 SCARG(&ia, com) = FIONBIO; 293 break; 294 case LINUX32_FIOASYNC: 295 SCARG(&ia, com) = FIOASYNC; 296 break; 297 case LINUX32_TIOCEXCL: 298 SCARG(&ia, com) = TIOCEXCL; 299 break; 300 case LINUX32_TIOCNXCL: 301 SCARG(&ia, com) = TIOCNXCL; 302 break; 303 case LINUX32_TIOCCONS: 304 SCARG(&ia, com) = TIOCCONS; 305 break; 306 case LINUX32_TIOCNOTTY: 307 SCARG(&ia, com) = TIOCNOTTY; 308 break; 309 case LINUX32_TCSBRK: 310 SCARG(&ia, com) = SCARG_P32(uap, data) ? TIOCDRAIN : TIOCSBRK; 311 break; 312 case LINUX32_TIOCMGET: 313 SCARG(&ia, com) = TIOCMGET; 314 break; 315 case LINUX32_TIOCMSET: 316 SCARG(&ia, com) = TIOCMSET; 317 break; 318 case LINUX32_TIOCMBIC: 319 SCARG(&ia, com) = TIOCMBIC; 320 break; 321 case LINUX32_TIOCMBIS: 322 SCARG(&ia, com) = TIOCMBIS; 323 break; 324 #ifdef LINUX32_TIOCGPTN 325 case LINUX32_TIOCGPTN: 326 #ifndef NO_DEV_PTM 327 { 328 struct ptmget ptm; 329 330 error = (*bsdioctl)(fp, TIOCPTSNAME, &ptm, l); 331 if (error != 0) 332 goto out; 333 334 error = copyout(&ptm.sfd, SCARG_P32(uap, data), 335 sizeof(ptm.sfd)); 336 goto out; 337 } 338 #endif /* NO_DEV_PTM */ 339 #endif /* LINUX32_TIOCGPTN */ 340 default: 341 error = EINVAL; 342 goto out; 343 } 344 345 SCARG(&ia, fd) = SCARG(uap, fd); 346 SCARG(&ia, data) = SCARG(uap, data); 347 /* XXX NJWLWP */ 348 error = netbsd32_ioctl(curlwp, &ia, retval); 349 out: 350 FILE_UNUSE(fp, l); 351 return error; 352 } 353