* feat: populate MyNodeInfo.device_id on all platforms RP2040/RP2350 use the 64-bit pico unique board id, STM32WL the 96-bit silicon UID, ESP32-S2 joins the existing OPTIONAL_UNIQUE_ID efuse branch, and everything else (classic ESP32 in particular) falls back to a deterministic factory-MAC-derived id, resolving the long-standing FIXME. Portduino keeps the config-supplied id preferred and now uses the MAC fallback when the config omits one. No proto or persistence changes; the id is re-read from silicon each boot and PhoneAPI still zeroes it for unauthenticated clients. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: declare zero_mac const to satisfy cppcheck Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix: address review feedback on device_id derivation Clear any disk-loaded device_id before the silicon derivation so a failed read leaves it unset rather than stale (Copilot), and size the portduino config copy with sizeof instead of a literal 16 (CodeRabbit). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor: extract device_id generation into per-arch getDeviceId() Per review feedback on #10995: move the platform-specific MyNodeInfo.device_id derivation out of the #if/#elif ladder in NodeDB.cpp into a getDeviceId() interface (target_specific.h) implemented per-architecture alongside each platform's getMacAddr(): - esp32: efuse OPTIONAL_UNIQUE_ID (C3/S2/S3/C6); classic ESP32 -> MAC - nrf52: FICR DEVICEID + DEVICEADDR - nrf54l15: FICR->INFO.DEVICEID + DEVICEADDR (NRF_FICR-guarded, MAC fallback) - rp2xx0: pico_get_unique_board_id() - stm32wl: HAL_GetUIDw0/1/2() - portduino: config-supplied id preferred, else MAC The shared MAC-derived fallback moves to meshUtils as getMacAddrDeviceId(). NodeDB.cpp now zero-inits the field and makes a single getDeviceId() call, dropping ~65 lines of platform boilerplate plus the esp_efuse/pico/stm32 includes that came with it. No behavior change: device_id is still re-read from silicon each boot and never persisted. Builds green: native-macos, tbeam, heltec-v3, rak4631, rak11310, rak3172. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: address review of device_id refactor - getMacAddrDeviceId(): zero-init the mac[6] buffer. getMacAddr() can return without writing (e.g. Portduino with no MAC source), so the old uninitialized buffer let stack garbage pass the all-zeros guard and become device_id. The pre-refactor code relied on the zero-initialized static ourMacAddr; restore that guarantee. - nrf54l15 getDeviceId(): drop the `#if defined(NRF_FICR)` guard and read FICR unconditionally (as the pre-refactor NodeDB code did). The guarded #else fell back to getMacAddr()'s hard-coded placeholder MAC, which would give every unit an identical device_id; a missing NRF_FICR should be a loud compile error. - NodeDB.cpp: `#include "target_specific.h"` instead of hand-copied externs for getMacAddr/getDeviceId; retire the stale FIXME. Same for meshUtils.cpp (whose extern comment wrongly claimed the TU was Arduino-free). - Delete the orphaned commented-out device_id hex-dump block in NodeDB.cpp. - Trim/de-duplicate the getDeviceId contract comments (single-sourced in target_specific.h). Builds green: native-macos, tbeam. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs: trim device_id comments to the repo's 1-2 line guideline Addresses CodeRabbit review nitpick on #10995: shorten the getDeviceId() (target_specific.h), getMacAddrDeviceId() (meshUtils.h), device-id refresh (NodeDB.cpp), and nrf54l15 getDeviceId comments to two lines each, per the "one or two lines maximum" coding guideline. Comment-only; no behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
91 lines
3.1 KiB
C++
91 lines
3.1 KiB
C++
#pragma once
|
|
#include "DebugConfiguration.h"
|
|
#include <algorithm>
|
|
#include <cstdarg>
|
|
#include <iterator>
|
|
#include <stdint.h>
|
|
|
|
/// C++ v17+ clamp function, limits a given value to a range defined by lo and hi
|
|
template <class T> constexpr const T &clamp(const T &v, const T &lo, const T &hi)
|
|
{
|
|
return (v < lo) ? lo : (hi < v) ? hi : v;
|
|
}
|
|
|
|
/// Return the smallest power of 2 >= n (undefined for n > 2^31)
|
|
static inline uint32_t nextPowerOf2(uint32_t n)
|
|
{
|
|
if (n <= 1)
|
|
return 1;
|
|
#if defined(__GNUC__)
|
|
return 1U << (32 - __builtin_clz(n - 1));
|
|
#else
|
|
n--;
|
|
n |= n >> 1;
|
|
n |= n >> 2;
|
|
n |= n >> 4;
|
|
n |= n >> 8;
|
|
n |= n >> 16;
|
|
return n + 1;
|
|
#endif
|
|
}
|
|
|
|
#if HAS_SCREEN
|
|
#define IF_SCREEN(X) \
|
|
if (screen) { \
|
|
X; \
|
|
}
|
|
#else
|
|
#define IF_SCREEN(...)
|
|
#endif
|
|
|
|
#if (defined(ARCH_PORTDUINO) && !defined(STRNSTR))
|
|
#define STRNSTR
|
|
#include <string.h>
|
|
char *strnstr(const char *s, const char *find, size_t slen);
|
|
#endif
|
|
|
|
void printBytes(const char *label, const uint8_t *p, size_t numbytes);
|
|
|
|
// is the memory region filled with a single character?
|
|
bool memfll(const uint8_t *mem, uint8_t find, size_t numbytes);
|
|
|
|
// getDeviceId() fallback (see target_specific.h): copies the 6-byte factory MAC, or returns false
|
|
// on an all-zero MAC so two blank devices don't collide on an all-zero id.
|
|
bool getMacAddrDeviceId(uint8_t *deviceId);
|
|
|
|
bool isOneOf(int item, int count, ...);
|
|
|
|
const std::string vformat(const char *const zcFormat, ...);
|
|
|
|
// Get actual string length for nanopb char array fields.
|
|
size_t pb_string_length(const char *str, size_t max_len);
|
|
|
|
// Sanitize a fixed-size char buffer in-place by replacing invalid UTF-8 sequences with '?'.
|
|
// Ensures the result is null-terminated within bufSize. Returns true if any bytes were replaced.
|
|
bool sanitizeUtf8(char *buf, size_t bufSize);
|
|
|
|
// Longest User.long_name content (bytes, excluding NUL) we store or transmit.
|
|
// The wire decode buffer stays at 40 so names from senders built against the
|
|
// older 39-byte limit still parse; everything we keep or send is clamped to
|
|
// this, matching the slim NodeInfoLite storage width in deviceonly.proto.
|
|
#define MAX_LONG_NAME_BYTES 24
|
|
|
|
// Clamp a long_name buffer (at least MAX_LONG_NAME_BYTES + 1 bytes) in-place
|
|
// to MAX_LONG_NAME_BYTES bytes of content, fixing any partial UTF-8 sequence
|
|
// left at the cut.
|
|
void clampLongName(char *longName);
|
|
|
|
/// Calculate 2^n without calling pow() - used for spreading factor and other calculations
|
|
inline uint32_t pow_of_2(uint32_t n)
|
|
{
|
|
return 1 << n;
|
|
}
|
|
|
|
/// Returns true if n is a power of two (n >= 1).
|
|
template <typename T> constexpr bool is_pow_of_2(T n)
|
|
{
|
|
return n >= T(1) && (n & (n - T(1))) == T(0);
|
|
}
|
|
|
|
#define IS_ONE_OF(item, ...) isOneOf(item, sizeof((int[]){__VA_ARGS__}) / sizeof(int), __VA_ARGS__)
|