xref: /rk3399_rockchip-uboot/common/rbsb.c (revision f8a983e5965e95c7c6bf3eb71de1a91cf440843c)
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 static unsigned
113 getspeed(int  code)
114 {
115 	int n;
116 
117 	for (n=0; speeds[n].baudr; ++n)
118 		if (speeds[n].speedcode == code)
119 			return speeds[n].baudr;
120 	return 38400;	/* Assume fifo if ioctl failed */
121 }
122 
123 /*
124  * return 1 if stdout and stderr are different devices
125  *  indicating this program operating with a modem on a
126  *  different line
127  */
128 int Fromcu;		/* Were called from cu or yam */
129 int
130 from_cu(void)
131 {
132 #if 0
133 #ifdef HAVE_ST_RDEV
134 	struct stat a, b;
135 #if defined(makedev)
136 	dev_t help=makedev(0,0);
137 #else
138 	int help=0;
139 #endif
140 
141 	/* in case fstat fails */
142 	a.st_rdev=b.st_rdev=a.st_dev=b.st_dev=help;
143 
144 	fstat(1, &a); fstat(2, &b);
145 
146 #if defined(major) && defined(minor)
147 	if (major(a.st_rdev) != major(b.st_rdev)
148 		|| minor(a.st_rdev) != minor(b.st_rdev))
149 		Fromcu=1;
150 	else if (major(a.st_dev) != major(b.st_dev)
151 		|| minor(a.st_dev) != minor(b.st_dev))
152 		Fromcu=1;
153 	else
154 		Fromcu=0;
155 #else
156 	Fromcu = (a.st_rdev != b.st_rdev) || (a.st_dev != b.st_dev);
157 #endif
158 #else
159 	Fromcu = 1; /* a bad guess .. */
160 #endif
161 	return Fromcu;
162 #endif
163 	return 0;
164 }
165 
166 
167 
168 int Twostop;		/* Use two stop bits */
169 
170 
171 #ifdef READCHECK_FIONREAD
172 /*
173  *  Return non 0 if something to read from io descriptor f
174  */
175 int
176 rdchk(int fd)
177 {
178 	static long lf;
179 
180 	ioctl(fd, FIONREAD, &lf);
181 	return ((int) lf);
182 }
183 #endif
184 
185 #ifdef READCHECK_GETFL
186 unsigned char checked = '\0' ;
187 /*
188  * Nonblocking I/O is a bit different in System V, Release 2
189  */
190 int
191 rdchk(int fd)
192 {
193 	int lf, savestat;
194 
195 	savestat = fcntl(fd, F_GETFL) ;
196 	if (savestat == -1)
197 		return 0;
198 #ifdef OVERLY_PARANOID
199 	if (-1==fcntl(fd, F_SETFL, savestat | O_NDELAY))
200 		return 0;
201 	lf = read(fd, &checked, 1) ;
202 	if (-1==fcntl(fd, F_SETFL, savestat)) {
203 #ifdef ENABLE_SYSLOG
204 		if (enable_syslog)
205 			lsyslog(LOG_CRIT,"F_SETFL failed in rdchk(): %s",
206 				strerror(errno));
207 #endif
208 		zpfatal("rdchk: F_SETFL failed\n"); /* lose */
209 		/* there is really no way to recover. And we can't tell
210 		 * the other side what's going on if we can't write to
211 		 * fd, but we try.
212 		 */
213 		canit(fd);
214 		exit(1);
215 	}
216 #else
217 	fcntl(fd, F_SETFL, savestat | O_NDELAY);
218 	lf = read(fd, &checked, 1) ;
219 	fcntl(fd, F_SETFL, savestat);
220 #endif
221 	return(lf == -1 && errno==EWOULDBLOCK ? 0 : lf) ;
222 }
223 #endif
224 
225 
226 
227 
228 
229 #ifdef USE_TERMIOS
230 struct termios oldtty, tty;
231 #else
232 #  if defined(USE_TERMIO)
233 struct termio oldtty, tty;
234 #  else
235 //struct sgttyb oldtty, tty;
236 //struct tchars oldtch, tch;
237 #  endif
238 #endif
239 
240 
241 /*
242  * mode(n)
243  *  3: save old tty stat, set raw mode with flow control
244  *  2: set XON/XOFF for sb/sz with ZMODEM or YMODEM-g
245  *  1: save old tty stat, set raw mode
246  *  0: restore original tty mode
247  */
248 int
249 io_mode(int fd, int n)
250 {
251 #if 1
252 	static int did0 = FALSE;
253 
254 	vfile("mode:%d", n);
255 
256 	switch(n) {
257 
258 #ifdef USE_TERMIOS
259 	case 2:		/* Un-raw mode used by sz, sb when -g detected */
260 		if(!did0) {
261 			did0 = TRUE;
262 			tcgetattr(fd,&oldtty);
263 		}
264 		tty = oldtty;
265 
266 		tty.c_iflag = BRKINT|IXON;
267 
268 		tty.c_oflag = 0;	/* Transparent output */
269 
270 		tty.c_cflag &= ~PARENB;	/* Disable parity */
271 		tty.c_cflag |= CS8;	/* Set character size = 8 */
272 		if (Twostop)
273 			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
274 
275 #ifdef READCHECK
276 		tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG;
277 		tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030;	/* Interrupt char */
278 #else
279 		tty.c_lflag = 0;
280 		tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030;	/* Interrupt char */
281 #endif
282 #ifdef _POSIX_VDISABLE
283 		if (((int) _POSIX_VDISABLE)!=(-1)) {
284 			tty.c_cc[VQUIT] = _POSIX_VDISABLE;		/* Quit char */
285 		} else {
286 			tty.c_cc[VQUIT] = -1;			/* Quit char */
287 		}
288 #else
289 		tty.c_cc[VQUIT] = -1;			/* Quit char */
290 #endif
291 #ifdef NFGVMIN
292 		tty.c_cc[VMIN] = 1;
293 #else
294 		tty.c_cc[VMIN] = 3;	 /* This many chars satisfies reads */
295 #endif
296 		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
297 
298 		tcsetattr(fd,TCSADRAIN,&tty);
299 
300 		return OK;
301 	case 1:
302 	case 3:
303 		if(!did0) {
304 			did0 = TRUE;
305 			tcgetattr(fd,&oldtty);
306 		}
307 		tty = oldtty;
308 
309 		tty.c_iflag = IGNBRK;
310 		if (n==3) /* with flow control */
311 			tty.c_iflag |= IXOFF;
312 
313 		 /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */
314 		tty.c_lflag &= ~(ECHO | ICANON | ISIG);
315 		tty.c_oflag = 0;	/* Transparent output */
316 
317 		tty.c_cflag &= ~(PARENB);	/* Same baud rate, disable parity */
318 		/* Set character size = 8 */
319 		tty.c_cflag &= ~(CSIZE);
320 		tty.c_cflag |= CS8;
321 		if (Twostop)
322 			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
323 #ifdef NFGVMIN
324 		tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
325 #else
326 		tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
327 #endif
328 		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
329 		tcsetattr(fd,TCSADRAIN,&tty);
330 		Baudrate = getspeed(cfgetospeed(&tty));
331 		return OK;
332 	case 0:
333 		if(!did0)
334 			return ERROR;
335 		tcdrain (fd); /* wait until everything is sent */
336 		tcflush (fd,TCIOFLUSH); /* flush input queue */
337 		tcsetattr (fd,TCSADRAIN,&oldtty);
338 		tcflow (fd,TCOON); /* restart output */
339 
340 		return OK;
341 #endif
342 
343 #ifdef USE_TERMIO
344 	case 2:		/* Un-raw mode used by sz, sb when -g detected */
345 		if(!did0)
346 			(void) ioctl(fd, TCGETA, &oldtty);
347 		tty = oldtty;
348 
349 		tty.c_iflag = BRKINT|IXON;
350 
351 		tty.c_oflag = 0;	/* Transparent output */
352 
353 		tty.c_cflag &= ~PARENB;	/* Disable parity */
354 		tty.c_cflag |= CS8;	/* Set character size = 8 */
355 		if (Twostop)
356 			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
357 
358 
359 #ifdef READCHECK
360 		tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG;
361 		tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030;	/* Interrupt char */
362 #else
363 		tty.c_lflag = 0;
364 		tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030;	/* Interrupt char */
365 #endif
366 		tty.c_cc[VQUIT] = -1;			/* Quit char */
367 #ifdef NFGVMIN
368 		tty.c_cc[VMIN] = 1;
369 #else
370 		tty.c_cc[VMIN] = 3;	 /* This many chars satisfies reads */
371 #endif
372 		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
373 
374 		(void) ioctl(fd, TCSETAW, &tty);
375 		did0 = TRUE;
376 		return OK;
377 	case 1:
378 	case 3:
379 		if(!did0)
380 			(void) ioctl(fd, TCGETA, &oldtty);
381 		tty = oldtty;
382 
383 		tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK;
384 
385 		 /* No echo, crlf mapping, delays, no erase/kill */
386 		tty.c_lflag &= ~(ECHO | ICANON | ISIG);
387 
388 		tty.c_oflag = 0;	/* Transparent output */
389 
390 		tty.c_cflag &= ~PARENB;	/* Same baud rate, disable parity */
391 		tty.c_cflag |= CS8;	/* Set character size = 8 */
392 		if (Twostop)
393 			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
394 #ifdef NFGVMIN
395 		tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
396 #else
397 		tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
398 #endif
399 		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
400 		(void) ioctl(fd, TCSETAW, &tty);
401 		did0 = TRUE;
402 		Baudrate = getspeed(tty.c_cflag & CBAUD);
403 		return OK;
404 	case 0:
405 		if(!did0)
406 			return ERROR;
407 		(void) ioctl(fd, TCSBRK, 1);	/* Wait for output to drain */
408 		(void) ioctl(fd, TCFLSH, 0);	/* Flush input queue */
409 		(void) ioctl(fd, TCSETAW, &oldtty);	/* Restore modes */
410 		(void) ioctl(fd, TCXONC,1);	/* Restart output */
411 		return OK;
412 #endif
413 
414 
415 #ifdef USE_SGTTY
416 	/*
417 	 *  NOTE: this should transmit all 8 bits and at the same time
418 	 *   respond to XOFF/XON flow control.  If no FIONREAD or other
419 	 *   READCHECK alternative, also must respond to INTRRUPT char
420 	 *   This doesn't work with V7.  It should work with LLITOUT,
421 	 *   but LLITOUT was broken on the machine I tried it on.
422 	 */
423 	case 2:		/* Un-raw mode used by sz, sb when -g detected */
424 		if(!did0) {
425 			ioctl(fd, TIOCEXCL, 0);
426 			ioctl(fd, TIOCGETP, &oldtty);
427 			ioctl(fd, TIOCGETC, &oldtch);
428 #ifdef LLITOUT
429 			ioctl(fd, TIOCLGET, &Locmode);
430 #endif
431 		}
432 		tty = oldtty;
433 		tch = oldtch;
434 #ifdef READCHECK
435 		tch.t_intrc = Zmodem ? -1:030;	/* Interrupt char */
436 #else
437 		tch.t_intrc = Zmodem ? 03:030;	/* Interrupt char */
438 #endif
439 		tty.sg_flags |= (ODDP|EVENP|CBREAK);
440 		tty.sg_flags &= ~(ALLDELAY|CRMOD|ECHO|LCASE);
441 		ioctl(fd, TIOCSETP, &tty);
442 		ioctl(fd, TIOCSETC, &tch);
443 #ifdef LLITOUT
444 		ioctl(fd, TIOCLBIS, &Locbit);
445 #else
446 		bibi(99);	/* un-raw doesn't work w/o lit out */
447 #endif
448 		did0 = TRUE;
449 		return OK;
450 	case 1:
451 	case 3:
452 		if(!did0) {
453 			ioctl(fd, TIOCEXCL, 0);
454 			ioctl(fd, TIOCGETP, &oldtty);
455 			ioctl(fd, TIOCGETC, &oldtch);
456 #ifdef LLITOUT
457 			ioctl(fd, TIOCLGET, &Locmode);
458 #endif
459 		}
460 		tty = oldtty;
461 		tty.sg_flags |= RAW;
462 		tty.sg_flags &= ~ECHO;
463 		ioctl(fd, TIOCSETP, &tty);
464 		did0 = TRUE;
465 		Baudrate = getspeed(tty.sg_ospeed);
466 		return OK;
467 	case 0:
468 		if(!did0)
469 			return ERROR;
470 		ioctl(fd, TIOCSETP, &oldtty);
471 		ioctl(fd, TIOCSETC, &oldtch);
472 		ioctl(fd, TIOCNXCL, 0);
473 #ifdef LLITOUT
474 		ioctl(fd, TIOCLSET, &Locmode);
475 #endif
476 #ifdef TIOCFLUSH
477 		{ int x=1; ioctl(fd,TIOCFLUSH,&x); }
478 #endif
479 #endif
480 
481 		return OK;
482 	default:
483 		return ERROR;
484 	}
485 #endif
486 }
487 
488 void
489 sendbrk(int fd)
490 {
491 #if 0
492 #ifdef USE_TERMIOS
493 	tcsendbreak(fd,0);
494 #endif
495 #ifdef USE_TERMIO
496 	ioctl(fd, TCSBRK, 0);
497 #endif
498 #ifdef USE_SGTTY
499 #ifdef TIOCSBRK
500 	sleep(1);
501 	ioctl(fd, TIOCSBRK, 0);
502 	sleep(1);
503 	ioctl(fd, TIOCCBRK, 0);
504 #endif
505 #endif
506 #endif
507 }
508 
509 void
510 purgeline(int fd)
511 {
512 	readline_purge();
513 #if 0
514 #ifdef TCFLSH
515 	ioctl(fd, TCFLSH, 0);
516 #else
517 	lseek(fd, 0L, 2);
518 #endif
519 #endif
520 }
521 
522 /* End of rbsb.c */
523