ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
radio_sniff.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4#ifndef PROTOCORE_RADIO_SNIFF_H
5#define PROTOCORE_RADIO_SNIFF_H
6
7#include "protocore_config.h" // the entry point: protocore_types.h for the widths
8
10
11/**
12 * @file radio_sniff.h
13 * @brief Receive-only radio channel sniffer -> pcap capture records (PROTOCORE_ENABLE_RADIO_SNIFF).
14 *
15 * The RF gateway drivers (CC1101, LoRa, the Thread 802.15.4 RCP) can run receive-only - sniff a channel
16 * without joining - and the frames they pull off the air belong in the same capture pipeline as the CAN
17 * and Wi-Fi captures (shared/protocore_pcap). For 802.15.4 that means wrapping each frame in the
18 * Wireshark IEEE 802.15.4 **TAP** pseudo-header so the per-frame RSSI and channel travel with it, then a
19 * standard pcap record, giving a `.pcap` a wired Wireshark opens with the radio metadata intact.
20 *
21 * This is that pure framing: ::protocore_radiosniff_global writes the pcap global header (DLT TAP), and
22 * ::protocore_radiosniff_tap_record writes one record (TAP header + RSSI/channel TLVs + the MAC frame). The
23 * radio drivers own the receive; this owns the on-wire capture bytes. No heap, no stdlib, host-testable.
24 *
25 * @c work is bytes the CALLER holds. This module reads none of them: it carries nothing
26 * between calls, so there is no state to keep and nothing to wipe. The parameter is there so
27 * a caller drives every namespace the same way.
28 */
29
30// PROTOCORE_RADIO_SNIFF_BORROW - the bytes this module runs out of - is stated in protocore_config.h, which sums
31// it into its arena. Its size and its offset are each a static_assert, so a feature
32// combination that does not fit fails to compile rather than overrunning at run time.
33
34/** @brief The TAP pseudo-header length this codec emits: 4 header + RSSI TLV(8) + channel TLV(8). */
35#define RADIO_SNIFF_TAP_LEN 20
36
37/** @brief Dispatch table. Addressed by offset, so the layout is asserted below. */
38typedef struct
39{
40 size_t (*global_header)(uint8_t *, uint8_t *, size_t);
41 uint32_t (*i2f32)(uint8_t *, int32_t);
42 size_t (*tap_record)(uint8_t *, uint8_t *, size_t, const uint8_t *, size_t, int32_t, uint16_t, uint32_t, uint32_t);
44PROTOCORE_NS_LAYOUT(RadioSniffNs, global_header, i2f32, tap_record);
45
46/**
47 * @brief Write the pcap global header for a TAP-framed 802.15.4 sniff. 24, .
48 * @param work PROTOCORE_RADIO_SNIFF_BORROW bytes the caller took. Not held past the call.
49 * @param out Out
50 * @param cap Cap
51 * @return The size_t.
52 */
53size_t protocore_radio_sniff_global_header(uint8_t *work, uint8_t *out, size_t cap);
54/**
55 * @brief Encode a signed integer dBm value as an IEEE-754 float32 .
56 * @param work PROTOCORE_RADIO_SNIFF_BORROW bytes the caller took. Not held past the call.
57 * @param dbm Dbm
58 * @return The uint32_t.
59 */
60uint32_t protocore_radio_sniff_i2f32(uint8_t *work, int32_t dbm);
61/**
62 * @brief Write one capture record: a pcap record header, the 802.15.4 TAP .
63 * @param work PROTOCORE_RADIO_SNIFF_BORROW bytes the caller took. Not held past the call.
64 * @param out Out
65 * @param cap Cap
66 * @param frame Frame
67 * @param flen Flen
68 * @param rssi_dbm Rssi dbm
69 * @param channel Channel
70 * @param ts_sec Ts sec
71 * @param ts_usec Ts usec
72 * @return The size_t.
73 */
74size_t protocore_radio_sniff_tap_record(uint8_t *work, uint8_t *out, size_t cap, const uint8_t *frame, size_t flen,
75 int32_t rssi_dbm, uint16_t channel, uint32_t ts_sec, uint32_t ts_usec);
76
77/** @brief Module namespace. */
81
83
84#endif // PROTOCORE_RADIO_SNIFF_H
#define PROTOCORE_NS_LAYOUT(T,...)
Pin every dispatch slot of a table that is nothing but function pointers.
#define PROTOCORE_NS
Storage for a dispatch table. The const is load bearing.
size_t protocore_radio_sniff_global_header(uint8_t *work, uint8_t *out, size_t cap)
Write the pcap global header for a TAP-framed 802.15.4 sniff. 24, .
size_t protocore_radio_sniff_tap_record(uint8_t *work, uint8_t *out, size_t cap, const uint8_t *frame, size_t flen, int32_t rssi_dbm, uint16_t channel, uint32_t ts_sec, uint32_t ts_usec)
Write one capture record: a pcap record header, the 802.15.4 TAP .
PROTOCORE_NS RadioSniffNs RadioSniff PROTOCORE_UNUSED
Module namespace.
Definition radio_sniff.h:78
uint32_t protocore_radio_sniff_i2f32(uint8_t *work, int32_t dbm)
Encode a signed integer dBm value as an IEEE-754 float32 .
Dispatch table. Addressed by offset, so the layout is asserted below.
Definition radio_sniff.h:39
size_t(* global_header)(uint8_t *, uint8_t *, size_t)
Definition radio_sniff.h:40
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
#define PROTOCORE_END_DECLS
Definition types.h:97