/* Serial interface for local (hardwired) serial ports on Un*x like systems
- Copyright 1992, 1993, 1994 Free Software Foundation, Inc.
+ Copyright 1992, 1993, 1994, 1998 Free Software Foundation, Inc.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "serial.h"
#include <fcntl.h>
#include <sys/types.h>
-
-#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY)
-#define HAVE_SGTTY
+#include "terminal.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
#endif
#ifdef HAVE_TERMIOS
-#include <termios.h>
-#include <unistd.h>
struct hardwire_ttystate
{
#endif /* termios */
#ifdef HAVE_TERMIO
-#include <termio.h>
/* It is believed that all systems which have added job control to SVR3
(e.g. sco) have also added termios. Even if not, trying to figure out
too if it existed on all systems. */
#include <sys/time.h>
-#include <sgtty.h>
-
struct hardwire_ttystate
{
struct sgttyb sgttyb;
static int rate_to_code PARAMS ((int rate));
static int hardwire_setbaudrate PARAMS ((serial_t scb, int rate));
static int hardwire_write PARAMS ((serial_t scb, const char *str, int len));
-/* FIXME: static void hardwire_restore PARAMS ((serial_t scb)); */
static void hardwire_close PARAMS ((serial_t scb));
static int get_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
static int set_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
static serial_ttystate hardwire_get_tty_state PARAMS ((serial_t scb));
static int hardwire_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
+static int hardwire_noflush_set_tty_state PARAMS ((serial_t, serial_ttystate,
+ serial_ttystate));
+static void hardwire_print_tty_state PARAMS ((serial_t, serial_ttystate));
+static int hardwire_drain_output PARAMS ((serial_t));
+static int hardwire_flush_output PARAMS ((serial_t));
+static int hardwire_flush_input PARAMS ((serial_t));
+static int hardwire_send_break PARAMS ((serial_t));
+static int hardwire_setstopbits PARAMS ((serial_t, int));
+
+void _initialize_ser_hardwire PARAMS ((void));
+
+extern int (*ui_loop_hook) PARAMS ((int));
/* Open up a real live device for serial I/O */
}
static int
-get_tty_state(scb, state)
+get_tty_state (scb, state)
serial_t scb;
struct hardwire_ttystate *state;
{
#ifdef HAVE_TERMIOS
- extern int errno;
-
if (tcgetattr(scb->fd, &state->termios) < 0)
return -1;
serial_ttystate old_ttystate;
{
struct hardwire_ttystate new_state;
+#ifdef HAVE_SGTTY
struct hardwire_ttystate *state = (struct hardwire_ttystate *) old_ttystate;
+#endif
new_state = *(struct hardwire_ttystate *)new_ttystate;
#endif
}
+/* Wait for the output to drain away, as opposed to flushing (discarding) it */
+
+static int
+hardwire_drain_output (scb)
+ serial_t scb;
+{
+#ifdef HAVE_TERMIOS
+ return tcdrain (scb->fd);
+#endif
+
+#ifdef HAVE_TERMIO
+ return ioctl (scb->fd, TCSBRK, 1);
+#endif
+
+#ifdef HAVE_SGTTY
+ /* Get the current state and then restore it using TIOCSETP,
+ which should cause the output to drain and pending input
+ to be discarded. */
+ {
+ struct hardwire_ttystate state;
+ if (get_tty_state (scb, &state))
+ {
+ return (-1);
+ }
+ else
+ {
+ return (ioctl (scb->fd, TIOCSETP, &state.sgttyb));
+ }
+ }
+#endif
+}
+
static int
hardwire_flush_output (scb)
serial_t scb;
hardwire_flush_input (scb)
serial_t scb;
{
+ scb->bufcnt = 0;
+ scb->bufp = scb->buf;
+
#ifdef HAVE_TERMIOS
return tcflush (scb->fd, TCIFLUSH);
#endif
state.termios.c_oflag = 0;
state.termios.c_lflag = 0;
state.termios.c_cflag &= ~(CSIZE|PARENB);
- state.termios.c_cflag |= CS8;
+ state.termios.c_cflag |= CLOCAL | CS8;
state.termios.c_cc[VMIN] = 0;
state.termios.c_cc[VTIME] = 0;
#endif
state.termio.c_oflag = 0;
state.termio.c_lflag = 0;
state.termio.c_cflag &= ~(CSIZE|PARENB);
- state.termio.c_cflag |= CS8;
+ state.termio.c_cflag |= CLOCAL | CS8;
state.termio.c_cc[VMIN] = 0;
state.termio.c_cc[VTIME] = 0;
#endif
serial_t scb;
int timeout;
{
- scb->timeout_remaining = 0;
-
#ifdef HAVE_SGTTY
{
struct timeval tv;
to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns
char if successful. Returns SERIAL_TIMEOUT if timeout expired, EOF if line
dropped dead, or SERIAL_ERROR for any other error (see errno in that case). */
-
static int
-hardwire_readchar(scb, timeout)
+hardwire_readchar (scb, timeout)
serial_t scb;
int timeout;
{
- int status;
+ int status, delta;
+ int detach = 0;
if (scb->bufcnt-- > 0)
return *scb->bufp++;
+ if (timeout > 0)
+ timeout++;
+
+ /* We have to be able to keep the GUI alive here, so we break the original
+ timeout into steps of 1 second, running the "keep the GUI alive" hook
+ each time through the loop.
+ Also, timeout = 0 means to poll, so we just set the delta to 0, so we
+ will only go through the loop once. */
+
+ delta = (timeout == 0 ? 0 : 1);
while (1)
{
- status = wait_for (scb, timeout);
+
+ /* N.B. The UI may destroy our world (for instance by calling
+ remote_stop,) in which case we want to get out of here as
+ quickly as possible. It is not safe to touch scb, since
+ someone else might have freed it. The ui_loop_hook signals that
+ we should exit by returning 1. */
+
+ if (ui_loop_hook)
+ detach = ui_loop_hook (0);
+
+ if (detach)
+ return SERIAL_TIMEOUT;
+
+ scb->timeout_remaining = (timeout < 0 ? timeout : timeout - delta);
+ status = wait_for (scb, delta);
if (status < 0)
return status;
timeout = scb->timeout_remaining;
continue;
}
+ else if (scb->timeout_remaining < 0)
+ continue;
else
return SERIAL_TIMEOUT;
}
+ else if (errno == EINTR)
+ continue;
else
return SERIAL_ERROR; /* Got an error from read */
}
{9600, B9600},
{19200, B19200},
{38400, B38400},
+#ifdef B57600
+ {57600, B57600},
+#endif
+#ifdef B115200
+ {115200, B115200},
+#endif
+#ifdef B230400
+ {230400, B230400},
+#endif
+#ifdef B460800
+ {460800, B460800},
+#endif
{-1, -1},
};
return set_tty_state (scb, &state);
}
+static int
+hardwire_setstopbits(scb, num)
+ serial_t scb;
+ int num;
+{
+ struct hardwire_ttystate state;
+ int newbit;
+
+ if (get_tty_state(scb, &state))
+ return -1;
+
+ switch (num)
+ {
+ case SERIAL_1_STOPBITS:
+ newbit = 0;
+ break;
+ case SERIAL_1_AND_A_HALF_STOPBITS:
+ case SERIAL_2_STOPBITS:
+ newbit = 1;
+ break;
+ default:
+ return 1;
+ }
+
+#ifdef HAVE_TERMIOS
+ if (!newbit)
+ state.termios.c_cflag &= ~CSTOPB;
+ else
+ state.termios.c_cflag |= CSTOPB; /* two bits */
+#endif
+
+#ifdef HAVE_TERMIO
+ if (!newbit)
+ state.termio.c_cflag &= ~CSTOPB;
+ else
+ state.termio.c_cflag |= CSTOPB; /* two bits */
+#endif
+
+#ifdef HAVE_SGTTY
+ return 0; /* sgtty doesn't support this */
+#endif
+
+ return set_tty_state (scb, &state);
+}
+
static int
hardwire_write(scb, str, len)
serial_t scb;
hardwire_print_tty_state,
hardwire_noflush_set_tty_state,
hardwire_setbaudrate,
+ hardwire_setstopbits,
+ hardwire_drain_output, /* wait for output to drain */
};
void