Skip to main content

bt_hci/event/
le.rs

1//! LE Meta events [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-9bfbd351-a103-f197-b85f-ffd9dcc92872)
2
3use crate::param::{
4    AddrKind, AdvHandle, BdAddr, BigHandle, BisConnHandle, ClockAccuracy, ConnHandle, CteKind, DataStatus, Duration,
5    ExtDuration, FrameSpaceInitiator, LeAdvReports, LeConnRole, LeDirectedAdvertisingReportParam, LeExtAdvReports,
6    LeFeatureMask, LeIQSample, LeTxPowerReportingReason, PacketStatus, PhyKind, PhyMask, PowerLevelKind, SpacingTypes,
7    Status, SyncHandle, ZoneEntered,
8};
9use crate::{FromHciBytes, FromHciBytesError};
10
11/// A trait for objects which contain the parameters for a specific HCI LE event
12pub trait LeEventParams<'a>: FromHciBytes<'a> {
13    /// The LE meta event subevent code these parameters are for
14    const SUBEVENT_CODE: u8;
15}
16
17macro_rules! le_events {
18    (
19        $(
20            $(#[$attrs:meta])*
21            struct $name:ident$(<$life:lifetime>)?($code:expr) {
22                $($field:ident: $ty:ty),*
23                $(,)?
24            }
25        )+
26    ) => {
27        /// LE Meta event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-9bfbd351-a103-f197-b85f-ffd9dcc92872)
28        #[non_exhaustive]
29        #[derive(Debug, Clone, Hash)]
30        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
31        pub enum LeEvent<'a> {
32            $(
33                #[doc = stringify!($name)]
34                $name($name$(<$life>)?),
35            )+
36        }
37
38        /// LE Meta event type [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-9bfbd351-a103-f197-b85f-ffd9dcc92872)
39        #[non_exhaustive]
40        #[derive(Debug, Clone, Copy, Hash, PartialEq)]
41        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
42        pub struct LeEventKind(pub u8);
43
44        #[allow(non_upper_case_globals)]
45        impl LeEventKind {
46            $(
47                #[doc = stringify!($name)]
48                pub const $name: LeEventKind = LeEventKind($code);
49            )+
50        }
51
52        impl<'a> $crate::FromHciBytes<'a> for LeEventKind {
53            fn from_hci_bytes(data: &'a [u8]) -> Result<(Self, &'a [u8]), FromHciBytesError> {
54                let (subcode, data) = data.split_first().ok_or(FromHciBytesError::InvalidSize)?;
55                match subcode {
56                    $($code => Ok((Self::$name, data)),)+
57                    _ => Err(FromHciBytesError::InvalidValue),
58                }
59            }
60        }
61
62        /// An Le Event HCI packet
63        #[derive(Debug, Clone, Hash)]
64        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
65        pub struct LeEventPacket<'a> {
66            /// Which kind of le event.
67            pub kind: LeEventKind,
68            /// Le event data.
69            pub data: &'a [u8],
70        }
71
72        impl<'a> LeEventPacket<'a> {
73            fn from_kind_hci_bytes(kind: LeEventKind, data: &'a [u8]) -> Result<Self, FromHciBytesError> {
74                Ok(Self {
75                    kind,
76                    data,
77                })
78            }
79        }
80
81        impl<'a> TryFrom<LeEventPacket<'a>> for LeEvent<'a> {
82            type Error = FromHciBytesError;
83            fn try_from(packet: LeEventPacket<'a>) -> Result<Self, Self::Error> {
84                match packet.kind {
85                    $(LeEventKind::$name => Ok(Self::$name($name::from_hci_bytes_complete(packet.data)?)),)+
86                    _ => Err(FromHciBytesError::InvalidValue),
87                }
88            }
89        }
90
91        impl<'a> $crate::FromHciBytes<'a> for LeEvent<'a> {
92            fn from_hci_bytes(data: &'a [u8]) -> Result<(Self, &'a [u8]), FromHciBytesError> {
93                let (subcode, data) = data.split_first().ok_or(FromHciBytesError::InvalidSize)?;
94                match subcode {
95                    $($code => $name::from_hci_bytes(data).map(|(x, y)| (Self::$name(x), y)),)+
96                    _ => Err(FromHciBytesError::InvalidValue),
97                }
98            }
99        }
100
101        $(
102            $(#[$attrs])*
103            #[derive(Debug, Clone, Hash)]
104            #[cfg_attr(feature = "defmt", derive(defmt::Format))]
105            pub struct $name$(<$life>)? {
106                $(
107                    #[doc = stringify!($field)]
108                    pub $field: $ty,
109                )*
110            }
111
112            #[automatically_derived]
113            impl<'a> $crate::FromHciBytes<'a> for $name$(<$life>)? {
114                #[allow(unused_variables)]
115                fn from_hci_bytes(data: &'a [u8]) -> Result<(Self, &'a [u8]), $crate::FromHciBytesError> {
116                    let total = 0;
117                    $(
118                        let ($field, data) = <$ty as $crate::FromHciBytes>::from_hci_bytes(data)?;
119                    )*
120                    Ok((Self {
121                        $($field,)*
122                    }, data))
123                }
124            }
125
126            #[automatically_derived]
127            impl<'a> LeEventParams<'a> for $name$(<$life>)? {
128                const SUBEVENT_CODE: u8 = $code;
129            }
130        )+
131    };
132}
133
134impl<'de> FromHciBytes<'de> for LeEventPacket<'de> {
135    fn from_hci_bytes(data: &'de [u8]) -> Result<(Self, &'de [u8]), FromHciBytesError> {
136        let (kind, data) = LeEventKind::from_hci_bytes(data)?;
137        let pkt = Self::from_kind_hci_bytes(kind, data)?;
138        Ok((pkt, &[]))
139    }
140}
141
142le_events! {
143    /// LE Connection Complete event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-eee7884c-c6d1-159a-9fc2-aebf6bcf30e7)
144    struct LeConnectionComplete(1) {
145        status: Status,
146        handle: ConnHandle,
147        role: LeConnRole,
148        peer_addr_kind: AddrKind,
149        peer_addr: BdAddr,
150        conn_interval: Duration<1_250>,
151        peripheral_latency: u16,
152        supervision_timeout: Duration<10_000>,
153        central_clock_accuracy: ClockAccuracy,
154    }
155
156    /// LE Advertising Report event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-bf6970a8-7187-7d2c-0408-b83aa09837e3)
157    struct LeAdvertisingReport<'a>(2) {
158        reports: LeAdvReports<'a>,
159    }
160
161    /// LE Connection Update Complete event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-5a3debb8-e7b3-44a4-9c42-317bc40ee1d2)
162    struct LeConnectionUpdateComplete(3) {
163        status: Status,
164        handle: ConnHandle,
165        conn_interval: Duration<1_250>,
166        peripheral_latency: u16,
167        supervision_timeout: Duration<10_000>,
168    }
169
170    /// LE Read Remote Features Complete event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-a33d9f3f-718b-016c-a89c-8a77c5589ba9)
171    struct LeReadRemoteFeaturesComplete(4) {
172        status: Status,
173        handle: ConnHandle,
174        le_features: LeFeatureMask,
175    }
176
177    /// LE Long Term Key Request event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-2bb7b9d8-d02b-0320-3dc8-9699e4b30332)
178    struct LeLongTermKeyRequest(5) {
179        handle: ConnHandle,
180        random_number: [u8; 8],
181        encrypted_diversifier: u16,
182    }
183
184    /// LE Remote Connection Parameter Request event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-98e6a66c-1561-7bd0-d4c6-79bff2ba7652)
185    struct LeRemoteConnectionParameterRequest(6) {
186        handle: ConnHandle,
187        interval_min: Duration<1_250>,
188        interval_max: Duration<1_250>,
189        max_latency: u16,
190        timeout: Duration<10_000>,
191    }
192
193    /// LE Data Length Change event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-631c5539-4155-072a-af53-a226e0bfb96a)
194    struct LeDataLengthChange(7) {
195        handle: ConnHandle,
196        max_tx_octets: u16,
197        max_tx_time: u16,
198        max_rx_octets: u16,
199        max_rx_time: u16,
200    }
201
202    /// LE Read Local P-256 Public Key Complete event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-b2210bd7-74d1-949a-091c-008440a8625f)
203    struct LeReadLocalP256PublicKeyComplete(8) {
204        status: Status,
205        key_x_coordinate: [u8; 32],
206        key_y_coordinate: [u8; 32],
207    }
208
209    /// LE Generate DHKey Complete event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-a5b34696-b6fa-ec1a-31ae-8a09db157322)
210    struct LeGenerateDhkeyComplete(9) {
211        status: Status,
212        dh_key: [u8; 32],
213    }
214
215    /// LE Enhanced Connection Complete event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-ed5dc708-ff96-949f-586a-4d418466b226)
216    struct LeEnhancedConnectionComplete(10) {
217        status: Status,
218        handle: ConnHandle,
219        role: LeConnRole,
220        peer_addr_kind: AddrKind,
221        peer_addr: BdAddr,
222        local_resolvable_private_addr: BdAddr,
223        peer_resolvable_private_addr: BdAddr,
224        conn_interval: Duration<1_250>,
225        peripheral_latency: u16,
226        supervision_timeout: Duration<10_000>,
227        central_clock_accuracy: ClockAccuracy,
228    }
229
230    /// LE Directed Advertising Report event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-3e0a8a2e-a30f-df11-7490-132e35ee5daa)
231    struct LeDirectedAdvertisingReport<'a>(11) {
232        reports: &'a [LeDirectedAdvertisingReportParam],
233    }
234
235    /// LE PHY Update Complete event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-1f6a363e-bd01-bbf7-be6f-fb86ffa645ec)
236    struct LePhyUpdateComplete(12) {
237        status: Status,
238        handle: ConnHandle,
239        tx_phy: PhyKind,
240        rx_phy: PhyKind,
241    }
242
243    /// LE Extended Advertising Report event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-37c674d6-c93f-c46c-420a-b2569dff4fa0)
244    struct LeExtendedAdvertisingReport<'a>(13) {
245        reports: LeExtAdvReports<'a>
246    }
247
248    /// LE Periodic Advertising Sync Established event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-1f76b4e2-f279-1976-1e33-5ba86d0955c2)
249    struct LePeriodicAdvertisingSyncEstablished(14) {
250        status: Status,
251        sync_handle: SyncHandle,
252        adv_sid: u8,
253        adv_addr_kind: AddrKind,
254        adv_addr: BdAddr,
255        adv_phy: PhyKind,
256        periodic_adv_interval: Duration<1_250>,
257        adv_clock_accuracy: ClockAccuracy,
258    }
259
260    /// LE Periodic Advertising Report event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-e216c26f-0383-c651-4b8d-1409b91c7e34)
261    struct LePeriodicAdvertisingReport<'a>(15) {
262        sync_handle: SyncHandle,
263        tx_power: i8,
264        rssi: i8,
265        cte_kind: CteKind,
266        data_status: DataStatus,
267        data: &'a [u8],
268    }
269
270    /// LE Periodic Advertising Sync Lost event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-a1a90403-d1b7-d117-0f30-620c8d3912ef)
271    struct LePeriodicAdvertisingSyncLost(16) {
272        sync_handle: SyncHandle,
273    }
274
275    /// LE Scan Timeout event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-fd746670-5772-b038-ad51-135d8371fb00)
276    struct LeScanTimeout(17) {}
277
278    /// LE Advertising Set Terminated event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-b7eedd85-4369-f88f-7872-7278f7778cd2)
279    struct LeAdvertisingSetTerminated(18) {
280        status: Status,
281        adv_handle: AdvHandle,
282        handle: ConnHandle,
283        num_completed_ext_adv_evts: u8,
284    }
285
286    /// LE Scan Request Received event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-10c1448e-03ab-9ce7-8d90-7ad870c8da20)
287    struct LeScanRequestReceived(19) {
288        adv_handle: AdvHandle,
289        scanner_addr_kind: AddrKind,
290        scanner_addr: BdAddr,
291    }
292
293    /// LE Channel Selection Algorithm event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-8ccdba3a-0523-031c-bb51-7d4f2c2e1191)
294    struct LeChannelSelectionAlgorithm(20) {
295        handle: ConnHandle,
296        channel_selection_algorithm: u8,
297    }
298
299    /// LE Connectionless IQ Report event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-fafa104b-6cb3-ef73-38bd-37539d44e865)
300    struct LeConnectionlessIqReport<'a>(21) {
301        sync_handle: SyncHandle,
302        channel_index: u8,
303        rssi: i16,
304        rssi_antenna_id: u8,
305        cte_kind: CteKind,
306        slot_durations: u8,
307        packet_status: PacketStatus,
308        periodic_event_counter: u16,
309        iq_samples: &'a [LeIQSample],
310    }
311
312    /// LE Connection IQ Report event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-b38e7527-8dc5-ea71-c7ce-892e2362e338)
313    struct LeConnectionIqReport<'a>(22) {
314        handle: ConnHandle,
315        rx_phy: PhyKind,
316        data_channel_index: u8,
317        rssi: i16,
318        rssi_antenna_id: u8,
319        cte_kind: CteKind,
320        slot_durations: u8,
321        packet_status: PacketStatus,
322        connection_event_counter: u16,
323        iq_samples: &'a [LeIQSample],
324    }
325
326    /// LE CTE Request Failed event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-f546f56f-fff2-6ba2-1b86-77dbcf8fc012)
327    struct LeCteRequestFailed(23) {
328        status: Status,
329        handle: ConnHandle,
330    }
331
332    /// LE Periodic Advertising Sync Transfer Received event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-6feaf258-f0a9-7db2-d837-5bd8c07ef396)
333    struct LePeriodicAdvertisingSyncTransferReceived(24) {
334        status: Status,
335        handle: ConnHandle,
336        service_data: u16,
337        sync_handle: SyncHandle,
338        adv_sid: u8,
339        adv_addr_kind: AddrKind,
340        adv_addr: BdAddr,
341        adv_phy: PhyKind,
342        periodic_adv_interval: Duration<1_250>,
343        adv_clock_accuracy: ClockAccuracy,
344    }
345
346    /// LE CIS Established event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-3c346948-9111-a11b-fc1d-6249936d559a)
347    struct LeCisEstablished(25) {
348        status: Status,
349        handle: ConnHandle,
350        cig_sync_delay: ExtDuration,
351        cis_sync_delay: ExtDuration,
352        transport_latency_c_to_p: ExtDuration,
353        transport_latency_p_to_c: ExtDuration,
354        phy_c_to_p: PhyKind,
355        phy_p_to_c: PhyKind,
356        nse: u8,
357        bn_c_to_p: u8,
358        bn_p_to_c: u8,
359        ft_c_to_p: u8,
360        ft_p_to_c: u8,
361        max_pdu_c_to_p: u16,
362        max_pdu_p_to_c: u16,
363        iso_interval: Duration<1_250>,
364    }
365
366    /// LE CIS Request event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-0e5babb6-41aa-4d16-41cb-062d2d7e51dd)
367    struct LeCisRequest(26) {
368        acl_handle: ConnHandle,
369        cis_handle: ConnHandle,
370        cig_id: u8,
371        cis_id: u8,
372    }
373
374    /// LE Create BIG Complete event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-8ca85f3c-5223-d2b4-2b8d-58bb15d58c67)
375    struct LeCreateBigComplete<'a>(27) {
376        status: Status,
377        big_handle: BigHandle,
378        big_sync_delay: ExtDuration,
379        transport_latency_big: ExtDuration,
380        phy: PhyKind,
381        nse: u8,
382        bn: u8,
383        pto: u8,
384        irc: u8,
385        max_pdu: u16,
386        iso_interval: Duration<1_250>,
387        bis_handles: &'a [BisConnHandle],
388    }
389
390    /// LE Terminate BIG Complete event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-4f2ef51e-85af-5f2a-fda4-822eb32bc6dd)
391    struct LeTerminateBigComplete(28) {
392        big_handle: BigHandle,
393        reason: Status,
394    }
395
396    /// LE BIG Sync Established event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-5d591ea2-a469-5df9-bfd1-e7bf9f0d0e59)
397    struct LeBigSyncEstablished<'a>(29) {
398        status: Status,
399        big_handle: BigHandle,
400        transport_latency_big: ExtDuration,
401        nse: u8,
402        bn: u8,
403        pto: u8,
404        irc: u8,
405        max_pdu: u16,
406        iso_interval: Duration<1_250>,
407        bis_handles: &'a [BisConnHandle],
408    }
409
410    /// LE BIG Sync Lost event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-1d70bc8d-a600-7f3e-a35e-4d198005b683)
411    struct LeBigSyncLost(30) {
412        big_handle: BigHandle,
413        reason: Status,
414    }
415
416    /// LE Request Peer SCA Complete event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-c03d0f69-243c-20d1-c62d-eacbec5c6769)
417    struct LeRequestPeerScaComplete(31) {
418        status: Status,
419        handle: ConnHandle,
420        peer_clock_accuracy: ClockAccuracy,
421    }
422
423    /// LE Path Loss Threshold event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-ddc59a86-983e-07ab-8e1e-7a18a033f2da)
424    struct LePathLossThreshold(32) {
425        handle: ConnHandle,
426        current_path_loss: u8,
427        zone_entered: ZoneEntered,
428    }
429
430    /// LE Transmit Power Reporting event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-56658b09-da26-d33e-e960-35a474cda8b4)
431    struct LeTransmitPowerReporting(33) {
432        status: Status,
433        handle: ConnHandle,
434        reason: LeTxPowerReportingReason,
435        phy: PhyKind,
436        tx_power_level: i8,
437        tx_power_level_flag: PowerLevelKind,
438        delta: i8,
439    }
440
441    /// LE BIGInfo Advertising Report event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-9b86e844-492e-a003-21cb-ff92c6aedf06)
442    struct LeBiginfoAdvertisingReport(34) {
443        sync_handle: SyncHandle,
444        num_bis: u8,
445        nse: u8,
446        iso_interval: u16,
447        bn: u8,
448        pto: u8,
449        irc: u8,
450        max_pdu: u16,
451        sdu_interval: ExtDuration,
452        max_sdu: u16,
453        phy: PhyKind,
454        is_framed: bool,
455        is_encrypted: bool,
456    }
457
458    /// LE Subrate Change event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-dd0459e3-1dd8-6cf1-c591-307412647335)
459    struct LeSubrateChange(35) {
460        status: Status,
461        handle: ConnHandle,
462        subrate_factor: u16,
463        peripheral_latency: u16,
464        continuation_number: u16,
465        supervision_timeout: Duration<10_000>,
466    }
467
468    /// LE Frame Space Update Complete event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-60/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-5ccb539a-6dd4-cd68-a9e1-1600f3868f29)
469    struct LeFrameSpaceUpdateComplete(53) {
470        status: Status,
471        handle: ConnHandle,
472        initiator: FrameSpaceInitiator,
473        frame_space: Duration<1>,
474        phys: PhyMask,
475        spacing_types: SpacingTypes,
476    }
477
478
479    /// LE Connection Rate Change event [📖](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-62/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-2c599471-bc69-6495-ccfa-56be30d10311)
480    struct LeConnectionRateChange(55) {
481        status: Status,
482        handle: ConnHandle,
483        conn_interval: Duration<125>,
484        subrate_factor: u16,
485        peripheral_latency: u16,
486        continuation_number: u16,
487        supervision_timeout: Duration<10_000>,
488    }
489}