mirror of
https://github.com/wjwwood/serial.git
synced 2026-01-22 11:44:53 +08:00
Merge a196d9fd68425e2b6fc57f4ee99aa7a29f36161f into 69e0372cf0d3796e84ce9a09aff1d74496f68720
This commit is contained in:
commit
9e9a032012
@ -195,9 +195,12 @@ private:
|
||||
flowcontrol_t flowcontrol_; // Flow Control
|
||||
|
||||
// Mutex used to lock the read functions
|
||||
HANDLE read_mutex;
|
||||
HANDLE read_mutex_;
|
||||
// Mutex used to lock the write functions
|
||||
HANDLE write_mutex;
|
||||
HANDLE write_mutex_;
|
||||
|
||||
OVERLAPPED ov_read_; // OVERLAPPED read
|
||||
OVERLAPPED ov_write_; // OVERLAPPED write
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
155
src/impl/win.cc
155
src/impl/win.cc
@ -37,19 +37,24 @@ Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate,
|
||||
flowcontrol_t flowcontrol)
|
||||
: port_ (port.begin(), port.end()), fd_ (INVALID_HANDLE_VALUE), is_open_ (false),
|
||||
baudrate_ (baudrate), parity_ (parity),
|
||||
bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol)
|
||||
bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol),
|
||||
ov_read_{}, ov_write_{}
|
||||
{
|
||||
if (port_.empty () == false)
|
||||
open ();
|
||||
read_mutex = CreateMutex(NULL, false, NULL);
|
||||
write_mutex = CreateMutex(NULL, false, NULL);
|
||||
read_mutex_ = CreateMutex(NULL, false, NULL);
|
||||
write_mutex_ = CreateMutex(NULL, false, NULL);
|
||||
ov_read_.hEvent = CreateEvent(NULL, 1, 0, NULL);
|
||||
ov_write_.hEvent = CreateEvent(NULL, 0, 0, NULL);
|
||||
}
|
||||
|
||||
Serial::SerialImpl::~SerialImpl ()
|
||||
{
|
||||
this->close();
|
||||
CloseHandle(read_mutex);
|
||||
CloseHandle(write_mutex);
|
||||
CloseHandle(read_mutex_);
|
||||
CloseHandle(write_mutex_);
|
||||
CloseHandle(ov_read_.hEvent);
|
||||
CloseHandle(ov_write_.hEvent);
|
||||
}
|
||||
|
||||
void
|
||||
@ -70,7 +75,7 @@ Serial::SerialImpl::open ()
|
||||
0,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
||||
0);
|
||||
|
||||
if (fd_ == INVALID_HANDLE_VALUE) {
|
||||
@ -277,7 +282,23 @@ Serial::SerialImpl::reconfigurePort ()
|
||||
void
|
||||
Serial::SerialImpl::close ()
|
||||
{
|
||||
if (is_open_ == true) {
|
||||
if (is_open_) {
|
||||
// Cancel a blocking operation.
|
||||
DWORD rc;
|
||||
BOOL err;
|
||||
err = GetOverlappedResult(fd_, &ov_read_, &rc, FALSE);
|
||||
if (!err) {
|
||||
rc = GetLastError();
|
||||
if (rc == ERROR_IO_PENDING || rc == ERROR_IO_INCOMPLETE)
|
||||
CancelIoEx(fd_, &ov_read_);
|
||||
}
|
||||
err = GetOverlappedResult(fd_, &ov_write_, &rc, FALSE);
|
||||
if (!err) {
|
||||
rc = GetLastError();
|
||||
if (rc == ERROR_IO_PENDING || rc == ERROR_IO_INCOMPLETE)
|
||||
CancelIoEx(fd_, &ov_write_);
|
||||
}
|
||||
|
||||
if (fd_ != INVALID_HANDLE_VALUE) {
|
||||
int ret;
|
||||
ret = CloseHandle(fd_);
|
||||
@ -315,16 +336,54 @@ Serial::SerialImpl::available ()
|
||||
}
|
||||
|
||||
bool
|
||||
Serial::SerialImpl::waitReadable (uint32_t /*timeout*/)
|
||||
Serial::SerialImpl::waitReadable (uint32_t timeout)
|
||||
{
|
||||
THROW (IOException, "waitReadable is not implemented on Windows.");
|
||||
COMSTAT cs;
|
||||
DWORD error;
|
||||
DWORD old_msk, msk, length;
|
||||
if (!isOpen()) {
|
||||
return false;
|
||||
}
|
||||
if (!GetCommMask(fd_, &old_msk)) {
|
||||
stringstream ss;
|
||||
ss << "Error while get mask of the serial port: " << GetLastError();
|
||||
THROW(IOException, ss.str().c_str());
|
||||
}
|
||||
msk = 0;
|
||||
SetCommMask(fd_, EV_RXCHAR | EV_ERR);
|
||||
if (!WaitCommEvent(fd_, &msk, &ov_read_)) {
|
||||
if (GetLastError() == ERROR_IO_PENDING) {
|
||||
if (WaitForSingleObject(ov_read_.hEvent, (DWORD)timeout) == WAIT_TIMEOUT) {
|
||||
SetCommMask(fd_, old_msk);
|
||||
return false;
|
||||
}
|
||||
GetOverlappedResult(fd_, &ov_read_, &length, TRUE);
|
||||
ResetEvent(ov_read_.hEvent);
|
||||
} else {
|
||||
ClearCommError(fd_, &error, &cs);
|
||||
SetCommMask(fd_, old_msk);
|
||||
return cs.cbInQue > 0;
|
||||
}
|
||||
}
|
||||
SetCommMask(fd_, old_msk);
|
||||
if (msk & EV_ERR) {
|
||||
ClearCommError(fd_, &error, &cs);
|
||||
return cs.cbInQue > 0;
|
||||
}
|
||||
if (msk & EV_RXCHAR) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Serial::SerialImpl::waitByteTimes (size_t /*count*/)
|
||||
Serial::SerialImpl::waitByteTimes (size_t count)
|
||||
{
|
||||
THROW (IOException, "waitByteTimes is not implemented on Windows.");
|
||||
DWORD wait_time = timeout_.inter_byte_timeout * count;
|
||||
HANDLE wait_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
ResetEvent(wait_event);
|
||||
WaitForSingleObject(wait_event, wait_time);
|
||||
CloseHandle(wait_event);
|
||||
}
|
||||
|
||||
size_t
|
||||
@ -333,13 +392,31 @@ Serial::SerialImpl::read (uint8_t *buf, size_t size)
|
||||
if (!is_open_) {
|
||||
throw PortNotOpenedException ("Serial::read");
|
||||
}
|
||||
DWORD bytes_read;
|
||||
if (!ReadFile(fd_, buf, static_cast<DWORD>(size), &bytes_read, NULL)) {
|
||||
stringstream ss;
|
||||
ss << "Error while reading from the serial port: " << GetLastError();
|
||||
THROW (IOException, ss.str().c_str());
|
||||
if (size > 0) {
|
||||
ResetEvent(ov_read_.hEvent);
|
||||
DWORD bytes_read;
|
||||
BOOL read_ok = ReadFile(fd_, buf, static_cast<DWORD>(size), &bytes_read, &ov_read_);
|
||||
if (!read_ok) {
|
||||
DWORD error = GetLastError();
|
||||
if ((error != ERROR_SUCCESS) && (error != ERROR_IO_PENDING)) {
|
||||
stringstream ss;
|
||||
ss << "Error while reading from the serial port: " << error;
|
||||
THROW (IOException, ss.str().c_str());
|
||||
}
|
||||
}
|
||||
BOOL result_ok = GetOverlappedResult(fd_, &ov_read_, &bytes_read, TRUE);
|
||||
if (!result_ok) {
|
||||
DWORD error = GetLastError();
|
||||
if (error != ERROR_OPERATION_ABORTED) {
|
||||
stringstream ss;
|
||||
ss << "GetOverlappedResult failed: " << error;
|
||||
THROW (IOException, ss.str().c_str());
|
||||
}
|
||||
}
|
||||
return (size_t) (bytes_read);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return (size_t) (bytes_read);
|
||||
}
|
||||
|
||||
size_t
|
||||
@ -349,12 +426,38 @@ Serial::SerialImpl::write (const uint8_t *data, size_t length)
|
||||
throw PortNotOpenedException ("Serial::write");
|
||||
}
|
||||
DWORD bytes_written;
|
||||
if (!WriteFile(fd_, data, static_cast<DWORD>(length), &bytes_written, NULL)) {
|
||||
stringstream ss;
|
||||
ss << "Error while writing to the serial port: " << GetLastError();
|
||||
THROW (IOException, ss.str().c_str());
|
||||
int success = WriteFile(fd_, data, static_cast<DWORD>(length), &bytes_written, &ov_write_);
|
||||
DWORD error = success ? ERROR_SUCCESS : GetLastError();
|
||||
if (timeout_.write_timeout_constant != 0) {
|
||||
if ((error != ERROR_SUCCESS) && (error != ERROR_IO_PENDING)) {
|
||||
stringstream ss;
|
||||
ss << "WriteFile failed: " << error;
|
||||
THROW (IOException, ss.str().c_str());
|
||||
}
|
||||
GetOverlappedResult(fd_, &ov_write_, &bytes_written, TRUE);
|
||||
error = GetLastError();
|
||||
if (error == ERROR_OPERATION_ABORTED) {
|
||||
return bytes_written;
|
||||
}
|
||||
if (bytes_written != length) {
|
||||
stringstream ss;
|
||||
ss << "Write timeout.";
|
||||
THROW (IOException, ss.str().c_str());
|
||||
}
|
||||
return bytes_written;
|
||||
} else {
|
||||
if ((error == ERROR_INVALID_USER_BUFFER) ||
|
||||
(error == ERROR_NOT_ENOUGH_MEMORY) ||
|
||||
(error == ERROR_OPERATION_ABORTED)) {
|
||||
return 0;
|
||||
} else if ((error == ERROR_SUCCESS) || (error == ERROR_IO_PENDING)) {
|
||||
return (size_t) (bytes_written);
|
||||
} else {
|
||||
stringstream ss;
|
||||
ss << "WriteFile failed: " << error;
|
||||
THROW (IOException, ss.str().c_str());
|
||||
}
|
||||
}
|
||||
return (size_t) (bytes_written);
|
||||
}
|
||||
|
||||
void
|
||||
@ -613,7 +716,7 @@ Serial::SerialImpl::getCD()
|
||||
void
|
||||
Serial::SerialImpl::readLock()
|
||||
{
|
||||
if (WaitForSingleObject(read_mutex, INFINITE) != WAIT_OBJECT_0) {
|
||||
if (WaitForSingleObject(read_mutex_, INFINITE) != WAIT_OBJECT_0) {
|
||||
THROW (IOException, "Error claiming read mutex.");
|
||||
}
|
||||
}
|
||||
@ -621,7 +724,7 @@ Serial::SerialImpl::readLock()
|
||||
void
|
||||
Serial::SerialImpl::readUnlock()
|
||||
{
|
||||
if (!ReleaseMutex(read_mutex)) {
|
||||
if (!ReleaseMutex(read_mutex_)) {
|
||||
THROW (IOException, "Error releasing read mutex.");
|
||||
}
|
||||
}
|
||||
@ -629,7 +732,7 @@ Serial::SerialImpl::readUnlock()
|
||||
void
|
||||
Serial::SerialImpl::writeLock()
|
||||
{
|
||||
if (WaitForSingleObject(write_mutex, INFINITE) != WAIT_OBJECT_0) {
|
||||
if (WaitForSingleObject(write_mutex_, INFINITE) != WAIT_OBJECT_0) {
|
||||
THROW (IOException, "Error claiming write mutex.");
|
||||
}
|
||||
}
|
||||
@ -637,7 +740,7 @@ Serial::SerialImpl::writeLock()
|
||||
void
|
||||
Serial::SerialImpl::writeUnlock()
|
||||
{
|
||||
if (!ReleaseMutex(write_mutex)) {
|
||||
if (!ReleaseMutex(write_mutex_)) {
|
||||
THROW (IOException, "Error releasing write mutex.");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user