1 use num_derive::{FromPrimitive, ToPrimitive}; 2 use num_traits::cast::{FromPrimitive, ToPrimitive}; 3 use std::convert::TryFrom; 4 use std::fmt::{Debug, Formatter, Result}; 5 use std::os::raw::c_char; 6 use std::sync::{Arc, Mutex}; 7 use std::vec::Vec; 8 9 use crate::bindings::root as bindings; 10 use crate::btif::{ 11 ascii_to_string, ptr_to_vec, BluetoothInterface, BtStatus, RawAddress, SupportedProfiles, Uuid, 12 }; 13 use crate::ccall; 14 use crate::topstack::get_dispatchers; 15 use crate::utils::{LTCheckedPtr, LTCheckedPtrMut}; 16 use topshim_macros::{cb_variant, log_args}; 17 18 #[derive(Clone, Debug, FromPrimitive, ToPrimitive, PartialEq, PartialOrd)] 19 #[repr(u32)] 20 pub enum BtSdpType { 21 Raw = 0, 22 MapMas, 23 MapMns, 24 PbapPse, 25 PbapPce, 26 OppServer, 27 SapServer, 28 Dip, 29 Mps, 30 } 31 32 impl From<bindings::bluetooth_sdp_types> for BtSdpType { from(item: bindings::bluetooth_sdp_types) -> Self33 fn from(item: bindings::bluetooth_sdp_types) -> Self { 34 BtSdpType::from_u32(item).unwrap_or(BtSdpType::Raw) 35 } 36 } 37 38 impl From<&BtSdpRecord> for BtSdpType { from(record: &BtSdpRecord) -> Self39 fn from(record: &BtSdpRecord) -> Self { 40 match record { 41 BtSdpRecord::HeaderOverlay(header) => header.sdp_type.clone(), 42 BtSdpRecord::MapMas(record) => record.hdr.sdp_type.clone(), 43 BtSdpRecord::MapMns(record) => record.hdr.sdp_type.clone(), 44 BtSdpRecord::PbapPse(record) => record.hdr.sdp_type.clone(), 45 BtSdpRecord::PbapPce(record) => record.hdr.sdp_type.clone(), 46 BtSdpRecord::OppServer(record) => record.hdr.sdp_type.clone(), 47 BtSdpRecord::SapServer(record) => record.hdr.sdp_type.clone(), 48 BtSdpRecord::Dip(record) => record.hdr.sdp_type.clone(), 49 BtSdpRecord::Mps(record) => record.hdr.sdp_type.clone(), 50 } 51 } 52 } 53 54 #[derive(Clone, Debug)] 55 pub struct BtSdpHeaderOverlay { 56 pub sdp_type: BtSdpType, 57 pub uuid: Uuid, 58 pub service_name_length: u32, 59 pub service_name: String, 60 pub rfcomm_channel_number: i32, 61 pub l2cap_psm: i32, 62 pub profile_version: i32, 63 64 pub user1_len: i32, 65 pub user1_data: Vec<u8>, 66 pub user2_len: i32, 67 pub user2_data: Vec<u8>, 68 } 69 70 impl From<bindings::_bluetooth_sdp_hdr_overlay> for BtSdpHeaderOverlay { from(item: bindings::_bluetooth_sdp_hdr_overlay) -> Self71 fn from(item: bindings::_bluetooth_sdp_hdr_overlay) -> Self { 72 let user1_len = item.user1_ptr_len; 73 let user1_data = unsafe { 74 std::slice::from_raw_parts(item.user1_ptr, item.user1_ptr_len as usize).to_vec() 75 }; 76 let user2_len = item.user2_ptr_len; 77 let user2_data = unsafe { 78 std::slice::from_raw_parts(item.user2_ptr, item.user2_ptr_len as usize).to_vec() 79 }; 80 81 let sdp_hdr = unsafe { 82 *((&item as *const bindings::_bluetooth_sdp_hdr_overlay) 83 as *const bindings::_bluetooth_sdp_hdr) 84 }; 85 let sdp_type = BtSdpType::from(sdp_hdr.type_); 86 let uuid = sdp_hdr.uuid; 87 let service_name_length = sdp_hdr.service_name_length; 88 let service_name = ascii_to_string( 89 unsafe { 90 std::slice::from_raw_parts( 91 sdp_hdr.service_name as *const u8, 92 sdp_hdr.service_name_length as usize, 93 ) 94 }, 95 sdp_hdr.service_name_length as usize, 96 ); 97 let rfcomm_channel_number = sdp_hdr.rfcomm_channel_number; 98 let l2cap_psm = sdp_hdr.l2cap_psm; 99 let profile_version = sdp_hdr.profile_version; 100 BtSdpHeaderOverlay { 101 sdp_type, 102 uuid, 103 service_name_length, 104 service_name, 105 rfcomm_channel_number, 106 l2cap_psm, 107 profile_version, 108 user1_len, 109 user1_data, 110 user2_len, 111 user2_data, 112 } 113 } 114 } 115 116 #[derive(Clone, Debug)] 117 pub struct BtSdpMasRecord { 118 pub hdr: BtSdpHeaderOverlay, 119 pub mas_instance_id: u32, 120 pub supported_features: u32, 121 pub supported_message_types: u32, 122 } 123 124 impl From<bindings::_bluetooth_sdp_mas_record> for BtSdpMasRecord { from(item: bindings::_bluetooth_sdp_mas_record) -> Self125 fn from(item: bindings::_bluetooth_sdp_mas_record) -> Self { 126 BtSdpMasRecord { 127 hdr: BtSdpHeaderOverlay::from(item.hdr), 128 mas_instance_id: item.mas_instance_id, 129 supported_features: item.supported_features, 130 supported_message_types: item.supported_message_types, 131 } 132 } 133 } 134 135 #[derive(Clone, Debug)] 136 pub struct BtSdpMnsRecord { 137 pub hdr: BtSdpHeaderOverlay, 138 pub supported_features: u32, 139 } 140 141 impl From<bindings::_bluetooth_sdp_mns_record> for BtSdpMnsRecord { from(item: bindings::_bluetooth_sdp_mns_record) -> Self142 fn from(item: bindings::_bluetooth_sdp_mns_record) -> Self { 143 BtSdpMnsRecord { 144 hdr: BtSdpHeaderOverlay::from(item.hdr), 145 supported_features: item.supported_features, 146 } 147 } 148 } 149 150 #[derive(Clone, Debug)] 151 pub struct BtSdpPseRecord { 152 pub hdr: BtSdpHeaderOverlay, 153 pub supported_features: u32, 154 pub supported_repositories: u32, 155 } 156 157 impl From<bindings::_bluetooth_sdp_pse_record> for BtSdpPseRecord { from(item: bindings::_bluetooth_sdp_pse_record) -> Self158 fn from(item: bindings::_bluetooth_sdp_pse_record) -> Self { 159 BtSdpPseRecord { 160 hdr: BtSdpHeaderOverlay::from(item.hdr), 161 supported_features: item.supported_features, 162 supported_repositories: item.supported_repositories, 163 } 164 } 165 } 166 167 #[derive(Clone, Debug)] 168 pub struct BtSdpPceRecord { 169 pub hdr: BtSdpHeaderOverlay, 170 } 171 172 impl From<bindings::_bluetooth_sdp_pce_record> for BtSdpPceRecord { from(item: bindings::_bluetooth_sdp_pce_record) -> Self173 fn from(item: bindings::_bluetooth_sdp_pce_record) -> Self { 174 BtSdpPceRecord { hdr: BtSdpHeaderOverlay::from(item.hdr) } 175 } 176 } 177 178 pub type SupportedFormatsList = [u8; 15usize]; 179 180 #[derive(Clone, Debug)] 181 pub struct BtSdpOpsRecord { 182 pub hdr: BtSdpHeaderOverlay, 183 pub supported_formats_list_len: i32, 184 pub supported_formats_list: SupportedFormatsList, 185 } 186 187 impl From<bindings::_bluetooth_sdp_ops_record> for BtSdpOpsRecord { from(item: bindings::_bluetooth_sdp_ops_record) -> Self188 fn from(item: bindings::_bluetooth_sdp_ops_record) -> Self { 189 BtSdpOpsRecord { 190 hdr: BtSdpHeaderOverlay::from(item.hdr), 191 supported_formats_list_len: item.supported_formats_list_len, 192 supported_formats_list: item.supported_formats_list, 193 } 194 } 195 } 196 197 #[derive(Clone, Debug)] 198 pub struct BtSdpSapRecord { 199 pub hdr: BtSdpHeaderOverlay, 200 } 201 202 impl From<bindings::_bluetooth_sdp_sap_record> for BtSdpSapRecord { from(item: bindings::_bluetooth_sdp_sap_record) -> Self203 fn from(item: bindings::_bluetooth_sdp_sap_record) -> Self { 204 BtSdpSapRecord { hdr: BtSdpHeaderOverlay::from(item.hdr) } 205 } 206 } 207 208 #[derive(Clone, Debug)] 209 pub struct BtSdpDipRecord { 210 pub hdr: BtSdpHeaderOverlay, 211 pub spec_id: u16, 212 pub vendor: u16, 213 pub vendor_id_source: u16, 214 pub product: u16, 215 pub version: u16, 216 pub primary_record: bool, 217 } 218 219 impl From<bindings::_bluetooth_sdp_dip_record> for BtSdpDipRecord { from(item: bindings::_bluetooth_sdp_dip_record) -> Self220 fn from(item: bindings::_bluetooth_sdp_dip_record) -> Self { 221 BtSdpDipRecord { 222 hdr: BtSdpHeaderOverlay::from(item.hdr), 223 spec_id: item.spec_id, 224 vendor: item.vendor, 225 vendor_id_source: item.vendor_id_source, 226 product: item.product, 227 version: item.version, 228 primary_record: item.primary_record, 229 } 230 } 231 } 232 233 pub type SupportedScenarios = [u8; 8usize]; 234 pub type SupportedDependencies = [u8; 2usize]; 235 236 #[derive(Clone, Debug)] 237 pub struct BtSdpMpsRecord { 238 pub hdr: BtSdpHeaderOverlay, 239 pub supported_scenarios_mpsd: SupportedScenarios, // LibBluetooth expects big endian data 240 pub supported_scenarios_mpmd: SupportedScenarios, // LibBluetooth expects big endian data 241 pub supported_dependencies: SupportedDependencies, // LibBluetooth expects big endian data 242 } 243 244 impl BtSdpMpsRecord { default() -> Self245 pub fn default() -> Self { 246 let empty_uuid = Uuid::try_from(vec![0x0, 0x0]).unwrap(); 247 BtSdpMpsRecord { 248 hdr: BtSdpHeaderOverlay { 249 sdp_type: BtSdpType::Mps, 250 uuid: empty_uuid, // Not used 251 service_name_length: 0, // Not used 252 service_name: String::new(), // Not used 253 rfcomm_channel_number: 0, // Not used 254 l2cap_psm: 0, // Not used 255 profile_version: 0x0100, 256 user1_len: 0, // Not used 257 user1_data: vec![], // Not used 258 user2_len: 0, // Not used 259 user2_data: vec![], // Not used 260 }, 261 // LibBluetooth accepts big endian data. CrOS supports: 262 // - 0 Answer Incoming Call during Audio Streaming (HFP-AG_A2DP-SRC) 263 // - 2 Outgoing Call during Audio Streaming (HFP-AG_A2DP-SRC) 264 // - 4 Reject/Ignore Incoming Call during Audio Streaming (HFP-AG_A2DP-SRC) 265 // - 6 HFP call termination during AVP connection (HFP-AG_A2DP-SRC) 266 // - 8 Press Play on Audio Player during active call (HFP-AG_A2DP-SRC) 267 // - 10 Start Audio Streaming after AVRCP Play Command (HFP-AG_A2DP-SRC) 268 // - 12 Suspend Audio Streaming after AVRCP Pause/Stop (HFP-AG_A2DP-SRC) 269 supported_scenarios_mpsd: [0, 0, 0, 0, 0, 0, 0b_1_0101, 0b_0101_0101], 270 supported_scenarios_mpmd: [0; 8], 271 // LibBluetooth accepts big endian data. CrOS supports: 272 // - 1 Sniff Mode During Streaming 273 // - 3 (Dis-)Connection Order / Behavior 274 supported_dependencies: [0, 0b_1010], 275 } 276 } 277 } 278 279 impl From<bindings::_bluetooth_sdp_mps_record> for BtSdpMpsRecord { from(item: bindings::_bluetooth_sdp_mps_record) -> Self280 fn from(item: bindings::_bluetooth_sdp_mps_record) -> Self { 281 BtSdpMpsRecord { 282 hdr: BtSdpHeaderOverlay::from(item.hdr), 283 supported_scenarios_mpsd: item.supported_scenarios_mpsd, 284 supported_scenarios_mpmd: item.supported_scenarios_mpmd, 285 supported_dependencies: item.supported_dependencies, 286 } 287 } 288 } 289 290 #[derive(Clone, Debug)] 291 pub enum BtSdpRecord { 292 HeaderOverlay(BtSdpHeaderOverlay), 293 MapMas(BtSdpMasRecord), 294 MapMns(BtSdpMnsRecord), 295 PbapPse(BtSdpPseRecord), 296 PbapPce(BtSdpPceRecord), 297 OppServer(BtSdpOpsRecord), 298 SapServer(BtSdpSapRecord), 299 Dip(BtSdpDipRecord), 300 Mps(BtSdpMpsRecord), 301 } 302 303 impl From<bindings::bluetooth_sdp_record> for BtSdpRecord { from(item: bindings::bluetooth_sdp_record) -> Self304 fn from(item: bindings::bluetooth_sdp_record) -> Self { 305 let sdp_type = unsafe { BtSdpType::from(item.hdr.type_) }; 306 307 match sdp_type { 308 BtSdpType::Raw => unsafe { 309 BtSdpRecord::HeaderOverlay(BtSdpHeaderOverlay::from(item.hdr)) 310 }, 311 BtSdpType::MapMas => unsafe { BtSdpRecord::MapMas(BtSdpMasRecord::from(item.mas)) }, 312 BtSdpType::MapMns => unsafe { BtSdpRecord::MapMns(BtSdpMnsRecord::from(item.mns)) }, 313 BtSdpType::PbapPse => unsafe { BtSdpRecord::PbapPse(BtSdpPseRecord::from(item.pse)) }, 314 BtSdpType::PbapPce => unsafe { BtSdpRecord::PbapPce(BtSdpPceRecord::from(item.pce)) }, 315 BtSdpType::OppServer => unsafe { 316 BtSdpRecord::OppServer(BtSdpOpsRecord::from(item.ops)) 317 }, 318 BtSdpType::SapServer => unsafe { 319 BtSdpRecord::SapServer(BtSdpSapRecord::from(item.sap)) 320 }, 321 BtSdpType::Dip => unsafe { BtSdpRecord::Dip(BtSdpDipRecord::from(item.dip)) }, 322 BtSdpType::Mps => unsafe { BtSdpRecord::Mps(BtSdpMpsRecord::from(item.mps)) }, 323 } 324 } 325 } 326 327 impl BtSdpRecord { convert_header<'a>(hdr: &'a mut BtSdpHeaderOverlay) -> bindings::bluetooth_sdp_hdr_overlay328 fn convert_header<'a>(hdr: &'a mut BtSdpHeaderOverlay) -> bindings::bluetooth_sdp_hdr_overlay { 329 let srv_name_ptr = LTCheckedPtrMut::from(&mut hdr.service_name); 330 let user1_ptr = LTCheckedPtr::from(&hdr.user1_data); 331 let user2_ptr = LTCheckedPtr::from(&hdr.user2_data); 332 bindings::bluetooth_sdp_hdr_overlay { 333 type_: hdr.sdp_type.to_u32().unwrap(), 334 uuid: hdr.uuid, 335 service_name_length: hdr.service_name_length, 336 service_name: srv_name_ptr.cast_into::<c_char>(), 337 rfcomm_channel_number: hdr.rfcomm_channel_number, 338 l2cap_psm: hdr.l2cap_psm, 339 profile_version: hdr.profile_version, 340 user1_ptr_len: hdr.user1_len, 341 user1_ptr: user1_ptr.into(), 342 user2_ptr_len: hdr.user2_len, 343 user2_ptr: user2_ptr.into(), 344 } 345 } 346 347 // Get sdp record with lifetime tied to self get_unsafe_record<'a>(&'a mut self) -> bindings::bluetooth_sdp_record348 fn get_unsafe_record<'a>(&'a mut self) -> bindings::bluetooth_sdp_record { 349 match self { 350 BtSdpRecord::HeaderOverlay(ref mut hdr) => { 351 bindings::bluetooth_sdp_record { hdr: BtSdpRecord::convert_header(hdr) } 352 } 353 BtSdpRecord::MapMas(mas) => bindings::bluetooth_sdp_record { 354 mas: bindings::_bluetooth_sdp_mas_record { 355 hdr: BtSdpRecord::convert_header(&mut mas.hdr), 356 mas_instance_id: mas.mas_instance_id, 357 supported_features: mas.supported_features, 358 supported_message_types: mas.supported_message_types, 359 }, 360 }, 361 BtSdpRecord::MapMns(mns) => bindings::bluetooth_sdp_record { 362 mns: bindings::_bluetooth_sdp_mns_record { 363 hdr: BtSdpRecord::convert_header(&mut mns.hdr), 364 supported_features: mns.supported_features, 365 }, 366 }, 367 BtSdpRecord::PbapPse(pse) => bindings::bluetooth_sdp_record { 368 pse: bindings::_bluetooth_sdp_pse_record { 369 hdr: BtSdpRecord::convert_header(&mut pse.hdr), 370 supported_features: pse.supported_features, 371 supported_repositories: pse.supported_repositories, 372 }, 373 }, 374 BtSdpRecord::PbapPce(pce) => bindings::bluetooth_sdp_record { 375 pce: bindings::_bluetooth_sdp_pce_record { 376 hdr: BtSdpRecord::convert_header(&mut pce.hdr), 377 }, 378 }, 379 BtSdpRecord::OppServer(ops) => bindings::bluetooth_sdp_record { 380 ops: bindings::_bluetooth_sdp_ops_record { 381 hdr: BtSdpRecord::convert_header(&mut ops.hdr), 382 supported_formats_list_len: ops.supported_formats_list_len, 383 supported_formats_list: ops.supported_formats_list, 384 }, 385 }, 386 BtSdpRecord::SapServer(sap) => bindings::bluetooth_sdp_record { 387 sap: bindings::_bluetooth_sdp_sap_record { 388 hdr: BtSdpRecord::convert_header(&mut sap.hdr), 389 }, 390 }, 391 BtSdpRecord::Dip(dip) => bindings::bluetooth_sdp_record { 392 dip: bindings::_bluetooth_sdp_dip_record { 393 hdr: BtSdpRecord::convert_header(&mut dip.hdr), 394 spec_id: dip.spec_id, 395 vendor: dip.vendor, 396 vendor_id_source: dip.vendor_id_source, 397 product: dip.product, 398 version: dip.version, 399 primary_record: dip.primary_record, 400 }, 401 }, 402 BtSdpRecord::Mps(mps) => bindings::bluetooth_sdp_record { 403 mps: bindings::_bluetooth_sdp_mps_record { 404 hdr: BtSdpRecord::convert_header(&mut mps.hdr), 405 supported_scenarios_mpsd: mps.supported_scenarios_mpsd, 406 supported_scenarios_mpmd: mps.supported_scenarios_mpmd, 407 supported_dependencies: mps.supported_dependencies, 408 }, 409 }, 410 } 411 } 412 } 413 414 #[derive(Debug)] 415 pub enum SdpCallbacks { 416 SdpSearch(BtStatus, RawAddress, Uuid, i32, Vec<BtSdpRecord>), 417 } 418 419 pub struct SdpCallbacksDispatcher { 420 pub dispatch: Box<dyn Fn(SdpCallbacks) + Send>, 421 } 422 423 impl Debug for SdpCallbacksDispatcher { fmt(&self, f: &mut Formatter<'_>) -> Result424 fn fmt(&self, f: &mut Formatter<'_>) -> Result { 425 write!(f, "SdpCallbacksDispatcher {{}}") 426 } 427 } 428 429 type SdpCb = Arc<Mutex<SdpCallbacksDispatcher>>; 430 431 cb_variant!(SdpCb, sdp_search_cb -> SdpCallbacks::SdpSearch, 432 bindings::bt_status_t -> BtStatus, 433 *const RawAddress, *const Uuid, i32, 434 *mut bindings::bluetooth_sdp_record, { 435 let _1 = unsafe { *_1 }; 436 let _2 = unsafe { *_2 }; 437 let _4 = ptr_to_vec(_4, _3 as usize); 438 }); 439 440 struct RawSdpWrapper { 441 pub raw: *const bindings::btsdp_interface_t, 442 } 443 444 unsafe impl Send for RawSdpWrapper {} 445 446 pub struct Sdp { 447 internal: RawSdpWrapper, 448 is_init: bool, 449 callbacks: Option<Box<bindings::btsdp_callbacks_t>>, 450 } 451 452 impl Sdp { 453 #[log_args] new(intf: &BluetoothInterface) -> Sdp454 pub fn new(intf: &BluetoothInterface) -> Sdp { 455 let r = intf.get_profile_interface(SupportedProfiles::Sdp); 456 Sdp { 457 internal: RawSdpWrapper { raw: r as *const bindings::btsdp_interface_t }, 458 is_init: false, 459 callbacks: None, 460 } 461 } 462 463 #[log_args] is_initialized(&self) -> bool464 pub fn is_initialized(&self) -> bool { 465 self.is_init 466 } 467 468 #[log_args] initialize(&mut self, callbacks: SdpCallbacksDispatcher) -> bool469 pub fn initialize(&mut self, callbacks: SdpCallbacksDispatcher) -> bool { 470 if get_dispatchers().lock().unwrap().set::<SdpCb>(Arc::new(Mutex::new(callbacks))) { 471 panic!("Tried to set dispatcher for SdpCallbacks but it already existed"); 472 } 473 474 let mut callbacks = Box::new(bindings::btsdp_callbacks_t { 475 size: 2 * 8, 476 sdp_search_cb: Some(sdp_search_cb), 477 }); 478 479 let cb_ptr = LTCheckedPtrMut::from(&mut callbacks); 480 481 let init = ccall!(self, init, cb_ptr.into()); 482 self.is_init = BtStatus::from(init) == BtStatus::Success; 483 self.callbacks = Some(callbacks); 484 485 return self.is_init; 486 } 487 488 #[log_args] sdp_search(&self, address: &mut RawAddress, uuid: &Uuid) -> BtStatus489 pub fn sdp_search(&self, address: &mut RawAddress, uuid: &Uuid) -> BtStatus { 490 let addr_ptr = LTCheckedPtrMut::from_ref(address); 491 BtStatus::from(ccall!(self, sdp_search, addr_ptr.into(), uuid)) 492 } 493 494 #[log_args] create_sdp_record(&self, record: &mut BtSdpRecord, handle: &mut i32) -> BtStatus495 pub fn create_sdp_record(&self, record: &mut BtSdpRecord, handle: &mut i32) -> BtStatus { 496 let mut converted = record.get_unsafe_record(); 497 let record_ptr = LTCheckedPtrMut::from_ref(&mut converted); 498 let handle_ptr = LTCheckedPtrMut::from_ref(handle); 499 BtStatus::from(ccall!(self, create_sdp_record, record_ptr.into(), handle_ptr.into())) 500 } 501 502 #[log_args] remove_sdp_record(&self, handle: i32) -> BtStatus503 pub fn remove_sdp_record(&self, handle: i32) -> BtStatus { 504 BtStatus::from(ccall!(self, remove_sdp_record, handle)) 505 } 506 } 507