Add a saved override to keep USB packet logging continuous
This commit is contained in:
1 parent
1f2fcfc449
commit
05679aa741
18 files changed
+382
-39
No files matched your search
@@ -1055,6 +1055,7 @@ void CommonCLI::loadPrefs(FILESYSTEM* fs) {
|
||||
_prefs->usb_logging_enabled = 1;
|
||||
#endif
|
||||
_prefs->usb_debug_enabled = 0;
|
||||
_prefs->usb_logging_always = 0;
|
||||
_prefs->trace_when_repeat_off = 0;
|
||||
_prefs->discovery_responses = mesh::discovery::DEFAULT_RESPONSES;
|
||||
_prefs->ota_channel = 0;
|
||||
@@ -1295,6 +1296,7 @@ void CommonCLI::loadPrefs(FILESYSTEM* fs) {
|
||||
#endif
|
||||
#if MESH_USB_LOGGING_AVAILABLE
|
||||
mesh::setUsbDebugEnabled(_prefs->usb_debug_enabled != 0);
|
||||
mesh::setUsbPacketLoggingAlways(_prefs->usb_logging_always != 0);
|
||||
mesh::setUsbLoggingEnabled(_prefs->usb_logging_enabled != 0);
|
||||
#endif
|
||||
_radio_profiles.adoptPrimaryPreamble(_prefs->primary_radio_preamble);
|
||||
@@ -1329,6 +1331,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
// Older or truncated preference images must never inherit these opt-ins
|
||||
// from a previous load of a newer image.
|
||||
_prefs->usb_debug_enabled = 0;
|
||||
_prefs->usb_logging_always = 0;
|
||||
_prefs->trace_when_repeat_off = 0;
|
||||
_prefs->discovery_responses = mesh::discovery::DEFAULT_RESPONSES;
|
||||
_prefs->gps_sync_interval_hours = 0;
|
||||
@@ -1408,7 +1411,9 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
file.read((uint8_t *)&_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120
|
||||
file.read((uint8_t *)&_prefs->path_hash_mode, sizeof(_prefs->path_hash_mode)); // 121
|
||||
file.read((uint8_t *)&_prefs->loop_detect, sizeof(_prefs->loop_detect)); // 122
|
||||
file.read(pad, 1); // 123
|
||||
uint8_t usb_logging_policy = 0;
|
||||
file.read(&usb_logging_policy, 1); // 123: formerly padding
|
||||
_prefs->usb_logging_always = usb_logging_policy == 0xA1 ? 1 : 0;
|
||||
file.read((uint8_t *)&_prefs->flood_max, sizeof(_prefs->flood_max)); // 124
|
||||
file.read((uint8_t *)&_prefs->flood_advert_interval, sizeof(_prefs->flood_advert_interval)); // 125
|
||||
file.read((uint8_t *)&_prefs->interference_threshold, sizeof(_prefs->interference_threshold)); // 126
|
||||
@@ -1963,6 +1968,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
|
||||
_prefs->usb_logging_enabled = constrain(_prefs->usb_logging_enabled, 0, 1); // boolean
|
||||
// Only a deliberately saved 1 enables diagnostics; corrupted bytes are OFF.
|
||||
_prefs->usb_debug_enabled = _prefs->usb_debug_enabled == 1 ? 1 : 0;
|
||||
_prefs->usb_logging_always = _prefs->usb_logging_always == 1 ? 1 : 0;
|
||||
// Corrupt or unknown values must not enable a repeat-off exception.
|
||||
_prefs->trace_when_repeat_off = _prefs->trace_when_repeat_off == 1 ? 1 : 0;
|
||||
_prefs->cad_enabled = constrain(_prefs->cad_enabled, 0, 1); // boolean
|
||||
@@ -2093,7 +2099,8 @@ static bool writeCommonPrefsImage(Writer& writer, NodePrefs* prefs) {
|
||||
WRITE_COMMON_PREFS(&prefs->agc_reset_interval); // 120
|
||||
WRITE_COMMON_PREFS(&prefs->path_hash_mode); // 121
|
||||
WRITE_COMMON_PREFS(&prefs->loop_detect); // 122
|
||||
WRITE_COMMON_PREFS_BYTES(pad, 1); // 123
|
||||
const uint8_t usb_logging_policy = prefs->usb_logging_always == 1 ? 0xA1 : 0;
|
||||
WRITE_COMMON_PREFS(&usb_logging_policy); // 123: formerly padding
|
||||
WRITE_COMMON_PREFS(&prefs->flood_max); // 124
|
||||
WRITE_COMMON_PREFS(&prefs->flood_advert_interval); // 125
|
||||
WRITE_COMMON_PREFS(&prefs->interference_threshold); // 126
|
||||
@@ -2311,6 +2318,7 @@ void CommonCLI::savePrefs(FILESYSTEM* fs, PrefsSaveRouting::Scope scope) {
|
||||
_common_save_result_known = true;
|
||||
_common_save_succeeded = false;
|
||||
_prefs->usb_debug_enabled = _prefs->usb_debug_enabled == 1 ? 1 : 0;
|
||||
_prefs->usb_logging_always = _prefs->usb_logging_always == 1 ? 1 : 0;
|
||||
_prefs->trace_when_repeat_off = _prefs->trace_when_repeat_off == 1 ? 1 : 0;
|
||||
if (_prefs->discovery_responses > mesh::discovery::DEFAULT_RESPONSES)
|
||||
_prefs->discovery_responses = mesh::discovery::DEFAULT_RESPONSES;
|
||||
@@ -2373,7 +2381,8 @@ void CommonCLI::savePrefs(FILESYSTEM* fs, PrefsSaveRouting::Scope scope) {
|
||||
file.write((uint8_t *)&_prefs->agc_reset_interval, sizeof(_prefs->agc_reset_interval)); // 120
|
||||
file.write((uint8_t *)&_prefs->path_hash_mode, sizeof(_prefs->path_hash_mode)); // 121
|
||||
file.write((uint8_t *)&_prefs->loop_detect, sizeof(_prefs->loop_detect)); // 122
|
||||
file.write(pad, 1); // 123
|
||||
const uint8_t usb_logging_policy = _prefs->usb_logging_always == 1 ? 0xA1 : 0;
|
||||
file.write(&usb_logging_policy, 1); // 123: formerly padding
|
||||
file.write((uint8_t *)&_prefs->flood_max, sizeof(_prefs->flood_max)); // 124
|
||||
file.write((uint8_t *)&_prefs->flood_advert_interval, sizeof(_prefs->flood_advert_interval)); // 125
|
||||
file.write((uint8_t *)&_prefs->interference_threshold, sizeof(_prefs->interference_threshold)); // 126
|
||||
@@ -2499,6 +2508,7 @@ void CommonCLI::savePrefs(FILESYSTEM* fs, PrefsSaveRouting::Scope scope) {
|
||||
// Dynamic config imports use this path too. Do not enable diagnostics
|
||||
// until the corresponding common preference image is committed.
|
||||
mesh::setUsbDebugEnabled(_prefs->usb_debug_enabled != 0);
|
||||
mesh::setUsbPacketLoggingAlways(_prefs->usb_logging_always != 0);
|
||||
mesh::setUsbLoggingEnabled(_prefs->usb_logging_enabled != 0);
|
||||
}
|
||||
#endif
|
||||
@@ -4438,6 +4448,29 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
}
|
||||
#endif
|
||||
#if MESH_USB_LOGGING_AVAILABLE
|
||||
#if !defined(MESH_DUAL_CDC_LOGGING)
|
||||
if (strncmp(config, "usb.logging.always", 18) == 0
|
||||
&& (config[18] == 0 || config[18] == ' ' || config[18] == '\t')) {
|
||||
const char* value = config + 18;
|
||||
while (*value == ' ' || *value == '\t') value++;
|
||||
bool enabled = false, reboot_if_needed = false;
|
||||
if (!mesh::cli::parseLoggingToggle(value, enabled, reboot_if_needed)
|
||||
|| reboot_if_needed) {
|
||||
mesh::cli::formatError(reply, 160, "usage set usb.logging.always on|off");
|
||||
return;
|
||||
}
|
||||
const uint8_t previous = _prefs->usb_logging_always;
|
||||
_prefs->usb_logging_always = enabled ? 1 : 0;
|
||||
if (!trySavePrefs()) {
|
||||
_prefs->usb_logging_always = previous;
|
||||
mesh::cli::formatError(reply, 160, "save unconfirmed; reboot may differ");
|
||||
return;
|
||||
}
|
||||
mesh::setUsbPacketLoggingAlways(enabled);
|
||||
snprintf(reply, 160, "OK - USB logging always %s (saved)", enabled ? "on" : "off");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (strncmp(config, "usb.logging", 11) == 0
|
||||
&& (config[11] == 0 || config[11] == ' ' || config[11] == '\t')) {
|
||||
const char* value = &config[11];
|
||||
@@ -6035,6 +6068,12 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
|
||||
}
|
||||
#endif
|
||||
#if MESH_USB_LOGGING_AVAILABLE
|
||||
#if !defined(MESH_DUAL_CDC_LOGGING)
|
||||
if (strcmp(config, "usb.logging.always") == 0) {
|
||||
snprintf(reply, 160, "> %s", mesh::isUsbPacketLoggingAlways() ? "on" : "off");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (strcmp(config, "usb.logging") == 0) {
|
||||
snprintf(reply, 160, "> %s",
|
||||
mesh::isUsbLoggingEnabled() ? "on" : "off");
|
||||
|
||||
@@ -201,6 +201,8 @@ public:
|
||||
// USB diagnostics are opt-in independently of the packet output gate.
|
||||
// Appended after GPS sync cadence in /com_prefs, not beside usb_log.
|
||||
uint8_t usb_debug_enabled = 0;
|
||||
// Reuses reserved /com_prefs byte 123; 0xA1 on disk means enabled.
|
||||
uint8_t usb_logging_always = 0;
|
||||
// Repeater-only opt-in for routed trace diagnostics while repeat is off.
|
||||
// Appended after usb_debug in /com_prefs; existing images stay disabled.
|
||||
uint8_t trace_when_repeat_off = 0;
|
||||
@@ -386,6 +388,7 @@ private:
|
||||
def("format", _parent->bridge_format);
|
||||
def("usb_log", _parent->usb_logging_enabled);
|
||||
def("usb_dbg", _parent->usb_debug_enabled);
|
||||
def("usb_always", _parent->usb_logging_always);
|
||||
#ifdef WITH_RS232_BRIDGE
|
||||
def("rs232_heartbeat", _parent->rs232_heartbeat);
|
||||
def("rs232_autosleep", _parent->rs232_autosleep);
|
||||
|
||||
@@ -96,6 +96,7 @@ static std::atomic<bool> usb_logging_preference_known{false};
|
||||
static std::atomic<bool> usb_debug_enabled{false};
|
||||
#if MESH_USB_LOGGING_AVAILABLE && !defined(MESH_DUAL_CDC_LOGGING)
|
||||
static std::atomic<uint32_t> usb_packet_logging_quiet_until{0};
|
||||
static std::atomic<bool> usb_packet_logging_always{false};
|
||||
#endif
|
||||
#if MESH_ENABLE_HOST_KISS
|
||||
static std::atomic<bool> usb_binary_stream_owned{false};
|
||||
@@ -1299,7 +1300,8 @@ bool isUsbLoggingEnabled() {
|
||||
|
||||
#if MESH_USB_LOGGING_AVAILABLE && !defined(MESH_DUAL_CDC_LOGGING)
|
||||
void noteUsbConsoleCommand(const char* command) {
|
||||
if (command == nullptr || hasDedicatedUsbLoggingPort() || isUsbLoggingPacketStream()) return;
|
||||
if (command == nullptr || isUsbPacketLoggingAlways()
|
||||
|| hasDedicatedUsbLoggingPort() || isUsbLoggingPacketStream()) return;
|
||||
while (*command == ' ' || *command == '\t' || *command == '\r' || *command == '\n') ++command;
|
||||
if (*command == 0 || isUsbLoggingStatsCommand(command)) return;
|
||||
for (const unsigned char* p = reinterpret_cast<const unsigned char*>(command); *p; ++p) {
|
||||
@@ -1314,6 +1316,15 @@ void resumeUsbPacketLogging() {
|
||||
usb_packet_logging_quiet_until.store(0, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void setUsbPacketLoggingAlways(bool enabled) {
|
||||
usb_packet_logging_always.store(enabled, std::memory_order_relaxed);
|
||||
if (enabled) resumeUsbPacketLogging();
|
||||
}
|
||||
|
||||
bool isUsbPacketLoggingAlways() {
|
||||
return usb_packet_logging_always.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
bool isUsbPacketLoggingAllowed() {
|
||||
uint32_t deadline = usb_packet_logging_quiet_until.load(std::memory_order_relaxed);
|
||||
bool quiet = deadline != 0;
|
||||
@@ -1323,7 +1334,7 @@ bool isUsbPacketLoggingAllowed() {
|
||||
deadline, 0, std::memory_order_relaxed) && deadline != 0;
|
||||
}
|
||||
return isUsbLoggingEnabled()
|
||||
&& (hasDedicatedUsbLoggingPort() || isUsbLoggingPacketStream() || !quiet);
|
||||
&& (isUsbPacketLoggingAlways() || hasDedicatedUsbLoggingPort() || isUsbLoggingPacketStream() || !quiet);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -98,6 +98,8 @@ void setUsbLoggingEnabled(bool enabled);
|
||||
inline void noteUsbConsoleCommand(const char*) {}
|
||||
inline void resumeUsbPacketLogging() {}
|
||||
inline bool isUsbPacketLoggingAllowed() { return isUsbLoggingEnabled(); }
|
||||
inline void setUsbPacketLoggingAlways(bool) {}
|
||||
inline bool isUsbPacketLoggingAlways() { return false; }
|
||||
#elif MESH_USB_LOGGING_AVAILABLE
|
||||
// Human console commands pause packet records for five minutes without
|
||||
// changing the saved logging setting, functional replies, or debug output.
|
||||
@@ -106,10 +108,15 @@ inline bool isUsbPacketLoggingAllowed() { return isUsbLoggingEnabled(); }
|
||||
void noteUsbConsoleCommand(const char* command);
|
||||
void resumeUsbPacketLogging();
|
||||
bool isUsbPacketLoggingAllowed();
|
||||
// The role persists this shared-port policy; it never enables the master gate.
|
||||
void setUsbPacketLoggingAlways(bool enabled);
|
||||
bool isUsbPacketLoggingAlways();
|
||||
#else
|
||||
inline void noteUsbConsoleCommand(const char*) {}
|
||||
inline void resumeUsbPacketLogging() {}
|
||||
inline bool isUsbPacketLoggingAllowed() { return false; }
|
||||
inline void setUsbPacketLoggingAlways(bool) {}
|
||||
inline bool isUsbPacketLoggingAlways() { return false; }
|
||||
#endif
|
||||
// Verbose diagnostics are opt-in and persisted by the role preferences.
|
||||
// The requested setting survives switching the master USB output gate off.
|
||||
|
||||
Reference in new issue
Block a user