mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-01-05 21:59:45 +00:00
att: moved service handling from att_db into att_server, att_register_service_handler -> att_server_register_service_handler
This commit is contained in:
parent
304b2f4d7e
commit
3d71c7a4e0
@ -71,8 +71,6 @@ static att_write_callback_t att_write_callback = NULL;
|
||||
static uint8_t att_prepare_write_error_code = 0;
|
||||
static uint16_t att_prepare_write_error_handle = 0x0000;
|
||||
|
||||
static btstack_linked_list_t service_handlers;
|
||||
|
||||
// new java-style iterator
|
||||
typedef struct att_iterator {
|
||||
// private
|
||||
@ -156,30 +154,6 @@ static int att_find_handle(att_iterator_t *it, uint16_t handle){
|
||||
return 0;
|
||||
}
|
||||
|
||||
static att_service_handler_t * att_service_handler_for_handle(uint16_t handle){
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &service_handlers);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
att_service_handler_t * handler = (att_service_handler_t*) btstack_linked_list_iterator_next(&it);
|
||||
if (handler->start_handle > handle) continue;
|
||||
if (handler->end_handle < handle) continue;
|
||||
return handler;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static att_read_callback_t att_read_callback_for_handle(uint16_t handle){
|
||||
att_service_handler_t * handler = att_service_handler_for_handle(handle);
|
||||
if (handler) return handler->read_callback;
|
||||
return att_read_callback;
|
||||
}
|
||||
|
||||
static att_write_callback_t att_write_callback_for_handle(uint16_t handle){
|
||||
att_service_handler_t * handler = att_service_handler_for_handle(handle);
|
||||
if (handler) return handler->write_callback;
|
||||
return att_write_callback;
|
||||
}
|
||||
|
||||
// experimental client API
|
||||
uint16_t att_uuid_for_handle(uint16_t attribute_handle){
|
||||
att_iterator_t it;
|
||||
@ -192,9 +166,7 @@ uint16_t att_uuid_for_handle(uint16_t attribute_handle){
|
||||
|
||||
static void att_update_value_len(att_iterator_t *it, hci_con_handle_t con_handle){
|
||||
if ((it->flags & ATT_PROPERTY_DYNAMIC) == 0) return;
|
||||
att_read_callback_t callback = att_read_callback_for_handle(it->handle);
|
||||
if (!callback) return;
|
||||
it->value_len = (*callback)(con_handle, it->handle, 0, NULL, 0);
|
||||
it->value_len = (*att_read_callback)(con_handle, it->handle, 0, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -203,9 +175,7 @@ static int att_copy_value(att_iterator_t *it, uint16_t offset, uint8_t * buffer,
|
||||
|
||||
// DYNAMIC
|
||||
if (it->flags & ATT_PROPERTY_DYNAMIC){
|
||||
att_read_callback_t callback = att_read_callback_for_handle(it->handle);
|
||||
if (!callback) return 0;
|
||||
return (*callback)(con_handle, it->handle, offset, buffer, buffer_size);
|
||||
return (*att_read_callback)(con_handle, it->handle, offset, buffer, buffer_size);
|
||||
}
|
||||
|
||||
// STATIC
|
||||
@ -906,8 +876,7 @@ static uint16_t handle_write_request(att_connection_t * att_connection, uint8_t
|
||||
if (!ok) {
|
||||
return setup_error_invalid_handle(response_buffer, request_type, handle);
|
||||
}
|
||||
att_write_callback_t callback = att_write_callback_for_handle(handle);
|
||||
if (!callback) {
|
||||
if (!att_write_callback) {
|
||||
return setup_error_write_not_permitted(response_buffer, request_type, handle);
|
||||
}
|
||||
if ((it.flags & ATT_PROPERTY_WRITE) == 0) {
|
||||
@ -921,7 +890,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 = (*callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3);
|
||||
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);
|
||||
}
|
||||
@ -940,8 +909,7 @@ static uint16_t handle_prepare_write_request(att_connection_t * att_connection,
|
||||
|
||||
uint16_t handle = little_endian_read_16(request_buffer, 1);
|
||||
uint16_t offset = little_endian_read_16(request_buffer, 3);
|
||||
att_write_callback_t callback = att_write_callback_for_handle(handle);
|
||||
if (!callback) {
|
||||
if (!att_write_callback) {
|
||||
return setup_error_write_not_permitted(response_buffer, request_type, handle);
|
||||
}
|
||||
att_iterator_t it;
|
||||
@ -961,7 +929,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 = (*callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_ACTIVE, offset, request_buffer + 5, request_len - 5);
|
||||
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;
|
||||
@ -980,38 +948,11 @@ static uint16_t handle_prepare_write_request(att_connection_t * att_connection,
|
||||
return request_len;
|
||||
}
|
||||
|
||||
static void att_notify_write_callbacks(att_connection_t * att_connection, uint16_t transaction_mode){
|
||||
// notify all
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &service_handlers);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
att_service_handler_t * handler = (att_service_handler_t*) btstack_linked_list_iterator_next(&it);
|
||||
if (!handler->write_callback) continue;
|
||||
(*handler->write_callback)(att_connection->con_handle, 0, transaction_mode, 0, NULL, 0);
|
||||
}
|
||||
if (!att_write_callback) return;
|
||||
(*att_write_callback)(att_connection->con_handle, 0, transaction_mode, 0, NULL, 0);
|
||||
}
|
||||
|
||||
// returns first reported error or 0
|
||||
static uint8_t att_validate_prepared_write(att_connection_t * att_connection){
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &service_handlers);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
att_service_handler_t * handler = (att_service_handler_t*) btstack_linked_list_iterator_next(&it);
|
||||
if (!handler->write_callback) continue;
|
||||
uint8_t error_code = (*handler->write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_VALIDATE, 0, NULL, 0);
|
||||
if (error_code) return error_code;
|
||||
}
|
||||
if (!att_write_callback) return 0;
|
||||
return (*att_write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_VALIDATE, 0, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief transcation queue of prepared writes, e.g., after disconnect
|
||||
*/
|
||||
void att_clear_transaction_queue(att_connection_t * att_connection){
|
||||
att_notify_write_callbacks(att_connection, ATT_TRANSACTION_MODE_CANCEL);
|
||||
(*att_write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_CANCEL, 0, NULL, 0);
|
||||
}
|
||||
|
||||
// MARK: ATT_EXECUTE_WRITE_REQUEST 0x18
|
||||
@ -1026,7 +967,7 @@ static uint16_t handle_execute_write_request(att_connection_t * att_connection,
|
||||
if (request_buffer[1]) {
|
||||
// validate queued write
|
||||
if (att_prepare_write_error_code == 0){
|
||||
att_prepare_write_error_code = att_validate_prepared_write(att_connection);
|
||||
att_prepare_write_error_code = (*att_write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_VALIDATE, 0, NULL, 0);
|
||||
}
|
||||
// deliver queued errors
|
||||
if (att_prepare_write_error_code){
|
||||
@ -1036,7 +977,7 @@ static uint16_t handle_execute_write_request(att_connection_t * att_connection,
|
||||
att_prepare_write_reset();
|
||||
return setup_error(response_buffer, request_type, handle, error_code);
|
||||
}
|
||||
att_notify_write_callbacks(att_connection, ATT_TRANSACTION_MODE_EXECUTE);
|
||||
att_write_callback(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_EXECUTE, 0, NULL, 0);
|
||||
} else {
|
||||
att_clear_transaction_queue(att_connection);
|
||||
}
|
||||
@ -1054,8 +995,7 @@ static void handle_write_command(att_connection_t * att_connection, uint8_t * re
|
||||
UNUSED(response_buffer_size);
|
||||
|
||||
uint16_t handle = little_endian_read_16(request_buffer, 1);
|
||||
att_write_callback_t callback = att_write_callback_for_handle(handle);
|
||||
if (!callback) return;
|
||||
if (!att_write_callback) return;
|
||||
|
||||
att_iterator_t it;
|
||||
int ok = att_find_handle(&it, handle);
|
||||
@ -1063,7 +1003,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;
|
||||
(*callback)(att_connection->con_handle, handle, ATT_TRANSACTION_MODE_NONE, 0, request_buffer + 3, request_len - 3);
|
||||
(*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
|
||||
@ -1160,19 +1100,6 @@ uint16_t att_handle_request(att_connection_t * att_connection,
|
||||
return response_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief register read/write callbacks for specific handle range
|
||||
* @param att_service_handler_t
|
||||
*/
|
||||
void att_register_service_handler(att_service_handler_t * handler){
|
||||
if (att_service_handler_for_handle(handler->start_handle) ||
|
||||
att_service_handler_for_handle(handler->end_handle)){
|
||||
log_error("att_register_service_handler: handler for range 0x%04x-0x%04x already registered", handler->start_handle, handler->end_handle);
|
||||
return;
|
||||
}
|
||||
btstack_linked_list_add(&service_handlers, (btstack_linked_item_t*) handler);
|
||||
}
|
||||
|
||||
// returns 1 if service found. only primary service.
|
||||
int gatt_server_get_get_handle_range_for_service_with_uuid16(uint16_t uuid16, uint16_t * start_handle, uint16_t * end_handle){
|
||||
uint16_t in_group = 0;
|
||||
|
@ -170,13 +170,6 @@ uint16_t att_prepare_handle_value_indication(att_connection_t * att_connection,
|
||||
*/
|
||||
void att_clear_transaction_queue(att_connection_t * att_connection);
|
||||
|
||||
/**
|
||||
* @brief register read/write callbacks for specific handle range
|
||||
* @param att_service_handler_t
|
||||
*/
|
||||
void att_register_service_handler(att_service_handler_t * handler);
|
||||
|
||||
|
||||
// att_read_callback helpers for a various data types
|
||||
|
||||
/*
|
||||
|
@ -72,8 +72,12 @@ static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
static btstack_packet_callback_registration_t sm_event_callback_registration;
|
||||
static btstack_packet_handler_t att_client_packet_handler = NULL;
|
||||
static btstack_linked_list_t can_send_now_clients;
|
||||
static btstack_linked_list_t service_handlers;
|
||||
static uint8_t att_client_waiting_for_can_send;
|
||||
|
||||
static att_read_callback_t att_server_client_read_callback;
|
||||
static att_write_callback_t att_server_client_write_callback;
|
||||
|
||||
static att_server_t * att_server_for_handle(hci_con_handle_t con_handle){
|
||||
hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
|
||||
if (!hci_connection) return NULL;
|
||||
@ -456,8 +460,99 @@ static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pa
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// gatt service management
|
||||
static att_service_handler_t * att_service_handler_for_handle(uint16_t handle){
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &service_handlers);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
att_service_handler_t * handler = (att_service_handler_t*) btstack_linked_list_iterator_next(&it);
|
||||
if (handler->start_handle > handle) continue;
|
||||
if (handler->end_handle < handle) continue;
|
||||
return handler;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
static att_read_callback_t att_server_read_callback_for_handle(uint16_t handle){
|
||||
att_service_handler_t * handler = att_service_handler_for_handle(handle);
|
||||
if (handler) return handler->read_callback;
|
||||
return att_server_client_read_callback;
|
||||
}
|
||||
|
||||
static att_write_callback_t att_server_write_callback_for_handle(uint16_t handle){
|
||||
att_service_handler_t * handler = att_service_handler_for_handle(handle);
|
||||
if (handler) return handler->write_callback;
|
||||
return att_server_client_write_callback;
|
||||
}
|
||||
|
||||
static void att_notify_write_callbacks(hci_con_handle_t con_handle, uint16_t transaction_mode){
|
||||
// notify all callbacks
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &service_handlers);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
att_service_handler_t * handler = (att_service_handler_t*) btstack_linked_list_iterator_next(&it);
|
||||
if (!handler->write_callback) continue;
|
||||
(*handler->write_callback)(con_handle, 0, transaction_mode, 0, NULL, 0);
|
||||
}
|
||||
if (!att_server_client_write_callback) return;
|
||||
(*att_server_client_write_callback)(con_handle, 0, transaction_mode, 0, NULL, 0);
|
||||
}
|
||||
|
||||
// returns first reported error or 0
|
||||
static uint8_t att_validate_prepared_write(hci_con_handle_t con_handle){
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &service_handlers);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
att_service_handler_t * handler = (att_service_handler_t*) btstack_linked_list_iterator_next(&it);
|
||||
if (!handler->write_callback) continue;
|
||||
uint8_t error_code = (*handler->write_callback)(con_handle, 0, ATT_TRANSACTION_MODE_VALIDATE, 0, NULL, 0);
|
||||
if (error_code) return error_code;
|
||||
}
|
||||
if (!att_server_client_write_callback) return 0;
|
||||
return (*att_server_client_write_callback)(con_handle, 0, ATT_TRANSACTION_MODE_VALIDATE, 0, NULL, 0);
|
||||
}
|
||||
|
||||
static uint16_t att_server_read_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size){
|
||||
att_read_callback_t callback = att_server_read_callback_for_handle(attribute_handle);
|
||||
return (*callback)(con_handle, attribute_handle, offset, buffer, buffer_size);
|
||||
}
|
||||
|
||||
static int att_server_write_callback(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size){
|
||||
switch (transaction_mode){
|
||||
case ATT_TRANSACTION_MODE_VALIDATE:
|
||||
return att_validate_prepared_write(con_handle);
|
||||
case ATT_TRANSACTION_MODE_EXECUTE:
|
||||
case ATT_TRANSACTION_MODE_CANCEL:
|
||||
att_notify_write_callbacks(con_handle, transaction_mode);
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
att_write_callback_t callback = att_server_write_callback_for_handle(attribute_handle);
|
||||
|
||||
// TODO: check if write for ccc, if yes store in tlv
|
||||
return (*callback)(con_handle, attribute_handle, transaction_mode, offset, buffer, buffer_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief register read/write callbacks for specific handle range
|
||||
* @param att_service_handler_t
|
||||
*/
|
||||
void att_server_register_service_handler(att_service_handler_t * handler){
|
||||
if (att_service_handler_for_handle(handler->start_handle) ||
|
||||
att_service_handler_for_handle(handler->end_handle)){
|
||||
log_error("handler for range 0x%04x-0x%04x already registered", handler->start_handle, handler->end_handle);
|
||||
return;
|
||||
}
|
||||
btstack_linked_list_add(&service_handlers, (btstack_linked_item_t*) handler);
|
||||
}
|
||||
|
||||
void att_server_init(uint8_t const * db, att_read_callback_t read_callback, att_write_callback_t write_callback){
|
||||
|
||||
// store callbacks
|
||||
att_server_client_read_callback = read_callback;
|
||||
att_server_client_write_callback = write_callback;
|
||||
|
||||
// register for HCI Events
|
||||
hci_event_callback_registration.callback = &att_event_packet_handler;
|
||||
hci_add_event_handler(&hci_event_callback_registration);
|
||||
@ -470,8 +565,8 @@ void att_server_init(uint8_t const * db, att_read_callback_t read_callback, att_
|
||||
att_dispatch_register_server(att_packet_handler);
|
||||
|
||||
att_set_db(db);
|
||||
att_set_read_callback(read_callback);
|
||||
att_set_write_callback(write_callback);
|
||||
att_set_read_callback(att_server_read_callback);
|
||||
att_set_write_callback(att_server_write_callback);
|
||||
|
||||
}
|
||||
|
||||
|
@ -63,6 +63,12 @@ void att_server_init(uint8_t const * db, att_read_callback_t read_callback, att_
|
||||
*/
|
||||
void att_server_register_packet_handler(btstack_packet_handler_t handler);
|
||||
|
||||
/**
|
||||
* @brief register read/write callbacks for specific handle range
|
||||
* @param att_service_handler_t
|
||||
*/
|
||||
void att_server_register_service_handler(att_service_handler_t * handler);
|
||||
|
||||
/*
|
||||
* @brief tests if a notification or indication can be send right now
|
||||
* @param con_handle
|
||||
|
@ -112,12 +112,12 @@ void battery_service_server_init(uint8_t value){
|
||||
battery_value_handle_value = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
|
||||
battery_value_handle_client_configuration = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL);
|
||||
|
||||
// register service with ATT DB
|
||||
// register service with ATT Server
|
||||
battery_service.start_handle = start_handle;
|
||||
battery_service.end_handle = end_handle;
|
||||
battery_service.read_callback = &battery_service_read_callback;
|
||||
battery_service.write_callback = &battery_service_write_callback;
|
||||
att_register_service_handler(&battery_service);
|
||||
att_server_register_service_handler(&battery_service);
|
||||
}
|
||||
|
||||
void battery_service_server_set_battery_value(uint8_t value){
|
||||
|
@ -129,12 +129,12 @@ void device_information_service_server_init(void){
|
||||
device_information_fields[i].value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_handle, end_handle, device_information_characteristic_uuids[i]);
|
||||
}
|
||||
|
||||
// register service with ATT DB
|
||||
// register service with ATT Server
|
||||
device_information_service.start_handle = start_handle;
|
||||
device_information_service.end_handle = end_handle;
|
||||
device_information_service.read_callback = &device_information_service_read_callback;
|
||||
device_information_service.write_callback = NULL;
|
||||
att_register_service_handler(&device_information_service);
|
||||
att_server_register_service_handler(&device_information_service);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,12 +196,12 @@ void hids_device_init(uint8_t country_code, const uint8_t * descriptor, uint16_t
|
||||
hid_report_input_value_handle = gatt_server_get_value_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_REPORT);
|
||||
hid_report_input_client_configuration_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(start_handle, end_handle, ORG_BLUETOOTH_CHARACTERISTIC_REPORT);
|
||||
|
||||
// register service with ATT DB
|
||||
// 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_register_service_handler(&hid_service);
|
||||
att_server_register_service_handler(&hid_service);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user