1
0
mirror of https://github.com/home-assistant/operating-system.git synced 2026-02-14 23:18:57 +00:00

Add generic_raw_uart patch for termios2/glibc 2.42+ compatibility (#4504)

This change adds termios2 compatibility to the ioctl interface of generic_raw_uart making it compatible to glibc 2.42+ environments which prefer termios2 rather than the old/obsolete termios ioctls. This is a similar change to what was introduced to eq3_char_loop in #4471. However, this change in generic_raw_uart is required so that /dev/raw-uart will be termios2 compatible for applications within the OpenCCU Add-on directly opening it in case a non-dualcopro RF module like HmIP-RFUSB-TK is using it directly. (This refs https://github.com/OpenCCU/OpenCCU/issues/3498)
This commit is contained in:
Jens Maus
2026-01-26 10:44:22 +01:00
committed by GitHub
parent e54e8c4bde
commit 472482776d

View File

@@ -0,0 +1,188 @@
kernel/generic_raw_uart.c: added termios2/glibc 2.42+ compatibility
Upstream: Not applicable
Signed-off-by: Jens Maus <mail@jens-maus.de>
diff --git a/kernel/generic_raw_uart.c b/kernel/generic_raw_uart.c
index 0c3e3de..fac1ff6 100644
--- a/kernel/generic_raw_uart.c
+++ b/kernel/generic_raw_uart.c
@@ -36,6 +36,10 @@
#include <linux/version.h>
#include <asm/ioctls.h>
#include <asm/termios.h>
+#include <linux/serial.h>
+#ifdef TCGETS2
+#include <asm/termbits.h>
+#endif
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/delay.h>
@@ -489,7 +493,7 @@ static long generic_raw_uart_ioctl(struct file *filep, unsigned int cmd, unsigne
/* Set connection priority */
case IOCTL_IOCSPRIORITY: /* Set: arg points to the value */
- if (_access_ok(VERIFY_WRITE, (void __user *)arg, sizeof(unsigned long)))
+ if (_access_ok(VERIFY_READ, (void __user *)arg, sizeof(unsigned long)))
{
ret = __get_user(temp, (unsigned long __user *)arg);
if (!ret)
@@ -503,7 +507,7 @@ static long generic_raw_uart_ioctl(struct file *filep, unsigned int cmd, unsigne
/* Get connection priority */
case IOCTL_IOCGPRIORITY: /* Get: arg is pointer to result */
- if (_access_ok(VERIFY_READ, (void __user *)arg, sizeof(unsigned long)))
+ if (_access_ok(VERIFY_WRITE, (void __user *)arg, sizeof(unsigned long)))
{
ret = __put_user(conn->priority, (unsigned long __user *)arg);
}
@@ -518,7 +522,7 @@ static long generic_raw_uart_ioctl(struct file *filep, unsigned int cmd, unsigne
break;
case IOCTL_IOCGDEVINFO:
- if (_access_ok(VERIFY_READ, (void __user *)arg, MAX_DEVICE_TYPE_LEN))
+ if (_access_ok(VERIFY_WRITE, (void __user *)arg, MAX_DEVICE_TYPE_LEN))
{
buf = kmalloc(MAX_DEVICE_TYPE_LEN, GFP_KERNEL);
if (buf)
@@ -543,7 +547,7 @@ static long generic_raw_uart_ioctl(struct file *filep, unsigned int cmd, unsigne
/* Emulated TTY ioctl: Get termios struct */
case TCGETS:
- if (_access_ok(VERIFY_READ, (void __user *)arg, sizeof(struct termios)))
+ if (_access_ok(VERIFY_WRITE, (void __user *)arg, sizeof(struct termios)))
{
if (down_interruptible(&instance->sem))
{
@@ -561,9 +565,86 @@ static long generic_raw_uart_ioctl(struct file *filep, unsigned int cmd, unsigne
}
break;
+#ifdef TCGETS2
+ /* Emulated TTY ioctl: Get termios2 struct */
+ case TCGETS2:
+ if (_access_ok(VERIFY_WRITE, (void __user *)arg, sizeof(struct termios2)))
+ {
+ struct termios2 t2;
+
+ if (down_interruptible(&instance->sem))
+ {
+ ret = -ERESTARTSYS;
+ }
+ else
+ {
+ memset(&t2, 0, sizeof(t2));
+ t2.c_iflag = instance->termios.c_iflag;
+ t2.c_oflag = instance->termios.c_oflag;
+ t2.c_cflag = instance->termios.c_cflag;
+ t2.c_lflag = instance->termios.c_lflag;
+ t2.c_line = instance->termios.c_line;
+ memcpy(t2.c_cc, instance->termios.c_cc, NCCS);
+
+ /* No dedicated speed storage in this driver; provide neutral values. */
+ t2.c_ispeed = 0;
+ t2.c_ospeed = 0;
+
+ ret = copy_to_user((void __user *)arg, &t2, sizeof(struct termios2));
+ up(&instance->sem);
+ }
+ }
+ else
+ {
+ ret = -EFAULT;
+ }
+ break;
+#endif
+
+#ifdef TCSETS2
+ /* Emulated TTY ioctl: Set termios2 struct */
+ case TCSETS2:
+#ifdef TCSETSW2
+ case TCSETSW2:
+#endif
+#ifdef TCSETSF2
+ case TCSETSF2:
+#endif
+ if (_access_ok(VERIFY_READ, (void __user *)arg, sizeof(struct termios2)))
+ {
+ struct termios2 t2;
+
+ if (down_interruptible(&instance->sem))
+ {
+ ret = -ERESTARTSYS;
+ }
+ else
+ {
+ ret = copy_from_user(&t2, (void __user *)arg, sizeof(struct termios2));
+ if (!ret)
+ {
+ instance->termios.c_iflag = t2.c_iflag;
+ instance->termios.c_oflag = t2.c_oflag;
+ instance->termios.c_cflag = t2.c_cflag;
+ instance->termios.c_lflag = t2.c_lflag;
+ instance->termios.c_line = t2.c_line;
+ memcpy(instance->termios.c_cc, t2.c_cc, NCCS);
+ }
+ up(&instance->sem);
+ }
+ }
+ else
+ {
+ ret = -EFAULT;
+ }
+ break;
+#endif
+
/* Emulated TTY ioctl: Set termios struct */
case TCSETS:
- if (_access_ok(VERIFY_WRITE, (void __user *)arg, sizeof(struct termios)))
+ case TCSETSW:
+ case TCSETSF:
+ if (_access_ok(VERIFY_READ, (void __user *)arg, sizeof(struct termios)))
{
if (down_interruptible(&instance->sem))
{
@@ -640,6 +721,33 @@ static long generic_raw_uart_ioctl(struct file *filep, unsigned int cmd, unsigne
case TIOCMSET:
break;
+ /* Serial meta ioctls probed by some userspace stacks: stub safely */
+ case TIOCSERGETLSR:
+ if (_access_ok(VERIFY_WRITE, (void __user *)arg, sizeof(temp)))
+ {
+ temp = TIOCSER_TEMT; /* transmitter empty */
+ ret = __put_user(temp, (int __user *)arg);
+ }
+ else
+ {
+ ret = -EFAULT;
+ }
+ break;
+
+ case TIOCGICOUNT:
+ if (_access_ok(VERIFY_WRITE, (void __user *)arg, sizeof(struct serial_icounter_struct)))
+ {
+ struct serial_icounter_struct icount;
+ memset(&icount, 0, sizeof(icount));
+ ret = copy_to_user((void __user *)arg, &icount, sizeof(icount));
+ }
+ else
+ {
+ ret = -EFAULT;
+ }
+ break;
+
+
default:
ret = -ENOTTY;
}
@@ -1355,7 +1463,7 @@ EXPORT_SYMBOL(generic_raw_uart_verify_dkey);
MODULE_ALIAS("platform:generic-raw-uart");
MODULE_LICENSE("GPL");
-MODULE_VERSION("1.31");
+MODULE_VERSION("1.32");
MODULE_DESCRIPTION("generic raw uart driver for communication of debmatic and piVCCU with the HM-MOD-RPI-PCB and RPI-RF-MOD radio modules");
MODULE_AUTHOR("Alexander Reinert <alex@areinert.de>");