xref: /btstack/src/ble/gatt_client.c (revision e71d840791b9e06a96d0a25776d9f2390f837f1a)
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 MATTHIAS
24  * RINGWALD 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 #include <stdint.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 #include "btstack_config.h"
44 
45 #include "att_dispatch.h"
46 #include "ble/ad_parser.h"
47 #include "ble/att_db.h"
48 #include "ble/core.h"
49 #include "ble/gatt_client.h"
50 #include "ble/le_device_db.h"
51 #include "ble/sm.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 "classic/sdp_util.h"
58 #include "hci.h"
59 #include "hci_cmd.h"
60 #include "hci_dump.h"
61 #include "l2cap.h"
62 
63 static btstack_linked_list_t gatt_client_connections;
64 static btstack_linked_list_t gatt_client_value_listeners;
65 static btstack_packet_callback_registration_t hci_event_callback_registration;
66 static uint8_t  pts_suppress_mtu_exchange;
67 
68 static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size);
69 static void gatt_client_hci_event_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
70 static void gatt_client_report_error_if_pending(gatt_client_t *peripheral, uint8_t error_code);
71 static void att_signed_write_handle_cmac_result(uint8_t hash[8]);
72 
73 static uint16_t peripheral_mtu(gatt_client_t *peripheral){
74     if (peripheral->mtu > l2cap_max_le_mtu()){
75         log_error("Peripheral mtu is not initialized");
76         return l2cap_max_le_mtu();
77     }
78     return peripheral->mtu;
79 }
80 
81 void gatt_client_init(void){
82     gatt_client_connections = NULL;
83     pts_suppress_mtu_exchange = 0;
84 
85     // regsister for HCI Events
86     hci_event_callback_registration.callback = &gatt_client_hci_event_packet_handler;
87     hci_add_event_handler(&hci_event_callback_registration);
88 
89     // and ATT Client PDUs
90     att_dispatch_register_client(gatt_client_att_packet_handler);
91 }
92 
93 static gatt_client_t * gatt_client_for_timer(btstack_timer_source_t * ts){
94     btstack_linked_list_iterator_t it;
95     btstack_linked_list_iterator_init(&it, &gatt_client_connections);
96     while (btstack_linked_list_iterator_has_next(&it)){
97         gatt_client_t * peripheral = (gatt_client_t *) btstack_linked_list_iterator_next(&it);
98         if ( &peripheral->gc_timeout == ts) {
99             return peripheral;
100         }
101     }
102     return NULL;
103 }
104 
105 static void gatt_client_timeout_handler(btstack_timer_source_t * timer){
106     gatt_client_t * peripheral = gatt_client_for_timer(timer);
107     if (!peripheral) return;
108     log_info("GATT client timeout handle, handle 0x%02x", peripheral->con_handle);
109     gatt_client_report_error_if_pending(peripheral, ATT_ERROR_TIMEOUT);
110 }
111 
112 static void gatt_client_timeout_start(gatt_client_t * peripheral){
113     log_info("GATT client timeout start, handle 0x%02x", peripheral->con_handle);
114     btstack_run_loop_remove_timer(&peripheral->gc_timeout);
115     btstack_run_loop_set_timer_handler(&peripheral->gc_timeout, gatt_client_timeout_handler);
116     btstack_run_loop_set_timer(&peripheral->gc_timeout, 30000); // 30 seconds sm timeout
117     btstack_run_loop_add_timer(&peripheral->gc_timeout);
118 }
119 
120 static void gatt_client_timeout_stop(gatt_client_t * peripheral){
121     log_info("GATT client timeout stop, handle 0x%02x", peripheral->con_handle);
122     btstack_run_loop_remove_timer(&peripheral->gc_timeout);
123 }
124 
125 static gatt_client_t * get_gatt_client_context_for_handle(uint16_t handle){
126     btstack_linked_item_t *it;
127     for (it = (btstack_linked_item_t *) gatt_client_connections; it ; it = it->next){
128         gatt_client_t * peripheral = (gatt_client_t *) it;
129         if (peripheral->con_handle == handle){
130             return peripheral;
131         }
132     }
133     return NULL;
134 }
135 
136 
137 // @returns context
138 // returns existing one, or tries to setup new one
139 static gatt_client_t * provide_context_for_conn_handle(hci_con_handle_t con_handle){
140     gatt_client_t * context = get_gatt_client_context_for_handle(con_handle);
141     if (context) return  context;
142 
143     context = btstack_memory_gatt_client_get();
144     if (!context) return NULL;
145     // init state
146     memset(context, 0, sizeof(gatt_client_t));
147     context->con_handle = con_handle;
148     context->mtu = ATT_DEFAULT_MTU;
149     context->mtu_state = SEND_MTU_EXCHANGE;
150     context->gatt_client_state = P_READY;
151     btstack_linked_list_add(&gatt_client_connections, (btstack_linked_item_t*)context);
152 
153     // skip mtu exchange for testing sm with pts
154     if (pts_suppress_mtu_exchange){
155          context->mtu_state = MTU_EXCHANGED;
156     }
157     return context;
158 }
159 
160 static gatt_client_t * provide_context_for_conn_handle_and_start_timer(hci_con_handle_t con_handle){
161     gatt_client_t * context = provide_context_for_conn_handle(con_handle);
162     if (!context) return NULL;
163     gatt_client_timeout_start(context);
164     return context;
165 }
166 
167 static int is_ready(gatt_client_t * context){
168     return context->gatt_client_state == P_READY;
169 }
170 
171 int gatt_client_is_ready(hci_con_handle_t con_handle){
172     gatt_client_t * context = provide_context_for_conn_handle(con_handle);
173     if (!context) return 0;
174     return is_ready(context);
175 }
176 
177 uint8_t gatt_client_get_mtu(hci_con_handle_t con_handle, uint16_t * mtu){
178     gatt_client_t * context = provide_context_for_conn_handle(con_handle);
179     if (context && context->mtu_state == MTU_EXCHANGED){
180         *mtu = context->mtu;
181         return 0;
182     }
183     *mtu = ATT_DEFAULT_MTU;
184     return GATT_CLIENT_IN_WRONG_STATE;
185 }
186 
187 // precondition: can_send_packet_now == TRUE
188 static void att_confirmation(uint16_t peripheral_handle){
189     l2cap_reserve_packet_buffer();
190     uint8_t * request = l2cap_get_outgoing_buffer();
191     request[0] = ATT_HANDLE_VALUE_CONFIRMATION;
192     l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 1);
193 }
194 
195 // precondition: can_send_packet_now == TRUE
196 static void att_find_information_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle){
197     l2cap_reserve_packet_buffer();
198     uint8_t * request = l2cap_get_outgoing_buffer();
199     request[0] = request_type;
200     little_endian_store_16(request, 1, start_handle);
201     little_endian_store_16(request, 3, end_handle);
202 
203     l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5);
204 }
205 
206 // precondition: can_send_packet_now == TRUE
207 static void att_find_by_type_value_request(uint16_t request_type, uint16_t attribute_group_type, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle, uint8_t * value, uint16_t value_size){
208     l2cap_reserve_packet_buffer();
209     uint8_t * request = l2cap_get_outgoing_buffer();
210 
211     request[0] = request_type;
212     little_endian_store_16(request, 1, start_handle);
213     little_endian_store_16(request, 3, end_handle);
214     little_endian_store_16(request, 5, attribute_group_type);
215     memcpy(&request[7], value, value_size);
216 
217     l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 7+value_size);
218 }
219 
220 // precondition: can_send_packet_now == TRUE
221 static void att_read_by_type_or_group_request_for_uuid16(uint16_t request_type, uint16_t uuid16, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle){
222     l2cap_reserve_packet_buffer();
223     uint8_t * request = l2cap_get_outgoing_buffer();
224     request[0] = request_type;
225     little_endian_store_16(request, 1, start_handle);
226     little_endian_store_16(request, 3, end_handle);
227     little_endian_store_16(request, 5, uuid16);
228 
229     l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 7);
230 }
231 
232 // precondition: can_send_packet_now == TRUE
233 static void att_read_by_type_or_group_request_for_uuid128(uint16_t request_type, uint8_t * uuid128, uint16_t peripheral_handle, uint16_t start_handle, uint16_t end_handle){
234     l2cap_reserve_packet_buffer();
235     uint8_t * request = l2cap_get_outgoing_buffer();
236     request[0] = request_type;
237     little_endian_store_16(request, 1, start_handle);
238     little_endian_store_16(request, 3, end_handle);
239     reverse_128(uuid128, &request[5]);
240 
241     l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 21);
242 }
243 
244 // precondition: can_send_packet_now == TRUE
245 static void att_read_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle){
246     l2cap_reserve_packet_buffer();
247     uint8_t * request = l2cap_get_outgoing_buffer();
248     request[0] = request_type;
249     little_endian_store_16(request, 1, attribute_handle);
250 
251     l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3);
252 }
253 
254 // precondition: can_send_packet_now == TRUE
255 static void att_read_blob_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_offset){
256     l2cap_reserve_packet_buffer();
257     uint8_t * request = l2cap_get_outgoing_buffer();
258     request[0] = request_type;
259     little_endian_store_16(request, 1, attribute_handle);
260     little_endian_store_16(request, 3, value_offset);
261 
262     l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5);
263 }
264 
265 static void att_read_multiple_request(uint16_t peripheral_handle, uint16_t num_value_handles, uint16_t * value_handles){
266     l2cap_reserve_packet_buffer();
267     uint8_t * request = l2cap_get_outgoing_buffer();
268     request[0] = ATT_READ_MULTIPLE_REQUEST;
269     int i;
270     int offset = 1;
271     for (i=0;i<num_value_handles;i++){
272         little_endian_store_16(request, offset, value_handles[i]);
273         offset += 2;
274     }
275     l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, offset);
276 }
277 
278 // precondition: can_send_packet_now == TRUE
279 static void att_signed_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_length, uint8_t * value, uint32_t sign_counter, uint8_t sgn[8]){
280     l2cap_reserve_packet_buffer();
281     uint8_t * request = l2cap_get_outgoing_buffer();
282     request[0] = request_type;
283     little_endian_store_16(request, 1, attribute_handle);
284     memcpy(&request[3], value, value_length);
285     little_endian_store_32(request, 3 + value_length, sign_counter);
286     reverse_64(sgn, &request[3 + value_length + 4]);
287     l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length + 12);
288 }
289 
290 // precondition: can_send_packet_now == TRUE
291 static void att_write_request(uint16_t request_type, uint16_t peripheral_handle, uint16_t attribute_handle, uint16_t value_length, uint8_t * value){
292     l2cap_reserve_packet_buffer();
293     uint8_t * request = l2cap_get_outgoing_buffer();
294     request[0] = request_type;
295     little_endian_store_16(request, 1, attribute_handle);
296     memcpy(&request[3], value, value_length);
297 
298     l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3 + value_length);
299 }
300 
301 // precondition: can_send_packet_now == TRUE
302 static void att_execute_write_request(uint16_t request_type, uint16_t peripheral_handle, uint8_t execute_write){
303     l2cap_reserve_packet_buffer();
304     uint8_t * request = l2cap_get_outgoing_buffer();
305     request[0] = request_type;
306     request[1] = execute_write;
307     l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 2);
308 }
309 
310 // precondition: can_send_packet_now == TRUE
311 static void att_prepare_write_request(uint16_t request_type, uint16_t peripheral_handle,  uint16_t attribute_handle, uint16_t value_offset, uint16_t blob_length, uint8_t * value){
312     l2cap_reserve_packet_buffer();
313     uint8_t * request = l2cap_get_outgoing_buffer();
314     request[0] = request_type;
315     little_endian_store_16(request, 1, attribute_handle);
316     little_endian_store_16(request, 3, value_offset);
317     memcpy(&request[5], &value[value_offset], blob_length);
318 
319     l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 5+blob_length);
320 }
321 
322 static void att_exchange_mtu_request(uint16_t peripheral_handle){
323     uint16_t mtu = l2cap_max_le_mtu();
324     l2cap_reserve_packet_buffer();
325     uint8_t * request = l2cap_get_outgoing_buffer();
326     request[0] = ATT_EXCHANGE_MTU_REQUEST;
327     little_endian_store_16(request, 1, mtu);
328     l2cap_send_prepared_connectionless(peripheral_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, 3);
329 }
330 
331 static uint16_t write_blob_length(gatt_client_t * peripheral){
332     uint16_t max_blob_length = peripheral_mtu(peripheral) - 5;
333     if (peripheral->attribute_offset >= peripheral->attribute_length) {
334         return 0;
335     }
336     uint16_t rest_length = peripheral->attribute_length - peripheral->attribute_offset;
337     if (max_blob_length > rest_length){
338         return rest_length;
339     }
340     return max_blob_length;
341 }
342 
343 static void send_gatt_services_request(gatt_client_t *peripheral){
344     att_read_by_type_or_group_request_for_uuid16(ATT_READ_BY_GROUP_TYPE_REQUEST, GATT_PRIMARY_SERVICE_UUID, peripheral->con_handle, peripheral->start_group_handle, peripheral->end_group_handle);
345 }
346 
347 static void send_gatt_by_uuid_request(gatt_client_t *peripheral, uint16_t attribute_group_type){
348     if (peripheral->uuid16){
349         uint8_t uuid16[2];
350         little_endian_store_16(uuid16, 0, peripheral->uuid16);
351         att_find_by_type_value_request(ATT_FIND_BY_TYPE_VALUE_REQUEST, attribute_group_type, peripheral->con_handle, peripheral->start_group_handle, peripheral->end_group_handle, uuid16, 2);
352         return;
353     }
354     uint8_t uuid128[16];
355     reverse_128(peripheral->uuid128, uuid128);
356     att_find_by_type_value_request(ATT_FIND_BY_TYPE_VALUE_REQUEST, attribute_group_type, peripheral->con_handle, peripheral->start_group_handle, peripheral->end_group_handle, uuid128, 16);
357 }
358 
359 static void send_gatt_services_by_uuid_request(gatt_client_t *peripheral){
360     send_gatt_by_uuid_request(peripheral, GATT_PRIMARY_SERVICE_UUID);
361 }
362 
363 static void send_gatt_included_service_uuid_request(gatt_client_t *peripheral){
364     att_read_request(ATT_READ_REQUEST, peripheral->con_handle, peripheral->query_start_handle);
365 }
366 
367 static void send_gatt_included_service_request(gatt_client_t *peripheral){
368     att_read_by_type_or_group_request_for_uuid16(ATT_READ_BY_TYPE_REQUEST, GATT_INCLUDE_SERVICE_UUID, peripheral->con_handle, peripheral->start_group_handle, peripheral->end_group_handle);
369 }
370 
371 static void send_gatt_characteristic_request(gatt_client_t *peripheral){
372     att_read_by_type_or_group_request_for_uuid16(ATT_READ_BY_TYPE_REQUEST, GATT_CHARACTERISTICS_UUID, peripheral->con_handle, peripheral->start_group_handle, peripheral->end_group_handle);
373 }
374 
375 static void send_gatt_characteristic_descriptor_request(gatt_client_t *peripheral){
376     att_find_information_request(ATT_FIND_INFORMATION_REQUEST, peripheral->con_handle, peripheral->start_group_handle, peripheral->end_group_handle);
377 }
378 
379 static void send_gatt_read_characteristic_value_request(gatt_client_t *peripheral){
380     att_read_request(ATT_READ_REQUEST, peripheral->con_handle, peripheral->attribute_handle);
381 }
382 
383 static void send_gatt_read_by_type_request(gatt_client_t * peripheral){
384     if (peripheral->uuid16){
385         att_read_by_type_or_group_request_for_uuid16(ATT_READ_BY_TYPE_REQUEST, peripheral->uuid16, peripheral->con_handle, peripheral->start_group_handle, peripheral->end_group_handle);
386     } else {
387         att_read_by_type_or_group_request_for_uuid128(ATT_READ_BY_TYPE_REQUEST, peripheral->uuid128, peripheral->con_handle, peripheral->start_group_handle, peripheral->end_group_handle);
388     }
389 }
390 
391 static void send_gatt_read_blob_request(gatt_client_t *peripheral){
392     att_read_blob_request(ATT_READ_BLOB_REQUEST, peripheral->con_handle, peripheral->attribute_handle, peripheral->attribute_offset);
393 }
394 
395 static void send_gatt_read_multiple_request(gatt_client_t * peripheral){
396     att_read_multiple_request(peripheral->con_handle, peripheral->read_multiple_handle_count, peripheral->read_multiple_handles);
397 }
398 
399 static void send_gatt_write_attribute_value_request(gatt_client_t * peripheral){
400     att_write_request(ATT_WRITE_REQUEST, peripheral->con_handle, peripheral->attribute_handle, peripheral->attribute_length, peripheral->attribute_value);
401 }
402 
403 static void send_gatt_write_client_characteristic_configuration_request(gatt_client_t * peripheral){
404     att_write_request(ATT_WRITE_REQUEST, peripheral->con_handle, peripheral->client_characteristic_configuration_handle, 2, peripheral->client_characteristic_configuration_value);
405 }
406 
407 static void send_gatt_prepare_write_request(gatt_client_t * peripheral){
408     att_prepare_write_request(ATT_PREPARE_WRITE_REQUEST, peripheral->con_handle, peripheral->attribute_handle, peripheral->attribute_offset, write_blob_length(peripheral), peripheral->attribute_value);
409 }
410 
411 static void send_gatt_execute_write_request(gatt_client_t * peripheral){
412     att_execute_write_request(ATT_EXECUTE_WRITE_REQUEST, peripheral->con_handle, 1);
413 }
414 
415 static void send_gatt_cancel_prepared_write_request(gatt_client_t * peripheral){
416     att_execute_write_request(ATT_EXECUTE_WRITE_REQUEST, peripheral->con_handle, 0);
417 }
418 
419 static void send_gatt_read_client_characteristic_configuration_request(gatt_client_t * peripheral){
420     att_read_by_type_or_group_request_for_uuid16(ATT_READ_BY_TYPE_REQUEST, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION, peripheral->con_handle, peripheral->start_group_handle, peripheral->end_group_handle);
421 }
422 
423 static void send_gatt_read_characteristic_descriptor_request(gatt_client_t * peripheral){
424     att_read_request(ATT_READ_REQUEST, peripheral->con_handle, peripheral->attribute_handle);
425 }
426 
427 static void send_gatt_signed_write_request(gatt_client_t * peripheral, uint32_t sign_counter){
428     att_signed_write_request(ATT_SIGNED_WRITE_COMMAND, peripheral->con_handle, peripheral->attribute_handle, peripheral->attribute_length, peripheral->attribute_value, sign_counter, peripheral->cmac);
429 }
430 
431 static uint16_t get_last_result_handle_from_service_list(uint8_t * packet, uint16_t size){
432     uint8_t attr_length = packet[1];
433     return little_endian_read_16(packet, size - attr_length + 2);
434 }
435 
436 static uint16_t get_last_result_handle_from_characteristics_list(uint8_t * packet, uint16_t size){
437     uint8_t attr_length = packet[1];
438     return little_endian_read_16(packet, size - attr_length + 3);
439 }
440 
441 static uint16_t get_last_result_handle_from_included_services_list(uint8_t * packet, uint16_t size){
442     uint8_t attr_length = packet[1];
443     return little_endian_read_16(packet, size - attr_length);
444 }
445 
446 static void gatt_client_handle_transaction_complete(gatt_client_t * peripheral){
447     peripheral->gatt_client_state = P_READY;
448     gatt_client_timeout_stop(peripheral);
449 }
450 
451 static void emit_event_new(btstack_packet_handler_t callback, uint8_t * packet, uint16_t size){
452     if (!callback) return;
453     (*callback)(HCI_EVENT_PACKET, 0, packet, size);
454 }
455 
456 /**
457  * @brief Register for notifications and indications of a characteristic enabled by gatt_client_write_client_characteristic_configuration
458  * @param notification struct used to store registration
459  * @param con_handle
460  * @param characteristic
461  */
462 void gatt_client_listen_for_characteristic_value_updates(gatt_client_notification_t * notification, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){
463     notification->con_handle = con_handle;
464     notification->attribute_handle = characteristic->value_handle;
465     btstack_linked_list_add(&gatt_client_value_listeners, (btstack_linked_item_t*) notification);
466 }
467 
468 static void emit_event_to_registered_listeners(hci_con_handle_t con_handle, uint16_t attribute_handle, uint8_t * packet, uint16_t size){
469     btstack_linked_list_iterator_t it;
470     btstack_linked_list_iterator_init(&it, &gatt_client_value_listeners);
471     while (btstack_linked_list_iterator_has_next(&it)){
472         gatt_client_notification_t * registration = (gatt_client_notification_t*) btstack_linked_list_iterator_next(&it);
473         if (registration->con_handle != con_handle) continue;
474         if (registration->attribute_handle != attribute_handle) continue;
475         (*registration->callback)(HCI_EVENT_PACKET, 0, packet, size);
476     }
477 }
478 
479 static void emit_gatt_complete_event(gatt_client_t * peripheral, uint8_t status){
480     // @format H1
481     uint8_t packet[5];
482     packet[0] = GATT_EVENT_QUERY_COMPLETE;
483     packet[1] = 3;
484     little_endian_store_16(packet, 2, peripheral->con_handle);
485     packet[4] = status;
486     emit_event_new(peripheral->callback, packet, sizeof(packet));
487 }
488 
489 static void emit_gatt_service_query_result_event(gatt_client_t * peripheral, uint16_t start_group_handle, uint16_t end_group_handle, uint8_t * uuid128){
490     // @format HX
491     uint8_t packet[24];
492     packet[0] = GATT_EVENT_SERVICE_QUERY_RESULT;
493     packet[1] = sizeof(packet) - 2;
494     little_endian_store_16(packet, 2, peripheral->con_handle);
495     ///
496     little_endian_store_16(packet, 4, start_group_handle);
497     little_endian_store_16(packet, 6, end_group_handle);
498     reverse_128(uuid128, &packet[8]);
499     emit_event_new(peripheral->callback, packet, sizeof(packet));
500 }
501 
502 static void emit_gatt_included_service_query_result_event(gatt_client_t * peripheral, uint16_t include_handle, uint16_t start_group_handle, uint16_t end_group_handle, uint8_t * uuid128){
503     // @format HX
504     uint8_t packet[26];
505     packet[0] = GATT_EVENT_INCLUDED_SERVICE_QUERY_RESULT;
506     packet[1] = sizeof(packet) - 2;
507     little_endian_store_16(packet, 2, peripheral->con_handle);
508     ///
509     little_endian_store_16(packet, 4, include_handle);
510     //
511     little_endian_store_16(packet, 6, start_group_handle);
512     little_endian_store_16(packet, 8, end_group_handle);
513     reverse_128(uuid128, &packet[10]);
514     emit_event_new(peripheral->callback, packet, sizeof(packet));
515 }
516 
517 static void emit_gatt_characteristic_query_result_event(gatt_client_t * peripheral, uint16_t start_handle, uint16_t value_handle, uint16_t end_handle,
518         uint16_t properties, uint8_t * uuid128){
519     // @format HY
520     uint8_t packet[28];
521     packet[0] = GATT_EVENT_CHARACTERISTIC_QUERY_RESULT;
522     packet[1] = sizeof(packet) - 2;
523     little_endian_store_16(packet, 2, peripheral->con_handle);
524     ///
525     little_endian_store_16(packet, 4,  start_handle);
526     little_endian_store_16(packet, 6,  value_handle);
527     little_endian_store_16(packet, 8,  end_handle);
528     little_endian_store_16(packet, 10, properties);
529     reverse_128(uuid128, &packet[12]);
530     emit_event_new(peripheral->callback, packet, sizeof(packet));
531 }
532 
533 static void emit_gatt_all_characteristic_descriptors_result_event(
534     gatt_client_t * peripheral, uint16_t descriptor_handle, uint8_t * uuid128){
535     // @format HZ
536     uint8_t packet[22];
537     packet[0] = GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT;
538     packet[1] = sizeof(packet) - 2;
539     little_endian_store_16(packet, 2, peripheral->con_handle);
540     ///
541     little_endian_store_16(packet, 4,  descriptor_handle);
542     reverse_128(uuid128, &packet[6]);
543     emit_event_new(peripheral->callback, packet, sizeof(packet));
544 }
545 ///
546 
547 static void report_gatt_services(gatt_client_t * peripheral, uint8_t * packet,  uint16_t size){
548     uint8_t attr_length = packet[1];
549     uint8_t uuid_length = attr_length - 4;
550 
551     int i;
552     for (i = 2; i < size; i += attr_length){
553         uint16_t start_group_handle = little_endian_read_16(packet,i);
554         uint16_t end_group_handle   = little_endian_read_16(packet,i+2);
555         uint8_t  uuid128[16];
556         uint16_t uuid16 = 0;
557 
558         if (uuid_length == 2){
559             uuid16 = little_endian_read_16(packet, i+4);
560             uuid_add_bluetooth_prefix((uint8_t*) &uuid128, uuid16);
561         } else {
562             reverse_128(&packet[i+4], uuid128);
563         }
564         emit_gatt_service_query_result_event(peripheral, start_group_handle, end_group_handle, uuid128);
565     }
566     // log_info("report_gatt_services for %02X done", peripheral->con_handle);
567 }
568 
569 // helper
570 static void characteristic_start_found(gatt_client_t * peripheral, uint16_t start_handle, uint8_t properties, uint16_t value_handle, uint8_t * uuid, uint16_t uuid_length){
571     uint8_t uuid128[16];
572     uint16_t uuid16 = 0;
573     if (uuid_length == 2){
574         uuid16 = little_endian_read_16(uuid, 0);
575         uuid_add_bluetooth_prefix((uint8_t*) uuid128, uuid16);
576     } else {
577         reverse_128(uuid, uuid128);
578     }
579 
580     if (peripheral->filter_with_uuid && memcmp(peripheral->uuid128, uuid128, 16) != 0) return;
581 
582     peripheral->characteristic_properties = properties;
583     peripheral->characteristic_start_handle = start_handle;
584     peripheral->attribute_handle = value_handle;
585 
586     if (peripheral->filter_with_uuid) return;
587 
588     peripheral->uuid16 = uuid16;
589     memcpy(peripheral->uuid128, uuid128, 16);
590 }
591 
592 static void characteristic_end_found(gatt_client_t * peripheral, uint16_t end_handle){
593     // TODO: stop searching if filter and uuid found
594 
595     if (!peripheral->characteristic_start_handle) return;
596 
597     emit_gatt_characteristic_query_result_event(peripheral, peripheral->characteristic_start_handle, peripheral->attribute_handle,
598         end_handle, peripheral->characteristic_properties, peripheral->uuid128);
599 
600     peripheral->characteristic_start_handle = 0;
601 }
602 
603 static void report_gatt_characteristics(gatt_client_t * peripheral, uint8_t * packet,  uint16_t size){
604     uint8_t attr_length = packet[1];
605     uint8_t uuid_length = attr_length - 5;
606     int i;
607     for (i = 2; i < size; i += attr_length){
608         uint16_t start_handle = little_endian_read_16(packet, i);
609         uint8_t  properties = packet[i+2];
610         uint16_t value_handle = little_endian_read_16(packet, i+3);
611         characteristic_end_found(peripheral, start_handle-1);
612         characteristic_start_found(peripheral, start_handle, properties, value_handle, &packet[i+5], uuid_length);
613     }
614 }
615 
616 static void report_gatt_included_service_uuid16(gatt_client_t * peripheral, uint16_t include_handle, uint16_t uuid16){
617     uint8_t normalized_uuid128[16];
618     uuid_add_bluetooth_prefix(normalized_uuid128, uuid16);
619     emit_gatt_included_service_query_result_event(peripheral, include_handle, peripheral->query_start_handle,
620         peripheral->query_end_handle, normalized_uuid128);
621 }
622 
623 static void report_gatt_included_service_uuid128(gatt_client_t * peripheral, uint16_t include_handle, uint8_t *uuid128){
624     emit_gatt_included_service_query_result_event(peripheral, include_handle, peripheral->query_start_handle,
625         peripheral->query_end_handle, uuid128);
626 }
627 
628 // @returns packet pointer
629 // @note assume that value is part of an l2cap buffer - overwrite HCI + L2CAP packet headers
630 static const int characteristic_value_event_header_size = 8;
631 static uint8_t * setup_characteristic_value_packet(uint8_t type, hci_con_handle_t con_handle, uint16_t attribute_handle, uint8_t * value, uint16_t length){
632     // before the value inside the ATT PDU
633     uint8_t * packet = value - characteristic_value_event_header_size;
634     packet[0] = type;
635     packet[1] = characteristic_value_event_header_size - 2 + length;
636     little_endian_store_16(packet, 2, con_handle);
637     little_endian_store_16(packet, 4, attribute_handle);
638     little_endian_store_16(packet, 6, length);
639     return packet;
640 }
641 
642 // @returns packet pointer
643 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
644 static const int long_characteristic_value_event_header_size = 10;
645 static uint8_t * setup_long_characteristic_value_packet(uint8_t type, hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * value, uint16_t length){
646 #if defined(HCI_INCOMING_PRE_BUFFER_SIZE) && (HCI_INCOMING_PRE_BUFFER_SIZE >= 10 - 8) // L2CAP Header (4) - ACL Header (4)
647     // before the value inside the ATT PDU
648     uint8_t * packet = value - long_characteristic_value_event_header_size;
649     packet[0] = type;
650     packet[1] = long_characteristic_value_event_header_size - 2 + length;
651     little_endian_store_16(packet, 2, con_handle);
652     little_endian_store_16(packet, 4, attribute_handle);
653     little_endian_store_16(packet, 6, offset);
654     little_endian_store_16(packet, 8, length);
655     return packet;
656 #else
657     log_error("HCI_INCOMING_PRE_BUFFER_SIZE >= 2 required for long characteristic reads");
658     return NULL;
659 #endif
660 }
661 
662 
663 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
664 static void report_gatt_notification(hci_con_handle_t con_handle, uint16_t value_handle, uint8_t * value, int length){
665     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_NOTIFICATION, con_handle, value_handle, value, length);
666     emit_event_to_registered_listeners(con_handle, value_handle, packet, characteristic_value_event_header_size + length);
667 }
668 
669 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
670 static void report_gatt_indication(hci_con_handle_t con_handle, uint16_t value_handle, uint8_t * value, int length){
671     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_INDICATION, con_handle, value_handle, value, length);
672     emit_event_to_registered_listeners(con_handle, value_handle, packet, characteristic_value_event_header_size + length);
673 }
674 
675 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
676 static void report_gatt_characteristic_value(gatt_client_t * peripheral, uint16_t attribute_handle, uint8_t * value, uint16_t length){
677     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT, peripheral->con_handle, attribute_handle, value, length);
678     emit_event_new(peripheral->callback, packet, characteristic_value_event_header_size + length);
679 }
680 
681 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
682 static void report_gatt_long_characteristic_value_blob(gatt_client_t * peripheral, uint16_t attribute_handle, uint8_t * blob, uint16_t blob_length, int value_offset){
683     uint8_t * packet = setup_long_characteristic_value_packet(GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT, peripheral->con_handle, attribute_handle, value_offset, blob, blob_length);
684     if (!packet) return;
685     emit_event_new(peripheral->callback, packet, blob_length + long_characteristic_value_event_header_size);
686 }
687 
688 static void report_gatt_characteristic_descriptor(gatt_client_t * peripheral, uint16_t descriptor_handle, uint8_t *value, uint16_t value_length, uint16_t value_offset){
689     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT, peripheral->con_handle, descriptor_handle, value, value_length);
690     emit_event_new(peripheral->callback, packet, value_length + 8);
691 }
692 
693 static void report_gatt_long_characteristic_descriptor(gatt_client_t * peripheral, uint16_t descriptor_handle, uint8_t *blob, uint16_t blob_length, uint16_t value_offset){
694     uint8_t * packet = setup_long_characteristic_value_packet(GATT_EVENT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT, peripheral->con_handle, descriptor_handle, value_offset, blob, blob_length);
695     if (!packet) return;
696     emit_event_new(peripheral->callback, packet, blob_length + long_characteristic_value_event_header_size);
697 }
698 
699 static void report_gatt_all_characteristic_descriptors(gatt_client_t * peripheral, uint8_t * packet, uint16_t size, uint16_t pair_size){
700     int i;
701     for (i = 0; i<size; i+=pair_size){
702         uint16_t descriptor_handle = little_endian_read_16(packet,i);
703         uint8_t uuid128[16];
704         uint16_t uuid16 = 0;
705         if (pair_size == 4){
706             uuid16 = little_endian_read_16(packet,i+2);
707             uuid_add_bluetooth_prefix(uuid128, uuid16);
708         } else {
709             reverse_128(&packet[i+2], uuid128);
710         }
711         emit_gatt_all_characteristic_descriptors_result_event(peripheral, descriptor_handle, uuid128);
712     }
713 
714 }
715 
716 static int is_query_done(gatt_client_t * peripheral, uint16_t last_result_handle){
717     return last_result_handle >= peripheral->end_group_handle;
718 }
719 
720 static void trigger_next_query(gatt_client_t * peripheral, uint16_t last_result_handle, gatt_client_state_t next_query_state){
721     if (is_query_done(peripheral, last_result_handle)){
722         gatt_client_handle_transaction_complete(peripheral);
723         emit_gatt_complete_event(peripheral, 0);
724         return;
725     }
726     // next
727     peripheral->start_group_handle = last_result_handle + 1;
728     peripheral->gatt_client_state = next_query_state;
729 }
730 
731 static inline void trigger_next_included_service_query(gatt_client_t * peripheral, uint16_t last_result_handle){
732     trigger_next_query(peripheral, last_result_handle, P_W2_SEND_INCLUDED_SERVICE_QUERY);
733 }
734 
735 static inline void trigger_next_service_query(gatt_client_t * peripheral, uint16_t last_result_handle){
736     trigger_next_query(peripheral, last_result_handle, P_W2_SEND_SERVICE_QUERY);
737 }
738 
739 static inline void trigger_next_service_by_uuid_query(gatt_client_t * peripheral, uint16_t last_result_handle){
740     trigger_next_query(peripheral, last_result_handle, P_W2_SEND_SERVICE_WITH_UUID_QUERY);
741 }
742 
743 static inline void trigger_next_characteristic_query(gatt_client_t * peripheral, uint16_t last_result_handle){
744     if (is_query_done(peripheral, last_result_handle)){
745         // report last characteristic
746         characteristic_end_found(peripheral, peripheral->end_group_handle);
747     }
748     trigger_next_query(peripheral, last_result_handle, P_W2_SEND_ALL_CHARACTERISTICS_OF_SERVICE_QUERY);
749 }
750 
751 static inline void trigger_next_characteristic_descriptor_query(gatt_client_t * peripheral, uint16_t last_result_handle){
752     trigger_next_query(peripheral, last_result_handle, P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY);
753 }
754 
755 static inline void trigger_next_read_by_type_query(gatt_client_t * peripheral, uint16_t last_result_handle){
756     trigger_next_query(peripheral, last_result_handle, P_W2_SEND_READ_BY_TYPE_REQUEST);
757 }
758 
759 static inline void trigger_next_prepare_write_query(gatt_client_t * peripheral, gatt_client_state_t next_query_state, gatt_client_state_t done_state){
760     peripheral->attribute_offset += write_blob_length(peripheral);
761     uint16_t next_blob_length =  write_blob_length(peripheral);
762 
763     if (next_blob_length == 0){
764         peripheral->gatt_client_state = done_state;
765         return;
766     }
767     peripheral->gatt_client_state = next_query_state;
768 }
769 
770 static inline void trigger_next_blob_query(gatt_client_t * peripheral, gatt_client_state_t next_query_state, uint16_t received_blob_length){
771 
772     uint16_t max_blob_length = peripheral_mtu(peripheral) - 1;
773     if (received_blob_length < max_blob_length){
774         gatt_client_handle_transaction_complete(peripheral);
775         emit_gatt_complete_event(peripheral, 0);
776         return;
777     }
778 
779     peripheral->attribute_offset += received_blob_length;
780     peripheral->gatt_client_state = next_query_state;
781 }
782 
783 
784 static int is_value_valid(gatt_client_t *peripheral, uint8_t *packet, uint16_t size){
785     uint16_t attribute_handle = little_endian_read_16(packet, 1);
786     uint16_t value_offset = little_endian_read_16(packet, 3);
787 
788     if (peripheral->attribute_handle != attribute_handle) return 0;
789     if (peripheral->attribute_offset != value_offset) return 0;
790     return memcmp(&peripheral->attribute_value[peripheral->attribute_offset], &packet[5], size-5) == 0;
791 }
792 
793 
794 static void gatt_client_run(void){
795 
796     btstack_linked_item_t *it;
797     for (it = (btstack_linked_item_t *) gatt_client_connections; it ; it = it->next){
798 
799         gatt_client_t * peripheral = (gatt_client_t *) it;
800 
801         if (!att_dispatch_server_can_send_now(peripheral->con_handle)) return;
802 
803         // log_info("- handle_peripheral_list, mtu state %u, client state %u", peripheral->mtu_state, peripheral->gatt_client_state);
804 
805         switch (peripheral->mtu_state) {
806             case SEND_MTU_EXCHANGE:{
807                 peripheral->mtu_state = SENT_MTU_EXCHANGE;
808                 att_exchange_mtu_request(peripheral->con_handle);
809                 return;
810             }
811             case SENT_MTU_EXCHANGE:
812                 return;
813             default:
814                 break;
815         }
816 
817         if (peripheral->send_confirmation){
818             peripheral->send_confirmation = 0;
819             att_confirmation(peripheral->con_handle);
820             return;
821         }
822 
823         // check MTU for writes
824         switch (peripheral->gatt_client_state){
825             case P_W2_SEND_WRITE_CHARACTERISTIC_VALUE:
826             case P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR:
827                 if (peripheral->attribute_length <= peripheral_mtu(peripheral) - 3) break;
828                 log_error("gatt_client_run: value len %u > MTU %u - 3\n", peripheral->attribute_length, peripheral_mtu(peripheral));
829                 gatt_client_handle_transaction_complete(peripheral);
830                 emit_gatt_complete_event(peripheral, ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH);
831                 return;
832             default:
833                 break;
834         }
835 
836         // log_info("gatt_client_state %u", peripheral->gatt_client_state);
837         switch (peripheral->gatt_client_state){
838             case P_W2_SEND_SERVICE_QUERY:
839                 peripheral->gatt_client_state = P_W4_SERVICE_QUERY_RESULT;
840                 send_gatt_services_request(peripheral);
841                 return;
842 
843             case P_W2_SEND_SERVICE_WITH_UUID_QUERY:
844                 peripheral->gatt_client_state = P_W4_SERVICE_WITH_UUID_RESULT;
845                 send_gatt_services_by_uuid_request(peripheral);
846                 return;
847 
848             case P_W2_SEND_ALL_CHARACTERISTICS_OF_SERVICE_QUERY:
849                 peripheral->gatt_client_state = P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT;
850                 send_gatt_characteristic_request(peripheral);
851                 return;
852 
853             case P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY:
854                 peripheral->gatt_client_state = P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT;
855                 send_gatt_characteristic_request(peripheral);
856                 return;
857 
858             case P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY:
859                 peripheral->gatt_client_state = P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT;
860                 send_gatt_characteristic_descriptor_request(peripheral);
861                 return;
862 
863             case P_W2_SEND_INCLUDED_SERVICE_QUERY:
864                 peripheral->gatt_client_state = P_W4_INCLUDED_SERVICE_QUERY_RESULT;
865                 send_gatt_included_service_request(peripheral);
866                 return;
867 
868             case P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY:
869                 peripheral->gatt_client_state = P_W4_INCLUDED_SERVICE_UUID_WITH_QUERY_RESULT;
870                 send_gatt_included_service_uuid_request(peripheral);
871                 return;
872 
873             case P_W2_SEND_READ_CHARACTERISTIC_VALUE_QUERY:
874                 peripheral->gatt_client_state = P_W4_READ_CHARACTERISTIC_VALUE_RESULT;
875                 send_gatt_read_characteristic_value_request(peripheral);
876                 return;
877 
878             case P_W2_SEND_READ_BLOB_QUERY:
879                 peripheral->gatt_client_state = P_W4_READ_BLOB_RESULT;
880                 send_gatt_read_blob_request(peripheral);
881                 return;
882 
883             case P_W2_SEND_READ_BY_TYPE_REQUEST:
884                 peripheral->gatt_client_state = P_W4_READ_BY_TYPE_RESPONSE;
885                 send_gatt_read_by_type_request(peripheral);
886                 break;
887 
888             case P_W2_SEND_READ_MULTIPLE_REQUEST:
889                 peripheral->gatt_client_state = P_W4_READ_MULTIPLE_RESPONSE;
890                 send_gatt_read_multiple_request(peripheral);
891                 break;
892 
893             case P_W2_SEND_WRITE_CHARACTERISTIC_VALUE:
894                 peripheral->gatt_client_state = P_W4_WRITE_CHARACTERISTIC_VALUE_RESULT;
895                 send_gatt_write_attribute_value_request(peripheral);
896                 return;
897 
898             case P_W2_PREPARE_WRITE:
899                 peripheral->gatt_client_state = P_W4_PREPARE_WRITE_RESULT;
900                 send_gatt_prepare_write_request(peripheral);
901                 return;
902 
903             case P_W2_PREPARE_WRITE_SINGLE:
904                 peripheral->gatt_client_state = P_W4_PREPARE_WRITE_SINGLE_RESULT;
905                 send_gatt_prepare_write_request(peripheral);
906                 return;
907 
908             case P_W2_PREPARE_RELIABLE_WRITE:
909                 peripheral->gatt_client_state = P_W4_PREPARE_RELIABLE_WRITE_RESULT;
910                 send_gatt_prepare_write_request(peripheral);
911                 return;
912 
913             case P_W2_EXECUTE_PREPARED_WRITE:
914                 peripheral->gatt_client_state = P_W4_EXECUTE_PREPARED_WRITE_RESULT;
915                 send_gatt_execute_write_request(peripheral);
916                 return;
917 
918             case P_W2_CANCEL_PREPARED_WRITE:
919                 peripheral->gatt_client_state = P_W4_CANCEL_PREPARED_WRITE_RESULT;
920                 send_gatt_cancel_prepared_write_request(peripheral);
921                 return;
922 
923             case P_W2_CANCEL_PREPARED_WRITE_DATA_MISMATCH:
924                 peripheral->gatt_client_state = P_W4_CANCEL_PREPARED_WRITE_DATA_MISMATCH_RESULT;
925                 send_gatt_cancel_prepared_write_request(peripheral);
926                 return;
927 
928             case P_W2_SEND_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY:
929                 peripheral->gatt_client_state = P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT;
930                 send_gatt_read_client_characteristic_configuration_request(peripheral);
931                 return;
932 
933             case P_W2_SEND_READ_CHARACTERISTIC_DESCRIPTOR_QUERY:
934                 peripheral->gatt_client_state = P_W4_READ_CHARACTERISTIC_DESCRIPTOR_RESULT;
935                 send_gatt_read_characteristic_descriptor_request(peripheral);
936                 return;
937 
938             case P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY:
939                 peripheral->gatt_client_state = P_W4_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_RESULT;
940                 send_gatt_read_blob_request(peripheral);
941                 return;
942 
943             case P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR:
944                 peripheral->gatt_client_state = P_W4_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
945                 send_gatt_write_attribute_value_request(peripheral);
946                 return;
947 
948             case P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION:
949                 peripheral->gatt_client_state = P_W4_CLIENT_CHARACTERISTIC_CONFIGURATION_RESULT;
950                 send_gatt_write_client_characteristic_configuration_request(peripheral);
951                 return;
952 
953             case P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR:
954                 peripheral->gatt_client_state = P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
955                 send_gatt_prepare_write_request(peripheral);
956                 return;
957 
958             case P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR:
959                 peripheral->gatt_client_state = P_W4_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
960                 send_gatt_execute_write_request(peripheral);
961                 return;
962 
963             case P_W4_CMAC_READY:
964                 if (sm_cmac_ready()){
965                     sm_key_t csrk;
966                     le_device_db_local_csrk_get(peripheral->le_device_index, csrk);
967                     uint32_t sign_counter = le_device_db_local_counter_get(peripheral->le_device_index);
968                     peripheral->gatt_client_state = P_W4_CMAC_RESULT;
969                     sm_cmac_start(csrk, ATT_SIGNED_WRITE_COMMAND, peripheral->attribute_handle, peripheral->attribute_length, peripheral->attribute_value, sign_counter, att_signed_write_handle_cmac_result);
970                 }
971                 return;
972 
973             case P_W2_SEND_SIGNED_WRITE: {
974                 peripheral->gatt_client_state = P_W4_SEND_SINGED_WRITE_DONE;
975                 // bump local signing counter
976                 uint32_t sign_counter = le_device_db_local_counter_get(peripheral->le_device_index);
977                 le_device_db_local_counter_set(peripheral->le_device_index, sign_counter + 1);
978 
979                 send_gatt_signed_write_request(peripheral, sign_counter);
980                 peripheral->gatt_client_state = P_READY;
981                 // finally, notifiy client that write is complete
982                 gatt_client_handle_transaction_complete(peripheral);
983                 return;
984             }
985 
986             default:
987                 break;
988         }
989     }
990 
991 }
992 
993 static void gatt_client_report_error_if_pending(gatt_client_t *peripheral, uint8_t error_code) {
994     if (is_ready(peripheral)) return;
995     gatt_client_handle_transaction_complete(peripheral);
996     emit_gatt_complete_event(peripheral, error_code);
997 }
998 
999 static void gatt_client_hci_event_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
1000     if (packet_type != HCI_EVENT_PACKET) return;
1001 
1002     switch (hci_event_packet_get_type(packet)) {
1003         case HCI_EVENT_DISCONNECTION_COMPLETE:
1004         {
1005             log_info("GATT Client: HCI_EVENT_DISCONNECTION_COMPLETE");
1006             hci_con_handle_t con_handle = little_endian_read_16(packet,3);
1007             gatt_client_t * peripheral = get_gatt_client_context_for_handle(con_handle);
1008             if (!peripheral) break;
1009             gatt_client_report_error_if_pending(peripheral, ATT_ERROR_HCI_DISCONNECT_RECEIVED);
1010 
1011             btstack_linked_list_remove(&gatt_client_connections, (btstack_linked_item_t *) peripheral);
1012             btstack_memory_gatt_client_free(peripheral);
1013             break;
1014         }
1015         default:
1016             break;
1017     }
1018 
1019     gatt_client_run();
1020 }
1021 
1022 static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){
1023 
1024     if (packet_type != ATT_DATA_PACKET) return;
1025 
1026     // special cases: notifications don't need a context while indications motivate creating one
1027     gatt_client_t * peripheral;
1028     switch (packet[0]){
1029         case ATT_HANDLE_VALUE_NOTIFICATION:
1030             report_gatt_notification(handle, little_endian_read_16(packet,1), &packet[3], size-3);
1031             return;
1032         case ATT_HANDLE_VALUE_INDICATION:
1033             peripheral = provide_context_for_conn_handle(handle);
1034             break;
1035         default:
1036             peripheral = get_gatt_client_context_for_handle(handle);
1037             break;
1038     }
1039 
1040     if (!peripheral) return;
1041 
1042     switch (packet[0]){
1043         case ATT_EXCHANGE_MTU_RESPONSE:
1044         {
1045             uint16_t remote_rx_mtu = little_endian_read_16(packet, 1);
1046             uint16_t local_rx_mtu = l2cap_max_le_mtu();
1047             peripheral->mtu = remote_rx_mtu < local_rx_mtu ? remote_rx_mtu : local_rx_mtu;
1048             peripheral->mtu_state = MTU_EXCHANGED;
1049 
1050             break;
1051         }
1052         case ATT_READ_BY_GROUP_TYPE_RESPONSE:
1053             switch(peripheral->gatt_client_state){
1054                 case P_W4_SERVICE_QUERY_RESULT:
1055                     report_gatt_services(peripheral, packet, size);
1056                     trigger_next_service_query(peripheral, get_last_result_handle_from_service_list(packet, size));
1057                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1058                     break;
1059                 default:
1060                     break;
1061             }
1062             break;
1063         case ATT_HANDLE_VALUE_INDICATION:
1064             report_gatt_indication(handle, little_endian_read_16(packet,1), &packet[3], size-3);
1065             peripheral->send_confirmation = 1;
1066             break;
1067 
1068         case ATT_READ_BY_TYPE_RESPONSE:
1069             switch (peripheral->gatt_client_state){
1070                 case P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT:
1071                     report_gatt_characteristics(peripheral, packet, size);
1072                     trigger_next_characteristic_query(peripheral, get_last_result_handle_from_characteristics_list(packet, size));
1073                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done, or by ATT_ERROR
1074                     break;
1075                 case P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT:
1076                     report_gatt_characteristics(peripheral, packet, size);
1077                     trigger_next_characteristic_query(peripheral, get_last_result_handle_from_characteristics_list(packet, size));
1078                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done, or by ATT_ERROR
1079                     break;
1080                 case P_W4_INCLUDED_SERVICE_QUERY_RESULT:
1081                 {
1082                     uint16_t uuid16 = 0;
1083                     uint16_t pair_size = packet[1];
1084 
1085                     if (pair_size < 7){
1086                         // UUIDs not available, query first included service
1087                         peripheral->start_group_handle = little_endian_read_16(packet, 2); // ready for next query
1088                         peripheral->query_start_handle = little_endian_read_16(packet, 4);
1089                         peripheral->query_end_handle = little_endian_read_16(packet,6);
1090                         peripheral->gatt_client_state = P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY;
1091                         break;
1092                     }
1093 
1094                     uint16_t offset;
1095                     for (offset = 2; offset < size; offset += pair_size){
1096                         uint16_t include_handle = little_endian_read_16(packet, offset);
1097                         peripheral->query_start_handle = little_endian_read_16(packet,offset+2);
1098                         peripheral->query_end_handle = little_endian_read_16(packet,offset+4);
1099                         uuid16 = little_endian_read_16(packet, offset+6);
1100                         report_gatt_included_service_uuid16(peripheral, include_handle, uuid16);
1101                     }
1102 
1103                     trigger_next_included_service_query(peripheral, get_last_result_handle_from_included_services_list(packet, size));
1104                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1105                     break;
1106                 }
1107                 case P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT:
1108                     peripheral->client_characteristic_configuration_handle = little_endian_read_16(packet, 2);
1109                     peripheral->gatt_client_state = P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
1110                     break;
1111                 case P_W4_READ_BY_TYPE_RESPONSE: {
1112                     uint16_t pair_size = packet[1];
1113                     uint16_t offset;
1114                     uint16_t last_result_handle = 0;
1115                     for (offset = 2; offset < size ; offset += pair_size){
1116                         uint16_t value_handle = little_endian_read_16(packet, offset);
1117                         report_gatt_characteristic_value(peripheral, value_handle, &packet[offset+2], pair_size-2);
1118                         last_result_handle = value_handle;
1119                     }
1120                     trigger_next_read_by_type_query(peripheral, last_result_handle);
1121                     break;
1122                 }
1123                 default:
1124                     break;
1125             }
1126             break;
1127         case ATT_READ_RESPONSE:
1128             switch (peripheral->gatt_client_state){
1129                 case P_W4_INCLUDED_SERVICE_UUID_WITH_QUERY_RESULT: {
1130                     uint8_t uuid128[16];
1131                     reverse_128(&packet[1], uuid128);
1132                     report_gatt_included_service_uuid128(peripheral, peripheral->start_group_handle, uuid128);
1133                     trigger_next_included_service_query(peripheral, peripheral->start_group_handle);
1134                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1135                     break;
1136                 }
1137                 case P_W4_READ_CHARACTERISTIC_VALUE_RESULT:
1138                     gatt_client_handle_transaction_complete(peripheral);
1139                     report_gatt_characteristic_value(peripheral, peripheral->attribute_handle, &packet[1], size-1);
1140                     emit_gatt_complete_event(peripheral, 0);
1141                     break;
1142 
1143                 case P_W4_READ_CHARACTERISTIC_DESCRIPTOR_RESULT:{
1144                     gatt_client_handle_transaction_complete(peripheral);
1145                     report_gatt_characteristic_descriptor(peripheral, peripheral->attribute_handle, &packet[1], size-1, 0);
1146                     emit_gatt_complete_event(peripheral, 0);
1147                     break;
1148                 }
1149                 default:
1150                     break;
1151             }
1152             break;
1153 
1154         case ATT_FIND_BY_TYPE_VALUE_RESPONSE:
1155         {
1156             uint8_t pair_size = 4;
1157             int i;
1158             uint16_t start_group_handle;
1159             uint16_t   end_group_handle= 0xffff; // asserts GATT_EVENT_QUERY_COMPLETE is emitted if no results
1160             for (i = 1; i<size; i+=pair_size){
1161                 start_group_handle = little_endian_read_16(packet,i);
1162                 end_group_handle = little_endian_read_16(packet,i+2);
1163                 emit_gatt_service_query_result_event(peripheral, start_group_handle, end_group_handle, peripheral->uuid128);
1164             }
1165             trigger_next_service_by_uuid_query(peripheral, end_group_handle);
1166             // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1167             break;
1168         }
1169         case ATT_FIND_INFORMATION_REPLY:
1170         {
1171             uint8_t pair_size = 4;
1172             if (packet[1] == 2){
1173                 pair_size = 18;
1174             }
1175             uint16_t last_descriptor_handle = little_endian_read_16(packet, size - pair_size);
1176 
1177             report_gatt_all_characteristic_descriptors(peripheral, &packet[2], size-2, pair_size);
1178             trigger_next_characteristic_descriptor_query(peripheral, last_descriptor_handle);
1179             // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1180             break;
1181         }
1182 
1183         case ATT_WRITE_RESPONSE:
1184             switch (peripheral->gatt_client_state){
1185                 case P_W4_WRITE_CHARACTERISTIC_VALUE_RESULT:
1186                     gatt_client_handle_transaction_complete(peripheral);
1187                     emit_gatt_complete_event(peripheral, 0);
1188                     break;
1189                 case P_W4_CLIENT_CHARACTERISTIC_CONFIGURATION_RESULT:
1190                     gatt_client_handle_transaction_complete(peripheral);
1191                     emit_gatt_complete_event(peripheral, 0);
1192                     break;
1193                 case P_W4_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:
1194                     gatt_client_handle_transaction_complete(peripheral);
1195                     emit_gatt_complete_event(peripheral, 0);
1196                     break;
1197                 default:
1198                     break;
1199             }
1200             break;
1201 
1202         case ATT_READ_BLOB_RESPONSE:{
1203             uint16_t received_blob_length = size-1;
1204 
1205             switch(peripheral->gatt_client_state){
1206                 case P_W4_READ_BLOB_RESULT:
1207                     report_gatt_long_characteristic_value_blob(peripheral, peripheral->attribute_handle, &packet[1], received_blob_length, peripheral->attribute_offset);
1208                     trigger_next_blob_query(peripheral, P_W2_SEND_READ_BLOB_QUERY, received_blob_length);
1209                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1210                     break;
1211                 case P_W4_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_RESULT:
1212                     report_gatt_long_characteristic_descriptor(peripheral, peripheral->attribute_handle,
1213                                                           &packet[1], received_blob_length,
1214                                                           peripheral->attribute_offset);
1215                     trigger_next_blob_query(peripheral, P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY, received_blob_length);
1216                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1217                     break;
1218                 default:
1219                     break;
1220             }
1221             break;
1222         }
1223         case ATT_PREPARE_WRITE_RESPONSE:
1224             switch (peripheral->gatt_client_state){
1225                 case P_W4_PREPARE_WRITE_SINGLE_RESULT:
1226                     gatt_client_handle_transaction_complete(peripheral);
1227                     if (is_value_valid(peripheral, packet, size)){
1228                         emit_gatt_complete_event(peripheral, 0);
1229                     } else {
1230                         emit_gatt_complete_event(peripheral, ATT_ERROR_DATA_MISMATCH);
1231                     }
1232                     break;
1233 
1234                 case P_W4_PREPARE_WRITE_RESULT:{
1235                     peripheral->attribute_offset = little_endian_read_16(packet, 3);
1236                     trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_WRITE, P_W2_EXECUTE_PREPARED_WRITE);
1237                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1238                     break;
1239                 }
1240                 case P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:{
1241                     peripheral->attribute_offset = little_endian_read_16(packet, 3);
1242                     trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR, P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR);
1243                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1244                     break;
1245                 }
1246                 case P_W4_PREPARE_RELIABLE_WRITE_RESULT:{
1247                     if (is_value_valid(peripheral, packet, size)){
1248                         peripheral->attribute_offset = little_endian_read_16(packet, 3);
1249                         trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_RELIABLE_WRITE, P_W2_EXECUTE_PREPARED_WRITE);
1250                         // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1251                         break;
1252                     }
1253                     peripheral->gatt_client_state = P_W2_CANCEL_PREPARED_WRITE_DATA_MISMATCH;
1254                     break;
1255                 }
1256                 default:
1257                     break;
1258             }
1259             break;
1260 
1261         case ATT_EXECUTE_WRITE_RESPONSE:
1262             switch (peripheral->gatt_client_state){
1263                 case P_W4_EXECUTE_PREPARED_WRITE_RESULT:
1264                     gatt_client_handle_transaction_complete(peripheral);
1265                     emit_gatt_complete_event(peripheral, 0);
1266                     break;
1267                 case P_W4_CANCEL_PREPARED_WRITE_RESULT:
1268                     gatt_client_handle_transaction_complete(peripheral);
1269                     emit_gatt_complete_event(peripheral, 0);
1270                     break;
1271                 case P_W4_CANCEL_PREPARED_WRITE_DATA_MISMATCH_RESULT:
1272                     gatt_client_handle_transaction_complete(peripheral);
1273                     emit_gatt_complete_event(peripheral, ATT_ERROR_DATA_MISMATCH);
1274                     break;
1275                 case P_W4_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:
1276                     gatt_client_handle_transaction_complete(peripheral);
1277                     emit_gatt_complete_event(peripheral, 0);
1278                     break;
1279                 default:
1280                     break;
1281 
1282             }
1283             break;
1284 
1285         case ATT_READ_MULTIPLE_RESPONSE:
1286             switch(peripheral->gatt_client_state){
1287                 case P_W4_READ_MULTIPLE_RESPONSE:
1288                     report_gatt_characteristic_value(peripheral, 0, &packet[1], size-1);
1289                     gatt_client_handle_transaction_complete(peripheral);
1290                     emit_gatt_complete_event(peripheral, 0);
1291                     break;
1292                 default:
1293                     break;
1294             }
1295             break;
1296 
1297         case ATT_ERROR_RESPONSE:
1298 
1299             switch (packet[4]){
1300                 case ATT_ERROR_ATTRIBUTE_NOT_FOUND: {
1301                     switch(peripheral->gatt_client_state){
1302                         case P_W4_SERVICE_QUERY_RESULT:
1303                         case P_W4_SERVICE_WITH_UUID_RESULT:
1304                         case P_W4_INCLUDED_SERVICE_QUERY_RESULT:
1305                         case P_W4_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT:
1306                             gatt_client_handle_transaction_complete(peripheral);
1307                             emit_gatt_complete_event(peripheral, 0);
1308                             break;
1309                         case P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT:
1310                         case P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT:
1311                             characteristic_end_found(peripheral, peripheral->end_group_handle);
1312                             gatt_client_handle_transaction_complete(peripheral);
1313                             emit_gatt_complete_event(peripheral, 0);
1314                             break;
1315                         case P_W4_READ_BY_TYPE_RESPONSE:
1316                             gatt_client_handle_transaction_complete(peripheral);
1317                             if (peripheral->start_group_handle == peripheral->query_start_handle){
1318                                 emit_gatt_complete_event(peripheral, ATT_ERROR_ATTRIBUTE_NOT_FOUND);
1319                             } else {
1320                                 emit_gatt_complete_event(peripheral, 0);
1321                             }
1322                             break;
1323                         default:
1324                             gatt_client_report_error_if_pending(peripheral, packet[4]);
1325                             break;
1326                     }
1327                     break;
1328                 }
1329                 default:
1330                     gatt_client_report_error_if_pending(peripheral, packet[4]);
1331                     break;
1332             }
1333             break;
1334 
1335         default:
1336             log_info("ATT Handler, unhandled response type 0x%02x", packet[0]);
1337             break;
1338     }
1339     gatt_client_run();
1340 }
1341 
1342 static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
1343     btstack_linked_list_iterator_t it;
1344     btstack_linked_list_iterator_init(&it, &gatt_client_connections);
1345     while (btstack_linked_list_iterator_has_next(&it)){
1346         gatt_client_t * peripheral = (gatt_client_t *) btstack_linked_list_iterator_next(&it);
1347         if (peripheral->gatt_client_state == P_W4_CMAC_RESULT){
1348             // store result
1349             memcpy(peripheral->cmac, hash, 8);
1350             // reverse_64(hash, peripheral->cmac);
1351             peripheral->gatt_client_state = P_W2_SEND_SIGNED_WRITE;
1352             gatt_client_run();
1353             return;
1354         }
1355     }
1356 }
1357 
1358 uint8_t gatt_client_signed_write_without_response(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t handle, uint16_t message_len, uint8_t * message){
1359     gatt_client_t * peripheral = provide_context_for_conn_handle(con_handle);
1360     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1361     peripheral->le_device_index = sm_le_device_index(con_handle);
1362     if (peripheral->le_device_index < 0) return GATT_CLIENT_IN_WRONG_STATE; // device lookup not done / no stored bonding information
1363 
1364     peripheral->callback = callback;
1365     peripheral->attribute_handle = handle;
1366     peripheral->attribute_length = message_len;
1367     peripheral->attribute_value = message;
1368     peripheral->gatt_client_state = P_W4_CMAC_READY;
1369 
1370     gatt_client_run();
1371     return 0;
1372 }
1373 
1374 uint8_t gatt_client_discover_primary_services(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
1375     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1376     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1377     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1378 
1379     peripheral->callback = callback;
1380     peripheral->start_group_handle = 0x0001;
1381     peripheral->end_group_handle   = 0xffff;
1382     peripheral->gatt_client_state = P_W2_SEND_SERVICE_QUERY;
1383     peripheral->uuid16 = 0;
1384     gatt_client_run();
1385     return 0;
1386 }
1387 
1388 
1389 uint8_t gatt_client_discover_primary_services_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t uuid16){
1390     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1391 
1392     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1393     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1394 
1395     peripheral->callback = callback;
1396     peripheral->start_group_handle = 0x0001;
1397     peripheral->end_group_handle   = 0xffff;
1398     peripheral->gatt_client_state = P_W2_SEND_SERVICE_WITH_UUID_QUERY;
1399     peripheral->uuid16 = uuid16;
1400     uuid_add_bluetooth_prefix((uint8_t*) &(peripheral->uuid128), peripheral->uuid16);
1401     gatt_client_run();
1402     return 0;
1403 }
1404 
1405 uint8_t gatt_client_discover_primary_services_by_uuid128(btstack_packet_handler_t callback, hci_con_handle_t con_handle, const uint8_t * uuid128){
1406     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1407 
1408     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1409     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1410 
1411     peripheral->callback = callback;
1412     peripheral->start_group_handle = 0x0001;
1413     peripheral->end_group_handle   = 0xffff;
1414     peripheral->uuid16 = 0;
1415     memcpy(peripheral->uuid128, uuid128, 16);
1416     peripheral->gatt_client_state = P_W2_SEND_SERVICE_WITH_UUID_QUERY;
1417     gatt_client_run();
1418     return 0;
1419 }
1420 
1421 uint8_t gatt_client_discover_characteristics_for_service(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_service_t *service){
1422     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1423 
1424     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1425     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1426 
1427     peripheral->callback = callback;
1428     peripheral->start_group_handle = service->start_group_handle;
1429     peripheral->end_group_handle   = service->end_group_handle;
1430     peripheral->filter_with_uuid = 0;
1431     peripheral->characteristic_start_handle = 0;
1432     peripheral->gatt_client_state = P_W2_SEND_ALL_CHARACTERISTICS_OF_SERVICE_QUERY;
1433     gatt_client_run();
1434     return 0;
1435 }
1436 
1437 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){
1438     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1439 
1440     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1441     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1442 
1443     peripheral->callback = callback;
1444     peripheral->start_group_handle = service->start_group_handle;
1445     peripheral->end_group_handle   = service->end_group_handle;
1446     peripheral->gatt_client_state = P_W2_SEND_INCLUDED_SERVICE_QUERY;
1447 
1448     gatt_client_run();
1449     return 0;
1450 }
1451 
1452 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){
1453     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1454 
1455     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1456     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1457 
1458     peripheral->callback = callback;
1459     peripheral->start_group_handle = start_handle;
1460     peripheral->end_group_handle   = end_handle;
1461     peripheral->filter_with_uuid = 1;
1462     peripheral->uuid16 = uuid16;
1463     uuid_add_bluetooth_prefix((uint8_t*) &(peripheral->uuid128), uuid16);
1464     peripheral->characteristic_start_handle = 0;
1465     peripheral->gatt_client_state = P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY;
1466 
1467     gatt_client_run();
1468     return 0;
1469 }
1470 
1471 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, uint8_t * uuid128){
1472     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1473 
1474     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1475     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1476 
1477     peripheral->callback = callback;
1478     peripheral->start_group_handle = start_handle;
1479     peripheral->end_group_handle   = end_handle;
1480     peripheral->filter_with_uuid = 1;
1481     peripheral->uuid16 = 0;
1482     memcpy(peripheral->uuid128, uuid128, 16);
1483     peripheral->characteristic_start_handle = 0;
1484     peripheral->gatt_client_state = P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY;
1485 
1486     gatt_client_run();
1487     return 0;
1488 }
1489 
1490 
1491 uint8_t gatt_client_discover_characteristics_for_service_by_uuid16(btstack_packet_handler_t callback, uint16_t handle, gatt_client_service_t *service, uint16_t  uuid16){
1492     return gatt_client_discover_characteristics_for_handle_range_by_uuid16(callback, handle, service->start_group_handle, service->end_group_handle, uuid16);
1493 }
1494 
1495 uint8_t gatt_client_discover_characteristics_for_service_by_uuid128(btstack_packet_handler_t callback, uint16_t handle, gatt_client_service_t *service, uint8_t * uuid128){
1496     return gatt_client_discover_characteristics_for_handle_range_by_uuid128(callback, handle, service->start_group_handle, service->end_group_handle, uuid128);
1497 }
1498 
1499 uint8_t gatt_client_discover_characteristic_descriptors(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t *characteristic){
1500     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1501 
1502     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1503     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1504 
1505     if (characteristic->value_handle == characteristic->end_handle){
1506         emit_gatt_complete_event(peripheral, 0);
1507         return 0;
1508     }
1509     peripheral->callback = callback;
1510     peripheral->start_group_handle = characteristic->value_handle + 1;
1511     peripheral->end_group_handle   = characteristic->end_handle;
1512     peripheral->gatt_client_state = P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY;
1513 
1514     gatt_client_run();
1515     return 0;
1516 }
1517 
1518 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){
1519     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1520 
1521     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1522     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1523 
1524     peripheral->callback = callback;
1525     peripheral->attribute_handle = value_handle;
1526     peripheral->attribute_offset = 0;
1527     peripheral->gatt_client_state = P_W2_SEND_READ_CHARACTERISTIC_VALUE_QUERY;
1528     gatt_client_run();
1529     return 0;
1530 }
1531 
1532 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){
1533     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1534 
1535     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1536     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1537 
1538     peripheral->callback = callback;
1539     peripheral->start_group_handle = start_handle;
1540     peripheral->end_group_handle = end_handle;
1541     peripheral->query_start_handle = start_handle;
1542     peripheral->query_end_handle = end_handle;
1543     peripheral->uuid16 = uuid16;
1544     uuid_add_bluetooth_prefix((uint8_t*) &(peripheral->uuid128), uuid16);
1545     peripheral->gatt_client_state = P_W2_SEND_READ_BY_TYPE_REQUEST;
1546     gatt_client_run();
1547     return 0;
1548 }
1549 
1550 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, uint8_t * uuid128){
1551     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1552 
1553     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1554     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1555 
1556     peripheral->callback = callback;
1557     peripheral->start_group_handle = start_handle;
1558     peripheral->end_group_handle = end_handle;
1559     peripheral->query_start_handle = start_handle;
1560     peripheral->query_end_handle = end_handle;
1561     peripheral->uuid16 = 0;
1562     memcpy(peripheral->uuid128, uuid128, 16);
1563     peripheral->gatt_client_state = P_W2_SEND_READ_BY_TYPE_REQUEST;
1564     gatt_client_run();
1565     return 0;
1566 }
1567 
1568 
1569 uint8_t gatt_client_read_value_of_characteristic(btstack_packet_handler_t callback, uint16_t handle, gatt_client_characteristic_t *characteristic){
1570     return gatt_client_read_value_of_characteristic_using_value_handle(callback, handle, characteristic->value_handle);
1571 }
1572 
1573 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 characteristic_value_handle, uint16_t offset){
1574     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1575 
1576     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1577     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1578 
1579     peripheral->callback = callback;
1580     peripheral->attribute_handle = characteristic_value_handle;
1581     peripheral->attribute_offset = offset;
1582     peripheral->gatt_client_state = P_W2_SEND_READ_BLOB_QUERY;
1583     gatt_client_run();
1584     return 0;
1585 }
1586 
1587 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 characteristic_value_handle){
1588     return gatt_client_read_long_value_of_characteristic_using_value_handle_with_offset(callback, con_handle, characteristic_value_handle, 0);
1589 }
1590 
1591 uint8_t gatt_client_read_long_value_of_characteristic(btstack_packet_handler_t callback, uint16_t handle, gatt_client_characteristic_t *characteristic){
1592     return gatt_client_read_long_value_of_characteristic_using_value_handle(callback, handle, characteristic->value_handle);
1593 }
1594 
1595 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){
1596     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1597 
1598     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1599     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1600 
1601     peripheral->callback = callback;
1602     peripheral->read_multiple_handle_count = num_value_handles;
1603     peripheral->read_multiple_handles = value_handles;
1604     peripheral->gatt_client_state = P_W2_SEND_READ_MULTIPLE_REQUEST;
1605     gatt_client_run();
1606     return 0;
1607 }
1608 
1609 uint8_t gatt_client_write_value_of_characteristic_without_response(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle, uint16_t value_length, uint8_t * value){
1610     gatt_client_t * peripheral = provide_context_for_conn_handle(con_handle);
1611 
1612     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1613     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1614 
1615     if (value_length > peripheral_mtu(peripheral) - 3) return GATT_CLIENT_VALUE_TOO_LONG;
1616     if (!att_dispatch_server_can_send_now(peripheral->con_handle)) return GATT_CLIENT_BUSY;
1617 
1618     peripheral->callback = callback;
1619     att_write_request(ATT_WRITE_COMMAND, peripheral->con_handle, value_handle, value_length, value);
1620     return 0;
1621 }
1622 
1623 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 * data){
1624     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1625 
1626     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1627     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1628 
1629     peripheral->callback = callback;
1630     peripheral->attribute_handle = value_handle;
1631     peripheral->attribute_length = value_length;
1632     peripheral->attribute_value = data;
1633     peripheral->gatt_client_state = P_W2_SEND_WRITE_CHARACTERISTIC_VALUE;
1634     gatt_client_run();
1635     return 0;
1636 }
1637 
1638 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  * data){
1639     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1640 
1641     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1642     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1643 
1644     peripheral->callback = callback;
1645     peripheral->attribute_handle = value_handle;
1646     peripheral->attribute_length = value_length;
1647     peripheral->attribute_offset = offset;
1648     peripheral->attribute_value = data;
1649     peripheral->gatt_client_state = P_W2_PREPARE_WRITE;
1650     gatt_client_run();
1651     return 0;
1652 }
1653 
1654 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){
1655     return gatt_client_write_long_value_of_characteristic_with_offset(callback, con_handle, value_handle, 0, value_length, value);
1656 }
1657 
1658 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){
1659     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1660 
1661     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1662     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1663 
1664     peripheral->callback = callback;
1665     peripheral->attribute_handle = value_handle;
1666     peripheral->attribute_length = value_length;
1667     peripheral->attribute_offset = 0;
1668     peripheral->attribute_value = value;
1669     peripheral->gatt_client_state = P_W2_PREPARE_RELIABLE_WRITE;
1670     gatt_client_run();
1671     return 0;
1672 }
1673 
1674 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){
1675     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1676 
1677     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1678     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1679 
1680     if ( (configuration & GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION) &&
1681         (characteristic->properties & ATT_PROPERTY_NOTIFY) == 0) {
1682         log_info("gatt_client_write_client_characteristic_configuration: GATT_CLIENT_CHARACTERISTIC_NOTIFICATION_NOT_SUPPORTED");
1683         return GATT_CLIENT_CHARACTERISTIC_NOTIFICATION_NOT_SUPPORTED;
1684     } else if ( (configuration & GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION) &&
1685                (characteristic->properties & ATT_PROPERTY_INDICATE) == 0){
1686         log_info("gatt_client_write_client_characteristic_configuration: GATT_CLIENT_CHARACTERISTIC_INDICATION_NOT_SUPPORTED");
1687         return GATT_CLIENT_CHARACTERISTIC_INDICATION_NOT_SUPPORTED;
1688     }
1689 
1690     peripheral->callback = callback;
1691     peripheral->start_group_handle = characteristic->value_handle;
1692     peripheral->end_group_handle = characteristic->end_handle;
1693     little_endian_store_16(peripheral->client_characteristic_configuration_value, 0, configuration);
1694 
1695     peripheral->gatt_client_state = P_W2_SEND_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY;
1696     gatt_client_run();
1697     return 0;
1698 }
1699 
1700 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){
1701     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1702 
1703     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1704     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1705 
1706     peripheral->callback = callback;
1707     peripheral->attribute_handle = descriptor_handle;
1708 
1709     peripheral->gatt_client_state = P_W2_SEND_READ_CHARACTERISTIC_DESCRIPTOR_QUERY;
1710     gatt_client_run();
1711     return 0;
1712 }
1713 
1714 uint8_t gatt_client_read_characteristic_descriptor(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_descriptor_t * descriptor){
1715     return gatt_client_read_characteristic_descriptor_using_descriptor_handle(callback, con_handle, descriptor->handle);
1716 }
1717 
1718 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){
1719     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1720 
1721     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1722     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1723 
1724     peripheral->callback = callback;
1725     peripheral->attribute_handle = descriptor_handle;
1726     peripheral->attribute_offset = offset;
1727     peripheral->gatt_client_state = P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY;
1728     gatt_client_run();
1729     return 0;
1730 }
1731 
1732 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){
1733     return gatt_client_read_long_characteristic_descriptor_using_descriptor_handle_with_offset(callback, con_handle, descriptor_handle, 0);
1734 }
1735 
1736 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){
1737     return gatt_client_read_long_characteristic_descriptor_using_descriptor_handle(callback, con_handle, descriptor->handle);
1738 }
1739 
1740 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 length, uint8_t  * data){
1741     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1742 
1743     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1744     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1745 
1746     peripheral->callback = callback;
1747     peripheral->attribute_handle = descriptor_handle;
1748     peripheral->attribute_length = length;
1749     peripheral->attribute_offset = 0;
1750     peripheral->attribute_value = data;
1751     peripheral->gatt_client_state = P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR;
1752     gatt_client_run();
1753     return 0;
1754 }
1755 
1756 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 length, uint8_t * value){
1757     return gatt_client_write_characteristic_descriptor_using_descriptor_handle(callback, con_handle, descriptor->handle, length, value);
1758 }
1759 
1760 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 length, uint8_t  * data){
1761     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1762 
1763     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1764     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1765 
1766     peripheral->callback = callback;
1767     peripheral->attribute_handle = descriptor_handle;
1768     peripheral->attribute_length = length;
1769     peripheral->attribute_offset = offset;
1770     peripheral->attribute_value = data;
1771     peripheral->gatt_client_state = P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR;
1772     gatt_client_run();
1773     return 0;
1774 }
1775 
1776 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 length, uint8_t * data){
1777     return gatt_client_write_long_characteristic_descriptor_using_descriptor_handle_with_offset(callback, con_handle, descriptor_handle, 0, length, data );
1778 }
1779 
1780 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 length, uint8_t * value){
1781     return gatt_client_write_long_characteristic_descriptor_using_descriptor_handle(callback, con_handle, descriptor->handle, length, value);
1782 }
1783 
1784 /**
1785  * @brief -> gatt complete event
1786  */
1787 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 length, uint8_t * data){
1788     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1789 
1790     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1791     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1792 
1793     peripheral->callback = callback;
1794     peripheral->attribute_handle = attribute_handle;
1795     peripheral->attribute_length = length;
1796     peripheral->attribute_offset = offset;
1797     peripheral->attribute_value = data;
1798     peripheral->gatt_client_state = P_W2_PREPARE_WRITE_SINGLE;
1799     gatt_client_run();
1800     return 0;
1801 }
1802 
1803 /**
1804  * @brief -> gatt complete event
1805  */
1806 uint8_t gatt_client_execute_write(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
1807     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1808 
1809     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1810     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1811 
1812     peripheral->callback = callback;
1813     peripheral->gatt_client_state = P_W2_EXECUTE_PREPARED_WRITE;
1814     gatt_client_run();
1815     return 0;
1816 }
1817 
1818 /**
1819  * @brief -> gatt complete event
1820  */
1821 uint8_t gatt_client_cancel_write(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
1822     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1823 
1824     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1825     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1826 
1827     peripheral->callback = callback;
1828     peripheral->gatt_client_state = P_W2_CANCEL_PREPARED_WRITE;
1829     gatt_client_run();
1830     return 0;
1831 }
1832 
1833 void gatt_client_pts_suppress_mtu_exchange(void){
1834     pts_suppress_mtu_exchange = 1;
1835 }
1836 
1837 void gatt_client_deserialize_service(const uint8_t *packet, int offset, gatt_client_service_t *service){
1838     service->start_group_handle = little_endian_read_16(packet, offset);
1839     service->end_group_handle = little_endian_read_16(packet, offset + 2);
1840     reverse_128(&packet[offset + 4], service->uuid128);
1841     if (uuid_has_bluetooth_prefix(service->uuid128)){
1842         service->uuid16 = big_endian_read_32(service->uuid128, 0);
1843     }
1844 }
1845 
1846 void gatt_client_deserialize_characteristic(const uint8_t * packet, int offset, gatt_client_characteristic_t * characteristic){
1847     characteristic->start_handle = little_endian_read_16(packet, offset);
1848     characteristic->value_handle = little_endian_read_16(packet, offset + 2);
1849     characteristic->end_handle = little_endian_read_16(packet, offset + 4);
1850     characteristic->properties = little_endian_read_16(packet, offset + 6);
1851     characteristic->uuid16 = little_endian_read_16(packet, offset + 8);
1852     reverse_128(&packet[offset+10], characteristic->uuid128);
1853     if (uuid_has_bluetooth_prefix(characteristic->uuid128)){
1854         characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0);
1855     }
1856 }
1857 
1858 void gatt_client_deserialize_characteristic_descriptor(const uint8_t * packet, int offset, gatt_client_characteristic_descriptor_t * descriptor){
1859     descriptor->handle = little_endian_read_16(packet, offset);
1860     reverse_128(&packet[offset+2], descriptor->uuid128);
1861 }
1862