]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb: unix: allow to use custom baud rate
authorAlexey Lapshin <alexey.lapshin@espressif.com>
Wed, 9 Apr 2025 16:19:02 +0000 (16:19 +0000)
committerSimon Marchi <simon.marchi@efficios.com>
Fri, 6 Jun 2025 19:52:43 +0000 (15:52 -0400)
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()

Approved-By: Simon Marchi <simon.marchi@efficios.com>
Change-Id: I5bc95982f5d90c7030b73f484ecc0f75c060ebf7

gdb/config.in
gdb/configure
gdb/configure.ac
gdb/ser-unix.c

index c0a050c7bc52b71af371ca76019f460bb905a1d4..149aeaf979bafe4eb8248d9ba0bdefe13a761de8 100644 (file)
@@ -96,6 +96,9 @@
 /* Define if amd-dbgapi is being linked in. */
 #undef HAVE_AMD_DBGAPI
 
+/* Define to 1 if you have the <asm/termios.h> header file. */
+#undef HAVE_ASM_TERMIOS_H
+
 /* Define to 1 if you have the `btowc' function. */
 #undef HAVE_BTOWC
 
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define to 1 if you have the <IOKit/serial/ioss.h> header file. */
+#undef HAVE_IOKIT_SERIAL_IOSS_H
+
 /* Define to 1 if you have the `kinfo_getfile' function. */
 #undef HAVE_KINFO_GETFILE
 
index 866ddce7af17a37d3caddb78236e054815a4cb96..8fc3b04efbfc2323c1bc9690a9ec7b10442ed5b1 100755 (executable)
@@ -29263,6 +29263,8 @@ $as_echo "#define STDC_HEADERS 1" >>confdefs.h
 fi
 
 for ac_header in  \
+  IOKit/serial/ioss.h \
+  asm/termios.h \
   machine/reg.h \
   nlist.h \
   ptrace.h \
index 52405f4face10f93ab1f6f0d2bb22a8a415a8f04..226e27e4fe54a9d3ac06e8be4439dd5dce8eb975 100644 (file)
@@ -1357,6 +1357,8 @@ AC_SUBST(SRCHIGH_CFLAGS)
 
 AC_HEADER_STDC
 AC_CHECK_HEADERS([ \
+  IOKit/serial/ioss.h \
+  asm/termios.h \
   machine/reg.h \
   nlist.h \
   ptrace.h \
index db614c86171220a65988cb395de0cb6c38d1af1d..cc81e3bb8265d24dc58ef2564906ce19ff4cef5c 100644 (file)
 #include "gdbsupport/gdb_select.h"
 #include "cli/cli-cmds.h"
 #include "gdbsupport/filestuff.h"
-#include <termios.h>
+
+#ifdef HAVE_SYS_IOCTL_H
+#  include <sys/ioctl.h>
+#endif
+
+#if HAVE_IOKIT_SERIAL_IOSS_H
+#  include <IOKit/serial/ioss.h>
+#endif
+
+#if HAVE_ASM_TERMIOS_H
+/* Workaround to resolve conflicting declarations of termios
+   in <asm/termbits.h> and <termios.h>.  */
+#  define termios asmtermios
+#  include <asm/termbits.h>
+#  undef termios
+#endif
+
+#ifdef HAVE_TERMIOS_H
+#  include <termios.h>
+#endif
+
 #include "gdbsupport/scoped_ignore_sigttou.h"
 
+#if defined(HAVE_SYS_IOCTL_H) && (defined(BOTHER) || defined(IOSSIOSPEED))
+#  define HAVE_CUSTOM_BAUDRATE_SUPPORT 1
+#endif
+
 struct hardwire_ttystate
   {
     struct termios termios;
@@ -436,6 +460,7 @@ rate_to_code (int rate)
          /* check if it is in between valid values.  */
          if (rate < baudtab[i].rate)
            {
+#if !HAVE_CUSTOM_BAUDRATE_SUPPORT
              if (i)
                {
                  error (_("Invalid baud rate %d.  "
@@ -447,29 +472,126 @@ rate_to_code (int rate)
                  error (_("Invalid baud rate %d.  Minimum value is %d."),
                         rate, baudtab[0].rate);
                }
+#else
+             return -1;
+#endif
            }
        }
     }
+
+#if !HAVE_CUSTOM_BAUDRATE_SUPPORT
   /* The requested speed was too large.  */
   error (_("Invalid baud rate %d.  Maximum value is %d."),
         rate, baudtab[i - 1].rate);
+#else
+  return -1;
+#endif
 }
 
+/* Set baud rate using B_code from termios.h.  */
+
 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");
+    perror_with_name (_("could not get tty state"));
 
   cfsetospeed (&state.termios, baud_code);
   cfsetispeed (&state.termios, baud_code);
 
   if (set_tty_state (scb, &state))
-    perror_with_name ("could not set tty state");
+    perror_with_name (_("could not set tty state"));
+}
+
+#if HAVE_CUSTOM_BAUDRATE_SUPPORT && defined(BOTHER)
+
+/* Set a custom baud rate using the termios BOTHER.  */
+
+static void
+set_custom_baudrate_linux (int fd, int rate)
+{
+#ifdef TCGETS2
+  struct termios2 tio;
+  const unsigned long req_get = TCGETS2;
+  const unsigned long req_set = TCSETS2;
+#else
+  struct termios tio;
+  const unsigned long req_get = TCGETS;
+  const unsigned long req_set = TCSETS;
+#endif
+
+  if (ioctl (fd, req_get, &tio) < 0)
+    perror_with_name (_("Can not get current baud rate"));
+
+  /* Clear the current output baud rate and fill a new value.  */
+  tio.c_cflag &= ~CBAUD;
+  tio.c_cflag |= BOTHER;
+  tio.c_ospeed = rate;
+
+  /* Clear the current input baud rate and fill a new value.  */
+  tio.c_cflag &= ~(CBAUD << IBSHIFT);
+  tio.c_cflag |= BOTHER << IBSHIFT;
+  tio.c_ispeed = rate;
+
+  if (ioctl (fd, req_set, &tio) < 0)
+    perror_with_name (_("Can not set custom baud rate"));
+}
+
+#elif HAVE_CUSTOM_BAUDRATE_SUPPORT && defined(IOSSIOSPEED)
+
+/* Set a custom baud rate using the IOSSIOSPEED ioctl call.  */
+
+static void
+set_custom_baudrate_darwin (int fd, int rate)
+{
+
+  if (ioctl (fd, IOSSIOSPEED, &rate) < 0)
+    perror_with_name (_("Can not set custom baud rate"));
+}
+
+#endif /* HAVE_CUSTOM_BAUDRATE_SUPPORT
+         && (defined(BOTHER) || defined(IOSSIOSPEED)) */
+
+#if HAVE_CUSTOM_BAUDRATE_SUPPORT
+
+/* Set a baud rate that differs from the OS B_codes.
+   This is possible if one of the following macros is available:
+   - BOTHER (Linux).
+   - IOSSIOSPEED (Darwin).  */
+
+static void
+set_custom_baudrate (int fd, int rate)
+{
+#if defined(BOTHER)
+  set_custom_baudrate_linux (fd, rate);
+#elif defined(IOSSIOSPEED)
+  set_custom_baudrate_darwin (fd, rate);
+#endif
+}
+
+#endif /* HAVE_CUSTOM_BAUDRATE_SUPPORT */
+
+/* Set the baud rate for the serial communication.  */
+
+static void
+hardwire_setbaudrate (struct serial *scb, int rate)
+{
+  int baud_code = rate_to_code (rate);
+
+  if (baud_code < 0)
+    {
+#if HAVE_CUSTOM_BAUDRATE_SUPPORT
+      set_custom_baudrate (scb->fd, rate);
+#else
+      /* An error should already have been thrown by rate_to_code().
+        Add an additional error in case execution somehow reaches this line.  */
+      gdb_assert_not_reached (_("Serial baud rate was not found in B_codes"));
+#endif
+    }
+  else
+    set_baudcode_baudrate (scb, baud_code);
 }
 
 static int