DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
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
10
11#if DETWS_ENABLE_RADIO_SNIFF
12
13namespace
14{
15void wr16le(uint8_t *p, uint16_t v)
16{
17 p[0] = (uint8_t)v;
18 p[1] = (uint8_t)(v >> 8);
19}
20void wr32le(uint8_t *p, uint32_t v)
21{
22 p[0] = (uint8_t)v;
23 p[1] = (uint8_t)(v >> 8);
24 p[2] = (uint8_t)(v >> 16);
25 p[3] = (uint8_t)(v >> 24);
26}
27} // namespace
28
29uint32_t detws_radiosniff_i2f32(int32_t dbm)
30{
31 if (dbm == 0)
32 return 0;
33 uint32_t sign = 0;
34 uint32_t mag;
35 if (dbm < 0)
36 {
37 sign = 0x80000000u;
38 mag = (uint32_t)(-(int64_t)dbm);
39 }
40 else
41 mag = (uint32_t)dbm;
42 int e = 31;
43 while (!((mag >> e) & 1u))
44 e--; // highest set bit
45 uint32_t exp = (uint32_t)(127 + e);
46 uint32_t mant = (e >= 23) ? ((mag >> (e - 23)) & 0x7FFFFFu) : ((mag << (23 - e)) & 0x7FFFFFu);
47 return sign | (exp << 23) | mant;
48}
49
50size_t detws_radiosniff_global(uint8_t *out, size_t cap)
51{
53}
54
55size_t detws_radiosniff_tap_record(uint8_t *out, size_t cap, const uint8_t *frame, size_t flen, int32_t rssi_dbm,
56 uint16_t channel, uint32_t ts_sec, uint32_t ts_usec)
57{
58 if (!out || !frame || flen == 0)
59 return 0;
60 size_t caplen = RADIO_SNIFF_TAP_LEN + flen;
61 size_t total = DET_PCAP_REC_HDR_LEN + caplen;
62 if (cap < total)
63 return 0;
64
65 // pcap record header.
66 det_pcap_record_header(out, cap, ts_sec, ts_usec, (uint32_t)caplen, (uint32_t)caplen);
67 uint8_t *p = out + DET_PCAP_REC_HDR_LEN;
68
69 // 802.15.4 TAP header: version(1)=0, reserved(1)=0, length(2 LE) = whole TAP block.
70 p[0] = 0;
71 p[1] = 0;
72 wr16le(p + 2, RADIO_SNIFF_TAP_LEN);
73 // TLV: Received Signal Strength (type 1, len 4), float32 dBm.
74 wr16le(p + 4, 1);
75 wr16le(p + 6, 4);
76 wr32le(p + 8, detws_radiosniff_i2f32(rssi_dbm));
77 // TLV: Channel Assignment (type 3, len 3 -> padded to 4): channel number(2 LE) + page(1).
78 wr16le(p + 12, 3);
79 wr16le(p + 14, 3);
80 wr16le(p + 16, channel);
81 p[18] = 0; // channel page 0
82 p[19] = 0; // pad
83
84 // The raw MAC frame.
85 uint8_t *f = p + RADIO_SNIFF_TAP_LEN;
86 for (size_t i = 0; i < flen; i++)
87 f[i] = frame[i];
88 return total;
89}
90
91#endif // DETWS_ENABLE_RADIO_SNIFF
void wr32le(uint8_t *p, uint32_t v)
Definition pcap.h:36
void wr16le(uint8_t *p, uint16_t v)
Definition pcap.h:43
size_t det_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:55
#define DET_DLT_IEEE802_15_4_TAP
802.15.4 with a TAP pseudo-header (RSSI / channel TLVs)
Definition pcap.h:32
size_t det_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:73
#define DET_PCAP_REC_HDR_LEN
Definition pcap.h:25
Receive-only radio channel sniffer -> pcap capture records (DETWS_ENABLE_RADIO_SNIFF).