• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #pragma once
16 #include <lib/fit/result.h>
17 
18 #include "pw_bluetooth_sapphire/internal/host/att/att.h"
19 #include "pw_bluetooth_sapphire/internal/host/common/identifier.h"
20 #include "pw_bluetooth_sapphire/internal/host/common/uuid.h"
21 
22 namespace bt::gatt {
23 
24 // 16-bit Attribute Types defined by the GATT profile (Vol 3, Part G, 3.4).
25 namespace types {
26 
27 inline constexpr uint16_t kPrimaryService16 = 0x2800;
28 inline constexpr uint16_t kSecondaryService16 = 0x2801;
29 inline constexpr uint16_t kIncludeDeclaration16 = 0x2802;
30 inline constexpr uint16_t kCharacteristicDeclaration16 = 0x2803;
31 inline constexpr uint16_t kCharacteristicExtProperties16 = 0x2900;
32 inline constexpr uint16_t kCharacteristicUserDescription16 = 0x2901;
33 inline constexpr uint16_t kClientCharacteristicConfig16 = 0x2902;
34 inline constexpr uint16_t kServerCharacteristicConfig16 = 0x2903;
35 inline constexpr uint16_t kCharacteristicFormat16 = 0x2904;
36 inline constexpr uint16_t kCharacteristicAggregateFormat16 = 0x2905;
37 inline constexpr uint16_t kGenericAttributeService16 = 0x1801;
38 inline constexpr uint16_t kServiceChangedCharacteristic16 = 0x2a05;
39 inline constexpr uint16_t kServerSupportedFeaturesCharacteristic16 = 0x2b3a;
40 
41 inline constexpr UUID kPrimaryService(kPrimaryService16);
42 inline constexpr UUID kSecondaryService(kSecondaryService16);
43 inline constexpr UUID kIncludeDeclaration(kIncludeDeclaration16);
44 inline constexpr UUID kCharacteristicDeclaration(kCharacteristicDeclaration16);
45 inline constexpr UUID kCharacteristicExtProperties(
46     kCharacteristicExtProperties16);
47 inline constexpr UUID kCharacteristicUserDescription(
48     kCharacteristicUserDescription16);
49 inline constexpr UUID kClientCharacteristicConfig(
50     kClientCharacteristicConfig16);
51 inline constexpr UUID kServerCharacteristicConfig(
52     kServerCharacteristicConfig16);
53 inline constexpr UUID kCharacteristicFormat(kCharacteristicFormat16);
54 inline constexpr UUID kCharacteristicAggregateFormat(
55     kCharacteristicAggregateFormat16);
56 
57 // Defined Generic Attribute Profile Service (Vol 3, Part G, 7)
58 inline constexpr bt::UUID kGenericAttributeService(kGenericAttributeService16);
59 constexpr bt::UUID kServiceChangedCharacteristic(
60     kServiceChangedCharacteristic16);
61 constexpr UUID kServerSupportedFeaturesCharacteristic(
62     kServerSupportedFeaturesCharacteristic16);
63 
64 }  // namespace types
65 
66 // Represents the reliability mode during long and prepared write operations.
67 enum ReliableMode {
68   kDisabled = 0x01,
69   kEnabled = 0x02,
70 };
71 
72 // Possible values that can be used in a "Characteristic Properties" bitfield.
73 // (see Vol 3, Part G, 3.3.1.1)
74 enum Property : uint8_t {
75   kBroadcast = 0x01,
76   kRead = 0x02,
77   kWriteWithoutResponse = 0x04,
78   kWrite = 0x08,
79   kNotify = 0x10,
80   kIndicate = 0x20,
81   kAuthenticatedSignedWrites = 0x40,
82   kExtendedProperties = 0x80,
83 };
84 using Properties = uint8_t;
85 
86 // Values for "Characteristic Extended Properties" bitfield.
87 // (see Vol 3, Part G, 3.3.3.1)
88 enum ExtendedProperty : uint16_t {
89   kReliableWrite = 0x0001,
90   kWritableAuxiliaries = 0x0002,
91 };
92 using ExtendedProperties = uint16_t;
93 
94 // Values for the "Client Characteristic Configuration" descriptor.
95 inline constexpr uint16_t kCCCNotificationBit = 0x0001;
96 inline constexpr uint16_t kCCCIndicationBit = 0x0002;
97 
98 using PeerId = PeerId;
99 
100 // An identity for a Characteristic within a RemoteService
101 // Characteristic IDs are guaranteed to equal the Value Handle for the
102 // characteristic
103 struct CharacteristicHandle {
CharacteristicHandleCharacteristicHandle104   constexpr explicit CharacteristicHandle(att::Handle handle) : value(handle) {}
105   CharacteristicHandle() = delete;
106   CharacteristicHandle(const CharacteristicHandle& other) = default;
107 
108   CharacteristicHandle& operator=(const CharacteristicHandle& other) = default;
109 
110   inline bool operator<(const CharacteristicHandle& rhs) const {
111     return this->value < rhs.value;
112   }
113   inline bool operator==(const CharacteristicHandle& rhs) const {
114     return this->value == rhs.value;
115   }
116 
117   att::Handle value;
118 };
119 
120 // Descriptors are identified by their underlying ATT handle
121 struct DescriptorHandle {
DescriptorHandleDescriptorHandle122   DescriptorHandle(att::Handle handle) : value(handle) {}
123   DescriptorHandle() = delete;
124   DescriptorHandle(const DescriptorHandle& other) = default;
125 
126   DescriptorHandle& operator=(const DescriptorHandle& other) = default;
127 
128   inline bool operator<(const DescriptorHandle& rhs) const {
129     return this->value < rhs.value;
130   }
131   inline bool operator==(const DescriptorHandle& rhs) const {
132     return this->value == rhs.value;
133   }
134 
135   att::Handle value;
136 };
137 
138 // An identifier uniquely identifies a local GATT service, characteristic, or
139 // descriptor.
140 using IdType = uint64_t;
141 
142 // 0 is reserved as an invalid ID.
143 inline constexpr IdType kInvalidId = 0u;
144 
145 // Types representing GATT discovery results.
146 
147 enum class ServiceKind {
148   PRIMARY,
149   SECONDARY,
150 };
151 
152 struct ServiceData {
153   ServiceData() = default;
154   ServiceData(ServiceKind kind,
155               att::Handle start,
156               att::Handle end,
157               const UUID& type);
158 
159   ServiceKind kind;
160   att::Handle range_start;
161   att::Handle range_end;
162   UUID type;
163 
164   // NOTE: In C++20 this can be generated via `= default` assignment.
165   bool operator==(const ServiceData& other) const {
166     return kind == other.kind && range_start == other.range_start &&
167            range_end == other.range_end && type == other.type;
168   }
169 };
170 
171 // An immutable definition of a GATT Characteristic
172 struct CharacteristicData {
173   CharacteristicData() = delete;
174   CharacteristicData(Properties props,
175                      std::optional<ExtendedProperties> ext_props,
176                      att::Handle handle,
177                      att::Handle value_handle,
178                      const UUID& type);
179 
180   Properties properties;
181   std::optional<ExtendedProperties> extended_properties;
182   att::Handle handle;
183   att::Handle value_handle;
184   UUID type;
185 
186   // NOTE: In C++20 this can be generated via `= default` assignment.
187   bool operator==(const CharacteristicData& other) const {
188     return properties == other.properties &&
189            extended_properties == other.extended_properties &&
190            handle == other.handle && value_handle == other.value_handle &&
191            type == other.type;
192   }
193 };
194 
195 // An immutable definition of a GATT Descriptor
196 struct DescriptorData {
197   DescriptorData() = delete;
198   DescriptorData(att::Handle handle, const UUID& type);
199 
200   const att::Handle handle;
201   const UUID type;
202 
203   // NOTE: In C++20 this can be generated via `= default` assignment.
204   bool operator==(const DescriptorData& other) const {
205     return handle == other.handle && type == other.type;
206   }
207 };
208 
209 // Delegates for ATT read/write operations
210 using ReadResponder = fit::callback<void(fit::result<att::ErrorCode> status,
211                                          const ByteBuffer& value)>;
212 using WriteResponder = fit::callback<void(fit::result<att::ErrorCode> status)>;
213 
214 // No-op implementations of asynchronous event handlers
NopReadHandler(PeerId,IdType,IdType,uint16_t,ReadResponder)215 inline void NopReadHandler(PeerId, IdType, IdType, uint16_t, ReadResponder) {}
NopWriteHandler(PeerId,IdType,IdType,uint16_t,const ByteBuffer &,WriteResponder)216 inline void NopWriteHandler(
217     PeerId, IdType, IdType, uint16_t, const ByteBuffer&, WriteResponder) {}
NopCCCallback(IdType,IdType,PeerId,bool,bool)218 inline void NopCCCallback(IdType, IdType, PeerId, bool, bool) {}
NopSendIndication(IdType,IdType,PeerId,BufferView)219 inline void NopSendIndication(IdType, IdType, PeerId, BufferView) {}
220 
221 // Characteristic Declaration attribute value (Core Spec v5.2, Vol 3,
222 // Sec 3.3.1).
223 template <att::UUIDType Format>
224 struct CharacteristicDeclarationAttributeValue {
225   Properties properties;
226   att::Handle value_handle;
227   att::AttributeType<Format> value_uuid;
228 } __attribute__((packed));
229 
230 // Service Changed Characteristic attribute value (Core Spec v5.2, Vol 3, Part
231 // G, Sec 7.1).
232 struct ServiceChangedCharacteristicValue {
233   att::Handle range_start_handle;
234   att::Handle range_end_handle;
235 } __attribute__((packed));
236 
237 }  // namespace bt::gatt
238 
239 // Specialization of std::hash for std::unordered_set, std::unordered_map, etc.
240 namespace std {
241 
242 template <>
243 struct hash<bt::gatt::CharacteristicHandle> {
244   size_t operator()(const bt::gatt::CharacteristicHandle& id) const {
245     return std::hash<uint16_t>()(id.value);
246   }
247 };
248 template <>
249 struct hash<bt::gatt::DescriptorHandle> {
250   size_t operator()(const bt::gatt::DescriptorHandle& id) const {
251     return std::hash<uint16_t>()(id.value);
252   }
253 };
254 
255 }  // namespace std
256