Skip to main content

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    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/// Handles are used as local-to-your-code identifiers for Characteristics and
183/// Descriptors.
184///
185/// Their value should be treated as opaque by clients of PeerService,
186/// and are explicitly not guaranteed to be equal to a peer's attribute handles.
187/// Stack implementations should provide unique handles for each Characteristic
188/// and Descriptor within a PeerService for the client.  It is not necessary or
189/// expected for different clients of the same service to have the same handles.
190///
191/// For LocalService publishing, Service Definitions are required to have no
192/// duplicate Handles across their defined Characteristics and Descriptors.
193/// Characteristic and ServiceDefinition will check and return
194/// Error::DuplicateHandle.  Handles in ServiceDefinitions should not match the
195/// attribute handles in the local GATT server.  They are local to your code for
196/// use in correlating with ServiceEvents from peers.  Stacks must translate
197/// the actual GATT handles to the handles provided in the ServiceDefinition
198/// for these events.
199#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
200pub struct Handle(pub u64);
201
202/// Whether a service is marked as Primary or Secondary on the server.
203#[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/// Characteristic Properties, including Extended Properties
217/// Determines how the Characteristic Value may be used.
218///
219/// Defined in Core Spec 5.3, Vol 3 Part G Sec 3.3.1.1 and 3.3.3.1
220#[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    /// Encryption is required / provided
283    pub encryption: bool,
284    /// Authentication is required / provided
285    pub authentication: bool,
286    /// Authorization is required / provided
287    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    /// If None, then this cannot be read. Otherwise the SecurityLevels given
305    /// are required to read.
306    pub read: Option<SecurityLevels>,
307    /// If None, then this cannot be written. Otherwise the SecurityLevels given
308    /// are required to write.
309    pub write: Option<SecurityLevels>,
310    /// If None, then this cannot be updated. Otherwise the SecurityLevels given
311    /// are required to update.
312    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(&notify_properties)).then_some(levels.clone()),
322        }
323    }
324}
325
326/// The different types of well-known Descriptors are defined here and should be
327/// automatically read during service characteristic discovery by Stack
328/// Implementations and included. Other Descriptor attribute values can be read
329/// using [`PeerService::read_descriptor`].
330///
331/// Characteristic Extended Properties are included in the
332/// CharacteristicProperties of the Characteristic.
333/// This is a subset of the descriptors defined in the Core Specification (v5.4,
334/// Vol 3 Part G Sec 3.3.3).  Missing DescriptorTypes are handled internally
335/// and are added automatically, and are omitted from descriptor APIs.
336#[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        // Values from https://bitbucket.org/bluetooth-SIG/public/src/main/assigned_numbers/uuids/descriptors.yaml
357        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    /// Permissions required needed to interact with this descriptor.  May not
370    /// be accurate on clients until the descriptor is interacted with.
371    pub permissions: AttributePermissions,
372    pub r#type: DescriptorType,
373}
374
375/// A Characteristic on a Service. Each Characteristic has a declaration, value,
376/// and zero or more descriptors.
377#[derive(Clone, Debug)]
378pub struct Characteristic {
379    pub handle: Handle,
380    pub uuid: Uuid,
381    pub properties: CharacteristicProperties,
382    /// Attribute Permissions that apply to the value
383    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}