/* port.c - All port related vrflash functions Copyright (C) 2001 Jeff Carneal 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include #include #include #include #include #include #ifdef HAVE_TERMIO_H #include #else #include #endif #include #include #ifdef HAVE_LOW_LATENCY #include #endif #include "main.h" #include "port.h" #include "xmodem.h" #include "vrerror.h" extern int do_portlog; /* * Returns the file descriptor on success or -1 on error. */ int port_open(char *filestr) { int fd; #ifdef HAVE_LOW_LATENCY struct serial_struct serinfo; #endif if((fd = open(filestr, O_RDWR | O_NOCTTY | O_NDELAY))<0) return -1; #ifdef HAVE_LOW_LATENCY if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) vr_error("Error: Cannot get linux serial options"); serinfo.flags |= ASYNC_LOW_LATENCY; if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0) vr_error("Error: Cannot set linux serial options"); /* * Major hack. For some reason the LOW_LATENCY flag * will not set on an open port. You have to close * and reopen port to make it work. I looked * for a TIOC ioctl flag that would override this * but couldn't find it. Let me know if you know * of one, cuz I hate this code */ close(fd); if((fd = open(filestr, O_RDWR | O_NOCTTY | O_NDELAY))<0) return -1; #endif fcntl(fd, F_SETFL, 0); return (fd); } void port_init(int fd) { struct termios options; /* * Get the port options */ if(tcgetattr(fd, &options) < 0) vr_error("Error: Cannot get serial options"); /* * Set to 115200 bps */ cfsetispeed(&options, B115200); cfsetospeed(&options, B115200); /* * Set to 8N1 */ options.c_cflag |= (CLOCAL | CREAD); options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; /* * Hardware FC */ #ifdef HAVE_CRTSCTS options.c_cflag |= CRTSCTS; #elif HAVE_NEW_RTSCTS options.c_cflag |= CNEW_RTSCTS; #endif options.c_iflag &= ~(IXON | IXOFF | IXANY); /* * Raw inputing. Disable local echo, * canonical input and signals */ options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* * Use parity checking */ options.c_iflag |= (INPCK | ISTRIP); /* * Raw output */ options.c_oflag &= ~OPOST; /* * Set 5s timeout value */ options.c_cc[VMIN] = 0; options.c_cc[VTIME] = TIMEOUT; /* options.c_cc[VEOF] = 1; options.c_cc[VEOL] = 0; * no wait * serinfo.flags |= ASYNC_LOW_LATENCY; */ /* * Set the new options for the port... */ if(tcsetattr(fd, TCSANOW, &options)<0) vr_error("Error: Cannot set serial options"); } void port_send(int fd, char *str, int len, int log) { int wlen = 0; int ret = 0; int i; fd_set fds; struct timeval tv; for(i=0; i 0) { if((wlen = write(fd,str,len))<0) { vr_error("Error: port_send unable to write to serial port"); } else if (wlen < len) { vr_error("Error: port_send to write full buffer to serial port"); } else { if(do_portlog && log) { port_log(str, len); } return; } } } vr_error("Error: port_send timeout writing to port"); } int port_readline(int fd, char *buf) { char inchar; char *prompt = "PMON> "; int i=0; int index=0; int ret=0; fd_set fds; struct timeval tv; memset(buf,0,BUFSIZE); for(i=0; i 0) { while(read(fd, (void *)&inchar, 1) >= 0) { /* * Skip '\n' and '\n' at beginning * ie, blank lines */ if((!index) && ((inchar == '\n') || (inchar == '\r'))) { continue; } if(strstr(buf, prompt) || (inchar == '\n') || (inchar == '\r')) { if(do_portlog) { port_log(buf, strlen(buf)); } return 0; } buf[index] = inchar; index++; if(index>=BUFSIZE) { vr_error("Error: port_readline line too long"); } } return -1; } } return -1; } void port_readflush(int fd) { char buf; char logbuf[BUFSIZE]; fd_set fds; int i=0; struct timeval tv; memset(logbuf,0,BUFSIZE); do { FD_ZERO(&fds); FD_SET(fd, &fds); /* * Short timeout since we're * flushing not reading */ tv.tv_sec = 0; tv.tv_usec = UTIMEOUT; if(read(fd, (void *)&buf, 1)<0) { vr_error("Error: port_readflush failed to read byte"); } if((i