git: 85bf328868c8 - main - linux: support termios2 ioctls

From: Warner Losh <imp_at_FreeBSD.org>
Date: Fri, 09 Jan 2026 21:03:18 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=85bf328868c8f6d8fede9d8d4b4ff8a589636990

commit 85bf328868c8f6d8fede9d8d4b4ff8a589636990
Author:     mothcompute <mothcompute@protonmail.com>
AuthorDate: 2026-01-06 03:19:21 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2026-01-09 20:58:25 +0000

    linux: support termios2 ioctls
    
    Signed-off-by: mothcompute <mothcompute@protonmail.com>
    Reviewed by: imp
    Pull Request: https://github.com/freebsd/freebsd-src/pull/1949
---
 sys/compat/linux/linux_ioctl.c | 69 +++++++++++++++++++++++++++++++++++++++++-
 sys/compat/linux/linux_ioctl.h | 10 ++++++
 2 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index ceb17bd040b5..f6c239b08ac2 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -331,6 +331,17 @@ struct linux_termios {
 	unsigned char c_cc[LINUX_NCCS];
 };
 
+struct linux_termios2 {
+	unsigned int c_iflag;
+	unsigned int c_oflag;
+	unsigned int c_cflag;
+	unsigned int c_lflag;
+	unsigned char c_line;
+	unsigned char c_cc[LINUX_NCCS];
+	unsigned int c_ispeed;
+	unsigned int c_ospeed;
+};
+
 struct linux_winsize {
 	unsigned short ws_row, ws_col;
 	unsigned short ws_xpixel, ws_ypixel;
@@ -386,7 +397,7 @@ bsd_to_linux_speed(int speed, struct speedtab *table)
 	for ( ; table->sp_speed != -1; table++)
 		if (table->sp_speed == speed)
 			return (table->sp_code);
-	return (-1);
+	return (LINUX_BOTHER);
 }
 
 static void
@@ -508,6 +519,14 @@ bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios)
 	lios->c_line = 0;
 }
 
+static void
+bsd_to_linux_termios2(struct termios *bios, struct linux_termios2 *lios2)
+{
+	bsd_to_linux_termios(bios, (struct linux_termios *)lios2);
+	lios2->c_ospeed = bios->c_ospeed;
+	lios2->c_ispeed = bios->c_ispeed;
+}
+
 static void
 linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios)
 {
@@ -628,6 +647,16 @@ linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios)
 	    linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab);
 }
 
+static void
+linux_to_bsd_termios2(struct linux_termios2 *lios2, struct termios *bios)
+{
+	linux_to_bsd_termios((struct linux_termios *)lios2, bios);
+	if ((lios2->c_cflag & LINUX_CBAUD) == LINUX_BOTHER)
+		bios->c_ospeed = lios2->c_ospeed;
+	if ((lios2->c_cflag & LINUX_CIBAUD) == LINUX_BOTHER << LINUX_IBSHIFT)
+		bios->c_ispeed = lios2->c_ispeed;
+}
+
 static void
 bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio)
 {
@@ -664,6 +693,7 @@ linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
 {
 	struct termios bios;
 	struct linux_termios lios;
+	struct linux_termios2 lios2;
 	struct linux_termio lio;
 	struct file *fp;
 	int error;
@@ -1001,6 +1031,43 @@ linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
 		args->cmd = TIOCCBRK;
 		error = (sys_ioctl(td, (struct ioctl_args *)args));
 		break;
+
+	case LINUX_TCGETS2:
+		error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
+		    td);
+		if (error)
+			break;
+		bsd_to_linux_termios2(&bios, &lios2);
+		error = copyout(&lios2, (void *)args->arg, sizeof(lios2));
+		break;
+
+	case LINUX_TCSETS2:
+		error = copyin((void *)args->arg, &lios2, sizeof(lios2));
+		if (error)
+			break;
+		linux_to_bsd_termios2(&lios2, &bios);
+		error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
+		    td));
+		break;
+
+	case LINUX_TCSETSW2:
+		error = copyin((void *)args->arg, &lios2, sizeof(lios2));
+		if (error)
+			break;
+		linux_to_bsd_termios2(&lios2, &bios);
+		error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
+		    td));
+		break;
+
+	case LINUX_TCSETSF2:
+		error = copyin((void *)args->arg, &lios2, sizeof(lios2));
+		if (error)
+			break;
+		linux_to_bsd_termios2(&lios2, &bios);
+		error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
+		    td));
+		break;
+
 	case LINUX_TIOCGPTN: {
 		int nb;
 
diff --git a/sys/compat/linux/linux_ioctl.h b/sys/compat/linux/linux_ioctl.h
index 8345b7e4b719..d01a30538981 100644
--- a/sys/compat/linux/linux_ioctl.h
+++ b/sys/compat/linux/linux_ioctl.h
@@ -383,6 +383,11 @@
 #define	LINUX_TIOCSBRK		0x5427
 #define	LINUX_TIOCCBRK		0x5428
 
+#define LINUX_TCGETS2		0x542A
+#define LINUX_TCSETS2		0x542B
+#define LINUX_TCSETSW2		0x542C
+#define LINUX_TCSETSF2		0x542D
+
 #define LINUX_TIOCGPTN		0x5430
 #define LINUX_TIOCSPTLCK	0x5431
 
@@ -501,6 +506,7 @@
 #define	LINUX_FF1		0x0008000
 
 #define	LINUX_CBAUD		0x0000100f
+#define	LINUX_CIBAUD		(LINUX_CBAUD << LINUX_IBSHIFT)
 
 #define	LINUX_B0		0x00000000
 #define	LINUX_B50		0x00000001
@@ -537,8 +543,12 @@
 #define	LINUX_HUPCL		0x00000400
 #define	LINUX_CLOCAL		0x00000800
 
+#define	LINUX_BOTHER		0x00001000
+
 #define	LINUX_CRTSCTS		0x80000000
 
+#define	LINUX_IBSHIFT		16
+
 /* Linux c_lflag masks */
 #define	LINUX_ISIG		0x00000001
 #define	LINUX_ICANON		0x00000002