extern crate nb;
use byteorder::{ByteOrder, LittleEndian};
const PACKET_TYPE_HCI_COMMAND: u8 = 0x01;
const PACKET_TYPE_HCI_EVENT: u8 = 0x04;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Error<E, VE> {
BadPacketType(u8),
BLE(::event::Error<VE>),
Comm(E),
}
#[derive(Clone, Debug)]
pub enum Packet<Vendor>
where
Vendor: ::event::VendorEvent,
{
Event(::Event<Vendor>),
}
pub struct CommandHeader {
opcode: ::opcode::Opcode,
param_len: u8,
}
pub trait Hci<E, Vendor, VE>: super::Hci<E> {
fn read(&mut self) -> nb::Result<Packet<Vendor>, Error<E, VE>>
where
Vendor: ::event::VendorEvent<Error = VE>;
}
impl super::HciHeader for CommandHeader {
const HEADER_LENGTH: usize = 4;
fn new(opcode: ::opcode::Opcode, param_len: usize) -> CommandHeader {
CommandHeader {
opcode: opcode,
param_len: param_len as u8,
}
}
fn into_bytes(&self, buffer: &mut [u8]) {
buffer[0] = PACKET_TYPE_HCI_COMMAND;
LittleEndian::write_u16(&mut buffer[1..=2], self.opcode.0);
buffer[3] = self.param_len;
}
}
fn rewrap_error<E, VE>(e: nb::Error<E>) -> nb::Error<Error<E, VE>> {
match e {
nb::Error::WouldBlock => nb::Error::WouldBlock,
nb::Error::Other(err) => nb::Error::Other(Error::Comm(err)),
}
}
fn read_event<E, T, Vendor, VE>(controller: &mut T) -> nb::Result<::Event<Vendor>, Error<E, VE>>
where
T: ::Controller<Error = E>,
Vendor: ::event::VendorEvent<Error = VE>,
{
const MAX_EVENT_LENGTH: usize = 255;
const PACKET_HEADER_LENGTH: usize = 1;
const EVENT_PACKET_HEADER_LENGTH: usize = 3;
const PARAM_LEN_BYTE: usize = 2;
let param_len = controller.peek(PARAM_LEN_BYTE).map_err(rewrap_error)? as usize;
let mut buf = [0; MAX_EVENT_LENGTH + EVENT_PACKET_HEADER_LENGTH];
controller
.read_into(&mut buf[..EVENT_PACKET_HEADER_LENGTH + param_len])
.map_err(rewrap_error)?;
::event::Event::new(::event::Packet(
&buf[PACKET_HEADER_LENGTH..EVENT_PACKET_HEADER_LENGTH + param_len],
)).map_err(|e| nb::Error::Other(Error::BLE(e)))
}
impl<E, Vendor, VE, T> Hci<E, Vendor, VE> for T
where
T: ::Controller<Error = E, Header = CommandHeader>,
{
fn read(&mut self) -> nb::Result<Packet<Vendor>, Error<E, VE>>
where
Vendor: ::event::VendorEvent<Error = VE>,
{
match self.peek(0).map_err(rewrap_error)? {
PACKET_TYPE_HCI_EVENT => Ok(Packet::Event(read_event(self)?)),
x => Err(nb::Error::Other(Error::BadPacketType(x))),
}
}
}