1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: raw.c 761 2007-10-23 22:35:18Z hubert@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2006 University of Washington
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * ========================================================================
25 #include "../estruct.h"
32 * These are the TERMIOS-style (POSIX) routines.
35 static struct termios _raw_tty
, _original_tty
;
39 * These are the TERMIO-style (System V) routines.
42 static struct termio _raw_tty
, _original_tty
;
46 * These are for the BSD-style routines.
49 static struct sgttyb _raw_tty
, _original_tty
;
50 static struct ltchars _raw_ltchars
, _original_ltchars
;
51 static struct tchars _raw_tchars
, _original_tchars
;
52 static int _raw_lmode
, _original_lmode
;
59 static short _inraw
= 0;
62 * Set up the tty driver
64 * Args: state -- which state to put it in. 1 means go into raw (cbreak),
67 * Result: returns 0 if successful and -1 if not.
72 /** state is either ON or OFF, as indicated by call **/
73 /* Check return code only on first call. If it fails we're done for and
74 if it goes OK the others will probably go OK too. */
76 if(state
== 0 && _inraw
){
77 /*----- restore state to original -----*/
81 if(tcsetattr(STDIN_FD
, TCSADRAIN
, &_original_tty
) < 0)
86 if(ioctl(STDIN_FD
, TCSETAW
, &_original_tty
) < 0)
91 if(ioctl(STDIN_FD
, TIOCSETP
, &_original_tty
) < 0)
94 (void)ioctl(STDIN_FD
, TIOCSLTC
, &_original_ltchars
);
95 (void)ioctl(STDIN_FD
, TIOCSETC
, &_original_tchars
);
96 (void)ioctl(STDIN_FD
, TIOCLSET
, &_original_lmode
);
102 else if(state
== 1 && ! _inraw
){
103 /*----- Go into raw mode (cbreak actually) ----*/
107 if(tcgetattr(STDIN_FD
, &_original_tty
) < 0)
110 tcgetattr(STDIN_FD
, &_raw_tty
);
111 _raw_tty
.c_lflag
&= ~(ICANON
| ECHO
| IEXTEN
); /* noecho raw mode */
112 _raw_tty
.c_lflag
&= ~ISIG
; /* disable signals */
113 _raw_tty
.c_iflag
&= ~ICRNL
; /* turn off CR->NL on input */
114 _raw_tty
.c_oflag
&= ~ONLCR
; /* turn off NL->CR on output */
116 _raw_tty
.c_cc
[VMIN
] = '\01'; /* min # of chars to queue */
117 _raw_tty
.c_cc
[VTIME
] = '\0'; /* min time to wait for input*/
118 _raw_tty
.c_cc
[VINTR
] = ctrl('C'); /* make it our special char */
119 _raw_tty
.c_cc
[VQUIT
] = 0;
120 _raw_tty
.c_cc
[VSUSP
] = 0;
121 tcsetattr(STDIN_FD
, TCSADRAIN
, &_raw_tty
);
125 if(ioctl(STDIN_FD
, TCGETA
, &_original_tty
) < 0)
128 (void)ioctl(STDIN_FD
, TCGETA
, &_raw_tty
); /** again! **/
129 _raw_tty
.c_lflag
&= ~(ICANON
| ECHO
); /* noecho raw mode */
130 _raw_tty
.c_lflag
&= ~ISIG
; /* disable signals */
131 _raw_tty
.c_iflag
&= ~ICRNL
; /* turn off CR->NL on input */
132 _raw_tty
.c_oflag
&= ~ONLCR
; /* turn off NL->CR on output */
133 _raw_tty
.c_cc
[VMIN
] = 1; /* min # of chars to queue */
134 _raw_tty
.c_cc
[VTIME
] = 0; /* min time to wait for input*/
135 _raw_tty
.c_cc
[VINTR
] = ctrl('C'); /* make it our special char */
136 _raw_tty
.c_cc
[VQUIT
] = 0;
137 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
140 if(ioctl(STDIN_FD
, TIOCGETP
, &_original_tty
) < 0)
143 (void)ioctl(STDIN_FD
, TIOCGETP
, &_raw_tty
);
144 (void)ioctl(STDIN_FD
, TIOCGETC
, &_original_tchars
);
145 (void)ioctl(STDIN_FD
, TIOCGETC
, &_raw_tchars
);
146 (void)ioctl(STDIN_FD
, TIOCGLTC
, &_original_ltchars
);
147 (void)ioctl(STDIN_FD
, TIOCGLTC
, &_raw_ltchars
);
148 (void)ioctl(STDIN_FD
, TIOCLGET
, &_original_lmode
);
149 (void)ioctl(STDIN_FD
, TIOCLGET
, &_raw_lmode
);
151 _raw_tty
.sg_flags
&= ~(ECHO
); /* echo off */
152 _raw_tty
.sg_flags
|= CBREAK
; /* raw on */
153 _raw_tty
.sg_flags
&= ~CRMOD
; /* Turn off CR -> LF mapping */
155 _raw_tchars
.t_intrc
= -1; /* Turn off ^C and ^D */
156 _raw_tchars
.t_eofc
= -1;
158 _raw_ltchars
.t_lnextc
= -1; /* Turn off ^V so we can use it */
159 _raw_ltchars
.t_dsuspc
= -1; /* Turn off ^Y so we can use it */
160 _raw_ltchars
.t_suspc
= -1; /* Turn off ^Z; we just read 'em */
161 _raw_ltchars
.t_werasc
= -1; /* Turn off ^w word erase */
162 _raw_ltchars
.t_rprntc
= -1; /* Turn off ^R reprint line */
163 _raw_ltchars
.t_flushc
= -1; /* Turn off ^O output flush */
165 (void)ioctl(STDIN_FD
, TIOCSETP
, &_raw_tty
);
166 (void)ioctl(STDIN_FD
, TIOCSLTC
, &_raw_ltchars
);
167 (void)ioctl(STDIN_FD
, TIOCSETC
, &_raw_tchars
);
168 (void)ioctl(STDIN_FD
, TIOCLSET
, &_raw_lmode
);
178 * Set up the tty driver to use XON/XOFF flow control
180 * Args: state -- True to make sure XON/XOFF turned on, FALSE off.
185 xonxoff_proc(int state
)
191 if(!(_raw_tty
.c_iflag
& IXON
)){
192 _raw_tty
.c_iflag
|= IXON
;
193 tcsetattr (STDIN_FD
, TCSADRAIN
, &_raw_tty
);
198 if(!(_raw_tty
.c_iflag
& IXON
)){
199 _raw_tty
.c_iflag
|= IXON
; /* turn ON ^S/^Q on input */
200 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
204 if(_raw_tchars
.t_startc
== -1 || _raw_tchars
.t_stopc
== -1){
205 _raw_tchars
.t_startc
= 'Q' - '@'; /* Turn ON ^S/^Q */
206 _raw_tchars
.t_stopc
= 'S' - '@';
207 (void)ioctl(STDIN_FD
, TIOCSETC
, &_raw_tchars
);
215 if(_raw_tty
.c_iflag
& IXON
){
216 _raw_tty
.c_iflag
&= ~IXON
; /* turn off ^S/^Q on input */
217 tcsetattr (STDIN_FD
, TCSADRAIN
, &_raw_tty
);
222 if(_raw_tty
.c_iflag
& IXON
){
223 _raw_tty
.c_iflag
&= ~IXON
; /* turn off ^S/^Q on input */
224 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
228 if(!(_raw_tchars
.t_startc
== -1 && _raw_tchars
.t_stopc
== -1)){
229 _raw_tchars
.t_startc
= -1; /* Turn off ^S/^Q */
230 _raw_tchars
.t_stopc
= -1;
231 (void)ioctl(STDIN_FD
, TIOCSETC
, &_raw_tchars
);
240 * Set up the tty driver to do LF->CR translation
242 * Args: state -- True to turn on translation, false to write raw LF's
250 if(state
){ /* turn ON NL->CR on output */
253 if(!(_raw_tty
.c_oflag
& ONLCR
)){
254 _raw_tty
.c_oflag
|= ONLCR
;
255 tcsetattr (STDIN_FD
, TCSADRAIN
, &_raw_tty
);
260 if(!(_raw_tty
.c_oflag
& ONLCR
)){
261 _raw_tty
.c_oflag
|= ONLCR
;
262 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
266 if(!(_raw_tty
.sg_flags
& CRMOD
)){
267 _raw_tty
.sg_flags
|= CRMOD
;
268 (void)ioctl(STDIN_FD
, TIOCSETP
, &_raw_tty
);
272 else{ /* turn OFF NL-CR on output */
275 if(_raw_tty
.c_oflag
& ONLCR
){
276 _raw_tty
.c_oflag
&= ~ONLCR
;
277 tcsetattr (STDIN_FD
, TCSADRAIN
, &_raw_tty
);
282 if(_raw_tty
.c_oflag
& ONLCR
){
283 _raw_tty
.c_oflag
&= ~ONLCR
;
284 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
289 if(_raw_tty
.sg_flags
& CRMOD
){
290 _raw_tty
.sg_flags
&= ~CRMOD
;
291 (void)ioctl(STDIN_FD
, TIOCSETP
, &_raw_tty
);
301 * Set up the tty driver to handle interrupt char
303 * Args: state -- True to turn on interrupt char, false to not
305 * Result: tty driver that'll send us SIGINT or not
314 _raw_tty
.c_lflag
|= ISIG
; /* enable signals */
315 tcsetattr(STDIN_FD
, TCSADRAIN
, &_raw_tty
);
319 _raw_tty
.c_lflag
|= ISIG
; /* enable signals */
320 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
324 _raw_tchars
.t_intrc
= ctrl('C');
325 (void)ioctl(STDIN_FD
, TIOCSETC
, &_raw_tchars
);
332 _raw_tty
.c_lflag
&= ~ISIG
; /* disable signals */
333 tcsetattr(STDIN_FD
, TCSADRAIN
, &_raw_tty
);
337 _raw_tty
.c_lflag
&= ~ISIG
; /* disable signals */
338 (void)ioctl(STDIN_FD
, TCSETAW
, &_raw_tty
);
341 _raw_tchars
.t_intrc
= -1;
342 (void)ioctl(STDIN_FD
, TIOCSETC
, &_raw_tchars
);
350 * Discard any pending input characters
354 * Result: pending input buffer flushed
361 tcflush(STDIN_FD
, TCIFLUSH
);
365 ioctl(STDIN_FD
, TCFLSH
, 0);
375 ioctl(STDIN_FD
, TIOCFLUSH
, &i
);
376 #endif /* TIOCFLUSH */
383 * Turn off hi bit stripping
390 _raw_tty
.c_iflag
&= ~ISTRIP
;
391 tcsetattr(STDIN_FD
, TCSADRAIN
, &_raw_tty
);
400 _raw_lmode
|= LPASS8
;
404 _raw_lmode
|= LPASS8OUT
;
407 (void)ioctl(STDIN_FD
, TIOCLSET
, &_raw_lmode
);
414 * Turn off quit character (^\) if possible
424 _raw_tchars
.t_quitc
= -1;
425 (void)ioctl(STDIN_FD
, TIOCSETC
, &_raw_tchars
);
431 * Returns TRUE if tty is < 4800, 0 otherwise.
438 return(cfgetospeed(&_raw_tty
) < B4800
);
442 return((_raw_tty
.c_cflag
&CBAUD
) < (unsigned int)B4800
);
446 return((int)_raw_tty
.sg_ispeed
< B4800
);