2 * ========================================================================
3 * Copyright 2006 University of Washington
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * ========================================================================
21 #include "../estruct.h"
28 * These are the TERMIOS-style (POSIX) routines.
31 static struct termios _raw_tty
, _original_tty
;
35 * These are the TERMIO-style (System V) routines.
38 static struct termio _raw_tty
, _original_tty
;
42 * These are for the BSD-style routines.
45 static struct sgttyb _raw_tty
, _original_tty
;
46 static struct ltchars _raw_ltchars
, _original_ltchars
;
47 static struct tchars _raw_tchars
, _original_tchars
;
48 static int _raw_lmode
, _original_lmode
;
55 static short _inraw
= 0;
58 * Set up the tty driver
60 * Args: state -- which state to put it in. 1 means go into raw (cbreak),
63 * Result: returns 0 if successful and -1 if not.
68 /** state is either ON or OFF, as indicated by call **/
69 /* Check return code only on first call. If it fails we're done for and
70 if it goes OK the others will probably go OK too. */
72 if(state
== 0 && _inraw
){
73 /*----- restore state to original -----*/
77 if(tcsetattr(STDIN_FD
, TCSADRAIN
, &_original_tty
) < 0)
82 if(ioctl(STDIN_FD
, TCSETAW
, &_original_tty
) < 0)
87 if(ioctl(STDIN_FD
, TIOCSETP
, &_original_tty
) < 0)
90 (void)ioctl(STDIN_FD
, TIOCSLTC
, &_original_ltchars
);
91 (void)ioctl(STDIN_FD
, TIOCSETC
, &_original_tchars
);
92 (void)ioctl(STDIN_FD
, TIOCLSET
, &_original_lmode
);
98 else if(state
== 1 && ! _inraw
){
99 /*----- Go into raw mode (cbreak actually) ----*/
103 if(tcgetattr(STDIN_FD
, &_original_tty
) < 0)
106 tcgetattr(STDIN_FD
, &_raw_tty
);
107 _raw_tty
.c_lflag
&= ~(ICANON
| ECHO
| IEXTEN
); /* noecho raw mode */
108 _raw_tty
.c_lflag
&= ~ISIG
; /* disable signals */
109 _raw_tty
.c_iflag
&= ~ICRNL
; /* turn off CR->NL on input */
110 _raw_tty
.c_oflag
&= ~ONLCR
; /* turn off NL->CR on output */
112 _raw_tty
.c_cc
[VMIN
] = '\01'; /* min # of chars to queue */
113 _raw_tty
.c_cc
[VTIME
] = '\0'; /* min time to wait for input*/
114 _raw_tty
.c_cc
[VINTR
] = ctrl('C'); /* make it our special char */
115 _raw_tty
.c_cc
[VQUIT
] = 0;
116 _raw_tty
.c_cc
[VSUSP
] = 0;
117 tcsetattr(STDIN_FD
, TCSADRAIN
, &_raw_tty
);
121 if(ioctl(STDIN_FD
, TCGETA
, &_original_tty
) < 0)
124 (void)ioctl(STDIN_FD
, TCGETA
, &_raw_tty
); /** again! **/
125 _raw_tty
.c_lflag
&= ~(ICANON
| ECHO
); /* noecho raw mode */
126 _raw_tty
.c_lflag
&= ~ISIG
; /* disable signals */
127 _raw_tty
.c_iflag
&= ~ICRNL
; /* turn off CR->NL on input */
128 _raw_tty
.c_oflag
&= ~ONLCR
; /* turn off NL->CR on output */
129 _raw_tty
.c_cc
[VMIN
] = 1; /* min # of chars to queue */
130 _raw_tty
.c_cc
[VTIME
] = 0; /* min time to wait for input*/
131 _raw_tty
.c_cc
[VINTR
] = ctrl('C'); /* make it our special char */
132 _raw_tty
.c_cc
[VQUIT
] = 0;
133 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
136 if(ioctl(STDIN_FD
, TIOCGETP
, &_original_tty
) < 0)
139 (void)ioctl(STDIN_FD
, TIOCGETP
, &_raw_tty
);
140 (void)ioctl(STDIN_FD
, TIOCGETC
, &_original_tchars
);
141 (void)ioctl(STDIN_FD
, TIOCGETC
, &_raw_tchars
);
142 (void)ioctl(STDIN_FD
, TIOCGLTC
, &_original_ltchars
);
143 (void)ioctl(STDIN_FD
, TIOCGLTC
, &_raw_ltchars
);
144 (void)ioctl(STDIN_FD
, TIOCLGET
, &_original_lmode
);
145 (void)ioctl(STDIN_FD
, TIOCLGET
, &_raw_lmode
);
147 _raw_tty
.sg_flags
&= ~(ECHO
); /* echo off */
148 _raw_tty
.sg_flags
|= CBREAK
; /* raw on */
149 _raw_tty
.sg_flags
&= ~CRMOD
; /* Turn off CR -> LF mapping */
151 _raw_tchars
.t_intrc
= -1; /* Turn off ^C and ^D */
152 _raw_tchars
.t_eofc
= -1;
154 _raw_ltchars
.t_lnextc
= -1; /* Turn off ^V so we can use it */
155 _raw_ltchars
.t_dsuspc
= -1; /* Turn off ^Y so we can use it */
156 _raw_ltchars
.t_suspc
= -1; /* Turn off ^Z; we just read 'em */
157 _raw_ltchars
.t_werasc
= -1; /* Turn off ^w word erase */
158 _raw_ltchars
.t_rprntc
= -1; /* Turn off ^R reprint line */
159 _raw_ltchars
.t_flushc
= -1; /* Turn off ^O output flush */
161 (void)ioctl(STDIN_FD
, TIOCSETP
, &_raw_tty
);
162 (void)ioctl(STDIN_FD
, TIOCSLTC
, &_raw_ltchars
);
163 (void)ioctl(STDIN_FD
, TIOCSETC
, &_raw_tchars
);
164 (void)ioctl(STDIN_FD
, TIOCLSET
, &_raw_lmode
);
174 * Set up the tty driver to use XON/XOFF flow control
176 * Args: state -- True to make sure XON/XOFF turned on, FALSE off.
181 xonxoff_proc(int state
)
187 if(!(_raw_tty
.c_iflag
& IXON
)){
188 _raw_tty
.c_iflag
|= IXON
;
189 tcsetattr (STDIN_FD
, TCSADRAIN
, &_raw_tty
);
194 if(!(_raw_tty
.c_iflag
& IXON
)){
195 _raw_tty
.c_iflag
|= IXON
; /* turn ON ^S/^Q on input */
196 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
200 if(_raw_tchars
.t_startc
== -1 || _raw_tchars
.t_stopc
== -1){
201 _raw_tchars
.t_startc
= 'Q' - '@'; /* Turn ON ^S/^Q */
202 _raw_tchars
.t_stopc
= 'S' - '@';
203 (void)ioctl(STDIN_FD
, TIOCSETC
, &_raw_tchars
);
211 if(_raw_tty
.c_iflag
& IXON
){
212 _raw_tty
.c_iflag
&= ~IXON
; /* turn off ^S/^Q on input */
213 tcsetattr (STDIN_FD
, TCSADRAIN
, &_raw_tty
);
218 if(_raw_tty
.c_iflag
& IXON
){
219 _raw_tty
.c_iflag
&= ~IXON
; /* turn off ^S/^Q on input */
220 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
224 if(!(_raw_tchars
.t_startc
== -1 && _raw_tchars
.t_stopc
== -1)){
225 _raw_tchars
.t_startc
= -1; /* Turn off ^S/^Q */
226 _raw_tchars
.t_stopc
= -1;
227 (void)ioctl(STDIN_FD
, TIOCSETC
, &_raw_tchars
);
236 * Set up the tty driver to do LF->CR translation
238 * Args: state -- True to turn on translation, false to write raw LF's
246 if(state
){ /* turn ON NL->CR on output */
249 if(!(_raw_tty
.c_oflag
& ONLCR
)){
250 _raw_tty
.c_oflag
|= ONLCR
;
251 tcsetattr (STDIN_FD
, TCSADRAIN
, &_raw_tty
);
256 if(!(_raw_tty
.c_oflag
& ONLCR
)){
257 _raw_tty
.c_oflag
|= ONLCR
;
258 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
262 if(!(_raw_tty
.sg_flags
& CRMOD
)){
263 _raw_tty
.sg_flags
|= CRMOD
;
264 (void)ioctl(STDIN_FD
, TIOCSETP
, &_raw_tty
);
268 else{ /* turn OFF NL-CR on output */
271 if(_raw_tty
.c_oflag
& ONLCR
){
272 _raw_tty
.c_oflag
&= ~ONLCR
;
273 tcsetattr (STDIN_FD
, TCSADRAIN
, &_raw_tty
);
278 if(_raw_tty
.c_oflag
& ONLCR
){
279 _raw_tty
.c_oflag
&= ~ONLCR
;
280 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
285 if(_raw_tty
.sg_flags
& CRMOD
){
286 _raw_tty
.sg_flags
&= ~CRMOD
;
287 (void)ioctl(STDIN_FD
, TIOCSETP
, &_raw_tty
);
297 * Set up the tty driver to handle interrupt char
299 * Args: state -- True to turn on interrupt char, false to not
301 * Result: tty driver that'll send us SIGINT or not
310 _raw_tty
.c_lflag
|= ISIG
; /* enable signals */
311 tcsetattr(STDIN_FD
, TCSADRAIN
, &_raw_tty
);
315 _raw_tty
.c_lflag
|= ISIG
; /* enable signals */
316 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
320 _raw_tchars
.t_intrc
= ctrl('C');
321 (void)ioctl(STDIN_FD
, TIOCSETC
, &_raw_tchars
);
328 _raw_tty
.c_lflag
&= ~ISIG
; /* disable signals */
329 tcsetattr(STDIN_FD
, TCSADRAIN
, &_raw_tty
);
333 _raw_tty
.c_lflag
&= ~ISIG
; /* disable signals */
334 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
337 _raw_tchars
.t_intrc
= -1;
338 (void)ioctl(STDIN_FD
, TIOCSETC
, &_raw_tchars
);
346 * Discard any pending input characters
350 * Result: pending input buffer flushed
357 tcflush(STDIN_FD
, TCIFLUSH
);
361 ioctl(STDIN_FD
, TCFLSH
, 0);
371 ioctl(STDIN_FD
, TIOCFLUSH
, &i
);
372 #endif /* TIOCFLUSH */
379 * Turn off hi bit stripping
386 _raw_tty
.c_iflag
&= ~ISTRIP
;
387 tcsetattr(STDIN_FD
, TCSADRAIN
, &_raw_tty
);
396 _raw_lmode
|= LPASS8
;
400 _raw_lmode
|= LPASS8OUT
;
403 (void)ioctl(STDIN_FD
, TIOCLSET
, &_raw_lmode
);
410 * Turn off quit character (^\) if possible
420 _raw_tchars
.t_quitc
= -1;
421 (void)ioctl(STDIN_FD
, TIOCSETC
, &_raw_tchars
);
427 * Returns TRUE if tty is < 4800, 0 otherwise.
434 return(cfgetospeed(&_raw_tty
) < B4800
);
438 return((_raw_tty
.c_cflag
&CBAUD
) < (unsigned int)B4800
);
442 return((int)_raw_tty
.sg_ispeed
< B4800
);