Trait bluetooth_hci::Controller [−][src]
pub trait Controller { type Error; type Header; type Vendor: Vendor; fn write(
&mut self,
header: &[u8],
payload: &[u8]
) -> Result<(), Self::Error>; fn read_into(&mut self, buffer: &mut [u8]) -> Result<(), Self::Error>; fn peek(&mut self, n: usize) -> Result<u8, Self::Error>; }
Interface to the Bluetooth controller from the host's perspective.
The Bluetooth application host must communicate with a controller (which, in turn, communicates
with the link layer) to control the Bluetooth radio. Device crates must implement this trait,
which enables full access to all of the functions and events of the HCI through host::Hci
and host::uart::Hci
, respectively.
Associated Types
type Error
Enumeration of Controller
errors. These typically will be specializations of
host::uart::Error
that specify both the vendor-specific error type and a communication
error type. The communication error type in turn will depend on the bus used to communicate
with the controller as well as the device crate (e.g., linux-embedded-hal::Spidev
uses
std::io::Error
).
type Header
The type of header sent to the controller for HCI commands. Should be either
[uart::CommandHeader
], [cmd_link::Header
], or [event_link::NoCommands
], depending on
the controller implementation.
type Vendor: Vendor
Type containing vendor-specific extensions for the controller, including vendor-specific errors, events, and status codes.
Required Methods
fn write(&mut self, header: &[u8], payload: &[u8]) -> Result<(), Self::Error>
Writes the bytes to the controller, in a single transaction if possible. All of header
shall be written, followed by all of payload
. write
is allowed to block internally, but
should return nb::Error::WouldBlock
if the controller is not ready to receive the data.
fn read_into(&mut self, buffer: &mut [u8]) -> Result<(), Self::Error>
Reads data from the controller into the provided buffer
. The length of the buffer
indicates the number of bytes to read. The implementor must not return bytes in an order
different from that in which they were received from the controller. For example, the
implementor may read all available bytes from the controller and maintain them in an
internal buffer, but read_into
shall only read the number of bytes requested.
Example
// Controller sends: // +------+------+------+------+------+------+------+------+ // | 0x12 | 0x34 | 0x56 | 0x78 | 0x9a | 0xbc | 0xde | 0xf0 | // +------+------+------+------+------+------+------+------+ // host calls: let mut buffer = [0; 4]; controller.read_into(&mut buffer[1..]); // read 3 bytes into buffer[1..] // buffer contains: // +------+------+------+------+ // | 0x00 | 0x12 | 0x34 | 0x56 | // +------+------+------+------+ // now the host calls: controller.read_into(&mut buffer); // read 4 bytes into buffer // buffer contains: // +------+------+------+------+ // | 0x78 | 0x9a | 0xbc | 0xde | // +------+------+------+------+
If the next call to read_into
requests more than 1 byte, the controller may return
nb::Error::WouldBlock
, or may attempt to read more data from the controller. If not
enough data is available from the controller, the implementor shall return
nb::Error::WouldBlock
.
fn peek(&mut self, n: usize) -> Result<u8, Self::Error>
Looks ahead at the data coming from the Controller without consuming it. Implementors should
be able to support values of n
up to 5 to support all potential data types.
peek(0)
will typically be used to the the packet type (see Bluetooth Spec, Vol 4, Part A,
Section 2), which will be followed by another peek to determine the amount of data to
read. For example, the code to read an HCI event looks like this:
const MAX_EVENT_LENGTH: usize = 255; const HEADER_LENGTH: usize = 2; let mut buffer = [0; MAX_EVENT_LENGTH + HEADER_LENGTH]; let packet_type = controller.peek(0)?; if packet_type == PACKET_TYPE_HCI_EVENT { // Byte 3 has the parameter length in HCI events let param_len = controller.peek(3)? as usize; // We want to consume the full HCI Event packet, and we now know the length. controller.read_into(&mut buffer[..HEADER_LENGTH + param_len])?; }