summaryrefslogtreecommitdiffstats
path: root/sw-linux/rom-loader/serial.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sw-linux/rom-loader/serial.cpp')
-rw-r--r--sw-linux/rom-loader/serial.cpp89
1 files changed, 89 insertions, 0 deletions
diff --git a/sw-linux/rom-loader/serial.cpp b/sw-linux/rom-loader/serial.cpp
new file mode 100644
index 0000000..7d25f02
--- /dev/null
+++ b/sw-linux/rom-loader/serial.cpp
@@ -0,0 +1,89 @@
+#include "serial.hpp"
+
+#include <ios>
+
+extern "C" {
+#include <fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+}
+
+serial::serial(const std::string& port, speed_t baud)
+{
+ m_fd = open(port.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
+
+ if (m_fd < 0) {
+ throw std::ios_base::failure("Failed to open serial port " + port);
+ }
+
+ tcgetattr(m_fd, &m_settings);
+
+ // set input and output baudrate
+ cfsetispeed(&m_settings, baud);
+ cfsetospeed(&m_settings, baud);
+
+ // disable parity, 1 stop bit, clear data size
+ m_settings.c_cflag &= ~(PARENB | CSTOPB | CSIZE);
+ // set data size to 8
+ m_settings.c_cflag |= CS8;
+
+ // disable hw flow control
+ m_settings.c_cflag &= ~CRTSCTS;
+ // enable receiver and ignore modem lines
+ m_settings.c_cflag |= CREAD | CLOCAL;
+
+ // disable XON / XOFF flow control
+ m_settings.c_iflag &= ~(IXON | IXOFF | IXANY);
+ // non canonical mode
+ m_settings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+
+ // no output processing
+ m_settings.c_oflag &= ~OPOST;
+
+ // input buffer of 8 bytes
+ m_settings.c_cc[VMIN] = 8;
+ // set indefinite timeout
+ m_settings.c_cc[VTIME] = 0;
+
+ if ((tcsetattr(m_fd, TCSANOW, &m_settings)) != 0)
+ throw std::ios_base::failure("Failed to set attributes");
+
+ // clean rx buffer
+ tcflush(m_fd, TCIFLUSH);
+}
+
+serial::~serial()
+{
+ if (m_fd > 0)
+ close(m_fd);
+}
+
+int serial::write(const std::string& data) const
+{
+ write(data.c_str(), data.length());
+}
+
+int serial::write(const char * const data, size_t len) const
+{
+ return ::write(m_fd, data, len);
+}
+
+char serial::read() const
+{
+ char ch;
+
+ if (::read(m_fd, &ch, 1) < 0)
+ throw std::ios_base::failure("Failed to read");
+
+ return ch;
+}
+
+std::string serial::read(size_t howmany) const
+{
+ char data[howmany] = {};
+
+ if (::read(m_fd, data, howmany) < 0)
+ throw std::ios_base::failure("Failed to read");
+
+ return std::string(data);
+}