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.le_audio
71 LeAudioEnableLeAudioOnly,
72 }
73
74 impl Into<(CString, bool)> for PropertyBool {
75 /// Convert the property into the property key name and a default value.
into(self) -> (CString, bool)76 fn into(self) -> (CString, bool) {
77 let (key, default_value) = match self {
78 PropertyBool::LeAdvMonRtlQuirk => ("bluetooth.core.le.adv_mon_rtl_quirk", false),
79 PropertyBool::LeAdvMonQcaQuirk => ("bluetooth.core.le.adv_mon_qca_quirk", false),
80 PropertyBool::LeAudioEnableLeAudioOnly => {
81 ("bluetooth.le_audio.enable_le_audio_only", false)
82 }
83 };
84
85 (CString::new(key).expect("CString::new failed on sysprop key"), default_value)
86 }
87 }
88
89 /// Get the boolean value for a system property.
get_bool(prop: PropertyBool) -> bool90 pub fn get_bool(prop: PropertyBool) -> bool {
91 let (key, default_value): (CString, bool) = prop.into();
92 let key_cptr = LTCheckedPtr::from(&key);
93
94 // SAFETY: Calling C++ function with compatible types (null terminated string and bool) is safe.
95 unsafe { bindings::osi_property_get_bool(key_cptr.into(), default_value) }
96 }
97