diff --git a/src/ser_posix.c b/src/ser_posix.c index 96d665f0..d2b3031b 100644 --- a/src/ser_posix.c +++ b/src/ser_posix.c @@ -98,19 +98,6 @@ static speed_t serial_baud_lookup(long baud) return baud; } -static tcflag_t translate_flags(unsigned long cflags) -{ - return ((cflags & SERIAL_CS5) ? CS5 : 0) | - ((cflags & SERIAL_CS6) ? CS6 : 0) | - ((cflags & SERIAL_CS7) ? CS7 : 0) | - ((cflags & SERIAL_CS8) ? CS8 : 0) | - ((cflags & SERIAL_CSTOPB) ? CSTOPB : 0) | - ((cflags & SERIAL_CREAD) ? CREAD : 0) | - ((cflags & (SERIAL_PARENB | SERIAL_PARODD)) ? PARENB : 0) | - ((cflags & SERIAL_PARODD) ? PARODD : 0) | - ((cflags & SERIAL_CLOCAL) ? CLOCAL : 0) ; -} - static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cflags) { int rc; @@ -137,16 +124,79 @@ static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cfla original_termios = termios; } - termios.c_iflag = IGNBRK; - termios.c_oflag = 0; - termios.c_lflag = 0; - termios.c_cflag = translate_flags(cflags); - termios.c_cc[VMIN] = 1; - termios.c_cc[VTIME] = 0; + if (cflags & SERIAL_CREAD) { + termios.c_cflag |= CREAD; + } + if (cflags & SERIAL_CLOCAL) { + termios.c_cflag |= CLOCAL; + } + termios.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG | IEXTEN); +#ifdef ECHOCTL + termios.c_lflag &= ~ECHOCTL; +#endif /* ECHOCTL */ +#ifdef ECHOKE + termios.c_lflag &= ~ECHOKE; +#endif /* ECHOKE */ + termios.c_oflag &= ~(OPOST | ONLCR | OCRNL); + termios.c_iflag &= ~(INLCR | IGNCR | ICRNL | IGNBRK); +#ifdef IUCLC + termios.c_iflag &= ~IUCLC; +#endif /* IUCLC */ +#ifdef PARMRK + termios.c_iflag &= ~PARMRK; +#endif /* PARMRK */ cfsetospeed(&termios, speed); cfsetispeed(&termios, speed); + termios.c_cflag &= ~CSIZE; + if (cflags & SERIAL_CS8) { + termios.c_cflag |= CS8; + } + if (cflags & SERIAL_CS7) { + termios.c_cflag |= CS7; + } + if (cflags & SERIAL_CS6) { + termios.c_cflag |= CS6; + } + if (cflags & SERIAL_CS5) { + termios.c_cflag |= CS5; + } + + if (cflags & SERIAL_CSTOPB) { + termios.c_cflag |= CSTOPB; + } else { + termios.c_cflag &= ~CSTOPB; + } + + termios.c_iflag &= ~(INPCK | ISTRIP); + + if (cflags & (SERIAL_PARENB | SERIAL_PARODD)) { + termios.c_cflag |= PARENB; + } else { + termios.c_cflag &= ~PARENB; + } + + if (cflags & SERIAL_PARODD) { + termios.c_cflag |= PARODD; + } else { + termios.c_cflag &= ~PARODD; + } + +#ifdef IXANY + termios.c_iflag &= ~IXANY; +#endif /* IXANY */ + termios.c_iflag &= ~(IXON | IXOFF); + +#ifdef CRTSCTS + termios.c_iflag &= ~CRTSCTS; +#endif /* CRTSCTS */ + +#ifdef CNEW_RTSCTS + termios.c_iflag &= ~CNEW_RTSCTS; +#endif /* CRTSCTS */ + + rc = tcsetattr(fd->ifd, TCSANOW, &termios); if (rc < 0) { avrdude_message(MSG_INFO, "%s: ser_setparams(): tcsetattr() failed\n", @@ -154,14 +204,8 @@ static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cfla return -errno; } - /* - * Everything is now set up for a local line without modem control - * or flow control, so clear O_NONBLOCK again. - */ - rc = fcntl(fd->ifd, F_GETFL, 0); - if (rc != -1) - fcntl(fd->ifd, F_SETFL, rc & ~O_NONBLOCK); - + tcflush(fd->ifd, TCIFLUSH); + return 0; }