• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Floss Bluetooth stack.
2 //!
3 //! This crate provides the API implementation of the Fluoride/GD Bluetooth
4 //! stack, independent of any RPC projection.
5 
6 #[macro_use]
7 extern crate num_derive;
8 
9 pub mod bluetooth;
10 pub mod bluetooth_gatt;
11 pub mod bluetooth_media;
12 pub mod suspend;
13 pub mod uuid;
14 
15 use log::debug;
16 use std::sync::{Arc, Mutex};
17 use tokio::sync::mpsc::channel;
18 use tokio::sync::mpsc::{Receiver, Sender};
19 
20 use crate::bluetooth::Bluetooth;
21 use crate::bluetooth_gatt::BluetoothGatt;
22 use crate::bluetooth_media::{BluetoothMedia, MediaActions};
23 use crate::suspend::Suspend;
24 use bt_topshim::{
25     btif::BaseCallbacks,
26     profiles::{
27         a2dp::A2dpCallbacks, avrcp::AvrcpCallbacks, gatt::GattClientCallbacks,
28         gatt::GattServerCallbacks, hfp::HfpCallbacks, hid_host::HHCallbacks, sdp::SdpCallbacks,
29     },
30 };
31 
32 #[derive(Clone, Debug)]
33 pub enum BluetoothCallbackType {
34     Adapter,
35     Connection,
36 }
37 
38 /// Message types that are sent to the stack main dispatch loop.
39 pub enum Message {
40     // Callbacks from libbluetooth
41     A2dp(A2dpCallbacks),
42     Avrcp(AvrcpCallbacks),
43     Base(BaseCallbacks),
44     GattClient(GattClientCallbacks),
45     GattServer(GattServerCallbacks),
46     HidHost(HHCallbacks),
47     Hfp(HfpCallbacks),
48     Sdp(SdpCallbacks),
49 
50     // Actions within the stack
51     Media(MediaActions),
52 
53     // Client callback disconnections
54     BluetoothCallbackDisconnected(u32, BluetoothCallbackType),
55 
56     // Update list of found devices and remove old instances.
57     DeviceFreshnessCheck,
58 
59     // Suspend related
60     SuspendCallbackRegistered(u32),
61     SuspendCallbackDisconnected(u32),
62 }
63 
64 /// Umbrella class for the Bluetooth stack.
65 pub struct Stack {}
66 
67 impl Stack {
68     /// Creates an mpsc channel for passing messages to the main dispatch loop.
create_channel() -> (Sender<Message>, Receiver<Message>)69     pub fn create_channel() -> (Sender<Message>, Receiver<Message>) {
70         channel::<Message>(1)
71     }
72 
73     /// Runs the main dispatch loop.
dispatch( mut rx: Receiver<Message>, bluetooth: Arc<Mutex<Box<Bluetooth>>>, bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>, suspend: Arc<Mutex<Box<Suspend>>>, )74     pub async fn dispatch(
75         mut rx: Receiver<Message>,
76         bluetooth: Arc<Mutex<Box<Bluetooth>>>,
77         bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>,
78         bluetooth_media: Arc<Mutex<Box<BluetoothMedia>>>,
79         suspend: Arc<Mutex<Box<Suspend>>>,
80     ) {
81         loop {
82             let m = rx.recv().await;
83 
84             if m.is_none() {
85                 eprintln!("Message dispatch loop quit");
86                 break;
87             }
88 
89             match m.unwrap() {
90                 Message::A2dp(a) => {
91                     bluetooth_media.lock().unwrap().dispatch_a2dp_callbacks(a);
92                 }
93 
94                 Message::Avrcp(av) => {
95                     bluetooth_media.lock().unwrap().dispatch_avrcp_callbacks(av);
96                 }
97 
98                 Message::Base(b) => {
99                     bluetooth.lock().unwrap().dispatch_base_callbacks(b);
100                 }
101 
102                 Message::GattClient(m) => {
103                     bluetooth_gatt.lock().unwrap().dispatch_gatt_client_callbacks(m);
104                 }
105 
106                 Message::GattServer(m) => {
107                     // TODO(b/193685149): dispatch GATT server callbacks.
108                     debug!("Unhandled Message::GattServer: {:?}", m);
109                 }
110 
111                 Message::Hfp(hf) => {
112                     bluetooth_media.lock().unwrap().dispatch_hfp_callbacks(hf);
113                 }
114 
115                 Message::HidHost(_h) => {
116                     // TODO(abps) - Handle hid host callbacks
117                     debug!("Received HH callback");
118                 }
119 
120                 Message::Sdp(s) => {
121                     bluetooth.lock().unwrap().dispatch_sdp_callbacks(s);
122                 }
123 
124                 Message::Media(action) => {
125                     bluetooth_media.lock().unwrap().dispatch_media_actions(action);
126                 }
127 
128                 Message::BluetoothCallbackDisconnected(id, cb_type) => {
129                     bluetooth.lock().unwrap().callback_disconnected(id, cb_type);
130                 }
131 
132                 Message::DeviceFreshnessCheck => {
133                     bluetooth.lock().unwrap().trigger_freshness_check();
134                 }
135 
136                 Message::SuspendCallbackRegistered(id) => {
137                     suspend.lock().unwrap().callback_registered(id);
138                 }
139 
140                 Message::SuspendCallbackDisconnected(id) => {
141                     suspend.lock().unwrap().remove_callback(id);
142                 }
143             }
144         }
145     }
146 }
147 
148 /// Signifies that the object may be a proxy to a remote RPC object.
149 ///
150 /// An object that implements RPCProxy trait signifies that the object may be a proxy to a remote
151 /// RPC object. Therefore the object may be disconnected and thus should implement
152 /// `register_disconnect` to let others observe the disconnection event.
153 pub trait RPCProxy {
154     /// Registers disconnect observer that will be notified when the remote object is disconnected.
register_disconnect(&mut self, f: Box<dyn Fn(u32) + Send>) -> u32155     fn register_disconnect(&mut self, f: Box<dyn Fn(u32) + Send>) -> u32;
156 
157     /// Returns the ID of the object. For example this would be an object path in D-Bus RPC.
get_object_id(&self) -> String158     fn get_object_id(&self) -> String;
159 
160     /// Unregisters callback with this id.
unregister(&mut self, id: u32) -> bool161     fn unregister(&mut self, id: u32) -> bool;
162 
163     /// Makes this object available for remote call.
export_for_rpc(self: Box<Self>)164     fn export_for_rpc(self: Box<Self>);
165 }
166