Skip to main content

bt_hci/
lib.rs

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