aboutsummaryrefslogtreecommitdiff
path: root/SerialPort
diff options
context:
space:
mode:
Diffstat (limited to 'SerialPort')
-rwxr-xr-xSerialPort/CMakeLists.txt19
-rwxr-xr-xSerialPort/SerialPort.cpp157
-rwxr-xr-xSerialPort/SerialPort.hpp37
-rwxr-xr-xSerialPort/SerialPortFactory.cpp21
-rwxr-xr-xSerialPort/SerialPortFactory.hpp13
-rwxr-xr-xSerialPort/SerialPortUnix.cpp285
-rwxr-xr-xSerialPort/SerialPortUnix.hpp35
-rwxr-xr-xSerialPort/SerialPortWin32.cpp238
-rwxr-xr-xSerialPort/SerialPortWin32.hpp49
9 files changed, 854 insertions, 0 deletions
diff --git a/SerialPort/CMakeLists.txt b/SerialPort/CMakeLists.txt
new file mode 100755
index 0000000..dc7aa6b
--- /dev/null
+++ b/SerialPort/CMakeLists.txt
@@ -0,0 +1,19 @@
+if (WIN32)
+ add_library (SerialPort STATIC
+ SerialPortFactory.cpp
+ SerialPort.cpp
+ SerialPortWin32.cpp
+ )
+else()
+ add_library (SerialPort STATIC
+ SerialPortFactory.cpp
+ SerialPort.cpp
+ SerialPortUnix.cpp
+ )
+endif()
+
+set_target_properties (SerialPort PROPERTIES
+ CXX_STANDARD 11
+ CXX_STANDARD_REQUIRED ON
+ CXX_EXTENSIONS OFF
+)
diff --git a/SerialPort/SerialPort.cpp b/SerialPort/SerialPort.cpp
new file mode 100755
index 0000000..93e9d20
--- /dev/null
+++ b/SerialPort/SerialPort.cpp
@@ -0,0 +1,157 @@
+#include "SerialPort.hpp"
+#include "Logger.hpp"
+#include "ExitException.hpp"
+#include "ExitCodes.hpp"
+#include <cstring>
+#include <sstream>
+
+using std::ostringstream;
+
+#define READ_DEFAULT_TIMEOUT 3000 // ms
+
+void
+CSerialPort::writeWord(uint16_t w)
+{
+ uint8_t b;
+
+ b = (w & 0xff);
+ this->write(&b, 1, 1);
+
+ b = (w & 0xff00) >> 8;
+ this->write(&b, 1, 1);
+}
+
+uint16_t
+CSerialPort::readWord()
+{
+ uint8_t b;
+ uint16_t w;
+
+ w = 0;
+
+ this->read(&b, 1);
+ w |= ((uint16_t) b);
+
+ this->read(&b, 1);
+ w |= ((uint16_t) b) << 8;
+
+ return w;
+}
+
+uint32_t
+CSerialPort::readDoubleWord()
+{
+ uint8_t b;
+ uint32_t dw;
+
+ dw = 0;
+
+ this->read(&b, 1);
+ dw |= ((uint32_t) b);
+
+ this->read(&b, 1);
+ dw |= ((uint32_t) b) << 8;
+
+ this->read(&b, 1);
+ dw |= ((uint32_t) b) << 16;
+
+ this->read(&b, 1);
+ dw |= ((uint32_t) b) << 24;
+
+ return dw;
+}
+
+void
+CSerialPort::setReadTimeout(int timetout)
+{
+ mReadTimeoutMs = timetout;
+}
+
+void
+CSerialPort::setDefaultTimeout()
+{
+ mReadTimeoutMs = READ_DEFAULT_TIMEOUT;
+}
+
+void
+CSerialPort::write(uint8_t *data, int data_length, int padd_to)
+{
+ // Write data
+ for (int i = 0; i < data_length; )
+ i += writeSingle(data, data_length);
+ // Write pad
+ // TODO: odkial brat hodnotu pad byte??
+ uint8_t p[512];
+ memset(p, 0xFF, 512);
+
+ for (padd_to -= data_length; padd_to > 0; ) {
+ int w = 512;
+ if (padd_to < 512)
+ w = padd_to;
+ padd_to -= writeSingle(p, w);
+ }
+}
+
+void
+CSerialPort::read(uint8_t *data, int data_length)
+{
+ for (int i = 0; i < data_length; ) {
+ int old_i = i;
+ i += readSingle(data + i, data_length - i);
+ // TODO: pre Win32, pretoze tam nedetekujeme timeout a moze vracat 0 bajtov precitanych
+ if (i == old_i) {
+ CLogger::error("Timeout occured while reading data from serial port", EXIT_SERIAL_PORT);
+ }
+ }
+}
+
+void
+CSerialPort::sendSafeByte(uint8_t b)
+{
+ uint8_t r;
+
+ this->write(&b, 1, 1);
+ this->read(&r, 1);
+ if (r != b) {
+ ostringstream os;
+ os << "Bad echo when sending byte safely, expected " << CLogger::decToHex(b);
+ os << " received " << CLogger::decToHex(r);
+ CLogger::error(os.str(), EXIT_SERIAL_PORT);
+ }
+ this->write(&b, 1, 1);
+ this->read(&r, 1);
+ if (r != 0x00) {
+ ostringstream os;
+ os << "Cannot send byte safely, expected 0x00 received " << CLogger::decToHex(r);
+ CLogger::error(os.str(), EXIT_SERIAL_PORT);
+ }
+}
+
+void
+CSerialPort::sendSafeWord(uint16_t w)
+{
+ this->writeWord(w);
+ uint16_t r = this->readWord();
+ if (r != w) {
+ ostringstream os;
+ os << "Bad echo when sending word safely, expected " << CLogger::decToHex(w);
+ os << " received " << CLogger::decToHex(r);
+ CLogger::error(os.str(), EXIT_SERIAL_PORT);
+ }
+ this->writeWord(w);
+ r = this->readWord();
+ if (r != 0x00) {
+ ostringstream os;
+ os << "Cannot send word safely, expected 0x0000 received " << CLogger::decToHex(r);
+ CLogger::error(os.str(), EXIT_SERIAL_PORT);
+ }
+}
+
+void
+CSerialPort::sendSafeDoubleWord(uint32_t w)
+{
+ // Send low word
+ sendSafeWord(w & 0x0000FFFF);
+ // Send high word
+ sendSafeWord((w & 0xFFFF0000) >> 16);
+}
diff --git a/SerialPort/SerialPort.hpp b/SerialPort/SerialPort.hpp
new file mode 100755
index 0000000..90bb87f
--- /dev/null
+++ b/SerialPort/SerialPort.hpp
@@ -0,0 +1,37 @@
+#ifndef SERIAL_PORT_H
+#define SERIAL_PORT_H 1
+
+#include <iostream>
+#include <cstdint>
+
+using std::string;
+
+class CSerialPort {
+protected:
+ int mReadTimeoutMs; // Miliseconds
+
+ virtual ssize_t readSingle(uint8_t *data, int data_length) = 0;
+ virtual ssize_t writeSingle(uint8_t *data, int data_length) = 0;
+public:
+ virtual ~CSerialPort() { ; };
+
+ virtual void open(string portName, string speed) = 0;
+ virtual string getSpeeds(string portName) = 0;
+
+ virtual void close() = 0;
+
+ void setReadTimeout(int ms);
+ void setDefaultTimeout();
+
+ void writeWord(uint16_t w);
+ uint16_t readWord();
+ uint32_t readDoubleWord();
+ void read(uint8_t *data, int data_length);
+ void write(uint8_t *data, int data_length, int padd);
+ void sendSafeByte(uint8_t b);
+ void sendSafeWord(uint16_t w);
+ void sendSafeDoubleWord(uint32_t w);
+
+};
+
+#endif
diff --git a/SerialPort/SerialPortFactory.cpp b/SerialPort/SerialPortFactory.cpp
new file mode 100755
index 0000000..a7e8e9f
--- /dev/null
+++ b/SerialPort/SerialPortFactory.cpp
@@ -0,0 +1,21 @@
+#include "SerialPortFactory.hpp"
+
+#ifdef WIN32
+#include "SerialPortWin32.hpp"
+#else
+#include "SerialPortUnix.hpp"
+#endif
+
+std::unique_ptr<CSerialPort>
+CSerialPortFactory::getSerialPort()
+{
+ std::unique_ptr<CSerialPort> sp;
+
+#ifdef WIN32
+ sp.reset(new CSerialPortWin32());
+#else
+ sp.reset(new CSerialPortUnix());
+#endif
+
+ return sp;
+}
diff --git a/SerialPort/SerialPortFactory.hpp b/SerialPort/SerialPortFactory.hpp
new file mode 100755
index 0000000..7cecc8c
--- /dev/null
+++ b/SerialPort/SerialPortFactory.hpp
@@ -0,0 +1,13 @@
+#ifndef SERIAL_PORT_FACTORY_HPP
+#define SERIAL_PORT_FACTORY_HPP 1
+
+#include <memory>
+
+#include "SerialPort.hpp"
+
+class CSerialPortFactory {
+public:
+ std::unique_ptr<CSerialPort> getSerialPort();
+};
+
+#endif
diff --git a/SerialPort/SerialPortUnix.cpp b/SerialPort/SerialPortUnix.cpp
new file mode 100755
index 0000000..20fba2e
--- /dev/null
+++ b/SerialPort/SerialPortUnix.cpp
@@ -0,0 +1,285 @@
+#include <stdio.h>
+#include <string.h> /* String function definitions */
+#include <unistd.h> /* UNIX standard function definitions */
+#include <fcntl.h> /* File control definitions */
+#include <errno.h> /* Error number definitions */
+#include <termios.h>
+#include <sys/select.h>
+#include <errno.h>
+
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+using std::ostringstream;
+using std::endl;
+using std::setw;
+using std::right;
+
+#include "ExitCodes.hpp"
+#include "SerialPortUnix.hpp"
+#include "Logger.hpp"
+#include "ExitException.hpp"
+
+#define DEFAULT_SERIAL_SPEED "19200"
+
+CSerialPortUnix::CSerialPortUnix()
+{
+ mSerialPortFd = -1;
+ mPortName = "";
+ // Construct vector of available system baudrates
+#ifdef B50
+ mBaudrates.push_back(pair<string, speed_t>("50", B50));
+#endif
+#ifdef B75
+ mBaudrates.push_back(pair<string, speed_t>("75", B75));
+#endif
+#ifdef B110
+ mBaudrates.push_back(pair<string, speed_t>("110", B110));
+#endif
+#ifdef B134
+ mBaudrates.push_back(pair<string, speed_t>("134", B134));
+#endif
+#ifdef B150
+ mBaudrates.push_back(pair<string, speed_t>("150", B150));
+#endif
+#ifdef B200
+ mBaudrates.push_back(pair<string, speed_t>("200", B200));
+#endif
+#ifdef B300
+ mBaudrates.push_back(pair<string, speed_t>("300", B300));
+#endif
+#ifdef B600
+ mBaudrates.push_back(pair<string, speed_t>("600", B600));
+#endif
+#ifdef B1200
+ mBaudrates.push_back(pair<string, speed_t>("1200", B1200));
+#endif
+#ifdef B1800
+ mBaudrates.push_back(pair<string, speed_t>("1800", B1800));
+#endif
+#ifdef B2400
+ mBaudrates.push_back(pair<string, speed_t>("2400", B2400));
+#endif
+#ifdef B4800
+ mBaudrates.push_back(pair<string, speed_t>("4800", B4800));
+#endif
+#ifdef B9600
+ mBaudrates.push_back(pair<string, speed_t>("9600", B9600));
+#endif
+#ifdef B19200
+ mBaudrates.push_back(pair<string, speed_t>("19200", B19200));
+#endif
+#ifdef B38400
+ mBaudrates.push_back(pair<string, speed_t>("38400", B38400));
+#endif
+#ifdef B57600
+ mBaudrates.push_back(pair<string, speed_t>("57600", B57600));
+#endif
+#ifdef B115200
+ mBaudrates.push_back(pair<string, speed_t>("115200", B115200));
+#endif
+#ifdef B230400
+ mBaudrates.push_back(pair<string, speed_t>("230400", B230400));
+#endif
+}
+
+CSerialPortUnix::~CSerialPortUnix()
+{
+ ;
+}
+
+void
+CSerialPortUnix::openPort(string portName)
+{
+ if (mSerialPortFd == -1) {
+ mSerialPortFd = ::open(portName.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
+ if (mSerialPortFd == -1)
+ CLogger::error("Cannot open serial port " + portName, EXIT_SERIAL_PORT);
+ mPortName = portName;
+ }
+}
+
+void
+CSerialPortUnix::open(string portName, string speed)
+{
+ this->setDefaultTimeout();
+
+ openPort(portName);
+ // Set parameters of serial communication
+ pair<string, speed_t> s = findSpeed(speed, getDeviceSpeeds());
+ setSpeed(s);
+
+ struct termios options;
+
+ tcgetattr(mSerialPortFd, &options);
+ // Control options
+ options.c_cflag |= (CLOCAL | CREAD);
+ options.c_cflag &= ~PARENB;
+ options.c_cflag &= ~CSTOPB;
+ options.c_cflag &= ~CSIZE;
+ options.c_cflag |= CS8;
+ // Turn off hardware flow controll
+ options.c_cflag &= ~CRTSCTS;
+ // Input Options - Turn off software flow controll, and CR <-> LF mapping
+ options.c_iflag &= ~(IXON | IXOFF | IXANY | INLCR | ICRNL);
+ // Line options - Raw input
+ options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+ // Raw output
+ options.c_oflag &= ~OPOST;
+ tcsetattr(mSerialPortFd, TCSANOW, &options);
+ // Blocking read
+ fcntl(mSerialPortFd, F_SETFL, 0);
+
+ CLogger::info("Serial port " + mPortName + " opened at speed " + s.first + " Bd");
+}
+
+void
+CSerialPortUnix::close()
+{
+ // Close only valid descriptor
+ if (mSerialPortFd != -1) {
+ if (::close(mSerialPortFd) == -1)
+ CLogger::error("Cannot close serial port", EXIT_SERIAL_PORT);
+ mSerialPortFd = -1;
+ mPortName = "";
+ }
+}
+
+vector<pair<string, speed_t>>
+CSerialPortUnix::getDeviceSpeeds()
+{
+ vector<pair<string, speed_t>> ds;
+ vector<pair<string, speed_t>>::const_iterator it;
+
+ // Test which baudrates are supported by underlying device
+ for (it = mBaudrates.begin(); it != mBaudrates.end(); ++it) {
+ // Try to set the baudrate
+ struct termios options;
+
+ if (tcgetattr(mSerialPortFd, &options) != 0)
+ CLogger::error("Cannot get attributes of serial port " + mPortName, EXIT_SERIAL_PORT);
+
+ if (!cfsetispeed(&options, it->second)
+ && !cfsetospeed(&options, it->second)
+ && !tcsetattr(mSerialPortFd, TCSANOW, &options)) {
+ ds.push_back(*it);
+ }
+ }
+
+ return ds;
+}
+
+string
+CSerialPortUnix::getSpeeds(string portName)
+{
+ ostringstream os;
+ int c;
+ vector<pair<string, speed_t>> s;
+ vector<pair<string, speed_t>>::const_iterator it;
+
+ openPort(portName);
+ s = getDeviceSpeeds();
+ for (c = 0, it = s.begin(); it != s.end(); ++c, ++it)
+ os << setw(7) << right << it->first << " Bd" << endl;
+ // Close serial port
+ close();
+
+ if (c == 0)
+ CLogger::error("Serial port device does not support any baudrates", EXIT_SERIAL_PORT);
+
+ return os.str();
+}
+
+pair<string, speed_t>
+CSerialPortUnix::findSpeed(string speed, const vector<pair<string, speed_t>> & list)
+{
+ vector<pair<string, speed_t>>::const_iterator it;
+ vector<pair<string, speed_t>>::const_iterator defit;
+ bool foundDef = false;
+
+ for (it = list.begin(); it != list.end(); ++it) {
+ if (!(it->first).compare(speed))
+ return *it; // Exact match
+ else if (!(it->first).compare(DEFAULT_SERIAL_SPEED)) {
+ defit = it; // We have found default serial speed
+ foundDef = true;
+ }
+ }
+
+ if (foundDef)
+ // We have not found exact speed and default speed. Choose
+ // highest supported.
+ return *defit;
+
+ return *(it - 1);
+}
+
+void
+CSerialPortUnix::setSpeed(pair<string, speed_t> speed)
+{
+ struct termios options;
+
+ if (tcgetattr(mSerialPortFd, &options)
+ || cfsetispeed(&options, speed.second)
+ || cfsetospeed(&options, speed.second)
+ || tcsetattr(mSerialPortFd, TCSANOW, &options)) {
+ CLogger::error("Cannot set serial speed: " + speed.first + ": " + strerror(errno), EXIT_SERIAL_PORT);
+ }
+}
+
+
+ssize_t
+CSerialPortUnix::writeSingle(uint8_t *data, int data_length)
+{
+ ssize_t r = ::write(mSerialPortFd, data, data_length);
+
+ if (r <= 0) {
+ ostringstream os;
+ os << "Cannot write to serial port";
+ if (r < 0)
+ os << ": " << string(strerror(errno));
+ CLogger::error(os.str(), EXIT_SERIAL_PORT);
+ }
+
+ return r;
+}
+
+ssize_t
+CSerialPortUnix::readSingle(uint8_t *data, int data_length)
+{
+ ssize_t r = 0;
+ int s;
+ fd_set read_fds, write_fds, except_fds;
+ struct timeval timeout;
+
+ // Renew file descriptor sets
+ FD_ZERO(&read_fds);
+ FD_ZERO(&write_fds);
+ FD_ZERO(&except_fds);
+ FD_SET(mSerialPortFd, &read_fds);
+ // Set timeout
+ timeout.tv_sec = mReadTimeoutMs / 1000;
+ timeout.tv_usec = 0;
+ // Wait for event
+ s = select(mSerialPortFd + 1, &read_fds, &write_fds, &except_fds, &timeout);
+ if (s == 1) {
+ // One descriptor changed, ready to read
+ r = ::read(mSerialPortFd, data, data_length);
+ } else if (s == 0) {
+ // Timeout occured
+ CLogger::error("Timeout occured while reading data from serial port", EXIT_SERIAL_PORT);
+ }
+
+ if ((s < 0) || (r <= 0)) {
+ // Error occured in select or read
+ ostringstream os;
+ os << "Cannot read from serial port";
+ if (r < 0) {
+ os << ": " << strerror(errno);
+ CLogger::error(os.str(), EXIT_SERIAL_PORT);
+ }
+ }
+
+ return r;
+}
diff --git a/SerialPort/SerialPortUnix.hpp b/SerialPort/SerialPortUnix.hpp
new file mode 100755
index 0000000..db1ae73
--- /dev/null
+++ b/SerialPort/SerialPortUnix.hpp
@@ -0,0 +1,35 @@
+#ifndef SERIAL_PORT_UNIX_H
+#define SERIAL_PORT_UNIX_H 1
+
+#include <termios.h>
+
+#include <vector>
+#include "SerialPort.hpp"
+
+using std::vector;
+using std::pair;
+
+class CSerialPortUnix : public CSerialPort {
+private:
+ int mSerialPortFd;
+ string mPortName;
+ vector< pair<string, speed_t> > mBaudrates;
+
+ vector<pair<string, speed_t>> getDeviceSpeeds();
+ pair<string, speed_t> findSpeed(string speed, const vector<pair<string, speed_t>> & list);
+ void setSpeed(pair<string, speed_t> speed);
+ void openPort(string portName);
+
+ ssize_t readSingle(uint8_t *data, int data_length);
+ ssize_t writeSingle(uint8_t *data, int data_length);
+public:
+ CSerialPortUnix();
+ ~CSerialPortUnix();
+
+ void open(string portName, string speed);
+ string getSpeeds(string portName);
+
+ void close();
+};
+
+#endif
diff --git a/SerialPort/SerialPortWin32.cpp b/SerialPort/SerialPortWin32.cpp
new file mode 100755
index 0000000..15316d2
--- /dev/null
+++ b/SerialPort/SerialPortWin32.cpp
@@ -0,0 +1,238 @@
+#include <sstream>
+#include <cstdio>
+
+#include "ExitCodes.hpp"
+#include "SerialPortWin32.hpp"
+#include "Logger.hpp"
+
+using std::ostringstream;
+using std::istringstream;
+
+//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
+string
+CSerialPortWin32::getLastErrorAsString()
+{
+ DWORD e = GetLastError();
+ if (e == 0)
+ return string();
+
+ LPSTR msgBuff = nullptr;
+ size_t size = FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ e,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR) &msgBuff,
+ 0,
+ NULL);
+
+ string m(msgBuff, size);
+
+ LocalFree(msgBuff);
+
+ return m;
+}
+
+
+
+
+CSerialPortWin32::CSerialPortWin32()
+{
+ mSerialPortH = INVALID_HANDLE_VALUE;
+
+ mMaxBaudrates.push_back(s_speed("User defined", BAUD_USER, 0));
+ mMaxBaudrates.push_back(s_speed("75", BAUD_075, 75));
+ mMaxBaudrates.push_back(s_speed("110", BAUD_110, 110));
+ mMaxBaudrates.push_back(s_speed("134.5", BAUD_134_5, 134));
+ mMaxBaudrates.push_back(s_speed("150", BAUD_150, 150));
+ mMaxBaudrates.push_back(s_speed("300", BAUD_300, 300));
+ mMaxBaudrates.push_back(s_speed("600", BAUD_600, 600));
+ mMaxBaudrates.push_back(s_speed("1200", BAUD_1200, 1200));
+ mMaxBaudrates.push_back(s_speed("1800", BAUD_1800, 1800));
+ mMaxBaudrates.push_back(s_speed("2400", BAUD_2400, 2400));
+ mMaxBaudrates.push_back(s_speed("4800", BAUD_4800, 4800));
+ mMaxBaudrates.push_back(s_speed("7200", BAUD_7200, 7200));
+ mMaxBaudrates.push_back(s_speed("9600", BAUD_9600, 9600));
+ mMaxBaudrates.push_back(s_speed("14400", BAUD_14400, 14400));
+ mMaxBaudrates.push_back(s_speed("19200", BAUD_19200, 19200));
+ mMaxBaudrates.push_back(s_speed("38400", BAUD_38400, 38400));
+ mMaxBaudrates.push_back(s_speed("56000", BAUD_56K, 56000));
+ mMaxBaudrates.push_back(s_speed("57600", BAUD_57600, 576000));
+ mMaxBaudrates.push_back(s_speed("115200", BAUD_115200, 115200));
+ mMaxBaudrates.push_back(s_speed("128000", BAUD_128K, 128000));
+}
+
+CSerialPortWin32::~CSerialPortWin32()
+{
+ ;
+}
+
+void
+CSerialPortWin32::openPort(string portName)
+{
+ if (mSerialPortH == INVALID_HANDLE_VALUE) {
+ // Construct Windows serial port name
+ ostringstream sn;
+ sn << "\\\\.\\" << portName;
+ // Open serial port
+ mSerialPortH = CreateFile(sn.str().c_str(), // Port name
+ GENERIC_READ | GENERIC_WRITE, // Read/Write
+ 0, // No Sharing
+ NULL, // No Security
+ OPEN_EXISTING,// Open existing port only
+ 0, // Non Overlapped I/O
+ NULL); // Null for Comm Devices
+
+ if (mSerialPortH == INVALID_HANDLE_VALUE) {
+ CLogger::error("Cannot open port " + portName + ": " + getLastErrorAsString(),
+ EXIT_SERIAL_PORT);
+ }
+ }
+}
+
+void
+CSerialPortWin32::open(string portName, string speed)
+{
+ this->setDefaultTimeout();
+
+ openPort(portName);
+
+ DWORD ms = getMaxSpeed(portName).value;
+
+ // Konfiguracia
+ DCB dcbSerialParams = { 0 };
+ dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
+
+ if (GetCommState(mSerialPortH, &dcbSerialParams) == 0) {
+ CLogger::error("Cannot get state for port " + portName + ": " + getLastErrorAsString(),
+ EXIT_SERIAL_PORT);
+ }
+ // Set speed
+ istringstream is(speed);
+ DWORD n;
+ is >> n;
+ if (n == 0) {
+ // User has requested default baudrate
+ n = ((ms == 0) || (19200 <= ms)) ? 19200 : ms;
+ } else if ((ms != 0) && (n > ms)) {
+ ostringstream os;
+ os << "Baudrate " << n << " Bd is higher than max. baudrate " << ms << " Bd supported by " << portName;
+ CLogger::error(os.str(), EXIT_SERIAL_PORT);
+ }
+
+ dcbSerialParams.BaudRate = n;
+ dcbSerialParams.ByteSize = 8; // Setting ByteSize = 8
+ dcbSerialParams.StopBits = ONESTOPBIT;// Setting StopBits = 1
+ dcbSerialParams.Parity = NOPARITY; // Setting Parity = None
+
+ if (SetCommState(mSerialPortH, &dcbSerialParams) == 0) {
+ CLogger::error("Cannot set state for port " + portName + ": " + getLastErrorAsString(),
+ EXIT_SERIAL_PORT);
+ }
+
+ ostringstream os;
+ os << n;
+ CLogger::info("Serial port " + portName + " opened at speed " + os.str() + " Bd");
+}
+
+CSerialPortWin32::s_speed
+CSerialPortWin32::getMaxSpeed(string portName)
+{
+ COMMPROP cp;
+
+ if (GetCommProperties(mSerialPortH, &cp) == 0) {
+ CLogger::error("Cannot get properties of " + portName + " port: " + getLastErrorAsString(),
+ EXIT_SERIAL_PORT);
+ }
+
+ // Convert key to baudrate value
+ list<s_speed>::const_iterator it;
+
+ for (it = mMaxBaudrates.begin(); it != mMaxBaudrates.end(); ++it) {
+ if (it->key == cp.dwMaxBaud)
+ break;
+ }
+
+ return *it;
+}
+
+string
+CSerialPortWin32::getSpeeds(string portName)
+{
+ openPort(portName);
+
+ s_speed m = getMaxSpeed(portName);
+
+ ostringstream os;
+ os << "User defined baudrate";
+ if (m.key != BAUD_USER)
+ os << " up to the " << m.name << " Bd";
+
+ close();
+ return os.str();
+}
+
+void
+CSerialPortWin32::close()
+{
+ if (mSerialPortH != INVALID_HANDLE_VALUE) {
+ if (CloseHandle(mSerialPortH) == 0) {
+ CLogger::error("Cannot close serial port: " + getLastErrorAsString(),
+ EXIT_SERIAL_PORT);
+ }
+ mSerialPortH = INVALID_HANDLE_VALUE;
+ }
+}
+
+void
+CSerialPortWin32::setTimeouts(int ms)
+{
+ COMMTIMEOUTS timeouts;
+
+ if (!GetCommTimeouts(mSerialPortH, &timeouts)) {
+ CLogger::error("Cannot get timeouts for serial port: " + getLastErrorAsString(),
+ EXIT_SERIAL_PORT);
+ }
+
+ timeouts.ReadIntervalTimeout = ms;
+ timeouts.ReadTotalTimeoutMultiplier = ms;
+ timeouts.ReadTotalTimeoutConstant = 0;
+
+ timeouts.WriteTotalTimeoutMultiplier = ms;
+ timeouts.WriteTotalTimeoutConstant = 0;
+
+ if (!SetCommTimeouts(mSerialPortH, &timeouts)) {
+ CLogger::error("Cannot set timeouts for port: " + getLastErrorAsString(),
+ EXIT_SERIAL_PORT);
+ }
+}
+
+ssize_t
+CSerialPortWin32::writeSingle(uint8_t *data, int data_length)
+{
+ DWORD written = 0;
+
+ setTimeouts(mReadTimeoutMs);
+ // TODO: Rozlisovat medzi timeoutom a chybou
+ if (!WriteFile(mSerialPortH, data, data_length, &written, NULL)) {
+ CLogger::error("Cannot write data to the serial port: " + getLastErrorAsString(),
+ EXIT_SERIAL_PORT);
+ }
+
+ return written;
+}
+
+ssize_t
+CSerialPortWin32::readSingle(uint8_t *data, int data_length)
+{
+ DWORD read;
+
+ setTimeouts(mReadTimeoutMs);
+
+ if (!ReadFile(mSerialPortH, data, data_length, &read, NULL)) {
+ CLogger::error("Cannot read data from serial port: " + getLastErrorAsString(),
+ EXIT_SERIAL_PORT);
+ }
+
+ return read;
+}
diff --git a/SerialPort/SerialPortWin32.hpp b/SerialPort/SerialPortWin32.hpp
new file mode 100755
index 0000000..2cba0f7
--- /dev/null
+++ b/SerialPort/SerialPortWin32.hpp
@@ -0,0 +1,49 @@
+#ifndef SERIAL_PORT_WIN32_H
+#define SERIAL_PORT_WIN32_H 1
+
+#include <windows.h>
+#include <list>
+#include "SerialPort.hpp"
+
+using std::pair;
+using std::list;
+
+class CSerialPortWin32 : public CSerialPort {
+private:
+ HANDLE mSerialPortH;
+
+ struct s_speed {
+ string name;
+ DWORD key;
+ DWORD value;
+
+ s_speed(string n, DWORD k, DWORD v) {
+ name = n;
+ key = k;
+ value = v;
+ }
+ };
+
+ list<struct s_speed> mMaxBaudrates;
+
+
+ void openPort(string portName);
+ s_speed getMaxSpeed(string portName);
+ void setTimeouts(int ms);
+ string getLastErrorAsString();
+
+ ssize_t readSingle(uint8_t *data, int data_length);
+ ssize_t writeSingle(uint8_t *data, int data_length);
+public:
+ CSerialPortWin32();
+ ~CSerialPortWin32();
+
+ void open(string portName, string speed);
+ string getSpeeds(string portName);
+
+ void close();
+ void write(uint8_t *data, int data_length, int padd_to);
+ void read(uint8_t *data, int data_length);
+};
+
+#endif