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