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