-
Notifications
You must be signed in to change notification settings - Fork 224
Expand file tree
/
Copy pathUartWidget.cpp
More file actions
189 lines (164 loc) · 4.53 KB
/
UartWidget.cpp
File metadata and controls
189 lines (164 loc) · 4.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/*
* 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 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* UartWidget.cpp
* This class is based on QLCFTDI class from
*
* Q Light Controller
* qlcftdi-libftdi.cpp
*
* Copyright (C) Heikki Junnila
*
* Only standard CPP conversion was changed and function name changed
* to follow OLA coding standards.
*
* by Rui Barreiros
* Copyright (C) 2014 Richard Ash
*/
#include <strings.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <string>
#include <algorithm>
#include <vector>
#include "ola/Constants.h"
#include "ola/io/ExtendedSerial.h"
#include "ola/io/IOUtils.h"
#include "ola/Logging.h"
#include "plugins/uartdmx/UartWidget.h"
namespace ola {
namespace plugin {
namespace uartdmx {
using std::string;
using std::vector;
UartWidget::UartWidget(const string& path)
: m_path(path),
m_fd(NOT_OPEN) {
}
UartWidget::~UartWidget() {
if (IsOpen()) {
Close();
}
}
bool UartWidget::Open() {
OLA_DEBUG << "Opening serial port " << Name();
if (!ola::io::Open(m_path, O_WRONLY, &m_fd)) {
m_fd = FAILED_OPEN;
OLA_WARN << Name() << " failed to open";
return false;
} else {
OLA_DEBUG << "Opened serial port " << Name();
return true;
}
}
bool UartWidget::Close() {
if (!IsOpen()) {
return true;
}
if (close(m_fd)) {
OLA_WARN << Name() << " error closing";
m_fd = NOT_OPEN;
return false;
}
m_fd = NOT_OPEN;
return true;
}
bool UartWidget::IsOpen() const {
return m_fd >= 0;
}
bool UartWidget::SetBreak(bool on) {
unsigned long request; /* NOLINT(runtime/int) */
/* this is passed to ioctl, which is declared to take
* unsigned long as it's second argument
*/
if (on == true) {
request = TIOCSBRK;
} else {
request = TIOCCBRK;
}
if (ioctl(m_fd, request, NULL) < 0) {
OLA_WARN << Name() << " ioctl() failed";
return false;
} else {
return true;
}
}
bool UartWidget::Write(const ola::DmxBuffer& data) {
unsigned char buffer[DMX_UNIVERSE_SIZE + 1];
unsigned int length = DMX_UNIVERSE_SIZE;
buffer[0] = DMX512_START_CODE;
data.Get(buffer + 1, &length);
if (write(m_fd, buffer, length + 1) <= 0) {
// TODO(richardash1981): handle errors better as per the test code,
// especially if we alter the scheduling!
OLA_WARN << Name() << " Short or failed write!";
return false;
} else {
return true;
}
}
bool UartWidget::Read(unsigned char *buff, int size) {
int readb = read(m_fd, buff, size);
if (readb <= 0) {
OLA_WARN << Name() << " read error";
return false;
} else {
return true;
}
}
/**
* Setup our device for DMX send
* Also used to test if device is working correctly
* before AddDevice()
*/
bool UartWidget::SetupOutput() {
struct termios my_tios;
// Setup the Uart for DMX
if (Open() == false) {
OLA_WARN << "Error Opening widget";
return false;
}
/* do the port settings */
if (tcgetattr(m_fd, &my_tios) < 0) { // get current settings
OLA_WARN << "Failed to get POSIX port settings";
return false;
}
cfmakeraw(&my_tios); // make it a binary data port
my_tios.c_cflag |= CLOCAL; // port is local, no flow control
my_tios.c_cflag &= ~CSIZE;
my_tios.c_cflag |= CS8; // 8 bit chars
my_tios.c_cflag &= ~PARENB; // no parity
my_tios.c_cflag |= CSTOPB; // 2 stop bit for DMX
my_tios.c_cflag &= ~CRTSCTS; // no CTS/RTS flow control
if (tcsetattr(m_fd, TCSANOW, &my_tios) < 0) { // apply settings
OLA_WARN << "Failed to get POSIX port settings";
return false;
}
/* Do the platform-specific initialisation of the UART to 250kbaud */
if (!ola::io::LinuxHelper::SetDmxBaud(m_fd)) {
OLA_WARN << "Failed to set baud rate to 250k";
return false;
}
/* everything must have worked to get here */
return true;
}
} // namespace uartdmx
} // namespace plugin
} // namespace ola