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