1 /* $Header: /p/tcsh/cvsroot/tcsh/mi.termios.c,v 1.5 2006/03/02 18:46:44 christos Exp $ */
2 /* termios.c - fake termios interface using sgtty interface
3 * by Magnus Doell and Bruce Evans.
7 RCSID("$tcsh: mi.termios.c,v 1.5 2006/03/02 18:46:44 christos Exp $")
9 #if defined(_MINIX) && !defined(_MINIX_VMD)
12 /* Undefine everything that clashes with sgtty.h. */
32 /* Do not #undef CRMOD. We want a warning when they differ! */
34 /* Do not #undef XTABS. We want a warning when they differ! */
36 /* Redefine some of the termios.h names just undefined with 'T_' prefixed
37 * to the name. Don't bother with the low speeds - Minix does not support
38 * them. Add support for higher speeds (speeds are now easy and don't need
39 * defines because they are not encoded).
46 static _PROTOTYPE( int tc_to_sg_speed
, (speed_t speed
) );
47 static _PROTOTYPE( speed_t sg_to_tc_speed
, (int speed
) );
50 /* The speed get/set functions could be macros in the Minix implementation
51 * because there are speed fields in the structure with no fancy packing
52 * and it is not practical to check the values outside the driver.
53 * Where tests are necessary because the driver acts different from what
54 * POSIX requires, they are done in tcsetattr.
57 speed_t
cfgetispeed(termios_p
)
58 struct termios
*termios_p
;
60 return termios_p
->c_ispeed
;
63 speed_t
cfgetospeed(termios_p
)
64 struct termios
*termios_p
;
66 return termios_p
->c_ospeed
;
69 speed_t
cfsetispeed(termios_p
, speed
)
70 struct termios
*termios_p
;
73 termios_p
->c_ispeed
= speed
;
77 speed_t
cfsetospeed(termios_p
, speed
)
78 struct termios
*termios_p
;
81 termios_p
->c_ospeed
= speed
;
85 static speed_t
sg_to_tc_speed(speed
)
88 /* The speed encodings in sgtty.h and termios.h are different. Both are
89 * inflexible. Minix doesn't really support B0 but we map it through
90 * anyway. It doesn't support B50, B75 or B134.
94 case B110
: return 110;
95 case B200
: return 200;
96 case B300
: return 300;
97 case B600
: return 600;
98 case B1200
: return 1200;
99 case B1800
: return 1800;
100 case B2400
: return 2400;
101 case B4800
: return 4800;
102 case B9600
: return 9600;
103 case B19200
: return 19200;
105 case B28800
: return 28800;
108 case B38400
: return 38400;
111 case B57600
: return 57600;
114 case B115200
: return 115200;
116 default: return (speed_t
)-1;
120 static int tc_to_sg_speed(speed
)
123 /* Don't use a switch here in case the compiler is 16-bit and doesn't
124 * properly support longs (speed_t's) in switches. It turns out the
125 * switch is larger and slower for most compilers anyway!
127 if (speed
== 0) return 0;
128 if (speed
== 110) return B110
;
129 if (speed
== 200) return B200
;
130 if (speed
== 300) return B300
;
131 if (speed
== 600) return B600
;
132 if (speed
== 1200) return B1200
;
133 if (speed
== 1800) return B1800
;
134 if (speed
== 2400) return B2400
;
135 if (speed
== 4800) return B4800
;
136 if (speed
== 9600) return B9600
;
137 if (speed
== 19200) return B19200
;
139 if (speed
== 28800) return B28800
;
142 if (speed
== 38400) return B38400
;
145 if (speed
== 57600) return B57600
;
148 if (speed
== 115200) return B115200
;
153 int tcgetattr(filedes
, termios_p
)
155 struct termios
*termios_p
;
160 if (ioctl(filedes
, TIOCGETP
, &sgbuf
) < 0
161 || ioctl(filedes
, TIOCGETC
, (struct sgttyb
*) &tcbuf
) < 0)
166 /* Minix input flags:
167 * BRKINT: forced off (break is not recognized)
168 * IGNBRK: forced on (break is not recognized)
169 * ICRNL: set if CRMOD is set and not RAW (CRMOD also controls output)
170 * IGNCR: forced off (ignoring cr's is not supported)
171 * INLCR: forced off (mapping nl's to cr's is not supported)
172 * ISTRIP: forced off (should be off for consoles, on for rs232 no RAW)
173 * IXOFF: forced off (rs232 uses CTS instead of XON/XOFF)
174 * IXON: forced on if not RAW
175 * PARMRK: forced off (no '\377', '\0', X sequence on errors)
176 * ? IGNPAR: forced off (input with parity/framing errors is kept)
177 * ? INPCK: forced off (input parity checking is not supported)
179 termios_p
->c_iflag
= IGNBRK
;
180 if (!(sgbuf
.sg_flags
& RAW
))
182 termios_p
->c_iflag
|= IXON
;
183 if (sgbuf
.sg_flags
& CRMOD
)
185 termios_p
->c_iflag
|= ICRNL
;
189 /* Minix output flags:
190 * OPOST: set if CRMOD or XTABS is set
191 * XTABS: copied from sg_flags
192 * CRMOD: copied from sg_flags
194 termios_p
->c_oflag
= sgbuf
.sg_flags
& (CRMOD
| XTABS
);
195 if (termios_p
->c_oflag
)
197 termios_p
->c_oflag
|= OPOST
;
200 /* Minix local flags:
201 * ECHO: set if ECHO is set
202 * ECHOE: set if ECHO is set (ERASE echoed as error-corecting backspace)
203 * ECHOK: set if ECHO is set ('\n' echoed after KILL char)
204 * ECHONL: forced off ('\n' not echoed when ECHO isn't set)
205 * ICANON: set if neither CBREAK nor RAW
207 * ISIG: set if not RAW
208 * NOFLSH: forced off (input/output queues are always flushed)
209 * TOSTOP: forced off (no job control)
211 termios_p
->c_lflag
= 0;
212 if (sgbuf
.sg_flags
& ECHO
)
214 termios_p
->c_lflag
|= T_ECHO
| ECHOE
| ECHOK
;
216 if (!(sgbuf
.sg_flags
& RAW
))
218 termios_p
->c_lflag
|= ISIG
;
219 if (!(sgbuf
.sg_flags
& CBREAK
))
221 termios_p
->c_lflag
|= ICANON
;
225 /* Minix control flags:
226 * CLOCAL: forced on (ignore modem status lines - not quite right)
227 * CREAD: forced on (receiver is always enabled)
228 * CSIZE: CS5-CS8 correspond directly to BITS5-BITS8
229 * CSTOPB: set for B110 (driver will generate 2 stop-bits than)
231 * PARENB: set if EVENP or ODDP is set
232 * PARODD: set if ODDP is set
234 termios_p
->c_cflag
= CLOCAL
| CREAD
;
235 switch (sgbuf
.sg_flags
& BITS8
)
237 case BITS5
: termios_p
->c_cflag
|= CS5
; break;
238 case BITS6
: termios_p
->c_cflag
|= CS6
; break;
239 case BITS7
: termios_p
->c_cflag
|= CS7
; break;
240 case BITS8
: termios_p
->c_cflag
|= CS8
; break;
242 if (sgbuf
.sg_flags
& ODDP
)
244 termios_p
->c_cflag
|= PARENB
| PARODD
;
246 if (sgbuf
.sg_flags
& EVENP
)
248 termios_p
->c_cflag
|= PARENB
;
250 if (sgbuf
.sg_ispeed
== B110
)
252 termios_p
->c_cflag
|= CSTOPB
;
255 /* Minix may give back different input and output baudrates,
256 * but only the input baudrate is valid for both.
257 * As our termios emulation will fail, if input baudrate differs
258 * from output baudrate, force them to be equal.
259 * Otherwise it would be very suprisingly not to be able to set
260 * the terminal back to the state returned by tcgetattr :).
262 termios_p
->c_ospeed
=
263 termios_p
->c_ispeed
=
264 sg_to_tc_speed((unsigned char) sgbuf
.sg_ispeed
);
266 /* Minix control characters correspond directly except VSUSP and the
267 * important VMIN and VTIME are not really supported.
269 termios_p
->c_cc
[VEOF
] = tcbuf
.t_eofc
;
270 termios_p
->c_cc
[VEOL
] = tcbuf
.t_brkc
;
271 termios_p
->c_cc
[VERASE
] = sgbuf
.sg_erase
;
272 termios_p
->c_cc
[VINTR
] = tcbuf
.t_intrc
;
273 termios_p
->c_cc
[VKILL
] = sgbuf
.sg_kill
;
274 termios_p
->c_cc
[VQUIT
] = tcbuf
.t_quitc
;
275 termios_p
->c_cc
[VSTART
] = tcbuf
.t_startc
;
276 termios_p
->c_cc
[VSTOP
] = tcbuf
.t_stopc
;
277 termios_p
->c_cc
[VMIN
] = 1;
278 termios_p
->c_cc
[VTIME
] = 0;
279 termios_p
->c_cc
[VSUSP
] = 0;
284 int tcsetattr(filedes
, opt_actions
, termios_p
)
287 struct termios
*termios_p
;
293 /* Posix 1003.1-1988 page 135 says:
294 * Attempts to set unsupported baud rates shall be ignored, and it is
295 * implementation-defined whether an error is returned by any or all of
296 * cfsetispeed(), cfsetospeed(), or tcsetattr(). This refers both to
297 * changes to baud rates not supported by the hardware, and to changes
298 * setting the input and output baud rates to different values if the
299 * hardware does not support it.
300 * Ignoring means not to change the existing settings, doesn't it?
302 if ((termios_p
->c_ispeed
!= 0 && termios_p
->c_ispeed
!= termios_p
->c_ospeed
)
303 || (sgspeed
= tc_to_sg_speed(termios_p
->c_ospeed
)) < 0)
309 sgbuf
.sg_ispeed
= sgbuf
.sg_ospeed
= sgspeed
;
312 /* I don't know what should happen with requests that are not supported by
313 * old Minix drivers and therefore cannot be emulated.
314 * Returning an error may confuse the application (the values aren't really
315 * invalid or unsupported by the hardware, they just couldn't be satisfied
316 * by the driver). Not returning an error might be even worse because the
317 * driver will act different to what the application requires it to act
318 * after sucessfully setting the attributes as specified.
319 * Settings that cannot be emulated fully include:
320 * c_ospeed != 110 && c_cflag & CSTOPB
321 * c_ospeed == 110 && ! c_cflag & CSTOPB
322 * (c_cc[VMIN] != 1 || c_cc[VTIME] != 0) && ! c_lflag & ICANON
323 * c_lflag & ICANON && ! c_lflag & ISIG
324 * For the moment I just ignore these conflicts.
327 if (termios_p
->c_oflag
& OPOST
)
329 /* CRMOD isn't Posix and may conflict with ICRNL, which is Posix,
330 * so we just ignore it.
332 if (termios_p
->c_oflag
& XTABS
)
334 sgbuf
.sg_flags
|= XTABS
;
338 if (termios_p
->c_iflag
& ICRNL
)
340 /* We couldn't do it better :-(. */
341 sgbuf
.sg_flags
|= CRMOD
;
344 if (termios_p
->c_lflag
& T_ECHO
)
346 sgbuf
.sg_flags
|= ECHO
;
348 if (!(termios_p
->c_lflag
& ICANON
))
350 if (termios_p
->c_lflag
& ISIG
)
352 sgbuf
.sg_flags
|= CBREAK
;
356 sgbuf
.sg_flags
|= RAW
;
360 switch (termios_p
->c_cflag
& CSIZE
)
362 case CS5
: sgbuf
.sg_flags
|= BITS5
; break;
363 case CS6
: sgbuf
.sg_flags
|= BITS6
; break;
364 case CS7
: sgbuf
.sg_flags
|= BITS7
; break;
365 case CS8
: sgbuf
.sg_flags
|= BITS8
; break;
367 if (termios_p
->c_cflag
& PARENB
)
369 if (termios_p
->c_cflag
& PARODD
)
371 sgbuf
.sg_flags
|= ODDP
;
375 sgbuf
.sg_flags
|= EVENP
;
379 sgbuf
.sg_erase
= termios_p
->c_cc
[VERASE
];
380 sgbuf
.sg_kill
= termios_p
->c_cc
[VKILL
];
382 tcbuf
.t_intrc
= termios_p
->c_cc
[VINTR
];
383 tcbuf
.t_quitc
= termios_p
->c_cc
[VQUIT
];
384 tcbuf
.t_startc
= termios_p
->c_cc
[VSTART
];
385 tcbuf
.t_stopc
= termios_p
->c_cc
[VSTOP
];
386 tcbuf
.t_eofc
= termios_p
->c_cc
[VEOF
];
387 tcbuf
.t_brkc
= termios_p
->c_cc
[VEOL
];
389 return ioctl(filedes
, TIOCSETP
, &sgbuf
) < 0 &&
390 ioctl(filedes
, TIOCSETC
, (struct sgttyb
*) &tcbuf
) < 0 ?
393 #endif /* _MINIX && !_MINIX_VMD */