gentoo/dev-libs/libserialport/files/libserialport-0.1.2-termios-glibc-2.42-3.patch
Sam James 8b9885718d
dev-libs/libserialport: fix compat w/ glibc-2.42 (termios changes)
Pull in hpa's patches from https://github.com/hpax/libserialport. He's
sent them upstream but I think sigrok are having some infra issues.

Bug: https://sourceware.org/PR33340
Closes: https://bugs.gentoo.org/962830
Signed-off-by: Sam James <sam@gentoo.org>
2025-09-14 07:25:27 +01:00

234 lines
8.1 KiB
Diff

https://bugs.gentoo.org/962830
https://sourceware.org/bugzilla/show_bug.cgi?id=33340#c24
From f051e30dff057a7304a6c94a942da9a09740851d Mon Sep 17 00:00:00 2001
From: "H. Peter Anvin" <hpa@zytor.com>
Date: Wed, 10 Sep 2025 18:01:48 -0700
Subject: [PATCH 3/3] termios: check to see if termios speed_t is a direct map
to baud
If termios speed_t is a direct mapping to bauds, it is presumably safe
to assume that it can be used as a generic interface. This applies to
Linux with glibc 2.42+, GNU Hurd, and at least some BSDs.
Try to detect this case and if so, do the simple thing.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
---
configure.ac | 56 +++++++++++++++++++++++++++++++++++++++-
libserialport_internal.h | 7 +++--
linux_termios.c | 12 ++++++---
serialport.c | 19 +++++++++++++-
4 files changed, 86 insertions(+), 8 deletions(-)
diff --git a/configure.ac b/configure.ac
index d71833fea141..ae6406e5e08b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -111,6 +111,60 @@ AC_SYS_LARGEFILE
# Define size_t if not defined as standard.
AC_TYPE_SIZE_T
+# Check to see if the baud rates in termios.h seem sane.
+AC_CACHE_CHECK([if <termios.h> is sane], [sp_cv_termios_sane], [
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <termios.h>
+#if (!defined(B0) || B0 == 0) \
+ && (!defined(B50) || B50 == 50) \
+ && (!defined(B75) || B75 == 75) \
+ && (!defined(B110) || B110 == 110) \
+ && (!defined(B134) || B134 == 134) \
+ && (!defined(B150) || B150 == 150) \
+ && (!defined(B200) || B200 == 200) \
+ && (!defined(B300) || B300 == 300) \
+ && (!defined(B600) || B600 == 600) \
+ && (!defined(B1200) || B1200 == 1200) \
+ && (!defined(B1800) || B1800 == 1800) \
+ && (!defined(B2400) || B2400 == 2400) \
+ && (!defined(B4800) || B4800 == 4800) \
+ && (!defined(B7200) || B7200 == 7200) \
+ && (!defined(B9600) || B9600 == 9600) \
+ && (!defined(B14400) || B14400 == 14400) \
+ && (!defined(B19200) || B19200 == 19200) \
+ && (!defined(B28800) || B28800 == 28800) \
+ && (!defined(B33600) || B33600 == 33600) \
+ && (!defined(B38400) || B38400 == 38400) \
+ && (!defined(B57600) || B57600 == 57600) \
+ && (!defined(B76800) || B76800 == 76800) \
+ && (!defined(B115200) || B115200 == 115200) \
+ && (!defined(B153600) || B153600 == 153600) \
+ && (!defined(B230400) || B230400 == 230400) \
+ && (!defined(B307200) || B307200 == 307200) \
+ && (!defined(B460800) || B460800 == 460800) \
+ && (!defined(B500000) || B500000 == 500000) \
+ && (!defined(B576000) || B576000 == 576000) \
+ && (!defined(B614400) || B614400 == 614400) \
+ && (!defined(B921600) || B921600 == 921600) \
+ && (!defined(B1000000) || B1000000 == 1000000) \
+ && (!defined(B1152000) || B1152000 == 1152000) \
+ && (!defined(B1500000) || B1500000 == 1500000) \
+ && (!defined(B2000000) || B2000000 == 2000000) \
+ && (!defined(B2500000) || B2500000 == 2500000) \
+ && (!defined(B3000000) || B3000000 == 3000000) \
+ && (!defined(B3500000) || B3500000 == 3500000) \
+ && (!defined(B4000000) || B4000000 == 4000000) \
+ && (!defined(B5000000) || B5000000 == 5000000) \
+ && (!defined(B10000000) || B10000000 == 10000000)
+# define TERMIOS_SPEED_T_SANE 1
+#else
+# error "<termios.h> uses stupid constants"
+#endif
+]])], [sp_cv_termios_sane=yes], [sp_cv_termios_sane=no])])
+
+AS_IF([test x$sp_cv_termios_sane = xyes],
+[AC_DEFINE(HAVE_SANE_TERMIOS, 1, [<termios.h> speeds are sane])],
+[
# Check for specific termios structures.
AC_CHECK_TYPES([struct termios2],,,
[[#include <linux/termios.h>]])
@@ -121,7 +175,7 @@ AC_CHECK_MEMBERS([struct termios.c_ispeed, struct termios.c_ospeed,
# Check for the BOTHER definition, needed for setting arbitrary baud rates.
# We can't just #ifdef BOTHER in the code, because of the separation between
# code using libc headers and code using kernel termios.h headers.
-AC_CHECK_DECLS([BOTHER],,, [[#include <linux/termios.h>]])
+AC_CHECK_DECLS([BOTHER],,, [[#include <linux/termios.h>]])])
# Check for serial_struct.
AC_CHECK_TYPES([struct serial_struct],,, [[#include <linux/serial.h>]])
diff --git a/libserialport_internal.h b/libserialport_internal.h
index 57346d653ad3..88bb9f60b06b 100644
--- a/libserialport_internal.h
+++ b/libserialport_internal.h
@@ -130,8 +130,11 @@
#endif
/* Non-standard baudrates are not available everywhere. */
-#if (defined(HAVE_TERMIOS_SPEED) || defined(HAVE_TERMIOS2_SPEED)) && HAVE_DECL_BOTHER
-#define USE_TERMIOS_SPEED
+#ifdef HAVE_SANE_TERMIOS
+/* Directly supported by termios */
+# undef USE_TERMIOS_SPEED
+#elif (defined(HAVE_TERMIOS_SPEED) || defined(HAVE_TERMIOS2_SPEED)) && HAVE_DECL_BOTHER
+# define USE_TERMIOS_SPEED
#endif
struct sp_port {
diff --git a/linux_termios.c b/linux_termios.c
index 0dd0b105726f..dad0e9cb4208 100644
--- a/linux_termios.c
+++ b/linux_termios.c
@@ -18,10 +18,10 @@
*/
/*
- * At the time of writing, glibc does not support the Linux kernel interfaces
- * for setting non-standard baud rates and flow control. We therefore have to
- * prepare the correct ioctls ourselves, for which we need the declarations in
- * linux/termios.h.
+ * glibc before version 2.42 does not support the Linux kernel
+ * interfaces for setting non-standard baud rates and flow control. We
+ * therefore have to prepare the correct ioctls ourselves, for which
+ * we need the declarations in linux/termios.h.
*
* We can't include linux/termios.h in serialport.c however, because its
* contents conflict with the termios.h provided by glibc. So this file exists
@@ -38,6 +38,8 @@
#include <linux/termios.h>
#include "linux_termios.h"
+#ifndef HAVE_SANE_TERMIOS
+
SP_PRIV unsigned long get_termios_get_ioctl(void)
{
#ifdef HAVE_STRUCT_TERMIOS2
@@ -127,3 +129,5 @@ SP_PRIV void set_termiox_flow(void *data, int rts, int cts, int dtr, int dsr)
termx->x_cflag |= DSRXON;
}
#endif
+
+#endif
diff --git a/serialport.c b/serialport.c
index 392ec61e95f2..f1279cff87ca 100644
--- a/serialport.c
+++ b/serialport.c
@@ -23,6 +23,7 @@
#include "libserialport_internal.h"
+#ifndef HAVE_SANE_TERMIOS
static const struct std_baudrate std_baudrates[] = {
#ifdef _WIN32
/*
@@ -42,8 +43,8 @@ static const struct std_baudrate std_baudrates[] = {
#endif
#endif
};
-
#define NUM_STD_BAUDRATES ARRAY_SIZE(std_baudrates)
+#endif
void (*sp_debug_handler)(const char *format, ...) = sp_default_debug_handler;
@@ -1692,7 +1693,9 @@ static enum sp_return set_flow(int fd, struct port_data *data)
static enum sp_return get_config(struct sp_port *port, struct port_data *data,
struct sp_port_config *config)
{
+#ifndef HAVE_SANE_TERMIOS
unsigned int i;
+#endif
TRACE("%p, %p, %p", port, data, config);
@@ -1811,6 +1814,9 @@ static enum sp_return get_config(struct sp_port *port, struct port_data *data,
data->termiox_supported = 0;
#endif
+#ifdef HAVE_SANE_TERMIOS
+ config->baudrate = cfgetospeed(&data->term);
+#else
for (i = 0; i < NUM_STD_BAUDRATES; i++) {
if (cfgetospeed(&data->term) == std_baudrates[i].index) {
config->baudrate = std_baudrates[i].value;
@@ -1827,6 +1833,7 @@ static enum sp_return get_config(struct sp_port *port, struct port_data *data,
config->baudrate = -1;
#endif
}
+#endif
switch (data->term.c_cflag & CSIZE) {
case CS8:
@@ -1898,7 +1905,10 @@ static enum sp_return get_config(struct sp_port *port, struct port_data *data,
static enum sp_return set_config(struct sp_port *port, struct port_data *data,
const struct sp_port_config *config)
{
+#ifndef HAVE_SANE_TERMIOS
unsigned int i;
+#endif
+
#ifdef __APPLE__
BAUD_TYPE baud_nonstd;
@@ -2064,6 +2074,12 @@ static enum sp_return set_config(struct sp_port *port, struct port_data *data,
int controlbits;
if (config->baudrate >= 0) {
+#ifdef HAVE_SANE_TERMIOS
+ if (cfsetospeed(&data->term, config->baudrate) < 0)
+ RETURN_FAIL("cfsetospeed() failed");
+ if (cfsetispeed(&data->term, config->baudrate) < 0)
+ RETURN_FAIL("cfsetispeed() failed");
+#else
for (i = 0; i < NUM_STD_BAUDRATES; i++) {
if (config->baudrate == std_baudrates[i].value) {
if (cfsetospeed(&data->term, std_baudrates[i].index) < 0)
@@ -2088,6 +2104,7 @@ static enum sp_return set_config(struct sp_port *port, struct port_data *data,
RETURN_ERROR(SP_ERR_SUPP, "Non-standard baudrate not supported");
#endif
}
+#endif
}
if (config->bits >= 0) {
--
2.51.0