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