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