From 1f2fcfc449ff828c40b2bc8296c9e6706e0942cf Mon Sep 17 00:00:00 2001 From: mikecarper Date: Tue, 27 Oct 2026 18:23:01 -0700 Subject: [PATCH] Keep dedicated USB logging quiet hooks out of nRF52 Full images --- src/helpers/UsbLogging.cpp | 4 ++-- src/helpers/UsbLogging.h | 8 +++++++- test/test_companion_fleet_control.py | 1 + test/test_usb_packet_logging_quiet.py | 29 +++++++++++++++++++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/helpers/UsbLogging.cpp b/src/helpers/UsbLogging.cpp index d13f1fcf1..32ec83907 100644 --- a/src/helpers/UsbLogging.cpp +++ b/src/helpers/UsbLogging.cpp @@ -94,7 +94,7 @@ static std::atomic usb_logging_enabled{true}; #endif static std::atomic usb_logging_preference_known{false}; static std::atomic usb_debug_enabled{false}; -#if MESH_USB_LOGGING_AVAILABLE +#if MESH_USB_LOGGING_AVAILABLE && !defined(MESH_DUAL_CDC_LOGGING) static std::atomic usb_packet_logging_quiet_until{0}; #endif #if MESH_ENABLE_HOST_KISS @@ -1297,7 +1297,7 @@ bool isUsbLoggingEnabled() { return usb_logging_enabled.load(std::memory_order_relaxed); } -#if MESH_USB_LOGGING_AVAILABLE +#if MESH_USB_LOGGING_AVAILABLE && !defined(MESH_DUAL_CDC_LOGGING) void noteUsbConsoleCommand(const char* command) { if (command == nullptr || hasDedicatedUsbLoggingPort() || isUsbLoggingPacketStream()) return; while (*command == ' ' || *command == '\t' || *command == '\r' || *command == '\n') ++command; diff --git a/src/helpers/UsbLogging.h b/src/helpers/UsbLogging.h index 4e514d15d..b317f1c67 100644 --- a/src/helpers/UsbLogging.h +++ b/src/helpers/UsbLogging.h @@ -92,7 +92,13 @@ inline size_t nextUsbLoggingIdentityOffset(size_t current_offset, // protect framed traffic and restores its saved choice after preferences load. bool isUsbLoggingEnabled(); void setUsbLoggingEnabled(bool enabled); -#if MESH_USB_LOGGING_AVAILABLE +#if MESH_USB_LOGGING_AVAILABLE && defined(MESH_DUAL_CDC_LOGGING) +// Either the dedicated CDC or explicit packet stream owns capture in these +// builds. Both bypass quieting, so no timer or command parser is needed. +inline void noteUsbConsoleCommand(const char*) {} +inline void resumeUsbPacketLogging() {} +inline bool isUsbPacketLoggingAllowed() { return isUsbLoggingEnabled(); } +#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. // Dedicated logging endpoints, explicit packet streams, and stats polls keep diff --git a/test/test_companion_fleet_control.py b/test/test_companion_fleet_control.py index de8634ce4..c41dd5f64 100644 --- a/test/test_companion_fleet_control.py +++ b/test/test_companion_fleet_control.py @@ -46,6 +46,7 @@ static RescueStream rescue_input, rescue_output; namespace mesh { static bool usb_binary_owned = false; bool isUsbBinaryStreamOwned() { return usb_binary_owned; } +void noteUsbConsoleCommand(const char*) {} Stream& usbTerminalPort() { return rescue_output; } Stream& usbCompanionPort() { return rescue_input; } namespace hostkiss { diff --git a/test/test_usb_packet_logging_quiet.py b/test/test_usb_packet_logging_quiet.py index c98036766..6727d3d99 100644 --- a/test/test_usb_packet_logging_quiet.py +++ b/test/test_usb_packet_logging_quiet.py @@ -181,6 +181,35 @@ class UsbPacketLoggingQuietTests(unittest.TestCase): ran = subprocess.run([str(binary)], capture_output=True, text=True, timeout=20) self.assertEqual(ran.returncode, 0, ran.stdout + ran.stderr) + def test_dual_cdc_inline_apis_preserve_both_continuous_capture_modes(self): + source = (ROOT / "src/helpers/UsbLogging.cpp").read_text() + harness = ''' +#include +#include +#include +namespace mesh { +bool enabled=false,packet_stream=false; +bool isUsbLoggingEnabled(){return enabled;} +bool isUsbLoggingPacketStream(){return packet_stream;} +@DEDICATED@ +} +int main(){ + for(bool stream:{false,true})for(bool enabled:{false,true}){ + mesh::packet_stream=stream;mesh::enabled=enabled; + assert(mesh::hasDedicatedUsbLoggingPort()==!stream); + mesh::noteUsbConsoleCommand(nullptr);mesh::noteUsbConsoleCommand("get name"); + assert(mesh::isUsbPacketLoggingAllowed()==enabled); + mesh::resumeUsbPacketLogging(); + assert(mesh::isUsbPacketLoggingAllowed()==enabled); + } +} +'''.replace("@DEDICATED@", method(source, "bool hasDedicatedUsbLoggingPort(")) + with tempfile.TemporaryDirectory(prefix="meshcore-packet-dual-") as directory: + binary = self.compile(Path(directory), "dual", harness, + ["-DMESH_DEBUG=1", "-DMESH_DUAL_CDC_LOGGING=1"]) + ran = subprocess.run([str(binary)], capture_output=True, text=True, timeout=20) + self.assertEqual(ran.returncode, 0, ran.stdout + ran.stderr) + def test_disabled_logging_build_has_noop_pause_apis(self): with tempfile.TemporaryDirectory(prefix="meshcore-packet-disabled-") as directory: for flags in ([], ["-DMESH_DEBUG=1", "-DMESH_USB_LOGGING_DISABLED=1"]):