[PATCH] gdb: unix: allow to use custom baud rate

Alexey Lapshin alexey.lapshin@espressif.com
Thu Sep 26 18:00:07 GMT 2024


Modern unix systems allow to set custom baud rate instead of predefined in termios.h.

- To use this in Linux it must have BOTHER macro in "asm/termio.h"
- MacOS could handle this using IOSSIOSPEED passed to ioctl()


---
 gdb/config.in    |   3 ++
 gdb/configure    |  37 +++++++++++++++++
 gdb/configure.ac |  20 ++++++++++
 gdb/ser-unix.c   | 102 +++++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 158 insertions(+), 4 deletions(-)

diff --git a/gdb/config.in b/gdb/config.in
index 57be033802e..b445fc3dd8f 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -562,6 +562,9 @@
 /* Define to 1 if you have the <sys/wait.h> header file. */
 #undef HAVE_SYS_WAIT_H
 
+/* Define if asm/termio.h defines the BOTHER request. */
+#undef HAVE_TERMIOS_BOTHER
+
 /* Define to 1 if you have the <termios.h> header file. */
 #undef HAVE_TERMIOS_H
 
diff --git a/gdb/configure b/gdb/configure
index 53eaad4f0e2..1016737c09a 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -30386,6 +30386,43 @@ $as_echo "#define HAVE_PT_GETDBREGS 1" >>confdefs.h
 
 fi
 
+# See if <asm/termios.h> provides the BOTHER request.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PT_GETDBREGS" >&5
+$as_echo_n "checking for PT_GETDBREGS... " >&6; }
+if ${gdb_cv_have_termios_bother+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <asm/termios.h>
+int
+main ()
+{
+BOTHER; TCGETS2;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  gdb_cv_have_termios_bother=yes
+else
+  gdb_cv_have_termios_bother=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_have_termios_bother" >&5
+$as_echo "$gdb_cv_have_termios_bother" >&6; }
+if test "$gdb_cv_have_termios_bother" = yes; then
+
+$as_echo "#define HAVE_TERMIOS_BOTHER 1" >>confdefs.h
+
+fi
+
+
 # See if <sys/ptrace.h> supports LWP names on FreeBSD
 # Older FreeBSD versions don't have the pl_tdname member of
 # `struct ptrace_lwpinfo'.
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 8368fea0423..4ffdf2d61ff 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1487,6 +1487,26 @@ if test "$gdb_cv_have_pt_getdbregs" = yes; then
   [Define if sys/ptrace.h defines the PT_GETDBREGS request.])
 fi
 
+# See if <asm/termios.h> provides the BOTHER request.
+AC_MSG_CHECKING(for PT_GETDBREGS)
+AC_CACHE_VAL(
+  [gdb_cv_have_termios_bother],
+  [AC_COMPILE_IFELSE(
+     [AC_LANG_PROGRAM(
+	[#include <asm/termios.h>],
+	[BOTHER; TCGETS2;]
+      )],
+     [gdb_cv_have_termios_bother=yes],
+     [gdb_cv_have_termios_bother=no]
+   )]
+)
+AC_MSG_RESULT($gdb_cv_have_termios_bother)
+if test "$gdb_cv_have_termios_bother" = yes; then
+  AC_DEFINE(HAVE_TERMIOS_BOTHER, 1,
+  [Define if asm/termios.h defines the BOTHER request.])
+fi
+
+
 # See if <sys/ptrace.h> supports LWP names on FreeBSD
 # Older FreeBSD versions don't have the pl_tdname member of
 # `struct ptrace_lwpinfo'.
diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c
index 02845aa938b..fe6ca3f0b94 100644
--- a/gdb/ser-unix.c
+++ b/gdb/ser-unix.c
@@ -30,6 +30,22 @@
 #include "gdbsupport/gdb_select.h"
 #include "cli/cli-cmds.h"
 #include "gdbsupport/filestuff.h"
+#if HAVE_TERMIOS_BOTHER || __APPLE__
+#include <sys/ioctl.h>
+#endif
+#if __APPLE__
+#include <IOKit/serial/ioss.h>
+#ifdef IOSSIOSPEED
+#define HAVE_APPLE_IOSSIOSPEED
+#endif
+#endif
+#if HAVE_TERMIOS_BOTHER
+/* Workaround to resolve conflicting declarations of termios
+ * in <asm/termbits.h> and <termios.h */
+#define termios asmtermios
+#include <asm/termbits.h>
+#undef termios
+#endif
 #include <termios.h>
 #include "gdbsupport/scoped_ignore_sigttou.h"
 
@@ -289,10 +305,28 @@ baudtab[] =
     4800, B4800
   }
   ,
+#ifdef B7200
+  {
+    7200, B7200
+  }
+  ,
+#endif
   {
     9600, B9600
   }
   ,
+#ifdef B14400
+  {
+    14400, B14400
+  }
+  ,
+#endif
+#ifdef B28800
+  {
+    28800, B28800
+  }
+  ,
+#endif
   {
     19200, B19200
   }
@@ -307,6 +341,12 @@ baudtab[] =
   }
   ,
 #endif
+#ifdef B76800
+  {
+    76800, B76800
+  }
+  ,
+#endif
 #ifdef B115200
   {
     115200, B115200
@@ -412,6 +452,7 @@ rate_to_code (int rate)
 	  /* check if it is in between valid values.  */
 	  if (rate < baudtab[i].rate)
 	    {
+#if !(HAVE_TERMIOS_BOTHER || HAVE_APPLE_IOSSIOSPEED)
 	      if (i)
 		{
 		  error (_("Invalid baud rate %d.  "
@@ -423,21 +464,27 @@ rate_to_code (int rate)
 		  error (_("Invalid baud rate %d.  Minimum value is %d."),
 			 rate, baudtab[0].rate);
 		}
+#else
+	      return -1;
+#endif
 	    }
 	}
     }
- 
+
+#if !(HAVE_TERMIOS_BOTHER || HAVE_APPLE_IOSSIOSPEED)
   /* The requested speed was too large.  */
   error (_("Invalid baud rate %d.  Maximum value is %d."),
 	 rate, baudtab[i - 1].rate);
+#else
+  return -1;
+#endif
 }
 
 static void
-hardwire_setbaudrate (struct serial *scb, int rate)
+set_baudcode_baudrate (struct serial *scb, int baud_code)
 {
   struct hardwire_ttystate state;
-  int baud_code = rate_to_code (rate);
-  
+
   if (get_tty_state (scb, &state))
     perror_with_name ("could not get tty state");
 
@@ -448,6 +495,53 @@ hardwire_setbaudrate (struct serial *scb, int rate)
     perror_with_name ("could not set tty state");
 }
 
+static void
+set_custom_baudrate (int fd, int rate)
+{
+#if HAVE_TERMIOS_BOTHER
+  struct termios2 tio;
+
+  if (ioctl (fd, TCGETS2, &tio) < 0)
+    {
+      error (_("Can not set custom baud rate %d.  Error is %d (TCGETS2)."),
+	       rate, errno);
+    }
+  tio.c_cflag &= ~CBAUD;
+  tio.c_cflag |= BOTHER;
+  tio.c_ispeed = rate;
+  tio.c_ospeed = rate;
+  if (ioctl (fd, TCSETS2, &tio) < 0)
+    {
+      error (_("Can not set custom baud rate %d.  Error is %d (TCSETS2)."),
+	       rate, errno);
+    }
+
+#elif HAVE_APPLE_IOSSIOSPEED
+  if (ioctl (fd, IOSSIOSPEED, &rate) < 0)
+    {
+      error (_("Can not set custom baud rate %d.  Error is %d."),
+	       rate, errno);
+    }
+#endif
+}
+
+static void
+hardwire_setbaudrate (struct serial *scb, int rate)
+{
+  int baud_code = rate_to_code (rate);
+
+  if (baud_code < 0)
+    {
+      /* The baud rate code was not found.
+         Try to set a custom baud rate.  */
+      set_custom_baudrate (scb->fd, rate);
+    }
+  else
+    {
+      set_baudcode_baudrate (scb, baud_code);
+    }
+}
+
 static int
 hardwire_setstopbits (struct serial *scb, int num)
 {
-- 
2.43.0




More information about the Gdb-patches mailing list