l2cap: round robin over all channel types (classic, le data channel, fixed)

This commit is contained in:
Matthias Ringwald 2018-02-02 20:14:47 +01:00
parent fad84caf30
commit 7740e150a7
2 changed files with 46 additions and 13 deletions

View File

@ -84,6 +84,7 @@ static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t channel, uint8
static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size );
static void l2cap_notify_channel_can_send(void);
static void l2cap_emit_can_send_now(btstack_packet_handler_t packet_handler, uint16_t channel);
static l2cap_fixed_channel_t * l2cap_fixed_channel_for_channel_id(uint16_t local_cid);
#ifdef ENABLE_CLASSIC
static void l2cap_handle_remote_supported_features_received(l2cap_channel_t * channel);
static void l2cap_handle_connection_complete(hci_con_handle_t con_handle, l2cap_channel_t * channel);
@ -726,7 +727,7 @@ void l2cap_init(void){
// Setup Connectionless Channel
l2cap_fixed_channel_connectionless.local_cid = L2CAP_CID_CONNECTIONLESS_CHANNEL;
l2cap_fixed_channel_connectionless.channel_type = L2CAP_CHANNEL_TYPE_FIXED;
l2cap_fixed_channel_connectionless.channel_type = L2CAP_CHANNEL_TYPE_CONNECTIONLESS;
btstack_linked_list_add(&l2cap_channels, (btstack_linked_item_t *) &l2cap_fixed_channel_connectionless);
#endif
@ -740,12 +741,12 @@ void l2cap_init(void){
// Setup fixed ATT Channel
l2cap_fixed_channel_att.local_cid = L2CAP_CID_ATTRIBUTE_PROTOCOL;
l2cap_fixed_channel_att.channel_type = L2CAP_CHANNEL_TYPE_FIXED;
l2cap_fixed_channel_att.channel_type = L2CAP_CHANNEL_TYPE_LE_FIXED;
btstack_linked_list_add(&l2cap_channels, (btstack_linked_item_t *) &l2cap_fixed_channel_att);
// Setup fixed SM Channel
l2cap_fixed_channel_sm.local_cid = L2CAP_CID_SECURITY_MANAGER_PROTOCOL;
l2cap_fixed_channel_sm.channel_type = L2CAP_CHANNEL_TYPE_FIXED;
l2cap_fixed_channel_sm.channel_type = L2CAP_CHANNEL_TYPE_LE_FIXED;
btstack_linked_list_add(&l2cap_channels, (btstack_linked_item_t *) &l2cap_fixed_channel_sm);
#endif
@ -773,7 +774,7 @@ void l2cap_register_packet_handler(void (*handler)(uint8_t packet_type, uint16_t
void l2cap_request_can_send_fix_channel_now_event(hci_con_handle_t con_handle, uint16_t channel_id){
UNUSED(con_handle); // ok: there is no con handle
l2cap_fixed_channel_t * channel = (l2cap_fixed_channel_t *) l2cap_get_channel_for_local_cid(channel_id);
l2cap_fixed_channel_t * channel = (l2cap_fixed_channel_t *) l2cap_fixed_channel_for_channel_id(channel_id);
if (!channel) return;
channel->waiting_for_can_send_now = 1;
l2cap_notify_channel_can_send();
@ -993,6 +994,16 @@ static int l2cap_is_dynamic_channel_type(l2cap_channel_type_t channel_type){
}
}
static int l2cap_is_le_channel_type(l2cap_channel_type_t channel_type){
switch (channel_type){
case L2CAP_CHANNEL_TYPE_LE_FIXED:
case L2CAP_CHANNEL_TYPE_LE_DATA_CHANNEL:
return 1;
default:
return 0;
}
}
// RTX Timer only exist for dynamic channels
static l2cap_channel_t * l2cap_channel_for_rtx_timer(btstack_timer_source_t * ts){
btstack_linked_list_iterator_t it;
@ -1886,14 +1897,35 @@ static void l2cap_handle_connection_success_for_addr(bd_addr_t address, hci_con_
#endif
static void l2cap_notify_channel_can_send(void){
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, &l2cap_channels);
while (btstack_linked_list_iterator_has_next(&it)){
l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it);
if (!channel->waiting_for_can_send_now) continue;
if (!hci_can_send_acl_packet_now(channel->con_handle)) continue;
channel->waiting_for_can_send_now = 0;
l2cap_emit_can_send_now(channel->packet_handler, channel->local_cid);
int done = 0;
while (!done){
done = 1;
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, &l2cap_channels);
while (btstack_linked_list_iterator_has_next(&it)){
l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it);
if (!channel->waiting_for_can_send_now) continue;
int can_send = 0;
if (l2cap_is_le_channel_type(channel->channel_type)){
#ifdef ENABLE_BLE
can_send = hci_can_send_acl_le_packet_now();
#endif
} else {
#ifdef ENABLE_CLASSIC
can_send = hci_can_send_acl_classic_packet_now();
#endif
}
if (!can_send) continue;
// requeue for fairness
btstack_linked_list_remove(&l2cap_channels, (btstack_linked_item_t *) channel);
btstack_linked_list_add_tail(&l2cap_channels, (btstack_linked_item_t *) channel);
// emit can send
channel->waiting_for_can_send_now = 0;
l2cap_emit_can_send_now(channel->packet_handler, channel->local_cid);
// exit inner loop as we just broke the iterator, but try again
done = 0;
break;
}
}
}

View File

@ -118,8 +118,9 @@ typedef enum {
typedef enum {
L2CAP_CHANNEL_TYPE_CLASSIC, // Classic Basic or ERTM
L2CAP_CHANNEL_TYPE_CONNECTIONLESS, // Classic Connectionless
L2CAP_CHANNEL_TYPE_LE_DATA_CHANNEL, // LE
L2CAP_CHANNEL_TYPE_FIXED, // Classic Connectionless + LE ATT + LE SM
L2CAP_CHANNEL_TYPE_LE_FIXED, // LE ATT + SM
} l2cap_channel_type_t;
typedef struct {