//! BT HCI HAL facade
-use crate::Hal;
+use crate::{AclHal, ControlHal};
use bt_common::GrpcFacade;
use bt_facade_proto::common::Data;
use bt_facade_proto::empty::Empty;
}
#[provides]
-async fn provide_facade(hal: Hal, rt: Arc<Runtime>) -> HciHalFacadeService {
- HciHalFacadeService { rt, hal }
+async fn provide_facade(control: ControlHal, acl: AclHal, rt: Arc<Runtime>) -> HciHalFacadeService {
+ HciHalFacadeService { rt, control, acl }
}
/// HCI HAL facade service
#[derive(Clone, Stoppable)]
pub struct HciHalFacadeService {
rt: Arc<Runtime>,
- hal: Hal,
+ control: ControlHal,
+ acl: AclHal,
}
impl GrpcFacade for HciHalFacadeService {
impl HciHalFacade for HciHalFacadeService {
fn send_command(&mut self, _ctx: RpcContext<'_>, mut data: Data, sink: UnarySink<Empty>) {
- let cmd_tx = self.hal.cmd_tx.clone();
+ let cmd_tx = self.control.tx.clone();
self.rt.block_on(async move {
cmd_tx.send(CommandPacket::parse(&data.take_payload()).unwrap()).await.unwrap();
});
}
fn send_acl(&mut self, _ctx: RpcContext<'_>, mut data: Data, sink: UnarySink<Empty>) {
- let acl_tx = self.hal.acl_tx.clone();
+ let acl_tx = self.acl.tx.clone();
self.rt.block_on(async move {
acl_tx.send(AclPacket::parse(&data.take_payload()).unwrap()).await.unwrap();
});
_: Empty,
mut sink: ServerStreamingSink<Data>,
) {
- let evt_rx = self.hal.evt_rx.clone();
+ let evt_rx = self.control.rx.clone();
self.rt.spawn(async move {
while let Some(event) = evt_rx.lock().await.recv().await {
let mut output = Data::default();
}
fn stream_acl(&mut self, _ctx: RpcContext<'_>, _: Empty, mut sink: ServerStreamingSink<Data>) {
- let acl_rx = self.hal.acl_rx.clone();
+ let acl_rx = self.acl.rx.clone();
self.rt.spawn(async move {
while let Some(acl) = acl_rx.lock().await.recv().await {
let mut output = Data::default();
#[cfg(target_os = "android")]
mod hidl_hal;
-use bt_packets::hci::{AclPacket, CommandPacket, EventPacket};
-use gddi::{module, Stoppable};
-use std::sync::Arc;
+use gddi::module;
use thiserror::Error;
-use tokio::sync::mpsc::{Receiver, Sender};
-use tokio::sync::Mutex;
#[cfg(target_os = "android")]
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 Hal {
- /// Transmit end of a channel used to send HCI commands
- pub cmd_tx: Sender<CommandPacket>,
- /// Receive end of a channel used to receive HCI events
- pub evt_rx: Arc<Mutex<Receiver<EventPacket>>>,
- /// Transmit end of a channel used to send ACL data
- pub acl_tx: Sender<AclPacket>,
- /// Receive end of a channel used to receive ACL data
- pub acl_rx: Arc<Mutex<Receiver<AclPacket>>>,
-}
+pub use snoop::AclHal;
+pub use snoop::ControlHal;
mod internal {
use bt_packets::hci::{AclPacket, CommandPacket, EventPacket};
//! BT snoop logger
use crate::internal::RawHal;
-use crate::Hal;
use bt_common::sys_prop;
use bt_packets::hci::{AclPacket, CommandPacket, EventPacket};
use bytes::{BufMut, Bytes, BytesMut};
-use gddi::{module, provides, Stoppable};
+use gddi::{module, part_out, provides, Stoppable};
use log::error;
use std::convert::TryFrom;
use std::sync::Arc;
use tokio::io::AsyncWriteExt;
use tokio::runtime::Runtime;
use tokio::select;
-use tokio::sync::mpsc::{channel, UnboundedReceiver};
+use tokio::sync::mpsc::{channel, Receiver, Sender, UnboundedReceiver};
use tokio::sync::Mutex;
+#[part_out]
+#[derive(Clone, Stoppable)]
+struct Hal {
+ control: ControlHal,
+ acl: AclHal,
+}
+
+/// Command & event tx/rx
+#[derive(Clone, Stoppable)]
+pub struct ControlHal {
+ /// Transmit end
+ pub tx: Sender<CommandPacket>,
+ /// Receive end
+ pub rx: Arc<Mutex<Receiver<EventPacket>>>,
+}
+
+/// Acl tx/rx
+#[derive(Clone, Stoppable)]
+pub struct AclHal {
+ /// Transmit end
+ pub tx: Sender<AclPacket>,
+ /// Receive end
+ pub rx: Arc<Mutex<Receiver<AclPacket>>>,
+}
+
/// The different modes snoop logging can be in
#[derive(Clone)]
pub enum SnoopMode {
module! {
snoop_module,
providers {
- Hal => provide_snooped_hal,
+ parts Hal => provide_snooped_hal,
},
}
});
Hal {
- cmd_tx: cmd_down_tx,
- evt_rx: Arc::new(Mutex::new(evt_up_rx)),
- acl_tx: acl_down_tx,
- acl_rx: Arc::new(Mutex::new(acl_up_rx)),
+ control: ControlHal { tx: cmd_down_tx, rx: Arc::new(Mutex::new(evt_up_rx)) },
+ acl: AclHal { tx: acl_down_tx, rx: Arc::new(Mutex::new(acl_up_rx)) },
}
}
//! HCI layer facade
-use crate::{EventRegistry, HciForAcl, RawCommandSender};
+use crate::{EventRegistry, RawCommandSender};
use bt_common::GrpcFacade;
use bt_facade_proto::common::Data;
use bt_facade_proto::empty::Empty;
use bt_facade_proto::hci_facade::EventRequest;
use bt_facade_proto::hci_facade_grpc::{create_hci_facade, HciFacade};
+use bt_hal::AclHal;
use bt_packets::hci::{
AclPacket, CommandPacket, EventCode, EventPacket, LeMetaEventPacket, SubeventCode,
};
async fn provide_facade(
commands: RawCommandSender,
events: EventRegistry,
- acl: HciForAcl,
+ acl: AclHal,
rt: Arc<Runtime>,
) -> HciFacadeService {
let (from_hci_evt_tx, to_grpc_evt_rx) = channel::<EventPacket>(10);
pub struct HciFacadeService {
commands: RawCommandSender,
events: EventRegistry,
- acl: HciForAcl,
+ acl: AclHal,
rt: Arc<Runtime>,
from_hci_evt_tx: Sender<EventPacket>,
to_grpc_evt_rx: Arc<Mutex<Receiver<EventPacket>>>,
pub use controller::ControllerExports;
use bt_common::time::Alarm;
-use bt_hal::Hal;
+use bt_hal::ControlHal;
use bt_packets::hci::EventChild::{
CommandComplete, CommandStatus, LeMetaEvent, MaxSlotsChange, PageScanRepetitionModeChange,
VendorSpecificEvent,
};
use bt_packets::hci::{
- AclPacket, CommandExpectations, CommandPacket, ErrorCode, EventCode, EventPacket,
- LeMetaEventPacket, ResetBuilder, SubeventCode,
+ CommandExpectations, CommandPacket, ErrorCode, EventCode, EventPacket, LeMetaEventPacket,
+ ResetBuilder, SubeventCode,
};
use error::Result;
use gddi::{module, part_out, provides, Stoppable};
raw_commands: RawCommandSender,
commands: CommandSender,
events: EventRegistry,
- acl: HciForAcl,
}
#[provides]
-async fn provide_hci(hal: Hal, rt: Arc<Runtime>) -> Hci {
+async fn provide_hci(control: ControlHal, rt: Arc<Runtime>) -> Hci {
let (cmd_tx, cmd_rx) = channel::<QueuedCommand>(10);
let evt_handlers = Arc::new(Mutex::new(HashMap::new()));
let le_evt_handlers = Arc::new(Mutex::new(HashMap::new()));
rt.spawn(dispatch(
evt_handlers.clone(),
le_evt_handlers.clone(),
- hal.evt_rx,
- hal.cmd_tx,
+ control.rx,
+ control.tx,
cmd_rx,
));
"reset did not complete successfully"
);
- Hci {
- raw_commands,
- commands,
- events: EventRegistry { evt_handlers, le_evt_handlers },
- acl: HciForAcl { tx: hal.acl_tx, rx: hal.acl_rx },
- }
+ Hci { raw_commands, commands, events: EventRegistry { evt_handlers, le_evt_handlers } }
}
#[derive(Debug)]
}
}
-/// Exposes the ACL send/receive interface
-#[derive(Clone, Stoppable)]
-pub struct HciForAcl {
- /// Transmit end
- pub tx: Sender<AclPacket>,
- /// Receive end
- pub rx: Arc<Mutex<Receiver<AclPacket>>>,
-}
-
/// Provides ability to register and unregister for HCI events
#[derive(Clone, Stoppable)]
pub struct EventRegistry {
//! Hci shim
-use bt_hci::{EventRegistry, HciForAcl, RawCommandSender};
+use bt_hal::AclHal;
+use bt_hci::{EventRegistry, RawCommandSender};
use bt_packets::hci::{
AclPacket, CommandPacket, EventCode, EventPacket, LeMetaEventPacket, SubeventCode,
};
pub struct Hci {
commands: RawCommandSender,
events: EventRegistry,
- acl: HciForAcl,
+ acl: AclHal,
rt: Arc<Runtime>,
acl_callback_set: bool,
evt_callback_set: bool,
rt: Arc<Runtime>,
commands: RawCommandSender,
events: EventRegistry,
- acl: HciForAcl,
+ acl: AclHal,
) -> Self {
let (evt_tx, evt_rx) = channel::<EventPacket>(10);
let (le_evt_tx, le_evt_rx) = channel::<LeMetaEventPacket>(10);
stack.get_runtime(),
stack.get_blocking::<bt_hci::RawCommandSender>(),
stack.get_blocking::<bt_hci::EventRegistry>(),
- stack.get_blocking::<bt_hci::HciForAcl>(),
+ stack.get_blocking::<bt_hal::AclHal>(),
))
}