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