xref: /OK3568_Linux_fs/u-boot/common/rbsb.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2   rbsb.c - terminal handling stuff for lrzsz
3   Copyright (C) until 1988 Chuck Forsberg (Omen Technology INC)
4   Copyright (C) 1994 Matt Porter, Michael D. Black
5   Copyright (C) 1996, 1997 Uwe Ohse
6 
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2, or (at your option)
10   any later version.
11 
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16 
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20   02111-1307, USA.
21 
22   originally written by Chuck Forsberg
23 */
24 
25 /*
26  *  Rev 05-05-1988
27  *  ============== (not quite, but originated there :-). -- uwe
28  */
29 #include "zglobal.h"
30 
31 #include <stdio.h>
32 #include <errno.h>
33 
34 #ifndef HAVE_ERRNO_DECLARATION
35 extern int errno;
36 #endif
37 
38 #ifdef USE_SGTTY
39 #  ifdef LLITOUT
40 long Locmode;		/* Saved "local mode" for 4.x BSD "new driver" */
41 long Locbit = LLITOUT;	/* Bit SUPPOSED to disable output translations */
42 #  endif
43 #endif
44 
45 #ifdef HAVE_SYS_IOCTL_H
46 #include <sys/ioctl.h>
47 #endif
48 
49 #ifdef MAJOR_IN_MKDEV
50 #include <sys/mkdev.h>
51 #else
52 # ifdef MAJOR_IN_SYSMACROS
53 # include <sys/sysmacros.h>
54 # endif
55 #endif
56 #ifndef HOWMANY
57 #ifdef NFGVMIN
58 #define HOWMANY MAX_BLOCK
59 #else
60 #define HOWMANY 255
61 #endif
62 #endif
63 
64 
65 #if defined(HOWMANY) && HOWMANY  > 255
66 #ifndef NFGVMIN
67 Howmany must be 255 or less
68 #endif
69 #endif
70 
71 #define B110 110
72 #define B300 300
73 #define B600 600
74 #define B1200 1200
75 #define B2400 2400
76 #define B2400 2400
77 static struct {
78 	unsigned baudr;
79 	int  speedcode;
80 } speeds[] = {
81 	{110,	B110},
82 	{300,	B300},
83 	{600,	B600},
84 	{1200,	B1200},
85 #ifdef B19200
86     {19200,  B19200},
87 #endif
88 #ifdef B38400
89     {38400,  B38400},
90 #endif
91 #ifdef B57600
92     {57600,  B57600},
93 #endif
94 #ifdef B115200
95     {115200,  B115200},
96 #endif
97 #ifdef B230400
98     {230400,  B230400},
99 #endif
100 #ifdef B460800
101     {460800,  B460800},
102 #endif
103 #ifdef EXTA
104 	{19200,	EXTA},
105 #endif
106 #ifdef EXTB
107 	{38400,	EXTB},
108 #endif
109 	{0, 0}
110 };
111 
112 extern int CYGACC_COMM_IF_GETC_TIMEOUT (char chan, char *c);
113 extern void CYGACC_COMM_IF_PUTC (char x, char y);
114 extern int CYGACC_COMM_IF_GETC_TIMEOUT (char chan, char *c);
115 
116 unsigned
getspeed(int code)117 getspeed(int  code)
118 {
119 	int n;
120 
121 	for (n=0; speeds[n].baudr; ++n)
122 		if (speeds[n].speedcode == code)
123 			return speeds[n].baudr;
124 	return 38400;	/* Assume fifo if ioctl failed */
125 }
126 
127 /*
128  * return 1 if stdout and stderr are different devices
129  *  indicating this program operating with a modem on a
130  *  different line
131  */
132 int Fromcu;		/* Were called from cu or yam */
133 int
from_cu(void)134 from_cu(void)
135 {
136 #if 0
137 #ifdef HAVE_ST_RDEV
138 	struct stat a, b;
139 #if defined(makedev)
140 	dev_t help=makedev(0,0);
141 #else
142 	int help=0;
143 #endif
144 
145 	/* in case fstat fails */
146 	a.st_rdev=b.st_rdev=a.st_dev=b.st_dev=help;
147 
148 	fstat(1, &a); fstat(2, &b);
149 
150 #if defined(major) && defined(minor)
151 	if (major(a.st_rdev) != major(b.st_rdev)
152 		|| minor(a.st_rdev) != minor(b.st_rdev))
153 		Fromcu=1;
154 	else if (major(a.st_dev) != major(b.st_dev)
155 		|| minor(a.st_dev) != minor(b.st_dev))
156 		Fromcu=1;
157 	else
158 		Fromcu=0;
159 #else
160 	Fromcu = (a.st_rdev != b.st_rdev) || (a.st_dev != b.st_dev);
161 #endif
162 #else
163 	Fromcu = 1; /* a bad guess .. */
164 #endif
165 	return Fromcu;
166 #endif
167 	return 0;
168 }
169 
170 
171 
172 int Twostop;		/* Use two stop bits */
173 
174 
175 #ifdef READCHECK_FIONREAD
176 /*
177  *  Return non 0 if something to read from io descriptor f
178  */
179 int
rdchk(int fd)180 rdchk(int fd)
181 {
182 	static long lf;
183 
184 	ioctl(fd, FIONREAD, &lf);
185 	return ((int) lf);
186 }
187 #endif
188 
189 #ifdef READCHECK_GETFL
190 unsigned char checked = '\0' ;
191 /*
192  * Nonblocking I/O is a bit different in System V, Release 2
193  */
194 int
rdchk(int fd)195 rdchk(int fd)
196 {
197 	int lf, savestat;
198 
199 	savestat = fcntl(fd, F_GETFL) ;
200 	if (savestat == -1)
201 		return 0;
202 #ifdef OVERLY_PARANOID
203 	if (-1==fcntl(fd, F_SETFL, savestat | O_NDELAY))
204 		return 0;
205 	lf = read(fd, &checked, 1) ;
206 	if (-1==fcntl(fd, F_SETFL, savestat)) {
207 #ifdef ENABLE_SYSLOG
208 		if (enable_syslog)
209 			lsyslog(LOG_CRIT,"F_SETFL failed in rdchk(): %s",
210 				strerror(errno));
211 #endif
212 		zpfatal("rdchk: F_SETFL failed\n"); /* lose */
213 		/* there is really no way to recover. And we can't tell
214 		 * the other side what's going on if we can't write to
215 		 * fd, but we try.
216 		 */
217 		canit(fd);
218 		exit(1);
219 	}
220 #else
221 	fcntl(fd, F_SETFL, savestat | O_NDELAY);
222 	lf = read(fd, &checked, 1) ;
223 	fcntl(fd, F_SETFL, savestat);
224 #endif
225 	return(lf == -1 && errno==EWOULDBLOCK ? 0 : lf) ;
226 }
227 #endif
228 
229 
230 
231 
232 
233 #ifdef USE_TERMIOS
234 struct termios oldtty, tty;
235 #else
236 #  if defined(USE_TERMIO)
237 struct termio oldtty, tty;
238 #  else
239 //struct sgttyb oldtty, tty;
240 //struct tchars oldtch, tch;
241 #  endif
242 #endif
243 
244 
245 /*
246  * mode(n)
247  *  3: save old tty stat, set raw mode with flow control
248  *  2: set XON/XOFF for sb/sz with ZMODEM or YMODEM-g
249  *  1: save old tty stat, set raw mode
250  *  0: restore original tty mode
251  */
252 int
io_mode(int fd,int n)253 io_mode(int fd, int n)
254 {
255 #if 1
256 	__maybe_unused static int did0 = FALSE;
257 
258 	vfile("mode:%d", n);
259 
260 	switch(n) {
261 
262 #ifdef USE_TERMIOS
263 	case 2:		/* Un-raw mode used by sz, sb when -g detected */
264 		if(!did0) {
265 			did0 = TRUE;
266 			tcgetattr(fd,&oldtty);
267 		}
268 		tty = oldtty;
269 
270 		tty.c_iflag = BRKINT|IXON;
271 
272 		tty.c_oflag = 0;	/* Transparent output */
273 
274 		tty.c_cflag &= ~PARENB;	/* Disable parity */
275 		tty.c_cflag |= CS8;	/* Set character size = 8 */
276 		if (Twostop)
277 			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
278 
279 #ifdef READCHECK
280 		tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG;
281 		tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030;	/* Interrupt char */
282 #else
283 		tty.c_lflag = 0;
284 		tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030;	/* Interrupt char */
285 #endif
286 #ifdef _POSIX_VDISABLE
287 		if (((int) _POSIX_VDISABLE)!=(-1)) {
288 			tty.c_cc[VQUIT] = _POSIX_VDISABLE;		/* Quit char */
289 		} else {
290 			tty.c_cc[VQUIT] = -1;			/* Quit char */
291 		}
292 #else
293 		tty.c_cc[VQUIT] = -1;			/* Quit char */
294 #endif
295 #ifdef NFGVMIN
296 		tty.c_cc[VMIN] = 1;
297 #else
298 		tty.c_cc[VMIN] = 3;	 /* This many chars satisfies reads */
299 #endif
300 		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
301 
302 		tcsetattr(fd,TCSADRAIN,&tty);
303 
304 		return OK;
305 	case 1:
306 	case 3:
307 		if(!did0) {
308 			did0 = TRUE;
309 			tcgetattr(fd,&oldtty);
310 		}
311 		tty = oldtty;
312 
313 		tty.c_iflag = IGNBRK;
314 		if (n==3) /* with flow control */
315 			tty.c_iflag |= IXOFF;
316 
317 		 /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */
318 		tty.c_lflag &= ~(ECHO | ICANON | ISIG);
319 		tty.c_oflag = 0;	/* Transparent output */
320 
321 		tty.c_cflag &= ~(PARENB);	/* Same baud rate, disable parity */
322 		/* Set character size = 8 */
323 		tty.c_cflag &= ~(CSIZE);
324 		tty.c_cflag |= CS8;
325 		if (Twostop)
326 			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
327 #ifdef NFGVMIN
328 		tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
329 #else
330 		tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
331 #endif
332 		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
333 		tcsetattr(fd,TCSADRAIN,&tty);
334 		Baudrate = getspeed(cfgetospeed(&tty));
335 		return OK;
336 	case 0:
337 		if(!did0)
338 			return ERROR;
339 		tcdrain (fd); /* wait until everything is sent */
340 		tcflush (fd,TCIOFLUSH); /* flush input queue */
341 		tcsetattr (fd,TCSADRAIN,&oldtty);
342 		tcflow (fd,TCOON); /* restart output */
343 
344 		return OK;
345 #endif
346 
347 #ifdef USE_TERMIO
348 	case 2:		/* Un-raw mode used by sz, sb when -g detected */
349 		if(!did0)
350 			(void) ioctl(fd, TCGETA, &oldtty);
351 		tty = oldtty;
352 
353 		tty.c_iflag = BRKINT|IXON;
354 
355 		tty.c_oflag = 0;	/* Transparent output */
356 
357 		tty.c_cflag &= ~PARENB;	/* Disable parity */
358 		tty.c_cflag |= CS8;	/* Set character size = 8 */
359 		if (Twostop)
360 			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
361 
362 
363 #ifdef READCHECK
364 		tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG;
365 		tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030;	/* Interrupt char */
366 #else
367 		tty.c_lflag = 0;
368 		tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030;	/* Interrupt char */
369 #endif
370 		tty.c_cc[VQUIT] = -1;			/* Quit char */
371 #ifdef NFGVMIN
372 		tty.c_cc[VMIN] = 1;
373 #else
374 		tty.c_cc[VMIN] = 3;	 /* This many chars satisfies reads */
375 #endif
376 		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
377 
378 		(void) ioctl(fd, TCSETAW, &tty);
379 		did0 = TRUE;
380 		return OK;
381 	case 1:
382 	case 3:
383 		if(!did0)
384 			(void) ioctl(fd, TCGETA, &oldtty);
385 		tty = oldtty;
386 
387 		tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK;
388 
389 		 /* No echo, crlf mapping, delays, no erase/kill */
390 		tty.c_lflag &= ~(ECHO | ICANON | ISIG);
391 
392 		tty.c_oflag = 0;	/* Transparent output */
393 
394 		tty.c_cflag &= ~PARENB;	/* Same baud rate, disable parity */
395 		tty.c_cflag |= CS8;	/* Set character size = 8 */
396 		if (Twostop)
397 			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
398 #ifdef NFGVMIN
399 		tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
400 #else
401 		tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
402 #endif
403 		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
404 		(void) ioctl(fd, TCSETAW, &tty);
405 		did0 = TRUE;
406 		Baudrate = getspeed(tty.c_cflag & CBAUD);
407 		return OK;
408 	case 0:
409 		if(!did0)
410 			return ERROR;
411 		(void) ioctl(fd, TCSBRK, 1);	/* Wait for output to drain */
412 		(void) ioctl(fd, TCFLSH, 0);	/* Flush input queue */
413 		(void) ioctl(fd, TCSETAW, &oldtty);	/* Restore modes */
414 		(void) ioctl(fd, TCXONC,1);	/* Restart output */
415 		return OK;
416 #endif
417 
418 
419 #ifdef USE_SGTTY
420 	/*
421 	 *  NOTE: this should transmit all 8 bits and at the same time
422 	 *   respond to XOFF/XON flow control.  If no FIONREAD or other
423 	 *   READCHECK alternative, also must respond to INTRRUPT char
424 	 *   This doesn't work with V7.  It should work with LLITOUT,
425 	 *   but LLITOUT was broken on the machine I tried it on.
426 	 */
427 	case 2:		/* Un-raw mode used by sz, sb when -g detected */
428 		if(!did0) {
429 			ioctl(fd, TIOCEXCL, 0);
430 			ioctl(fd, TIOCGETP, &oldtty);
431 			ioctl(fd, TIOCGETC, &oldtch);
432 #ifdef LLITOUT
433 			ioctl(fd, TIOCLGET, &Locmode);
434 #endif
435 		}
436 		tty = oldtty;
437 		tch = oldtch;
438 #ifdef READCHECK
439 		tch.t_intrc = Zmodem ? -1:030;	/* Interrupt char */
440 #else
441 		tch.t_intrc = Zmodem ? 03:030;	/* Interrupt char */
442 #endif
443 		tty.sg_flags |= (ODDP|EVENP|CBREAK);
444 		tty.sg_flags &= ~(ALLDELAY|CRMOD|ECHO|LCASE);
445 		ioctl(fd, TIOCSETP, &tty);
446 		ioctl(fd, TIOCSETC, &tch);
447 #ifdef LLITOUT
448 		ioctl(fd, TIOCLBIS, &Locbit);
449 #else
450 		bibi(99);	/* un-raw doesn't work w/o lit out */
451 #endif
452 		did0 = TRUE;
453 		return OK;
454 	case 1:
455 	case 3:
456 		if(!did0) {
457 			ioctl(fd, TIOCEXCL, 0);
458 			ioctl(fd, TIOCGETP, &oldtty);
459 			ioctl(fd, TIOCGETC, &oldtch);
460 #ifdef LLITOUT
461 			ioctl(fd, TIOCLGET, &Locmode);
462 #endif
463 		}
464 		tty = oldtty;
465 		tty.sg_flags |= RAW;
466 		tty.sg_flags &= ~ECHO;
467 		ioctl(fd, TIOCSETP, &tty);
468 		did0 = TRUE;
469 		Baudrate = getspeed(tty.sg_ospeed);
470 		return OK;
471 	case 0:
472 		if(!did0)
473 			return ERROR;
474 		ioctl(fd, TIOCSETP, &oldtty);
475 		ioctl(fd, TIOCSETC, &oldtch);
476 		ioctl(fd, TIOCNXCL, 0);
477 #ifdef LLITOUT
478 		ioctl(fd, TIOCLSET, &Locmode);
479 #endif
480 #ifdef TIOCFLUSH
481 		{ int x=1; ioctl(fd,TIOCFLUSH,&x); }
482 #endif
483 #endif
484 
485 		return OK;
486 	default:
487 		return ERROR;
488 	}
489 #endif
490 }
491 
492 void
sendbrk(int fd)493 sendbrk(int fd)
494 {
495 #if 0
496 #ifdef USE_TERMIOS
497 	tcsendbreak(fd,0);
498 #endif
499 #ifdef USE_TERMIO
500 	ioctl(fd, TCSBRK, 0);
501 #endif
502 #ifdef USE_SGTTY
503 #ifdef TIOCSBRK
504 	sleep(1);
505 	ioctl(fd, TIOCSBRK, 0);
506 	sleep(1);
507 	ioctl(fd, TIOCCBRK, 0);
508 #endif
509 #endif
510 #endif
511 }
512 
513 void
purgeline(int fd)514 purgeline(int fd)
515 {
516 	readline_purge();
517 #if 0
518 #ifdef TCFLSH
519 	ioctl(fd, TCFLSH, 0);
520 #else
521 	lseek(fd, 0L, 2);
522 #endif
523 #endif
524 }
525 
526 /* End of rbsb.c */
527