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