1
0
mirror of https://github.com/wjwwood/serial.git synced 2026-01-22 19:54:57 +08:00

Merge 02654f03eb1a2342d3fdd513bd2c95108434be42 into 69e0372cf0d3796e84ce9a09aff1d74496f68720

This commit is contained in:
Mr. Chip 2024-08-20 22:20:25 -07:00 committed by GitHub
commit d64df04f11
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 78 additions and 14 deletions

View File

@ -198,6 +198,7 @@ private:
HANDLE read_mutex; HANDLE read_mutex;
// Mutex used to lock the write functions // Mutex used to lock the write functions
HANDLE write_mutex; HANDLE write_mutex;
OVERLAPPED overlapped_;
}; };
} }

View File

@ -43,6 +43,8 @@ Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate,
open (); open ();
read_mutex = CreateMutex(NULL, false, NULL); read_mutex = CreateMutex(NULL, false, NULL);
write_mutex = CreateMutex(NULL, false, NULL); write_mutex = CreateMutex(NULL, false, NULL);
memset(&overlapped_, 0x00, sizeof(overlapped_));
overlapped_.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
} }
Serial::SerialImpl::~SerialImpl () Serial::SerialImpl::~SerialImpl ()
@ -50,6 +52,7 @@ Serial::SerialImpl::~SerialImpl ()
this->close(); this->close();
CloseHandle(read_mutex); CloseHandle(read_mutex);
CloseHandle(write_mutex); CloseHandle(write_mutex);
CloseHandle(overlapped_.hEvent);
} }
void void
@ -70,7 +73,7 @@ Serial::SerialImpl::open ()
0, 0,
0, 0,
OPEN_EXISTING, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
0); 0);
if (fd_ == INVALID_HANDLE_VALUE) { if (fd_ == INVALID_HANDLE_VALUE) {
@ -279,6 +282,8 @@ Serial::SerialImpl::close ()
{ {
if (is_open_ == true) { if (is_open_ == true) {
if (fd_ != INVALID_HANDLE_VALUE) { if (fd_ != INVALID_HANDLE_VALUE) {
SetCommMask(fd_, 0);
ResetEvent(overlapped_.hEvent);
int ret; int ret;
ret = CloseHandle(fd_); ret = CloseHandle(fd_);
if (ret == 0) { if (ret == 0) {
@ -315,16 +320,60 @@ Serial::SerialImpl::available ()
} }
bool 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, &overlapped_)) {
if (GetLastError() == ERROR_IO_PENDING) {
if (WaitForSingleObject(overlapped_.hEvent, (DWORD)timeout) == WAIT_TIMEOUT) {
SetCommMask(fd_, old_msk);
return false;
}
GetOverlappedResult(fd_, &overlapped_, &length, TRUE);
::ResetEvent(overlapped_.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; return false;
} }
void 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 size_t
@ -334,11 +383,13 @@ Serial::SerialImpl::read (uint8_t *buf, size_t size)
throw PortNotOpenedException ("Serial::read"); throw PortNotOpenedException ("Serial::read");
} }
DWORD bytes_read; DWORD bytes_read;
if (!ReadFile(fd_, buf, static_cast<DWORD>(size), &bytes_read, NULL)) { overlapped_.Offset = 0;
stringstream ss; overlapped_.OffsetHigh = 0;
ss << "Error while reading from the serial port: " << GetLastError(); if (!ReadFile(fd_, buf, static_cast<DWORD>(size), NULL, &overlapped_)) {
THROW (IOException, ss.str().c_str()); WaitForSingleObject(overlapped_.hEvent, timeout_.read_timeout_constant);
} }
GetOverlappedResult(fd_, &overlapped_, &bytes_read, TRUE);
::ResetEvent(overlapped_.hEvent);
return (size_t) (bytes_read); return (size_t) (bytes_read);
} }
@ -349,11 +400,13 @@ Serial::SerialImpl::write (const uint8_t *data, size_t length)
throw PortNotOpenedException ("Serial::write"); throw PortNotOpenedException ("Serial::write");
} }
DWORD bytes_written; DWORD bytes_written;
if (!WriteFile(fd_, data, static_cast<DWORD>(length), &bytes_written, NULL)) { overlapped_.Offset = 0;
stringstream ss; overlapped_.OffsetHigh = 0;
ss << "Error while writing to the serial port: " << GetLastError(); if (!WriteFile(fd_, data, static_cast<DWORD>(length), NULL, &overlapped_)) {
THROW (IOException, ss.str().c_str()); WaitForSingleObject(overlapped_.hEvent, timeout_.write_timeout_constant);
} }
GetOverlappedResult(fd_, &overlapped_, &bytes_written, TRUE);
::ResetEvent(overlapped_.hEvent);
return (size_t) (bytes_written); return (size_t) (bytes_written);
} }
@ -374,7 +427,17 @@ Serial::SerialImpl::setTimeout (serial::Timeout &timeout)
{ {
timeout_ = timeout; timeout_ = timeout;
if (is_open_) { if (is_open_) {
reconfigurePort (); //reconfigurePort ();
// Setup timeouts
COMMTIMEOUTS timeouts = { 0 };
timeouts.ReadIntervalTimeout = timeout_.inter_byte_timeout;
timeouts.ReadTotalTimeoutConstant = timeout_.read_timeout_constant;
timeouts.ReadTotalTimeoutMultiplier = timeout_.read_timeout_multiplier;
timeouts.WriteTotalTimeoutConstant = timeout_.write_timeout_constant;
timeouts.WriteTotalTimeoutMultiplier = timeout_.write_timeout_multiplier;
if (!SetCommTimeouts(fd_, &timeouts)) {
THROW(IOException, "Error setting timeouts.");
}
} }
} }