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