X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fser-unix.c;h=2e7b1b45e3ec4728d9d185c6eab3eac8a2c5fa50;hb=b8162e5ac9e052b2a88912b729081600972e854c;hp=c92567bd0338786fe1db812ef4af44e29100b4a9;hpb=c5aa993b1f4add48fbdc6cc3117059f616e49875;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c index c92567bd03..2e7b1b45e3 100644 --- a/gdb/ser-unix.c +++ b/gdb/ser-unix.c @@ -1,11 +1,12 @@ /* Serial interface for local (hardwired) serial ports on Un*x like systems - Copyright 1992, 1993, 1994, 1998 Free Software Foundation, Inc. + + Copyright (C) 1992-2016 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,18 +15,22 @@ 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., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "serial.h" +#include "ser-base.h" +#include "ser-unix.h" + #include #include #include "terminal.h" -#ifdef HAVE_UNISTD_H -#include -#endif +#include +#include "gdb_sys_time.h" + +#include "gdb_select.h" +#include "gdbcmd.h" +#include "filestuff.h" #ifdef HAVE_TERMIOS @@ -33,6 +38,18 @@ struct hardwire_ttystate { struct termios termios; }; + +#ifdef CRTSCTS +/* Boolean to explicitly enable or disable h/w flow control. */ +static int serial_hwflow; +static void +show_serial_hwflow (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Hardware flow control is %s.\n"), value); +} +#endif + #endif /* termios */ #ifdef HAVE_TERMIO @@ -49,10 +66,6 @@ struct hardwire_ttystate #endif /* termio */ #ifdef HAVE_SGTTY -/* Needed for the code which uses select(). We would include - too if it existed on all systems. */ -#include - struct hardwire_ttystate { struct sgttyb sgttyb; @@ -63,39 +76,39 @@ struct hardwire_ttystate }; #endif /* sgtty */ -static int hardwire_open PARAMS ((serial_t scb, const char *name)); -static void hardwire_raw PARAMS ((serial_t scb)); -static int wait_for PARAMS ((serial_t scb, int timeout)); -static int hardwire_readchar PARAMS ((serial_t scb, int timeout)); -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)); -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 hardwire_open (struct serial *scb, const char *name); +static void hardwire_raw (struct serial *scb); +static int wait_for (struct serial *scb, int timeout); +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); +static int set_tty_state (struct serial *scb, + struct hardwire_ttystate * state); +static serial_ttystate hardwire_get_tty_state (struct serial *scb); +static int hardwire_set_tty_state (struct serial *scb, serial_ttystate state); +static int hardwire_noflush_set_tty_state (struct serial *, serial_ttystate, + serial_ttystate); +static void hardwire_print_tty_state (struct serial *, serial_ttystate, + struct ui_file *); +static int hardwire_drain_output (struct serial *); +static int hardwire_flush_output (struct serial *); +static int hardwire_flush_input (struct serial *); +static int hardwire_send_break (struct serial *); +static int hardwire_setstopbits (struct serial *, int); + +void _initialize_ser_hardwire (void); + +/* Open up a real live device for serial I/O. */ static int -hardwire_open (scb, name) - serial_t scb; - const char *name; +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; @@ -103,9 +116,7 @@ hardwire_open (scb, name) } static int -get_tty_state (scb, state) - serial_t scb; - struct hardwire_ttystate *state; +get_tty_state (struct serial *scb, struct hardwire_ttystate *state) { #ifdef HAVE_TERMIOS if (tcgetattr (scb->fd, &state->termios) < 0) @@ -135,9 +146,7 @@ get_tty_state (scb, state) } static int -set_tty_state (scb, state) - serial_t scb; - struct hardwire_ttystate *state; +set_tty_state (struct serial *scb, struct hardwire_ttystate *state) { #ifdef HAVE_TERMIOS if (tcsetattr (scb->fd, TCSANOW, &state->termios) < 0) @@ -167,23 +176,31 @@ set_tty_state (scb, state) } static serial_ttystate -hardwire_get_tty_state (scb) - serial_t scb; +hardwire_get_tty_state (struct serial *scb) { - struct hardwire_ttystate *state; - - state = (struct hardwire_ttystate *) xmalloc (sizeof *state); + struct hardwire_ttystate *state = XNEW (struct hardwire_ttystate); 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 = XNEW (struct hardwire_ttystate); + + *state = *(struct hardwire_ttystate *) ttystate; return (serial_ttystate) state; } static int -hardwire_set_tty_state (scb, ttystate) - serial_t scb; - serial_ttystate ttystate; +hardwire_set_tty_state (struct serial *scb, serial_ttystate ttystate) { struct hardwire_ttystate *state; @@ -193,10 +210,9 @@ hardwire_set_tty_state (scb, ttystate) } static int -hardwire_noflush_set_tty_state (scb, new_ttystate, old_ttystate) - serial_t scb; - serial_ttystate new_ttystate; - serial_ttystate old_ttystate; +hardwire_noflush_set_tty_state (struct serial *scb, + serial_ttystate new_ttystate, + serial_ttystate old_ttystate) { struct hardwire_ttystate new_state; #ifdef HAVE_SGTTY @@ -227,63 +243,66 @@ hardwire_noflush_set_tty_state (scb, new_ttystate, old_ttystate) } static void -hardwire_print_tty_state (scb, ttystate) - serial_t scb; - serial_ttystate ttystate; +hardwire_print_tty_state (struct serial *scb, + serial_ttystate ttystate, + struct ui_file *stream) { struct hardwire_ttystate *state = (struct hardwire_ttystate *) ttystate; int i; #ifdef HAVE_TERMIOS - printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n", - state->termios.c_iflag, state->termios.c_oflag); - printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x\n", - state->termios.c_cflag, state->termios.c_lflag); + fprintf_filtered (stream, "c_iflag = 0x%x, c_oflag = 0x%x,\n", + (int) state->termios.c_iflag, + (int) state->termios.c_oflag); + fprintf_filtered (stream, "c_cflag = 0x%x, c_lflag = 0x%x\n", + (int) state->termios.c_cflag, + (int) state->termios.c_lflag); #if 0 /* This not in POSIX, and is not really documented by those systems which have it (at least not Sun). */ - printf_filtered ("c_line = 0x%x.\n", state->termios.c_line); + fprintf_filtered (stream, "c_line = 0x%x.\n", state->termios.c_line); #endif - printf_filtered ("c_cc: "); + fprintf_filtered (stream, "c_cc: "); for (i = 0; i < NCCS; i += 1) - printf_filtered ("0x%x ", state->termios.c_cc[i]); - printf_filtered ("\n"); + fprintf_filtered (stream, "0x%x ", state->termios.c_cc[i]); + fprintf_filtered (stream, "\n"); #endif #ifdef HAVE_TERMIO - printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n", - state->termio.c_iflag, state->termio.c_oflag); - printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n", - state->termio.c_cflag, state->termio.c_lflag, - state->termio.c_line); - printf_filtered ("c_cc: "); + fprintf_filtered (stream, "c_iflag = 0x%x, c_oflag = 0x%x,\n", + state->termio.c_iflag, state->termio.c_oflag); + fprintf_filtered (stream, "c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n", + state->termio.c_cflag, state->termio.c_lflag, + state->termio.c_line); + fprintf_filtered (stream, "c_cc: "); for (i = 0; i < NCC; i += 1) - printf_filtered ("0x%x ", state->termio.c_cc[i]); - printf_filtered ("\n"); + fprintf_filtered (stream, "0x%x ", state->termio.c_cc[i]); + fprintf_filtered (stream, "\n"); #endif #ifdef HAVE_SGTTY - printf_filtered ("sgttyb.sg_flags = 0x%x.\n", state->sgttyb.sg_flags); + fprintf_filtered (stream, "sgttyb.sg_flags = 0x%x.\n", + state->sgttyb.sg_flags); - printf_filtered ("tchars: "); + fprintf_filtered (stream, "tchars: "); for (i = 0; i < (int) sizeof (struct tchars); i++) - printf_filtered ("0x%x ", ((unsigned char *) &state->tc)[i]); - printf_filtered ("\n"); + fprintf_filtered (stream, "0x%x ", ((unsigned char *) &state->tc)[i]); + fprintf_filtered (stream, "\n"); - printf_filtered ("ltchars: "); + fprintf_filtered (stream, "ltchars: "); for (i = 0; i < (int) sizeof (struct ltchars); i++) - printf_filtered ("0x%x ", ((unsigned char *) &state->ltc)[i]); - printf_filtered ("\n"); + fprintf_filtered (stream, "0x%x ", ((unsigned char *) &state->ltc)[i]); + fprintf_filtered (stream, "\n"); - printf_filtered ("lmode: 0x%x\n", state->lmode); + fprintf_filtered (stream, "lmode: 0x%x\n", state->lmode); #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 (scb) - serial_t scb; +hardwire_drain_output (struct serial *scb) { #ifdef HAVE_TERMIOS return tcdrain (scb->fd); @@ -296,9 +315,10 @@ hardwire_drain_output (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); @@ -312,8 +332,7 @@ hardwire_drain_output (scb) } static int -hardwire_flush_output (scb) - serial_t scb; +hardwire_flush_output (struct serial *scb) { #ifdef HAVE_TERMIOS return tcflush (scb->fd, TCOFLUSH); @@ -330,11 +349,9 @@ hardwire_flush_output (scb) } static int -hardwire_flush_input (scb) - serial_t scb; +hardwire_flush_input (struct serial *scb) { - scb->bufcnt = 0; - scb->bufp = scb->buf; + ser_base_flush_input (scb); #ifdef HAVE_TERMIOS return tcflush (scb->fd, TCIFLUSH); @@ -351,8 +368,7 @@ hardwire_flush_input (scb) } static int -hardwire_send_break (scb) - serial_t scb; +hardwire_send_break (struct serial *scb) { #ifdef HAVE_TERMIOS return tcsendbreak (scb->fd, 0); @@ -365,16 +381,13 @@ hardwire_send_break (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; - 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; } @@ -382,20 +395,33 @@ hardwire_send_break (scb) } static void -hardwire_raw (scb) - serial_t scb; +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. */ + if (serial_hwflow) + state.termios.c_cflag |= CRTSCTS; + else + state.termios.c_cflag &= ~CRTSCTS; +#ifdef CRTS_IFLOW + if (serial_hwflow) + state.termios.c_cflag |= CRTS_IFLOW; + else + state.termios.c_cflag &= ~CRTS_IFLOW; +#endif +#endif state.termios.c_cc[VMIN] = 0; state.termios.c_cc[VTIME] = 0; #endif @@ -404,7 +430,7 @@ hardwire_raw (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; @@ -418,147 +444,90 @@ hardwire_raw (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. + otherwise SERIAL_TIMEOUT or SERIAL_ERROR. */ + +/* FIXME: cagney/1999-09-16: Don't replace this with the equivalent + ser_base*() until the old TERMIOS/SGTTY/... timer code has been + flushed. . */ - For termio{s}, we actually just setup VTIME if necessary, and let the - timeout occur in the read() in hardwire_read(). - */ +/* 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. */ static int -wait_for (scb, timeout) - serial_t scb; - int timeout; +wait_for (struct serial *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; + QUIT; - 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 = interruptible_select (scb->fd + 1, &readfds, 0, 0, &tv); + else + numfds = interruptible_select (scb->fd + 1, &readfds, 0, 0, 0); - 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 */ + if (numfds == -1 && errno == EINTR) + continue; + else if (numfds == -1) + return SERIAL_ERROR; + else if (numfds == 0) + return SERIAL_TIMEOUT; - return 0; - } - } -#endif /* HAVE_SGTTY */ + return 0; + } +} -#if defined HAVE_TERMIO || defined HAVE_TERMIOS - if (timeout == scb->current_timeout) - return 0; +/* 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). */ - scb->current_timeout = timeout; +/* FIXME: cagney/1999-09-16: Don't replace this with the equivalent + ser_base*() until the old TERMIOS/SGTTY/... timer code has been + flushed. */ - { - struct hardwire_ttystate state; +/* 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. */ - if (get_tty_state (scb, &state)) - fprintf_unfiltered (gdb_stderr, "get_tty_state failed: %s\n", safe_strerror (errno)); - -#ifdef HAVE_TERMIOS - if (timeout < 0) - { - /* No timeout. */ - state.termios.c_cc[VTIME] = 0; - state.termios.c_cc[VMIN] = 1; - } - else - { - state.termios.c_cc[VMIN] = 0; - state.termios.c_cc[VTIME] = timeout * 10; - if (state.termios.c_cc[VTIME] != timeout * 10) - { - - /* If c_cc is an 8-bit signed character, we can't go - bigger than this. If it is always unsigned, we could use - 25. */ - - scb->current_timeout = 12; - state.termios.c_cc[VTIME] = scb->current_timeout * 10; - scb->timeout_remaining = timeout - scb->current_timeout; - } - } -#endif - -#ifdef HAVE_TERMIO - if (timeout < 0) - { - /* No timeout. */ - state.termio.c_cc[VTIME] = 0; - state.termio.c_cc[VMIN] = 1; - } - else - { - state.termio.c_cc[VMIN] = 0; - state.termio.c_cc[VTIME] = timeout * 10; - if (state.termio.c_cc[VTIME] != timeout * 10) - { - /* If c_cc is an 8-bit signed character, we can't go - bigger than this. If it is always unsigned, we could use - 25. */ - - scb->current_timeout = 12; - state.termio.c_cc[VTIME] = scb->current_timeout * 10; - scb->timeout_remaining = timeout - scb->current_timeout; - } - } -#endif - - if (set_tty_state (scb, &state)) - 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). */ static int -hardwire_readchar (scb, timeout) - serial_t scb; - int timeout; +do_hardwire_readchar (struct serial *scb, int timeout) { 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. */ + /* 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) @@ -567,11 +536,12 @@ hardwire_readchar (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. */ + someone else might have freed it. The + deprecated_ui_loop_hook signals that we should exit by + returning 1. */ - if (ui_loop_hook) - detach = ui_loop_hook (0); + if (deprecated_ui_loop_hook) + detach = deprecated_ui_loop_hook (0); if (detach) return SERIAL_TIMEOUT; @@ -582,11 +552,11 @@ hardwire_readchar (scb, timeout) if (status < 0) return status; - scb->bufcnt = read (scb->fd, scb->buf, BUFSIZ); + status = read (scb->fd, scb->buf, BUFSIZ); - if (scb->bufcnt <= 0) + if (status <= 0) { - if (scb->bufcnt == 0) + if (status == 0) { /* Zero characters means timeout (it could also be EOF, but we don't (yet at least) distinguish). */ @@ -603,15 +573,23 @@ hardwire_readchar (scb, 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; scb->bufcnt--; scb->bufp = scb->buf; return *scb->bufp++; } } +static int +hardwire_readchar (struct serial *scb, int timeout) +{ + return generic_readchar (scb, timeout, do_hardwire_readchar); +} + + #ifndef B19200 #define B19200 EXTA #endif @@ -721,31 +699,62 @@ baudtab[] = }; static int -rate_to_code (rate) - int rate; +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; } static int -hardwire_setbaudrate (scb, rate) - serial_t scb; - int rate; +hardwire_setbaudrate (struct serial *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 @@ -754,21 +763,19 @@ hardwire_setbaudrate (scb, 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); } static int -hardwire_setstopbits (scb, num) - serial_t scb; - int num; +hardwire_setstopbits (struct serial *scb, int num) { struct hardwire_ttystate state; int newbit; @@ -810,29 +817,53 @@ hardwire_setstopbits (scb, num) return set_tty_state (scb, &state); } +/* Implement the "setparity" serial_ops callback. */ + static int -hardwire_write (scb, str, len) - serial_t scb; - const char *str; - int len; +hardwire_setparity (struct serial *scb, int parity) { - int cc; + struct hardwire_ttystate state; + int newparity = 0; - while (len > 0) - { - cc = write (scb->fd, str, len); + if (get_tty_state (scb, &state)) + return -1; - if (cc < 0) - return 1; - len -= cc; - str += cc; + 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; } - return 0; + +#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 (scb) - serial_t scb; +hardwire_close (struct serial *scb) { if (scb->fd < 0) return; @@ -840,30 +871,68 @@ hardwire_close (scb) close (scb->fd); scb->fd = -1; } + + + +/* The hardwire ops. */ -static struct serial_ops hardwire_ops = +static const struct serial_ops hardwire_ops = { "hardwire", - 0, 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, - hardwire_write, + 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_drain_output, /* wait for output to drain */ + hardwire_setparity, + hardwire_drain_output, + ser_base_async, + ser_unix_read_prim, + ser_unix_write_prim }; void -_initialize_ser_hardwire () +_initialize_ser_hardwire (void) { serial_add_interface (&hardwire_ops); + +#ifdef HAVE_TERMIOS +#ifdef CRTSCTS + add_setshow_boolean_cmd ("remoteflow", no_class, + &serial_hwflow, _("\ +Set use of hardware flow control for remote serial I/O."), _("\ +Show use of hardware flow control for remote serial I/O."), _("\ +Enable or disable hardware flow control (RTS/CTS) on the serial port\n\ +when debugging using remote targets."), + NULL, + show_serial_hwflow, + &setlist, &showlist); +#endif +#endif +} + +int +ser_unix_read_prim (struct serial *scb, size_t count) +{ + return read (scb->fd, scb->buf, count); +} + +int +ser_unix_write_prim (struct serial *scb, const void *buf, size_t len) +{ + return write (scb->fd, buf, len); }