xref: /original-bsd/sys/kern/tty_compat.c (revision fac0c393)
1 /*-
2  * Copyright (c) 1982, 1986, 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)tty_compat.c	8.2 (Berkeley) 01/09/95
8  */
9 
10 /*
11  * mapping routines for old line discipline (yuck)
12  */
13 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
14 
15 #include <sys/param.h>
16 #include <sys/systm.h>
17 #include <sys/ioctl.h>
18 #include <sys/proc.h>
19 #include <sys/tty.h>
20 #include <sys/termios.h>
21 #include <sys/file.h>
22 #include <sys/conf.h>
23 #include <sys/kernel.h>
24 #include <sys/syslog.h>
25 
26 int ttydebug = 0;
27 
28 static struct speedtab compatspeeds[] = {
29 	{ 38400, 15 },
30 	{ 19200, 14 },
31 	{ 9600,	13 },
32 	{ 4800,	12 },
33 	{ 2400,	11 },
34 	{ 1800,	10 },
35 	{ 1200,	9 },
36 	{ 600,	8 },
37 	{ 300,	7 },
38 	{ 200,	6 },
39 	{ 150,	5 },
40 	{ 134,	4 },
41 	{ 110,	3 },
42 	{ 75,	2 },
43 	{ 50,	1 },
44 	{ 0,	0 },
45 	{ -1,	-1 },
46 };
47 static int compatspcodes[16] = {
48 	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
49 	1800, 2400, 4800, 9600, 19200, 38400,
50 };
51 
52 /*ARGSUSED*/
53 ttcompat(tp, com, data, flag)
54 	register struct tty *tp;
55 	u_long com;
56 	caddr_t data;
57 	int flag;
58 {
59 
60 	switch (com) {
61 	case TIOCGETP: {
62 		register struct sgttyb *sg = (struct sgttyb *)data;
63 		register u_char *cc = tp->t_cc;
64 		register speed;
65 
66 		speed = ttspeedtab(tp->t_ospeed, compatspeeds);
67 		sg->sg_ospeed = (speed == -1) ? 15 : speed;
68 		if (tp->t_ispeed == 0)
69 			sg->sg_ispeed = sg->sg_ospeed;
70 		else {
71 			speed = ttspeedtab(tp->t_ispeed, compatspeeds);
72 			sg->sg_ispeed = (speed == -1) ? 15 : speed;
73 		}
74 		sg->sg_erase = cc[VERASE];
75 		sg->sg_kill = cc[VKILL];
76 		sg->sg_flags = ttcompatgetflags(tp);
77 		break;
78 	}
79 
80 	case TIOCSETP:
81 	case TIOCSETN: {
82 		register struct sgttyb *sg = (struct sgttyb *)data;
83 		struct termios term;
84 		int speed;
85 
86 		term = tp->t_termios;
87 		if ((speed = sg->sg_ispeed) > 15 || speed < 0)
88 			term.c_ispeed = speed;
89 		else
90 			term.c_ispeed = compatspcodes[speed];
91 		if ((speed = sg->sg_ospeed) > 15 || speed < 0)
92 			term.c_ospeed = speed;
93 		else
94 			term.c_ospeed = compatspcodes[speed];
95 		term.c_cc[VERASE] = sg->sg_erase;
96 		term.c_cc[VKILL] = sg->sg_kill;
97 		tp->t_flags = tp->t_flags&0xffff0000 | sg->sg_flags&0xffff;
98 		ttcompatsetflags(tp, &term);
99 		return (ttioctl(tp, com == TIOCSETP ? TIOCSETAF : TIOCSETA,
100 			&term, flag));
101 	}
102 
103 	case TIOCGETC: {
104 		struct tchars *tc = (struct tchars *)data;
105 		register u_char *cc = tp->t_cc;
106 
107 		tc->t_intrc = cc[VINTR];
108 		tc->t_quitc = cc[VQUIT];
109 		tc->t_startc = cc[VSTART];
110 		tc->t_stopc = cc[VSTOP];
111 		tc->t_eofc = cc[VEOF];
112 		tc->t_brkc = cc[VEOL];
113 		break;
114 	}
115 	case TIOCSETC: {
116 		struct tchars *tc = (struct tchars *)data;
117 		register u_char *cc = tp->t_cc;
118 
119 		cc[VINTR] = tc->t_intrc;
120 		cc[VQUIT] = tc->t_quitc;
121 		cc[VSTART] = tc->t_startc;
122 		cc[VSTOP] = tc->t_stopc;
123 		cc[VEOF] = tc->t_eofc;
124 		cc[VEOL] = tc->t_brkc;
125 		if (tc->t_brkc == -1)
126 			cc[VEOL2] = _POSIX_VDISABLE;
127 		break;
128 	}
129 	case TIOCSLTC: {
130 		struct ltchars *ltc = (struct ltchars *)data;
131 		register u_char *cc = tp->t_cc;
132 
133 		cc[VSUSP] = ltc->t_suspc;
134 		cc[VDSUSP] = ltc->t_dsuspc;
135 		cc[VREPRINT] = ltc->t_rprntc;
136 		cc[VDISCARD] = ltc->t_flushc;
137 		cc[VWERASE] = ltc->t_werasc;
138 		cc[VLNEXT] = ltc->t_lnextc;
139 		break;
140 	}
141 	case TIOCGLTC: {
142 		struct ltchars *ltc = (struct ltchars *)data;
143 		register u_char *cc = tp->t_cc;
144 
145 		ltc->t_suspc = cc[VSUSP];
146 		ltc->t_dsuspc = cc[VDSUSP];
147 		ltc->t_rprntc = cc[VREPRINT];
148 		ltc->t_flushc = cc[VDISCARD];
149 		ltc->t_werasc = cc[VWERASE];
150 		ltc->t_lnextc = cc[VLNEXT];
151 		break;
152 	}
153 	case TIOCLBIS:
154 	case TIOCLBIC:
155 	case TIOCLSET: {
156 		struct termios term;
157 
158 		term = tp->t_termios;
159 		if (com == TIOCLSET)
160 			tp->t_flags = (tp->t_flags&0xffff) | *(int *)data<<16;
161 		else {
162 			tp->t_flags =
163 			 (ttcompatgetflags(tp)&0xffff0000)|(tp->t_flags&0xffff);
164 			if (com == TIOCLBIS)
165 				tp->t_flags |= *(int *)data<<16;
166 			else
167 				tp->t_flags &= ~(*(int *)data<<16);
168 		}
169 		ttcompatsetlflags(tp, &term);
170 		return (ttioctl(tp, TIOCSETA, &term, flag));
171 	}
172 	case TIOCLGET:
173 		*(int *)data = ttcompatgetflags(tp)>>16;
174 		if (ttydebug)
175 			printf("CLGET: returning %x\n", *(int *)data);
176 		break;
177 
178 	case OTIOCGETD:
179 		*(int *)data = tp->t_line ? tp->t_line : 2;
180 		break;
181 
182 	case OTIOCSETD: {
183 		int ldisczero = 0;
184 
185 		return (ttioctl(tp, TIOCSETD,
186 			*(int *)data == 2 ? (caddr_t)&ldisczero : data, flag));
187 	    }
188 
189 	case OTIOCCONS:
190 		*(int *)data = 1;
191 		return (ttioctl(tp, TIOCCONS, data, flag));
192 
193 	default:
194 		return (-1);
195 	}
196 	return (0);
197 }
198 
199 ttcompatgetflags(tp)
200 	register struct tty *tp;
201 {
202 	register long iflag = tp->t_iflag;
203 	register long lflag = tp->t_lflag;
204 	register long oflag = tp->t_oflag;
205 	register long cflag = tp->t_cflag;
206 	register flags = 0;
207 
208 	if (iflag&IXOFF)
209 		flags |= TANDEM;
210 	if (iflag&ICRNL || oflag&ONLCR)
211 		flags |= CRMOD;
212 	if (cflag&PARENB) {
213 		if (iflag&INPCK) {
214 			if (cflag&PARODD)
215 				flags |= ODDP;
216 			else
217 				flags |= EVENP;
218 		} else
219 			flags |= EVENP | ODDP;
220 	} else {
221 		if ((tp->t_flags&LITOUT) && !(oflag&OPOST))
222 			flags |= LITOUT;
223 		if (tp->t_flags&PASS8)
224 			flags |= PASS8;
225 	}
226 
227 	if ((lflag&ICANON) == 0) {
228 		/* fudge */
229 		if (iflag&IXON || lflag&ISIG || lflag&IEXTEN || cflag&PARENB)
230 			flags |= CBREAK;
231 		else
232 			flags |= RAW;
233 	}
234 	if (cflag&MDMBUF)
235 		flags |= MDMBUF;
236 	if ((cflag&HUPCL) == 0)
237 		flags |= NOHANG;
238 	if (oflag&OXTABS)
239 		flags |= XTABS;
240 	if (lflag&ECHOE)
241 		flags |= CRTERA|CRTBS;
242 	if (lflag&ECHOKE)
243 		flags |= CRTKIL|CRTBS;
244 	if (lflag&ECHOPRT)
245 		flags |= PRTERA;
246 	if (lflag&ECHOCTL)
247 		flags |= CTLECH;
248 	if ((iflag&IXANY) == 0)
249 		flags |= DECCTQ;
250 	flags |= lflag&(ECHO|TOSTOP|FLUSHO|PENDIN|NOFLSH);
251 if (ttydebug)
252 	printf("getflags: %x\n", flags);
253 	return (flags);
254 }
255 
256 ttcompatsetflags(tp, t)
257 	register struct tty *tp;
258 	register struct termios *t;
259 {
260 	register flags = tp->t_flags;
261 	register long iflag = t->c_iflag;
262 	register long oflag = t->c_oflag;
263 	register long lflag = t->c_lflag;
264 	register long cflag = t->c_cflag;
265 
266 	if (flags & RAW) {
267 		iflag &= IXOFF;
268 		oflag &= ~OPOST;
269 		lflag &= ~(ECHOCTL|ISIG|ICANON|IEXTEN);
270 	} else {
271 		iflag |= BRKINT|IXON|IMAXBEL;
272 		oflag |= OPOST;
273 		lflag |= ISIG|IEXTEN|ECHOCTL;	/* XXX was echoctl on ? */
274 		if (flags & XTABS)
275 			oflag |= OXTABS;
276 		else
277 			oflag &= ~OXTABS;
278 		if (flags & CBREAK)
279 			lflag &= ~ICANON;
280 		else
281 			lflag |= ICANON;
282 		if (flags&CRMOD) {
283 			iflag |= ICRNL;
284 			oflag |= ONLCR;
285 		} else {
286 			iflag &= ~ICRNL;
287 			oflag &= ~ONLCR;
288 		}
289 	}
290 	if (flags&ECHO)
291 		lflag |= ECHO;
292 	else
293 		lflag &= ~ECHO;
294 
295 	if (flags&(RAW|LITOUT|PASS8)) {
296 		cflag &= ~(CSIZE|PARENB);
297 		cflag |= CS8;
298 		if ((flags&(RAW|PASS8)) == 0)
299 			iflag |= ISTRIP;
300 		else
301 			iflag &= ~ISTRIP;
302 	} else {
303 		cflag &= ~CSIZE;
304 		cflag |= CS7|PARENB;
305 		iflag |= ISTRIP;
306 	}
307 	if ((flags&(EVENP|ODDP)) == EVENP) {
308 		iflag |= INPCK;
309 		cflag &= ~PARODD;
310 	} else if ((flags&(EVENP|ODDP)) == ODDP) {
311 		iflag |= INPCK;
312 		cflag |= PARODD;
313 	} else
314 		iflag &= ~INPCK;
315 	if (flags&LITOUT)
316 		oflag &= ~OPOST;	/* move earlier ? */
317 	if (flags&TANDEM)
318 		iflag |= IXOFF;
319 	else
320 		iflag &= ~IXOFF;
321 	t->c_iflag = iflag;
322 	t->c_oflag = oflag;
323 	t->c_lflag = lflag;
324 	t->c_cflag = cflag;
325 }
326 
327 ttcompatsetlflags(tp, t)
328 	register struct tty *tp;
329 	register struct termios *t;
330 {
331 	register flags = tp->t_flags;
332 	register long iflag = t->c_iflag;
333 	register long oflag = t->c_oflag;
334 	register long lflag = t->c_lflag;
335 	register long cflag = t->c_cflag;
336 
337 	if (flags&CRTERA)
338 		lflag |= ECHOE;
339 	else
340 		lflag &= ~ECHOE;
341 	if (flags&CRTKIL)
342 		lflag |= ECHOKE;
343 	else
344 		lflag &= ~ECHOKE;
345 	if (flags&PRTERA)
346 		lflag |= ECHOPRT;
347 	else
348 		lflag &= ~ECHOPRT;
349 	if (flags&CTLECH)
350 		lflag |= ECHOCTL;
351 	else
352 		lflag &= ~ECHOCTL;
353 	if ((flags&DECCTQ) == 0)
354 		iflag |= IXANY;
355 	else
356 		iflag &= ~IXANY;
357 	if (flags & MDMBUF)
358 		cflag |= MDMBUF;
359 	else
360 		cflag &= ~MDMBUF;
361 	if (flags&NOHANG)
362 		cflag &= ~HUPCL;
363 	else
364 		cflag |= HUPCL;
365 	lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH);
366 	lflag |= flags&(TOSTOP|FLUSHO|PENDIN|NOFLSH);
367 	if (flags&(LITOUT|PASS8)) {
368 		iflag &= ~ISTRIP;
369 		cflag &= ~(CSIZE|PARENB);
370 		cflag |= CS8;
371 		if (flags&LITOUT)
372 			oflag &= ~OPOST;
373 		if ((flags&(PASS8|RAW)) == 0)
374 			iflag |= ISTRIP;
375 	} else if ((flags&RAW) == 0) {
376 		cflag &= ~CSIZE;
377 		cflag |= CS7|PARENB;
378 		oflag |= OPOST;
379 	}
380 	t->c_iflag = iflag;
381 	t->c_oflag = oflag;
382 	t->c_lflag = lflag;
383 	t->c_cflag = cflag;
384 }
385 #endif	/* COMPAT_43 || COMPAT_SUNOS */
386