1 //! Shim to provide more structured access to sysprops from Rust.
2
3 use std::ffi::CString;
4
5 use crate::bindings::root as bindings;
6 use crate::utils::LTCheckedPtr;
7
8 /// List of properties accessible to Rust. Add new ones here as they become
9 /// necessary.
10 pub enum PropertyI32 {
11 // bluetooth.core.le
12 LeInquiryScanInterval,
13 LeInquiryScanWindow,
14 LeAdvMonScanInterval,
15 LeAdvMonScanWindow,
16
17 // bluetooth.device_id
18 ProductId,
19 ProductVersion,
20 VendorId,
21 VendorIdSource,
22 }
23
24 impl Into<(CString, i32)> for PropertyI32 {
25 /// Convert the property into the property key name and a default value.
into(self) -> (CString, i32)26 fn into(self) -> (CString, i32) {
27 let (key, default_value) = match self {
28 // Inquiry scan interval = N * 0.625 ms; value of 36 = 22.5ms
29 PropertyI32::LeInquiryScanInterval => ("bluetooth.core.le.inquiry_scan_interval", 36),
30
31 //Inquiry scan window = N * 0.625 ms; value of 18 = 11.25ms
32 PropertyI32::LeInquiryScanWindow => ("bluetooth.core.le.inquiry_scan_window", 18),
33
34 // Adv Mon scan interval = N * 0.625 ms; value of 40 = 25ms
35 PropertyI32::LeAdvMonScanInterval => ("bluetooth.core.le.adv_mon_scan_interval", 40),
36
37 // Adv Mon scan window = N * 0.625 ms; value of 20 = 12.5ms
38 PropertyI32::LeAdvMonScanWindow => ("bluetooth.core.le.adv_mon_scan_window", 20),
39
40 PropertyI32::ProductId => ("bluetooth.device_id.product_id", 0),
41 PropertyI32::ProductVersion => ("bluetooth.device_id.product_version", 0),
42
43 // Vendor ID defaults to Google (0xE0)
44 PropertyI32::VendorId => ("bluetooth.device_id.vendor_id", 0xE0),
45
46 // Vendor ID source defaults to Bluetooth Sig (0x1)
47 PropertyI32::VendorIdSource => ("bluetooth.device_id.vendor_id_source", 0x1),
48 };
49
50 (CString::new(key).expect("CString::new failed on sysprop key"), default_value)
51 }
52 }
53
54 /// Get the i32 value for a system property.
get_i32(prop: PropertyI32) -> i3255 pub fn get_i32(prop: PropertyI32) -> i32 {
56 let (key, default_value): (CString, i32) = prop.into();
57 let key_cptr = LTCheckedPtr::from(&key);
58
59 // SAFETY: Calling C++ function with compatible types (null terminated string and i32) is safe.
60 unsafe { bindings::osi_property_get_int32(key_cptr.into(), default_value) }
61 }
62
63 /// List of properties accessible to Rust. Add new ones here as they become
64 /// necessary.
65 pub enum PropertyBool {
66 // bluetooth.core.le
67 LeAdvMonRtlQuirk,
68 LeAdvMonQcaQuirk,
69
70 // bluetooth.core.gap
71 LePrivacyEnabled,
72 LePrivacyOwnAddressTypeEnabled,
73
74 // bluetooth.le_audio
75 LeAudioEnableLeAudioOnly,
76 }
77
78 impl Into<(CString, bool)> for PropertyBool {
79 /// Convert the property into the property key name and a default value.
into(self) -> (CString, bool)80 fn into(self) -> (CString, bool) {
81 let (key, default_value) = match self {
82 PropertyBool::LeAdvMonRtlQuirk => ("bluetooth.core.le.adv_mon_rtl_quirk", false),
83 PropertyBool::LeAdvMonQcaQuirk => ("bluetooth.core.le.adv_mon_qca_quirk", false),
84 PropertyBool::LeAudioEnableLeAudioOnly => {
85 ("bluetooth.le_audio.enable_le_audio_only", false)
86 }
87 PropertyBool::LePrivacyEnabled => ("bluetooth.core.gap.le.privacy.enabled", false),
88 PropertyBool::LePrivacyOwnAddressTypeEnabled => {
89 ("bluetooth.core.gap.le.privacy.own_address_type.enabled", false)
90 }
91 };
92
93 (CString::new(key).expect("CString::new failed on sysprop key"), default_value)
94 }
95 }
96
97 /// Get the boolean value for a system property.
get_bool(prop: PropertyBool) -> bool98 pub fn get_bool(prop: PropertyBool) -> bool {
99 let (key, default_value): (CString, bool) = prop.into();
100 let key_cptr = LTCheckedPtr::from(&key);
101
102 // SAFETY: Calling C++ function with compatible types (null terminated string and bool) is safe.
103 unsafe { bindings::osi_property_get_bool(key_cptr.into(), default_value) }
104 }
105