1 use std::collections::HashMap; 2 use std::sync::{Arc, Mutex}; 3 4 use crate::ClientContext; 5 use crate::{console_yellow, print_info}; 6 7 use bt_topshim::btif::Uuid; 8 use bt_topshim::profiles::gatt::{LeDiscMode, LePhy}; 9 use btstack::bluetooth_adv::{AdvertiseData, AdvertiserId, AdvertisingSetParameters}; 10 use btstack::bluetooth_gatt::IBluetoothGatt; 11 12 /// Avertisement parameter and data for a BLE advertising set. 13 #[derive(Debug, Clone)] 14 pub(crate) struct AdvSet { 15 /// ID for the advertising set if it's being started successfully, None otherwise. 16 pub(crate) adv_id: Option<AdvertiserId>, 17 18 /// Advertising parameters. 19 pub(crate) params: AdvertisingSetParameters, 20 21 /// Advertising data. 22 pub(crate) data: AdvertiseData, 23 24 /// Scan response data. 25 pub(crate) scan_rsp: AdvertiseData, 26 } 27 28 impl AdvSet { new(is_legacy: bool) -> Self29 pub(crate) fn new(is_legacy: bool) -> Self { 30 let params = AdvertisingSetParameters { 31 discoverable: LeDiscMode::GeneralDiscoverable, 32 connectable: false, 33 scannable: false, 34 is_legacy, 35 is_anonymous: false, 36 include_tx_power: true, 37 primary_phy: LePhy::Phy1m, 38 secondary_phy: LePhy::Phy1m, 39 interval: 100, 40 tx_power_level: 0x7f, // no preference 41 own_address_type: 1, // random 42 }; 43 44 let data = AdvertiseData { 45 service_uuids: Vec::new(), 46 solicit_uuids: Vec::new(), 47 transport_discovery_data: Vec::new(), 48 manufacturer_data: HashMap::from([(0, vec![0, 1, 2])]), 49 service_data: HashMap::new(), 50 include_tx_power_level: true, 51 include_device_name: true, 52 }; 53 54 let scan_rsp = AdvertiseData { 55 service_uuids: vec![Uuid::from([ 56 0x00, 0x00, 0xfe, 0xf3, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 57 0x34, 0xfb, 58 ])], 59 solicit_uuids: Vec::new(), 60 transport_discovery_data: Vec::new(), 61 manufacturer_data: HashMap::new(), 62 service_data: HashMap::from([( 63 "0000fef3-0000-1000-8000-00805f9b34fb".to_string(), 64 vec![0x0a, 0x0b], 65 )]), 66 include_tx_power_level: false, 67 include_device_name: false, 68 }; 69 70 AdvSet { adv_id: None, params, data, scan_rsp } 71 } 72 start(context: Arc<Mutex<ClientContext>>, s: AdvSet, callback_id: u32)73 pub(crate) fn start(context: Arc<Mutex<ClientContext>>, s: AdvSet, callback_id: u32) { 74 let mut context = context.lock().unwrap(); 75 76 let reg_id = context.gatt_dbus.as_mut().unwrap().start_advertising_set( 77 s.params.clone(), 78 s.data.clone(), 79 None, 80 None, 81 None, 82 0, 83 0, 84 callback_id, 85 ); 86 print_info!("Starting advertising set for reg_id = {}", reg_id); 87 context.adv_sets.insert(reg_id, s); 88 } 89 stop_all(context: Arc<Mutex<ClientContext>>)90 pub(crate) fn stop_all(context: Arc<Mutex<ClientContext>>) { 91 let mut context = context.lock().unwrap(); 92 93 let adv_ids: Vec<_> = context.adv_sets.iter().filter_map(|(_, s)| s.adv_id).collect(); 94 for adv_id in adv_ids { 95 print_info!("Stopping advertising set {}", adv_id); 96 context.gatt_dbus.as_mut().unwrap().stop_advertising_set(adv_id); 97 } 98 context.adv_sets.clear(); 99 } 100 } 101