X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fser-unix.c;h=356e5e7d1a29ec8c09e799eb61f538f0bad89762;hb=dac804dfa6389b71f50b5e169ffa4e239958e774;hp=0a1c53e872fa771b78a288f45cda74cdae3a422a;hpb=a9762ec78a53fbe9209fe1654db42df0cd328d50;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c index 0a1c53e872..356e5e7d1a 100644 --- a/gdb/ser-unix.c +++ b/gdb/ser-unix.c @@ -1,7 +1,6 @@ /* Serial interface for local (hardwired) serial ports on Un*x like systems - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2003, - 2004, 2005, 2007 Free Software Foundation, Inc. + Copyright (C) 1992-2015 Free Software Foundation, Inc. This file is part of GDB. @@ -30,8 +29,8 @@ #include #include "gdb_select.h" -#include "gdb_string.h" #include "gdbcmd.h" +#include "filestuff.h" #ifdef HAVE_TERMIOS @@ -84,6 +83,7 @@ static int hardwire_readchar (struct serial *scb, int timeout); static int do_hardwire_readchar (struct serial *scb, int timeout); static int rate_to_code (int rate); static int hardwire_setbaudrate (struct serial *scb, int rate); +static int hardwire_setparity (struct serial *scb, int parity); static void hardwire_close (struct serial *scb); static int get_tty_state (struct serial *scb, struct hardwire_ttystate * state); @@ -103,12 +103,12 @@ static int hardwire_setstopbits (struct serial *, int); void _initialize_ser_hardwire (void); -/* Open up a real live device for serial I/O */ +/* Open up a real live device for serial I/O. */ static int hardwire_open (struct serial *scb, const char *name) { - scb->fd = open (name, O_RDWR); + scb->fd = gdb_open_cloexec (name, O_RDWR, 0); if (scb->fd < 0) return -1; @@ -183,7 +183,21 @@ hardwire_get_tty_state (struct serial *scb) state = (struct hardwire_ttystate *) xmalloc (sizeof *state); if (get_tty_state (scb, state)) - return NULL; + { + xfree (state); + return NULL; + } + + return (serial_ttystate) state; +} + +static serial_ttystate +hardwire_copy_tty_state (struct serial *scb, serial_ttystate ttystate) +{ + struct hardwire_ttystate *state; + + state = (struct hardwire_ttystate *) xmalloc (sizeof *state); + *state = *(struct hardwire_ttystate *) ttystate; return (serial_ttystate) state; } @@ -287,7 +301,8 @@ hardwire_print_tty_state (struct serial *scb, #endif } -/* Wait for the output to drain away, as opposed to flushing (discarding) it */ +/* Wait for the output to drain away, as opposed to flushing + (discarding) it. */ static int hardwire_drain_output (struct serial *scb) @@ -303,9 +318,10 @@ hardwire_drain_output (struct serial *scb) #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. */ + to be discarded. */ { struct hardwire_ttystate state; + if (get_tty_state (scb, &state)) { return (-1); @@ -368,16 +384,13 @@ hardwire_send_break (struct serial *scb) #ifdef HAVE_SGTTY { int status; - struct timeval timeout; status = ioctl (scb->fd, TIOCSBRK, 0); /* Can't use usleep; it doesn't exist in BSD 4.2. */ - /* Note that if this select() is interrupted by a signal it will not wait - the full length of time. I think that is OK. */ - timeout.tv_sec = 0; - timeout.tv_usec = 250000; - gdb_select (0, 0, 0, 0, &timeout); + /* Note that if this gdb_select() is interrupted by a signal it will not + wait the full length of time. I think that is OK. */ + gdb_usleep (250000); status = ioctl (scb->fd, TIOCCBRK, 0); return status; } @@ -390,13 +403,14 @@ hardwire_raw (struct serial *scb) struct hardwire_ttystate state; if (get_tty_state (scb, &state)) - fprintf_unfiltered (gdb_stderr, "get_tty_state failed: %s\n", safe_strerror (errno)); + fprintf_unfiltered (gdb_stderr, "get_tty_state failed: %s\n", + safe_strerror (errno)); #ifdef HAVE_TERMIOS state.termios.c_iflag = 0; state.termios.c_oflag = 0; state.termios.c_lflag = 0; - state.termios.c_cflag &= ~(CSIZE | PARENB); + state.termios.c_cflag &= ~CSIZE; state.termios.c_cflag |= CLOCAL | CS8; #ifdef CRTSCTS /* h/w flow control. */ @@ -419,7 +433,7 @@ hardwire_raw (struct serial *scb) state.termio.c_iflag = 0; state.termio.c_oflag = 0; state.termio.c_lflag = 0; - state.termio.c_cflag &= ~(CSIZE | PARENB); + state.termio.c_cflag &= ~CSIZE; state.termio.c_cflag |= CLOCAL | CS8; state.termio.c_cc[VMIN] = 0; state.termio.c_cc[VTIME] = 0; @@ -433,24 +447,24 @@ hardwire_raw (struct serial *scb) scb->current_timeout = 0; if (set_tty_state (scb, &state)) - fprintf_unfiltered (gdb_stderr, "set_tty_state failed: %s\n", safe_strerror (errno)); + fprintf_unfiltered (gdb_stderr, "set_tty_state failed: %s\n", + safe_strerror (errno)); } /* Wait for input on scb, with timeout seconds. Returns 0 on success, otherwise SERIAL_TIMEOUT or SERIAL_ERROR. For termio{s}, we actually just setup VTIME if necessary, and let the - timeout occur in the read() in hardwire_read(). - */ + timeout occur in the read() in hardwire_read(). */ /* FIXME: cagney/1999-09-16: Don't replace this with the equivalent ser_base*() until the old TERMIOS/SGTTY/... timer code has been - flushed. . */ + flushed. . */ /* NOTE: cagney/1999-09-30: Much of the code below is dead. The only possible values of the TIMEOUT parameter are ONE and ZERO. Consequently all the code that tries to handle the possability of - an overflowed timer is unnecessary. */ + an overflowed timer is unnecessary. */ static int wait_for (struct serial *scb, int timeout) @@ -464,7 +478,7 @@ wait_for (struct serial *scb, int timeout) /* 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. */ + arguments before each call. */ tv.tv_sec = timeout; tv.tv_usec = 0; @@ -483,7 +497,7 @@ wait_for (struct serial *scb, int timeout) else if (errno == EINTR) continue; else - return SERIAL_ERROR; /* Got an error from select or poll */ + return SERIAL_ERROR; /* Got an error from select or poll. */ return 0; } @@ -499,7 +513,8 @@ wait_for (struct serial *scb, int timeout) struct hardwire_ttystate state; if (get_tty_state (scb, &state)) - fprintf_unfiltered (gdb_stderr, "get_tty_state failed: %s\n", safe_strerror (errno)); + fprintf_unfiltered (gdb_stderr, "get_tty_state failed: %s\n", + safe_strerror (errno)); #ifdef HAVE_TERMIOS if (timeout < 0) @@ -551,27 +566,29 @@ wait_for (struct serial *scb, int timeout) #endif if (set_tty_state (scb, &state)) - fprintf_unfiltered (gdb_stderr, "set_tty_state failed: %s\n", safe_strerror (errno)); + fprintf_unfiltered (gdb_stderr, "set_tty_state failed: %s\n", + safe_strerror (errno)); return 0; } #endif /* HAVE_TERMIO || HAVE_TERMIOS */ } -/* 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 SERIAL_TIMEOUT if timeout expired, EOF if line - dropped dead, or SERIAL_ERROR for any other error (see errno in that case). */ +/* 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 SERIAL_TIMEOUT if + timeout expired, EOF if line dropped dead, or SERIAL_ERROR for any + other error (see errno in that case). */ /* FIXME: cagney/1999-09-16: Don't replace this with the equivalent ser_base*() until the old TERMIOS/SGTTY/... timer code has been - flushed. */ + flushed. */ /* NOTE: cagney/1999-09-16: This function is not identical to ser_base_readchar() as part of replacing it with ser_base*() merging will be required - this code handles the case where read() times out due to no data while ser_base_readchar() doesn't expect - that. */ + that. */ static int do_hardwire_readchar (struct serial *scb, int timeout) @@ -633,7 +650,7 @@ do_hardwire_readchar (struct serial *scb, int timeout) else if (errno == EINTR) continue; else - return SERIAL_ERROR; /* Got an error from read */ + return SERIAL_ERROR; /* Got an error from read. */ } scb->bufcnt = status; @@ -765,30 +782,31 @@ rate_to_code (int rate) for (i = 0; baudtab[i].rate != -1; i++) { - /* test for perfect macth. */ + /* test for perfect macth. */ if (rate == baudtab[i].rate) return baudtab[i].code; else { - /* check if it is in between valid values. */ + /* 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); + 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); + rate, baudtab[0].rate); } return -1; } } } - /* The requested speed was too large. */ + /* The requested speed was too large. */ warning (_("Invalid baud rate %d. Maximum value is %d."), rate, baudtab[i - 1].rate); return -1; @@ -803,7 +821,7 @@ hardwire_setbaudrate (struct serial *scb, int rate) if (baud_code < 0) { /* The baud rate was not valid. - A warning has already been issued. */ + A warning has already been issued. */ errno = EINVAL; return -1; } @@ -876,6 +894,51 @@ hardwire_setstopbits (struct serial *scb, int num) return set_tty_state (scb, &state); } +/* Implement the "setparity" serial_ops callback. */ + +static int +hardwire_setparity (struct serial *scb, int parity) +{ + struct hardwire_ttystate state; + int newparity = 0; + + if (get_tty_state (scb, &state)) + return -1; + + switch (parity) + { + case GDBPARITY_NONE: + newparity = 0; + break; + case GDBPARITY_ODD: + newparity = PARENB | PARODD; + break; + case GDBPARITY_EVEN: + newparity = PARENB; + break; + default: + internal_warning (__FILE__, __LINE__, + "Incorrect parity value: %d", parity); + return -1; + } + +#ifdef HAVE_TERMIOS + state.termios.c_cflag &= ~(PARENB | PARODD); + state.termios.c_cflag |= newparity; +#endif + +#ifdef HAVE_TERMIO + state.termio.c_cflag &= ~(PARENB | PARODD); + state.termio.c_cflag |= newparity; +#endif + +#ifdef HAVE_SGTTY + return 0; /* sgtty doesn't support this */ +#endif + return set_tty_state (scb, &state); +} + + static void hardwire_close (struct serial *scb) { @@ -887,35 +950,42 @@ hardwire_close (struct serial *scb) } + +/* The hardwire ops. */ + +static const struct serial_ops hardwire_ops = +{ + "hardwire", + hardwire_open, + hardwire_close, + NULL, + /* FIXME: Don't replace this with the equivalent ser_base*() until + the old TERMIOS/SGTTY/... timer code has been flushed. cagney + 1999-09-16. */ + hardwire_readchar, + ser_base_write, + hardwire_flush_output, + hardwire_flush_input, + hardwire_send_break, + hardwire_raw, + hardwire_get_tty_state, + hardwire_copy_tty_state, + hardwire_set_tty_state, + hardwire_print_tty_state, + hardwire_noflush_set_tty_state, + hardwire_setbaudrate, + hardwire_setstopbits, + hardwire_setparity, + hardwire_drain_output, + ser_base_async, + ser_unix_read_prim, + ser_unix_write_prim +}; + void _initialize_ser_hardwire (void) { - struct serial_ops *ops = XMALLOC (struct serial_ops); - memset (ops, 0, sizeof (struct serial_ops)); - ops->name = "hardwire"; - ops->next = 0; - ops->open = hardwire_open; - ops->close = hardwire_close; - /* FIXME: Don't replace this with the equivalent ser_base*() until - the old TERMIOS/SGTTY/... timer code has been flushed. cagney - 1999-09-16. */ - ops->readchar = hardwire_readchar; - ops->write = ser_base_write; - ops->flush_output = hardwire_flush_output; - ops->flush_input = hardwire_flush_input; - ops->send_break = hardwire_send_break; - ops->go_raw = hardwire_raw; - ops->get_tty_state = hardwire_get_tty_state; - ops->set_tty_state = hardwire_set_tty_state; - ops->print_tty_state = hardwire_print_tty_state; - ops->noflush_set_tty_state = hardwire_noflush_set_tty_state; - ops->setbaudrate = hardwire_setbaudrate; - ops->setstopbits = hardwire_setstopbits; - ops->drain_output = hardwire_drain_output; - ops->async = ser_base_async; - ops->read_prim = ser_unix_read_prim; - ops->write_prim = ser_unix_write_prim; - serial_add_interface (ops); + serial_add_interface (&hardwire_ops); #ifdef HAVE_TERMIOS #ifdef CRTSCTS