bt_hci/
lib.rs

1#![doc = include_str!("../README.md")]
2#![warn(missing_docs)]
3#![no_std]
4
5use core::future::Future;
6
7use embedded_io::ReadExactError;
8
9mod fmt;
10
11pub mod cmd;
12pub mod controller;
13pub mod data;
14pub mod event;
15pub mod param;
16pub mod transport;
17pub use btuuid as uuid;
18
19/// Errors from parsing HCI data.
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22pub enum FromHciBytesError {
23    /// Size of input did not match valid size.
24    InvalidSize,
25    /// Value of input did not match valid values.
26    InvalidValue,
27}
28
29/// A HCI type which can be represented as bytes.
30pub trait AsHciBytes {
31    /// Get the byte representation of this type.
32    fn as_hci_bytes(&self) -> &[u8];
33}
34
35/// A fixed size HCI type that can be deserialized from bytes.
36pub trait FromHciBytes<'de>: Sized {
37    /// Deserialize bytes into a HCI type, return additional bytes.
38    fn from_hci_bytes(data: &'de [u8]) -> Result<(Self, &'de [u8]), FromHciBytesError>;
39
40    /// Deserialize bytes into a HCI type, must consume all bytes.
41    fn from_hci_bytes_complete(data: &'de [u8]) -> Result<Self, FromHciBytesError> {
42        let (val, buf) = Self::from_hci_bytes(data)?;
43        if buf.is_empty() {
44            Ok(val)
45        } else {
46            Err(FromHciBytesError::InvalidSize)
47        }
48    }
49}
50
51/// Errors from reading HCI data.
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
53#[cfg_attr(feature = "defmt", derive(defmt::Format))]
54pub enum ReadHciError<E: embedded_io::Error> {
55    /// Not enough bytes in buffer for reading.
56    BufferTooSmall,
57    /// Value of input did not match valid values.
58    InvalidValue,
59    /// Error from underlying embedded-io type.
60    Read(ReadExactError<E>),
61}
62
63impl<E: embedded_io::Error> embedded_io::Error for ReadHciError<E> {
64    fn kind(&self) -> embedded_io::ErrorKind {
65        match self {
66            Self::BufferTooSmall => embedded_io::ErrorKind::OutOfMemory,
67            Self::InvalidValue => embedded_io::ErrorKind::InvalidInput,
68            Self::Read(ReadExactError::Other(e)) => e.kind(),
69            Self::Read(ReadExactError::UnexpectedEof) => embedded_io::ErrorKind::BrokenPipe,
70        }
71    }
72}
73
74impl<E: embedded_io::Error> From<ReadExactError<E>> for ReadHciError<E> {
75    fn from(value: ReadExactError<E>) -> Self {
76        ReadHciError::Read(value)
77    }
78}
79
80impl<E: embedded_io::Error> From<FromHciBytesError> for ReadHciError<E> {
81    fn from(value: FromHciBytesError) -> Self {
82        match value {
83            FromHciBytesError::InvalidSize => ReadHciError::Read(ReadExactError::UnexpectedEof),
84            FromHciBytesError::InvalidValue => ReadHciError::InvalidValue,
85        }
86    }
87}
88
89/// Adapter trait for deserializing HCI types from embedded-io implementations.
90pub trait ReadHci<'de>: FromHciBytes<'de> {
91    /// Max length read by this type.
92    const MAX_LEN: usize;
93
94    /// Read this type from the provided reader.
95    fn read_hci<R: embedded_io::Read>(reader: R, buf: &'de mut [u8]) -> Result<Self, ReadHciError<R::Error>>;
96
97    /// Read this type from the provided reader, async version.
98    fn read_hci_async<R: embedded_io_async::Read>(
99        reader: R,
100        buf: &'de mut [u8],
101    ) -> impl Future<Output = Result<Self, ReadHciError<R::Error>>>;
102}
103
104/// Adapter trait for serializing HCI types to embedded-io implementations.
105pub trait WriteHci {
106    /// The number of bytes this value will write
107    fn size(&self) -> usize;
108
109    /// Write this value to the provided writer.
110    fn write_hci<W: embedded_io::Write>(&self, writer: W) -> Result<(), W::Error>;
111
112    /// Write this value to the provided writer, async version.
113    fn write_hci_async<W: embedded_io_async::Write>(&self, writer: W) -> impl Future<Output = Result<(), W::Error>>;
114}
115
116/// Trait representing a HCI packet.
117pub trait HostToControllerPacket: WriteHci {
118    /// Packet kind associated with this HCI packet.
119    const KIND: PacketKind;
120}
121
122/// Marker trait for HCI values that have a known, fixed size
123///
124/// # Safety
125/// - Must not contain any padding (uninitialized) bytes (recursively)
126/// - structs must be `#[repr(C)]` or `#[repr(transparent)]`
127/// - enums must be `#[repr(<int>)]`
128/// - Must not contain any references, pointers, atomics, or interior mutability
129/// - `is_valid()` must return true only if `data` is a valid bit representation of `Self`
130pub unsafe trait FixedSizeValue: Copy {
131    /// Checks if the bit representation in data is valid for Self.
132    ///
133    /// May panic if `data.len() != core::mem::size_of::<Self>()`
134    fn is_valid(data: &[u8]) -> bool;
135}
136
137/// Marker trait for [`FixedSizeValue`]s that have byte alignment.
138///
139/// # Safety
140/// - Must have `core::mem::align_of::<T>() == 1`
141pub unsafe trait ByteAlignedValue: FixedSizeValue {
142    /// Obtain a reference to this type from a byte slice.
143    ///
144    /// # Safety
145    /// - Must have `core::mem::align_of::<T>() == 1`
146    fn ref_from_hci_bytes(data: &[u8]) -> Result<(&Self, &[u8]), FromHciBytesError> {
147        if data.len() < core::mem::size_of::<Self>() {
148            Err(FromHciBytesError::InvalidSize)
149        } else if !Self::is_valid(data) {
150            Err(FromHciBytesError::InvalidValue)
151        } else {
152            let (data, rest) = data.split_at(core::mem::size_of::<Self>());
153            Ok((unsafe { &*(data.as_ptr() as *const Self) }, rest))
154        }
155    }
156}
157
158impl<T: FixedSizeValue> AsHciBytes for T {
159    fn as_hci_bytes(&self) -> &[u8] {
160        unsafe { core::slice::from_raw_parts(self as *const _ as *const u8, core::mem::size_of::<Self>()) }
161    }
162}
163
164impl<'de, T: FixedSizeValue> FromHciBytes<'de> for T {
165    fn from_hci_bytes(data: &'de [u8]) -> Result<(Self, &'de [u8]), FromHciBytesError> {
166        if data.len() < core::mem::size_of::<Self>() {
167            Err(FromHciBytesError::InvalidSize)
168        } else if !Self::is_valid(data) {
169            Err(FromHciBytesError::InvalidValue)
170        } else {
171            let (data, rest) = data.split_at(core::mem::size_of::<Self>());
172            Ok((unsafe { core::ptr::read_unaligned(data.as_ptr() as *const Self) }, rest))
173        }
174    }
175}
176
177impl<'de, T: ByteAlignedValue> FromHciBytes<'de> for &'de [T] {
178    fn from_hci_bytes(data: &'de [u8]) -> Result<(Self, &'de [u8]), FromHciBytesError> {
179        let Some((len, data)) = data.split_first() else {
180            return Err(FromHciBytesError::InvalidSize);
181        };
182
183        let len = usize::from(*len);
184        let byte_len = len * core::mem::size_of::<T>();
185        if byte_len > data.len() {
186            return Err(FromHciBytesError::InvalidSize);
187        }
188
189        let (data, rest) = data.split_at(byte_len);
190
191        if !data.chunks_exact(core::mem::size_of::<T>()).all(|x| T::is_valid(x)) {
192            return Err(FromHciBytesError::InvalidValue);
193        }
194
195        Ok((
196            unsafe { core::slice::from_raw_parts(data.as_ptr() as *const T, len) },
197            rest,
198        ))
199    }
200}
201
202impl<'de, T: FixedSizeValue> ReadHci<'de> for T {
203    const MAX_LEN: usize = core::mem::size_of::<Self>();
204
205    fn read_hci<R: embedded_io::Read>(mut reader: R, buf: &'de mut [u8]) -> Result<Self, ReadHciError<R::Error>> {
206        if buf.len() < core::mem::size_of::<Self>() {
207            Err(ReadHciError::BufferTooSmall)
208        } else {
209            let (buf, _) = buf.split_at_mut(core::mem::size_of::<Self>());
210            reader.read_exact(buf)?;
211            Self::from_hci_bytes(buf).map(|(x, _)| x).map_err(Into::into)
212        }
213    }
214
215    async fn read_hci_async<R: embedded_io_async::Read>(
216        mut reader: R,
217        buf: &'de mut [u8],
218    ) -> Result<Self, ReadHciError<R::Error>> {
219        if buf.len() < core::mem::size_of::<Self>() {
220            Err(ReadHciError::BufferTooSmall)
221        } else {
222            let (buf, _) = buf.split_at_mut(core::mem::size_of::<Self>());
223            reader.read_exact(buf).await?;
224            Self::from_hci_bytes(buf).map(|(x, _)| x).map_err(Into::into)
225        }
226    }
227}
228
229impl<T: FixedSizeValue> WriteHci for T {
230    #[inline(always)]
231    fn size(&self) -> usize {
232        core::mem::size_of::<Self>()
233    }
234
235    fn write_hci<W: embedded_io::Write>(&self, mut writer: W) -> Result<(), W::Error> {
236        writer.write_all(self.as_hci_bytes())
237    }
238
239    async fn write_hci_async<W: embedded_io_async::Write>(&self, mut writer: W) -> Result<(), W::Error> {
240        writer.write_all(self.as_hci_bytes()).await
241    }
242}
243
244/// Enum of valid HCI packet types.
245#[repr(u8)]
246#[derive(Debug, Clone, Copy, PartialEq, Eq)]
247#[cfg_attr(feature = "defmt", derive(defmt::Format))]
248pub enum PacketKind {
249    /// Command.
250    Cmd = 1,
251    /// ACL data.
252    AclData = 2,
253    /// Sync data.
254    SyncData = 3,
255    /// Event.
256    Event = 4,
257    /// Isochronous Data.
258    IsoData = 5,
259}
260
261impl<'de> FromHciBytes<'de> for PacketKind {
262    fn from_hci_bytes(data: &'de [u8]) -> Result<(Self, &'de [u8]), FromHciBytesError> {
263        if data.is_empty() {
264            Err(FromHciBytesError::InvalidSize)
265        } else {
266            let (data, rest) = data.split_at(1);
267            match data[0] {
268                1 => Ok((PacketKind::Cmd, rest)),
269                2 => Ok((PacketKind::AclData, rest)),
270                3 => Ok((PacketKind::SyncData, rest)),
271                4 => Ok((PacketKind::Event, rest)),
272                5 => Ok((PacketKind::IsoData, rest)),
273                _ => Err(FromHciBytesError::InvalidValue),
274            }
275        }
276    }
277}
278
279impl WriteHci for PacketKind {
280    #[inline(always)]
281    fn size(&self) -> usize {
282        1
283    }
284
285    #[inline(always)]
286    fn write_hci<W: embedded_io::Write>(&self, mut writer: W) -> Result<(), W::Error> {
287        writer.write_all(&(*self as u8).to_le_bytes())
288    }
289
290    #[inline(always)]
291    async fn write_hci_async<W: embedded_io_async::Write>(&self, mut writer: W) -> Result<(), W::Error> {
292        writer.write_all(&(*self as u8).to_le_bytes()).await
293    }
294}
295
296/// Type representing valid deserialized HCI packets.
297#[derive(Debug)]
298#[cfg_attr(feature = "defmt", derive(defmt::Format))]
299pub enum ControllerToHostPacket<'a> {
300    /// ACL packet.
301    Acl(data::AclPacket<'a>),
302    /// Sync packet.
303    Sync(data::SyncPacket<'a>),
304    /// Event packet.
305    Event(event::EventPacket<'a>),
306    /// Isochronous packet.
307    Iso(data::IsoPacket<'a>),
308}
309
310impl<'a> ControllerToHostPacket<'a> {
311    /// The packet kind.
312    pub fn kind(&self) -> PacketKind {
313        match self {
314            Self::Acl(_) => PacketKind::AclData,
315            Self::Sync(_) => PacketKind::SyncData,
316            Self::Event(_) => PacketKind::Event,
317            Self::Iso(_) => PacketKind::IsoData,
318        }
319    }
320
321    /// Deserialize data assuming a specific kind of packet.
322    pub fn from_hci_bytes_with_kind(
323        kind: PacketKind,
324        data: &'a [u8],
325    ) -> Result<(ControllerToHostPacket<'a>, &'a [u8]), FromHciBytesError> {
326        match kind {
327            PacketKind::Cmd => Err(FromHciBytesError::InvalidValue),
328            PacketKind::AclData => data::AclPacket::from_hci_bytes(data).map(|(x, y)| (Self::Acl(x), y)),
329            PacketKind::SyncData => data::SyncPacket::from_hci_bytes(data).map(|(x, y)| (Self::Sync(x), y)),
330            PacketKind::Event => event::EventPacket::from_hci_bytes(data).map(|(x, y)| (Self::Event(x), y)),
331            PacketKind::IsoData => data::IsoPacket::from_hci_bytes(data).map(|(x, y)| (Self::Iso(x), y)),
332        }
333    }
334}
335
336impl<'de> FromHciBytes<'de> for ControllerToHostPacket<'de> {
337    fn from_hci_bytes(data: &'de [u8]) -> Result<(Self, &'de [u8]), FromHciBytesError> {
338        let (kind, data) = PacketKind::from_hci_bytes(data)?;
339        match kind {
340            PacketKind::Cmd => Err(FromHciBytesError::InvalidValue),
341            PacketKind::AclData => data::AclPacket::from_hci_bytes(data).map(|(x, y)| (Self::Acl(x), y)),
342            PacketKind::SyncData => data::SyncPacket::from_hci_bytes(data).map(|(x, y)| (Self::Sync(x), y)),
343            PacketKind::Event => event::EventPacket::from_hci_bytes(data).map(|(x, y)| (Self::Event(x), y)),
344            PacketKind::IsoData => data::IsoPacket::from_hci_bytes(data).map(|(x, y)| (Self::Iso(x), y)),
345        }
346    }
347}
348
349impl<'de> ReadHci<'de> for ControllerToHostPacket<'de> {
350    const MAX_LEN: usize = 258;
351
352    fn read_hci<R: embedded_io::Read>(mut reader: R, buf: &'de mut [u8]) -> Result<Self, ReadHciError<R::Error>> {
353        let mut kind = [0];
354        reader.read_exact(&mut kind)?;
355        match PacketKind::from_hci_bytes(&kind)?.0 {
356            PacketKind::Cmd => Err(ReadHciError::InvalidValue),
357            PacketKind::AclData => data::AclPacket::read_hci(reader, buf).map(Self::Acl),
358            PacketKind::SyncData => data::SyncPacket::read_hci(reader, buf).map(Self::Sync),
359            PacketKind::Event => event::EventPacket::read_hci(reader, buf).map(Self::Event),
360            PacketKind::IsoData => data::IsoPacket::read_hci(reader, buf).map(Self::Iso),
361        }
362    }
363
364    async fn read_hci_async<R: embedded_io_async::Read>(
365        mut reader: R,
366        buf: &'de mut [u8],
367    ) -> Result<Self, ReadHciError<R::Error>> {
368        let mut kind = [0u8];
369        reader.read_exact(&mut kind).await?;
370        match PacketKind::from_hci_bytes(&kind)?.0 {
371            PacketKind::Cmd => Err(ReadHciError::InvalidValue),
372            PacketKind::AclData => data::AclPacket::read_hci_async(reader, buf).await.map(Self::Acl),
373            PacketKind::SyncData => data::SyncPacket::read_hci_async(reader, buf).await.map(Self::Sync),
374            PacketKind::Event => event::EventPacket::read_hci_async(reader, buf).await.map(Self::Event),
375            PacketKind::IsoData => data::IsoPacket::read_hci_async(reader, buf).await.map(Self::Iso),
376        }
377    }
378}