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