esp_wifi/ble/
mod.rs

1//! Bluetooth Low Energy HCI interface
2
3#[cfg(any(esp32, esp32c3, esp32s3))]
4pub(crate) mod btdm;
5
6#[cfg(any(esp32c2, esp32c6, esp32h2))]
7pub(crate) mod npl;
8
9use alloc::{boxed::Box, collections::vec_deque::VecDeque, vec::Vec};
10use core::{cell::RefCell, mem::MaybeUninit};
11
12pub(crate) use ble::{ble_deinit, ble_init, send_hci};
13use critical_section::Mutex;
14
15#[cfg(any(esp32, esp32c3, esp32s3))]
16use self::btdm as ble;
17#[cfg(any(esp32c2, esp32c6, esp32h2))]
18use self::npl as ble;
19
20pub mod controller;
21
22pub(crate) unsafe extern "C" fn malloc(size: u32) -> *mut crate::binary::c_types::c_void {
23    unsafe { crate::compat::malloc::malloc(size as usize).cast() }
24}
25
26#[cfg(any(esp32, esp32c3, esp32s3))]
27pub(crate) unsafe extern "C" fn malloc_internal(size: u32) -> *mut crate::binary::c_types::c_void {
28    unsafe { crate::compat::malloc::malloc(size as usize).cast() }
29}
30
31pub(crate) unsafe extern "C" fn free(ptr: *mut crate::binary::c_types::c_void) {
32    unsafe { crate::compat::malloc::free(ptr.cast()) }
33}
34
35// Stores received packets until the the BLE stack dequeues them
36static BT_RECEIVE_QUEUE: Mutex<RefCell<VecDeque<ReceivedPacket>>> =
37    Mutex::new(RefCell::new(VecDeque::new()));
38
39static mut HCI_OUT_COLLECTOR: MaybeUninit<HciOutCollector> = MaybeUninit::uninit();
40
41#[derive(PartialEq, Debug)]
42enum HciOutType {
43    Unknown,
44    Acl,
45    Command,
46}
47
48struct HciOutCollector {
49    data: [u8; 256],
50    index: usize,
51    ready: bool,
52    kind: HciOutType,
53}
54
55impl HciOutCollector {
56    fn new() -> HciOutCollector {
57        HciOutCollector {
58            data: [0u8; 256],
59            index: 0,
60            ready: false,
61            kind: HciOutType::Unknown,
62        }
63    }
64
65    fn is_ready(&self) -> bool {
66        self.ready
67    }
68
69    fn push(&mut self, data: &[u8]) {
70        self.data[self.index..(self.index + data.len())].copy_from_slice(data);
71        self.index += data.len();
72
73        if self.kind == HciOutType::Unknown {
74            self.kind = match self.data[0] {
75                1 => HciOutType::Command,
76                2 => HciOutType::Acl,
77                _ => HciOutType::Unknown,
78            };
79        }
80
81        if !self.ready {
82            if self.kind == HciOutType::Command && self.index >= 4 {
83                if self.index == self.data[3] as usize + 4 {
84                    self.ready = true;
85                }
86            } else if self.kind == HciOutType::Acl
87                && self.index >= 5
88                && self.index == (self.data[3] as usize) + ((self.data[4] as usize) << 8) + 5
89            {
90                self.ready = true;
91            }
92        }
93    }
94
95    fn reset(&mut self) {
96        self.index = 0;
97        self.ready = false;
98        self.kind = HciOutType::Unknown;
99    }
100
101    fn packet(&self) -> &[u8] {
102        &self.data[0..self.index]
103    }
104}
105
106static BLE_HCI_READ_DATA: Mutex<RefCell<Vec<u8>>> = Mutex::new(RefCell::new(Vec::new()));
107
108#[derive(Debug, Clone)]
109pub struct ReceivedPacket {
110    pub data: Box<[u8]>,
111}
112
113#[cfg(feature = "defmt")]
114impl defmt::Format for ReceivedPacket {
115    fn format(&self, fmt: defmt::Formatter<'_>) {
116        defmt::write!(fmt, "ReceivedPacket {}", &self.data[..])
117    }
118}
119
120pub fn have_hci_read_data() -> bool {
121    critical_section::with(|cs| {
122        let queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs);
123        let hci_read_data = BLE_HCI_READ_DATA.borrow_ref(cs);
124        !queue.is_empty() || !hci_read_data.is_empty()
125    })
126}
127
128pub(crate) fn read_next(data: &mut [u8]) -> usize {
129    critical_section::with(|cs| {
130        let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs);
131
132        match queue.pop_front() {
133            Some(packet) => {
134                data[..packet.data.len()].copy_from_slice(&packet.data[..packet.data.len()]);
135                packet.data.len()
136            }
137            None => 0,
138        }
139    })
140}
141
142pub fn read_hci(data: &mut [u8]) -> usize {
143    critical_section::with(|cs| {
144        let mut hci_read_data = BLE_HCI_READ_DATA.borrow_ref_mut(cs);
145
146        if hci_read_data.is_empty() {
147            let mut queue = BT_RECEIVE_QUEUE.borrow_ref_mut(cs);
148
149            if let Some(packet) = queue.pop_front() {
150                hci_read_data.extend_from_slice(&packet.data);
151            }
152        }
153
154        let l = usize::min(hci_read_data.len(), data.len());
155        data[..l].copy_from_slice(&hci_read_data[..l]);
156        hci_read_data.drain(..l);
157        l
158    })
159}
160
161fn dump_packet_info(_buffer: &[u8]) {
162    #[cfg(dump_packets)]
163    critical_section::with(|_cs| {
164        info!("@HCIFRAME {:?}", _buffer);
165    });
166}