Commit 0528cdd1398fae482c270c2baf065d0a809fe78c

Authored by Geoffrey Hunter
2 parents 7ceed20b 18eb9073

Merge branch 'develop'

.gitignore
@@ -4,4 +4,7 @@ cmake-build-debug/ @@ -4,4 +4,7 @@ cmake-build-debug/
4 .vscode/ 4 .vscode/
5 5
6 # Sphinx build dir 6 # Sphinx build dir
7 -docs/_build/  
8 \ No newline at end of file 7 \ No newline at end of file
  8 +docs/_build/
  9 +
  10 +# Build artifacts
  11 +a.out
9 \ No newline at end of file 12 \ No newline at end of file
.vscode/c_cpp_properties.json
@@ -60,7 +60,8 @@ @@ -60,7 +60,8 @@
60 }, 60 },
61 "compilerPath": "/usr/bin/gcc", 61 "compilerPath": "/usr/bin/gcc",
62 "cStandard": "c11", 62 "cStandard": "c11",
63 - "cppStandard": "c++17" 63 + "cppStandard": "c++17",
  64 + "configurationProvider": "ms-vscode.cmake-tools"
64 }, 65 },
65 { 66 {
66 "name": "Win32", 67 "name": "Win32",
CHANGELOG.md
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
7 7
8 ## [Unreleased] 8 ## [Unreleased]
9 9
  10 +## [v2.1.0] - 2020-11-08
  11 +
  12 +### Added
  13 +- Support for custom baud rates.
  14 +- Support for all standard UNIX baud rates.
  15 +- Improved Doxygen documentation.
  16 +- Improved README.md documentation.
  17 +
  18 +### Removed
  19 +- Dependencies from the README, they weren't that useful and were not accurate anyway.
  20 +
10 ## [v2.0.3] - 2020-10-13 21 ## [v2.0.3] - 2020-10-13
11 22
12 ### Added 23 ### Added
README.md
1 # CppLinuxSerial 1 # CppLinuxSerial
2 2
3 -Serial port library written in C++ 3 +Linux serial port library written in C++.
4 4
5 [![Build Status](https://travis-ci.org/gbmhunter/CppLinuxSerial.svg?branch=master)](https://travis-ci.org/gbmhunter/CppLinuxSerial) 5 [![Build Status](https://travis-ci.org/gbmhunter/CppLinuxSerial.svg?branch=master)](https://travis-ci.org/gbmhunter/CppLinuxSerial)
6 6
@@ -8,7 +8,9 @@ Serial port library written in C++ @@ -8,7 +8,9 @@ Serial port library written in C++
8 8
9 Library for communicating with COM ports on a Linux system. 9 Library for communicating with COM ports on a Linux system.
10 10
11 -Uses fstream to the file I/O. 11 +* Simple API
  12 +* Supports custom baud rates
  13 +* cmake based build system
12 14
13 ## Installation 15 ## Installation
14 16
@@ -66,18 +68,20 @@ using namespace mn::CppLinuxSerial; @@ -66,18 +68,20 @@ using namespace mn::CppLinuxSerial;
66 68
67 int main() { 69 int main() {
68 // Create serial port object and open serial port 70 // Create serial port object and open serial port
69 - SerialPort serialPort0("/dev/ttyUSB0", BaudRate::B_57600);  
70 - serialPort0.Open(); 71 + SerialPort serialPort("/dev/ttyUSB0", BaudRate::B_57600);
  72 + // Use SerialPort serialPort("/dev/ttyACM0", 13000); instead if you want to provide a custom baud rate
  73 + serialPort.SetTimeout(-1); // Block when reading until any data is received
  74 + serialPort.Open();
71 75
72 // Write some ASCII datae 76 // Write some ASCII datae
73 - serialPort0.Write("Hello"); 77 + serialPort.Write("Hello");
74 78
75 - // Read some data back 79 + // Read some data back (will block until at least 1 byte is received due to the SetTimeout(-1) call above)
76 std::string readData; 80 std::string readData;
77 - serialPort0.Read(readData); 81 + serialPort.Read(readData);
78 82
79 // Close the serial port 83 // Close the serial port
80 - serialPort0.Close(); 84 + serialPort.Close();
81 } 85 }
82 ``` 86 ```
83 87
@@ -87,34 +91,7 @@ If the above code was in a file called `main.cpp` and you had installed `CppLinu @@ -87,34 +91,7 @@ If the above code was in a file called `main.cpp` and you had installed `CppLinu
87 g++ main.cpp -lCppLinuxSerial 91 g++ main.cpp -lCppLinuxSerial
88 ``` 92 ```
89 93
90 -For more examples, see the `.cpp` files in `test/unit/`.  
91 -  
92 -## Dependencies  
93 -  
94 -The following table lists all of the libraries dependencies.  
95 -  
96 -<table>  
97 - <thead>  
98 - <tr>  
99 - <td>Dependency</td>  
100 - <td>Comments</td>  
101 - </tr>  
102 - </thead>  
103 - <tbody>  
104 - <tr>  
105 - <td>C++14</td>  
106 - <td>C++14 used for strongly typed enums, `std::chrono` and literals.</td>  
107 - </tr>  
108 - <tr>  
109 - <td>stdio.h</td>  
110 - <td>snprintf()</td>  
111 - </tr>  
112 - <tr>  
113 - <td>stty</td>  
114 - <td>Used in unit tests to verify the serial port is configured correctly.</td>  
115 - </tr>  
116 - </tbody>  
117 -</table> 94 +For more examples, see the files in `test/`.
118 95
119 ## Issues 96 ## Issues
120 97
@@ -122,7 +99,7 @@ See GitHub Issues. @@ -122,7 +99,7 @@ See GitHub Issues.
122 99
123 ## FAQ 100 ## FAQ
124 101
125 -1. My code stalls when calling functions like `SerialPort::Read()`. This is probably because the library is set up to do a blocking read, and not enough characters have been received to allow `SerialPort::Read()` to return. Use `SerialPort::SetNumCharsToWait()` to determine how many characters to wait for before returning (set to 0 for non-blocking mode). 102 +1. My code stalls when calling functions like `SerialPort::Read()`. This is probably because the library is set up to do a blocking read, and not enough characters have been received to allow `SerialPort::Read()` to return. Call `SerialPort::SetTimeout(0)` before the serial port is open to set a non-blocking mode.
126 103
127 ## Changelog 104 ## Changelog
128 105
include/CppLinuxSerial/SerialPort.hpp
@@ -15,8 +15,11 @@ @@ -15,8 +15,11 @@
15 #include <string> 15 #include <string>
16 #include <fstream> // For file I/O (reading/writing to COM port) 16 #include <fstream> // For file I/O (reading/writing to COM port)
17 #include <sstream> 17 #include <sstream>
18 -#include <termios.h> // POSIX terminal control definitions (struct termios) 18 +// #include <termios.h> // POSIX terminal control definitions (struct termios)
  19 +// #include <asm/termios.h> // Terminal control definitions (struct termios)
19 #include <vector> 20 #include <vector>
  21 +#include <asm/ioctls.h>
  22 +#include <asm/termbits.h>
20 23
21 // User headers 24 // User headers
22 #include "Exception.hpp" 25 #include "Exception.hpp"
@@ -24,18 +27,44 @@ @@ -24,18 +27,44 @@
24 namespace mn { 27 namespace mn {
25 namespace CppLinuxSerial { 28 namespace CppLinuxSerial {
26 29
  30 + /// \brief Represents the baud rate "types" that can be used with the serial port. STANDARD represents all
  31 + /// the standard baud rates as provided by UNIX, CUSTOM represents a baud rate defined by an arbitray integer.
  32 + enum class BaudRateType {
  33 + STANDARD,
  34 + CUSTOM,
  35 + };
  36 +
27 /// \brief Strongly-typed enumeration of baud rates for use with the SerialPort class 37 /// \brief Strongly-typed enumeration of baud rates for use with the SerialPort class
  38 + /// \details Specifies all the same baud rates as UNIX, as well as B_CUSTOM to specify your
  39 + /// own. See https://linux.die.net/man/3/cfsetispeed for list of supported UNIX baud rates.
28 enum class BaudRate { 40 enum class BaudRate {
  41 + B_0,
  42 + B_50,
  43 + B_75,
  44 + B_110,
  45 + B_134,
  46 + B_150,
  47 + B_200,
  48 + B_300,
  49 + B_600,
  50 + B_1200,
  51 + B_1800,
  52 + B_2400,
  53 + B_4800,
29 B_9600, 54 B_9600,
  55 + B_19200,
30 B_38400, 56 B_38400,
31 B_57600, 57 B_57600,
32 B_115200, 58 B_115200,
33 - CUSTOM 59 + B_230400,
  60 + B_460800,
  61 + B_CUSTOM, // Placeholder
34 }; 62 };
35 63
  64 + /// \brief Represents the state of the serial port.
36 enum class State { 65 enum class State {
37 CLOSED, 66 CLOSED,
38 - OPEN 67 + OPEN,
39 }; 68 };
40 69
41 /// \brief SerialPort object is used to perform rx/tx serial communication. 70 /// \brief SerialPort object is used to perform rx/tx serial communication.
@@ -48,15 +77,22 @@ namespace mn { @@ -48,15 +77,22 @@ namespace mn {
48 /// \brief Constructor that sets up serial port with the basic (required) parameters. 77 /// \brief Constructor that sets up serial port with the basic (required) parameters.
49 SerialPort(const std::string &device, BaudRate baudRate); 78 SerialPort(const std::string &device, BaudRate baudRate);
50 79
51 - //! @brief Destructor. Closes serial port if still open. 80 + /// \brief Constructor that sets up serial port with the basic (required) parameters.
  81 + SerialPort(const std::string &device, speed_t baudRate);
  82 +
  83 + /// \brief Destructor. Closes serial port if still open.
52 virtual ~SerialPort(); 84 virtual ~SerialPort();
53 85
54 /// \brief Sets the device to use for serial port communications. 86 /// \brief Sets the device to use for serial port communications.
55 /// \details Method can be called when serial port is in any state. 87 /// \details Method can be called when serial port is in any state.
56 void SetDevice(const std::string &device); 88 void SetDevice(const std::string &device);
57 89
  90 + /// \brief Allows the user to set a standard baud rate.
58 void SetBaudRate(BaudRate baudRate); 91 void SetBaudRate(BaudRate baudRate);
59 92
  93 + /// \brief Allows the user to set a custom baud rate.
  94 + void SetBaudRate(speed_t baudRate);
  95 +
60 /// \brief Sets the read timeout (in milliseconds)/blocking mode. 96 /// \brief Sets the read timeout (in milliseconds)/blocking mode.
61 /// \details Only call when state != OPEN. This method manupulates VMIN and VTIME. 97 /// \details Only call when state != OPEN. This method manupulates VMIN and VTIME.
62 /// \param timeout_ms Set to -1 to infinite timeout, 0 to return immediately with any data (non 98 /// \param timeout_ms Set to -1 to infinite timeout, 0 to return immediately with any data (non
@@ -92,13 +128,19 @@ namespace mn { @@ -92,13 +128,19 @@ namespace mn {
92 private: 128 private:
93 129
94 /// \brief Returns a populated termios structure for the passed in file descriptor. 130 /// \brief Returns a populated termios structure for the passed in file descriptor.
95 - termios GetTermios(); 131 + // termios GetTermios();
96 132
97 /// \brief Configures the tty device as a serial port. 133 /// \brief Configures the tty device as a serial port.
98 /// \warning Device must be open (valid file descriptor) when this is called. 134 /// \warning Device must be open (valid file descriptor) when this is called.
99 void ConfigureTermios(); 135 void ConfigureTermios();
100 136
101 - void SetTermios(termios myTermios); 137 + // void SetTermios(termios myTermios);
  138 +
  139 + /// \brief Returns a populated termios2 structure for the serial port pointed to by the file descriptor.
  140 + termios2 GetTermios2();
  141 +
  142 + /// \brief Assigns the provided tty settings to the serial port pointed to by the file descriptor.
  143 + void SetTermios2(termios2 tty);
102 144
103 /// \brief Keeps track of the serial port's state. 145 /// \brief Keeps track of the serial port's state.
104 State state_; 146 State state_;
@@ -106,8 +148,14 @@ namespace mn { @@ -106,8 +148,14 @@ namespace mn {
106 /// \brief The file path to the serial port device (e.g. "/dev/ttyUSB0"). 148 /// \brief The file path to the serial port device (e.g. "/dev/ttyUSB0").
107 std::string device_; 149 std::string device_;
108 150
109 - /// \brief The current baud rate.  
110 - BaudRate baudRate_; 151 + /// \brief The type of baud rate that the user has specified.
  152 + BaudRateType baudRateType_;
  153 +
  154 + /// \brief The current baud rate if baudRateType_ == STANDARD.
  155 + BaudRate baudRateStandard_;
  156 +
  157 + /// \brief The current baud rate if baudRateType_ == CUSTOM.
  158 + speed_t baudRateCustom_;
111 159
112 /// \brief The file descriptor for the open file. This gets written to when Open() is called. 160 /// \brief The file descriptor for the open file. This gets written to when Open() is called.
113 int fileDesc_; 161 int fileDesc_;
src/SerialPort.cpp
@@ -15,20 +15,28 @@ @@ -15,20 +15,28 @@
15 #include <unistd.h> // UNIX standard function definitions 15 #include <unistd.h> // UNIX standard function definitions
16 #include <fcntl.h> // File control definitions 16 #include <fcntl.h> // File control definitions
17 #include <errno.h> // Error number definitions 17 #include <errno.h> // Error number definitions
18 -#include <termios.h> // POSIX terminal control definitions (struct termios) 18 +// #include <termios.h> // POSIX terminal control definitions (struct termios)
19 #include <system_error> // For throwing std::system_error 19 #include <system_error> // For throwing std::system_error
  20 +#include <sys/ioctl.h> // Used for TCGETS2, which is required for custom baud rates
  21 +#include <cassert>
  22 +// #include <asm/termios.h> // Terminal control definitions (struct termios)
  23 +#include <asm/ioctls.h>
  24 +#include <asm/termbits.h>
20 25
21 // User includes 26 // User includes
22 #include "CppLinuxSerial/Exception.hpp" 27 #include "CppLinuxSerial/Exception.hpp"
23 #include "CppLinuxSerial/SerialPort.hpp" 28 #include "CppLinuxSerial/SerialPort.hpp"
24 29
  30 +#define BOTHER 0010000
  31 +
25 namespace mn { 32 namespace mn {
26 namespace CppLinuxSerial { 33 namespace CppLinuxSerial {
27 34
28 SerialPort::SerialPort() { 35 SerialPort::SerialPort() {
29 echo_ = false; 36 echo_ = false;
30 timeout_ms_ = defaultTimeout_ms_; 37 timeout_ms_ = defaultTimeout_ms_;
31 - baudRate_ = defaultBaudRate_; 38 + baudRateType_ = BaudRateType::STANDARD;
  39 + baudRateStandard_ = defaultBaudRate_;
32 readBufferSize_B_ = defaultReadBufferSize_B_; 40 readBufferSize_B_ = defaultReadBufferSize_B_;
33 readBuffer_.reserve(readBufferSize_B_); 41 readBuffer_.reserve(readBufferSize_B_);
34 state_ = State::CLOSED; 42 state_ = State::CLOSED;
@@ -37,7 +45,15 @@ namespace CppLinuxSerial { @@ -37,7 +45,15 @@ namespace CppLinuxSerial {
37 SerialPort::SerialPort(const std::string& device, BaudRate baudRate) : 45 SerialPort::SerialPort(const std::string& device, BaudRate baudRate) :
38 SerialPort() { 46 SerialPort() {
39 device_ = device; 47 device_ = device;
40 - baudRate_ = baudRate; 48 + baudRateType_ = BaudRateType::STANDARD;
  49 + baudRateStandard_ = baudRate;
  50 + }
  51 +
  52 + SerialPort::SerialPort(const std::string& device, speed_t baudRate) :
  53 + SerialPort() {
  54 + device_ = device;
  55 + baudRateType_ = BaudRateType::CUSTOM;
  56 + baudRateCustom_ = baudRate;
41 } 57 }
42 58
43 SerialPort::~SerialPort() { 59 SerialPort::~SerialPort() {
@@ -52,13 +68,21 @@ namespace CppLinuxSerial { @@ -52,13 +68,21 @@ namespace CppLinuxSerial {
52 void SerialPort::SetDevice(const std::string& device) { 68 void SerialPort::SetDevice(const std::string& device) {
53 device_ = device; 69 device_ = device;
54 if(state_ == State::OPEN) 70 if(state_ == State::OPEN)
55 -  
56 -  
57 - ConfigureTermios(); 71 + ConfigureTermios();
58 } 72 }
59 73
60 void SerialPort::SetBaudRate(BaudRate baudRate) { 74 void SerialPort::SetBaudRate(BaudRate baudRate) {
61 - baudRate_ = baudRate; 75 + std::cout << "standard called\n";
  76 + baudRateType_ = BaudRateType::STANDARD;
  77 + baudRateStandard_ = baudRate;
  78 + if(state_ == State::OPEN)
  79 + ConfigureTermios();
  80 + }
  81 +
  82 + void SerialPort::SetBaudRate(speed_t baudRate) {
  83 + std::cout << " custom called\n";
  84 + baudRateType_ = BaudRateType::CUSTOM;
  85 + baudRateCustom_ = baudRate;
62 if(state_ == State::OPEN) 86 if(state_ == State::OPEN)
63 ConfigureTermios(); 87 ConfigureTermios();
64 } 88 }
@@ -66,7 +90,7 @@ namespace CppLinuxSerial { @@ -66,7 +90,7 @@ namespace CppLinuxSerial {
66 void SerialPort::Open() 90 void SerialPort::Open()
67 { 91 {
68 92
69 - std::cout << "Attempting to open COM port \"" << device_ << "\"." << std::endl; 93 + // std::cout << "Attempting to open COM port \"" << device_ << "\"." << std::endl;
70 94
71 if(device_.empty()) { 95 if(device_.empty()) {
72 THROW_EXCEPT("Attempted to open file when file path has not been assigned to."); 96 THROW_EXCEPT("Attempted to open file when file path has not been assigned to.");
@@ -86,7 +110,7 @@ namespace CppLinuxSerial { @@ -86,7 +110,7 @@ namespace CppLinuxSerial {
86 110
87 ConfigureTermios(); 111 ConfigureTermios();
88 112
89 - std::cout << "COM port opened successfully." << std::endl; 113 + // std::cout << "COM port opened successfully." << std::endl;
90 state_ = State::OPEN; 114 state_ = State::OPEN;
91 } 115 }
92 116
@@ -97,11 +121,12 @@ namespace CppLinuxSerial { @@ -97,11 +121,12 @@ namespace CppLinuxSerial {
97 121
98 void SerialPort::ConfigureTermios() 122 void SerialPort::ConfigureTermios()
99 { 123 {
100 - std::cout << "Configuring COM port \"" << device_ << "\"." << std::endl; 124 + // std::cout << "Configuring COM port \"" << device_ << "\"." << std::endl;
101 125
102 //================== CONFIGURE ==================// 126 //================== CONFIGURE ==================//
103 127
104 - termios tty = GetTermios(); 128 + // termios tty = GetTermios();
  129 + termios2 tty = GetTermios2();
105 130
106 //================= (.c_cflag) ===============// 131 //================= (.c_cflag) ===============//
107 132
@@ -115,29 +140,171 @@ namespace CppLinuxSerial { @@ -115,29 +140,171 @@ namespace CppLinuxSerial {
115 140
116 //===================== BAUD RATE =================// 141 //===================== BAUD RATE =================//
117 142
118 - switch(baudRate_) {  
119 - case BaudRate::B_9600:  
120 - cfsetispeed(&tty, B9600);  
121 - cfsetospeed(&tty, B9600);  
122 - break;  
123 - case BaudRate::B_38400:  
124 - cfsetispeed(&tty, B38400);  
125 - cfsetospeed(&tty, B38400);  
126 - break;  
127 - case BaudRate::B_57600:  
128 - cfsetispeed(&tty, B57600);  
129 - cfsetospeed(&tty, B57600);  
130 - break;  
131 - case BaudRate::B_115200:  
132 - cfsetispeed(&tty, B115200);  
133 - cfsetospeed(&tty, B115200);  
134 - break;  
135 - case BaudRate::CUSTOM:  
136 - // See https://gist.github.com/kennethryerson/f7d1abcf2633b7c03cf0  
137 - throw std::runtime_error("Custom baud rate not yet supported.");  
138 - default:  
139 - throw std::runtime_error(std::string() + "baudRate passed to " + __PRETTY_FUNCTION__ + " unrecognized.");  
140 - } 143 + // We used to use cfsetispeed() and cfsetospeed() with the B... macros, but this didn't allow
  144 + // us to set custom baud rates. So now to support both standard and custom baud rates lets
  145 + // just make everything "custom". This giant switch statement could be replaced with a map/lookup
  146 + // in the future
  147 + if (baudRateType_ == BaudRateType::STANDARD) {
  148 + tty.c_cflag &= ~CBAUD;
  149 + tty.c_cflag |= CBAUDEX;
  150 + switch(baudRateStandard_) {
  151 + case BaudRate::B_0:
  152 + // cfsetispeed(&tty, B0);
  153 + // cfsetospeed(&tty, B0);
  154 + tty.c_ispeed = 0;
  155 + tty.c_ospeed = 0;
  156 + break;
  157 + case BaudRate::B_50:
  158 + // cfsetispeed(&tty, B50);
  159 + // cfsetospeed(&tty, B50);
  160 + tty.c_ispeed = 50;
  161 + tty.c_ospeed = 50;
  162 + break;
  163 + case BaudRate::B_75:
  164 + // cfsetispeed(&tty, B75);
  165 + // cfsetospeed(&tty, B75);
  166 + tty.c_ispeed = 75;
  167 + tty.c_ospeed = 75;
  168 + break;
  169 + case BaudRate::B_110:
  170 + // cfsetispeed(&tty, B110);
  171 + // cfsetospeed(&tty, B110);
  172 + tty.c_ispeed = 110;
  173 + tty.c_ospeed = 110;
  174 + break;
  175 + case BaudRate::B_134:
  176 + // cfsetispeed(&tty, B134);
  177 + // cfsetospeed(&tty, B134);
  178 + tty.c_ispeed = 134;
  179 + tty.c_ospeed = 134;
  180 + break;
  181 + case BaudRate::B_150:
  182 + // cfsetispeed(&tty, B150);
  183 + // cfsetospeed(&tty, B150);
  184 + tty.c_ispeed = 150;
  185 + tty.c_ospeed = 150;
  186 + break;
  187 + case BaudRate::B_200:
  188 + // cfsetispeed(&tty, B200);
  189 + // cfsetospeed(&tty, B200);
  190 + tty.c_ispeed = 200;
  191 + tty.c_ospeed = 200;
  192 + break;
  193 + case BaudRate::B_300:
  194 + // cfsetispeed(&tty, B300);
  195 + // cfsetospeed(&tty, B300);
  196 + tty.c_ispeed = 300;
  197 + tty.c_ospeed = 300;
  198 + break;
  199 + case BaudRate::B_600:
  200 + // cfsetispeed(&tty, B600);
  201 + // cfsetospeed(&tty, B600);
  202 + tty.c_ispeed = 600;
  203 + tty.c_ospeed = 600;
  204 + break;
  205 + case BaudRate::B_1200:
  206 + // cfsetispeed(&tty, B1200);
  207 + // cfsetospeed(&tty, B1200);
  208 + tty.c_ispeed = 1200;
  209 + tty.c_ospeed = 1200;
  210 + break;
  211 + case BaudRate::B_1800:
  212 + // cfsetispeed(&tty, B1800);
  213 + // cfsetospeed(&tty, B1800);
  214 + tty.c_ispeed = 1800;
  215 + tty.c_ospeed = 1800;
  216 + break;
  217 + case BaudRate::B_2400:
  218 + // cfsetispeed(&tty, B2400);
  219 + // cfsetospeed(&tty, B2400);
  220 + tty.c_ispeed = 2400;
  221 + tty.c_ospeed = 2400;
  222 + break;
  223 + case BaudRate::B_4800:
  224 + // cfsetispeed(&tty, B4800);
  225 + // cfsetospeed(&tty, B4800);
  226 + tty.c_ispeed = 4800;
  227 + tty.c_ospeed = 4800;
  228 + break;
  229 + case BaudRate::B_9600:
  230 + // cfsetispeed(&tty, B9600);
  231 + // cfsetospeed(&tty, B9600);
  232 + tty.c_ispeed = 9600;
  233 + tty.c_ospeed = 9600;
  234 + break;
  235 + case BaudRate::B_19200:
  236 + // cfsetispeed(&tty, B19200);
  237 + // cfsetospeed(&tty, B19200);
  238 + tty.c_ispeed = 19200;
  239 + tty.c_ospeed = 19200;
  240 + break;
  241 + case BaudRate::B_38400:
  242 + // cfsetispeed(&tty, B38400);
  243 + // cfsetospeed(&tty, B38400);
  244 + tty.c_ispeed = 38400;
  245 + tty.c_ospeed = 38400;
  246 + break;
  247 + case BaudRate::B_57600:
  248 + // cfsetispeed(&tty, B57600);
  249 + // cfsetospeed(&tty, B57600);
  250 + tty.c_ispeed = 57600;
  251 + tty.c_ospeed = 57600;
  252 + break;
  253 + case BaudRate::B_115200:
  254 + // cfsetispeed(&tty, B115200);
  255 + // cfsetospeed(&tty, B115200);
  256 + tty.c_ispeed = 115200;
  257 + tty.c_ospeed = 115200;
  258 + break;
  259 + case BaudRate::B_230400:
  260 + // cfsetispeed(&tty, B230400);
  261 + // cfsetospeed(&tty, B230400);
  262 + tty.c_ispeed = 230400;
  263 + tty.c_ospeed = 230400;
  264 + break;
  265 + case BaudRate::B_460800:
  266 + // cfsetispeed(&tty, B460800);
  267 + // cfsetospeed(&tty, B460800);
  268 + tty.c_ispeed = 460800;
  269 + tty.c_ospeed = 460800;
  270 + break;
  271 + default:
  272 + throw std::runtime_error(std::string() + "baudRate passed to " + __PRETTY_FUNCTION__ + " unrecognized.");
  273 + }
  274 + }
  275 + // This does no different than STANDARD atm, but let's keep
  276 + // them separate for now....
  277 + else if (baudRateType_ == BaudRateType::CUSTOM)
  278 + {
  279 + tty.c_cflag &= ~CBAUD;
  280 + tty.c_cflag |= CBAUDEX;
  281 + // tty.c_cflag |= BOTHER;
  282 + tty.c_ispeed = baudRateCustom_;
  283 + tty.c_ospeed = baudRateCustom_;
  284 +
  285 +
  286 + // #include <linux/serial.h>
  287 + // // configure port to use custom speed instead of 38400
  288 + // struct serial_struct ss;
  289 + // ioctl(fileDesc_, TIOCGSERIAL, &ss);
  290 + // ss.flags = (ss.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
  291 + // ss.custom_divisor = (ss.baud_base + (baudRateCustom_ / 2)) / baudRateCustom_;
  292 + // int closestSpeed = ss.baud_base / ss.custom_divisor;
  293 +
  294 + // if (closestSpeed < baudRateCustom_ * 98 / 100 || closestSpeed > baudRateCustom_ * 102 / 100) {
  295 + // printf("Cannot set serial port speed to %d. Closest possible is %d\n", baudRateCustom_, closestSpeed);
  296 + // }
  297 +
  298 + // ioctl(fileDesc_, TIOCSSERIAL, &ss);
  299 +
  300 + // cfsetispeed(&tty, B38400);
  301 + // cfsetospeed(&tty, B38400);
  302 + }
  303 + else
  304 + {
  305 + // Should never get here, bug in this libraries code!
  306 + assert(false);
  307 + }
141 308
142 //===================== (.c_oflag) =================// 309 //===================== (.c_oflag) =================//
143 310
@@ -170,14 +337,11 @@ namespace CppLinuxSerial { @@ -170,14 +337,11 @@ namespace CppLinuxSerial {
170 tty.c_cc[VMIN] = 0; 337 tty.c_cc[VMIN] = 0;
171 } 338 }
172 339
173 -  
174 //======================== (.c_iflag) ====================// 340 //======================== (.c_iflag) ====================//
175 341
176 tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl 342 tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
177 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); 343 tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);
178 344
179 -  
180 -  
181 //=========================== LOCAL MODES (c_lflag) =======================// 345 //=========================== LOCAL MODES (c_lflag) =======================//
182 346
183 // Canonical input is when read waits for EOL or EOF characters before returning. In non-canonical mode, the rate at which 347 // Canonical input is when read waits for EOL or EOF characters before returning. In non-canonical mode, the rate at which
@@ -189,11 +353,11 @@ namespace CppLinuxSerial { @@ -189,11 +353,11 @@ namespace CppLinuxSerial {
189 tty.c_lflag &= ~ISIG; // Disables recognition of INTR (interrupt), QUIT and SUSP (suspend) characters 353 tty.c_lflag &= ~ISIG; // Disables recognition of INTR (interrupt), QUIT and SUSP (suspend) characters
190 354
191 355
192 -  
193 // Try and use raw function call 356 // Try and use raw function call
194 //cfmakeraw(&tty); 357 //cfmakeraw(&tty);
195 358
196 - this->SetTermios(tty); 359 + // this->SetTermios(tty);
  360 + this->SetTermios2(tty);
197 361
198 /* 362 /*
199 // Flush port, then apply attributes 363 // Flush port, then apply attributes
@@ -262,39 +426,60 @@ namespace CppLinuxSerial { @@ -262,39 +426,60 @@ namespace CppLinuxSerial {
262 // If code reaches here, read must of been successful 426 // If code reaches here, read must of been successful
263 } 427 }
264 428
265 - termios SerialPort::GetTermios() {  
266 - if(fileDesc_ == -1)  
267 - throw std::runtime_error("GetTermios() called but file descriptor was not valid."); 429 + // termios SerialPort::GetTermios() {
  430 + // if(fileDesc_ == -1)
  431 + // throw std::runtime_error("GetTermios() called but file descriptor was not valid.");
268 432
269 - struct termios tty;  
270 - memset(&tty, 0, sizeof(tty)); 433 + // struct termios tty;
  434 + // memset(&tty, 0, sizeof(tty));
271 435
272 - // Get current settings (will be stored in termios structure)  
273 - if(tcgetattr(fileDesc_, &tty) != 0)  
274 - {  
275 - // Error occurred  
276 - std::cout << "Could not get terminal attributes for \"" << device_ << "\" - " << strerror(errno) << std::endl;  
277 - throw std::system_error(EFAULT, std::system_category());  
278 - //return false;  
279 - } 436 + // // Get current settings (will be stored in termios structure)
  437 + // if(tcgetattr(fileDesc_, &tty) != 0)
  438 + // {
  439 + // // Error occurred
  440 + // std::cout << "Could not get terminal attributes for \"" << device_ << "\" - " << strerror(errno) << std::endl;
  441 + // throw std::system_error(EFAULT, std::system_category());
  442 + // //return false;
  443 + // }
280 444
281 - return tty;  
282 - } 445 + // return tty;
  446 + // }
283 447
284 - void SerialPort::SetTermios(termios myTermios)  
285 - {  
286 - // Flush port, then apply attributes  
287 - tcflush(fileDesc_, TCIFLUSH); 448 + // void SerialPort::SetTermios(termios myTermios)
  449 + // {
  450 + // // Flush port, then apply attributes
  451 + // tcflush(fileDesc_, TCIFLUSH);
288 452
289 - if(tcsetattr(fileDesc_, TCSANOW, &myTermios) != 0)  
290 - {  
291 - // Error occurred  
292 - std::cout << "Could not apply terminal attributes for \"" << device_ << "\" - " << strerror(errno) << std::endl;  
293 - throw std::system_error(EFAULT, std::system_category()); 453 + // if(tcsetattr(fileDesc_, TCSANOW, &myTermios) != 0)
  454 + // {
  455 + // // Error occurred
  456 + // std::cout << "Could not apply terminal attributes for \"" << device_ << "\" - " << strerror(errno) << std::endl;
  457 + // throw std::system_error(EFAULT, std::system_category());
294 458
295 - } 459 + // }
  460 +
  461 + // // Successful!
  462 + // }
296 463
297 - // Successful! 464 + termios2 SerialPort::GetTermios2()
  465 + {
  466 + struct termios2 term2;
  467 +
  468 + ioctl(fileDesc_, TCGETS2, &term2);
  469 +
  470 + return term2;
  471 +
  472 + // term2.c_cflag &= ~CBAUD; /* Remove current BAUD rate */
  473 + // term2.c_cflag |= BOTHER; /* Allow custom BAUD rate using int input */
  474 + // term2.c_ispeed = speed; /* Set the input BAUD rate */
  475 + // term2.c_ospeed = speed; /* Set the output BAUD rate */
  476 +
  477 + // ioctl(fd, TCSETS2, &term2);
  478 + }
  479 +
  480 + void SerialPort::SetTermios2(termios2 tty)
  481 + {
  482 + ioctl(fileDesc_, TCSETS2, &tty);
298 } 483 }
299 484
300 void SerialPort::Close() { 485 void SerialPort::Close() {
test/arduino/Basic/Basic.ino 0 → 100644
  1 +/*
  2 + AnalogReadSerial
  3 +
  4 + Reads an analog input on pin 0, prints the result to the Serial Monitor.
  5 + Graphical representation is available using Serial Plotter (Tools > Serial Plotter menu).
  6 + Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.
  7 +
  8 + This example code is in the public domain.
  9 +
  10 + http://www.arduino.cc/en/Tutorial/AnalogReadSerial
  11 +*/
  12 +
  13 +// the setup routine runs once when you press reset:
  14 +void setup() {
  15 + // initialize serial communication at 9600 bits per second:
  16 + Serial.begin(9600);
  17 +// Serial.begin(81234); // Used to test custom baud rates
  18 +}
  19 +
  20 +// the loop routine runs over and over again forever:
  21 +void loop() {
  22 + Serial.println("Hello");
  23 + delay(100); // delay in between reads for stability
  24 +}
test/arduino/main.cpp 0 → 100644
  1 +#include <CppLinuxSerial/SerialPort.hpp>
  2 +
  3 +using namespace mn::CppLinuxSerial;
  4 +
  5 +int main() {
  6 + // Create serial port object and open serial port
  7 + SerialPort serialPort("/dev/ttyACM0", BaudRate::B_9600);
  8 + // SerialPort serialPort("/dev/ttyACM0", 13000);
  9 + serialPort.SetTimeout(-1); // Block when reading until any data is received
  10 + serialPort.Open();
  11 +
  12 + // Write some ASCII datae
  13 + // serialPort0.Write("Hello");
  14 +
  15 + // Read some data back
  16 + while(1) {
  17 + std::string readData;
  18 + serialPort.Read(readData);
  19 + std::cout << "Received data: " << readData;
  20 + }
  21 +
  22 + // Close the serial port
  23 + serialPort.Close();
  24 +}
0 \ No newline at end of file 25 \ No newline at end of file