att_db: add helper functions for auto-pts btpclient

This commit is contained in:
Matthias Ringwald 2019-12-18 17:45:21 +01:00
parent e33c5309b0
commit 44127f4351
2 changed files with 135 additions and 0 deletions

View File

@ -38,6 +38,7 @@
#define BTSTACK_FILE__ "att_db.c"
#include <string.h>
#include <auto-pts/btp.h>
#include "ble/att_db.h"
#include "ble/core.h"
@ -1434,3 +1435,131 @@ uint16_t att_read_callback_handle_byte(uint8_t value, uint16_t offset, uint8_t *
value_buffer[0] = value;
return att_read_callback_handle_blob(value_buffer, sizeof(value_buffer), offset, buffer, buffer_size);
}
#ifdef ENABLE_BTP
#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 & ATT_PROPERTY_READ){
if (flags & ATT_PROPERTY_READ_PERMISSION_BIT_0) {
read_security_level |= 1;
}
if (flags & 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 & ATT_PROPERTY_WRITE_PERMISSION_BIT_0) {
write_security_level |= 1;
}
if (flags & 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){
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);
if (it.handle == 0) break;
if (it.handle < start_handle) continue;
if (it.handle > end_handle) break;
if (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(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 - unclear what is meant by that
response_buffer[pos++] = 0;
// 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;
}
#endif

View File

@ -306,6 +306,12 @@ uint16_t gatt_server_get_client_configuration_handle_for_characteristic_with_uui
*/
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(uint16_t attribute_handle, uint8_t * response_buffer, uint16_t response_buffer_size);
#endif
#if defined __cplusplus
}