1 //! Adapter service facade
2
3 use bt_topshim::btif;
4 use bt_topshim::btif::{BaseCallbacks, BaseCallbacksDispatcher, BluetoothInterface, BtIoCap};
5
6 use crate::utils::converters::{bluetooth_property_to_event_data, event_data_from_string};
7 use bt_topshim_facade_protobuf::empty::Empty;
8 use bt_topshim_facade_protobuf::facade::{
9 EventType, FetchEventsRequest, FetchEventsResponse, SetDefaultEventMaskExceptRequest,
10 SetDiscoveryModeRequest, SetDiscoveryModeResponse, SetLocalIoCapsRequest,
11 SetLocalIoCapsResponse, ToggleDiscoveryRequest, ToggleDiscoveryResponse, ToggleStackRequest,
12 ToggleStackResponse,
13 };
14 use bt_topshim_facade_protobuf::facade_grpc::{create_adapter_service, AdapterService};
15 use futures::sink::SinkExt;
16 use grpcio::*;
17 use num_traits::cast::FromPrimitive;
18
19 use std::sync::{Arc, Mutex};
20 use tokio::runtime::Runtime;
21 use tokio::sync::mpsc;
22 use tokio::sync::Mutex as TokioMutex;
23
get_bt_dispatcher( btif: Arc<Mutex<BluetoothInterface>>, tx: mpsc::Sender<BaseCallbacks>, ) -> BaseCallbacksDispatcher24 fn get_bt_dispatcher(
25 btif: Arc<Mutex<BluetoothInterface>>,
26 tx: mpsc::Sender<BaseCallbacks>,
27 ) -> BaseCallbacksDispatcher {
28 BaseCallbacksDispatcher {
29 dispatch: Box::new(move |cb: BaseCallbacks| {
30 if tx.clone().try_send(cb.clone()).is_err() {
31 println!("Cannot send event {:?}", cb);
32 }
33 match cb {
34 BaseCallbacks::AdapterState(state) => {
35 println!("State changed to {:?}", state);
36 }
37 BaseCallbacks::SspRequest(addr, variant, passkey) => {
38 println!(
39 "SSP Request made for address {:?} with variant {:?} and passkey {:?}",
40 addr.to_string(),
41 variant,
42 passkey
43 );
44 btif.lock().unwrap().ssp_reply(&addr, variant, 1, passkey);
45 }
46 BaseCallbacks::AdapterProperties(status, _, properties) => {
47 println!(
48 "Adapter attributes changed, status = {:?}, properties = {:?}",
49 status, properties
50 );
51 }
52 BaseCallbacks::DiscoveryState(state) => {
53 println!("Discovery state changed, state = {:?}, ", state);
54 }
55 BaseCallbacks::DeviceFound(_, properties) => {
56 println!("Device found with properties : {:?}", properties)
57 }
58 BaseCallbacks::BondState(_, address, state, _) => {
59 println!(
60 "Device in state {:?} with device address {}",
61 state,
62 address.to_string()
63 );
64 }
65 _ => (),
66 }
67 }),
68 }
69 }
70
71 /// Main object for Adapter facade service
72 #[derive(Clone)]
73 pub struct AdapterServiceImpl {
74 #[allow(dead_code)]
75 rt: Arc<Runtime>,
76 btif_intf: Arc<Mutex<BluetoothInterface>>,
77 event_rx: Arc<TokioMutex<mpsc::Receiver<BaseCallbacks>>>,
78 #[allow(dead_code)]
79 event_tx: mpsc::Sender<BaseCallbacks>,
80 }
81
encode_hex(bytes: &[u8]) -> String82 fn encode_hex(bytes: &[u8]) -> String {
83 let mut s = String::with_capacity(2 * bytes.len());
84 for &b in bytes {
85 let bstr: String = format!("{:02X}", b);
86 s.push_str(&bstr);
87 }
88 s
89 }
90
91 impl AdapterServiceImpl {
92 /// Create a new instance of the root facade service
create(rt: Arc<Runtime>, btif_intf: Arc<Mutex<BluetoothInterface>>) -> grpcio::Service93 pub fn create(rt: Arc<Runtime>, btif_intf: Arc<Mutex<BluetoothInterface>>) -> grpcio::Service {
94 let (event_tx, rx) = mpsc::channel(10);
95 btif_intf.lock().unwrap().initialize(
96 get_bt_dispatcher(btif_intf.clone(), event_tx.clone()),
97 vec!["INIT_gd_hci=true".to_string()],
98 );
99 create_adapter_service(Self {
100 rt,
101 btif_intf,
102 event_rx: Arc::new(TokioMutex::new(rx)),
103 event_tx,
104 })
105 }
106 }
107
108 impl AdapterService for AdapterServiceImpl {
fetch_events( &mut self, ctx: RpcContext<'_>, _req: FetchEventsRequest, mut sink: ServerStreamingSink<FetchEventsResponse>, )109 fn fetch_events(
110 &mut self,
111 ctx: RpcContext<'_>,
112 _req: FetchEventsRequest,
113 mut sink: ServerStreamingSink<FetchEventsResponse>,
114 ) {
115 let rx = self.event_rx.clone();
116 ctx.spawn(async move {
117 while let Some(event) = rx.lock().await.recv().await {
118 match event {
119 BaseCallbacks::AdapterState(_state) => {
120 let mut rsp = FetchEventsResponse::new();
121 rsp.event_type = EventType::ADAPTER_STATE.into();
122 rsp.params.insert(
123 String::from("state"),
124 event_data_from_string(String::from("ON")),
125 );
126 sink.send((rsp, WriteFlags::default())).await.unwrap();
127 }
128 BaseCallbacks::SspRequest(_, _, _) => {}
129 BaseCallbacks::LeRandCallback(random) => {
130 let mut rsp = FetchEventsResponse::new();
131 rsp.event_type = EventType::LE_RAND.into();
132 rsp.params.insert(
133 String::from("data"),
134 event_data_from_string(random.to_string()),
135 );
136 sink.send((rsp, WriteFlags::default())).await.unwrap();
137 }
138 BaseCallbacks::GenerateLocalOobData(transport, data) => {
139 let mut rsp = FetchEventsResponse::new();
140 rsp.event_type = EventType::GENERATE_LOCAL_OOB_DATA.into();
141 rsp.params.insert(
142 String::from("is_valid"),
143 event_data_from_string(String::from(if data.is_valid {
144 "1"
145 } else {
146 "0"
147 })),
148 );
149 rsp.params.insert(
150 String::from("transport"),
151 event_data_from_string(format!("{}", transport)),
152 );
153 rsp.params.insert(
154 String::from("address"),
155 event_data_from_string(encode_hex(&data.address)),
156 );
157 rsp.params.insert(
158 String::from("confirmation"),
159 event_data_from_string(encode_hex(&data.c)),
160 );
161 rsp.params.insert(
162 String::from("randomizer"),
163 event_data_from_string(encode_hex(&data.r)),
164 );
165 sink.send((rsp, WriteFlags::default())).await.unwrap();
166 }
167 BaseCallbacks::AdapterProperties(status, _, properties) => {
168 let mut rsp = FetchEventsResponse::new();
169 rsp.event_type = EventType::ADAPTER_PROPERTY.into();
170 rsp.params.insert(
171 String::from("status"),
172 event_data_from_string(format!("{:?}", status)),
173 );
174 for property in properties.clone() {
175 let (key, event_data) = bluetooth_property_to_event_data(property);
176 if key == "skip" {
177 continue;
178 }
179 rsp.params.insert(key, event_data);
180 }
181 sink.send((rsp, WriteFlags::default())).await.unwrap();
182 }
183 BaseCallbacks::DiscoveryState(state) => {
184 let mut rsp = FetchEventsResponse::new();
185 rsp.event_type = EventType::DISCOVERY_STATE.into();
186 rsp.params.insert(
187 String::from("discovery_state"),
188 event_data_from_string(format!("{:?}", state)),
189 );
190 sink.send((rsp, WriteFlags::default())).await.unwrap();
191 }
192 BaseCallbacks::DeviceFound(_, properties) => {
193 let mut rsp = FetchEventsResponse::new();
194 rsp.event_type = EventType::DEVICE_FOUND.into();
195 for property in properties.clone() {
196 let (key, event_data) = bluetooth_property_to_event_data(property);
197 if key == "skip" {
198 continue;
199 }
200 rsp.params.insert(key, event_data);
201 }
202 sink.send((rsp, WriteFlags::default())).await.unwrap();
203 }
204 BaseCallbacks::BondState(_, address, state, _) => {
205 let mut rsp = FetchEventsResponse::new();
206 rsp.event_type = EventType::BOND_STATE.into();
207 rsp.params.insert(
208 String::from("bond_state"),
209 event_data_from_string(format!("{:?}", state)),
210 );
211 rsp.params.insert(
212 String::from("address"),
213 event_data_from_string(address.to_string()),
214 );
215 sink.send((rsp, WriteFlags::default())).await.unwrap();
216 }
217 _ => (),
218 }
219 }
220 })
221 }
222
toggle_stack( &mut self, ctx: RpcContext<'_>, req: ToggleStackRequest, sink: UnarySink<ToggleStackResponse>, )223 fn toggle_stack(
224 &mut self,
225 ctx: RpcContext<'_>,
226 req: ToggleStackRequest,
227 sink: UnarySink<ToggleStackResponse>,
228 ) {
229 match req.start_stack {
230 true => self.btif_intf.lock().unwrap().enable(),
231 false => self.btif_intf.lock().unwrap().disable(),
232 };
233 ctx.spawn(async move {
234 sink.success(ToggleStackResponse::default()).await.unwrap();
235 })
236 }
237
set_discovery_mode( &mut self, ctx: RpcContext<'_>, req: SetDiscoveryModeRequest, sink: UnarySink<SetDiscoveryModeResponse>, )238 fn set_discovery_mode(
239 &mut self,
240 ctx: RpcContext<'_>,
241 req: SetDiscoveryModeRequest,
242 sink: UnarySink<SetDiscoveryModeResponse>,
243 ) {
244 let scan_mode = if req.enable_inquiry_scan {
245 btif::BtScanMode::ConnectableDiscoverable
246 } else if req.enable_page_scan {
247 btif::BtScanMode::Connectable
248 } else {
249 btif::BtScanMode::None_
250 };
251 let status = self
252 .btif_intf
253 .lock()
254 .unwrap()
255 .set_adapter_property(btif::BluetoothProperty::AdapterScanMode(scan_mode));
256
257 let mut resp = SetDiscoveryModeResponse::new();
258 resp.status = status;
259 ctx.spawn(async move {
260 sink.success(resp).await.unwrap();
261 })
262 }
263
clear_event_filter(&mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>)264 fn clear_event_filter(&mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>) {
265 self.btif_intf.lock().unwrap().clear_event_filter();
266 ctx.spawn(async move {
267 sink.success(Empty::default()).await.unwrap();
268 })
269 }
270
clear_event_mask(&mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>)271 fn clear_event_mask(&mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>) {
272 self.btif_intf.lock().unwrap().clear_event_mask();
273 ctx.spawn(async move {
274 sink.success(Empty::default()).await.unwrap();
275 })
276 }
277
clear_filter_accept_list( &mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>, )278 fn clear_filter_accept_list(
279 &mut self,
280 ctx: RpcContext<'_>,
281 _req: Empty,
282 sink: UnarySink<Empty>,
283 ) {
284 self.btif_intf.lock().unwrap().clear_filter_accept_list();
285 ctx.spawn(async move {
286 sink.success(Empty::default()).await.unwrap();
287 })
288 }
289
disconnect_all_acls(&mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>)290 fn disconnect_all_acls(&mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>) {
291 self.btif_intf.lock().unwrap().disconnect_all_acls();
292 ctx.spawn(async move {
293 sink.success(Empty::default()).await.unwrap();
294 })
295 }
296
le_rand(&mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>)297 fn le_rand(&mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>) {
298 self.btif_intf.lock().unwrap().le_rand();
299 ctx.spawn(async move {
300 sink.success(Empty::default()).await.unwrap();
301 })
302 }
303
allow_wake_by_hid(&mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>)304 fn allow_wake_by_hid(&mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>) {
305 self.btif_intf.lock().unwrap().allow_wake_by_hid();
306 ctx.spawn(async move {
307 sink.success(Empty::default()).await.unwrap();
308 })
309 }
310
restore_filter_accept_list( &mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>, )311 fn restore_filter_accept_list(
312 &mut self,
313 ctx: RpcContext<'_>,
314 _req: Empty,
315 sink: UnarySink<Empty>,
316 ) {
317 self.btif_intf.lock().unwrap().restore_filter_accept_list();
318 ctx.spawn(async move {
319 sink.success(Empty::default()).await.unwrap();
320 })
321 }
322
set_default_event_mask_except( &mut self, ctx: RpcContext<'_>, req: SetDefaultEventMaskExceptRequest, sink: UnarySink<Empty>, )323 fn set_default_event_mask_except(
324 &mut self,
325 ctx: RpcContext<'_>,
326 req: SetDefaultEventMaskExceptRequest,
327 sink: UnarySink<Empty>,
328 ) {
329 self.btif_intf.lock().unwrap().set_default_event_mask_except(req.mask, req.le_mask);
330 ctx.spawn(async move {
331 sink.success(Empty::default()).await.unwrap();
332 })
333 }
334
set_event_filter_inquiry_result_all_devices( &mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>, )335 fn set_event_filter_inquiry_result_all_devices(
336 &mut self,
337 ctx: RpcContext<'_>,
338 _req: Empty,
339 sink: UnarySink<Empty>,
340 ) {
341 self.btif_intf.lock().unwrap().set_event_filter_inquiry_result_all_devices();
342 ctx.spawn(async move {
343 sink.success(Empty::default()).await.unwrap();
344 })
345 }
346
set_event_filter_connection_setup_all_devices( &mut self, ctx: RpcContext<'_>, _req: Empty, sink: UnarySink<Empty>, )347 fn set_event_filter_connection_setup_all_devices(
348 &mut self,
349 ctx: RpcContext<'_>,
350 _req: Empty,
351 sink: UnarySink<Empty>,
352 ) {
353 self.btif_intf.lock().unwrap().set_event_filter_connection_setup_all_devices();
354 ctx.spawn(async move {
355 sink.success(Empty::default()).await.unwrap();
356 })
357 }
358
set_local_io_caps( &mut self, ctx: RpcContext<'_>, req: SetLocalIoCapsRequest, sink: UnarySink<SetLocalIoCapsResponse>, )359 fn set_local_io_caps(
360 &mut self,
361 ctx: RpcContext<'_>,
362 req: SetLocalIoCapsRequest,
363 sink: UnarySink<SetLocalIoCapsResponse>,
364 ) {
365 let status = self.btif_intf.lock().unwrap().set_adapter_property(
366 btif::BluetoothProperty::LocalIoCaps(
367 BtIoCap::from_i32(req.io_capability).unwrap_or(BtIoCap::Unknown),
368 ),
369 );
370 let mut resp = SetLocalIoCapsResponse::new();
371 resp.status = status;
372 ctx.spawn(async move {
373 sink.success(resp).await.unwrap();
374 })
375 }
376
toggle_discovery( &mut self, ctx: RpcContext<'_>, req: ToggleDiscoveryRequest, sink: UnarySink<ToggleDiscoveryResponse>, )377 fn toggle_discovery(
378 &mut self,
379 ctx: RpcContext<'_>,
380 req: ToggleDiscoveryRequest,
381 sink: UnarySink<ToggleDiscoveryResponse>,
382 ) {
383 let status = match req.is_start {
384 true => self.btif_intf.lock().unwrap().start_discovery(),
385 false => self.btif_intf.lock().unwrap().cancel_discovery(),
386 };
387 let mut resp = ToggleDiscoveryResponse::new();
388 resp.status = status;
389 ctx.spawn(async move {
390 sink.success(resp).await.unwrap();
391 })
392 }
393 }
394