att_server: use hci_connection_t instead of att_server_t as function param

This commit is contained in:
Matthias Ringwald 2020-12-28 23:01:42 +01:00
parent 3cd2e1916c
commit 68591e36e9

View File

@ -71,13 +71,13 @@
#define NVN_NUM_GATT_SERVER_CCC 20
#endif
static void att_run_for_context(att_server_t * att_server);
static void att_run_for_context(hci_connection_t * hci_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);
static void att_server_handle_can_send_now(void);
static void att_server_persistent_ccc_restore(att_server_t * att_server);
static void att_server_persistent_ccc_clear(att_server_t * att_server);
static void att_server_handle_att_pdu(att_server_t * att_server, uint8_t * packet, uint16_t size);
static void att_server_persistent_ccc_restore(hci_connection_t * hci_connection);
static void att_server_persistent_ccc_clear(hci_connection_t * hci_connection);
static void att_server_handle_att_pdu(hci_connection_t * hci_connection, uint8_t * packet, uint16_t size);
typedef enum {
ATT_SERVER_RUN_PHASE_1_REQUESTS,
@ -106,39 +106,21 @@ 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 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;
return &hci_connection->att_server;
}
#ifdef ENABLE_GATT_OVER_CLASSIC
static att_server_t * att_server_for_l2cap_cid(uint16_t l2cap_cid){
btstack_linked_list_iterator_t it;
hci_connections_get_iterator(&it);
while(btstack_linked_list_iterator_has_next(&it)){
hci_connection_t * connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
att_server_t * att_server = &connection->att_server;
if (att_server->l2cap_cid == l2cap_cid) return att_server;
}
return NULL;
}
#endif
#ifdef ENABLE_LE_SIGNED_WRITE
static att_server_t * att_server_for_state(att_server_state_t state){
static hci_connection_t * hci_connection_for_state(att_server_state_t state){
btstack_linked_list_iterator_t it;
hci_connections_get_iterator(&it);
while(btstack_linked_list_iterator_has_next(&it)){
hci_connection_t * connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
att_server_t * att_server = &connection->att_server;
if (att_server->state == state) return att_server;
if (att_server->state == state) return connection;
}
return NULL;
}
#endif
static void att_server_request_can_send_now(att_server_t * att_server){
static void att_server_request_can_send_now(hci_connection_t * hci_connection){
att_server_t * att_server = &hci_connection->att_server;
#ifdef ENABLE_GATT_OVER_CLASSIC
if (att_server->l2cap_cid != 0){
l2cap_request_can_send_now_event(att_server->l2cap_cid);
@ -148,7 +130,8 @@ static void att_server_request_can_send_now(att_server_t * att_server){
att_dispatch_server_request_can_send_now_event(att_server->connection.con_handle);
}
static int att_server_can_send_packet(att_server_t * att_server){
static int att_server_can_send_packet(hci_connection_t * hci_connection){
att_server_t * att_server = &hci_connection->att_server;
#ifdef ENABLE_GATT_OVER_CLASSIC
if (att_server->l2cap_cid != 0){
return l2cap_can_send_packet_now(att_server->l2cap_cid);
@ -212,7 +195,8 @@ static void att_emit_can_send_now_event(void * context){
(*att_client_packet_handler)(HCI_EVENT_PACKET, 0, &event[0], sizeof(event));
}
static void att_emit_connected_event(att_server_t * att_server){
static void att_emit_connected_event(hci_connection_t * hci_connection){
att_server_t * att_server = &hci_connection->att_server;
uint8_t event[11];
int pos = 0;
event[pos++] = ATT_EVENT_CONNECTED;
@ -243,9 +227,10 @@ static void att_emit_disconnected_event(uint16_t con_handle){
static void att_handle_value_indication_timeout(btstack_timer_source_t *ts){
void * context = btstack_run_loop_get_timer_context(ts);
hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) context;
att_server_t * att_server = att_server_for_handle(con_handle);
if (!att_server) return;
// @note: after a transcation timeout, no more requests shall be sent over this ATT Bearer
hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) return;
att_server_t * att_server = &hci_connection->att_server;
// @note: after a transaction timeout, no more requests shall be sent over this ATT Bearer
// (that's why we don't reset the value_indication_handle)
uint16_t att_handle = att_server->value_indication_handle;
att_handle_value_indication_notify_client(ATT_HANDLE_VALUE_INDICATION_TIMEOUT, att_server->connection.con_handle, att_handle);
@ -258,8 +243,10 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
att_server_t * att_server;
hci_con_handle_t con_handle;
hci_connection_t * hci_connection;
#ifdef ENABLE_GATT_OVER_CLASSIC
bd_addr_t address;
btstack_linked_list_iterator_t it;
#endif
switch (packet_type) {
@ -275,8 +262,9 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
break;
case L2CAP_EVENT_CHANNEL_OPENED:
con_handle = l2cap_event_channel_opened_get_handle(packet);
att_server = att_server_for_handle(con_handle);
if (!att_server) break;
hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) break;
att_server = &hci_connection->att_server;
// store connection info
att_server->peer_addr_type = BD_ADDR_TYPE_ACL;
l2cap_event_channel_opened_get_address(packet, att_server->peer_address);
@ -300,11 +288,11 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
att_server->connection.encryption_key_size, att_server->connection.authenticated, att_server->connection.secure_connection);
// notify connection opened
att_emit_connected_event(att_server);
att_emit_connected_event(hci_connection);
// restore persisten ccc if encrypted
if ( gap_security_level(con_handle) >= LEVEL_2){
att_server_persistent_ccc_restore(att_server);
att_server_persistent_ccc_restore(hci_connection);
}
// TODO: what to do about le device db?
att_server->pairing_active = 0;
@ -318,9 +306,10 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
switch (packet[2]) {
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
con_handle = little_endian_read_16(packet, 4);
att_server = att_server_for_handle(con_handle);
if (!att_server) break;
// store connection info
hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) break;
att_server = &hci_connection->att_server;
// store connection info
att_server->peer_addr_type = packet[7];
reverse_bd_addr(&packet[8], att_server->peer_address);
att_server->connection.con_handle = con_handle;
@ -341,7 +330,7 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
// notify all - old
att_emit_event_to_all(packet, size);
// notify all - new
att_emit_connected_event(att_server);
att_emit_connected_event(hci_connection);
break;
default:
@ -353,10 +342,11 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
case HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE:
// check handle
con_handle = little_endian_read_16(packet, 3);
att_server = att_server_for_handle(con_handle);
if (!att_server) break;
hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) break;
if (gap_get_connection_type(con_handle) != GAP_CONNECTION_LE) break;
// update security params
att_server = &hci_connection->att_server;
att_server->connection.encryption_key_size = gap_encryption_key_size(con_handle);
att_server->connection.authenticated = gap_authenticated(con_handle);
att_server->connection.secure_connection = gap_secure_connection(con_handle);
@ -365,17 +355,18 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
if (hci_event_packet_get_type(packet) == HCI_EVENT_ENCRYPTION_CHANGE){
// restore CCC values when encrypted for LE Connections
if (hci_event_encryption_change_get_encryption_enabled(packet)){
att_server_persistent_ccc_restore(att_server);
att_server_persistent_ccc_restore(hci_connection);
}
}
att_run_for_context(att_server);
att_run_for_context(hci_connection);
break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
// check handle
con_handle = hci_event_disconnection_complete_get_connection_handle(packet);
att_server = att_server_for_handle(con_handle);
if (!att_server) break;
hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) break;
att_server = &hci_connection->att_server;
att_clear_transaction_queue(&att_server->connection);
att_server->connection.con_handle = 0;
att_server->pairing_active = 0;
@ -395,28 +386,31 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
// Identity Resolving
case SM_EVENT_IDENTITY_RESOLVING_STARTED:
con_handle = sm_event_identity_resolving_started_get_handle(packet);
att_server = att_server_for_handle(con_handle);
if (!att_server) break;
hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) break;
att_server = &hci_connection->att_server;
log_info("SM_EVENT_IDENTITY_RESOLVING_STARTED");
att_server->ir_lookup_active = 1;
break;
case SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED:
con_handle = sm_event_identity_created_get_handle(packet);
att_server = att_server_for_handle(con_handle);
if (!att_server) return;
hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) return;
att_server = &hci_connection->att_server;
att_server->ir_lookup_active = 0;
att_server->ir_le_device_db_index = sm_event_identity_resolving_succeeded_get_index(packet);
log_info("SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED");
att_run_for_context(att_server);
att_run_for_context(hci_connection);
break;
case SM_EVENT_IDENTITY_RESOLVING_FAILED:
con_handle = sm_event_identity_resolving_failed_get_handle(packet);
att_server = att_server_for_handle(con_handle);
if (!att_server) break;
hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) break;
att_server = &hci_connection->att_server;
log_info("SM_EVENT_IDENTITY_RESOLVING_FAILED");
att_server->ir_lookup_active = 0;
att_server->ir_le_device_db_index = -1;
att_run_for_context(att_server);
att_run_for_context(hci_connection);
break;
// Pairing started - delete stored CCC values
@ -427,12 +421,13 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
case SM_EVENT_PASSKEY_INPUT_NUMBER:
case SM_EVENT_NUMERIC_COMPARISON_REQUEST:
con_handle = sm_event_just_works_request_get_handle(packet);
att_server = att_server_for_handle(con_handle);
if (!att_server) break;
hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) break;
att_server = &hci_connection->att_server;
att_server->pairing_active = 1;
log_info("SM Pairing started");
if (att_server->ir_le_device_db_index < 0) break;
att_server_persistent_ccc_clear(att_server);
att_server_persistent_ccc_clear(hci_connection);
// index not valid anymore
att_server->ir_le_device_db_index = -1;
break;
@ -440,29 +435,32 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
// Bonding completed
case SM_EVENT_IDENTITY_CREATED:
con_handle = sm_event_identity_created_get_handle(packet);
att_server = att_server_for_handle(con_handle);
if (!att_server) return;
hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) return;
att_server = &hci_connection->att_server;
att_server->pairing_active = 0;
att_server->ir_le_device_db_index = sm_event_identity_created_get_index(packet);
att_run_for_context(att_server);
att_run_for_context(hci_connection);
break;
// Pairing complete (with/without bonding=storing of pairing information)
case SM_EVENT_PAIRING_COMPLETE:
con_handle = sm_event_pairing_complete_get_handle(packet);
att_server = att_server_for_handle(con_handle);
if (!att_server) return;
hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) return;
att_server = &hci_connection->att_server;
att_server->pairing_active = 0;
att_run_for_context(att_server);
att_run_for_context(hci_connection);
break;
// Authorization
case SM_EVENT_AUTHORIZATION_RESULT: {
con_handle = sm_event_authorization_result_get_handle(packet);
att_server = att_server_for_handle(con_handle);
if (!att_server) break;
hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) break;
att_server = &hci_connection->att_server;
att_server->connection.authorized = sm_event_authorization_result_get_authorization_result(packet);
att_server_request_can_send_now(att_server);
att_server_request_can_send_now(hci_connection);
break;
}
default:
@ -471,10 +469,15 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
break;
#ifdef ENABLE_GATT_OVER_CLASSIC
case L2CAP_DATA_PACKET:
att_server = att_server_for_l2cap_cid(channel);
if (!att_server) break;
att_server_handle_att_pdu(att_server, packet, size);
hci_connections_get_iterator(&it);
while(btstack_linked_list_iterator_has_next(&it)){
hci_connection_t * connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
att_server = &connection->att_server;
if (att_server->l2cap_cid == channel) {
att_server_handle_att_pdu(connection, packet, size);
break;
}
}
break;
#endif
@ -486,8 +489,9 @@ static void att_event_packet_handler (uint8_t packet_type, uint16_t channel, uin
#ifdef ENABLE_LE_SIGNED_WRITE
static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
att_server_t * att_server = att_server_for_state(ATT_SERVER_W4_SIGNED_WRITE_VALIDATION);
if (!att_server) return;
hci_connection_t * hci_connection = hci_connection_for_state(ATT_SERVER_W4_SIGNED_WRITE_VALIDATION);
if (!hci_connection) return;
att_server_t * att_server = &hci_connection->att_server;
uint8_t hash_flipped[8];
reverse_64(hash, hash_flipped);
@ -502,14 +506,15 @@ static void att_signed_write_handle_cmac_result(uint8_t hash[8]){
uint32_t counter_packet = little_endian_read_32(att_server->request_buffer, att_server->request_size-12);
le_device_db_remote_counter_set(att_server->ir_le_device_db_index, counter_packet+1);
att_server->state = ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED;
att_server_request_can_send_now(att_server);
att_server_request_can_send_now(hci_connection);
}
#endif
// pre: att_server->state == ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED
// pre: can send now
// returns: 1 if packet was sent
static int att_server_process_validated_request(att_server_t * att_server){
static int att_server_process_validated_request(hci_connection_t * hci_connection){
att_server_t * att_server = & hci_connection->att_server;
l2cap_reserve_packet_buffer();
uint8_t * att_response_buffer = l2cap_get_outgoing_buffer();
@ -574,17 +579,20 @@ static int att_server_process_validated_request(att_server_t * att_server){
#ifdef ENABLE_ATT_DELAYED_RESPONSE
int att_server_response_ready(hci_con_handle_t con_handle){
att_server_t * att_server = att_server_for_handle(con_handle);
if (!att_server) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
att_server_t * att_server = &hci_connection->att_server;
if (att_server->state != ATT_SERVER_RESPONSE_PENDING) return ERROR_CODE_COMMAND_DISALLOWED;
att_server->state = ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED;
att_server_request_can_send_now(att_server);
att_server_request_can_send_now(hci_connection);
return ERROR_CODE_SUCCESS;
}
#endif
static void att_run_for_context(att_server_t * att_server){
static void att_run_for_context(hci_connection_t * hci_connection){
att_server_t * att_server = &hci_connection->att_server;
switch (att_server->state){
case ATT_SERVER_REQUEST_RECEIVED:
@ -646,7 +654,7 @@ static void att_run_for_context(att_server_t * att_server){
#endif
// move on
att_server->state = ATT_SERVER_REQUEST_RECEIVED_AND_VALIDATED;
att_server_request_can_send_now(att_server);
att_server_request_can_send_now(hci_connection);
break;
default:
@ -668,11 +676,12 @@ static int att_server_data_ready_for_phase(att_server_t * att_server, att_serve
}
}
static void att_server_trigger_send_for_phase(att_server_t * att_server, att_server_run_phase_t phase){
static void att_server_trigger_send_for_phase(hci_connection_t * hci_connection, att_server_run_phase_t phase){
btstack_context_callback_registration_t * client;
att_server_t * att_server = &hci_connection->att_server;
switch (phase){
case ATT_SERVER_RUN_PHASE_1_REQUESTS:
att_server_process_validated_request(att_server);
att_server_process_validated_request(hci_connection);
break;
case ATT_SERVER_RUN_PHASE_2_INDICATIONS:
client = (btstack_context_callback_registration_t*) att_server->indication_requests;
@ -693,7 +702,7 @@ static void att_server_trigger_send_for_phase(att_server_t * att_server, att_se
static void att_server_handle_can_send_now(void){
hci_con_handle_t last_send_con_handle = HCI_CON_HANDLE_INVALID;
att_server_t * request_att_server = NULL;
hci_connection_t * request_hci_connection = NULL;
int can_send_now = 1;
int phase_index;
@ -713,8 +722,8 @@ static void att_server_handle_can_send_now(void){
// skip until last sender found (which is also skipped)
if (skip_connections_until != HCI_CON_HANDLE_INVALID){
if (data_ready && (request_att_server == NULL)){
request_att_server = att_server;
if (data_ready && (request_hci_connection == NULL)){
request_hci_connection = connection;
}
if (skip_connections_until == att_server->connection.con_handle){
skip_connections_until = HCI_CON_HANDLE_INVALID;
@ -724,15 +733,15 @@ static void att_server_handle_can_send_now(void){
if (data_ready){
if (can_send_now){
att_server_trigger_send_for_phase(att_server, phase);
att_server_trigger_send_for_phase(connection, phase);
last_send_con_handle = att_server->connection.con_handle;
can_send_now = att_server_can_send_packet(att_server);
can_send_now = att_server_can_send_packet(connection);
data_ready = att_server_data_ready_for_phase(att_server, phase);
if (data_ready && (request_att_server == NULL)){
request_att_server = att_server;
if (data_ready && (request_hci_connection == NULL)){
request_hci_connection = connection;
}
} else {
request_att_server = att_server;
request_hci_connection = connection;
break;
}
}
@ -745,10 +754,10 @@ static void att_server_handle_can_send_now(void){
if (!can_send_now) break;
// Exit loop, if we can send but there are also no further request
if (request_att_server == NULL) break;
if (request_hci_connection == NULL) break;
// Finally, if we still can send and there are requests, just try again
request_att_server = NULL;
request_hci_connection = NULL;
}
// update last send con handle for round robin
if (last_send_con_handle != HCI_CON_HANDLE_INVALID){
@ -756,11 +765,12 @@ static void att_server_handle_can_send_now(void){
}
}
if (request_att_server == NULL) return;
att_server_request_can_send_now(request_att_server);
if (request_hci_connection == NULL) return;
att_server_request_can_send_now(request_hci_connection);
}
static void att_server_handle_att_pdu(att_server_t * att_server, uint8_t * packet, uint16_t size){
static void att_server_handle_att_pdu(hci_connection_t * hci_connection, uint8_t * packet, uint16_t size){
att_server_t * att_server = &hci_connection->att_server;
// handle value indication confirms
if ((packet[0] == ATT_HANDLE_VALUE_CONFIRMATION) && att_server->value_indication_handle){
@ -768,7 +778,7 @@ static void att_server_handle_att_pdu(att_server_t * att_server, uint8_t * packe
uint16_t att_handle = att_server->value_indication_handle;
att_server->value_indication_handle = 0;
att_handle_value_indication_notify_client(0, att_server->connection.con_handle, att_handle);
att_server_request_can_send_now(att_server);
att_server_request_can_send_now(hci_connection);
return;
}
@ -808,11 +818,12 @@ static void att_server_handle_att_pdu(att_server_t * att_server, uint8_t * packe
att_server->request_size = size;
(void)memcpy(att_server->request_buffer, packet, size);
att_run_for_context(att_server);
att_run_for_context(hci_connection);
}
static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){
att_server_t * att_server;
hci_connection_t * hci_connection;
switch (packet_type){
case HCI_EVENT_PACKET:
@ -822,8 +833,9 @@ static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pa
break;
case ATT_EVENT_MTU_EXCHANGE_COMPLETE:
// GATT client has negotiated the mtu for this connection
att_server = att_server_for_handle(handle);
if (!att_server) break;
hci_connection = hci_connection_for_handle(handle);
if (!hci_connection) break;
att_server = &hci_connection->att_server;
att_server->connection.mtu = little_endian_read_16(packet, 4);
break;
default:
@ -833,10 +845,10 @@ static void att_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *pa
case ATT_DATA_PACKET:
log_debug("ATT Packet, handle 0x%04x", handle);
att_server = att_server_for_handle(handle);
if (!att_server) break;
hci_connection = hci_connection_for_handle(handle);
if (!hci_connection) break;
att_server_handle_att_pdu(att_server, packet, size);
att_server_handle_att_pdu(hci_connection, packet, size);
break;
default:
@ -852,8 +864,9 @@ static uint32_t att_server_persistent_ccc_tag_for_index(uint8_t index){
static void att_server_persistent_ccc_write(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t value){
// lookup att_server instance
att_server_t * att_server = att_server_for_handle(con_handle);
if (!att_server) return;
hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) return;
att_server_t * att_server = &hci_connection->att_server;
int le_device_index = att_server->ir_le_device_db_index;
log_info("Store CCC value 0x%04x for handle 0x%04x of remote %s, le device id %d", value, att_handle, bd_addr_to_str(att_server->peer_address), le_device_index);
@ -944,8 +957,10 @@ static void att_server_persistent_ccc_write(hci_con_handle_t con_handle, uint16_
}
}
static void att_server_persistent_ccc_clear(att_server_t * att_server){
if (!att_server) return;
static void att_server_persistent_ccc_clear(hci_connection_t * hci_connection){
if (!hci_connection) return;
att_server_t * att_server = &hci_connection->att_server;
int le_device_index = att_server->ir_le_device_db_index;
log_info("Clear CCC values of remote %s, le device id %d", bd_addr_to_str(att_server->peer_address), le_device_index);
// check if bonded
@ -969,8 +984,10 @@ static void att_server_persistent_ccc_clear(att_server_t * att_server){
}
}
static void att_server_persistent_ccc_restore(att_server_t * att_server){
if (!att_server) return;
static void att_server_persistent_ccc_restore(hci_connection_t * hci_connection){
if (!hci_connection) return;
att_server_t * att_server = &hci_connection->att_server;
int le_device_index = att_server->ir_le_device_db_index;
log_info("Restore CCC values of remote %s, le device id %d", bd_addr_to_str(att_server->peer_address), le_device_index);
// check if bonded
@ -1134,9 +1151,9 @@ void att_server_register_packet_handler(btstack_packet_handler_t handler){
// to be deprecated
int att_server_can_send_packet_now(hci_con_handle_t con_handle){
att_server_t * att_server = att_server_for_handle(con_handle);
if (!att_server) return 0;
return att_server_can_send_packet(att_server);
hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) return 0;
return att_server_can_send_packet(hci_connection);
}
int att_server_register_can_send_now_callback(btstack_context_callback_registration_t * callback_registration, hci_con_handle_t con_handle){
@ -1150,10 +1167,11 @@ void att_server_request_can_send_now_event(hci_con_handle_t con_handle){
// end of deprecated
int att_server_request_to_send_notification(btstack_context_callback_registration_t * callback_registration, hci_con_handle_t con_handle){
att_server_t * att_server = att_server_for_handle(con_handle);
if (!att_server) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
att_server_t * att_server = &hci_connection->att_server;
bool added = btstack_linked_list_add_tail(&att_server->notification_requests, (btstack_linked_item_t*) callback_registration);
att_server_request_can_send_now(att_server);
att_server_request_can_send_now(hci_connection);
if (added){
return ERROR_CODE_SUCCESS;
} else {
@ -1162,10 +1180,11 @@ int att_server_request_to_send_notification(btstack_context_callback_registratio
}
int att_server_request_to_send_indication(btstack_context_callback_registration_t * callback_registration, hci_con_handle_t con_handle){
att_server_t * att_server = att_server_for_handle(con_handle);
if (!att_server) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
att_server_t * att_server = &hci_connection->att_server;
bool added = btstack_linked_list_add_tail(&att_server->indication_requests, (btstack_linked_item_t*) callback_registration);
att_server_request_can_send_now(att_server);
att_server_request_can_send_now(hci_connection);
if (added){
return ERROR_CODE_SUCCESS;
} else {
@ -1174,9 +1193,11 @@ int att_server_request_to_send_indication(btstack_context_callback_registration_
}
int att_server_notify(hci_con_handle_t con_handle, uint16_t attribute_handle, const uint8_t *value, uint16_t value_len){
att_server_t * att_server = att_server_for_handle(con_handle);
if (!att_server) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
if (!att_server_can_send_packet(att_server)) return BTSTACK_ACL_BUFFERS_FULL;
hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
att_server_t * att_server = &hci_connection->att_server;
if (!att_server_can_send_packet(hci_connection)) return BTSTACK_ACL_BUFFERS_FULL;
l2cap_reserve_packet_buffer();
uint8_t * packet_buffer = l2cap_get_outgoing_buffer();
@ -1185,11 +1206,12 @@ int att_server_notify(hci_con_handle_t con_handle, uint16_t attribute_handle, co
}
int att_server_indicate(hci_con_handle_t con_handle, uint16_t attribute_handle, const uint8_t *value, uint16_t value_len){
att_server_t * att_server = att_server_for_handle(con_handle);
if (!att_server) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
att_server_t * att_server = &hci_connection->att_server;
if (att_server->value_indication_handle) return ATT_HANDLE_VALUE_INDICATION_IN_PROGRESS;
if (!att_server_can_send_packet(att_server)) return BTSTACK_ACL_BUFFERS_FULL;
if (!att_server_can_send_packet(hci_connection)) return BTSTACK_ACL_BUFFERS_FULL;
// track indication
att_server->value_indication_handle = attribute_handle;
@ -1205,7 +1227,8 @@ int att_server_indicate(hci_con_handle_t con_handle, uint16_t attribute_handle,
}
uint16_t att_server_get_mtu(hci_con_handle_t con_handle){
att_server_t * att_server = att_server_for_handle(con_handle);
if (!att_server) return 0;
hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
if (!hci_connection) return 0;
att_server_t * att_server = &hci_connection->att_server;
return att_server->connection.mtu;
}