* fhandler_serial.cc (fhandler_serial::open): Avoid extraneous setting of res.

* termios.cc (tcsetattr): Correctly record errno after tcsetattr call.
* fhandler_serial.cc (fhandler_serial::tcsetattr): Add error-checking so that
if any Win32 SetComm*() calls fail, errno gets set to EINVAL and tcsetattr()
returns -1.  Catch invalid bitrates, mostly.  If baud rate setting is B0, just
drop DTR and leave Win32 DCB bitrate as-is since 0 is not a valid Win32
setting.
(fhandler_serial::tcgetattr): If DTR is low, populate the bitrate as B0,
otherwise get it from the DCB.
This commit is contained in:
Christopher Faylor 2003-02-01 04:48:03 +00:00
parent aa0a224816
commit b0a82a859d
3 changed files with 187 additions and 161 deletions

View File

@ -1,3 +1,20 @@
2003-01-31 Christopher Faylor <cgf@redhat.com>
* fhandler_serial.cc (fhandler_serial::open): Avoid extraneous setting
of res.
* termios.cc (tcsetattr): Correctly record errno after tcsetattr call.
2003-01-31 Troy Curtiss <troyc@usa.net>
* fhandler_serial.cc (fhandler_serial::tcsetattr): Add error-checking
so that if any Win32 SetComm*() calls fail, errno gets set to EINVAL
and tcsetattr() returns -1. Catch invalid bitrates, mostly. If baud
rate setting is B0, just drop DTR and leave Win32 DCB bitrate as-is
since 0 is not a valid Win32 setting.
(fhandler_serial::tcgetattr): If DTR is low, populate the bitrate as
B0, otherwise get it from the DCB.
2003-01-31 Christopher Faylor <cgf@redhat.com> 2003-01-31 Christopher Faylor <cgf@redhat.com>
* passwd.cc (pwdgrp::read_passwd): linebuf *must* be static (from * passwd.cc (pwdgrp::read_passwd): linebuf *must* be static (from

View File

@ -168,12 +168,12 @@ fhandler_serial::raw_write (const void *ptr, size_t len)
switch (GetLastError ()) switch (GetLastError ())
{ {
case ERROR_OPERATION_ABORTED: case ERROR_OPERATION_ABORTED:
continue; continue;
case ERROR_IO_PENDING: case ERROR_IO_PENDING:
break; break;
default: default:
goto err; goto err;
} }
if (!GetOverlappedResult (get_handle (), &write_status, &bytes_written, TRUE)) if (!GetOverlappedResult (get_handle (), &write_status, &bytes_written, TRUE))
@ -214,7 +214,7 @@ fhandler_serial::open (path_conv *, int flags, mode_t mode)
syscall_printf ("fhandler_serial::open (%s, %p, %p)", syscall_printf ("fhandler_serial::open (%s, %p, %p)",
get_name (), flags, mode); get_name (), flags, mode);
if (!(res = this->fhandler_base::open (NULL, flags, mode))) if (!this->fhandler_base::open (NULL, flags, mode))
return 0; return 0;
res = 1; res = 1;
@ -347,27 +347,27 @@ fhandler_serial::tcflow (int action)
switch (action) switch (action)
{ {
case TCOOFF: case TCOOFF:
win32action = SETXOFF; win32action = SETXOFF;
break; break;
case TCOON: case TCOON:
win32action = SETXON; win32action = SETXON;
break; break;
case TCION: case TCION:
case TCIOFF: case TCIOFF:
if (GetCommState (get_handle (), &dcb) == 0) if (GetCommState (get_handle (), &dcb) == 0)
return -1;
if (action == TCION)
xchar = (dcb.XonChar ? dcb.XonChar : 0x11);
else
xchar = (dcb.XoffChar ? dcb.XoffChar : 0x13);
if (TransmitCommChar (get_handle (), xchar) == 0)
return -1;
return 0;
break;
default:
return -1; return -1;
break; if (action == TCION)
xchar = (dcb.XonChar ? dcb.XonChar : 0x11);
else
xchar = (dcb.XoffChar ? dcb.XoffChar : 0x13);
if (TransmitCommChar (get_handle (), xchar) == 0)
return -1;
return 0;
break;
default:
return -1;
break;
} }
if (EscapeCommFunction (get_handle (), win32action) == 0) if (EscapeCommFunction (get_handle (), win32action) == 0)
@ -530,8 +530,8 @@ fhandler_serial::tcsetattr (int action, const struct termios *t)
COMMTIMEOUTS to; COMMTIMEOUTS to;
DCB ostate, state; DCB ostate, state;
unsigned int ovtime = vtime_, ovmin = vmin_; unsigned int ovtime = vtime_, ovmin = vmin_;
int tmpDtr, tmpRts; int tmpDtr, tmpRts, res;
tmpDtr = tmpRts = 0; res = tmpDtr = tmpRts = 0;
termios_printf ("action %d", action); termios_printf ("action %d", action);
if ((action == TCSADRAIN) || (action == TCSAFLUSH)) if ((action == TCSADRAIN) || (action == TCSAFLUSH))
@ -554,75 +554,76 @@ fhandler_serial::tcsetattr (int action, const struct termios *t)
switch (t->c_ospeed) switch (t->c_ospeed)
{ {
case B0: /* drop DTR */ case B0:
dropDTR = TRUE; /* Drop DTR - but leave DCB-resident bitrate as-is since
state.BaudRate = 0; 0 is an invalid bitrate in Win32 */
break; dropDTR = TRUE;
case B110: break;
state.BaudRate = CBR_110; case B110:
break; state.BaudRate = CBR_110;
case B300: break;
state.BaudRate = CBR_300; case B300:
break; state.BaudRate = CBR_300;
case B600: break;
state.BaudRate = CBR_600; case B600:
break; state.BaudRate = CBR_600;
case B1200: break;
state.BaudRate = CBR_1200; case B1200:
break; state.BaudRate = CBR_1200;
case B2400: break;
state.BaudRate = CBR_2400; case B2400:
break; state.BaudRate = CBR_2400;
case B4800: break;
state.BaudRate = CBR_4800; case B4800:
break; state.BaudRate = CBR_4800;
case B9600: break;
state.BaudRate = CBR_9600; case B9600:
break; state.BaudRate = CBR_9600;
case B19200: break;
state.BaudRate = CBR_19200; case B19200:
break; state.BaudRate = CBR_19200;
case B38400: break;
state.BaudRate = CBR_38400; case B38400:
break; state.BaudRate = CBR_38400;
case B57600: break;
state.BaudRate = CBR_57600; case B57600:
break; state.BaudRate = CBR_57600;
case B115200: break;
state.BaudRate = CBR_115200; case B115200:
break; state.BaudRate = CBR_115200;
case B230400: break;
state.BaudRate = 230400 /* CBR_230400 - not defined */; case B230400:
break; state.BaudRate = 230400 /* CBR_230400 - not defined */;
default: break;
/* Unsupported baud rate! */ default:
termios_printf ("Invalid t->c_ospeed %d", t->c_ospeed); /* Unsupported baud rate! */
set_errno (EINVAL); termios_printf ("Invalid t->c_ospeed %d", t->c_ospeed);
return -1; set_errno (EINVAL);
return -1;
} }
/* -------------- Set byte size ------------------ */ /* -------------- Set byte size ------------------ */
switch (t->c_cflag & CSIZE) switch (t->c_cflag & CSIZE)
{ {
case CS5: case CS5:
state.ByteSize = 5; state.ByteSize = 5;
break; break;
case CS6: case CS6:
state.ByteSize = 6; state.ByteSize = 6;
break; break;
case CS7: case CS7:
state.ByteSize = 7; state.ByteSize = 7;
break; break;
case CS8: case CS8:
state.ByteSize = 8; state.ByteSize = 8;
break; break;
default: default:
/* Unsupported byte size! */ /* Unsupported byte size! */
termios_printf ("Invalid t->c_cflag byte size %d", termios_printf ("Invalid t->c_cflag byte size %d",
t->c_cflag & CSIZE); t->c_cflag & CSIZE);
set_errno (EINVAL); set_errno (EINVAL);
return -1; return -1;
} }
/* -------------- Set stop bits ------------------ */ /* -------------- Set stop bits ------------------ */
@ -725,8 +726,16 @@ fhandler_serial::tcsetattr (int action, const struct termios *t)
state.fAbortOnError = TRUE; state.fAbortOnError = TRUE;
if (memcmp (&ostate, &state, sizeof (state)) != 0) if ((memcmp (&ostate, &state, sizeof (state)) != 0)
SetCommState (get_handle (), &state); && !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, %E");
__seterrno ();
res = -1;
}
set_r_binary ((t->c_iflag & IGNCR) ? 0 : 1); set_r_binary ((t->c_iflag & IGNCR) ? 0 : 1);
set_w_binary ((t->c_oflag & ONLCR) ? 0 : 1); set_w_binary ((t->c_oflag & ONLCR) ? 0 : 1);
@ -750,8 +759,7 @@ fhandler_serial::tcsetattr (int action, const struct termios *t)
rts = tmpRts; rts = tmpRts;
dtr = tmpDtr; dtr = tmpDtr;
/* /* The following documentation on was taken from "Linux Serial Programming
The following documentation on was taken from "Linux Serial Programming
HOWTO". It explains how MIN (t->c_cc[VMIN] || vmin_) and TIME HOWTO". It explains how MIN (t->c_cc[VMIN] || vmin_) and TIME
(t->c_cc[VTIME] || vtime_) is to be used. (t->c_cc[VTIME] || vtime_) is to be used.
@ -794,49 +802,51 @@ fhandler_serial::tcsetattr (int action, const struct termios *t)
debug_printf ("vtime %d, vmin %d", vtime_, vmin_); debug_printf ("vtime %d, vmin %d", vtime_, vmin_);
if (ovmin == vmin_ && ovtime == vtime_) if (ovmin != vmin_ || ovtime != vtime_)
return 0; {
memset (&to, 0, sizeof (to));
memset (&to, 0, sizeof (to)); 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 */
to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
to.ReadTotalTimeoutConstant = MAXDWORD - 1;
}
else if ((vmin_ == 0) && (vtime_ > 0))
{
/* set timeoout constant appropriately and we will only try to
read one character in ReadFile() */
to.ReadTotalTimeoutConstant = vtime_;
to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
}
else if ((vmin_ > 0) && (vtime_ > 0))
{
/* time applies to the interval time for this case */
to.ReadIntervalTimeout = vtime_;
}
else if ((vmin_ == 0) && (vtime_ == 0))
{
/* returns immediately with whatever is in buffer as per
Time-Outs docs in Win32 SDK API docs */
to.ReadIntervalTimeout = MAXDWORD;
}
if ((vmin_ > 0) && (vtime_ == 0)) debug_printf ("ReadTotalTimeoutConstant %d, ReadIntervalTimeout %d, ReadTotalTimeoutMultiplier %d",
{ to.ReadTotalTimeoutConstant, to.ReadIntervalTimeout, to.ReadTotalTimeoutMultiplier);
/* 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 */
to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
to.ReadTotalTimeoutConstant = MAXDWORD - 1;
}
else if ((vmin_ == 0) && (vtime_ > 0))
{
/* set timeoout constant appropriately and we will only try to
read one character in ReadFile() */
to.ReadTotalTimeoutConstant = vtime_;
to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
}
else if ((vmin_ > 0) && (vtime_ > 0))
{
/* time applies to the interval time for this case */
to.ReadIntervalTimeout = vtime_;
}
else if ((vmin_ == 0) && (vtime_ == 0))
{
/* returns immediately with whatever is in buffer as per
Time-Outs docs in Win32 SDK API docs */
to.ReadIntervalTimeout = MAXDWORD;
}
debug_printf ("ReadTotalTimeoutConstant %d, ReadIntervalTimeout %d, ReadTotalTimeoutMultiplier %d", if (!SetCommTimeouts(get_handle (), &to))
to.ReadTotalTimeoutConstant, to.ReadIntervalTimeout, to.ReadTotalTimeoutMultiplier); {
int res = SetCommTimeouts (get_handle (), &to); /* SetCommTimeouts() failed. Keep track of this so we
if (!res) can set errno to EINVAL later and return failure */
{ termios_printf ("SetCommTimeouts() failed, %E");
system_printf ("SetCommTimeout failed, %E"); __seterrno ();
__seterrno (); res = -1;
return -1; }
} }
return 0; return res;
} }
/* tcgetattr: POSIX 7.2.1.1 */ /* tcgetattr: POSIX 7.2.1.1 */
@ -854,12 +864,12 @@ fhandler_serial::tcgetattr (struct termios *t)
/* -------------- Baud rate ------------------ */ /* -------------- Baud rate ------------------ */
switch (state.BaudRate) /* If DTR is NOT set, return B0 as our speed */
{ if (dtr != TIOCM_DTR)
case 0: t->c_cflag = t->c_ospeed = t->c_ispeed = B0;
/* FIXME: need to drop DTR */ else
t->c_cflag = t->c_ospeed = t->c_ispeed = B0; switch (state.BaudRate)
break; {
case CBR_110: case CBR_110:
t->c_cflag = t->c_ospeed = t->c_ispeed = B110; t->c_cflag = t->c_ospeed = t->c_ispeed = B110;
break; break;
@ -901,29 +911,29 @@ fhandler_serial::tcgetattr (struct termios *t)
termios_printf ("Invalid baud rate %d", state.BaudRate); termios_printf ("Invalid baud rate %d", state.BaudRate);
set_errno (EINVAL); set_errno (EINVAL);
return -1; return -1;
} }
/* -------------- Byte size ------------------ */ /* -------------- Byte size ------------------ */
switch (state.ByteSize) switch (state.ByteSize)
{ {
case 5: case 5:
t->c_cflag |= CS5; t->c_cflag |= CS5;
break; break;
case 6: case 6:
t->c_cflag |= CS6; t->c_cflag |= CS6;
break; break;
case 7: case 7:
t->c_cflag |= CS7; t->c_cflag |= CS7;
break; break;
case 8: case 8:
t->c_cflag |= CS8; t->c_cflag |= CS8;
break; break;
default: default:
/* Unsupported byte size! */ /* Unsupported byte size! */
termios_printf ("Invalid byte size %d", state.ByteSize); termios_printf ("Invalid byte size %d", state.ByteSize);
set_errno (EINVAL); set_errno (EINVAL);
return -1; return -1;
} }
/* -------------- Stop bits ------------------ */ /* -------------- Stop bits ------------------ */

View File

@ -144,8 +144,7 @@ tcsetattr (int fd, int a, const struct termios *t)
case bg_ok: case bg_ok:
if (cfd.isopen ()) if (cfd.isopen ())
res = cfd->tcsetattr (a, t); res = cfd->tcsetattr (a, t);
else e = get_errno ();
e = get_errno ();
break; break;
case bg_signalled: case bg_signalled:
if (thisframe.call_signal_handler ()) if (thisframe.call_signal_handler ())