| /* |
| * agent-proxy-rs232.c rs232 specific stubs for the agent-proxy |
| * |
| * Copyright (c) 2005-2008 Wind River Systems, Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| * |
| * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| * |
| */ |
| /*-----------------WINDOWS SERIAL IMPLEMENTATION-----------------*/ |
| #ifdef _WIN32 |
| /* |
| * Feel free to contribute some code to put here. :-) |
| * Please send patches to kgdb-bugreport@lists.sourceforge.net |
| */ |
| #else /* ! _WIN32 */ |
| /*-----------------UNIX SERIAL IMPLEMENTATION-----------------*/ |
| #include <stdio.h> |
| #include <unistd.h> |
| #include <errno.h> |
| #include <string.h> |
| #ifdef linux |
| #define HAVE_TERMIOS |
| #endif /* linux */ |
| #ifdef sun |
| #define HAVE_TERMIOS |
| #endif /* solaris */ |
| #ifdef HAVE_TERMIOS |
| #include <termios.h> |
| #endif /* HAVE_TERMIOS */ |
| #include "agent-proxy.h" |
| |
| 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 }, |
| #ifdef B57600 |
| { 57600, B57600 }, |
| #endif |
| #ifdef B115200 |
| { 115200, B115200 }, |
| #endif |
| #ifdef B230400 |
| { 230400, B230400 }, |
| #endif |
| #ifdef B460800 |
| { 460800, B460800 }, |
| #endif |
| { -1, -1 }, |
| }; |
| |
| #ifdef HAVE_TERMIOS |
| |
| struct hardwire_ttystate { |
| struct termios termios; |
| }; |
| #endif /* termios */ |
| |
| #ifdef HAVE_TERMIO |
| |
| struct hardwire_ttystate { |
| struct termio termio; |
| }; |
| #endif /* termio */ |
| |
| #ifdef HAVE_SGTTY |
| struct hardwire_ttystate { |
| struct sgttyb sgttyb; |
| struct tchars tc; |
| struct ltchars ltc; |
| /* Line discipline flags. */ |
| int lmode; |
| }; |
| #endif /* sgtty */ |
| |
| static int rate_to_code(int rate) |
| { |
| int i; |
| |
| for (i = 0; baudtab[i].rate != -1; i++) { |
| /* 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) { |
| return -1; |
| } |
| } |
| } |
| return -1; |
| } |
| |
| static int get_tty_state(unsigned int sock, struct hardwire_ttystate *state) |
| { |
| #ifdef HAVE_TERMIOS |
| if (tcgetattr(sock, &state->termios) < 0) |
| return -1; |
| |
| return 0; |
| #endif |
| |
| #ifdef HAVE_TERMIO |
| if (ioctl(sock, TCGETA, &state->termio) < 0) |
| return -1; |
| return 0; |
| #endif |
| |
| #ifdef HAVE_SGTTY |
| if (ioctl(sock, TIOCGETP, &state->sgttyb) < 0) |
| return -1; |
| if (ioctl(sock, TIOCGETC, &state->tc) < 0) |
| return -1; |
| if (ioctl(sock, TIOCGLTC, &state->ltc) < 0) |
| return -1; |
| if (ioctl(sock, TIOCLGET, &state->lmode) < 0) |
| return -1; |
| |
| return 0; |
| #endif |
| } |
| |
| static int set_tty_state(unsigned int sock, struct hardwire_ttystate *state) |
| { |
| #ifdef HAVE_TERMIOS |
| if (tcsetattr(sock, TCSANOW, &state->termios) < 0) |
| return -1; |
| |
| return 0; |
| #endif |
| |
| #ifdef HAVE_TERMIO |
| if (ioctl(sock, TCSETA, &state->termio) < 0) |
| return -1; |
| return 0; |
| #endif |
| |
| #ifdef HAVE_SGTTY |
| if (ioctl(sock, TIOCSETN, &state->sgttyb) < 0) |
| return -1; |
| if (ioctl(sock, TIOCSETC, &state->tc) < 0) |
| return -1; |
| if (ioctl(sock, TIOCSLTC, &state->ltc) < 0) |
| return -1; |
| if (ioctl(sock, TIOCLSET, &state->lmode) < 0) |
| return -1; |
| |
| return 0; |
| #endif |
| } |
| |
| int setbaudrate(int sock, int baud) |
| { |
| struct hardwire_ttystate state; |
| int baud_code = rate_to_code(baud); |
| |
| if (baud_code < 0) { |
| /* The baud rate was not valid. |
| A warning has already been issued. */ |
| errno = EINVAL; |
| return -1; |
| } |
| |
| if (get_tty_state(sock, &state)) |
| return -1; |
| |
| #ifdef HAVE_TERMIOS |
| cfsetospeed(&state.termios, baud_code); |
| cfsetispeed(&state.termios, baud_code); |
| #endif |
| |
| #ifdef HAVE_TERMIO |
| #ifndef CIBAUD |
| #define CIBAUD CBAUD |
| #endif |
| |
| state.termio.c_cflag &= ~(CBAUD | CIBAUD); |
| state.termio.c_cflag |= baud_code; |
| #endif |
| |
| #ifdef HAVE_SGTTY |
| state.sgttyb.sg_ispeed = baud_code; |
| state.sgttyb.sg_ospeed = baud_code; |
| #endif |
| |
| return set_tty_state(sock, &state); |
| } |
| |
| int setstopbits(unsigned int sock, char *stopbits) |
| { |
| struct hardwire_ttystate state; |
| int newbit; |
| |
| if (get_tty_state(sock, &state)) |
| return -1; |
| |
| if (strcmp(stopbits, "2") == 0) |
| newbit = 1; |
| else if (strcmp(stopbits, "1.5") == 0) |
| newbit = 1; |
| else /* Default to 1 stop bit */ |
| newbit = 0; |
| |
| #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 -1; /* sgtty doesn't support this */ |
| #endif |
| |
| return set_tty_state(sock, &state); |
| } |
| |
| int setcondefaults(unsigned int sock) |
| { |
| struct hardwire_ttystate state; |
| |
| if (get_tty_state(sock, &state)) |
| return -1; |
| |
| #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 |= CLOCAL | CS8; |
| state.termios.c_cc[VMIN] = 0; |
| state.termios.c_cc[VTIME] = 0; |
| #endif |
| |
| #ifdef HAVE_TERMIO |
| 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 |= CLOCAL | CS8; |
| state.termio.c_cc[VMIN] = 0; |
| state.termio.c_cc[VTIME] = 0; |
| #endif |
| |
| #ifdef HAVE_SGTTY |
| state.sgttyb.sg_flags |= RAW | ANYP; |
| state.sgttyb.sg_flags &= ~(CBREAK | ECHO); |
| #endif |
| |
| if (set_tty_state(sock, &state)) |
| return -1; |
| return 0; |
| } |
| |
| /* |
| * TCP specific routine for shutting down comunications |
| */ |
| void rs232_portclose(struct port_st *port) |
| { |
| close(port->sock); |
| FD_CLR(port->sock, &master_rds); |
| port->sock = -1; |
| } |
| |
| /* |
| * TCP specific routine for reading |
| */ |
| |
| int rs232_portread(struct port_st *port, char *buf, int size, int opts) |
| { |
| opts = 0; |
| return read(port->sock, buf, size); |
| } |
| |
| /* |
| * TCP specific routine for reading |
| */ |
| |
| int rs232_portwrite(struct port_st *port, char *buf, int size, int opts) |
| { |
| opts = 0; |
| return write(port->sock, buf, size); |
| } |
| |
| #endif /* !_WIN32 */ |