* 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:
parent
aa0a224816
commit
b0a82a859d
@ -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
|
||||||
|
@ -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 ------------------ */
|
||||||
|
@ -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 ())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user