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