Skip to main content

esp_radio/ble/controller/
mod.rs

1//! BLE controller
2use core::task::Poll;
3
4use bt_hci::{
5    ControllerToHostPacket,
6    FromHciBytes,
7    FromHciBytesError,
8    HostToControllerPacket,
9    WriteHci,
10    transport::{Transport, WithIndicator},
11};
12use docsplay::Display;
13use esp_phy::PhyInitGuard;
14
15use crate::{
16    RadioRefGuard,
17    asynch::AtomicWaker,
18    ble::{Config, InvalidConfigError, have_hci_read_data, read_hci, read_next, send_hci},
19};
20
21#[derive(Display, Debug, Copy, Clone, Eq, PartialEq, Hash)]
22#[cfg_attr(feature = "defmt", derive(defmt::Format))]
23/// Error enum for BLE initialization failures.
24pub enum BleInitError {
25    /// Failure during initial validation of the provided configuration: {0}.
26    Config(InvalidConfigError),
27}
28
29impl core::error::Error for BleInitError {}
30
31// Implement the From trait for cleaner error mapping
32impl From<InvalidConfigError> for BleInitError {
33    fn from(err: InvalidConfigError) -> Self {
34        BleInitError::Config(err)
35    }
36}
37
38/// A blocking HCI connector
39#[instability::unstable]
40pub struct BleConnector<'d> {
41    _phy_init_guard: PhyInitGuard<'d>,
42    _device: crate::hal::peripherals::BT<'d>,
43    _guard: RadioRefGuard,
44}
45
46impl Drop for BleConnector<'_> {
47    fn drop(&mut self) {
48        crate::ble::ble_deinit();
49    }
50}
51impl<'d> BleConnector<'d> {
52    /// Create and init a new BLE connector.
53    #[instability::unstable]
54    pub fn new(
55        device: crate::hal::peripherals::BT<'d>,
56        config: Config,
57    ) -> Result<BleConnector<'d>, BleInitError> {
58        let _guard = RadioRefGuard::new();
59
60        config.validate()?;
61
62        Ok(Self {
63            _phy_init_guard: crate::ble::ble_init(&config),
64            _device: device,
65            _guard,
66        })
67    }
68
69    /// Read the next HCI packet from the BLE controller.
70    #[instability::unstable]
71    pub fn next(&mut self, buf: &mut [u8]) -> Result<usize, BleConnectorError> {
72        Ok(read_next(buf))
73    }
74
75    /// Read from HCI.
76    #[instability::unstable]
77    pub fn read(&mut self, mut buf: &mut [u8]) -> Result<usize, BleConnectorError> {
78        let mut total = 0;
79        while !buf.is_empty() {
80            let len = read_hci(buf);
81            if len == 0 {
82                break;
83            }
84
85            buf = &mut buf[len..];
86            total += len;
87        }
88        Ok(total)
89    }
90
91    /// Read from HCI.
92    #[instability::unstable]
93    pub async fn read_async(&mut self, buf: &mut [u8]) -> Result<usize, BleConnectorError> {
94        if buf.is_empty() {
95            return Ok(0);
96        }
97
98        if !have_hci_read_data() {
99            HciReadyEventFuture.await;
100        }
101
102        self.read(buf)
103    }
104
105    /// Write to HCI.
106    #[instability::unstable]
107    pub fn write(&mut self, buf: &[u8]) -> Result<usize, BleConnectorError> {
108        for b in buf {
109            send_hci(&[*b]);
110        }
111        Ok(buf.len())
112    }
113}
114
115#[derive(Display, Debug, Copy, Clone, Eq, PartialEq, Hash)]
116#[cfg_attr(feature = "defmt", derive(defmt::Format))]
117/// Error type for the BLE connector.
118#[instability::unstable]
119pub enum BleConnectorError {
120    /// Unknown BLE error occurred.
121    Unknown,
122}
123
124impl embedded_io_06::Error for BleConnectorError {
125    fn kind(&self) -> embedded_io_06::ErrorKind {
126        embedded_io_06::ErrorKind::Other
127    }
128}
129
130impl embedded_io_07::Error for BleConnectorError {
131    fn kind(&self) -> embedded_io_07::ErrorKind {
132        embedded_io_07::ErrorKind::Other
133    }
134}
135
136impl core::error::Error for BleConnectorError {}
137
138impl embedded_io_06::ErrorType for BleConnector<'_> {
139    type Error = BleConnectorError;
140}
141
142impl embedded_io_06::Read for BleConnector<'_> {
143    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
144        self.read(buf)
145    }
146}
147
148impl embedded_io_06::Write for BleConnector<'_> {
149    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
150        self.write(buf)
151    }
152
153    fn flush(&mut self) -> Result<(), Self::Error> {
154        // nothing to do
155        Ok(())
156    }
157}
158
159impl embedded_io_07::ErrorType for BleConnector<'_> {
160    type Error = BleConnectorError;
161}
162
163impl embedded_io_07::Read for BleConnector<'_> {
164    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
165        self.read(buf)
166    }
167}
168
169impl embedded_io_07::Write for BleConnector<'_> {
170    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
171        self.write(buf)
172    }
173
174    fn flush(&mut self) -> Result<(), Self::Error> {
175        // nothing to do
176        Ok(())
177    }
178}
179
180static HCI_WAKER: AtomicWaker = AtomicWaker::new();
181
182pub(crate) fn hci_read_data_available() {
183    HCI_WAKER.wake();
184}
185
186impl embedded_io_async_06::Read for BleConnector<'_> {
187    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, BleConnectorError> {
188        self.read_async(buf).await
189    }
190}
191
192impl embedded_io_async_06::Write for BleConnector<'_> {
193    async fn write(&mut self, buf: &[u8]) -> Result<usize, BleConnectorError> {
194        send_hci(buf);
195        Ok(buf.len())
196    }
197
198    async fn flush(&mut self) -> Result<(), BleConnectorError> {
199        // nothing to do
200        Ok(())
201    }
202}
203
204impl embedded_io_async_07::Read for BleConnector<'_> {
205    async fn read(&mut self, buf: &mut [u8]) -> Result<usize, BleConnectorError> {
206        self.read_async(buf).await
207    }
208}
209
210impl embedded_io_async_07::Write for BleConnector<'_> {
211    async fn write(&mut self, buf: &[u8]) -> Result<usize, BleConnectorError> {
212        send_hci(buf);
213        Ok(buf.len())
214    }
215
216    async fn flush(&mut self) -> Result<(), BleConnectorError> {
217        // nothing to do
218        Ok(())
219    }
220}
221
222impl From<FromHciBytesError> for BleConnectorError {
223    fn from(_e: FromHciBytesError) -> Self {
224        BleConnectorError::Unknown
225    }
226}
227
228#[must_use = "futures do nothing unless you `.await` or poll them"]
229pub(crate) struct HciReadyEventFuture;
230
231impl core::future::Future for HciReadyEventFuture {
232    type Output = ();
233
234    fn poll(
235        self: core::pin::Pin<&mut Self>,
236        cx: &mut core::task::Context<'_>,
237    ) -> Poll<Self::Output> {
238        HCI_WAKER.register(cx.waker());
239
240        if have_hci_read_data() {
241            Poll::Ready(())
242        } else {
243            Poll::Pending
244        }
245    }
246}
247
248fn parse_hci(data: &[u8]) -> Result<Option<ControllerToHostPacket<'_>>, BleConnectorError> {
249    match ControllerToHostPacket::from_hci_bytes_complete(data) {
250        Ok(p) => Ok(Some(p)),
251        Err(e) => {
252            warn!("[hci] error parsing packet: {:?}", e);
253            Err(BleConnectorError::Unknown)
254        }
255    }
256}
257
258impl Transport for BleConnector<'_> {
259    /// Read a complete HCI packet into the rx buffer
260    async fn read<'a>(&self, rx: &'a mut [u8]) -> Result<ControllerToHostPacket<'a>, Self::Error> {
261        loop {
262            if !have_hci_read_data() {
263                HciReadyEventFuture.await;
264            }
265
266            // Workaround for borrow checker.
267            // Safety: we only return a reference to x once, if parsing is successful.
268            let rx =
269                unsafe { &mut *core::ptr::slice_from_raw_parts_mut(rx.as_mut_ptr(), rx.len()) };
270
271            let len = crate::ble::read_next(rx);
272            if let Some(packet) = parse_hci(&rx[..len])? {
273                return Ok(packet);
274            }
275        }
276    }
277
278    /// Write a complete HCI packet from the tx buffer
279    async fn write<T: HostToControllerPacket>(&self, val: &T) -> Result<(), Self::Error> {
280        let mut buf: [u8; 259] = [0; 259];
281        let w = WithIndicator::new(val);
282        let len = w.size();
283        w.write_hci(&mut buf[..])
284            .map_err(|_| BleConnectorError::Unknown)?;
285        send_hci(&buf[..len]);
286        Ok(())
287    }
288}