migrate to async IO model
new PIIODevice::interrupt() virtual method new PIWaitEvent private class PIEthernet and PISerial basically tested on Windows and Linux
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include "piconfig.h"
|
||||
#include "pidir.h"
|
||||
#include "pipropertystorage.h"
|
||||
#include "piwaitevent_p.h"
|
||||
#include <errno.h>
|
||||
|
||||
#if defined(MICRO_PIP)
|
||||
@@ -169,24 +170,22 @@ REGISTER_DEVICE(PISerial)
|
||||
|
||||
|
||||
PRIVATE_DEFINITION_START(PISerial)
|
||||
PIWaitEvent event;
|
||||
#ifdef WINDOWS
|
||||
PIWaitEvent event_write;
|
||||
DCB desc, sdesc;
|
||||
void * hCom;
|
||||
DWORD readed, mask;
|
||||
HANDLE hCom = nullptr;
|
||||
DWORD readed = 0, mask = 0;
|
||||
OVERLAPPED overlap, overlap_write;
|
||||
#else
|
||||
termios desc, sdesc;
|
||||
uint readed;
|
||||
uint readed = 0;
|
||||
#endif
|
||||
PRIVATE_DEFINITION_END(PISerial)
|
||||
|
||||
|
||||
|
||||
|
||||
PISerial::DeviceInfo::DeviceInfo() {
|
||||
vID = pID = 0;
|
||||
}
|
||||
|
||||
|
||||
PIString PISerial::DeviceInfo::id() const {
|
||||
return PIString::fromNumber(vID, 16).toLowerCase().expandLeftTo(4, '0') + ":" +
|
||||
PIString::fromNumber(pID, 16).toLowerCase().expandLeftTo(4, '0');
|
||||
@@ -209,19 +208,18 @@ PISerial::PISerial(const PIString & device_, PISerial::Speed speed_, PIFlags<PIS
|
||||
|
||||
|
||||
PISerial::~PISerial() {
|
||||
stop();
|
||||
stopAndWait();
|
||||
close();
|
||||
PRIVATE->event.destroy();
|
||||
#ifdef WINDOWS
|
||||
PRIVATE->event_write.destroy();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void PISerial::construct() {
|
||||
#ifdef WINDOWS
|
||||
PRIVATE->hCom = 0;
|
||||
#endif
|
||||
fd = -1;
|
||||
//setPriority(piHigh);
|
||||
vtime = 10;
|
||||
sending = false;
|
||||
//setPriority(piHigh);
|
||||
setParameters(0);
|
||||
setSpeed(S115200);
|
||||
setDataBitsCount(8);
|
||||
@@ -628,6 +626,15 @@ bool PISerial::send(const void * data, int size) {
|
||||
}
|
||||
|
||||
|
||||
void PISerial::interrupt() {
|
||||
//piCoutObj << "interrupt";
|
||||
PRIVATE->event.interrupt();
|
||||
#ifdef WINDOWS
|
||||
PRIVATE->event_write.interrupt();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool PISerial::openDevice() {
|
||||
PIString p = path();
|
||||
//piCout << "ser open" << p;
|
||||
@@ -651,7 +658,7 @@ bool PISerial::openDevice() {
|
||||
if (isReadable()) {ds |= GENERIC_READ; sm |= FILE_SHARE_READ;}
|
||||
if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;}
|
||||
PIString wp = "//./" + p;
|
||||
PRIVATE->hCom = CreateFileA(wp.dataAscii(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
|
||||
PRIVATE->hCom = CreateFileA(wp.dataAscii(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
|
||||
if (PRIVATE->hCom == INVALID_HANDLE_VALUE) {
|
||||
piCoutObj << "Unable to open \"" << p << "\"";
|
||||
fd = -1;
|
||||
@@ -675,6 +682,11 @@ bool PISerial::openDevice() {
|
||||
//piCoutObj << "Initialized " << p;
|
||||
#endif
|
||||
applySettings();
|
||||
PRIVATE->event.create();
|
||||
#ifdef WINDOWS
|
||||
PRIVATE->event_write.create();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -696,6 +708,10 @@ bool PISerial::closeDevice() {
|
||||
#endif
|
||||
fd = -1;
|
||||
}
|
||||
PRIVATE->event.destroy();
|
||||
#ifdef WINDOWS
|
||||
PRIVATE->event_write.destroy();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -796,12 +812,21 @@ ssize_t PISerial::readDevice(void * read_to, ssize_t max_size) {
|
||||
#ifdef WINDOWS
|
||||
if (!canRead()) return -1;
|
||||
if (sending) return -1;
|
||||
// piCoutObj << "com event ...";
|
||||
//piCoutObj << "read ..." << PRIVATE->hCom;
|
||||
ReadFile(PRIVATE->hCom, read_to, max_size, &PRIVATE->readed, 0);
|
||||
memset(&(PRIVATE->overlap), 0, sizeof(PRIVATE->overlap));
|
||||
PRIVATE->overlap.hEvent = PRIVATE->event.event;
|
||||
ReadFile(PRIVATE->hCom, read_to, max_size, NULL, &(PRIVATE->overlap));
|
||||
PRIVATE->readed = 0;
|
||||
if (PRIVATE->event.wait()) {
|
||||
GetOverlappedResult(PRIVATE->hCom, &(PRIVATE->overlap), &(PRIVATE->readed), FALSE);
|
||||
} else
|
||||
return -1;
|
||||
//piCoutObj << "read done" << PRIVATE->readed;
|
||||
DWORD err = GetLastError();
|
||||
//piCout << err;
|
||||
if (err == ERROR_TIMEOUT && PRIVATE->readed == 0)
|
||||
return 0;
|
||||
if (err == ERROR_BAD_COMMAND || err == ERROR_ACCESS_DENIED) {
|
||||
piCoutObj << "read error" << (PRIVATE->readed) << errorString();
|
||||
softStopThreadedRead();
|
||||
close();
|
||||
return 0;
|
||||
@@ -810,9 +835,8 @@ ssize_t PISerial::readDevice(void * read_to, ssize_t max_size) {
|
||||
return PRIVATE->readed;
|
||||
#else
|
||||
if (!canRead()) return -1;
|
||||
reading_now = true;
|
||||
if (!PRIVATE->event.wait(fd)) return -1;
|
||||
ssize_t ret = ::read(fd, read_to, max_size);
|
||||
reading_now = false;
|
||||
if (ret < 0) {
|
||||
int err = errno;
|
||||
if (err == EBADF || err == EFAULT || err == EINVAL || err == EIO) {
|
||||
@@ -832,12 +856,17 @@ ssize_t PISerial::writeDevice(const void * data, ssize_t max_size) {
|
||||
return -1;
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
DWORD wrote;
|
||||
// piCoutObj << "send ...";// << max_size;// << ": " << PIString((char*)data, max_size);
|
||||
DWORD wrote(0);
|
||||
//piCoutObj << "send ..." << max_size;// << ": " << PIString((char*)data, max_size);
|
||||
sending = true;
|
||||
WriteFile(PRIVATE->hCom, data, max_size, &wrote, 0);
|
||||
memset(&(PRIVATE->overlap_write), 0, sizeof(PRIVATE->overlap_write));
|
||||
PRIVATE->overlap_write.hEvent = PRIVATE->event_write.event;
|
||||
WriteFile(PRIVATE->hCom, data, max_size, NULL, &(PRIVATE->overlap_write));
|
||||
if (PRIVATE->event_write.wait()) {
|
||||
GetOverlappedResult(PRIVATE->hCom, &(PRIVATE->overlap_write), &wrote, FALSE);
|
||||
}
|
||||
sending = false;
|
||||
// piCoutObj << "send ok";// << wrote << " bytes in " << path();
|
||||
//piCoutObj << "send ok" << wrote;// << " bytes in " << path();
|
||||
#else
|
||||
ssize_t wrote;
|
||||
wrote = ::write(fd, data, max_size);
|
||||
@@ -1148,7 +1177,7 @@ PIVector<PISerial::DeviceInfo> PISerial::availableDevicesInfo(bool test) {
|
||||
if (test) {
|
||||
for (int i = 0; i < ret.size_s(); ++i) {
|
||||
#ifdef WINDOWS
|
||||
void * hComm = CreateFileA(ret[i].path.dataAscii(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
|
||||
void * hComm = CreateFileA(ret[i].path.dataAscii(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
|
||||
if (hComm == INVALID_HANDLE_VALUE) {
|
||||
#else
|
||||
int fd = ::open(ret[i].path.dataAscii(), O_NOCTTY | O_RDONLY);
|
||||
|
||||
Reference in New Issue
Block a user