| 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 LGPL v2.1 as described in the | ||
| 10 | * included LICENSE.LGPL file. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include "fpp-pch.h" | ||
| 14 | |||
| 15 | #include "fpp-json.h" | ||
| 16 | #include <cstdint> | ||
| 17 | #include <thread> | ||
| 18 | |||
| 19 | #include "../log.h" | ||
| 20 | |||
| 21 | #include "MuxSensorSource.h" | ||
| 22 | |||
| 23 | // Bounds for user-editable sensors.json. The largest realistic mux is a | ||
| 24 | // handful of select pins (2^N groups) over an 8/16-channel ADC; anything | ||
| 25 | // near these caps is corrupt or malicious. Capping keeps the per-update | ||
| 26 | // loops and the enable()/getValue() vectors bounded. | ||
| 27 | static constexpr int kMaxChannelsPerMux = 1024; | ||
| 28 | static constexpr int kMaxMuxCount = 1024; | ||
| 29 | static constexpr int kMaxTotalMuxChannels = 4096; | ||
| 30 | static constexpr int kMaxMuxSwitchDelayMs = 5000; | ||
| 31 | static constexpr int kMaxMuxSwitchReadCount = 100; | ||
| 32 | |||
| 33 | 5 | MuxSensorSource::MuxSensorSource(Json::Value& config) : | |
| 34 | 5 | SensorSource(config) { | |
| 35 |
3/4✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1 times.
|
5 | std::string sourcename = config["source"].asString(); |
| 36 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | source = Sensors::INSTANCE.getSensorSource(sourcename); |
| 37 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | channelsPerMux = config["channels"].asInt(); |
| 38 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | muxCount = config["muxCount"].asInt(); |
| 39 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
4 | if (channelsPerMux <= 0 || muxCount <= 0 || |
| 40 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | channelsPerMux > kMaxChannelsPerMux || muxCount > kMaxMuxCount || |
| 41 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | (int64_t)channelsPerMux * (int64_t)muxCount > kMaxTotalMuxChannels) { |
| 42 | // User-editable sensors.json: a zero/negative value would divide by | ||
| 43 | // zero in enable()/getValue(), and a huge value would hang the | ||
| 44 | // per-update loops or OOM the vectors. Fail creation instead -- | ||
| 45 | // addSensorSources warns and drops sources where isOK() is false. | ||
| 46 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | LogErr(VB_GENERAL, "MuxSensorSource '%s' has invalid channels (%d) or muxCount (%d), ignoring\n", |
| 47 | getID().c_str(), (int)channelsPerMux, (int)muxCount); | ||
| 48 | 1 | source = nullptr; | |
| 49 | 1 | return; | |
| 50 | } | ||
| 51 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if (source == nullptr) { |
| 52 | // Unknown "source" name. The object would be dropped by isOK() below, | ||
| 53 | // but return before touching GPIO so a doomed object has no HW side | ||
| 54 | // effects. | ||
| 55 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | LogErr(VB_GENERAL, "MuxSensorSource '%s' references unknown source '%s', ignoring\n", |
| 56 | getID().c_str(), sourcename.c_str()); | ||
| 57 | 1 | return; | |
| 58 | } | ||
| 59 |
4/6✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 1 times.
|
4 | for (int x = 0; x < config["muxPins"].size(); x++) { |
| 60 |
4/8✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
3 | const PinCapabilities& pc = PinCapabilities::getPinByName(config["muxPins"][x].asString()); |
| 61 |
3/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
|
3 | if (pc.ptr() == nullptr) { |
| 62 | // Unknown pin name yields the null pin (ptr() == nullptr); using it | ||
| 63 | // below would crash. Fail creation the same way as above. | ||
| 64 |
4/8✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
|
1 | LogErr(VB_GENERAL, "MuxSensorSource '%s' references unknown pin '%s', ignoring\n", |
| 65 | getID().c_str(), config["muxPins"][x].asString().c_str()); | ||
| 66 | 1 | source = nullptr; | |
| 67 | 1 | pins.clear(); | |
| 68 | 1 | return; | |
| 69 | } | ||
| 70 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | pins.push_back(pc.ptr()); |
| 71 | } | ||
| 72 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (auto p : pins) { |
| 73 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
6 | p->configPin("gpio", true, sourcename + "-Mux"); |
| 74 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | p->setValue(0); |
| 75 | } | ||
| 76 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (config.isMember("muxSwitchDelay")) { |
| 77 | ✗ | muxSwitchDelay = config["muxSwitchDelay"].asInt(); | |
| 78 | ✗ | if (muxSwitchDelay < 0) { | |
| 79 | ✗ | muxSwitchDelay = 0; | |
| 80 | ✗ | } else if (muxSwitchDelay > kMaxMuxSwitchDelayMs) { | |
| 81 | ✗ | muxSwitchDelay = kMaxMuxSwitchDelayMs; | |
| 82 | } | ||
| 83 | } | ||
| 84 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (config.isMember("muxSwitchReadCount")) { |
| 85 | ✗ | muxSwitchReadCount = config["muxSwitchReadCount"].asInt(); | |
| 86 | ✗ | if (muxSwitchReadCount < 0) { | |
| 87 | ✗ | muxSwitchReadCount = 0; | |
| 88 | ✗ | } else if (muxSwitchReadCount > kMaxMuxSwitchReadCount) { | |
| 89 | ✗ | muxSwitchReadCount = kMaxMuxSwitchReadCount; | |
| 90 | } | ||
| 91 | } | ||
| 92 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
9 | } |
| 93 | 12 | MuxSensorSource::~MuxSensorSource() { | |
| 94 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
6 | for (auto p : pins) { |
| 95 | ✗ | p->releasePin(); | |
| 96 | } | ||
| 97 | 12 | } | |
| 98 | |||
| 99 | 1 | void MuxSensorSource::Init(std::map<int, std::function<bool(int)>>& callbacks) { | |
| 100 | 1 | std::map<int, std::function<bool(int)>> cb; | |
| 101 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!source) { |
| 102 | ✗ | return; | |
| 103 | } | ||
| 104 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | source->Init(cb); |
| 105 | 1 | updatingByCallback = false; | |
| 106 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!cb.empty()) { |
| 107 | ✗ | updatingByCallback = true; | |
| 108 | ✗ | for (auto& c : cb) { | |
| 109 | ✗ | auto call = c.second; | |
| 110 | ✗ | callbacks[c.first] = [call, this](int i) { | |
| 111 | ✗ | std::lock_guard<std::recursive_mutex> lk(muxLock); | |
| 112 | ✗ | call(i); | |
| 113 | ✗ | if (updateCount > 0) { | |
| 114 | ✗ | getValues(); | |
| 115 | } | ||
| 116 | ✗ | updateCount = 1 + updateCount; | |
| 117 | ✗ | if (updateCount == 4) { | |
| 118 | ✗ | nextMux(); | |
| 119 | } | ||
| 120 | ✗ | return false; | |
| 121 | ✗ | }; | |
| 122 | ✗ | } | |
| 123 | } | ||
| 124 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | } |
| 125 | 75 | void MuxSensorSource::nextMux() { | |
| 126 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
|
75 | if (lockedToGroup) { |
| 127 | ✗ | return; | |
| 128 | } | ||
| 129 |
3/6✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 75 times.
|
75 | if (!source || channelsPerMux <= 0 || muxCount <= 0) { |
| 130 | ✗ | return; | |
| 131 | } | ||
| 132 |
3/6✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 75 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 75 times.
|
75 | if (curMux < 0 || curMux >= muxCount) { |
| 133 | ✗ | curMux = 0; | |
| 134 | } | ||
| 135 | 75 | int cm = curMux; | |
| 136 | 75 | int64_t start64 = (int64_t)cm * (int64_t)channelsPerMux; | |
| 137 |
2/2✓ Branch 0 taken 150 times.
✓ Branch 1 taken 75 times.
|
225 | for (int x = 0; x < channelsPerMux; x++) { |
| 138 | 150 | int64_t idx = start64 + x; | |
| 139 |
4/8✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 150 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 150 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 150 times.
|
150 | if (idx < 0 || (uint64_t)idx >= enabled.size() || (uint64_t)idx >= current.size()) { |
| 140 | ✗ | continue; | |
| 141 | } | ||
| 142 |
7/10✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 150 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 150 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✓ Branch 7 taken 141 times.
✓ Branch 8 taken 9 times.
✓ Branch 9 taken 141 times.
|
150 | if (enabled[(size_t)idx] && !current[(size_t)idx]) { |
| 143 | 9 | getValues(); | |
| 144 | } | ||
| 145 | } | ||
| 146 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 57 times.
|
75 | if ((curMux + 1) >= muxCount) { |
| 147 | 18 | curMux = 0; | |
| 148 | } else { | ||
| 149 | 57 | curMux = 1 + curMux; | |
| 150 | } | ||
| 151 | 75 | updateCount = 0; | |
| 152 | 75 | cm = curMux; | |
| 153 | 75 | start64 = (int64_t)cm * (int64_t)channelsPerMux; | |
| 154 |
2/2✓ Branch 0 taken 150 times.
✓ Branch 1 taken 75 times.
|
225 | for (int x = 0; x < channelsPerMux; x++) { |
| 155 | 150 | int64_t idx = start64 + x; | |
| 156 |
3/6✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 150 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 150 times.
|
150 | if (idx < 0 || (uint64_t)idx >= current.size()) { |
| 157 | ✗ | continue; | |
| 158 | } | ||
| 159 |
1/2✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
|
150 | current[(size_t)idx] = false; |
| 160 | } | ||
| 161 | 75 | setGroupPins(); | |
| 162 | } | ||
| 163 | 75 | void MuxSensorSource::setGroupPins() { | |
| 164 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
|
75 | if (!source) { |
| 165 | ✗ | return; | |
| 166 | } | ||
| 167 | 75 | int tmp = curMux; | |
| 168 |
2/2✓ Branch 0 taken 150 times.
✓ Branch 1 taken 75 times.
|
225 | for (auto& a : pins) { |
| 169 |
1/2✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
|
150 | a->setValue(tmp & 0x1 ? 1 : 0); |
| 170 | 150 | tmp >>= 1; | |
| 171 | } | ||
| 172 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
|
75 | if (muxSwitchDelay > 0) { |
| 173 | ✗ | std::this_thread::sleep_for(std::chrono::milliseconds(muxSwitchDelay)); | |
| 174 | } | ||
| 175 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
|
75 | for (int x = 0; x < muxSwitchReadCount; x++) { |
| 176 | ✗ | source->update(true); | |
| 177 | } | ||
| 178 | } | ||
| 179 | ✗ | void MuxSensorSource::lockToGroup(int i) { | |
| 180 | ✗ | std::lock_guard<std::recursive_mutex> lk(muxLock); | |
| 181 | ✗ | if (!source || channelsPerMux <= 0 || muxCount <= 0) { | |
| 182 | ✗ | return; | |
| 183 | } | ||
| 184 | ✗ | if (i >= 0 && i < muxCount) { | |
| 185 | ✗ | lockedToGroup = true; | |
| 186 | ✗ | if (curMux != i) { | |
| 187 | ✗ | curMux = i; | |
| 188 | ✗ | updateCount = 0; | |
| 189 | } | ||
| 190 | ✗ | setGroupPins(); | |
| 191 | ✗ | } else if (lockedToGroup) { | |
| 192 | ✗ | lockedToGroup = false; | |
| 193 | ✗ | nextMux(); | |
| 194 | } | ||
| 195 | ✗ | } | |
| 196 | |||
| 197 | 263 | void MuxSensorSource::getValues() { | |
| 198 |
3/6✓ Branch 0 taken 263 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 263 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 263 times.
|
263 | if (!source || channelsPerMux <= 0 || muxCount <= 0) { |
| 199 | ✗ | return; | |
| 200 | } | ||
| 201 |
3/6✓ Branch 0 taken 263 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 263 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 263 times.
|
263 | if (curMux < 0 || curMux >= muxCount) { |
| 202 | ✗ | return; | |
| 203 | } | ||
| 204 | 263 | int cm = curMux; | |
| 205 | 263 | int64_t start = (int64_t)cm * (int64_t)channelsPerMux; | |
| 206 |
2/2✓ Branch 0 taken 526 times.
✓ Branch 1 taken 263 times.
|
789 | for (int x = 0; x < channelsPerMux; x++) { |
| 207 | 526 | int64_t idx = start + x; | |
| 208 |
1/2✓ Branch 0 taken 526 times.
✗ Branch 1 not taken.
|
526 | if (idx < 0 || (uint64_t)idx >= enabled.size() || |
| 209 |
4/8✓ Branch 0 taken 526 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 526 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 526 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 526 times.
|
1052 | (uint64_t)idx >= values.size() || (uint64_t)idx >= current.size()) { |
| 210 | ✗ | continue; | |
| 211 | } | ||
| 212 |
2/4✓ Branch 0 taken 526 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 526 times.
✗ Branch 3 not taken.
|
526 | if (enabled[(size_t)idx]) { |
| 213 | 526 | values[(size_t)idx] = source->getValue(x); | |
| 214 |
1/2✓ Branch 0 taken 526 times.
✗ Branch 1 not taken.
|
526 | current[(size_t)idx] = true; |
| 215 | } | ||
| 216 | } | ||
| 217 | } | ||
| 218 | |||
| 219 | 302 | void MuxSensorSource::update(bool forceInstant) { | |
| 220 |
1/2✓ Branch 0 taken 302 times.
✗ Branch 1 not taken.
|
302 | std::lock_guard<std::recursive_mutex> lk(muxLock); |
| 221 |
3/6✓ Branch 0 taken 302 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 302 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 302 times.
|
302 | if (!source || channelsPerMux <= 0 || muxCount <= 0) { |
| 222 | ✗ | return; | |
| 223 | } | ||
| 224 |
1/2✓ Branch 0 taken 302 times.
✗ Branch 1 not taken.
|
302 | if (!updatingByCallback) { |
| 225 |
4/6✓ Branch 0 taken 302 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 226 times.
✓ Branch 4 taken 302 times.
✗ Branch 5 not taken.
|
302 | source->update(forceInstant || (updateCount == 0)); |
| 226 | 302 | updateCount = 1 + updateCount; | |
| 227 |
2/2✓ Branch 0 taken 75 times.
✓ Branch 1 taken 227 times.
|
302 | if (updateCount == 4) { |
| 228 |
1/2✓ Branch 0 taken 75 times.
✗ Branch 1 not taken.
|
75 | nextMux(); |
| 229 | } else { | ||
| 230 | 227 | int cm = curMux; | |
| 231 | 227 | int64_t start = (int64_t)cm * (int64_t)channelsPerMux; | |
| 232 |
2/2✓ Branch 0 taken 454 times.
✓ Branch 1 taken 227 times.
|
681 | for (int x = 0; x < channelsPerMux; x++) { |
| 233 | 454 | int64_t idx = start + x; | |
| 234 |
3/6✓ Branch 0 taken 454 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 454 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 454 times.
|
454 | if (idx < 0 || (uint64_t)idx >= current.size()) { |
| 235 | ✗ | continue; | |
| 236 | } | ||
| 237 |
1/2✓ Branch 0 taken 454 times.
✗ Branch 1 not taken.
|
454 | current[(size_t)idx] = false; |
| 238 | } | ||
| 239 | } | ||
| 240 | } | ||
| 241 |
1/2✓ Branch 0 taken 302 times.
✗ Branch 1 not taken.
|
302 | } |
| 242 | 8 | void MuxSensorSource::enable(int id) { | |
| 243 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | std::lock_guard<std::recursive_mutex> lk(muxLock); |
| 244 |
4/8✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 8 times.
|
8 | if (!source || channelsPerMux <= 0 || muxCount <= 0 || id < 0) { |
| 245 | ✗ | return; | |
| 246 | } | ||
| 247 | // Valid mux channels are 0 .. channelsPerMux*muxCount-1. Anything else is | ||
| 248 | // a corrupt sensors.json entry: ignore it instead of growing the vectors | ||
| 249 | // without bound (OOM) via resize(id+1). | ||
| 250 | 8 | int64_t total = (int64_t)channelsPerMux * (int64_t)muxCount; | |
| 251 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if ((int64_t)id >= total) { |
| 252 | ✗ | return; | |
| 253 | } | ||
| 254 | |||
| 255 | 8 | int i = id % channelsPerMux; | |
| 256 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | source->enable(i); |
| 257 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if ((size_t)id >= values.size()) { |
| 258 | 8 | size_t need = (size_t)id + 1; | |
| 259 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | values.resize(need); |
| 260 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | enabled.resize(need); |
| 261 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | current.resize(need); |
| 262 | } | ||
| 263 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | enabled[(size_t)id] = true; |
| 264 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | current[(size_t)id] = false; |
| 265 | 8 | values[(size_t)id] = 0; | |
| 266 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | } |
| 267 | 2416 | int32_t MuxSensorSource::getValue(int id) { | |
| 268 |
1/2✓ Branch 0 taken 2416 times.
✗ Branch 1 not taken.
|
2416 | std::lock_guard<std::recursive_mutex> lk(muxLock); |
| 269 |
5/10✓ Branch 0 taken 2416 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2416 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2416 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2416 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2416 times.
|
2416 | if (!source || channelsPerMux <= 0 || id < 0 || (size_t)id >= values.size()) { |
| 270 | ✗ | return 0; | |
| 271 | } | ||
| 272 |
3/6✓ Branch 0 taken 2416 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2416 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2416 times.
|
2416 | if ((size_t)id >= enabled.size() || (size_t)id >= current.size()) { |
| 273 | ✗ | return values[(size_t)id]; | |
| 274 | } | ||
| 275 |
7/10✓ Branch 0 taken 2416 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2416 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2416 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 292 times.
✓ Branch 7 taken 2124 times.
✓ Branch 8 taken 292 times.
✓ Branch 9 taken 2124 times.
|
2416 | if (enabled[(size_t)id] && !current[(size_t)id]) { |
| 276 | 292 | int i = id / channelsPerMux; | |
| 277 |
2/2✓ Branch 0 taken 254 times.
✓ Branch 1 taken 38 times.
|
292 | if (i == curMux) { |
| 278 |
1/2✓ Branch 0 taken 254 times.
✗ Branch 1 not taken.
|
254 | getValues(); |
| 279 | } | ||
| 280 | } | ||
| 281 | 2416 | return values[(size_t)id]; | |
| 282 | 2416 | } | |
| 283 |