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