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:
parent
69e0372cf0
commit
a7e90c0f84
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user