remove signature from att_write callback, add connection handle to att read and write callbacks, update examples

This commit is contained in:
matthias.ringwald 2014-06-10 21:44:05 +00:00
parent baecf7ef51
commit 7763678c43
6 changed files with 48 additions and 63 deletions

View File

@ -160,7 +160,7 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
#include "profile.h"
// write requests
static int att_write_callback(uint16_t handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size, signature_t * signature){
static int att_write_callback(uint16_t con_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
printf("WRITE Callback, handle %04x\n", handle);
switch(handle){
case ATT_CHARACTERISTIC_FFF1_01_VALUE_HANDLE:

View File

@ -164,18 +164,18 @@ uint16_t att_uuid_for_handle(uint16_t handle){
}
// end of client API
static void att_update_value_len(att_iterator_t *it){
static void att_update_value_len(att_iterator_t *it, uint16_t con_handle){
if ((it->flags & ATT_PROPERTY_DYNAMIC) == 0 || !att_read_callback) return;
it->value_len = (*att_read_callback)(it->handle, 0, NULL, 0);
it->value_len = (*att_read_callback)(con_handle, it->handle, 0, 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){
static int att_copy_value(att_iterator_t *it, uint16_t offset, uint8_t * buffer, uint16_t buffer_size, uint16_t con_handle){
// DYNAMIC
if ((it->flags & ATT_PROPERTY_DYNAMIC) && att_read_callback) {
return (*att_read_callback)(it->handle, offset, buffer, buffer_size);
return (*att_read_callback)(con_handle, it->handle, offset, buffer, buffer_size);
}
// STATIC
@ -498,7 +498,7 @@ static uint16_t handle_read_by_type_request2(att_connection_t * att_connection,
error_code = att_validate_security(att_connection, &it);
if (error_code) break;
att_update_value_len(&it);
att_update_value_len(&it, att_connection->con_handle);
// check if value has same len as last one
uint16_t this_pair_len = 2 + it.value_len;
@ -525,7 +525,7 @@ static uint16_t handle_read_by_type_request2(att_connection_t * att_connection,
// store
bt_store_16(response_buffer, offset, it.handle);
offset += 2;
uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len);
uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len, att_connection->con_handle);
offset += bytes_copied;
}
@ -585,7 +585,7 @@ static uint16_t handle_read_request2(att_connection_t * att_connection, uint8_t
return setup_error(response_buffer, request_type, handle, error_code);
}
att_update_value_len(&it);
att_update_value_len(&it, att_connection->con_handle);
uint16_t offset = 1;
// limit data
@ -594,7 +594,7 @@ static uint16_t handle_read_request2(att_connection_t * att_connection, uint8_t
}
// store
uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len);
uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len, att_connection->con_handle);
offset += bytes_copied;
response_buffer[0] = ATT_READ_RESPONSE;
@ -630,7 +630,7 @@ static uint16_t handle_read_blob_request2(att_connection_t * att_connection, uin
return setup_error(response_buffer, request_type, handle, error_code);
}
att_update_value_len(&it);
att_update_value_len(&it, att_connection->con_handle);
if (value_offset > it.value_len){
return setup_error_invalid_offset(response_buffer, request_type, handle);
@ -643,7 +643,7 @@ static uint16_t handle_read_blob_request2(att_connection_t * att_connection, uin
}
// store
uint16_t bytes_copied = att_copy_value(&it, value_offset, response_buffer + offset, it.value_len - value_offset);
uint16_t bytes_copied = att_copy_value(&it, value_offset, response_buffer + offset, it.value_len - value_offset, att_connection->con_handle);
offset += bytes_copied;
response_buffer[0] = ATT_READ_BLOB_RESPONSE;
@ -696,7 +696,7 @@ static uint16_t handle_read_multiple_request2(att_connection_t * att_connection,
error_code = att_validate_security(att_connection, &it);
if (error_code) break;
att_update_value_len(&it);
att_update_value_len(&it, att_connection->con_handle);
// limit data
if (offset + it.value_len > response_buffer_size) {
@ -704,7 +704,7 @@ static uint16_t handle_read_multiple_request2(att_connection_t * att_connection,
}
// store
uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len);
uint16_t bytes_copied = att_copy_value(&it, 0, response_buffer + offset, it.value_len, att_connection->con_handle);
offset += bytes_copied;
}
@ -866,7 +866,7 @@ static uint16_t handle_write_request(att_connection_t * att_connection, uint8_t
if (error_code) {
return setup_error(response_buffer, request_type, handle, error_code);
}
error_code = (*att_write_callback)(handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3, NULL);
error_code = (*att_write_callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3);
if (error_code) {
return setup_error(response_buffer, request_type, handle, error_code);
}
@ -903,7 +903,7 @@ static uint16_t handle_prepare_write_request(att_connection_t * att_connection,
return setup_error(response_buffer, request_type, handle, error_code);
}
error_code = (*att_write_callback)(handle, ATT_TRANSACTION_MODE_ACTIVE, offset, request_buffer + 5, request_len - 5, NULL);
error_code = (*att_write_callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_ACTIVE, offset, request_buffer + 5, request_len - 5);
switch (error_code){
case 0:
break;
@ -925,9 +925,9 @@ static uint16_t handle_prepare_write_request(att_connection_t * att_connection,
/*
* @brief transcation queue of prepared writes, e.g., after disconnect
*/
void att_clear_transaction_queue(){
void att_clear_transaction_queue(att_connection_t * att_connection){
if (!att_write_callback) return;
(*att_write_callback)(0, ATT_TRANSACTION_MODE_CANCEL, 0, NULL, 0, NULL);
(*att_write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_CANCEL, 0, NULL, 0);
}
// MARK: ATT_EXECUTE_WRITE_REQUEST 0x18
@ -943,15 +943,15 @@ static uint16_t handle_execute_write_request(att_connection_t * att_connection,
if (request_buffer[1]) {
// deliver queued errors
if (att_prepare_write_error_code){
att_clear_transaction_queue();
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)(0, ATT_TRANSACTION_MODE_EXECUTE, 0, NULL, 0, NULL);
(*att_write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_EXECUTE, 0, NULL, 0);
} else {
att_clear_transaction_queue();
att_clear_transaction_queue(att_connection);
}
response_buffer[0] = ATT_EXECUTE_WRITE_RESPONSE;
return 1;
@ -971,25 +971,7 @@ static void handle_write_command(att_connection_t * att_connection, uint8_t * re
if ((it.flags & ATT_PROPERTY_DYNAMIC) == 0) return;
if ((it.flags & ATT_PROPERTY_WRITE_WITHOUT_RESPONSE) == 0) return;
if (att_validate_security(att_connection, &it)) return;
(*att_write_callback)(handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3, NULL);
}
// MARK: ATT_SIGNED_WRITE_COMAND 0xD2
// Core 4.0, vol 3, part F, 3.4.5.4
// "No Error Response or Write Response shall be sent in response to this command"
static void handle_signed_write_command(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 < 15) return;
if (!att_write_callback) return;
uint16_t handle = READ_BT_16(request_buffer, 1);
att_iterator_t it;
int ok = att_find_handle(&it, handle);
if (!ok) return;
if ((it.flags & ATT_PROPERTY_DYNAMIC) == 0) return;
if ((it.flags & ATT_PROPERTY_AUTHENTICATED_SIGNED_WRITE) == 0) return;
if (att_validate_security(att_connection, &it)) return;
(*att_write_callback)(handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3 - 12, (signature_t *) request_buffer + request_len - 12);
(*att_write_callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3);
}
// MARK: helper for ATT_HANDLE_VALUE_NOTIFICATION and ATT_HANDLE_VALUE_INDICATION
@ -1074,7 +1056,7 @@ uint16_t att_handle_request(att_connection_t * att_connection,
handle_write_command(att_connection, request_buffer, request_len, response_buffer, response_buffer_size);
break;
case ATT_SIGNED_WRITE_COMAND:
handle_signed_write_command(att_connection, request_buffer, request_len, response_buffer, response_buffer_size);
printf("handle_signed_write_command preprocessed by att_server.c\n");
break;
default:
printf("Unhandled ATT Command: %02X, DATA: ", request_buffer[0]);

View File

@ -148,29 +148,33 @@ extern "C" {
typedef struct att_connection {
uint16_t con_handle;
uint16_t mtu;
uint8_t encryption_key_size;
uint8_t authenticated;
uint8_t authorized;
} att_connection_t;
typedef uint8_t signature_t[12];
// 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
// @param con_handle of hci le connection
// @param attribute_handle to be read
// @param offset defines start of attribute value
typedef uint16_t (*att_read_callback_t)(uint16_t handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size);
// @param buffer
// @param buffer_size
typedef uint16_t (*att_read_callback_t)(uint16_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size);
// ATT Client Write Callback for Dynamic Data
// @param handle to be written
// @param con_handle of hci le connection
// @param attribute_handle to be written
// @param transaction - ATT_TRANSACTION_MODE_NONE for regular writes, ATT_TRANSACTION_MODE_ACTIVE for prepared writes and ATT_TRANSACTION_MODE_EXECUTE
// @param offset into the value - used for queued writes and long attributes
// @param buffer
// @param buffer_size
// @param signature used for signed write commmands
// @returns 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)(uint16_t handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size, signature_t * signature);
typedef int (*att_write_callback_t)(uint16_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size);
// MARK: ATT Operations

View File

@ -75,7 +75,6 @@ static att_server_state_t att_server_state;
static uint8_t att_client_addr_type;
static bd_addr_t att_client_address;
static uint16_t att_request_handle = 0;
static uint16_t att_request_size = 0;
static uint8_t att_request_buffer[28];
@ -103,7 +102,7 @@ static void att_handle_value_indication_notify_client(uint8_t status, uint16_t c
static void att_handle_value_indication_timeout(timer_source_t *ts){
uint16_t att_handle = att_handle_value_indication_handle;
att_handle_value_indication_notify_client(ATT_HANDLE_VALUE_INDICATION_TIMEOUT, att_request_handle, att_handle);
att_handle_value_indication_notify_client(ATT_HANDLE_VALUE_INDICATION_TIMEOUT, att_connection.con_handle, att_handle);
}
static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
@ -121,10 +120,10 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
switch (packet[2]) {
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
// store connection info
att_request_handle = READ_BT_16(packet, 4);
att_client_addr_type = packet[7];
bt_flip_addr(att_client_address, &packet[8]);
// reset connection properties
att_connection.con_handle = READ_BT_16(packet, 4);
att_connection.mtu = 23;
att_connection.encryption_key_size = 0;
att_connection.authenticated = 0;
@ -138,18 +137,18 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
case HCI_EVENT_ENCRYPTION_CHANGE:
// check handle
if (att_request_handle != READ_BT_16(packet, 3)) break;
if (att_connection.con_handle != READ_BT_16(packet, 3)) break;
att_connection.encryption_key_size = sm_encryption_key_size(att_client_addr_type, att_client_address);
att_connection.authenticated = sm_authenticated(att_client_addr_type, att_client_address);
break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
att_clear_transaction_queue(&att_connection);
att_connection.con_handle = 0;
att_handle_value_indication_handle = 0; // reset error state
// restart advertising if we have been connected before
// -> avoid sending advertise enable a second time before command complete was received
att_server_state = ATT_SERVER_IDLE;
att_request_handle = 0;
att_handle_value_indication_handle = 0; // reset error state
att_clear_transaction_queue();
break;
case SM_IDENTITY_RESOLVING_STARTED:
@ -284,7 +283,7 @@ static void att_run(void){
return;
}
l2cap_send_prepared_connectionless(att_request_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, att_response_size);
l2cap_send_prepared_connectionless(att_connection.con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, att_response_size);
break;
}
}
@ -297,7 +296,7 @@ static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pa
run_loop_remove_timer(&att_handle_value_indication_timer);
uint16_t att_handle = att_handle_value_indication_handle;
att_handle_value_indication_handle = 0;
att_handle_value_indication_notify_client(0, att_request_handle, att_handle);
att_handle_value_indication_notify_client(0, att_connection.con_handle, att_handle);
return;
}
@ -333,7 +332,7 @@ void att_server_register_packet_handler(btstack_packet_handler_t handler){
}
int att_server_can_send(){
if (att_request_handle == 0) return 0;
if (att_connection.con_handle == 0) return 0;
return l2cap_can_send_connectionless_packet_now();
}
@ -343,7 +342,7 @@ int att_server_notify(uint16_t handle, uint8_t *value, uint16_t value_len){
l2cap_reserve_packet_buffer();
uint8_t * packet_buffer = l2cap_get_outgoing_buffer();
uint16_t size = att_prepare_handle_value_notification(&att_connection, handle, value, value_len, packet_buffer);
return l2cap_send_prepared_connectionless(att_request_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, size);
return l2cap_send_prepared_connectionless(att_connection.con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, size);
}
int att_server_indicate(uint16_t handle, uint8_t *value, uint16_t value_len){
@ -359,6 +358,6 @@ int att_server_indicate(uint16_t handle, uint8_t *value, uint16_t value_len){
l2cap_reserve_packet_buffer();
uint8_t * packet_buffer = l2cap_get_outgoing_buffer();
uint16_t size = att_prepare_handle_value_indication(&att_connection, handle, value, value_len, packet_buffer);
l2cap_send_prepared_connectionless(att_request_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, size);
l2cap_send_prepared_connectionless(att_connection.con_handle, L2CAP_CID_ATTRIBUTE_PROTOCOL, size);
return 0;
}

View File

@ -301,7 +301,7 @@ static void app_run(){
// - if buffer == NULL, don't copy data, just return size of value
// - if buffer != NULL, copy data and return number bytes copied
// @param offset defines start of attribute value
static uint16_t att_read_callback(uint16_t handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
static uint16_t att_read_callback(uint16_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
printf("READ Callback, handle %04x, offset %u, buffer size %u\n", handle, offset, buffer_size);
uint16_t att_value_len;
@ -374,7 +374,7 @@ static uint16_t att_read_callback(uint16_t handle, uint16_t offset, uint8_t * bu
}
// write requests
static int att_write_callback(uint16_t handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size, signature_t * signature){
static int att_write_callback(uint16_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
printf("WRITE Callback, handle %04x, mode %u, offset %u, data: ", handle, transaction_mode, offset);
hexdump(buffer, buffer_size);

View File

@ -165,8 +165,8 @@ static void packet_handler (void * connection, uint8_t packet_type, uint16_t cha
// - if buffer == NULL, don't copy data, just return size of value
// - if buffer != NULL, copy data and return number bytes copied
// @param offset defines start of attribute value
static uint16_t att_read_callback(uint16_t handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
if (handle == ATT_CHARACTERISTIC_0000FF11_0000_1000_8000_00805F9B34FB_01_VALUE_HANDLE){
static uint16_t att_read_callback(uint16_t con_handle, uint16_t att_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
if (att_handle == ATT_CHARACTERISTIC_0000FF11_0000_1000_8000_00805F9B34FB_01_VALUE_HANDLE){
if (buffer){
memcpy(buffer, &counter_string[offset], counter_string_len - offset);
}
@ -176,10 +176,10 @@ static uint16_t att_read_callback(uint16_t handle, uint16_t offset, uint8_t * bu
}
// write requests
static int att_write_callback(uint16_t handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size, signature_t * signature){
static int att_write_callback(uint16_t con_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
// printf("WRITE Callback, handle %04x, mode %u, offset %u, data: ", handle, transaction_mode, offset);
// hexdump(buffer, buffer_size);
if (handle != ATT_CHARACTERISTIC_0000FF11_0000_1000_8000_00805F9B34FB_01_CLIENT_CONFIGURATION_HANDLE) return 0;
if (att_handle != ATT_CHARACTERISTIC_0000FF11_0000_1000_8000_00805F9B34FB_01_CLIENT_CONFIGURATION_HANDLE) return 0;
le_notification_enabled = READ_BT_16(buffer, 0) == GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION;
return 0;
}