From bb38f0573479840fea287bac2a8c2ae6b5a83aea Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Tue, 1 Nov 2016 15:42:03 +0100 Subject: [PATCH] att_server: allow individual service implementations to register for can send now callbacks --- src/ble/att_server.c | 29 ++++++++++++++++++++++++++++- src/ble/att_server.h | 11 ++++++++++- src/btstack_defines.h | 7 +++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/ble/att_server.c b/src/ble/att_server.c index b4db34c18..236c2e8ce 100644 --- a/src/ble/att_server.c +++ b/src/ble/att_server.c @@ -95,6 +95,8 @@ 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 void att_handle_value_indication_notify_client(uint8_t status, uint16_t client_handle, uint16_t attribute_handle){ if (!att_client_packet_handler) return; @@ -345,12 +347,27 @@ static void att_server_handle_can_send_now(void){ if (att_server_state == ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED){ int sent = att_server_process_validated_request(att_connection.con_handle); - if (sent && att_client_waiting_for_can_send){ + if (sent && (att_client_waiting_for_can_send || !btstack_linked_list_empty(&can_send_now_clients))){ att_dispatch_server_request_can_send_now_event(att_connection.con_handle); return; } } + while (!btstack_linked_list_empty(&can_send_now_clients)){ + // handle first client + btstack_context_callback_registration_t * client = (btstack_context_callback_registration_t*) can_send_now_clients; + btstack_linked_list_remove(&can_send_now_clients, (btstack_linked_item_t *) client); + client->callback(client->context); + + // request again if needed + if (!att_dispatch_server_can_send_now(att_connection.con_handle)){ + if (!btstack_linked_list_empty(&can_send_now_clients) || att_client_waiting_for_can_send){ + att_dispatch_server_request_can_send_now_event(att_connection.con_handle); + } + return; + } + } + if (att_client_waiting_for_can_send){ att_client_waiting_for_can_send = 0; att_emit_can_send_now_event(); @@ -441,6 +458,16 @@ void att_server_request_can_send_now_event(hci_con_handle_t con_handle){ att_dispatch_server_request_can_send_now_event(att_connection.con_handle); } +void att_server_register_can_send_now_callback(btstack_context_callback_registration_t * callback_registration, hci_con_handle_t con_handle){ + // check if can send already + if (att_dispatch_server_can_send_now(con_handle)){ + callback_registration->callback(callback_registration->context); + return; + } + btstack_linked_list_add_tail(&can_send_now_clients, (btstack_linked_item_t*) callback_registration); + att_dispatch_server_request_can_send_now_event(con_handle); +} + int att_server_notify(hci_con_handle_t con_handle, uint16_t attribute_handle, uint8_t *value, uint16_t value_len){ if (!att_dispatch_server_can_send_now(att_connection.con_handle)) return BTSTACK_ACL_BUFFERS_FULL; diff --git a/src/ble/att_server.h b/src/ble/att_server.h index 8f482a36b..e9e576bf3 100644 --- a/src/ble/att_server.h +++ b/src/ble/att_server.h @@ -56,8 +56,9 @@ void att_server_init(uint8_t const * db, att_read_callback_t read_callback, att_ /* * @brief register packet handler for ATT server events: - * - ATT_EVENT_MTU_EXCHANGE_COMPLETE + * - ATT_EVENT_CAN_SEND_NOW * - ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE + * - ATT_EVENT_MTU_EXCHANGE_COMPLETE * @param handler */ void att_server_register_packet_handler(btstack_packet_handler_t handler); @@ -77,6 +78,14 @@ int att_server_can_send_packet_now(hci_con_handle_t con_handle); */ void att_server_request_can_send_now_event(hci_con_handle_t con_handle); +/** + * @brief Request callback when sending is possible + * @note callback might happend during call to this function + * @param callback_registration to point to callback function and context information + * @param con_handle + */ +void att_server_register_can_send_now_callback(btstack_context_callback_registration_t * callback_registration, hci_con_handle_t con_handle); + /* * @brief notify client about attribute value change * @param con_handle diff --git a/src/btstack_defines.h b/src/btstack_defines.h index a6fc4460c..b8a01b41c 100644 --- a/src/btstack_defines.h +++ b/src/btstack_defines.h @@ -61,6 +61,13 @@ typedef struct { btstack_packet_handler_t callback; } btstack_packet_callback_registration_t; +// context callback supporting multiple registrations +typedef struct { + btstack_linked_item_t * item; + void (*callback)(void * context); + void * context; +} btstack_context_callback_registration_t; + /** * @brief 128 bit key used with AES128 in Security Manager */