1 /* $NetBSD: linux_termios.c,v 1.24 2005/12/11 12:20:19 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 1998 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 and Eric Haszlakiewicz. 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: linux_termios.c,v 1.24 2005/12/11 12:20:19 christos Exp $"); 41 42 #if defined(_KERNEL_OPT) 43 #include "opt_ptm.h" 44 #endif 45 46 #include <sys/param.h> 47 #include <sys/proc.h> 48 #include <sys/systm.h> 49 #include <sys/file.h> 50 #include <sys/filedesc.h> 51 #include <sys/ioctl.h> 52 #include <sys/mount.h> 53 #include <sys/termios.h> 54 55 #include <sys/sa.h> 56 #include <sys/syscallargs.h> 57 58 #include <compat/linux/common/linux_types.h> 59 #include <compat/linux/common/linux_ioctl.h> 60 #include <compat/linux/common/linux_signal.h> 61 #include <compat/linux/common/linux_util.h> 62 #include <compat/linux/common/linux_termios.h> 63 64 #include <compat/linux/linux_syscallargs.h> 65 66 static speed_t linux_speeds[] = { 67 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 68 9600, 19200, 38400, 57600, 115200, 230400 69 }; 70 71 static const int linux_spmasks[] = { 72 LINUX_B0, LINUX_B50, LINUX_B75, LINUX_B110, LINUX_B134, LINUX_B150, 73 LINUX_B200, LINUX_B300, LINUX_B600, LINUX_B1200, LINUX_B1800, 74 LINUX_B2400, LINUX_B4800, LINUX_B9600, LINUX_B19200, LINUX_B38400, 75 LINUX_B57600, LINUX_B115200, LINUX_B230400 76 }; 77 78 79 static void linux_termio_to_bsd_termios __P((struct linux_termio *, 80 struct termios *)); 81 static void bsd_termios_to_linux_termio __P((struct termios *, 82 struct linux_termio *)); 83 static void linux_termios_to_bsd_termios __P((struct linux_termios *, 84 struct termios *)); 85 static void bsd_termios_to_linux_termios __P((struct termios *, 86 struct linux_termios *)); 87 88 /* 89 * Deal with termio ioctl cruft. This doesn't look very good.. 90 * XXX too much code duplication, obviously.. 91 * 92 * The conversion routines between Linux and BSD structures assume 93 * that the fields are already filled with the current values, 94 * so that fields present in BSD but not in Linux keep their current 95 * values. 96 */ 97 98 static void 99 linux_termio_to_bsd_termios(lt, bts) 100 struct linux_termio *lt; 101 struct termios *bts; 102 { 103 int index; 104 105 bts->c_iflag = 0; 106 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNBRK, IGNBRK); 107 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_BRKINT, BRKINT); 108 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNPAR, IGNPAR); 109 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_INPCK, INPCK); 110 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_ISTRIP, ISTRIP); 111 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_INLCR, INLCR); 112 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IGNCR, IGNCR); 113 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_ICRNL, ICRNL); 114 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXON, IXON); 115 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXANY, IXANY); 116 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IXOFF, IXOFF); 117 bts->c_iflag |= cvtto_bsd_mask(lt->c_iflag, LINUX_IMAXBEL, IMAXBEL); 118 119 bts->c_oflag = 0; 120 bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_OPOST, OPOST); 121 bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_ONLCR, ONLCR); 122 bts->c_oflag |= cvtto_bsd_mask(lt->c_oflag, LINUX_XTABS, OXTABS); 123 124 /* 125 * This could have been: 126 * bts->c_cflag = (lt->c_flag & LINUX_CSIZE) << 4 127 * But who knows, those values might perhaps change one day. 128 */ 129 switch (lt->c_cflag & LINUX_CSIZE) { 130 case LINUX_CS5: 131 bts->c_cflag = CS5; 132 break; 133 case LINUX_CS6: 134 bts->c_cflag = CS6; 135 break; 136 case LINUX_CS7: 137 bts->c_cflag = CS7; 138 break; 139 case LINUX_CS8: 140 bts->c_cflag = CS8; 141 break; 142 } 143 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CSTOPB, CSTOPB); 144 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CREAD, CREAD); 145 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_PARENB, PARENB); 146 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_PARODD, PARODD); 147 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_HUPCL, HUPCL); 148 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CLOCAL, CLOCAL); 149 bts->c_cflag |= cvtto_bsd_mask(lt->c_cflag, LINUX_CRTSCTS, CRTSCTS); 150 151 bts->c_lflag = 0; 152 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ISIG, ISIG); 153 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ICANON, ICANON); 154 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHO, ECHO); 155 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOE, ECHOE); 156 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOK, ECHOK); 157 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHONL, ECHONL); 158 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_NOFLSH, NOFLSH); 159 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_TOSTOP, TOSTOP); 160 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOCTL, ECHOCTL); 161 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOPRT, ECHOPRT); 162 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_ECHOKE, ECHOKE); 163 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_FLUSHO, FLUSHO); 164 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_PENDIN, PENDIN); 165 bts->c_lflag |= cvtto_bsd_mask(lt->c_lflag, LINUX_IEXTEN, IEXTEN); 166 167 index = lt->c_cflag & LINUX_CBAUD; 168 if (index & LINUX_CBAUDEX) 169 index = (index & ~LINUX_CBAUDEX) + LINUX_NSPEEDS - 1; 170 bts->c_ispeed = bts->c_ospeed = linux_speeds[index]; 171 172 bts->c_cc[VINTR] = lt->c_cc[LINUX_OLD_VINTR]; 173 bts->c_cc[VQUIT] = lt->c_cc[LINUX_OLD_VQUIT]; 174 bts->c_cc[VERASE] = lt->c_cc[LINUX_OLD_VERASE]; 175 bts->c_cc[VKILL] = lt->c_cc[LINUX_OLD_VKILL]; 176 bts->c_cc[VEOF] = lt->c_cc[LINUX_OLD_VEOF]; 177 bts->c_cc[VTIME] = lt->c_cc[LINUX_OLD_VTIME]; 178 bts->c_cc[VMIN] = lt->c_cc[LINUX_OLD_VMIN]; 179 } 180 181 static void 182 bsd_termios_to_linux_termio(bts, lt) 183 struct termios *bts; 184 struct linux_termio *lt; 185 { 186 int i, mask; 187 188 lt->c_iflag = 0; 189 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNBRK, LINUX_IGNBRK); 190 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, BRKINT, LINUX_BRKINT); 191 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNPAR, LINUX_IGNPAR); 192 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, INPCK, LINUX_INPCK); 193 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, ISTRIP, LINUX_ISTRIP); 194 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, INLCR, LINUX_INLCR); 195 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNCR, LINUX_IGNCR); 196 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, ICRNL, LINUX_ICRNL); 197 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXON, LINUX_IXON); 198 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXANY, LINUX_IXANY); 199 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXOFF, LINUX_IXOFF); 200 lt->c_iflag |= cvtto_linux_mask(bts->c_iflag, IMAXBEL, LINUX_IMAXBEL); 201 202 lt->c_oflag = 0; 203 lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, OPOST, LINUX_OPOST); 204 lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, ONLCR, LINUX_ONLCR); 205 lt->c_oflag |= cvtto_linux_mask(bts->c_oflag, OXTABS, LINUX_XTABS); 206 207 switch (bts->c_cflag & CSIZE) { 208 case CS5: 209 lt->c_cflag = LINUX_CS5; 210 break; 211 case CS6: 212 lt->c_cflag = LINUX_CS6; 213 break; 214 case CS7: 215 lt->c_cflag = LINUX_CS7; 216 break; 217 case CS8: 218 lt->c_cflag = LINUX_CS8; 219 break; 220 } 221 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CSTOPB, LINUX_CSTOPB); 222 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CREAD, LINUX_CREAD); 223 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARENB, LINUX_PARENB); 224 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARODD, LINUX_PARODD); 225 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, HUPCL, LINUX_HUPCL); 226 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CLOCAL, LINUX_CLOCAL); 227 lt->c_cflag |= cvtto_linux_mask(bts->c_cflag, CRTSCTS, LINUX_CRTSCTS); 228 229 lt->c_lflag = 0; 230 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ISIG, LINUX_ISIG); 231 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ICANON, LINUX_ICANON); 232 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHO, LINUX_ECHO); 233 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOE, LINUX_ECHOE); 234 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOK, LINUX_ECHOK); 235 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHONL, LINUX_ECHONL); 236 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, NOFLSH, LINUX_NOFLSH); 237 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, TOSTOP, LINUX_TOSTOP); 238 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOCTL, LINUX_ECHOCTL); 239 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOPRT, LINUX_ECHOPRT); 240 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOKE, LINUX_ECHOKE); 241 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, FLUSHO, LINUX_FLUSHO); 242 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, PENDIN, LINUX_PENDIN); 243 lt->c_lflag |= cvtto_linux_mask(bts->c_lflag, IEXTEN, LINUX_IEXTEN); 244 245 mask = LINUX_B9600; /* XXX default value should this be 0? */ 246 for (i = 0; i < sizeof (linux_speeds) / sizeof (speed_t); i++) { 247 if (bts->c_ospeed == linux_speeds[i]) { 248 mask = linux_spmasks[i]; 249 break; 250 } 251 } 252 lt->c_cflag |= mask; 253 254 lt->c_cc[LINUX_VINTR] = bts->c_cc[VINTR]; 255 lt->c_cc[LINUX_VQUIT] = bts->c_cc[VQUIT]; 256 lt->c_cc[LINUX_VERASE] = bts->c_cc[VERASE]; 257 lt->c_cc[LINUX_VKILL] = bts->c_cc[VKILL]; 258 lt->c_cc[LINUX_VEOF] = bts->c_cc[VEOF]; 259 lt->c_cc[LINUX_VTIME] = bts->c_cc[VTIME]; 260 lt->c_cc[LINUX_VMIN] = bts->c_cc[VMIN]; 261 lt->c_cc[LINUX_VSWTC] = 0; 262 263 /* XXX should be fixed someday */ 264 lt->c_line = 0; 265 } 266 267 static void 268 linux_termios_to_bsd_termios(lts, bts) 269 struct linux_termios *lts; 270 struct termios *bts; 271 { 272 int index; 273 274 bts->c_iflag = 0; 275 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNBRK, IGNBRK); 276 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_BRKINT, BRKINT); 277 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNPAR, IGNPAR); 278 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_INPCK, INPCK); 279 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_ISTRIP, ISTRIP); 280 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_INLCR, INLCR); 281 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IGNCR, IGNCR); 282 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_ICRNL, ICRNL); 283 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXON, IXON); 284 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXANY, IXANY); 285 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IXOFF, IXOFF); 286 bts->c_iflag |= cvtto_bsd_mask(lts->c_iflag, LINUX_IMAXBEL, IMAXBEL); 287 288 bts->c_oflag = 0; 289 bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_OPOST, OPOST); 290 bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_ONLCR, ONLCR); 291 bts->c_oflag |= cvtto_bsd_mask(lts->c_oflag, LINUX_XTABS, OXTABS); 292 293 bts->c_cflag = 0; 294 switch (lts->c_cflag & LINUX_CSIZE) { 295 case LINUX_CS5: 296 bts->c_cflag = CS5; 297 break; 298 case LINUX_CS6: 299 bts->c_cflag = CS6; 300 break; 301 case LINUX_CS7: 302 bts->c_cflag = CS7; 303 break; 304 case LINUX_CS8: 305 bts->c_cflag = CS8; 306 break; 307 } 308 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CSTOPB, CSTOPB); 309 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CREAD, CREAD); 310 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_PARENB, PARENB); 311 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_PARODD, PARODD); 312 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_HUPCL, HUPCL); 313 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CLOCAL, CLOCAL); 314 bts->c_cflag |= cvtto_bsd_mask(lts->c_cflag, LINUX_CRTSCTS, CRTSCTS); 315 316 bts->c_lflag = 0; 317 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ISIG, ISIG); 318 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ICANON, ICANON); 319 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHO, ECHO); 320 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOE, ECHOE); 321 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOK, ECHOK); 322 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHONL, ECHONL); 323 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_NOFLSH, NOFLSH); 324 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_TOSTOP, TOSTOP); 325 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOCTL, ECHOCTL); 326 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOPRT, ECHOPRT); 327 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_ECHOKE, ECHOKE); 328 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_FLUSHO, FLUSHO); 329 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_PENDIN, PENDIN); 330 bts->c_lflag |= cvtto_bsd_mask(lts->c_lflag, LINUX_IEXTEN, IEXTEN); 331 332 index = lts->c_cflag & LINUX_CBAUD; 333 if (index & LINUX_CBAUDEX) 334 index = (index & ~LINUX_CBAUDEX) + LINUX_NSPEEDS - 1; 335 bts->c_ispeed = bts->c_ospeed = linux_speeds[index]; 336 /* 337 * A null c_ospeed causes NetBSD to hangup the terminal. 338 * Linux does not do this, and it sets c_ospeed to zero 339 * sometimes. If it is null, we store -1 in the kernel 340 */ 341 if (bts->c_ospeed == 0) 342 bts->c_ospeed = -1; 343 344 bts->c_cc[VINTR] = lts->c_cc[LINUX_VINTR]; 345 bts->c_cc[VQUIT] = lts->c_cc[LINUX_VQUIT]; 346 bts->c_cc[VERASE] = lts->c_cc[LINUX_VERASE]; 347 bts->c_cc[VKILL] = lts->c_cc[LINUX_VKILL]; 348 bts->c_cc[VEOF] = lts->c_cc[LINUX_VEOF]; 349 bts->c_cc[VTIME] = lts->c_cc[LINUX_VTIME]; 350 bts->c_cc[VMIN] = lts->c_cc[LINUX_VMIN]; 351 bts->c_cc[VEOL] = lts->c_cc[LINUX_VEOL]; 352 bts->c_cc[VEOL2] = lts->c_cc[LINUX_VEOL2]; 353 bts->c_cc[VWERASE] = lts->c_cc[LINUX_VWERASE]; 354 bts->c_cc[VSUSP] = lts->c_cc[LINUX_VSUSP]; 355 bts->c_cc[VSTART] = lts->c_cc[LINUX_VSTART]; 356 bts->c_cc[VSTOP] = lts->c_cc[LINUX_VSTOP]; 357 bts->c_cc[VLNEXT] = lts->c_cc[LINUX_VLNEXT]; 358 bts->c_cc[VDISCARD] = lts->c_cc[LINUX_VDISCARD]; 359 bts->c_cc[VREPRINT] = lts->c_cc[LINUX_VREPRINT]; 360 } 361 362 static void 363 bsd_termios_to_linux_termios(bts, lts) 364 struct termios *bts; 365 struct linux_termios *lts; 366 { 367 int i, mask; 368 369 lts->c_iflag = 0; 370 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNBRK, LINUX_IGNBRK); 371 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, BRKINT, LINUX_BRKINT); 372 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNPAR, LINUX_IGNPAR); 373 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, INPCK, LINUX_INPCK); 374 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, ISTRIP, LINUX_ISTRIP); 375 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, INLCR, LINUX_INLCR); 376 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IGNCR, LINUX_IGNCR); 377 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, ICRNL, LINUX_ICRNL); 378 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXON, LINUX_IXON); 379 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXANY, LINUX_IXANY); 380 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IXOFF, LINUX_IXOFF); 381 lts->c_iflag |= cvtto_linux_mask(bts->c_iflag, IMAXBEL, LINUX_IMAXBEL); 382 383 lts->c_oflag = 0; 384 lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, OPOST, LINUX_OPOST); 385 lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, ONLCR, LINUX_ONLCR); 386 lts->c_oflag |= cvtto_linux_mask(bts->c_oflag, OXTABS, LINUX_XTABS); 387 388 switch (bts->c_cflag & CSIZE) { 389 case CS5: 390 lts->c_cflag = LINUX_CS5; 391 break; 392 case CS6: 393 lts->c_cflag = LINUX_CS6; 394 break; 395 case CS7: 396 lts->c_cflag = LINUX_CS7; 397 break; 398 case CS8: 399 lts->c_cflag = LINUX_CS8; 400 break; 401 } 402 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS5, LINUX_CS5); 403 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS6, LINUX_CS6); 404 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS7, LINUX_CS7); 405 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CS8, LINUX_CS8); 406 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CSTOPB, LINUX_CSTOPB); 407 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CREAD, LINUX_CREAD); 408 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARENB, LINUX_PARENB); 409 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, PARODD, LINUX_PARODD); 410 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, HUPCL, LINUX_HUPCL); 411 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CLOCAL, LINUX_CLOCAL); 412 lts->c_cflag |= cvtto_linux_mask(bts->c_cflag, CRTSCTS, LINUX_CRTSCTS); 413 414 lts->c_lflag = 0; 415 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ISIG, LINUX_ISIG); 416 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ICANON, LINUX_ICANON); 417 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHO, LINUX_ECHO); 418 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOE, LINUX_ECHOE); 419 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOK, LINUX_ECHOK); 420 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHONL, LINUX_ECHONL); 421 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, NOFLSH, LINUX_NOFLSH); 422 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, TOSTOP, LINUX_TOSTOP); 423 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOCTL, LINUX_ECHOCTL); 424 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOPRT, LINUX_ECHOPRT); 425 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, ECHOKE, LINUX_ECHOKE); 426 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, FLUSHO, LINUX_FLUSHO); 427 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, PENDIN, LINUX_PENDIN); 428 lts->c_lflag |= cvtto_linux_mask(bts->c_lflag, IEXTEN, LINUX_IEXTEN); 429 430 mask = LINUX_B9600; /* XXX default value */ 431 for (i = 0; i < sizeof (linux_speeds) / sizeof (speed_t); i++) { 432 if (bts->c_ospeed == linux_speeds[i]) { 433 mask = linux_spmasks[i]; 434 break; 435 } 436 } 437 /* 438 * A null c_ospeed causes NetBSD to hangup the terminal. 439 * Linux does not do this, and it sets c_ospeed to zero 440 * sometimes. If it is null, we store -1 in the kernel 441 */ 442 if (bts->c_ospeed == -1) 443 bts->c_ospeed = 0; 444 lts->c_cflag |= mask; 445 446 lts->c_cc[LINUX_VINTR] = bts->c_cc[VINTR]; 447 lts->c_cc[LINUX_VQUIT] = bts->c_cc[VQUIT]; 448 lts->c_cc[LINUX_VERASE] = bts->c_cc[VERASE]; 449 lts->c_cc[LINUX_VKILL] = bts->c_cc[VKILL]; 450 lts->c_cc[LINUX_VEOF] = bts->c_cc[VEOF]; 451 lts->c_cc[LINUX_VTIME] = bts->c_cc[VTIME]; 452 lts->c_cc[LINUX_VMIN] = bts->c_cc[VMIN]; 453 lts->c_cc[LINUX_VEOL] = bts->c_cc[VEOL]; 454 lts->c_cc[LINUX_VEOL2] = bts->c_cc[VEOL2]; 455 lts->c_cc[LINUX_VWERASE] = bts->c_cc[VWERASE]; 456 lts->c_cc[LINUX_VSUSP] = bts->c_cc[VSUSP]; 457 lts->c_cc[LINUX_VSTART] = bts->c_cc[VSTART]; 458 lts->c_cc[LINUX_VSTOP] = bts->c_cc[VSTOP]; 459 lts->c_cc[LINUX_VLNEXT] = bts->c_cc[VLNEXT]; 460 lts->c_cc[LINUX_VDISCARD] = bts->c_cc[VDISCARD]; 461 lts->c_cc[LINUX_VREPRINT] = bts->c_cc[VREPRINT]; 462 lts->c_cc[LINUX_VSWTC] = 0; 463 464 /* XXX should be fixed someday */ 465 lts->c_line = 0; 466 } 467 468 int 469 linux_ioctl_termios(l, uap, retval) 470 struct lwp *l; 471 struct linux_sys_ioctl_args /* { 472 syscallarg(int) fd; 473 syscallarg(u_long) com; 474 syscallarg(caddr_t) data; 475 } */ *uap; 476 register_t *retval; 477 { 478 struct file *fp; 479 struct filedesc *fdp; 480 u_long com; 481 struct linux_termio tmplt; 482 struct linux_termios tmplts; 483 struct termios tmpbts; 484 int idat; 485 struct sys_ioctl_args ia; 486 int error; 487 char tioclinux; 488 int (*bsdioctl)(struct file *, u_long, void *, struct lwp *); 489 490 fdp = l->l_proc->p_fd; 491 if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL) 492 return (EBADF); 493 494 if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 495 error = EBADF; 496 goto out; 497 } 498 499 FILE_USE(fp); 500 501 bsdioctl = fp->f_ops->fo_ioctl; 502 com = SCARG(uap, com); 503 retval[0] = 0; 504 505 switch (com & 0xffff) { 506 case LINUX_TCGETS: 507 error = (*bsdioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, l); 508 if (error) 509 goto out; 510 bsd_termios_to_linux_termios(&tmpbts, &tmplts); 511 error = copyout(&tmplts, SCARG(uap, data), sizeof tmplts); 512 goto out; 513 case LINUX_TCSETS: 514 case LINUX_TCSETSW: 515 case LINUX_TCSETSF: 516 /* 517 * First fill in all fields, so that we keep the current 518 * values for fields that Linux doesn't know about. 519 */ 520 error = (*bsdioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, l); 521 if (error) 522 goto out; 523 error = copyin(SCARG(uap, data), &tmplts, sizeof tmplts); 524 if (error) 525 goto out; 526 linux_termios_to_bsd_termios(&tmplts, &tmpbts); 527 switch (com) { 528 case LINUX_TCSETS: 529 com = TIOCSETA; 530 break; 531 case LINUX_TCSETSW: 532 com = TIOCSETAW; 533 break; 534 case LINUX_TCSETSF: 535 com = TIOCSETAF; 536 break; 537 } 538 error = (*bsdioctl)(fp, com, (caddr_t)&tmpbts, l); 539 goto out; 540 case LINUX_TCGETA: 541 error = (*bsdioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, l); 542 if (error) 543 goto out; 544 bsd_termios_to_linux_termio(&tmpbts, &tmplt); 545 error = copyout(&tmplt, SCARG(uap, data), sizeof tmplt); 546 goto out; 547 case LINUX_TCSETA: 548 case LINUX_TCSETAW: 549 case LINUX_TCSETAF: 550 /* 551 * First fill in all fields, so that we keep the current 552 * values for fields that Linux doesn't know about. 553 */ 554 error = (*bsdioctl)(fp, TIOCGETA, (caddr_t)&tmpbts, l); 555 if (error) 556 goto out; 557 error = copyin(SCARG(uap, data), &tmplt, sizeof tmplt); 558 if (error) 559 goto out; 560 linux_termio_to_bsd_termios(&tmplt, &tmpbts); 561 switch (com) { 562 case LINUX_TCSETA: 563 com = TIOCSETA; 564 break; 565 case LINUX_TCSETAW: 566 com = TIOCSETAW; 567 break; 568 case LINUX_TCSETAF: 569 com = TIOCSETAF; 570 break; 571 } 572 error = (*bsdioctl)(fp, com, (caddr_t)&tmpbts, l); 573 goto out; 574 case LINUX_TCFLSH: 575 switch((u_long)SCARG(uap, data)) { 576 case 0: 577 idat = FREAD; 578 break; 579 case 1: 580 idat = FWRITE; 581 break; 582 case 2: 583 idat = 0; 584 break; 585 default: 586 error = EINVAL; 587 goto out; 588 } 589 error = (*bsdioctl)(fp, TIOCFLUSH, (caddr_t)&idat, l); 590 goto out; 591 case LINUX_TIOCGETD: 592 error = (*bsdioctl)(fp, TIOCGETD, (caddr_t)&idat, l); 593 if (error) 594 goto out; 595 switch (idat) { 596 case TTYDISC: 597 idat = LINUX_N_TTY; 598 break; 599 case SLIPDISC: 600 idat = LINUX_N_SLIP; 601 break; 602 case PPPDISC: 603 idat = LINUX_N_PPP; 604 break; 605 case STRIPDISC: 606 idat = LINUX_N_STRIP; 607 break; 608 /* 609 * Linux does not have the tablet line discipline. 610 */ 611 case TABLDISC: 612 default: 613 idat = -1; /* XXX What should this be? */ 614 break; 615 } 616 error = copyout(&idat, SCARG(uap, data), sizeof idat); 617 goto out; 618 case LINUX_TIOCSETD: 619 error = copyin(SCARG(uap, data), &idat, sizeof idat); 620 if (error) 621 goto out; 622 switch (idat) { 623 case LINUX_N_TTY: 624 idat = TTYDISC; 625 break; 626 case LINUX_N_SLIP: 627 idat = SLIPDISC; 628 break; 629 case LINUX_N_PPP: 630 idat = PPPDISC; 631 break; 632 case LINUX_N_STRIP: 633 idat = STRIPDISC; 634 break; 635 /* 636 * We can't handle the mouse line discipline Linux has. 637 */ 638 case LINUX_N_MOUSE: 639 case LINUX_N_AX25: 640 case LINUX_N_X25: 641 case LINUX_N_6PACK: 642 default: 643 error = EINVAL; 644 goto out; 645 } 646 error = (*bsdioctl)(fp, TIOCSETD, (caddr_t)&idat, l); 647 goto out; 648 case LINUX_TIOCLINUX: 649 error = copyin(SCARG(uap, data), &tioclinux, sizeof tioclinux); 650 if (error != 0) 651 goto out; 652 switch (tioclinux) { 653 case LINUX_TIOCLINUX_KERNMSG: 654 /* 655 * XXX needed to not fail for some things. Could 656 * try to use TIOCCONS, but the char argument 657 * specifies the VT #, not an fd. 658 */ 659 error = 0; 660 goto out; 661 case LINUX_TIOCLINUX_COPY: 662 case LINUX_TIOCLINUX_PASTE: 663 case LINUX_TIOCLINUX_UNBLANK: 664 case LINUX_TIOCLINUX_LOADLUT: 665 case LINUX_TIOCLINUX_READSHIFT: 666 case LINUX_TIOCLINUX_READMOUSE: 667 case LINUX_TIOCLINUX_VESABLANK: 668 case LINUX_TIOCLINUX_CURCONS: /* could use VT_GETACTIVE */ 669 error = EINVAL; 670 goto out; 671 } 672 break; 673 case LINUX_TIOCGWINSZ: 674 SCARG(&ia, com) = TIOCGWINSZ; 675 break; 676 case LINUX_TIOCSWINSZ: 677 SCARG(&ia, com) = TIOCSWINSZ; 678 break; 679 case LINUX_TIOCGPGRP: 680 SCARG(&ia, com) = TIOCGPGRP; 681 break; 682 case LINUX_TIOCSPGRP: 683 SCARG(&ia, com) = TIOCSPGRP; 684 break; 685 case LINUX_FIONREAD: 686 SCARG(&ia, com) = FIONREAD; 687 break; 688 case LINUX_FIONBIO: 689 SCARG(&ia, com) = FIONBIO; 690 break; 691 case LINUX_FIOASYNC: 692 SCARG(&ia, com) = FIOASYNC; 693 break; 694 case LINUX_TIOCEXCL: 695 SCARG(&ia, com) = TIOCEXCL; 696 break; 697 case LINUX_TIOCNXCL: 698 SCARG(&ia, com) = TIOCNXCL; 699 break; 700 case LINUX_TIOCCONS: 701 SCARG(&ia, com) = TIOCCONS; 702 break; 703 case LINUX_TIOCNOTTY: 704 SCARG(&ia, com) = TIOCNOTTY; 705 break; 706 case LINUX_TCSBRK: 707 SCARG(&ia, com) = SCARG(uap, data) ? TIOCDRAIN : TIOCSBRK; 708 break; 709 case LINUX_TIOCMGET: 710 SCARG(&ia, com) = TIOCMGET; 711 break; 712 case LINUX_TIOCMSET: 713 SCARG(&ia, com) = TIOCMSET; 714 break; 715 case LINUX_TIOCMBIC: 716 SCARG(&ia, com) = TIOCMBIC; 717 break; 718 case LINUX_TIOCMBIS: 719 SCARG(&ia, com) = TIOCMBIS; 720 break; 721 #ifdef LINUX_TIOCGPTN 722 case LINUX_TIOCGPTN: 723 #ifndef NO_DEV_PTM 724 { 725 caddr_t sg = stackgap_init(l->l_proc, 0); 726 struct ptmget ptm, *ptmp = stackgap_alloc(l->l_proc, &sg, 727 sizeof(*ptmp)); 728 729 SCARG(&ia, fd) = SCARG(uap, fd); 730 SCARG(&ia, com) = TIOCPTSNAME; 731 SCARG(&ia, data) = ptmp; 732 733 if ((error = sys_ioctl(curlwp, &ia, retval)) != 0) 734 goto out; 735 736 if ((error = copyin(ptmp, &ptm, sizeof(ptm))) != 0) 737 printf("copyin %d\n", error); 738 739 error = copyout(&ptm.sfd, SCARG(uap, data), 740 sizeof(ptm.sfd)); 741 goto out; 742 } 743 #endif /* NO_DEV_PTM */ 744 #endif /* LINUX_TIOCGPTN */ 745 default: 746 error = EINVAL; 747 goto out; 748 } 749 750 SCARG(&ia, fd) = SCARG(uap, fd); 751 SCARG(&ia, data) = SCARG(uap, data); 752 /* XXX NJWLWP */ 753 error = sys_ioctl(curlwp, &ia, retval); 754 out: 755 FILE_UNUSE(fp, l); 756 return error; 757 } 758