blob: 99f11d100c4fb0c28c057760c5f34a1711b27e91 [file] [log] [blame]
//! HCI Hardware Abstraction Layer
//! Supports sending HCI commands to the HAL and receving
//! HCI events from the HAL
#[cfg(target_os = "android")]
#[macro_use]
extern crate lazy_static;
pub mod facade;
pub mod rootcanal_hal;
pub mod snoop;
#[cfg(target_os = "android")]
mod hidl_hal;
use bt_packet::{HciCommand, HciEvent, RawPacket};
use gddi::{module, Stoppable};
use std::sync::Arc;
use thiserror::Error;
use tokio::sync::{mpsc, Mutex};
#[cfg(target_os = "android")]
module! {
hal_module,
submodules {
facade::hal_facade_module,
hidl_hal::hidl_hal_module
},
}
#[cfg(not(target_os = "android"))]
module! {
hal_module,
submodules {
facade::hal_facade_module,
rootcanal_hal::rootcanal_hal_module
},
}
/// H4 packet header size
const H4_HEADER_SIZE: usize = 1;
/// HAL interface
/// This is used by the HCI module to send commands to the
/// HAL and receive events from the HAL
#[derive(Clone, Stoppable)]
pub struct HalExports {
/// Transmit end of a channel used to send HCI commands
pub cmd_tx: mpsc::UnboundedSender<HciCommand>,
/// Receive end of a channel used to receive HCI events
pub evt_rx: Arc<Mutex<mpsc::UnboundedReceiver<HciEvent>>>,
/// Transmit end of a channel used to send ACL data
pub acl_tx: mpsc::UnboundedSender<RawPacket>,
/// Receive end of a channel used to receive ACL data
pub acl_rx: Arc<Mutex<mpsc::UnboundedReceiver<RawPacket>>>,
}
/// HCI HAL
/// Receive HCI commands, send HCI events
pub struct Hal {
/// Receive end of a channel used to receive HCI commands
pub cmd_rx: mpsc::UnboundedReceiver<HciCommand>,
/// Transmit end of a channel used to send HCI events
pub evt_tx: mpsc::UnboundedSender<HciEvent>,
/// Receive end of a channel used to send ACL data
pub acl_rx: mpsc::UnboundedReceiver<RawPacket>,
/// Transmit end of a channel used to receive ACL data
pub acl_tx: mpsc::UnboundedSender<RawPacket>,
}
impl Hal {
/// Create a new Hal instance
pub fn new() -> (HalExports, Self) {
let (cmd_tx, cmd_rx) = mpsc::unbounded_channel();
let (evt_tx, evt_rx) = mpsc::unbounded_channel();
let (acl_down_tx, acl_down_rx) = mpsc::unbounded_channel();
let (acl_up_tx, acl_up_rx) = mpsc::unbounded_channel();
(
HalExports {
cmd_tx,
evt_rx: Arc::new(Mutex::new(evt_rx)),
acl_tx: acl_down_tx,
acl_rx: Arc::new(Mutex::new(acl_up_rx)),
},
Self {
cmd_rx,
evt_tx,
acl_rx: acl_down_rx,
acl_tx: acl_up_tx,
},
)
}
}
/// Result type
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
/// Errors that can be encountered while dealing with the HAL
#[derive(Error, Debug)]
pub enum HalError {
/// Invalid rootcanal host error
#[error("Invalid rootcanal host")]
InvalidAddressError,
/// Error while connecting to rootcanal
#[error("Connection to rootcanal failed: {0}")]
RootcanalConnectError(#[from] tokio::io::Error),
}