1use bt_common::{PeerId, Uuid};
6use thiserror::Error;
7
8#[derive(Debug, Copy, Clone, PartialEq)]
12pub enum GattError {
13 InvalidHandle = 1,
14 ReadNotPermitted = 2,
15 WriteNotPermitted = 3,
16 InvalidPdu = 4,
17 InsufficientAuthentication = 5,
18 RequestNotSupported = 6,
19 InvalidOffset = 7,
20 InsufficientAuthorization = 8,
21 InsufficientEncryptionKeySize = 12,
22 InvalidAttributeValueLength = 13,
23 UnlikelyError = 14,
24 InsufficientEncryption = 15,
25 InsufficientResources = 17,
26 ValueNotAllowed = 19,
27 ApplicationError80 = 128,
28 ApplicationError81 = 129,
29 ApplicationError82 = 130,
30 ApplicationError83 = 131,
31 ApplicationError84 = 132,
32 ApplicationError85 = 133,
33 ApplicationError86 = 134,
34 ApplicationError87 = 135,
35 ApplicationError88 = 136,
36 ApplicationError89 = 137,
37 ApplicationError8A = 138,
38 ApplicationError8B = 139,
39 ApplicationError8C = 140,
40 ApplicationError8D = 141,
41 ApplicationError8E = 142,
42 ApplicationError8F = 143,
43 ApplicationError90 = 144,
44 ApplicationError91 = 145,
45 ApplicationError92 = 146,
46 ApplicationError93 = 147,
47 ApplicationError94 = 148,
48 ApplicationError95 = 149,
49 ApplicationError96 = 150,
50 ApplicationError97 = 151,
51 ApplicationError98 = 152,
52 ApplicationError99 = 153,
53 ApplicationError9A = 154,
54 ApplicationError9B = 155,
55 ApplicationError9C = 156,
56 ApplicationError9D = 157,
57 ApplicationError9E = 158,
58 ApplicationError9F = 159,
59 WriteRequestRejected = 252,
60 CccDescriptorImproperlyConfigured = 253,
61 ProcedureAlreadyInProgress = 254,
62 OutOfRange = 255,
63 InvalidParameters = 257,
64 TooManyResults = 258,
65}
66
67impl std::fmt::Display for GattError {
68 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69 write!(f, "{:?}", self)
70 }
71}
72
73impl std::error::Error for GattError {}
74
75impl TryFrom<u32> for GattError {
76 type Error = Error;
77
78 fn try_from(value: u32) -> std::result::Result<Self, Self::Error> {
79 match value {
80 1 => Ok(Self::InvalidHandle),
81 2 => Ok(Self::ReadNotPermitted),
82 3 => Ok(Self::WriteNotPermitted),
83 4 => Ok(Self::InvalidPdu),
84 5 => Ok(Self::InsufficientAuthentication),
85 6 => Ok(Self::RequestNotSupported),
86 7 => Ok(Self::InvalidOffset),
87 8 => Ok(Self::InsufficientAuthorization),
88 12 => Ok(Self::InsufficientEncryptionKeySize),
89 13 => Ok(Self::InvalidAttributeValueLength),
90 14 => Ok(Self::UnlikelyError),
91 15 => Ok(Self::InsufficientEncryption),
92 17 => Ok(Self::InsufficientResources),
93 19 => Ok(Self::ValueNotAllowed),
94 128 => Ok(Self::ApplicationError80),
95 129 => Ok(Self::ApplicationError81),
96 130 => Ok(Self::ApplicationError82),
97 131 => Ok(Self::ApplicationError83),
98 132 => Ok(Self::ApplicationError84),
99 133 => Ok(Self::ApplicationError85),
100 134 => Ok(Self::ApplicationError86),
101 135 => Ok(Self::ApplicationError87),
102 136 => Ok(Self::ApplicationError88),
103 137 => Ok(Self::ApplicationError89),
104 138 => Ok(Self::ApplicationError8A),
105 139 => Ok(Self::ApplicationError8B),
106 140 => Ok(Self::ApplicationError8C),
107 141 => Ok(Self::ApplicationError8D),
108 142 => Ok(Self::ApplicationError8E),
109 143 => Ok(Self::ApplicationError8F),
110 144 => Ok(Self::ApplicationError90),
111 145 => Ok(Self::ApplicationError91),
112 146 => Ok(Self::ApplicationError92),
113 147 => Ok(Self::ApplicationError93),
114 148 => Ok(Self::ApplicationError94),
115 149 => Ok(Self::ApplicationError95),
116 150 => Ok(Self::ApplicationError96),
117 151 => Ok(Self::ApplicationError97),
118 152 => Ok(Self::ApplicationError98),
119 153 => Ok(Self::ApplicationError99),
120 154 => Ok(Self::ApplicationError9A),
121 155 => Ok(Self::ApplicationError9B),
122 156 => Ok(Self::ApplicationError9C),
123 157 => Ok(Self::ApplicationError9D),
124 158 => Ok(Self::ApplicationError9E),
125 159 => Ok(Self::ApplicationError9F),
126 252 => Ok(Self::WriteRequestRejected),
127 253 => Ok(Self::CccDescriptorImproperlyConfigured),
128 254 => Ok(Self::ProcedureAlreadyInProgress),
129 255 => Ok(Self::OutOfRange),
130 257 => Ok(Self::InvalidParameters),
131 258 => Ok(Self::TooManyResults),
132 x => Err(Error::Conversion(format!("Unknown GATT Error Value: {x}"))),
133 }
134 }
135}
136
137#[derive(Error, Debug)]
138#[non_exhaustive]
139pub enum Error {
140 #[error("peer {0} was not recognized")]
141 PeerNotRecognized(PeerId),
142 #[error("peer {0} was disconnected")]
143 PeerDisconnected(PeerId),
144 #[error("conversion error: {0}")]
145 Conversion(String),
146 #[error("scan failed: {0}")]
147 ScanFailed(String),
148 #[error("another error: {0}")]
149 Other(#[from] Box<dyn std::error::Error + Send + Sync>),
150 #[error("GATT error: {0}")]
151 Gatt(#[from] GattError),
152 #[error("definition error: duplicate handle(s) {0:?}")]
153 DuplicateHandle(Vec<Handle>),
154 #[error("service for {0:?} already published")]
155 AlreadyPublished(crate::server::ServiceId),
156 #[error("Encoding/decoding error: {0}")]
157 Encoding(#[from] bt_common::packet_encoding::Error),
158 #[error("Periodic Advertising error: {0}")]
159 PeriodicAdvertising(crate::periodic_advertising::Error),
160}
161
162impl Error {
163 pub fn other(e: impl std::error::Error + Send + Sync + 'static) -> Self {
164 Self::Other(Box::new(e))
165 }
166}
167
168impl From<String> for Error {
169 fn from(value: String) -> Self {
170 Self::Other(Box::<dyn std::error::Error + Send + Sync>::from(value))
171 }
172}
173
174impl From<&str> for Error {
175 fn from(value: &str) -> Self {
176 String::from(value).into()
177 }
178}
179
180pub type Result<T> = core::result::Result<T, Error>;
181
182#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
200pub struct Handle(pub u64);
201
202#[derive(Clone, Copy, Debug, Eq, PartialEq)]
204pub enum ServiceKind {
205 Primary,
206 Secondary,
207}
208
209#[derive(Clone, Copy, Debug, Eq, PartialEq)]
210pub enum WriteMode {
211 None,
212 Reliable,
213 WithoutResponse,
214}
215
216#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
221pub enum CharacteristicProperty {
222 Broadcast = 0x01,
223 Read = 0x02,
224 WriteWithoutResponse = 0x04,
225 Write = 0x08,
226 Notify = 0x10,
227 Indicate = 0x20,
228 AuthenticatedSignedWrites = 0x40,
229 ReliableWrite = 0x100,
230 WritableAuxiliaries = 0x200,
231}
232
233impl std::ops::BitOr for CharacteristicProperty {
234 type Output = CharacteristicProperties;
235
236 fn bitor(self, rhs: Self) -> Self::Output {
237 CharacteristicProperties(vec![self, rhs])
238 }
239}
240
241#[derive(Default, Debug, Clone)]
242pub struct CharacteristicProperties(pub Vec<CharacteristicProperty>);
243
244impl From<CharacteristicProperty> for CharacteristicProperties {
245 fn from(value: CharacteristicProperty) -> Self {
246 Self(vec![value])
247 }
248}
249
250impl FromIterator<CharacteristicProperty> for CharacteristicProperties {
251 fn from_iter<T: IntoIterator<Item = CharacteristicProperty>>(iter: T) -> Self {
252 Self(iter.into_iter().collect())
253 }
254}
255
256impl std::ops::BitOr<CharacteristicProperty> for CharacteristicProperties {
257 type Output = Self;
258
259 fn bitor(mut self, rhs: CharacteristicProperty) -> Self::Output {
260 self.0.push(rhs);
261 self
262 }
263}
264
265impl CharacteristicProperties {
266 pub fn is_disjoint(&self, other: &Self) -> bool {
267 for property in self.0.iter() {
268 if other.0.contains(&property) {
269 return false;
270 }
271 }
272 true
273 }
274
275 pub fn contains(&self, property: CharacteristicProperty) -> bool {
276 self.0.contains(&property)
277 }
278}
279
280#[derive(Debug, Clone, Copy, Default)]
281pub struct SecurityLevels {
282 pub encryption: bool,
284 pub authentication: bool,
286 pub authorization: bool,
288}
289
290impl SecurityLevels {
291 pub fn satisfied(&self, provided: SecurityLevels) -> bool {
292 (!self.encryption || provided.encryption)
293 && (!self.authentication || provided.authentication)
294 && (!self.authorization || provided.encryption)
295 }
296
297 pub const fn encryption_required() -> Self {
298 Self { encryption: true, authentication: false, authorization: false }
299 }
300}
301
302#[derive(Debug, Clone, Copy, Default)]
303pub struct AttributePermissions {
304 pub read: Option<SecurityLevels>,
307 pub write: Option<SecurityLevels>,
310 pub update: Option<SecurityLevels>,
313}
314
315impl AttributePermissions {
316 pub fn with_levels(properties: &CharacteristicProperties, levels: &SecurityLevels) -> Self {
317 let notify_properties = CharacteristicProperty::Notify | CharacteristicProperty::Indicate;
318 Self {
319 read: properties.contains(CharacteristicProperty::Read).then_some(levels.clone()),
320 write: properties.contains(CharacteristicProperty::Write).then_some(levels.clone()),
321 update: (!properties.is_disjoint(¬ify_properties)).then_some(levels.clone()),
322 }
323 }
324}
325
326#[derive(Clone, Debug)]
337pub enum DescriptorType {
338 UserDescription(String),
339 ServerConfiguration {
340 broadcast: bool,
341 },
342 CharacteristicPresentation {
343 format: u8,
344 exponent: i8,
345 unit: u16,
346 name_space: u8,
347 description: u16,
348 },
349 Other {
350 uuid: Uuid,
351 },
352}
353
354impl From<&DescriptorType> for Uuid {
355 fn from(value: &DescriptorType) -> Self {
356 match value {
358 DescriptorType::UserDescription(_) => Uuid::from_u16(0x2901),
359 DescriptorType::ServerConfiguration { .. } => Uuid::from_u16(0x2903),
360 DescriptorType::CharacteristicPresentation { .. } => Uuid::from_u16(0x2904),
361 DescriptorType::Other { uuid } => uuid.clone(),
362 }
363 }
364}
365
366#[derive(Clone, Debug)]
367pub struct Descriptor {
368 pub handle: Handle,
369 pub permissions: AttributePermissions,
372 pub r#type: DescriptorType,
373}
374
375#[derive(Clone, Debug)]
378pub struct Characteristic {
379 pub handle: Handle,
380 pub uuid: Uuid,
381 pub properties: CharacteristicProperties,
382 pub permissions: AttributePermissions,
384 pub descriptors: Vec<Descriptor>,
385}
386
387impl Characteristic {
388 pub fn properties(&self) -> &CharacteristicProperties {
389 &self.properties
390 }
391
392 pub fn supports_property(&self, property: &CharacteristicProperty) -> bool {
393 self.properties.0.contains(property)
394 }
395
396 pub fn descriptors(&self) -> impl Iterator<Item = &Descriptor> {
397 self.descriptors.iter()
398 }
399
400 pub fn handles(&self) -> impl Iterator<Item = Handle> + '_ {
401 std::iter::once(self.handle).chain(self.descriptors.iter().map(|d| d.handle))
402 }
403}