• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OpenLightingProject / ola / 16911433572

12 Aug 2025 02:08PM UTC coverage: 45.869% (-0.04%) from 45.909%
16911433572

Pull #1739

github

web-flow
Merge 02faeaa2d into 3566c28d9
Pull Request #1739: New web UI, store highest channel number used

7157 of 16316 branches covered (43.86%)

20915 of 45597 relevant lines covered (45.87%)

52.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

31.11
/plugins/usbpro/UsbSerialPlugin.cpp
1
/*
2
 * This program is free software; you can redistribute it and/or modify
3
 * it under the terms of the GNU General Public License as published by
4
 * the Free Software Foundation; either version 2 of the License, or
5
 * (at your option) any later version.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU Library General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
15
 *
16
 * UsbSerialPlugin.cpp
17
 * The UsbPro plugin for ola
18
 * Copyright (C) 2006 Simon Newton
19
 */
20

21
#include <stdlib.h>
22
#include <stdio.h>
23
#include <memory>
24
#include <string>
25
#include <vector>
26

27
#include "ola/Callback.h"
28
#include "ola/Logging.h"
29
#include "ola/StringUtils.h"
30
#include "olad/PluginAdaptor.h"
31
#include "olad/Preferences.h"
32

33
#include "plugins/usbpro/ArduinoRGBDevice.h"
34
#include "plugins/usbpro/DmxTriDevice.h"
35
#include "plugins/usbpro/DmxTriWidget.h"
36
#include "plugins/usbpro/DmxterDevice.h"
37
#include "plugins/usbpro/RobeDevice.h"
38
#include "plugins/usbpro/RobeWidgetDetector.h"
39
#include "plugins/usbpro/UltraDMXProDevice.h"
40
#include "plugins/usbpro/UltraDMXProWidget.h"
41
#include "plugins/usbpro/UsbProDevice.h"
42
#include "plugins/usbpro/UsbSerialPlugin.h"
43

44

45
namespace ola {
46
namespace plugin {
47
namespace usbpro {
48

49
using std::auto_ptr;
50
using std::string;
51
using std::vector;
52

53
const char UsbSerialPlugin::DEFAULT_DEVICE_DIR[] = "/dev";
54
const char UsbSerialPlugin::DEVICE_DIR_KEY[] = "device_dir";
55
const char UsbSerialPlugin::DEVICE_PREFIX_KEY[] = "device_prefix";
56
const char UsbSerialPlugin::IGNORED_DEVICES_KEY[] = "ignore_device";
57
const char UsbSerialPlugin::LINUX_DEVICE_PREFIX[] = "ttyUSB";
58
const char UsbSerialPlugin::BSD_DEVICE_PREFIX[] = "ttyU";
59
const char UsbSerialPlugin::MAC_DEVICE_PREFIX[] = "cu.usbserial-";
60
const char UsbSerialPlugin::PLUGIN_NAME[] = "Serial USB";
61
const char UsbSerialPlugin::PLUGIN_PREFIX[] = "usbserial";
62
const char UsbSerialPlugin::ROBE_DEVICE_NAME[] = "Robe Universal Interface";
63
const char UsbSerialPlugin::TRI_USE_RAW_RDM_KEY[] = "tri_use_raw_rdm";
64
const char UsbSerialPlugin::USBPRO_DEVICE_NAME[] = "Enttec Usb Pro Device";
65
const char UsbSerialPlugin::USB_PRO_FPS_LIMIT_KEY[] = "pro_fps_limit";
66
const char UsbSerialPlugin::ULTRA_FPS_LIMIT_KEY[] = "ultra_fps_limit";
67

68
UsbSerialPlugin::UsbSerialPlugin(PluginAdaptor *plugin_adaptor)
1✔
69
    : Plugin(plugin_adaptor),
70
      m_detector_thread(this, plugin_adaptor) {
1✔
71
}
1✔
72

73

74
/*
75
 * Return the description for this plugin
76
 */
77
string UsbSerialPlugin::Description() const {
×
78
    return
×
79
"Serial USB Plugin\n"
×
80
"----------------------------\n"
81
"\n"
82
"This plugin supports DMX USB devices that emulate a serial port. This \n"
83
"includes:\n"
84
" - Arduino RGB Mixer\n"
85
" - DMX-TRI & RDM-TRI\n"
86
" - DMXking USB DMX512-A, Ultra DMX, Ultra DMX Pro\n"
87
" - DMXter4, DMXter4A & mini DMXter\n"
88
" - Enttec DMX USB Pro & USB Pro Mk II\n"
89
" - Robe Universe Interface\n"
90
"\n"
91
"See https://wiki.openlighting.org/index.php/USB_Protocol_Extensions for \n"
92
"more info.\n"
93
"\n"
94
"--- Config file : ola-usbserial.conf ---\n"
95
"\n"
96
"device_dir = /dev\n"
97
"The directory to look for devices in.\n"
98
"\n"
99
"device_prefix = ttyUSB\n"
100
"The prefix of filenames to consider as devices. Multiple keys are allowed.\n"
101
"\n"
102
"ignore_device = /dev/ttyUSB\n"
103
"Ignore the device matching this string. Multiple keys are allowed.\n"
104
"\n"
105
"pro_fps_limit = 190\n"
106
"The max frames per second to send to a Usb Pro or DMXKing device.\n"
107
"\n"
108
"tri_use_raw_rdm = [true|false]\n"
109
"Bypass RDM handling in the {DMX,RDM}-TRI widgets.\n"
110
"\n"
111
"ultra_fps_limit = 40\n"
112
"The max frames per second to send to a Ultra DMX Pro device.\n"
113
"\n";
×
114
}
115

116

117
/*
118
 * Called when a device is removed
119
 */
120
void UsbSerialPlugin::DeviceRemoved(UsbSerialDevice *device) {
×
121
  vector<UsbSerialDevice*>::iterator iter;
×
122

123
  for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) {
×
124
    if (*iter == device) {
×
125
      break;
126
    }
127
  }
128

129
  if (iter == m_devices.end()) {
×
130
    OLA_WARN << "Couldn't find the device that was removed";
×
131
    return;
×
132
  }
133

134
  DeleteDevice(device);
×
135
  m_devices.erase(iter);
×
136
}
137

138

139
/**
140
 * Handle a new ArduinoWidget.
141
 */
142
void UsbSerialPlugin::NewWidget(
×
143
    ArduinoWidget *widget,
144
    const UsbProWidgetInformation &information) {
145
  AddDevice(new ArduinoRGBDevice(
×
146
      m_plugin_adaptor,
×
147
      this,
148
      GetDeviceName(information),
×
149
      widget,
150
      information.esta_id,
×
151
      information.device_id,
×
152
      information.serial));
×
153
}
×
154

155

156
/**
157
 * Handle a new Enttec Usb Pro Widget.
158
 */
159
void UsbSerialPlugin::NewWidget(
×
160
    EnttecUsbProWidget *widget,
161
    const UsbProWidgetInformation &information) {
162
  string device_name = GetDeviceName(information);
×
163
  if (device_name.empty()) {
×
164
    device_name = USBPRO_DEVICE_NAME;
×
165
  }
166

167
  AddDevice(new UsbProDevice(m_plugin_adaptor, this, device_name, widget,
×
168
                             information.serial, information.firmware_version,
×
169
                             GetProFrameLimit()));
×
170
}
×
171

172

173
/**
174
 * Handle a new Dmx-Tri Widget.
175
 */
176
void UsbSerialPlugin::NewWidget(
×
177
    DmxTriWidget *widget,
178
    const UsbProWidgetInformation &information) {
179
  widget->UseRawRDM(
×
180
      m_preferences->GetValueAsBool(TRI_USE_RAW_RDM_KEY));
×
181
  AddDevice(new DmxTriDevice(
×
182
      this,
183
      GetDeviceName(information),
×
184
      widget,
185
      information.esta_id,
×
186
      information.device_id,
×
187
      information.serial,
×
188
      information.firmware_version));
×
189
}
×
190

191

192
/**
193
 * Handle a new Dmxter.
194
 */
195
void UsbSerialPlugin::NewWidget(
×
196
    DmxterWidget *widget,
197
    const UsbProWidgetInformation &information) {
198
  AddDevice(new DmxterDevice(
×
199
      this,
200
      GetDeviceName(information),
×
201
      widget,
202
      information.esta_id,
×
203
      information.device_id,
×
204
      information.serial));
×
205
}
×
206

207

208
/**
209
 * New Robe Universal Interface.
210
 */
211
void UsbSerialPlugin::NewWidget(
×
212
    RobeWidget *widget,
213
    const RobeWidgetInformation&) {
214
  AddDevice(new RobeDevice(m_plugin_adaptor,
×
215
                           this,
216
                           ROBE_DEVICE_NAME,
217
                           widget));
×
218
}
×
219

220

221
/**
222
 * A New Ultra DMX Pro Widget
223
 */
224
void UsbSerialPlugin::NewWidget(UltraDMXProWidget *widget,
×
225
                                const UsbProWidgetInformation &information) {
226
  AddDevice(new UltraDMXProDevice(
×
227
      m_plugin_adaptor,
228
      this,
229
      GetDeviceName(information),
×
230
      widget,
231
      information.esta_id,
×
232
      information.device_id,
×
233
      information.serial,
×
234
      information.firmware_version,
×
235
      GetUltraDMXProFrameLimit()));
×
236
}
×
237

238

239
/*
240
 * Add a new device to the list
241
 * @param device the new UsbSerialDevice
242
 */
243
void UsbSerialPlugin::AddDevice(UsbSerialDevice *device) {
×
244
  if (!device->Start()) {
×
245
    delete device;
×
246
    return;
×
247
  }
248

249
  device->SetOnRemove(NewSingleCallback(this,
×
250
                                        &UsbSerialPlugin::DeviceRemoved,
251
                                        device));
252
  m_devices.push_back(device);
×
253
  m_plugin_adaptor->RegisterDevice(device);
×
254
}
255

256

257
/*
258
 * Start the plugin
259
 */
260
bool UsbSerialPlugin::StartHook() {
1✔
261
  const vector<string> ignored_devices =
1✔
262
      m_preferences->GetMultipleValue(IGNORED_DEVICES_KEY);
1✔
263
  m_detector_thread.SetIgnoredDevices(ignored_devices);
1✔
264

265
  m_detector_thread.SetDeviceDirectory(
1✔
266
      m_preferences->GetValue(DEVICE_DIR_KEY));
2✔
267
  m_detector_thread.SetDevicePrefixes(
1✔
268
      m_preferences->GetMultipleValue(DEVICE_PREFIX_KEY));
2✔
269
  if (!m_detector_thread.Start()) {
1✔
270
    OLA_FATAL << "Failed to start the widget discovery thread";
×
271
    return false;
×
272
  }
273
  m_detector_thread.WaitUntilRunning();
1✔
274
  return true;
275
}
1✔
276

277

278
/*
279
 * Stop the plugin
280
 * @return true on success, false on failure
281
 */
282
bool UsbSerialPlugin::StopHook() {
1✔
283
  vector<UsbSerialDevice*>::iterator iter;
1✔
284
  for (iter = m_devices.begin(); iter != m_devices.end(); ++iter) {
1✔
285
    DeleteDevice(*iter);
×
286
  }
287
  m_detector_thread.Join(NULL);
1✔
288
  m_devices.clear();
1✔
289
  return true;
1✔
290
}
291

292

293
/*
294
 * Default to sensible values
295
 */
296
bool UsbSerialPlugin::SetDefaultPreferences() {
1✔
297
  if (!m_preferences) {
1✔
298
    return false;
299
  }
300

301
  bool save = false;
1✔
302

303
  vector<string> device_prefixes =
1✔
304
    m_preferences->GetMultipleValue(DEVICE_PREFIX_KEY);
1✔
305
  if (device_prefixes.empty()) {
1✔
306
    m_preferences->SetMultipleValue(DEVICE_PREFIX_KEY, LINUX_DEVICE_PREFIX);
2✔
307
    m_preferences->SetMultipleValue(DEVICE_PREFIX_KEY, MAC_DEVICE_PREFIX);
2✔
308
    m_preferences->SetMultipleValue(DEVICE_PREFIX_KEY, BSD_DEVICE_PREFIX);
2✔
309
    save = true;
1✔
310
  }
311

312
  save |= m_preferences->SetDefaultValue(DEVICE_DIR_KEY, StringValidator(),
1✔
313
                                         DEFAULT_DEVICE_DIR);
314

315
  save |= m_preferences->SetDefaultValue(USB_PRO_FPS_LIMIT_KEY,
1✔
316
                                         UIntValidator(0, MAX_PRO_FPS_LIMIT),
1✔
317
                                         DEFAULT_PRO_FPS_LIMIT);
318

319
  save |= m_preferences->SetDefaultValue(ULTRA_FPS_LIMIT_KEY,
1✔
320
                                         UIntValidator(0, MAX_ULTRA_FPS_LIMIT),
1✔
321
                                         DEFAULT_ULTRA_FPS_LIMIT);
322

323
  save |= m_preferences->SetDefaultValue(TRI_USE_RAW_RDM_KEY,
1✔
324
                                         BoolValidator(),
1✔
325
                                         false);
326

327
  if (save) {
1✔
328
    m_preferences->Save();
1✔
329
  }
330

331
  device_prefixes = m_preferences->GetMultipleValue(DEVICE_PREFIX_KEY);
2✔
332
  if (device_prefixes.empty()) {
1✔
333
    return false;
×
334
  }
335
  return true;
336
}
1✔
337

338

339
void UsbSerialPlugin::DeleteDevice(UsbSerialDevice *device) {
×
340
  SerialWidgetInterface *widget = device->GetWidget();
×
341
  m_plugin_adaptor->UnregisterDevice(device);
×
342
  device->Stop();
×
343
  delete device;
×
344
  m_detector_thread.FreeWidget(widget);
×
345
}
×
346

347

348
/**
349
 * Get a nicely formatted device name from the widget information.
350
 */
351
string UsbSerialPlugin::GetDeviceName(
×
352
    const UsbProWidgetInformation &information) {
353
  string device_name = information.manufacturer;
×
354
  if (!(information.manufacturer.empty() ||
×
355
        information.device.empty())) {
×
356
    device_name += " - ";
×
357
  }
358
  device_name += information.device;
×
359
  return device_name;
×
360
}
×
361

362

363
/*
364
 * Get the Frames per second limit for a pro device
365
 */
366
unsigned int UsbSerialPlugin::GetProFrameLimit() {
×
367
  unsigned int fps_limit;
×
368
  if (!StringToInt(m_preferences->GetValue(USB_PRO_FPS_LIMIT_KEY) ,
×
369
                   &fps_limit)) {
370
    return DEFAULT_PRO_FPS_LIMIT;
371
  }
372
  return fps_limit;
×
373
}
374

375

376
/*
377
 * Get the Frames per second limit for a Ultra DMX Pro Device
378
 */
379
unsigned int UsbSerialPlugin::GetUltraDMXProFrameLimit() {
×
380
  unsigned int fps_limit;
×
381
  if (!StringToInt(m_preferences->GetValue(ULTRA_FPS_LIMIT_KEY) ,
×
382
                   &fps_limit)) {
383
    return DEFAULT_ULTRA_FPS_LIMIT;
384
  }
385
  return fps_limit;
×
386
}
387
}  // namespace usbpro
388
}  // namespace plugin
389
}  // namespace ola
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc