ProtoCore v0.0.2
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
radio_sniff.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file radio_sniff.cpp
6 * @brief Receive-only radio channel sniffer -> pcap capture records (see radio_sniff.h).
7 */
8
11
12#if PC_ENABLE_RADIO_SNIFF
13
14uint32_t pc_radiosniff_i2f32(int32_t dbm)
15{
16 if (dbm == 0)
17 {
18 return 0;
19 }
20 uint32_t sign = 0;
21 uint32_t mag;
22 if (dbm < 0)
23 {
24 sign = 0x80000000u;
25 mag = (uint32_t)(-(int64_t)dbm);
26 }
27 else
28 {
29 mag = (uint32_t)dbm;
30 }
31 int e = 31;
32 while (!((mag >> e) & 1u))
33 {
34 e--; // highest set bit
35 }
36 uint32_t exp = (uint32_t)(127 + e);
37 uint32_t mant = (e >= 23) ? ((mag >> (e - 23)) & 0x7FFFFFu) : ((mag << (23 - e)) & 0x7FFFFFu);
38 return sign | (exp << 23) | mant;
39}
40
41size_t pc_radiosniff_global(uint8_t *out, size_t cap)
42{
44}
45
46size_t pc_radiosniff_tap_record(uint8_t *out, size_t cap, const uint8_t *frame, size_t flen, int32_t rssi_dbm,
47 uint16_t channel, uint32_t ts_sec, uint32_t ts_usec)
48{
49 if (!out || !frame || flen == 0)
50 {
51 return 0;
52 }
53 size_t caplen = RADIO_SNIFF_TAP_LEN + flen;
54 size_t total = PC_PCAP_REC_HDR_LEN + caplen;
55 if (cap < total)
56 {
57 return 0;
58 }
59
60 // pcap record header.
61 pc_pcap_record_header(out, cap, ts_sec, ts_usec, (uint32_t)caplen, (uint32_t)caplen);
62 uint8_t *p = out + PC_PCAP_REC_HDR_LEN;
63
64 // 802.15.4 TAP header: version(1)=0, reserved(1)=0, length(2 LE) = whole TAP block.
65 p[0] = 0;
66 p[1] = 0;
67 pc_wr16le(p + 2, RADIO_SNIFF_TAP_LEN);
68 // TLV: Received Signal Strength (type 1, len 4), float32 dBm.
69 pc_wr16le(p + 4, 1);
70 pc_wr16le(p + 6, 4);
71 pc_wr32le(p + 8, pc_radiosniff_i2f32(rssi_dbm));
72 // TLV: Channel Assignment (type 3, len 3 -> padded to 4): channel number(2 LE) + page(1).
73 pc_wr16le(p + 12, 3);
74 pc_wr16le(p + 14, 3);
75 pc_wr16le(p + 16, channel);
76 p[18] = 0; // channel page 0
77 p[19] = 0; // pad
78
79 // The raw MAC frame.
80 uint8_t *f = p + RADIO_SNIFF_TAP_LEN;
81 for (size_t i = 0; i < flen; i++)
82 {
83 f[i] = frame[i];
84 }
85 return total;
86}
87
88#endif // PC_ENABLE_RADIO_SNIFF
Fixed-width integer serializers into a raw uint8_t* buffer - one source of truth.
size_t pc_wr32le(uint8_t *p, uint32_t v)
Write v little-endian at p.
Definition endian.h:40
size_t pc_wr16le(uint8_t *p, uint16_t v)
Write v little-endian at p.
Definition endian.h:32
size_t pc_pcap_record_header(uint8_t *out, size_t cap, uint32_t ts_sec, uint32_t ts_usec, uint32_t caplen, uint32_t origlen)
Write a 16-byte libpcap record header for one captured frame.
Definition pcap.h:60
#define PC_PCAP_REC_HDR_LEN
Definition pcap.h:26
size_t pc_pcap_global_header(uint8_t *out, size_t cap, uint32_t linktype)
Write the 24-byte libpcap global header (little-endian, microsecond timestamps).
Definition pcap.h:40
#define PC_DLT_IEEE802_15_4_TAP
802.15.4 with a TAP pseudo-header (RSSI / channel TLVs)
Definition pcap.h:33
Receive-only radio channel sniffer -> pcap capture records (PC_ENABLE_RADIO_SNIFF).