stm32wb_hci/host/uart.rs
1//! Implementation of the HCI that includes the packet ID byte in the header.
2
3use byteorder::{ByteOrder, LittleEndian};
4
5const PACKET_TYPE_HCI_COMMAND: u8 = 0x01;
6// const PACKET_TYPE_ACL_DATA: u8 = 0x02;
7// const PACKET_TYPE_SYNC_DATA: u8 = 0x03;
8const PACKET_TYPE_HCI_EVENT: u8 = 0x04;
9
10/// Potential errors from reading or writing packets to the controller.
11///
12/// Must be specialized both for communication errors (`E`) and vendor-specific errors (`VE`).
13#[derive(Copy, Clone, Debug, PartialEq)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15pub enum Error {
16 /// The host expected the controller to begin a packet, but the next byte is not a valid packet
17 /// type byte. Contains the value of the byte.
18 BadPacketType(u8),
19 /// There was an error deserializing an event. Contains the underlying error.
20 BLE(crate::event::Error),
21}
22
23/// Packet types that may be read from the controller.
24#[derive(Clone, Debug)]
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26pub enum Packet {
27 // AclData(AclData),
28 // SyncData(SyncData),
29 /// The HCI Event Packet is used by the Controller to notify the Host when events
30 /// occur. The event is specialized to support vendor-specific events.
31 Event(crate::Event),
32}
33
34/// Header for HCI Commands.
35pub struct CommandHeader {
36 opcode: crate::opcode::Opcode,
37 param_len: u8,
38}
39
40/// Trait for reading packets from the controller.
41///
42/// Implementors must also implement [`crate::host::HostHci`], which provides all of the functions to
43/// write commands to the controller. This trait adds the ability to read packets back from the
44/// controller.
45///
46/// Must be specialized for communication errors (`E`), vendor-specific events (`Vendor`), and
47/// vendor-specific errors (`VE`).
48pub trait UartHci: super::HostHci {
49 /// Reads and returns a packet from the controller. Consumes exactly enough bytes to read the
50 /// next packet including its header.
51 ///
52 /// # Errors
53 ///
54 /// - Returns [`Error::BadPacketType`] if the next byte is not a valid
55 /// packet type.
56 /// - Returns [`Error::BLE`] if there is an error deserializing the
57 /// packet (such as a mismatch between the packet length and the expected length of the
58 /// event). See [`crate::event::Error`] for possible values of `e`.
59 /// - Returns [`Error::Comm`] if there is an error reading from the
60 /// controller.
61 async fn read(&mut self) -> Result<Packet, Error>;
62}
63
64impl super::HciHeader for CommandHeader {
65 const HEADER_LENGTH: usize = 4;
66
67 fn new(opcode: crate::opcode::Opcode, param_len: usize) -> CommandHeader {
68 CommandHeader {
69 opcode,
70 param_len: param_len as u8,
71 }
72 }
73
74 fn copy_into_slice(&self, buffer: &mut [u8]) {
75 buffer[0] = PACKET_TYPE_HCI_COMMAND;
76 LittleEndian::write_u16(&mut buffer[1..=2], self.opcode.0);
77 buffer[3] = self.param_len;
78 }
79}
80
81impl<T> UartHci for T
82where
83 T: crate::Controller,
84{
85 async fn read(&mut self) -> Result<Packet, Error> {
86 const MAX_EVENT_LENGTH: usize = 256;
87 const PACKET_HEADER_LENGTH: usize = 1;
88 const EVENT_PACKET_HEADER_LENGTH: usize = 3;
89 const PARAM_LEN_BYTE: usize = 2;
90
91 let mut packet = [0u8; MAX_EVENT_LENGTH];
92 self.controller_read_into(&mut packet).await;
93
94 let packet_type = packet[0];
95 match packet_type {
96 PACKET_TYPE_HCI_EVENT => {
97 let param_len = packet[PARAM_LEN_BYTE] as usize;
98
99 let mut buf = [0; MAX_EVENT_LENGTH + EVENT_PACKET_HEADER_LENGTH];
100 buf[..EVENT_PACKET_HEADER_LENGTH + param_len]
101 .copy_from_slice(&packet[..EVENT_PACKET_HEADER_LENGTH + param_len]);
102
103 Ok(Packet::Event(
104 crate::event::Event::new(crate::event::Packet(
105 &buf[PACKET_HEADER_LENGTH..EVENT_PACKET_HEADER_LENGTH + param_len],
106 ))
107 .map_err(Error::BLE)?,
108 ))
109 }
110 x => Err(Error::BadPacketType(x)),
111 }
112 }
113}