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