1 /*
2 * Copyright (C) 2014 BlueKitchen GmbH
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holders nor the names of
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * 4. Any redistribution, use, or modification is done solely for
17 * personal benefit and not for any commercial purpose or for
18 * monetary gain.
19 *
20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * Please inquire about commercial licensing options at
34 * [email protected]
35 *
36 */
37
38 #define BTSTACK_FILE__ "gatt_client.c"
39
40 #include <stdint.h>
41 #include <string.h>
42 #include <stddef.h>
43
44 #include "btstack_config.h"
45
46 #include "ble/att_dispatch.h"
47 #include "ble/att_db.h"
48 #include "ble/gatt_client.h"
49 #include "ble/le_device_db.h"
50 #include "ble/sm.h"
51 #include "bluetooth_psm.h"
52 #include "btstack_debug.h"
53 #include "btstack_event.h"
54 #include "btstack_memory.h"
55 #include "btstack_run_loop.h"
56 #include "btstack_util.h"
57 #include "hci.h"
58 #include "hci_dump.h"
59 #include "hci_event_builder.h"
60 #include "l2cap.h"
61 #include "classic/sdp_client.h"
62 #include "bluetooth_gatt.h"
63 #include "bluetooth_sdp.h"
64 #include "classic/sdp_util.h"
65
66 #if defined(ENABLE_GATT_OVER_EATT) && !defined(ENABLE_L2CAP_ENHANCED_CREDIT_BASED_FLOW_CONTROL_MODE)
67 #error "GATT Over EATT requires support for L2CAP Enhanced CoC. Please enable ENABLE_L2CAP_ENHANCED_CREDIT_BASED_FLOW_CONTROL_MODE"
68 #endif
69
70 // L2CAP Test Spec p35 defines a minimum of 100 ms, but PTS might indicate an error if we sent after 100 ms
71 #define GATT_CLIENT_COLLISION_BACKOFF_MS 150
72
73 static btstack_linked_list_t gatt_client_connections;
74 static btstack_linked_list_t gatt_client_value_listeners;
75 static btstack_linked_list_t gatt_client_service_value_listeners;
76 #ifdef ENABLE_GATT_CLIENT_SERVICE_CHANGED
77 static btstack_linked_list_t gatt_client_service_changed_handler;
78 #endif
79 static btstack_packet_callback_registration_t hci_event_callback_registration;
80 static btstack_packet_callback_registration_t sm_event_callback_registration;
81 static btstack_context_callback_registration_t gatt_client_deferred_event_emit;
82
83 // GATT Client Configuration
84 static bool gatt_client_mtu_exchange_enabled;
85 static gap_security_level_t gatt_client_required_security_level;
86
87 static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size);
88 static void gatt_client_event_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
89 static void gatt_client_report_error_if_pending(gatt_client_t *gatt_client, uint8_t att_error_code);
90
91 #ifdef ENABLE_LE_SIGNED_WRITE
92 static void att_signed_write_handle_cmac_result(uint8_t hash[8]);
93 #endif
94
95 #ifdef ENABLE_GATT_OVER_CLASSIC
96 static gatt_client_t * gatt_client_get_context_for_l2cap_cid(uint16_t l2cap_cid);
97 static void gatt_client_classic_handle_connected(gatt_client_t * gatt_client, uint8_t status);
98 static void gatt_client_classic_handle_disconnected(gatt_client_t * gatt_client);
99 static void gatt_client_classic_retry(btstack_timer_source_t * ts);
100 #endif
101
102 #ifdef ENABLE_GATT_OVER_EATT
103 static bool gatt_client_eatt_enabled;
104 static bool gatt_client_le_enhanced_handle_can_send_query(gatt_client_t * gatt_client);
105 static void gatt_client_le_enhanced_retry(btstack_timer_source_t * ts);
106 #endif
107
gatt_client_init(void)108 void gatt_client_init(void){
109 gatt_client_connections = NULL;
110 gatt_client_value_listeners = NULL;
111 gatt_client_service_value_listeners = NULL;
112 #ifdef ENABLE_GATT_CLIENT_SERVICE_CHANGED
113 gatt_client_service_changed_handler = NULL;
114 #endif
115 // default configuration
116 gatt_client_mtu_exchange_enabled = true;
117 gatt_client_required_security_level = LEVEL_0;
118
119 // register for HCI Events
120 hci_event_callback_registration.callback = &gatt_client_event_packet_handler;
121 hci_add_event_handler(&hci_event_callback_registration);
122
123 // register for SM Events
124 sm_event_callback_registration.callback = &gatt_client_event_packet_handler;
125 sm_add_event_handler(&sm_event_callback_registration);
126
127 // and ATT Client PDUs
128 att_dispatch_register_client(gatt_client_att_packet_handler);
129
130 #ifdef ENABLE_GATT_OVER_EATT
131 gatt_client_eatt_enabled = true;
132 #endif
133 }
134
gatt_client_set_required_security_level(gap_security_level_t level)135 void gatt_client_set_required_security_level(gap_security_level_t level){
136 gatt_client_required_security_level = level;
137 }
138
gatt_client_for_timer(btstack_timer_source_t * ts)139 static gatt_client_t * gatt_client_for_timer(btstack_timer_source_t * ts){
140 btstack_linked_list_iterator_t it;
141 btstack_linked_list_iterator_init(&it, &gatt_client_connections);
142 while (btstack_linked_list_iterator_has_next(&it)){
143 gatt_client_t * gatt_client = (gatt_client_t *) btstack_linked_list_iterator_next(&it);
144 if (&gatt_client->gc_timeout == ts) {
145 return gatt_client;
146 }
147 }
148 return NULL;
149 }
150
gatt_client_timeout_handler(btstack_timer_source_t * timer)151 static void gatt_client_timeout_handler(btstack_timer_source_t * timer){
152 gatt_client_t * gatt_client = gatt_client_for_timer(timer);
153 if (gatt_client == NULL) return;
154 log_info("GATT client timeout handle, handle 0x%02x", gatt_client->con_handle);
155 gatt_client_report_error_if_pending(gatt_client, ATT_ERROR_TIMEOUT);
156 }
157
gatt_client_timeout_start(gatt_client_t * gatt_client)158 static void gatt_client_timeout_start(gatt_client_t * gatt_client){
159 log_debug("GATT client timeout start, handle 0x%02x", gatt_client->con_handle);
160 btstack_run_loop_remove_timer(&gatt_client->gc_timeout);
161 btstack_run_loop_set_timer_handler(&gatt_client->gc_timeout, gatt_client_timeout_handler);
162 btstack_run_loop_set_timer(&gatt_client->gc_timeout, 30000); // 30 seconds sm timeout
163 btstack_run_loop_add_timer(&gatt_client->gc_timeout);
164 }
165
gatt_client_timeout_stop(gatt_client_t * gatt_client)166 static void gatt_client_timeout_stop(gatt_client_t * gatt_client){
167 log_debug("GATT client timeout stop, handle 0x%02x", gatt_client->con_handle);
168 btstack_run_loop_remove_timer(&gatt_client->gc_timeout);
169 }
170
gatt_client_le_security_level_for_connection(hci_con_handle_t con_handle)171 static gap_security_level_t gatt_client_le_security_level_for_connection(hci_con_handle_t con_handle){
172 uint8_t encryption_key_size = gap_encryption_key_size(con_handle);
173 if (encryption_key_size == 0) return LEVEL_0;
174
175 bool authenticated = gap_authenticated(con_handle);
176 if (!authenticated) return LEVEL_2;
177
178 return encryption_key_size == 16 ? LEVEL_4 : LEVEL_3;
179 }
180
gatt_client_get_context_for_handle(uint16_t handle)181 static gatt_client_t * gatt_client_get_context_for_handle(uint16_t handle){
182 btstack_linked_item_t *it;
183 for (it = (btstack_linked_item_t *) gatt_client_connections; it != NULL; it = it->next){
184 gatt_client_t * gatt_client = (gatt_client_t *) it;
185 if (gatt_client->con_handle == handle){
186 return gatt_client;
187 }
188 }
189 return NULL;
190 }
191
192
193 // @return gatt_client context
194 // returns existing one, or tries to setup new one
gatt_client_provide_context_for_handle(hci_con_handle_t con_handle,gatt_client_t ** out_gatt_client)195 static uint8_t gatt_client_provide_context_for_handle(hci_con_handle_t con_handle, gatt_client_t ** out_gatt_client){
196 gatt_client_t * gatt_client = gatt_client_get_context_for_handle(con_handle);
197
198 if (gatt_client != NULL){
199 *out_gatt_client = gatt_client;
200 return ERROR_CODE_SUCCESS;
201 }
202
203 // bail if no such hci connection
204 hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
205 if (hci_connection == NULL){
206 log_error("No connection for handle 0x%04x", con_handle);
207 *out_gatt_client = NULL;
208 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
209 }
210
211 gatt_client = btstack_memory_gatt_client_get();
212 if (gatt_client == NULL){
213 *out_gatt_client = NULL;
214 return ERROR_CODE_MEMORY_CAPACITY_EXCEEDED;
215 }
216 // init state
217 gatt_client->bearer_type = ATT_BEARER_UNENHANCED_LE;
218 gatt_client->con_handle = con_handle;
219 gatt_client->mtu = ATT_DEFAULT_MTU;
220 gatt_client->security_level = gatt_client_le_security_level_for_connection(con_handle);
221 if (gatt_client_mtu_exchange_enabled){
222 gatt_client->mtu_state = SEND_MTU_EXCHANGE;
223 } else {
224 gatt_client->mtu_state = MTU_AUTO_EXCHANGE_DISABLED;
225 }
226 gatt_client->state = P_READY;
227 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_DISCOVER_W2_SEND;
228 #ifdef ENABLE_GATT_OVER_EATT
229 gatt_client->eatt_state = GATT_CLIENT_EATT_IDLE;
230 #endif
231 btstack_linked_list_add(&gatt_client_connections, (btstack_linked_item_t*)gatt_client);
232
233 // get unenhanced att bearer state
234 if (hci_connection->att_connection.mtu_exchanged){
235 gatt_client->mtu = hci_connection->att_connection.mtu;
236 gatt_client->mtu_state = MTU_EXCHANGED;
237 }
238 *out_gatt_client = gatt_client;
239 return ERROR_CODE_SUCCESS;
240 }
241
is_ready(gatt_client_t * gatt_client)242 static bool is_ready(gatt_client_t * gatt_client){
243 return gatt_client->state == P_READY;
244 }
245
gatt_client_provide_context_for_request(hci_con_handle_t con_handle,gatt_client_t ** out_gatt_client)246 static uint8_t gatt_client_provide_context_for_request(hci_con_handle_t con_handle, gatt_client_t ** out_gatt_client){
247 gatt_client_t * gatt_client = NULL;
248 uint8_t status = gatt_client_provide_context_for_handle(con_handle, &gatt_client);
249 if (status != ERROR_CODE_SUCCESS){
250 return status;
251 }
252
253 #ifdef ENABLE_GATT_OVER_EATT
254 if ((gatt_client->eatt_state == GATT_CLIENT_EATT_READY) && gatt_client_eatt_enabled){
255 btstack_linked_list_iterator_t it;
256 gatt_client_t * eatt_client = NULL;
257 // find free eatt client
258 btstack_linked_list_iterator_init(&it, &gatt_client->eatt_clients);
259 while (btstack_linked_list_iterator_has_next(&it)){
260 gatt_client_t * client = (gatt_client_t *) btstack_linked_list_iterator_next(&it);
261 if (client->state == P_READY){
262 eatt_client = client;
263 break;
264 }
265 }
266 if (eatt_client == NULL){
267 return ERROR_CODE_COMMAND_DISALLOWED;
268 }
269 gatt_client = eatt_client;
270 }
271 #endif
272
273 if (is_ready(gatt_client) == false){
274 return GATT_CLIENT_IN_WRONG_STATE;
275 }
276
277 gatt_client_timeout_start(gatt_client);
278
279 *out_gatt_client = gatt_client;
280
281 return status;
282 }
283
gatt_client_is_ready(hci_con_handle_t con_handle)284 int gatt_client_is_ready(hci_con_handle_t con_handle){
285 gatt_client_t * gatt_client;
286 uint8_t status = gatt_client_provide_context_for_handle(con_handle, &gatt_client);
287 if (status != ERROR_CODE_SUCCESS){
288 return 0;
289 }
290 return is_ready(gatt_client) ? 1 : 0;
291 }
292
gatt_client_mtu_enable_auto_negotiation(uint8_t enabled)293 void gatt_client_mtu_enable_auto_negotiation(uint8_t enabled){
294 gatt_client_mtu_exchange_enabled = enabled != 0;
295 }
296
gatt_client_get_mtu(hci_con_handle_t con_handle,uint16_t * mtu)297 uint8_t gatt_client_get_mtu(hci_con_handle_t con_handle, uint16_t * mtu){
298 gatt_client_t * gatt_client;
299 uint8_t status = gatt_client_provide_context_for_handle(con_handle, &gatt_client);
300 if (status != ERROR_CODE_SUCCESS){
301 *mtu = 0;
302 return status;
303 }
304
305 if ((gatt_client->mtu_state == MTU_EXCHANGED) || (gatt_client->mtu_state == MTU_AUTO_EXCHANGE_DISABLED)){
306 *mtu = gatt_client->mtu;
307 return ERROR_CODE_SUCCESS;
308 }
309 *mtu = ATT_DEFAULT_MTU;
310 return GATT_CLIENT_IN_WRONG_STATE;
311 }
312
gatt_client_reserve_request_buffer(gatt_client_t * gatt_client)313 static uint8_t *gatt_client_reserve_request_buffer(gatt_client_t *gatt_client) {
314 switch (gatt_client->bearer_type){
315 #ifdef ENABLE_GATT_OVER_CLASSIC
316 case ATT_BEARER_UNENHANCED_CLASSIC:
317 #endif
318 case ATT_BEARER_UNENHANCED_LE:
319 l2cap_reserve_packet_buffer();
320 return l2cap_get_outgoing_buffer();
321 #ifdef ENABLE_GATT_OVER_EATT
322 case ATT_BEARER_ENHANCED_LE:
323 return gatt_client->eatt_storage_buffer;
324 #endif
325 default:
326 btstack_unreachable();
327 break;
328 }
329 return NULL;
330 }
331
332 // precondition: can_send_packet_now == TRUE
gatt_client_send(gatt_client_t * gatt_client,uint16_t len)333 static uint8_t gatt_client_send(gatt_client_t * gatt_client, uint16_t len){
334 switch (gatt_client->bearer_type){
335 case ATT_BEARER_UNENHANCED_LE:
336 return l2cap_send_prepared_connectionless(gatt_client->con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, len);
337 #ifdef ENABLE_GATT_OVER_CLASSIC
338 case ATT_BEARER_UNENHANCED_CLASSIC:
339 return l2cap_send_prepared(gatt_client->l2cap_cid, len);
340 #endif
341 #ifdef ENABLE_GATT_OVER_EATT
342 case ATT_BEARER_ENHANCED_LE:
343 return l2cap_send(gatt_client->l2cap_cid, gatt_client->eatt_storage_buffer, len);
344 #endif
345 default:
346 btstack_unreachable();
347 return ERROR_CODE_HARDWARE_FAILURE;
348 }
349 }
350
351 // precondition: can_send_packet_now == TRUE
att_confirmation(gatt_client_t * gatt_client)352 static uint8_t att_confirmation(gatt_client_t * gatt_client) {
353 uint8_t *request = gatt_client_reserve_request_buffer(gatt_client);
354
355 request[0] = ATT_HANDLE_VALUE_CONFIRMATION;
356
357 return gatt_client_send(gatt_client, 1);
358 }
359
360 // precondition: can_send_packet_now == TRUE
att_find_information_request(gatt_client_t * gatt_client,uint8_t request_type,uint16_t start_handle,uint16_t end_handle)361 static uint8_t att_find_information_request(gatt_client_t *gatt_client, uint8_t request_type, uint16_t start_handle,
362 uint16_t end_handle) {
363 uint8_t *request = gatt_client_reserve_request_buffer(gatt_client);
364
365 request[0] = request_type;
366 little_endian_store_16(request, 1, start_handle);
367 little_endian_store_16(request, 3, end_handle);
368
369 return gatt_client_send(gatt_client, 5);
370 }
371
372 // precondition: can_send_packet_now == TRUE
373 static uint8_t
att_find_by_type_value_request(gatt_client_t * gatt_client,uint8_t request_type,uint16_t attribute_group_type,uint16_t start_handle,uint16_t end_handle,uint8_t * value,uint16_t value_size)374 att_find_by_type_value_request(gatt_client_t *gatt_client, uint8_t request_type, uint16_t attribute_group_type,
375 uint16_t start_handle, uint16_t end_handle, uint8_t *value, uint16_t value_size) {
376 uint8_t *request = gatt_client_reserve_request_buffer(gatt_client);
377 request[0] = request_type;
378
379 little_endian_store_16(request, 1, start_handle);
380 little_endian_store_16(request, 3, end_handle);
381 little_endian_store_16(request, 5, attribute_group_type);
382 (void)memcpy(&request[7], value, value_size);
383
384 return gatt_client_send(gatt_client, 7u + value_size);
385 }
386
387 // precondition: can_send_packet_now == TRUE
388 static uint8_t
att_read_by_type_or_group_request_for_uuid16(gatt_client_t * gatt_client,uint8_t request_type,uint16_t uuid16,uint16_t start_handle,uint16_t end_handle)389 att_read_by_type_or_group_request_for_uuid16(gatt_client_t *gatt_client, uint8_t request_type, uint16_t uuid16,
390 uint16_t start_handle, uint16_t end_handle) {
391 uint8_t *request = gatt_client_reserve_request_buffer(gatt_client);
392
393 request[0] = request_type;
394 little_endian_store_16(request, 1, start_handle);
395 little_endian_store_16(request, 3, end_handle);
396 little_endian_store_16(request, 5, uuid16);
397
398 return gatt_client_send(gatt_client, 7);
399 }
400
401 // precondition: can_send_packet_now == TRUE
402 static uint8_t
att_read_by_type_or_group_request_for_uuid128(gatt_client_t * gatt_client,uint8_t request_type,const uint8_t * uuid128,uint16_t start_handle,uint16_t end_handle)403 att_read_by_type_or_group_request_for_uuid128(gatt_client_t *gatt_client, uint8_t request_type, const uint8_t *uuid128,
404 uint16_t start_handle, uint16_t end_handle) {
405 uint8_t *request = gatt_client_reserve_request_buffer(gatt_client);
406
407 request[0] = request_type;
408 little_endian_store_16(request, 1, start_handle);
409 little_endian_store_16(request, 3, end_handle);
410 reverse_128(uuid128, &request[5]);
411
412 return gatt_client_send(gatt_client, 21);
413 }
414
415 // precondition: can_send_packet_now == TRUE
att_read_request(gatt_client_t * gatt_client,uint8_t request_type,uint16_t attribute_handle)416 static uint8_t att_read_request(gatt_client_t *gatt_client, uint8_t request_type, uint16_t attribute_handle) {
417 uint8_t *request = gatt_client_reserve_request_buffer(gatt_client);
418
419 request[0] = request_type;
420 little_endian_store_16(request, 1, attribute_handle);
421
422 return gatt_client_send(gatt_client, 3);
423 }
424
425 // precondition: can_send_packet_now == TRUE
att_read_blob_request(gatt_client_t * gatt_client,uint8_t request_type,uint16_t attribute_handle,uint16_t value_offset)426 static uint8_t att_read_blob_request(gatt_client_t *gatt_client, uint8_t request_type, uint16_t attribute_handle,
427 uint16_t value_offset) {
428 uint8_t *request = gatt_client_reserve_request_buffer(gatt_client);
429
430 request[0] = request_type;
431 little_endian_store_16(request, 1, attribute_handle);
432 little_endian_store_16(request, 3, value_offset);
433
434 return gatt_client_send(gatt_client, 5);
435 }
436
437 static uint8_t
att_read_multiple_request_with_opcode(gatt_client_t * gatt_client,uint16_t num_value_handles,uint16_t * value_handles,uint8_t opcode)438 att_read_multiple_request_with_opcode(gatt_client_t *gatt_client, uint16_t num_value_handles, uint16_t *value_handles, uint8_t opcode) {
439 uint8_t *request = gatt_client_reserve_request_buffer(gatt_client);
440
441 request[0] = opcode;
442 uint16_t i;
443 uint16_t offset = 1;
444 for (i=0;i<num_value_handles;i++){
445 little_endian_store_16(request, offset, value_handles[i]);
446 offset += 2;
447 }
448
449 return gatt_client_send(gatt_client, offset);
450 }
451
452 static uint8_t
att_read_multiple_request(gatt_client_t * gatt_client,uint16_t num_value_handles,uint16_t * value_handles)453 att_read_multiple_request(gatt_client_t *gatt_client, uint16_t num_value_handles, uint16_t *value_handles) {
454 return att_read_multiple_request_with_opcode(gatt_client, num_value_handles, value_handles, ATT_READ_MULTIPLE_REQUEST);
455 }
456
457 #ifdef ENABLE_GATT_OVER_EATT
458 static uint8_t
att_read_multiple_variable_request(gatt_client_t * gatt_client,uint16_t num_value_handles,uint16_t * value_handles)459 att_read_multiple_variable_request(gatt_client_t *gatt_client, uint16_t num_value_handles, uint16_t *value_handles) {
460 return att_read_multiple_request_with_opcode(gatt_client, num_value_handles, value_handles, ATT_READ_MULTIPLE_VARIABLE_REQ);
461 }
462 #endif
463
464 #ifdef ENABLE_LE_SIGNED_WRITE
465 // precondition: can_send_packet_now == TRUE
att_signed_write_request(gatt_client_t * gatt_client,uint16_t request_type,uint16_t attribute_handle,uint16_t value_length,uint8_t * value,uint32_t sign_counter,uint8_t sgn[8])466 static uint8_t att_signed_write_request(gatt_client_t *gatt_client, uint16_t request_type, uint16_t attribute_handle,
467 uint16_t value_length, uint8_t *value, uint32_t sign_counter, uint8_t sgn[8]) {
468 uint8_t *request = gatt_client_reserve_request_buffer(gatt_client);
469
470 request[0] = request_type;
471 little_endian_store_16(request, 1, attribute_handle);
472 (void)memcpy(&request[3], value, value_length);
473 little_endian_store_32(request, 3 + value_length, sign_counter);
474 reverse_64(sgn, &request[3 + value_length + 4]);
475
476 return gatt_client_send(gatt_client, 3 + value_length + 12);
477 }
478 #endif
479
480 // precondition: can_send_packet_now == TRUE
481 static uint8_t
att_write_request(gatt_client_t * gatt_client,uint8_t request_type,uint16_t attribute_handle,uint16_t value_length,uint8_t * value)482 att_write_request(gatt_client_t *gatt_client, uint8_t request_type, uint16_t attribute_handle, uint16_t value_length,
483 uint8_t *value) {
484 uint8_t *request = gatt_client_reserve_request_buffer(gatt_client);
485
486 request[0] = request_type;
487 little_endian_store_16(request, 1, attribute_handle);
488 (void)memcpy(&request[3], value, value_length);
489
490 return gatt_client_send(gatt_client, 3u + value_length);
491 }
492
493 // precondition: can_send_packet_now == TRUE
att_execute_write_request(gatt_client_t * gatt_client,uint8_t request_type,uint8_t execute_write)494 static uint8_t att_execute_write_request(gatt_client_t *gatt_client, uint8_t request_type, uint8_t execute_write) {
495 uint8_t *request = gatt_client_reserve_request_buffer(gatt_client);
496
497 request[0] = request_type;
498 request[1] = execute_write;
499
500 return gatt_client_send(gatt_client, 2);
501 }
502
503 // precondition: can_send_packet_now == TRUE
att_prepare_write_request(gatt_client_t * gatt_client,uint8_t request_type,uint16_t attribute_handle,uint16_t value_offset,uint16_t blob_length,uint8_t * value)504 static uint8_t att_prepare_write_request(gatt_client_t *gatt_client, uint8_t request_type, uint16_t attribute_handle,
505 uint16_t value_offset, uint16_t blob_length, uint8_t *value) {
506 uint8_t *request = gatt_client_reserve_request_buffer(gatt_client);
507
508 request[0] = request_type;
509 little_endian_store_16(request, 1, attribute_handle);
510 little_endian_store_16(request, 3, value_offset);
511 (void)memcpy(&request[5], &value[value_offset], blob_length);
512
513 return gatt_client_send(gatt_client, 5u + blob_length);
514 }
515
att_exchange_mtu_request(gatt_client_t * gatt_client)516 static uint8_t att_exchange_mtu_request(gatt_client_t *gatt_client) {
517 uint8_t *request = gatt_client_reserve_request_buffer(gatt_client);
518
519 request[0] = ATT_EXCHANGE_MTU_REQUEST;
520 uint16_t mtu = l2cap_max_le_mtu();
521 little_endian_store_16(request, 1, mtu);
522
523 return gatt_client_send(gatt_client, 3);
524 }
525
write_blob_length(gatt_client_t * gatt_client)526 static uint16_t write_blob_length(gatt_client_t * gatt_client){
527 uint16_t max_blob_length = gatt_client->mtu - 5u;
528 if (gatt_client->attribute_offset >= gatt_client->attribute_length) {
529 return 0;
530 }
531 uint16_t rest_length = gatt_client->attribute_length - gatt_client->attribute_offset;
532 if (max_blob_length > rest_length){
533 return rest_length;
534 }
535 return max_blob_length;
536 }
537
send_gatt_services_request(gatt_client_t * gatt_client)538 static void send_gatt_services_request(gatt_client_t *gatt_client){
539 att_read_by_type_or_group_request_for_uuid16(gatt_client, ATT_READ_BY_GROUP_TYPE_REQUEST,
540 gatt_client->uuid16, gatt_client->start_group_handle,
541 gatt_client->end_group_handle);
542 }
543
send_gatt_by_uuid_request(gatt_client_t * gatt_client,uint16_t attribute_group_type)544 static void send_gatt_by_uuid_request(gatt_client_t *gatt_client, uint16_t attribute_group_type){
545 if (gatt_client->uuid16 != 0u){
546 uint8_t uuid16[2];
547 little_endian_store_16(uuid16, 0, gatt_client->uuid16);
548 att_find_by_type_value_request(gatt_client, ATT_FIND_BY_TYPE_VALUE_REQUEST, attribute_group_type,
549 gatt_client->start_group_handle, gatt_client->end_group_handle, uuid16, 2);
550 return;
551 }
552 uint8_t uuid128[16];
553 reverse_128(gatt_client->uuid128, uuid128);
554 att_find_by_type_value_request(gatt_client, ATT_FIND_BY_TYPE_VALUE_REQUEST, attribute_group_type,
555 gatt_client->start_group_handle, gatt_client->end_group_handle, uuid128, 16);
556 }
557
send_gatt_services_by_uuid_request(gatt_client_t * gatt_client)558 static void send_gatt_services_by_uuid_request(gatt_client_t *gatt_client){
559 send_gatt_by_uuid_request(gatt_client, GATT_PRIMARY_SERVICE_UUID);
560 }
561
send_gatt_included_service_uuid_request(gatt_client_t * gatt_client)562 static void send_gatt_included_service_uuid_request(gatt_client_t *gatt_client){
563 att_read_request(gatt_client, ATT_READ_REQUEST, gatt_client->query_start_handle);
564 }
565
send_gatt_included_service_request(gatt_client_t * gatt_client)566 static void send_gatt_included_service_request(gatt_client_t *gatt_client){
567 att_read_by_type_or_group_request_for_uuid16(gatt_client, ATT_READ_BY_TYPE_REQUEST,
568 GATT_INCLUDE_SERVICE_UUID, gatt_client->start_group_handle,
569 gatt_client->end_group_handle);
570 }
571
send_gatt_characteristic_request(gatt_client_t * gatt_client)572 static void send_gatt_characteristic_request(gatt_client_t *gatt_client){
573 att_read_by_type_or_group_request_for_uuid16(gatt_client, ATT_READ_BY_TYPE_REQUEST,
574 GATT_CHARACTERISTICS_UUID, gatt_client->start_group_handle,
575 gatt_client->end_group_handle);
576 }
577
send_gatt_characteristic_descriptor_request(gatt_client_t * gatt_client)578 static void send_gatt_characteristic_descriptor_request(gatt_client_t *gatt_client){
579 att_find_information_request(gatt_client, ATT_FIND_INFORMATION_REQUEST, gatt_client->start_group_handle,
580 gatt_client->end_group_handle);
581 }
582
send_gatt_read_characteristic_value_request(gatt_client_t * gatt_client)583 static void send_gatt_read_characteristic_value_request(gatt_client_t *gatt_client){
584 att_read_request(gatt_client, ATT_READ_REQUEST, gatt_client->attribute_handle);
585 }
586
send_gatt_read_by_type_request(gatt_client_t * gatt_client)587 static void send_gatt_read_by_type_request(gatt_client_t * gatt_client){
588 if (gatt_client->uuid16 != 0u){
589 att_read_by_type_or_group_request_for_uuid16(gatt_client, ATT_READ_BY_TYPE_REQUEST,
590 gatt_client->uuid16, gatt_client->start_group_handle,
591 gatt_client->end_group_handle);
592 } else {
593 att_read_by_type_or_group_request_for_uuid128(gatt_client, ATT_READ_BY_TYPE_REQUEST,
594 gatt_client->uuid128, gatt_client->start_group_handle,
595 gatt_client->end_group_handle);
596 }
597 }
598
send_gatt_read_blob_request(gatt_client_t * gatt_client)599 static void send_gatt_read_blob_request(gatt_client_t *gatt_client){
600 if (gatt_client->attribute_offset == 0){
601 att_read_request(gatt_client, ATT_READ_REQUEST, gatt_client->attribute_handle);
602 } else {
603 att_read_blob_request(gatt_client, ATT_READ_BLOB_REQUEST, gatt_client->attribute_handle,
604 gatt_client->attribute_offset);
605 }
606 }
607
send_gatt_read_multiple_request(gatt_client_t * gatt_client)608 static void send_gatt_read_multiple_request(gatt_client_t * gatt_client){
609 att_read_multiple_request(gatt_client, gatt_client->read_multiple_handle_count, gatt_client->read_multiple_handles);
610 }
611
612 #ifdef ENABLE_GATT_OVER_EATT
send_gatt_read_multiple_variable_request(gatt_client_t * gatt_client)613 static void send_gatt_read_multiple_variable_request(gatt_client_t * gatt_client){
614 att_read_multiple_variable_request(gatt_client, gatt_client->read_multiple_handle_count, gatt_client->read_multiple_handles);
615 }
616 #endif
617
send_gatt_write_attribute_value_request(gatt_client_t * gatt_client)618 static void send_gatt_write_attribute_value_request(gatt_client_t * gatt_client){
619 att_write_request(gatt_client, ATT_WRITE_REQUEST, gatt_client->attribute_handle, gatt_client->attribute_length,
620 gatt_client->attribute_value);
621 }
622
send_gatt_write_client_characteristic_configuration_request(gatt_client_t * gatt_client)623 static void send_gatt_write_client_characteristic_configuration_request(gatt_client_t * gatt_client){
624 att_write_request(gatt_client, ATT_WRITE_REQUEST, gatt_client->client_characteristic_configuration_handle, 2,
625 gatt_client->client_characteristic_configuration_value);
626 }
627
send_gatt_prepare_write_request(gatt_client_t * gatt_client)628 static void send_gatt_prepare_write_request(gatt_client_t * gatt_client){
629 att_prepare_write_request(gatt_client, ATT_PREPARE_WRITE_REQUEST, gatt_client->attribute_handle,
630 gatt_client->attribute_offset, write_blob_length(gatt_client),
631 gatt_client->attribute_value);
632 }
633
send_gatt_execute_write_request(gatt_client_t * gatt_client)634 static void send_gatt_execute_write_request(gatt_client_t * gatt_client){
635 att_execute_write_request(gatt_client, ATT_EXECUTE_WRITE_REQUEST, 1);
636 }
637
send_gatt_cancel_prepared_write_request(gatt_client_t * gatt_client)638 static void send_gatt_cancel_prepared_write_request(gatt_client_t * gatt_client){
639 att_execute_write_request(gatt_client, ATT_EXECUTE_WRITE_REQUEST, 0);
640 }
641
642 #ifndef ENABLE_GATT_FIND_INFORMATION_FOR_CCC_DISCOVERY
send_gatt_read_client_characteristic_configuration_request(gatt_client_t * gatt_client)643 static void send_gatt_read_client_characteristic_configuration_request(gatt_client_t * gatt_client){
644 att_read_by_type_or_group_request_for_uuid16(gatt_client, ATT_READ_BY_TYPE_REQUEST,
645 GATT_CLIENT_CHARACTERISTICS_CONFIGURATION,
646 gatt_client->start_group_handle, gatt_client->end_group_handle);
647 }
648 #endif
649
send_gatt_read_characteristic_descriptor_request(gatt_client_t * gatt_client)650 static void send_gatt_read_characteristic_descriptor_request(gatt_client_t * gatt_client){
651 att_read_request(gatt_client, ATT_READ_REQUEST, gatt_client->attribute_handle);
652 }
653
654 #ifdef ENABLE_LE_SIGNED_WRITE
send_gatt_signed_write_request(gatt_client_t * gatt_client,uint32_t sign_counter)655 static void send_gatt_signed_write_request(gatt_client_t * gatt_client, uint32_t sign_counter){
656 att_signed_write_request(gatt_client, ATT_SIGNED_WRITE_COMMAND, gatt_client->attribute_handle,
657 gatt_client->attribute_length, gatt_client->attribute_value, sign_counter,
658 gatt_client->cmac);
659 }
660 #endif
661
get_last_result_handle_from_service_list(uint8_t * packet,uint16_t size)662 static uint16_t get_last_result_handle_from_service_list(uint8_t * packet, uint16_t size){
663 if (size < 2) return 0xffff;
664 uint8_t attr_length = packet[1];
665 if ((2 + attr_length) > size) return 0xffff;
666 return little_endian_read_16(packet, size - attr_length + 2u);
667 }
668
get_last_result_handle_from_characteristics_list(uint8_t * packet,uint16_t size)669 static uint16_t get_last_result_handle_from_characteristics_list(uint8_t * packet, uint16_t size){
670 if (size < 2) return 0xffff;
671 uint8_t attr_length = packet[1];
672 if ((2 + attr_length) > size) return 0xffff;
673 return little_endian_read_16(packet, size - attr_length + 3u);
674 }
675
get_last_result_handle_from_included_services_list(uint8_t * packet,uint16_t size)676 static uint16_t get_last_result_handle_from_included_services_list(uint8_t * packet, uint16_t size){
677 if (size < 2) return 0xffff;
678 uint8_t attr_length = packet[1];
679 if ((2 + attr_length) > size) return 0xffff;
680 return little_endian_read_16(packet, size - attr_length);
681 }
682
683 #ifdef ENABLE_GATT_CLIENT_SERVICE_CHANGED
gatt_client_service_emit_event(gatt_client_t * gatt_client,uint8_t * event,uint16_t size)684 static void gatt_client_service_emit_event(gatt_client_t * gatt_client, uint8_t * event, uint16_t size){
685 btstack_linked_list_iterator_t it;
686 btstack_linked_list_iterator_init(&it, &gatt_client_service_changed_handler);
687 while (btstack_linked_list_iterator_has_next(&it)) {
688 btstack_packet_callback_registration_t *callback = (btstack_packet_callback_registration_t *) btstack_linked_list_iterator_next(&it);
689 (*callback->callback)(HCI_EVENT_PACKET, (uint16_t) gatt_client->con_handle, event, size);
690 }
691 }
692
693 static void
gatt_client_service_emit_database_hash(gatt_client_t * gatt_client,const uint8_t * value,uint16_t value_len)694 gatt_client_service_emit_database_hash(gatt_client_t *gatt_client, const uint8_t *value, uint16_t value_len) {
695 if (value_len == 16){
696 uint8_t event[21];
697 hci_event_builder_context_t context;
698 hci_event_builder_init(&context, event, sizeof(event), HCI_EVENT_GATTSERVICE_META, GATTSERVICE_SUBEVENT_GATT_DATABASE_HASH);
699 hci_event_builder_add_con_handle(&context, gatt_client->con_handle);
700 hci_event_builder_add_bytes(&context, value, 16);
701 gatt_client_service_emit_event(gatt_client, event, hci_event_builder_get_length(&context));
702 }
703 }
704
705 static void
gatt_client_service_emit_service_changed(gatt_client_t * gatt_client,const uint8_t * value,uint16_t value_len)706 gatt_client_service_emit_service_changed(gatt_client_t *gatt_client, const uint8_t *value, uint16_t value_len) {
707 if (value_len == 4){
708 uint8_t event[9];
709 hci_event_builder_context_t context;
710 hci_event_builder_init(&context, event, sizeof(event), HCI_EVENT_GATTSERVICE_META, GATTSERVICE_SUBEVENT_GATT_SERVICE_CHANGED);
711 hci_event_builder_add_con_handle(&context, gatt_client->con_handle);
712 hci_event_builder_add_bytes(&context, value, 4);
713 gatt_client_service_emit_event(gatt_client, event, hci_event_builder_get_length(&context));
714 }
715 }
716
gatt_client_service_packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)717 static void gatt_client_service_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
718 UNUSED(channel); // ok: handling own l2cap events
719 UNUSED(size); // ok: there is no channel
720
721 hci_con_handle_t con_handle;
722 gatt_client_t *gatt_client;
723 gatt_client_service_t service;
724 gatt_client_characteristic_t characteristic;
725 switch (packet_type) {
726 case HCI_EVENT_PACKET:
727 switch (hci_event_packet_get_type(packet)) {
728 case GATT_EVENT_SERVICE_QUERY_RESULT:
729 con_handle = gatt_event_service_query_result_get_handle(packet);
730 gatt_client = gatt_client_get_context_for_handle(con_handle);
731 btstack_assert(gatt_client != NULL);
732 btstack_assert(gatt_client->gatt_service_state == GATT_CLIENT_SERVICE_DISCOVER_W4_DONE);
733 gatt_event_service_query_result_get_service(packet, &service);
734 gatt_client->gatt_service_start_group_handle = service.start_group_handle;
735 gatt_client->gatt_service_end_group_handle = service.end_group_handle;
736 break;
737 case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
738 con_handle = gatt_event_characteristic_query_result_get_handle(packet);
739 gatt_client = gatt_client_get_context_for_handle(con_handle);
740 btstack_assert(gatt_client != NULL);
741 btstack_assert(gatt_client->gatt_service_state == GATT_CLIENT_SERVICE_DISCOVER_CHARACTERISTICS_W4_DONE);
742 gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic);
743 switch (characteristic.uuid16){
744 case ORG_BLUETOOTH_CHARACTERISTIC_GATT_SERVICE_CHANGED:
745 gatt_client->gatt_service_changed_value_handle = characteristic.value_handle;
746 gatt_client->gatt_service_changed_end_handle = characteristic.end_handle;
747 break;
748 case ORG_BLUETOOTH_CHARACTERISTIC_DATABASE_HASH:
749 gatt_client->gatt_service_database_hash_value_handle = characteristic.value_handle;
750 gatt_client->gatt_service_database_hash_end_handle = characteristic.end_handle;
751 break;
752 default:
753 break;
754 }
755 break;
756 case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT:
757 con_handle = gatt_event_characteristic_value_query_result_get_handle(packet);
758 gatt_client = gatt_client_get_context_for_handle(con_handle);
759 btstack_assert(gatt_client != NULL);
760 btstack_assert(gatt_client->gatt_service_state == GATT_CLIENT_SERVICE_DATABASE_HASH_READ_W4_DONE);
761 gatt_client_service_emit_database_hash(gatt_client,
762 gatt_event_characteristic_value_query_result_get_value(packet),
763 gatt_event_characteristic_value_query_result_get_value_length(packet));
764 break;
765 case GATT_EVENT_QUERY_COMPLETE:
766 con_handle = gatt_event_query_complete_get_handle(packet);
767 gatt_client = gatt_client_get_context_for_handle(con_handle);
768 btstack_assert(gatt_client != NULL);
769 switch (gatt_client->gatt_service_state) {
770 case GATT_CLIENT_SERVICE_DISCOVER_W4_DONE:
771 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_DISCOVER_CHARACTERISTICS_W2_SEND;
772 break;
773 case GATT_CLIENT_SERVICE_DISCOVER_CHARACTERISTICS_W4_DONE:
774 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_SERVICE_CHANGED_WRITE_CCCD_W2_SEND;
775 break;
776 case GATT_CLIENT_SERVICE_SERVICE_CHANGED_WRITE_CCCD_W4_DONE:
777 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_DATABASE_HASH_READ_W2_SEND;
778 break;
779 case GATT_CLIENT_SERVICE_DATABASE_HASH_READ_W4_DONE:
780 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_DATABASE_HASH_WRITE_CCCD_W2_SEND;
781 break;
782 case GATT_CLIENT_SERVICE_DATABASE_HASH_WRITE_CCCD_W4_DONE:
783 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_DONE;
784 break;
785 default:
786 btstack_unreachable();
787 break;
788 }
789 break;
790 default:
791 break;
792 }
793 break;
794 default:
795 break;
796 }
797 }
798 #endif
799
gatt_client_notify_can_send_query(gatt_client_t * gatt_client)800 static void gatt_client_notify_can_send_query(gatt_client_t * gatt_client){
801
802 #ifdef ENABLE_GATT_OVER_EATT
803 // if eatt is ready, notify all clients that can send a query
804 if (gatt_client->eatt_state == GATT_CLIENT_EATT_READY){
805 btstack_linked_list_iterator_t it;
806 btstack_linked_list_iterator_init(&it, &gatt_client->eatt_clients);
807 while (btstack_linked_list_iterator_has_next(&it)){
808 gatt_client_t * client = (gatt_client_t *) btstack_linked_list_iterator_next(&it);
809 if (client->state == P_READY){
810 // call callback
811 btstack_context_callback_registration_t * callback = (btstack_context_callback_registration_t *) btstack_linked_list_pop(&gatt_client->query_requests);
812 if (callback == NULL) {
813 return;
814 }
815 (*callback->callback)(callback->context);
816 }
817 }
818 return;
819 }
820 #endif
821
822 while (gatt_client->state == P_READY){
823 bool query_sent = false;
824 UNUSED(query_sent);
825
826 #ifdef ENABLE_GATT_CLIENT_SERVICE_CHANGED
827 uint8_t status = ERROR_CODE_SUCCESS;
828 gatt_client_service_t gatt_service;
829 gatt_client_characteristic_t characteristic;
830 switch (gatt_client->gatt_service_state){
831 case GATT_CLIENT_SERVICE_DISCOVER_W2_SEND:
832 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_DISCOVER_W4_DONE;
833 status = gatt_client_discover_primary_services_by_uuid16(&gatt_client_service_packet_handler,
834 gatt_client->con_handle,
835 ORG_BLUETOOTH_SERVICE_GENERIC_ATTRIBUTE);
836 query_sent = true;
837 break;
838 case GATT_CLIENT_SERVICE_DISCOVER_CHARACTERISTICS_W2_SEND:
839 if (gatt_client->gatt_service_start_group_handle != 0){
840 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_DISCOVER_CHARACTERISTICS_W4_DONE;
841 gatt_service.start_group_handle = gatt_client->gatt_service_start_group_handle;
842 gatt_service.end_group_handle = gatt_client->gatt_service_end_group_handle;
843 status = gatt_client_discover_characteristics_for_service(&gatt_client_service_packet_handler, gatt_client->con_handle, &gatt_service);
844 query_sent = true;
845 break;
846 }
847
848 /* fall through */
849
850 case GATT_CLIENT_SERVICE_SERVICE_CHANGED_WRITE_CCCD_W2_SEND:
851 if (gatt_client->gatt_service_changed_value_handle != 0){
852 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_SERVICE_CHANGED_WRITE_CCCD_W4_DONE;
853 characteristic.value_handle = gatt_client->gatt_service_changed_value_handle;
854 characteristic.end_handle = gatt_client->gatt_service_changed_end_handle;
855 // we assume good case. We cannot do much otherwise
856 characteristic.properties = ATT_PROPERTY_INDICATE;
857 status = gatt_client_write_client_characteristic_configuration(&gatt_client_service_packet_handler,
858 gatt_client->con_handle, &characteristic,
859 GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION);
860 query_sent = true;
861 break;
862 }
863
864 /* fall through */
865
866 case GATT_CLIENT_SERVICE_DATABASE_HASH_READ_W2_SEND:
867 if (gatt_client->gatt_service_database_hash_value_handle != 0){
868 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_DATABASE_HASH_READ_W4_DONE;
869 status = gatt_client_read_value_of_characteristics_by_uuid16(&gatt_client_service_packet_handler,
870 gatt_client->con_handle,
871 0x0001, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_DATABASE_HASH);
872 query_sent = true;
873 break;
874 }
875
876 /* fall through */
877
878 case GATT_CLIENT_SERVICE_DATABASE_HASH_WRITE_CCCD_W2_SEND:
879 if (gatt_client->gatt_service_database_hash_value_handle != 0) {
880 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_DATABASE_HASH_WRITE_CCCD_W4_DONE;
881 characteristic.value_handle = gatt_client->gatt_service_database_hash_value_handle;
882 characteristic.end_handle = gatt_client->gatt_service_database_hash_end_handle;
883 // we assume good case. We cannot do much otherwise
884 characteristic.properties = ATT_PROPERTY_INDICATE;
885 status = gatt_client_write_client_characteristic_configuration(&gatt_client_service_packet_handler,
886 gatt_client->con_handle,
887 &characteristic,
888 GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION);
889 query_sent = true;
890 break;
891 }
892
893 // DONE
894 gatt_client->gatt_service_state = GATT_CLIENT_SERVICE_DONE;
895 break;
896 default:
897 break;
898 }
899 btstack_assert(status == ERROR_CODE_SUCCESS);
900 UNUSED(status);
901 if (query_sent){
902 continue;
903 }
904 #endif
905
906 #ifdef ENABLE_GATT_OVER_EATT
907 query_sent = gatt_client_le_enhanced_handle_can_send_query(gatt_client);
908 if (query_sent){
909 continue;
910 }
911 #endif
912 btstack_context_callback_registration_t * callback = (btstack_context_callback_registration_t *) btstack_linked_list_pop(&gatt_client->query_requests);
913 if (callback == NULL) {
914 return;
915 }
916 (*callback->callback)(callback->context);
917 }
918 }
919
920 // test if notification/indication should be delivered to application (BLESA)
gatt_client_accept_server_message(gatt_client_t * gatt_client)921 static bool gatt_client_accept_server_message(gatt_client_t *gatt_client) {
922 // ignore messages until re-encryption is complete
923 if (gap_reconnect_security_setup_active(gatt_client->con_handle)) return false;
924
925 // after that ignore if bonded but not encrypted
926 return !gap_bonded(gatt_client->con_handle) || (gap_encryption_key_size(gatt_client->con_handle) > 0);
927 }
928
emit_event_new(btstack_packet_handler_t callback,uint8_t * packet,uint16_t size)929 static void emit_event_new(btstack_packet_handler_t callback, uint8_t * packet, uint16_t size){
930 if (!callback) return;
931 hci_dump_btstack_event(packet, size);
932 (*callback)(HCI_EVENT_PACKET, 0, packet, size);
933 }
934
emit_gatt_complete_event(gatt_client_t * gatt_client,uint8_t att_status)935 static void emit_gatt_complete_event(gatt_client_t * gatt_client, uint8_t att_status){
936 // @format H122
937 uint8_t packet[9];
938 hci_event_builder_context_t context;
939 hci_event_builder_init(&context, packet, sizeof(packet), GATT_EVENT_QUERY_COMPLETE, 0);
940 hci_event_builder_add_con_handle(&context, gatt_client->con_handle);
941 hci_event_builder_add_16(&context, gatt_client->service_id);
942 hci_event_builder_add_16(&context, gatt_client->connection_id);
943 hci_event_builder_add_08(&context, att_status);
944 emit_event_new(gatt_client->callback, packet, hci_event_builder_get_length(&context));
945 }
946
emit_gatt_service_query_result_event(gatt_client_t * gatt_client,uint16_t start_group_handle,uint16_t end_group_handle,const uint8_t * uuid128)947 static void emit_gatt_service_query_result_event(gatt_client_t * gatt_client, uint16_t start_group_handle, uint16_t end_group_handle, const uint8_t * uuid128){
948 // @format H22X
949 uint8_t packet[28];
950 hci_event_builder_context_t context;
951 hci_event_builder_init(&context, packet, sizeof(packet), GATT_EVENT_SERVICE_QUERY_RESULT, 0);
952 hci_event_builder_add_con_handle(&context, gatt_client->con_handle);
953 hci_event_builder_add_16(&context, gatt_client->service_id);
954 hci_event_builder_add_16(&context, gatt_client->connection_id);
955 hci_event_builder_add_16(&context, start_group_handle);
956 hci_event_builder_add_16(&context, end_group_handle);
957 hci_event_builder_add_128(&context, uuid128);
958 emit_event_new(gatt_client->callback, packet, hci_event_builder_get_length(&context));
959 }
960
emit_gatt_included_service_query_result_event(gatt_client_t * gatt_client,uint16_t include_handle,uint16_t start_group_handle,uint16_t end_group_handle,const uint8_t * uuid128)961 static void emit_gatt_included_service_query_result_event(gatt_client_t * gatt_client, uint16_t include_handle, uint16_t start_group_handle, uint16_t end_group_handle, const uint8_t * uuid128){
962 // @format H22X
963 uint8_t packet[30];
964 hci_event_builder_context_t context;
965 hci_event_builder_init(&context, packet, sizeof(packet), GATT_EVENT_INCLUDED_SERVICE_QUERY_RESULT, 0);
966 hci_event_builder_add_con_handle(&context, gatt_client->con_handle);
967 hci_event_builder_add_16(&context, gatt_client->service_id);
968 hci_event_builder_add_16(&context, gatt_client->connection_id);
969 hci_event_builder_add_16(&context, include_handle);
970 hci_event_builder_add_16(&context, start_group_handle);
971 hci_event_builder_add_16(&context, end_group_handle);
972 hci_event_builder_add_128(&context, uuid128);
973 emit_event_new(gatt_client->callback, packet, hci_event_builder_get_length(&context));
974 }
975
emit_gatt_characteristic_query_result_event(gatt_client_t * gatt_client,uint16_t start_handle,uint16_t value_handle,uint16_t end_handle,uint16_t properties,const uint8_t * uuid128)976 static void emit_gatt_characteristic_query_result_event(gatt_client_t * gatt_client, uint16_t start_handle, uint16_t value_handle, uint16_t end_handle,
977 uint16_t properties, const uint8_t * uuid128){
978 // @format H22Y
979 uint8_t packet[32];
980 hci_event_builder_context_t context;
981 hci_event_builder_init(&context, packet, sizeof(packet), GATT_EVENT_CHARACTERISTIC_QUERY_RESULT, 0);
982 hci_event_builder_add_con_handle(&context, gatt_client->con_handle);
983 hci_event_builder_add_16(&context, gatt_client->service_id);
984 hci_event_builder_add_16(&context, gatt_client->connection_id);
985 hci_event_builder_add_16(&context, start_handle);
986 hci_event_builder_add_16(&context, value_handle);
987 hci_event_builder_add_16(&context, end_handle);
988 hci_event_builder_add_16(&context, properties);
989 hci_event_builder_add_128(&context, uuid128);
990 emit_event_new(gatt_client->callback, packet, hci_event_builder_get_length(&context));
991 }
992
emit_gatt_all_characteristic_descriptors_result_event(gatt_client_t * gatt_client,uint16_t descriptor_handle,const uint8_t * uuid128)993 static void emit_gatt_all_characteristic_descriptors_result_event(
994 gatt_client_t * gatt_client, uint16_t descriptor_handle, const uint8_t * uuid128){
995 // @format H22Z
996 uint8_t packet[26];
997 hci_event_builder_context_t context;
998 hci_event_builder_init(&context, packet, sizeof(packet), GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT, 0);
999 hci_event_builder_add_con_handle(&context, gatt_client->con_handle);
1000 hci_event_builder_add_16(&context, gatt_client->service_id);
1001 hci_event_builder_add_16(&context, gatt_client->connection_id);
1002 hci_event_builder_add_16(&context, descriptor_handle);
1003 hci_event_builder_add_128(&context, uuid128);
1004 emit_event_new(gatt_client->callback, packet, hci_event_builder_get_length(&context));
1005 }
1006
emit_gatt_mtu_exchanged_result_event(gatt_client_t * gatt_client,uint16_t new_mtu)1007 static void emit_gatt_mtu_exchanged_result_event(gatt_client_t * gatt_client, uint16_t new_mtu){
1008 // @format H2
1009 uint8_t packet[6];
1010 packet[0] = GATT_EVENT_MTU;
1011 packet[1] = sizeof(packet) - 2u;
1012 little_endian_store_16(packet, 2, gatt_client->con_handle);
1013 little_endian_store_16(packet, 4, new_mtu);
1014 att_dispatch_client_mtu_exchanged(gatt_client->con_handle, new_mtu);
1015 emit_event_new(gatt_client->callback, packet, sizeof(packet));
1016 }
1017
1018 // helper
gatt_client_handle_transaction_complete(gatt_client_t * gatt_client,uint8_t att_status)1019 static void gatt_client_handle_transaction_complete(gatt_client_t *gatt_client, uint8_t att_status) {
1020 gatt_client->state = P_READY;
1021 gatt_client_timeout_stop(gatt_client);
1022 emit_gatt_complete_event(gatt_client, att_status);
1023 gatt_client_notify_can_send_query(gatt_client);
1024 }
1025
1026 // @return packet pointer
1027 // @note assume that value is part of an l2cap buffer - overwrite HCI + L2CAP packet headers + 4 pre_buffer bytes
1028 #define CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE 12
1029 static uint8_t *
setup_characteristic_value_packet(const gatt_client_t * gatt_client,uint8_t type,uint16_t attribute_handle,uint8_t * value,uint16_t length,uint16_t service_id,uint16_t connection_id)1030 setup_characteristic_value_packet(const gatt_client_t *gatt_client, uint8_t type, uint16_t attribute_handle,
1031 uint8_t *value, uint16_t length, uint16_t service_id, uint16_t connection_id) {
1032 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1033 // copy value into test packet for testing
1034 static uint8_t packet[1000];
1035 memcpy(&packet[CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE], value, length);
1036 #else
1037 // before the value inside the ATT PDU
1038 uint8_t * packet = value - CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE;
1039 #endif
1040 packet[0] = type;
1041 packet[1] = CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE - 2 + length;
1042 little_endian_store_16(packet, 2, gatt_client->con_handle);
1043 little_endian_store_16(packet, 4, service_id);
1044 little_endian_store_16(packet, 6, connection_id);
1045 little_endian_store_16(packet, 8, attribute_handle);
1046 little_endian_store_16(packet, 10, length);
1047 return packet;
1048 }
1049
1050 // @return packet pointer
1051 // @note assume that value is part of an l2cap buffer - overwrite HCI + L2CAP packet headers + 6 pre_buffer bytes
1052 #define LONG_CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE 14
1053
1054 // L2CAP Header (4) + ACL Header (4) => 8 bytes
1055 #if !defined(HCI_INCOMING_PRE_BUFFER_SIZE) || ((HCI_INCOMING_PRE_BUFFER_SIZE < LONG_CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE - 8))
1056 #error "Long Characteristic reads requires HCI_INCOMING_PRE_BUFFER_SIZE >= 6"
1057 #endif
1058
1059 static uint8_t *
setup_long_characteristic_value_packet(const gatt_client_t * gatt_client,uint8_t type,uint16_t attribute_handle,uint16_t offset,uint8_t * value,uint16_t length)1060 setup_long_characteristic_value_packet(const gatt_client_t *gatt_client, uint8_t type, uint16_t attribute_handle,
1061 uint16_t offset, uint8_t *value, uint16_t length) {
1062 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1063 // avoid using pre ATT headers.
1064 // copy value into test packet for testing
1065 static uint8_t packet[1000];
1066 memcpy(&packet[LONG_CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE], value, length);
1067 #else
1068 // before the value inside the ATT PDU
1069 uint8_t * packet = value - LONG_CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE;
1070 #endif
1071 packet[0] = type;
1072 packet[1] = LONG_CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE - 2 + length;
1073 little_endian_store_16(packet, 2, gatt_client->con_handle);
1074 little_endian_store_16(packet, 4, gatt_client->service_id);
1075 little_endian_store_16(packet, 6, gatt_client->connection_id);
1076 little_endian_store_16(packet, 8, attribute_handle);
1077 little_endian_store_16(packet, 10, offset);
1078 little_endian_store_16(packet, 12, length);
1079 return packet;
1080 }
1081
1082 #if (LONG_CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE > CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE)
1083 #define REPORT_PREBUFFER_HEADER LONG_CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE
1084 #else
1085 #define REPORT_PREBUFFER_HEADER CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE
1086 #endif
1087
1088 ///
report_gatt_services(gatt_client_t * gatt_client,uint8_t * packet,uint16_t size)1089 static void report_gatt_services(gatt_client_t * gatt_client, uint8_t * packet, uint16_t size){
1090 if (size < 2) return;
1091 uint8_t attr_length = packet[1];
1092 uint8_t uuid_length = attr_length - 4u;
1093
1094 int i;
1095 for (i = 2; (i+attr_length) <= size; i += attr_length){
1096 uint16_t start_group_handle = little_endian_read_16(packet,i);
1097 uint16_t end_group_handle = little_endian_read_16(packet,i+2);
1098 uint8_t uuid128[16];
1099 uint16_t uuid16 = 0;
1100
1101 if (uuid_length == 2u){
1102 uuid16 = little_endian_read_16(packet, i+4);
1103 uuid_add_bluetooth_prefix((uint8_t*) &uuid128, uuid16);
1104 } else if (uuid_length == 16u) {
1105 reverse_128(&packet[i+4], uuid128);
1106 } else {
1107 return;
1108 }
1109 emit_gatt_service_query_result_event(gatt_client, start_group_handle, end_group_handle, uuid128);
1110 }
1111 }
1112
report_gatt_characteristic_start_found(gatt_client_t * gatt_client,uint16_t start_handle,uint8_t properties,uint16_t value_handle,uint8_t * uuid,uint16_t uuid_length)1113 static void report_gatt_characteristic_start_found(gatt_client_t * gatt_client, uint16_t start_handle, uint8_t properties, uint16_t value_handle, uint8_t * uuid, uint16_t uuid_length){
1114 uint8_t uuid128[16];
1115 uint16_t uuid16 = 0;
1116 if (uuid_length == 2u){
1117 uuid16 = little_endian_read_16(uuid, 0);
1118 uuid_add_bluetooth_prefix((uint8_t*) uuid128, uuid16);
1119 } else if (uuid_length == 16u){
1120 reverse_128(uuid, uuid128);
1121 } else {
1122 return;
1123 }
1124
1125 if (gatt_client->filter_with_uuid && (memcmp(gatt_client->uuid128, uuid128, 16) != 0)) return;
1126
1127 gatt_client->characteristic_properties = properties;
1128 gatt_client->characteristic_start_handle = start_handle;
1129 gatt_client->attribute_handle = value_handle;
1130
1131 if (gatt_client->filter_with_uuid) return;
1132
1133 gatt_client->uuid16 = uuid16;
1134 (void)memcpy(gatt_client->uuid128, uuid128, 16);
1135 }
1136
report_gatt_characteristic_end_found(gatt_client_t * gatt_client,uint16_t end_handle)1137 static void report_gatt_characteristic_end_found(gatt_client_t * gatt_client, uint16_t end_handle){
1138 // TODO: stop searching if filter and uuid found
1139
1140 if (!gatt_client->characteristic_start_handle) return;
1141
1142 emit_gatt_characteristic_query_result_event(gatt_client, gatt_client->characteristic_start_handle, gatt_client->attribute_handle,
1143 end_handle, gatt_client->characteristic_properties, gatt_client->uuid128);
1144
1145 gatt_client->characteristic_start_handle = 0;
1146 }
1147
1148
report_gatt_characteristics(gatt_client_t * gatt_client,uint8_t * packet,uint16_t size)1149 static void report_gatt_characteristics(gatt_client_t * gatt_client, uint8_t * packet, uint16_t size){
1150 if (size < 2u) return;
1151 uint8_t attr_length = packet[1];
1152 if ((attr_length != 7u) && (attr_length != 21u)) return;
1153 uint8_t uuid_length = attr_length - 5u;
1154 int i;
1155 for (i = 2u; (i + attr_length) <= size; i += attr_length){
1156 uint16_t start_handle = little_endian_read_16(packet, i);
1157 uint8_t properties = packet[i+2];
1158 uint16_t value_handle = little_endian_read_16(packet, i+3);
1159 report_gatt_characteristic_end_found(gatt_client, start_handle - 1u);
1160 report_gatt_characteristic_start_found(gatt_client, start_handle, properties, value_handle, &packet[i + 5],
1161 uuid_length);
1162 }
1163 }
1164
report_gatt_included_service_uuid16(gatt_client_t * gatt_client,uint16_t include_handle,uint16_t uuid16)1165 static void report_gatt_included_service_uuid16(gatt_client_t * gatt_client, uint16_t include_handle, uint16_t uuid16){
1166 uint8_t normalized_uuid128[16];
1167 uuid_add_bluetooth_prefix(normalized_uuid128, uuid16);
1168 emit_gatt_included_service_query_result_event(gatt_client, include_handle, gatt_client->query_start_handle,
1169 gatt_client->query_end_handle, normalized_uuid128);
1170 }
1171
report_gatt_included_service_uuid128(gatt_client_t * gatt_client,uint16_t include_handle,const uint8_t * uuid128)1172 static void report_gatt_included_service_uuid128(gatt_client_t * gatt_client, uint16_t include_handle, const uint8_t * uuid128){
1173 emit_gatt_included_service_query_result_event(gatt_client, include_handle, gatt_client->query_start_handle,
1174 gatt_client->query_end_handle, uuid128);
1175 }
1176
report_gatt_characteristic_value_change(gatt_client_t * gatt_client,uint8_t event_type,uint16_t value_handle,uint8_t * value,int length)1177 static void report_gatt_characteristic_value_change(gatt_client_t *gatt_client, uint8_t event_type, uint16_t value_handle, uint8_t *value, int length) {
1178 uint8_t * packet;
1179
1180 // Single Characteristic listener, setup packet with service + connection id = 0
1181 packet = setup_characteristic_value_packet(gatt_client, event_type, value_handle, value, length, 0, 0);
1182 btstack_linked_list_iterator_t it;
1183 btstack_linked_list_iterator_init(&it, &gatt_client_value_listeners);
1184 while (btstack_linked_list_iterator_has_next(&it)) {
1185 gatt_client_notification_t *notification = (gatt_client_notification_t *) btstack_linked_list_iterator_next(&it);
1186 if ((notification->con_handle != GATT_CLIENT_ANY_CONNECTION) && (notification->con_handle != gatt_client->con_handle)) continue;
1187 if ((notification->attribute_handle != GATT_CLIENT_ANY_VALUE_HANDLE) && (notification->attribute_handle != value_handle)) continue;
1188
1189 (*notification->callback)(HCI_EVENT_PACKET, 0, packet, CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE + length);
1190 }
1191
1192 // Service characteristics
1193 btstack_linked_list_iterator_init(&it, &gatt_client_service_value_listeners);
1194 while (btstack_linked_list_iterator_has_next(&it)){
1195 const gatt_client_service_notification_t * notification = (gatt_client_service_notification_t*) btstack_linked_list_iterator_next(&it);
1196 if (notification->con_handle != gatt_client->con_handle) continue;
1197 if (notification->start_group_handle > value_handle) continue;
1198 if (notification->end_group_handle < value_handle) continue;
1199 // (re)setup value packet with service and connection id (to avoid patching event later)
1200 packet = setup_characteristic_value_packet(gatt_client, event_type, value_handle, value, length, notification->service_id, notification->connection_id);
1201 (*notification->callback)(HCI_EVENT_PACKET, 0, packet, CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE + length);
1202 }
1203 }
1204
1205 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
report_gatt_notification(gatt_client_t * gatt_client,uint16_t value_handle,uint8_t * value,int length)1206 static void report_gatt_notification(gatt_client_t *gatt_client, uint16_t value_handle, uint8_t *value, int length) {
1207 if (!gatt_client_accept_server_message(gatt_client)) return;
1208 report_gatt_characteristic_value_change(gatt_client, GATT_EVENT_NOTIFICATION, value_handle, value, length);
1209 }
1210
1211 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
report_gatt_indication(gatt_client_t * gatt_client,uint16_t value_handle,uint8_t * value,int length)1212 static void report_gatt_indication(gatt_client_t *gatt_client, uint16_t value_handle, uint8_t *value, int length) {
1213 if (!gatt_client_accept_server_message(gatt_client)) return;
1214 #ifdef ENABLE_GATT_CLIENT_SERVICE_CHANGED
1215 // Directly Handle GATT Service Changed and Database Hash indications
1216 if (value_handle == gatt_client->gatt_service_database_hash_value_handle){
1217 gatt_client_service_emit_database_hash(gatt_client, value, length);
1218 }
1219 if (value_handle == gatt_client->gatt_service_changed_value_handle){
1220 gatt_client_service_emit_service_changed(gatt_client, value, length);
1221 }
1222 #endif
1223 report_gatt_characteristic_value_change(gatt_client, GATT_EVENT_INDICATION, value_handle, value, length);
1224 }
1225
1226 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
report_gatt_characteristic_value(gatt_client_t * gatt_client,uint16_t attribute_handle,uint8_t * value,uint16_t length)1227 static void report_gatt_characteristic_value(gatt_client_t * gatt_client, uint16_t attribute_handle, uint8_t * value, uint16_t length){
1228 uint8_t * packet = setup_characteristic_value_packet(
1229 gatt_client, GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT, attribute_handle, value, length, gatt_client->service_id, gatt_client->connection_id);
1230 emit_event_new(gatt_client->callback, packet, CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE + length);
1231 }
1232
1233 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
report_gatt_long_characteristic_value_blob(gatt_client_t * gatt_client,uint16_t attribute_handle,uint8_t * blob,uint16_t blob_length,int value_offset)1234 static void report_gatt_long_characteristic_value_blob(gatt_client_t * gatt_client, uint16_t attribute_handle, uint8_t * blob, uint16_t blob_length, int value_offset){
1235 uint8_t * packet = setup_long_characteristic_value_packet(gatt_client,
1236 GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT,
1237 attribute_handle, value_offset,
1238 blob, blob_length);
1239 emit_event_new(gatt_client->callback, packet, blob_length + LONG_CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE);
1240 }
1241
report_gatt_characteristic_descriptor(gatt_client_t * gatt_client,uint16_t descriptor_handle,uint8_t * value,uint16_t value_length,uint16_t value_offset)1242 static void report_gatt_characteristic_descriptor(gatt_client_t * gatt_client, uint16_t descriptor_handle, uint8_t *value, uint16_t value_length, uint16_t value_offset){
1243 UNUSED(value_offset);
1244 uint8_t * packet = setup_characteristic_value_packet(gatt_client, GATT_EVENT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT,
1245 descriptor_handle, value,
1246 value_length, gatt_client->service_id, gatt_client->connection_id);
1247 emit_event_new(gatt_client->callback, packet, value_length + 8u);
1248 }
1249
report_gatt_long_characteristic_descriptor(gatt_client_t * gatt_client,uint16_t descriptor_handle,uint8_t * blob,uint16_t blob_length,uint16_t value_offset)1250 static void report_gatt_long_characteristic_descriptor(gatt_client_t * gatt_client, uint16_t descriptor_handle, uint8_t *blob, uint16_t blob_length, uint16_t value_offset){
1251 uint8_t * packet = setup_long_characteristic_value_packet(gatt_client,
1252 GATT_EVENT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT,
1253 descriptor_handle, value_offset,
1254 blob, blob_length);
1255 emit_event_new(gatt_client->callback, packet, blob_length + LONG_CHARACTERISTIC_VALUE_EVENT_HEADER_SIZE);
1256 }
1257
report_gatt_all_characteristic_descriptors(gatt_client_t * gatt_client,uint8_t * packet,uint16_t size,uint16_t pair_size)1258 static void report_gatt_all_characteristic_descriptors(gatt_client_t * gatt_client, uint8_t * packet, uint16_t size, uint16_t pair_size){
1259 int i;
1260 for (i = 0u; (i + pair_size) <= size; i += pair_size){
1261 uint16_t descriptor_handle = little_endian_read_16(packet,i);
1262 uint8_t uuid128[16];
1263 uint16_t uuid16 = 0;
1264 if (pair_size == 4u){
1265 uuid16 = little_endian_read_16(packet,i+2);
1266 uuid_add_bluetooth_prefix(uuid128, uuid16);
1267 } else {
1268 reverse_128(&packet[i+2], uuid128);
1269 }
1270 emit_gatt_all_characteristic_descriptors_result_event(gatt_client, descriptor_handle, uuid128);
1271 }
1272
1273 }
1274
is_query_done(gatt_client_t * gatt_client,uint16_t last_result_handle)1275 static bool is_query_done(gatt_client_t * gatt_client, uint16_t last_result_handle){
1276 return last_result_handle >= gatt_client->end_group_handle;
1277 }
1278
trigger_next_query(gatt_client_t * gatt_client,uint16_t last_result_handle,gatt_client_state_t next_query_state)1279 static void trigger_next_query(gatt_client_t * gatt_client, uint16_t last_result_handle, gatt_client_state_t next_query_state){
1280 if (is_query_done(gatt_client, last_result_handle)){
1281 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
1282 return;
1283 }
1284 // next
1285 gatt_client->start_group_handle = last_result_handle + 1u;
1286 gatt_client->state = next_query_state;
1287 }
1288
trigger_next_included_service_query(gatt_client_t * gatt_client,uint16_t last_result_handle)1289 static void trigger_next_included_service_query(gatt_client_t * gatt_client, uint16_t last_result_handle){
1290 trigger_next_query(gatt_client, last_result_handle, P_W2_SEND_INCLUDED_SERVICE_QUERY);
1291 }
1292
trigger_next_service_query(gatt_client_t * gatt_client,uint16_t last_result_handle)1293 static void trigger_next_service_query(gatt_client_t * gatt_client, uint16_t last_result_handle){
1294 trigger_next_query(gatt_client, last_result_handle, P_W2_SEND_SERVICE_QUERY);
1295 }
1296
trigger_next_service_by_uuid_query(gatt_client_t * gatt_client,uint16_t last_result_handle)1297 static void trigger_next_service_by_uuid_query(gatt_client_t * gatt_client, uint16_t last_result_handle){
1298 trigger_next_query(gatt_client, last_result_handle, P_W2_SEND_SERVICE_WITH_UUID_QUERY);
1299 }
1300
trigger_next_characteristic_query(gatt_client_t * gatt_client,uint16_t last_result_handle)1301 static void trigger_next_characteristic_query(gatt_client_t * gatt_client, uint16_t last_result_handle){
1302 if (is_query_done(gatt_client, last_result_handle)){
1303 // report last characteristic
1304 report_gatt_characteristic_end_found(gatt_client, gatt_client->end_group_handle);
1305 }
1306 trigger_next_query(gatt_client, last_result_handle, P_W2_SEND_ALL_CHARACTERISTICS_OF_SERVICE_QUERY);
1307 }
1308
trigger_next_characteristic_descriptor_query(gatt_client_t * gatt_client,uint16_t last_result_handle)1309 static void trigger_next_characteristic_descriptor_query(gatt_client_t * gatt_client, uint16_t last_result_handle){
1310 trigger_next_query(gatt_client, last_result_handle, P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY);
1311 }
1312
trigger_next_read_by_type_query(gatt_client_t * gatt_client,uint16_t last_result_handle)1313 static void trigger_next_read_by_type_query(gatt_client_t * gatt_client, uint16_t last_result_handle){
1314 trigger_next_query(gatt_client, last_result_handle, P_W2_SEND_READ_BY_TYPE_REQUEST);
1315 }
1316
trigger_next_prepare_write_query(gatt_client_t * gatt_client,gatt_client_state_t next_query_state,gatt_client_state_t done_state)1317 static void trigger_next_prepare_write_query(gatt_client_t * gatt_client, gatt_client_state_t next_query_state, gatt_client_state_t done_state){
1318 gatt_client->attribute_offset += write_blob_length(gatt_client);
1319 uint16_t next_blob_length = write_blob_length(gatt_client);
1320
1321 if (next_blob_length == 0u){
1322 gatt_client->state = done_state;
1323 return;
1324 }
1325 gatt_client->state = next_query_state;
1326 }
1327
trigger_next_blob_query(gatt_client_t * gatt_client,gatt_client_state_t next_query_state,uint16_t received_blob_length)1328 static void trigger_next_blob_query(gatt_client_t * gatt_client, gatt_client_state_t next_query_state, uint16_t received_blob_length){
1329
1330 uint16_t max_blob_length = gatt_client->mtu - 1u;
1331 if (received_blob_length < max_blob_length){
1332 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
1333 return;
1334 }
1335
1336 gatt_client->attribute_offset += received_blob_length;
1337 gatt_client->state = next_query_state;
1338 }
1339
gatt_client_listen_for_characteristic_value_updates(gatt_client_notification_t * notification,btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_characteristic_t * characteristic)1340 void gatt_client_listen_for_characteristic_value_updates(gatt_client_notification_t * notification, btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){
1341 notification->callback = callback;
1342 notification->con_handle = con_handle;
1343 if (characteristic == NULL){
1344 notification->attribute_handle = GATT_CLIENT_ANY_VALUE_HANDLE;
1345 } else {
1346 notification->attribute_handle = characteristic->value_handle;
1347 }
1348 btstack_linked_list_add(&gatt_client_value_listeners, (btstack_linked_item_t*) notification);
1349 }
1350
gatt_client_stop_listening_for_characteristic_value_updates(gatt_client_notification_t * notification)1351 void gatt_client_stop_listening_for_characteristic_value_updates(gatt_client_notification_t * notification){
1352 btstack_linked_list_remove(&gatt_client_value_listeners, (btstack_linked_item_t*) notification);
1353 }
1354
gatt_client_listen_for_service_characteristic_value_updates(gatt_client_service_notification_t * notification,btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_service_t * service,uint16_t service_id,uint16_t connection_id)1355 void gatt_client_listen_for_service_characteristic_value_updates(gatt_client_service_notification_t * notification,
1356 btstack_packet_handler_t callback,
1357 hci_con_handle_t con_handle,
1358 gatt_client_service_t * service,
1359 uint16_t service_id,
1360 uint16_t connection_id){
1361 notification->callback = callback;
1362 notification->con_handle = con_handle;
1363 notification->start_group_handle = service->start_group_handle;
1364 notification->end_group_handle = service->end_group_handle;
1365 notification->service_id = service_id;
1366 notification->connection_id = connection_id;
1367 btstack_linked_list_add(&gatt_client_service_value_listeners, (btstack_linked_item_t*) notification);
1368 }
1369
1370 /**
1371 * @brief Stop listening to characteristic value updates for registered service with
1372 * the gatt_client_listen_for_characteristic_value_updates function.
1373 * @param notification struct used in gatt_client_listen_for_characteristic_value_updates
1374 */
gatt_client_stop_listening_for_service_characteristic_value_updates(gatt_client_service_notification_t * notification)1375 void gatt_client_stop_listening_for_service_characteristic_value_updates(gatt_client_service_notification_t * notification){
1376 btstack_linked_list_remove(&gatt_client_service_value_listeners, (btstack_linked_item_t*) notification);
1377 }
1378
is_value_valid(gatt_client_t * gatt_client,uint8_t * packet,uint16_t size)1379 static bool is_value_valid(gatt_client_t *gatt_client, uint8_t *packet, uint16_t size){
1380 uint16_t attribute_handle = little_endian_read_16(packet, 1);
1381 uint16_t value_offset = little_endian_read_16(packet, 3);
1382
1383 if (gatt_client->attribute_handle != attribute_handle) return false;
1384 if (gatt_client->attribute_offset != value_offset) return false;
1385 return memcmp(&gatt_client->attribute_value[gatt_client->attribute_offset], &packet[5], size - 5u) == 0u;
1386 }
1387
1388 #ifdef ENABLE_LE_SIGNED_WRITE
gatt_client_run_for_client_start_signed_write(gatt_client_t * gatt_client)1389 static void gatt_client_run_for_client_start_signed_write(gatt_client_t *gatt_client) {
1390 sm_key_t csrk;
1391 le_device_db_local_csrk_get(gatt_client->le_device_index, csrk);
1392 uint32_t sign_counter = le_device_db_local_counter_get(gatt_client->le_device_index);
1393 gatt_client->state = P_W4_CMAC_RESULT;
1394 sm_cmac_signed_write_start(csrk, ATT_SIGNED_WRITE_COMMAND, gatt_client->attribute_handle, gatt_client->attribute_length, gatt_client->attribute_value, sign_counter, att_signed_write_handle_cmac_result);
1395 }
1396 #endif
1397
1398 // returns true if packet was sent
gatt_client_run_for_gatt_client(gatt_client_t * gatt_client)1399 static bool gatt_client_run_for_gatt_client(gatt_client_t * gatt_client){
1400
1401 // wait until re-encryption is complete
1402 if (gap_reconnect_security_setup_active(gatt_client->con_handle)) return false;
1403
1404 // wait until re-encryption is complete
1405 if (gatt_client->reencryption_active) return false;
1406
1407 // wait until pairing complete (either reactive authentication or due to required security level)
1408 if (gatt_client->wait_for_authentication_complete) return false;
1409
1410 bool client_request_pending = gatt_client->state != P_READY;
1411
1412 // verify security level for Mandatory Authentication over LE
1413 bool check_security;
1414 switch (gatt_client->bearer_type){
1415 case ATT_BEARER_UNENHANCED_LE:
1416 check_security = true;
1417 break;
1418 default:
1419 check_security = false;
1420 break;
1421 }
1422 if (client_request_pending && (gatt_client_required_security_level > gatt_client->security_level) && check_security){
1423 log_info("Trigger pairing, current security level %u, required %u\n", gatt_client->security_level, gatt_client_required_security_level);
1424 gatt_client->wait_for_authentication_complete = true;
1425 // set att error code for pairing failure based on required level
1426 switch (gatt_client_required_security_level){
1427 case LEVEL_4:
1428 case LEVEL_3:
1429 gatt_client->pending_error_code = ATT_ERROR_INSUFFICIENT_AUTHENTICATION;
1430 break;
1431 default:
1432 gatt_client->pending_error_code = ATT_ERROR_INSUFFICIENT_ENCRYPTION;
1433 break;
1434 }
1435 sm_request_pairing(gatt_client->con_handle);
1436 // sm probably just sent a pdu
1437 return true;
1438 }
1439
1440 switch (gatt_client->mtu_state) {
1441 case SEND_MTU_EXCHANGE:
1442 gatt_client->mtu_state = SENT_MTU_EXCHANGE;
1443 att_exchange_mtu_request(gatt_client);
1444 return true;
1445 case SENT_MTU_EXCHANGE:
1446 return false;
1447 default:
1448 break;
1449 }
1450
1451 if (gatt_client->send_confirmation){
1452 gatt_client->send_confirmation = false;
1453 att_confirmation(gatt_client);
1454 return true;
1455 }
1456
1457 // check MTU for writes
1458 switch (gatt_client->state){
1459 case P_W2_SEND_WRITE_CHARACTERISTIC_VALUE:
1460 case P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR:
1461 if (gatt_client->attribute_length <= (gatt_client->mtu - 3u)) break;
1462 log_error("gatt_client_run: value len %u > MTU %u - 3\n", gatt_client->attribute_length,gatt_client->mtu);
1463 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH);
1464 return false;
1465 default:
1466 break;
1467 }
1468
1469 bool packet_sent = true;
1470 bool done = true;
1471 switch (gatt_client->state){
1472 case P_W2_SEND_SERVICE_QUERY:
1473 gatt_client->state = P_W4_SERVICE_QUERY_RESULT;
1474 send_gatt_services_request(gatt_client);
1475 break;
1476
1477 case P_W2_SEND_SERVICE_WITH_UUID_QUERY:
1478 gatt_client->state = P_W4_SERVICE_WITH_UUID_RESULT;
1479 send_gatt_services_by_uuid_request(gatt_client);
1480 break;
1481
1482 case P_W2_SEND_ALL_CHARACTERISTICS_OF_SERVICE_QUERY:
1483 gatt_client->state = P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT;
1484 send_gatt_characteristic_request(gatt_client);
1485 break;
1486
1487 case P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY:
1488 gatt_client->state = P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT;
1489 send_gatt_characteristic_request(gatt_client);
1490 break;
1491
1492 case P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY:
1493 gatt_client->state = P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT;
1494 send_gatt_characteristic_descriptor_request(gatt_client);
1495 break;
1496
1497 case P_W2_SEND_INCLUDED_SERVICE_QUERY:
1498 gatt_client->state = P_W4_INCLUDED_SERVICE_QUERY_RESULT;
1499 send_gatt_included_service_request(gatt_client);
1500 break;
1501
1502 case P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY:
1503 gatt_client->state = P_W4_INCLUDED_SERVICE_UUID_WITH_QUERY_RESULT;
1504 send_gatt_included_service_uuid_request(gatt_client);
1505 break;
1506
1507 case P_W2_SEND_READ_CHARACTERISTIC_VALUE_QUERY:
1508 gatt_client->state = P_W4_READ_CHARACTERISTIC_VALUE_RESULT;
1509 send_gatt_read_characteristic_value_request(gatt_client);
1510 break;
1511
1512 case P_W2_SEND_READ_BLOB_QUERY:
1513 gatt_client->state = P_W4_READ_BLOB_RESULT;
1514 send_gatt_read_blob_request(gatt_client);
1515 break;
1516
1517 case P_W2_SEND_READ_BY_TYPE_REQUEST:
1518 gatt_client->state = P_W4_READ_BY_TYPE_RESPONSE;
1519 send_gatt_read_by_type_request(gatt_client);
1520 break;
1521
1522 case P_W2_SEND_READ_MULTIPLE_REQUEST:
1523 gatt_client->state = P_W4_READ_MULTIPLE_RESPONSE;
1524 send_gatt_read_multiple_request(gatt_client);
1525 break;
1526
1527 #ifdef ENABLE_GATT_OVER_EATT
1528 case P_W2_SEND_READ_MULTIPLE_VARIABLE_REQUEST:
1529 gatt_client->state = P_W4_READ_MULTIPLE_VARIABLE_RESPONSE;
1530 send_gatt_read_multiple_variable_request(gatt_client);
1531 break;
1532 #endif
1533
1534 case P_W2_SEND_WRITE_CHARACTERISTIC_VALUE:
1535 gatt_client->state = P_W4_WRITE_CHARACTERISTIC_VALUE_RESULT;
1536 send_gatt_write_attribute_value_request(gatt_client);
1537 break;
1538
1539 case P_W2_PREPARE_WRITE:
1540 gatt_client->state = P_W4_PREPARE_WRITE_RESULT;
1541 send_gatt_prepare_write_request(gatt_client);
1542 break;
1543
1544 case P_W2_PREPARE_WRITE_SINGLE:
1545 gatt_client->state = P_W4_PREPARE_WRITE_SINGLE_RESULT;
1546 send_gatt_prepare_write_request(gatt_client);
1547 break;
1548
1549 case P_W2_PREPARE_RELIABLE_WRITE:
1550 gatt_client->state = P_W4_PREPARE_RELIABLE_WRITE_RESULT;
1551 send_gatt_prepare_write_request(gatt_client);
1552 break;
1553
1554 case P_W2_EXECUTE_PREPARED_WRITE:
1555 gatt_client->state = P_W4_EXECUTE_PREPARED_WRITE_RESULT;
1556 send_gatt_execute_write_request(gatt_client);
1557 break;
1558
1559 case P_W2_CANCEL_PREPARED_WRITE:
1560 gatt_client->state = P_W4_CANCEL_PREPARED_WRITE_RESULT;
1561 send_gatt_cancel_prepared_write_request(gatt_client);
1562 break;
1563
1564 case P_W2_CANCEL_PREPARED_WRITE_DATA_MISMATCH:
1565 gatt_client->state = P_W4_CANCEL_PREPARED_WRITE_DATA_MISMATCH_RESULT;
1566 send_gatt_cancel_prepared_write_request(gatt_client);
1567 break;
1568
1569 #ifdef ENABLE_GATT_FIND_INFORMATION_FOR_CCC_DISCOVERY
1570 case P_W2_SEND_FIND_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY:
1571 // use Find Information
1572 gatt_client->state = P_W4_FIND_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT;
1573 send_gatt_characteristic_descriptor_request(gatt_client);
1574 #else
1575 case P_W2_SEND_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY:
1576 // Use Read By Type
1577 gatt_client->state = P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT;
1578 send_gatt_read_client_characteristic_configuration_request(gatt_client);
1579 #endif
1580 break;
1581
1582 case P_W2_SEND_READ_CHARACTERISTIC_DESCRIPTOR_QUERY:
1583 gatt_client->state = P_W4_READ_CHARACTERISTIC_DESCRIPTOR_RESULT;
1584 send_gatt_read_characteristic_descriptor_request(gatt_client);
1585 break;
1586
1587 case P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY:
1588 gatt_client->state = P_W4_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_RESULT;
1589 send_gatt_read_blob_request(gatt_client);
1590 break;
1591
1592 case P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR:
1593 gatt_client->state = P_W4_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
1594 send_gatt_write_attribute_value_request(gatt_client);
1595 break;
1596
1597 case P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION:
1598 gatt_client->state = P_W4_CLIENT_CHARACTERISTIC_CONFIGURATION_RESULT;
1599 send_gatt_write_client_characteristic_configuration_request(gatt_client);
1600 break;
1601
1602 case P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR:
1603 gatt_client->state = P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
1604 send_gatt_prepare_write_request(gatt_client);
1605 break;
1606
1607 case P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR:
1608 gatt_client->state = P_W4_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
1609 send_gatt_execute_write_request(gatt_client);
1610 break;
1611
1612 #ifdef ENABLE_LE_SIGNED_WRITE
1613 case P_W4_IDENTITY_RESOLVING:
1614 log_info("P_W4_IDENTITY_RESOLVING - state %x", sm_identity_resolving_state(gatt_client->con_handle));
1615 switch (sm_identity_resolving_state(gatt_client->con_handle)){
1616 case IRK_LOOKUP_SUCCEEDED:
1617 gatt_client->le_device_index = sm_le_device_index(gatt_client->con_handle);
1618 gatt_client->state = P_W4_CMAC_READY;
1619 if (sm_cmac_ready()){
1620 gatt_client_run_for_client_start_signed_write(gatt_client);
1621 }
1622 break;
1623 case IRK_LOOKUP_FAILED:
1624 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_BONDING_INFORMATION_MISSING);
1625 break;
1626 default:
1627 break;
1628 }
1629 packet_sent = false;
1630 break;
1631
1632 case P_W4_CMAC_READY:
1633 if (sm_cmac_ready()){
1634 gatt_client_run_for_client_start_signed_write(gatt_client);
1635 }
1636 packet_sent = false;
1637 break;
1638
1639 case P_W2_SEND_SIGNED_WRITE: {
1640 gatt_client->state = P_W4_SEND_SIGNED_WRITE_DONE;
1641 // bump local signing counter
1642 uint32_t sign_counter = le_device_db_local_counter_get(gatt_client->le_device_index);
1643 le_device_db_local_counter_set(gatt_client->le_device_index, sign_counter + 1);
1644 // send signed write command
1645 send_gatt_signed_write_request(gatt_client, sign_counter);
1646 // finally, notifiy client that write is complete
1647 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
1648 break;
1649 }
1650 #endif
1651 default:
1652 done = false;
1653 break;
1654 }
1655
1656 if (done){
1657 return packet_sent;
1658 }
1659
1660 // write without response callback
1661 btstack_context_callback_registration_t * callback =
1662 (btstack_context_callback_registration_t *) btstack_linked_list_pop(&gatt_client->write_without_response_requests);
1663 if (callback != NULL){
1664 (*callback->callback)(callback->context);
1665 return true;
1666 }
1667
1668 // requested can send now old
1669 if (gatt_client->write_without_response_callback != NULL){
1670 btstack_packet_handler_t packet_handler = gatt_client->write_without_response_callback;
1671 gatt_client->write_without_response_callback = NULL;
1672 uint8_t event[4];
1673 event[0] = GATT_EVENT_CAN_WRITE_WITHOUT_RESPONSE;
1674 event[1] = sizeof(event) - 2u;
1675 little_endian_store_16(event, 2, gatt_client->con_handle);
1676 packet_handler(HCI_EVENT_PACKET, gatt_client->con_handle, event, sizeof(event));
1677 return true; // to trigger requeueing (even if higher layer didn't sent)
1678 }
1679
1680 return false;
1681 }
1682
gatt_client_run(void)1683 static void gatt_client_run(void){
1684 btstack_linked_item_t *it;
1685 bool packet_sent;
1686 #ifdef ENABLE_GATT_OVER_EATT
1687 btstack_linked_list_iterator_t it_eatt;
1688 #endif
1689 for (it = (btstack_linked_item_t *) gatt_client_connections; it != NULL; it = it->next){
1690 gatt_client_t * gatt_client = (gatt_client_t *) it;
1691 switch (gatt_client->bearer_type){
1692 case ATT_BEARER_UNENHANCED_LE:
1693 #ifdef ENABLE_GATT_OVER_EATT
1694 btstack_linked_list_iterator_init(&it_eatt, &gatt_client->eatt_clients);
1695 while (btstack_linked_list_iterator_has_next(&it_eatt)) {
1696 gatt_client_t * eatt_client = (gatt_client_t *) btstack_linked_list_iterator_next(&it_eatt);
1697 if (eatt_client->state != P_READY){
1698 if (att_dispatch_client_can_send_now(gatt_client->con_handle)){
1699 gatt_client_run_for_gatt_client(eatt_client);
1700 }
1701 }
1702 }
1703 #endif
1704 if (!att_dispatch_client_can_send_now(gatt_client->con_handle)) {
1705 att_dispatch_client_request_can_send_now_event(gatt_client->con_handle);
1706 return;
1707 }
1708 packet_sent = gatt_client_run_for_gatt_client(gatt_client);
1709 if (packet_sent){
1710 // request new permission
1711 att_dispatch_client_request_can_send_now_event(gatt_client->con_handle);
1712 // requeue client for fairness and exit
1713 // note: iterator has become invalid
1714 btstack_linked_list_remove(&gatt_client_connections, (btstack_linked_item_t *) gatt_client);
1715 btstack_linked_list_add_tail(&gatt_client_connections, (btstack_linked_item_t *) gatt_client);
1716 return;
1717 }
1718 break;
1719 #ifdef ENABLE_GATT_OVER_CLASSIC
1720 case ATT_BEARER_UNENHANCED_CLASSIC:
1721 if (gatt_client->con_handle == HCI_CON_HANDLE_INVALID) {
1722 continue;
1723 }
1724
1725 // handle GATT over BR/EDR
1726 if (att_dispatch_client_can_send_now(gatt_client->con_handle) == false) {
1727 att_dispatch_client_request_can_send_now_event(gatt_client->con_handle);
1728 return;
1729 }
1730 packet_sent = gatt_client_run_for_gatt_client(gatt_client);
1731 if (packet_sent){
1732 // request new permission
1733 att_dispatch_client_request_can_send_now_event(gatt_client->con_handle);
1734 // requeue client for fairness and exit
1735 // note: iterator has become invalid
1736 btstack_linked_list_remove(&gatt_client_connections, (btstack_linked_item_t *) gatt_client);
1737 btstack_linked_list_add_tail(&gatt_client_connections, (btstack_linked_item_t *) gatt_client);
1738 return;
1739 }
1740 break;
1741 #endif
1742 default:
1743 btstack_unreachable();
1744 break;
1745 }
1746
1747
1748 }
1749 }
1750
1751 // emit complete event, used to avoid emitting event from API call
gatt_client_emit_events(void * context)1752 static void gatt_client_emit_events(void * context){
1753 UNUSED(context);
1754 btstack_linked_item_t *it;
1755 for (it = (btstack_linked_item_t *) gatt_client_connections; it != NULL; it = it->next) {
1756 gatt_client_t *gatt_client = (gatt_client_t *) it;
1757 if (gatt_client->state == P_W2_EMIT_QUERY_COMPLETE_EVENT){
1758 gatt_client->state = P_READY;
1759 emit_gatt_complete_event(gatt_client, ATT_ERROR_SUCCESS);
1760 }
1761 }
1762 }
1763
gatt_client_report_error_if_pending(gatt_client_t * gatt_client,uint8_t att_error_code)1764 static void gatt_client_report_error_if_pending(gatt_client_t *gatt_client, uint8_t att_error_code) {
1765 if (is_ready(gatt_client)) return;
1766 gatt_client_handle_transaction_complete(gatt_client, att_error_code);
1767 }
1768
gatt_client_handle_reencryption_complete(const uint8_t * packet)1769 static void gatt_client_handle_reencryption_complete(const uint8_t * packet){
1770 hci_con_handle_t con_handle = sm_event_reencryption_complete_get_handle(packet);
1771 gatt_client_t * gatt_client = gatt_client_get_context_for_handle(con_handle);
1772 if (gatt_client == NULL) return;
1773
1774 // update security level
1775 gatt_client->security_level = gatt_client_le_security_level_for_connection(con_handle);
1776
1777 gatt_client->reencryption_result = sm_event_reencryption_complete_get_status(packet);
1778 gatt_client->reencryption_active = false;
1779 gatt_client->wait_for_authentication_complete = false;
1780
1781 if (gatt_client->state == P_READY) return;
1782
1783 switch (sm_event_reencryption_complete_get_status(packet)){
1784 case ERROR_CODE_SUCCESS:
1785 log_info("re-encryption success, retry operation");
1786 break;
1787 case ERROR_CODE_AUTHENTICATION_FAILURE:
1788 case ERROR_CODE_PIN_OR_KEY_MISSING:
1789 #if defined(ENABLE_GATT_CLIENT_PAIRING) && !defined(ENABLE_LE_PROACTIVE_AUTHENTICATION)
1790 if (gatt_client_required_security_level == LEVEL_0) {
1791 // re-encryption failed for reactive authentication with pairing and we have a pending client request
1792 // => try to resolve it by deleting bonding information if we started pairing before
1793 // delete bonding information
1794 int le_device_db_index = sm_le_device_index(gatt_client->con_handle);
1795 btstack_assert(le_device_db_index >= 0);
1796 log_info("reactive auth with pairing: delete bonding and start pairing");
1797 #ifdef ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION
1798 hci_remove_le_device_db_entry_from_resolving_list((uint16_t) le_device_db_index);
1799 #endif
1800 le_device_db_remove(le_device_db_index);
1801 // trigger pairing again
1802 sm_request_pairing(gatt_client->con_handle);
1803 break;
1804 }
1805 #endif
1806 // report bonding information missing
1807 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_BONDING_INFORMATION_MISSING);
1808 break;
1809 default:
1810 // report bonding information missing
1811 gatt_client_handle_transaction_complete(gatt_client, gatt_client->pending_error_code);
1812 break;
1813 }
1814 }
1815
gatt_client_handle_disconnection_complete(const uint8_t * packet)1816 static void gatt_client_handle_disconnection_complete(const uint8_t * packet){
1817 log_info("GATT Client: HCI_EVENT_DISCONNECTION_COMPLETE");
1818 hci_con_handle_t con_handle = little_endian_read_16(packet,3);
1819 gatt_client_t * gatt_client = gatt_client_get_context_for_handle(con_handle);
1820 if (gatt_client == NULL) return;
1821
1822 gatt_client_report_error_if_pending(gatt_client, ATT_ERROR_HCI_DISCONNECT_RECEIVED);
1823 gatt_client_timeout_stop(gatt_client);
1824 btstack_linked_list_remove(&gatt_client_connections, (btstack_linked_item_t *) gatt_client);
1825 btstack_memory_gatt_client_free(gatt_client);
1826 }
1827
gatt_client_event_packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)1828 static void gatt_client_event_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
1829 UNUSED(channel); // ok: handling own l2cap events
1830 UNUSED(size); // ok: there is no channel
1831
1832 if (packet_type != HCI_EVENT_PACKET) return;
1833
1834 hci_con_handle_t con_handle;
1835 gatt_client_t * gatt_client;
1836 switch (hci_event_packet_get_type(packet)) {
1837 case HCI_EVENT_DISCONNECTION_COMPLETE:
1838 gatt_client_handle_disconnection_complete(packet);
1839 break;
1840
1841 // Pairing complete (with/without bonding=storing of pairing information)
1842 case SM_EVENT_PAIRING_COMPLETE:
1843 con_handle = sm_event_pairing_complete_get_handle(packet);
1844 gatt_client = gatt_client_get_context_for_handle(con_handle);
1845 if (gatt_client == NULL) break;
1846
1847 // update security level
1848 gatt_client->security_level = gatt_client_le_security_level_for_connection(con_handle);
1849
1850 if (gatt_client->wait_for_authentication_complete){
1851 gatt_client->wait_for_authentication_complete = false;
1852 if (sm_event_pairing_complete_get_status(packet) != ERROR_CODE_SUCCESS){
1853 log_info("pairing failed, report previous error 0x%x", gatt_client->pending_error_code);
1854 gatt_client_report_error_if_pending(gatt_client, gatt_client->pending_error_code);
1855 } else {
1856 log_info("pairing success, retry operation");
1857 }
1858 }
1859 break;
1860
1861 #ifdef ENABLE_LE_SIGNED_WRITE
1862 // Identity Resolving completed (no code, gatt_client_run will continue)
1863 case SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED:
1864 case SM_EVENT_IDENTITY_RESOLVING_FAILED:
1865 break;
1866 #endif
1867
1868 // re-encryption started
1869 case SM_EVENT_REENCRYPTION_STARTED:
1870 con_handle = sm_event_reencryption_complete_get_handle(packet);
1871 gatt_client = gatt_client_get_context_for_handle(con_handle);
1872 if (gatt_client == NULL) break;
1873
1874 gatt_client->reencryption_active = true;
1875 gatt_client->reencryption_result = ERROR_CODE_SUCCESS;
1876 break;
1877
1878 // re-encryption complete
1879 case SM_EVENT_REENCRYPTION_COMPLETE:
1880 gatt_client_handle_reencryption_complete(packet);
1881 break;
1882 default:
1883 break;
1884 }
1885
1886 gatt_client_run();
1887 }
1888
gatt_client_handle_att_read_response(gatt_client_t * gatt_client,uint8_t * packet,uint16_t size)1889 static void gatt_client_handle_att_read_response(gatt_client_t *gatt_client, uint8_t *packet, uint16_t size) {
1890 switch (gatt_client->state) {
1891 case P_W4_INCLUDED_SERVICE_UUID_WITH_QUERY_RESULT:
1892 if (size >= 17) {
1893 uint8_t uuid128[16];
1894 reverse_128(&packet[1], uuid128);
1895 report_gatt_included_service_uuid128(gatt_client, gatt_client->start_group_handle, uuid128);
1896 }
1897 trigger_next_included_service_query(gatt_client, gatt_client->start_group_handle);
1898 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1899 break;
1900
1901 case P_W4_READ_CHARACTERISTIC_VALUE_RESULT:
1902 report_gatt_characteristic_value(gatt_client, gatt_client->attribute_handle, &packet[1], size - 1u);
1903 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
1904 break;
1905
1906 case P_W4_READ_CHARACTERISTIC_DESCRIPTOR_RESULT:
1907 report_gatt_characteristic_descriptor(gatt_client, gatt_client->attribute_handle, &packet[1],
1908 size - 1u, 0u);
1909 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
1910 break;
1911
1912 // Use ATT_READ_REQUEST for first blob of Read Long Characteristic
1913 case P_W4_READ_BLOB_RESULT:
1914 report_gatt_long_characteristic_value_blob(gatt_client, gatt_client->attribute_handle, &packet[1],
1915 size - 1u, gatt_client->attribute_offset);
1916 trigger_next_blob_query(gatt_client, P_W2_SEND_READ_BLOB_QUERY, size - 1u);
1917 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1918 break;
1919
1920 // Use ATT_READ_REQUEST for first blob of Read Long Characteristic Descriptor
1921 case P_W4_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_RESULT:
1922 report_gatt_long_characteristic_descriptor(gatt_client, gatt_client->attribute_handle, &packet[1],
1923 size - 1u, gatt_client->attribute_offset);
1924 trigger_next_blob_query(gatt_client, P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY,
1925 size - 1u);
1926 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1927 break;
1928
1929 default:
1930 break;
1931 }
1932 }
1933
gatt_client_handle_att_read_by_type_response(gatt_client_t * gatt_client,uint8_t * packet,uint16_t size)1934 static void gatt_client_handle_att_read_by_type_response(gatt_client_t *gatt_client, uint8_t *packet, uint16_t size) {
1935 switch (gatt_client->state) {
1936 case P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT:
1937 report_gatt_characteristics(gatt_client, packet, size);
1938 trigger_next_characteristic_query(gatt_client,
1939 get_last_result_handle_from_characteristics_list(packet, size));
1940 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done, or by ATT_ERROR
1941 break;
1942 case P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT:
1943 report_gatt_characteristics(gatt_client, packet, size);
1944 trigger_next_characteristic_query(gatt_client,
1945 get_last_result_handle_from_characteristics_list(packet, size));
1946 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done, or by ATT_ERROR
1947 break;
1948 case P_W4_INCLUDED_SERVICE_QUERY_RESULT: {
1949 if (size < 2u) break;
1950 uint16_t uuid16 = 0;
1951 uint16_t pair_size = packet[1];
1952
1953 if (pair_size == 6u) {
1954 if (size < 8u) break;
1955 // UUIDs not available, query first included service
1956 gatt_client->start_group_handle = little_endian_read_16(packet, 2); // ready for next query
1957 gatt_client->query_start_handle = little_endian_read_16(packet, 4);
1958 gatt_client->query_end_handle = little_endian_read_16(packet, 6);
1959 gatt_client->state = P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY;
1960 break;
1961 }
1962
1963 if (pair_size != 8u) break;
1964
1965 // UUIDs included, report all of them
1966 uint16_t offset;
1967 for (offset = 2u; (offset + 8u) <= size; offset += pair_size) {
1968 uint16_t include_handle = little_endian_read_16(packet, offset);
1969 gatt_client->query_start_handle = little_endian_read_16(packet, offset + 2u);
1970 gatt_client->query_end_handle = little_endian_read_16(packet, offset + 4u);
1971 uuid16 = little_endian_read_16(packet, offset + 6u);
1972 report_gatt_included_service_uuid16(gatt_client, include_handle, uuid16);
1973 }
1974
1975 trigger_next_included_service_query(gatt_client,
1976 get_last_result_handle_from_included_services_list(packet,
1977 size));
1978 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1979 break;
1980 }
1981 #ifndef ENABLE_GATT_FIND_INFORMATION_FOR_CCC_DISCOVERY
1982 case P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT:
1983 gatt_client->client_characteristic_configuration_handle = little_endian_read_16(packet, 2);
1984 gatt_client->state = P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
1985 break;
1986 #endif
1987 case P_W4_READ_BY_TYPE_RESPONSE: {
1988 uint16_t pair_size = packet[1];
1989 // set last result handle to last valid handle, only used if pair_size invalid
1990 uint16_t last_result_handle = 0xffff;
1991 if (pair_size > 2) {
1992 uint16_t offset;
1993 for (offset = 2; offset < size; offset += pair_size) {
1994 uint16_t value_handle = little_endian_read_16(packet, offset);
1995 report_gatt_characteristic_value(gatt_client, value_handle, &packet[offset + 2u],
1996 pair_size - 2u);
1997 last_result_handle = value_handle;
1998 }
1999 }
2000 trigger_next_read_by_type_query(gatt_client, last_result_handle);
2001 break;
2002 }
2003 default:
2004 break;
2005 }
2006 }
2007
gatt_client_handle_att_write_response(gatt_client_t * gatt_client)2008 static void gatt_client_handle_att_write_response(gatt_client_t *gatt_client) {
2009 switch (gatt_client->state) {
2010 case P_W4_WRITE_CHARACTERISTIC_VALUE_RESULT:
2011 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
2012 break;
2013 case P_W4_CLIENT_CHARACTERISTIC_CONFIGURATION_RESULT:
2014 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
2015 break;
2016 case P_W4_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:
2017 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
2018 break;
2019 default:
2020 break;
2021 }
2022 }
2023
gatt_client_handle_att_response(gatt_client_t * gatt_client,uint8_t * packet,uint16_t size)2024 static void gatt_client_handle_att_response(gatt_client_t * gatt_client, uint8_t * packet, uint16_t size) {
2025 uint8_t att_status;
2026 switch (packet[0]) {
2027 case ATT_EXCHANGE_MTU_RESPONSE: {
2028 if (size < 3u) break;
2029 bool update_gatt_server_att_mtu = false;
2030 uint16_t remote_rx_mtu = little_endian_read_16(packet, 1);
2031 uint16_t local_rx_mtu = l2cap_max_le_mtu();
2032 switch (gatt_client->bearer_type){
2033 case ATT_BEARER_UNENHANCED_LE:
2034 update_gatt_server_att_mtu = true;
2035 break;
2036 #ifdef ENABLE_GATT_OVER_CLASSIC
2037 case ATT_BEARER_UNENHANCED_CLASSIC:
2038 local_rx_mtu = gatt_client->mtu;
2039 break;
2040 #endif
2041 default:
2042 btstack_unreachable();
2043 break;
2044 }
2045
2046 uint16_t mtu = (remote_rx_mtu < local_rx_mtu) ? remote_rx_mtu : local_rx_mtu;
2047
2048 // set gatt client mtu
2049 gatt_client->mtu = mtu;
2050 gatt_client->mtu_state = MTU_EXCHANGED;
2051
2052 if (update_gatt_server_att_mtu){
2053 // set per connection mtu state - for fixed channel
2054 hci_connection_t *hci_connection = hci_connection_for_handle(gatt_client->con_handle);
2055 hci_connection->att_connection.mtu = gatt_client->mtu;
2056 hci_connection->att_connection.mtu_exchanged = true;
2057 }
2058 emit_gatt_mtu_exchanged_result_event(gatt_client, gatt_client->mtu);
2059 break;
2060 }
2061 case ATT_READ_BY_GROUP_TYPE_RESPONSE:
2062 switch (gatt_client->state) {
2063 case P_W4_SERVICE_QUERY_RESULT:
2064 report_gatt_services(gatt_client, packet, size);
2065 trigger_next_service_query(gatt_client, get_last_result_handle_from_service_list(packet, size));
2066 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
2067 break;
2068 default:
2069 break;
2070 }
2071 break;
2072 case ATT_HANDLE_VALUE_NOTIFICATION:
2073 if (size < 3u) return;
2074 report_gatt_notification(gatt_client, little_endian_read_16(packet, 1u), &packet[3], size - 3u);
2075 return;
2076 #ifdef ENABLE_GATT_OVER_EATT
2077 case ATT_MULTIPLE_HANDLE_VALUE_NTF:
2078 if (size >= 5u) {
2079 uint16_t offset = 1;
2080 while (true){
2081 uint16_t value_handle = little_endian_read_16(packet, offset);
2082 offset += 2;
2083 uint16_t value_length = little_endian_read_16(packet, offset);
2084 offset += 2;
2085 if ((offset + value_length) > size) break;
2086 report_gatt_notification(gatt_client, value_handle, &packet[offset], value_length);
2087 offset += value_length;
2088 }
2089 }
2090 return;
2091 #endif
2092 case ATT_HANDLE_VALUE_INDICATION:
2093 if (size < 3u) break;
2094 report_gatt_indication(gatt_client, little_endian_read_16(packet, 1u), &packet[3], size - 3u);
2095 gatt_client->send_confirmation = true;
2096 break;
2097 case ATT_READ_BY_TYPE_RESPONSE:
2098 gatt_client_handle_att_read_by_type_response(gatt_client, packet, size);
2099 break;
2100 case ATT_READ_RESPONSE:
2101 gatt_client_handle_att_read_response(gatt_client, packet, size);
2102 break;
2103 case ATT_FIND_BY_TYPE_VALUE_RESPONSE: {
2104 uint8_t pair_size = 4;
2105 int i;
2106 uint16_t start_group_handle;
2107 uint16_t end_group_handle = 0xffff; // asserts GATT_EVENT_QUERY_COMPLETE is emitted if no results
2108 for (i = 1u; (i + pair_size) <= size; i += pair_size) {
2109 start_group_handle = little_endian_read_16(packet, i);
2110 end_group_handle = little_endian_read_16(packet, i + 2);
2111 emit_gatt_service_query_result_event(gatt_client, start_group_handle, end_group_handle,
2112 gatt_client->uuid128);
2113 }
2114 trigger_next_service_by_uuid_query(gatt_client, end_group_handle);
2115 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
2116 break;
2117 }
2118 case ATT_FIND_INFORMATION_REPLY: {
2119 if (size < 2u) break;
2120
2121 uint8_t pair_size = 4;
2122 if (packet[1u] == 2u) {
2123 pair_size = 18;
2124 }
2125 uint16_t offset = 2;
2126
2127 if (size < (pair_size + offset)) break;
2128 uint16_t last_descriptor_handle = little_endian_read_16(packet, size - pair_size);
2129
2130 #ifdef ENABLE_GATT_FIND_INFORMATION_FOR_CCC_DISCOVERY
2131 log_info("ENABLE_GATT_FIND_INFORMATION_FOR_CCC_DISCOVERY, state %x", gatt_client->state);
2132 if (gatt_client->state == P_W4_FIND_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT){
2133 // iterate over descriptors looking for CCC
2134 if (pair_size == 4){
2135 while ((offset + 4) <= size){
2136 uint16_t uuid16 = little_endian_read_16(packet, offset + 2);
2137 if (uuid16 == GATT_CLIENT_CHARACTERISTICS_CONFIGURATION){
2138 gatt_client->client_characteristic_configuration_handle = little_endian_read_16(packet, offset);
2139 gatt_client->state = P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
2140 log_info("CCC found %x", gatt_client->client_characteristic_configuration_handle);
2141 break;
2142 }
2143 offset += pair_size;
2144 }
2145 }
2146 if (is_query_done(gatt_client, last_descriptor_handle)){
2147
2148 } else {
2149 // next
2150 gatt_client->start_group_handle = last_descriptor_handle + 1;
2151 gatt_client->state = P_W2_SEND_FIND_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY;
2152 }
2153 break;
2154 }
2155 #endif
2156 report_gatt_all_characteristic_descriptors(gatt_client, &packet[2], size - 2u, pair_size);
2157 trigger_next_characteristic_descriptor_query(gatt_client, last_descriptor_handle);
2158 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
2159 break;
2160 }
2161
2162 case ATT_WRITE_RESPONSE:
2163 gatt_client_handle_att_write_response(gatt_client);
2164 break;
2165
2166 case ATT_READ_BLOB_RESPONSE: {
2167 uint16_t received_blob_length = size - 1u;
2168 switch (gatt_client->state) {
2169 case P_W4_READ_BLOB_RESULT:
2170 report_gatt_long_characteristic_value_blob(gatt_client, gatt_client->attribute_handle, &packet[1],
2171 received_blob_length, gatt_client->attribute_offset);
2172 trigger_next_blob_query(gatt_client, P_W2_SEND_READ_BLOB_QUERY, received_blob_length);
2173 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
2174 break;
2175 case P_W4_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_RESULT:
2176 report_gatt_long_characteristic_descriptor(gatt_client, gatt_client->attribute_handle,
2177 &packet[1], received_blob_length,
2178 gatt_client->attribute_offset);
2179 trigger_next_blob_query(gatt_client, P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY,
2180 received_blob_length);
2181 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
2182 break;
2183 default:
2184 break;
2185 }
2186 break;
2187 }
2188 case ATT_PREPARE_WRITE_RESPONSE:
2189 switch (gatt_client->state) {
2190 case P_W4_PREPARE_WRITE_SINGLE_RESULT:
2191 if (is_value_valid(gatt_client, packet, size)) {
2192 att_status = ATT_ERROR_SUCCESS;
2193 } else {
2194 att_status = ATT_ERROR_DATA_MISMATCH;
2195 }
2196 gatt_client_handle_transaction_complete(gatt_client, att_status);
2197 break;
2198
2199 case P_W4_PREPARE_WRITE_RESULT: {
2200 gatt_client->attribute_offset = little_endian_read_16(packet, 3);
2201 trigger_next_prepare_write_query(gatt_client, P_W2_PREPARE_WRITE, P_W2_EXECUTE_PREPARED_WRITE);
2202 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
2203 break;
2204 }
2205 case P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT: {
2206 gatt_client->attribute_offset = little_endian_read_16(packet, 3);
2207 trigger_next_prepare_write_query(gatt_client, P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR,
2208 P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR);
2209 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
2210 break;
2211 }
2212 case P_W4_PREPARE_RELIABLE_WRITE_RESULT: {
2213 if (is_value_valid(gatt_client, packet, size)) {
2214 gatt_client->attribute_offset = little_endian_read_16(packet, 3);
2215 trigger_next_prepare_write_query(gatt_client, P_W2_PREPARE_RELIABLE_WRITE,
2216 P_W2_EXECUTE_PREPARED_WRITE);
2217 // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
2218 break;
2219 }
2220 gatt_client->state = P_W2_CANCEL_PREPARED_WRITE_DATA_MISMATCH;
2221 break;
2222 }
2223 default:
2224 break;
2225 }
2226 break;
2227
2228 case ATT_EXECUTE_WRITE_RESPONSE:
2229 switch (gatt_client->state) {
2230 case P_W4_EXECUTE_PREPARED_WRITE_RESULT:
2231 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
2232 break;
2233 case P_W4_CANCEL_PREPARED_WRITE_RESULT:
2234 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
2235 break;
2236 case P_W4_CANCEL_PREPARED_WRITE_DATA_MISMATCH_RESULT:
2237 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_DATA_MISMATCH);
2238 break;
2239 case P_W4_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:
2240 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
2241 break;
2242 default:
2243 break;
2244
2245 }
2246 break;
2247
2248 case ATT_READ_MULTIPLE_RESPONSE:
2249 switch (gatt_client->state) {
2250 case P_W4_READ_MULTIPLE_RESPONSE:
2251 report_gatt_characteristic_value(gatt_client, 0u, &packet[1], size - 1u);
2252 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
2253 break;
2254 default:
2255 break;
2256 }
2257 break;
2258
2259 #ifdef ENABLE_GATT_OVER_EATT
2260 case ATT_READ_MULTIPLE_VARIABLE_RSP:
2261 switch (gatt_client->state) {
2262 case P_W4_READ_MULTIPLE_VARIABLE_RESPONSE:
2263 report_gatt_characteristic_value(gatt_client, 0u, &packet[1], size - 1u);
2264 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
2265 break;
2266 default:
2267 break;
2268 }
2269 break;
2270 #endif
2271
2272 case ATT_ERROR_RESPONSE:
2273 if (size < 5u) return;
2274 att_status = packet[4];
2275 switch (att_status) {
2276 case ATT_ERROR_ATTRIBUTE_NOT_FOUND: {
2277 switch (gatt_client->state) {
2278 case P_W4_SERVICE_QUERY_RESULT:
2279 case P_W4_SERVICE_WITH_UUID_RESULT:
2280 case P_W4_INCLUDED_SERVICE_QUERY_RESULT:
2281 case P_W4_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT:
2282 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
2283 break;
2284 case P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT:
2285 case P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT:
2286 report_gatt_characteristic_end_found(gatt_client, gatt_client->end_group_handle);
2287 gatt_client_handle_transaction_complete(gatt_client, ATT_ERROR_SUCCESS);
2288 break;
2289 case P_W4_READ_BY_TYPE_RESPONSE:
2290 if (gatt_client->start_group_handle == gatt_client->query_start_handle) {
2291 att_status = ATT_ERROR_ATTRIBUTE_NOT_FOUND;
2292 } else {
2293 att_status = ATT_ERROR_SUCCESS;
2294 }
2295 gatt_client_handle_transaction_complete(gatt_client, att_status);
2296 break;
2297 default:
2298 gatt_client_report_error_if_pending(gatt_client, att_status);
2299 break;
2300 }
2301 break;
2302 }
2303
2304 #ifdef ENABLE_GATT_CLIENT_PAIRING
2305
2306 case ATT_ERROR_INSUFFICIENT_AUTHENTICATION:
2307 case ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE:
2308 case ATT_ERROR_INSUFFICIENT_ENCRYPTION: {
2309
2310 // security too low
2311 if (gatt_client->security_counter > 0) {
2312 gatt_client_report_error_if_pending(gatt_client, att_status);
2313 break;
2314 }
2315 // start security
2316 gatt_client->security_counter++;
2317
2318 // setup action
2319 int retry = 1;
2320 switch (gatt_client->state){
2321 case P_W4_READ_CHARACTERISTIC_VALUE_RESULT:
2322 gatt_client->state = P_W2_SEND_READ_CHARACTERISTIC_VALUE_QUERY ;
2323 break;
2324 case P_W4_READ_BLOB_RESULT:
2325 gatt_client->state = P_W2_SEND_READ_BLOB_QUERY;
2326 break;
2327 case P_W4_READ_BY_TYPE_RESPONSE:
2328 gatt_client->state = P_W2_SEND_READ_BY_TYPE_REQUEST;
2329 break;
2330 case P_W4_READ_MULTIPLE_RESPONSE:
2331 gatt_client->state = P_W2_SEND_READ_MULTIPLE_REQUEST;
2332 break;
2333 case P_W4_READ_MULTIPLE_VARIABLE_RESPONSE:
2334 gatt_client->state = P_W2_SEND_READ_MULTIPLE_VARIABLE_REQUEST;
2335 break;
2336 case P_W4_WRITE_CHARACTERISTIC_VALUE_RESULT:
2337 gatt_client->state = P_W2_SEND_WRITE_CHARACTERISTIC_VALUE;
2338 break;
2339 case P_W4_PREPARE_WRITE_RESULT:
2340 gatt_client->state = P_W2_PREPARE_WRITE;
2341 break;
2342 case P_W4_PREPARE_WRITE_SINGLE_RESULT:
2343 gatt_client->state = P_W2_PREPARE_WRITE_SINGLE;
2344 break;
2345 case P_W4_PREPARE_RELIABLE_WRITE_RESULT:
2346 gatt_client->state = P_W2_PREPARE_RELIABLE_WRITE;
2347 break;
2348 case P_W4_EXECUTE_PREPARED_WRITE_RESULT:
2349 gatt_client->state = P_W2_EXECUTE_PREPARED_WRITE;
2350 break;
2351 case P_W4_CANCEL_PREPARED_WRITE_RESULT:
2352 gatt_client->state = P_W2_CANCEL_PREPARED_WRITE;
2353 break;
2354 case P_W4_CANCEL_PREPARED_WRITE_DATA_MISMATCH_RESULT:
2355 gatt_client->state = P_W2_CANCEL_PREPARED_WRITE_DATA_MISMATCH;
2356 break;
2357 case P_W4_READ_CHARACTERISTIC_DESCRIPTOR_RESULT:
2358 gatt_client->state = P_W2_SEND_READ_CHARACTERISTIC_DESCRIPTOR_QUERY;
2359 break;
2360 case P_W4_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_RESULT:
2361 gatt_client->state = P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY;
2362 break;
2363 case P_W4_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:
2364 gatt_client->state = P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR;
2365 break;
2366 case P_W4_CLIENT_CHARACTERISTIC_CONFIGURATION_RESULT:
2367 gatt_client->state = P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
2368 break;
2369 case P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:
2370 gatt_client->state = P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR;
2371 break;
2372 case P_W4_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:
2373 gatt_client->state = P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR;
2374 break;
2375 #ifdef ENABLE_LE_SIGNED_WRITE
2376 case P_W4_SEND_SIGNED_WRITE_DONE:
2377 gatt_client->state = P_W2_SEND_SIGNED_WRITE;
2378 break;
2379 #endif
2380 default:
2381 log_info("retry not supported for state %x", gatt_client->state);
2382 retry = 0;
2383 break;
2384 }
2385
2386 if (!retry) {
2387 gatt_client_report_error_if_pending(gatt_client, att_status);
2388 break;
2389 }
2390
2391 log_info("security error, start pairing");
2392
2393 // start pairing for higher security level
2394 gatt_client->wait_for_authentication_complete = true;
2395 gatt_client->pending_error_code = att_status;
2396 sm_request_pairing(gatt_client->con_handle);
2397 break;
2398 }
2399 #endif
2400
2401 // nothing we can do about that
2402 case ATT_ERROR_INSUFFICIENT_AUTHORIZATION:
2403 default:
2404 gatt_client_report_error_if_pending(gatt_client, att_status);
2405 break;
2406 }
2407 break;
2408
2409 default:
2410 log_info("ATT Handler, unhandled response type 0x%02x", packet[0]);
2411 break;
2412 }
2413 }
2414
gatt_client_att_packet_handler(uint8_t packet_type,uint16_t handle,uint8_t * packet,uint16_t size)2415 static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size) {
2416 gatt_client_t *gatt_client;
2417 #ifdef ENABLE_GATT_OVER_CLASSIC
2418 uint8_t status;
2419 hci_connection_t * hci_connection;
2420 hci_con_handle_t con_handle;
2421 #endif
2422
2423 if (size < 1u) return;
2424 switch (packet_type){
2425 case HCI_EVENT_PACKET:
2426 switch (hci_event_packet_get_type(packet)) {
2427 #ifdef ENABLE_GATT_OVER_CLASSIC
2428 case L2CAP_EVENT_CHANNEL_OPENED:
2429 status = l2cap_event_channel_opened_get_status(packet);
2430 gatt_client = gatt_client_get_context_for_l2cap_cid(l2cap_event_channel_opened_get_local_cid(packet));
2431 if (gatt_client != NULL){
2432 con_handle = l2cap_event_channel_opened_get_handle(packet);
2433 hci_connection = hci_connection_for_handle(con_handle);
2434 if (status == L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_RESOURCES){
2435 if ((hci_connection != NULL) && hci_connection->att_server.incoming_connection_request) {
2436 log_info("Collision, retry in 100ms");
2437 gatt_client->state = P_W2_L2CAP_CONNECT;
2438 // set timer for retry
2439 btstack_run_loop_set_timer(&gatt_client->gc_timeout, GATT_CLIENT_COLLISION_BACKOFF_MS);
2440 btstack_run_loop_set_timer_handler(&gatt_client->gc_timeout, gatt_client_classic_retry);
2441 btstack_run_loop_add_timer(&gatt_client->gc_timeout);
2442 break;
2443 }
2444 }
2445 // if status != 0, gatt_client will be discarded
2446 gatt_client->state = P_READY;
2447 gatt_client->con_handle = l2cap_event_channel_opened_get_handle(packet);
2448 gatt_client->mtu = l2cap_event_channel_opened_get_remote_mtu(packet);
2449 gatt_client_classic_handle_connected(gatt_client, status);
2450 }
2451 break;
2452 case L2CAP_EVENT_CHANNEL_CLOSED:
2453 gatt_client = gatt_client_get_context_for_l2cap_cid(l2cap_event_channel_closed_get_local_cid(packet));
2454 if (gatt_client != NULL){
2455 // discard gatt client object
2456 gatt_client_classic_handle_disconnected(gatt_client);
2457 }
2458 break;
2459 #endif
2460 case L2CAP_EVENT_CAN_SEND_NOW:
2461 gatt_client_run();
2462 break;
2463 // att_server has negotiated the mtu for this connection, cache if context exists
2464 case ATT_EVENT_MTU_EXCHANGE_COMPLETE:
2465 if (size < 6u) break;
2466 gatt_client = gatt_client_get_context_for_handle(handle);
2467 if (gatt_client != NULL) {
2468 gatt_client->mtu = little_endian_read_16(packet, 4);
2469 }
2470 break;
2471 default:
2472 break;
2473 }
2474 break;
2475
2476 case ATT_DATA_PACKET:
2477 // special cases: notifications & indications motivate creating context
2478 switch (packet[0]) {
2479 case ATT_HANDLE_VALUE_NOTIFICATION:
2480 case ATT_HANDLE_VALUE_INDICATION:
2481 gatt_client_provide_context_for_handle(handle, &gatt_client);
2482 break;
2483 default:
2484 gatt_client = gatt_client_get_context_for_handle(handle);
2485 break;
2486 }
2487
2488 if (gatt_client != NULL) {
2489 gatt_client_handle_att_response(gatt_client, packet, size);
2490 gatt_client_run();
2491 }
2492 break;
2493
2494 #ifdef ENABLE_GATT_OVER_CLASSIC
2495 case L2CAP_DATA_PACKET:
2496 gatt_client = gatt_client_get_context_for_l2cap_cid(handle);
2497 if (gatt_client != NULL){
2498 gatt_client_handle_att_response(gatt_client, packet, size);
2499 gatt_client_run();
2500 }
2501 break;
2502 #endif
2503
2504 default:
2505 break;
2506 }
2507 }
2508
2509 #ifdef ENABLE_LE_SIGNED_WRITE
att_signed_write_handle_cmac_result(uint8_t hash[8])2510 static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
2511 btstack_linked_list_iterator_t it;
2512 btstack_linked_list_iterator_init(&it, &gatt_client_connections);
2513 while (btstack_linked_list_iterator_has_next(&it)){
2514 gatt_client_t * gatt_client = (gatt_client_t *) btstack_linked_list_iterator_next(&it);
2515 if (gatt_client->state == P_W4_CMAC_RESULT){
2516 // store result
2517 (void)memcpy(gatt_client->cmac, hash, 8);
2518 // reverse_64(hash, gatt_client->cmac);
2519 gatt_client->state = P_W2_SEND_SIGNED_WRITE;
2520 gatt_client_run();
2521 return;
2522 }
2523 }
2524 }
2525
gatt_client_signed_write_without_response(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t value_handle,uint16_t message_len,uint8_t * message)2526 uint8_t gatt_client_signed_write_without_response(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle, uint16_t message_len, uint8_t * message){
2527 gatt_client_t * gatt_client;
2528 uint8_t status = gatt_client_provide_context_for_handle(con_handle, &gatt_client);
2529 if (status != ERROR_CODE_SUCCESS){
2530 return status;
2531 }
2532 if (is_ready(gatt_client) == 0){
2533 return GATT_CLIENT_IN_WRONG_STATE;
2534 }
2535
2536 gatt_client->callback = callback;
2537 gatt_client->attribute_handle = value_handle;
2538 gatt_client->attribute_length = message_len;
2539 gatt_client->attribute_value = message;
2540 gatt_client->state = P_W4_IDENTITY_RESOLVING;
2541 gatt_client_run();
2542 return ERROR_CODE_SUCCESS;
2543 }
2544 #endif
2545
gatt_client_discover_primary_services(btstack_packet_handler_t callback,hci_con_handle_t con_handle)2546 uint8_t gatt_client_discover_primary_services(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
2547 gatt_client_t * gatt_client;
2548 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2549 if (status != ERROR_CODE_SUCCESS){
2550 return status;
2551 }
2552
2553 gatt_client->callback = callback;
2554 gatt_client->start_group_handle = 0x0001;
2555 gatt_client->end_group_handle = 0xffff;
2556 gatt_client->state = P_W2_SEND_SERVICE_QUERY;
2557 gatt_client->uuid16 = GATT_PRIMARY_SERVICE_UUID;
2558 gatt_client_run();
2559 return ERROR_CODE_SUCCESS;
2560 }
2561
gatt_client_discover_secondary_services(btstack_packet_handler_t callback,hci_con_handle_t con_handle)2562 uint8_t gatt_client_discover_secondary_services(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
2563 gatt_client_t * gatt_client;
2564 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2565 if (status != ERROR_CODE_SUCCESS){
2566 return status;
2567 }
2568
2569 gatt_client->callback = callback;
2570 gatt_client->start_group_handle = 0x0001;
2571 gatt_client->end_group_handle = 0xffff;
2572 gatt_client->state = P_W2_SEND_SERVICE_QUERY;
2573 gatt_client->uuid16 = GATT_SECONDARY_SERVICE_UUID;
2574 gatt_client_run();
2575 return ERROR_CODE_SUCCESS;
2576 }
2577
gatt_client_discover_primary_services_by_uuid16_with_context(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t uuid16,uint16_t service_id,uint16_t connection_id)2578 uint8_t gatt_client_discover_primary_services_by_uuid16_with_context(btstack_packet_handler_t callback, hci_con_handle_t con_handle,
2579 uint16_t uuid16, uint16_t service_id, uint16_t connection_id){
2580 gatt_client_t * gatt_client;
2581 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2582 if (status != ERROR_CODE_SUCCESS){
2583 return status;
2584 }
2585
2586 gatt_client->callback = callback;
2587 gatt_client->service_id = service_id;
2588 gatt_client->connection_id = connection_id;
2589 gatt_client->start_group_handle = 0x0001;
2590 gatt_client->end_group_handle = 0xffff;
2591 gatt_client->state = P_W2_SEND_SERVICE_WITH_UUID_QUERY;
2592 gatt_client->uuid16 = uuid16;
2593 uuid_add_bluetooth_prefix((uint8_t*) &(gatt_client->uuid128), gatt_client->uuid16);
2594 gatt_client_run();
2595 return ERROR_CODE_SUCCESS;
2596 }
2597
gatt_client_discover_primary_services_by_uuid16(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t uuid16)2598 uint8_t gatt_client_discover_primary_services_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t uuid16){
2599 return gatt_client_discover_primary_services_by_uuid16_with_context(callback, con_handle, uuid16, 0, 0);
2600 }
2601
gatt_client_discover_primary_services_by_uuid128(btstack_packet_handler_t callback,hci_con_handle_t con_handle,const uint8_t * uuid128)2602 uint8_t gatt_client_discover_primary_services_by_uuid128(btstack_packet_handler_t callback, hci_con_handle_t con_handle, const uint8_t * uuid128){
2603 gatt_client_t * gatt_client;
2604 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2605 if (status != ERROR_CODE_SUCCESS){
2606 return status;
2607 }
2608
2609 gatt_client->callback = callback;
2610 gatt_client->start_group_handle = 0x0001;
2611 gatt_client->end_group_handle = 0xffff;
2612 gatt_client->uuid16 = 0;
2613 (void)memcpy(gatt_client->uuid128, uuid128, 16);
2614 gatt_client->state = P_W2_SEND_SERVICE_WITH_UUID_QUERY;
2615 gatt_client_run();
2616 return ERROR_CODE_SUCCESS;
2617 }
2618
gatt_client_discover_characteristics_for_service_with_context(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_service_t * service,uint16_t service_id,uint16_t connection_id)2619 uint8_t gatt_client_discover_characteristics_for_service_with_context(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_service_t * service,
2620 uint16_t service_id, uint16_t connection_id){
2621 gatt_client_t * gatt_client;
2622 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2623 if (status != ERROR_CODE_SUCCESS){
2624 return status;
2625 }
2626
2627 gatt_client->callback = callback;
2628 gatt_client->service_id = service_id;
2629 gatt_client->connection_id = connection_id;
2630 gatt_client->start_group_handle = service->start_group_handle;
2631 gatt_client->end_group_handle = service->end_group_handle;
2632 gatt_client->filter_with_uuid = false;
2633 gatt_client->characteristic_start_handle = 0;
2634 gatt_client->state = P_W2_SEND_ALL_CHARACTERISTICS_OF_SERVICE_QUERY;
2635 gatt_client_run();
2636 return ERROR_CODE_SUCCESS;
2637 }
2638
gatt_client_discover_characteristics_for_service(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_service_t * service)2639 uint8_t gatt_client_discover_characteristics_for_service(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_service_t * service){
2640 return gatt_client_discover_characteristics_for_service_with_context(callback, con_handle, service, 0, 0);
2641 }
2642
gatt_client_find_included_services_for_service_with_context(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_service_t * service,uint16_t service_id,uint16_t connection_id)2643 uint8_t gatt_client_find_included_services_for_service_with_context(btstack_packet_handler_t callback, hci_con_handle_t con_handle,
2644 gatt_client_service_t * service, uint16_t service_id, uint16_t connection_id){
2645 gatt_client_t * gatt_client;
2646 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2647 if (status != ERROR_CODE_SUCCESS){
2648 return status;
2649 }
2650
2651 gatt_client->callback = callback;
2652 gatt_client->service_id = service_id;
2653 gatt_client->connection_id = connection_id;
2654 gatt_client->start_group_handle = service->start_group_handle;
2655 gatt_client->end_group_handle = service->end_group_handle;
2656 gatt_client->state = P_W2_SEND_INCLUDED_SERVICE_QUERY;
2657
2658 gatt_client_run();
2659 return ERROR_CODE_SUCCESS;
2660 }
2661
gatt_client_find_included_services_for_service(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_service_t * service)2662 uint8_t gatt_client_find_included_services_for_service(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_service_t * service) {
2663 return gatt_client_find_included_services_for_service_with_context(callback, con_handle, service, 0, 0);
2664 }
2665
gatt_client_discover_characteristics_for_handle_range_by_uuid16(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t start_handle,uint16_t end_handle,uint16_t uuid16)2666 uint8_t gatt_client_discover_characteristics_for_handle_range_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t start_handle, uint16_t end_handle, uint16_t uuid16){
2667 gatt_client_t * gatt_client;
2668 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2669 if (status != ERROR_CODE_SUCCESS){
2670 return status;
2671 }
2672
2673 gatt_client->callback = callback;
2674 gatt_client->start_group_handle = start_handle;
2675 gatt_client->end_group_handle = end_handle;
2676 gatt_client->filter_with_uuid = true;
2677 gatt_client->uuid16 = uuid16;
2678 uuid_add_bluetooth_prefix((uint8_t*) &(gatt_client->uuid128), uuid16);
2679 gatt_client->characteristic_start_handle = 0;
2680 gatt_client->state = P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY;
2681 gatt_client_run();
2682 return ERROR_CODE_SUCCESS;
2683 }
2684
gatt_client_discover_characteristics_for_handle_range_by_uuid128(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t start_handle,uint16_t end_handle,const uint8_t * uuid128)2685 uint8_t gatt_client_discover_characteristics_for_handle_range_by_uuid128(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t start_handle, uint16_t end_handle, const uint8_t * uuid128){
2686 gatt_client_t * gatt_client;
2687 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2688 if (status != ERROR_CODE_SUCCESS){
2689 return status;
2690 }
2691
2692 gatt_client->callback = callback;
2693 gatt_client->start_group_handle = start_handle;
2694 gatt_client->end_group_handle = end_handle;
2695 gatt_client->filter_with_uuid = true;
2696 gatt_client->uuid16 = 0;
2697 (void)memcpy(gatt_client->uuid128, uuid128, 16);
2698 gatt_client->characteristic_start_handle = 0;
2699 gatt_client->state = P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY;
2700 gatt_client_run();
2701 return ERROR_CODE_SUCCESS;
2702 }
2703
2704
gatt_client_discover_characteristics_for_service_by_uuid16(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_service_t * service,uint16_t uuid16)2705 uint8_t gatt_client_discover_characteristics_for_service_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_service_t * service, uint16_t uuid16){
2706 return gatt_client_discover_characteristics_for_handle_range_by_uuid16(callback, con_handle, service->start_group_handle, service->end_group_handle, uuid16);
2707 }
2708
gatt_client_discover_characteristics_for_service_by_uuid128(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_service_t * service,const uint8_t * uuid128)2709 uint8_t gatt_client_discover_characteristics_for_service_by_uuid128(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_service_t * service, const uint8_t * uuid128){
2710 return gatt_client_discover_characteristics_for_handle_range_by_uuid128(callback, con_handle, service->start_group_handle, service->end_group_handle, uuid128);
2711 }
2712
gatt_client_discover_characteristic_descriptors_with_context(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_characteristic_t * characteristic,uint16_t service_id,uint16_t connection_id)2713 uint8_t gatt_client_discover_characteristic_descriptors_with_context(btstack_packet_handler_t callback, hci_con_handle_t con_handle,
2714 gatt_client_characteristic_t * characteristic, uint16_t service_id, uint16_t connection_id){
2715 gatt_client_t * gatt_client;
2716 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2717 if (status != ERROR_CODE_SUCCESS){
2718 return status;
2719 }
2720
2721 gatt_client->service_id = service_id;
2722 gatt_client->connection_id = connection_id;
2723
2724 // check if there is space for characteristics descriptors
2725 if (characteristic->end_handle > characteristic->value_handle){
2726 gatt_client->callback = callback;
2727 gatt_client->start_group_handle = characteristic->value_handle + 1u;
2728 gatt_client->end_group_handle = characteristic->end_handle;
2729 gatt_client->state = P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY;
2730 gatt_client_run();
2731 } else {
2732 // schedule gatt complete event on next run loop iteration otherwise
2733 gatt_client->state = P_W2_EMIT_QUERY_COMPLETE_EVENT;
2734 gatt_client_deferred_event_emit.callback = gatt_client_emit_events;
2735 btstack_run_loop_execute_on_main_thread(&gatt_client_deferred_event_emit);
2736 }
2737 return ERROR_CODE_SUCCESS;
2738 }
2739
gatt_client_discover_characteristic_descriptors(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_characteristic_t * characteristic)2740 uint8_t gatt_client_discover_characteristic_descriptors(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){
2741 return gatt_client_discover_characteristic_descriptors_with_context(callback, con_handle, characteristic, 0, 0);
2742 }
2743
gatt_client_read_value_of_characteristic_using_value_handle_with_context(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t value_handle,uint16_t service_id,uint16_t connection_id)2744 uint8_t gatt_client_read_value_of_characteristic_using_value_handle_with_context(btstack_packet_handler_t callback,
2745 hci_con_handle_t con_handle,
2746 uint16_t value_handle,
2747 uint16_t service_id,
2748 uint16_t connection_id) {
2749 gatt_client_t * gatt_client;
2750 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2751 if (status != ERROR_CODE_SUCCESS){
2752 return status;
2753 }
2754
2755 gatt_client->callback = callback;
2756 gatt_client->service_id = service_id;
2757 gatt_client->connection_id = connection_id;
2758 gatt_client->attribute_handle = value_handle;
2759 gatt_client->attribute_offset = 0;
2760 gatt_client->state = P_W2_SEND_READ_CHARACTERISTIC_VALUE_QUERY;
2761 gatt_client_run();
2762 return ERROR_CODE_SUCCESS;
2763 }
2764
gatt_client_read_value_of_characteristic_using_value_handle(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t value_handle)2765 uint8_t gatt_client_read_value_of_characteristic_using_value_handle(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle){
2766 return gatt_client_read_value_of_characteristic_using_value_handle_with_context(callback, con_handle, value_handle, 0, 0);
2767
2768 }
2769
gatt_client_read_value_of_characteristics_by_uuid16(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t start_handle,uint16_t end_handle,uint16_t uuid16)2770 uint8_t gatt_client_read_value_of_characteristics_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t start_handle, uint16_t end_handle, uint16_t uuid16){
2771 gatt_client_t * gatt_client;
2772 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2773 if (status != ERROR_CODE_SUCCESS){
2774 return status;
2775 }
2776
2777 gatt_client->callback = callback;
2778 gatt_client->start_group_handle = start_handle;
2779 gatt_client->end_group_handle = end_handle;
2780 gatt_client->query_start_handle = start_handle;
2781 gatt_client->query_end_handle = end_handle;
2782 gatt_client->uuid16 = uuid16;
2783 uuid_add_bluetooth_prefix((uint8_t*) &(gatt_client->uuid128), uuid16);
2784 gatt_client->state = P_W2_SEND_READ_BY_TYPE_REQUEST;
2785 gatt_client_run();
2786 return ERROR_CODE_SUCCESS;
2787 }
2788
gatt_client_read_value_of_characteristics_by_uuid128(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t start_handle,uint16_t end_handle,const uint8_t * uuid128)2789 uint8_t gatt_client_read_value_of_characteristics_by_uuid128(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t start_handle, uint16_t end_handle, const uint8_t * uuid128){
2790 gatt_client_t * gatt_client;
2791 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2792 if (status != ERROR_CODE_SUCCESS){
2793 return status;
2794 }
2795
2796 gatt_client->callback = callback;
2797 gatt_client->start_group_handle = start_handle;
2798 gatt_client->end_group_handle = end_handle;
2799 gatt_client->query_start_handle = start_handle;
2800 gatt_client->query_end_handle = end_handle;
2801 gatt_client->uuid16 = 0;
2802 (void)memcpy(gatt_client->uuid128, uuid128, 16);
2803 gatt_client->state = P_W2_SEND_READ_BY_TYPE_REQUEST;
2804 gatt_client_run();
2805 return ERROR_CODE_SUCCESS;
2806 }
2807
2808
gatt_client_read_value_of_characteristic(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_characteristic_t * characteristic)2809 uint8_t gatt_client_read_value_of_characteristic(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){
2810 return gatt_client_read_value_of_characteristic_using_value_handle(callback, con_handle, characteristic->value_handle);
2811 }
2812
gatt_client_read_long_value_of_characteristic_using_value_handle_with_offset(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t value_handle,uint16_t offset)2813 uint8_t gatt_client_read_long_value_of_characteristic_using_value_handle_with_offset(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle, uint16_t offset){
2814 gatt_client_t * gatt_client;
2815 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2816 if (status != ERROR_CODE_SUCCESS){
2817 return status;
2818 }
2819
2820 gatt_client->callback = callback;
2821 gatt_client->attribute_handle = value_handle;
2822 gatt_client->attribute_offset = offset;
2823 gatt_client->state = P_W2_SEND_READ_BLOB_QUERY;
2824 gatt_client_run();
2825 return ERROR_CODE_SUCCESS;
2826 }
gatt_client_read_long_value_of_characteristic_using_value_handle_with_context(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t value_handle,uint16_t service_id,uint16_t connection_id)2827 uint8_t gatt_client_read_long_value_of_characteristic_using_value_handle_with_context(btstack_packet_handler_t callback,
2828 hci_con_handle_t con_handle, uint16_t value_handle,
2829 uint16_t service_id, uint16_t connection_id){
2830 // TODO: move into gatt_client_read_long_value_of_characteristic_using_value_handle_with_offset once
2831 // gatt_client_read_long_value_of_characteristic_using_value_handle_with_offset_and_context exists
2832 gatt_client_t * gatt_client;
2833 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2834 if (status != ERROR_CODE_SUCCESS){
2835 return status;
2836 }
2837 gatt_client->service_id = service_id;
2838 gatt_client->connection_id = connection_id;
2839 return gatt_client_read_long_value_of_characteristic_using_value_handle_with_offset(callback, con_handle, value_handle, 0);
2840 }
2841
gatt_client_read_long_value_of_characteristic_using_value_handle(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t value_handle)2842 uint8_t gatt_client_read_long_value_of_characteristic_using_value_handle(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle){
2843 return gatt_client_read_long_value_of_characteristic_using_value_handle_with_context(callback, con_handle, value_handle, 0, 0);
2844 }
2845
gatt_client_read_long_value_of_characteristic(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_characteristic_t * characteristic)2846 uint8_t gatt_client_read_long_value_of_characteristic(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){
2847 return gatt_client_read_long_value_of_characteristic_using_value_handle(callback, con_handle, characteristic->value_handle);
2848 }
2849
gatt_client_read_multiple_characteristic_values_with_state(btstack_packet_handler_t callback,hci_con_handle_t con_handle,int num_value_handles,uint16_t * value_handles,gatt_client_state_t state)2850 static uint8_t gatt_client_read_multiple_characteristic_values_with_state(btstack_packet_handler_t callback, hci_con_handle_t con_handle, int num_value_handles, uint16_t * value_handles, gatt_client_state_t state){
2851 gatt_client_t * gatt_client;
2852 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2853 if (status != ERROR_CODE_SUCCESS){
2854 return status;
2855 }
2856
2857 gatt_client->callback = callback;
2858 gatt_client->read_multiple_handle_count = num_value_handles;
2859 gatt_client->read_multiple_handles = value_handles;
2860 gatt_client->state = state;
2861 gatt_client_run();
2862 return ERROR_CODE_SUCCESS;
2863 }
2864
gatt_client_read_multiple_characteristic_values(btstack_packet_handler_t callback,hci_con_handle_t con_handle,int num_value_handles,uint16_t * value_handles)2865 uint8_t gatt_client_read_multiple_characteristic_values(btstack_packet_handler_t callback, hci_con_handle_t con_handle, int num_value_handles, uint16_t * value_handles){
2866 return gatt_client_read_multiple_characteristic_values_with_state(callback, con_handle, num_value_handles, value_handles, P_W2_SEND_READ_MULTIPLE_REQUEST);
2867 }
2868
2869 #ifdef ENABLE_GATT_OVER_EATT
gatt_client_read_multiple_variable_characteristic_values(btstack_packet_handler_t callback,hci_con_handle_t con_handle,int num_value_handles,uint16_t * value_handles)2870 uint8_t gatt_client_read_multiple_variable_characteristic_values(btstack_packet_handler_t callback, hci_con_handle_t con_handle, int num_value_handles, uint16_t * value_handles){
2871 return gatt_client_read_multiple_characteristic_values_with_state(callback, con_handle, num_value_handles, value_handles, P_W2_SEND_READ_MULTIPLE_VARIABLE_REQUEST);
2872 }
2873 #endif
2874
gatt_client_write_value_of_characteristic_without_response(hci_con_handle_t con_handle,uint16_t value_handle,uint16_t value_length,uint8_t * value)2875 uint8_t gatt_client_write_value_of_characteristic_without_response(hci_con_handle_t con_handle, uint16_t value_handle, uint16_t value_length, uint8_t * value){
2876 gatt_client_t * gatt_client;
2877 uint8_t status = gatt_client_provide_context_for_handle(con_handle, &gatt_client);
2878 if (status != ERROR_CODE_SUCCESS){
2879 return status;
2880 }
2881
2882 if (value_length > (gatt_client->mtu - 3u)) return GATT_CLIENT_VALUE_TOO_LONG;
2883 if (!att_dispatch_client_can_send_now(gatt_client->con_handle)) return GATT_CLIENT_BUSY;
2884
2885 return att_write_request(gatt_client, ATT_WRITE_COMMAND, value_handle, value_length, value);
2886 }
gatt_client_write_value_of_characteristic_with_context(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t value_handle,uint16_t value_length,uint8_t * value,uint16_t service_id,uint16_t connection_id)2887 uint8_t gatt_client_write_value_of_characteristic_with_context(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle,
2888 uint16_t value_length, uint8_t * value, uint16_t service_id, uint16_t connection_id){
2889 gatt_client_t * gatt_client;
2890 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2891 if (status != ERROR_CODE_SUCCESS){
2892 return status;
2893 }
2894
2895 gatt_client->callback = callback;
2896 gatt_client->service_id = service_id;
2897 gatt_client->connection_id = connection_id;
2898 gatt_client->attribute_handle = value_handle;
2899 gatt_client->attribute_length = value_length;
2900 gatt_client->attribute_value = value;
2901 gatt_client->state = P_W2_SEND_WRITE_CHARACTERISTIC_VALUE;
2902 gatt_client_run();
2903 return ERROR_CODE_SUCCESS;
2904 }
gatt_client_write_value_of_characteristic(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t value_handle,uint16_t value_length,uint8_t * value)2905 uint8_t gatt_client_write_value_of_characteristic(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle, uint16_t value_length, uint8_t * value) {
2906 return gatt_client_write_value_of_characteristic_with_context(callback, con_handle, value_handle, value_length, value, 0, 0);
2907 }
2908
gatt_client_write_long_value_of_characteristic_with_offset(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t value_handle,uint16_t offset,uint16_t value_length,uint8_t * value)2909 uint8_t gatt_client_write_long_value_of_characteristic_with_offset(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle, uint16_t offset, uint16_t value_length, uint8_t * value){
2910 gatt_client_t * gatt_client;
2911 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2912 if (status != ERROR_CODE_SUCCESS){
2913 return status;
2914 }
2915
2916 gatt_client->callback = callback;
2917 gatt_client->attribute_handle = value_handle;
2918 gatt_client->attribute_length = value_length;
2919 gatt_client->attribute_offset = offset;
2920 gatt_client->attribute_value = value;
2921 gatt_client->state = P_W2_PREPARE_WRITE;
2922 gatt_client_run();
2923 return ERROR_CODE_SUCCESS;
2924 }
2925
gatt_client_write_long_value_of_characteristic_with_context(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t value_handle,uint16_t value_length,uint8_t * value,uint16_t service_id,uint16_t connection_id)2926 uint8_t gatt_client_write_long_value_of_characteristic_with_context(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle, uint16_t value_length, uint8_t * value, uint16_t service_id, uint16_t connection_id){
2927 // TODO: move into gatt_client_write_long_value_of_characteristic_with_offset once gatt_client_write_long_value_of_characteristic_with_offset_with_context exists
2928 gatt_client_t * gatt_client;
2929 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2930 if (status != ERROR_CODE_SUCCESS){
2931 return status;
2932 }
2933 gatt_client->service_id = service_id;
2934 gatt_client->connection_id = connection_id;
2935 return gatt_client_write_long_value_of_characteristic_with_offset(callback, con_handle, value_handle, 0, value_length, value);
2936 }
2937
gatt_client_write_long_value_of_characteristic(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t value_handle,uint16_t value_length,uint8_t * value)2938 uint8_t gatt_client_write_long_value_of_characteristic(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle, uint16_t value_length, uint8_t * value){
2939 return gatt_client_write_long_value_of_characteristic_with_context(callback, con_handle, value_handle, value_length, value, 0, 0);
2940 }
2941
gatt_client_reliable_write_long_value_of_characteristic(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t value_handle,uint16_t value_length,uint8_t * value)2942 uint8_t gatt_client_reliable_write_long_value_of_characteristic(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle, uint16_t value_length, uint8_t * value){
2943 gatt_client_t * gatt_client;
2944 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2945 if (status != ERROR_CODE_SUCCESS){
2946 return status;
2947 }
2948
2949 gatt_client->callback = callback;
2950 gatt_client->attribute_handle = value_handle;
2951 gatt_client->attribute_length = value_length;
2952 gatt_client->attribute_offset = 0;
2953 gatt_client->attribute_value = value;
2954 gatt_client->state = P_W2_PREPARE_RELIABLE_WRITE;
2955 gatt_client_run();
2956 return ERROR_CODE_SUCCESS;
2957 }
2958
gatt_client_write_client_characteristic_configuration_with_context(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_characteristic_t * characteristic,uint16_t configuration,uint16_t service_id,uint16_t connection_id)2959 uint8_t gatt_client_write_client_characteristic_configuration_with_context(btstack_packet_handler_t callback, hci_con_handle_t con_handle,
2960 gatt_client_characteristic_t * characteristic, uint16_t configuration, uint16_t service_id, uint16_t connection_id){
2961 gatt_client_t * gatt_client;
2962 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
2963 if (status != ERROR_CODE_SUCCESS){
2964 return status;
2965 }
2966
2967 if (configuration > 3){
2968 return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE;
2969 }
2970
2971 if ( (configuration & GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION) &&
2972 ((characteristic->properties & ATT_PROPERTY_NOTIFY) == 0u)) {
2973 log_info("gatt_client_write_client_characteristic_configuration: GATT_CLIENT_CHARACTERISTIC_NOTIFICATION_NOT_SUPPORTED");
2974 return GATT_CLIENT_CHARACTERISTIC_NOTIFICATION_NOT_SUPPORTED;
2975 } else if ( (configuration & GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION) &&
2976 ((characteristic->properties & ATT_PROPERTY_INDICATE) == 0u)){
2977 log_info("gatt_client_write_client_characteristic_configuration: GATT_CLIENT_CHARACTERISTIC_INDICATION_NOT_SUPPORTED");
2978 return GATT_CLIENT_CHARACTERISTIC_INDICATION_NOT_SUPPORTED;
2979 }
2980
2981 gatt_client->callback = callback;
2982 gatt_client->service_id = service_id;
2983 gatt_client->connection_id = connection_id;
2984 gatt_client->start_group_handle = characteristic->value_handle;
2985 gatt_client->end_group_handle = characteristic->end_handle;
2986 little_endian_store_16(gatt_client->client_characteristic_configuration_value, 0, configuration);
2987
2988 #ifdef ENABLE_GATT_FIND_INFORMATION_FOR_CCC_DISCOVERY
2989 gatt_client->state = P_W2_SEND_FIND_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY;
2990 #else
2991 gatt_client->state = P_W2_SEND_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY;
2992 #endif
2993 gatt_client_run();
2994 return ERROR_CODE_SUCCESS;
2995 }
2996
gatt_client_write_client_characteristic_configuration(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_characteristic_t * characteristic,uint16_t configuration)2997 uint8_t gatt_client_write_client_characteristic_configuration(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic, uint16_t configuration){
2998 return gatt_client_write_client_characteristic_configuration_with_context(callback, con_handle, characteristic, configuration, 0, 0);
2999 }
3000
gatt_client_read_characteristic_descriptor_using_descriptor_handle(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t descriptor_handle)3001 uint8_t gatt_client_read_characteristic_descriptor_using_descriptor_handle(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t descriptor_handle){
3002 gatt_client_t * gatt_client;
3003 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
3004 if (status != ERROR_CODE_SUCCESS){
3005 return status;
3006 }
3007
3008 gatt_client->callback = callback;
3009 gatt_client->attribute_handle = descriptor_handle;
3010
3011 gatt_client->state = P_W2_SEND_READ_CHARACTERISTIC_DESCRIPTOR_QUERY;
3012 gatt_client_run();
3013 return ERROR_CODE_SUCCESS;
3014 }
3015
gatt_client_read_characteristic_descriptor(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_characteristic_descriptor_t * descriptor)3016 uint8_t gatt_client_read_characteristic_descriptor(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_descriptor_t * descriptor){
3017 return gatt_client_read_characteristic_descriptor_using_descriptor_handle(callback, con_handle, descriptor->handle);
3018 }
3019
gatt_client_read_long_characteristic_descriptor_using_descriptor_handle_with_offset(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t descriptor_handle,uint16_t offset)3020 uint8_t gatt_client_read_long_characteristic_descriptor_using_descriptor_handle_with_offset(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t descriptor_handle, uint16_t offset){
3021 gatt_client_t * gatt_client;
3022 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
3023 if (status != ERROR_CODE_SUCCESS){
3024 return status;
3025 }
3026
3027 gatt_client->callback = callback;
3028 gatt_client->attribute_handle = descriptor_handle;
3029 gatt_client->attribute_offset = offset;
3030 gatt_client->state = P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY;
3031 gatt_client_run();
3032 return ERROR_CODE_SUCCESS;
3033 }
3034
gatt_client_read_long_characteristic_descriptor_using_descriptor_handle(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t descriptor_handle)3035 uint8_t gatt_client_read_long_characteristic_descriptor_using_descriptor_handle(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t descriptor_handle){
3036 return gatt_client_read_long_characteristic_descriptor_using_descriptor_handle_with_offset(callback, con_handle, descriptor_handle, 0);
3037 }
3038
gatt_client_read_long_characteristic_descriptor(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_characteristic_descriptor_t * descriptor)3039 uint8_t gatt_client_read_long_characteristic_descriptor(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_descriptor_t * descriptor){
3040 return gatt_client_read_long_characteristic_descriptor_using_descriptor_handle(callback, con_handle, descriptor->handle);
3041 }
3042
gatt_client_write_characteristic_descriptor_using_descriptor_handle(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t descriptor_handle,uint16_t value_length,uint8_t * value)3043 uint8_t gatt_client_write_characteristic_descriptor_using_descriptor_handle(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t descriptor_handle, uint16_t value_length, uint8_t * value){
3044 gatt_client_t * gatt_client;
3045 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
3046 if (status != ERROR_CODE_SUCCESS){
3047 return status;
3048 }
3049
3050 gatt_client->callback = callback;
3051 gatt_client->attribute_handle = descriptor_handle;
3052 gatt_client->attribute_length = value_length;
3053 gatt_client->attribute_offset = 0;
3054 gatt_client->attribute_value = value;
3055 gatt_client->state = P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR;
3056 gatt_client_run();
3057 return ERROR_CODE_SUCCESS;
3058 }
3059
gatt_client_write_characteristic_descriptor(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_characteristic_descriptor_t * descriptor,uint16_t value_length,uint8_t * value)3060 uint8_t gatt_client_write_characteristic_descriptor(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_descriptor_t * descriptor, uint16_t value_length, uint8_t * value){
3061 return gatt_client_write_characteristic_descriptor_using_descriptor_handle(callback, con_handle, descriptor->handle, value_length, value);
3062 }
3063
gatt_client_write_long_characteristic_descriptor_using_descriptor_handle_with_offset(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t descriptor_handle,uint16_t offset,uint16_t value_length,uint8_t * value)3064 uint8_t gatt_client_write_long_characteristic_descriptor_using_descriptor_handle_with_offset(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t descriptor_handle, uint16_t offset, uint16_t value_length, uint8_t * value){
3065 gatt_client_t * gatt_client;
3066 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
3067 if (status != ERROR_CODE_SUCCESS){
3068 return status;
3069 }
3070
3071 gatt_client->callback = callback;
3072 gatt_client->attribute_handle = descriptor_handle;
3073 gatt_client->attribute_length = value_length;
3074 gatt_client->attribute_offset = offset;
3075 gatt_client->attribute_value = value;
3076 gatt_client->state = P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR;
3077 gatt_client_run();
3078 return ERROR_CODE_SUCCESS;
3079 }
3080
gatt_client_write_long_characteristic_descriptor_using_descriptor_handle(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t descriptor_handle,uint16_t value_length,uint8_t * value)3081 uint8_t gatt_client_write_long_characteristic_descriptor_using_descriptor_handle(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t descriptor_handle, uint16_t value_length, uint8_t * value){
3082 return gatt_client_write_long_characteristic_descriptor_using_descriptor_handle_with_offset(callback, con_handle, descriptor_handle, 0, value_length, value);
3083 }
3084
gatt_client_write_long_characteristic_descriptor(btstack_packet_handler_t callback,hci_con_handle_t con_handle,gatt_client_characteristic_descriptor_t * descriptor,uint16_t value_length,uint8_t * value)3085 uint8_t gatt_client_write_long_characteristic_descriptor(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_descriptor_t * descriptor, uint16_t value_length, uint8_t * value){
3086 return gatt_client_write_long_characteristic_descriptor_using_descriptor_handle(callback, con_handle, descriptor->handle, value_length, value);
3087 }
3088
3089 /**
3090 * @brief -> gatt complete event
3091 */
gatt_client_prepare_write(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint16_t attribute_handle,uint16_t offset,uint16_t value_length,uint8_t * value)3092 uint8_t gatt_client_prepare_write(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t offset, uint16_t value_length, uint8_t * value){
3093 gatt_client_t * gatt_client;
3094 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
3095 if (status != ERROR_CODE_SUCCESS){
3096 return status;
3097 }
3098
3099 gatt_client->callback = callback;
3100 gatt_client->attribute_handle = attribute_handle;
3101 gatt_client->attribute_length = value_length;
3102 gatt_client->attribute_offset = offset;
3103 gatt_client->attribute_value = value;
3104 gatt_client->state = P_W2_PREPARE_WRITE_SINGLE;
3105 gatt_client_run();
3106 return ERROR_CODE_SUCCESS;
3107 }
3108
3109 /**
3110 * @brief -> gatt complete event
3111 */
gatt_client_execute_write(btstack_packet_handler_t callback,hci_con_handle_t con_handle)3112 uint8_t gatt_client_execute_write(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
3113 gatt_client_t * gatt_client;
3114 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
3115 if (status != ERROR_CODE_SUCCESS){
3116 return status;
3117 }
3118
3119 gatt_client->callback = callback;
3120 gatt_client->state = P_W2_EXECUTE_PREPARED_WRITE;
3121 gatt_client_run();
3122 return ERROR_CODE_SUCCESS;
3123 }
3124
3125 /**
3126 * @brief -> gatt complete event
3127 */
gatt_client_cancel_write(btstack_packet_handler_t callback,hci_con_handle_t con_handle)3128 uint8_t gatt_client_cancel_write(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
3129 gatt_client_t * gatt_client;
3130 uint8_t status = gatt_client_provide_context_for_request(con_handle, &gatt_client);
3131 if (status != ERROR_CODE_SUCCESS){
3132 return status;
3133 }
3134
3135 gatt_client->callback = callback;
3136 gatt_client->state = P_W2_CANCEL_PREPARED_WRITE;
3137 gatt_client_run();
3138 return ERROR_CODE_SUCCESS;
3139 }
3140
gatt_client_deserialize_service(const uint8_t * packet,int offset,gatt_client_service_t * service)3141 void gatt_client_deserialize_service(const uint8_t *packet, int offset, gatt_client_service_t * service){
3142 service->start_group_handle = little_endian_read_16(packet, offset);
3143 service->end_group_handle = little_endian_read_16(packet, offset + 2);
3144 reverse_128(&packet[offset + 4], service->uuid128);
3145 if (uuid_has_bluetooth_prefix(service->uuid128)){
3146 service->uuid16 = big_endian_read_32(service->uuid128, 0);
3147 } else {
3148 service->uuid16 = 0;
3149 }
3150 }
3151
gatt_client_deserialize_characteristic(const uint8_t * packet,int offset,gatt_client_characteristic_t * characteristic)3152 void gatt_client_deserialize_characteristic(const uint8_t * packet, int offset, gatt_client_characteristic_t * characteristic){
3153 characteristic->start_handle = little_endian_read_16(packet, offset);
3154 characteristic->value_handle = little_endian_read_16(packet, offset + 2);
3155 characteristic->end_handle = little_endian_read_16(packet, offset + 4);
3156 characteristic->properties = little_endian_read_16(packet, offset + 6);
3157 reverse_128(&packet[offset+8], characteristic->uuid128);
3158 if (uuid_has_bluetooth_prefix(characteristic->uuid128)){
3159 characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0);
3160 } else {
3161 characteristic->uuid16 = 0;
3162 }
3163 }
3164
gatt_client_deserialize_characteristic_descriptor(const uint8_t * packet,int offset,gatt_client_characteristic_descriptor_t * descriptor)3165 void gatt_client_deserialize_characteristic_descriptor(const uint8_t * packet, int offset, gatt_client_characteristic_descriptor_t * descriptor){
3166 descriptor->handle = little_endian_read_16(packet, offset);
3167 reverse_128(&packet[offset+2], descriptor->uuid128);
3168 if (uuid_has_bluetooth_prefix(descriptor->uuid128)){
3169 descriptor->uuid16 = big_endian_read_32(descriptor->uuid128, 0);
3170 } else {
3171 descriptor->uuid16 = 0;
3172 }
3173 }
3174
gatt_client_send_mtu_negotiation(btstack_packet_handler_t callback,hci_con_handle_t con_handle)3175 void gatt_client_send_mtu_negotiation(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
3176 gatt_client_t * gatt_client;
3177 uint8_t status = gatt_client_provide_context_for_handle(con_handle, &gatt_client);
3178 if (status != ERROR_CODE_SUCCESS){
3179 return;
3180 }
3181 if (gatt_client->mtu_state == MTU_AUTO_EXCHANGE_DISABLED){
3182 gatt_client->callback = callback;
3183 gatt_client->mtu_state = SEND_MTU_EXCHANGE;
3184 gatt_client_run();
3185 }
3186 }
3187
gatt_client_request_to_write_without_response(btstack_context_callback_registration_t * callback_registration,hci_con_handle_t con_handle)3188 uint8_t gatt_client_request_to_write_without_response(btstack_context_callback_registration_t * callback_registration, hci_con_handle_t con_handle){
3189 gatt_client_t * gatt_client;
3190 uint8_t status = gatt_client_provide_context_for_handle(con_handle, &gatt_client);
3191 if (status != ERROR_CODE_SUCCESS){
3192 return status;
3193 }
3194 bool added = btstack_linked_list_add_tail(&gatt_client->write_without_response_requests, (btstack_linked_item_t*) callback_registration);
3195 if (added == false){
3196 return ERROR_CODE_COMMAND_DISALLOWED;
3197 } else {
3198 att_dispatch_client_request_can_send_now_event(gatt_client->con_handle);
3199 return ERROR_CODE_SUCCESS;
3200 }
3201 }
3202
gatt_client_request_to_send_gatt_query(btstack_context_callback_registration_t * callback_registration,hci_con_handle_t con_handle)3203 uint8_t gatt_client_request_to_send_gatt_query(btstack_context_callback_registration_t * callback_registration, hci_con_handle_t con_handle){
3204 gatt_client_t * gatt_client;
3205 uint8_t status = gatt_client_provide_context_for_handle(con_handle, &gatt_client);
3206 if (status != ERROR_CODE_SUCCESS){
3207 return status;
3208 }
3209 bool added = btstack_linked_list_add_tail(&gatt_client->query_requests, (btstack_linked_item_t*) callback_registration);
3210 if (added == false){
3211 return ERROR_CODE_COMMAND_DISALLOWED;
3212 } else {
3213 gatt_client_notify_can_send_query(gatt_client);
3214 return ERROR_CODE_SUCCESS;
3215 }
3216 }
3217
gatt_client_remove_gatt_query(btstack_context_callback_registration_t * callback_registration,hci_con_handle_t con_handle)3218 uint8_t gatt_client_remove_gatt_query(btstack_context_callback_registration_t * callback_registration, hci_con_handle_t con_handle){
3219 gatt_client_t * gatt_client;
3220 uint8_t status = gatt_client_provide_context_for_handle(con_handle, &gatt_client);
3221 if (status != ERROR_CODE_SUCCESS){
3222 return status;
3223 }
3224 (void)btstack_linked_list_remove(&gatt_client->query_requests, (btstack_linked_item_t*) callback_registration);
3225 return ERROR_CODE_SUCCESS;
3226 }
3227
gatt_client_request_can_write_without_response_event(btstack_packet_handler_t callback,hci_con_handle_t con_handle)3228 uint8_t gatt_client_request_can_write_without_response_event(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
3229 gatt_client_t * gatt_client;
3230 uint8_t status = gatt_client_provide_context_for_handle(con_handle, &gatt_client);
3231 if (status != ERROR_CODE_SUCCESS){
3232 return status;
3233 }
3234 if (gatt_client->write_without_response_callback != NULL){
3235 return GATT_CLIENT_IN_WRONG_STATE;
3236 }
3237 gatt_client->write_without_response_callback = callback;
3238 att_dispatch_client_request_can_send_now_event(gatt_client->con_handle);
3239 return ERROR_CODE_SUCCESS;
3240 }
3241
gatt_client_att_status_to_error_code(uint8_t att_error_code)3242 uint8_t gatt_client_att_status_to_error_code(uint8_t att_error_code){
3243 switch (att_error_code){
3244 case ATT_ERROR_SUCCESS:
3245 return ERROR_CODE_SUCCESS;
3246 case ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH:
3247 return ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE;
3248 default:
3249 log_info("ATT ERROR 0x%02x mapped to ERROR_CODE_UNSPECIFIED_ERROR", att_error_code);
3250 return ERROR_CODE_UNSPECIFIED_ERROR;
3251 }
3252 }
3253
3254 #ifdef ENABLE_GATT_CLIENT_SERVICE_CHANGED
gatt_client_add_service_changed_handler(btstack_packet_callback_registration_t * callback)3255 void gatt_client_add_service_changed_handler(btstack_packet_callback_registration_t * callback) {
3256 btstack_linked_list_add_tail(&gatt_client_service_changed_handler, (btstack_linked_item_t*) callback);
3257 }
3258
gatt_client_remove_service_changed_handler(btstack_packet_callback_registration_t * callback)3259 void gatt_client_remove_service_changed_handler(btstack_packet_callback_registration_t * callback){
3260 btstack_linked_list_remove(&gatt_client_service_changed_handler, (btstack_linked_item_t*) callback);
3261 }
3262 #endif
3263
3264 #if defined(ENABLE_GATT_OVER_CLASSIC) || defined(ENABLE_GATT_OVER_EATT)
3265
3266 #include "hci_event.h"
3267
3268 static const hci_event_t gatt_client_connected = {
3269 GATT_EVENT_CONNECTED, 0, "11BH"
3270 };
3271
3272 static const hci_event_t gatt_client_disconnected = {
3273 GATT_EVENT_DISCONNECTED, 0, "H"
3274 };
3275
3276 static void
gatt_client_emit_connected(btstack_packet_handler_t callback,uint8_t status,bd_addr_type_t addr_type,bd_addr_t addr,hci_con_handle_t con_handle)3277 gatt_client_emit_connected(btstack_packet_handler_t callback, uint8_t status, bd_addr_type_t addr_type, bd_addr_t addr,
3278 hci_con_handle_t con_handle) {
3279 uint8_t buffer[20];
3280 uint16_t len = hci_event_create_from_template_and_arguments(buffer, sizeof(buffer), &gatt_client_connected, status, addr_type, addr, con_handle);
3281 (*callback)(HCI_EVENT_PACKET, 0, buffer, len);
3282 }
3283
3284 #endif
3285
3286 #ifdef ENABLE_GATT_OVER_CLASSIC
3287
3288 #include "bluetooth_psm.h"
3289
3290 // single active SDP query
3291 static gatt_client_t * gatt_client_classic_active_sdp_query;
3292
3293 // macos protocol descriptor list requires 16 bytes
3294 static uint8_t gatt_client_classic_sdp_buffer[32];
3295
3296
gatt_client_get_context_for_classic_addr(bd_addr_t addr)3297 static gatt_client_t * gatt_client_get_context_for_classic_addr(bd_addr_t addr){
3298 btstack_linked_item_t *it;
3299 for (it = (btstack_linked_item_t *) gatt_client_connections; it != NULL; it = it->next){
3300 gatt_client_t * gatt_client = (gatt_client_t *) it;
3301 if (memcmp(gatt_client->addr, addr, 6) == 0){
3302 return gatt_client;
3303 }
3304 }
3305 return NULL;
3306 }
3307
gatt_client_get_context_for_l2cap_cid(uint16_t l2cap_cid)3308 static gatt_client_t * gatt_client_get_context_for_l2cap_cid(uint16_t l2cap_cid){
3309 btstack_linked_item_t *it;
3310 for (it = (btstack_linked_item_t *) gatt_client_connections; it != NULL; it = it->next){
3311 gatt_client_t * gatt_client = (gatt_client_t *) it;
3312 if (gatt_client->l2cap_cid == l2cap_cid){
3313 return gatt_client;
3314 }
3315 }
3316 return NULL;
3317 }
3318
gatt_client_classic_handle_connected(gatt_client_t * gatt_client,uint8_t status)3319 static void gatt_client_classic_handle_connected(gatt_client_t * gatt_client, uint8_t status){
3320 // cache peer information
3321 bd_addr_t addr;
3322 // cppcheck-suppress uninitvar ; addr is reported as uninitialized although it's the destination of the memcpy
3323 memcpy(addr, gatt_client->addr, 6);
3324 bd_addr_type_t addr_type = gatt_client->addr_type;
3325 gatt_client->addr_type = BD_ADDR_TYPE_ACL;
3326 hci_con_handle_t con_handle = gatt_client->con_handle;
3327 btstack_packet_handler_t callback = gatt_client->callback;
3328
3329 if (status != ERROR_CODE_SUCCESS){
3330 btstack_linked_list_remove(&gatt_client_connections, (btstack_linked_item_t *) gatt_client);
3331 btstack_memory_gatt_client_free(gatt_client);
3332 }
3333
3334 gatt_client_emit_connected(callback, status, addr_type, addr, con_handle);
3335 }
3336
gatt_client_classic_retry(btstack_timer_source_t * ts)3337 static void gatt_client_classic_retry(btstack_timer_source_t * ts){
3338 gatt_client_t * gatt_client = gatt_client_for_timer(ts);
3339 if (gatt_client != NULL){
3340 gatt_client->state = P_W4_L2CAP_CONNECTION;
3341 att_dispatch_classic_connect(gatt_client->addr, gatt_client->l2cap_psm, &gatt_client->l2cap_cid);
3342 }
3343 }
3344
gatt_client_classic_handle_disconnected(gatt_client_t * gatt_client)3345 static void gatt_client_classic_handle_disconnected(gatt_client_t * gatt_client){
3346
3347 gatt_client_report_error_if_pending(gatt_client, ATT_ERROR_HCI_DISCONNECT_RECEIVED);
3348 gatt_client_timeout_stop(gatt_client);
3349
3350 hci_con_handle_t con_handle = gatt_client->con_handle;
3351 btstack_packet_handler_t callback = gatt_client->callback;
3352 btstack_linked_list_remove(&gatt_client_connections, (btstack_linked_item_t *) gatt_client);
3353 btstack_memory_gatt_client_free(gatt_client);
3354
3355 uint8_t buffer[20];
3356 uint16_t len = hci_event_create_from_template_and_arguments(buffer, sizeof(buffer), &gatt_client_disconnected, con_handle);
3357 (*callback)(HCI_EVENT_PACKET, 0, buffer, len);
3358 }
3359
gatt_client_handle_sdp_client_query_attribute_value(gatt_client_t * connection,uint8_t * packet)3360 static void gatt_client_handle_sdp_client_query_attribute_value(gatt_client_t * connection, uint8_t *packet){
3361 des_iterator_t des_list_it;
3362 des_iterator_t prot_it;
3363
3364 if (sdp_event_query_attribute_byte_get_attribute_length(packet) <= sizeof(gatt_client_classic_sdp_buffer)) {
3365 gatt_client_classic_sdp_buffer[sdp_event_query_attribute_byte_get_data_offset(packet)] = sdp_event_query_attribute_byte_get_data(packet);
3366 if ((uint16_t)(sdp_event_query_attribute_byte_get_data_offset(packet)+1) == sdp_event_query_attribute_byte_get_attribute_length(packet)) {
3367 switch(sdp_event_query_attribute_byte_get_attribute_id(packet)) {
3368 case BLUETOOTH_ATTRIBUTE_PROTOCOL_DESCRIPTOR_LIST:
3369 for (des_iterator_init(&des_list_it, gatt_client_classic_sdp_buffer); des_iterator_has_more(&des_list_it); des_iterator_next(&des_list_it)) {
3370 uint8_t *des_element;
3371 uint8_t *element;
3372 uint32_t uuid;
3373
3374 if (des_iterator_get_type(&des_list_it) != DE_DES) continue;
3375
3376 des_element = des_iterator_get_element(&des_list_it);
3377 des_iterator_init(&prot_it, des_element);
3378 element = des_iterator_get_element(&prot_it);
3379
3380 if (de_get_element_type(element) != DE_UUID) continue;
3381
3382 uuid = de_get_uuid32(element);
3383 des_iterator_next(&prot_it);
3384 // we assume that the even if there are both roles supported, remote device uses the same psm and avdtp version for both
3385 switch (uuid){
3386 case BLUETOOTH_PROTOCOL_L2CAP:
3387 if (!des_iterator_has_more(&prot_it)) continue;
3388 de_element_get_uint16(des_iterator_get_element(&prot_it), &connection->l2cap_psm);
3389 break;
3390 default:
3391 break;
3392 }
3393 }
3394 break;
3395
3396 default:
3397 break;
3398 }
3399 }
3400 }
3401 }
3402
gatt_client_classic_sdp_handler(uint8_t packet_type,uint16_t handle,uint8_t * packet,uint16_t size)3403 static void gatt_client_classic_sdp_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){
3404 gatt_client_t * gatt_client = gatt_client_classic_active_sdp_query;
3405 btstack_assert(gatt_client != NULL);
3406 uint8_t status;
3407
3408 // TODO: handle sdp events, get l2cap psm
3409 switch (hci_event_packet_get_type(packet)){
3410 case SDP_EVENT_QUERY_ATTRIBUTE_VALUE:
3411 gatt_client_handle_sdp_client_query_attribute_value(gatt_client, packet);
3412 // TODO:
3413 return;
3414 case SDP_EVENT_QUERY_COMPLETE:
3415 status = sdp_event_query_complete_get_status(packet);
3416 gatt_client_classic_active_sdp_query = NULL;
3417 log_info("l2cap psm: %0x, status %02x", gatt_client->l2cap_psm, status);
3418 if (status != ERROR_CODE_SUCCESS) break;
3419 if (gatt_client->l2cap_psm == 0) {
3420 status = SDP_SERVICE_NOT_FOUND;
3421 break;
3422 }
3423 break;
3424 default:
3425 btstack_assert(false);
3426 return;
3427 }
3428
3429 // done
3430 if (status == ERROR_CODE_SUCCESS){
3431 gatt_client->state = P_W4_L2CAP_CONNECTION;
3432 status = att_dispatch_classic_connect(gatt_client->addr, gatt_client->l2cap_psm, &gatt_client->l2cap_cid);
3433 }
3434 if (status != ERROR_CODE_SUCCESS) {
3435 gatt_client_classic_handle_connected(gatt_client, status);
3436 }
3437 }
3438
gatt_client_classic_sdp_start(void * context)3439 static void gatt_client_classic_sdp_start(void * context){
3440 gatt_client_classic_active_sdp_query = (gatt_client_t *) context;
3441 gatt_client_classic_active_sdp_query->state = P_W4_SDP_QUERY;
3442 sdp_client_query_uuid16(gatt_client_classic_sdp_handler, gatt_client_classic_active_sdp_query->addr, ORG_BLUETOOTH_SERVICE_GENERIC_ATTRIBUTE);
3443 }
3444
gatt_client_classic_emit_connected(void * context)3445 static void gatt_client_classic_emit_connected(void * context){
3446 gatt_client_t * gatt_client = (gatt_client_t *) context;
3447 gatt_client->state = P_READY;
3448 gatt_client_emit_connected(gatt_client->callback, ERROR_CODE_SUCCESS, gatt_client->addr_type, gatt_client->addr, gatt_client->con_handle);
3449 }
3450
gatt_client_classic_connect(btstack_packet_handler_t callback,bd_addr_t addr)3451 uint8_t gatt_client_classic_connect(btstack_packet_handler_t callback, bd_addr_t addr){
3452 gatt_client_t * gatt_client = gatt_client_get_context_for_classic_addr(addr);
3453 if (gatt_client != NULL){
3454 return ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS;
3455 }
3456 gatt_client = btstack_memory_gatt_client_get();
3457 if (gatt_client == NULL){
3458 return ERROR_CODE_MEMORY_CAPACITY_EXCEEDED;
3459 }
3460 // init state
3461 gatt_client->bearer_type = ATT_BEARER_UNENHANCED_CLASSIC;
3462 gatt_client->con_handle = HCI_CON_HANDLE_INVALID;
3463 memcpy(gatt_client->addr, addr, 6);
3464 gatt_client->addr_type = BD_ADDR_TYPE_ACL;
3465 gatt_client->mtu = ATT_DEFAULT_MTU;
3466 gatt_client->security_level = LEVEL_0;
3467 gatt_client->mtu_state = MTU_AUTO_EXCHANGE_DISABLED;
3468 gatt_client->callback = callback;
3469 #ifdef ENABLE_GATT_OVER_EATT
3470 gatt_client->eatt_state = GATT_CLIENT_EATT_IDLE;
3471 #endif
3472 btstack_linked_list_add(&gatt_client_connections, (btstack_linked_item_t*)gatt_client);
3473
3474 // schedule emitted event if already connected, otherwise
3475 bool already_connected = false;
3476 hci_connection_t * hci_connection = hci_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_ACL);
3477 if (hci_connection != NULL){
3478 if (hci_connection->att_server.l2cap_cid != 0){
3479 already_connected = true;
3480 }
3481 }
3482 gatt_client->callback_request.context = gatt_client;
3483 if (already_connected){
3484 gatt_client->con_handle = hci_connection->con_handle;
3485 gatt_client->callback_request.callback = &gatt_client_classic_emit_connected;
3486 gatt_client->state = P_W2_EMIT_CONNECTED;
3487 btstack_run_loop_execute_on_main_thread(&gatt_client->callback_request);
3488 } else {
3489 gatt_client->callback_request.callback = &gatt_client_classic_sdp_start;
3490 gatt_client->state = P_W2_SDP_QUERY;
3491 sdp_client_register_query_callback(&gatt_client->callback_request);
3492 }
3493 return ERROR_CODE_SUCCESS;
3494 }
3495
gatt_client_classic_disconnect(btstack_packet_handler_t callback,hci_con_handle_t con_handle)3496 uint8_t gatt_client_classic_disconnect(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
3497 gatt_client_t * gatt_client = gatt_client_get_context_for_handle(con_handle);
3498 if (gatt_client == NULL){
3499 return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
3500 }
3501 gatt_client->callback = callback;
3502 return l2cap_disconnect(gatt_client->l2cap_cid);
3503 }
3504 #endif
3505
3506 #ifdef ENABLE_GATT_OVER_EATT
3507
3508 #define MAX_NR_EATT_CHANNELS 5
3509
3510 static void gatt_client_le_enhanced_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
3511
gatt_client_le_enhanced_num_eatt_clients_in_state(gatt_client_t * gatt_client,gatt_client_state_t state)3512 static uint8_t gatt_client_le_enhanced_num_eatt_clients_in_state(gatt_client_t * gatt_client, gatt_client_state_t state){
3513 uint8_t num_clients = 0;
3514 btstack_linked_list_iterator_t it;
3515 btstack_linked_list_iterator_init(&it, &gatt_client->eatt_clients);
3516 while (btstack_linked_list_iterator_has_next(&it)){
3517 gatt_client_t * eatt_client = (gatt_client_t *) btstack_linked_list_iterator_next(&it);
3518 if (eatt_client->state == state){
3519 num_clients++;
3520 }
3521 }
3522 return num_clients;
3523 }
3524
gatt_client_eatt_finalize(gatt_client_t * gatt_client)3525 static void gatt_client_eatt_finalize(gatt_client_t * gatt_client) {
3526 // free eatt clients
3527 btstack_linked_list_iterator_t it;
3528 btstack_linked_list_iterator_init(&it, &gatt_client_connections);
3529 while (btstack_linked_list_iterator_has_next(&it)) {
3530 gatt_client_t *eatt_client = (gatt_client_t *) btstack_linked_list_iterator_next(&it);
3531 btstack_linked_list_iterator_remove(&it);
3532 btstack_memory_gatt_client_free(eatt_client);
3533 }
3534 }
3535
3536 // all channels connected
gatt_client_le_enhanced_handle_connected(gatt_client_t * gatt_client,uint8_t status)3537 static void gatt_client_le_enhanced_handle_connected(gatt_client_t * gatt_client, uint8_t status) {
3538 if (status == ERROR_CODE_SUCCESS){
3539 uint8_t num_ready = gatt_client_le_enhanced_num_eatt_clients_in_state(gatt_client, P_READY);
3540 if (num_ready > 0){
3541 gatt_client->eatt_state = GATT_CLIENT_EATT_READY;
3542 // free unused channels
3543 btstack_linked_list_iterator_t it;
3544 btstack_linked_list_iterator_init(&it, &gatt_client_connections);
3545 while (btstack_linked_list_iterator_has_next(&it)) {
3546 gatt_client_t *eatt_client = (gatt_client_t *) btstack_linked_list_iterator_next(&it);
3547 if (eatt_client->state == P_L2CAP_CLOSED){
3548 btstack_linked_list_iterator_remove(&it);
3549 btstack_memory_gatt_client_free(eatt_client);
3550 }
3551 }
3552 } else {
3553 hci_connection_t * hci_connection = hci_connection_for_handle(gatt_client->con_handle);
3554 btstack_assert(hci_connection != NULL);
3555 if (hci_connection->att_server.incoming_connection_request){
3556 hci_connection->att_server.incoming_connection_request = false;
3557 log_info("Collision, retry in 100ms");
3558 gatt_client->state = P_W2_L2CAP_CONNECT;
3559 // set timer for retry
3560 btstack_run_loop_set_timer(&gatt_client->gc_timeout, GATT_CLIENT_COLLISION_BACKOFF_MS);
3561 btstack_run_loop_set_timer_handler(&gatt_client->gc_timeout, gatt_client_le_enhanced_retry);
3562 btstack_run_loop_add_timer(&gatt_client->gc_timeout);
3563 return;
3564 } else {
3565 gatt_client->eatt_state = GATT_CLIENT_EATT_IDLE;
3566 status = ERROR_CODE_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES;
3567 }
3568 }
3569 } else {
3570 gatt_client_eatt_finalize(gatt_client);
3571 gatt_client->eatt_state = GATT_CLIENT_EATT_IDLE;
3572 }
3573
3574 gatt_client_emit_connected(gatt_client->callback, status, gatt_client->addr_type, gatt_client->addr, gatt_client->con_handle);
3575 }
3576
3577 // single channel disconnected
gatt_client_le_enhanced_handle_ecbm_disconnected(gatt_client_t * gatt_client,gatt_client_t * eatt_client)3578 static void gatt_client_le_enhanced_handle_ecbm_disconnected(gatt_client_t * gatt_client, gatt_client_t * eatt_client) {
3579
3580 // report error
3581 gatt_client_report_error_if_pending(eatt_client, ATT_ERROR_HCI_DISCONNECT_RECEIVED);
3582
3583 // free memory
3584 btstack_linked_list_remove(&gatt_client->eatt_clients, (btstack_linked_item_t *) eatt_client);
3585 btstack_memory_gatt_client_free(eatt_client);
3586
3587 // last channel
3588 if (btstack_linked_list_empty(&gatt_client->eatt_clients)){
3589 hci_connection_t * hci_connection = hci_connection_for_handle(gatt_client->con_handle);
3590 hci_connection->att_server.eatt_outgoing_active = false;
3591
3592 if (gatt_client->eatt_state == GATT_CLIENT_EATT_READY) {
3593 // report disconnected if last channel closed
3594 uint8_t buffer[20];
3595 uint16_t len = hci_event_create_from_template_and_arguments(buffer, sizeof(buffer), &gatt_client_disconnected, gatt_client->con_handle);
3596 (*gatt_client->callback)(HCI_EVENT_PACKET, 0, buffer, len);
3597 }
3598 }
3599 }
3600
gatt_client_le_enhanced_get_context_for_l2cap_cid(uint16_t l2cap_cid,gatt_client_t ** out_eatt_client)3601 static gatt_client_t * gatt_client_le_enhanced_get_context_for_l2cap_cid(uint16_t l2cap_cid, gatt_client_t ** out_eatt_client){
3602 btstack_linked_list_iterator_t it;
3603 btstack_linked_list_iterator_init(&it, &gatt_client_connections);
3604 while (btstack_linked_list_iterator_has_next(&it)) {
3605 gatt_client_t * gatt_client = (gatt_client_t *) btstack_linked_list_iterator_next(&it);
3606 btstack_linked_list_iterator_t it2;
3607 btstack_linked_list_iterator_init(&it2, &gatt_client->eatt_clients);
3608 while (btstack_linked_list_iterator_has_next(&it2)) {
3609 gatt_client_t * eatt_client = (gatt_client_t *) btstack_linked_list_iterator_next(&it2);
3610 if (eatt_client->l2cap_cid == l2cap_cid){
3611 *out_eatt_client = eatt_client;
3612 return gatt_client;
3613 }
3614 }
3615 }
3616 return NULL;
3617 }
3618
gatt_client_le_enhanced_setup_l2cap_channel(gatt_client_t * gatt_client)3619 static void gatt_client_le_enhanced_setup_l2cap_channel(gatt_client_t * gatt_client){
3620 uint8_t num_channels = gatt_client->eatt_num_clients;
3621
3622 // setup channels
3623 uint16_t buffer_size_per_client = gatt_client->eatt_storage_size / num_channels;
3624 uint16_t max_mtu = (buffer_size_per_client - REPORT_PREBUFFER_HEADER) / 2;
3625 uint8_t * receive_buffers[MAX_NR_EATT_CHANNELS];
3626 uint16_t new_cids[MAX_NR_EATT_CHANNELS];
3627 memset(gatt_client->eatt_storage_buffer, 0, gatt_client->eatt_storage_size);
3628 uint8_t i;
3629 for (i=0;i<gatt_client->eatt_num_clients; i++){
3630 receive_buffers[i] = &gatt_client->eatt_storage_buffer[REPORT_PREBUFFER_HEADER];
3631 gatt_client->eatt_storage_buffer += REPORT_PREBUFFER_HEADER + max_mtu;
3632 }
3633
3634 log_info("%u EATT clients with receive buffer size %u", gatt_client->eatt_num_clients, buffer_size_per_client);
3635
3636 uint8_t status = l2cap_ecbm_create_channels(&gatt_client_le_enhanced_packet_handler,
3637 gatt_client->con_handle,
3638 gatt_client->security_level,
3639 BLUETOOTH_PSM_EATT, num_channels,
3640 L2CAP_LE_AUTOMATIC_CREDITS,
3641 buffer_size_per_client,
3642 receive_buffers,
3643 new_cids);
3644
3645 if (status == ERROR_CODE_SUCCESS){
3646 i = 0;
3647 btstack_linked_list_iterator_t it;
3648 btstack_linked_list_iterator_init(&it, &gatt_client->eatt_clients);
3649 while (btstack_linked_list_iterator_has_next(&it)) {
3650 gatt_client_t *new_eatt_client = (gatt_client_t *) btstack_linked_list_iterator_next(&it);
3651
3652 // init state with new cid and transmit buffer
3653 new_eatt_client->bearer_type = ATT_BEARER_ENHANCED_LE;
3654 new_eatt_client->con_handle = gatt_client->con_handle;
3655 new_eatt_client->mtu = 64;
3656 new_eatt_client->security_level = LEVEL_0;
3657 new_eatt_client->mtu_state = MTU_AUTO_EXCHANGE_DISABLED;
3658 new_eatt_client->state = P_W4_L2CAP_CONNECTION;
3659 new_eatt_client->l2cap_cid = new_cids[i];
3660 new_eatt_client->eatt_storage_buffer = gatt_client->eatt_storage_buffer;
3661 gatt_client->eatt_storage_buffer += max_mtu;
3662 i++;
3663 }
3664 gatt_client->eatt_state = GATT_CLIENT_EATT_L2CAP_SETUP;
3665 } else {
3666 gatt_client_le_enhanced_handle_connected(gatt_client, status);
3667 }
3668 }
3669
gatt_client_le_enhanced_retry(btstack_timer_source_t * ts)3670 static void gatt_client_le_enhanced_retry(btstack_timer_source_t * ts){
3671 gatt_client_t * gatt_client = gatt_client_for_timer(ts);
3672 if (gatt_client != NULL){
3673 gatt_client->state = P_W4_L2CAP_CONNECTION;
3674 gatt_client_le_enhanced_setup_l2cap_channel(gatt_client);
3675 }
3676 }
3677
gatt_client_le_enhanced_packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)3678 static void gatt_client_le_enhanced_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
3679 gatt_client_t *gatt_client;
3680 gatt_client_t *eatt_client;
3681 hci_con_handle_t con_handle;
3682 uint16_t l2cap_cid;
3683 uint8_t status;
3684 gatt_client_characteristic_t characteristic;
3685 gatt_client_service_t service;
3686 switch (packet_type) {
3687 case HCI_EVENT_PACKET:
3688 switch (hci_event_packet_get_type(packet)) {
3689 case GATT_EVENT_SERVICE_QUERY_RESULT:
3690 con_handle = gatt_event_service_query_result_get_handle(packet);
3691 gatt_client = gatt_client_get_context_for_handle(con_handle);
3692 btstack_assert(gatt_client != NULL);
3693 btstack_assert(gatt_client->eatt_state == GATT_CLIENT_EATT_DISCOVER_GATT_SERVICE_W4_DONE);
3694 gatt_event_service_query_result_get_service(packet, &service);
3695 gatt_client->gatt_service_start_group_handle = service.start_group_handle;
3696 gatt_client->gatt_service_end_group_handle = service.end_group_handle;
3697 break;
3698 case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT:
3699 con_handle = gatt_event_characteristic_value_query_result_get_handle(packet);
3700 gatt_client = gatt_client_get_context_for_handle(con_handle);
3701 btstack_assert(gatt_client != NULL);
3702 btstack_assert(gatt_client->eatt_state == GATT_CLIENT_EATT_READ_SERVER_SUPPORTED_FEATURES_W4_DONE);
3703 if (gatt_event_characteristic_value_query_result_get_value_length(packet) >= 1) {
3704 gatt_client->gatt_server_supported_features = gatt_event_characteristic_value_query_result_get_value(packet)[0];
3705 }
3706 break;
3707 case GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
3708 con_handle = gatt_event_characteristic_query_result_get_handle(packet);
3709 gatt_client = gatt_client_get_context_for_handle(con_handle);
3710 btstack_assert(gatt_client != NULL);
3711 btstack_assert(gatt_client->eatt_state == GATT_CLIENT_EATT_FIND_CLIENT_SUPPORTED_FEATURES_W4_DONE);
3712 gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic);
3713 gatt_client->gatt_client_supported_features_handle = characteristic.value_handle;
3714 break;
3715 case GATT_EVENT_QUERY_COMPLETE:
3716 con_handle = gatt_event_query_complete_get_handle(packet);
3717 gatt_client = gatt_client_get_context_for_handle(con_handle);
3718 btstack_assert(gatt_client != NULL);
3719 switch (gatt_client->eatt_state){
3720 case GATT_CLIENT_EATT_DISCOVER_GATT_SERVICE_W4_DONE:
3721 if (gatt_client->gatt_service_start_group_handle == 0){
3722 gatt_client_le_enhanced_handle_connected(gatt_client, ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE);
3723 } else {
3724 gatt_client->eatt_state = GATT_CLIENT_EATT_READ_SERVER_SUPPORTED_FEATURES_W2_SEND;
3725 }
3726 break;
3727 case GATT_CLIENT_EATT_READ_SERVER_SUPPORTED_FEATURES_W4_DONE:
3728 if ((gatt_client->gatt_server_supported_features & 1) == 0) {
3729 gatt_client_le_enhanced_handle_connected(gatt_client, ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE);
3730 } else {
3731 gatt_client->eatt_state = GATT_CLIENT_EATT_FIND_CLIENT_SUPPORTED_FEATURES_W2_SEND;
3732 }
3733 break;
3734 case GATT_CLIENT_EATT_FIND_CLIENT_SUPPORTED_FEATURES_W4_DONE:
3735 if (gatt_client->gatt_client_supported_features_handle == 0){
3736 gatt_client_le_enhanced_handle_connected(gatt_client, ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE);
3737 } else {
3738 gatt_client->eatt_state = GATT_CLIENT_EATT_WRITE_ClIENT_SUPPORTED_FEATURES_W2_SEND;
3739 }
3740 break;
3741 case GATT_CLIENT_EATT_WRITE_ClIENT_SUPPORTED_FEATURES_W4_DONE:
3742 gatt_client_le_enhanced_setup_l2cap_channel(gatt_client);
3743 break;
3744 default:
3745 break;
3746 }
3747 break;
3748 case L2CAP_EVENT_ECBM_CHANNEL_OPENED:
3749 l2cap_cid = l2cap_event_ecbm_channel_opened_get_local_cid(packet);
3750 gatt_client = gatt_client_le_enhanced_get_context_for_l2cap_cid(l2cap_cid, &eatt_client);
3751
3752 btstack_assert(gatt_client != NULL);
3753 btstack_assert(eatt_client != NULL);
3754 btstack_assert(eatt_client->state == P_W4_L2CAP_CONNECTION);
3755
3756 status = l2cap_event_channel_opened_get_status(packet);
3757 if (status == ERROR_CODE_SUCCESS){
3758 eatt_client->state = P_READY;
3759 eatt_client->mtu = l2cap_event_channel_opened_get_remote_mtu(packet);
3760 } else {
3761 eatt_client->state = P_L2CAP_CLOSED;
3762 }
3763 // connected if opened event for all channels received
3764 if (gatt_client_le_enhanced_num_eatt_clients_in_state(gatt_client, P_W4_L2CAP_CONNECTION) == 0){
3765 gatt_client_le_enhanced_handle_connected(gatt_client, ERROR_CODE_SUCCESS);
3766 }
3767 break;
3768 case L2CAP_EVENT_CHANNEL_CLOSED:
3769 l2cap_cid = l2cap_event_channel_closed_get_local_cid(packet);
3770 gatt_client = gatt_client_le_enhanced_get_context_for_l2cap_cid(l2cap_cid, &eatt_client);
3771 btstack_assert(gatt_client != NULL);
3772 btstack_assert(eatt_client != NULL);
3773 gatt_client_le_enhanced_handle_ecbm_disconnected(gatt_client, eatt_client);
3774 break;
3775 default:
3776 break;
3777 }
3778 break;
3779 case L2CAP_DATA_PACKET:
3780 gatt_client = gatt_client_le_enhanced_get_context_for_l2cap_cid(channel, &eatt_client);
3781 btstack_assert(gatt_client != NULL);
3782 btstack_assert(eatt_client != NULL);
3783 gatt_client_handle_att_response(eatt_client, packet, size);
3784 gatt_client_run();
3785 break;
3786 default:
3787 break;
3788 }
3789 }
3790
gatt_client_le_enhanced_handle_can_send_query(gatt_client_t * gatt_client)3791 static bool gatt_client_le_enhanced_handle_can_send_query(gatt_client_t * gatt_client){
3792 uint8_t status = ERROR_CODE_SUCCESS;
3793 uint8_t gatt_client_supported_features = 0x06; // eatt + multiple value notifications
3794 switch (gatt_client->eatt_state){
3795 case GATT_CLIENT_EATT_DISCOVER_GATT_SERVICE_W2_SEND:
3796 gatt_client->gatt_service_start_group_handle = 0;
3797 gatt_client->eatt_state = GATT_CLIENT_EATT_DISCOVER_GATT_SERVICE_W4_DONE;
3798 status = gatt_client_discover_primary_services_by_uuid16(&gatt_client_le_enhanced_packet_handler,
3799 gatt_client->con_handle,
3800 ORG_BLUETOOTH_SERVICE_GENERIC_ATTRIBUTE);
3801 break;
3802 case GATT_CLIENT_EATT_READ_SERVER_SUPPORTED_FEATURES_W2_SEND:
3803 gatt_client->gatt_server_supported_features = 0;
3804 gatt_client->eatt_state = GATT_CLIENT_EATT_READ_SERVER_SUPPORTED_FEATURES_W4_DONE;
3805 status = gatt_client_read_value_of_characteristics_by_uuid16(&gatt_client_le_enhanced_packet_handler,
3806 gatt_client->con_handle,
3807 gatt_client->gatt_service_start_group_handle,
3808 gatt_client->gatt_service_end_group_handle,
3809 ORG_BLUETOOTH_CHARACTERISTIC_SERVER_SUPPORTED_FEATURES);
3810 return true;
3811 case GATT_CLIENT_EATT_FIND_CLIENT_SUPPORTED_FEATURES_W2_SEND:
3812 gatt_client->gatt_client_supported_features_handle = 0;
3813 gatt_client->eatt_state = GATT_CLIENT_EATT_FIND_CLIENT_SUPPORTED_FEATURES_W4_DONE;
3814 status = gatt_client_discover_characteristics_for_handle_range_by_uuid16(&gatt_client_le_enhanced_packet_handler,
3815 gatt_client->con_handle,
3816 gatt_client->gatt_service_start_group_handle,
3817 gatt_client->gatt_service_end_group_handle,
3818 ORG_BLUETOOTH_CHARACTERISTIC_CLIENT_SUPPORTED_FEATURES);
3819 return true;
3820 case GATT_CLIENT_EATT_WRITE_ClIENT_SUPPORTED_FEATURES_W2_SEND:
3821 gatt_client->eatt_state = GATT_CLIENT_EATT_WRITE_ClIENT_SUPPORTED_FEATURES_W4_DONE;
3822 status = gatt_client_write_value_of_characteristic(&gatt_client_le_enhanced_packet_handler, gatt_client->con_handle,
3823 gatt_client->gatt_client_supported_features_handle, 1,
3824 &gatt_client_supported_features);
3825 return true;
3826 default:
3827 break;
3828 }
3829 btstack_assert(status == ERROR_CODE_SUCCESS);
3830 UNUSED(status);
3831 return false;
3832 }
3833
gatt_client_le_enhanced_connect(btstack_packet_handler_t callback,hci_con_handle_t con_handle,uint8_t num_channels,uint8_t * storage_buffer,uint16_t storage_size)3834 uint8_t gatt_client_le_enhanced_connect(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint8_t num_channels, uint8_t * storage_buffer, uint16_t storage_size) {
3835 gatt_client_t * gatt_client;
3836 uint8_t status = gatt_client_provide_context_for_handle(con_handle, &gatt_client);
3837 if (status != ERROR_CODE_SUCCESS){
3838 return status;
3839 }
3840
3841 if (gatt_client->eatt_state != GATT_CLIENT_EATT_IDLE){
3842 return ERROR_CODE_COMMAND_DISALLOWED;
3843 }
3844
3845 // need one buffer for sending and one for receiving. Receiving includes pre-buffer for reports
3846 uint16_t buffer_size_per_client = storage_size / num_channels;
3847 uint16_t max_mtu = (buffer_size_per_client - REPORT_PREBUFFER_HEADER) / 2;
3848 if (max_mtu < 64) {
3849 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
3850 }
3851
3852 if ((num_channels == 0) || (num_channels > MAX_NR_EATT_CHANNELS)){
3853 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
3854 }
3855
3856 // create max num_channel eatt clients
3857 uint8_t i;
3858 btstack_linked_list_t eatt_clients = NULL;
3859 for (i=0;i<num_channels;i++) {
3860 gatt_client_t * new_gatt_client = btstack_memory_gatt_client_get();
3861 if (new_gatt_client == NULL) {
3862 break;
3863 }
3864 btstack_linked_list_add(&eatt_clients, (btstack_linked_item_t*)new_gatt_client);
3865 }
3866
3867 if (i != num_channels){
3868 while (true){
3869 gatt_client = (gatt_client_t *) btstack_linked_list_pop(&eatt_clients);
3870 if (gatt_client == NULL) {
3871 break;
3872 }
3873 btstack_memory_gatt_client_free(gatt_client);
3874 }
3875 return ERROR_CODE_MEMORY_CAPACITY_EXCEEDED;
3876 }
3877
3878 hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
3879 hci_connection->att_server.eatt_outgoing_active = true;
3880
3881 gatt_client->callback = callback;
3882 gatt_client->eatt_num_clients = num_channels;
3883 gatt_client->eatt_storage_buffer = storage_buffer;
3884 gatt_client->eatt_storage_size = storage_size;
3885 gatt_client->eatt_clients = eatt_clients;
3886 gatt_client->eatt_state = GATT_CLIENT_EATT_DISCOVER_GATT_SERVICE_W2_SEND;
3887 gatt_client_notify_can_send_query(gatt_client);
3888
3889 return ERROR_CODE_SUCCESS;
3890 }
3891
gatt_client_le_enhanced_enable(bool enable)3892 void gatt_client_le_enhanced_enable(bool enable){
3893 gatt_client_eatt_enabled = enable;
3894 }
3895
3896
3897 #endif
3898
3899 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
gatt_client_att_packet_handler_fuzz(uint8_t packet_type,uint16_t handle,uint8_t * packet,uint16_t size)3900 void gatt_client_att_packet_handler_fuzz(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){
3901 gatt_client_att_packet_handler(packet_type, handle, packet, size);
3902 }
3903
gatt_client_get_client(hci_con_handle_t con_handle,gatt_client_t ** out_gatt_client)3904 uint8_t gatt_client_get_client(hci_con_handle_t con_handle, gatt_client_t ** out_gatt_client){
3905 uint8_t status = gatt_client_provide_context_for_handle(con_handle, out_gatt_client);
3906 return status;
3907 }
3908 #endif
3909