18.03.2013 - Bug fixes, add in/out speed diagnostic to PIProtocol, fixed PIConsole tab switch segfault, PIObject EVENT / EVENT_HANDLER mechanism update - new EVENT macros that use EVENT_HANDLER with raiseEvent implementation.
This allow compile check event for CONNECT and use EVENT as CONNECT target, also raise event now is simple execute EVENT function.
This commit is contained in:
190
piserial.cpp
Executable file → Normal file
190
piserial.cpp
Executable file → Normal file
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
COM
|
||||
Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
||||
Copyright (C) 2013 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -60,6 +60,81 @@ PISerial::~PISerial() {
|
||||
}
|
||||
|
||||
|
||||
bool PISerial::setPin(int number, bool on) {
|
||||
switch (number) {
|
||||
case 1: return setCAR(on); break;
|
||||
case 2: return setSR(on); break;
|
||||
case 3: return setST(on); break;
|
||||
case 4: return setDTR(on); break;
|
||||
case 5:
|
||||
piCout << "[PISerial] Pin number 5 is ground" << endl;
|
||||
return false;
|
||||
case 6: return setDSR(on); break;
|
||||
case 7: return setRTS(on); break;
|
||||
case 8: return setCTS(on); break;
|
||||
case 9: return setRNG(on); break;
|
||||
default:
|
||||
piCout << "[PISerial] Pin number " << number << " doesn`t exists!" << endl;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool PISerial::isPin(int number) const {
|
||||
switch (number) {
|
||||
case 1: return isCAR(); break;
|
||||
case 2: return isSR(); break;
|
||||
case 3: return isST(); break;
|
||||
case 4: return isDTR(); break;
|
||||
case 5: return false;
|
||||
case 6: return isDSR(); break;
|
||||
case 7: return isRTS(); break;
|
||||
case 8: return isCTS(); break;
|
||||
case 9: return isRNG(); break;
|
||||
default:
|
||||
piCout << "[PISerial] Pin number " << number << " doesn`t exists!" << endl;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool PISerial::setBit(int bit, bool on, const PIString & bname) {
|
||||
#ifndef WINDOWS
|
||||
if (fd < 0) {
|
||||
piCout << "[PISerial] set" << bname << " error: \"" << path_ << "\" is not opened!" << endl;
|
||||
return false;
|
||||
}
|
||||
if (ioctl(fd, on ? TIOCMBIS : TIOCMBIC, &bit) < 0) {
|
||||
piCout << "[PISerial] set" << bname << " error: " << errorString();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(" << endl;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool PISerial::isBit(int bit, const PIString & bname) const {
|
||||
#ifndef WINDOWS
|
||||
if (fd < 0) {
|
||||
piCout << "[PISerial] is" << bname << " error: \"" << path_ << "\" is not opened!" << endl;
|
||||
return false;
|
||||
}
|
||||
int ret = 0;
|
||||
if (ioctl(fd, TIOCMGET, &ret) < 0)
|
||||
piCout << "[PISerial] is" << bname << " error: " << errorString();
|
||||
return ret & bit;
|
||||
#else
|
||||
piCout << "[PISerial] set" << bname << " doesn`t implemented on Windows, sorry :-(" << endl;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool PISerial::closeDevice() {
|
||||
if (!isInitialized()) return true;
|
||||
if (isRunning()) {
|
||||
@@ -86,6 +161,8 @@ bool PISerial::closeDevice() {
|
||||
|
||||
int PISerial::convertSpeed(PISerial::Speed speed) {
|
||||
switch (speed) {
|
||||
case S50: return B50;
|
||||
case S75: return B75;
|
||||
case S110: return B110;
|
||||
case S300: return B300;
|
||||
case S600: return B600;
|
||||
@@ -97,6 +174,13 @@ int PISerial::convertSpeed(PISerial::Speed speed) {
|
||||
case S38400: return B38400;
|
||||
case S57600: return B57600;
|
||||
case S115200: return B115200;
|
||||
case S1500000: return B1500000;
|
||||
case S2000000: return B2000000;
|
||||
case S2500000: return B2500000;
|
||||
case S3000000: return B3000000;
|
||||
case S3500000: return B3500000;
|
||||
case S4000000: return B4000000;
|
||||
default: break;
|
||||
}
|
||||
return B115200;
|
||||
}
|
||||
@@ -114,6 +198,7 @@ bool PISerial::read(void * data, int size, double timeout_ms) {
|
||||
if (ret > 0) all += ret;
|
||||
else msleep(1);
|
||||
}
|
||||
received(data, all);
|
||||
return (all == size);
|
||||
} else {
|
||||
setReadIsBlocking(true);
|
||||
@@ -122,15 +207,96 @@ bool PISerial::read(void * data, int size, double timeout_ms) {
|
||||
ret = ::read(fd, &((uchar * )data)[all], size - all);
|
||||
if (ret > 0) all += ret;
|
||||
}
|
||||
received(data, all);
|
||||
return (all == size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
PIByteArray PISerial::readData(int size, double timeout_ms) {
|
||||
int ret, all = 0;
|
||||
uchar td[1024];
|
||||
PIByteArray str;
|
||||
if (timeout_ms > 0.) {
|
||||
setReadIsBlocking(false);
|
||||
timer.reset();
|
||||
if (size <= 0) {
|
||||
while (timer.elapsed_m() < timeout_ms) {
|
||||
ret = ::read(fd, td, 1024);
|
||||
if (ret <= 0) msleep(1);
|
||||
else str << PIByteArray(td, ret);
|
||||
}
|
||||
} else {
|
||||
while (all < size && timer.elapsed_m() < timeout_ms) {
|
||||
ret = ::read(fd, td, size - all);
|
||||
if (ret <= 0) msleep(1);
|
||||
else {
|
||||
str << PIByteArray(td, ret);
|
||||
all += ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setReadIsBlocking(true);
|
||||
all = ::read(fd, td, 1);
|
||||
str << PIByteArray(td, all);
|
||||
while (all < size) {
|
||||
ret = ::read(fd, td, size - all);
|
||||
if (ret <= 0) msleep(1);
|
||||
else {
|
||||
str << PIByteArray(td, ret);
|
||||
all += ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
PIString PISerial::read(int size, double timeout_ms) {
|
||||
int ret, all = 0;
|
||||
uchar td[1024];
|
||||
PIString str;
|
||||
if (timeout_ms > 0.) {
|
||||
setReadIsBlocking(false);
|
||||
timer.reset();
|
||||
if (size <= 0) {
|
||||
while (timer.elapsed_m() < timeout_ms) {
|
||||
ret = ::read(fd, td, 1024);
|
||||
if (ret <= 0) msleep(1);
|
||||
else str << PIString((char*)td, ret);
|
||||
}
|
||||
} else {
|
||||
while (all < size && timer.elapsed_m() < timeout_ms) {
|
||||
ret = ::read(fd, td, size - all);
|
||||
if (ret <= 0) msleep(1);
|
||||
else {
|
||||
str << PIString((char*)td, ret);
|
||||
all += ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setReadIsBlocking(true);
|
||||
all = ::read(fd, td, 1);
|
||||
str << PIString((char*)td, all);
|
||||
while (all < size) {
|
||||
ret = ::read(fd, td, size - all);
|
||||
if (ret <= 0) msleep(1);
|
||||
else {
|
||||
str << PIString((char*)td, ret);
|
||||
all += ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
bool PISerial::openDevice() {
|
||||
#ifdef WINDOWS
|
||||
DWORD da = 0, sm = 0;
|
||||
DWORD ds = 0, sm = 0;
|
||||
if (isReadable()) {ds |= GENERIC_READ; sm |= FILE_SHARE_READ;}
|
||||
if (isWriteable()) {ds |= GENERIC_WRITE; sm |= FILE_SHARE_WRITE;}
|
||||
hCom = CreateFileA(path_.data(), ds, sm, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
|
||||
@@ -176,19 +342,19 @@ bool PISerial::openDevice() {
|
||||
case PIIODevice::WriteOnly: om = O_WRONLY; break;
|
||||
case PIIODevice::ReadWrite: om = O_RDWR; break;
|
||||
}
|
||||
//cout << "init ser " << path_ << " mode " << om << endl;
|
||||
//cout << "init ser " << path_ << " mode " << om << " param " << params << endl;
|
||||
fd = ::open(path_.data(), O_NOCTTY | om);
|
||||
if(fd == -1) {
|
||||
piCout << "[PISerial] Unable to open \"" << path_ << "\"" << endl;
|
||||
return false;
|
||||
}
|
||||
fcntl(fd, F_SETFL, 0);
|
||||
|
||||
tcgetattr(fd, &desc);
|
||||
sdesc = desc;
|
||||
desc.c_iflag = desc.c_oflag = desc.c_lflag = 0;
|
||||
desc.c_iflag = desc.c_oflag = desc.c_lflag = desc.c_cflag = 0;
|
||||
desc.c_cflag = CLOCAL | CSIZE | CS8;
|
||||
if (isReadable()) desc.c_cflag |= CREAD;
|
||||
if (params[PISerial::HardwareFlowControl]) desc.c_cflag |= CRTSCTS;
|
||||
if (params[PISerial::TwoStopBits]) desc.c_cflag |= CSTOPB;
|
||||
if (params[PISerial::ParityControl]) {
|
||||
desc.c_iflag |= INPCK;
|
||||
@@ -201,12 +367,14 @@ bool PISerial::openDevice() {
|
||||
cfsetispeed(&desc, convertSpeed(ispeed));
|
||||
cfsetospeed(&desc, convertSpeed(ospeed));
|
||||
|
||||
tcflush(fd, TCIOFLUSH);
|
||||
fcntl(fd, F_SETFL, 0);
|
||||
|
||||
if(tcsetattr(fd, TCSANOW, &desc) < 0) {
|
||||
piCout << "[PISerial] Can`t set attributes for \"" << path_ << "\"" << endl;
|
||||
::close(fd);
|
||||
return false;
|
||||
}
|
||||
tcflush(fd, TCIOFLUSH);
|
||||
//piCout << "[PISerial] Initialized " << path_ << endl;
|
||||
#endif
|
||||
return true;
|
||||
@@ -214,7 +382,7 @@ bool PISerial::openDevice() {
|
||||
|
||||
|
||||
int PISerial::write(const void * data, int max_size, bool wait) {
|
||||
//piCout << "[PISerial] send size: " << sizeof(data) << endl;
|
||||
//piCout << "[PISerial] send " << max_size << ": " << PIString((char*)data, max_size) << endl;
|
||||
if (fd == -1 || !canWrite()) {
|
||||
//piCout << "[PISerial] Can`t write to uninitialized COM" << endl;
|
||||
return -1;
|
||||
@@ -222,12 +390,18 @@ int PISerial::write(const void * data, int max_size, bool wait) {
|
||||
#ifdef WINDOWS
|
||||
DWORD wrote;
|
||||
WriteFile(hCom, data, max_size, &wrote, 0);
|
||||
if (wait) {
|
||||
DWORD event;
|
||||
SetCommMask(hCom, EV_TXEMPTY);
|
||||
WaitCommEvent(hCom, &event, NULL);
|
||||
SetCommMask(hCom, EV_RXCHAR);
|
||||
}
|
||||
#else
|
||||
int wrote;
|
||||
wrote = ::write(fd, data, max_size);
|
||||
if (wait) tcdrain(fd);
|
||||
#endif
|
||||
return (int)wrote;
|
||||
//piCout << "[PISerial] Error while sending" << endl;
|
||||
//piCout << "[PISerial] Error while sending" << endl;
|
||||
//piCout << "[PISerial] Wrote " << wrote << " bytes in " << path_ << endl;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user