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

Full duplex support on Windows.

This commit is contained in:
chinaheyu 2022-11-21 16:53:44 +08:00
parent 69e0372cf0
commit a7e90c0f84
2 changed files with 57 additions and 11 deletions

View File

@ -198,6 +198,9 @@ 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 ov_read; // OVERLAPPED read
OVERLAPPED ov_write; // OVERLAPPED write
}; };
} }

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);
ov_read.hEvent = CreateEvent(NULL, 1, 0, NULL);
ov_write.hEvent = CreateEvent(NULL, 0, 0, NULL);
} }
Serial::SerialImpl::~SerialImpl () Serial::SerialImpl::~SerialImpl ()
@ -50,6 +52,8 @@ Serial::SerialImpl::~SerialImpl ()
this->close(); this->close();
CloseHandle(read_mutex); CloseHandle(read_mutex);
CloseHandle(write_mutex); CloseHandle(write_mutex);
CloseHandle(ov_read.hEvent);
CloseHandle(ov_write.hEvent);
} }
void void
@ -70,7 +74,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) {
@ -277,7 +281,23 @@ Serial::SerialImpl::reconfigurePort ()
void void
Serial::SerialImpl::close () Serial::SerialImpl::close ()
{ {
if (is_open_ == true) { if (is_open_) {
// Cancel a blocking operation.
DWORD rc;
WINBOOL 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) { if (fd_ != INVALID_HANDLE_VALUE) {
int ret; int ret;
ret = CloseHandle(fd_); ret = CloseHandle(fd_);
@ -333,13 +353,31 @@ Serial::SerialImpl::read (uint8_t *buf, size_t size)
if (!is_open_) { if (!is_open_) {
throw PortNotOpenedException ("Serial::read"); throw PortNotOpenedException ("Serial::read");
} }
DWORD bytes_read; if (size > 0) {
if (!ReadFile(fd_, buf, static_cast<DWORD>(size), &bytes_read, NULL)) { ResetEvent(ov_read.hEvent);
stringstream ss; DWORD bytes_read;
ss << "Error while reading from the serial port: " << GetLastError(); WINBOOL read_ok = ReadFile(fd_, buf, static_cast<DWORD>(size), &bytes_read, &ov_read);
THROW (IOException, ss.str().c_str()); 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());
}
}
WINBOOL 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 size_t
@ -349,12 +387,17 @@ 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)) { int success = WriteFile(fd_, data, static_cast<DWORD>(length), &bytes_written, &ov_write);
DWORD error = success ? ERROR_SUCCESS : GetLastError();
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; stringstream ss;
ss << "Error while writing to the serial port: " << GetLastError(); ss << "WriteFile failed: " << error;
THROW (IOException, ss.str().c_str()); THROW (IOException, ss.str().c_str());
} }
return (size_t) (bytes_written);
} }
void void