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

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).

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 containing vendor-specific extensions for the controller, including vendor-specific errors, events, and status codes.

Required Methods

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.

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.


// 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.

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])?;