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