The logger loop disable optimization was guarded by USE_LOGGER_USB_CDC,
which is a platform capability flag defined whenever the platform
supports USB CDC. This meant the optimization was disabled on all
ESP32-S2, S3, C3, C5, C6, C61, H2, and P4 variants regardless of
whether USB CDC was actually selected as the hardware UART.
Changed all guards to use USE_LOGGER_UART_SELECTION_USB_CDC which is
only defined when USB CDC is the selected hardware UART. Also changed
the guard logic from || to && so the loop only stays permanently active
when both Zephyr AND USB CDC is selected (the only case that needs
cdc_loop_() to poll port readiness).
Additionally set USE_LOGGER_UART_SELECTION_USB_CDC in the Zephyr
codepath when USB CDC is selected, and updated defines.h for static
analysis coverage.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Bump the pioarduino ESP-IDF framework from v5.5.3 to v5.5.3.1 which
fixes the gatt_main.c compile error when GATTS is disabled. This allows
reverting the workaround that unconditionally enabled CONFIG_BT_GATTS_ENABLE.
Also update _format_framework_espidf_version to support dot-separated
sub-release versions (e.g., 5.5.3.1) in both the tag and asset filename.
Log a warning when a client connects with an API version older than
1.14. This alerts users that their client needs updating before the
backward-compatibility code for pre-1.14 clients is removed in 2026.7.0.
Same pattern as the decode side - the bit manipulation was
duplicated in the main loop and tail path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
base64_find_char() safely handles any input including 0,
returning 0 via strchr fallback - no special contract needed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fold the output copy loop into base64_decode_quad_ since both
call sites use the same truncation-checked copy logic, differing
only in count (3 vs i-1).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The base64 character-to-byte conversion and output copy loop were
duplicated in both the main decode loop and the tail/padding path.
Extract into a shared static helper to reduce flash usage (-64 bytes
on ESP32) and eliminate duplicated logic.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The base64 character-to-byte conversion was duplicated in both the
main decode loop and the tail/padding path. Extract into a shared
static helper to reduce flash usage (-64 bytes on ESP32).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the scheduler lock is already held, atomic loads of the remove
flag don't need acquire ordering — the mutex provides all necessary
synchronization guarantees. Add is_item_removed_locked_() helper that
uses memory_order_relaxed and use it in all _locked_ call sites.
This eliminates redundant memw barriers on Xtensa, saving 12 bytes
in matches_item_locked_ (152 → 140 B) and reducing pipeline stalls
in the scheduler hot path.
Replace the std::chrono::steady_clock approach with the scheduler's
existing millis_64() rollover tracking. This avoids pulling in
gettimeofday_r, system_clock, and the ArduinoJson int64_t serializer
template, saving ~270 bytes of flash and 8 bytes of RAM on ESP8266.
Send uptime as uint32_t seconds (good for ~136 years) instead of
int64_t milliseconds.