mirror of
https://github.com/wjwwood/serial.git
synced 2026-01-23 04:04:54 +08:00
Found an error in my buffering code and added a timeout
to write
This commit is contained in:
parent
8b2c7d4359
commit
49ae058770
@ -265,7 +265,6 @@ Serial::SerialImpl::read (char* buf, size_t size)
|
|||||||
bytes_read = ::read (fd_, buf, size);
|
bytes_read = ::read (fd_, buf, size);
|
||||||
// read should always return some data as select reported it was
|
// read should always return some data as select reported it was
|
||||||
// ready to read when we get to this point.
|
// ready to read when we get to this point.
|
||||||
// printf("bytes_read: %lu\n", bytes_read);
|
|
||||||
if (bytes_read < 1)
|
if (bytes_read < 1)
|
||||||
{
|
{
|
||||||
// Disconnected devices, at least on Linux, show the
|
// Disconnected devices, at least on Linux, show the
|
||||||
@ -292,24 +291,53 @@ Serial::SerialImpl::write (const string &data)
|
|||||||
throw PortNotOpenedException ("Serial::write");
|
throw PortNotOpenedException ("Serial::write");
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t n = ::write (fd_, data.c_str (), data.length ());
|
fd_set writefds;
|
||||||
|
ssize_t bytes_written = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (timeout_ != -1)
|
||||||
|
{
|
||||||
|
FD_ZERO (&writefds);
|
||||||
|
FD_SET (fd_, &writefds);
|
||||||
|
struct timeval timeout;
|
||||||
|
timeout.tv_sec = timeout_ / 1000;
|
||||||
|
timeout.tv_usec = static_cast<int> (timeout_ % 1000) * 1000;
|
||||||
|
int r = select (fd_ + 1, NULL, &writefds, NULL, &timeout);
|
||||||
|
|
||||||
if (n != static_cast<ssize_t> (data.length ()))
|
if (r == -1 && errno == EINTR)
|
||||||
{
|
continue;
|
||||||
throw IOException ("Write did not complete");
|
|
||||||
}
|
if (r == -1)
|
||||||
else if (n == -1)
|
|
||||||
{
|
|
||||||
if (errno == EINTR)
|
|
||||||
{
|
|
||||||
return write (data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
throw IOException (errno);
|
throw IOException (errno);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return static_cast<size_t> (n);
|
|
||||||
|
if (timeout_ == -1 || FD_ISSET (fd_, &writefds))
|
||||||
|
{
|
||||||
|
bytes_written = ::write (fd_, data.c_str (), data.length ());
|
||||||
|
// read should always return some data as select reported it was
|
||||||
|
// ready to read when we get to this point.
|
||||||
|
if (bytes_written < 1)
|
||||||
|
{
|
||||||
|
// Disconnected devices, at least on Linux, show the
|
||||||
|
// behavior that they are always ready to read immediately
|
||||||
|
// but reading returns nothing.
|
||||||
|
throw SerialExecption ("device reports readiness to read but "
|
||||||
|
"returned no data (device disconnected?)");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bytes_written != static_cast<ssize_t> (data.length ()))
|
||||||
|
{
|
||||||
|
throw IOException ("Write did not complete");
|
||||||
|
}
|
||||||
|
return static_cast<size_t> (bytes_written);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@ -91,7 +91,7 @@ Serial::read (size_t size)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Needs to read, loop until we have read enough... or timeout
|
// Needs to read, loop until we have read enough or timeout
|
||||||
size_t chars_left = 0;
|
size_t chars_left = 0;
|
||||||
string result = "";
|
string result = "";
|
||||||
|
|
||||||
@ -114,8 +114,8 @@ Serial::read (size_t size)
|
|||||||
*(read_cache_ + chars_read) = '\0';
|
*(read_cache_ + chars_read) = '\0';
|
||||||
if (chars_left > chars_read)
|
if (chars_left > chars_read)
|
||||||
{
|
{
|
||||||
|
result.append (read_cache_, chars_read);
|
||||||
memset (read_cache_, 0, buffer_size_);
|
memset (read_cache_, 0, buffer_size_);
|
||||||
result.append (read_cache_);
|
|
||||||
chars_left -= chars_read;
|
chars_left -= chars_read;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user