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:
peri4
2013-03-18 12:07:44 +04:00
parent cfc5eed75e
commit 66c53a27fc
72 changed files with 4407 additions and 960 deletions

190
piserial.cpp Executable file → Normal file
View 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;
}