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