diff --git a/cores/rp2040/sdkoverride/att_db.c b/cores/rp2040/sdkoverride/att_db.c deleted file mode 100644 index e48e2c02b..000000000 --- a/cores/rp2040/sdkoverride/att_db.c +++ /dev/null @@ -1,1863 +0,0 @@ -/* - Copyright (C) 2014 BlueKitchen GmbH - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the names of - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - 4. Any redistribution, use, or modification is done solely for - personal benefit and not for any commercial purpose or for - monetary gain. - - THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN - GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - Please inquire about commercial licensing options at - contact@bluekitchen-gmbh.com - -*/ - -#define BTSTACK_FILE__ "att_db.c" - -#if defined ENABLE_CLASSIC - -#include -#include -#include "ble/att_db.h" -#include "ble/core.h" - -#include "btstack_debug.h" -#include "btstack_util.h" - -// check for ENABLE_ATT_DELAYED_READ_RESPONSE -> ENABLE_ATT_DELAYED_RESPONSE, -#ifdef ENABLE_ATT_DELAYED_READ_RESPONSE -#error "ENABLE_ATT_DELAYED_READ_RESPONSE was replaced by ENABLE_ATT_DELAYED_RESPONSE. Please update btstack_config.h" -#endif - -typedef enum { - ATT_READ, - ATT_WRITE, -} att_operation_t; - - -static int is_Bluetooth_Base_UUID(uint8_t const *uuid) { - // Bluetooth Base UUID 00000000-0000-1000-8000-00805F9B34FB in little endian - static const uint8_t bluetooth_base_uuid[] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - if (memcmp(&uuid[0], &bluetooth_base_uuid[0], 12) != 0) { - return false; - } - if (memcmp(&uuid[14], &bluetooth_base_uuid[14], 2) != 0) { - return false; - } - return true; - -} - -static uint16_t uuid16_from_uuid(uint16_t uuid_len, uint8_t * uuid) { - if (uuid_len == 2u) { - return little_endian_read_16(uuid, 0u); - } - if (!is_Bluetooth_Base_UUID(uuid)) { - return 0; - } - return little_endian_read_16(uuid, 12); -} - -// ATT Database - -// new java-style iterator -typedef struct att_iterator { - // private - uint8_t const * att_ptr; - // public - uint16_t size; - uint16_t flags; - uint16_t handle; - uint8_t const * uuid; - uint16_t value_len; - uint8_t const * value; -} att_iterator_t; - -static void att_persistent_ccc_cache(att_iterator_t * it); - -static uint8_t const * att_database = NULL; -static att_read_callback_t att_read_callback = NULL; -static att_write_callback_t att_write_callback = NULL; -static int att_prepare_write_error_code = 0; -static uint16_t att_prepare_write_error_handle = 0x0000; - -// single cache for att_is_persistent_ccc - stores flags before write callback -static uint16_t att_persistent_ccc_handle; -static uint16_t att_persistent_ccc_uuid16; - -static void att_iterator_init(att_iterator_t *it) { - it->att_ptr = att_database; -} - -static bool att_iterator_has_next(att_iterator_t *it) { - return it->att_ptr != NULL; -} - -static void att_iterator_fetch_next(att_iterator_t *it) { - it->size = little_endian_read_16(it->att_ptr, 0); - if (it->size == 0u) { - it->flags = 0; - it->handle = 0; - it->uuid = NULL; - it->value_len = 0; - it->value = NULL; - it->att_ptr = NULL; - return; - } - it->flags = little_endian_read_16(it->att_ptr, 2); - it->handle = little_endian_read_16(it->att_ptr, 4); - it->uuid = &it->att_ptr[6]; - // handle 128 bit UUIDs - if ((it->flags & (uint16_t)ATT_PROPERTY_UUID128) != 0u) { - it->value_len = it->size - 22u; - it->value = &it->att_ptr[22]; - } else { - it->value_len = it->size - 8u; - it->value = &it->att_ptr[8]; - } - // advance AFTER setting values - it->att_ptr += it->size; -} - -static int att_iterator_match_uuid16(att_iterator_t *it, uint16_t uuid) { - if (it->handle == 0u) { - return 0u; - } - if (it->flags & (uint16_t)ATT_PROPERTY_UUID128) { - if (!is_Bluetooth_Base_UUID(it->uuid)) { - return 0; - } - return little_endian_read_16(it->uuid, 12) == uuid; - } - return little_endian_read_16(it->uuid, 0) == uuid; -} - -static int att_iterator_match_uuid(att_iterator_t *it, uint8_t *uuid, uint16_t uuid_len) { - if (it->handle == 0u) { - return 0u; - } - // input: UUID16 - if (uuid_len == 2u) { - return att_iterator_match_uuid16(it, little_endian_read_16(uuid, 0)); - } - // input and db: UUID128 - if ((it->flags & (uint16_t)ATT_PROPERTY_UUID128) != 0u) { - return memcmp(it->uuid, uuid, 16) == 0; - } - // input: UUID128, db: UUID16 - if (!is_Bluetooth_Base_UUID(uuid)) { - return 0; - } - return little_endian_read_16(uuid, 12) == little_endian_read_16(it->uuid, 0); -} - - -static int att_find_handle(att_iterator_t *it, uint16_t handle) { - if (handle == 0u) { - return 0u; - } - att_iterator_init(it); - while (att_iterator_has_next(it)) { - att_iterator_fetch_next(it); - if (it->handle != handle) { - continue; - } - return 1; - } - return 0; -} - -// experimental client API -uint16_t att_uuid_for_handle(uint16_t attribute_handle) { - att_iterator_t it; - int ok = att_find_handle(&it, attribute_handle); - if (!ok) { - return 0u; - } - if ((it.flags & (uint16_t)ATT_PROPERTY_UUID128) != 0u) { - return 0u; - } - return little_endian_read_16(it.uuid, 0); -} - -const uint8_t * gatt_server_get_const_value_for_handle(uint16_t attribute_handle, uint16_t * out_value_len) { - att_iterator_t it; - int ok = att_find_handle(&it, attribute_handle); - if (!ok) { - return 0u; - } - if ((it.flags & (uint16_t)ATT_PROPERTY_DYNAMIC) != 0u) { - return 0u; - } - *out_value_len = it.value_len; - return it.value; -} - -// end of client API - -static void att_update_value_len(att_iterator_t *it, uint16_t offset, hci_con_handle_t con_handle) { - if ((it->flags & (uint16_t)ATT_PROPERTY_DYNAMIC) == 0u) { - return; - } - it->value_len = (*att_read_callback)(con_handle, it->handle, offset, NULL, 0); - return; -} - -// copy attribute value from offset into buffer with given size -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) { - - // DYNAMIC - if ((it->flags & (uint16_t)ATT_PROPERTY_DYNAMIC) != 0u) { - return (*att_read_callback)(con_handle, it->handle, offset, buffer, buffer_size); - } - - // STATIC - uint16_t bytes_to_copy = btstack_min(it->value_len - offset, buffer_size); - (void)memcpy(buffer, it->value, bytes_to_copy); - return bytes_to_copy; -} - -void att_set_db(uint8_t const * db) { - // validate db version - if (db == NULL) { - return; - } - if (*db != (uint8_t)ATT_DB_VERSION) { - log_error("ATT DB version differs, please regenerate .h from .gatt file or update att_db_util.c"); - return; - } - log_info("att_set_db %p", db); - // ignore db version - att_database = &db[1]; -} - -void att_set_read_callback(att_read_callback_t callback) { - att_read_callback = callback; -} - -void att_set_write_callback(att_write_callback_t callback) { - att_write_callback = callback; -} - -void att_dump_attributes(void) { - att_iterator_t it; - att_iterator_init(&it); - uint8_t uuid128[16]; - log_info("att_dump_attributes, table %p", att_database); - while (att_iterator_has_next(&it)) { - att_iterator_fetch_next(&it); - if (it.handle == 0u) { - log_info("Handle: END"); - return; - } - log_info("Handle: 0x%04x, flags: 0x%04x, uuid: ", it.handle, it.flags); - if ((it.flags & (uint16_t)ATT_PROPERTY_UUID128) != 0u) { - reverse_128(it.uuid, uuid128); - log_info("%s", uuid128_to_str(uuid128)); - } else { - log_info("%04x", little_endian_read_16(it.uuid, 0)); - } - log_info(", value_len: %u, value: ", it.value_len); - log_info_hexdump(it.value, it.value_len); - } -} - -static void att_prepare_write_reset(void) { - att_prepare_write_error_code = 0; - att_prepare_write_error_handle = 0x0000; -} - -static void att_prepare_write_update_errors(uint8_t error_code, uint16_t handle) { - // first ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH has highest priority - if ((error_code == (uint8_t)ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH) && (error_code != (uint8_t)att_prepare_write_error_code)) { - att_prepare_write_error_code = error_code; - att_prepare_write_error_handle = handle; - return; - } - // first ATT_ERROR_INVALID_OFFSET is next - if ((error_code == (uint8_t)ATT_ERROR_INVALID_OFFSET) && (att_prepare_write_error_code == 0)) { - att_prepare_write_error_code = error_code; - att_prepare_write_error_handle = handle; - return; - } -} - -static uint16_t setup_error(uint8_t * response_buffer, uint8_t request_opcode, uint16_t handle, uint8_t error_code) { - response_buffer[0] = (uint8_t)ATT_ERROR_RESPONSE; - response_buffer[1] = request_opcode; - little_endian_store_16(response_buffer, 2, handle); - response_buffer[4] = error_code; - return 5; -} - -static inline uint16_t setup_error_read_not_permitted(uint8_t * response_buffer, uint8_t request_opcode, uint16_t start_handle) { - return setup_error(response_buffer, request_opcode, start_handle, ATT_ERROR_READ_NOT_PERMITTED); -} - -static inline uint16_t setup_error_write_not_permitted(uint8_t * response_buffer, uint8_t request, uint16_t start_handle) { - return setup_error(response_buffer, request, start_handle, ATT_ERROR_WRITE_NOT_PERMITTED); -} - -static inline uint16_t setup_error_atribute_not_found(uint8_t * response_buffer, uint8_t request_opcode, uint16_t start_handle) { - return setup_error(response_buffer, request_opcode, start_handle, ATT_ERROR_ATTRIBUTE_NOT_FOUND); -} - -static inline uint16_t setup_error_invalid_handle(uint8_t * response_buffer, uint8_t request_opcode, uint16_t handle) { - return setup_error(response_buffer, request_opcode, handle, ATT_ERROR_INVALID_HANDLE); -} - -static inline uint16_t setup_error_invalid_offset(uint8_t * response_buffer, uint8_t request_opcode, uint16_t handle) { - return setup_error(response_buffer, request_opcode, handle, ATT_ERROR_INVALID_OFFSET); -} - -static inline uint16_t setup_error_invalid_pdu(uint8_t *response_buffer, uint8_t request_opcode) { - return setup_error(response_buffer, request_opcode, 0, ATT_ERROR_INVALID_PDU); -} - -struct att_security_settings { - uint8_t required_security_level; - bool requires_secure_connection; -}; - -static void att_validate_security_get_settings(struct att_security_settings * security_settings, att_operation_t operation, att_iterator_t *it) { - security_settings->required_security_level = 0u; - security_settings->requires_secure_connection = false; - switch (operation) { - case ATT_READ: - if ((it->flags & (uint16_t)ATT_PROPERTY_READ_PERMISSION_BIT_0) != 0u) { - security_settings->required_security_level |= 1u; - } - if ((it->flags & (uint16_t)ATT_PROPERTY_READ_PERMISSION_BIT_1) != 0u) { - security_settings->required_security_level |= 2u; - } - if ((it->flags & (uint16_t)ATT_PROPERTY_READ_PERMISSION_SC) != 0u) { - security_settings->requires_secure_connection = true; - } - break; - case ATT_WRITE: - if ((it->flags & (uint16_t)ATT_PROPERTY_WRITE_PERMISSION_BIT_0) != 0u) { - security_settings->required_security_level |= 1u; - } - if ((it->flags & (uint16_t)ATT_PROPERTY_WRITE_PERMISSION_BIT_1) != 0u) { - security_settings->required_security_level |= 2u; - } - if ((it->flags & (uint16_t)ATT_PROPERTY_WRITE_PERMISSION_SC) != 0u) { - security_settings->requires_secure_connection = true; - } - break; - default: - btstack_assert(false); - break; - } -} - -static uint8_t att_validate_security(att_connection_t * att_connection, att_operation_t operation, att_iterator_t * it) { - struct att_security_settings security_settings; - att_validate_security_get_settings(&security_settings, operation, it); - - uint8_t required_encryption_size = (uint8_t)(it->flags >> 12); - if (required_encryption_size != 0u) { - required_encryption_size++; // store -1 to fit into 4 bit - } - log_debug("att_validate_security. flags 0x%04x (=> security level %u, key size %u) authorized %u, authenticated %u, encryption_key_size %u, secure connection %u", - it->flags, security_settings.required_security_level, required_encryption_size, att_connection->authorized, att_connection->authenticated, att_connection->encryption_key_size, att_connection->secure_connection); - - bool sc_missing = security_settings.requires_secure_connection && (att_connection->secure_connection == 0u); - switch (security_settings.required_security_level) { - case ATT_SECURITY_AUTHORIZED: - if ((att_connection->authorized == 0u) || sc_missing) { - return ATT_ERROR_INSUFFICIENT_AUTHORIZATION; - } - /* fall through */ - case ATT_SECURITY_AUTHENTICATED: - if ((att_connection->authenticated == 0u) || sc_missing) { - return ATT_ERROR_INSUFFICIENT_AUTHENTICATION; - } - /* fall through */ - case ATT_SECURITY_ENCRYPTED: - if ((required_encryption_size > 0u) && ((att_connection->encryption_key_size == 0u) || sc_missing)) { - return ATT_ERROR_INSUFFICIENT_ENCRYPTION; - } - if (required_encryption_size > att_connection->encryption_key_size) { - return ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE; - } - break; - default: - break; - } - return ATT_ERROR_SUCCESS; -} - -// -// MARK: ATT_EXCHANGE_MTU_REQUEST -// -static uint16_t handle_exchange_mtu_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, - uint8_t * response_buffer) { - - if (request_len != 3u) { - return setup_error_invalid_pdu(response_buffer, ATT_EXCHANGE_MTU_REQUEST); - } - - uint16_t client_rx_mtu = little_endian_read_16(request_buffer, 1); - - // find min(local max mtu, remote mtu) >= ATT_DEFAULT_MTU and use as mtu for this connection - uint16_t min_mtu = btstack_min(client_rx_mtu, att_connection->max_mtu); - uint16_t new_mtu = btstack_max(ATT_DEFAULT_MTU, min_mtu); - att_connection->mtu_exchanged = true; - att_connection->mtu = new_mtu; - - response_buffer[0] = ATT_EXCHANGE_MTU_RESPONSE; - little_endian_store_16(response_buffer, 1, att_connection->mtu); - return 3; -} - - -// -// MARK: ATT_FIND_INFORMATION_REQUEST -// -// TODO: handle other types then GATT_PRIMARY_SERVICE_UUID and GATT_SECONDARY_SERVICE_UUID -// -static uint16_t handle_find_information_request2(att_connection_t * att_connection, uint8_t * response_buffer, uint16_t response_buffer_size, - uint16_t start_handle, uint16_t end_handle) { - - UNUSED(att_connection); - - log_info("ATT_FIND_INFORMATION_REQUEST: from %04X to %04X", start_handle, end_handle); - uint8_t request_type = ATT_FIND_INFORMATION_REQUEST; - - if ((start_handle > end_handle) || (start_handle == 0u)) { - return setup_error_invalid_handle(response_buffer, request_type, start_handle); - } - - uint16_t offset = 1; - uint16_t uuid_len = 0; - - att_iterator_t it; - att_iterator_init(&it); - while (att_iterator_has_next(&it)) { - att_iterator_fetch_next(&it); - if (!it.handle) { - break; - } - if (it.handle > end_handle) { - break; - } - if (it.handle < start_handle) { - continue; - } - - // log_info("Handle 0x%04x", it.handle); - - uint16_t this_uuid_len = (it.flags & (uint16_t)ATT_PROPERTY_UUID128) ? 16u : 2u; - - // check if value has same len as last one if not first result - if (offset > 1u) { - if (this_uuid_len != uuid_len) { - break; - } - } - - // first - if (offset == 1u) { - uuid_len = this_uuid_len; - // set format field - response_buffer[offset] = (it.flags & (uint16_t)ATT_PROPERTY_UUID128) ? 0x02u : 0x01u; - offset++; - } - - // space? - if ((offset + 2u + uuid_len) > response_buffer_size) { - break; - } - - // store - little_endian_store_16(response_buffer, offset, it.handle); - offset += 2u; - - (void)memcpy(response_buffer + offset, it.uuid, uuid_len); - offset += uuid_len; - } - - if (offset == 1u) { - return setup_error_atribute_not_found(response_buffer, request_type, start_handle); - } - - response_buffer[0] = ATT_FIND_INFORMATION_REPLY; - return offset; -} - -static uint16_t handle_find_information_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, - uint8_t * response_buffer, uint16_t response_buffer_size) { - - if (request_len != 5u) { - return setup_error_invalid_pdu(response_buffer, ATT_FIND_INFORMATION_REQUEST); - } - - uint16_t start_handle = little_endian_read_16(request_buffer, 1); - uint16_t end_handle = little_endian_read_16(request_buffer, 3); - return handle_find_information_request2(att_connection, response_buffer, response_buffer_size, start_handle, end_handle); -} - -// -// MARK: ATT_FIND_BY_TYPE_VALUE -// -// "Only attributes with attribute handles between and including the Starting Handle parameter -// and the Ending Handle parameter that match the requested attri- bute type and the attribute -// value that have sufficient permissions to allow reading will be returned" -> (1) -// -// TODO: handle other types then GATT_PRIMARY_SERVICE_UUID and GATT_SECONDARY_SERVICE_UUID -// -// NOTE: doesn't handle DYNAMIC values -// NOTE: only supports 16 bit UUIDs -// -static uint16_t handle_find_by_type_value_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, - uint8_t * response_buffer, uint16_t response_buffer_size) { - UNUSED(att_connection); - - if (request_len < 7u) { - return setup_error_invalid_pdu(response_buffer, ATT_FIND_BY_TYPE_VALUE_REQUEST); - } - - // parse request - uint16_t start_handle = little_endian_read_16(request_buffer, 1); - uint16_t end_handle = little_endian_read_16(request_buffer, 3); - uint16_t attribute_type = little_endian_read_16(request_buffer, 5); - const uint8_t *attribute_value = &request_buffer[7]; - uint16_t attribute_len = request_len - 7u; - - log_info("ATT_FIND_BY_TYPE_VALUE_REQUEST: from %04X to %04X, type %04X, value: ", start_handle, end_handle, attribute_type); - log_info_hexdump(attribute_value, attribute_len); - uint8_t request_type = ATT_FIND_BY_TYPE_VALUE_REQUEST; - - if ((start_handle > end_handle) || (start_handle == 0u)) { - return setup_error_invalid_handle(response_buffer, request_type, start_handle); - } - - uint16_t offset = 1; - bool in_group = false; - uint16_t prev_handle = 0; - - att_iterator_t it; - att_iterator_init(&it); - while (att_iterator_has_next(&it)) { - att_iterator_fetch_next(&it); - - if ((it.handle != 0u) && (it.handle < start_handle)) { - continue; - } - if (it.handle > end_handle) { - break; // (1) - } - - // close current tag, if within a group and a new service definition starts or we reach end of att db - if (in_group && - ((it.handle == 0u) || att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID))) { - - log_info("End of group, handle 0x%04x", prev_handle); - little_endian_store_16(response_buffer, offset, prev_handle); - offset += 2u; - in_group = false; - - // check if space for another handle pair available - if ((offset + 4u) > response_buffer_size) { - break; - } - } - - // keep track of previous handle - prev_handle = it.handle; - - // does current attribute match - if ((it.handle != 0u) && att_iterator_match_uuid16(&it, attribute_type) && (attribute_len == it.value_len) && (memcmp(attribute_value, it.value, it.value_len) == 0)) { - log_info("Begin of group, handle 0x%04x", it.handle); - little_endian_store_16(response_buffer, offset, it.handle); - offset += 2u; - in_group = true; - } - } - - if (offset == 1u) { - return setup_error_atribute_not_found(response_buffer, request_type, start_handle); - } - - response_buffer[0] = ATT_FIND_BY_TYPE_VALUE_RESPONSE; - return offset; -} - -// -// MARK: ATT_READ_BY_TYPE_REQUEST -// -static uint16_t handle_read_by_type_request2(att_connection_t * att_connection, uint8_t * response_buffer, uint16_t response_buffer_size, - uint16_t start_handle, uint16_t end_handle, - uint16_t attribute_type_len, uint8_t * attribute_type) { - - log_info("ATT_READ_BY_TYPE_REQUEST: from %04X to %04X, type: ", start_handle, end_handle); - log_info_hexdump(attribute_type, attribute_type_len); - uint8_t request_type = ATT_READ_BY_TYPE_REQUEST; - - if ((start_handle > end_handle) || (start_handle == 0u)) { - return setup_error_invalid_handle(response_buffer, request_type, start_handle); - } - - uint16_t offset = 1; - uint16_t pair_len = 0; - - att_iterator_t it; - att_iterator_init(&it); - uint8_t error_code = 0; - uint16_t first_matching_but_unreadable_handle = 0; - - while (att_iterator_has_next(&it)) { - att_iterator_fetch_next(&it); - - if ((it.handle == 0u) || (it.handle > end_handle)) { - break; - } - - // does current attribute match - if ((it.handle < start_handle) || !att_iterator_match_uuid(&it, attribute_type, attribute_type_len)) { - continue; - } - - // skip handles that cannot be read but remember that there has been at least one - if ((it.flags & (uint16_t)ATT_PROPERTY_READ) == 0u) { - if (first_matching_but_unreadable_handle == 0u) { - first_matching_but_unreadable_handle = it.handle; - } - continue; - } - - // check security requirements - error_code = att_validate_security(att_connection, ATT_READ, &it); - if (error_code != 0u) { - break; - } - - att_update_value_len(&it, 0, att_connection->con_handle); - -#ifdef ENABLE_ATT_DELAYED_RESPONSE - if (it.value_len == (uint16_t)ATT_READ_RESPONSE_PENDING) { - return ATT_READ_RESPONSE_PENDING; - } -#endif - - // allow to return ATT Error Code in ATT Read Callback - if (it.value_len > (uint16_t)ATT_READ_ERROR_CODE_OFFSET) { - error_code = (uint8_t)(it.value_len - (uint16_t)ATT_READ_ERROR_CODE_OFFSET); - break; - } - - // check if value has same len as last one - uint16_t this_pair_len = 2u + it.value_len; - if ((offset > 1u) && (pair_len != this_pair_len)) { - break; - } - - // first - if (offset == 1u) { - pair_len = this_pair_len; - response_buffer[offset] = (uint8_t) pair_len; - offset++; - } - - // space? - if ((offset + pair_len) > response_buffer_size) { - if (offset > 2u) { - break; - } - it.value_len = response_buffer_size - 4u; - response_buffer[1u] = 2u + it.value_len; - } - - // store - little_endian_store_16(response_buffer, offset, it.handle); - offset += 2u; - uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len, att_connection->con_handle); - offset += bytes_copied; - } - - // at least one attribute could be read - if (offset > 1u) { - response_buffer[0] = ATT_READ_BY_TYPE_RESPONSE; - return offset; - } - - // first attribute had an error - if (error_code != 0u) { - return setup_error(response_buffer, request_type, start_handle, error_code); - } - - // no other errors, but all found attributes had been non-readable - if (first_matching_but_unreadable_handle != 0u) { - return setup_error_read_not_permitted(response_buffer, request_type, first_matching_but_unreadable_handle); - } - - // attribute not found - return setup_error_atribute_not_found(response_buffer, request_type, start_handle); -} - -static uint16_t handle_read_by_type_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, - uint8_t * response_buffer, uint16_t response_buffer_size) { - - uint16_t attribute_type_len; - switch (request_len) { - case 7: - attribute_type_len = 2; - break; - case 21: - attribute_type_len = 16; - break; - default: - return setup_error_invalid_pdu(response_buffer, ATT_READ_BY_TYPE_REQUEST); - } - - uint16_t start_handle = little_endian_read_16(request_buffer, 1); - uint16_t end_handle = little_endian_read_16(request_buffer, 3); - return handle_read_by_type_request2(att_connection, response_buffer, response_buffer_size, start_handle, end_handle, attribute_type_len, &request_buffer[5]); -} - -// -// MARK: ATT_READ_BY_TYPE_REQUEST -// -static uint16_t handle_read_request2(att_connection_t * att_connection, uint8_t * response_buffer, uint16_t response_buffer_size, uint16_t handle) { - - log_info("ATT_READ_REQUEST: handle %04x", handle); - uint8_t request_type = ATT_READ_REQUEST; - - att_iterator_t it; - int ok = att_find_handle(&it, handle); - if (!ok) { - return setup_error_invalid_handle(response_buffer, request_type, handle); - } - - // check if handle can be read - if ((it.flags & (uint16_t)ATT_PROPERTY_READ) == 0u) { - return setup_error_read_not_permitted(response_buffer, request_type, handle); - } - - // check security requirements - uint8_t error_code = att_validate_security(att_connection, ATT_READ, &it); - if (error_code != 0u) { - return setup_error(response_buffer, request_type, handle, error_code); - } - - att_update_value_len(&it, 0, att_connection->con_handle); - -#ifdef ENABLE_ATT_DELAYED_RESPONSE - if (it.value_len == (uint16_t)ATT_READ_RESPONSE_PENDING) { - return ATT_READ_RESPONSE_PENDING; - } -#endif - - // allow to return ATT Error Code in ATT Read Callback - if (it.value_len > (uint16_t)ATT_READ_ERROR_CODE_OFFSET) { - error_code = (uint8_t)(it.value_len - (uint16_t)ATT_READ_ERROR_CODE_OFFSET); - return setup_error(response_buffer, request_type, handle, error_code); - } - - // store - uint16_t offset = 1; - uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, response_buffer_size - offset, att_connection->con_handle); - offset += bytes_copied; - - response_buffer[0] = ATT_READ_RESPONSE; - return offset; -} - -static uint16_t handle_read_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, - uint8_t * response_buffer, uint16_t response_buffer_size) { - - if (request_len != 3u) { - return setup_error_invalid_pdu(response_buffer, ATT_READ_REQUEST); - } - - uint16_t handle = little_endian_read_16(request_buffer, 1); - return handle_read_request2(att_connection, response_buffer, response_buffer_size, handle); -} - -//s -// MARK: ATT_READ_BLOB_REQUEST 0x0c -// -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) { - log_info("ATT_READ_BLOB_REQUEST: handle %04x, offset %u", handle, value_offset); - uint8_t request_type = ATT_READ_BLOB_REQUEST; - - att_iterator_t it; - int ok = att_find_handle(&it, handle); - if (!ok) { - return setup_error_invalid_handle(response_buffer, request_type, handle); - } - - // check if handle can be read - if ((it.flags & (uint16_t)ATT_PROPERTY_READ) == 0u) { - return setup_error_read_not_permitted(response_buffer, request_type, handle); - } - - // check security requirements - uint8_t error_code = att_validate_security(att_connection, ATT_READ, &it); - if (error_code != 0u) { - return setup_error(response_buffer, request_type, handle, error_code); - } - - att_update_value_len(&it, value_offset, att_connection->con_handle); - -#ifdef ENABLE_ATT_DELAYED_RESPONSE - if (it.value_len == (uint16_t)ATT_READ_RESPONSE_PENDING) { - return ATT_READ_RESPONSE_PENDING; - } -#endif - - // allow to return ATT Error Code in ATT Read Callback - if (it.value_len > (uint16_t)ATT_READ_ERROR_CODE_OFFSET) { - error_code = (uint8_t)(it.value_len - (uint16_t)ATT_READ_ERROR_CODE_OFFSET); - return setup_error(response_buffer, request_type, handle, error_code); - } - - if (value_offset > it.value_len) { - return setup_error_invalid_offset(response_buffer, request_type, handle); - } - - // prepare response - response_buffer[0] = ATT_READ_BLOB_RESPONSE; - uint16_t offset = 1; - - // fetch more data if available - if (value_offset < it.value_len) { - uint16_t bytes_copied = att_copy_value(&it, value_offset, &response_buffer[offset], response_buffer_size - offset, att_connection->con_handle); - offset += bytes_copied; - } - return offset; -} - -static uint16_t handle_read_blob_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, - uint8_t * response_buffer, uint16_t response_buffer_size) { - - if (request_len != 5u) { - return setup_error_invalid_pdu(response_buffer, ATT_READ_BLOB_REQUEST); - } - - uint16_t handle = little_endian_read_16(request_buffer, 1); - uint16_t value_offset = little_endian_read_16(request_buffer, 3); - return handle_read_blob_request2(att_connection, response_buffer, response_buffer_size, handle, value_offset); -} - -// -// MARK: ATT_READ_MULTIPLE_REQUEST 0x0e -// MARK: ATT_READ_MULTIPLE_REQUEST 0x20 -// -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, bool store_length) { - log_info("ATT_READ_MULTIPLE_(VARIABLE_)REQUEST: num handles %u", num_handles); - uint8_t request_type = store_length ? ATT_READ_MULTIPLE_VARIABLE_REQ : ATT_READ_MULTIPLE_REQUEST; - uint8_t response_type = store_length ? ATT_READ_MULTIPLE_VARIABLE_RSP : ATT_READ_MULTIPLE_RESPONSE; - uint16_t offset = 1; - - uint16_t i; - uint8_t error_code = 0; - uint16_t handle = 0; - -#ifdef ENABLE_ATT_DELAYED_RESPONSE - bool read_request_pending = false; -#endif - - for (i = 0; i < num_handles; i++) { - handle = little_endian_read_16(handles, i << 1); - - if (handle == 0u) { - return setup_error_invalid_handle(response_buffer, request_type, handle); - } - - att_iterator_t it; - - int ok = att_find_handle(&it, handle); - if (!ok) { - return setup_error_invalid_handle(response_buffer, request_type, handle); - } - - // check if handle can be read - if ((it.flags & (uint16_t)ATT_PROPERTY_READ) == 0u) { - error_code = (uint8_t)ATT_ERROR_READ_NOT_PERMITTED; - break; - } - - // check security requirements - error_code = att_validate_security(att_connection, ATT_READ, &it); - if (error_code != 0u) { - break; - } - - att_update_value_len(&it, 0, att_connection->con_handle); - -#ifdef ENABLE_ATT_DELAYED_RESPONSE - if (it.value_len == (uint16_t)ATT_READ_RESPONSE_PENDING) { - read_request_pending = true; - } - if (read_request_pending) { - continue; - } -#endif - - // allow to return ATT Error Code in ATT Read Callback - if (it.value_len > (uint16_t)ATT_READ_ERROR_CODE_OFFSET) { - error_code = (uint8_t)(it.value_len - (uint16_t)ATT_READ_ERROR_CODE_OFFSET); - break; - } - -#ifdef ENABLE_GATT_OVER_EATT - // assert that at least Value Length can be stored - if (store_length && ((offset + 2) >= response_buffer_size)) { - break; - } - // skip length field - uint16_t offset_value_length = offset; - if (store_length) { - offset += 2; - } -#endif - // store data - uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, response_buffer_size - offset, att_connection->con_handle); - offset += bytes_copied; -#ifdef ENABLE_GATT_OVER_EATT - // set length field - if (store_length) { - little_endian_store_16(response_buffer, offset_value_length, bytes_copied); - } -#endif - } - - if (error_code != 0u) { - return setup_error(response_buffer, request_type, handle, error_code); - } - - response_buffer[0] = (uint8_t)response_type; - return offset; -} - -static uint16_t -handle_read_multiple_request(att_connection_t *att_connection, uint8_t *request_buffer, uint16_t request_len, - uint8_t *response_buffer, uint16_t response_buffer_size, bool store_length) { - - uint8_t request_type = store_length ? ATT_READ_MULTIPLE_VARIABLE_REQ : ATT_READ_MULTIPLE_REQUEST; - - // 1 byte opcode + two or more attribute handles (2 bytes each) - if ((request_len < 5u) || ((request_len & 1u) == 0u)) { - return setup_error_invalid_pdu(response_buffer, request_type); - } - - uint8_t num_handles = (request_len - 1u) >> 1u; - return handle_read_multiple_request2(att_connection, response_buffer, response_buffer_size, num_handles, - &request_buffer[1], store_length); -} - -// -// MARK: ATT_READ_BY_GROUP_TYPE_REQUEST 0x10 -// -// Only handles GATT_PRIMARY_SERVICE_UUID and GATT_SECONDARY_SERVICE_UUID -// Core v4.0, vol 3, part g, 2.5.3 -// "The «Primary Service» and «Secondary Service» grouping types may be used in the Read By Group Type Request. -// The «Characteristic» grouping type shall not be used in the ATT Read By Group Type Request." -// -// NOTE: doesn't handle DYNAMIC values -// -// NOTE: we don't check for security as PRIMARY and SECONDARY SERVICE definition shouldn't be protected -// Core 4.0, vol 3, part g, 8.1 -// "The list of services and characteristics that a device supports is not considered private or -// confidential information, and therefore the Service and Characteristic Discovery procedures -// shall always be permitted. " -// -static uint16_t handle_read_by_group_type_request2(att_connection_t * att_connection, uint8_t * response_buffer, uint16_t response_buffer_size, - uint16_t start_handle, uint16_t end_handle, - uint16_t attribute_type_len, uint8_t * attribute_type) { - - UNUSED(att_connection); - - log_info("ATT_READ_BY_GROUP_TYPE_REQUEST: from %04X to %04X, buffer size %u, type: ", start_handle, end_handle, response_buffer_size); - log_info_hexdump(attribute_type, attribute_type_len); - uint8_t request_type = ATT_READ_BY_GROUP_TYPE_REQUEST; - - if ((start_handle > end_handle) || (start_handle == 0u)) { - return setup_error_invalid_handle(response_buffer, request_type, start_handle); - } - - // assert UUID is primary or secondary service uuid - uint16_t uuid16 = uuid16_from_uuid(attribute_type_len, attribute_type); - if ((uuid16 != (uint16_t)GATT_PRIMARY_SERVICE_UUID) && (uuid16 != (uint16_t)GATT_SECONDARY_SERVICE_UUID)) { - return setup_error(response_buffer, request_type, start_handle, ATT_ERROR_UNSUPPORTED_GROUP_TYPE); - } - - uint16_t offset = 1; - uint16_t pair_len = 0; - bool in_group = false; - uint16_t group_start_handle = 0; - uint8_t const * group_start_value = NULL; - uint16_t prev_handle = 0; - - att_iterator_t it; - att_iterator_init(&it); - while (att_iterator_has_next(&it)) { - att_iterator_fetch_next(&it); - - if ((it.handle != 0u) && (it.handle < start_handle)) { - continue; - } - if (it.handle > end_handle) { - break; // (1) - } - - // log_info("Handle 0x%04x", it.handle); - - // close current tag, if within a group and a new service definition starts or we reach end of att db - if (in_group && - ((it.handle == 0u) || att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID))) { - // log_info("End of group, handle 0x%04x, val_len: %u", prev_handle, pair_len - 4); - - little_endian_store_16(response_buffer, offset, group_start_handle); - offset += 2u; - little_endian_store_16(response_buffer, offset, prev_handle); - offset += 2u; - (void)memcpy(response_buffer + offset, group_start_value, - pair_len - 4u); - offset += pair_len - 4u; - in_group = false; - - // check if space for another handle pair available - if ((offset + pair_len) > response_buffer_size) { - break; - } - } - - // keep track of previous handle - prev_handle = it.handle; - - // does current attribute match - // log_info("compare: %04x == %04x", *(uint16_t*) context->attribute_type, *(uint16_t*) uuid); - if ((it.handle != 0u) && att_iterator_match_uuid(&it, attribute_type, attribute_type_len)) { - - // check if value has same len as last one - uint16_t this_pair_len = 4u + it.value_len; - if (offset > 1u) { - if (this_pair_len != pair_len) { - break; - } - } - - // log_info("Begin of group, handle 0x%04x", it.handle); - - // first - if (offset == 1u) { - pair_len = this_pair_len; - response_buffer[offset] = (uint8_t) this_pair_len; - offset++; - } - - group_start_handle = it.handle; - group_start_value = it.value; - in_group = true; - } - } - - if (offset == 1u) { - return setup_error_atribute_not_found(response_buffer, request_type, start_handle); - } - - response_buffer[0] = ATT_READ_BY_GROUP_TYPE_RESPONSE; - return offset; -} - -static uint16_t handle_read_by_group_type_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, - uint8_t * response_buffer, uint16_t response_buffer_size) { - uint16_t attribute_type_len; - switch (request_len) { - case 7: - attribute_type_len = 2; - break; - case 21: - attribute_type_len = 16; - break; - default: - return setup_error_invalid_pdu(response_buffer, ATT_READ_BY_GROUP_TYPE_REQUEST); - } - - uint16_t start_handle = little_endian_read_16(request_buffer, 1); - uint16_t end_handle = little_endian_read_16(request_buffer, 3); - return handle_read_by_group_type_request2(att_connection, response_buffer, response_buffer_size, start_handle, end_handle, attribute_type_len, &request_buffer[5]); -} - -// -// MARK: ATT_WRITE_REQUEST 0x12 -static uint16_t handle_write_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, - uint8_t * response_buffer, uint16_t response_buffer_size) { - - UNUSED(response_buffer_size); - - if (request_len < 3u) { - return setup_error_invalid_pdu(response_buffer, ATT_WRITE_REQUEST); - } - - uint8_t request_type = ATT_WRITE_REQUEST; - - uint16_t handle = little_endian_read_16(request_buffer, 1); - att_iterator_t it; - int ok = att_find_handle(&it, handle); - if (!ok) { - return setup_error_invalid_handle(response_buffer, request_type, handle); - } - if (att_write_callback == NULL) { - return setup_error_write_not_permitted(response_buffer, request_type, handle); - } - if ((it.flags & (uint16_t)ATT_PROPERTY_WRITE) == 0u) { - return setup_error_write_not_permitted(response_buffer, request_type, handle); - } - if ((it.flags & (uint16_t)ATT_PROPERTY_DYNAMIC) == 0u) { - return setup_error_write_not_permitted(response_buffer, request_type, handle); - } - // check security requirements - int error_code = att_validate_security(att_connection, ATT_WRITE, &it); - if (error_code != 0) { - return setup_error(response_buffer, request_type, handle, error_code); - } - att_persistent_ccc_cache(&it); - error_code = (*att_write_callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_NONE, 0u, request_buffer + 3u, request_len - 3u); - -#ifdef ENABLE_ATT_DELAYED_RESPONSE - if (error_code == ATT_ERROR_WRITE_RESPONSE_PENDING) { - return ATT_INTERNAL_WRITE_RESPONSE_PENDING; - } -#endif - - if (error_code != 0) { - return setup_error(response_buffer, request_type, handle, error_code); - } - response_buffer[0] = (uint8_t)ATT_WRITE_RESPONSE; - return 1; -} - -// -// MARK: ATT_PREPARE_WRITE_REQUEST 0x16 -static uint16_t handle_prepare_write_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, - uint8_t * response_buffer, uint16_t response_buffer_size) { - - uint8_t request_type = ATT_PREPARE_WRITE_REQUEST; - - if (request_len < 5u) { - return setup_error_invalid_pdu(response_buffer, request_type); - } - - uint16_t handle = little_endian_read_16(request_buffer, 1); - uint16_t offset = little_endian_read_16(request_buffer, 3); - if (att_write_callback == NULL) { - return setup_error_write_not_permitted(response_buffer, request_type, handle); - } - att_iterator_t it; - if (att_find_handle(&it, handle) == 0) { - return setup_error_invalid_handle(response_buffer, request_type, handle); - } - if ((it.flags & (uint16_t)ATT_PROPERTY_WRITE) == 0u) { - return setup_error_write_not_permitted(response_buffer, request_type, handle); - } - if ((it.flags & (uint16_t)ATT_PROPERTY_DYNAMIC) == 0u) { - return setup_error_write_not_permitted(response_buffer, request_type, handle); - } - // check security requirements - int error_code = att_validate_security(att_connection, ATT_WRITE, &it); - if (error_code != 0) { - return setup_error(response_buffer, request_type, handle, error_code); - } - - error_code = (*att_write_callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_ACTIVE, offset, request_buffer + 5u, request_len - 5u); - switch (error_code) { - case 0: - break; - case ATT_ERROR_INVALID_OFFSET: - case ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH: - // postpone to execute write request - att_prepare_write_update_errors(error_code, handle); - break; -#ifdef ENABLE_ATT_DELAYED_RESPONSE - case ATT_ERROR_WRITE_RESPONSE_PENDING: - return ATT_INTERNAL_WRITE_RESPONSE_PENDING; -#endif - default: - return setup_error(response_buffer, request_type, handle, error_code); - } - - // response: echo request - uint16_t bytes_to_echo = btstack_min(request_len, response_buffer_size); - (void)memcpy(response_buffer, request_buffer, bytes_to_echo); - response_buffer[0] = ATT_PREPARE_WRITE_RESPONSE; - return request_len; -} - -/* - @brief transaction queue of prepared writes, e.g., after disconnect -*/ -void att_clear_transaction_queue(att_connection_t * att_connection) { - (*att_write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_CANCEL, 0, NULL, 0); -} - -// MARK: ATT_EXECUTE_WRITE_REQUEST 0x18 -// NOTE: security has been verified by handle_prepare_write_request -static uint16_t handle_execute_write_request(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, - uint8_t * response_buffer, uint16_t response_buffer_size) { - - UNUSED(response_buffer_size); - - uint8_t request_type = ATT_EXECUTE_WRITE_REQUEST; - - if (request_len < 2u) { - return setup_error_invalid_pdu(response_buffer, request_type); - } - - if (att_write_callback == NULL) { - return setup_error_write_not_permitted(response_buffer, request_type, 0); - } - - if (request_buffer[1]) { - // validate queued write - if (att_prepare_write_error_code == 0) { - att_prepare_write_error_code = (*att_write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_VALIDATE, 0, NULL, 0); - } -#ifdef ENABLE_ATT_DELAYED_RESPONSE - if (att_prepare_write_error_code == ATT_ERROR_WRITE_RESPONSE_PENDING) { - return ATT_INTERNAL_WRITE_RESPONSE_PENDING; - } -#endif - // deliver queued errors - if (att_prepare_write_error_code != 0) { - att_clear_transaction_queue(att_connection); - uint8_t error_code = att_prepare_write_error_code; - uint16_t handle = att_prepare_write_error_handle; - att_prepare_write_reset(); - return setup_error(response_buffer, request_type, handle, error_code); - } - att_write_callback(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_EXECUTE, 0, NULL, 0); - } else { - att_clear_transaction_queue(att_connection); - } - response_buffer[0] = ATT_EXECUTE_WRITE_RESPONSE; - return 1; -} - -// MARK: ATT_WRITE_COMMAND 0x52 -// Core 4.0, vol 3, part F, 3.4.5.3 -// "No Error Response or Write Response shall be sent in response to this command" -static void handle_write_command(att_connection_t * att_connection, uint8_t * request_buffer, uint16_t request_len, uint16_t required_flags) { - - if (request_len < 3u) { - return; - } - - uint16_t handle = little_endian_read_16(request_buffer, 1); - if (att_write_callback == NULL) { - return; - } - - att_iterator_t it; - int ok = att_find_handle(&it, handle); - if (!ok) { - return; - } - if ((it.flags & (uint16_t)ATT_PROPERTY_DYNAMIC) == 0u) { - return; - } - if ((it.flags & required_flags) == 0u) { - return; - } - if (att_validate_security(att_connection, ATT_WRITE, &it)) { - return; - } - att_persistent_ccc_cache(&it); - (*att_write_callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_NONE, 0u, request_buffer + 3u, request_len - 3u); -} - -// MARK: helper for ATT_HANDLE_VALUE_NOTIFICATION and ATT_HANDLE_VALUE_INDICATION -static uint16_t prepare_handle_value(att_connection_t * att_connection, - uint16_t handle, - const uint8_t *value, - uint16_t value_len, - uint8_t * response_buffer) { - little_endian_store_16(response_buffer, 1, handle); - uint16_t bytes_to_copy = btstack_min(value_len, att_connection->mtu - 3u); - (void)memcpy(&response_buffer[3], value, bytes_to_copy); - return value_len + 3u; -} - -// MARK: ATT_HANDLE_VALUE_NOTIFICATION 0x1b -uint16_t att_prepare_handle_value_notification(att_connection_t * att_connection, - uint16_t attribute_handle, - const uint8_t *value, - uint16_t value_len, - uint8_t * response_buffer) { - - response_buffer[0] = ATT_HANDLE_VALUE_NOTIFICATION; - return prepare_handle_value(att_connection, attribute_handle, value, value_len, response_buffer); -} - -// MARK: ATT_MULTIPLE_HANDLE_VALUE_NTF 0x23u -uint16_t att_prepare_handle_value_multiple_notification(att_connection_t * att_connection, - uint8_t num_attributes, - const uint16_t * attribute_handles, - const uint8_t ** values_data, - const uint16_t * values_len, - uint8_t * response_buffer) { - - response_buffer[0] = ATT_MULTIPLE_HANDLE_VALUE_NTF; - uint8_t i; - uint16_t offset = 1; - uint16_t response_buffer_size = att_connection->mtu - 3u; - for (i = 0; i < num_attributes; i++) { - uint16_t value_len = values_len[i]; - if ((offset + 4 + value_len) > response_buffer_size) { - break; - } - little_endian_store_16(response_buffer, offset, attribute_handles[i]); - offset += 2; - little_endian_store_16(response_buffer, offset, value_len); - offset += 2; - (void) memcpy(&response_buffer[offset], values_data[i], value_len); - offset += value_len; - } - return offset; -} - -// MARK: ATT_HANDLE_VALUE_INDICATION 0x1d -uint16_t att_prepare_handle_value_indication(att_connection_t * att_connection, - uint16_t attribute_handle, - const uint8_t *value, - uint16_t value_len, - uint8_t * response_buffer) { - - response_buffer[0] = ATT_HANDLE_VALUE_INDICATION; - return prepare_handle_value(att_connection, attribute_handle, value, value_len, response_buffer); -} - -// MARK: Dispatcher -uint16_t att_handle_request(att_connection_t * att_connection, - uint8_t * request_buffer, - uint16_t request_len, - uint8_t * response_buffer) { - uint16_t response_len = 0; - const uint16_t response_buffer_size = att_connection->mtu; - const uint8_t request_opcode = request_buffer[0]; - - switch (request_opcode) { - case ATT_EXCHANGE_MTU_REQUEST: - response_len = handle_exchange_mtu_request(att_connection, request_buffer, request_len, response_buffer); - break; - case ATT_FIND_INFORMATION_REQUEST: - response_len = handle_find_information_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); - break; - case ATT_FIND_BY_TYPE_VALUE_REQUEST: - response_len = handle_find_by_type_value_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); - break; - case ATT_READ_BY_TYPE_REQUEST: - response_len = handle_read_by_type_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); - break; - case ATT_READ_REQUEST: - response_len = handle_read_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); - break; - case ATT_READ_BLOB_REQUEST: - response_len = handle_read_blob_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); - break; - case ATT_READ_MULTIPLE_REQUEST: - response_len = handle_read_multiple_request(att_connection, request_buffer, request_len, response_buffer, - response_buffer_size, false); - break; - case ATT_READ_MULTIPLE_VARIABLE_REQ: - response_len = handle_read_multiple_request(att_connection, request_buffer, request_len, response_buffer, - response_buffer_size, true); - break; - case ATT_READ_BY_GROUP_TYPE_REQUEST: - response_len = handle_read_by_group_type_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); - break; - case ATT_WRITE_REQUEST: - response_len = handle_write_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); - break; - case ATT_PREPARE_WRITE_REQUEST: - response_len = handle_prepare_write_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); - break; - case ATT_EXECUTE_WRITE_REQUEST: - response_len = handle_execute_write_request(att_connection, request_buffer, request_len, response_buffer, response_buffer_size); - break; - case ATT_WRITE_COMMAND: - handle_write_command(att_connection, request_buffer, request_len, ATT_PROPERTY_WRITE_WITHOUT_RESPONSE); - break; -#ifdef ENABLE_LE_SIGNED_WRITE - case ATT_SIGNED_WRITE_COMMAND: - handle_write_command(att_connection, request_buffer, request_len, ATT_PROPERTY_AUTHENTICATED_SIGNED_WRITE); - break; -#endif - default: - response_len = setup_error(response_buffer, request_opcode, 0, ATT_ERROR_REQUEST_NOT_SUPPORTED); - break; - } - return response_len; -} - -// returns 1 if service found. only primary service. -bool gatt_server_get_handle_range_for_service_with_uuid16(uint16_t uuid16, uint16_t * start_handle, uint16_t * end_handle) { - bool in_group = false; - uint16_t prev_handle = 0; - uint16_t service_start = 0; - - uint8_t attribute_value[2]; - int attribute_len = sizeof(attribute_value); - little_endian_store_16(attribute_value, 0, uuid16); - - att_iterator_t it; - att_iterator_init(&it); - while (att_iterator_has_next(&it)) { - att_iterator_fetch_next(&it); - int new_service_started = att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID); - - // close current tag, if within a group and a new service definition starts or we reach end of att db - if (in_group && - ((it.handle == 0u) || new_service_started)) { - in_group = false; - // check range - if ((service_start >= *start_handle) && (prev_handle <= *end_handle)) { - *start_handle = service_start; - *end_handle = prev_handle; - return true; - } - } - - // keep track of previous handle - prev_handle = it.handle; - - // check if found - if ((it.handle != 0u) && new_service_started && (attribute_len == it.value_len) && (memcmp(attribute_value, it.value, it.value_len) == 0)) { - service_start = it.handle; - in_group = true; - } - } - return false; -} - -// returns false if not found -uint16_t gatt_server_get_value_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t uuid16) { - att_iterator_t it; - att_iterator_init(&it); - while (att_iterator_has_next(&it)) { - att_iterator_fetch_next(&it); - if ((it.handle != 0u) && (it.handle < start_handle)) { - continue; - } - if (it.handle > end_handle) { - break; // (1) - } - if (it.handle == 0u) { - break; - } - if (att_iterator_match_uuid16(&it, uuid16)) { - return it.handle; - } - } - return 0; -} - -uint16_t gatt_server_get_descriptor_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t characteristic_uuid16, uint16_t descriptor_uuid16) { - att_iterator_t it; - att_iterator_init(&it); - bool characteristic_found = false; - while (att_iterator_has_next(&it)) { - att_iterator_fetch_next(&it); - if ((it.handle != 0u) && (it.handle < start_handle)) { - continue; - } - if (it.handle > end_handle) { - break; // (1) - } - if (it.handle == 0u) { - break; - } - if (att_iterator_match_uuid16(&it, characteristic_uuid16)) { - characteristic_found = true; - continue; - } - if (att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) - || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID) - || att_iterator_match_uuid16(&it, GATT_CHARACTERISTICS_UUID)) { - if (characteristic_found) { - break; - } - continue; - } - if (characteristic_found && att_iterator_match_uuid16(&it, descriptor_uuid16)) { - return it.handle; - } - } - return 0; -} - -// returns 0 if not found -uint16_t gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t characteristic_uuid16) { - return gatt_server_get_descriptor_handle_for_characteristic_with_uuid16(start_handle, end_handle, characteristic_uuid16, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION); -} -// returns 0 if not found - -uint16_t gatt_server_get_server_configuration_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t characteristic_uuid16) { - return gatt_server_get_descriptor_handle_for_characteristic_with_uuid16(start_handle, end_handle, characteristic_uuid16, GATT_SERVER_CHARACTERISTICS_CONFIGURATION); -} - -// returns true if service found. only primary service. -bool gatt_server_get_handle_range_for_service_with_uuid128(const uint8_t * uuid128, uint16_t * start_handle, uint16_t * end_handle) { - bool in_group = false; - uint16_t prev_handle = 0; - - uint8_t attribute_value[16]; - uint16_t attribute_len = (uint16_t)sizeof(attribute_value); - reverse_128(uuid128, attribute_value); - - att_iterator_t it; - att_iterator_init(&it); - while (att_iterator_has_next(&it)) { - att_iterator_fetch_next(&it); - int new_service_started = att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID); - - // close current tag, if within a group and a new service definition starts or we reach end of att db - if (in_group && - ((it.handle == 0u) || new_service_started)) { - *end_handle = prev_handle; - return true; - } - - // keep track of previous handle - prev_handle = it.handle; - - // check if found - if ((it.handle != 0u) && new_service_started && (attribute_len == it.value_len) && (memcmp(attribute_value, it.value, it.value_len) == 0)) { - *start_handle = it.handle; - in_group = true; - } - } - return false; -} - -// returns 0 if not found -uint16_t gatt_server_get_value_handle_for_characteristic_with_uuid128(uint16_t start_handle, uint16_t end_handle, const uint8_t * uuid128) { - uint8_t attribute_value[16]; - reverse_128(uuid128, attribute_value); - att_iterator_t it; - att_iterator_init(&it); - while (att_iterator_has_next(&it)) { - att_iterator_fetch_next(&it); - if ((it.handle != 0u) && (it.handle < start_handle)) { - continue; - } - if (it.handle > end_handle) { - break; // (1) - } - if (it.handle == 0u) { - break; - } - if (att_iterator_match_uuid(&it, attribute_value, 16)) { - return it.handle; - } - } - return 0; -} - -// returns 0 if not found -uint16_t gatt_server_get_client_configuration_handle_for_characteristic_with_uuid128(uint16_t start_handle, uint16_t end_handle, const uint8_t * uuid128) { - uint8_t attribute_value[16]; - reverse_128(uuid128, attribute_value); - att_iterator_t it; - att_iterator_init(&it); - int characteristic_found = 0; - while (att_iterator_has_next(&it)) { - att_iterator_fetch_next(&it); - if ((it.handle != 0u) && (it.handle < start_handle)) { - continue; - } - if (it.handle > end_handle) { - break; // (1) - } - if (it.handle == 0u) { - break; - } - if (att_iterator_match_uuid(&it, attribute_value, 16)) { - characteristic_found = 1; - continue; - } - if (att_iterator_match_uuid16(&it, GATT_PRIMARY_SERVICE_UUID) - || att_iterator_match_uuid16(&it, GATT_SECONDARY_SERVICE_UUID) - || att_iterator_match_uuid16(&it, GATT_CHARACTERISTICS_UUID)) { - if (characteristic_found) { - break; - } - continue; - } - if (characteristic_found && att_iterator_match_uuid16(&it, GATT_CLIENT_CHARACTERISTICS_CONFIGURATION)) { - return it.handle; - } - } - return 0; -} - - -bool gatt_server_get_included_service_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t uuid16, - uint16_t * out_included_service_handle, uint16_t * out_included_service_start_handle, uint16_t * out_included_service_end_handle) { - - att_iterator_t it; - att_iterator_init(&it); - while (att_iterator_has_next(&it)) { - att_iterator_fetch_next(&it); - if ((it.handle != 0u) && (it.handle < start_handle)) { - continue; - } - if (it.handle > end_handle) { - break; // (1) - } - if (it.handle == 0u) { - break; - } - if ((it.value_len == 6) && (att_iterator_match_uuid16(&it, GATT_INCLUDE_SERVICE_UUID))) { - if (little_endian_read_16(it.value, 4) == uuid16) { - *out_included_service_handle = it.handle; - *out_included_service_start_handle = little_endian_read_16(it.value, 0); - *out_included_service_end_handle = little_endian_read_16(it.value, 2); - return true; - } - } - } - return false; -} - -// 1-item cache to optimize query during write_callback -static void att_persistent_ccc_cache(att_iterator_t * it) { - att_persistent_ccc_handle = it->handle; - if (it->flags & (uint16_t)ATT_PROPERTY_UUID128) { - att_persistent_ccc_uuid16 = 0u; - } else { - att_persistent_ccc_uuid16 = little_endian_read_16(it->uuid, 0); - } -} - -bool att_is_persistent_ccc(uint16_t handle) { - if (handle != att_persistent_ccc_handle) { - att_iterator_t it; - int ok = att_find_handle(&it, handle); - if (!ok) { - return false; - } - att_persistent_ccc_cache(&it); - } - switch (att_persistent_ccc_uuid16) { - case GATT_CLIENT_CHARACTERISTICS_CONFIGURATION: - case GATT_CLIENT_SUPPORTED_FEATURES: - return true; - default: - return false; - } -} - -// att_read_callback helpers -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) { - btstack_assert(blob != NULL); - - if (buffer != NULL) { - uint16_t bytes_to_copy = 0; - if (blob_size >= offset) { - bytes_to_copy = btstack_min(blob_size - offset, buffer_size); - (void)memcpy(buffer, &blob[offset], bytes_to_copy); - } - return bytes_to_copy; - } else { - return blob_size; - } -} - -uint16_t att_read_callback_handle_little_endian_32(uint32_t value, uint16_t offset, uint8_t * buffer, uint16_t buffer_size) { - uint8_t value_buffer[4]; - little_endian_store_32(value_buffer, 0, value); - return att_read_callback_handle_blob(value_buffer, sizeof(value_buffer), offset, buffer, buffer_size); -} - -uint16_t att_read_callback_handle_little_endian_16(uint16_t value, uint16_t offset, uint8_t * buffer, uint16_t buffer_size) { - uint8_t value_buffer[2]; - little_endian_store_16(value_buffer, 0, value); - return att_read_callback_handle_blob(value_buffer, sizeof(value_buffer), offset, buffer, buffer_size); -} - -uint16_t att_read_callback_handle_byte(uint8_t value, uint16_t offset, uint8_t * buffer, uint16_t buffer_size) { - uint8_t value_buffer[1]; - value_buffer[0] = value; - return att_read_callback_handle_blob(value_buffer, sizeof(value_buffer), offset, buffer, buffer_size); -} - - -#ifdef ENABLE_BTP - -// start of auto-PTS testing code, not used in production -// LCOV_EXCL_START -#include "btp.h" - -static uint8_t btp_permissions_for_flags(uint16_t flags) { - - // see BT_GATT_PERM_* - // https://docs.zephyrproject.org/latest/reference/bluetooth/gatt.html - // set bit indicates requirement, e.g. BTP_GATT_PERM_READ_AUTHN requires authenticated connection - - uint8_t permissions = 0; - - uint8_t read_security_level = 0; - uint8_t write_security_level = 0; - if (flags & (uint16_t)ATT_PROPERTY_READ) { - if (flags & (uint16_t)ATT_PROPERTY_READ_PERMISSION_BIT_0) { - read_security_level |= 1; - } - if (flags & (uint16_t)ATT_PROPERTY_READ_PERMISSION_BIT_1) { - read_security_level |= 2; - } - if (read_security_level == ATT_SECURITY_AUTHORIZED) { - permissions |= BTP_GATT_PERM_READ_AUTHZ; - } - if (read_security_level == ATT_SECURITY_AUTHENTICATED) { - permissions |= BTP_GATT_PERM_READ_AUTHN; - } - if (read_security_level == ATT_SECURITY_ENCRYPTED) { - permissions |= BTP_GATT_PERM_READ_ENC; - } - if (read_security_level == ATT_SECURITY_NONE) { - permissions |= BTP_GATT_PERM_READ; - } - } - if (flags & (ATT_PROPERTY_WRITE | ATT_PROPERTY_WRITE_WITHOUT_RESPONSE)) { - if (flags & (uint16_t)ATT_PROPERTY_WRITE_PERMISSION_BIT_0) { - write_security_level |= 1; - } - if (flags & (uint16_t)ATT_PROPERTY_WRITE_PERMISSION_BIT_1) { - write_security_level |= 2; - } - if (write_security_level == ATT_SECURITY_AUTHORIZED) { - permissions |= BTP_GATT_PERM_WRITE_AUTHZ; - } - if (write_security_level == ATT_SECURITY_AUTHENTICATED) { - permissions |= BTP_GATT_PERM_WRITE_AUTHN; - } - if (write_security_level == ATT_SECURITY_ENCRYPTED) { - permissions |= BTP_GATT_PERM_WRITE_ENC; - } - if (write_security_level == ATT_SECURITY_NONE) { - permissions |= BTP_GATT_PERM_WRITE; - } - } - return permissions; -} - -uint16_t btp_att_get_attributes_by_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t uuid16, uint8_t * response_buffer, uint16_t response_buffer_size) { - log_info("btp_att_get_attributes_by_uuid16 %04x from 0x%04x to 0x%04x, db %p", uuid16, start_handle, end_handle, att_database); - att_dump_attributes(); - - uint8_t num_attributes = 0; - uint16_t pos = 1; - - att_iterator_t it; - att_iterator_init(&it); - while (att_iterator_has_next(&it) && ((pos + 6) < response_buffer_size)) { - att_iterator_fetch_next(&it); - log_info("handle %04x", it.handle); - if (it.handle == 0) { - break; - } - if (it.handle < start_handle) { - continue; - } - if (it.handle > end_handle) { - break; - } - if ((uuid16 == 0) || att_iterator_match_uuid16(&it, uuid16)) { - little_endian_store_16(response_buffer, pos, it.handle); - pos += 2; - response_buffer[pos++] = btp_permissions_for_flags(it.flags); - response_buffer[pos++] = 2; - little_endian_store_16(response_buffer, pos, uuid16); - pos += 2; - num_attributes++; - } - } - response_buffer[0] = num_attributes; - return pos; -} - -uint16_t btp_att_get_attributes_by_uuid128(uint16_t start_handle, uint16_t end_handle, const uint8_t * uuid128, uint8_t * response_buffer, uint16_t response_buffer_size) { - uint8_t num_attributes = 0; - uint16_t pos = 1; - att_iterator_t it; - att_iterator_init(&it); - while (att_iterator_has_next(&it) && ((pos + 20) < response_buffer_size)) { - att_iterator_fetch_next(&it); - if (it.handle == 0) { - break; - } - if (it.handle < start_handle) { - continue; - } - if (it.handle > end_handle) { - break; - } - if (att_iterator_match_uuid(&it, (uint8_t*) uuid128, 16)) { - little_endian_store_16(response_buffer, pos, it.handle); - pos += 2; - response_buffer[pos++] = btp_permissions_for_flags(it.flags); - response_buffer[pos++] = 16; - reverse_128(uuid128, &response_buffer[pos]); - pos += 16; - num_attributes++; - } - } - response_buffer[0] = num_attributes; - return pos; -} - -uint16_t btp_att_get_attribute_value(att_connection_t * att_connection, uint16_t attribute_handle, uint8_t * response_buffer, uint16_t response_buffer_size) { - att_iterator_t it; - int ok = att_find_handle(&it, attribute_handle); - if (!ok) { - return 0; - } - - uint16_t pos = 0; - // field: ATT_Response - simulate READ operation on given connection - response_buffer[pos++] = att_validate_security(att_connection, ATT_READ, &it); - // fetch len - // assume: con handle not relevant here, else, it needs to get passed in - // att_update_value_len(&it, HCI_CON_HANDLE_INVALID); - uint16_t bytes_to_copy = btstack_min(response_buffer_size - 3, it.value_len); - little_endian_store_16(response_buffer, pos, bytes_to_copy); - pos += 2; - // get value - only works for non-dynamic data - if (it.value) { - memcpy(&response_buffer[pos], it.value, bytes_to_copy); - pos += bytes_to_copy; - } - return pos; -} -// LCOV_EXCL_STOP -#endif - -#endif diff --git a/cores/rp2040/sdkoverride/att_db.h b/cores/rp2040/sdkoverride/att_db.h deleted file mode 100644 index f7b0880d3..000000000 --- a/cores/rp2040/sdkoverride/att_db.h +++ /dev/null @@ -1,443 +0,0 @@ -/* - Copyright (C) 2014 BlueKitchen GmbH - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the names of - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - 4. Any redistribution, use, or modification is done solely for - personal benefit and not for any commercial purpose or for - monetary gain. - - THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN - GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - Please inquire about commercial licensing options at - contact@bluekitchen-gmbh.com - -*/ - -/** - @title ATT Database Engine - -*/ - -#ifndef ATT_DB_H -#define ATT_DB_H - -#if defined ENABLE_CLASSIC - -#include -#include -#include "btstack_linked_list.h" -#include "btstack_defines.h" -#include "btstack_bool.h" - -#if defined __cplusplus -extern "C" { -#endif - - // MARK: Attribute PDU Opcodes -#define ATT_ERROR_RESPONSE 0x01u - -#define ATT_EXCHANGE_MTU_REQUEST 0x02u -#define ATT_EXCHANGE_MTU_RESPONSE 0x03u - -#define ATT_FIND_INFORMATION_REQUEST 0x04u -#define ATT_FIND_INFORMATION_REPLY 0x05u -#define ATT_FIND_BY_TYPE_VALUE_REQUEST 0x06u -#define ATT_FIND_BY_TYPE_VALUE_RESPONSE 0x07u - -#define ATT_READ_BY_TYPE_REQUEST 0x08u -#define ATT_READ_BY_TYPE_RESPONSE 0x09u -#define ATT_READ_REQUEST 0x0au -#define ATT_READ_RESPONSE 0x0bu -#define ATT_READ_BLOB_REQUEST 0x0cu -#define ATT_READ_BLOB_RESPONSE 0x0du -#define ATT_READ_MULTIPLE_REQUEST 0x0eu -#define ATT_READ_MULTIPLE_RESPONSE 0x0fu -#define ATT_READ_BY_GROUP_TYPE_REQUEST 0x10u -#define ATT_READ_BY_GROUP_TYPE_RESPONSE 0x11u - -#define ATT_WRITE_REQUEST 0x12u -#define ATT_WRITE_RESPONSE 0x13u - -#define ATT_PREPARE_WRITE_REQUEST 0x16u -#define ATT_PREPARE_WRITE_RESPONSE 0x17u -#define ATT_EXECUTE_WRITE_REQUEST 0x18u -#define ATT_EXECUTE_WRITE_RESPONSE 0x19u - -#define ATT_HANDLE_VALUE_NOTIFICATION 0x1bu -#define ATT_HANDLE_VALUE_INDICATION 0x1du -#define ATT_HANDLE_VALUE_CONFIRMATION 0x1eu - -#define ATT_READ_MULTIPLE_VARIABLE_REQ 0x20u -#define ATT_READ_MULTIPLE_VARIABLE_RSP 0x21u -#define ATT_MULTIPLE_HANDLE_VALUE_NTF 0x23u - -#define ATT_WRITE_COMMAND 0x52u -#define ATT_SIGNED_WRITE_COMMAND 0xD2u - - - // internal additions - // 128 bit UUID used -#define ATT_PROPERTY_UUID128 0x200u - // Read/Write Permission bits -#define ATT_PROPERTY_READ_PERMISSION_BIT_0 0x0400u -#define ATT_PROPERTY_READ_PERMISSION_BIT_1 0x0800u -#define ATT_PROPERTY_WRITE_PERMISSION_BIT_0 0x0001u -#define ATT_PROPERTY_WRITE_PERMISSION_BIT_1 0x0010u -#define ATT_PROPERTY_READ_PERMISSION_SC 0x0020u -#define ATT_PROPERTY_WRITE_PERMISSION_SC 0x0080u - - - typedef struct att_connection { - hci_con_handle_t con_handle; - uint16_t mtu; // initialized to ATT_DEFAULT_MTU (23), negotiated during MTU exchange - uint16_t max_mtu; // local maximal L2CAP_MTU, set to l2cap_max_le_mtu() - bool mtu_exchanged; - uint8_t encryption_key_size; - uint8_t authenticated; - uint8_t authorized; - uint8_t secure_connection; - } att_connection_t; - - /* API_START */ - - // map ATT ERROR CODES on to att_read_callback length -#define ATT_READ_ERROR_CODE_OFFSET 0xfe00u - - // custom BTstack ATT Response Pending for att_read_callback -#define ATT_READ_RESPONSE_PENDING 0xffffu - - // internally used to signal write response pending -#define ATT_INTERNAL_WRITE_RESPONSE_PENDING 0xfffeu - - /** - @brief ATT Client Read Callback for Dynamic Data - - if buffer == NULL, don't copy data, just return size of value - - if buffer != NULL, copy data and return number bytes copied - If ENABLE_ATT_DELAYED_READ_RESPONSE is defined, you may return ATT_READ_RESPONSE_PENDING if data isn't available yet - @param con_handle of hci le connection - @param attribute_handle to be read - @param offset defines start of attribute value - @param buffer - @param buffer_size - @return size of value if buffer is NULL, otherwise number of bytes copied - */ - typedef uint16_t (*att_read_callback_t)(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size); - - /** - @brief ATT Client Write Callback for Dynamic Data - Each Prepared Write Request triggers a callback with transaction mode ATT_TRANSACTION_MODE_ACTIVE. - On Execute Write, the callback will be called with ATT_TRANSACTION_MODE_VALIDATE and allows to validate all queued writes and return an application error. - If none of the registered callbacks return an error for ATT_TRANSACTION_MODE_VALIDATE and the callback will be called with ATT_TRANSACTION_MODE_EXECUTE. - Otherwise, all callbacks will be called with ATT_TRANSACTION_MODE_CANCEL. - - If the additional validation step is not needed, just return 0 for all callbacks with transaction mode ATT_TRANSACTION_MODE_VALIDATE. - - @param con_handle of hci le connection - @param attribute_handle to be written - @param transaction - ATT_TRANSACTION_MODE_NONE for regular writes. For prepared writes: ATT_TRANSACTION_MODE_ACTIVE, ATT_TRANSACTION_MODE_VALIDATE, ATT_TRANSACTION_MODE_EXECUTE, ATT_TRANSACTION_MODE_CANCEL - @param offset into the value - used for queued writes and long attributes - @param buffer - @param buffer_size - @param signature used for signed write commands - @return 0 if write was ok, ATT_ERROR_PREPARE_QUEUE_FULL if no space in queue, ATT_ERROR_INVALID_OFFSET if offset is larger than max buffer - */ - typedef int (*att_write_callback_t)(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size); - - // Read & Write Callbacks for handle range - typedef struct att_service_handler { - btstack_linked_item_t * item; - uint16_t start_handle; - uint16_t end_handle; - att_read_callback_t read_callback; - att_write_callback_t write_callback; - btstack_packet_handler_t packet_handler; - } att_service_handler_t; - - // MARK: ATT Operations - - /** - @brief setup ATT database - @param db - */ - void att_set_db(uint8_t const * db); - - /* - @brief set callback for read of dynamic attributes - @param callback - */ - void att_set_read_callback(att_read_callback_t callback); - - /** - @brief set callback for write of dynamic attributes - @param callback - */ - void att_set_write_callback(att_write_callback_t callback); - - /** - @brief debug helper, dump ATT database to stdout using log_info - */ - void att_dump_attributes(void); - - /** - @brief process ATT request against database and put response into response buffer - @param att_connection used for mtu and security properties - @param request_buffer, request_len: ATT request from client - @param response_buffer for result - @return len of data in response buffer. 0 = no response, - ATT_READ_RESPONSE_PENDING if it was returned at least once for dynamic data (requires ENABLE_ATT_DELAYED_READ_RESPONSE) - */ - uint16_t att_handle_request(att_connection_t * att_connection, - uint8_t * request_buffer, - uint16_t request_len, - uint8_t * response_buffer); - - /** - @brief setup value notification in response buffer for a given handle and value - @param att_connection - @param attribute_handle - @param value - @param value_len - @param response_buffer for notification - */ - uint16_t att_prepare_handle_value_notification(att_connection_t * att_connection, - uint16_t attribute_handle, - const uint8_t *value, - uint16_t value_len, - uint8_t * response_buffer); - - /** - @brief setup value notification in response buffer for multiple handles and values - @param att_connection - @param attribute_handle - @param value - @param value_len - @param response_buffer for notification - */ - uint16_t att_prepare_handle_value_multiple_notification(att_connection_t * att_connection, - uint8_t num_attributes, - const uint16_t * attribute_handles, - const uint8_t ** values_data, - const uint16_t * values_len, - uint8_t * response_buffer); - - /** - @brief setup value indication in response buffer for a given handle and value - @param att_connection - @param attribute_handle - @param value - @param value_len - @param response_buffer for indication - */ - uint16_t att_prepare_handle_value_indication(att_connection_t * att_connection, - uint16_t attribute_handle, - const uint8_t *value, - uint16_t value_len, - uint8_t * response_buffer); - - /** - @brief transaction queue of prepared writes, e.g., after disconnect - @return att_connection - */ - void att_clear_transaction_queue(att_connection_t * att_connection); - - // att_read_callback helpers for a various data types - - /** - @brief Handle read of blob like data for att_read_callback - @param blob of data - @param blob_size of blob - @param offset from att_read_callback - @param buffer from att_read_callback - @param buffer_size from att_read_callback - @return value size for buffer == 0 and num bytes copied otherwise - */ - 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); - - /** - @brief Handle read of little endian unsigned 32 bit value for att_read_callback - @param value - @param offset from att_read_callback - @param buffer from att_read_callback - @param buffer_size from att_read_callback - @return value size for buffer == 0 and num bytes copied otherwise - */ - uint16_t att_read_callback_handle_little_endian_32(uint32_t value, uint16_t offset, uint8_t * buffer, uint16_t buffer_size); - - /** - @brief Handle read of little endian unsigned 16 bit value for att_read_callback - @param value - @param offset from att_read_callback - @param buffer from att_read_callback - @param buffer_size from att_read_callback - @return value size for buffer == 0 and num bytes copied otherwise - */ - uint16_t att_read_callback_handle_little_endian_16(uint16_t value, uint16_t offset, uint8_t * buffer, uint16_t buffer_size); - - /** - @brief Handle read of single byte for att_read_callback - @param blob of data - @param blob_size of blob - @param offset from att_read_callback - @param buffer from att_read_callback - @param buffer_size from att_read_callback - @return value size for buffer == 0 and num bytes copied otherwise - */ - uint16_t att_read_callback_handle_byte(uint8_t value, uint16_t offset, uint8_t * buffer, uint16_t buffer_size); - - - // experimental client API - /** - @brief Get UUID for handle - @param attribute_handle - @return 0 if not found - */ - uint16_t att_uuid_for_handle(uint16_t attribute_handle); - - /** - @brief Get const value for handle - @param attribute_handle - @param out_value_len output variable that hold value len - @return value - */ - - const uint8_t * gatt_server_get_const_value_for_handle(uint16_t attribute_handle, uint16_t * out_value_len); - - // experimental GATT Server API - - /** - @brief Get handle range for primary service. - @param uuid16 - @param start_handle - @param end_handle - @return false if not found - */ - bool gatt_server_get_handle_range_for_service_with_uuid16(uint16_t uuid16, uint16_t * start_handle, uint16_t * end_handle); - - /** - @brief Get handle range for included service. - @param start_handle - @param end_handle - @param uuid16 - @param out_included_service_handle - @param out_included_service_start_handle - @param out_included_service_end_handle - @return false if not found - */ - bool gatt_server_get_included_service_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t uuid16, - uint16_t * out_included_service_handle, uint16_t * out_included_service_start_handle, uint16_t * out_included_service_end_handle); - - /** - @brief Get value handle for characteristic. - @param start_handle - @param end_handle - @param uuid16 - @return 0 if not found - */ - uint16_t gatt_server_get_value_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t uuid16); - - /** - @brief Get descriptor handle for characteristic. - @param start_handle - @param end_handle - @param characteristic_uuid16 - @param descriptor_uuid16 - @return 0 if not found - */ - uint16_t gatt_server_get_descriptor_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t characteristic_uuid16, uint16_t descriptor_uuid16); - - /** - @brief Get client configuration handle for characteristic. - @param start_handle - @param end_handle - @param characteristic_uuid16 - @return 0 if not found - */ - uint16_t gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t characteristic_uuid16); - - /** - @brief Get server configuration handle for characteristic. - @param start_handle - @param end_handle - @param characteristic_uuid16 - @param descriptor_uuid16 - @return 0 if not found - */ - uint16_t gatt_server_get_server_configuration_handle_for_characteristic_with_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t characteristic_uuid16); - - - /** - @brief Get handle range for primary service. - @param uuid128 - @param start_handle - @param end_handle - @return false if not found - */ - bool gatt_server_get_handle_range_for_service_with_uuid128(const uint8_t * uuid128, uint16_t * start_handle, uint16_t * end_handle); - - /** - @brief Get value handle. - @param start_handle - @param end_handle - @param uuid128 - @return 0 if not found - */ - uint16_t gatt_server_get_value_handle_for_characteristic_with_uuid128(uint16_t start_handle, uint16_t end_handle, const uint8_t * uuid128); - - /** - @brief Get client configuration handle. - @param start_handle - @param end_handle - @param uuid128 - @return 0 if not found - */ - uint16_t gatt_server_get_client_configuration_handle_for_characteristic_with_uuid128(uint16_t start_handle, uint16_t end_handle, const uint8_t * uuid128); - - /* API_END */ - - // non-user functionality for att_server - - /** - @brief Check if writes to handle should be persistent - @param handle - @return 1 if persistent - */ - bool att_is_persistent_ccc(uint16_t handle); - - - - // auto-pts testing, returns response size -#ifdef ENABLE_BTP - uint16_t btp_att_get_attributes_by_uuid16(uint16_t start_handle, uint16_t end_handle, uint16_t uuid16, uint8_t * response_buffer, uint16_t response_buffer_size); - uint16_t btp_att_get_attributes_by_uuid128(uint16_t start_handle, uint16_t end_handle, const uint8_t * uuid128, uint8_t * response_buffer, uint16_t response_buffer_size); - uint16_t btp_att_get_attribute_value(att_connection_t * att_connection, uint16_t attribute_handle, uint8_t * response_buffer, uint16_t response_buffer_size); -#endif - -#if defined __cplusplus -} -#endif - -#endif - -#endif // ATT_H diff --git a/cores/rp2040/sdkoverride/bluetooth.h b/cores/rp2040/sdkoverride/bluetooth.h deleted file mode 100644 index d27835e5b..000000000 --- a/cores/rp2040/sdkoverride/bluetooth.h +++ /dev/null @@ -1,926 +0,0 @@ -/* - Copyright (C) 2015 BlueKitchen GmbH - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the names of - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - 4. Any redistribution, use, or modification is done solely for - personal benefit and not for any commercial purpose or for - monetary gain. - - THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN - GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - Please inquire about commercial licensing options at - contact@bluekitchen-gmbh.com - -*/ - -/* - bluetooth.h - - Numbers defined or derived from the official Bluetooth specification -*/ - -#ifndef BLUETOOTH_H -#define BLUETOOTH_H - -#include - -/** - @brief hci connection handle type -*/ -typedef uint16_t hci_con_handle_t; - -/** - @brief Length of a bluetooth device address. -*/ -#define BD_ADDR_LEN 6 - -/** - @brief Bluetooth address -*/ -typedef uint8_t bd_addr_t[BD_ADDR_LEN]; - -/** - Address types -*/ -typedef enum { - // Public Device Address - BD_ADDR_TYPE_LE_PUBLIC = 0, - // Random Device Address - BD_ADDR_TYPE_LE_RANDOM = 1, - // Public Identity Address (Corresponds to Resolved Private Address) - BD_ADDR_TYPE_LE_PUBLIC_IDENTITY = 2, - // Random (static) Identity Address (Corresponds to Resolved Private Address) - BD_ADDR_TYPE_LE_RANDOM_IDENTITY = 3, - // internal BTstack addr types for Classic connections - BD_ADDR_TYPE_SCO = 0xfc, - BD_ADDR_TYPE_ACL = 0xfd, - BD_ADDR_TYPE_UNKNOWN = 0xfe, // also used as 'invalid' -} bd_addr_type_t; - -/** - Link types for BR/EDR Connections -*/ -typedef enum { - HCI_LINK_TYPE_SCO = 0, - HCI_LINK_TYPE_ACL = 1, - HCI_LINK_TYPE_ESCO = 2, -} hci_link_type_t; - - -/** - @brief link key -*/ -#define LINK_KEY_LEN 16 -#define LINK_KEY_STR_LEN (LINK_KEY_LEN*2) -typedef uint8_t link_key_t[LINK_KEY_LEN]; - -/** - @brief link key type -*/ -typedef enum { - INVALID_LINK_KEY = 0xffff, - COMBINATION_KEY = 0, // standard pairing - LOCAL_UNIT_KEY, // ? - REMOTE_UNIT_KEY, // ? - DEBUG_COMBINATION_KEY, // SSP with debug - UNAUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P192, // SSP Simple Pairing - AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P192, // SSP Passkey, Number confirm, OOB - CHANGED_COMBINATION_KEY, // Link key changed using Change Connection Lnk Key - UNAUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256, // SSP Simpe Pairing - AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256, // SSP Passkey, Number confirm, OOB -} link_key_type_t; - -/** - LE Privacy 1.2 -*/ -typedef enum { - LE_PRIVACY_MODE_NETWORK = 0, - LE_PRIVACY_MODE_DEVICE = 1, -} le_privacy_mode_t; - -/** - @brief Extended Inquiry Response -*/ -#define EXTENDED_INQUIRY_RESPONSE_DATA_LEN 240 - -/** - @brief Inquiry modes -*/ -typedef enum { - INQUIRY_MODE_STANDARD = 0, - INQUIRY_MODE_RSSI, - INQUIRY_MODE_RSSI_AND_EIR, -} inquiry_mode_t; - -/** - @brief Page Scan Types -*/ -typedef enum { - PAGE_SCAN_MODE_STANDARD = 0, - PAGE_SCAN_MODE_INTERLACED, -} page_scan_type_t; - -/** - @brief Inquiry Scan Types -*/ -typedef enum { - INQUIRY_SCAN_MODE_STANDARD = 0, - INQUIRY_SCAN_MODE_INTERLACED, -} inquiry_scan_type_t; - -/** - Link Supervision Timeout Default, 0x7d00 * 0.625ms = 20s -*/ -#define HCI_LINK_SUPERVISION_TIMEOUT_DEFAULT 0x7D00 - -/** - Service Type used for QoS Setup and Flow Specification -*/ -typedef enum { - HCI_SERVICE_TYPE_NO_TRAFFIC = 0, - HCI_SERVICE_TYPE_BEST_EFFORT, - HCI_SERVICE_TYPE_GUARANTEED, - HCI_SERVICE_TYPE_INVALID, -} hci_service_type_t; - -/** - HCI Transport -*/ - -/** - packet types - used in BTstack and over the H4 UART interface -*/ -#define HCI_COMMAND_DATA_PACKET 0x01 -#define HCI_ACL_DATA_PACKET 0x02 -#define HCI_SCO_DATA_PACKET 0x03 -#define HCI_EVENT_PACKET 0x04 -#define HCI_ISO_DATA_PACKET 0x05 - -/** - Other assigned numbers, Assigned_Numbers_Host Controller Interface.pdf -*/ - -typedef enum { - HCI_AUDIO_CODING_FORMAT_U_LAW_LOG = 0x00, - HCI_AUDIO_CODING_FORMAT_A_LAW_LOG, - HCI_AUDIO_CODING_FORMAT_CVSD, - HCI_AUDIO_CODING_FORMAT_TRANSPARENT, // Indicates that the controller does not do any transcoding or resampling. This is also used for test mode. - HCI_AUDIO_CODING_FORMAT_LINEAR_PCM, - HCI_AUDIO_CODING_FORMAT_MSBC, - HCI_AUDIO_CODING_FORMAT_LC3, - HCI_AUDIO_CODING_FORMAT_G_729A, - HCI_AUDIO_CODING_FORMAT_RFU, - HCI_AUDIO_CODING_FORMAT_VENDOR_SPECIFIC = 0xFF -} hci_audio_coding_format_t; - -/** - HCI Layer -*/ - -// -// Error Codes rfom Bluetooth Core Specification -// - -/* ENUM_START: BLUETOOTH_ERROR_CODE */ -#define ERROR_CODE_SUCCESS 0x00 -#define ERROR_CODE_UNKNOWN_HCI_COMMAND 0x01 -#define ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER 0x02 -#define ERROR_CODE_HARDWARE_FAILURE 0x03 -#define ERROR_CODE_PAGE_TIMEOUT 0x04 -#define ERROR_CODE_AUTHENTICATION_FAILURE 0x05 -#define ERROR_CODE_PIN_OR_KEY_MISSING 0x06 -#define ERROR_CODE_MEMORY_CAPACITY_EXCEEDED 0x07 -#define ERROR_CODE_CONNECTION_TIMEOUT 0x08 -#define ERROR_CODE_CONNECTION_LIMIT_EXCEEDED 0x09 -#define ERROR_CODE_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED 0x0A -#define ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS 0x0B -#define ERROR_CODE_COMMAND_DISALLOWED 0x0C -#define ERROR_CODE_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES 0x0D -#define ERROR_CODE_CONNECTION_REJECTED_DUE_TO_SECURITY_REASONS 0x0E -#define ERROR_CODE_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR 0x0F -#define ERROR_CODE_CONNECTION_ACCEPT_TIMEOUT_EXCEEDED 0x10 -#define ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE 0x11 -#define ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS 0x12 -#define ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION 0x13 -#define ERROR_CODE_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES 0x14 -#define ERROR_CODE_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_POWER_OFF 0x15 -#define ERROR_CODE_CONNECTION_TERMINATED_BY_LOCAL_HOST 0x16 -#define ERROR_CODE_REPEATED_ATTEMPTS 0x17 -#define ERROR_CODE_PAIRING_NOT_ALLOWED 0x18 -#define ERROR_CODE_UNKNOWN_LMP_PDU 0x19 -#define ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE_UNSUPPORTED_LMP_FEATURE 0x1A -#define ERROR_CODE_SCO_OFFSET_REJECTED 0x1B -#define ERROR_CODE_SCO_INTERVAL_REJECTED 0x1C -#define ERROR_CODE_SCO_AIR_MODE_REJECTED 0x1D -#define ERROR_CODE_INVALID_LMP_PARAMETERS_INVALID_LL_PARAMETERS 0x1E -#define ERROR_CODE_UNSPECIFIED_ERROR 0x1F -#define ERROR_CODE_UNSUPPORTED_LMP_PARAMETER_VALUE_UNSUPPORTED_LL_PARAMETER_VALUE 0x20 -#define ERROR_CODE_ROLE_CHANGE_NOT_ALLOWED 0x21 -#define ERROR_CODE_LMP_RESPONSE_TIMEOUT_LL_RESPONSE_TIMEOUT 0x22 -#define ERROR_CODE_LMP_ERROR_TRANSACTION_COLLISION 0x23 -#define ERROR_CODE_LMP_PDU_NOT_ALLOWED 0x24 -#define ERROR_CODE_ENCRYPTION_MODE_NOT_ACCEPTABLE 0x25 -#define ERROR_CODE_LINK_KEY_CANNOT_BE_CHANGED 0x26 -#define ERROR_CODE_REQUESTED_QOS_NOT_SUPPORTED 0x27 -#define ERROR_CODE_INSTANT_PASSED 0x28 -#define ERROR_CODE_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED 0x29 -#define ERROR_CODE_DIFFERENT_TRANSACTION_COLLISION 0x2A -#define ERROR_CODE_RESERVED 0x2B -#define ERROR_CODE_QOS_UNACCEPTABLE_PARAMETER 0x2C -#define ERROR_CODE_QOS_REJECTED 0x2D -#define ERROR_CODE_CHANNEL_CLASSIFICATION_NOT_SUPPORTED 0x2E -#define ERROR_CODE_INSUFFICIENT_SECURITY 0x2F -#define ERROR_CODE_PARAMETER_OUT_OF_MANDATORY_RANGE 0x30 -// #define ERROR_CODE_RESERVED -#define ERROR_CODE_ROLE_SWITCH_PENDING 0x32 -// #define ERROR_CODE_RESERVED -#define ERROR_CODE_RESERVED_SLOT_VIOLATION 0x34 -#define ERROR_CODE_ROLE_SWITCH_FAILED 0x35 -#define ERROR_CODE_EXTENDED_INQUIRY_RESPONSE_TOO_LARGE 0x36 -#define ERROR_CODE_SECURE_SIMPLE_PAIRING_NOT_SUPPORTED_BY_HOST 0x37 -#define ERROR_CODE_HOST_BUSY_PAIRING 0x38 -#define ERROR_CODE_CONNECTION_REJECTED_DUE_TO_NO_SUITABLE_CHANNEL_FOUND 0x39 -#define ERROR_CODE_CONTROLLER_BUSY 0x3A -#define ERROR_CODE_UNACCEPTABLE_CONNECTION_PARAMETERS 0x3B -#define ERROR_CODE_DIRECTED_ADVERTISING_TIMEOUT 0x3C -#define ERROR_CODE_CONNECTION_TERMINATED_DUE_TO_MIC_FAILURE 0x3D -#define ERROR_CODE_CONNECTION_FAILED_TO_BE_ESTABLISHED 0x3E -#define ERROR_CODE_MAC_CONNECTION_FAILED 0x3F -#define ERROR_CODE_COARSE_CLOCK_ADJUSTMENT_REJECTED_BUT_WILL_TRY_TO_ADJUST_USING_CLOCK_DRAGGING 0x40 - -// BTstack defined ERRORS, mapped into BLuetooth status code range - -#define BTSTACK_CONNECTION_TO_BTDAEMON_FAILED 0x50 -#define BTSTACK_ACTIVATION_FAILED_SYSTEM_BLUETOOTH 0x51 -#define BTSTACK_ACTIVATION_POWERON_FAILED 0x52 -#define BTSTACK_ACTIVATION_FAILED_UNKNOWN 0x53 -#define BTSTACK_NOT_ACTIVATED 0x54 -#define BTSTACK_BUSY 0x55 -#define BTSTACK_MEMORY_ALLOC_FAILED 0x56 -#define BTSTACK_ACL_BUFFERS_FULL 0x57 - -// l2cap errors - enumeration by the command that created them -#define L2CAP_COMMAND_REJECT_REASON_COMMAND_NOT_UNDERSTOOD 0x60 -#define L2CAP_COMMAND_REJECT_REASON_SIGNALING_MTU_EXCEEDED 0x61 -#define L2CAP_COMMAND_REJECT_REASON_INVALID_CID_IN_REQUEST 0x62 - -#define L2CAP_CONNECTION_RESPONSE_RESULT_SUCCESSFUL 0x63 -#define L2CAP_CONNECTION_RESPONSE_RESULT_PENDING 0x64 -#define L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_PSM 0x65 -#define L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_SECURITY 0x66 -#define L2CAP_CONNECTION_RESPONSE_RESULT_REFUSED_RESOURCES 0x67 -#define L2CAP_CONNECTION_RESPONSE_RESULT_ERTM_NOT_SUPPORTED 0x68 - -// should be L2CAP_CONNECTION_RTX_TIMEOUT -#define L2CAP_CONNECTION_RESPONSE_RESULT_RTX_TIMEOUT 0x69 -#define L2CAP_CONNECTION_BASEBAND_DISCONNECT 0x6A -#define L2CAP_SERVICE_ALREADY_REGISTERED 0x6B -#define L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU 0x6C -#define L2CAP_SERVICE_DOES_NOT_EXIST 0x6D -#define L2CAP_LOCAL_CID_DOES_NOT_EXIST 0x6E -#define L2CAP_CONNECTION_RESPONSE_UNKNOWN_ERROR 0x6F - -#define RFCOMM_MULTIPLEXER_STOPPED 0x70 -#define RFCOMM_CHANNEL_ALREADY_REGISTERED 0x71 -#define RFCOMM_NO_OUTGOING_CREDITS 0x72 -#define RFCOMM_AGGREGATE_FLOW_OFF 0x73 -#define RFCOMM_DATA_LEN_EXCEEDS_MTU 0x74 - -#define HFP_REMOTE_REJECTS_AUDIO_CONNECTION 0x7F - -#define SDP_HANDLE_ALREADY_REGISTERED 0x80 -#define SDP_QUERY_INCOMPLETE 0x81 -#define SDP_SERVICE_NOT_FOUND 0x82 -#define SDP_HANDLE_INVALID 0x83 -#define SDP_QUERY_BUSY 0x84 - -#define ATT_HANDLE_VALUE_INDICATION_IN_PROGRESS 0x90 -#define ATT_HANDLE_VALUE_INDICATION_TIMEOUT 0x91 -#define ATT_HANDLE_VALUE_INDICATION_DISCONNECT 0x92 - -#define GATT_CLIENT_NOT_CONNECTED 0x93 -#define GATT_CLIENT_BUSY 0x94 -#define GATT_CLIENT_IN_WRONG_STATE 0x95 -#define GATT_CLIENT_DIFFERENT_CONTEXT_FOR_ADDRESS_ALREADY_EXISTS 0x96 -#define GATT_CLIENT_VALUE_TOO_LONG 0x97 -#define GATT_CLIENT_CHARACTERISTIC_NOTIFICATION_NOT_SUPPORTED 0x98 -#define GATT_CLIENT_CHARACTERISTIC_INDICATION_NOT_SUPPORTED 0x99 - -#define BNEP_SERVICE_ALREADY_REGISTERED 0xA0 -#define BNEP_CHANNEL_NOT_CONNECTED 0xA1 -#define BNEP_DATA_LEN_EXCEEDS_MTU 0xA2 - -// OBEX ERRORS -#define OBEX_UNKNOWN_ERROR 0xB0 -#define OBEX_CONNECT_FAILED 0xB1 -#define OBEX_DISCONNECTED 0xB2 -#define OBEX_NOT_FOUND 0xB3 -#define OBEX_NOT_ACCEPTABLE 0xB4 -#define OBEX_ABORTED 0xB5 - -#define MESH_ERROR_APPKEY_INDEX_INVALID 0xD0 -/* ENUM_END */ - - -/* ENUM_START: AVRCP_BROWSING_ERROR_CODE */ -#define AVRCP_BROWSING_ERROR_CODE_INVALID_COMMAND 0x00 // Sent if TG received a PDU that it did not understand. Valid for All. -#define AVRCP_BROWSING_ERROR_CODE_INVALID_PARAMETER 0x01 // Sent if the TG received a PDU with a parameter ID that it did not understand. Sent if there is only one parameter ID in the PDU. Valid for All. -#define AVRCP_BROWSING_ERROR_CODE_SPECIFIED_PARAMETER_NOT_FOUND 0x02 // Sent if the parameter ID is understood, but content is wrong or corrupted. Valid for All. -#define AVRCP_BROWSING_ERROR_CODE_INTERNAL_ERROR 0x03 // Sent if there are error conditions not covered by a more specific error code. Valid for All. -#define AVRCP_BROWSING_ERROR_CODE_SUCCESS 0x04 // This is the status that should be returned if the operation was successful. Valid for All except where the response CType is AV/C REJECTED. -#define AVRCP_BROWSING_ERROR_CODE_UID_CHANGED 0x05 // The UIDs on the device have changed. Valid for All. -#define AVRCP_BROWSING_ERROR_CODE_RESERVED_06 0x06 // Valid for All. -#define AVRCP_BROWSING_ERROR_CODE_INVALID_DIRECTION 0x07 // The Direction parameter is invalid. Valid for Change Path. -#define AVRCP_BROWSING_ERROR_CODE_NOT_A_DIRECTORY 0x08 // The UID provided does not refer to a folder item. Valid for Change Path. -#define AVRCP_BROWSING_ERROR_CODE_DOES_NOT_EXIST 0x09 // The UID provided does not refer to any currently valid. Valid for Change Path, PlayItem, AddToNowPlaying, GetItemAttributes. -#define AVRCP_BROWSING_ERROR_CODE_INVALID_SCOPE 0x0a // The scope parameter is invalid. Valid for GetFolderItems, PlayItem, AddToNowPlayer, GetItemAttributes,. -#define AVRCP_BROWSING_ERROR_CODE_RANGE_OUT_OF_BOUNDS 0x0b // The start of range provided is not valid. Valid for GetFolderItems. -#define AVRCP_BROWSING_ERROR_CODE_UID_IS_A_DIRECTORY 0x0c // The UID provided refers to a directory, which cannot be handled by this media player. Valid for PlayItem, AddToNowPlaying. -#define AVRCP_BROWSING_ERROR_CODE_MEDIA_IN_USES 0x0d // The media is not able to be used for this operation at this time. Valid for PlayItem, AddToNowPlaying. -#define AVRCP_BROWSING_ERROR_CODE_NOW_PLAYING_LIST_FULL 0x0e // No more items can be added to the Now Playing List. Valid for AddToNowPlaying. -#define AVRCP_BROWSING_ERROR_CODE_SEARCH_NOT_SUPPORTED 0x0f // The Browsed Media Player does not support search. Valid for Search. -#define AVRCP_BROWSING_ERROR_CODE_SEARCH_IN_PROGRESS 0x10 // A search operation is already in progress. Valid for Search. -#define AVRCP_BROWSING_ERROR_CODE_INVALID_PLAYER_ID 0x11 // The specified Player Id does not refer to a valid player. Valid for SetAddressedPlayer, SetBrowsedPlayer. -#define AVRCP_BROWSING_ERROR_CODE_PLAYER_NOT_BROWSABLE 0x12 // The Player Id supplied refers to a Media Player which does not support browsing. Valid for SetBrowsedPlayer. -#define AVRCP_BROWSING_ERROR_CODE_PLAYER_NOT_ADDRESSED 0x13 // The Player Id supplied refers to a player which is not currently addressed, and the command is not able to be performed if the player is not set as addressed. Valid for Search SetBrowsedPlayer. -#define AVRCP_BROWSING_ERROR_CODE_NO_VALID_SEARCH_RESULTS 0x14 // The Search result list does not contain valid entries, e.g. after being invalidated due to change of browsed player. Valid for GetFolderItems. -#define AVRCP_BROWSING_ERROR_CODE_NO_AVAILABLE_PLAYERS 0x15 // Valid for All. -#define AVRCP_BROWSING_ERROR_CODE_ADDRESSED_PLAYER_CHANGED 0x16 // Valid for Register Notification. -// 0x17-0xff Reserved -/* ENUM_END */ - -// HCI roles -typedef enum { - HCI_ROLE_MASTER = 0, - HCI_ROLE_SLAVE = 1, - HCI_ROLE_INVALID = 0xff, -} hci_role_t; - -// packet sizes (max payload) -#define HCI_ACL_DM1_SIZE 17 -#define HCI_ACL_DH1_SIZE 27 -#define HCI_ACL_2DH1_SIZE 54 -#define HCI_ACL_3DH1_SIZE 83 -#define HCI_ACL_DM3_SIZE 121 -#define HCI_ACL_DH3_SIZE 183 -#define HCI_ACL_DM5_SIZE 224 -#define HCI_ACL_DH5_SIZE 339 -#define HCI_ACL_2DH3_SIZE 367 -#define HCI_ACL_3DH3_SIZE 552 -#define HCI_ACL_2DH5_SIZE 679 -#define HCI_ACL_3DH5_SIZE 1021 -#define HCI_SCO_HV1_SIZE 10 -#define HCI_SCO_HV2_SIZE 20 -#define HCI_SCO_HV3_SIZE 30 -#define HCI_SCO_EV3_SIZE 30 -#define HCI_SCO_EV4_SIZE 120 -#define HCI_SCO_EV5_SIZE 180 -#define HCI_SCO_2EV3_SIZE 60 -#define HCI_SCO_2EV5_SIZE 360 -#define HCI_SCO_3EV3_SIZE 90 -#define HCI_SCO_3EV5_SIZE 540 - -#define LE_ADVERTISING_DATA_SIZE 31 -#define LE_EXTENDED_ADVERTISING_DATA_SIZE 229 -#define LE_EXTENDED_ADVERTISING_MAX_HANDLE 0xEFu -#define LE_EXTENDED_ADVERTISING_MAX_CHUNK_LEN 251 - -// advertising event properties for extended advertising -#define LE_ADVERTISING_PROPERTIES_CONNECTABLE (1u<<0) -#define LE_ADVERTISING_PROPERTIES_SCANNABLE (1u<<1) -#define LE_ADVERTISING_PROPERTIES_DIRECTED (1u<<2) -#define LE_ADVERTISING_PROPERTIES_HIGH_DUTY_CYCLE (1u<<3) -#define LE_ADVERTISING_PROPERTIES_LEGACY (1u<<4) -#define LE_ADVERTISING_PROPERTIES_ANONYMOUS (1u<<5) -#define LE_ADVERTISING_PROPERTIES_INCLUDE_TX_POWER (1u<<6) - - -// SCO Packet Types -#define SCO_PACKET_TYPES_NONE 0x0000 -#define SCO_PACKET_TYPES_HV1 0x0001 -#define SCO_PACKET_TYPES_HV2 0x0002 -#define SCO_PACKET_TYPES_HV3 0x0004 -#define SCO_PACKET_TYPES_EV3 0x0008 -#define SCO_PACKET_TYPES_EV4 0x0010 -#define SCO_PACKET_TYPES_EV5 0x0020 -#define SCO_PACKET_TYPES_2EV3 0x0040 -#define SCO_PACKET_TYPES_3EV3 0x0080 -#define SCO_PACKET_TYPES_2EV5 0x0100 -#define SCO_PACKET_TYPES_3EV5 0x0200 -#define SCO_PACKET_TYPES_ALL 0x03FF -#define SCO_PACKET_TYPES_SCO 0x0007 -#define SCO_PACKET_TYPES_ESCO 0x03F8 - -// Link Policy Settings -#define LM_LINK_POLICY_DISABLE_ALL_LM_MODES 0 -#define LM_LINK_POLICY_ENABLE_ROLE_SWITCH 1 -#define LM_LINK_POLICY_ENABLE_HOLD_MODE 2 -#define LM_LINK_POLICY_ENABLE_SNIFF_MODE 4 - -// ACL Connection Modes -#define ACL_CONNECTION_MODE_ACTIVE 0 -#define ACL_CONNECTION_MODE_HOLD 1 -#define ACL_CONNECTION_MODE_SNIFF 2 - -/** - Default INQ Mode -*/ -#define GAP_IAC_GENERAL_INQUIRY 0x9E8B33L // General/Unlimited Inquiry Access Code (GIAC) -#define GAP_IAC_LIMITED_INQUIRY 0x9E8B00L // Limited Dedicated Inquiry Access Code (LIAC) - -/** - SSP IO Capabilities -*/ -#define SSP_IO_CAPABILITY_DISPLAY_ONLY 0 -#define SSP_IO_CAPABILITY_DISPLAY_YES_NO 1 -#define SSP_IO_CAPABILITY_KEYBOARD_ONLY 2 -#define SSP_IO_CAPABILITY_NO_INPUT_NO_OUTPUT 3 -#define SSP_IO_CAPABILITY_UNKNOWN 0xff - - -/** - SSP Authentication Requirements, see IO Capability Request Reply Command -*/ - -// Numeric comparison with automatic accept allowed. -#define SSP_IO_AUTHREQ_MITM_PROTECTION_NOT_REQUIRED_NO_BONDING 0x00 - -// Use IO Capabilities to deter- mine authentication procedure -#define SSP_IO_AUTHREQ_MITM_PROTECTION_REQUIRED_NO_BONDING 0x01 - -// Numeric compar- ison with automatic accept allowed. -#define SSP_IO_AUTHREQ_MITM_PROTECTION_NOT_REQUIRED_DEDICATED_BONDING 0x02 - -// Use IO Capabilities to determine authentication procedure -#define SSP_IO_AUTHREQ_MITM_PROTECTION_REQUIRED_DEDICATED_BONDING 0x03 - -// Numeric Compari- son with automatic accept allowed. -#define SSP_IO_AUTHREQ_MITM_PROTECTION_NOT_REQUIRED_GENERAL_BONDING 0x04 - -// Use IO capabilities to determine authentication procedure. -#define SSP_IO_AUTHREQ_MITM_PROTECTION_REQUIRED_GENERAL_BONDING 0x05 - - -// OGFs -#define OGF_LINK_CONTROL 0x01 -#define OGF_LINK_POLICY 0x02 -#define OGF_CONTROLLER_BASEBAND 0x03 -#define OGF_INFORMATIONAL_PARAMETERS 0x04 -#define OGF_STATUS_PARAMETERS 0x05 -#define OGF_TESTING 0x06 -#define OGF_LE_CONTROLLER 0x08 -#define OGF_VENDOR 0x3f - - - - -/** - L2CAP Layer -*/ - -#define L2CAP_HEADER_SIZE 4 - -// minimum signaling MTU -#define L2CAP_MINIMAL_MTU 48 -#define L2CAP_DEFAULT_MTU 672 - -// Minimum/default MTU -#define L2CAP_LE_DEFAULT_MTU 23 - -// L2CAP Fixed Channel IDs -#define L2CAP_CID_SIGNALING 0x0001 -#define L2CAP_CID_CONNECTIONLESS_CHANNEL 0x0002 -#define L2CAP_CID_ATTRIBUTE_PROTOCOL 0x0004 -#define L2CAP_CID_SIGNALING_LE 0x0005 -#define L2CAP_CID_SECURITY_MANAGER_PROTOCOL 0x0006 -#define L2CAP_CID_BR_EDR_SECURITY_MANAGER 0x0007 - -// L2CAP Channels in Basic and Enhanced Retransmission Mode - -// connection response result -#define L2CAP_CONNECTION_RESULT_SUCCESS 0x0000 -#define L2CAP_CONNECTION_RESULT_PENDING 0x0001 -#define L2CAP_CONNECTION_RESULT_PSM_NOT_SUPPORTED 0x0002 -#define L2CAP_CONNECTION_RESULT_SECURITY_BLOCK 0x0003 -#define L2CAP_CONNECTION_RESULT_NO_RESOURCES_AVAILABLE 0x0004 -#define L2CAP_CONNECTION_RESULT_INVALID_SOURCE_CID 0x0006 -#define L2CAP_CONNECTION_RESULT_SOURCE_CID_ALREADY_ALLOCATED 0x0007 - -// L2CAP Channels in LE Credit-Based Flow-Control Mode - -// connection response result -#define L2CAP_CBM_CONNECTION_RESULT_SUCCESS 0x0000 -#define L2CAP_CBM_CONNECTION_RESULT_SPSM_NOT_SUPPORTED 0x0002 -#define L2CAP_CBM_CONNECTION_RESULT_NO_RESOURCES_AVAILABLE 0x0004 -#define L2CAP_CBM_CONNECTION_RESULT_INSUFFICIENT_AUTHENTICATION 0x0005 -#define L2CAP_CBM_CONNECTION_RESULT_INSUFFICIENT_AUTHORIZATION 0x0006 -#define L2CAP_CBM_CONNECTION_RESULT_ENCYRPTION_KEY_SIZE_TOO_SHORT 0x0007 -#define L2CAP_CBM_CONNECTION_RESULT_INSUFFICIENT_ENCRYPTION 0x0008 -#define L2CAP_CBM_CONNECTION_RESULT_INVALID_SOURCE_CID 0x0009 -#define L2CAP_CBM_CONNECTION_RESULT_SOURCE_CID_ALREADY_ALLOCATED 0x000A -#define L2CAP_CBM_CONNECTION_RESULT_UNACCEPTABLE_PARAMETERS 0x000B - - -// L2CAP Channels in Enhanced Credit-Based Flow-Control Mode - -// number of CIDs in single connection+reconfiguration request/response -#define L2CAP_ECBM_MAX_CID_ARRAY_SIZE 5 - -// connection response result -#define L2CAP_ECBM_CONNECTION_RESULT_ALL_SUCCESS 0x0000 -#define L2CAP_ECBM_CONNECTION_RESULT_ALL_REFUSED_SPSM_NOT_SUPPORTED 0x0002 -#define L2CAP_ECBM_CONNECTION_RESULT_SOME_REFUSED_INSUFFICIENT_RESOURCES_AVAILABLE 0x0004 -#define L2CAP_ECBM_CONNECTION_RESULT_ALL_REFUSED_INSUFFICIENT_AUTHENTICATION 0x0005 -#define L2CAP_ECBM_CONNECTION_RESULT_ALL_REFUSED_INSUFFICIENT_AUTHORIZATION 0x0006 -#define L2CAP_ECBM_CONNECTION_RESULT_ALL_REFUSED_ENCYRPTION_KEY_SIZE_TOO_SHORT 0x0007 -#define L2CAP_ECBM_CONNECTION_RESULT_ALL_REFUSED_INSUFFICIENT_ENCRYPTION 0x0008 -#define L2CAP_ECBM_CONNECTION_RESULT_SOME_REFUSED_INVALID_SOURCE_CID 0x0009 -#define L2CAP_ECBM_CONNECTION_RESULT_SOME_REFUSED_SOURCE_CID_ALREADY_ALOCATED 0x000A -#define L2CAP_ECBM_CONNECTION_RESULT_ALL_REFUSED_UNACCEPTABLE_PARAMETERS 0x000B -#define L2CAP_ECBM_CONNECTION_RESULT_ALL_REFUSED_INVALID_PARAMETERS 0x000C -#define L2CAP_ECBM_CONNECTION_RESULT_ALL_PENDING_NO_FURTHER_INFORMATION 0x000D -#define L2CAP_ECBM_CONNECTION_RESULT_ALL_PENDING_AUTHENTICATION 0x000E -#define L2CAP_ECBM_CONNECTION_RESULT_ALL_PENDING_AUTHORIZATION 0x000F - - -// Result for Reconfigure Request -#define L2CAP_ECBM_RECONFIGURE_SUCCESS 0 -#define L2CAP_ECBM_RECONFIGURE_FAILED_MTU_REDUCTION_NOT_ALLOWED 1 -#define L2CAP_ECBM_RECONFIGURE_FAILED_MPS_REDUCTION_MULTIPLE_CHANNELS 2 -#define L2CAP_ECBM_RECONFIGURE_FAILED_DESTINATION_CID_INVALID 3 -#define L2CAP_ECBM_RECONFIGURE_FAILED_UNACCEPTABLE_PARAMETERS 4 - -/** - SDP Protocol -*/ - -// Device Vendor ID Sources -#define DEVICE_ID_VENDOR_ID_SOURCE_BLUETOOTH 0x0001 -#define DEVICE_ID_VENDOR_ID_SOURCE_USB 0x0002 - -// OBEX -#define SDP_vCard_2_1 0x01 -#define SDP_vCard_3_0 0x02 -#define SDP_vCal_1_0 0x03 -#define SDP_iCal_2_0 0x04 -#define SDP_vNote 0x05 -#define SDP_vMessage 0x06 -#define SDP_OBEXFileTypeAny 0xFF - -/** - RFCOMM Protocol -*/ - -// Line Status -#define LINE_STATUS_NO_ERROR 0x00 -#define LINE_STATUS_OVERRUN_ERROR 0x03 -#define LINE_STATUS_PARITY_ERORR 0x05 -#define LINE_STATUS_FRAMING_ERROR 0x09 - -// Modem Status Flags -#define MODEM_STATUS_FC 0x02 -#define MODEM_STATUS_RTC 0x04 -#define MODEM_STATUS_RTR 0x08 -#define MODEM_STATUS_IC 0x40 -#define MODEM_STATUS_DV 0x80 - -typedef enum rpn_baud { - RPN_BAUD_2400 = 0, - RPN_BAUD_4800, - RPN_BAUD_7200, - RPN_BAUD_9600, - RPN_BAUD_19200, - RPN_BAUD_38400, - RPN_BAUD_57600, - RPN_BAUD_115200, - RPN_BAUD_230400 -} rpn_baud_t; - -typedef enum rpn_data_bits { - RPN_DATA_BITS_5 = 0, - RPN_DATA_BITS_6 = 0, - RPN_DATA_BITS_7 = 0, - RPN_DATA_BITS_8 = 0 -} rpn_data_bits_t; - -typedef enum rpn_stop_bits { - RPN_STOP_BITS_1_0 = 0, - RPN_STOP_BITS_1_5 -} rpn_stop_bits_t; - -typedef enum rpn_parity { - RPN_PARITY_NONE = 0, - RPN_PARITY_ODD = 1, - RPN_PARITY_EVEN = 3, - RPN_PARITY_MARK = 5, - RPN_PARITY_SPACE = 7, -} rpn_parity_t; - -#define RPN_FLOW_CONTROL_XONXOFF_ON_INPUT 0x01 -#define RPN_FLOW_CONTROL_XONXOFF_ON_OUTPUT 0x02 -#define RPN_FLOW_CONTROL_RTR_ON_INPUT 0x04 -#define RPN_FLOW_CONTROL_RTR_ON_OUTPUT 0x08 -#define RPN_FLOW_CONTROL_RTC_ON_INPUT 0x10 -#define RPN_FLOW_CONTROL_RTC_ON_OUTPUT 0x20 - -#define RPN_PARAM_MASK_0_BAUD 0x01 -#define RPN_PARAM_MASK_0_DATA_BITS 0x02 -#define RPN_PARAM_MASK_0_STOP_BITS 0x04 -#define RPN_PARAM_MASK_0_PARITY 0x08 -#define RPN_PARAM_MASK_0_PARITY_TYPE 0x10 -#define RPN_PARAM_MASK_0_XON_CHAR 0x20 -#define RPN_PARAM_MASK_0_XOFF_CHAR 0x40 -#define RPN_PARAM_MASK_0_RESERVED 0x80 - -// @note: values are identical to rpn_flow_control_t -#define RPN_PARAM_MASK_1_XONOFF_ON_INPUT 0x01 -#define RPN_PARAM_MASK_1_XONOFF_ON_OUTPUT 0x02 -#define RPN_PARAM_MASK_1_RTR_ON_INPUT 0x04 -#define RPN_PARAM_MASK_1_RTR_ON_OUTPUT 0x08 -#define RPN_PARAM_MASK_1_RTC_ON_INPUT 0x10 -#define RPN_PARAM_MASK_1_RTC_ON_OUTPUT 0x20 -#define RPN_PARAM_MASK_1_RESERVED_0 0x40 -#define RPN_PARAM_MASK_1_RESERVED_1 0x80 - -/** - BNEP Protocol -*/ - -#ifndef ETHER_ADDR_LEN -#define ETHER_ADDR_LEN 6 -#endif - -#ifndef ETHERTYPE_VLAN -#define ETHERTYPE_VLAN 0x8100 /* IEEE 802.1Q VLAN tag */ -#endif - -#define BNEP_MTU_MIN 1691 - - -/** - PAN Profile -*/ - -typedef enum { - BNEP_SECURITY_NONE = 0x0000, - BNEP_SECURITY_SERVICE_LEVEL_ENFORCED, - BNEP_SECURITY_802_1X -} security_description_t; - -typedef enum { - PAN_NET_ACCESS_TYPE_PSTN = 0x0000, - PAN_NET_ACCESS_TYPE_ISDN, - PAN_NET_ACCESS_TYPE_DSL, - PAN_NET_ACCESS_TYPE_CABLE_MODEM, - PAN_NET_ACCESS_TYPE_10MB_ETHERNET, - PAN_NET_ACCESS_TYPE_100MB_ETHERNET, - PAN_NET_ACCESS_TYPE_4MB_TOKEN_RING, - PAN_NET_ACCESS_TYPE_16MB_TOKEN_RING, - PAN_NET_ACCESS_TYPE_100MB_TOKEN_RING, - PAN_NET_ACCESS_TYPE_FDDI, - PAN_NET_ACCESS_TYPE_GSM, - PAN_NET_ACCESS_TYPE_CDMA, - PAN_NET_ACCESS_TYPE_GPRS, - PAN_NET_ACCESS_TYPE_3G, - PAN_NET_ACCESS_TYPE_CELULAR, - PAN_NET_ACCESS_TYPE_OTHER = 0xFFFE, - PAN_NET_ACCESS_TYPE_NONE -} net_access_type_t; - -/** - ATT -*/ - -// Minimum/default MTU -#define ATT_DEFAULT_MTU 23 - -// MARK: ATT Error Codes -#define ATT_ERROR_SUCCESS 0x00 -#define ATT_ERROR_INVALID_HANDLE 0x01 -#define ATT_ERROR_READ_NOT_PERMITTED 0x02 -#define ATT_ERROR_WRITE_NOT_PERMITTED 0x03 -#define ATT_ERROR_INVALID_PDU 0x04 -#define ATT_ERROR_INSUFFICIENT_AUTHENTICATION 0x05 -#define ATT_ERROR_REQUEST_NOT_SUPPORTED 0x06 -#define ATT_ERROR_INVALID_OFFSET 0x07 -#define ATT_ERROR_INSUFFICIENT_AUTHORIZATION 0x08 -#define ATT_ERROR_PREPARE_QUEUE_FULL 0x09 -#define ATT_ERROR_ATTRIBUTE_NOT_FOUND 0x0a -#define ATT_ERROR_ATTRIBUTE_NOT_LONG 0x0b -#define ATT_ERROR_INSUFFICIENT_ENCRYPTION_KEY_SIZE 0x0c -#define ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LENGTH 0x0d -#define ATT_ERROR_UNLIKELY_ERROR 0x0e -#define ATT_ERROR_INSUFFICIENT_ENCRYPTION 0x0f -#define ATT_ERROR_UNSUPPORTED_GROUP_TYPE 0x10 -#define ATT_ERROR_INSUFFICIENT_RESOURCES 0x11 -#define ATT_ERROR_VALUE_NOT_ALLOWED 0x13 - -// MARK: ATT Error Codes defined by BTstack -#define ATT_ERROR_HCI_DISCONNECT_RECEIVED 0x1f -#define ATT_ERROR_BONDING_INFORMATION_MISSING 0x70 -#define ATT_ERROR_DATA_MISMATCH 0x7e -#define ATT_ERROR_TIMEOUT 0x7F -#define ATT_ERROR_WRITE_RESPONSE_PENDING 0x100 - -// MARK: ATT Error Codes from Bluetooth Core Specification Supplement, Version 9 or later -#define ATT_ERROR_WRITE_REQUEST_REJECTED 0xFC -#define ATT_ERROR_CLIENT_CHARACTERISTIC_CONFIGURATION_DESCRIPTOR_IMPROPERLY_CONFIGURED 0xFD -#define ATT_ERROR_PROCEDURE_ALREADY_IN_PROGRESS 0xFE -#define ATT_ERROR_OUT_OF_RANGE 0xFF - -// MARK: ATT Error Codes from Cycling Power Service spec -#define CYCLING_POWER_ERROR_CODE_INAPPROPRIATE_CONNECTION_PARAMETERS 0x80 -#define CYCLING_POWER_ERROR_CODE_PROCEDURE_ALREADY_IN_PROGRESS 0xFE -#define CYCLING_POWER_ERROR_CODE_CCC_DESCRIPTOR_IMPROPERLY_CONFIGURED 0xFD - -// MARK: ATT Error Codes from Cycling Speed and Cadence Service spec -#define CYCLING_SPEED_AND_CADENCE_ERROR_CODE_PROCEDURE_ALREADY_IN_PROGRESS 0x80 -#define CYCLING_SPEED_AND_CADENCE_ERROR_CODE_CCC_DESCRIPTOR_IMPROPERLY_CONFIGURED 0x81 - - -// MARK: Attribute Property Flags -#define ATT_PROPERTY_BROADCAST 0x01 -#define ATT_PROPERTY_READ 0x02 -#define ATT_PROPERTY_WRITE_WITHOUT_RESPONSE 0x04 -#define ATT_PROPERTY_WRITE 0x08 -#define ATT_PROPERTY_NOTIFY 0x10 -#define ATT_PROPERTY_INDICATE 0x20 -#define ATT_PROPERTY_AUTHENTICATED_SIGNED_WRITE 0x40 -#define ATT_PROPERTY_EXTENDED_PROPERTIES 0x80 - -// MARK: Attribute Property Flag, BTstack extension -// value is asked from client -#define ATT_PROPERTY_DYNAMIC 0x100 - -// Security levels -#define ATT_SECURITY_NONE 0 -#define ATT_SECURITY_ENCRYPTED 1 -#define ATT_SECURITY_AUTHENTICATED 2 -#define ATT_SECURITY_AUTHORIZED 3 -#define ATT_SECURITY_AUTHENTICATED_SC 4 - -// ATT Transaction Timeout of 30 seconds for Command/Response or Indication/Confirmation -#define ATT_TRANSACTION_TIMEOUT_MS 30000 - -#define ATT_TRANSACTION_MODE_NONE 0x0 -#define ATT_TRANSACTION_MODE_ACTIVE 0x1 -#define ATT_TRANSACTION_MODE_EXECUTE 0x2 -#define ATT_TRANSACTION_MODE_CANCEL 0x3 -#define ATT_TRANSACTION_MODE_VALIDATE 0x4 - -// MARK: GATT UUIDs -#define GATT_PRIMARY_SERVICE_UUID 0x2800 -#define GATT_SECONDARY_SERVICE_UUID 0x2801 -#define GATT_INCLUDE_SERVICE_UUID 0x2802 -#define GATT_CHARACTERISTICS_UUID 0x2803 -#define GATT_CHARACTERISTIC_EXTENDED_PROPERTIES 0x2900 -#define GATT_CHARACTERISTIC_USER_DESCRIPTION 0x2901 -#define GATT_CLIENT_CHARACTERISTICS_CONFIGURATION 0x2902 -#define GATT_SERVER_CHARACTERISTICS_CONFIGURATION 0x2903 -#define GATT_CHARACTERISTIC_PRESENTATION_FORMAT 0x2904 -#define GATT_CHARACTERISTIC_AGGREGATE_FORMAT 0x2905 -#define GATT_CLIENT_SUPPORTED_FEATURES 0x2B29 -#define GATT_SERVER_SUPPORTED_FEATURES 0x2B3A - -#define GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NONE 0 -#define GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION 1 -#define GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION 2 - -#define GATT_CLIENT_ANY_CONNECTION 0xffff -#define GATT_CLIENT_ANY_VALUE_HANDLE 0x0000 - -// GAP Service and Characteristics -#define GAP_SERVICE_UUID 0x1800 -#define GAP_DEVICE_NAME_UUID 0x2a00 -#define GAP_APPEARANCE_UUID 0x2a01 -#define GAP_PERIPHERAL_PRIVACY_FLAG 0x2a02 -#define GAP_RECONNECTION_ADDRESS_UUID 0x2a03 -#define GAP_PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS_UUID 0x2a04 -#define GAP_SERVICE_CHANGED 0x2a05 - -// Bluetooth GATT types - -typedef struct { - uint16_t year; // 0 - year is not known; or [1582,9999] - uint8_t month; // 0 - month is not known; or [1,12] - uint8_t day; // 0 - day is not known; or [1,31] - uint8_t hours; // [0,23] - uint8_t minutes; // [0,59] - uint8_t seconds; // [0,59] -} gatt_date_time_t; - -typedef enum { - GATT_MICROPHONE_CONTROL_MUTE_OFF = 0x00, - GATT_MICROPHONE_CONTROL_MUTE_ON, - GATT_MICROPHONE_CONTROL_MUTE_DISABLED -} gatt_microphone_control_mute_t; - -/** - SM - LE Security Manager -*/ -// Bluetooth Spec definitions -typedef enum { - SM_CODE_PAIRING_REQUEST = 0X01, - SM_CODE_PAIRING_RESPONSE, - SM_CODE_PAIRING_CONFIRM, - SM_CODE_PAIRING_RANDOM, - SM_CODE_PAIRING_FAILED, - SM_CODE_ENCRYPTION_INFORMATION, - SM_CODE_MASTER_IDENTIFICATION, - SM_CODE_IDENTITY_INFORMATION, - SM_CODE_IDENTITY_ADDRESS_INFORMATION, - SM_CODE_SIGNING_INFORMATION, - SM_CODE_SECURITY_REQUEST, - SM_CODE_PAIRING_PUBLIC_KEY, - SM_CODE_PAIRING_DHKEY_CHECK, - SM_CODE_KEYPRESS_NOTIFICATION, -} SECURITY_MANAGER_COMMANDS; - -// IO Capability Values -typedef enum { - IO_CAPABILITY_DISPLAY_ONLY = 0, - IO_CAPABILITY_DISPLAY_YES_NO, - IO_CAPABILITY_KEYBOARD_ONLY, - IO_CAPABILITY_NO_INPUT_NO_OUTPUT, - IO_CAPABILITY_KEYBOARD_DISPLAY, // not used by secure simple pairing -} io_capability_t; - -// Authentication requirement flags -#define SM_AUTHREQ_NO_BONDING 0x00 -#define SM_AUTHREQ_BONDING 0x01 -#define SM_AUTHREQ_MITM_PROTECTION 0x04 -#define SM_AUTHREQ_SECURE_CONNECTION 0x08 -#define SM_AUTHREQ_KEYPRESS 0x10 -#define SM_AUTHREQ_CT2 0x20 - -// Key distribution flags used by spec -#define SM_KEYDIST_ENC_KEY 0x01 -#define SM_KEYDIST_ID_KEY 0x02 -#define SM_KEYDIST_SIGN 0x04 -#define SM_KEYDIST_LINK_KEY 0x08 - -// Key distribution flags used internally -#define SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION 0x01 -#define SM_KEYDIST_FLAG_MASTER_IDENTIFICATION 0x02 -#define SM_KEYDIST_FLAG_IDENTITY_INFORMATION 0x04 -#define SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION 0x08 -#define SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION 0x10 - -// STK Generation Methods -#define SM_STK_GENERATION_METHOD_JUST_WORKS 0x01 -#define SM_STK_GENERATION_METHOD_OOB 0x02 -#define SM_STK_GENERATION_METHOD_PASSKEY 0x04 -#define SM_STK_GENERATION_METHOD_NUMERIC_COMPARISON 0x08 - -// Pairing Failed Reasons -#define SM_REASON_RESERVED 0x00 -#define SM_REASON_PASSKEY_ENTRY_FAILED 0x01 -#define SM_REASON_OOB_NOT_AVAILABLE 0x02 -#define SM_REASON_AUTHENTHICATION_REQUIREMENTS 0x03 -#define SM_REASON_CONFIRM_VALUE_FAILED 0x04 -#define SM_REASON_PAIRING_NOT_SUPPORTED 0x05 -#define SM_REASON_ENCRYPTION_KEY_SIZE 0x06 -#define SM_REASON_COMMAND_NOT_SUPPORTED 0x07 -#define SM_REASON_UNSPECIFIED_REASON 0x08 -#define SM_REASON_REPEATED_ATTEMPTS 0x09 -#define SM_REASON_INVALID_PARAMETERS 0x0a -#define SM_REASON_DHKEY_CHECK_FAILED 0x0b -#define SM_REASON_NUMERIC_COMPARISON_FAILED 0x0c -#define SM_REASON_BR_EDR_PAIRING_IN_PROGRESS 0x0d -#define SM_REASON_CROSS_TRANSPORT_KEY_DERIVATION_NOT_ALLOWED 0x0e -#define SM_REASON_KEY_REJECTED 0x0f - -// also, invalid parameters -// and reserved - -// Keypress Notifications -#define SM_KEYPRESS_PASSKEY_ENTRY_STARTED 0x00 -#define SM_KEYPRESS_PASSKEY_DIGIT_ENTERED 0x01 -#define SM_KEYPRESS_PASSKEY_DIGIT_ERASED 0x02 -#define SM_KEYPRESS_PASSKEY_CLEARED 0x03 -#define SM_KEYPRESS_PASSKEY_ENTRY_COMPLETED 0x04 - - -#endif diff --git a/cores/rp2040/sdkoverride/hids_device.c b/cores/rp2040/sdkoverride/hids_device.c deleted file mode 100644 index 17a74b24a..000000000 --- a/cores/rp2040/sdkoverride/hids_device.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - Copyright (C) 2014 BlueKitchen GmbH - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the names of - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - 4. Any redistribution, use, or modification is done solely for - personal benefit and not for any commercial purpose or for - monetary gain. - - THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN - GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - Please inquire about commercial licensing options at - contact@bluekitchen-gmbh.com - -*/ - -#if defined ENABLE_CLASSIC - -#define BTSTACK_FILE__ "hids_device.c" - -/** - Implementation of the GATT HIDS Device - To use with your application, add '#import ' to your .gatt file -*/ - -#include "hids_device.h" - -#include "ble/att_db.h" -#include "ble/att_server.h" -#include "bluetooth_gatt.h" -#include "btstack_util.h" -#include "btstack_debug.h" - -#define HIDS_DEVICE_ERROR_CODE_INAPPROPRIATE_CONNECTION_PARAMETERS 0x80 - -// storage for 'generic' HID Device with single Input, Output, and Feature Report -static hids_device_report_t hid_reports_generic_storage[3]; - -typedef struct { - uint16_t con_handle; - - uint8_t hid_country_code; - const uint8_t * hid_descriptor; - uint16_t hid_descriptor_size; - - uint16_t hid_report_map_handle; - uint8_t hid_protocol_mode; - uint16_t hid_protocol_mode_value_handle; - - uint16_t hid_boot_mouse_input_value_handle; - uint16_t hid_boot_mouse_input_client_configuration_handle; - uint16_t hid_boot_mouse_input_client_configuration_value; - - uint16_t hid_boot_keyboard_input_value_handle; - uint16_t hid_boot_keyboard_input_client_configuration_handle; - uint16_t hid_boot_keyboard_input_client_configuration_value; - - hids_device_report_t * hid_reports; - - uint8_t hid_input_reports_num; - uint8_t hid_output_reports_num; - uint8_t hid_feature_reports_num; - - uint16_t hid_control_point_value_handle; - uint8_t hid_control_point_suspend; - - btstack_context_callback_registration_t battery_callback; -} hids_device_t; - -static hids_device_t hids_device; - -static btstack_packet_handler_t packet_handler; -static att_service_handler_t hid_service; - -// TODO: store hids device connection into list -static hids_device_t * hids_device_get_instance_for_con_handle(uint16_t con_handle) { - UNUSED(con_handle); - return &hids_device; -} - -static hids_device_t * hids_device_create_instance(void) { - memset(&hids_device, 0, sizeof(hids_device_t)); - return &hids_device; -} - -static hids_device_report_t * hids_device_get_report_for_client_configuration_handle(hids_device_t * device, uint16_t client_configuration_handle) { - uint8_t pos; - uint8_t total_reports = device->hid_input_reports_num + device->hid_output_reports_num + device->hid_feature_reports_num; - for (pos = 0 ; pos < total_reports ; pos++) { - if (device->hid_reports[pos].client_configuration_handle == client_configuration_handle) { - return &device->hid_reports[pos]; - } - } - return NULL; -} - -static hids_device_report_t * -hids_device_get_report_for_id_and_type(hids_device_t *device, uint16_t report_id, hid_report_type_t type) { - uint8_t pos; - uint8_t total_reports = device->hid_input_reports_num + device->hid_output_reports_num + device->hid_feature_reports_num; - for (pos = 0 ; pos < total_reports ; pos++) { - if ((device->hid_reports[pos].type == type) && (device->hid_reports[pos].id == report_id)) { - return &device->hid_reports[pos]; - } - } - return NULL; -} - -static void hids_device_emit_event_with_uint8(uint8_t event, hci_con_handle_t con_handle, uint8_t value) { - hids_device_t * instance = hids_device_get_instance_for_con_handle(con_handle); - if (!instance) { - log_error("no instance for handle 0x%02x", con_handle); - return; - } - - if (!packet_handler) { - return; - } - uint8_t buffer[6]; - buffer[0] = HCI_EVENT_HIDS_META; - buffer[1] = 4; - buffer[2] = event; - little_endian_store_16(buffer, 3, (uint16_t) con_handle); - buffer[5] = value; - (*packet_handler)(HCI_EVENT_PACKET, 0, buffer, sizeof(buffer)); -} - -static void hids_device_emit_event_with_uint8_uint8_t(uint8_t event, hci_con_handle_t con_handle, uint8_t value_1, uint8_t value_2) { - hids_device_t * instance = hids_device_get_instance_for_con_handle(con_handle); - if (!instance) { - log_error("no instance for handle 0x%02x", con_handle); - return; - } - - if (!packet_handler) { - return; - } - uint8_t buffer[7]; - buffer[0] = HCI_EVENT_HIDS_META; - buffer[1] = 4; - buffer[2] = event; - little_endian_store_16(buffer, 3, (uint16_t) con_handle); - buffer[5] = value_1; - buffer[6] = value_2; - (*packet_handler)(HCI_EVENT_PACKET, 0, buffer, sizeof(buffer)); -} - -static void hids_device_emit_event(uint8_t event, hci_con_handle_t con_handle) { - hids_device_t * instance = hids_device_get_instance_for_con_handle(con_handle); - if (!instance) { - log_error("no instance for handle 0x%02x", con_handle); - return; - } - - if (!packet_handler) { - return; - } - uint8_t buffer[5]; - buffer[0] = HCI_EVENT_HIDS_META; - buffer[1] = 4; - buffer[2] = event; - little_endian_store_16(buffer, 3, (uint16_t) con_handle); - (*packet_handler)(HCI_EVENT_PACKET, 0, buffer, sizeof(buffer)); -} - -static void hids_device_can_send_now(void * context) { - hci_con_handle_t con_handle = (hci_con_handle_t)(uintptr_t) context; - // notify client - hids_device_t * instance = hids_device_get_instance_for_con_handle(con_handle); - if (!instance) { - log_error("no instance for handle 0x%02x", con_handle); - return; - } - - if (!packet_handler) { - return; - } - uint8_t buffer[5]; - buffer[0] = HCI_EVENT_HIDS_META; - buffer[1] = 3; - buffer[2] = HIDS_SUBEVENT_CAN_SEND_NOW; - little_endian_store_16(buffer, 3, (uint16_t) con_handle); - (*packet_handler)(HCI_EVENT_PACKET, 0, buffer, sizeof(buffer)); -} - -// ATT Client Read Callback for Dynamic Data -// - if buffer == NULL, don't copy data, just return size of value -// - if buffer != NULL, copy data and return number bytes copied -static uint16_t att_read_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size) { - hids_device_t * instance = hids_device_get_instance_for_con_handle(con_handle); - if (!instance) { - log_error("no instance for handle 0x%02x", con_handle); - return HIDS_DEVICE_ERROR_CODE_INAPPROPRIATE_CONNECTION_PARAMETERS; - } - - if (att_handle == instance->hid_protocol_mode_value_handle) { - log_info("Read protocol mode"); - return att_read_callback_handle_byte(instance->hid_protocol_mode, offset, buffer, buffer_size); - } - - if (att_handle == instance->hid_report_map_handle) { - log_info("Read report map"); - return att_read_callback_handle_blob(instance->hid_descriptor, instance->hid_descriptor_size, offset, buffer, buffer_size); - } - - if (att_handle == instance->hid_boot_mouse_input_client_configuration_handle) { - return att_read_callback_handle_little_endian_16(instance->hid_boot_mouse_input_client_configuration_value, offset, buffer, buffer_size); - } - - if (att_handle == instance->hid_boot_keyboard_input_client_configuration_handle) { - return att_read_callback_handle_little_endian_16(instance->hid_boot_keyboard_input_client_configuration_value, offset, buffer, buffer_size); - } - - if (att_handle == instance->hid_control_point_value_handle) { - if (buffer && (buffer_size >= 1u)) { - buffer[0] = instance->hid_control_point_suspend; - } - return 1; - } - - hids_device_report_t * report = hids_device_get_report_for_client_configuration_handle(instance, att_handle); - if (report != NULL) { - return att_read_callback_handle_little_endian_16(report->client_configuration_value, offset, buffer, buffer_size); - } - return 0; -} - -static int att_write_callback(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) { - UNUSED(transaction_mode); - UNUSED(buffer_size); - UNUSED(offset); - - hids_device_t * instance = hids_device_get_instance_for_con_handle(con_handle); - if (!instance) { - log_error("no instance for handle 0x%02x", con_handle); - return HIDS_DEVICE_ERROR_CODE_INAPPROPRIATE_CONNECTION_PARAMETERS; - } - - if (att_handle == instance->hid_boot_mouse_input_client_configuration_handle) { - uint16_t new_value = little_endian_read_16(buffer, 0); - instance->hid_boot_mouse_input_client_configuration_value = new_value; - hids_device_emit_event_with_uint8(HIDS_SUBEVENT_BOOT_MOUSE_INPUT_REPORT_ENABLE, con_handle, (uint8_t) new_value); - } - if (att_handle == instance->hid_boot_keyboard_input_client_configuration_handle) { - uint16_t new_value = little_endian_read_16(buffer, 0); - instance->hid_boot_keyboard_input_client_configuration_value = new_value; - hids_device_emit_event_with_uint8(HIDS_SUBEVENT_BOOT_KEYBOARD_INPUT_REPORT_ENABLE, con_handle, (uint8_t) new_value); - } - - if (att_handle == instance->hid_protocol_mode_value_handle) { - instance->hid_protocol_mode = buffer[0]; - log_info("Set protocol mode: %u", instance->hid_protocol_mode); - hids_device_emit_event_with_uint8(HIDS_SUBEVENT_PROTOCOL_MODE, con_handle, instance->hid_protocol_mode); - } - - if (att_handle == instance->hid_control_point_value_handle) { - if (buffer_size < 1u) { - return ATT_ERROR_INVALID_OFFSET; - } - instance->hid_control_point_suspend = buffer[0]; - instance->con_handle = con_handle; - log_info("Set suspend tp: %u", instance->hid_control_point_suspend); - if (instance->hid_control_point_suspend == 0u) { - hids_device_emit_event(HIDS_SUBEVENT_SUSPEND, con_handle); - } else if (instance->hid_control_point_suspend == 1u) { - hids_device_emit_event(HIDS_SUBEVENT_EXIT_SUSPEND, con_handle); - } - } - - hids_device_report_t * report = hids_device_get_report_for_client_configuration_handle(instance, att_handle); - if (report != NULL) { - uint16_t new_value = little_endian_read_16(buffer, 0); - report->client_configuration_value = new_value; - log_info("Enable Report (type %u) notifications: %x", (uint8_t) report->type, new_value); - - switch (report->type) { - case HID_REPORT_TYPE_INPUT: - hids_device_emit_event_with_uint8_uint8_t(HIDS_SUBEVENT_INPUT_REPORT_ENABLE, con_handle, report->id, (uint8_t) new_value); - break; - case HID_REPORT_TYPE_OUTPUT: - hids_device_emit_event_with_uint8_uint8_t(HIDS_SUBEVENT_OUTPUT_REPORT_ENABLE, con_handle, report->id, (uint8_t) new_value); - break; - case HID_REPORT_TYPE_FEATURE: - hids_device_emit_event_with_uint8_uint8_t(HIDS_SUBEVENT_FEATURE_REPORT_ENABLE, con_handle, report->id, (uint8_t) new_value); - break; - default: - btstack_unreachable(); - break; - } - } - return 0; -} - -void hids_device_init_with_storage(uint8_t hid_country_code, const uint8_t * hid_descriptor, uint16_t hid_descriptor_size, - uint16_t num_reports, hids_device_report_t * report_storage) { - - hids_device_t * instance = hids_device_create_instance(); - - btstack_assert(num_reports > 0); - btstack_assert(report_storage != NULL); - - instance->hid_country_code = hid_country_code; - instance->hid_descriptor = hid_descriptor; - instance->hid_descriptor_size = hid_descriptor_size; - - // default - instance->hid_protocol_mode = 1; - - // get service handle range - uint16_t start_handle = 0; - uint16_t end_handle = 0xffff; - int service_found = gatt_server_get_handle_range_for_service_with_uuid16(ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE, &start_handle, &end_handle); - btstack_assert(service_found != 0); - UNUSED(service_found); - - // get report map handle - instance->hid_report_map_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_REPORT_MAP); - - // get report map handle - instance->hid_protocol_mode_value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_PROTOCOL_MODE); - - // get value and client configuration handles for boot mouse input, boot keyboard input and report input - instance->hid_boot_mouse_input_value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_BOOT_MOUSE_INPUT_REPORT); - instance->hid_boot_mouse_input_client_configuration_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_BOOT_MOUSE_INPUT_REPORT); - - instance->hid_boot_keyboard_input_value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_INPUT_REPORT); - instance->hid_boot_keyboard_input_client_configuration_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_BOOT_KEYBOARD_INPUT_REPORT); - - instance->hid_control_point_value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_HID_CONTROL_POINT); - - log_info("hid_report_map_handle 0x%02x", instance->hid_report_map_handle); - log_info("hid_protocol_mode_value_handle 0x%02x", instance->hid_protocol_mode_value_handle); - log_info("hid_boot_mouse_input_value_handle 0x%02x", instance->hid_boot_mouse_input_value_handle); - log_info("hid_boot_mouse_input_client_configuration_handle 0x%02x", instance->hid_boot_mouse_input_client_configuration_handle); - log_info("hid_boot_keyboard_input_value_handle 0x%02x", instance->hid_boot_keyboard_input_value_handle); - log_info("hid_boot_keyboard_input_client_configuration_handle 0x%02x", instance->hid_boot_keyboard_input_client_configuration_handle); - log_info("hid_control_point_value_handle 0x%02x", instance->hid_control_point_value_handle); - - instance->hid_reports = report_storage; - - uint16_t hid_reports_num = num_reports; - uint16_t assigned_reports_num = 0; - uint16_t start_chr_handle = start_handle; - - while ((start_chr_handle < end_handle) && (assigned_reports_num < hid_reports_num)) { - // mandatory - uint16_t chr_value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_chr_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_REPORT); - if (chr_value_handle == 0) { - break; - } - - // optional - uint16_t chr_client_configuration_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(start_chr_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_REPORT); - - // mandatory - uint16_t report_reference_handle = gatt_server_get_descriptor_handle_for_characteristic_with_uuid16(start_chr_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_REPORT, ORG_BLUETOOTH_DESCRIPTOR_REPORT_REFERENCE); - if (report_reference_handle == 0) { - break; - } - - // get report id and type from report reference - uint16_t report_reference_value_len; - const uint8_t * report_reference_value = gatt_server_get_const_value_for_handle(report_reference_handle, &report_reference_value_len); - if (report_reference_value == NULL) { - break; - } - if (report_reference_value_len != 2) { - break; - } - uint8_t report_id = report_reference_value[0]; - hid_report_type_t report_type = (hid_report_type_t) report_reference_value[1]; - - // store report info - hids_device_report_t * report = &report_storage[assigned_reports_num]; - report->value_handle = chr_value_handle; - report->client_configuration_handle = chr_client_configuration_handle; - report->client_configuration_value = 0; - report->id = report_id; - report->type = report_type; - - switch (report->type) { - case HID_REPORT_TYPE_INPUT: - instance->hid_input_reports_num++; - break; - case HID_REPORT_TYPE_OUTPUT: - instance->hid_output_reports_num++; - break; - case HID_REPORT_TYPE_FEATURE: - instance->hid_feature_reports_num++; - break; - default: - btstack_unreachable(); - return; - } - log_info("hid_report_value_handle 0x%02x, id %u, type %u", report->value_handle, report->id, (uint8_t)report->type); - if (report->client_configuration_handle != 0) { - log_info("hid_report_client_configuration_handle 0x%02x", report->client_configuration_handle); - } - - assigned_reports_num++; - start_chr_handle = report_reference_handle + 1; - } - - // register service with ATT Server - hid_service.start_handle = start_handle; - hid_service.end_handle = end_handle; - hid_service.read_callback = &att_read_callback; - hid_service.write_callback = &att_write_callback; - att_server_register_service_handler(&hid_service); -} - -/** - @brief Set up HIDS Device -*/ -void hids_device_init(uint8_t country_code, const uint8_t * descriptor, uint16_t descriptor_size) { - uint16_t hid_reports_num = sizeof(hid_reports_generic_storage) / sizeof(hids_device_report_t); - hids_device_init_with_storage(country_code, descriptor, descriptor_size, hid_reports_num, hid_reports_generic_storage); -} - -/** - @brief Register callback for the HIDS Device client. - @param callback -*/ -void hids_device_register_packet_handler(btstack_packet_handler_t callback) { - packet_handler = callback; -} - -/** - @brief Request can send now event to send HID Report - Generates an HIDS_SUBEVENT_CAN_SEND_NOW subevent - @param hid_cid -*/ -void hids_device_request_can_send_now_event(hci_con_handle_t con_handle) { - hids_device_t * instance = hids_device_get_instance_for_con_handle(con_handle); - if (!instance) { - log_error("no instance for handle 0x%02x", con_handle); - return; - } - - instance->battery_callback.callback = &hids_device_can_send_now; - instance->battery_callback.context = (void*)(uintptr_t) con_handle; - att_server_register_can_send_now_callback(&instance->battery_callback, con_handle); -} - -uint8_t hids_device_send_input_report_for_id(hci_con_handle_t con_handle, uint16_t report_id, const uint8_t * report, uint16_t report_len) { - hids_device_t * instance = hids_device_get_instance_for_con_handle(con_handle); - if (!instance) { - log_error("no instance for handle 0x%02x", con_handle); - return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; - } - - hids_device_report_t * report_storage = hids_device_get_report_for_id_and_type(instance, report_id, - HID_REPORT_TYPE_INPUT); - if (report_storage == NULL) { - return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE; - } - - return att_server_notify(con_handle, report_storage->value_handle, report, report_len); -} - -uint8_t hids_device_send_input_report(hci_con_handle_t con_handle, const uint8_t * report, uint16_t report_len) { - hids_device_t * device = hids_device_get_instance_for_con_handle(con_handle); - if (!device) { - log_error("no instance for handle 0x%02x", con_handle); - return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; - } - - uint8_t pos; - uint8_t total_reports = device->hid_input_reports_num + device->hid_output_reports_num + device->hid_feature_reports_num; - for (pos = 0 ; pos < total_reports ; pos++) { - hids_device_report_t * report_storage = &device->hid_reports[pos]; - if (report_storage->type == HID_REPORT_TYPE_INPUT) { - return att_server_notify(con_handle, report_storage->value_handle, report, report_len); - } - } - return ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE; -} - -/** - @brief Send HID Boot Mouse Input Report -*/ -uint8_t hids_device_send_boot_mouse_input_report(hci_con_handle_t con_handle, const uint8_t * report, uint16_t report_len) { - hids_device_t * instance = hids_device_get_instance_for_con_handle(con_handle); - if (!instance) { - log_error("no instance for handle 0x%02x", con_handle); - return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; - } - return att_server_notify(con_handle, instance->hid_boot_mouse_input_value_handle, report, report_len); -} - -/** - @brief Send HID Boot Mouse Input Report -*/ -uint8_t hids_device_send_boot_keyboard_input_report(hci_con_handle_t con_handle, const uint8_t * report, uint16_t report_len) { - hids_device_t * instance = hids_device_get_instance_for_con_handle(con_handle); - if (!instance) { - log_error("no instance for handle 0x%02x", con_handle); - return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER; - } - return att_server_notify(con_handle, instance->hid_boot_keyboard_input_value_handle, report, report_len); -} - -#endif diff --git a/cores/rp2040/sdkoverride/hids_device.h b/cores/rp2040/sdkoverride/hids_device.h deleted file mode 100644 index f98b5c3bb..000000000 --- a/cores/rp2040/sdkoverride/hids_device.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - Copyright (C) 2014 BlueKitchen GmbH - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the names of - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - 4. Any redistribution, use, or modification is done solely for - personal benefit and not for any commercial purpose or for - monetary gain. - - THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN - GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - Please inquire about commercial licensing options at - contact@bluekitchen-gmbh.com - -*/ - -/** - @title HID Service Server - -*/ - -#ifndef HIDS_DEVICE_H -#define HIDS_DEVICE_H - -#if defined ENABLE_CLASSIC - -#include -#include -#include "btstack_defines.h" -#include "btstack_hid.h" -#include "bluetooth.h" - -#if defined __cplusplus -extern "C" { -#endif - - /* API_START */ - - typedef struct { - uint16_t value_handle; - uint16_t client_configuration_handle; - uint16_t client_configuration_value; - - hid_report_type_t type; - uint16_t id; - } hids_device_report_t; - - /** - @text Implementation of the GATT HIDS Device - To use with your application, add '#import ' to your .gatt file - */ - - /** - @brief Set up HIDS Device with single INPUT, OUTPUT and FEATURE report - */ - void hids_device_init(uint8_t hid_country_code, const uint8_t * hid_descriptor, uint16_t hid_descriptor_size); - - /** - @brief Set up HIDS Device for multiple instances of INPUT, OUTPUT and FEATURE reports - */ - void hids_device_init_with_storage(uint8_t hid_country_code, const uint8_t * hid_descriptor, uint16_t hid_descriptor_size, - uint16_t num_reports, hids_device_report_t * report_storage); - - /** - @brief Register callback for the HIDS Device client. - @param callback - */ - void hids_device_register_packet_handler(btstack_packet_handler_t callback); - - /** - @brief Request can send now event to send HID Report - Generates an HIDS_SUBEVENT_CAN_SEND_NOW subevent - @param hid_cid - */ - void hids_device_request_can_send_now_event(hci_con_handle_t con_handle); - - /** - @brief Send HID Input Report for Report ID - @param con_handle - @param report_id - @param report - @param report_len - @returns status - */ - uint8_t hids_device_send_input_report_for_id(hci_con_handle_t con_handle, uint16_t report_id, const uint8_t * report, uint16_t report_len); - - /** - @brief Send HID Input Report for first Input Report - @param con_handle - @param report - @param report_len - @returns status - */ - uint8_t hids_device_send_input_report(hci_con_handle_t con_handle, const uint8_t * report, uint16_t report_len); - - /** - @brief Send HID Boot Mouse Input Report - @param con_handle - @param report - @param report_len - @returns status - */ - uint8_t hids_device_send_boot_mouse_input_report(hci_con_handle_t con_handle, const uint8_t * report, uint16_t report_len); - - /** - @brief Send HID Boot Mouse Input Report - @param con_handle - @param report - @param report_len - @returns status - */ - uint8_t hids_device_send_boot_keyboard_input_report(hci_con_handle_t con_handle, const uint8_t * report, uint16_t report_len); - - /* API_END */ - -#if defined __cplusplus -} -#endif - -#endif - -#endif diff --git a/libraries/HID_Bluetooth/src/PicoBluetoothBLEHID.h b/libraries/HID_Bluetooth/src/PicoBluetoothBLEHID.h index f251bfc72..b3f26fbdc 100644 --- a/libraries/HID_Bluetooth/src/PicoBluetoothBLEHID.h +++ b/libraries/HID_Bluetooth/src/PicoBluetoothBLEHID.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include <_needsbt.h> #include #include @@ -35,8 +35,8 @@ #define HID_REPORT_TYPE_OUTPUT HID_REPORT_TYPE_OUTPUT_BT #define HID_REPORT_TYPE_FEATURE HID_REPORT_TYPE_FEATURE_BT #define hid_report_type_t hid_report_type_t_bt -#include -#include +#include +#include #include #undef hid_report_type_t #undef HID_REPORT_TYPE_FEATURE diff --git a/libraries/HID_Bluetooth/src/PicoBluetoothHID.h b/libraries/HID_Bluetooth/src/PicoBluetoothHID.h index ae0fa0578..484cd7e63 100644 --- a/libraries/HID_Bluetooth/src/PicoBluetoothHID.h +++ b/libraries/HID_Bluetooth/src/PicoBluetoothHID.h @@ -21,7 +21,7 @@ #pragma once -#include +#include #include <_needsbt.h> #include #include @@ -33,8 +33,8 @@ #define HID_REPORT_TYPE_OUTPUT HID_REPORT_TYPE_OUTPUT_BT #define HID_REPORT_TYPE_FEATURE HID_REPORT_TYPE_FEATURE_BT #define hid_report_type_t hid_report_type_t_bt -#include -#include +#include +#include #include #undef hid_report_type_t #undef HID_REPORT_TYPE_FEATURE