1 //! TODO(b/277818879) - Temporary DIS implementation 2 3 use log; 4 use std::sync::{Arc, Mutex}; 5 use tokio::sync::mpsc::Sender; 6 7 use crate::bluetooth_gatt::{ 8 BluetoothGatt, BluetoothGattCharacteristic, BluetoothGattService, GattDbElementType, 9 IBluetoothGatt, IBluetoothGattServerCallback, 10 }; 11 use crate::uuid::{Profile, UuidHelper}; 12 use crate::{Message, RPCProxy}; 13 use bt_topshim::profiles::gatt::{GattStatus, LePhy}; 14 use bt_topshim::sysprop; 15 16 /// Random uuid generated for registering against gatt server. 17 const DIS_APP_RANDOM_UUID: &str = "1b518948-fd77-4459-906f-4923104bb639"; 18 19 /// UUID for PNP ID characteristic. 20 const PNP_ID_CHAR_UUID: &str = "00002A50-0000-1000-8000-00805F9B34FB"; 21 22 /// Handles exporting the Device Information Service (DIS). 23 pub struct DeviceInformation { 24 /// Reference to Gatt server implementation to export service. 25 bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, 26 27 /// Server id (available once we are registered). 28 gatt_server_id: Option<i32>, 29 30 /// Handle for the PNP ID characteristic. 31 pnp_id_handle: Option<i32>, 32 33 /// Sender for stack mainloop. 34 tx: Sender<Message>, 35 } 36 37 impl DeviceInformation { new(bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, tx: Sender<Message>) -> Self38 pub fn new(bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, tx: Sender<Message>) -> Self { 39 Self { bluetooth_gatt, gatt_server_id: None, pnp_id_handle: None, tx } 40 } 41 initialize(&mut self)42 pub(crate) fn initialize(&mut self) { 43 let callback = Box::new(DeviceInformationServerCallbacks::new(self.tx.clone())); 44 45 // First register for callbacks with the server. 46 self.bluetooth_gatt.lock().unwrap().register_server( 47 DIS_APP_RANDOM_UUID.to_string(), 48 callback, 49 /*eatt_support=*/ true, 50 ); 51 } 52 handle_callbacks(&mut self, callback: &ServiceCallbacks)53 pub(crate) fn handle_callbacks(&mut self, callback: &ServiceCallbacks) { 54 match callback { 55 ServiceCallbacks::Registered(status, server_id) => { 56 if status != &GattStatus::Success { 57 log::error!("DIS failed to register callbacks. Status={:?}", status); 58 return; 59 } 60 61 self.gatt_server_id = Some(*server_id); 62 63 // Construct and add Device Information service. 64 let mut service = BluetoothGattService::new( 65 UuidHelper::get_profile_uuid(&Profile::Dis) 66 .expect("DIS uuid mapping missing") 67 .clone(), 68 /*instance_id=*/ 0, 69 GattDbElementType::PrimaryService.into(), 70 ); 71 72 service.characteristics.push(BluetoothGattCharacteristic::new( 73 UuidHelper::from_string(PNP_ID_CHAR_UUID).expect("PNP ID uuid is malformed"), 74 /*instance_id=*/ 0, 75 BluetoothGattCharacteristic::PROPERTY_READ, 76 BluetoothGattCharacteristic::PERMISSION_READ, 77 )); 78 79 self.bluetooth_gatt.lock().unwrap().add_service(*server_id, service); 80 } 81 82 ServiceCallbacks::ServiceAdded(status, service) => { 83 if status != &GattStatus::Success { 84 return; 85 } 86 87 let pnp_uuid = 88 UuidHelper::from_string(PNP_ID_CHAR_UUID).expect("PNP ID uuid is malformed"); 89 90 // Find the PNP ID characteristic we inserted before and store 91 // the handle for it. 92 for characteristic in &service.characteristics { 93 if characteristic.uuid == pnp_uuid { 94 self.pnp_id_handle = Some(characteristic.instance_id); 95 } 96 } 97 } 98 ServiceCallbacks::OnCharacteristicReadRequest( 99 addr, 100 trans_id, 101 offset, 102 _is_long, 103 handle, 104 ) => match (self.gatt_server_id, self.pnp_id_handle) { 105 (Some(server_id), Some(pnp_handle)) => { 106 if &pnp_handle == handle { 107 let vendor_id = sysprop::get_i32(sysprop::PropertyI32::VendorId); 108 let vendor_id_source = 109 sysprop::get_i32(sysprop::PropertyI32::VendorIdSource); 110 let product_id = sysprop::get_i32(sysprop::PropertyI32::ProductId); 111 let product_version = 112 sysprop::get_i32(sysprop::PropertyI32::ProductVersion); 113 114 // PNP ID ordering (all values are in little endian): 115 // - Vendor ID source (1 octet) 116 // - Vendor ID (2 octet) 117 // - Product ID (2 octet) 118 // - Product Version (2 octet) 119 let mut value: Vec<u8> = Vec::new(); 120 value.push(vendor_id_source.to_le_bytes()[0]); 121 value.extend_from_slice(&vendor_id.to_le_bytes()[0..2]); 122 value.extend_from_slice(&product_id.to_le_bytes()[0..2]); 123 value.extend_from_slice(&product_version.to_le_bytes()[0..2]); 124 125 self.bluetooth_gatt.lock().unwrap().send_response( 126 server_id, 127 addr.clone(), 128 *trans_id, 129 GattStatus::Success, 130 *offset, 131 value, 132 ); 133 } 134 } 135 136 (_, _) => (), 137 }, 138 } 139 } 140 } 141 142 // Callbacks we need to handle for DIS. 143 pub enum ServiceCallbacks { 144 Registered(GattStatus, i32), 145 ServiceAdded(GattStatus, BluetoothGattService), 146 OnCharacteristicReadRequest(String, i32, i32, bool, i32), 147 } 148 149 // Handle callbacks for DIS to register 150 struct DeviceInformationServerCallbacks { 151 // Sender to the main loop 152 tx: Sender<Message>, 153 } 154 155 impl DeviceInformationServerCallbacks { new(tx: Sender<Message>) -> Self156 fn new(tx: Sender<Message>) -> Self { 157 Self { tx } 158 } 159 } 160 161 impl IBluetoothGattServerCallback for DeviceInformationServerCallbacks { on_server_registered(&mut self, status: GattStatus, server_id: i32)162 fn on_server_registered(&mut self, status: GattStatus, server_id: i32) { 163 let txl = self.tx.clone(); 164 tokio::spawn(async move { 165 let _ = txl.send(Message::Dis(ServiceCallbacks::Registered(status, server_id))).await; 166 }); 167 } 168 on_service_added(&mut self, status: GattStatus, service: BluetoothGattService)169 fn on_service_added(&mut self, status: GattStatus, service: BluetoothGattService) { 170 let txl = self.tx.clone(); 171 tokio::spawn(async move { 172 let _ = txl.send(Message::Dis(ServiceCallbacks::ServiceAdded(status, service))).await; 173 }); 174 } 175 on_characteristic_read_request( &mut self, addr: String, trans_id: i32, offset: i32, is_long: bool, handle: i32, )176 fn on_characteristic_read_request( 177 &mut self, 178 addr: String, 179 trans_id: i32, 180 offset: i32, 181 is_long: bool, 182 handle: i32, 183 ) { 184 let txl = self.tx.clone(); 185 tokio::spawn(async move { 186 let _ = txl 187 .send(Message::Dis(ServiceCallbacks::OnCharacteristicReadRequest( 188 addr, trans_id, offset, is_long, handle, 189 ))) 190 .await; 191 }); 192 } 193 194 // Remaining callbacks are unhandled 195 on_service_removed(&mut self, _status: GattStatus, _handle: i32)196 fn on_service_removed(&mut self, _status: GattStatus, _handle: i32) {} on_server_connection_state(&mut self, _server_id: i32, _connected: bool, _addr: String)197 fn on_server_connection_state(&mut self, _server_id: i32, _connected: bool, _addr: String) {} on_descriptor_read_request( &mut self, _addr: String, _trans_id: i32, _offset: i32, _is_long: bool, _handle: i32, )198 fn on_descriptor_read_request( 199 &mut self, 200 _addr: String, 201 _trans_id: i32, 202 _offset: i32, 203 _is_long: bool, 204 _handle: i32, 205 ) { 206 } on_characteristic_write_request( &mut self, _addr: String, _trans_id: i32, _offset: i32, _len: i32, _is_prep: bool, _need_rsp: bool, _handle: i32, _value: Vec<u8>, )207 fn on_characteristic_write_request( 208 &mut self, 209 _addr: String, 210 _trans_id: i32, 211 _offset: i32, 212 _len: i32, 213 _is_prep: bool, 214 _need_rsp: bool, 215 _handle: i32, 216 _value: Vec<u8>, 217 ) { 218 } on_descriptor_write_request( &mut self, _addr: String, _trans_id: i32, _offset: i32, _len: i32, _is_prep: bool, _need_rsp: bool, _handle: i32, _value: Vec<u8>, )219 fn on_descriptor_write_request( 220 &mut self, 221 _addr: String, 222 _trans_id: i32, 223 _offset: i32, 224 _len: i32, 225 _is_prep: bool, 226 _need_rsp: bool, 227 _handle: i32, 228 _value: Vec<u8>, 229 ) { 230 } on_execute_write(&mut self, _addr: String, _trans_id: i32, _exec_write: bool)231 fn on_execute_write(&mut self, _addr: String, _trans_id: i32, _exec_write: bool) {} on_notification_sent(&mut self, _addr: String, _status: GattStatus)232 fn on_notification_sent(&mut self, _addr: String, _status: GattStatus) {} on_mtu_changed(&mut self, _addr: String, _mtu: i32)233 fn on_mtu_changed(&mut self, _addr: String, _mtu: i32) {} on_phy_update( &mut self, _addr: String, _tx_phy: LePhy, _rx_phy: LePhy, _status: GattStatus, )234 fn on_phy_update( 235 &mut self, 236 _addr: String, 237 _tx_phy: LePhy, 238 _rx_phy: LePhy, 239 _status: GattStatus, 240 ) { 241 } on_phy_read(&mut self, _addr: String, _tx_phy: LePhy, _rx_phy: LePhy, _status: GattStatus)242 fn on_phy_read(&mut self, _addr: String, _tx_phy: LePhy, _rx_phy: LePhy, _status: GattStatus) {} on_connection_updated( &mut self, _addr: String, _interval: i32, _latency: i32, _timeout: i32, _status: GattStatus, )243 fn on_connection_updated( 244 &mut self, 245 _addr: String, 246 _interval: i32, 247 _latency: i32, 248 _timeout: i32, 249 _status: GattStatus, 250 ) { 251 } on_subrate_change( &mut self, _addr: String, _subrate_factor: i32, _latency: i32, _cont_num: i32, _timeout: i32, _status: GattStatus, )252 fn on_subrate_change( 253 &mut self, 254 _addr: String, 255 _subrate_factor: i32, 256 _latency: i32, 257 _cont_num: i32, 258 _timeout: i32, 259 _status: GattStatus, 260 ) { 261 } 262 } 263 264 impl RPCProxy for DeviceInformationServerCallbacks { get_object_id(&self) -> String265 fn get_object_id(&self) -> String { 266 "DIS Gatt Server Callback".to_string() 267 } 268 } 269