xref: /btstack/src/ble/gatt_client.c (revision bc37f7b0d0a3eaa5763a873c5730bc14b849aaa0)
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 "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     hci_dump_packet(HCI_EVENT_PACKET, 0, packet, size);
454     (*callback)(HCI_EVENT_PACKET, 0, packet, size);
455 }
456 
457 void gatt_client_listen_for_characteristic_value_updates(gatt_client_notification_t * notification, btstack_packet_handler_t packet_handler, hci_con_handle_t con_handle, gatt_client_characteristic_t * characteristic){
458     notification->callback = packet_handler;
459     notification->con_handle = con_handle;
460     notification->attribute_handle = characteristic->value_handle;
461     btstack_linked_list_add(&gatt_client_value_listeners, (btstack_linked_item_t*) notification);
462 }
463 
464 static void emit_event_to_registered_listeners(hci_con_handle_t con_handle, uint16_t attribute_handle, uint8_t * packet, uint16_t size){
465     btstack_linked_list_iterator_t it;
466     btstack_linked_list_iterator_init(&it, &gatt_client_value_listeners);
467     while (btstack_linked_list_iterator_has_next(&it)){
468         gatt_client_notification_t * notification = (gatt_client_notification_t*) btstack_linked_list_iterator_next(&it);
469         if (notification->con_handle != con_handle) continue;
470         if (notification->attribute_handle != attribute_handle) continue;
471         (*notification->callback)(HCI_EVENT_PACKET, 0, packet, size);
472     }
473 }
474 
475 static void emit_gatt_complete_event(gatt_client_t * peripheral, uint8_t status){
476     // @format H1
477     uint8_t packet[5];
478     packet[0] = GATT_EVENT_QUERY_COMPLETE;
479     packet[1] = 3;
480     little_endian_store_16(packet, 2, peripheral->con_handle);
481     packet[4] = status;
482     emit_event_new(peripheral->callback, packet, sizeof(packet));
483 }
484 
485 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){
486     // @format HX
487     uint8_t packet[24];
488     packet[0] = GATT_EVENT_SERVICE_QUERY_RESULT;
489     packet[1] = sizeof(packet) - 2;
490     little_endian_store_16(packet, 2, peripheral->con_handle);
491     ///
492     little_endian_store_16(packet, 4, start_group_handle);
493     little_endian_store_16(packet, 6, end_group_handle);
494     reverse_128(uuid128, &packet[8]);
495     emit_event_new(peripheral->callback, packet, sizeof(packet));
496 }
497 
498 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){
499     // @format HX
500     uint8_t packet[26];
501     packet[0] = GATT_EVENT_INCLUDED_SERVICE_QUERY_RESULT;
502     packet[1] = sizeof(packet) - 2;
503     little_endian_store_16(packet, 2, peripheral->con_handle);
504     ///
505     little_endian_store_16(packet, 4, include_handle);
506     //
507     little_endian_store_16(packet, 6, start_group_handle);
508     little_endian_store_16(packet, 8, end_group_handle);
509     reverse_128(uuid128, &packet[10]);
510     emit_event_new(peripheral->callback, packet, sizeof(packet));
511 }
512 
513 static void emit_gatt_characteristic_query_result_event(gatt_client_t * peripheral, uint16_t start_handle, uint16_t value_handle, uint16_t end_handle,
514         uint16_t properties, uint8_t * uuid128){
515     // @format HY
516     uint8_t packet[28];
517     packet[0] = GATT_EVENT_CHARACTERISTIC_QUERY_RESULT;
518     packet[1] = sizeof(packet) - 2;
519     little_endian_store_16(packet, 2, peripheral->con_handle);
520     ///
521     little_endian_store_16(packet, 4,  start_handle);
522     little_endian_store_16(packet, 6,  value_handle);
523     little_endian_store_16(packet, 8,  end_handle);
524     little_endian_store_16(packet, 10, properties);
525     reverse_128(uuid128, &packet[12]);
526     emit_event_new(peripheral->callback, packet, sizeof(packet));
527 }
528 
529 static void emit_gatt_all_characteristic_descriptors_result_event(
530     gatt_client_t * peripheral, uint16_t descriptor_handle, uint8_t * uuid128){
531     // @format HZ
532     uint8_t packet[22];
533     packet[0] = GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT;
534     packet[1] = sizeof(packet) - 2;
535     little_endian_store_16(packet, 2, peripheral->con_handle);
536     ///
537     little_endian_store_16(packet, 4,  descriptor_handle);
538     reverse_128(uuid128, &packet[6]);
539     emit_event_new(peripheral->callback, packet, sizeof(packet));
540 }
541 ///
542 
543 static void report_gatt_services(gatt_client_t * peripheral, uint8_t * packet,  uint16_t size){
544     uint8_t attr_length = packet[1];
545     uint8_t uuid_length = attr_length - 4;
546 
547     int i;
548     for (i = 2; i < size; i += attr_length){
549         uint16_t start_group_handle = little_endian_read_16(packet,i);
550         uint16_t end_group_handle   = little_endian_read_16(packet,i+2);
551         uint8_t  uuid128[16];
552         uint16_t uuid16 = 0;
553 
554         if (uuid_length == 2){
555             uuid16 = little_endian_read_16(packet, i+4);
556             uuid_add_bluetooth_prefix((uint8_t*) &uuid128, uuid16);
557         } else {
558             reverse_128(&packet[i+4], uuid128);
559         }
560         emit_gatt_service_query_result_event(peripheral, start_group_handle, end_group_handle, uuid128);
561     }
562     // log_info("report_gatt_services for %02X done", peripheral->con_handle);
563 }
564 
565 // helper
566 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){
567     uint8_t uuid128[16];
568     uint16_t uuid16 = 0;
569     if (uuid_length == 2){
570         uuid16 = little_endian_read_16(uuid, 0);
571         uuid_add_bluetooth_prefix((uint8_t*) uuid128, uuid16);
572     } else {
573         reverse_128(uuid, uuid128);
574     }
575 
576     if (peripheral->filter_with_uuid && memcmp(peripheral->uuid128, uuid128, 16) != 0) return;
577 
578     peripheral->characteristic_properties = properties;
579     peripheral->characteristic_start_handle = start_handle;
580     peripheral->attribute_handle = value_handle;
581 
582     if (peripheral->filter_with_uuid) return;
583 
584     peripheral->uuid16 = uuid16;
585     memcpy(peripheral->uuid128, uuid128, 16);
586 }
587 
588 static void characteristic_end_found(gatt_client_t * peripheral, uint16_t end_handle){
589     // TODO: stop searching if filter and uuid found
590 
591     if (!peripheral->characteristic_start_handle) return;
592 
593     emit_gatt_characteristic_query_result_event(peripheral, peripheral->characteristic_start_handle, peripheral->attribute_handle,
594         end_handle, peripheral->characteristic_properties, peripheral->uuid128);
595 
596     peripheral->characteristic_start_handle = 0;
597 }
598 
599 static void report_gatt_characteristics(gatt_client_t * peripheral, uint8_t * packet,  uint16_t size){
600     uint8_t attr_length = packet[1];
601     uint8_t uuid_length = attr_length - 5;
602     int i;
603     for (i = 2; i < size; i += attr_length){
604         uint16_t start_handle = little_endian_read_16(packet, i);
605         uint8_t  properties = packet[i+2];
606         uint16_t value_handle = little_endian_read_16(packet, i+3);
607         characteristic_end_found(peripheral, start_handle-1);
608         characteristic_start_found(peripheral, start_handle, properties, value_handle, &packet[i+5], uuid_length);
609     }
610 }
611 
612 static void report_gatt_included_service_uuid16(gatt_client_t * peripheral, uint16_t include_handle, uint16_t uuid16){
613     uint8_t normalized_uuid128[16];
614     uuid_add_bluetooth_prefix(normalized_uuid128, uuid16);
615     emit_gatt_included_service_query_result_event(peripheral, include_handle, peripheral->query_start_handle,
616         peripheral->query_end_handle, normalized_uuid128);
617 }
618 
619 static void report_gatt_included_service_uuid128(gatt_client_t * peripheral, uint16_t include_handle, uint8_t *uuid128){
620     emit_gatt_included_service_query_result_event(peripheral, include_handle, peripheral->query_start_handle,
621         peripheral->query_end_handle, uuid128);
622 }
623 
624 // @returns packet pointer
625 // @note assume that value is part of an l2cap buffer - overwrite HCI + L2CAP packet headers
626 static const int characteristic_value_event_header_size = 8;
627 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){
628     // before the value inside the ATT PDU
629     uint8_t * packet = value - characteristic_value_event_header_size;
630     packet[0] = type;
631     packet[1] = characteristic_value_event_header_size - 2 + length;
632     little_endian_store_16(packet, 2, con_handle);
633     little_endian_store_16(packet, 4, attribute_handle);
634     little_endian_store_16(packet, 6, length);
635     return packet;
636 }
637 
638 // @returns packet pointer
639 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
640 static const int long_characteristic_value_event_header_size = 10;
641 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){
642 #if defined(HCI_INCOMING_PRE_BUFFER_SIZE) && (HCI_INCOMING_PRE_BUFFER_SIZE >= 10 - 8) // L2CAP Header (4) - ACL Header (4)
643     // before the value inside the ATT PDU
644     uint8_t * packet = value - long_characteristic_value_event_header_size;
645     packet[0] = type;
646     packet[1] = long_characteristic_value_event_header_size - 2 + length;
647     little_endian_store_16(packet, 2, con_handle);
648     little_endian_store_16(packet, 4, attribute_handle);
649     little_endian_store_16(packet, 6, offset);
650     little_endian_store_16(packet, 8, length);
651     return packet;
652 #else
653     log_error("HCI_INCOMING_PRE_BUFFER_SIZE >= 2 required for long characteristic reads");
654     return NULL;
655 #endif
656 }
657 
658 
659 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
660 static void report_gatt_notification(hci_con_handle_t con_handle, uint16_t value_handle, uint8_t * value, int length){
661     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_NOTIFICATION, con_handle, value_handle, value, length);
662     emit_event_to_registered_listeners(con_handle, value_handle, packet, characteristic_value_event_header_size + length);
663 }
664 
665 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
666 static void report_gatt_indication(hci_con_handle_t con_handle, uint16_t value_handle, uint8_t * value, int length){
667     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_INDICATION, con_handle, value_handle, value, length);
668     emit_event_to_registered_listeners(con_handle, value_handle, packet, characteristic_value_event_header_size + length);
669 }
670 
671 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
672 static void report_gatt_characteristic_value(gatt_client_t * peripheral, uint16_t attribute_handle, uint8_t * value, uint16_t length){
673     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT, peripheral->con_handle, attribute_handle, value, length);
674     emit_event_new(peripheral->callback, packet, characteristic_value_event_header_size + length);
675 }
676 
677 // @note assume that value is part of an l2cap buffer - overwrite parts of the HCI/L2CAP/ATT packet (4/4/3) bytes
678 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){
679     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);
680     if (!packet) return;
681     emit_event_new(peripheral->callback, packet, blob_length + long_characteristic_value_event_header_size);
682 }
683 
684 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){
685     uint8_t * packet = setup_characteristic_value_packet(GATT_EVENT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT, peripheral->con_handle, descriptor_handle, value, value_length);
686     emit_event_new(peripheral->callback, packet, value_length + 8);
687 }
688 
689 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){
690     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);
691     if (!packet) return;
692     emit_event_new(peripheral->callback, packet, blob_length + long_characteristic_value_event_header_size);
693 }
694 
695 static void report_gatt_all_characteristic_descriptors(gatt_client_t * peripheral, uint8_t * packet, uint16_t size, uint16_t pair_size){
696     int i;
697     for (i = 0; i<size; i+=pair_size){
698         uint16_t descriptor_handle = little_endian_read_16(packet,i);
699         uint8_t uuid128[16];
700         uint16_t uuid16 = 0;
701         if (pair_size == 4){
702             uuid16 = little_endian_read_16(packet,i+2);
703             uuid_add_bluetooth_prefix(uuid128, uuid16);
704         } else {
705             reverse_128(&packet[i+2], uuid128);
706         }
707         emit_gatt_all_characteristic_descriptors_result_event(peripheral, descriptor_handle, uuid128);
708     }
709 
710 }
711 
712 static int is_query_done(gatt_client_t * peripheral, uint16_t last_result_handle){
713     return last_result_handle >= peripheral->end_group_handle;
714 }
715 
716 static void trigger_next_query(gatt_client_t * peripheral, uint16_t last_result_handle, gatt_client_state_t next_query_state){
717     if (is_query_done(peripheral, last_result_handle)){
718         gatt_client_handle_transaction_complete(peripheral);
719         emit_gatt_complete_event(peripheral, 0);
720         return;
721     }
722     // next
723     peripheral->start_group_handle = last_result_handle + 1;
724     peripheral->gatt_client_state = next_query_state;
725 }
726 
727 static inline void trigger_next_included_service_query(gatt_client_t * peripheral, uint16_t last_result_handle){
728     trigger_next_query(peripheral, last_result_handle, P_W2_SEND_INCLUDED_SERVICE_QUERY);
729 }
730 
731 static inline void trigger_next_service_query(gatt_client_t * peripheral, uint16_t last_result_handle){
732     trigger_next_query(peripheral, last_result_handle, P_W2_SEND_SERVICE_QUERY);
733 }
734 
735 static inline void trigger_next_service_by_uuid_query(gatt_client_t * peripheral, uint16_t last_result_handle){
736     trigger_next_query(peripheral, last_result_handle, P_W2_SEND_SERVICE_WITH_UUID_QUERY);
737 }
738 
739 static inline void trigger_next_characteristic_query(gatt_client_t * peripheral, uint16_t last_result_handle){
740     if (is_query_done(peripheral, last_result_handle)){
741         // report last characteristic
742         characteristic_end_found(peripheral, peripheral->end_group_handle);
743     }
744     trigger_next_query(peripheral, last_result_handle, P_W2_SEND_ALL_CHARACTERISTICS_OF_SERVICE_QUERY);
745 }
746 
747 static inline void trigger_next_characteristic_descriptor_query(gatt_client_t * peripheral, uint16_t last_result_handle){
748     trigger_next_query(peripheral, last_result_handle, P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY);
749 }
750 
751 static inline void trigger_next_read_by_type_query(gatt_client_t * peripheral, uint16_t last_result_handle){
752     trigger_next_query(peripheral, last_result_handle, P_W2_SEND_READ_BY_TYPE_REQUEST);
753 }
754 
755 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){
756     peripheral->attribute_offset += write_blob_length(peripheral);
757     uint16_t next_blob_length =  write_blob_length(peripheral);
758 
759     if (next_blob_length == 0){
760         peripheral->gatt_client_state = done_state;
761         return;
762     }
763     peripheral->gatt_client_state = next_query_state;
764 }
765 
766 static inline void trigger_next_blob_query(gatt_client_t * peripheral, gatt_client_state_t next_query_state, uint16_t received_blob_length){
767 
768     uint16_t max_blob_length = peripheral_mtu(peripheral) - 1;
769     if (received_blob_length < max_blob_length){
770         gatt_client_handle_transaction_complete(peripheral);
771         emit_gatt_complete_event(peripheral, 0);
772         return;
773     }
774 
775     peripheral->attribute_offset += received_blob_length;
776     peripheral->gatt_client_state = next_query_state;
777 }
778 
779 
780 static int is_value_valid(gatt_client_t *peripheral, uint8_t *packet, uint16_t size){
781     uint16_t attribute_handle = little_endian_read_16(packet, 1);
782     uint16_t value_offset = little_endian_read_16(packet, 3);
783 
784     if (peripheral->attribute_handle != attribute_handle) return 0;
785     if (peripheral->attribute_offset != value_offset) return 0;
786     return memcmp(&peripheral->attribute_value[peripheral->attribute_offset], &packet[5], size-5) == 0;
787 }
788 
789 
790 static void gatt_client_run(void){
791 
792     btstack_linked_item_t *it;
793     for (it = (btstack_linked_item_t *) gatt_client_connections; it ; it = it->next){
794 
795         gatt_client_t * peripheral = (gatt_client_t *) it;
796 
797         if (!att_dispatch_client_can_send_now(peripheral->con_handle)) {
798             att_dispatch_client_request_can_send_now_event(peripheral->con_handle);
799             return;
800         }
801 
802         // log_info("- handle_peripheral_list, mtu state %u, client state %u", peripheral->mtu_state, peripheral->gatt_client_state);
803 
804         switch (peripheral->mtu_state) {
805             case SEND_MTU_EXCHANGE:{
806                 peripheral->mtu_state = SENT_MTU_EXCHANGE;
807                 att_exchange_mtu_request(peripheral->con_handle);
808                 return;
809             }
810             case SENT_MTU_EXCHANGE:
811                 return;
812             default:
813                 break;
814         }
815 
816         if (peripheral->send_confirmation){
817             peripheral->send_confirmation = 0;
818             att_confirmation(peripheral->con_handle);
819             return;
820         }
821 
822         // check MTU for writes
823         switch (peripheral->gatt_client_state){
824             case P_W2_SEND_WRITE_CHARACTERISTIC_VALUE:
825             case P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR:
826                 if (peripheral->attribute_length <= peripheral_mtu(peripheral) - 3) break;
827                 log_error("gatt_client_run: value len %u > MTU %u - 3\n", peripheral->attribute_length, peripheral_mtu(peripheral));
828                 gatt_client_handle_transaction_complete(peripheral);
829                 emit_gatt_complete_event(peripheral, ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH);
830                 return;
831             default:
832                 break;
833         }
834 
835         // log_info("gatt_client_state %u", peripheral->gatt_client_state);
836         switch (peripheral->gatt_client_state){
837             case P_W2_SEND_SERVICE_QUERY:
838                 peripheral->gatt_client_state = P_W4_SERVICE_QUERY_RESULT;
839                 send_gatt_services_request(peripheral);
840                 return;
841 
842             case P_W2_SEND_SERVICE_WITH_UUID_QUERY:
843                 peripheral->gatt_client_state = P_W4_SERVICE_WITH_UUID_RESULT;
844                 send_gatt_services_by_uuid_request(peripheral);
845                 return;
846 
847             case P_W2_SEND_ALL_CHARACTERISTICS_OF_SERVICE_QUERY:
848                 peripheral->gatt_client_state = P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT;
849                 send_gatt_characteristic_request(peripheral);
850                 return;
851 
852             case P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY:
853                 peripheral->gatt_client_state = P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT;
854                 send_gatt_characteristic_request(peripheral);
855                 return;
856 
857             case P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY:
858                 peripheral->gatt_client_state = P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT;
859                 send_gatt_characteristic_descriptor_request(peripheral);
860                 return;
861 
862             case P_W2_SEND_INCLUDED_SERVICE_QUERY:
863                 peripheral->gatt_client_state = P_W4_INCLUDED_SERVICE_QUERY_RESULT;
864                 send_gatt_included_service_request(peripheral);
865                 return;
866 
867             case P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY:
868                 peripheral->gatt_client_state = P_W4_INCLUDED_SERVICE_UUID_WITH_QUERY_RESULT;
869                 send_gatt_included_service_uuid_request(peripheral);
870                 return;
871 
872             case P_W2_SEND_READ_CHARACTERISTIC_VALUE_QUERY:
873                 peripheral->gatt_client_state = P_W4_READ_CHARACTERISTIC_VALUE_RESULT;
874                 send_gatt_read_characteristic_value_request(peripheral);
875                 return;
876 
877             case P_W2_SEND_READ_BLOB_QUERY:
878                 peripheral->gatt_client_state = P_W4_READ_BLOB_RESULT;
879                 send_gatt_read_blob_request(peripheral);
880                 return;
881 
882             case P_W2_SEND_READ_BY_TYPE_REQUEST:
883                 peripheral->gatt_client_state = P_W4_READ_BY_TYPE_RESPONSE;
884                 send_gatt_read_by_type_request(peripheral);
885                 break;
886 
887             case P_W2_SEND_READ_MULTIPLE_REQUEST:
888                 peripheral->gatt_client_state = P_W4_READ_MULTIPLE_RESPONSE;
889                 send_gatt_read_multiple_request(peripheral);
890                 break;
891 
892             case P_W2_SEND_WRITE_CHARACTERISTIC_VALUE:
893                 peripheral->gatt_client_state = P_W4_WRITE_CHARACTERISTIC_VALUE_RESULT;
894                 send_gatt_write_attribute_value_request(peripheral);
895                 return;
896 
897             case P_W2_PREPARE_WRITE:
898                 peripheral->gatt_client_state = P_W4_PREPARE_WRITE_RESULT;
899                 send_gatt_prepare_write_request(peripheral);
900                 return;
901 
902             case P_W2_PREPARE_WRITE_SINGLE:
903                 peripheral->gatt_client_state = P_W4_PREPARE_WRITE_SINGLE_RESULT;
904                 send_gatt_prepare_write_request(peripheral);
905                 return;
906 
907             case P_W2_PREPARE_RELIABLE_WRITE:
908                 peripheral->gatt_client_state = P_W4_PREPARE_RELIABLE_WRITE_RESULT;
909                 send_gatt_prepare_write_request(peripheral);
910                 return;
911 
912             case P_W2_EXECUTE_PREPARED_WRITE:
913                 peripheral->gatt_client_state = P_W4_EXECUTE_PREPARED_WRITE_RESULT;
914                 send_gatt_execute_write_request(peripheral);
915                 return;
916 
917             case P_W2_CANCEL_PREPARED_WRITE:
918                 peripheral->gatt_client_state = P_W4_CANCEL_PREPARED_WRITE_RESULT;
919                 send_gatt_cancel_prepared_write_request(peripheral);
920                 return;
921 
922             case P_W2_CANCEL_PREPARED_WRITE_DATA_MISMATCH:
923                 peripheral->gatt_client_state = P_W4_CANCEL_PREPARED_WRITE_DATA_MISMATCH_RESULT;
924                 send_gatt_cancel_prepared_write_request(peripheral);
925                 return;
926 
927             case P_W2_SEND_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY:
928                 peripheral->gatt_client_state = P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT;
929                 send_gatt_read_client_characteristic_configuration_request(peripheral);
930                 return;
931 
932             case P_W2_SEND_READ_CHARACTERISTIC_DESCRIPTOR_QUERY:
933                 peripheral->gatt_client_state = P_W4_READ_CHARACTERISTIC_DESCRIPTOR_RESULT;
934                 send_gatt_read_characteristic_descriptor_request(peripheral);
935                 return;
936 
937             case P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY:
938                 peripheral->gatt_client_state = P_W4_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_RESULT;
939                 send_gatt_read_blob_request(peripheral);
940                 return;
941 
942             case P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR:
943                 peripheral->gatt_client_state = P_W4_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
944                 send_gatt_write_attribute_value_request(peripheral);
945                 return;
946 
947             case P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION:
948                 peripheral->gatt_client_state = P_W4_CLIENT_CHARACTERISTIC_CONFIGURATION_RESULT;
949                 send_gatt_write_client_characteristic_configuration_request(peripheral);
950                 return;
951 
952             case P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR:
953                 peripheral->gatt_client_state = P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
954                 send_gatt_prepare_write_request(peripheral);
955                 return;
956 
957             case P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR:
958                 peripheral->gatt_client_state = P_W4_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT;
959                 send_gatt_execute_write_request(peripheral);
960                 return;
961 
962             case P_W4_CMAC_READY:
963                 if (sm_cmac_ready()){
964                     sm_key_t csrk;
965                     le_device_db_local_csrk_get(peripheral->le_device_index, csrk);
966                     uint32_t sign_counter = le_device_db_local_counter_get(peripheral->le_device_index);
967                     peripheral->gatt_client_state = P_W4_CMAC_RESULT;
968                     sm_cmac_signed_write_start(csrk, ATT_SIGNED_WRITE_COMMAND, peripheral->attribute_handle, peripheral->attribute_length, peripheral->attribute_value, sign_counter, att_signed_write_handle_cmac_result);
969                 }
970                 return;
971 
972             case P_W2_SEND_SIGNED_WRITE: {
973                 peripheral->gatt_client_state = P_W4_SEND_SINGED_WRITE_DONE;
974                 // bump local signing counter
975                 uint32_t sign_counter = le_device_db_local_counter_get(peripheral->le_device_index);
976                 le_device_db_local_counter_set(peripheral->le_device_index, sign_counter + 1);
977 
978                 send_gatt_signed_write_request(peripheral, sign_counter);
979                 peripheral->gatt_client_state = P_READY;
980                 // finally, notifiy client that write is complete
981                 gatt_client_handle_transaction_complete(peripheral);
982                 return;
983             }
984 
985             default:
986                 break;
987         }
988     }
989 
990 }
991 
992 static void gatt_client_report_error_if_pending(gatt_client_t *peripheral, uint8_t error_code) {
993     if (is_ready(peripheral)) return;
994     gatt_client_handle_transaction_complete(peripheral);
995     emit_gatt_complete_event(peripheral, error_code);
996 }
997 
998 static void gatt_client_hci_event_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
999     if (packet_type != HCI_EVENT_PACKET) return;
1000 
1001     switch (hci_event_packet_get_type(packet)) {
1002         case HCI_EVENT_DISCONNECTION_COMPLETE:
1003         {
1004             log_info("GATT Client: HCI_EVENT_DISCONNECTION_COMPLETE");
1005             hci_con_handle_t con_handle = little_endian_read_16(packet,3);
1006             gatt_client_t * peripheral = get_gatt_client_context_for_handle(con_handle);
1007             if (!peripheral) break;
1008             gatt_client_report_error_if_pending(peripheral, ATT_ERROR_HCI_DISCONNECT_RECEIVED);
1009 
1010             btstack_linked_list_remove(&gatt_client_connections, (btstack_linked_item_t *) peripheral);
1011             btstack_memory_gatt_client_free(peripheral);
1012             break;
1013         }
1014         default:
1015             break;
1016     }
1017 
1018     gatt_client_run();
1019 }
1020 
1021 static void gatt_client_att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){
1022 
1023     if (packet_type == HCI_EVENT_PACKET && packet[0] == L2CAP_EVENT_CAN_SEND_NOW){
1024         gatt_client_run();
1025     }
1026 
1027     if (packet_type != ATT_DATA_PACKET) return;
1028 
1029     // special cases: notifications don't need a context while indications motivate creating one
1030     gatt_client_t * peripheral;
1031     switch (packet[0]){
1032         case ATT_HANDLE_VALUE_NOTIFICATION:
1033             report_gatt_notification(handle, little_endian_read_16(packet,1), &packet[3], size-3);
1034             return;
1035         case ATT_HANDLE_VALUE_INDICATION:
1036             peripheral = provide_context_for_conn_handle(handle);
1037             break;
1038         default:
1039             peripheral = get_gatt_client_context_for_handle(handle);
1040             break;
1041     }
1042 
1043     if (!peripheral) return;
1044 
1045     switch (packet[0]){
1046         case ATT_EXCHANGE_MTU_RESPONSE:
1047         {
1048             uint16_t remote_rx_mtu = little_endian_read_16(packet, 1);
1049             uint16_t local_rx_mtu = l2cap_max_le_mtu();
1050             peripheral->mtu = remote_rx_mtu < local_rx_mtu ? remote_rx_mtu : local_rx_mtu;
1051             peripheral->mtu_state = MTU_EXCHANGED;
1052 
1053             break;
1054         }
1055         case ATT_READ_BY_GROUP_TYPE_RESPONSE:
1056             switch(peripheral->gatt_client_state){
1057                 case P_W4_SERVICE_QUERY_RESULT:
1058                     report_gatt_services(peripheral, packet, size);
1059                     trigger_next_service_query(peripheral, get_last_result_handle_from_service_list(packet, size));
1060                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1061                     break;
1062                 default:
1063                     break;
1064             }
1065             break;
1066         case ATT_HANDLE_VALUE_INDICATION:
1067             report_gatt_indication(handle, little_endian_read_16(packet,1), &packet[3], size-3);
1068             peripheral->send_confirmation = 1;
1069             break;
1070 
1071         case ATT_READ_BY_TYPE_RESPONSE:
1072             switch (peripheral->gatt_client_state){
1073                 case P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT:
1074                     report_gatt_characteristics(peripheral, packet, size);
1075                     trigger_next_characteristic_query(peripheral, get_last_result_handle_from_characteristics_list(packet, size));
1076                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done, or by ATT_ERROR
1077                     break;
1078                 case P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT:
1079                     report_gatt_characteristics(peripheral, packet, size);
1080                     trigger_next_characteristic_query(peripheral, get_last_result_handle_from_characteristics_list(packet, size));
1081                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done, or by ATT_ERROR
1082                     break;
1083                 case P_W4_INCLUDED_SERVICE_QUERY_RESULT:
1084                 {
1085                     uint16_t uuid16 = 0;
1086                     uint16_t pair_size = packet[1];
1087 
1088                     if (pair_size < 7){
1089                         // UUIDs not available, query first included service
1090                         peripheral->start_group_handle = little_endian_read_16(packet, 2); // ready for next query
1091                         peripheral->query_start_handle = little_endian_read_16(packet, 4);
1092                         peripheral->query_end_handle = little_endian_read_16(packet,6);
1093                         peripheral->gatt_client_state = P_W2_SEND_INCLUDED_SERVICE_WITH_UUID_QUERY;
1094                         break;
1095                     }
1096 
1097                     uint16_t offset;
1098                     for (offset = 2; offset < size; offset += pair_size){
1099                         uint16_t include_handle = little_endian_read_16(packet, offset);
1100                         peripheral->query_start_handle = little_endian_read_16(packet,offset+2);
1101                         peripheral->query_end_handle = little_endian_read_16(packet,offset+4);
1102                         uuid16 = little_endian_read_16(packet, offset+6);
1103                         report_gatt_included_service_uuid16(peripheral, include_handle, uuid16);
1104                     }
1105 
1106                     trigger_next_included_service_query(peripheral, get_last_result_handle_from_included_services_list(packet, size));
1107                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1108                     break;
1109                 }
1110                 case P_W4_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY_RESULT:
1111                     peripheral->client_characteristic_configuration_handle = little_endian_read_16(packet, 2);
1112                     peripheral->gatt_client_state = P_W2_WRITE_CLIENT_CHARACTERISTIC_CONFIGURATION;
1113                     break;
1114                 case P_W4_READ_BY_TYPE_RESPONSE: {
1115                     uint16_t pair_size = packet[1];
1116                     uint16_t offset;
1117                     uint16_t last_result_handle = 0;
1118                     for (offset = 2; offset < size ; offset += pair_size){
1119                         uint16_t value_handle = little_endian_read_16(packet, offset);
1120                         report_gatt_characteristic_value(peripheral, value_handle, &packet[offset+2], pair_size-2);
1121                         last_result_handle = value_handle;
1122                     }
1123                     trigger_next_read_by_type_query(peripheral, last_result_handle);
1124                     break;
1125                 }
1126                 default:
1127                     break;
1128             }
1129             break;
1130         case ATT_READ_RESPONSE:
1131             switch (peripheral->gatt_client_state){
1132                 case P_W4_INCLUDED_SERVICE_UUID_WITH_QUERY_RESULT: {
1133                     uint8_t uuid128[16];
1134                     reverse_128(&packet[1], uuid128);
1135                     report_gatt_included_service_uuid128(peripheral, peripheral->start_group_handle, uuid128);
1136                     trigger_next_included_service_query(peripheral, peripheral->start_group_handle);
1137                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1138                     break;
1139                 }
1140                 case P_W4_READ_CHARACTERISTIC_VALUE_RESULT:
1141                     gatt_client_handle_transaction_complete(peripheral);
1142                     report_gatt_characteristic_value(peripheral, peripheral->attribute_handle, &packet[1], size-1);
1143                     emit_gatt_complete_event(peripheral, 0);
1144                     break;
1145 
1146                 case P_W4_READ_CHARACTERISTIC_DESCRIPTOR_RESULT:{
1147                     gatt_client_handle_transaction_complete(peripheral);
1148                     report_gatt_characteristic_descriptor(peripheral, peripheral->attribute_handle, &packet[1], size-1, 0);
1149                     emit_gatt_complete_event(peripheral, 0);
1150                     break;
1151                 }
1152                 default:
1153                     break;
1154             }
1155             break;
1156 
1157         case ATT_FIND_BY_TYPE_VALUE_RESPONSE:
1158         {
1159             uint8_t pair_size = 4;
1160             int i;
1161             uint16_t start_group_handle;
1162             uint16_t   end_group_handle= 0xffff; // asserts GATT_EVENT_QUERY_COMPLETE is emitted if no results
1163             for (i = 1; i<size; i+=pair_size){
1164                 start_group_handle = little_endian_read_16(packet,i);
1165                 end_group_handle = little_endian_read_16(packet,i+2);
1166                 emit_gatt_service_query_result_event(peripheral, start_group_handle, end_group_handle, peripheral->uuid128);
1167             }
1168             trigger_next_service_by_uuid_query(peripheral, end_group_handle);
1169             // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1170             break;
1171         }
1172         case ATT_FIND_INFORMATION_REPLY:
1173         {
1174             uint8_t pair_size = 4;
1175             if (packet[1] == 2){
1176                 pair_size = 18;
1177             }
1178             uint16_t last_descriptor_handle = little_endian_read_16(packet, size - pair_size);
1179 
1180             report_gatt_all_characteristic_descriptors(peripheral, &packet[2], size-2, pair_size);
1181             trigger_next_characteristic_descriptor_query(peripheral, last_descriptor_handle);
1182             // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1183             break;
1184         }
1185 
1186         case ATT_WRITE_RESPONSE:
1187             switch (peripheral->gatt_client_state){
1188                 case P_W4_WRITE_CHARACTERISTIC_VALUE_RESULT:
1189                     gatt_client_handle_transaction_complete(peripheral);
1190                     emit_gatt_complete_event(peripheral, 0);
1191                     break;
1192                 case P_W4_CLIENT_CHARACTERISTIC_CONFIGURATION_RESULT:
1193                     gatt_client_handle_transaction_complete(peripheral);
1194                     emit_gatt_complete_event(peripheral, 0);
1195                     break;
1196                 case P_W4_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:
1197                     gatt_client_handle_transaction_complete(peripheral);
1198                     emit_gatt_complete_event(peripheral, 0);
1199                     break;
1200                 default:
1201                     break;
1202             }
1203             break;
1204 
1205         case ATT_READ_BLOB_RESPONSE:{
1206             uint16_t received_blob_length = size-1;
1207 
1208             switch(peripheral->gatt_client_state){
1209                 case P_W4_READ_BLOB_RESULT:
1210                     report_gatt_long_characteristic_value_blob(peripheral, peripheral->attribute_handle, &packet[1], received_blob_length, peripheral->attribute_offset);
1211                     trigger_next_blob_query(peripheral, P_W2_SEND_READ_BLOB_QUERY, received_blob_length);
1212                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1213                     break;
1214                 case P_W4_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_RESULT:
1215                     report_gatt_long_characteristic_descriptor(peripheral, peripheral->attribute_handle,
1216                                                           &packet[1], received_blob_length,
1217                                                           peripheral->attribute_offset);
1218                     trigger_next_blob_query(peripheral, P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY, received_blob_length);
1219                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1220                     break;
1221                 default:
1222                     break;
1223             }
1224             break;
1225         }
1226         case ATT_PREPARE_WRITE_RESPONSE:
1227             switch (peripheral->gatt_client_state){
1228                 case P_W4_PREPARE_WRITE_SINGLE_RESULT:
1229                     gatt_client_handle_transaction_complete(peripheral);
1230                     if (is_value_valid(peripheral, packet, size)){
1231                         emit_gatt_complete_event(peripheral, 0);
1232                     } else {
1233                         emit_gatt_complete_event(peripheral, ATT_ERROR_DATA_MISMATCH);
1234                     }
1235                     break;
1236 
1237                 case P_W4_PREPARE_WRITE_RESULT:{
1238                     peripheral->attribute_offset = little_endian_read_16(packet, 3);
1239                     trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_WRITE, P_W2_EXECUTE_PREPARED_WRITE);
1240                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1241                     break;
1242                 }
1243                 case P_W4_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:{
1244                     peripheral->attribute_offset = little_endian_read_16(packet, 3);
1245                     trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR, P_W2_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR);
1246                     // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1247                     break;
1248                 }
1249                 case P_W4_PREPARE_RELIABLE_WRITE_RESULT:{
1250                     if (is_value_valid(peripheral, packet, size)){
1251                         peripheral->attribute_offset = little_endian_read_16(packet, 3);
1252                         trigger_next_prepare_write_query(peripheral, P_W2_PREPARE_RELIABLE_WRITE, P_W2_EXECUTE_PREPARED_WRITE);
1253                         // GATT_EVENT_QUERY_COMPLETE is emitted by trigger_next_xxx when done
1254                         break;
1255                     }
1256                     peripheral->gatt_client_state = P_W2_CANCEL_PREPARED_WRITE_DATA_MISMATCH;
1257                     break;
1258                 }
1259                 default:
1260                     break;
1261             }
1262             break;
1263 
1264         case ATT_EXECUTE_WRITE_RESPONSE:
1265             switch (peripheral->gatt_client_state){
1266                 case P_W4_EXECUTE_PREPARED_WRITE_RESULT:
1267                     gatt_client_handle_transaction_complete(peripheral);
1268                     emit_gatt_complete_event(peripheral, 0);
1269                     break;
1270                 case P_W4_CANCEL_PREPARED_WRITE_RESULT:
1271                     gatt_client_handle_transaction_complete(peripheral);
1272                     emit_gatt_complete_event(peripheral, 0);
1273                     break;
1274                 case P_W4_CANCEL_PREPARED_WRITE_DATA_MISMATCH_RESULT:
1275                     gatt_client_handle_transaction_complete(peripheral);
1276                     emit_gatt_complete_event(peripheral, ATT_ERROR_DATA_MISMATCH);
1277                     break;
1278                 case P_W4_EXECUTE_PREPARED_WRITE_CHARACTERISTIC_DESCRIPTOR_RESULT:
1279                     gatt_client_handle_transaction_complete(peripheral);
1280                     emit_gatt_complete_event(peripheral, 0);
1281                     break;
1282                 default:
1283                     break;
1284 
1285             }
1286             break;
1287 
1288         case ATT_READ_MULTIPLE_RESPONSE:
1289             switch(peripheral->gatt_client_state){
1290                 case P_W4_READ_MULTIPLE_RESPONSE:
1291                     report_gatt_characteristic_value(peripheral, 0, &packet[1], size-1);
1292                     gatt_client_handle_transaction_complete(peripheral);
1293                     emit_gatt_complete_event(peripheral, 0);
1294                     break;
1295                 default:
1296                     break;
1297             }
1298             break;
1299 
1300         case ATT_ERROR_RESPONSE:
1301 
1302             switch (packet[4]){
1303                 case ATT_ERROR_ATTRIBUTE_NOT_FOUND: {
1304                     switch(peripheral->gatt_client_state){
1305                         case P_W4_SERVICE_QUERY_RESULT:
1306                         case P_W4_SERVICE_WITH_UUID_RESULT:
1307                         case P_W4_INCLUDED_SERVICE_QUERY_RESULT:
1308                         case P_W4_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT:
1309                             gatt_client_handle_transaction_complete(peripheral);
1310                             emit_gatt_complete_event(peripheral, 0);
1311                             break;
1312                         case P_W4_ALL_CHARACTERISTICS_OF_SERVICE_QUERY_RESULT:
1313                         case P_W4_CHARACTERISTIC_WITH_UUID_QUERY_RESULT:
1314                             characteristic_end_found(peripheral, peripheral->end_group_handle);
1315                             gatt_client_handle_transaction_complete(peripheral);
1316                             emit_gatt_complete_event(peripheral, 0);
1317                             break;
1318                         case P_W4_READ_BY_TYPE_RESPONSE:
1319                             gatt_client_handle_transaction_complete(peripheral);
1320                             if (peripheral->start_group_handle == peripheral->query_start_handle){
1321                                 emit_gatt_complete_event(peripheral, ATT_ERROR_ATTRIBUTE_NOT_FOUND);
1322                             } else {
1323                                 emit_gatt_complete_event(peripheral, 0);
1324                             }
1325                             break;
1326                         default:
1327                             gatt_client_report_error_if_pending(peripheral, packet[4]);
1328                             break;
1329                     }
1330                     break;
1331                 }
1332                 default:
1333                     gatt_client_report_error_if_pending(peripheral, packet[4]);
1334                     break;
1335             }
1336             break;
1337 
1338         default:
1339             log_info("ATT Handler, unhandled response type 0x%02x", packet[0]);
1340             break;
1341     }
1342     gatt_client_run();
1343 }
1344 
1345 static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
1346     btstack_linked_list_iterator_t it;
1347     btstack_linked_list_iterator_init(&it, &gatt_client_connections);
1348     while (btstack_linked_list_iterator_has_next(&it)){
1349         gatt_client_t * peripheral = (gatt_client_t *) btstack_linked_list_iterator_next(&it);
1350         if (peripheral->gatt_client_state == P_W4_CMAC_RESULT){
1351             // store result
1352             memcpy(peripheral->cmac, hash, 8);
1353             // reverse_64(hash, peripheral->cmac);
1354             peripheral->gatt_client_state = P_W2_SEND_SIGNED_WRITE;
1355             gatt_client_run();
1356             return;
1357         }
1358     }
1359 }
1360 
1361 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){
1362     gatt_client_t * peripheral = provide_context_for_conn_handle(con_handle);
1363     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1364     peripheral->le_device_index = sm_le_device_index(con_handle);
1365     if (peripheral->le_device_index < 0) return GATT_CLIENT_IN_WRONG_STATE; // device lookup not done / no stored bonding information
1366 
1367     peripheral->callback = callback;
1368     peripheral->attribute_handle = handle;
1369     peripheral->attribute_length = message_len;
1370     peripheral->attribute_value = message;
1371     peripheral->gatt_client_state = P_W4_CMAC_READY;
1372 
1373     gatt_client_run();
1374     return 0;
1375 }
1376 
1377 uint8_t gatt_client_discover_primary_services(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
1378     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1379     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1380     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1381 
1382     peripheral->callback = callback;
1383     peripheral->start_group_handle = 0x0001;
1384     peripheral->end_group_handle   = 0xffff;
1385     peripheral->gatt_client_state = P_W2_SEND_SERVICE_QUERY;
1386     peripheral->uuid16 = 0;
1387     gatt_client_run();
1388     return 0;
1389 }
1390 
1391 
1392 uint8_t gatt_client_discover_primary_services_by_uuid16(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t uuid16){
1393     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1394 
1395     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1396     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1397 
1398     peripheral->callback = callback;
1399     peripheral->start_group_handle = 0x0001;
1400     peripheral->end_group_handle   = 0xffff;
1401     peripheral->gatt_client_state = P_W2_SEND_SERVICE_WITH_UUID_QUERY;
1402     peripheral->uuid16 = uuid16;
1403     uuid_add_bluetooth_prefix((uint8_t*) &(peripheral->uuid128), peripheral->uuid16);
1404     gatt_client_run();
1405     return 0;
1406 }
1407 
1408 uint8_t gatt_client_discover_primary_services_by_uuid128(btstack_packet_handler_t callback, hci_con_handle_t con_handle, const uint8_t * uuid128){
1409     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1410 
1411     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1412     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1413 
1414     peripheral->callback = callback;
1415     peripheral->start_group_handle = 0x0001;
1416     peripheral->end_group_handle   = 0xffff;
1417     peripheral->uuid16 = 0;
1418     memcpy(peripheral->uuid128, uuid128, 16);
1419     peripheral->gatt_client_state = P_W2_SEND_SERVICE_WITH_UUID_QUERY;
1420     gatt_client_run();
1421     return 0;
1422 }
1423 
1424 uint8_t gatt_client_discover_characteristics_for_service(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_service_t *service){
1425     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1426 
1427     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1428     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1429 
1430     peripheral->callback = callback;
1431     peripheral->start_group_handle = service->start_group_handle;
1432     peripheral->end_group_handle   = service->end_group_handle;
1433     peripheral->filter_with_uuid = 0;
1434     peripheral->characteristic_start_handle = 0;
1435     peripheral->gatt_client_state = P_W2_SEND_ALL_CHARACTERISTICS_OF_SERVICE_QUERY;
1436     gatt_client_run();
1437     return 0;
1438 }
1439 
1440 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){
1441     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1442 
1443     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1444     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1445 
1446     peripheral->callback = callback;
1447     peripheral->start_group_handle = service->start_group_handle;
1448     peripheral->end_group_handle   = service->end_group_handle;
1449     peripheral->gatt_client_state = P_W2_SEND_INCLUDED_SERVICE_QUERY;
1450 
1451     gatt_client_run();
1452     return 0;
1453 }
1454 
1455 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){
1456     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1457 
1458     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1459     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1460 
1461     peripheral->callback = callback;
1462     peripheral->start_group_handle = start_handle;
1463     peripheral->end_group_handle   = end_handle;
1464     peripheral->filter_with_uuid = 1;
1465     peripheral->uuid16 = uuid16;
1466     uuid_add_bluetooth_prefix((uint8_t*) &(peripheral->uuid128), uuid16);
1467     peripheral->characteristic_start_handle = 0;
1468     peripheral->gatt_client_state = P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY;
1469 
1470     gatt_client_run();
1471     return 0;
1472 }
1473 
1474 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){
1475     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1476 
1477     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1478     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1479 
1480     peripheral->callback = callback;
1481     peripheral->start_group_handle = start_handle;
1482     peripheral->end_group_handle   = end_handle;
1483     peripheral->filter_with_uuid = 1;
1484     peripheral->uuid16 = 0;
1485     memcpy(peripheral->uuid128, uuid128, 16);
1486     peripheral->characteristic_start_handle = 0;
1487     peripheral->gatt_client_state = P_W2_SEND_CHARACTERISTIC_WITH_UUID_QUERY;
1488 
1489     gatt_client_run();
1490     return 0;
1491 }
1492 
1493 
1494 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){
1495     return gatt_client_discover_characteristics_for_handle_range_by_uuid16(callback, handle, service->start_group_handle, service->end_group_handle, uuid16);
1496 }
1497 
1498 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){
1499     return gatt_client_discover_characteristics_for_handle_range_by_uuid128(callback, handle, service->start_group_handle, service->end_group_handle, uuid128);
1500 }
1501 
1502 uint8_t gatt_client_discover_characteristic_descriptors(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_t *characteristic){
1503     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1504 
1505     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1506     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1507 
1508     if (characteristic->value_handle == characteristic->end_handle){
1509         emit_gatt_complete_event(peripheral, 0);
1510         return 0;
1511     }
1512     peripheral->callback = callback;
1513     peripheral->start_group_handle = characteristic->value_handle + 1;
1514     peripheral->end_group_handle   = characteristic->end_handle;
1515     peripheral->gatt_client_state = P_W2_SEND_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY;
1516 
1517     gatt_client_run();
1518     return 0;
1519 }
1520 
1521 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){
1522     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1523 
1524     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1525     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1526 
1527     peripheral->callback = callback;
1528     peripheral->attribute_handle = value_handle;
1529     peripheral->attribute_offset = 0;
1530     peripheral->gatt_client_state = P_W2_SEND_READ_CHARACTERISTIC_VALUE_QUERY;
1531     gatt_client_run();
1532     return 0;
1533 }
1534 
1535 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){
1536     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1537 
1538     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1539     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1540 
1541     peripheral->callback = callback;
1542     peripheral->start_group_handle = start_handle;
1543     peripheral->end_group_handle = end_handle;
1544     peripheral->query_start_handle = start_handle;
1545     peripheral->query_end_handle = end_handle;
1546     peripheral->uuid16 = uuid16;
1547     uuid_add_bluetooth_prefix((uint8_t*) &(peripheral->uuid128), uuid16);
1548     peripheral->gatt_client_state = P_W2_SEND_READ_BY_TYPE_REQUEST;
1549     gatt_client_run();
1550     return 0;
1551 }
1552 
1553 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){
1554     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1555 
1556     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1557     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1558 
1559     peripheral->callback = callback;
1560     peripheral->start_group_handle = start_handle;
1561     peripheral->end_group_handle = end_handle;
1562     peripheral->query_start_handle = start_handle;
1563     peripheral->query_end_handle = end_handle;
1564     peripheral->uuid16 = 0;
1565     memcpy(peripheral->uuid128, uuid128, 16);
1566     peripheral->gatt_client_state = P_W2_SEND_READ_BY_TYPE_REQUEST;
1567     gatt_client_run();
1568     return 0;
1569 }
1570 
1571 
1572 uint8_t gatt_client_read_value_of_characteristic(btstack_packet_handler_t callback, uint16_t handle, gatt_client_characteristic_t *characteristic){
1573     return gatt_client_read_value_of_characteristic_using_value_handle(callback, handle, characteristic->value_handle);
1574 }
1575 
1576 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){
1577     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1578 
1579     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1580     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1581 
1582     peripheral->callback = callback;
1583     peripheral->attribute_handle = characteristic_value_handle;
1584     peripheral->attribute_offset = offset;
1585     peripheral->gatt_client_state = P_W2_SEND_READ_BLOB_QUERY;
1586     gatt_client_run();
1587     return 0;
1588 }
1589 
1590 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){
1591     return gatt_client_read_long_value_of_characteristic_using_value_handle_with_offset(callback, con_handle, characteristic_value_handle, 0);
1592 }
1593 
1594 uint8_t gatt_client_read_long_value_of_characteristic(btstack_packet_handler_t callback, uint16_t handle, gatt_client_characteristic_t *characteristic){
1595     return gatt_client_read_long_value_of_characteristic_using_value_handle(callback, handle, characteristic->value_handle);
1596 }
1597 
1598 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){
1599     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1600 
1601     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1602     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1603 
1604     peripheral->callback = callback;
1605     peripheral->read_multiple_handle_count = num_value_handles;
1606     peripheral->read_multiple_handles = value_handles;
1607     peripheral->gatt_client_state = P_W2_SEND_READ_MULTIPLE_REQUEST;
1608     gatt_client_run();
1609     return 0;
1610 }
1611 
1612 uint8_t gatt_client_write_value_of_characteristic_without_response(hci_con_handle_t con_handle, uint16_t value_handle, uint16_t value_length, uint8_t * value){
1613     gatt_client_t * peripheral = provide_context_for_conn_handle(con_handle);
1614 
1615     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1616     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1617 
1618     if (value_length > peripheral_mtu(peripheral) - 3) return GATT_CLIENT_VALUE_TOO_LONG;
1619     if (!att_dispatch_client_can_send_now(peripheral->con_handle)) return GATT_CLIENT_BUSY;
1620 
1621     att_write_request(ATT_WRITE_COMMAND, peripheral->con_handle, value_handle, value_length, value);
1622     return 0;
1623 }
1624 
1625 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){
1626     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1627 
1628     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1629     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1630 
1631     peripheral->callback = callback;
1632     peripheral->attribute_handle = value_handle;
1633     peripheral->attribute_length = value_length;
1634     peripheral->attribute_value = data;
1635     peripheral->gatt_client_state = P_W2_SEND_WRITE_CHARACTERISTIC_VALUE;
1636     gatt_client_run();
1637     return 0;
1638 }
1639 
1640 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){
1641     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1642 
1643     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1644     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1645 
1646     peripheral->callback = callback;
1647     peripheral->attribute_handle = value_handle;
1648     peripheral->attribute_length = value_length;
1649     peripheral->attribute_offset = offset;
1650     peripheral->attribute_value = data;
1651     peripheral->gatt_client_state = P_W2_PREPARE_WRITE;
1652     gatt_client_run();
1653     return 0;
1654 }
1655 
1656 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){
1657     return gatt_client_write_long_value_of_characteristic_with_offset(callback, con_handle, value_handle, 0, value_length, value);
1658 }
1659 
1660 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){
1661     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1662 
1663     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1664     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1665 
1666     peripheral->callback = callback;
1667     peripheral->attribute_handle = value_handle;
1668     peripheral->attribute_length = value_length;
1669     peripheral->attribute_offset = 0;
1670     peripheral->attribute_value = value;
1671     peripheral->gatt_client_state = P_W2_PREPARE_RELIABLE_WRITE;
1672     gatt_client_run();
1673     return 0;
1674 }
1675 
1676 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){
1677     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1678 
1679     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1680     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1681 
1682     if ( (configuration & GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION) &&
1683         (characteristic->properties & ATT_PROPERTY_NOTIFY) == 0) {
1684         log_info("gatt_client_write_client_characteristic_configuration: GATT_CLIENT_CHARACTERISTIC_NOTIFICATION_NOT_SUPPORTED");
1685         return GATT_CLIENT_CHARACTERISTIC_NOTIFICATION_NOT_SUPPORTED;
1686     } else if ( (configuration & GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION) &&
1687                (characteristic->properties & ATT_PROPERTY_INDICATE) == 0){
1688         log_info("gatt_client_write_client_characteristic_configuration: GATT_CLIENT_CHARACTERISTIC_INDICATION_NOT_SUPPORTED");
1689         return GATT_CLIENT_CHARACTERISTIC_INDICATION_NOT_SUPPORTED;
1690     }
1691 
1692     peripheral->callback = callback;
1693     peripheral->start_group_handle = characteristic->value_handle;
1694     peripheral->end_group_handle = characteristic->end_handle;
1695     little_endian_store_16(peripheral->client_characteristic_configuration_value, 0, configuration);
1696 
1697     peripheral->gatt_client_state = P_W2_SEND_READ_CLIENT_CHARACTERISTIC_CONFIGURATION_QUERY;
1698     gatt_client_run();
1699     return 0;
1700 }
1701 
1702 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){
1703     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1704 
1705     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1706     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1707 
1708     peripheral->callback = callback;
1709     peripheral->attribute_handle = descriptor_handle;
1710 
1711     peripheral->gatt_client_state = P_W2_SEND_READ_CHARACTERISTIC_DESCRIPTOR_QUERY;
1712     gatt_client_run();
1713     return 0;
1714 }
1715 
1716 uint8_t gatt_client_read_characteristic_descriptor(btstack_packet_handler_t callback, hci_con_handle_t con_handle, gatt_client_characteristic_descriptor_t * descriptor){
1717     return gatt_client_read_characteristic_descriptor_using_descriptor_handle(callback, con_handle, descriptor->handle);
1718 }
1719 
1720 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){
1721     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1722 
1723     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1724     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1725 
1726     peripheral->callback = callback;
1727     peripheral->attribute_handle = descriptor_handle;
1728     peripheral->attribute_offset = offset;
1729     peripheral->gatt_client_state = P_W2_SEND_READ_BLOB_CHARACTERISTIC_DESCRIPTOR_QUERY;
1730     gatt_client_run();
1731     return 0;
1732 }
1733 
1734 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){
1735     return gatt_client_read_long_characteristic_descriptor_using_descriptor_handle_with_offset(callback, con_handle, descriptor_handle, 0);
1736 }
1737 
1738 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){
1739     return gatt_client_read_long_characteristic_descriptor_using_descriptor_handle(callback, con_handle, descriptor->handle);
1740 }
1741 
1742 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){
1743     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1744 
1745     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1746     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1747 
1748     peripheral->callback = callback;
1749     peripheral->attribute_handle = descriptor_handle;
1750     peripheral->attribute_length = length;
1751     peripheral->attribute_offset = 0;
1752     peripheral->attribute_value = data;
1753     peripheral->gatt_client_state = P_W2_SEND_WRITE_CHARACTERISTIC_DESCRIPTOR;
1754     gatt_client_run();
1755     return 0;
1756 }
1757 
1758 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){
1759     return gatt_client_write_characteristic_descriptor_using_descriptor_handle(callback, con_handle, descriptor->handle, length, value);
1760 }
1761 
1762 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){
1763     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1764 
1765     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1766     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1767 
1768     peripheral->callback = callback;
1769     peripheral->attribute_handle = descriptor_handle;
1770     peripheral->attribute_length = length;
1771     peripheral->attribute_offset = offset;
1772     peripheral->attribute_value = data;
1773     peripheral->gatt_client_state = P_W2_PREPARE_WRITE_CHARACTERISTIC_DESCRIPTOR;
1774     gatt_client_run();
1775     return 0;
1776 }
1777 
1778 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){
1779     return gatt_client_write_long_characteristic_descriptor_using_descriptor_handle_with_offset(callback, con_handle, descriptor_handle, 0, length, data );
1780 }
1781 
1782 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){
1783     return gatt_client_write_long_characteristic_descriptor_using_descriptor_handle(callback, con_handle, descriptor->handle, length, value);
1784 }
1785 
1786 /**
1787  * @brief -> gatt complete event
1788  */
1789 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){
1790     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1791 
1792     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1793     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1794 
1795     peripheral->callback = callback;
1796     peripheral->attribute_handle = attribute_handle;
1797     peripheral->attribute_length = length;
1798     peripheral->attribute_offset = offset;
1799     peripheral->attribute_value = data;
1800     peripheral->gatt_client_state = P_W2_PREPARE_WRITE_SINGLE;
1801     gatt_client_run();
1802     return 0;
1803 }
1804 
1805 /**
1806  * @brief -> gatt complete event
1807  */
1808 uint8_t gatt_client_execute_write(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
1809     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1810 
1811     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1812     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1813 
1814     peripheral->callback = callback;
1815     peripheral->gatt_client_state = P_W2_EXECUTE_PREPARED_WRITE;
1816     gatt_client_run();
1817     return 0;
1818 }
1819 
1820 /**
1821  * @brief -> gatt complete event
1822  */
1823 uint8_t gatt_client_cancel_write(btstack_packet_handler_t callback, hci_con_handle_t con_handle){
1824     gatt_client_t * peripheral = provide_context_for_conn_handle_and_start_timer(con_handle);
1825 
1826     if (!peripheral) return BTSTACK_MEMORY_ALLOC_FAILED;
1827     if (!is_ready(peripheral)) return GATT_CLIENT_IN_WRONG_STATE;
1828 
1829     peripheral->callback = callback;
1830     peripheral->gatt_client_state = P_W2_CANCEL_PREPARED_WRITE;
1831     gatt_client_run();
1832     return 0;
1833 }
1834 
1835 void gatt_client_pts_suppress_mtu_exchange(void){
1836     pts_suppress_mtu_exchange = 1;
1837 }
1838 
1839 void gatt_client_deserialize_service(const uint8_t *packet, int offset, gatt_client_service_t *service){
1840     service->start_group_handle = little_endian_read_16(packet, offset);
1841     service->end_group_handle = little_endian_read_16(packet, offset + 2);
1842     reverse_128(&packet[offset + 4], service->uuid128);
1843     if (uuid_has_bluetooth_prefix(service->uuid128)){
1844         service->uuid16 = big_endian_read_32(service->uuid128, 0);
1845     }
1846 }
1847 
1848 void gatt_client_deserialize_characteristic(const uint8_t * packet, int offset, gatt_client_characteristic_t * characteristic){
1849     characteristic->start_handle = little_endian_read_16(packet, offset);
1850     characteristic->value_handle = little_endian_read_16(packet, offset + 2);
1851     characteristic->end_handle = little_endian_read_16(packet, offset + 4);
1852     characteristic->properties = little_endian_read_16(packet, offset + 6);
1853     reverse_128(&packet[offset+8], characteristic->uuid128);
1854     if (uuid_has_bluetooth_prefix(characteristic->uuid128)){
1855         characteristic->uuid16 = big_endian_read_32(characteristic->uuid128, 0);
1856     }
1857 }
1858 
1859 void gatt_client_deserialize_characteristic_descriptor(const uint8_t * packet, int offset, gatt_client_characteristic_descriptor_t * descriptor){
1860     descriptor->handle = little_endian_read_16(packet, offset);
1861     reverse_128(&packet[offset+2], descriptor->uuid128);
1862 }
1863