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