--- term.c.orig	2015-06-07 14:33:57.371711393 +0200
+++ term.c	2019-07-10 19:21:50.893412759 +0200
@@ -34,21 +34,59 @@
 #include <errno.h>
 #include <unistd.h>
 #ifdef __linux__
-#include <termio.h>
+#include <asm/ioctls.h>
+#include <asm/termios.h>
 #else
 #include <termios.h>
 #endif /* of __linux__ */
 
 #include "term.h"
 
+/* XXX: We can't include sys/ioctl.h as that causes a redefinition of 'struct
+ * winsize' **/
+/* Perform the I/O control operation specified by REQUEST on FD.
+   One argument may follow; its presence and type depend on REQUEST.
+   Return value depends on REQUEST.  Usually -1 indicates error.  */
+extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;
+
+/* XXX: Unable to include termios.h because 'struct termios' is redefined in
+ * libc. */
+static int tcflush(int fd, int queue_selector)
+{
+	return 0;
+}
+
+static void cfmakeraw(struct termios2 *termios_p)
+{
+	termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
+			| INLCR | IGNCR | ICRNL | IXON);
+	termios_p->c_oflag &= ~OPOST;
+	termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+	termios_p->c_cflag &= ~(CSIZE | PARENB);
+	termios_p->c_cflag |= CS8;
+}
+
+static int tcsendbreak(int fd, int duration)
+{
+	return ioctl(fd, TCSBRKP, duration);
+}
+
+static int tcdrain(int fd)
+{
+	/* from tty_ioctl(4):
+	 * >> SVr4,  UnixWare,  Solaris,  Linux treat tcsendbreak(fd,arg) with nonzero arg like tcdrain(fd)
+	 */
+	return ioctl(fd, TCSBRK, 1);
+}
+
 /***************************************************************************/
 
 static struct term_s {
 	int init;
 	int fd[MAX_TERMS];
-	struct termios origtermios[MAX_TERMS];
-	struct termios currtermios[MAX_TERMS];
-	struct termios nexttermios[MAX_TERMS];
+	struct termios2 origtermios[MAX_TERMS];
+	struct termios2 currtermios[MAX_TERMS];
+	struct termios2 nexttermios[MAX_TERMS];
 } term;
 
 /***************************************************************************/
@@ -204,7 +242,7 @@
 			do { /* dummy */
 				r = tcflush(term.fd[i], TCIOFLUSH);
 				if ( r < 0 ) break;
-				r = tcsetattr(term.fd[i], TCSAFLUSH, &term.origtermios[i]);
+				r = ioctl(term.fd[i], TCSETSF2, &term.origtermios[i]);
 				if ( r < 0 ) break;
 			} while (0);
 			if ( r < 0 ) {
@@ -238,7 +276,7 @@
 				do {
 					r = tcflush(term.fd[i], TCIOFLUSH);
 					if ( r < 0 ) break;
-					r = tcsetattr(term.fd[i], TCSAFLUSH, &term.origtermios[i]);
+					r = ioctl(term.fd[i], TCSETSF2, &term.origtermios[i]);
 					if ( r < 0 ) break;
 				} while (0);
 				if ( r < 0 ) {
@@ -297,7 +335,7 @@
 			break;
 		}
 
-		r = tcgetattr(fd, &term.origtermios[i]);
+		r = ioctl(fd, TCGETS2, &term.origtermios[i]);
 		if ( r < 0 ) {
 			term_errno = TERM_EGETATTR;
 			rval = -1;
@@ -335,7 +373,7 @@
 				rval = -1;
 				break;
 			}
-			r = tcsetattr(term.fd[i], TCSAFLUSH, &term.origtermios[i]);
+			r = ioctl(term.fd[i], TCSETS2, &term.origtermios[i]);
 			if ( r < 0 ) {
 				term_errno = TERM_ESETATTR;
 				rval = -1;
@@ -388,7 +426,7 @@
 			break;
 		}
 
-		r = tcsetattr(newfd, TCSAFLUSH, &term.currtermios[i]);
+		r = ioctl(newfd, TCSETSF2, &term.currtermios[i]);
 		if ( r < 0 ) {
 			term_errno = TERM_ESETATTR;
 			rval = -1;
@@ -425,7 +463,7 @@
 			rval = -1;
 			break;
 		}
-		r = tcsetattr(term.fd[i], TCSAFLUSH, &term.origtermios[i]);
+		r = ioctl(term.fd[i], TCSETSF2, &term.origtermios[i]);
 		if ( r < 0 ) {
 			term_errno = TERM_ESETATTR;
 			rval = -1;
@@ -480,7 +518,7 @@
 			break;
 		}
 
-		r = tcgetattr(fd, &term.currtermios[i]);
+		r = ioctl(fd, TCGETS2, &term.currtermios[i]);
 		if ( r < 0 ) {
 			term_errno = TERM_EGETATTR;
 			rval = -1;
@@ -509,7 +547,7 @@
 			break;
 		}
 		
-		r = tcsetattr(term.fd[i], TCSAFLUSH, &term.nexttermios[i]);
+		r = ioctl(term.fd[i], TCSETSF2 , &term.nexttermios[i]);
 		if ( r < 0 ) {
 			term_errno = TERM_ESETATTR;
 			rval = -1;
@@ -554,11 +592,11 @@
 /***************************************************************************/
 
 int
-term_set_baudrate (int fd, int baudrate)
+//term_set_baudrate (int fd, speed_t baud_rate)
+term_set_baudrate (int fd, int baud_rate)
 {
-	int rval, r, i;
-	speed_t spd;
-	struct termios tio;
+	int rval, i;
+	struct termios2 tio;
 
 	rval = 0;
 
@@ -572,92 +610,14 @@
 
 		tio = term.nexttermios[i];
 
-		switch (baudrate) {
-		case 0:
-			spd = B0;
-			break;
-		case 50:
-			spd = B50;
-			break;
-		case 75:
-			spd = B75;
-			break;
-		case 110:
-			spd = B110;
-			break;
-		case 134:
-			spd = B134;
-			break;
-		case 150:
-			spd = B150;
-			break;
-		case 200:
-			spd = B200;
-			break;
-		case 300:
-			spd = B300;
-			break;
-		case 600:
-			spd = B600;
-			break;
-		case 1200:
-			spd = B1200;
-			break;
-		case 1800:
-			spd = B1800;
-			break;
-		case 2400:
-			spd = B2400;
-			break;
-		case 4800:
-			spd = B4800;
-			break;
-		case 9600:
-			spd = B9600;
-			break;
-		case 19200:
-			spd = B19200;
-			break;
-		case 38400:
-			spd = B38400;
-			break;
-		case 57600:
-			spd = B57600;
-			break;
-		case 115200:
-			spd = B115200;
-			break;
-#ifdef HIGH_BAUD
-		case 230400:
-			spd = B230400;
-			break;
-		case 460800:
-			spd = B460800;
-			break;
-		case 921600:
-			spd = B921600;
-			break;
-#endif
-		default:
-			term_errno = TERM_EBAUD;
-			rval = -1;
-			break;
-		}
-		if ( rval < 0 ) break;
-
-		r = cfsetospeed(&tio, spd);
-		if ( r < 0 ) {
-			term_errno = TERM_ESETOSPEED;
-			rval = -1;
-			break;
-		}
-			
-		r = cfsetispeed(&tio, spd);
-		if ( r < 0 ) {
-			term_errno = TERM_ESETISPEED;
-			rval = -1;
-			break;
-		}
+		/* drivers/tty/tty_ioctl.c :: tty_termios_baud_rate() */
+		tio.c_cflag = (tio.c_cflag & ~CBAUD) | BOTHER;
+		tio.c_ospeed = baud_rate;
+
+		/* drivers/tty/tty_ioctl.c :: tty_termios_input_baud_rate() */
+		/* If CIBAUD == B0, use output baud rate. Setting tio.c_ispeed is
+		 * unneeded */
+		tio.c_cflag = (tio.c_cflag & ~(CBAUD << IBSHIFT)) | (B0 << IBSHIFT);
 
 		term.nexttermios[i] = tio;
 
@@ -672,7 +632,7 @@
 term_set_parity (int fd, enum parity_e parity) 
 {
 	int rval, i;
-	struct termios *tiop;
+	struct termios2 *tiop;
 
 	rval = 0;
 
@@ -712,10 +672,38 @@
 /***************************************************************************/
 
 int
+term_set_stopbits (int fd, int stopbits) 
+{
+	int rval, i;
+	struct termios2 *tiop;
+
+	rval = 0;
+        do { /* dummy */
+
+		i = term_find(fd);
+		if ( i < 0 ) {
+			rval = -1;
+			break;
+		}
+
+		tiop = &term.nexttermios[i];
+
+                if(stopbits<2) tiop->c_cflag &= ~CSTOPB;
+                         else  tiop->c_cflag |= CSTOPB;
+                break;
+
+	} while (0);
+
+	return rval;
+}
+
+/***************************************************************************/
+
+int
 term_set_databits (int fd, int databits)
 {
 	int rval, i;
-	struct termios *tiop;
+	struct termios2 *tiop;
 
 	rval = 0;
 
@@ -760,7 +748,7 @@
 term_set_flowcntrl (int fd, enum flowcntrl_e flowcntl)
 {
 	int rval, i;
-	struct termios *tiop;
+	struct termios2 *tiop;
 
 	rval = 0;
 
@@ -805,7 +793,7 @@
 term_set_local(int fd, int local)
 {
 	int rval, i;
-	struct termios *tiop;
+	struct termios2 *tiop;
 
 	rval = 0;
 
@@ -835,7 +823,7 @@
 term_set_hupcl (int fd, int on)
 {
 	int rval, i;
-	struct termios *tiop;
+	struct termios2 *tiop;
 
 	rval = 0;
 
@@ -864,11 +852,11 @@
 int
 term_set(int fd,
 		 int raw,
-		 int baud, enum parity_e parity, int bits, enum flowcntrl_e fc,
+		 int baud, enum parity_e parity, int bits, int stopbits, enum flowcntrl_e fc,
 		 int local, int hup_close)
 {
 	int rval, r, i, ni;
-	struct termios tio;
+	struct termios2 tio;
 
 	rval = 0;
 
@@ -903,6 +891,9 @@
 			r = term_set_databits(fd, bits);
 			if ( r < 0 ) { rval = -1; break; }
 			
+			r = term_set_stopbits(fd, stopbits);
+			if ( r < 0 ) { rval = -1; break; }
+			
 			r = term_set_flowcntrl(fd, fc);
 			if ( r < 0 ) { rval = -1; break; }
 			
@@ -967,7 +958,7 @@
 		}
 #else
 		{
-			struct termios tio, tioold;
+			struct termios2 tio, tioold;
 
 			r = tcgetattr(fd, &tio);
 			if ( r < 0 ) {
@@ -1077,7 +1068,7 @@
 		}
 #else
 		{
-			struct termios tio;
+			struct termios2 tio;
 
 			r = tcgetattr(fd, &tio);
 			if ( r < 0 ) {
@@ -1191,8 +1182,283 @@
 	return rval;
 }
 
+
 /**************************************************************************/
 
+int
+term_raise_rts(int fd)
+{
+	int rval, r, i;
+
+	rval = 0;
+
+	do { /* dummy */
+
+		i = term_find(fd);
+		if ( i < 0 ) {
+			rval = -1;
+			break;
+		}
+
+#ifdef __linux__
+		{
+			int opins = TIOCM_RTS;
+
+			r = ioctl(fd, TIOCMBIS, &opins);
+			if ( r < 0 ) {
+				term_errno = TERM_EDTRUP;
+				rval = -1;
+				break;
+			}
+		}
+#else
+// TODO: check if this would work on non-linux platforms on RTS
+		r = tcsetattr(fd, TCSANOW, &term.currtermios[i]);
+		if ( r < 0 ) {
+			/* FIXME: perhaps try to update currtermios */
+			term_errno = TERM_ESETATTR;
+			rval = -1;
+			break;
+		}
+#endif /* of __linux__ */
+	} while (0);
+
+	return rval;
+}
+
+/***************************************************************************/
+
+
+int
+term_lower_rts(int fd)
+{
+	int rval, r, i;
+
+	rval = 0;
+
+	do { /* dummy */
+
+		i = term_find(fd);
+		if ( i < 0 ) { 
+			rval = -1;
+			break;
+		}
+
+#ifdef __linux__
+		{
+			int opins = TIOCM_RTS;
+
+			r = ioctl(fd, TIOCMBIC, &opins);
+			if ( r < 0 ) {
+				term_errno = TERM_EDTRDOWN;
+				rval = -1;
+				break;
+			}
+		}
+#else
+// TODO: check if this would work on non-linux platforms on RTS
+		{
+			struct termios tio;
+
+			r = tcgetattr(fd, &tio);
+			if ( r < 0 ) {
+				term_errno = TERM_EGETATTR;
+				rval = -1;
+				break;
+			}
+			term.currtermios[i] = tio;
+			
+			cfsetospeed(&tio, B0);
+			cfsetispeed(&tio, B0);
+			
+			r = tcsetattr(fd, TCSANOW, &tio);
+			if ( r < 0 ) {
+				term_errno = TERM_ESETATTR;
+				rval = -1;
+				break;
+			}
+		}
+#endif /* of __linux__ */
+	} while (0);
+	
+	return rval;
+}
+
+
+/***************************************************************************/
+// TODO: nonstandard speeds
+
+int
+term_get_baudrate (int fd)
+{
+	int i;
+	int spd;
+	struct termios2 tio;
+
+	do { /* dummy */
+
+		i = term_find(fd);
+		if ( i < 0 ) {
+			spd = -1;
+			break;
+		}
+
+		tio = term.nexttermios[i];
+		spd=tio.c_ospeed;
+
+	} while (0);
+
+	return spd;
+}
+
+int
+term_get_databits (int fd)
+{
+ {
+ tcflag_t flg;
+ int i, bits;
+ do { /* dummy */
+ i = term_find(fd);
+ if ( i < 0 ) {
+ bits = -1;
+ break;
+ }
+ flg = term.currtermios[i].c_cflag & CSIZE;
+ switch (flg) {
+ case CS5: bits = 5; break;
+ case CS6: bits = 6; break;
+ case CS7: bits = 7; break;
+ case CS8:
+ default:  bits = 8; break;
+ }
+ } while (0);
+ return bits;
+ }
+}
+
+/***************************************************************************/
+
+int
+term_get_cflag (int fd) 
+{
+	int rval, i;
+	struct termios2 *tiop;
+
+	rval = 0;
+
+	do { /* dummy */
+
+		i = term_find(fd);
+		if ( i < 0 ) {
+			rval = -1;
+			break;
+		}
+
+		tiop = &term.nexttermios[i];
+
+		rval=tiop->c_cflag;
+
+	} while (0);
+
+	return rval;
+}
+
+/***************************************************************************/
+
+int
+term_get_iflag (int fd) 
+{
+	int rval, i;
+	struct termios2 *tiop;
+
+	rval = 0;
+
+	do { /* dummy */
+
+		i = term_find(fd);
+		if ( i < 0 ) {
+			rval = -1;
+			break;
+		}
+
+		tiop = &term.nexttermios[i];
+
+		rval=tiop->c_iflag;
+
+	} while (0);
+
+	return rval;
+}
+
+
+/***************************************************************************/
+
+
+int
+term_get_modem_flags(int fd)
+{
+	int rval, r;
+
+	rval = 0;
+
+	do { /* dummy */
+
+#ifdef __linux__
+		{
+			r = ioctl(fd, TIOCMGET, &rval);
+			if ( r < 0 ) {
+				term_errno = TERM_EDTRUP;
+				rval = -1;
+				break;
+			}
+		}
+#else
+/*
+		int i;
+		i = term_find(fd);
+		if ( i < 0 ) {
+			rval = -1;
+			break;
+		}
+
+	TODO: correct this!!!
+		r = tcsetattr(fd, TCSANOW, &term.currtermios[i]);
+		if ( r < 0 ) {
+			term_errno = TERM_ESETATTR;
+			rval = -1;
+			break;
+		}
+*/
+#endif /* of __linux__ */
+	} while (0);
+
+	return rval;
+}
+
+
+
+/*
+static int tiny_tiocmget(struct tty_struct *tty, struct file *file)
+{
+    struct tiny_serial *tiny = tty->driver_data;
+
+    unsigned int result = 0;
+    unsigned int msr = tiny->msr;
+    unsigned int mcr = tiny->mcr;
+*/
+//    result = ((mcr & MCR_DTR)  ? TIOCM_DTR  : 0) |  /* DTR is set */
+//             ((mcr & MCR_RTS)  ? TIOCM_RTS  : 0) |  /* RTS is set */
+//             ((mcr & MCR_LOOP) ? TIOCM_LOOP : 0) |  /* LOOP is set */
+//             ((msr & MSR_CTS)  ? TIOCM_CTS  : 0) |  /* CTS is set */
+//             ((msr & MSR_CD)   ? TIOCM_CAR  : 0) |  /* Carrier detect is set*/
+//             ((msr & MSR_RI)   ? TIOCM_RI   : 0) |  /* Ring Indicator is set */
+//             ((msr & MSR_DSR)  ? TIOCM_DSR  : 0);   /* DSR is set */
+/*
+    return result;
+}
+*/
+
+/***************************************************************************/
 /*
  * Local Variables:
  * mode:c
