Line data Source code
1 : #include "Serial.hpp"
2 :
3 : #include <cstring>
4 : #include <iostream>
5 : #include <stdexcept>
6 : #include <string>
7 : #include <fcntl.h>
8 : #include <termios.h>
9 : #include <unistd.h>
10 :
11 : namespace HLR
12 : {
13 : namespace Kinematics
14 : {
15 : namespace RV2AJ
16 : {
17 0 : Serial::~Serial()
18 : {
19 : try
20 : {
21 0 : if (opened())
22 : {
23 0 : close();
24 : }
25 : }
26 0 : catch (...)
27 : {
28 : // This may happen when close() is called after the if statement
29 : // not a real problem, so continue destructing and do not crash
30 : // the application.
31 0 : std::cerr << "caught exception in Serial::~Serial" << std::endl;
32 : }
33 0 : }
34 :
35 0 : void Serial::open(const std::string& dev)
36 : {
37 : // Verify args.
38 0 : if (dev.empty())
39 : {
40 0 : throw std::invalid_argument("invalid device name");
41 : }
42 :
43 : // Check if open.
44 0 : if (opened())
45 : {
46 0 : throw std::runtime_error("device already open");
47 : }
48 :
49 : // Open device.
50 0 : fd = ::open(dev.c_str(), O_RDWR | O_NOCTTY | O_SYNC);
51 0 : if (!opened())
52 : {
53 0 : throw std::runtime_error("could not open device");
54 : }
55 :
56 : // Create termios tty mapping.
57 : struct termios tty;
58 0 : memset(&tty, 0, sizeof(tty));
59 0 : if (tcgetattr(fd, &tty) != 0)
60 : {
61 0 : ::close(fd);
62 0 : fd = -1;
63 0 : throw std::runtime_error("could not get device attributes");
64 : }
65 :
66 : // Set baud rate.
67 0 : cfsetispeed(&tty, B9600);
68 0 : cfsetospeed(&tty, B9600);
69 :
70 : // Set tty properties.
71 : // Some sets are probably not needed.
72 0 : tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
73 0 : tty.c_iflag &= ~IGNBRK; // disable break processing
74 0 : tty.c_lflag = 0; // no signaling chars, echo, canonical processing
75 0 : tty.c_oflag = 0; // no remapping, delays
76 0 : tty.c_cc[VMIN] = 1; // block when reading for 1 char
77 0 : tty.c_cc[VTIME] = 0; // do not timeout on read, block instead
78 0 : tty.c_iflag &= ~(IXON | IXOFF | IXANY); // disable xon/xoff controls
79 0 : tty.c_cflag |= (CLOCAL | CREAD); // ignore modem control, allow read
80 0 : tty.c_cflag &= ~(PARENB | PARODD); // disable parity
81 0 : tty.c_cflag |= 0; // set to 1 to enable parity
82 0 : tty.c_cflag &= ~CSTOPB; // stop bit
83 :
84 : // Write tty properties.
85 0 : if (tcsetattr(fd, TCSANOW, &tty) != 0)
86 : {
87 0 : ::close(fd);
88 0 : fd = -1;
89 0 : throw std::runtime_error("could not set tty properties");
90 : }
91 0 : }
92 :
93 0 : void Serial::close()
94 : {
95 : // Check if open.
96 0 : if (!opened())
97 : {
98 0 : throw std::runtime_error("file is not opened");
99 : }
100 :
101 : // Close device.
102 0 : ::close(fd);
103 0 : fd = -1;
104 0 : }
105 :
106 0 : bool Serial::opened() const
107 : {
108 0 : return fd >= 0;
109 : }
110 :
111 0 : void Serial::write(const std::string& msg)
112 : {
113 : // Verify args.
114 0 : if (msg.empty())
115 : {
116 0 : throw std::invalid_argument("empty message");
117 : }
118 :
119 : // Check if open.
120 0 : if (!opened())
121 : {
122 0 : throw std::runtime_error("device not open");
123 : }
124 :
125 : // Write msg. The \0 terminator is not sent over the serial port.
126 0 : if (::write(fd, msg.c_str(), msg.length() * sizeof(char)) == -1)
127 : {
128 0 : throw std::runtime_error("could not write data to device");
129 : }
130 0 : }
131 :
132 : } // namespace RV2AJ
133 : } // namespace Kinematics
134 3 : } // namespace HLR
|