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__ "att_db.c" 39 40 #include <string.h> 41 42 #include "ble/att_db.h" 43 #include "ble/core.h" 44 #include "bluetooth.h" 45 #include "btstack_debug.h" 46 #include "btstack_util.h" 47 48 // check for ENABLE_ATT_DELAYED_READ_RESPONSE -> ENABLE_ATT_DELAYED_RESPONSE, 49 #ifdef ENABLE_ATT_DELAYED_READ_RESPONSE 50 #error "ENABLE_ATT_DELAYED_READ_RESPONSE was replaced by ENABLE_ATT_DELAYED_RESPONSE. Please update btstack_config.h" 51 #endif 52 53 typedef enum { 54 ATT_READ, 55 ATT_WRITE, 56 } att_operation_t; 57 58 // Buetooth Base UUID 00000000-0000-1000-8000-00805F9B34FB in little endian 59 static const uint8_t bluetooth_base_uuid[] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 60 61 62 static int is_Bluetooth_Base_UUID(uint8_t const *uuid){ 63 if (memcmp(&uuid[0], &bluetooth_base_uuid[0], 12)) return 0; 64 if (memcmp(&uuid[14], &bluetooth_base_uuid[14], 2)) return 0; 65 return 1; 66 67 } 68 69 static uint16_t uuid16_from_uuid(uint16_t uuid_len, uint8_t * uuid){ 70 if (uuid_len == 2) return little_endian_read_16(uuid, 0); 71 if (!is_Bluetooth_Base_UUID(uuid)) return 0; 72 return little_endian_read_16(uuid, 12); 73 } 74 75 // ATT Database 76 77 // new java-style iterator 78 typedef struct att_iterator { 79 // private 80 uint8_t const * att_ptr; 81 // public 82 uint16_t size; 83 uint16_t flags; 84 uint16_t handle; 85 uint8_t const * uuid; 86 uint16_t value_len; 87 uint8_t const * value; 88 } att_iterator_t; 89 90 static void att_persistent_ccc_cache(att_iterator_t * it); 91 92 static uint8_t const * att_db = NULL; 93 static att_read_callback_t att_read_callback = NULL; 94 static att_write_callback_t att_write_callback = NULL; 95 static int att_prepare_write_error_code = 0; 96 static uint16_t att_prepare_write_error_handle = 0x0000; 97 98 // single cache for att_is_persistent_ccc - stores flags before write callback 99 static uint16_t att_persistent_ccc_handle; 100 static uint16_t att_persistent_ccc_uuid16; 101 102 static void att_iterator_init(att_iterator_t *it){ 103 it->att_ptr = att_db; 104 } 105 106 static int att_iterator_has_next(att_iterator_t *it){ 107 return it->att_ptr != NULL; 108 } 109 110 static void att_iterator_fetch_next(att_iterator_t *it){ 111 it->size = little_endian_read_16(it->att_ptr, 0); 112 if (it->size == 0){ 113 it->flags = 0; 114 it->handle = 0; 115 it->uuid = NULL; 116 it->value_len = 0; 117 it->value = NULL; 118 it->att_ptr = NULL; 119 return; 120 } 121 it->flags = little_endian_read_16(it->att_ptr, 2); 122 it->handle = little_endian_read_16(it->att_ptr, 4); 123 it->uuid = &it->att_ptr[6]; 124 // handle 128 bit UUIDs 125 if (it->flags & ATT_PROPERTY_UUID128){ 126 it->value_len = it->size - 22; 127 it->value = &it->att_ptr[22]; 128 } else { 129 it->value_len = it->size - 8; 130 it->value = &it->att_ptr[8]; 131 } 132 // advance AFTER setting values 133 it->att_ptr += it->size; 134 } 135 136 static int att_iterator_match_uuid16(att_iterator_t *it, uint16_t uuid){ 137 if (it->handle == 0) return 0; 138 if (it->flags & ATT_PROPERTY_UUID128){ 139 if (!is_Bluetooth_Base_UUID(it->uuid)) return 0; 140 return little_endian_read_16(it->uuid, 12) == uuid; 141 } 142 return little_endian_read_16(it->uuid, 0) == uuid; 143 } 144 145 static int att_iterator_match_uuid(att_iterator_t *it, uint8_t *uuid, uint16_t uuid_len){ 146 if (it->handle == 0) return 0; 147 // input: UUID16 148 if (uuid_len == 2) { 149 return att_iterator_match_uuid16(it, little_endian_read_16(uuid, 0)); 150 } 151 // input and db: UUID128 152 if (it->flags & ATT_PROPERTY_UUID128){ 153 return memcmp(it->uuid, uuid, 16) == 0; 154 } 155 // input: UUID128, db: UUID16 156 if (!is_Bluetooth_Base_UUID(uuid)) return 0; 157 return little_endian_read_16(uuid, 12) == little_endian_read_16(it->uuid, 0); 158 } 159 160 161 static int att_find_handle(att_iterator_t *it, uint16_t handle){ 162 if (handle == 0) return 0; 163 att_iterator_init(it); 164 while (att_iterator_has_next(it)){ 165 att_iterator_fetch_next(it); 166 if (it->handle != handle) continue; 167 return 1; 168 } 169 return 0; 170 } 171 172 // experimental client API 173 uint16_t att_uuid_for_handle(uint16_t attribute_handle){ 174 att_iterator_t it; 175 int ok = att_find_handle(&it, attribute_handle); 176 if (!ok) return 0; 177 if (it.flags & ATT_PROPERTY_UUID128) return 0; 178 return little_endian_read_16(it.uuid, 0); 179 } 180 // end of client API 181 182 static void att_update_value_len(att_iterator_t *it, hci_con_handle_t con_handle){ 183 if ((it->flags & ATT_PROPERTY_DYNAMIC) == 0) return; 184 it->value_len = (*att_read_callback)(con_handle, it->handle, 0, NULL, 0); 185 return; 186 } 187 188 // copy attribute value from offset into buffer with given size 189 static int att_copy_value(att_iterator_t *it, uint16_t offset, uint8_t * buffer, uint16_t buffer_size, hci_con_handle_t con_handle){ 190 191 // DYNAMIC 192 if (it->flags & ATT_PROPERTY_DYNAMIC){ 193 return (*att_read_callback)(con_handle, it->handle, offset, buffer, buffer_size); 194 } 195 196 // STATIC 197 uint16_t bytes_to_copy = it->value_len - offset; 198 if (bytes_to_copy > buffer_size){ 199 bytes_to_copy = buffer_size; 200 } 201 memcpy(buffer, it->value, bytes_to_copy); 202 return bytes_to_copy; 203 } 204 205 void att_set_db(uint8_t const * db){ 206 // validate db version 207 if (db == NULL) return; 208 if (*db++ != ATT_DB_VERSION){ 209 log_error("ATT DB version differs, please regenerate .h from .gatt file or update att_db_util.c"); 210 return; 211 } 212 att_db = db; 213 } 214 215 void att_set_read_callback(att_read_callback_t callback){ 216 att_read_callback = callback; 217 } 218 219 void att_set_write_callback(att_write_callback_t callback){ 220 att_write_callback = callback; 221 } 222 223 void att_dump_attributes(void){ 224 att_iterator_t it; 225 att_iterator_init(&it); 226 uint8_t uuid128[16]; 227 while (att_iterator_has_next(&it)){ 228 att_iterator_fetch_next(&it); 229 if (it.handle == 0) { 230 log_info("Handle: END"); 231 return; 232 } 233 log_info("Handle: 0x%04x, flags: 0x%04x, uuid: ", it.handle, it.flags); 234 if (it.flags & ATT_PROPERTY_UUID128){ 235 reverse_128(it.uuid, uuid128); 236 log_info("%s", uuid128_to_str(uuid128)); 237 } else { 238 log_info("%04x", little_endian_read_16(it.uuid, 0)); 239 } 240 log_info(", value_len: %u, value: ", it.value_len); 241 log_info_hexdump(it.value, it.value_len); 242 } 243 } 244 245 static void att_prepare_write_reset(void){ 246 att_prepare_write_error_code = 0; 247 att_prepare_write_error_handle = 0x0000; 248 } 249 250 static void att_prepare_write_update_errors(uint8_t error_code, uint16_t handle){ 251 // first ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH has highest priority 252 if (error_code == ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH && error_code != att_prepare_write_error_code){ 253 att_prepare_write_error_code = error_code; 254 att_prepare_write_error_handle = handle; 255 return; 256 } 257 // first ATT_ERROR_INVALID_OFFSET is next 258 if (error_code == ATT_ERROR_INVALID_OFFSET && att_prepare_write_error_code == 0){ 259 att_prepare_write_error_code = error_code; 260 att_prepare_write_error_handle = handle; 261 return; 262 } 263 } 264 265 static uint16_t setup_error(uint8_t * response_buffer, uint16_t request, uint16_t handle, uint8_t error_code){ 266 response_buffer[0] = ATT_ERROR_RESPONSE; 267 response_buffer[1] = request; 268 little_endian_store_16(response_buffer, 2, handle); 269 response_buffer[4] = error_code; 270 return 5; 271 } 272 273 static inline uint16_t setup_error_read_not_permitted(uint8_t * response_buffer, uint16_t request, uint16_t start_handle){ 274 return setup_error(response_buffer, request, start_handle, ATT_ERROR_READ_NOT_PERMITTED); 275 } 276 277 static inline uint16_t setup_error_write_not_permitted(uint8_t * response_buffer, uint16_t request, uint16_t start_handle){ 278 return setup_error(response_buffer, request, start_handle, ATT_ERROR_WRITE_NOT_PERMITTED); 279 } 280 281 static inline uint16_t setup_error_atribute_not_found(uint8_t * response_buffer, uint16_t request, uint16_t start_handle){ 282 return setup_error(response_buffer, request, start_handle, ATT_ERROR_ATTRIBUTE_NOT_FOUND); 283 } 284 285 static inline uint16_t setup_error_invalid_handle(uint8_t * response_buffer, uint16_t request, uint16_t handle){ 286 return setup_error(response_buffer, request, handle, ATT_ERROR_INVALID_HANDLE); 287 } 288 289 static inline uint16_t setup_error_invalid_offset(uint8_t * response_buffer, uint16_t request, uint16_t handle){ 290 return setup_error(response_buffer, request, handle, ATT_ERROR_INVALID_OFFSET); 291 } 292 293 static uint8_t att_validate_security(att_connection_t * att_connection, att_operation_t operation, att_iterator_t * it){ 294 int required_security_level = 0; 295 int requires_secure_connection = 0; 296 switch (operation){ 297 case ATT_READ: 298 if (it->flags & ATT_PROPERTY_READ_PERMISSION_BIT_0) { 299 required_security_level |= 1; 300 } 301 if (it->flags & ATT_PROPERTY_READ_PERMISSION_BIT_1) { 302 required_security_level |= 2; 303 } 304 if (it->flags & ATT_PROPERTY_READ_PERMISSION_SC) { 305 requires_secure_connection = 1; 306 } 307 break; 308 case ATT_WRITE: 309 if (it->flags & ATT_PROPERTY_WRITE_PERMISSION_BIT_0) { 310 required_security_level |= 1; 311 } 312 if (it->flags & ATT_PROPERTY_WRITE_PERMISSION_BIT_1) { 313 required_security_level |= 2; 314 } 315 if (it->flags & ATT_PROPERTY_WRITE_PERMISSION_SC) { 316 requires_secure_connection = 1; 317 } 318 break; 319 } 320 321 int required_encryption_size = it->flags >> 12; 322 if (required_encryption_size) required_encryption_size++; // store -1 to fit into 4 bit 323 324 log_debug("att_validate_security. flags 0x%04x (=> security level %u, key size %u) authorized %u, authenticated %u, encryption_key_size %u", 325 it->flags, required_security_level, required_encryption_size, att_connection->authorized, att_connection->authenticated, att_connection->encryption_key_size); 326 327 if ((required_security_level >= ATT_SECURITY_AUTHORIZED) && (att_connection->authorized == 0)) { 328 return ATT_ERROR_INSUFFICIENT_AUTHORIZATION; 329 } 330 if ((required_security_level >= ATT_SECURITY_AUTHENTICATED) && (att_connection->authenticated == 0)) { 331 return ATT_ERROR_INSUFFICIENT_AUTHENTICATION; 332 } 333 if (required_security_level >= ATT_SECURITY_ENCRYPTED) { 334 if ((required_encryption_size > 0) && (att_connection->encryption_key_size == 0)){ 335 return ATT_ERROR_INSUFFICIENT_ENCRYPTION; 336 } 337 if (required_encryption_size > att_connection->encryption_key_size){ 338 return ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE; 339 } 340 } 341 return 0; 342 } 343 344 // 345 // MARK: ATT_EXCHANGE_MTU_REQUEST 346 // 347 static uint16_t handle_exchange_mtu_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, 348 uint8_t * response_buffer){ 349 350 UNUSED(request_len); 351 352 uint16_t client_rx_mtu = little_endian_read_16(request_buffer, 1); 353 354 // find min(local max mtu, remote mtu) and use as mtu for this connection 355 if (client_rx_mtu < att_connection->max_mtu){ 356 att_connection->mtu = client_rx_mtu; 357 } else { 358 att_connection->mtu = att_connection->max_mtu; 359 } 360 361 response_buffer[0] = ATT_EXCHANGE_MTU_RESPONSE; 362 little_endian_store_16(response_buffer, 1, att_connection->mtu); 363 return 3; 364 } 365 366 367 // 368 // MARK: ATT_FIND_INFORMATION_REQUEST 369 // 370 // TODO: handle other types then GATT_PRIMARY_SERVICE_UUID and GATT_SECONDARY_SERVICE_UUID 371 // 372 static uint16_t handle_find_information_request2(att_connection_t * att_connection, uint8_t * response_buffer, uint16_t response_buffer_size, 373 uint16_t start_handle, uint16_t end_handle){ 374 375 UNUSED(att_connection); 376 377 log_info("ATT_FIND_INFORMATION_REQUEST: from %04X to %04X", start_handle, end_handle); 378 uint8_t request_type = ATT_FIND_INFORMATION_REQUEST; 379 380 if (start_handle > end_handle || start_handle == 0){ 381 return setup_error_invalid_handle(response_buffer, request_type, start_handle); 382 } 383 384 uint16_t offset = 1; 385 uint16_t uuid_len = 0; 386 387 att_iterator_t it; 388 att_iterator_init(&it); 389 while (att_iterator_has_next(&it)){ 390 att_iterator_fetch_next(&it); 391 if (!it.handle) break; 392 if (it.handle > end_handle) break; 393 if (it.handle < start_handle) continue; 394 395 // log_info("Handle 0x%04x", it.handle); 396 397 uint16_t this_uuid_len = (it.flags & ATT_PROPERTY_UUID128) ? 16 : 2; 398 399 // check if value has same len as last one if not first result 400 if (offset > 1){ 401 if (this_uuid_len != uuid_len) { 402 break; 403 } 404 } 405 406 // first 407 if (offset == 1) { 408 uuid_len = this_uuid_len; 409 // set format field 410 response_buffer[offset] = (it.flags & ATT_PROPERTY_UUID128) ? 0x02 : 0x01; 411 offset++; 412 } 413 414 // space? 415 if (offset + 2 + uuid_len > response_buffer_size) break; 416 417 // store 418 little_endian_store_16(response_buffer, offset, it.handle); 419 offset += 2; 420 421 memcpy(response_buffer + offset, it.uuid, uuid_len); 422 offset += uuid_len; 423 } 424 425 if (offset == 1){ 426 return setup_error_atribute_not_found(response_buffer, request_type, start_handle); 427 } 428 429 response_buffer[0] = ATT_FIND_INFORMATION_REPLY; 430 return offset; 431 } 432 433 static uint16_t handle_find_information_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, 434 uint8_t * response_buffer, uint16_t response_buffer_size){ 435 UNUSED(request_len); 436 return handle_find_information_request2(att_connection, response_buffer, response_buffer_size, little_endian_read_16(request_buffer, 1), little_endian_read_16(request_buffer, 3)); 437 } 438 439 // 440 // MARK: ATT_FIND_BY_TYPE_VALUE 441 // 442 // "Only attributes with attribute handles between and including the Starting Handle parameter 443 // and the Ending Handle parameter that match the requested attri- bute type and the attribute 444 // value that have sufficient permissions to allow reading will be returned" -> (1) 445 // 446 // TODO: handle other types then GATT_PRIMARY_SERVICE_UUID and GATT_SECONDARY_SERVICE_UUID 447 // 448 // NOTE: doesn't handle DYNAMIC values 449 // NOTE: only supports 16 bit UUIDs 450 // 451 static uint16_t handle_find_by_type_value_request2(att_connection_t * att_connection, uint8_t * response_buffer, uint16_t response_buffer_size, 452 uint16_t start_handle, uint16_t end_handle, 453 uint16_t attribute_type, uint16_t attribute_len, uint8_t* attribute_value){ 454 455 UNUSED(att_connection); 456 457 log_info("ATT_FIND_BY_TYPE_VALUE_REQUEST: from %04X to %04X, type %04X, value: ", start_handle, end_handle, attribute_type); 458 log_info_hexdump(attribute_value, attribute_len); 459 uint8_t request_type = ATT_FIND_BY_TYPE_VALUE_REQUEST; 460 461 if (start_handle > end_handle || start_handle == 0){ 462 return setup_error_invalid_handle(response_buffer, request_type, start_handle); 463 } 464 465 uint16_t offset = 1; 466 uint16_t in_group = 0; 467 uint16_t prev_handle = 0; 468 469 att_iterator_t it; 470 att_iterator_init(&it); 471 while (att_iterator_has_next(&it)){ 472 att_iterator_fetch_next(&it); 473 474 if (it.handle && it.handle < start_handle) continue; 475 if (it.handle > end_handle) break; // (1) 476 477 // close current tag, if within a group and a new service definition starts or we reach end of att db 478 if (in_group && 479 (it.handle == 0 || att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID))){ 480 481 log_info("End of group, handle 0x%04x", prev_handle); 482 little_endian_store_16(response_buffer, offset, prev_handle); 483 offset += 2; 484 in_group = 0; 485 486 // check if space for another handle pair available 487 if (offset + 4 > response_buffer_size){ 488 break; 489 } 490 } 491 492 // keep track of previous handle 493 prev_handle = it.handle; 494 495 // does current attribute match 496 if (it.handle && att_iterator_match_uuid16(&it, attribute_type) && attribute_len == it.value_len && memcmp(attribute_value, it.value, it.value_len) == 0){ 497 log_info("Begin of group, handle 0x%04x", it.handle); 498 little_endian_store_16(response_buffer, offset, it.handle); 499 offset += 2; 500 in_group = 1; 501 } 502 } 503 504 if (offset == 1){ 505 return setup_error_atribute_not_found(response_buffer, request_type, start_handle); 506 } 507 508 response_buffer[0] = ATT_FIND_BY_TYPE_VALUE_RESPONSE; 509 return offset; 510 } 511 512 static uint16_t handle_find_by_type_value_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, 513 uint8_t * response_buffer, uint16_t response_buffer_size){ 514 int attribute_len = request_len - 7; 515 return handle_find_by_type_value_request2(att_connection, response_buffer, response_buffer_size, little_endian_read_16(request_buffer, 1), 516 little_endian_read_16(request_buffer, 3), little_endian_read_16(request_buffer, 5), attribute_len, &request_buffer[7]); 517 } 518 519 // 520 // MARK: ATT_READ_BY_TYPE_REQUEST 521 // 522 static uint16_t handle_read_by_type_request2(att_connection_t * att_connection, uint8_t * response_buffer, uint16_t response_buffer_size, 523 uint16_t start_handle, uint16_t end_handle, 524 uint16_t attribute_type_len, uint8_t * attribute_type){ 525 526 log_info("ATT_READ_BY_TYPE_REQUEST: from %04X to %04X, type: ", start_handle, end_handle); 527 log_info_hexdump(attribute_type, attribute_type_len); 528 uint8_t request_type = ATT_READ_BY_TYPE_REQUEST; 529 530 if (start_handle > end_handle || start_handle == 0){ 531 return setup_error_invalid_handle(response_buffer, request_type, start_handle); 532 } 533 534 uint16_t offset = 1; 535 uint16_t pair_len = 0; 536 537 att_iterator_t it; 538 att_iterator_init(&it); 539 uint8_t error_code = 0; 540 uint16_t first_matching_but_unreadable_handle = 0; 541 542 #ifdef ENABLE_ATT_DELAYED_RESPONSE 543 int read_request_pending = 0; 544 #endif 545 546 while (att_iterator_has_next(&it)){ 547 att_iterator_fetch_next(&it); 548 549 if (!it.handle) break; 550 if (it.handle < start_handle) continue; 551 if (it.handle > end_handle) break; // (1) 552 553 // does current attribute match 554 if (!att_iterator_match_uuid(&it, attribute_type, attribute_type_len)) continue; 555 556 // skip handles that cannot be read but rembember that there has been at least one 557 if ((it.flags & ATT_PROPERTY_READ) == 0) { 558 if (first_matching_but_unreadable_handle == 0) { 559 first_matching_but_unreadable_handle = it.handle; 560 } 561 continue; 562 } 563 564 // check security requirements 565 error_code = att_validate_security(att_connection, ATT_READ, &it); 566 if (error_code) break; 567 568 att_update_value_len(&it, att_connection->con_handle); 569 570 #ifdef ENABLE_ATT_DELAYED_RESPONSE 571 if (it.value_len == ATT_READ_RESPONSE_PENDING){ 572 read_request_pending = 1; 573 } 574 if (read_request_pending) continue; 575 #endif 576 577 // check if value has same len as last one 578 uint16_t this_pair_len = 2 + it.value_len; 579 if (offset > 1){ 580 if (pair_len != this_pair_len) { 581 break; 582 } 583 } 584 585 // first 586 if (offset == 1) { 587 pair_len = this_pair_len; 588 response_buffer[offset] = pair_len; 589 offset++; 590 } 591 592 // space? 593 if (offset + pair_len > response_buffer_size) { 594 if (offset > 2) break; 595 it.value_len = response_buffer_size - 4; 596 response_buffer[1] = 2 + it.value_len; 597 } 598 599 // store 600 little_endian_store_16(response_buffer, offset, it.handle); 601 offset += 2; 602 uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len, att_connection->con_handle); 603 offset += bytes_copied; 604 } 605 606 #ifdef ENABLE_ATT_DELAYED_RESPONSE 607 if (read_request_pending) return ATT_READ_RESPONSE_PENDING; 608 #endif 609 610 // at least one attribute could be read 611 if (offset > 1){ 612 response_buffer[0] = ATT_READ_BY_TYPE_RESPONSE; 613 return offset; 614 } 615 616 // first attribute had an error 617 if (error_code){ 618 return setup_error(response_buffer, request_type, start_handle, error_code); 619 } 620 621 // no other errors, but all found attributes had been non-readable 622 if (first_matching_but_unreadable_handle){ 623 return setup_error_read_not_permitted(response_buffer, request_type, first_matching_but_unreadable_handle); 624 } 625 626 // attribute not found 627 return setup_error_atribute_not_found(response_buffer, request_type, start_handle); 628 } 629 630 static uint16_t handle_read_by_type_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, 631 uint8_t * response_buffer, uint16_t response_buffer_size){ 632 int attribute_type_len; 633 if (request_len <= 7){ 634 attribute_type_len = 2; 635 } else { 636 attribute_type_len = 16; 637 } 638 return handle_read_by_type_request2(att_connection, response_buffer, response_buffer_size, little_endian_read_16(request_buffer, 1), little_endian_read_16(request_buffer, 3), attribute_type_len, &request_buffer[5]); 639 } 640 641 // 642 // MARK: ATT_READ_BY_TYPE_REQUEST 643 // 644 static uint16_t handle_read_request2(att_connection_t * att_connection, uint8_t * response_buffer, uint16_t response_buffer_size, uint16_t handle){ 645 646 log_info("ATT_READ_REQUEST: handle %04x", handle); 647 uint8_t request_type = ATT_READ_REQUEST; 648 649 att_iterator_t it; 650 int ok = att_find_handle(&it, handle); 651 if (!ok){ 652 return setup_error_invalid_handle(response_buffer, request_type, handle); 653 } 654 655 // check if handle can be read 656 if ((it.flags & ATT_PROPERTY_READ) == 0) { 657 return setup_error_read_not_permitted(response_buffer, request_type, handle); 658 } 659 660 // check security requirements 661 uint8_t error_code = att_validate_security(att_connection, ATT_READ, &it); 662 if (error_code) { 663 return setup_error(response_buffer, request_type, handle, error_code); 664 } 665 666 att_update_value_len(&it, att_connection->con_handle); 667 668 #ifdef ENABLE_ATT_DELAYED_RESPONSE 669 if (it.value_len == ATT_READ_RESPONSE_PENDING) return ATT_READ_RESPONSE_PENDING; 670 #endif 671 672 uint16_t offset = 1; 673 // limit data 674 if (offset + it.value_len > response_buffer_size) { 675 it.value_len = response_buffer_size - 1; 676 } 677 678 // store 679 uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len, att_connection->con_handle); 680 offset += bytes_copied; 681 682 response_buffer[0] = ATT_READ_RESPONSE; 683 return offset; 684 } 685 686 static uint16_t handle_read_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, 687 uint8_t * response_buffer, uint16_t response_buffer_size){ 688 UNUSED(request_len); 689 return handle_read_request2(att_connection, response_buffer, response_buffer_size, little_endian_read_16(request_buffer, 1)); 690 } 691 692 // 693 // MARK: ATT_READ_BLOB_REQUEST 0x0c 694 // 695 static uint16_t handle_read_blob_request2(att_connection_t * att_connection, uint8_t * response_buffer, uint16_t response_buffer_size, uint16_t handle, uint16_t value_offset){ 696 log_info("ATT_READ_BLOB_REQUEST: handle %04x, offset %u", handle, value_offset); 697 uint8_t request_type = ATT_READ_BLOB_REQUEST; 698 699 att_iterator_t it; 700 int ok = att_find_handle(&it, handle); 701 if (!ok){ 702 return setup_error_invalid_handle(response_buffer, request_type, handle); 703 } 704 705 // check if handle can be read 706 if ((it.flags & ATT_PROPERTY_READ) == 0) { 707 return setup_error_read_not_permitted(response_buffer, request_type, handle); 708 } 709 710 // check security requirements 711 uint8_t error_code = att_validate_security(att_connection, ATT_READ, &it); 712 if (error_code) { 713 return setup_error(response_buffer, request_type, handle, error_code); 714 } 715 716 att_update_value_len(&it, att_connection->con_handle); 717 718 #ifdef ENABLE_ATT_DELAYED_RESPONSE 719 if (it.value_len == ATT_READ_RESPONSE_PENDING) return ATT_READ_RESPONSE_PENDING; 720 #endif 721 722 if (value_offset > it.value_len){ 723 return setup_error_invalid_offset(response_buffer, request_type, handle); 724 } 725 726 // limit data 727 uint16_t offset = 1; 728 if (offset + it.value_len - value_offset > response_buffer_size) { 729 it.value_len = response_buffer_size - 1 + value_offset; 730 } 731 732 // store 733 uint16_t bytes_copied = att_copy_value(&it, value_offset, response_buffer + offset, it.value_len - value_offset, att_connection->con_handle); 734 offset += bytes_copied; 735 736 response_buffer[0] = ATT_READ_BLOB_RESPONSE; 737 return offset; 738 } 739 740 static uint16_t handle_read_blob_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, 741 uint8_t * response_buffer, uint16_t response_buffer_size){ 742 UNUSED(request_len); 743 return handle_read_blob_request2(att_connection, response_buffer, response_buffer_size, little_endian_read_16(request_buffer, 1), little_endian_read_16(request_buffer, 3)); 744 } 745 746 // 747 // MARK: ATT_READ_MULTIPLE_REQUEST 0x0e 748 // 749 static uint16_t handle_read_multiple_request2(att_connection_t * att_connection, uint8_t * response_buffer, uint16_t response_buffer_size, uint16_t num_handles, uint8_t * handles){ 750 log_info("ATT_READ_MULTIPLE_REQUEST: num handles %u", num_handles); 751 uint8_t request_type = ATT_READ_MULTIPLE_REQUEST; 752 753 // TODO: figure out which error to respond with 754 // if (num_handles < 2){ 755 // return setup_error(response_buffer, ATT_READ_MULTIPLE_REQUEST, handle, ???); 756 // } 757 758 uint16_t offset = 1; 759 760 int i; 761 uint8_t error_code = 0; 762 uint16_t handle = 0; 763 764 #ifdef ENABLE_ATT_DELAYED_RESPONSE 765 int read_request_pending = 0; 766 #endif 767 768 for (i=0;i<num_handles;i++){ 769 handle = little_endian_read_16(handles, i << 1); 770 771 if (handle == 0){ 772 return setup_error_invalid_handle(response_buffer, request_type, handle); 773 } 774 775 att_iterator_t it; 776 777 int ok = att_find_handle(&it, handle); 778 if (!ok){ 779 return setup_error_invalid_handle(response_buffer, request_type, handle); 780 } 781 782 // check if handle can be read 783 if ((it.flags & ATT_PROPERTY_READ) == 0) { 784 error_code = ATT_ERROR_READ_NOT_PERMITTED; 785 break; 786 } 787 788 // check security requirements 789 error_code = att_validate_security(att_connection, ATT_READ, &it); 790 if (error_code) break; 791 792 att_update_value_len(&it, att_connection->con_handle); 793 794 #ifdef ENABLE_ATT_DELAYED_RESPONSE 795 if (it.value_len == ATT_READ_RESPONSE_PENDING) { 796 read_request_pending = 1; 797 } 798 if (read_request_pending) continue; 799 #endif 800 801 // limit data 802 if (offset + it.value_len > response_buffer_size) { 803 it.value_len = response_buffer_size - 1; 804 } 805 806 // store 807 uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len, att_connection->con_handle); 808 offset += bytes_copied; 809 } 810 811 if (error_code){ 812 return setup_error(response_buffer, request_type, handle, error_code); 813 } 814 815 response_buffer[0] = ATT_READ_MULTIPLE_RESPONSE; 816 return offset; 817 } 818 static uint16_t handle_read_multiple_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, 819 uint8_t * response_buffer, uint16_t response_buffer_size){ 820 int num_handles = (request_len - 1) >> 1; 821 return handle_read_multiple_request2(att_connection, response_buffer, response_buffer_size, num_handles, &request_buffer[1]); 822 } 823 824 // 825 // MARK: ATT_READ_BY_GROUP_TYPE_REQUEST 0x10 826 // 827 // Only handles GATT_PRIMARY_SERVICE_UUID and GATT_SECONDARY_SERVICE_UUID 828 // Core v4.0, vol 3, part g, 2.5.3 829 // "The «Primary Service» and «Secondary Service» grouping types may be used in the Read By Group Type Request. 830 // The «Characteristic» grouping type shall not be used in the ATT Read By Group Type Request." 831 // 832 // NOTE: doesn't handle DYNAMIC values 833 // 834 // NOTE: we don't check for security as PRIMARY and SECONDAY SERVICE definition shouldn't be protected 835 // Core 4.0, vol 3, part g, 8.1 836 // "The list of services and characteristics that a device supports is not considered private or 837 // confidential information, and therefore the Service and Characteristic Discovery procedures 838 // shall always be permitted. " 839 // 840 static uint16_t handle_read_by_group_type_request2(att_connection_t * att_connection, uint8_t * response_buffer, uint16_t response_buffer_size, 841 uint16_t start_handle, uint16_t end_handle, 842 uint16_t attribute_type_len, uint8_t * attribute_type){ 843 844 UNUSED(att_connection); 845 846 log_info("ATT_READ_BY_GROUP_TYPE_REQUEST: from %04X to %04X, buffer size %u, type: ", start_handle, end_handle, response_buffer_size); 847 log_info_hexdump(attribute_type, attribute_type_len); 848 uint8_t request_type = ATT_READ_BY_GROUP_TYPE_REQUEST; 849 850 if (start_handle > end_handle || start_handle == 0){ 851 return setup_error_invalid_handle(response_buffer, request_type, start_handle); 852 } 853 854 // assert UUID is primary or secondary service uuid 855 uint16_t uuid16 = uuid16_from_uuid(attribute_type_len, attribute_type); 856 if (uuid16 != GATT_PRIMARY_SERVICE_UUID && uuid16 != GATT_SECONDARY_SERVICE_UUID){ 857 return setup_error(response_buffer, request_type, start_handle, ATT_ERROR_UNSUPPORTED_GROUP_TYPE); 858 } 859 860 uint16_t offset = 1; 861 uint16_t pair_len = 0; 862 uint16_t in_group = 0; 863 uint16_t group_start_handle = 0; 864 uint8_t const * group_start_value = NULL; 865 uint16_t prev_handle = 0; 866 867 att_iterator_t it; 868 att_iterator_init(&it); 869 while (att_iterator_has_next(&it)){ 870 att_iterator_fetch_next(&it); 871 872 if (it.handle && it.handle < start_handle) continue; 873 if (it.handle > end_handle) break; // (1) 874 875 // log_info("Handle 0x%04x", it.handle); 876 877 // close current tag, if within a group and a new service definition starts or we reach end of att db 878 if (in_group && 879 (it.handle == 0 || att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID))){ 880 // log_info("End of group, handle 0x%04x, val_len: %u", prev_handle, pair_len - 4); 881 882 little_endian_store_16(response_buffer, offset, group_start_handle); 883 offset += 2; 884 little_endian_store_16(response_buffer, offset, prev_handle); 885 offset += 2; 886 memcpy(response_buffer + offset, group_start_value, pair_len - 4); 887 offset += pair_len - 4; 888 in_group = 0; 889 890 // check if space for another handle pair available 891 if (offset + pair_len > response_buffer_size){ 892 break; 893 } 894 } 895 896 // keep track of previous handle 897 prev_handle = it.handle; 898 899 // does current attribute match 900 // log_info("compare: %04x == %04x", *(uint16_t*) context->attribute_type, *(uint16_t*) uuid); 901 if (it.handle && att_iterator_match_uuid(&it, attribute_type, attribute_type_len)) { 902 903 // check if value has same len as last one 904 uint16_t this_pair_len = 4 + it.value_len; 905 if (offset > 1){ 906 if (this_pair_len != pair_len) { 907 break; 908 } 909 } 910 911 // log_info("Begin of group, handle 0x%04x", it.handle); 912 913 // first 914 if (offset == 1) { 915 pair_len = this_pair_len; 916 response_buffer[offset] = this_pair_len; 917 offset++; 918 } 919 920 group_start_handle = it.handle; 921 group_start_value = it.value; 922 in_group = 1; 923 } 924 } 925 926 if (offset == 1){ 927 return setup_error_atribute_not_found(response_buffer, request_type, start_handle); 928 } 929 930 response_buffer[0] = ATT_READ_BY_GROUP_TYPE_RESPONSE; 931 return offset; 932 } 933 static uint16_t handle_read_by_group_type_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, 934 uint8_t * response_buffer, uint16_t response_buffer_size){ 935 int attribute_type_len; 936 if (request_len <= 7){ 937 attribute_type_len = 2; 938 } else { 939 attribute_type_len = 16; 940 } 941 return handle_read_by_group_type_request2(att_connection, response_buffer, response_buffer_size, little_endian_read_16(request_buffer, 1), little_endian_read_16(request_buffer, 3), attribute_type_len, &request_buffer[5]); 942 } 943 944 // 945 // MARK: ATT_WRITE_REQUEST 0x12 946 static uint16_t handle_write_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, 947 uint8_t * response_buffer, uint16_t response_buffer_size){ 948 949 UNUSED(response_buffer_size); 950 951 uint8_t request_type = ATT_WRITE_REQUEST; 952 953 uint16_t handle = little_endian_read_16(request_buffer, 1); 954 att_iterator_t it; 955 int ok = att_find_handle(&it, handle); 956 if (!ok) { 957 return setup_error_invalid_handle(response_buffer, request_type, handle); 958 } 959 if (!att_write_callback) { 960 return setup_error_write_not_permitted(response_buffer, request_type, handle); 961 } 962 if ((it.flags & ATT_PROPERTY_WRITE) == 0) { 963 return setup_error_write_not_permitted(response_buffer, request_type, handle); 964 } 965 if ((it.flags & ATT_PROPERTY_DYNAMIC) == 0) { 966 return setup_error_write_not_permitted(response_buffer, request_type, handle); 967 } 968 // check security requirements 969 int error_code = att_validate_security(att_connection, ATT_WRITE, &it); 970 if (error_code) { 971 return setup_error(response_buffer, request_type, handle, error_code); 972 } 973 att_persistent_ccc_cache(&it); 974 error_code = (*att_write_callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3); 975 976 #ifdef ENABLE_ATT_DELAYED_RESPONSE 977 if (error_code == ATT_ERROR_WRITE_RESPONSE_PENDING) return ATT_INTERNAL_WRITE_RESPONSE_PENDING; 978 #endif 979 980 if (error_code) { 981 return setup_error(response_buffer, request_type, handle, error_code); 982 } 983 response_buffer[0] = ATT_WRITE_RESPONSE; 984 return 1; 985 } 986 987 // 988 // MARK: ATT_PREPARE_WRITE_REQUEST 0x16 989 static uint16_t handle_prepare_write_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, 990 uint8_t * response_buffer, uint16_t response_buffer_size){ 991 992 UNUSED(response_buffer_size); 993 994 uint8_t request_type = ATT_PREPARE_WRITE_REQUEST; 995 996 uint16_t handle = little_endian_read_16(request_buffer, 1); 997 uint16_t offset = little_endian_read_16(request_buffer, 3); 998 if (!att_write_callback) { 999 return setup_error_write_not_permitted(response_buffer, request_type, handle); 1000 } 1001 att_iterator_t it; 1002 int ok = att_find_handle(&it, handle); 1003 if (!ok) { 1004 return setup_error_invalid_handle(response_buffer, request_type, handle); 1005 } 1006 if ((it.flags & ATT_PROPERTY_WRITE) == 0) { 1007 return setup_error_write_not_permitted(response_buffer, request_type, handle); 1008 } 1009 if ((it.flags & ATT_PROPERTY_DYNAMIC) == 0) { 1010 return setup_error_write_not_permitted(response_buffer, request_type, handle); 1011 } 1012 // check security requirements 1013 int error_code = att_validate_security(att_connection, ATT_WRITE, &it); 1014 if (error_code) { 1015 return setup_error(response_buffer, request_type, handle, error_code); 1016 } 1017 1018 error_code = (*att_write_callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_ACTIVE, offset, request_buffer + 5, request_len - 5); 1019 switch (error_code){ 1020 case 0: 1021 break; 1022 case ATT_ERROR_INVALID_OFFSET: 1023 case ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH: 1024 // postpone to execute write request 1025 att_prepare_write_update_errors(error_code, handle); 1026 break; 1027 #ifdef ENABLE_ATT_DELAYED_RESPONSE 1028 case ATT_ERROR_WRITE_RESPONSE_PENDING: 1029 return ATT_INTERNAL_WRITE_RESPONSE_PENDING; 1030 #endif 1031 default: 1032 return setup_error(response_buffer, request_type, handle, error_code); 1033 } 1034 1035 // response: echo request 1036 memcpy(response_buffer, request_buffer, request_len); 1037 response_buffer[0] = ATT_PREPARE_WRITE_RESPONSE; 1038 return request_len; 1039 } 1040 1041 /* 1042 * @brief transcation queue of prepared writes, e.g., after disconnect 1043 */ 1044 void att_clear_transaction_queue(att_connection_t * att_connection){ 1045 (*att_write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_CANCEL, 0, NULL, 0); 1046 } 1047 1048 // MARK: ATT_EXECUTE_WRITE_REQUEST 0x18 1049 // NOTE: security has been verified by handle_prepare_write_request 1050 static uint16_t handle_execute_write_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, 1051 uint8_t * response_buffer, uint16_t response_buffer_size){ 1052 1053 UNUSED(request_len); 1054 UNUSED(response_buffer_size); 1055 1056 uint8_t request_type = ATT_EXECUTE_WRITE_REQUEST; 1057 if (request_buffer[1]) { 1058 // validate queued write 1059 if (att_prepare_write_error_code == 0){ 1060 att_prepare_write_error_code = (*att_write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_VALIDATE, 0, NULL, 0); 1061 } 1062 #ifdef ENABLE_ATT_DELAYED_RESPONSE 1063 if (att_prepare_write_error_code == ATT_ERROR_WRITE_RESPONSE_PENDING) return ATT_INTERNAL_WRITE_RESPONSE_PENDING; 1064 #endif 1065 // deliver queued errors 1066 if (att_prepare_write_error_code){ 1067 att_clear_transaction_queue(att_connection); 1068 uint8_t error_code = att_prepare_write_error_code; 1069 uint16_t handle = att_prepare_write_error_handle; 1070 att_prepare_write_reset(); 1071 return setup_error(response_buffer, request_type, handle, error_code); 1072 } 1073 att_write_callback(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_EXECUTE, 0, NULL, 0); 1074 } else { 1075 att_clear_transaction_queue(att_connection); 1076 } 1077 response_buffer[0] = ATT_EXECUTE_WRITE_RESPONSE; 1078 return 1; 1079 } 1080 1081 // MARK: ATT_WRITE_COMMAND 0x52 1082 // Core 4.0, vol 3, part F, 3.4.5.3 1083 // "No Error Response or Write Response shall be sent in response to this command" 1084 static void handle_write_command(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, 1085 uint8_t * response_buffer, uint16_t response_buffer_size){ 1086 1087 UNUSED(response_buffer); 1088 UNUSED(response_buffer_size); 1089 1090 uint16_t handle = little_endian_read_16(request_buffer, 1); 1091 if (!att_write_callback) return; 1092 1093 att_iterator_t it; 1094 int ok = att_find_handle(&it, handle); 1095 if (!ok) return; 1096 if ((it.flags & ATT_PROPERTY_DYNAMIC) == 0) return; 1097 if ((it.flags & ATT_PROPERTY_WRITE_WITHOUT_RESPONSE) == 0) return; 1098 if (att_validate_security(att_connection, ATT_WRITE, &it)) return; 1099 att_persistent_ccc_cache(&it); 1100 (*att_write_callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3); 1101 } 1102 1103 // MARK: helper for ATT_HANDLE_VALUE_NOTIFICATION and ATT_HANDLE_VALUE_INDICATION 1104 static uint16_t prepare_handle_value(att_connection_t * att_connection, 1105 uint16_t handle, 1106 const uint8_t *value, 1107 uint16_t value_len, 1108 uint8_t * response_buffer){ 1109 little_endian_store_16(response_buffer, 1, handle); 1110 if (value_len > att_connection->mtu - 3){ 1111 value_len = att_connection->mtu - 3; 1112 } 1113 memcpy(&response_buffer[3], value, value_len); 1114 return value_len + 3; 1115 } 1116 1117 // MARK: ATT_HANDLE_VALUE_NOTIFICATION 0x1b 1118 uint16_t att_prepare_handle_value_notification(att_connection_t * att_connection, 1119 uint16_t handle, 1120 const uint8_t *value, 1121 uint16_t value_len, 1122 uint8_t * response_buffer){ 1123 1124 response_buffer[0] = ATT_HANDLE_VALUE_NOTIFICATION; 1125 return prepare_handle_value(att_connection, handle, value, value_len, response_buffer); 1126 } 1127 1128 // MARK: ATT_HANDLE_VALUE_INDICATION 0x1d 1129 uint16_t att_prepare_handle_value_indication(att_connection_t * att_connection, 1130 uint16_t handle, 1131 const uint8_t *value, 1132 uint16_t value_len, 1133 uint8_t * response_buffer){ 1134 1135 response_buffer[0] = ATT_HANDLE_VALUE_INDICATION; 1136 return prepare_handle_value(att_connection, handle, value, value_len, response_buffer); 1137 } 1138 1139 // MARK: Dispatcher 1140 uint16_t att_handle_request(att_connection_t * att_connection, 1141 uint8_t * request_buffer, 1142 uint16_t request_len, 1143 uint8_t * response_buffer){ 1144 uint16_t response_len = 0; 1145 uint16_t response_buffer_size = att_connection->mtu; 1146 1147 switch (request_buffer[0]){ 1148 case ATT_EXCHANGE_MTU_REQUEST: 1149 response_len = handle_exchange_mtu_request(att_connection, request_buffer, request_len, response_buffer); 1150 break; 1151 case ATT_FIND_INFORMATION_REQUEST: 1152 response_len = handle_find_information_request(att_connection, request_buffer, request_len,response_buffer, response_buffer_size); 1153 break; 1154 case ATT_FIND_BY_TYPE_VALUE_REQUEST: 1155 response_len = handle_find_by_type_value_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); 1156 break; 1157 case ATT_READ_BY_TYPE_REQUEST: 1158 response_len = handle_read_by_type_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); 1159 break; 1160 case ATT_READ_REQUEST: 1161 response_len = handle_read_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); 1162 break; 1163 case ATT_READ_BLOB_REQUEST: 1164 response_len = handle_read_blob_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); 1165 break; 1166 case ATT_READ_MULTIPLE_REQUEST: 1167 response_len = handle_read_multiple_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); 1168 break; 1169 case ATT_READ_BY_GROUP_TYPE_REQUEST: 1170 response_len = handle_read_by_group_type_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); 1171 break; 1172 case ATT_WRITE_REQUEST: 1173 response_len = handle_write_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); 1174 break; 1175 case ATT_PREPARE_WRITE_REQUEST: 1176 response_len = handle_prepare_write_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); 1177 break; 1178 case ATT_EXECUTE_WRITE_REQUEST: 1179 response_len = handle_execute_write_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); 1180 break; 1181 case ATT_WRITE_COMMAND: 1182 handle_write_command(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); 1183 break; 1184 #ifdef ENABLE_LE_SIGNED_WRITE 1185 case ATT_SIGNED_WRITE_COMMAND: 1186 log_info("handle_signed_write_command preprocessed by att_server.c"); 1187 break; 1188 #endif 1189 default: 1190 log_info("Unhandled ATT Command: %02X, DATA: ", request_buffer[0]); 1191 log_info_hexdump(&request_buffer[9], request_len-9); 1192 break; 1193 } 1194 return response_len; 1195 } 1196 1197 // returns 1 if service found. only primary service. 1198 int gatt_server_get_get_handle_range_for_service_with_uuid16(uint16_t uuid16, uint16_t * start_handle, uint16_t * end_handle){ 1199 uint16_t in_group = 0; 1200 uint16_t prev_handle = 0; 1201 1202 uint8_t attribute_value[2]; 1203 int attribute_len = sizeof(attribute_value); 1204 little_endian_store_16(attribute_value, 0, uuid16); 1205 1206 att_iterator_t it; 1207 att_iterator_init(&it); 1208 while (att_iterator_has_next(&it)){ 1209 att_iterator_fetch_next(&it); 1210 int new_service_started = att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID); 1211 1212 // close current tag, if within a group and a new service definition starts or we reach end of att db 1213 if (in_group && 1214 (it.handle == 0 || new_service_started)){ 1215 *end_handle = prev_handle; 1216 return 1; 1217 } 1218 1219 // keep track of previous handle 1220 prev_handle = it.handle; 1221 1222 // check if found 1223 if (it.handle && new_service_started && attribute_len == it.value_len && memcmp(attribute_value, it.value, it.value_len) == 0){ 1224 *start_handle = it.handle; 1225 in_group = 1; 1226 } 1227 } 1228 return 0; 1229 } 1230 1231 // returns 0 if not found 1232 uint16_t gatt_server_get_value_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t uuid16){ 1233 att_iterator_t it; 1234 att_iterator_init(&it); 1235 while (att_iterator_has_next(&it)){ 1236 att_iterator_fetch_next(&it); 1237 if (it.handle && it.handle < start_handle) continue; 1238 if (it.handle > end_handle) break; // (1) 1239 if (it.handle == 0) break; 1240 if (att_iterator_match_uuid16(&it, uuid16)) return it.handle; 1241 } 1242 return 0; 1243 } 1244 1245 uint16_t gatt_server_get_descriptor_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t characteristic_uuid16, uint16_t descriptor_uuid16){ 1246 att_iterator_t it; 1247 att_iterator_init(&it); 1248 int characteristic_found = 0; 1249 while (att_iterator_has_next(&it)){ 1250 att_iterator_fetch_next(&it); 1251 if (it.handle && it.handle < start_handle) continue; 1252 if (it.handle > end_handle) break; // (1) 1253 if (it.handle == 0) break; 1254 if (att_iterator_match_uuid16(&it, characteristic_uuid16)){ 1255 characteristic_found = 1; 1256 continue; 1257 } 1258 if (att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) 1259 || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID) 1260 || att_iterator_match_uuid16(&it, GATT_CHARACTERISTICS_UUID)){ 1261 if (characteristic_found) break; 1262 continue; 1263 } 1264 if (characteristic_found && att_iterator_match_uuid16(&it, descriptor_uuid16)){ 1265 return it.handle; 1266 } 1267 } 1268 return 0; 1269 } 1270 1271 // returns 0 if not found 1272 uint16_t gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t characteristic_uuid16){ 1273 return gatt_server_get_descriptor_handle_for_characteristic_with_uuid16(start_handle, end_handle, characteristic_uuid16, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION); 1274 } 1275 // returns 0 if not found 1276 1277 uint16_t gatt_server_get_server_configuration_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t characteristic_uuid16){ 1278 return gatt_server_get_descriptor_handle_for_characteristic_with_uuid16(start_handle, end_handle, characteristic_uuid16, GATT_SERVER_CHARACTERISTICS_CONFIGURATION); 1279 } 1280 1281 // returns 1 if service found. only primary service. 1282 int gatt_server_get_get_handle_range_for_service_with_uuid128(const uint8_t * uuid128, uint16_t * start_handle, uint16_t * end_handle){ 1283 uint16_t in_group = 0; 1284 uint16_t prev_handle = 0; 1285 1286 uint8_t attribute_value[16]; 1287 int attribute_len = sizeof(attribute_value); 1288 reverse_128(uuid128, attribute_value); 1289 1290 att_iterator_t it; 1291 att_iterator_init(&it); 1292 while (att_iterator_has_next(&it)){ 1293 att_iterator_fetch_next(&it); 1294 int new_service_started = att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID); 1295 1296 // close current tag, if within a group and a new service definition starts or we reach end of att db 1297 if (in_group && 1298 (it.handle == 0 || new_service_started)){ 1299 *end_handle = prev_handle; 1300 return 1; 1301 } 1302 1303 // keep track of previous handle 1304 prev_handle = it.handle; 1305 1306 // check if found 1307 if (it.handle && new_service_started && attribute_len == it.value_len && memcmp(attribute_value, it.value, it.value_len) == 0){ 1308 *start_handle = it.handle; 1309 in_group = 1; 1310 } 1311 } 1312 return 0; 1313 } 1314 1315 // returns 0 if not found 1316 uint16_t gatt_server_get_value_handle_for_characteristic_with_uuid128(uint16_t start_handle, uint16_t end_handle, const uint8_t * uuid128){ 1317 uint8_t attribute_value[16]; 1318 reverse_128(uuid128, attribute_value); 1319 att_iterator_t it; 1320 att_iterator_init(&it); 1321 while (att_iterator_has_next(&it)){ 1322 att_iterator_fetch_next(&it); 1323 if (it.handle && it.handle < start_handle) continue; 1324 if (it.handle > end_handle) break; // (1) 1325 if (it.handle == 0) break; 1326 if (att_iterator_match_uuid(&it, attribute_value, 16)) return it.handle; 1327 } 1328 return 0; 1329 } 1330 1331 // returns 0 if not found 1332 uint16_t gatt_server_get_client_configuration_handle_for_characteristic_with_uuid128(uint16_t start_handle, uint16_t end_handle, const uint8_t * uuid128){ 1333 uint8_t attribute_value[16]; 1334 reverse_128(uuid128, attribute_value); 1335 att_iterator_t it; 1336 att_iterator_init(&it); 1337 int characteristic_found = 0; 1338 while (att_iterator_has_next(&it)){ 1339 att_iterator_fetch_next(&it); 1340 if (it.handle && it.handle < start_handle) continue; 1341 if (it.handle > end_handle) break; // (1) 1342 if (it.handle == 0) break; 1343 if (att_iterator_match_uuid(&it, attribute_value, 16)){ 1344 characteristic_found = 1; 1345 continue; 1346 } 1347 if (att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) 1348 || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID) 1349 || att_iterator_match_uuid16(&it, GATT_CHARACTERISTICS_UUID)){ 1350 if (characteristic_found) break; 1351 continue; 1352 } 1353 if (characteristic_found && att_iterator_match_uuid16(&it, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION)){ 1354 return it.handle; 1355 } 1356 } 1357 return 0; 1358 } 1359 1360 1361 // 1-item cache to optimize query during write_callback 1362 static void att_persistent_ccc_cache(att_iterator_t * it){ 1363 att_persistent_ccc_handle = it->handle; 1364 if (it->flags & ATT_PROPERTY_UUID128){ 1365 att_persistent_ccc_uuid16 = 0; 1366 } else { 1367 att_persistent_ccc_uuid16 = little_endian_read_16(it->uuid, 0); 1368 } 1369 } 1370 1371 int att_is_persistent_ccc(uint16_t handle){ 1372 if (handle != att_persistent_ccc_handle){ 1373 att_iterator_t it; 1374 int ok = att_find_handle(&it, handle); 1375 if (!ok) return 0; 1376 att_persistent_ccc_cache(&it); 1377 } 1378 return att_persistent_ccc_uuid16 == GATT_CLIENT_CHARACTERISTICS_CONFIGURATION; 1379 } 1380 1381 // att_read_callback helpers 1382 uint16_t att_read_callback_handle_blob(const uint8_t * blob, uint16_t blob_size, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){ 1383 if (buffer){ 1384 uint16_t bytes_to_copy = btstack_min(blob_size - offset, buffer_size); 1385 memcpy(buffer, &blob[offset], bytes_to_copy); 1386 return bytes_to_copy; 1387 } else { 1388 return blob_size; 1389 } 1390 } 1391 1392 uint16_t att_read_callback_handle_little_endian_32(uint32_t value, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){ 1393 uint8_t value_buffer[4]; 1394 little_endian_store_32(value_buffer, 0, value); 1395 return att_read_callback_handle_blob(value_buffer, sizeof(value_buffer), offset, buffer, buffer_size); 1396 } 1397 1398 uint16_t att_read_callback_handle_little_endian_16(uint16_t value, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){ 1399 uint8_t value_buffer[2]; 1400 little_endian_store_16(value_buffer, 0, value); 1401 return att_read_callback_handle_blob(value_buffer, sizeof(value_buffer), offset, buffer, buffer_size); 1402 } 1403 1404 uint16_t att_read_callback_handle_byte(uint8_t value, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){ 1405 uint8_t value_buffer[1]; 1406 value_buffer[0] = value; 1407 return att_read_callback_handle_blob(value_buffer, sizeof(value_buffer), offset, buffer, buffer_size); 1408 } 1409