mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-10-23 21:33:53 +00:00
Expose actual BLE identity in nRF52 trace diagnostics
This commit is contained in:
1 parent
c1c0c3178c
commit
042d5b7f0d
3 files changed
+122
No files matched your search
@@ -30,6 +30,7 @@ struct MeshBleTraceBuffer {
|
||||
};
|
||||
extern "C" { extern MeshBleTraceBuffer mesh_ble_trace; }
|
||||
void meshBleTraceState(char* reply, size_t capacity);
|
||||
void meshBleTraceIdentity(char* reply, size_t capacity);
|
||||
static inline void meshBleTraceMax(std::atomic<uint32_t>& value, uint32_t sample) {
|
||||
uint32_t old = value.load(std::memory_order_relaxed);
|
||||
while (sample > old && !value.compare_exchange_weak(old, sample,
|
||||
@@ -77,6 +78,11 @@ static inline void meshBleTraceDispatchExit(uint32_t event, uint32_t handle) {
|
||||
}
|
||||
static inline bool meshBleTraceCommand(const char* command, char* reply,
|
||||
size_t capacity) {
|
||||
if (!strcmp(command, "get bluetooth.trace.identity")
|
||||
|| !strcmp(command, "get ble.trace.identity")) {
|
||||
meshBleTraceIdentity(reply, capacity);
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(command, "get bluetooth.trace.state")) {
|
||||
meshBleTraceState(reply, capacity);
|
||||
return true;
|
||||
|
||||
@@ -52,6 +52,48 @@ void meshBleTraceState(char* reply, size_t capacity) {
|
||||
if (instance) instance->formatDebugState(reply, capacity);
|
||||
else snprintf(reply, capacity, "> Bluetooth not initialized");
|
||||
}
|
||||
|
||||
void meshBleTraceIdentity(char* reply, size_t capacity) {
|
||||
if (!instance) {
|
||||
snprintf(reply, capacity, "> Bluetooth not initialized");
|
||||
return;
|
||||
}
|
||||
ble_gap_addr_t address = {};
|
||||
const uint32_t address_status = sd_ble_gap_addr_get(&address);
|
||||
// Read the real GAP name rather than the application's saved preferences.
|
||||
// The SDK returns a non-NUL-terminated byte string and the complete length,
|
||||
// even when it only copies the supplied buffer's bounded prefix.
|
||||
uint8_t name[32] = {};
|
||||
uint16_t name_length = sizeof(name);
|
||||
const uint32_t name_status = sd_ble_gap_device_name_get(name, &name_length);
|
||||
// The global SVC ABI guard protects these calls under LTO. Also retain the
|
||||
// explicit output reload barrier used by the other diagnostic SDK queries.
|
||||
__asm__ __volatile__("" ::: "memory");
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
char address_hex[13] = {};
|
||||
if (address_status == NRF_SUCCESS) {
|
||||
for (size_t i = 0; i < sizeof(address.addr); ++i) {
|
||||
const uint8_t byte = address.addr[sizeof(address.addr) - 1 - i];
|
||||
address_hex[2 * i] = hex[byte >> 4];
|
||||
address_hex[2 * i + 1] = hex[byte & 15];
|
||||
}
|
||||
}
|
||||
char name_hex[2 * sizeof(name) + 1] = {};
|
||||
if (name_status == NRF_SUCCESS) {
|
||||
const size_t copied = name_length < sizeof(name) ? name_length : sizeof(name);
|
||||
for (size_t i = 0; i < copied; ++i) {
|
||||
name_hex[2 * i] = hex[name[i] >> 4];
|
||||
name_hex[2 * i + 1] = hex[name[i] & 15];
|
||||
}
|
||||
}
|
||||
snprintf(reply, capacity,
|
||||
"> a=%lu,t=%u,mac=%s,n=%lu,len=%u,hex=%s,adv=%u,scan=%u",
|
||||
(unsigned long)address_status,
|
||||
address_status == NRF_SUCCESS ? (unsigned)address.addr_type : 255u,
|
||||
address_hex, (unsigned long)name_status, (unsigned)name_length,
|
||||
name_hex, (unsigned)Bluefruit.Advertising.count(),
|
||||
(unsigned)Bluefruit.ScanResponse.count());
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool formatDeviceName(char* dest, size_t capacity,
|
||||
|
||||
@@ -24,6 +24,9 @@ extern "C" { MeshBleTraceBuffer mesh_ble_trace; }
|
||||
void meshBleTraceState(char* reply, size_t capacity) {
|
||||
snprintf(reply,capacity,"> state");
|
||||
}
|
||||
void meshBleTraceIdentity(char* reply, size_t capacity) {
|
||||
snprintf(reply,capacity,"> identity");
|
||||
}
|
||||
int main() {
|
||||
char reply[160];
|
||||
assert(!meshBleTraceCommand("get radio",reply,sizeof(reply)));
|
||||
@@ -42,6 +45,10 @@ int main() {
|
||||
assert(!strcmp(reply,"> 257,1234,0x0010,65535,0,0"));
|
||||
assert(meshBleTraceCommand("get bluetooth.trace.state",reply,sizeof(reply)));
|
||||
assert(!strcmp(reply,"> state"));
|
||||
for (const char* command : {"get bluetooth.trace.identity", "get ble.trace.identity"}) {
|
||||
assert(meshBleTraceCommand(command,reply,sizeof(reply)));
|
||||
assert(!strcmp(reply,"> identity"));
|
||||
}
|
||||
meshBleTraceDispatchEnter(0x10,0);
|
||||
assert(mesh_ble_trace.dispatch_event.load()==0x10);
|
||||
meshBleTraceDispatchExit(0x10,0);
|
||||
@@ -76,6 +83,73 @@ int main() {
|
||||
check=True, capture_output=True)
|
||||
subprocess.run([str(binary)],check=True,capture_output=True)
|
||||
|
||||
def test_real_identity_query_bounds_sdk_outputs_and_reports_failures(self):
|
||||
source = (ROOT / "src/helpers/nrf52/SerialBLEInterface.cpp").read_text()
|
||||
start = source.index("void meshBleTraceIdentity(")
|
||||
implementation = source[start:source.index("\n}\n", start) + 3]
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
work = Path(directory)
|
||||
cpp = work / "identity.cpp"
|
||||
cpp.write_text(r'''
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
static constexpr uint32_t NRF_SUCCESS = 0;
|
||||
struct ble_gap_addr_t { uint8_t addr_type; uint8_t addr[6]; };
|
||||
static bool initialized;
|
||||
static void* instance;
|
||||
static unsigned calls;
|
||||
static uint32_t address_result, name_result;
|
||||
static uint16_t actual_length;
|
||||
struct Data { uint8_t count() { return 255; } };
|
||||
static struct { Data Advertising, ScanResponse; } Bluefruit;
|
||||
static uint32_t sd_ble_gap_addr_get(ble_gap_addr_t* address) {
|
||||
assert(initialized); ++calls;
|
||||
*address = {1, {0xc6, 0xbb, 0xcd, 0x86, 0xa0, 0xd1}};
|
||||
return address_result;
|
||||
}
|
||||
static uint32_t sd_ble_gap_device_name_get(uint8_t* name, uint16_t* length) {
|
||||
assert(initialized && *length == 32); ++calls;
|
||||
const uint8_t bytes[] = {0x41, 0x00, 0xc3, 0xa9};
|
||||
const size_t copied = actual_length < *length ? actual_length : *length;
|
||||
for (size_t i = 0; i < copied; ++i) name[i] = bytes[i % sizeof(bytes)];
|
||||
*length = actual_length;
|
||||
return name_result;
|
||||
}
|
||||
@IMPLEMENTATION@
|
||||
int main() {
|
||||
char reply[172];
|
||||
meshBleTraceIdentity(reply, sizeof(reply));
|
||||
assert(!strcmp(reply, "> Bluetooth not initialized") && calls == 0);
|
||||
initialized = true; instance = &initialized; actual_length = 4;
|
||||
meshBleTraceIdentity(reply, sizeof(reply));
|
||||
assert(!strcmp(reply, "> a=0,t=1,mac=d1a086cdbbc6,n=0,len=4,hex=4100c3a9,adv=255,scan=255"));
|
||||
actual_length = 65535;
|
||||
meshBleTraceIdentity(reply, sizeof(reply));
|
||||
assert(strstr(reply, ",len=65535,hex="));
|
||||
assert(strstr(reply, ",adv=255,scan=255"));
|
||||
assert(strlen(reply) < sizeof(reply) - 1);
|
||||
const char* begin = strstr(reply, "hex=") + 4;
|
||||
assert(strchr(begin, ',') - begin == 64);
|
||||
address_result = name_result = UINT32_MAX;
|
||||
meshBleTraceIdentity(reply, sizeof(reply));
|
||||
assert(!strcmp(reply, "> a=4294967295,t=255,mac=,n=4294967295,len=65535,hex=,adv=255,scan=255"));
|
||||
char tiny[5] = {};
|
||||
meshBleTraceIdentity(tiny, sizeof(tiny));
|
||||
assert(tiny[4] == 0);
|
||||
}
|
||||
'''.replace("@IMPLEMENTATION@", implementation))
|
||||
binary = work / "identity"
|
||||
compiled = subprocess.run([
|
||||
"c++", "-std=c++17", "-O2", "-flto", "-Wall", "-Wextra", "-Werror",
|
||||
"-fsanitize=address,undefined", "-fno-omit-frame-pointer",
|
||||
"-fno-pie", "-no-pie", str(cpp), "-o", str(binary),
|
||||
], capture_output=True, text=True)
|
||||
self.assertEqual(compiled.returncode, 0, compiled.stderr)
|
||||
result = subprocess.run([str(binary)], capture_output=True, text=True)
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
|
||||
def test_concurrent_reader_never_accepts_mixed_records(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
work = Path(directory)
|
||||
|
||||
Reference in new issue
Block a user