btle/le/
scan.rs

1use crate::ConversionError;
2
3use crate::hci::adapter;
4use crate::le::advertisement::StaticAdvBuffer;
5use crate::le::report::ReportInfo;
6use core::convert::TryFrom;
7use futures_util::future::LocalBoxFuture;
8use futures_util::stream::LocalBoxStream;
9
10#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)]
11pub enum ScanningFilterPolicy {
12    All = 0x00,
13    Whitelisted = 0x01,
14    DirectedAll = 0x02,
15    DirectedWhitelisted = 0x03,
16}
17impl From<ScanningFilterPolicy> for u8 {
18    fn from(p: ScanningFilterPolicy) -> Self {
19        p as u8
20    }
21}
22impl TryFrom<u8> for ScanningFilterPolicy {
23    type Error = ConversionError;
24
25    fn try_from(value: u8) -> Result<Self, Self::Error> {
26        match value {
27            0 => Ok(ScanningFilterPolicy::All),
28            1 => Ok(ScanningFilterPolicy::Whitelisted),
29            2 => Ok(ScanningFilterPolicy::DirectedAll),
30            3 => Ok(ScanningFilterPolicy::DirectedWhitelisted),
31            _ => Err(ConversionError(())),
32        }
33    }
34}
35const INTERVAL_MIN: u16 = 0x0004;
36const INTERVAL_MAX: u16 = 0x4000;
37/// Range 0x0004 --> 0x4000
38/// Default 0x0010 (10 ms)
39/// Time = N *  0.625 ms
40/// Time Range 2.5 ms --> 10.24 s
41#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)]
42pub struct ScanInterval(u16);
43impl ScanInterval {
44    pub const MIN: ScanInterval = ScanInterval(INTERVAL_MIN);
45    pub const MAX: ScanInterval = ScanInterval(INTERVAL_MAX);
46    pub const BYTE_LEN: usize = 2;
47    pub const DEFAULT: ScanInterval = ScanInterval(0x0010);
48    pub fn new(interval: u16) -> ScanInterval {
49        assert!(
50            interval >= INTERVAL_MIN && interval <= INTERVAL_MAX,
51            "interval '{}' is out of range"
52        );
53        ScanInterval(interval)
54    }
55    pub fn as_microseconds(self) -> u32 {
56        u32::from(u16::from(self)) * 625
57    }
58}
59impl From<ScanInterval> for u16 {
60    fn from(i: ScanInterval) -> u16 {
61        i.0
62    }
63}
64impl Default for ScanInterval {
65    fn default() -> Self {
66        Self::DEFAULT
67    }
68}
69#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)]
70pub struct ScanWindow(u16);
71impl ScanWindow {
72    pub const MIN: ScanWindow = ScanWindow(INTERVAL_MIN);
73    pub const MAX: ScanWindow = ScanWindow(INTERVAL_MAX);
74    pub const BYTE_LEN: usize = 2;
75    pub const DEFAULT: ScanWindow = ScanWindow(0x0010);
76    pub fn new(window: u16) -> ScanWindow {
77        assert!(
78            window >= INTERVAL_MIN && window <= INTERVAL_MAX,
79            "window '{}' is out of range"
80        );
81        ScanWindow(window)
82    }
83    pub fn as_microseconds(self) -> u32 {
84        u32::from(u16::from(self)) * 625
85    }
86}
87impl From<ScanWindow> for u16 {
88    fn from(w: ScanWindow) -> u16 {
89        w.0
90    }
91}
92impl Default for ScanWindow {
93    fn default() -> Self {
94        Self::DEFAULT
95    }
96}
97
98#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)]
99pub enum OwnAddressType {
100    Public = 0x00,
101    Random = 0x01,
102    PrivateOrPublic = 0x02,
103    PrivateOrRandom = 0x03,
104}
105
106impl From<OwnAddressType> for u8 {
107    fn from(s: OwnAddressType) -> Self {
108        s as u8
109    }
110}
111impl TryFrom<u8> for OwnAddressType {
112    type Error = ConversionError;
113
114    fn try_from(value: u8) -> Result<Self, Self::Error> {
115        match value {
116            0 => Ok(OwnAddressType::Public),
117            1 => Ok(OwnAddressType::Random),
118            2 => Ok(OwnAddressType::PrivateOrPublic),
119            3 => Ok(OwnAddressType::PrivateOrRandom),
120            _ => Err(ConversionError(())),
121        }
122    }
123}
124/// Advertising scan type (Active or Passive).
125#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)]
126pub enum ScanType {
127    Passive = 0x00,
128    Active = 0x01,
129}
130impl From<ScanType> for u8 {
131    fn from(s: ScanType) -> Self {
132        s as u8
133    }
134}
135impl TryFrom<u8> for ScanType {
136    type Error = ConversionError;
137
138    fn try_from(value: u8) -> Result<Self, Self::Error> {
139        match value {
140            0 => Ok(ScanType::Passive),
141            1 => Ok(ScanType::Active),
142            _ => Err(ConversionError(())),
143        }
144    }
145}
146#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)]
147pub struct ScanParameters {
148    pub scan_type: ScanType,
149    pub scan_interval: ScanInterval,
150    pub scan_window: ScanWindow,
151    pub own_address_type: OwnAddressType,
152    pub scanning_filter_policy: ScanningFilterPolicy,
153}
154impl ScanParameters {
155    pub const DEFAULT: ScanParameters = ScanParameters {
156        scan_type: ScanType::Passive,
157        scan_interval: ScanInterval::DEFAULT,
158        scan_window: ScanWindow::DEFAULT,
159        own_address_type: OwnAddressType::Public,
160        scanning_filter_policy: ScanningFilterPolicy::All,
161    };
162}
163impl Default for ScanParameters {
164    fn default() -> Self {
165        Self::DEFAULT
166    }
167}
168#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)]
169pub enum ObserverError {
170    AdapterError(adapter::Error),
171}
172impl crate::error::Error for ObserverError {}
173pub trait Observer {
174    fn set_scan_parameters<'a>(
175        &'a mut self,
176        scan_parameters: ScanParameters,
177    ) -> LocalBoxFuture<'a, Result<(), adapter::Error>>;
178    fn set_scan_enable<'a>(
179        &'a mut self,
180        is_enabled: bool,
181        filter_duplicates: bool,
182    ) -> LocalBoxFuture<'a, Result<(), adapter::Error>>;
183    fn advertisement_stream<'a>(
184        &'a mut self,
185    ) -> LocalBoxFuture<
186        'a,
187        Result<
188            LocalBoxStream<'a, Result<ReportInfo<StaticAdvBuffer>, adapter::Error>>,
189            adapter::Error,
190        >,
191    >;
192    /// Optimize `advertisement_stream` by avoiding setting HCI event masks. Defaults to calling
193    /// `advertisement_stream()`.
194    /// # Caution
195    /// This function does not guarantee that the event masks won't be changed! By default, this
196    /// function doesn't do anything different than `advertisement_stream()`.
197    fn advertisement_stream_without_mask<'a>(
198        &'a mut self,
199    ) -> LocalBoxFuture<
200        'a,
201        Result<
202            LocalBoxStream<'a, Result<ReportInfo<StaticAdvBuffer>, adapter::Error>>,
203            adapter::Error,
204        >,
205    > {
206        self.advertisement_stream()
207    }
208}