stm32wb_hci/types/
extended_advertisement.rs

1use core::time::Duration;
2
3use byteorder::{ByteOrder, LittleEndian};
4
5use crate::AdvertisingHandle;
6
7#[cfg(not(feature = "defmt"))]
8bitflags::bitflags! {
9    /// Extended advertising modes
10    pub struct AdvertisingMode: u8 {
11        /// Use specific random address
12        const SPECIFIC = 0x01;
13    }
14}
15
16#[cfg(feature = "defmt")]
17defmt::bitflags! {
18    /// Extended advertising modes
19    pub struct AdvertisingMode: u8 {
20        /// Use specific random address
21        const SPECIFIC = 0x01;
22    }
23}
24
25#[cfg(not(feature = "defmt"))]
26bitflags::bitflags! {
27    /// Advertising event types
28    pub struct AdvertisingEvent: u16 {
29        /// Connectable advertising
30        const CONNECTABLE = 0x0001;
31        /// Scannable advertising
32        const SCANNABLE = 0x0002;
33        /// Directed advertising
34        const DIRECTED = 0x0004;
35        /// High duty cycle directed connectable advertising
36        const HIGH_DUTY_DIRECTED = 0x0008;
37        /// Use legacy advertising PDUs
38        const LEGACY = 0x0010;
39        /// Anonymous advertising
40        const ANONYMOUS = 0x0020;
41        /// Include Tx power in at least one advertising PDU
42        const INCLUDE_TX_POWER = 0x0040;
43    }
44}
45
46#[cfg(feature = "defmt")]
47defmt::bitflags! {
48    /// Advertising event types
49    pub struct AdvertisingEvent: u16 {
50        /// Connectable advertising
51        const CONNECTABLE = 0x0001;
52        /// Scannable advertising
53        const SCANNABLE = 0x0002;
54        /// Directed advertising
55        const DIRECTED = 0x0004;
56        /// High duty cycle directed connectable advertising
57        const HIGH_DUTY_DIRECTED = 0x0008;
58        /// Use legacy advertising PDUs
59        const LEGACY = 0x0010;
60        /// Anonymous advertising
61        const ANONYMOUS = 0x0020;
62        /// Include Tx power in at least one advertising PDU
63        const INCLUDE_TX_POWER = 0x0040;
64    }
65}
66
67/// Define an extended advertising interval range.
68///
69/// The advertising interval min shall be less than or equal to the advertising interval
70/// max. The advertising interval min and advertising interval max should not be the same
71/// values to enable the Controller to determine the best advertising interval given other
72/// adctivities, through this implementation allows them to be equal.
73pub struct ExtendedAdvertisingInterval {
74    /// The first field is the min, the second is the max
75    interval: (Duration, Duration),
76}
77
78impl ExtendedAdvertisingInterval {
79    /// Creates an advertising interval with the provided minimum and maximum values.
80    ///
81    /// # Errors
82    ///
83    /// - [TooShort](ExtendedAdvertisingIntervalError::TooShort) if the minimum value is too small. For
84    ///   Bluetooth specifications v4.x, if the advertising type is
85    ///   [ScannableUndirected](AdvertisingType::ScannableUndirected), then the minimum value is 100
86    ///   ms. In all other cases, the minimum value is 20 ms.
87    /// - [TooLong](ExtendedAdvertisingIntervalError::TooLong) if the maximum value is too large. The
88    ///   maximum value is 10.24 seconds.
89    /// - [Inverted](ExtendedAdvertisingIntervalError::Inverted) if the minimum is greater than the
90    ///   maximum.
91    pub fn with_range(
92        min: Duration,
93        max: Duration,
94    ) -> Result<Self, ExtendedAdvertisingIntervalError> {
95        const MIN: Duration = Duration::from_millis(20);
96        const MAX: Duration = Duration::from_micros(10485759375);
97
98        if min < MIN {
99            return Err(ExtendedAdvertisingIntervalError::TooShort(min));
100        }
101        if max > MAX {
102            return Err(ExtendedAdvertisingIntervalError::TooLong(max));
103        }
104        if min > max {
105            return Err(ExtendedAdvertisingIntervalError::Inverted(min, max));
106        }
107
108        Ok(Self {
109            interval: (min, max),
110        })
111    }
112
113    fn duration_as_u32(d: Duration) -> u32 {
114        // T = 0.625 ms * N
115        // so N = T / 0.625 ms
116        //      = T / 625 us
117        //
118        // Note: 1600 = 1_000_000 / 625
119        1600 * d.as_secs() as u32 + (d.subsec_micros() / 625)
120    }
121
122    /// Serialize the interval into the given buffer.
123    ///
124    /// Serializes the minimum range of the interval (4 bytes), the maximum range of the
125    /// interval (4 bytees)
126    ///
127    /// # Panics
128    ///
129    /// - If the provided buffer is not at least 8 bytes long.
130    pub fn copy_into_slice(&self, bytes: &mut [u8]) {
131        LittleEndian::write_u32(&mut bytes[0..], Self::duration_as_u32(self.interval.0));
132        LittleEndian::write_u32(&mut bytes[4..], Self::duration_as_u32(self.interval.1));
133    }
134}
135
136/// Potential errors that can occur when specifying an [`ExtendedAdvertisingInterval`].
137#[derive(Copy, Clone, Debug, PartialEq)]
138#[cfg_attr(feature = "defmt", derive(defmt::Format))]
139pub enum ExtendedAdvertisingIntervalError {
140    /// The minimum value was too short. Includes the invalid value.
141    TooShort(Duration),
142    /// The maximum value was too long. Includes the invalid value.
143    TooLong(Duration),
144    /// The minimum value was greater than the maximum value. Includes the provided minimum and
145    /// value, respectively.
146    Inverted(Duration, Duration),
147}
148
149/// Advertising PHY
150#[derive(Clone, Copy, Debug)]
151#[cfg_attr(feature = "defmt", derive(defmt::Format))]
152pub enum AdvertisingPhy {
153    /// Advertisement PHY is LE 1M
154    Le1M = 0x01,
155    /// Advertisement PHY is LE 2M
156    Le2M = 0x02,
157}
158
159/// Advertising set
160pub struct AdvSet {
161    /// Used to identify an advertising set
162    pub handle: AdvertisingHandle,
163    /// Duration of advertising set.
164    ///
165    /// Values:
166    /// - 0x0000 (0 ms) : No advertising duration.
167    /// - 0x0001 (10 ms)  ... 0xFFFF (655350 ms) : Advertising duration
168    pub duration: u16,
169    /// Maximum number of advertising events.
170    ///
171    /// Values:
172    /// - 0x00: No maximum number of advertising events
173    /// - 0x01 .. 0xFF: Maximum number of extended advertising events the
174    /// Controller shall attempt to send prior to terminating the extended
175    /// advertising
176    pub max_extended_adv_events: u8,
177}
178
179impl AdvSet {
180    pub(crate) fn copy_into_slice(&self, bytes: &mut [u8]) {
181        bytes[0] = self.handle.0;
182        LittleEndian::write_u16(&mut bytes[1..], self.duration);
183        bytes[3] = self.max_extended_adv_events;
184    }
185}
186
187/// Advertising Operation
188#[derive(Clone, Copy, Debug)]
189#[cfg_attr(feature = "defmt", derive(defmt::Format))]
190pub enum AdvertisingOperation {
191    /// Intermediate fragment of fragmented extended advertising data
192    IntermediateFragment = 0x00,
193    /// First fragment of fragmented extended advertising data
194    FirstFragment = 0x01,
195    /// Last fragment of fragmented extended advertising data
196    LastFragment = 0x02,
197    /// Complete extended advertising data
198    CompleteData = 0x03,
199    /// Unchanged data (just update the advertising DID)
200    UnchangedData = 0x04,
201}