1use crate::le::advertisement::{RawAdvertisement, StaticAdvBuffer};
2use crate::ConversionError;
3use crate::{BTAddress, BT_ADDRESS_LEN, RSSI};
4use core::convert::TryFrom;
5use core::fmt::Formatter;
6
7pub struct NumReports(u8);
8impl NumReports {
9 pub const NUM_REPORTS_MIN: u8 = 0x01;
10 pub const NUM_REPORTS_MAX: u8 = 0x19;
11 pub fn new(num_reports: u8) -> NumReports {
12 if let Ok(r) = NumReports::try_from(num_reports) {
13 r
14 } else {
15 panic!("invalid number of reports: {}", num_reports);
16 }
17 }
18}
19impl From<NumReports> for u8 {
20 fn from(n: NumReports) -> Self {
21 n.0
22 }
23}
24impl TryFrom<u8> for NumReports {
25 type Error = ConversionError;
26
27 fn try_from(value: u8) -> Result<Self, Self::Error> {
28 if value <= NumReports::NUM_REPORTS_MAX && value >= NumReports::NUM_REPORTS_MIN {
29 Ok(NumReports(value))
30 } else {
31 Err(ConversionError(()))
32 }
33 }
34}
35impl TryFrom<usize> for NumReports {
36 type Error = ConversionError;
37
38 fn try_from(value: usize) -> Result<Self, Self::Error> {
39 match u8::try_from(value).map(NumReports::try_from) {
40 Ok(Ok(v)) => Ok(v),
41 _ => Err(ConversionError(())),
42 }
43 }
44}
45#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)]
46pub enum EventType {
47 AdvInd = 0x00,
48 AdvDirectInd = 0x01,
49 AdvScanInd = 0x02,
50 AdvNonconnInd = 0x03,
51 ScanRsp = 0x04,
52}
53impl EventType {
54 pub fn as_str(self) -> &'static str {
55 match self {
56 EventType::AdvInd => "ADV_IND",
57 EventType::AdvDirectInd => "ADV_DIRECT_IND",
58 EventType::AdvScanInd => "ADV_SCAN_IND",
59 EventType::AdvNonconnInd => "ADV_NONNCONN_IND",
60 EventType::ScanRsp => "SCAN_RSP",
61 }
62 }
63}
64impl core::fmt::Display for EventType {
65 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
66 f.write_str(self.as_str())
67 }
68}
69impl TryFrom<u8> for EventType {
70 type Error = ConversionError;
71 fn try_from(v: u8) -> Result<Self, Self::Error> {
72 match v {
73 0x00 => Ok(EventType::AdvInd),
74 0x01 => Ok(EventType::AdvDirectInd),
75 0x02 => Ok(EventType::AdvScanInd),
76 0x03 => Ok(EventType::AdvNonconnInd),
77 0x04 => Ok(EventType::ScanRsp),
78 _ => Err(ConversionError(())),
79 }
80 }
81}
82impl From<EventType> for u8 {
83 fn from(e: EventType) -> Self {
84 e as u8
85 }
86}
87#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)]
88pub enum AddressType {
89 PublicDevice = 0x00,
90 RandomDevice = 0x01,
91 PublicIdentity = 0x02,
92 RandomIdentity = 0x03,
93}
94impl TryFrom<u8> for AddressType {
95 type Error = ConversionError;
96
97 fn try_from(value: u8) -> Result<Self, Self::Error> {
98 match value {
99 0x00 => Ok(AddressType::PublicDevice),
100 0x01 => Ok(AddressType::RandomDevice),
101 0x02 => Ok(AddressType::PublicIdentity),
102 0x03 => Ok(AddressType::RandomIdentity),
103 _ => Err(ConversionError(())),
104 }
105 }
106}
107impl From<AddressType> for u8 {
108 fn from(a: AddressType) -> Self {
109 a as u8
110 }
111}
112#[derive(Copy, Clone)]
120pub struct ReportInfo<T = StaticAdvBuffer> {
121 pub event_type: EventType,
123 pub address_type: AddressType,
125 pub address: BTAddress,
127 pub data: RawAdvertisement<T>,
129 pub rssi: Option<RSSI>,
131}
132impl<T: AsRef<[u8]>> core::fmt::Debug for ReportInfo<T> {
133 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
134 f.debug_struct("ReportInfo")
135 .field("event_type", &self.event_type)
136 .field("address_type", &self.address_type)
137 .field("address", &self.address)
138 .field("rssi", &self.rssi)
139 .field("data", &self.data.as_ref())
140 .finish()
141 }
142}
143impl<T: AsRef<[u8]> + Default> Default for ReportInfo<T> {
144 fn default() -> Self {
145 Self {
146 event_type: EventType::AdvInd,
147 address_type: AddressType::PublicDevice,
148 address: BTAddress::ZEROED,
149 data: RawAdvertisement(T::default()),
150 rssi: None,
151 }
152 }
153}
154impl<T: AsRef<[u8]>> ReportInfo<T> {
155 pub fn byte_len(&self) -> usize {
156 1 + 1 + BT_ADDRESS_LEN + self.data.as_ref().len() + 1
158 }
159 pub fn as_ref(&self) -> ReportInfo<&[u8]> {
160 ReportInfo {
161 event_type: self.event_type,
162 address_type: self.address_type,
163 address: self.address,
164 data: RawAdvertisement(self.data.as_ref()),
165 rssi: self.rssi,
166 }
167 }
168}