311 lines
10 KiB
C++
311 lines
10 KiB
C++
/*! \file piserial.h
|
|
* \brief Serial device
|
|
*/
|
|
/*
|
|
PIP - Platform Independent Primitives
|
|
COM
|
|
Copyright (C) 2014 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
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef PISERIAL_H
|
|
#define PISERIAL_H
|
|
|
|
#include "pitimer.h"
|
|
#include "piiodevice.h"
|
|
#ifndef WINDOWS
|
|
# include <termios.h>
|
|
# include <fcntl.h>
|
|
# include <sys/ioctl.h>
|
|
# ifndef B50
|
|
# define B50 0000001
|
|
# endif
|
|
# ifndef B75
|
|
# define B75 0000002
|
|
# endif
|
|
# ifndef B1500000
|
|
# define B1500000 0010012
|
|
# endif
|
|
# ifndef B2000000
|
|
# define B2000000 0010013
|
|
# endif
|
|
# ifndef B2500000
|
|
# define B2500000 0010014
|
|
# endif
|
|
# ifndef B3000000
|
|
# define B3000000 0010015
|
|
# endif
|
|
# ifndef B3500000
|
|
# define B3500000 0010016
|
|
# endif
|
|
# ifndef B4000000
|
|
# define B4000000 0010017
|
|
# endif
|
|
#else
|
|
# define TIOCM_LE 1
|
|
# define TIOCM_DTR 4
|
|
# define TIOCM_RTS 7
|
|
# define TIOCM_CTS 8
|
|
# define TIOCM_ST 3
|
|
# define TIOCM_SR 2
|
|
# define TIOCM_CAR 1
|
|
# define TIOCM_RNG 9
|
|
# define TIOCM_DSR 6
|
|
# define B50 50
|
|
# define B75 75
|
|
# define B110 110
|
|
# define B300 300
|
|
# define B600 600
|
|
# define B1200 1200
|
|
# define B2400 2400
|
|
# define B4800 4800
|
|
# define B9600 9600
|
|
# define B14400 14400
|
|
# define B19200 19200
|
|
# define B38400 38400
|
|
# define B57600 57600
|
|
# define B115200 115200
|
|
# define B128000 128000
|
|
# define B256000 256000
|
|
# define B1500000 1500000
|
|
# define B2000000 2000000
|
|
# define B2500000 2500000
|
|
# define B3000000 3000000
|
|
# define B3500000 3500000
|
|
# define B4000000 4000000
|
|
#endif
|
|
#ifndef CRTSCTS
|
|
# define CRTSCTS 020000000000
|
|
#endif
|
|
|
|
|
|
class PIP_EXPORT PISerial: public PIIODevice
|
|
{
|
|
PIIODEVICE(PISerial)
|
|
public:
|
|
|
|
//! Contructs an empty %PISerial
|
|
PISerial();
|
|
|
|
//! \brief Parameters of PISerial
|
|
enum Parameters {
|
|
ParityControl /*! Enable parity check and generate */ = 0x1,
|
|
ParityOdd /*! Parity is odd instead of even */ = 0x2,
|
|
TwoStopBits /*! Two stop bits instead of one */ = 0x4
|
|
};
|
|
|
|
//! \brief Speed of PISerial
|
|
enum Speed {
|
|
S50 /*! 50 baud */ = 50,
|
|
S75 /*! 75 baud */ = 75,
|
|
S110 /*! 110 baud */ = 110,
|
|
S300 /*! 300 baud */ = 300,
|
|
S600 /*! 600 baud */ = 600,
|
|
S1200 /*! 1200 baud */ = 1200,
|
|
S2400 /*! 2400 baud */ = 2400,
|
|
S4800 /*! 4800 baud */ = 4800,
|
|
S9600 /*! 9600 baud */ = 9600,
|
|
S19200 /*! 19200 baud */ = 19200,
|
|
S38400 /*! 38400 baud */ = 38400,
|
|
S57600 /*! 57600 baud */ = 57600,
|
|
S115200 /*! 115200 baud */ = 115200,
|
|
S1500000 = 1500000, // Linux only
|
|
S2000000 = 2000000, // Linux only
|
|
S2500000 = 2500000, // Linux only
|
|
S3000000 = 3000000, // Linux only
|
|
S3500000 = 3500000, // Linux only
|
|
S4000000 = 4000000 // Linux only
|
|
};
|
|
|
|
//! Contructs %PISerial with device name "device", speed "speed" and parameters "params"
|
|
PISerial(const PIString & device, PISerial::Speed speed = S115200, PIFlags<PISerial::Parameters> params = 0);
|
|
|
|
~PISerial();
|
|
|
|
|
|
//! Set both input and output speed to "speed"
|
|
void setSpeed(PISerial::Speed speed) {setProperty("outSpeed", (int)speed); setProperty("inSpeed", (int)speed); applySettings();}
|
|
|
|
//! Set output speed to "speed"
|
|
void setOutSpeed(PISerial::Speed speed) {setProperty("outSpeed", (int)speed); applySettings();}
|
|
|
|
//! Set input speed to "speed"
|
|
void setInSpeed(PISerial::Speed speed) {setProperty("inSpeed", (int)speed); applySettings();}
|
|
|
|
//! Set device name to "dev"
|
|
void setDevice(const PIString & dev) {setPath(dev); if (isOpened()) {close(); open();};}
|
|
|
|
|
|
//! Set parameters to "parameters_"
|
|
void setParameters(PIFlags<PISerial::Parameters> parameters_) {setProperty("parameters", (int)parameters_); applySettings();}
|
|
|
|
//! Set parameter "parameter" to "on" state
|
|
void setParameter(PISerial::Parameters parameter, bool on = true);
|
|
|
|
//! Returns if parameter "parameter" is set
|
|
bool isParameterSet(PISerial::Parameters parameter) const;
|
|
|
|
//! Returns parameters
|
|
PIFlags<PISerial::Parameters> parameters() const {return (PIFlags<Parameters>)(property("parameters").toInt());}
|
|
|
|
|
|
//! Set data bits count. Valid range is from 5 to 8, befault is 8
|
|
void setDataBitsCount(int bits) {setProperty("dataBitsCount", bits); applySettings();}
|
|
|
|
//! Returns data bits count
|
|
int dataBitsCount() const {return property("dataBitsCount").toInt();}
|
|
|
|
|
|
//! Set pin number "number" to logic level "on". Valid numbers are 4 (DTR) and 7 (RTS)
|
|
bool setPin(int number, bool on);
|
|
|
|
//! Returns pin number "number" logic level. Valid numbers range is from 1 to 9
|
|
bool isPin(int number) const;
|
|
|
|
bool setLE(bool on) {return setBit(TIOCM_LE, on, "LE");} // useless function, just formally
|
|
bool setDTR(bool on) {return setBit(TIOCM_DTR, on, "DTR");}
|
|
bool setRTS(bool on) {return setBit(TIOCM_RTS, on, "RTS");}
|
|
bool setCTS(bool on) {return setBit(TIOCM_CTS, on, "CTS");} // useless function, just formally
|
|
bool setST(bool on) {return setBit(TIOCM_ST, on, "ST");} // useless function, just formally
|
|
bool setSR(bool on) {return setBit(TIOCM_SR, on, "SR");} // useless function, just formally
|
|
bool setCAR(bool on) {return setBit(TIOCM_CAR, on, "CAR");} // useless function, just formally
|
|
bool setRNG(bool on) {return setBit(TIOCM_RNG, on, "RNG");} // useless function, just formally
|
|
bool setDSR(bool on) {return setBit(TIOCM_DSR, on, "DSR");} // useless function, just formally
|
|
|
|
bool isLE() const {return isBit(TIOCM_LE, "LE");}
|
|
bool isDTR() const {return isBit(TIOCM_DTR, "DTR");}
|
|
bool isRTS() const {return isBit(TIOCM_RTS, "RTS");}
|
|
bool isCTS() const {return isBit(TIOCM_CTS, "CTS");}
|
|
bool isST() const {return isBit(TIOCM_ST, "ST");}
|
|
bool isSR() const {return isBit(TIOCM_SR, "SR");}
|
|
bool isCAR() const {return isBit(TIOCM_CAR, "CAR");}
|
|
bool isRNG() const {return isBit(TIOCM_RNG, "RNG");}
|
|
bool isDSR() const {return isBit(TIOCM_DSR, "DSR");}
|
|
|
|
void setVTime(int t) {vtime = t; applySettings();}
|
|
|
|
|
|
//! Set read is blocking for function read(void * read_to, int max_size)
|
|
void setReadIsBlocking(bool yes);
|
|
|
|
|
|
//! Returns device name
|
|
PIString device() const {return path();}
|
|
|
|
//! Returns output speed
|
|
PISerial::Speed outSpeed() const {return (PISerial::Speed)(property("outSpeed").toInt());}
|
|
|
|
//! Returns input speed
|
|
PISerial::Speed inSpeed() const {return (PISerial::Speed)(property("inSpeed").toInt());}
|
|
|
|
int VTime() const {return vtime;}
|
|
|
|
|
|
//! Discard all buffered input and output data
|
|
void flush() {
|
|
#ifndef WINDOWS
|
|
if (fd != -1) tcflush(fd, TCIOFLUSH);
|
|
#endif
|
|
}
|
|
|
|
int read(void * read_to, int max_size);
|
|
bool read(void * read_to, int max_size, double timeout_ms);
|
|
PIString read(int size = -1, double timeout_ms = 1000.);
|
|
PIByteArray readData(int size = -1, double timeout_ms = 1000.);
|
|
|
|
|
|
//! \brief Write to device data "data" with maximum size "max_size" and wait for data written if "wait" is \b true.
|
|
//! \returns sended bytes count
|
|
int write(const void * data, int max_size, bool wait = false);
|
|
|
|
//! \brief Write to device data "data" with maximum size "size" and wait for data written if "wait" is \b true.
|
|
//! \returns \b true if sended bytes count = "size"
|
|
bool send(const void * data, int size, bool wait = false) {return (write(data, size, wait) == size);}
|
|
|
|
//! \brief Write to device string "data" and wait for data written if "wait" is \b true.
|
|
//! \returns \b true if sended bytes count = size of string
|
|
bool send(const PIString & data, bool wait = false) {return (write(data.data(), data.lengthAscii(), wait) == data.size_s());}
|
|
|
|
//! \brief Write to device byte array "data" and wait for data written if "wait" is \b true.
|
|
//! \returns \b true if sended bytes count = size of string
|
|
bool send(const PIByteArray & data, bool wait = false) {return (write(data.data(), data.size_s(), wait) == data.size_s());}
|
|
|
|
PIString constructFullPath() const;
|
|
|
|
|
|
//! \brief Returns all available speeds for serial devices
|
|
static PIVector<int> availableSpeeds();
|
|
|
|
//! \brief Returns all available system devices. If "test" each device will be tried to open
|
|
static PIStringList availableDevices(bool test = false);
|
|
|
|
//! \ioparams
|
|
//! \{
|
|
#ifdef DOXYGEN
|
|
//! \brief device, default ""
|
|
string device;
|
|
|
|
//! \brief input/output speed, default 115200
|
|
int speed;
|
|
|
|
//! \brief dataBitsCount, default 8
|
|
int dataBitsCount;
|
|
|
|
//! \brief parityControl, default false
|
|
bool parityControl;
|
|
|
|
//! \brief parityOdd, default false
|
|
bool parityOdd;
|
|
|
|
//! \brief twoStopBits, default false
|
|
bool twoStopBits;
|
|
#endif
|
|
//! \}
|
|
|
|
protected:
|
|
PIString fullPathPrefix() const {return "ser";}
|
|
void configureFromFullPath(const PIString & full_path);
|
|
bool configureDevice(const void * e_main, const void * e_parent = 0);
|
|
int write(const void * data, int max_size) {return write(data, max_size, true);}
|
|
|
|
//! Executes when any read function was successful. Default implementation does nothing
|
|
virtual void received(const void * data, int size) {;}
|
|
|
|
void _init();
|
|
void applySettings();
|
|
int convertSpeed(PISerial::Speed speed);
|
|
bool setBit(int bit, bool on, const PIString & bname);
|
|
bool isBit(int bit, const PIString & bname) const;
|
|
|
|
bool openDevice();
|
|
bool closeDevice();
|
|
|
|
#ifdef WINDOWS
|
|
DCB desc, sdesc;
|
|
void * hCom;
|
|
DWORD readed, mask;
|
|
bool block_write;
|
|
#else
|
|
termios desc, sdesc;
|
|
uint readed;
|
|
#endif
|
|
int fd, vtime;
|
|
bool block_read;
|
|
PITimer timer;
|
|
|
|
};
|
|
|
|
#endif // PISERIAL_H
|