1 //! Implementation of the HAl that talks to BT controller over Android's HIDL
2 use crate::internal::{InnerHal, RawHal};
3 use bt_packets::hci::{AclPacket, CommandPacket, EventPacket, IsoPacket, Packet};
4 use gddi::{module, provides};
5 use std::sync::Arc;
6 use std::sync::Mutex;
7 use tokio::runtime::Runtime;
8 use tokio::select;
9 use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
10
11 module! {
12 hidl_hal_module,
13 providers {
14 RawHal => provide_hidl_hal,
15 }
16 }
17
18 #[provides]
provide_hidl_hal(rt: Arc<Runtime>) -> RawHal19 async fn provide_hidl_hal(rt: Arc<Runtime>) -> RawHal {
20 let (raw_hal, inner_hal) = InnerHal::new();
21 let (init_tx, mut init_rx) = unbounded_channel();
22 *CALLBACKS.lock().unwrap() = Some(Callbacks {
23 init_tx,
24 evt_tx: inner_hal.evt_tx,
25 acl_tx: inner_hal.acl_tx,
26 iso_tx: inner_hal.iso_tx,
27 });
28 ffi::start_hal();
29 init_rx.recv().await.unwrap();
30
31 rt.spawn(dispatch_outgoing(inner_hal.cmd_rx, inner_hal.acl_rx, inner_hal.iso_rx));
32
33 raw_hal
34 }
35
36 #[cxx::bridge(namespace = bluetooth::hal)]
37 // TODO Either use or remove these functions, this shouldn't be the long term state
38 #[allow(dead_code)]
39 mod ffi {
40 unsafe extern "C++" {
41 include!("src/ffi/hidl.h");
start_hal()42 fn start_hal();
stop_hal()43 fn stop_hal();
send_command(data: &[u8])44 fn send_command(data: &[u8]);
send_acl(data: &[u8])45 fn send_acl(data: &[u8]);
send_sco(data: &[u8])46 fn send_sco(data: &[u8]);
send_iso(data: &[u8])47 fn send_iso(data: &[u8]);
48 }
49
50 extern "Rust" {
on_init_complete()51 fn on_init_complete();
on_event(data: &[u8])52 fn on_event(data: &[u8]);
on_acl(data: &[u8])53 fn on_acl(data: &[u8]);
on_sco(data: &[u8])54 fn on_sco(data: &[u8]);
on_iso(data: &[u8])55 fn on_iso(data: &[u8]);
56 }
57 }
58
59 struct Callbacks {
60 init_tx: UnboundedSender<()>,
61 evt_tx: UnboundedSender<EventPacket>,
62 acl_tx: UnboundedSender<AclPacket>,
63 iso_tx: UnboundedSender<IsoPacket>,
64 }
65
66 lazy_static! {
67 static ref CALLBACKS: Mutex<Option<Callbacks>> = Mutex::new(None);
68 }
69
on_init_complete()70 fn on_init_complete() {
71 let callbacks = CALLBACKS.lock().unwrap();
72 callbacks.as_ref().unwrap().init_tx.send(()).unwrap();
73 }
74
on_event(data: &[u8])75 fn on_event(data: &[u8]) {
76 log::error!("got event: {:02x?}", data);
77 let callbacks = CALLBACKS.lock().unwrap();
78 match EventPacket::parse(data) {
79 Ok(p) => callbacks.as_ref().unwrap().evt_tx.send(p).unwrap(),
80 Err(e) => log::error!("failure to parse event: {:?} data: {:02x?}", e, data),
81 }
82 }
83
on_acl(data: &[u8])84 fn on_acl(data: &[u8]) {
85 let callbacks = CALLBACKS.lock().unwrap();
86 match AclPacket::parse(data) {
87 Ok(p) => callbacks.as_ref().unwrap().acl_tx.send(p).unwrap(),
88 Err(e) => log::error!("failure to parse incoming ACL: {:?} data: {:02x?}", e, data),
89 }
90 }
91
on_sco(_data: &[u8])92 fn on_sco(_data: &[u8]) {}
93
on_iso(data: &[u8])94 fn on_iso(data: &[u8]) {
95 let callbacks = CALLBACKS.lock().unwrap();
96 match IsoPacket::parse(data) {
97 Ok(p) => callbacks.as_ref().unwrap().iso_tx.send(p).unwrap(),
98 Err(e) => log::error!("failure to parse incoming ISO: {:?} data: {:02x?}", e, data),
99 }
100 }
101
dispatch_outgoing( mut cmd_rx: UnboundedReceiver<CommandPacket>, mut acl_rx: UnboundedReceiver<AclPacket>, mut iso_rx: UnboundedReceiver<IsoPacket>, )102 async fn dispatch_outgoing(
103 mut cmd_rx: UnboundedReceiver<CommandPacket>,
104 mut acl_rx: UnboundedReceiver<AclPacket>,
105 mut iso_rx: UnboundedReceiver<IsoPacket>,
106 ) {
107 loop {
108 select! {
109 Some(cmd) = cmd_rx.recv() => ffi::send_command(&cmd.to_bytes()),
110 Some(acl) = acl_rx.recv() => ffi::send_acl(&acl.to_bytes()),
111 Some(iso) = iso_rx.recv() => ffi::send_iso(&iso.to_bytes()),
112 else => break,
113 }
114 }
115 }
116