aboutsummaryrefslogtreecommitdiff
path: root/gdb/ser-unix.c
diff options
context:
space:
mode:
authorStu Grossman <grossman@cygnus>1993-04-06 05:50:54 +0000
committerStu Grossman <grossman@cygnus>1993-04-06 05:50:54 +0000
commit4e772f4426b2e004da8aaa4cccc7ea483eadf794 (patch)
tree52ef0674eefe2186020a8ccc68265c6cd2a0d9ab /gdb/ser-unix.c
parent9acdb2dc824dfdfbd94bbd4481473dc3b9c2c09b (diff)
downloadgdb-4e772f4426b2e004da8aaa4cccc7ea483eadf794.zip
gdb-4e772f4426b2e004da8aaa4cccc7ea483eadf794.tar.gz
gdb-4e772f4426b2e004da8aaa4cccc7ea483eadf794.tar.bz2
* Makefile.in (SFILES OBS): Add serial.[co] & ser-hardwire.[co].
These implement a new serial line interface for talking to remote targets. * configure.in: Link ser-hardwire.c to ser-unix.c for all hosts, EXCEPT go32, which gets ser-go32.c. * remote.c: Use new serial interface. More remote-xxx's to be converted later. * ser-bsd.c, ser-termios.c: Removed. * serial.c: New. Implements common operations for all serial types. * ser-unix.c: New. Unix specific serial operations for various flavors of Unix (Posix, SysV, BSD). * serial.h: Generic serial interface defs. * config/i386/go32.mh, config/i386/i386bsd.h, config/m68k/apollo68b.mh, config/sparc/sun4os4.mh: Remove ser-bsd.o from XDEPFILES. All the magic is now handled in configure.in.
Diffstat (limited to 'gdb/ser-unix.c')
-rw-r--r--gdb/ser-unix.c324
1 files changed, 324 insertions, 0 deletions
diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c
new file mode 100644
index 0000000..541e4c2
--- /dev/null
+++ b/gdb/ser-unix.c
@@ -0,0 +1,324 @@
+/* Serial interface for local (hardwired) serial ports on Un*x like systems
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+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. */
+
+#include "defs.h"
+#include "serial.h"
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY)
+#define HAVE_SGTTY
+#endif
+
+#ifdef HAVE_TERMIOS
+#include <termios.h>
+#include <unistd.h>
+#endif
+#ifdef HAVE_TERMIO
+#include <sys/termio.h>
+#endif
+#ifdef HAVE_SGTTY
+#include <sgtty.h>
+#endif
+
+/* Open up a real live device for serial I/O */
+
+static int
+hardwire_open(scb, name)
+ serial_t scb;
+ const char *name;
+{
+ scb->fd = open (name, O_RDWR);
+ if (scb->fd < 0)
+ return errno;
+
+ return 0;
+}
+
+static void
+hardwire_raw(scb)
+ serial_t scb;
+{
+#ifdef HAVE_TERMIOS
+ struct termios termios;
+
+ if (tcgetattr(scb->fd, &termios))
+ {
+ fprintf(stderr, "tcgetattr failed: %s\n", safe_strerror(errno));
+ }
+
+ termios.c_iflag = 0;
+ termios.c_oflag = 0;
+ termios.c_lflag = 0;
+ termios.c_cflag &= ~(CSIZE|PARENB);
+ termios.c_cflag |= CS8;
+ termios.c_cc[VMIN] = 0;
+ termios.c_cc[VTIME] = 0;
+
+ if (tcsetattr(scb->fd, TCSANOW, &termios))
+ {
+ fprintf(stderr, "tcsetattr failed: %s\n", safe_strerror(errno));
+ }
+#endif
+
+#ifdef HAVE_TERMIO
+ struct termio termio;
+
+ if (ioctl (scb->fd, TCGETA, &termio))
+ {
+ fprintf(stderr, "TCGETA failed: %s\n", safe_strerror(errno));
+ }
+
+ termio.c_iflag = 0;
+ termio.c_oflag = 0;
+ termio.c_lflag = 0;
+ termio.c_cflag &= ~(CSIZE|PARENB);
+ termio.c_cflag |= CS8;
+ termio.c_cc[VMIN] = 0;
+ termio.c_cc[VTIME] = 0;
+
+ if (ioctl (scb->fd, TCSETA, &termio))
+ {
+ fprintf(stderr, "TCSETA failed: %s\n", safe_strerror(errno));
+ }
+#endif
+
+#ifdef HAVE_SGTTY
+ struct sgttyb sgttyb;
+
+ if (ioctl (scb->fd, TIOCGETP, &sgttyb))
+ fprintf(stderr, "TIOCGETP failed: %s\n", safe_strerror(errno));
+
+ sgttyb.sg_flags |= RAW | ANYP;
+ sgttyb.sg_flags &= ~(CBREAK | ECHO);
+
+ if (ioctl (scb->fd, TIOCSETP, &sgttyb))
+ fprintf(stderr, "TIOCSETP failed: %s\n", safe_strerror(errno));
+#endif
+}
+
+/* Read a character with user-specified timeout. TIMEOUT is number of seconds
+ to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns
+ char if successful. Returns -2 if timeout expired, EOF if line dropped
+ dead, or -3 for any other error (see errno in that case). */
+
+static int
+hardwire_readchar(scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ int numfds;
+ struct timeval tv;
+ fd_set readfds;
+
+ if (scb->bufcnt-- > 0)
+ return *scb->bufp++;
+
+ FD_ZERO (&readfds);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ FD_SET(scb->fd, &readfds);
+
+ if (timeout >= 0)
+ numfds = select(scb->fd+1, &readfds, 0, 0, &tv);
+ else
+ numfds = select(scb->fd+1, &readfds, 0, 0, 0);
+
+ if (numfds <= 0)
+ if (numfds == 0)
+ return -2; /* Timeout */
+ else
+ return -3; /* Got an error from select */
+
+ scb->bufcnt = read(scb->fd, scb->buf, BUFSIZ);
+
+ if (scb->bufcnt <= 0)
+ if (scb->bufcnt == 0)
+ return EOF; /* 0 chars means end of file */
+ else
+ return -3; /* Got an error from read */
+
+ scb->bufcnt--;
+ scb->bufp = scb->buf;
+ return *scb->bufp++;
+}
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+/* Translate baud rates from integers to damn B_codes. Unix should
+ have outgrown this crap years ago, but even POSIX wouldn't buck it. */
+
+static struct
+{
+ int rate;
+ int code;
+}
+baudtab[] =
+{
+ {50, B50},
+ {75, B75},
+ {110, B110},
+ {134, B134},
+ {150, B150},
+ {200, B200},
+ {300, B300},
+ {600, B600},
+ {1200, B1200},
+ {1800, B1800},
+ {2400, B2400},
+ {4800, B4800},
+ {9600, B9600},
+ {19200, B19200},
+ {38400, B38400},
+ {-1, -1},
+};
+
+static int
+rate_to_code(rate)
+ int rate;
+{
+ int i;
+
+ for (i = 0; baudtab[i].rate != -1; i++)
+ if (rate == baudtab[i].rate)
+ return baudtab[i].code;
+
+ return -1;
+}
+
+static int
+hardwire_setbaudrate(scb, rate)
+ serial_t scb;
+ int rate;
+{
+#ifdef HAVE_TERMIOS
+ struct termios termios;
+
+ if (tcgetattr (scb->fd, &termios))
+ error("hardwire_setbaudrate: tcgetattr failed: %s\n", safe_strerror(errno));
+
+ cfsetospeed (&termios, rate_to_code (rate));
+ cfsetispeed (&termios, rate_to_code (rate));
+
+ if (tcsetattr (scb->fd, TCSANOW, &termios))
+ error ("hardwire_setbaudrate: tcsetattr failed: %s\n", safe_strerror(errno));
+
+ return 1;
+#endif
+
+#ifdef HAVE_TERMIO
+ struct termio termio;
+
+ if (ioctl (scb->fd, TCGETA, &termio))
+ {
+ fprintf(stderr, "TCGETA failed: %s\n", safe_strerror(errno));
+ }
+
+#ifndef CIBAUD
+#define CIBAUD CBAUD
+#endif
+
+ termio.c_cflag &= ~(CBAUD | CIBAUD);
+ termio.c_cflag |= rate_to_code (rate);
+
+ if (ioctl (scb->fd, TCSETA, &termio))
+ {
+ fprintf(stderr, "TCSETA failed: %s\n", safe_strerror(errno));
+ }
+#endif
+
+#ifdef HAVE_SGTTY
+ struct sgttyb sgttyb;
+
+ if (ioctl (scb->fd, TIOCGETP, &sgttyb))
+ fprintf (stderr, "TIOCGETP failed: %s\n", safe_strerror (errno));
+
+ sgttyb.sg_ispeed = rate_to_code (rate);
+ sgttyb.sg_ospeed = rate_to_code (rate);
+
+ if (ioctl (scb->fd, TIOCSETP, &sgttyb))
+ fprintf (stderr, "TIOCSETP failed: %s\n", safe_strerror (errno));
+#endif
+}
+
+static int
+hardwire_write(scb, str, len)
+ serial_t scb;
+ const char *str;
+ int len;
+{
+ int cc;
+
+ while (len > 0)
+ {
+ cc = write(scb->fd, str, len);
+
+ if (cc < 0)
+ return 1;
+ len -= cc;
+ str += cc;
+ }
+ return 0;
+}
+
+static void
+hardwire_restore(scb)
+ serial_t scb;
+{
+}
+
+static void
+hardwire_close(scb)
+ serial_t scb;
+{
+ if (scb->fd < 0)
+ return;
+
+ SERIAL_RESTORE(scb);
+
+ close(scb->fd);
+ scb->fd = -1;
+}
+
+static struct serial_ops hardwire_ops =
+{
+ "hardwire",
+ 0,
+ hardwire_open,
+ hardwire_close,
+ hardwire_readchar,
+ hardwire_write,
+ hardwire_raw,
+ hardwire_restore,
+ hardwire_setbaudrate
+};
+
+_initialize_ser_hardwire ()
+{
+ serial_add_interface (&hardwire_ops);
+}