att_sever: call att_read_callback on services with ATT_READ_RESPONSE_PENDING

# Conflicts:
#	CHANGELOG.md
This commit is contained in:
Matthias Ringwald 2024-01-23 15:36:25 +01:00
parent 85878f9d1f
commit c61037cc77
2 changed files with 44 additions and 10 deletions

View File

@ -7,13 +7,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
---
## Unreleased
### Added
- GAP: support coordinated private random address updates
### Fixed
- GAP: allow use of own address type different from gap_random_set_mode() incl. RPA in LE Extended Advertising
- HFP HF: send HF Indicator update only if enabled by AG
- SM: abort pairing with invalid parameter error for encryption key size > 16
- ATT Server: support delayed read responses for registered services
- HFP HF: send HF Indicator update only if enabled by AG
### Changed
## Release v1.6
### Added

View File

@ -77,6 +77,8 @@
#define NVN_NUM_GATT_SERVER_CCC 20
#endif
#define ATT_SERVICE_FLAGS_DELAYED_RESPONSE (1<<0u)
static void att_run_for_context(att_server_t * att_server, att_connection_t * att_connection);
static att_write_callback_t att_server_write_callback_for_handle(uint16_t handle);
static btstack_packet_handler_t att_server_packet_handler_for_handle(uint16_t handle);
@ -112,6 +114,8 @@ static att_write_callback_t att_server_client_write_callback;
// round robin
static hci_con_handle_t att_server_last_can_send_now = HCI_CON_HANDLE_INVALID;
static uint8_t att_server_flags;
#ifdef ENABLE_GATT_OVER_EATT
typedef struct {
btstack_linked_item_t item;
@ -587,7 +591,22 @@ att_server_process_validated_request(att_server_t *att_server, att_connection_t
// callback with handle ATT_READ_RESPONSE_PENDING for reads
if (att_response_size == ATT_READ_RESPONSE_PENDING){
att_server_client_read_callback(att_connection->con_handle, ATT_READ_RESPONSE_PENDING, 0, NULL, 0);
// notify services that returned response pending
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->flags & ATT_SERVICE_FLAGS_DELAYED_RESPONSE) != 0){
handler->flags &= ~ATT_SERVICE_FLAGS_DELAYED_RESPONSE;
handler->read_callback(att_connection->con_handle, ATT_READ_RESPONSE_PENDING, 0, NULL, 0);
}
}
// notify main read callback if it returned response pending
if ((att_server_flags & ATT_SERVICE_FLAGS_DELAYED_RESPONSE) != 0){
// flag was set by read callback
btstack_assert(att_server_client_read_callback != NULL);
(*att_server_client_read_callback)(att_connection->con_handle, ATT_READ_RESPONSE_PENDING, 0, NULL, 0);
}
}
// free reserved buffer
@ -1172,11 +1191,6 @@ static att_service_handler_t * att_service_handler_for_handle(uint16_t handle){
}
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 != NULL) 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);
@ -1218,9 +1232,22 @@ static uint8_t att_validate_prepared_write(hci_con_handle_t con_handle){
}
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);
if (!callback) return 0;
return (*callback)(con_handle, attribute_handle, offset, buffer, buffer_size);
att_service_handler_t * service = att_service_handler_for_handle(attribute_handle);
att_read_callback_t read_callback = (service != NULL) ? service->read_callback : att_server_client_read_callback;
uint16_t result = 0;
if (read_callback != NULL){
result = (*read_callback)(con_handle, attribute_handle, offset, buffer, buffer_size);
#ifdef ENABLE_ATT_DELAYED_RESPONSE
if (result == ATT_READ_RESPONSE_PENDING){
if (service == NULL){
att_server_flags |= ATT_SERVICE_FLAGS_DELAYED_RESPONSE;
} else {
service->flags |= ATT_SERVICE_FLAGS_DELAYED_RESPONSE;
}
}
#endif
}
return result;
}
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){
@ -1467,6 +1494,7 @@ void att_server_deinit(void){
att_server_client_write_callback = NULL;
att_client_packet_handler = NULL;
service_handlers = NULL;
att_server_flags = 0;
}
#ifdef ENABLE_GATT_OVER_EATT