15.10.2012 - version 0.2.0 - PIIODevice - base of file, ethernet, serial and packets extractor. PIEthernet now support also TCP (client and server). PIConsole now can align labels in each column individually.
This commit is contained in:
177
piserial.cpp
Normal file → Executable file
177
piserial.cpp
Normal file → Executable file
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
PIP - Platform Independent Primitives
|
||||
COM
|
||||
Copyright (C) 2011 Ivan Pelipenko peri4ko@gmail.com, Bychkov Andrey wapmobil@gmail.com
|
||||
Copyright (C) 2012 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
|
||||
@@ -20,32 +20,48 @@
|
||||
#include "piserial.h"
|
||||
|
||||
|
||||
PISerial::PISerial(PIString name, void * data_, SerialFunc slot, SerialHeaderFunc slot_header): PIThread() {
|
||||
PISerial::PISerial(const PIString & device, void * data_, ReadRetFunc slot): PIIODevice(device, ReadWrite) {
|
||||
piMonitor.serials++;
|
||||
setPriority(piHigh);
|
||||
path_ = device;
|
||||
data = data_;
|
||||
devName = name;
|
||||
fd = -1;
|
||||
missed = 0;
|
||||
dataSize = headerSize = 0;
|
||||
headerPtr = 0;
|
||||
ret_func = slot;
|
||||
ret_func_header = slot_header;
|
||||
params = 0;
|
||||
vtime = 1;
|
||||
ret_func_ = slot;
|
||||
#ifdef WINDOWS
|
||||
hCom = 0;
|
||||
#endif
|
||||
ispeed = ospeed = S115200;
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
PISerial::PISerial(void * data_, ReadRetFunc slot): PIIODevice("", ReadWrite) {
|
||||
piMonitor.serials++;
|
||||
setPriority(piHigh);
|
||||
data = data_;
|
||||
fd = -1;
|
||||
headerPtr = 0;
|
||||
params = 0;
|
||||
vtime = 1;
|
||||
ret_func_ = slot;
|
||||
#ifdef WINDOWS
|
||||
hCom = 0;
|
||||
#endif
|
||||
ispeed = ospeed = S115200;
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
PISerial::~PISerial() {
|
||||
piMonitor.serials--;
|
||||
terminate();
|
||||
}
|
||||
|
||||
|
||||
void PISerial::terminate() {
|
||||
if (!initialized()) return;
|
||||
bool PISerial::closeDevice() {
|
||||
if (!isInitialized()) return true;
|
||||
if (isRunning()) {
|
||||
stop();
|
||||
PIThread::terminate();
|
||||
@@ -60,10 +76,11 @@ void PISerial::terminate() {
|
||||
#else
|
||||
if (fd != -1) {
|
||||
tcsetattr(fd, TCSANOW, &sdesc);
|
||||
close(fd);
|
||||
::close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,79 +102,51 @@ int PISerial::convertSpeed(PISerial::Speed speed) {
|
||||
}
|
||||
|
||||
|
||||
void PISerial::begin() {
|
||||
allReaded = addSize = curInd = 0;
|
||||
first = false;
|
||||
packetSize = headerSize + dataSize;
|
||||
if (headerSize > 0) mheader.resize(headerSize);
|
||||
if (!init()) stop();
|
||||
}
|
||||
|
||||
|
||||
void PISerial::run() {
|
||||
if (dataSize == 0) return;
|
||||
while (allReaded < packetSize + addSize) {
|
||||
#ifdef WINDOWS
|
||||
WaitCommEvent(hCom, 0, 0);
|
||||
ReadFile(hCom, &buffer[allReaded], SERIAL_BUFFER_SIZE, &readed, 0);
|
||||
#else
|
||||
readed = read(fd, &buffer[allReaded], SERIAL_BUFFER_SIZE);
|
||||
#endif
|
||||
allReaded += readed;
|
||||
}
|
||||
if (headerSize > 0) {
|
||||
if (allReaded + curInd >= SERIAL_BUFFER_SIZE) {
|
||||
memcpy(sbuffer, buffer, SERIAL_BUFFER_SIZE);
|
||||
memcpy(buffer, &sbuffer[SERIAL_BUFFER_SIZE - packetSize], allReaded);
|
||||
allReaded = packetSize;
|
||||
addSize = curInd = 0;
|
||||
bool PISerial::read(void * data, int size, double timeout_ms) {
|
||||
if (data == 0) return false;
|
||||
int ret, all = 0;
|
||||
if (timeout_ms > 0.) {
|
||||
setReadIsBlocking(false);
|
||||
all = ::read(fd, data, 1);
|
||||
timer.reset();
|
||||
while (all < size && timer.elapsed_m() < timeout_ms) {
|
||||
ret = ::read(fd, &((uchar * )data)[all], size - all);
|
||||
if (ret > 0) all += ret;
|
||||
else msleep(1);
|
||||
}
|
||||
while (!ret_func_header(data, (uchar * )headerPtr, &buffer[curInd], headerSize)) {
|
||||
curInd++; missed++;
|
||||
if (curInd > addSize) {
|
||||
addSize += packetSize;
|
||||
return;
|
||||
}
|
||||
}
|
||||
memcpy(mheader.data(), &buffer[curInd + headerSize], headerSize);
|
||||
if (!ret_func(data, &buffer[curInd + headerSize], dataSize)) {
|
||||
curInd++; missed++;
|
||||
return;
|
||||
}
|
||||
memcpy(sbuffer, buffer, allReaded);
|
||||
memcpy(buffer, &sbuffer[packetSize + curInd], allReaded);
|
||||
allReaded -= packetSize + curInd;
|
||||
curInd = addSize = 0;
|
||||
return (all == size);
|
||||
} else {
|
||||
ret_func(data, buffer, dataSize);
|
||||
memcpy(sbuffer, buffer, allReaded);
|
||||
memcpy(buffer, &sbuffer[packetSize], allReaded);
|
||||
allReaded -= packetSize;
|
||||
setReadIsBlocking(true);
|
||||
all = ::read(fd, data, 1);
|
||||
while (all < size) {
|
||||
ret = ::read(fd, &((uchar * )data)[all], size - all);
|
||||
if (ret > 0) all += ret;
|
||||
}
|
||||
return (all == size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void PISerial::end() {
|
||||
terminate();
|
||||
}
|
||||
|
||||
|
||||
bool PISerial::init() {
|
||||
bool PISerial::openDevice() {
|
||||
#ifdef WINDOWS
|
||||
hCom = CreateFileA(devName.stdString().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, 0);
|
||||
DWORD da = 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);
|
||||
if(hCom == INVALID_HANDLE_VALUE) {
|
||||
cout << "[PISerial] Unable to open \"" << devName << "\"" << endl;
|
||||
piCout << "[PISerial] Unable to open \"" << path_ << "\"" << endl;
|
||||
return false;
|
||||
}
|
||||
fd = 0;
|
||||
COMMTIMEOUTS times;
|
||||
times.ReadIntervalTimeout = 1;
|
||||
times.ReadIntervalTimeout = vtime;
|
||||
times.ReadTotalTimeoutConstant = 1;
|
||||
times.ReadTotalTimeoutMultiplier = 0;
|
||||
times.WriteTotalTimeoutConstant = 0;
|
||||
times.WriteTotalTimeoutMultiplier = 1;
|
||||
times.WriteTotalTimeoutConstant = 1;
|
||||
times.WriteTotalTimeoutMultiplier = 0;
|
||||
if (SetCommTimeouts(hCom, ×) == -1) {
|
||||
cout << "[PISerial] Unable to set timeouts for \"" << devName << "\"" << endl;
|
||||
piCout << "[PISerial] Unable to set timeouts for \"" << path_ << "\"" << endl;
|
||||
CloseHandle(hCom);
|
||||
fd = -1;
|
||||
return false;
|
||||
@@ -175,15 +164,22 @@ bool PISerial::init() {
|
||||
}
|
||||
desc.StopBits = params[PISerial::TwoStopBits] ? TWOSTOPBITS : ONESTOPBIT;
|
||||
if (SetCommState(hCom, &desc) == -1) {
|
||||
cout << "[PISerial] Unable to set comm state for \"" << devName << "\"" << endl;
|
||||
piCout << "[PISerial] Unable to set comm state for \"" << path_ << "\"" << endl;
|
||||
CloseHandle(hCom);
|
||||
fd = -1;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
fd = open(devName.data(), O_NOCTTY | O_RDWR);
|
||||
int om = 0;
|
||||
switch (mode_) {
|
||||
case PIIODevice::ReadOnly: om = O_RDONLY; break;
|
||||
case PIIODevice::WriteOnly: om = O_WRONLY; break;
|
||||
case PIIODevice::ReadWrite: om = O_RDWR; break;
|
||||
}
|
||||
//cout << "init ser " << path_ << " mode " << om << endl;
|
||||
fd = ::open(path_.data(), O_NOCTTY | om);
|
||||
if(fd == -1) {
|
||||
cout << "[PISerial] Unable to open \"" << devName << "\"" << endl;
|
||||
piCout << "[PISerial] Unable to open \"" << path_ << "\"" << endl;
|
||||
return false;
|
||||
}
|
||||
fcntl(fd, F_SETFL, 0);
|
||||
@@ -191,48 +187,47 @@ bool PISerial::init() {
|
||||
tcgetattr(fd, &desc);
|
||||
sdesc = desc;
|
||||
desc.c_iflag = desc.c_oflag = desc.c_lflag = 0;
|
||||
desc.c_cflag = CLOCAL | CREAD | CSIZE;
|
||||
desc.c_cflag = CLOCAL | CSIZE | CS8;
|
||||
if (isReadable()) desc.c_cflag |= CREAD;
|
||||
if (params[PISerial::TwoStopBits]) desc.c_cflag |= CSTOPB;
|
||||
if (params[PISerial::ParityControl]) {
|
||||
desc.c_iflag |= INPCK;
|
||||
desc.c_cflag |= PARENB;
|
||||
if (params[PISerial::ParityOdd]) desc.c_cflag |= PARODD;
|
||||
}
|
||||
desc.c_cc[VMIN] = 0;
|
||||
desc.c_cc[VTIME] = 1;
|
||||
desc.c_cc[VMIN] = 1;
|
||||
desc.c_cc[VTIME] = vtime;
|
||||
|
||||
cfsetispeed(&desc, convertSpeed(ispeed));
|
||||
cfsetospeed(&desc, convertSpeed(ospeed));
|
||||
|
||||
if(tcsetattr(fd, TCSANOW, &desc) < 0) {
|
||||
cout << "[PISerial] Can`t set attributes for \"" << devName << "\"" << endl;
|
||||
close(fd);
|
||||
piCout << "[PISerial] Can`t set attributes for \"" << path_ << "\"" << endl;
|
||||
::close(fd);
|
||||
return false;
|
||||
}
|
||||
tcflush(fd, TCIOFLUSH);
|
||||
//cout << "[PISerial] Initialized " << devName << endl;
|
||||
//piCout << "[PISerial] Initialized " << path_ << endl;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PISerial::send(uchar * data, int size) {
|
||||
//cout << "[PISerial] send size: " << sizeof(data) << endl;
|
||||
if (fd == -1) {
|
||||
//cout << "[PISerial] Can`t write to uninitialized COM" << endl;
|
||||
return false;
|
||||
int PISerial::write(const void * data, int max_size, bool wait) {
|
||||
//piCout << "[PISerial] send size: " << sizeof(data) << endl;
|
||||
if (fd == -1 || !canWrite()) {
|
||||
//piCout << "[PISerial] Can`t write to uninitialized COM" << endl;
|
||||
return -1;
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
DWORD wrote;
|
||||
WriteFile(hCom, data, size, &wrote, 0);
|
||||
WriteFile(hCom, data, max_size, &wrote, 0);
|
||||
#else
|
||||
int wrote;
|
||||
wrote = write(fd, data, size);
|
||||
wrote = ::write(fd, data, max_size);
|
||||
if (wait) tcdrain(fd);
|
||||
#endif
|
||||
if ((int)wrote != size) {
|
||||
//cout << "[PISerial] Error while sending" << endl;
|
||||
return false;
|
||||
}
|
||||
//cout << "[PISerial] Wrote " << wrote << " bytes in " << devName << endl;
|
||||
return true;
|
||||
return (int)wrote;
|
||||
//piCout << "[PISerial] Error while sending" << endl;
|
||||
//piCout << "[PISerial] Wrote " << wrote << " bytes in " << path_ << endl;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user