GCC Code Coverage Report


Directory: ./
File: channeloutput/USBPixelnet.cpp
Date: 2026-10-29 08:11:58
Exec Total Coverage
Lines: 69 79 87.3%
Functions: 10 10 100.0%
Branches: 32 64 50.0%

Line Branch Exec Source
1 /*
2 * This file is part of the Falcon Player (FPP) and is Copyright (C)
3 * 2013-2022 by the Falcon Player Developers.
4 *
5 * The Falcon Player (FPP) is free software, and is covered under
6 * multiple Open Source licenses. Please see the included 'LICENSES'
7 * file for descriptions of what files are covered by each license.
8 *
9 * This source file is covered under the GPL v2 as described in the
10 * included LICENSE.GPL file.
11 */
12
13 #include "fpp-pch.h"
14
15 #include "fpp-json.h"
16
17 #include <unistd.h>
18
19 #include "../log.h"
20
21 #include "USBPixelnet.h"
22 #include "serialutil.h"
23 #include "ChannelOutputSetup.h"
24
25 #include "Plugin.h"
26 class USBPixelnetPlugin : public FPPPlugins::Plugin, public FPPPlugins::ChannelOutputPlugin {
27 public:
28 2 USBPixelnetPlugin() :
29
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
6 FPPPlugins::Plugin("USBPixelnet") {
30 2 }
31 2 virtual ChannelOutput* createChannelOutput(unsigned int startChannel, unsigned int channelCount) override {
32
2/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 return new USBPixelnetOutput(startChannel, channelCount);
33 }
34 };
35
36 extern "C" {
37 2 FPPPlugins::Plugin* createPlugin() {
38
2/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
4 return new USBPixelnetPlugin();
39 }
40 }
41
42 /////////////////////////////////////////////////////////////////////////////
43
44 /*
45 *
46 */
47 2 USBPixelnetOutput::USBPixelnetOutput(unsigned int startChannel,
48 2 unsigned int channelCount) :
49 ThreadedChannelOutput(startChannel, channelCount),
50 2 m_outputData(NULL),
51 2 m_pixelnetData(NULL),
52
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 m_dongleType(PIXELNET_DVC_UNKNOWN) {
53
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 LogDebug(VB_CHANNELOUT, "USBPixelnetOutput::USBPixelnetOutput(%u, %u)\n",
54 startChannel, channelCount);
55
56 // one Pixelnet universe; m_rawData holds the header plus 4096 channels,
57 // and RawSendData copies m_channelCount into it
58
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (m_channelCount > 4096) {
59 1 m_channelCount = 4096;
60 }
61 2 m_useDoubleBuffer = 1;
62 2 }
63
64 /*
65 *
66 */
67 8 USBPixelnetOutput::~USBPixelnetOutput() {
68 4 LogDebug(VB_CHANNELOUT, "USBPixelnetOutput::~USBPixelnetOutput()\n");
69 8 }
70 2 int USBPixelnetOutput::Init(Json::Value config) {
71 2 LogDebug(VB_CHANNELOUT, "USBPixelnetOutput::Init()\n");
72
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (config.isMember("type")) {
73
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 std::string type = config["type"].asString();
74
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (type == "Pixelnet-Lynx") {
75 ✗ LogDebug(VB_CHANNELOUT, "Treating device as Pixelnet-Lynx compatible\n");
76 ✗ m_dongleType = PIXELNET_DVC_LYNX;
77
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 } else if (type == "Pixelnet-Open") {
78
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LogDebug(VB_CHANNELOUT, "Treating device as Pixelnet-Open compatible\n");
79 1 m_dongleType = PIXELNET_DVC_OPEN;
80 }
81 2 }
82
83
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (m_dongleType == PIXELNET_DVC_LYNX) {
84 ✗ if (!setupSerialPort(config, 115200, "8N1")) {
85 ✗ return 0;
86 }
87
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 } else if (m_dongleType == PIXELNET_DVC_OPEN) {
88
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!setupSerialPort(config, 1000000, "8N2")) {
89 ✗ return 0;
90 }
91 } else {
92 1 LogErr(VB_CHANNELOUT, "Invalid Config. Unknown dongle type.\n");
93
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 AddOutputConfigWarning(28, "USBPixelnet: Invalid Config. Unknown dongle type.");
94 1 return 0;
95 }
96
97
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (m_dongleType == PIXELNET_DVC_LYNX) {
98 ✗ m_outputData = m_rawData + 7;
99 ✗ m_pixelnetData = m_outputData + 1;
100
101 ✗ m_outputData[0] = '\xAA';
102
103 ✗ m_outputPacketSize = 4097;
104
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 } else if (m_dongleType == PIXELNET_DVC_OPEN) {
105 1 m_outputData = m_rawData + 2;
106 1 m_pixelnetData = m_outputData + 6;
107
108 1 m_outputData[0] = '\xAA';
109 1 m_outputData[1] = '\x55';
110 1 m_outputData[2] = '\x55';
111 1 m_outputData[3] = '\xAA';
112 1 m_outputData[4] = '\x15';
113 1 m_outputData[5] = '\x5D';
114
115 1 m_outputPacketSize = 4102;
116 }
117
118
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 return ThreadedChannelOutput::Init(config);
119 }
120
121 2 void USBPixelnetOutput::GetRequiredChannelRanges(const std::function<void(int, int)>& addRange) {
122 2 addRange(m_startChannel, m_startChannel + m_channelCount - 1);
123 2 }
124
125 /*
126 *
127 */
128 1 int USBPixelnetOutput::Close(void) {
129 1 LogDebug(VB_CHANNELOUT, "USBPixelnetOutput::Close()\n");
130 1 closeSerialPort();
131 1 return ThreadedChannelOutput::Close();
132 }
133
134 /*
135 *
136 */
137 49 int USBPixelnetOutput::RawSendData(unsigned char* channelData) {
138 49 LogExcess(VB_CHANNELOUT, "USBPixelnetOutput::RawSendData(%p)\n", channelData);
139
140 49 memcpy(m_pixelnetData, channelData, m_channelCount);
141
142 // 0xAA is start of Pixelnet packet, so convert 0xAA (170) to 0xAB (171)
143 49 unsigned char* dptr = m_pixelnetData;
144 49 unsigned char* eptr = dptr + m_channelCount;
145
2/2
✓ Branch 0 taken 200704 times.
✓ Branch 1 taken 49 times.
200753 for (; dptr < eptr; dptr++) {
146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 200704 times.
200704 if (*dptr == 0xAA)
147 ✗ *dptr = 0xAB;
148 }
149
150 // Send Header and Pixelnet Data
151 49 SerialWriteAll(m_fd, m_outputData, m_outputPacketSize, 500);
152
153 49 return m_channelCount;
154 }
155
156 /*
157 *
158 */
159 2 void USBPixelnetOutput::DumpConfig(void) {
160 2 LogDebug(VB_CHANNELOUT, "USBPixelnetOutput::DumpConfig()\n");
161 2 dumpSerialConfig();
162 2 LogDebug(VB_CHANNELOUT, " Output Packet Size: %d\n", m_outputPacketSize);
163 2 ThreadedChannelOutput::DumpConfig();
164 2 }
165