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