Index: cygwin/fhandler_serial.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/fhandler_serial.cc,v retrieving revision 1.40 diff -u -p -r1.40 fhandler_serial.cc --- cygwin/fhandler_serial.cc 10 Jan 2003 12:32:46 -0000 1.40 +++ cygwin/fhandler_serial.cc 23 Jan 2003 00:07:32 -0000 @@ -530,8 +530,8 @@ fhandler_serial::tcsetattr (int action, COMMTIMEOUTS to; DCB ostate, state; unsigned int ovtime = vtime_, ovmin = vmin_; - int tmpDtr, tmpRts; - tmpDtr = tmpRts = 0; + int tmpDtr, tmpRts, setcommerr; + setcommerr = tmpDtr = tmpRts = 0; termios_printf ("action %d", action); if ((action == TCSADRAIN) || (action == TCSAFLUSH)) @@ -554,9 +554,10 @@ fhandler_serial::tcsetattr (int action, switch (t->c_ospeed) { - case B0: /* drop DTR */ + case B0: + /* Drop DTR - but leave DCB-resident bitrate as-is since + 0 is an invalid bitrate in Win32 */ dropDTR = TRUE; - state.BaudRate = 0; break; case B110: state.BaudRate = CBR_110; @@ -725,8 +726,16 @@ fhandler_serial::tcsetattr (int action, state.fAbortOnError = TRUE; - if (memcmp (&ostate, &state, sizeof (state)) != 0) - SetCommState (get_handle (), &state); + if ((memcmp (&ostate, &state, sizeof (state)) != 0) && + !SetCommState (get_handle (), &state)) + { + /* SetCommState() failed, usually due to invalid DCB param. + Keep track of this so we can set errno to EINVAL later + and return failure */ + termios_printf ("SetCommState() failed, GetLastError = %d", + GetLastError()); + setcommerr = -1; + } set_r_binary ((t->c_iflag & IGNCR) ? 0 : 1); set_w_binary ((t->c_oflag & ONLCR) ? 0 : 1); @@ -794,49 +803,55 @@ fhandler_serial::tcsetattr (int action, debug_printf ("vtime %d, vmin %d", vtime_, vmin_); - if (ovmin == vmin_ && ovtime == vtime_) - return 0; + if (ovmin != vmin_ || ovtime != vtime_) + { + memset (&to, 0, sizeof (to)); - memset (&to, 0, sizeof (to)); - - if ((vmin_ > 0) && (vtime_ == 0)) + if ((vmin_ > 0) && (vtime_ == 0)) { /* Returns immediately with whatever is in buffer on a ReadFile(); - or blocks if nothing found. We will keep calling ReadFile(); until - vmin_ characters are read */ + or blocks if nothing found. We will keep calling ReadFile(); until + vmin_ characters are read */ to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD; to.ReadTotalTimeoutConstant = MAXDWORD - 1; } - else if ((vmin_ == 0) && (vtime_ > 0)) + else if ((vmin_ == 0) && (vtime_ > 0)) { /* set timeoout constant appropriately and we will only try to - read one character in ReadFile() */ + read one character in ReadFile() */ to.ReadTotalTimeoutConstant = vtime_; to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD; } - else if ((vmin_ > 0) && (vtime_ > 0)) + else if ((vmin_ > 0) && (vtime_ > 0)) { /* time applies to the interval time for this case */ to.ReadIntervalTimeout = vtime_; } - else if ((vmin_ == 0) && (vtime_ == 0)) + else if ((vmin_ == 0) && (vtime_ == 0)) { /* returns immediately with whatever is in buffer as per - Time-Outs docs in Win32 SDK API docs */ + Time-Outs docs in Win32 SDK API docs */ to.ReadIntervalTimeout = MAXDWORD; } - debug_printf ("ReadTotalTimeoutConstant %d, ReadIntervalTimeout %d, ReadTotalTimeoutMultiplier %d", - to.ReadTotalTimeoutConstant, to.ReadIntervalTimeout, to.ReadTotalTimeoutMultiplier); - int res = SetCommTimeouts (get_handle (), &to); - if (!res) - { - system_printf ("SetCommTimeout failed, %E"); - __seterrno (); - return -1; - } + debug_printf ("ReadTotalTimeoutConstant %d, ReadIntervalTimeout %d, ReadTotalTimeoutMultiplier %d", + to.ReadTotalTimeoutConstant, to.ReadIntervalTimeout, to.ReadTotalTimeoutMultiplier); - return 0; + if (!SetCommTimeouts(get_handle (), &to)) + { + /* SetCommTimeouts() failed. Keep track of this so we + can set errno to EINVAL later and return failure */ + termios_printf ("SetCommTimeouts() failed, GetLastError = %d", + GetLastError()); + setcommerr = -1; + } + } + + /* If one or more of the Win32 SetComm*()'s failed, + set errno = EINVAL */ + if (setcommerr) set_errno(EINVAL); + + return setcommerr; } /* tcgetattr: POSIX 7.2.1.1 */ @@ -854,12 +869,10 @@ fhandler_serial::tcgetattr (struct termi /* -------------- Baud rate ------------------ */ - switch (state.BaudRate) + /* If DTR is NOT set, return B0 as our speed */ + if (dtr != TIOCM_DTR) t->c_cflag = t->c_ospeed = t->c_ispeed = B0; + else switch (state.BaudRate) { - case 0: - /* FIXME: need to drop DTR */ - t->c_cflag = t->c_ospeed = t->c_ispeed = B0; - break; case CBR_110: t->c_cflag = t->c_ospeed = t->c_ispeed = B110; break;