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     /// Snd 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 }
44 
45 pub trait IBluetoothQACallback: RPCProxy {
on_fetch_discoverable_mode_completed(&mut self, mode: BtDiscMode)46     fn on_fetch_discoverable_mode_completed(&mut self, mode: BtDiscMode);
on_fetch_connectable_completed(&mut self, connectable: bool)47     fn on_fetch_connectable_completed(&mut self, connectable: bool);
on_set_connectable_completed(&mut self, succeed: bool)48     fn on_set_connectable_completed(&mut self, succeed: bool);
on_fetch_alias_completed(&mut self, alias: String)49     fn on_fetch_alias_completed(&mut self, alias: String);
on_get_hid_report_completed(&mut self, status: BtStatus)50     fn on_get_hid_report_completed(&mut self, status: BtStatus);
on_set_hid_report_completed(&mut self, status: BtStatus)51     fn on_set_hid_report_completed(&mut self, status: BtStatus);
on_send_hid_data_completed(&mut self, status: BtStatus)52     fn on_send_hid_data_completed(&mut self, status: BtStatus);
53 }
54 
55 pub struct BluetoothQA {
56     tx: Sender<Message>,
57     callbacks: Callbacks<dyn IBluetoothQACallback + Send>,
58 }
59 
60 impl BluetoothQA {
new(tx: Sender<Message>) -> BluetoothQA61     pub fn new(tx: Sender<Message>) -> BluetoothQA {
62         BluetoothQA {
63             tx: tx.clone(),
64             callbacks: Callbacks::new(tx.clone(), Message::QaCallbackDisconnected),
65         }
66     }
on_fetch_discoverable_mode_completed(&mut self, mode: BtDiscMode)67     pub fn on_fetch_discoverable_mode_completed(&mut self, mode: BtDiscMode) {
68         self.callbacks.for_all_callbacks(|cb| {
69             cb.on_fetch_discoverable_mode_completed(mode.clone());
70         });
71     }
on_fetch_connectable_completed(&mut self, connectable: bool)72     pub fn on_fetch_connectable_completed(&mut self, connectable: bool) {
73         self.callbacks.for_all_callbacks(|cb| {
74             cb.on_fetch_connectable_completed(connectable);
75         });
76     }
on_set_connectable_completed(&mut self, succeed: bool)77     pub fn on_set_connectable_completed(&mut self, succeed: bool) {
78         self.callbacks.for_all_callbacks(|cb: &mut Box<dyn IBluetoothQACallback + Send>| {
79             cb.on_set_connectable_completed(succeed);
80         });
81     }
on_fetch_alias_completed(&mut self, alias: String)82     pub fn on_fetch_alias_completed(&mut self, alias: String) {
83         self.callbacks.for_all_callbacks(|cb: &mut Box<dyn IBluetoothQACallback + Send>| {
84             cb.on_fetch_alias_completed(alias.clone());
85         });
86     }
on_get_hid_report_completed(&mut self, status: BtStatus)87     pub fn on_get_hid_report_completed(&mut self, status: BtStatus) {
88         self.callbacks.for_all_callbacks(|cb: &mut Box<dyn IBluetoothQACallback + Send>| {
89             cb.on_get_hid_report_completed(status);
90         });
91     }
on_set_hid_report_completed(&mut self, status: BtStatus)92     pub fn on_set_hid_report_completed(&mut self, status: BtStatus) {
93         self.callbacks.for_all_callbacks(|cb: &mut Box<dyn IBluetoothQACallback + Send>| {
94             cb.on_set_hid_report_completed(status);
95         });
96     }
on_send_hid_data_completed(&mut self, status: BtStatus)97     pub fn on_send_hid_data_completed(&mut self, status: BtStatus) {
98         self.callbacks.for_all_callbacks(|cb: &mut Box<dyn IBluetoothQACallback + Send>| {
99             cb.on_send_hid_data_completed(status);
100         });
101     }
102 }
103 
104 impl IBluetoothQA for BluetoothQA {
register_qa_callback(&mut self, callback: Box<dyn IBluetoothQACallback + Send>) -> u32105     fn register_qa_callback(&mut self, callback: Box<dyn IBluetoothQACallback + Send>) -> u32 {
106         self.callbacks.add_callback(callback)
107     }
108 
unregister_qa_callback(&mut self, callback_id: u32) -> bool109     fn unregister_qa_callback(&mut self, callback_id: u32) -> bool {
110         self.callbacks.remove_callback(callback_id)
111     }
add_media_player(&self, name: String, browsing_supported: bool)112     fn add_media_player(&self, name: String, browsing_supported: bool) {
113         let txl = self.tx.clone();
114         tokio::spawn(async move {
115             let _ = txl.send(Message::QaAddMediaPlayer(name, browsing_supported)).await;
116         });
117     }
rfcomm_send_msc(&self, dlci: u8, addr: RawAddress)118     fn rfcomm_send_msc(&self, dlci: u8, addr: RawAddress) {
119         let txl = self.tx.clone();
120         tokio::spawn(async move {
121             let _ = txl.send(Message::QaRfcommSendMsc(dlci, addr)).await;
122         });
123     }
fetch_discoverable_mode(&self)124     fn fetch_discoverable_mode(&self) {
125         let txl = self.tx.clone();
126         tokio::spawn(async move {
127             let _ = txl.send(Message::QaFetchDiscoverableMode).await;
128         });
129     }
fetch_connectable(&self)130     fn fetch_connectable(&self) {
131         let txl = self.tx.clone();
132         tokio::spawn(async move {
133             let _ = txl.send(Message::QaFetchConnectable).await;
134         });
135     }
set_connectable(&self, mode: bool)136     fn set_connectable(&self, mode: bool) {
137         let txl = self.tx.clone();
138         tokio::spawn(async move {
139             let _ = txl.send(Message::QaSetConnectable(mode)).await;
140         });
141     }
fetch_alias(&self)142     fn fetch_alias(&self) {
143         let txl = self.tx.clone();
144         tokio::spawn(async move {
145             let _ = txl.send(Message::QaFetchAlias).await;
146         });
147     }
get_modalias(&self) -> String148     fn get_modalias(&self) -> String {
149         format!("bluetooth:v00E0pC405d{:04x}", FLOSS_VER)
150     }
get_hid_report(&self, addr: RawAddress, report_type: BthhReportType, report_id: u8)151     fn get_hid_report(&self, addr: RawAddress, report_type: BthhReportType, report_id: u8) {
152         let txl = self.tx.clone();
153         tokio::spawn(async move {
154             let _ = txl.send(Message::QaGetHidReport(addr, report_type, report_id)).await;
155         });
156     }
set_hid_report(&self, addr: RawAddress, report_type: BthhReportType, report: String)157     fn set_hid_report(&self, addr: RawAddress, report_type: BthhReportType, report: String) {
158         let txl = self.tx.clone();
159         tokio::spawn(async move {
160             let _ = txl.send(Message::QaSetHidReport(addr, report_type, report)).await;
161         });
162     }
send_hid_data(&self, addr: RawAddress, data: String)163     fn send_hid_data(&self, addr: RawAddress, data: String) {
164         let txl = self.tx.clone();
165         tokio::spawn(async move {
166             let _ = txl.send(Message::QaSendHidData(addr, data)).await;
167         });
168     }
169 }
170