71 bool open(
const std::string &port,
int settleMs = 0);
72 bool open(
const std::string &port,
int settleMs,
bool exclusive);
88 int connect(
const std::string &port,
int settleMs = 0);
103 std::string *detail =
nullptr);
105 std::string *detail =
nullptr);
124 unsigned long long &verifiedSeq);
157 int setOutput(
unsigned firmwareIndex,
bool enabled);
172 cancelFn_ = std::move(fn);
176 void setWriteFunctionForTesting(std::function<ssize_t(
int,
const void *,
size_t)> fn)
178 writeFn_ = std::move(fn);
180 void setFdForTesting(
int fd)
184 int syncWriteForTesting(
const std::string &command);
185 size_t queuedCommandCountForTesting();
186 void injectStatusForTesting(
const StatusFrame &status);
188 bool parseFirmwarePayloadForTesting(
const std::string &frame, std::string &raw,
int &numeric)
const;
196 std::string &error)
const;
207 struct TelemetryCallbackEntry;
208 struct ConnectionCallbackEntry;
211 int lastOpenErrno_ = 0;
212 bool lastOpenBusy_ =
false;
213 int wakeReadFd_ = -1;
214 int wakeWriteFd_ = -1;
215 std::string lastPort_;
216 int lastSettleMs_ = 0;
217 std::atomic<bool> connected_{
false};
218 std::atomic<bool> communicationFailureNotified_{
false};
219 std::atomic<std::uint64_t> connectionGeneration_{0};
220 mutable instrumentation::Dispatcher instrumentation_;
222 mutable std::mutex firmwareMutex_;
223 std::string firmwareVersionRaw_;
224 int firmwareVersionNumeric_ = 0;
225 bool haveFirmwareVersion_ =
false;
228 std::mutex cacheMutex_;
229 std::condition_variable frameCv_;
230 StatusFrame cachedStatus_{};
231 unsigned long long frameSeq_{0};
232 std::chrono::steady_clock::time_point lastFrameTime_{};
239 std::mutex queueMutex_;
240 std::condition_variable queueCv_;
241 std::deque<std::string> queue_;
242 static constexpr size_t kQueueCap = 16;
245 std::mutex writeMutex_;
246 std::function<ssize_t(
int,
const void *,
size_t)> writeFn_;
247 std::function<bool()> cancelFn_;
249 std::mutex telemetryCallbackMutex_;
250 std::mutex callbackDispatchMutex_;
251 std::condition_variable callbackDispatchCv_;
252 bool callbackDispatchInProgress_ =
false;
253 std::vector<std::shared_ptr<TelemetryCallbackEntry>> telemetryCallbacks_;
256 std::mutex connectionCallbackMutex_;
257 std::vector<std::shared_ptr<ConnectionCallbackEntry>> connectionCallbacks_;
262 bool transactOnce(
const std::string &command, std::string &response,
267 std::string &response,
268 std::string *detail);
269 bool readFrameOnce(std::string &response,
int timeoutMs);
270 bool readTokenFrameOnce(
char token, std::string &response,
int timeoutMs);
271 bool parseFirmwareFrame(
const std::string &frame, std::string &raw,
int &numeric)
const;
272 int connectInternal(
const std::string &port,
int settleMs,
ConnectionEvent successEvent);
273 bool cancelled()
const;
274 bool sleepCancelable(
int milliseconds)
const;
277 void readerLoop(
int serialFd,
int wakeFd);
280 TelemetrySnapshot storeStatusFrame(
const StatusFrame &status,
bool dispatchCallbacks);
281 TelemetrySnapshot makeTelemetrySnapshot(
const StatusFrame &status,
282 unsigned long long sequence,
283 std::chrono::steady_clock::time_point timestamp)
const;
284 void beginCallbackDispatch();
285 void endCallbackDispatch();
286 void dispatchTelemetrySnapshot(
const TelemetrySnapshot &snapshot);
287 void dispatchConnectionEvent(
ConnectionEvent event,
const std::string &reason = std::string());
288 void notifyCommunicationFailure(
const std::string &reason);
293 bool writeAllLocked(
const std::string &command);
295 int syncCommand(
const std::string &command);
298 int enqueueCommand(
const std::string &command);
300 void drainInputLocked();
302 void closeWakePipe();
303 void signalReaderWake();
304 void drainReaderWake(
int wakeFd);
306 void emitInstrumentationEvent(instrumentation::Event event)
const;
309 const std::string &reason = std::string())
const;
311 const std::string &frame)
const;
314 const std::string &message)
const;
317 const std::string &detail,
318 const std::string &frame = std::string())
const;
319 void emitReconnectInstrumentation(
unsigned attempt,
320 unsigned maxAttempts,
321 std::chrono::milliseconds delayBeforeAttempt,
325 std::chrono::steady_clock::time_point start,
328 const std::string &detail,
329 unsigned long long relatedSequence)
const;