bluetooth-hci 0.1.0

Implementation of the Bluetooth HCI
Documentation
//! Bluetooth events and event deserialization.
//!
//! This module defines all of the HCI events that can be generated by the Bluetooth controller. In
//! addition to all of the event types, the core functionality of the module is the `Event` enum,
//! which converts a byte buffer into an HCI event.

#![macro_use]

/// Verifies that the length of the LHS expression is exactly the RHS expression.  Fails with a
/// [`BadLength`](crate::event::Error::BadLength) error if not.
#[macro_export]
macro_rules! require_len {
    ($left:expr, $right:expr) => {
        if $left.len() != $right {
            return Err($crate::event::Error::BadLength($left.len(), $right));
        }
    };
}

/// Verifies that the length of the LHS expression is greater than or equal to the RHS expression.
/// Fails with a [`BadLength`](crate::event::Error::BadLength) error if not.
#[macro_export]
macro_rules! require_len_at_least {
    ($left:expr, $right:expr) => {
        if $left.len() < $right {
            return Err($crate::event::Error::BadLength($left.len(), $right));
        }
    };
}

/// Converts a specific generic enum value between specializations.  This is used below to convert
/// from [`Error<NeverError>`] to [`Error<VendorError>`] in various places where only one error
/// value is possible (such as from `try_into`).
macro_rules! self_convert {
    ($val:path) => {
        |e| {
            if let $val(value) = e {
                return $val(value);
            }
            unreachable!();
        }
    };
}

pub mod command;

use crate::types::{ConnectionIntervalError, FixedConnectionInterval};
use crate::{BadStatusError, ConnectionHandle, Status};
use byteorder::{ByteOrder, LittleEndian};
use core::convert::{TryFrom, TryInto};
use core::fmt::{Debug, Formatter, Result as FmtResult};
use core::marker::{PhantomData, Sized};
use core::mem;

/// Potential events that can be generated by the controller.
///
/// See the Bluetooth Spec v4.1, Vol 2, Part E, Section 7.7 for a description of each event.  The
/// events are the same for versions 4.1, 4.2, and 5.0 except where noted.
///
/// The spec defines an "LE Meta-Event" event. This event is not exposed directly. Instead,
/// individual LE events are included in this enum.
#[allow(clippy::large_enum_variant)]
#[derive(Clone, Debug)]
pub enum Event<V>
where
    V: VendorEvent,
{
    /// Vol 2, Part E, Section 7.7.3
    ConnectionComplete(ConnectionComplete<V::Status>),

    /// Vol 2, Part E, Section 7.7.5
    DisconnectionComplete(DisconnectionComplete<V::Status>),

    /// Vol 2, Part E, Section 7.7.8
    EncryptionChange(EncryptionChange<V::Status>),

    /// Vol 2, Part E, Section 7.7.12
    ReadRemoteVersionInformationComplete(RemoteVersionInformation<V::Status>),

    /// Vol 2, Part E, Section 7.7.14
    CommandComplete(command::CommandComplete<V>),

    /// Vol 2, Part E, Section 7.7.15
    CommandStatus(CommandStatus<V::Status>),

    /// Vol 2, Part E, Section 7.7.16
    HardwareError(HardwareError),

    /// Vol 2, Part E, Section 7.7.19
    NumberOfCompletedPackets(NumberOfCompletedPackets),

    /// Vol 2, Part E, Section 7.7.26
    DataBufferOverflow(DataBufferOverflow),

    /// Vol 2, Part E, Section 7.7.39
    EncryptionKeyRefreshComplete(EncryptionKeyRefreshComplete<V::Status>),

    /// Vol 2, Part E, Section 7.7.65.1
    LeConnectionComplete(LeConnectionComplete<V::Status>),

    /// Vol 2, Part E, Section 7.7.65.2
    LeAdvertisingReport(LeAdvertisingReport),

    /// Vol 2, Part E, Section 7.7.65.3
    LeConnectionUpdateComplete(LeConnectionUpdateComplete<V::Status>),

    /// Vol 2, Part E, Section 7.7.65.4
    LeReadRemoteUsedFeaturesComplete(LeReadRemoteUsedFeaturesComplete<V::Status>),

    /// Vol 2, Part E, Section 7.7.65.5
    LeLongTermKeyRequest(LeLongTermKeyRequest),

    /// Vendor-specific events (opcode 0xFF)
    Vendor(V),
}

/// Trait for [vendor-specific events](Event::Vendor).
pub trait VendorEvent {
    /// Enumeration of vendor-specific errors that may occur when deserializing events. Generally,
    /// this means some values in the buffer are out of range for the event.
    type Error;

    /// Enumeration of vendor-specific status codes.
    type Status: TryFrom<u8, Error = BadStatusError> + Clone + Debug;

    /// Enumeration of return parameters for vendor-specific commands.
    type ReturnParameters: VendorReturnParameters<Error = Self::Error> + Clone + Debug;

    /// Creates a new vendor-specific event from the contents of buffer. The buffer contains only
    /// the payload of the event, which does not include the BLE event type (which must be 0xFF) or
    /// the parameter length (which is provided by `buffer.len()`).
    ///
    /// # Errors
    ///
    /// - Shall return one of the appropriate error types (potentially including vendor-specific
    ///   errors) if the buffer does not describe a valid event.
    fn new(buffer: &[u8]) -> Result<Self, Error<Self::Error>>
    where
        Self: Sized;
}

/// Trait for return parameters for vendor-specific commands.
pub trait VendorReturnParameters {
    /// Enumeration of vendor-specific errors that may occur when deserializing return parameters
    /// for vendor-specific commands.
    type Error;

    /// Deserializes vendor-specific return parameters from the contents of the buffer.  The buffer
    /// is the full payload of the command complete event, starting with the length (1 byte) and
    /// opcode (2 bytes).
    fn new(buffer: &[u8]) -> Result<Self, Error<Self::Error>>
    where
        Self: Sized;
}

/// Errors that may occur when deserializing an event. Must be specialized by the vendor crate to
/// allow for vendor-specific event errors.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Error<V> {
    /// The event type byte was unknown. The byte is provided.
    UnknownEvent(u8),

    /// The buffer provided that is supposed to contain an event does not have the correct
    /// length. Field 0 is the provided length, field 1 is the expected length.
    BadLength(usize, usize),

    /// For all events: The status was not recognized (reserved for future use). Includes the
    /// unrecognized byte.
    BadStatus(u8),

    /// For the [Connection Complete](Event::ConnectionComplete) or [Data Buffer
    /// Overflow](Event::DataBufferOverflow) events: the link type was not recognized (reserved for
    /// future use). Includes the unrecognized byte.
    BadLinkType(u8),

    /// For the [Connection Complete](Event::ConnectionComplete) event: the encryption enabled value
    /// was not recognized (reserved for future use). Includes the unrecognized byte.
    BadEncryptionEnabledValue(u8),

    /// For the [Disconnection Complete](Event::DisconnectionComplete) event: the disconnection
    /// reason was not recognized.  Includes the unrecognized byte.
    BadReason(u8),

    /// For the [Encryption Change](Event::EncryptionChange) event: The encryption type was not
    /// recognized.  Includes the unrecognized byte.
    BadEncryptionType(u8),

    /// For the [Command Complete](Event::CommandComplete) event: The event indicated a command
    /// completed whose opcode was not recognized. Includes the unrecognized opcode.
    UnknownOpcode(crate::opcode::Opcode),

    /// For the [Command Complete](Event::CommandComplete) event, for the Read Local Supported
    /// Commands command return parameters: The returned command flags are invalid (i.e., they
    /// include a flag that is reserved for future use).
    BadCommandFlag,

    /// For the [Command Complete](Event::CommandComplete) event, for the [LE Read Channel
    /// Map](command::ReturnParameters::LeReadChannelMap) command return parameters: The returned
    /// channel map includes a reserved bit.
    InvalidChannelMap([u8; 5]),

    /// For the [Command Complete](Event::CommandComplete) event, for the [LE Read Supported
    /// States](command::ReturnParameters::LeReadSupportedStates) command return parameters: The
    /// returned supported states bitfield includes a reserved bit.
    InvalidLeStates(u64),

    /// For the [LE Connection Complete](Event::LeConnectionComplete) event: The connection role was
    /// not recognized. Includes the unrecognized byte.
    BadLeConnectionRole(u8),

    /// For the [LE Connection Complete](Event::LeConnectionComplete) or [LE Advertising
    /// Report](Event::LeAdvertisingReport) events: The address type was not recognized. Includes
    /// the unrecognized byte.
    BadLeAddressType(u8),

    /// For the [LE Connection Complete](Event::LeConnectionComplete) event: The returned connection
    /// interval was invalid. Includes the error returned when attempting to create the
    /// [FixedConnectionInterval].
    BadConnectionInterval(ConnectionIntervalError),

    /// For the [LE Connection Complete](Event::LeConnectionComplete) event: The central clock
    /// accuracy value was not recognized.  Includes the unrecognized byte.
    BadLeCentralClockAccuracy(u8),

    /// For the [LE Advertising Report](Event::LeAdvertisingReport) event: The packet ended with a
    /// partial report.
    LeAdvertisementReportIncomplete,

    /// For the [LE Advertising Report](Event::LeAdvertisingReport) event: The packet includes an
    /// invalid advertisement type.  Includes the unrecognized byte.
    BadLeAdvertisementType(u8),

    /// For the [LE Read Remote Used Features Complete](Event::LeReadRemoteUsedFeaturesComplete)
    /// event: The response included an invalid bit set for the remote features.  Includes the 8
    /// bytes of flags.
    BadRemoteUsedFeatureFlag(u64),

    /// A vendor-specific error was detected when deserializing a vendor-specific event.
    Vendor(V),
}

/// Extracts the value from a [`BadStatusError`](BadStatusError) and returns it as a
/// [`BadStatus`](Error::BadStatus) error.
pub fn rewrap_bad_status<VE>(bad_status: BadStatusError) -> Error<VE> {
    let BadStatusError::BadValue(v) = bad_status;
    Error::BadStatus(v)
}

fn rewrap_bad_reason<VE>(bad_status: BadStatusError) -> Error<VE> {
    let BadStatusError::BadValue(v) = bad_status;
    Error::BadReason(v)
}

fn rewrap_bd_addr_type_err<VE>(bad_addr_type: crate::BdAddrTypeError) -> Error<VE> {
    Error::BadLeAddressType(bad_addr_type.0)
}

/// Defines a newtype to indicate that the buffer is supposed to contain an HCI event.
pub struct Packet<'a>(pub &'a [u8]);

impl<'a> Packet<'a> {
    fn full_length(&self) -> usize {
        PACKET_HEADER_LENGTH + self.0[PARAM_LEN_BYTE] as usize
    }
}

const PACKET_HEADER_LENGTH: usize = 2;
const EVENT_TYPE_BYTE: usize = 0;
const PARAM_LEN_BYTE: usize = 1;

impl<V> Event<V>
where
    V: VendorEvent,
{
    /// Deserializes an event from the given packet. The packet should contain all of the data
    /// needed to deserialize the event.
    ///
    /// # Errors
    ///
    /// - [`UnknownEvent`](Error::UnknownEvent) error if the first byte of the header is not a
    ///   recognized event type. This includes events that may be valid BLE events, but are not yet
    ///   be implemented by this crate.
    /// - [`BadLength`](Error::BadLength) error if the length of the packet is not sufficient to
    ///   either (1) contain a packet header, or (2) contain the packet data as defined by the
    ///   header.
    /// - Other errors if the particular event cannot be correctly deserialized from the
    ///   packet. This includes vendor-specific errors for vendor events.
    pub fn new(packet: Packet) -> Result<Event<V>, Error<V::Error>> {
        require_len_at_least!(packet.0, PACKET_HEADER_LENGTH);
        require_len!(packet.0, packet.full_length());

        let event_type = packet.0[EVENT_TYPE_BYTE];
        let payload = &packet.0[PACKET_HEADER_LENGTH..packet.full_length()];
        match event_type {
            0x03 => Ok(Event::ConnectionComplete(to_connection_complete(payload)?)),
            0x05 => Ok(Event::DisconnectionComplete(to_disconnection_complete(
                payload,
            )?)),
            0x08 => Ok(Event::EncryptionChange(to_encryption_change(payload)?)),
            0x0C => Ok(Event::ReadRemoteVersionInformationComplete(
                to_remote_version_info(payload)?,
            )),
            0x0E => Ok(Event::CommandComplete(command::CommandComplete::new(
                payload,
            )?)),
            0x0F => Ok(Event::CommandStatus(to_command_status(payload)?)),
            0x10 => Ok(Event::HardwareError(to_hardware_error(payload)?)),
            0x13 => Ok(Event::NumberOfCompletedPackets(
                to_number_of_completed_packets(payload)?,
            )),
            0x1A => Ok(Event::DataBufferOverflow(to_data_buffer_overflow(payload)?)),
            0x30 => Ok(Event::EncryptionKeyRefreshComplete(
                to_encryption_key_refresh_complete(payload)?,
            )),
            0x3E => to_le_meta_event(payload),
            0xFF => Ok(Event::Vendor(V::new(payload)?)),
            _ => Err(Error::UnknownEvent(event_type)),
        }
    }
}

fn to_le_meta_event<V>(payload: &[u8]) -> Result<Event<V>, Error<V::Error>>
where
    V: VendorEvent,
{
    require_len_at_least!(payload, 1);
    match payload[0] {
        0x01 => Ok(Event::LeConnectionComplete(to_le_connection_complete(
            payload,
        )?)),
        0x02 => Ok(Event::LeAdvertisingReport(to_le_advertising_report(
            payload,
        )?)),
        0x03 => Ok(Event::LeConnectionUpdateComplete(
            to_le_connection_update_complete(payload)?,
        )),
        0x04 => Ok(Event::LeReadRemoteUsedFeaturesComplete(
            to_le_read_remote_used_features_complete(payload)?,
        )),
        0x05 => Ok(Event::LeLongTermKeyRequest(to_le_ltk_request(payload)?)),
        _ => Err(Error::UnknownEvent(payload[0])),
    }
}

/// The [Connection Complete](Event::ConnectionComplete) event indicates to both of the Hosts
/// forming the connection that a new connection has been established.
///
/// This event also indicates to the Host which issued the connection command and then received a
/// [Command Status](Event::CommandStatus) event, if the issued command failed or was successful.
#[derive(Copy, Clone, Debug)]
pub struct ConnectionComplete<VS> {
    /// Did the connection attempt fail, and if so, how?
    pub status: Status<VS>,
    /// Identifies a connection between two BR/ EDR Controllers. This is used as an identifier for
    /// transmitting and receiving voice or data.
    pub conn_handle: ConnectionHandle,
    /// BD ADDR of the other connected device forming the connection.
    pub bd_addr: crate::BdAddr,
    /// Type of connection.
    pub link_type: LinkType,
    /// True if the connection is encrypted.
    pub encryption_enabled: bool,
}

/// Permissible values for [`ConnectionComplete::link_type`].
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum LinkType {
    /// Synchronous, connection-oriented link
    Sco,
    /// Asynchronous, connection-less link
    Acl,
}

/// [TODO](https://doc.rust-lang.org/std/primitive.never.html): Replace NeverError with the
/// language's never type (!).
#[derive(Debug)]
pub enum NeverError {}

impl TryFrom<u8> for LinkType {
    type Error = Error<NeverError>;

    fn try_from(value: u8) -> Result<LinkType, Self::Error> {
        match value {
            0 => Ok(LinkType::Sco),
            1 => Ok(LinkType::Acl),
            _ => Err(Error::BadLinkType(value)),
        }
    }
}

fn to_connection_complete<VE, VS>(payload: &[u8]) -> Result<ConnectionComplete<VS>, Error<VE>>
where
    Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
    require_len!(payload, 11);

    let mut bd_addr = crate::BdAddr([0; 6]);
    bd_addr.0.copy_from_slice(&payload[3..9]);
    Ok(ConnectionComplete {
        status: payload[0].try_into().map_err(rewrap_bad_status)?,
        conn_handle: ConnectionHandle(LittleEndian::read_u16(&payload[1..])),
        bd_addr,
        link_type: payload[9]
            .try_into()
            .map_err(self_convert!(Error::BadLinkType))?,
        encryption_enabled: try_into_encryption_enabled(payload[10])
            .map_err(self_convert!(Error::BadEncryptionEnabledValue))?,
    })
}

fn try_into_encryption_enabled(value: u8) -> Result<bool, Error<NeverError>> {
    match value {
        0 => Ok(false),
        1 => Ok(true),
        _ => Err(Error::BadEncryptionEnabledValue(value)),
    }
}

/// The [Disconnection Complete](Event::DisconnectionComplete) event occurs when a connection is
/// terminated.
///
/// Note: When a physical link fails, one Disconnection Complete event will be returned for each
/// logical channel on the physical link with the corresponding [connection
/// handle](DisconnectionComplete::conn_handle) as a parameter.
///
/// See the Bluetooth v4.1 spec, Vol 2, Part E, Section 7.7.5.
#[derive(Copy, Clone, Debug)]
pub struct DisconnectionComplete<VS> {
    /// Indicates if the disconnection was successful or not.
    pub status: Status<VS>,

    /// Connection handle which was disconnected.
    pub conn_handle: ConnectionHandle,

    /// Indicates the reason for the disconnection if the disconnection was successful. If the
    /// disconnection was not successful, the value of the reason parameter can be ignored by the
    /// Host. For example, this can be the case if the Host has issued the
    /// [Disconnect](crate::host::Hci::disconnect) command and there was a parameter error, or the
    /// command was not presently allowed, or a connection handle that didn't correspond to a
    /// connection was given.
    pub reason: Status<VS>,
}

fn to_disconnection_complete<VE, VS>(payload: &[u8]) -> Result<DisconnectionComplete<VS>, Error<VE>>
where
    Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
    require_len!(payload, 4);

    Ok(DisconnectionComplete {
        status: payload[0].try_into().map_err(rewrap_bad_status)?,
        conn_handle: ConnectionHandle(LittleEndian::read_u16(&payload[1..])),
        reason: payload[3].try_into().map_err(rewrap_bad_reason)?,
    })
}

/// The [Encryption Change](Event::EncryptionChange) event is used to indicate that the change of
/// the encryption mode has been completed.
///
/// This event will occur on both devices to notify the Hosts when Encryption has changed for the
/// specified connection handle between two devices. Note: This event shall not be generated if
/// encryption is paused or resumed; during a role switch, for example.
///
/// See the Bluetooth v4.1 spec, Vol 2, Part E, Section 7.7.8.
#[derive(Copy, Clone, Debug)]
pub struct EncryptionChange<VS> {
    /// Indicates if the encryption change was successful or not.
    pub status: Status<VS>,

    /// Connection handle for which the link layer encryption has been enabled/disabled for all
    /// connection handles with the same BR/EDR Controller endpoint as the specified
    /// connection handle.
    ///
    /// The connection handle will be a connection handle for an ACL connection.
    pub conn_handle: ConnectionHandle,

    /// Specifies the new encryption type parameter for
    /// [`conn_handle`](EncryptionChange::conn_handle).
    pub encryption: Encryption,
}

/// The type of used encryption for the connection.
///
/// The meaning of the encryption type depends on whether the Host has indicated support for Secure
/// Connections in the secure connections host support parameter. When secure connections host
/// support is 'disabled' or the connection handle refers to an LE link, the Controller shall only
/// use values [`Off`](Encryption::Off) and [`On`](Encryption::On). When secure connections host
/// support is 'enabled' and the connection handle refers to a BR/EDR link, the Controller shall set
/// the encryption type [`Off`](Encryption::Off) when encryption is off, to [`On`](Encryption::On)
/// when encryption is on and using E0 and to [`OnAesCcmForBrEdr`](Encryption::OnAesCcmForBrEdr)
/// when encryption is on and using AES-CCM.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Encryption {
    /// Encryption is disabled.
    Off,
    /// - On a BR/EDR link, encryption is enabled using E0
    /// - On an LE link, encryption is enabled using AES-CCM
    On,
    /// On a BR/EDR link, encryption is enabled using AES-CCM. Unused for LE links.
    OnAesCcmForBrEdr,
}

impl TryFrom<u8> for Encryption {
    type Error = Error<NeverError>;
    fn try_from(value: u8) -> Result<Encryption, Self::Error> {
        match value {
            0x00 => Ok(Encryption::Off),
            0x01 => Ok(Encryption::On),
            0x02 => Ok(Encryption::OnAesCcmForBrEdr),
            _ => Err(Error::BadEncryptionType(value)),
        }
    }
}

fn to_encryption_change<VE, VS>(payload: &[u8]) -> Result<EncryptionChange<VS>, Error<VE>>
where
    Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
    require_len!(payload, 4);
    Ok(EncryptionChange {
        status: payload[0].try_into().map_err(rewrap_bad_status)?,
        conn_handle: ConnectionHandle(LittleEndian::read_u16(&payload[1..])),
        encryption: payload[3]
            .try_into()
            .map_err(self_convert!(Error::BadEncryptionType))?,
    })
}

/// Indicates the completion of the process obtaining the version information of the remote
/// Controller specified by [`conn_handle`](RemoteVersionInformation::conn_handle).
///
/// See [`RemoteVersionInformationComplete`](Event::ReadRemoteVersionInformationComplete).
#[derive(Copy, Clone, Debug)]
pub struct RemoteVersionInformation<VS> {
    /// Status of the read event.
    pub status: Status<VS>,

    /// Connection Handle which was used for the
    /// [`read_remote_version_information`](crate::host::Hci::read_remote_version_information)
    /// command.  The connection handle shall be for an ACL connection.
    pub conn_handle: ConnectionHandle,

    /// Version of the Current LMP in the remote Controller. See [LMP] version and [Link Layer]
    /// version in the Bluetooth Assigned Numbers.
    /// - When the connection handle is associated with a BR/EDR ACL-U logical link, the Version
    ///   event parameter shall be LMP version parameter
    /// - When the connection handle is associated with an LE-U logical link, the Version event
    ///   parameter shall be Link Layer version parameter
    ///
    /// [LMP]: https://www.bluetooth.com/specifications/assigned-numbers/link-manager
    /// [Link Layer]: https://www.bluetooth.com/specifications/assigned-numbers/link-layer
    pub version: u8,

    /// Manufacturer name of the remote Controller. See [CompId] in the Bluetooth Assigned Numbers.
    ///
    /// [CompId]: https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
    pub mfgr_name: u16,

    /// Subversion of the [LMP] in the remote Controller. See the Bluetooth Spec, v4.1, Vol 2, Part
    /// C, Table 5.2 and Vol 6, Part B, Section 2.4.2.13 (SubVersNr).  The sections are the same in
    /// v4.2 and v5.0 of the spec.
    ///
    /// This field shall contain a unique value for each implementation or revision of an
    /// implementation of the Bluetooth Controller.
    ///
    /// The meaning of the subversion is implementation-defined.
    ///
    /// [LMP]: https://www.bluetooth.com/specifications/assigned-numbers/link-manager
    pub subversion: u16,
}

fn to_remote_version_info<VE, VS>(payload: &[u8]) -> Result<RemoteVersionInformation<VS>, Error<VE>>
where
    Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
    require_len!(payload, 8);
    Ok(RemoteVersionInformation {
        status: payload[0].try_into().map_err(rewrap_bad_status)?,
        conn_handle: ConnectionHandle(LittleEndian::read_u16(&payload[1..])),
        version: payload[3],
        mfgr_name: LittleEndian::read_u16(&payload[4..]),
        subversion: LittleEndian::read_u16(&payload[6..]),
    })
}

/// The [Command Status](Event::CommandStatus) event is used to indicate that the command described
/// by the [`opcode`](CommandStatus::opcode) parameter has been received, and that the Controller is
/// currently performing the task for this command.
///
/// Defined in Vol 2, Part E, Section 7.7.15 of the spec.
#[derive(Copy, Clone, Debug)]
pub struct CommandStatus<VS> {
    /// Status of the command that has started.
    pub status: Status<VS>,

    /// Number of HCI Command packets that can be sent to the controller from the host.
    pub num_hci_command_packets: u8,

    /// Opcode of the command that generated this event. The controller can generate a spontaneous
    /// [`Command Status`](Event::CommandStatus) with opcode 0 if the number of allowed HCI commands
    /// has changed.
    pub opcode: crate::opcode::Opcode,
}

fn to_command_status<VE, VS>(buffer: &[u8]) -> Result<CommandStatus<VS>, Error<VE>>
where
    Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
    require_len!(buffer, 4);

    Ok(CommandStatus {
        status: buffer[0].try_into().map_err(rewrap_bad_status)?,
        num_hci_command_packets: buffer[1],
        opcode: crate::opcode::Opcode(LittleEndian::read_u16(&buffer[2..])),
    })
}

/// The [Hardware Error](Event::HardwareError) event is used to notify the Host that a hardware
/// failure has occurred in the Controller.
///
/// Defined in Vol 2, Part E, Section 7.7.16 of the spec.
#[derive(Copy, Clone, Debug)]
pub struct HardwareError {
    /// These hardware codes will be implementation-specific, and can be assigned to indicate
    /// various hardware problems.
    pub code: u8,
}

fn to_hardware_error<VE>(payload: &[u8]) -> Result<HardwareError, Error<VE>> {
    require_len!(payload, 1);
    Ok(HardwareError { code: payload[0] })
}

/// The [`Number of Completed Packets`](Event::NumberOfCompletedPackets) event is used by the
/// Controller to indicate to the Host how many HCI Data Packets have been completed (transmitted or
/// flushed) for each connection handle since the previous Number Of Completed Packets event was
/// sent to the Host.
///
/// Defined in Vol 2, Part E, Section 7.7.19 of the spec.
#[derive(Copy, Clone)]
pub struct NumberOfCompletedPackets {
    /// Number of connection handles whose data is sent in this event.
    num_handles: usize,

    /// Data buffer for the event.
    data_buf: [u8; NUMBER_OF_COMPLETED_PACKETS_MAX_LEN],
}

// The maximum number of bytes in the buffer is the max HCI packet size (255) less the other data in
// the packet.
const NUMBER_OF_COMPLETED_PACKETS_MAX_LEN: usize = 254;

impl Debug for NumberOfCompletedPackets {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{{")?;
        for pair in self.iter() {
            write!(f, "{:?}", pair)?;
        }
        write!(f, "}}")
    }
}

impl NumberOfCompletedPackets {
    /// Returns an iterator over the connection handle-number of completed packet pairs.
    pub fn iter(&self) -> NumberOfCompletedPacketsIterator {
        NumberOfCompletedPacketsIterator {
            event: self,
            next_index: 0,
        }
    }
}

/// Iterator over the connection handle-number of completed packet pairs from the
/// [`NumberOfCompletedPackets`] event.
pub struct NumberOfCompletedPacketsIterator<'a> {
    event: &'a NumberOfCompletedPackets,
    next_index: usize,
}

const NUM_COMPLETED_PACKETS_PAIR_LEN: usize = 4;
impl<'a> Iterator for NumberOfCompletedPacketsIterator<'a> {
    type Item = NumberOfCompletedPacketsPair;

    /// Returns the next connection handle-number of completed packets pair from the event.
    fn next(&mut self) -> Option<Self::Item> {
        if self.next_index >= self.event.num_handles * NUM_COMPLETED_PACKETS_PAIR_LEN {
            return None;
        }

        let index = self.next_index;
        self.next_index += NUM_COMPLETED_PACKETS_PAIR_LEN;
        Some(NumberOfCompletedPacketsPair {
            conn_handle: ConnectionHandle(LittleEndian::read_u16(&self.event.data_buf[index..])),
            num_completed_packets: LittleEndian::read_u16(&self.event.data_buf[index + 2..])
                as usize,
        })
    }
}

/// The [`NumberOfCompletedPackets`] event includes a series of connection handle-number of
/// completed packets pairs.
#[derive(Copy, Clone, Debug)]
pub struct NumberOfCompletedPacketsPair {
    /// Connection handle
    pub conn_handle: ConnectionHandle,
    /// The number of HCI Data Packets that have been completed (transmitted or flushed) for
    /// [`conn_handle`](NumberOfCompletedPacketsPair::conn_handle) since the previous time the event
    /// was returned.
    pub num_completed_packets: usize,
}

fn to_number_of_completed_packets<VE>(
    payload: &[u8],
) -> Result<NumberOfCompletedPackets, Error<VE>> {
    require_len_at_least!(payload, 1);

    let num_pairs = payload[0] as usize;
    require_len!(payload, 1 + num_pairs * NUM_COMPLETED_PACKETS_PAIR_LEN);

    let mut data_buf = [0; NUMBER_OF_COMPLETED_PACKETS_MAX_LEN];
    data_buf[..num_pairs * NUM_COMPLETED_PACKETS_PAIR_LEN].copy_from_slice(&payload[1..]);
    Ok(NumberOfCompletedPackets {
        num_handles: num_pairs,
        data_buf,
    })
}

/// Indicates that the Controller's data buffers have been overflowed.  This can occur if the Host
/// has sent more packets than allowed.
///
/// Defined in Vol 2, Part E, Section 7.7.26 of the spec.
#[derive(Copy, Clone, Debug)]
pub struct DataBufferOverflow {
    /// Indicates whether the overflow was caused by ACL or synchronous data.
    pub link_type: LinkType,
}

fn to_data_buffer_overflow<VE>(payload: &[u8]) -> Result<DataBufferOverflow, Error<VE>> {
    require_len!(payload, 1);
    Ok(DataBufferOverflow {
        link_type: payload[0]
            .try_into()
            .map_err(self_convert!(Error::BadLinkType))?,
    })
}

/// Indicates to the Host that the encryption key was refreshed.
///
/// The encryption key is refreshed on the given
/// [`conn_handle`](EncryptionKeyRefreshComplete::conn_handle) any time encryption is paused and
/// then resumed. The BR/EDR Controller shall send this event when the encryption key has been
/// refreshed due to encryption being started or resumed.
///
/// If the [Encryption Key Refresh Complete](Event::EncryptionKeyRefreshComplete) event was
/// generated due to an encryption pause and resume operation embedded within a change connection
/// link key procedure, the Encryption Key Refresh Complete event shall be sent prior to the Change
/// Connection Link Key Complete event.
///
/// If the Encryption Key Refresh Complete event was generated due to an encryption pause and resume
/// operation embedded within a role switch procedure, the Encryption Key Refresh Complete event
/// shall be sent prior to the Role Change event.
///
/// Defined in Vol 2, Part E, Section 7.7.39 of the spec.
#[derive(Copy, Clone, Debug)]
pub struct EncryptionKeyRefreshComplete<VS> {
    /// Did the encryption key refresh fail, and if so, how?
    pub status: Status<VS>,
    /// Connection Handle for the ACL connection to have the encryption key refreshed on.
    pub conn_handle: ConnectionHandle,
}

fn to_encryption_key_refresh_complete<VE, VS>(
    payload: &[u8],
) -> Result<EncryptionKeyRefreshComplete<VS>, Error<VE>>
where
    Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
    require_len!(payload, 3);
    Ok(EncryptionKeyRefreshComplete {
        status: payload[0].try_into().map_err(rewrap_bad_status)?,
        conn_handle: ConnectionHandle(LittleEndian::read_u16(&payload[1..])),
    })
}

/// Indicates to both of the Hosts forming the connection that a new connection has been
/// created. Upon the creation of the connection a connection handle shall be assigned by the
/// Controller, and passed to the Host in this event. If the connection establishment fails this
/// event shall be provided to the Host that had issued the [LE Create
/// Connection](crate::host::Hci::le_create_connection) command.
///
/// This event indicates to the Host which issued a [LE Create
/// Connection](crate::host::Hci::le_create_connection) command and received a [Command
/// Status](Event::CommandStatus) event if the connection establishment failed or was successful.
///
/// Defined in Vol 2, Part E, Section 7.7.65.1 of the spec.
#[derive(Copy, Clone, Debug)]
pub struct LeConnectionComplete<VS> {
    /// Did the LE Connection fail, and if so, how?
    pub status: Status<VS>,

    /// Connection handle to be used to identify a connection between two Bluetooth devices. The
    /// connection handle is used as an identifier for transmitting and receiving data.
    pub conn_handle: ConnectionHandle,

    /// Role of the device receiving this event in the connection.
    pub role: ConnectionRole,

    /// Address of the peer device.
    pub peer_bd_addr: crate::BdAddrType,

    /// Connection interval used on this connection.
    pub conn_interval: FixedConnectionInterval,

    /// This is only valid for a peripheral. On a central device, this parameter shall be set to
    /// Ppm500.
    pub central_clock_accuracy: CentralClockAccuracy,
}

/// Connection roles as returned by the [LE Connection Complete](Event::LeConnectionComplete) event.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ConnectionRole {
    /// The device is the central device for the connection.
    ///
    /// The Bluetooth spec refers to these as "master" devices.
    Central,
    /// The device is a peripheral device for the connection.
    ///
    /// The Bluetooth spec refers to these as "slave" devices.
    Peripheral,
}

impl TryFrom<u8> for ConnectionRole {
    type Error = Error<NeverError>;
    fn try_from(value: u8) -> Result<ConnectionRole, Self::Error> {
        match value {
            0 => Ok(ConnectionRole::Central),
            1 => Ok(ConnectionRole::Peripheral),
            _ => Err(Error::BadLeConnectionRole(value)),
        }
    }
}

/// Values for the central (master) clock accuracy as returned by the [LE Connection
/// Complete](Event::LeConnectionComplete) event.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum CentralClockAccuracy {
    /// The central clock is accurate to at least 500 parts-per-million.  This value is also used
    /// when the device is a central device.
    Ppm500,
    /// The central clock is accurate to at least 250 parts-per-million.
    Ppm250,
    /// The central clock is accurate to at least 150 parts-per-million.
    Ppm150,
    /// The central clock is accurate to at least 100 parts-per-million.
    Ppm100,
    /// The central clock is accurate to at least 75 parts-per-million.
    Ppm75,
    /// The central clock is accurate to at least 50 parts-per-million.
    Ppm50,
    /// The central clock is accurate to at least 30 parts-per-million.
    Ppm30,
    /// The central clock is accurate to at least 20 parts-per-million.
    Ppm20,
}

impl TryFrom<u8> for CentralClockAccuracy {
    type Error = Error<NeverError>;
    fn try_from(value: u8) -> Result<CentralClockAccuracy, Self::Error> {
        match value {
            0 => Ok(CentralClockAccuracy::Ppm500),
            1 => Ok(CentralClockAccuracy::Ppm250),
            2 => Ok(CentralClockAccuracy::Ppm150),
            3 => Ok(CentralClockAccuracy::Ppm100),
            4 => Ok(CentralClockAccuracy::Ppm75),
            5 => Ok(CentralClockAccuracy::Ppm50),
            6 => Ok(CentralClockAccuracy::Ppm30),
            7 => Ok(CentralClockAccuracy::Ppm20),
            _ => Err(Error::BadLeCentralClockAccuracy(value)),
        }
    }
}

fn to_le_connection_complete<VE, VS>(payload: &[u8]) -> Result<LeConnectionComplete<VS>, Error<VE>>
where
    Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
    require_len!(payload, 19);
    let mut bd_addr = crate::BdAddr([0; 6]);
    bd_addr.0.copy_from_slice(&payload[6..12]);
    Ok(LeConnectionComplete {
        status: payload[1].try_into().map_err(rewrap_bad_status)?,
        conn_handle: ConnectionHandle(LittleEndian::read_u16(&payload[2..])),
        role: payload[4]
            .try_into()
            .map_err(self_convert!(Error::BadLeConnectionRole))?,
        peer_bd_addr: crate::to_bd_addr_type(payload[5], bd_addr)
            .map_err(rewrap_bd_addr_type_err)?,
        conn_interval: FixedConnectionInterval::from_bytes(&payload[12..18])
            .map_err(Error::BadConnectionInterval)?,
        central_clock_accuracy: payload[18]
            .try_into()
            .map_err(self_convert!(Error::BadLeCentralClockAccuracy))?,
    })
}

/// The [LE Advertising Report](Event::LeAdvertisingReport) event indicates that a Bluetooth device
/// or multiple Bluetooth devices have responded to an active scan or received some information
/// during a passive scan. The Controller may queue these advertising reports and send information
/// from multiple devices in one event.
///
/// For Bluetooth Version 5.0: This event shall only be generated if scanning was enabled using the
/// [LE Set Scan Enable](crate::host::Hci::le_set_scan_enable) command. It only reports advertising
/// events that used legacy advertising PDUs.
///
/// Defined in Vol 2, Part E, Section 7.7.65.2 of the spec.
#[derive(Copy, Clone)]
pub struct LeAdvertisingReport {
    data_len: usize,
    data_buf: [u8; MAX_ADVERTISING_REPORT_LEN],
}

const MAX_ADVERTISING_REPORT_LEN: usize = 253;

impl LeAdvertisingReport {
    /// Returns an iterator over the advertisements from the event.
    pub fn iter(&self) -> LeAdvertisingReportIterator {
        LeAdvertisingReportIterator {
            inner_iter: self.inner_iter(),
        }
    }

    fn inner_iter<VE>(&self) -> LeAdvertisingReportInnerIterator<'_, VE> {
        LeAdvertisingReportInnerIterator {
            event_data: &self.data_buf[..self.data_len],
            next_index: 0,
            phantom: PhantomData,
        }
    }
}

/// Collection of functions to aid in external tests.
pub mod test_helpers {
    use super::*;

    /// Create an [`LeAdvertisingReport`] from a slice of [`LeAdvertisement`] structs.
    ///
    /// Panics if the resulting report would be too big to fit in a report event.
    pub fn report_with_advertisements<'a>(
        advertisements: &[LeAdvertisement<'a>],
    ) -> LeAdvertisingReport {
        let mut data_len = 0;
        let mut data_buf = [0; MAX_ADVERTISING_REPORT_LEN];

        for advertisement in advertisements {
            let event_type_index = data_len;
            let addr_index = 1 + event_type_index;
            let data_len_index = 7 + addr_index;
            let data_start_index = 1 + data_len_index;
            let rssi_index = data_start_index + advertisement.data.len();

            data_buf[event_type_index] = advertisement.event_type as u8;
            advertisement
                .address
                .copy_into_slice(&mut data_buf[addr_index..data_len_index]);
            data_buf[data_len_index] = advertisement.data.len() as u8;
            data_buf[data_start_index..rssi_index].copy_from_slice(advertisement.data);
            data_buf[rssi_index] =
                unsafe { mem::transmute::<i8, u8>(advertisement.rssi.unwrap_or(127)) };

            data_len = 1 + rssi_index;
        }

        LeAdvertisingReport { data_len, data_buf }
    }
}

impl Debug for LeAdvertisingReport {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{{")?;
        for report in self.iter() {
            write!(f, "{:?}", report)?;
        }
        write!(f, "}}")
    }
}

/// Iterator over the individual LE advertisement responses in the [LE Advertising
/// Report](Event::LeAdvertisingReport) event.
pub struct LeAdvertisingReportIterator<'a> {
    inner_iter: LeAdvertisingReportInnerIterator<'a, NeverError>,
}

struct LeAdvertisingReportInnerIterator<'a, VE> {
    event_data: &'a [u8],
    next_index: usize,
    phantom: PhantomData<VE>,
}

impl<'a> Iterator for LeAdvertisingReportIterator<'a> {
    type Item = LeAdvertisement<'a>;

    /// Returns the next connection handle-number of completed packets pair from the event.
    fn next(&mut self) -> Option<Self::Item> {
        self.inner_iter.next().unwrap()
    }
}

impl<'a, VE> LeAdvertisingReportInnerIterator<'a, VE> {
    fn next(&mut self) -> Result<Option<LeAdvertisement<'a>>, Error<VE>> {
        if self.next_index >= self.event_data.len() {
            return Ok(None);
        }

        let event_type_index = self.next_index;
        let addr_type_index = event_type_index + 1;
        let addr_index = addr_type_index + 1;
        let data_len_index = addr_index + 6;
        let data_len = self.event_data[data_len_index] as usize;
        let data_start_index = data_len_index + 1;
        let rssi_index = data_start_index + data_len;
        self.next_index = rssi_index + 1;

        if self.next_index > self.event_data.len() {
            return Err(Error::LeAdvertisementReportIncomplete);
        }

        let mut bd_addr = crate::BdAddr([0; 6]);
        bd_addr
            .0
            .copy_from_slice(&self.event_data[addr_index..data_len_index]);
        Ok(Some(LeAdvertisement {
            event_type: self.event_data[event_type_index]
                .try_into()
                .map_err(self_convert!(Error::BadLeAdvertisementType))?,
            address: crate::to_bd_addr_type(self.event_data[addr_type_index], bd_addr)
                .map_err(rewrap_bd_addr_type_err)?,
            data: &self.event_data[data_start_index..rssi_index],
            rssi: match unsafe { mem::transmute::<u8, i8>(self.event_data[rssi_index]) } {
                127 => None,
                value => Some(value),
            },
        }))
    }
}

/// A single advertising report returned by the [LE Advertising Report](Event::LeAdvertisingReport)
/// event.
#[derive(Copy, Clone, Debug)]
pub struct LeAdvertisement<'a> {
    /// Advertising respons type
    pub event_type: AdvertisementEvent,
    /// Address of the advertising device
    pub address: crate::BdAddrType,
    /// Advertising or scan response data formatted as defined in Vol 3, Part C, Section 11 of the
    /// spec.
    pub data: &'a [u8],
    /// Received signal strength.
    ///
    /// - Range is -128 dBm to 20 dBm.
    /// - If the controller sends the value 127, `None` is returned here, since that value indicates
    ///   "RSSI is not available".
    pub rssi: Option<i8>,
}

/// Types of advertisement reports.
///
/// See [`LeAdvertisement`]($crate::event::LeAdvertisement).
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum AdvertisementEvent {
    /// Connectable undirected advertising
    Advertisement,
    /// Connectable directed advertising
    DirectAdvertisement,
    /// Scannable undirected advertising
    Scan,
    /// Non connectable undirected advertising
    NonConnectableAdvertisement,
    /// Scan Response
    ScanResponse,
}

impl TryFrom<u8> for AdvertisementEvent {
    type Error = Error<NeverError>;

    fn try_from(value: u8) -> Result<AdvertisementEvent, Self::Error> {
        match value {
            0 => Ok(AdvertisementEvent::Advertisement),
            1 => Ok(AdvertisementEvent::DirectAdvertisement),
            2 => Ok(AdvertisementEvent::Scan),
            3 => Ok(AdvertisementEvent::NonConnectableAdvertisement),
            4 => Ok(AdvertisementEvent::ScanResponse),
            _ => Err(Error::BadLeAdvertisementType(value)),
        }
    }
}

fn to_le_advertising_report<VE>(payload: &[u8]) -> Result<LeAdvertisingReport, Error<VE>> {
    let mut check_iter = LeAdvertisingReportInnerIterator {
        event_data: &payload[2..],
        next_index: 0,
        phantom: PhantomData,
    };
    while let Some(_) = check_iter.next()? {}

    let data_len = payload.len() - 2;
    let mut data_buf = [0; MAX_ADVERTISING_REPORT_LEN];
    data_buf[..data_len].copy_from_slice(&payload[2..]);
    Ok(LeAdvertisingReport { data_len, data_buf })
}

/// Indicates that the Controller process to update the connection has completed.
///
/// On a peripheral, if no connection parameters are updated, then this event shall not
/// be issued.
///
/// On a central device, this event shall be issued if the
/// [`connection_update`](crate::host::Hci::le_connection_update) command was sent.
///
/// Note: This event can be issued autonomously by the central device's Controller if it decides to
/// change the connection interval based on the range of allowable connection intervals for that
/// connection.
///
/// Note: The parameter values returned in this event may be different from the parameter values
/// provided by the Host through the [LE Connection Update](crate::host::Hci::le_connection_update)
/// command or the LE Remote Connection Parameter Request Reply command (Section 7.8.31).
///
/// Defined in Vol 2, Part E, Section 7.7.65.3 of the spec.
#[derive(Copy, Clone, Debug)]
pub struct LeConnectionUpdateComplete<VS> {
    /// Did the LE Connection Update fail, and if so, how?
    pub status: Status<VS>,

    /// Connection handle to be used to identify a connection between two Bluetooth devices. The
    /// connection handle is used as an identifier for transmitting and receiving data.
    pub conn_handle: ConnectionHandle,

    /// Connection interval used on this connection.
    pub conn_interval: FixedConnectionInterval,
}

fn to_le_connection_update_complete<VE, VS>(
    payload: &[u8],
) -> Result<LeConnectionUpdateComplete<VS>, Error<VE>>
where
    Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
    require_len!(payload, 10);
    Ok(LeConnectionUpdateComplete {
        status: payload[1].try_into().map_err(rewrap_bad_status)?,
        conn_handle: ConnectionHandle(LittleEndian::read_u16(&payload[2..])),
        conn_interval: FixedConnectionInterval::from_bytes(&payload[4..10])
            .map_err(Error::BadConnectionInterval)?,
    })
}

/// Indicates the completion of the process of the Controller obtaining the features used on the
/// connection and the features supported by the remote Bluetooth device specified by
/// [`conn_handle`](LeReadRemoteUsedFeaturesComplete::conn_handle).
///
/// Note (v5.0): If the features are requested more than once while a connection exists between the
/// two devices, the second and subsequent requests may report a cached copy of the features rather
/// than fetching the feature mask again.
///
/// Defined in Vol 2, Part E, Section 7.7.65.4 of the spec.
#[derive(Copy, Clone, Debug)]
pub struct LeReadRemoteUsedFeaturesComplete<VS> {
    /// Did the read fail, and if so, how?
    pub status: Status<VS>,
    /// Connection handle to be used to identify a connection between two Bluetooth devices.
    pub conn_handle: ConnectionHandle,
    /// Bit Mask List of used LE features.
    pub features: crate::LinkLayerFeature,
}

fn to_le_read_remote_used_features_complete<VE, VS>(
    payload: &[u8],
) -> Result<LeReadRemoteUsedFeaturesComplete<VS>, Error<VE>>
where
    Status<VS>: TryFrom<u8, Error = BadStatusError>,
{
    require_len!(payload, 12);

    let feature_flags = LittleEndian::read_u64(&payload[4..]);
    Ok(LeReadRemoteUsedFeaturesComplete {
        status: payload[1].try_into().map_err(rewrap_bad_status)?,
        conn_handle: ConnectionHandle(LittleEndian::read_u16(&payload[2..])),
        features: crate::LinkLayerFeature::from_bits(feature_flags)
            .ok_or_else(|| Error::BadRemoteUsedFeatureFlag(feature_flags))?,
    })
}

/// The [LE Long Term Key Request](Event::LeLongTermKeyRequest) event indicates that the master
/// device is attempting to encrypt or re-encrypt the link and is requesting the Long Term Key from
/// the Host. (See Vol 6, Part B, Section 5.1.3).
///
/// Defined in Vol 2, Part E, Section 7.7.65.5 of the spec.
#[derive(Copy, Clone, Debug)]
pub struct LeLongTermKeyRequest {
    /// Connection handle to be used to identify a connection between two Bluetooth devices.
    pub conn_handle: ConnectionHandle,
    /// 64-bit random number.
    pub random_value: u64,
    /// 16-bit encrypted diversifier
    pub encrypted_diversifier: u16,
}

fn to_le_ltk_request<VE>(payload: &[u8]) -> Result<LeLongTermKeyRequest, Error<VE>> {
    require_len!(payload, 13);

    Ok(LeLongTermKeyRequest {
        conn_handle: ConnectionHandle(LittleEndian::read_u16(&payload[1..])),
        random_value: LittleEndian::read_u64(&payload[3..]),
        encrypted_diversifier: LittleEndian::read_u16(&payload[11..]),
    })
}