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