1 //! Anything related to the Qualification API (IBluetoothQA).
2 
3 use crate::callbacks::Callbacks;
4 use crate::{bluetooth::FLOSS_VER, Message, RPCProxy};
5 use bt_topshim::btif::{BtDiscMode, BtStatus, RawAddress};
6 use bt_topshim::profiles::hid_host::BthhReportType;
7 use tokio::sync::mpsc::Sender;
8 
9 /// Defines the Qualification API
10 pub trait IBluetoothQA {
11     /// Register client callback
register_qa_callback(&mut self, callback: Box<dyn IBluetoothQACallback + Send>) -> u3212     fn register_qa_callback(&mut self, callback: Box<dyn IBluetoothQACallback + Send>) -> u32;
13     /// Unregister a client callback
unregister_qa_callback(&mut self, callback_id: u32) -> bool14     fn unregister_qa_callback(&mut self, callback_id: u32) -> bool;
15     /// Register a media player
add_media_player(&self, name: String, browsing_supported: bool)16     fn add_media_player(&self, name: String, browsing_supported: bool);
17     /// Send RFCOMM MSC command to the remote
rfcomm_send_msc(&self, dlci: u8, addr: RawAddress)18     fn rfcomm_send_msc(&self, dlci: u8, addr: RawAddress);
19     /// Fetch adapter's discoverable mode.
20     /// Result will be returned in the callback |OnFetchDiscoverableModeComplete|
fetch_discoverable_mode(&self)21     fn fetch_discoverable_mode(&self);
22     /// Fetch adapter's connectable mode.
23     /// Result will be returned in the callback |OnFetchConnectableComplete|
fetch_connectable(&self)24     fn fetch_connectable(&self);
25     /// Set adapter's connectable mode.
26     /// Result will be returned in the callback |OnSetConnectableComplete|
set_connectable(&self, mode: bool)27     fn set_connectable(&self, mode: bool);
28     /// Fetch the adapter's Bluetooth friendly name.
29     /// Result will be returned in the callback |OnFetchAliasComplete|
fetch_alias(&self)30     fn fetch_alias(&self);
31     /// Returns the adapter's Device ID information in modalias format
32     /// used by the kernel and udev.
get_modalias(&self) -> String33     fn get_modalias(&self) -> String;
34     /// Gets HID report on the peer.
35     /// Result will be returned in the callback |OnGetHIDReportComplete|
get_hid_report(&self, addr: RawAddress, report_type: BthhReportType, report_id: u8)36     fn get_hid_report(&self, addr: RawAddress, report_type: BthhReportType, report_id: u8);
37     /// Sets HID report to the peer.
38     /// Result will be returned in the callback |OnSetHIDReportComplete|
set_hid_report(&self, addr: RawAddress, report_type: BthhReportType, report: String)39     fn set_hid_report(&self, addr: RawAddress, report_type: BthhReportType, report: String);
40     /// Sends HID data report to the peer.
41     /// Result will be returned in the callback |OnSendHIDDataComplete|
send_hid_data(&self, addr: RawAddress, data: String)42     fn send_hid_data(&self, addr: RawAddress, data: String);
43     /// Sends HID virtual unplug to the peer.
44     /// Result will be returned in the callback |OnSendHIDVirtualUnplugComplete|
send_hid_virtual_unplug(&self, addr: RawAddress)45     fn send_hid_virtual_unplug(&self, addr: RawAddress);
46 }
47 
48 pub trait IBluetoothQACallback: RPCProxy {
on_fetch_discoverable_mode_completed(&mut self, mode: BtDiscMode)49     fn on_fetch_discoverable_mode_completed(&mut self, mode: BtDiscMode);
on_fetch_connectable_completed(&mut self, connectable: bool)50     fn on_fetch_connectable_completed(&mut self, connectable: bool);
on_set_connectable_completed(&mut self, succeed: bool)51     fn on_set_connectable_completed(&mut self, succeed: bool);
on_fetch_alias_completed(&mut self, alias: String)52     fn on_fetch_alias_completed(&mut self, alias: String);
on_get_hid_report_completed(&mut self, status: BtStatus)53     fn on_get_hid_report_completed(&mut self, status: BtStatus);
on_set_hid_report_completed(&mut self, status: BtStatus)54     fn on_set_hid_report_completed(&mut self, status: BtStatus);
on_send_hid_data_completed(&mut self, status: BtStatus)55     fn on_send_hid_data_completed(&mut self, status: BtStatus);
on_send_hid_virtual_unplug_completed(&mut self, status: BtStatus)56     fn on_send_hid_virtual_unplug_completed(&mut self, status: BtStatus);
57 }
58 
59 pub struct BluetoothQA {
60     tx: Sender<Message>,
61     callbacks: Callbacks<dyn IBluetoothQACallback + Send>,
62 }
63 
64 impl BluetoothQA {
new(tx: Sender<Message>) -> BluetoothQA65     pub fn new(tx: Sender<Message>) -> BluetoothQA {
66         BluetoothQA {
67             tx: tx.clone(),
68             callbacks: Callbacks::new(tx.clone(), Message::QaCallbackDisconnected),
69         }
70     }
on_fetch_discoverable_mode_completed(&mut self, mode: BtDiscMode)71     pub fn on_fetch_discoverable_mode_completed(&mut self, mode: BtDiscMode) {
72         self.callbacks.for_all_callbacks(|cb| {
73             cb.on_fetch_discoverable_mode_completed(mode.clone());
74         });
75     }
on_fetch_connectable_completed(&mut self, connectable: bool)76     pub fn on_fetch_connectable_completed(&mut self, connectable: bool) {
77         self.callbacks.for_all_callbacks(|cb| {
78             cb.on_fetch_connectable_completed(connectable);
79         });
80     }
on_set_connectable_completed(&mut self, succeed: bool)81     pub fn on_set_connectable_completed(&mut self, succeed: bool) {
82         self.callbacks.for_all_callbacks(|cb: &mut Box<dyn IBluetoothQACallback + Send>| {
83             cb.on_set_connectable_completed(succeed);
84         });
85     }
on_fetch_alias_completed(&mut self, alias: String)86     pub fn on_fetch_alias_completed(&mut self, alias: String) {
87         self.callbacks.for_all_callbacks(|cb: &mut Box<dyn IBluetoothQACallback + Send>| {
88             cb.on_fetch_alias_completed(alias.clone());
89         });
90     }
on_get_hid_report_completed(&mut self, status: BtStatus)91     pub fn on_get_hid_report_completed(&mut self, status: BtStatus) {
92         self.callbacks.for_all_callbacks(|cb: &mut Box<dyn IBluetoothQACallback + Send>| {
93             cb.on_get_hid_report_completed(status);
94         });
95     }
on_set_hid_report_completed(&mut self, status: BtStatus)96     pub fn on_set_hid_report_completed(&mut self, status: BtStatus) {
97         self.callbacks.for_all_callbacks(|cb: &mut Box<dyn IBluetoothQACallback + Send>| {
98             cb.on_set_hid_report_completed(status);
99         });
100     }
on_send_hid_data_completed(&mut self, status: BtStatus)101     pub fn on_send_hid_data_completed(&mut self, status: BtStatus) {
102         self.callbacks.for_all_callbacks(|cb: &mut Box<dyn IBluetoothQACallback + Send>| {
103             cb.on_send_hid_data_completed(status);
104         });
105     }
on_send_hid_virtual_unplug_completed(&mut self, status: BtStatus)106     pub fn on_send_hid_virtual_unplug_completed(&mut self, status: BtStatus) {
107         self.callbacks.for_all_callbacks(|cb: &mut Box<dyn IBluetoothQACallback + Send>| {
108             cb.on_send_hid_virtual_unplug_completed(status);
109         });
110     }
111 }
112 
113 impl IBluetoothQA for BluetoothQA {
register_qa_callback(&mut self, callback: Box<dyn IBluetoothQACallback + Send>) -> u32114     fn register_qa_callback(&mut self, callback: Box<dyn IBluetoothQACallback + Send>) -> u32 {
115         self.callbacks.add_callback(callback)
116     }
117 
unregister_qa_callback(&mut self, callback_id: u32) -> bool118     fn unregister_qa_callback(&mut self, callback_id: u32) -> bool {
119         self.callbacks.remove_callback(callback_id)
120     }
add_media_player(&self, name: String, browsing_supported: bool)121     fn add_media_player(&self, name: String, browsing_supported: bool) {
122         let txl = self.tx.clone();
123         tokio::spawn(async move {
124             let _ = txl.send(Message::QaAddMediaPlayer(name, browsing_supported)).await;
125         });
126     }
rfcomm_send_msc(&self, dlci: u8, addr: RawAddress)127     fn rfcomm_send_msc(&self, dlci: u8, addr: RawAddress) {
128         let txl = self.tx.clone();
129         tokio::spawn(async move {
130             let _ = txl.send(Message::QaRfcommSendMsc(dlci, addr)).await;
131         });
132     }
fetch_discoverable_mode(&self)133     fn fetch_discoverable_mode(&self) {
134         let txl = self.tx.clone();
135         tokio::spawn(async move {
136             let _ = txl.send(Message::QaFetchDiscoverableMode).await;
137         });
138     }
fetch_connectable(&self)139     fn fetch_connectable(&self) {
140         let txl = self.tx.clone();
141         tokio::spawn(async move {
142             let _ = txl.send(Message::QaFetchConnectable).await;
143         });
144     }
set_connectable(&self, mode: bool)145     fn set_connectable(&self, mode: bool) {
146         let txl = self.tx.clone();
147         tokio::spawn(async move {
148             let _ = txl.send(Message::QaSetConnectable(mode)).await;
149         });
150     }
fetch_alias(&self)151     fn fetch_alias(&self) {
152         let txl = self.tx.clone();
153         tokio::spawn(async move {
154             let _ = txl.send(Message::QaFetchAlias).await;
155         });
156     }
get_modalias(&self) -> String157     fn get_modalias(&self) -> String {
158         format!("bluetooth:v00E0pC405d{:04x}", FLOSS_VER)
159     }
get_hid_report(&self, addr: RawAddress, report_type: BthhReportType, report_id: u8)160     fn get_hid_report(&self, addr: RawAddress, report_type: BthhReportType, report_id: u8) {
161         let txl = self.tx.clone();
162         tokio::spawn(async move {
163             let _ = txl.send(Message::QaGetHidReport(addr, report_type, report_id)).await;
164         });
165     }
set_hid_report(&self, addr: RawAddress, report_type: BthhReportType, report: String)166     fn set_hid_report(&self, addr: RawAddress, report_type: BthhReportType, report: String) {
167         let txl = self.tx.clone();
168         tokio::spawn(async move {
169             let _ = txl.send(Message::QaSetHidReport(addr, report_type, report)).await;
170         });
171     }
send_hid_data(&self, addr: RawAddress, data: String)172     fn send_hid_data(&self, addr: RawAddress, data: String) {
173         let txl = self.tx.clone();
174         tokio::spawn(async move {
175             let _ = txl.send(Message::QaSendHidData(addr, data)).await;
176         });
177     }
send_hid_virtual_unplug(&self, addr: RawAddress)178     fn send_hid_virtual_unplug(&self, addr: RawAddress) {
179         let txl = self.tx.clone();
180         tokio::spawn(async move {
181             let _ = txl.send(Message::QaSendHidVirtualUnplug(addr)).await;
182         });
183     }
184 }
185