2001-07-07 Ben Elliston <bje@redhat.com>
[deliverable/binutils-gdb.git] / gdb / ser-unix.c
index 5a1ec1dc14f0d02f95fee8648d60c70dbfc9e67a..ee17c122c78526259734a9503e1bf5ca321ab6ba 100644 (file)
@@ -1,5 +1,6 @@
 /* Serial interface for local (hardwired) serial ports on Un*x like systems
-   Copyright 1992-1994, 1998-2000 Free Software Foundation, Inc.
+   Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -25,7 +26,6 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include "terminal.h"
-#include "gdb_wait.h"
 #include <sys/socket.h>
 #include <sys/time.h>
 
@@ -268,7 +268,7 @@ hardwire_print_tty_state (serial_t scb,
   fprintf_filtered (stream, "tchars: ");
   for (i = 0; i < (int) sizeof (struct tchars); i++)
     fprintf_filtered (stream, "0x%x ", ((unsigned char *) &state->tc)[i]);
-  fprintf_filtered ("\n");
+  fprintf_filtered (stream, "\n");
 
   fprintf_filtered (stream, "ltchars: ");
   for (i = 0; i < (int) sizeof (struct ltchars); i++)
@@ -435,37 +435,37 @@ static int
 wait_for (serial_t scb, int timeout)
 {
 #ifdef HAVE_SGTTY
-  {
-    struct timeval tv;
-    fd_set readfds;
+  while (1)
+    {
+      struct timeval tv;
+      fd_set readfds;
+      int numfds;
 
-    FD_ZERO (&readfds);
+      /* NOTE: Some OS's can scramble the READFDS when the select()
+         call fails (ex the kernel with Red Hat 5.2).  Initialize all
+         arguments before each call. */
 
-    tv.tv_sec = timeout;
-    tv.tv_usec = 0;
+      tv.tv_sec = timeout;
+      tv.tv_usec = 0;
 
-    FD_SET (scb->fd, &readfds);
+      FD_ZERO (&readfds);
+      FD_SET (scb->fd, &readfds);
 
-    while (1)
-      {
-       int numfds;
+      if (timeout >= 0)
+       numfds = select (scb->fd + 1, &readfds, 0, 0, &tv);
+      else
+       numfds = select (scb->fd + 1, &readfds, 0, 0, 0);
 
-       if (timeout >= 0)
-         numfds = select (scb->fd + 1, &readfds, 0, 0, &tv);
+      if (numfds <= 0)
+       if (numfds == 0)
+         return SERIAL_TIMEOUT;
+       else if (errno == EINTR)
+         continue;
        else
-         numfds = select (scb->fd + 1, &readfds, 0, 0, 0);
+         return SERIAL_ERROR;  /* Got an error from select or poll */
 
-       if (numfds <= 0)
-         if (numfds == 0)
-           return SERIAL_TIMEOUT;
-         else if (errno == EINTR)
-           continue;
-         else
-           return SERIAL_ERROR;        /* Got an error from select or poll */
-
-       return 0;
-      }
-  }
+      return 0;
+    }
 #endif /* HAVE_SGTTY */
 
 #if defined HAVE_TERMIO || defined HAVE_TERMIOS
@@ -741,9 +741,33 @@ rate_to_code (int rate)
   int i;
 
   for (i = 0; baudtab[i].rate != -1; i++)
-    if (rate == baudtab[i].rate)
-      return baudtab[i].code;
-
+    {
+      /* test for perfect macth. */
+      if (rate == baudtab[i].rate)
+        return baudtab[i].code;
+      else
+        {
+         /* check if it is in between valid values. */
+          if (rate < baudtab[i].rate)
+           {
+             if (i)
+               {
+                 warning ("Invalid baud rate %d.  Closest values are %d and %d.",
+                           rate, baudtab[i - 1].rate, baudtab[i].rate);
+               }
+             else
+               {
+                 warning ("Invalid baud rate %d.  Minimum value is %d.",
+                           rate, baudtab[0].rate);
+               }
+             return -1;
+           }
+        }
+    }
+  /* The requested speed was too large. */
+  warning ("Invalid baud rate %d.  Maximum value is %d.",
+            rate, baudtab[i - 1].rate);
   return -1;
 }
 
@@ -751,13 +775,22 @@ static int
 hardwire_setbaudrate (serial_t scb, int rate)
 {
   struct hardwire_ttystate state;
+  int baud_code = rate_to_code (rate);
+  
+  if (baud_code < 0)
+    {
+      /* The baud rate was not valid.
+         A warning has already been issued. */
+      errno = EINVAL;
+      return -1;
+    }
 
   if (get_tty_state (scb, &state))
     return -1;
 
 #ifdef HAVE_TERMIOS
-  cfsetospeed (&state.termios, rate_to_code (rate));
-  cfsetispeed (&state.termios, rate_to_code (rate));
+  cfsetospeed (&state.termios, baud_code);
+  cfsetispeed (&state.termios, baud_code);
 #endif
 
 #ifdef HAVE_TERMIO
@@ -766,12 +799,12 @@ hardwire_setbaudrate (serial_t scb, int rate)
 #endif
 
   state.termio.c_cflag &= ~(CBAUD | CIBAUD);
-  state.termio.c_cflag |= rate_to_code (rate);
+  state.termio.c_cflag |= baud_code;
 #endif
 
 #ifdef HAVE_SGTTY
-  state.sgttyb.sg_ispeed = rate_to_code (rate);
-  state.sgttyb.sg_ospeed = rate_to_code (rate);
+  state.sgttyb.sg_ispeed = baud_code;
+  state.sgttyb.sg_ospeed = baud_code;
 #endif
 
   return set_tty_state (scb, &state);
@@ -858,21 +891,24 @@ ser_unix_nop_raw (serial_t scb)
 int
 ser_unix_wait_for (serial_t scb, int timeout)
 {
-  int numfds;
-  struct timeval tv;
-  fd_set readfds, exceptfds;
+  while (1)
+    {
+      int numfds;
+      struct timeval tv;
+      fd_set readfds, exceptfds;
 
-  FD_ZERO (&readfds);
-  FD_ZERO (&exceptfds);
+      /* NOTE: Some OS's can scramble the READFDS when the select()
+         call fails (ex the kernel with Red Hat 5.2).  Initialize all
+         arguments before each call. */
 
-  tv.tv_sec = timeout;
-  tv.tv_usec = 0;
+      tv.tv_sec = timeout;
+      tv.tv_usec = 0;
 
-  FD_SET (scb->fd, &readfds);
-  FD_SET (scb->fd, &exceptfds);
+      FD_ZERO (&readfds);
+      FD_ZERO (&exceptfds);
+      FD_SET (scb->fd, &readfds);
+      FD_SET (scb->fd, &exceptfds);
 
-  while (1)
-    {
       if (timeout >= 0)
        numfds = select (scb->fd + 1, &readfds, 0, &exceptfds, &tv);
       else
@@ -927,7 +963,8 @@ do_unix_readchar (serial_t scb, int timeout)
        }
 
       status = ser_unix_wait_for (scb, delta);
-      timeout -= delta;
+      if (timeout > 0)
+        timeout -= delta;
 
       /* If we got a character or an error back from wait_for, then we can 
          break from the loop before the timeout is completed. */
@@ -1276,7 +1313,7 @@ ser_unix_async (serial_t scb,
       if (SERIAL_DEBUG_P (scb))
        fprintf_unfiltered (gdb_stdlog, "[fd%d->synchronous]\n",
                            scb->fd);
-      /* De-schedule what ever tasks are currently scheduled. */
+      /* De-schedule whatever tasks are currently scheduled. */
       switch (scb->async_state)
        {
        case FD_SCHEDULED:
This page took 0.026675 seconds and 4 git commands to generate.