1use core::iter::FusedIterator;
2
3use super::{param, param_slice, BdAddr, ConnHandle, Duration, RemainingBytes};
4use crate::{ByteAlignedValue, FixedSizeValue, FromHciBytes, FromHciBytesError, WriteHci};
5
6param!(struct AddrKind(u8));
7
8#[allow(missing_docs)]
9impl AddrKind {
10 pub const PUBLIC: AddrKind = AddrKind(0);
11 pub const RANDOM: AddrKind = AddrKind(1);
12 pub const RESOLVABLE_PRIVATE_OR_PUBLIC: AddrKind = AddrKind(2);
13 pub const RESOLVABLE_PRIVATE_OR_RANDOM: AddrKind = AddrKind(3);
14 pub const ANONYMOUS_ADV: AddrKind = AddrKind(0xff);
15
16 pub const fn new(v: u8) -> Self {
18 Self(v)
19 }
20
21 pub fn as_raw(&self) -> u8 {
23 self.0
24 }
25}
26
27unsafe impl ByteAlignedValue for AddrKind {}
28
29impl<'de> crate::FromHciBytes<'de> for &'de AddrKind {
30 #[inline(always)]
31 fn from_hci_bytes(data: &'de [u8]) -> Result<(Self, &'de [u8]), crate::FromHciBytesError> {
32 <AddrKind as crate::ByteAlignedValue>::ref_from_hci_bytes(data)
33 }
34}
35
36param! {
37 bitfield AdvChannelMap[1] {
38 (0, is_channel_37_enabled, enable_channel_37);
39 (1, is_channel_38_enabled, enable_channel_38);
40 (2, is_channel_39_enabled, enable_channel_39);
41 }
42}
43
44#[allow(missing_docs)]
45impl AdvChannelMap {
46 pub const ALL: AdvChannelMap = AdvChannelMap(0x07);
47 pub const CHANNEL_37: AdvChannelMap = AdvChannelMap(0x01);
48 pub const CHANNEL_38: AdvChannelMap = AdvChannelMap(0x02);
49 pub const CHANNEL_39: AdvChannelMap = AdvChannelMap(0x04);
50}
51
52param!(struct ChannelMap([u8; 5]));
53
54impl ChannelMap {
55 pub fn new() -> Self {
57 Self([0xff, 0xff, 0xff, 0xff, 0x1f])
58 }
59
60 pub fn is_channel_bad(&self, channel: u8) -> bool {
62 let byte = usize::from(channel / 8);
63 let bit = channel % 8;
64 (self.0[byte] & (1 << bit)) == 0
65 }
66
67 pub fn set_channel_bad(&mut self, channel: u8, bad: bool) {
69 let byte = usize::from(channel / 8);
70 let bit = channel % 8;
71 self.0[byte] = (self.0[byte] & !(1 << bit)) | (u8::from(!bad) << bit);
72 }
73}
74
75unsafe impl ByteAlignedValue for ChannelMap {}
76
77impl<'de> crate::FromHciBytes<'de> for &'de ChannelMap {
78 #[inline(always)]
79 fn from_hci_bytes(data: &'de [u8]) -> Result<(Self, &'de [u8]), crate::FromHciBytesError> {
80 <ChannelMap as crate::ByteAlignedValue>::ref_from_hci_bytes(data)
81 }
82}
83
84param! {
85 #[derive(Default)]
86 enum AdvKind {
87 #[default]
88 AdvInd = 0,
89 AdvDirectIndHigh = 1,
90 AdvScanInd = 2,
91 AdvNonconnInd = 3,
92 AdvDirectIndLow = 4,
93 }
94}
95
96param! {
97 #[derive(Default)]
98 enum AdvFilterPolicy {
99 #[default]
100 Unfiltered = 0,
101 FilterScan = 1,
102 FilterConn = 2,
103 FilterConnAndScan = 3,
104 }
105}
106
107param! {
108 #[derive(Default)]
109 enum LeScanKind {
110 #[default]
111 Passive = 0,
112 Active = 1,
113 }
114}
115
116param! {
117 #[derive(Default)]
118 enum ScanningFilterPolicy {
119 #[default]
120 BasicUnfiltered = 0,
121 BasicFiltered = 1,
122 ExtUnfiltered = 2,
123 ExtFiltered = 3,
124 }
125}
126
127param! {
128 #[derive(Default)]
129 enum PhyKind {
130 #[default]
131 Le1M = 1,
132 Le2M = 2,
133 LeCoded = 3,
134 LeCodedS2 = 4,
135 }
136}
137
138param! {
139 bitfield AllPhys[1] {
140 (0, has_no_tx_phy_preference, set_has_no_tx_phy_preference);
141 (1, has_no_rx_phy_preference, set_has_no_rx_phy_preference);
142 }
143}
144
145param! {
146 bitfield PhyMask[1] {
147 (0, is_le_1m_preferred, set_le_1m_preferred);
148 (1, is_le_2m_preferred, set_le_2m_preferred);
149 (2, is_le_coded_preferred, set_le_coded_preferred);
150 }
151}
152
153#[derive(Default)]
155#[repr(u16, align(1))]
156#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
157#[cfg_attr(feature = "defmt", derive(defmt::Format))]
158#[allow(missing_docs)]
159pub enum PhyOptions {
160 #[default]
161 NoPreferredCoding = 0,
162 S2CodingPreferred = 1,
163 S8CodingPreferred = 2,
164}
165
166unsafe impl FixedSizeValue for PhyOptions {
167 #[inline(always)]
168 fn is_valid(data: &[u8]) -> bool {
169 data[0] == 0 || data[0] == 1 || data[0] == 2
170 }
171}
172
173unsafe impl ByteAlignedValue for PhyOptions {}
174
175impl<'de> FromHciBytes<'de> for &'de PhyOptions {
176 #[inline(always)]
177 fn from_hci_bytes(data: &'de [u8]) -> Result<(Self, &'de [u8]), FromHciBytesError> {
178 <PhyOptions as ByteAlignedValue>::ref_from_hci_bytes(data)
179 }
180}
181
182#[derive(Default)]
184#[repr(u16, align(1))]
185#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
186#[cfg_attr(feature = "defmt", derive(defmt::Format))]
187#[allow(missing_docs)]
188pub enum AdvPhyOptions {
189 #[default]
190 NoPreferredCoding = 0,
191 S2CodingPreferred = 1,
192 S8CodingPreferred = 2,
193 S2CodingRequired = 3,
194 S8CodingRequired = 4,
195}
196
197unsafe impl FixedSizeValue for AdvPhyOptions {
198 #[inline(always)]
199 fn is_valid(data: &[u8]) -> bool {
200 data[0] == 0 || data[0] == 1 || data[0] == 2 || data[0] == 3 || data[0] == 4
201 }
202}
203
204unsafe impl ByteAlignedValue for AdvPhyOptions {}
205
206impl<'de> FromHciBytes<'de> for &'de AdvPhyOptions {
207 #[inline(always)]
208 fn from_hci_bytes(data: &'de [u8]) -> Result<(Self, &'de [u8]), FromHciBytesError> {
209 <AdvPhyOptions as ByteAlignedValue>::ref_from_hci_bytes(data)
210 }
211}
212
213param! {
214 struct ScanningPhy {
215 active_scan: bool,
216 scan_interval: Duration<625>,
217 scan_window: Duration<625>,
218 }
219}
220
221param! {
222 struct InitiatingPhy {
223 scan_interval: Duration<625>,
224 scan_window: Duration<625>,
225 conn_interval_min: Duration<1_250>,
226 conn_interval_max: Duration<1_250>,
227 max_latency: u16,
228 supervision_timeout: Duration<10_000>,
229 min_ce_len: Duration<625>,
230 max_ce_len: Duration<625>,
231 }
232}
233
234#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
236#[cfg_attr(feature = "defmt", derive(defmt::Format))]
237pub struct PhyParams<T> {
238 pub le_1m_phy: Option<T>,
240 pub le_2m_phy: Option<T>,
242 pub le_coded_phy: Option<T>,
244}
245
246impl<T> PhyParams<T> {
247 pub fn scanning_phys(&self) -> PhyMask {
249 PhyMask::new()
250 .set_le_1m_preferred(self.le_1m_phy.is_some())
251 .set_le_2m_preferred(self.le_2m_phy.is_some())
252 .set_le_coded_preferred(self.le_coded_phy.is_some())
253 }
254}
255
256impl<T: WriteHci> WriteHci for PhyParams<T> {
257 #[inline(always)]
258 fn size(&self) -> usize {
259 1 + self.le_1m_phy.size() + self.le_2m_phy.size() + self.le_coded_phy.size()
260 }
261
262 #[inline(always)]
263 fn write_hci<W: embedded_io::Write>(&self, mut writer: W) -> Result<(), W::Error> {
264 self.scanning_phys().write_hci(&mut writer)?;
265 self.le_1m_phy.write_hci(&mut writer)?;
266 self.le_2m_phy.write_hci(&mut writer)?;
267 self.le_coded_phy.write_hci(&mut writer)?;
268 Ok(())
269 }
270
271 #[inline(always)]
272 async fn write_hci_async<W: ::embedded_io_async::Write>(&self, mut writer: W) -> Result<(), W::Error> {
273 self.scanning_phys().write_hci_async(&mut writer).await?;
274 self.le_1m_phy.write_hci_async(&mut writer).await?;
275 self.le_2m_phy.write_hci_async(&mut writer).await?;
276 self.le_coded_phy.write_hci_async(&mut writer).await?;
277 Ok(())
278 }
279}
280
281param!(struct AdvHandle(u8));
282
283impl AdvHandle {
284 pub const fn new(v: u8) -> Self {
286 Self(v)
287 }
288
289 pub fn as_raw(&self) -> u8 {
291 self.0
292 }
293}
294
295unsafe impl ByteAlignedValue for AdvHandle {}
296
297impl<'de> crate::FromHciBytes<'de> for &'de AdvHandle {
298 #[inline(always)]
299 fn from_hci_bytes(data: &'de [u8]) -> Result<(Self, &'de [u8]), crate::FromHciBytesError> {
300 <AdvHandle as crate::ByteAlignedValue>::ref_from_hci_bytes(data)
301 }
302}
303
304param! {
305 bitfield AdvEventProps[2] {
306 (0, connectable_adv, set_connectable_adv);
307 (1, scannable_adv, set_scannable_adv);
308 (2, directed_adv, set_directed_adv);
309 (3, high_duty_cycle_directed_connectable_adv, set_high_duty_cycle_directed_connectable_adv);
310 (4, legacy_adv, set_legacy_adv);
311 (5, anonymous_adv, set_anonymous_adv);
312 (6, include_tx_power, set_include_tx_power);
313 }
314}
315
316param! {
317 #[derive(Default)]
318 enum Operation {
319 #[default]
320 IntermediateFragment = 0,
321 FirstFragment = 1,
322 LastFragment = 2,
323 Complete = 3,
324 Unchanged = 4,
325 }
326}
327
328param! {
329 struct AdvSet {
330 adv_handle: AdvHandle,
331 duration: Duration<10_000>,
332 max_ext_adv_events: u8,
333 }
334}
335
336param_slice!(&'a [AdvSet]);
337
338param! {
339 bitfield PeriodicAdvProps[2] {
340 (6, is_tx_power_included, include_tx_power);
341 }
342}
343
344param! {
345 #[derive(Default)]
346 enum FilterDuplicates {
347 #[default]
348 Disabled = 0,
349 Enabled = 1,
350 EnabledPerScanPeriod = 2,
351 }
352}
353
354param! {
355 bitfield LePeriodicAdvCreateSyncOptions[1] {
356 (0, is_using_periodic_adv_list, use_periodic_adv_list);
357 (1, is_reporting_initially_disabled, disable_initial_reporting);
358 (2, is_duplicate_filtering_enabled, enable_duplicate_filtering);
359 }
360}
361
362param! {
363 bitfield CteMask[1] {
364 (0, is_aoa_cte, set_aoa_cte);
365 (1, is_aod_1us_cte, set_aod_1us_cte);
366 (2, is_aod_2us_cte, set_aod_2us_cte);
367 (3, is_type_3_cte, set_type_3_cte);
368 (4, is_non_cte, set_non_cte);
369 }
370}
371
372param!(struct SyncHandle(u16));
373
374param!(struct BigHandle(u16));
375
376param! {
377 #[derive(Default)]
378 enum PrivacyMode {
379 #[default]
380 Network = 0,
381 Device = 1,
382 }
383}
384
385param! {
386 #[derive(Default)]
387 enum CteKind {
388 #[default]
389 AoA = 0,
390 AoD1Us = 1,
391 AoD2Us = 2,
392 }
393}
394
395param! {
396 bitfield SwitchingSamplingRates[1] {
397 (0, is_1us_aod_tx, set_1us_aod_tx);
398 (1, is_1us_aod_rx, set_1us_aod_rx);
399 (2, is_1us_aoa_rx, set_1us_aoa_rx);
400 }
401}
402
403param! {
404 bitfield LePeriodicAdvReceiveEnable[1] {
405 (0, is_reporting, set_reporting);
406 (1, is_duplicate_filtering, set_duplicate_filtering);
407 }
408}
409
410param! {
411 #[derive(Default)]
412 enum LePeriodicAdvSyncTransferMode {
413 #[default]
414 NoSync = 0,
415 SyncRx = 1,
416 SyncRxReport = 2,
417 SyncRxReportFilterDuplicates = 3,
418 }
419}
420
421param! {
422 bitfield LeDataRelatedAddrChangeReasons[1] {
423 (0, change_on_adv_data_change, set_change_addr_on_adv_data_changes);
424 (1, change_on_scan_response_data_change, set_change_addr_on_scan_response_data_changes);
425 }
426}
427
428param! {
429 #[derive(Default)]
430 enum LeConnRole {
431 #[default]
432 Central = 0,
433 Peripheral = 1,
434 }
435}
436
437param! {
438 #[derive(Default)]
439 enum ClockAccuracy {
440 #[default]
441 Ppm500 = 0,
442 Ppm250 = 1,
443 Ppm150 = 2,
444 Ppm100 = 3,
445 Ppm75 = 4,
446 Ppm50 = 5,
447 Ppm30 = 6,
448 Ppm20 = 7,
449 }
450}
451
452param! {
453 struct LeAdvertisingReportParam<'a> {
454 event_type: u8,
455 addr_kind: AddrKind,
456 addr: BdAddr,
457 data: &'a [u8],
458 rssi: i8,
459 }
460}
461
462param_slice! {
463 [LeDirectedAdvertisingReportParam; 16] {
464 event_type[0]: u8,
465 addr_kind[1]: AddrKind,
466 addr[2]: BdAddr,
467 direct_addr_kind[8]: AddrKind,
468 direct_addr[9]: BdAddr,
469 rssi[15]: i8,
470 }
471}
472
473param_slice! {
474 [LeIQSample; 2] {
475 i_sample[0]: i8,
476 q_sample[1]: i8,
477 }
478}
479
480param_slice! {
481 [BisConnHandle; 2] {
482 handle[0]: ConnHandle,
483 }
484}
485
486param! {
487 #[derive(Default)]
488 enum DataStatus {
489 #[default]
490 Complete = 0,
491 Incomplete = 1,
492 }
493}
494
495param! {
496 #[derive(Default)]
497 enum PacketStatus {
498 #[default]
499 CrcCorrect = 0,
500 CrcIncorrectUsedLength = 1,
501 CrcIncorrectUsedOther = 2,
502 InsufficientResources = 0xff,
503 }
504}
505
506param! {
507 #[derive(Default)]
508 enum ZoneEntered {
509 #[default]
510 Low = 0,
511 Middle = 1,
512 High = 2,
513 }
514}
515
516param! {
517 #[derive(Default)]
518 enum LeTxPowerReportingReason {
519 #[default]
520 LocalTxPowerChanged = 0,
521 RemoteTxPowerChanged = 1,
522 LeReadRemoteTxPowerLevelCompleted = 2,
523 }
524}
525
526param! {
527 #[derive(Default)]
528 enum LeAdvEventKind {
529 #[default]
530 AdvInd = 0,
531 AdvDirectInd = 1,
532 AdvScanInd = 2,
533 AdvNonconnInd = 3,
534 ScanRsp = 4,
535 }
536}
537
538param! {
539 bitfield LeExtAdvEventKind[2] {
540 (0, connectable, set_connectable);
541 (1, scannable, set_scannable);
542 (2, directed, set_directed);
543 (3, scan_response, set_scan_response);
544 (4, legacy, set_legacy);
545 }
546}
547
548#[allow(missing_docs)]
550pub enum LeExtAdvDataStatus {
551 Complete,
552 IncompleteMoreExpected,
553 IncompleteTruncated,
554 Reserved,
555}
556
557impl LeExtAdvEventKind {
558 pub fn data_status(&self) -> LeExtAdvDataStatus {
560 let data_status = (self.0[0] >> 5) & 0x03;
561 match data_status {
562 0 => LeExtAdvDataStatus::Complete,
563 1 => LeExtAdvDataStatus::IncompleteMoreExpected,
564 2 => LeExtAdvDataStatus::IncompleteTruncated,
565 _ => LeExtAdvDataStatus::Reserved,
566 }
567 }
568
569 pub fn set_data_status(mut self, status: LeExtAdvDataStatus) -> Self {
571 let value = match status {
572 LeExtAdvDataStatus::Complete => 0,
573 LeExtAdvDataStatus::IncompleteMoreExpected => 1,
574 LeExtAdvDataStatus::IncompleteTruncated => 2,
575 LeExtAdvDataStatus::Reserved => 3,
576 };
577 self.0[0] &= !(0x03 << 5);
578 self.0[0] |= value << 5;
579 self
580 }
581}
582
583param! {
584 struct LeAdvReport<'a> {
585 event_kind: LeAdvEventKind,
586 addr_kind: AddrKind,
587 addr: BdAddr,
588 data: &'a [u8],
589 rssi: i8,
590 }
591}
592
593param! {
594 struct LeAdvReports<'a> {
595 num_reports: u8,
596 bytes: RemainingBytes<'a>,
597 }
598}
599
600impl LeAdvReports<'_> {
601 pub fn is_empty(&self) -> bool {
603 self.num_reports == 0
604 }
605
606 pub fn len(&self) -> usize {
608 usize::from(self.num_reports)
609 }
610
611 pub fn iter(&self) -> LeAdvReportsIter<'_> {
613 LeAdvReportsIter {
614 len: self.len(),
615 bytes: &self.bytes,
616 }
617 }
618}
619
620pub struct LeAdvReportsIter<'a> {
622 len: usize,
623 bytes: &'a [u8],
624}
625
626impl<'a> Iterator for LeAdvReportsIter<'a> {
627 type Item = Result<LeAdvReport<'a>, FromHciBytesError>;
628
629 fn next(&mut self) -> Option<Self::Item> {
630 if self.len == 0 {
631 None
632 } else {
633 match LeAdvReport::from_hci_bytes(self.bytes) {
634 Ok((report, rest)) => {
635 self.bytes = rest;
636 self.len -= 1;
637 Some(Ok(report))
638 }
639 Err(err) => {
640 self.len = 0;
641 Some(Err(err))
642 }
643 }
644 }
645 }
646
647 fn size_hint(&self) -> (usize, Option<usize>) {
648 (self.len, Some(self.len))
649 }
650}
651
652impl ExactSizeIterator for LeAdvReportsIter<'_> {
653 fn len(&self) -> usize {
654 self.len
655 }
656}
657
658impl FusedIterator for LeAdvReportsIter<'_> {}
659
660#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
661#[cfg_attr(feature = "defmt", derive(defmt::Format))]
662#[allow(missing_docs)]
663pub struct LeExtAdvReport<'a> {
664 pub event_kind: LeExtAdvEventKind,
665 pub addr_kind: AddrKind,
666 pub addr: BdAddr,
667 pub primary_adv_phy: PhyKind,
668 pub secondary_adv_phy: Option<PhyKind>,
669 pub adv_sid: u8,
670 pub tx_power: i8,
671 pub rssi: i8,
672 pub adv_interval: Duration<1_250>,
673 pub direct_addr_kind: AddrKind,
674 pub direct_addr: BdAddr,
675 pub data: &'a [u8],
676}
677
678impl WriteHci for LeExtAdvReport<'_> {
679 #[inline(always)]
680 fn size(&self) -> usize {
681 WriteHci::size(&self.event_kind)
682 + WriteHci::size(&self.addr_kind)
683 + WriteHci::size(&self.addr)
684 + WriteHci::size(&self.primary_adv_phy)
685 + 1 + WriteHci::size(&self.adv_sid)
687 + WriteHci::size(&self.tx_power)
688 + WriteHci::size(&self.rssi)
689 + WriteHci::size(&self.adv_interval)
690 + WriteHci::size(&self.direct_addr_kind)
691 + WriteHci::size(&self.direct_addr)
692 + WriteHci::size(&self.data)
693 }
694 #[inline(always)]
695 fn write_hci<W: ::embedded_io::Write>(&self, mut writer: W) -> Result<(), W::Error> {
696 self.event_kind.write_hci(&mut writer)?;
697 self.addr_kind.write_hci(&mut writer)?;
698 self.addr.write_hci(&mut writer)?;
699 self.primary_adv_phy.write_hci(&mut writer)?;
700 match self.secondary_adv_phy {
701 None => 0u8.write_hci(&mut writer)?,
702 Some(val) => val.write_hci(&mut writer)?,
703 };
704 self.adv_sid.write_hci(&mut writer)?;
705 self.tx_power.write_hci(&mut writer)?;
706 self.rssi.write_hci(&mut writer)?;
707 self.adv_interval.write_hci(&mut writer)?;
708 self.direct_addr_kind.write_hci(&mut writer)?;
709 self.direct_addr.write_hci(&mut writer)?;
710 self.data.write_hci(&mut writer)?;
711 Ok(())
712 }
713 #[inline(always)]
714 async fn write_hci_async<W: ::embedded_io_async::Write>(&self, mut writer: W) -> Result<(), W::Error> {
715 self.event_kind.write_hci_async(&mut writer).await?;
716 self.addr_kind.write_hci_async(&mut writer).await?;
717 self.addr.write_hci_async(&mut writer).await?;
718 self.primary_adv_phy.write_hci_async(&mut writer).await?;
719 match self.secondary_adv_phy {
720 None => 0u8.write_hci_async(&mut writer).await?,
721 Some(val) => val.write_hci_async(&mut writer).await?,
722 };
723 self.adv_sid.write_hci_async(&mut writer).await?;
724 self.tx_power.write_hci_async(&mut writer).await?;
725 self.rssi.write_hci_async(&mut writer).await?;
726 self.adv_interval.write_hci_async(&mut writer).await?;
727 self.direct_addr_kind.write_hci_async(&mut writer).await?;
728 self.direct_addr.write_hci_async(&mut writer).await?;
729 self.data.write_hci_async(&mut writer).await?;
730 Ok(())
731 }
732}
733
734impl<'de> crate::FromHciBytes<'de> for LeExtAdvReport<'de> {
735 #[allow(unused_variables)]
736 fn from_hci_bytes(data: &'de [u8]) -> Result<(Self, &'de [u8]), crate::FromHciBytesError> {
737 let (event_kind, data) = <LeExtAdvEventKind as crate::FromHciBytes>::from_hci_bytes(data)?;
738 let (addr_kind, data) = <AddrKind as crate::FromHciBytes>::from_hci_bytes(data)?;
739 let (addr, data) = <BdAddr as crate::FromHciBytes>::from_hci_bytes(data)?;
740 let (primary_adv_phy, data) = <PhyKind as crate::FromHciBytes>::from_hci_bytes(data)?;
741 let (secondary_adv_phy, data) = if data[0] == 0 {
742 (None, &data[1..])
743 } else {
744 let (ret, rest) = <PhyKind as crate::FromHciBytes>::from_hci_bytes(data)?;
745 (Some(ret), rest)
746 };
747 let (adv_sid, data) = <u8 as crate::FromHciBytes>::from_hci_bytes(data)?;
748 let (tx_power, data) = <i8 as crate::FromHciBytes>::from_hci_bytes(data)?;
749 let (rssi, data) = <i8 as crate::FromHciBytes>::from_hci_bytes(data)?;
750 let (adv_interval, data) = <Duration<1_250> as crate::FromHciBytes>::from_hci_bytes(data)?;
751 let (direct_addr_kind, data) = <AddrKind as crate::FromHciBytes>::from_hci_bytes(data)?;
752 let (direct_addr, data) = <BdAddr as crate::FromHciBytes>::from_hci_bytes(data)?;
753 let (data, rest) = <&'de [u8] as crate::FromHciBytes>::from_hci_bytes(data)?;
754 Ok((
755 Self {
756 event_kind,
757 addr_kind,
758 addr,
759 primary_adv_phy,
760 secondary_adv_phy,
761 adv_sid,
762 tx_power,
763 rssi,
764 adv_interval,
765 direct_addr_kind,
766 direct_addr,
767 data,
768 },
769 rest,
770 ))
771 }
772}
773
774param! {
775 struct LeExtAdvReports<'a> {
776 num_reports: u8,
777 bytes: RemainingBytes<'a>,
778 }
779}
780
781impl LeExtAdvReports<'_> {
782 pub fn is_empty(&self) -> bool {
784 self.num_reports == 0
785 }
786
787 pub fn len(&self) -> usize {
789 usize::from(self.num_reports)
790 }
791
792 pub fn iter(&self) -> LeExtAdvReportsIter<'_> {
794 LeExtAdvReportsIter {
795 len: self.len(),
796 bytes: &self.bytes,
797 }
798 }
799}
800
801pub struct LeExtAdvReportsIter<'a> {
803 len: usize,
804 bytes: &'a [u8],
805}
806
807impl<'a> Iterator for LeExtAdvReportsIter<'a> {
808 type Item = Result<LeExtAdvReport<'a>, FromHciBytesError>;
809
810 fn next(&mut self) -> Option<Self::Item> {
811 if self.len == 0 {
812 None
813 } else {
814 match LeExtAdvReport::from_hci_bytes(self.bytes) {
815 Ok((report, rest)) => {
816 self.bytes = rest;
817 self.len -= 1;
818 Some(Ok(report))
819 }
820 Err(err) => {
821 self.len = 0;
822 Some(Err(err))
823 }
824 }
825 }
826 }
827
828 fn size_hint(&self) -> (usize, Option<usize>) {
829 (self.len, Some(self.len))
830 }
831}
832
833impl ExactSizeIterator for LeExtAdvReportsIter<'_> {
834 fn len(&self) -> usize {
835 self.len
836 }
837}
838
839impl FusedIterator for LeExtAdvReportsIter<'_> {}
840
841param! {
842 struct LePeriodicAdvSubeventData<'a> {
843 subevent: u8,
844 response_slot_start: u8,
845 response_slot_count: u8,
846 subevent_data: &'a [u8],
847 }
848}
849
850impl<'a, 'b: 'a> WriteHci for &'a [LePeriodicAdvSubeventData<'b>] {
851 #[inline(always)]
852 fn size(&self) -> usize {
853 1 + self.iter().map(WriteHci::size).sum::<usize>()
854 }
855 #[inline(always)]
856 fn write_hci<W: ::embedded_io::Write>(&self, mut writer: W) -> Result<(), W::Error> {
857 writer.write_all(&[self.len() as u8])?;
858 for x in self.iter() {
859 <LePeriodicAdvSubeventData as WriteHci>::write_hci(x, &mut writer)?;
860 }
861 Ok(())
862 }
863 #[inline(always)]
864 async fn write_hci_async<W: ::embedded_io_async::Write>(&self, mut writer: W) -> Result<(), W::Error> {
865 writer.write_all(&[self.len() as u8]).await?;
866 for x in self.iter() {
867 <LePeriodicAdvSubeventData as WriteHci>::write_hci_async(x, &mut writer).await?;
868 }
869 Ok(())
870 }
871}
872
873#[cfg(test)]
874mod tests {
875 use super::*;
876
877 #[test]
878 fn test_ext_adv_event_kind() {
879 let k = LeExtAdvEventKind::new().set_connectable(true);
880 assert_eq!(k.0[0], 0b0000001);
881 let k = k.set_data_status(LeExtAdvDataStatus::Complete);
882 assert_eq!(k.0[0], 0b0000001);
883 let k = k.set_data_status(LeExtAdvDataStatus::IncompleteMoreExpected);
884 assert_eq!(k.0[0], 0b0100001);
885 let k = k.set_data_status(LeExtAdvDataStatus::IncompleteTruncated);
886 assert_eq!(k.0[0], 0b1000001);
887 }
888
889 #[test]
890 fn test_channel_map_new() {
891 let m = ChannelMap::new();
892 for chan in 0..37 {
893 assert!(!m.is_channel_bad(chan));
894 }
895
896 for chan in 37..40 {
897 assert!(m.is_channel_bad(chan));
898 }
899 }
900}