bt_gatt/
types.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use bt_common::{PeerId, Uuid};
6use thiserror::Error;
7
8/// Errors that can be returned from GATT procedures. These errors are sent from
9/// the peer. These are defined to match the Bluetooth Core Spec (v5.4, Vol 3,
10/// Part F, Sec 3.4.1.1)
11#[derive(Debug, Copy, Clone, PartialEq)]
12pub enum GattError {
13    InvalidHandle = 1,
14    ReadNotPermitted = 2,
15    WriteNotPermitted = 3,
16    InvalidPdu = 4,
17    InsufficientAuthentication = 5,
18    InvalidOffset = 7,
19    InsufficientAuthorization = 8,
20    InsufficientEncryptionKeySize = 12,
21    InvalidAttributeValueLength = 13,
22    UnlikelyError = 14,
23    InsufficientEncryption = 15,
24    InsufficientResources = 17,
25    ValueNotAllowed = 19,
26    ApplicationError80 = 128,
27    ApplicationError81 = 129,
28    ApplicationError82 = 130,
29    ApplicationError83 = 131,
30    ApplicationError84 = 132,
31    ApplicationError85 = 133,
32    ApplicationError86 = 134,
33    ApplicationError87 = 135,
34    ApplicationError88 = 136,
35    ApplicationError89 = 137,
36    ApplicationError8A = 138,
37    ApplicationError8B = 139,
38    ApplicationError8C = 140,
39    ApplicationError8D = 141,
40    ApplicationError8E = 142,
41    ApplicationError8F = 143,
42    ApplicationError90 = 144,
43    ApplicationError91 = 145,
44    ApplicationError92 = 146,
45    ApplicationError93 = 147,
46    ApplicationError94 = 148,
47    ApplicationError95 = 149,
48    ApplicationError96 = 150,
49    ApplicationError97 = 151,
50    ApplicationError98 = 152,
51    ApplicationError99 = 153,
52    ApplicationError9A = 154,
53    ApplicationError9B = 155,
54    ApplicationError9C = 156,
55    ApplicationError9D = 157,
56    ApplicationError9E = 158,
57    ApplicationError9F = 159,
58    WriteRequestRejected = 252,
59    CccDescriptorImproperlyConfigured = 253,
60    ProcedureAlreadyInProgress = 254,
61    OutOfRange = 255,
62    InvalidParameters = 257,
63    TooManyResults = 258,
64}
65
66impl std::fmt::Display for GattError {
67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        write!(f, "{:?}", self)
69    }
70}
71
72impl std::error::Error for GattError {}
73
74impl TryFrom<u32> for GattError {
75    type Error = Error;
76
77    fn try_from(value: u32) -> std::result::Result<Self, Self::Error> {
78        match value {
79            1 => Ok(Self::InvalidHandle),
80            2 => Ok(Self::ReadNotPermitted),
81            3 => Ok(Self::WriteNotPermitted),
82            4 => Ok(Self::InvalidPdu),
83            5 => Ok(Self::InsufficientAuthentication),
84            7 => Ok(Self::InvalidOffset),
85            8 => Ok(Self::InsufficientAuthorization),
86            12 => Ok(Self::InsufficientEncryptionKeySize),
87            13 => Ok(Self::InvalidAttributeValueLength),
88            14 => Ok(Self::UnlikelyError),
89            15 => Ok(Self::InsufficientEncryption),
90            17 => Ok(Self::InsufficientResources),
91            19 => Ok(Self::ValueNotAllowed),
92            128 => Ok(Self::ApplicationError80),
93            129 => Ok(Self::ApplicationError81),
94            130 => Ok(Self::ApplicationError82),
95            131 => Ok(Self::ApplicationError83),
96            132 => Ok(Self::ApplicationError84),
97            133 => Ok(Self::ApplicationError85),
98            134 => Ok(Self::ApplicationError86),
99            135 => Ok(Self::ApplicationError87),
100            136 => Ok(Self::ApplicationError88),
101            137 => Ok(Self::ApplicationError89),
102            138 => Ok(Self::ApplicationError8A),
103            139 => Ok(Self::ApplicationError8B),
104            140 => Ok(Self::ApplicationError8C),
105            141 => Ok(Self::ApplicationError8D),
106            142 => Ok(Self::ApplicationError8E),
107            143 => Ok(Self::ApplicationError8F),
108            144 => Ok(Self::ApplicationError90),
109            145 => Ok(Self::ApplicationError91),
110            146 => Ok(Self::ApplicationError92),
111            147 => Ok(Self::ApplicationError93),
112            148 => Ok(Self::ApplicationError94),
113            149 => Ok(Self::ApplicationError95),
114            150 => Ok(Self::ApplicationError96),
115            151 => Ok(Self::ApplicationError97),
116            152 => Ok(Self::ApplicationError98),
117            153 => Ok(Self::ApplicationError99),
118            154 => Ok(Self::ApplicationError9A),
119            155 => Ok(Self::ApplicationError9B),
120            156 => Ok(Self::ApplicationError9C),
121            157 => Ok(Self::ApplicationError9D),
122            158 => Ok(Self::ApplicationError9E),
123            159 => Ok(Self::ApplicationError9F),
124            252 => Ok(Self::WriteRequestRejected),
125            253 => Ok(Self::CccDescriptorImproperlyConfigured),
126            254 => Ok(Self::ProcedureAlreadyInProgress),
127            255 => Ok(Self::OutOfRange),
128            257 => Ok(Self::InvalidParameters),
129            258 => Ok(Self::TooManyResults),
130            x => Err(Error::Conversion(format!("Unknown GATT Error Value: {x}"))),
131        }
132    }
133}
134
135#[derive(Error, Debug)]
136#[non_exhaustive]
137pub enum Error {
138    #[error("peer {0} was not recognized")]
139    PeerNotRecognized(PeerId),
140    #[error("peer {0} was disconnected")]
141    PeerDisconnected(PeerId),
142    #[error("conversion error: {0}")]
143    Conversion(String),
144    #[error("scan failed: {0}")]
145    ScanFailed(String),
146    #[error("another error: {0}")]
147    Other(#[from] Box<dyn std::error::Error + Send + Sync>),
148    #[error("GATT error: {0}")]
149    Gatt(#[from] GattError),
150    #[error("definition error: duplicate handle(s) {0:?}")]
151    DuplicateHandle(Vec<Handle>),
152    #[error("service for {0:?} already published")]
153    AlreadyPublished(crate::server::ServiceId),
154    #[error("Encoding/decoding error: {0}")]
155    Encoding(#[from] bt_common::packet_encoding::Error),
156    #[error("Periodic Advertising error: {0}")]
157    PeriodicAdvertising(crate::periodic_advertising::Error),
158}
159
160impl Error {
161    pub fn other(e: impl std::error::Error + Send + Sync + 'static) -> Self {
162        Self::Other(Box::new(e))
163    }
164}
165
166impl From<String> for Error {
167    fn from(value: String) -> Self {
168        Self::Other(Box::<dyn std::error::Error + Send + Sync>::from(value))
169    }
170}
171
172impl From<&str> for Error {
173    fn from(value: &str) -> Self {
174        String::from(value).into()
175    }
176}
177
178pub type Result<T> = core::result::Result<T, Error>;
179
180/// Handles are used as local-to-your-code identifiers for Characteristics and
181/// Descriptors.
182///
183/// Their value should be treated as opaque by clients of PeerService,
184/// and are explicitly not guaranteed to be equal to a peer's attribute handles.
185/// Stack implementations should provide unique handles for each Characteristic
186/// and Descriptor within a PeerService for the client.  It is not necessary or
187/// expected for different clients of the same service to have the same handles.
188///
189/// For LocalService publishing, Service Definitions are required to have no
190/// duplicate Handles across their defined Characteristics and Descriptors.
191/// Characteristic and ServiceDefinition will check and return
192/// Error::DuplicateHandle.  Handles in ServiceDefinitions should not match the
193/// attribute handles in the local GATT server.  They are local to your code for
194/// use in correlating with ServiceEvents from peers.  Stacks must translate
195/// the actual GATT handles to the handles provided in the ServiceDefinition
196/// for these events.
197#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
198pub struct Handle(pub u64);
199
200/// Whether a service is marked as Primary or Secondary on the server.
201#[derive(Clone, Copy, Debug, Eq, PartialEq)]
202pub enum ServiceKind {
203    Primary,
204    Secondary,
205}
206
207#[derive(Clone, Copy, Debug, Eq, PartialEq)]
208pub enum WriteMode {
209    None,
210    Reliable,
211    WithoutResponse,
212}
213
214/// Characteristic Properties, including Extended Properties
215/// Determines how the Characteristic Value may be used.
216///
217/// Defined in Core Spec 5.3, Vol 3 Part G Sec 3.3.1.1 and 3.3.3.1
218#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
219pub enum CharacteristicProperty {
220    Broadcast = 0x01,
221    Read = 0x02,
222    WriteWithoutResponse = 0x04,
223    Write = 0x08,
224    Notify = 0x10,
225    Indicate = 0x20,
226    AuthenticatedSignedWrites = 0x40,
227    ReliableWrite = 0x100,
228    WritableAuxiliaries = 0x200,
229}
230
231impl std::ops::BitOr for CharacteristicProperty {
232    type Output = CharacteristicProperties;
233
234    fn bitor(self, rhs: Self) -> Self::Output {
235        CharacteristicProperties(vec![self, rhs])
236    }
237}
238
239#[derive(Default, Debug, Clone)]
240pub struct CharacteristicProperties(pub Vec<CharacteristicProperty>);
241
242impl From<CharacteristicProperty> for CharacteristicProperties {
243    fn from(value: CharacteristicProperty) -> Self {
244        Self(vec![value])
245    }
246}
247
248impl FromIterator<CharacteristicProperty> for CharacteristicProperties {
249    fn from_iter<T: IntoIterator<Item = CharacteristicProperty>>(iter: T) -> Self {
250        Self(iter.into_iter().collect())
251    }
252}
253
254impl std::ops::BitOr<CharacteristicProperty> for CharacteristicProperties {
255    type Output = Self;
256
257    fn bitor(mut self, rhs: CharacteristicProperty) -> Self::Output {
258        self.0.push(rhs);
259        self
260    }
261}
262
263impl CharacteristicProperties {
264    pub fn is_disjoint(&self, other: &Self) -> bool {
265        for property in self.0.iter() {
266            if other.0.contains(&property) {
267                return false;
268            }
269        }
270        true
271    }
272
273    pub fn contains(&self, property: CharacteristicProperty) -> bool {
274        self.0.contains(&property)
275    }
276}
277
278#[derive(Debug, Clone, Copy, Default)]
279pub struct SecurityLevels {
280    /// Encryption is required / provided
281    pub encryption: bool,
282    /// Authentication is required / provided
283    pub authentication: bool,
284    /// Authorization is required / provided
285    pub authorization: bool,
286}
287
288impl SecurityLevels {
289    pub fn satisfied(&self, provided: SecurityLevels) -> bool {
290        (!self.encryption || provided.encryption)
291            && (!self.authentication || provided.authentication)
292            && (!self.authorization || provided.encryption)
293    }
294
295    pub const fn encryption_required() -> Self {
296        Self { encryption: true, authentication: false, authorization: false }
297    }
298}
299
300#[derive(Debug, Clone, Copy, Default)]
301pub struct AttributePermissions {
302    /// If None, then this cannot be read. Otherwise the SecurityLevels given
303    /// are required to read.
304    pub read: Option<SecurityLevels>,
305    /// If None, then this cannot be written. Otherwise the SecurityLevels given
306    /// are required to write.
307    pub write: Option<SecurityLevels>,
308    /// If None, then this cannot be updated. Otherwise the SecurityLevels given
309    /// are required to update.
310    pub update: Option<SecurityLevels>,
311}
312
313impl AttributePermissions {
314    pub fn with_levels(properties: &CharacteristicProperties, levels: &SecurityLevels) -> Self {
315        let notify_properties = CharacteristicProperty::Notify | CharacteristicProperty::Indicate;
316        Self {
317            read: properties.contains(CharacteristicProperty::Read).then_some(levels.clone()),
318            write: properties.contains(CharacteristicProperty::Write).then_some(levels.clone()),
319            update: (!properties.is_disjoint(&notify_properties)).then_some(levels.clone()),
320        }
321    }
322}
323
324/// The different types of well-known Descriptors are defined here and should be
325/// automatically read during service characteristic discovery by Stack
326/// Implementations and included. Other Descriptor attribute values can be read
327/// using [`PeerService::read_descriptor`].
328///
329/// Characteristic Extended Properties are included in the
330/// CharacteristicProperties of the Characteristic.
331/// This is a subset of the descriptors defined in the Core Specification (v5.4,
332/// Vol 3 Part G Sec 3.3.3).  Missing DescriptorTypes are handled internally
333/// and are added automatically, and are omitted from descriptor APIs.
334#[derive(Clone, Debug)]
335pub enum DescriptorType {
336    UserDescription(String),
337    ServerConfiguration {
338        broadcast: bool,
339    },
340    CharacteristicPresentation {
341        format: u8,
342        exponent: i8,
343        unit: u16,
344        name_space: u8,
345        description: u16,
346    },
347    Other {
348        uuid: Uuid,
349    },
350}
351
352impl From<&DescriptorType> for Uuid {
353    fn from(value: &DescriptorType) -> Self {
354        // Values from https://bitbucket.org/bluetooth-SIG/public/src/main/assigned_numbers/uuids/descriptors.yaml
355        match value {
356            DescriptorType::UserDescription(_) => Uuid::from_u16(0x2901),
357            DescriptorType::ServerConfiguration { .. } => Uuid::from_u16(0x2903),
358            DescriptorType::CharacteristicPresentation { .. } => Uuid::from_u16(0x2904),
359            DescriptorType::Other { uuid } => uuid.clone(),
360        }
361    }
362}
363
364#[derive(Clone, Debug)]
365pub struct Descriptor {
366    pub handle: Handle,
367    /// Permissions required needed to interact with this descriptor.  May not
368    /// be accurate on clients until the descriptor is interacted with.
369    pub permissions: AttributePermissions,
370    pub r#type: DescriptorType,
371}
372
373/// A Characteristic on a Service. Each Characteristic has a declaration, value,
374/// and zero or more descriptors.
375#[derive(Clone, Debug)]
376pub struct Characteristic {
377    pub handle: Handle,
378    pub uuid: Uuid,
379    pub properties: CharacteristicProperties,
380    /// Attribute Permissions that apply to the value
381    pub permissions: AttributePermissions,
382    pub descriptors: Vec<Descriptor>,
383}
384
385impl Characteristic {
386    pub fn properties(&self) -> &CharacteristicProperties {
387        &self.properties
388    }
389
390    pub fn supports_property(&self, property: &CharacteristicProperty) -> bool {
391        self.properties.0.contains(property)
392    }
393
394    pub fn descriptors(&self) -> impl Iterator<Item = &Descriptor> {
395        self.descriptors.iter()
396    }
397
398    pub fn handles(&self) -> impl Iterator<Item = Handle> + '_ {
399        std::iter::once(self.handle).chain(self.descriptors.iter().map(|d| d.handle))
400    }
401}