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