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