mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-26 11:37:10 +00:00
l2cap: reduce code size if ENABLE_CLASSIC not defined
This commit is contained in:
parent
3a18db10c5
commit
09e9d05bab
395
src/l2cap.c
395
src/l2cap.c
@ -81,18 +81,23 @@
|
||||
#define L2CAP_FIXED_CHANNEL_TABLE_INDEX_CONNECTIONLESS_CHANNEL 2
|
||||
#define L2CAP_FIXED_CHANNEL_TABLE_SIZE (L2CAP_FIXED_CHANNEL_TABLE_INDEX_CONNECTIONLESS_CHANNEL+1)
|
||||
|
||||
#if defined(ENABLE_LE_DATA_CHANNELS) || defined(ENABLE_CLASSIC)
|
||||
#define L2CAP_USES_CHANNELS
|
||||
#endif
|
||||
|
||||
// prototypes
|
||||
static void l2cap_finialize_channel_close(l2cap_channel_t *channel);
|
||||
static inline l2cap_service_t * l2cap_get_service(uint16_t psm);
|
||||
static void l2cap_emit_channel_opened(l2cap_channel_t *channel, uint8_t status);
|
||||
static void l2cap_emit_can_send_now(btstack_packet_handler_t packet_handler, uint16_t channel);
|
||||
static void l2cap_emit_channel_closed(l2cap_channel_t *channel);
|
||||
static void l2cap_emit_incoming_connection(l2cap_channel_t *channel);
|
||||
static int l2cap_channel_ready_for_open(l2cap_channel_t *channel);
|
||||
static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
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);
|
||||
#ifdef ENABLE_CLASSIC
|
||||
static void l2cap_finialize_channel_close(l2cap_channel_t *channel);
|
||||
static inline l2cap_service_t * l2cap_get_service(uint16_t psm);
|
||||
static void l2cap_emit_channel_opened(l2cap_channel_t *channel, uint8_t status);
|
||||
static void l2cap_emit_channel_closed(l2cap_channel_t *channel);
|
||||
static void l2cap_emit_incoming_connection(l2cap_channel_t *channel);
|
||||
static int l2cap_channel_ready_for_open(l2cap_channel_t *channel);
|
||||
#endif
|
||||
#ifdef ENABLE_LE_DATA_CHANNELS
|
||||
static void l2cap_emit_le_channel_opened(l2cap_channel_t *channel, uint8_t status);
|
||||
static void l2cap_emit_le_incoming_connection(l2cap_channel_t *channel);
|
||||
@ -107,8 +112,11 @@ typedef struct l2cap_fixed_channel {
|
||||
uint8_t waiting_for_can_send_now;
|
||||
} l2cap_fixed_channel_t;
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
static btstack_linked_list_t l2cap_channels;
|
||||
static btstack_linked_list_t l2cap_services;
|
||||
static uint8_t require_security_level2_for_outgoing_sdp;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LE_DATA_CHANNELS
|
||||
static btstack_linked_list_t l2cap_le_channels;
|
||||
@ -119,8 +127,6 @@ static btstack_linked_list_t l2cap_le_services;
|
||||
static l2cap_signaling_response_t signaling_responses[NR_PENDING_SIGNALING_RESPONSES];
|
||||
static int signaling_responses_pending;
|
||||
|
||||
static uint8_t require_security_level2_for_outgoing_sdp;
|
||||
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
|
||||
static btstack_packet_handler_t l2cap_event_packet_handler;
|
||||
@ -159,8 +165,11 @@ static int l2cap_fixed_channel_table_index_is_le(int index){
|
||||
void l2cap_init(void){
|
||||
signaling_responses_pending = 0;
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
l2cap_channels = NULL;
|
||||
l2cap_services = NULL;
|
||||
require_security_level2_for_outgoing_sdp = 0;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_LE_DATA_CHANNELS
|
||||
l2cap_le_services = NULL;
|
||||
@ -170,8 +179,6 @@ void l2cap_init(void){
|
||||
l2cap_event_packet_handler = NULL;
|
||||
memset(fixed_channels, 0, sizeof(fixed_channels));
|
||||
|
||||
require_security_level2_for_outgoing_sdp = 0;
|
||||
|
||||
//
|
||||
// register callback with HCI
|
||||
//
|
||||
@ -187,6 +194,88 @@ void l2cap_register_packet_handler(void (*handler)(uint8_t packet_type, uint16_t
|
||||
l2cap_event_packet_handler = handler;
|
||||
}
|
||||
|
||||
void l2cap_request_can_send_fix_channel_now_event(hci_con_handle_t con_handle, uint16_t channel_id){
|
||||
int index = l2cap_fixed_channel_table_index_for_channel_id(channel_id);
|
||||
if (index < 0) return;
|
||||
fixed_channels[index].waiting_for_can_send_now = 1;
|
||||
l2cap_notify_channel_can_send();
|
||||
}
|
||||
|
||||
int l2cap_can_send_fixed_channel_packet_now(hci_con_handle_t con_handle, uint16_t channel_id){
|
||||
return hci_can_send_acl_packet_now(con_handle);
|
||||
}
|
||||
|
||||
uint8_t *l2cap_get_outgoing_buffer(void){
|
||||
return hci_get_outgoing_packet_buffer() + COMPLETE_L2CAP_HEADER; // 8 bytes
|
||||
}
|
||||
|
||||
int l2cap_reserve_packet_buffer(void){
|
||||
return hci_reserve_packet_buffer();
|
||||
}
|
||||
|
||||
void l2cap_release_packet_buffer(void){
|
||||
hci_release_packet_buffer();
|
||||
}
|
||||
|
||||
static void l2cap_setup_header(uint8_t * acl_buffer, hci_con_handle_t con_handle, uint16_t remote_cid, uint16_t len){
|
||||
int pb = hci_non_flushable_packet_boundary_flag_supported() ? 0x00 : 0x02;
|
||||
|
||||
// 0 - Connection handle : PB=pb : BC=00
|
||||
little_endian_store_16(acl_buffer, 0, con_handle | (pb << 12) | (0 << 14));
|
||||
// 2 - ACL length
|
||||
little_endian_store_16(acl_buffer, 2, len + 4);
|
||||
// 4 - L2CAP packet length
|
||||
little_endian_store_16(acl_buffer, 4, len + 0);
|
||||
// 6 - L2CAP channel DEST
|
||||
little_endian_store_16(acl_buffer, 6, remote_cid);
|
||||
}
|
||||
|
||||
int l2cap_send_prepared_connectionless(hci_con_handle_t con_handle, uint16_t cid, uint16_t len){
|
||||
|
||||
if (!hci_is_packet_buffer_reserved()){
|
||||
log_error("l2cap_send_prepared_connectionless called without reserving packet first");
|
||||
return BTSTACK_ACL_BUFFERS_FULL;
|
||||
}
|
||||
|
||||
if (!hci_can_send_prepared_acl_packet_now(con_handle)){
|
||||
log_info("l2cap_send_prepared_connectionless handle 0x%02x, cid 0x%02x, cannot send", con_handle, cid);
|
||||
return BTSTACK_ACL_BUFFERS_FULL;
|
||||
}
|
||||
|
||||
log_debug("l2cap_send_prepared_connectionless handle %u, cid 0x%02x", con_handle, cid);
|
||||
|
||||
uint8_t *acl_buffer = hci_get_outgoing_packet_buffer();
|
||||
l2cap_setup_header(acl_buffer, con_handle, cid, len);
|
||||
// send
|
||||
return hci_send_acl_packet_buffer(len+8);
|
||||
}
|
||||
|
||||
int l2cap_send_connectionless(hci_con_handle_t con_handle, uint16_t cid, uint8_t *data, uint16_t len){
|
||||
|
||||
if (!hci_can_send_acl_packet_now(con_handle)){
|
||||
log_info("l2cap_send cid 0x%02x, cannot send", cid);
|
||||
return BTSTACK_ACL_BUFFERS_FULL;
|
||||
}
|
||||
|
||||
hci_reserve_packet_buffer();
|
||||
uint8_t *acl_buffer = hci_get_outgoing_packet_buffer();
|
||||
|
||||
memcpy(&acl_buffer[8], data, len);
|
||||
|
||||
return l2cap_send_prepared_connectionless(con_handle, cid, len);
|
||||
}
|
||||
|
||||
static void l2cap_emit_can_send_now(btstack_packet_handler_t packet_handler, uint16_t channel) {
|
||||
log_info("L2CAP_EVENT_CHANNEL_CAN_SEND_NOW local_cid 0x%x", channel);
|
||||
uint8_t event[4];
|
||||
event[0] = L2CAP_EVENT_CAN_SEND_NOW;
|
||||
event[1] = sizeof(event) - 2;
|
||||
little_endian_store_16(event, 2, channel);
|
||||
hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
packet_handler(HCI_EVENT_PACKET, channel, event, sizeof(event));
|
||||
}
|
||||
|
||||
#ifdef L2CAP_USES_CHANNELS
|
||||
static void l2cap_dispatch_to_channel(l2cap_channel_t *channel, uint8_t type, uint8_t * data, uint16_t size){
|
||||
(* (channel->packet_handler))(type, channel->local_cid, data, size);
|
||||
}
|
||||
@ -199,7 +288,9 @@ static void l2cap_emit_simple_event_with_cid(l2cap_channel_t * channel, uint8_t
|
||||
hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
void l2cap_emit_channel_opened(l2cap_channel_t *channel, uint8_t status) {
|
||||
log_info("L2CAP_EVENT_CHANNEL_OPENED status 0x%x addr %s handle 0x%x psm 0x%x local_cid 0x%x remote_cid 0x%x local_mtu %u, remote_mtu %u, flush_timeout %u",
|
||||
status, bd_addr_to_str(channel->address), channel->con_handle, channel->psm,
|
||||
@ -225,17 +316,6 @@ static void l2cap_emit_channel_closed(l2cap_channel_t *channel) {
|
||||
l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_CHANNEL_CLOSED);
|
||||
}
|
||||
|
||||
|
||||
static void l2cap_emit_can_send_now(btstack_packet_handler_t packet_handler, uint16_t channel) {
|
||||
log_info("L2CAP_EVENT_CHANNEL_CAN_SEND_NOW local_cid 0x%x", channel);
|
||||
uint8_t event[4];
|
||||
event[0] = L2CAP_EVENT_CAN_SEND_NOW;
|
||||
event[1] = sizeof(event) - 2;
|
||||
little_endian_store_16(event, 2, channel);
|
||||
hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
packet_handler(HCI_EVENT_PACKET, channel, event, sizeof(event));
|
||||
}
|
||||
|
||||
static void l2cap_emit_incoming_connection(l2cap_channel_t *channel) {
|
||||
log_info("L2CAP_EVENT_INCOMING_CONNECTION addr %s handle 0x%x psm 0x%x local_cid 0x%x remote_cid 0x%x",
|
||||
bd_addr_to_str(channel->address), channel->con_handle, channel->psm, channel->local_cid, channel->remote_cid);
|
||||
@ -251,17 +331,6 @@ static void l2cap_emit_incoming_connection(l2cap_channel_t *channel) {
|
||||
l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event));
|
||||
}
|
||||
|
||||
static void l2cap_emit_connection_parameter_update_response(hci_con_handle_t con_handle, uint16_t result){
|
||||
uint8_t event[6];
|
||||
event[0] = L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE;
|
||||
event[1] = 4;
|
||||
little_endian_store_16(event, 2, con_handle);
|
||||
little_endian_store_16(event, 4, result);
|
||||
hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
if (!l2cap_event_packet_handler) return;
|
||||
(*l2cap_event_packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
static l2cap_channel_t * l2cap_get_channel_for_local_cid(uint16_t local_cid){
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &l2cap_channels);
|
||||
@ -283,15 +352,6 @@ void l2cap_request_can_send_now_event(uint16_t local_cid){
|
||||
l2cap_notify_channel_can_send();
|
||||
}
|
||||
|
||||
void l2cap_request_can_send_fix_channel_now_event(hci_con_handle_t con_handle, uint16_t channel_id){
|
||||
int index = l2cap_fixed_channel_table_index_for_channel_id(channel_id);
|
||||
if (index < 0) return;
|
||||
fixed_channels[index].waiting_for_can_send_now = 1;
|
||||
l2cap_notify_channel_can_send();
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
int l2cap_can_send_packet_now(uint16_t local_cid){
|
||||
l2cap_channel_t *channel = l2cap_get_channel_for_local_cid(local_cid);
|
||||
if (!channel) return 0;
|
||||
@ -303,13 +363,6 @@ int l2cap_can_send_prepared_packet_now(uint16_t local_cid){
|
||||
if (!channel) return 0;
|
||||
return hci_can_send_prepared_acl_packet_now(channel->con_handle);
|
||||
}
|
||||
|
||||
int l2cap_can_send_fixed_channel_packet_now(hci_con_handle_t con_handle, uint16_t channel_id){
|
||||
return hci_can_send_acl_packet_now(con_handle);
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
uint16_t l2cap_get_remote_mtu_for_local_cid(uint16_t local_cid){
|
||||
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
|
||||
if (channel) {
|
||||
@ -377,7 +430,6 @@ static int l2cap_security_level_0_allowed_for_PSM(uint16_t psm){
|
||||
}
|
||||
|
||||
static int l2cap_send_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){
|
||||
|
||||
if (!hci_can_send_acl_packet_now(handle)){
|
||||
log_info("l2cap_send_signaling_packet, cannot send");
|
||||
return BTSTACK_ACL_BUFFERS_FULL;
|
||||
@ -394,52 +446,6 @@ static int l2cap_send_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_
|
||||
return hci_send_acl_packet_buffer(len);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
static int l2cap_send_le_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){
|
||||
|
||||
if (!hci_can_send_acl_packet_now(handle)){
|
||||
log_info("l2cap_send_signaling_packet, cannot send");
|
||||
return BTSTACK_ACL_BUFFERS_FULL;
|
||||
}
|
||||
|
||||
// log_info("l2cap_send_signaling_packet type %u", cmd);
|
||||
hci_reserve_packet_buffer();
|
||||
uint8_t *acl_buffer = hci_get_outgoing_packet_buffer();
|
||||
va_list argptr;
|
||||
va_start(argptr, identifier);
|
||||
uint16_t len = l2cap_create_signaling_le(acl_buffer, handle, cmd, identifier, argptr);
|
||||
va_end(argptr);
|
||||
// log_info("l2cap_send_signaling_packet con %u!", handle);
|
||||
return hci_send_acl_packet_buffer(len);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t *l2cap_get_outgoing_buffer(void){
|
||||
return hci_get_outgoing_packet_buffer() + COMPLETE_L2CAP_HEADER; // 8 bytes
|
||||
}
|
||||
|
||||
int l2cap_reserve_packet_buffer(void){
|
||||
return hci_reserve_packet_buffer();
|
||||
}
|
||||
|
||||
void l2cap_release_packet_buffer(void){
|
||||
hci_release_packet_buffer();
|
||||
}
|
||||
|
||||
static void l2cap_setup_header(uint8_t * acl_buffer, hci_con_handle_t con_handle, uint16_t remote_cid, uint16_t len){
|
||||
|
||||
int pb = hci_non_flushable_packet_boundary_flag_supported() ? 0x00 : 0x02;
|
||||
|
||||
// 0 - Connection handle : PB=pb : BC=00
|
||||
little_endian_store_16(acl_buffer, 0, con_handle | (pb << 12) | (0 << 14));
|
||||
// 2 - ACL length
|
||||
little_endian_store_16(acl_buffer, 2, len + 4);
|
||||
// 4 - L2CAP packet length
|
||||
little_endian_store_16(acl_buffer, 4, len + 0);
|
||||
// 6 - L2CAP channel DEST
|
||||
little_endian_store_16(acl_buffer, 6, remote_cid);
|
||||
}
|
||||
|
||||
int l2cap_send_prepared(uint16_t local_cid, uint16_t len){
|
||||
|
||||
if (!hci_is_packet_buffer_reserved()){
|
||||
@ -466,26 +472,6 @@ int l2cap_send_prepared(uint16_t local_cid, uint16_t len){
|
||||
return hci_send_acl_packet_buffer(len+8);
|
||||
}
|
||||
|
||||
int l2cap_send_prepared_connectionless(hci_con_handle_t con_handle, uint16_t cid, uint16_t len){
|
||||
|
||||
if (!hci_is_packet_buffer_reserved()){
|
||||
log_error("l2cap_send_prepared_connectionless called without reserving packet first");
|
||||
return BTSTACK_ACL_BUFFERS_FULL;
|
||||
}
|
||||
|
||||
if (!hci_can_send_prepared_acl_packet_now(con_handle)){
|
||||
log_info("l2cap_send_prepared_connectionless handle 0x%02x, cid 0x%02x, cannot send", con_handle, cid);
|
||||
return BTSTACK_ACL_BUFFERS_FULL;
|
||||
}
|
||||
|
||||
log_debug("l2cap_send_prepared_connectionless handle %u, cid 0x%02x", con_handle, cid);
|
||||
|
||||
uint8_t *acl_buffer = hci_get_outgoing_packet_buffer();
|
||||
l2cap_setup_header(acl_buffer, con_handle, cid, len);
|
||||
// send
|
||||
return hci_send_acl_packet_buffer(len+8);
|
||||
}
|
||||
|
||||
int l2cap_send(uint16_t local_cid, uint8_t *data, uint16_t len){
|
||||
|
||||
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
|
||||
@ -512,21 +498,6 @@ int l2cap_send(uint16_t local_cid, uint8_t *data, uint16_t len){
|
||||
return l2cap_send_prepared(local_cid, len);
|
||||
}
|
||||
|
||||
int l2cap_send_connectionless(hci_con_handle_t con_handle, uint16_t cid, uint8_t *data, uint16_t len){
|
||||
|
||||
if (!hci_can_send_acl_packet_now(con_handle)){
|
||||
log_info("l2cap_send cid 0x%02x, cannot send", cid);
|
||||
return BTSTACK_ACL_BUFFERS_FULL;
|
||||
}
|
||||
|
||||
hci_reserve_packet_buffer();
|
||||
uint8_t *acl_buffer = hci_get_outgoing_packet_buffer();
|
||||
|
||||
memcpy(&acl_buffer[8], data, len);
|
||||
|
||||
return l2cap_send_prepared_connectionless(con_handle, cid, len);
|
||||
}
|
||||
|
||||
int l2cap_send_echo_request(hci_con_handle_t con_handle, uint8_t *data, uint16_t len){
|
||||
return l2cap_send_signaling_packet(con_handle, ECHO_REQUEST, 0x77, len, data);
|
||||
}
|
||||
@ -538,8 +509,36 @@ static inline void channelStateVarSetFlag(l2cap_channel_t *channel, L2CAP_CHANNE
|
||||
static inline void channelStateVarClearFlag(l2cap_channel_t *channel, L2CAP_CHANNEL_STATE_VAR flag){
|
||||
channel->state_var = (L2CAP_CHANNEL_STATE_VAR) (channel->state_var & ~flag);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
static int l2cap_send_le_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, uint8_t identifier, ...){
|
||||
|
||||
if (!hci_can_send_acl_packet_now(handle)){
|
||||
log_info("l2cap_send_le_signaling_packet, cannot send");
|
||||
return BTSTACK_ACL_BUFFERS_FULL;
|
||||
}
|
||||
|
||||
// log_info("l2cap_send_le_signaling_packet type %u", cmd);
|
||||
hci_reserve_packet_buffer();
|
||||
uint8_t *acl_buffer = hci_get_outgoing_packet_buffer();
|
||||
va_list argptr;
|
||||
va_start(argptr, identifier);
|
||||
uint16_t len = l2cap_create_signaling_le(acl_buffer, handle, cmd, identifier, argptr);
|
||||
va_end(argptr);
|
||||
// log_info("l2cap_send_le_signaling_packet con %u!", handle);
|
||||
return hci_send_acl_packet_buffer(len);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t l2cap_max_mtu(void){
|
||||
return HCI_ACL_PAYLOAD_SIZE - L2CAP_HEADER_SIZE;
|
||||
}
|
||||
|
||||
uint16_t l2cap_max_le_mtu(void){
|
||||
return l2cap_max_mtu();
|
||||
}
|
||||
|
||||
// MARK: L2CAP_RUN
|
||||
// process outstanding signaling tasks
|
||||
@ -559,6 +558,9 @@ static void l2cap_run(void){
|
||||
uint16_t result = signaling_responses[0].data; // CONNECTION_REQUEST, COMMAND_REJECT
|
||||
uint8_t response_code = signaling_responses[0].code;
|
||||
|
||||
// avoid warnings
|
||||
(void) infoType;
|
||||
|
||||
// remove first item before sending (to avoid sending response mutliple times)
|
||||
signaling_responses_pending--;
|
||||
int i;
|
||||
@ -567,6 +569,7 @@ static void l2cap_run(void){
|
||||
}
|
||||
|
||||
switch (response_code){
|
||||
#ifdef ENABLE_CLASSIC
|
||||
case CONNECTION_REQUEST:
|
||||
l2cap_send_signaling_packet(handle, CONNECTION_RESPONSE, sig_id, 0, 0, result, 0);
|
||||
// also disconnect if result is 0x0003 - security blocked
|
||||
@ -606,6 +609,7 @@ static void l2cap_run(void){
|
||||
case COMMAND_REJECT:
|
||||
l2cap_send_signaling_packet(handle, COMMAND_REJECT, sig_id, result, 0, NULL);
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_BLE
|
||||
case LE_CREDIT_BASED_CONNECTION_REQUEST:
|
||||
l2cap_send_le_signaling_packet(handle, LE_CREDIT_BASED_CONNECTION_RESPONSE, sig_id, 0, 0, 0, 0, result);
|
||||
@ -620,8 +624,11 @@ static void l2cap_run(void){
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t config_options[4];
|
||||
btstack_linked_list_iterator_t it;
|
||||
(void) it;
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
uint8_t config_options[4];
|
||||
btstack_linked_list_iterator_init(&it, &l2cap_channels);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
|
||||
@ -729,8 +736,8 @@ static void l2cap_run(void){
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
#ifdef ENABLE_LE_DATA_CHANNELS
|
||||
btstack_linked_list_iterator_init(&it, &l2cap_le_channels);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
@ -833,7 +840,9 @@ static void l2cap_run(void){
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
// send l2cap con paramter update if necessary
|
||||
hci_connections_get_iterator(&it);
|
||||
while(btstack_linked_list_iterator_has_next(&it)){
|
||||
@ -858,20 +867,12 @@ static void l2cap_run(void){
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// log_info("l2cap_run: exit");
|
||||
}
|
||||
|
||||
uint16_t l2cap_max_mtu(void){
|
||||
return HCI_ACL_PAYLOAD_SIZE - L2CAP_HEADER_SIZE;
|
||||
}
|
||||
|
||||
uint16_t l2cap_max_le_mtu(void){
|
||||
return l2cap_max_mtu();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
static void l2cap_handle_connection_complete(hci_con_handle_t con_handle, l2cap_channel_t * channel){
|
||||
if (channel->state == L2CAP_STATE_WAIT_CONNECTION_COMPLETE || channel->state == L2CAP_STATE_WILL_SEND_CREATE_CONNECTION) {
|
||||
log_info("l2cap_handle_connection_complete expected state");
|
||||
@ -896,7 +897,9 @@ static void l2cap_handle_remote_supported_features_received(l2cap_channel_t * ch
|
||||
// fine, go ahead
|
||||
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_REQUEST;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef L2CAP_USES_CHANNELS
|
||||
static l2cap_channel_t * l2cap_create_channel_entry(btstack_packet_handler_t packet_handler, bd_addr_t address, bd_addr_type_t address_type,
|
||||
uint16_t psm, uint16_t local_mtu, gap_security_level_t security_level){
|
||||
|
||||
@ -928,6 +931,9 @@ static l2cap_channel_t * l2cap_create_channel_entry(btstack_packet_handler_t pac
|
||||
channel->local_sig_id = L2CAP_SIG_ID_INVALID;
|
||||
return channel;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
|
||||
/**
|
||||
* @brief Creates L2CAP channel to the PSM of a remote device with baseband address. A new baseband connection will be initiated if necessary.
|
||||
@ -1021,8 +1027,11 @@ static void l2cap_handle_connection_success_for_addr(bd_addr_t address, hci_con_
|
||||
// process
|
||||
l2cap_run();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void l2cap_notify_channel_can_send(void){
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
btstack_linked_list_iterator_t it;
|
||||
btstack_linked_list_iterator_init(&it, &l2cap_channels);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
@ -1032,7 +1041,7 @@ static void l2cap_notify_channel_can_send(void){
|
||||
channel->waiting_for_can_send_now = 0;
|
||||
l2cap_emit_can_send_now(channel->packet_handler, channel->local_cid);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int i;
|
||||
for (i=0;i<L2CAP_FIXED_CHANNEL_TABLE_SIZE;i++){
|
||||
@ -1054,11 +1063,28 @@ static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *
|
||||
|
||||
bd_addr_t address;
|
||||
hci_con_handle_t handle;
|
||||
btstack_linked_list_iterator_t it;
|
||||
int hci_con_used;
|
||||
|
||||
btstack_linked_list_iterator_t it;
|
||||
|
||||
// avoid unused warnings
|
||||
(void) address;
|
||||
(void) hci_con_used;
|
||||
(void) it;
|
||||
|
||||
switch(hci_event_packet_get_type(packet)){
|
||||
|
||||
// Notify channel packet handler if they can send now
|
||||
case HCI_EVENT_TRANSPORT_PACKET_SENT:
|
||||
case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
|
||||
l2cap_run(); // try sending signaling packets first
|
||||
l2cap_notify_channel_can_send();
|
||||
break;
|
||||
|
||||
case HCI_EVENT_COMMAND_STATUS:
|
||||
l2cap_run(); // try sending signaling packets first
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
// handle connection complete events
|
||||
case HCI_EVENT_CONNECTION_COMPLETE:
|
||||
reverse_bd_addr(&packet[5], address);
|
||||
@ -1069,7 +1095,7 @@ static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *
|
||||
l2cap_handle_connection_failed_for_addr(address, packet[2]);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
// handle successful create connection cancel command
|
||||
case HCI_EVENT_COMMAND_COMPLETE:
|
||||
if (HCI_EVENT_IS_COMMAND_COMPLETE(packet, hci_create_connection_cancel)) {
|
||||
@ -1081,15 +1107,13 @@ static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *
|
||||
}
|
||||
l2cap_run(); // try sending signaling packets first
|
||||
break;
|
||||
|
||||
case HCI_EVENT_COMMAND_STATUS:
|
||||
l2cap_run(); // try sending signaling packets first
|
||||
break;
|
||||
#endif
|
||||
|
||||
// handle disconnection complete events
|
||||
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||
// send l2cap disconnect events for all channels on this handle and free them
|
||||
handle = little_endian_read_16(packet, 3);
|
||||
#ifdef ENABLE_CLASSIC
|
||||
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);
|
||||
@ -1099,6 +1123,7 @@ static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *
|
||||
btstack_linked_list_iterator_remove(&it);
|
||||
btstack_memory_l2cap_channel_free(channel);
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_LE_DATA_CHANNELS
|
||||
btstack_linked_list_iterator_init(&it, &l2cap_le_channels);
|
||||
while (btstack_linked_list_iterator_has_next(&it)){
|
||||
@ -1111,14 +1136,8 @@ static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *
|
||||
#endif
|
||||
break;
|
||||
|
||||
// Notify channel packet handler if they can send now
|
||||
case HCI_EVENT_TRANSPORT_PACKET_SENT:
|
||||
case HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS:
|
||||
l2cap_run(); // try sending signaling packets first
|
||||
l2cap_notify_channel_can_send();
|
||||
break;
|
||||
|
||||
// HCI Connection Timeouts
|
||||
#ifdef ENABLE_CLASSIC
|
||||
case L2CAP_EVENT_TIMEOUT_CHECK:
|
||||
handle = little_endian_read_16(packet, 2);
|
||||
if (gap_get_connection_type(handle) != GAP_CONNECTION_ACL) break;
|
||||
@ -1185,6 +1204,7 @@ static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -1193,12 +1213,6 @@ static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *
|
||||
l2cap_run();
|
||||
}
|
||||
|
||||
static void l2cap_handle_disconnect_request(l2cap_channel_t *channel, uint16_t identifier){
|
||||
channel->remote_sig_id = identifier;
|
||||
channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE;
|
||||
l2cap_run();
|
||||
}
|
||||
|
||||
static void l2cap_register_signaling_response(hci_con_handle_t handle, uint8_t code, uint8_t sig_id, uint16_t data){
|
||||
// Vol 3, Part A, 4.3: "The DCID and SCID fields shall be ignored when the result field indi- cates the connection was refused."
|
||||
if (signaling_responses_pending < NR_PENDING_SIGNALING_RESPONSES) {
|
||||
@ -1211,6 +1225,13 @@ static void l2cap_register_signaling_response(hci_con_handle_t handle, uint8_t c
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
static void l2cap_handle_disconnect_request(l2cap_channel_t *channel, uint16_t identifier){
|
||||
channel->remote_sig_id = identifier;
|
||||
channel->state = L2CAP_STATE_WILL_SEND_DISCONNECT_RESPONSE;
|
||||
l2cap_run();
|
||||
}
|
||||
|
||||
static void l2cap_handle_connection_request(hci_con_handle_t handle, uint8_t sig_id, uint16_t psm, uint16_t source_cid){
|
||||
|
||||
// log_info("l2cap_handle_connection_request for handle %u, psm %u cid 0x%02x", handle, psm, source_cid);
|
||||
@ -1521,8 +1542,21 @@ static void l2cap_signaling_handler_dispatch( hci_con_handle_t handle, uint8_t *
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
|
||||
static void l2cap_emit_connection_parameter_update_response(hci_con_handle_t con_handle, uint16_t result){
|
||||
uint8_t event[6];
|
||||
event[0] = L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE;
|
||||
event[1] = 4;
|
||||
little_endian_store_16(event, 2, con_handle);
|
||||
little_endian_store_16(event, 4, result);
|
||||
hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
if (!l2cap_event_packet_handler) return;
|
||||
(*l2cap_event_packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
|
||||
}
|
||||
|
||||
// @returns valid
|
||||
static int l2cap_le_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t * command, uint8_t sig_id){
|
||||
hci_connection_t * connection;
|
||||
@ -1799,12 +1833,16 @@ static int l2cap_le_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t
|
||||
|
||||
static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size ){
|
||||
|
||||
l2cap_channel_t * l2cap_channel;
|
||||
(void) l2cap_channel;
|
||||
|
||||
// Get Channel ID
|
||||
uint16_t channel_id = READ_L2CAP_CHANNEL_ID(packet);
|
||||
hci_con_handle_t handle = READ_ACL_CONNECTION_HANDLE(packet);
|
||||
|
||||
switch (channel_id) {
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
case L2CAP_CID_SIGNALING: {
|
||||
uint16_t command_offset = 8;
|
||||
while (command_offset < size) {
|
||||
@ -1816,7 +1854,8 @@ static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
case L2CAP_CID_SIGNALING_LE: {
|
||||
uint16_t sig_id = packet[COMPLETE_L2CAP_HEADER + 1];
|
||||
@ -1846,14 +1885,14 @@ static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
default:
|
||||
#ifdef ENABLE_CLASSIC
|
||||
// Find channel for this channel_id and connection handle
|
||||
l2cap_channel_t * l2cap_channel;
|
||||
l2cap_channel = l2cap_get_channel_for_local_cid(channel_id);
|
||||
if (l2cap_channel) {
|
||||
l2cap_dispatch_to_channel(l2cap_channel, L2CAP_DATA_PACKET, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER);
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef ENABLE_LE_DATA_CHANNELS
|
||||
l2cap_channel = l2cap_le_get_channel_for_local_cid(channel_id);
|
||||
if (l2cap_channel) {
|
||||
@ -1891,12 +1930,19 @@ static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
l2cap_run();
|
||||
}
|
||||
|
||||
// Bluetooth 4.0 - allows to register handler for Attribute Protocol and Security Manager Protocol
|
||||
void l2cap_register_fixed_channel(btstack_packet_handler_t the_packet_handler, uint16_t channel_id) {
|
||||
int index = l2cap_fixed_channel_table_index_for_channel_id(channel_id);
|
||||
if (index < 0) return;
|
||||
fixed_channels[index].callback = the_packet_handler;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CLASSIC
|
||||
// finalize closed channel - l2cap_handle_disconnect_request & DISCONNECTION_RESPONSE
|
||||
void l2cap_finialize_channel_close(l2cap_channel_t * channel){
|
||||
channel->state = L2CAP_STATE_CLOSED;
|
||||
@ -1972,15 +2018,8 @@ uint8_t l2cap_unregister_service(uint16_t psm){
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Bluetooth 4.0 - allows to register handler for Attribute Protocol and Security Manager Protocol
|
||||
void l2cap_register_fixed_channel(btstack_packet_handler_t the_packet_handler, uint16_t channel_id) {
|
||||
int index = l2cap_fixed_channel_table_index_for_channel_id(channel_id);
|
||||
if (index < 0) return;
|
||||
fixed_channels[index].callback = the_packet_handler;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_BLE
|
||||
|
||||
#ifdef ENABLE_LE_DATA_CHANNELS
|
||||
|
||||
@ -2306,5 +2345,3 @@ uint8_t l2cap_le_disconnect(uint16_t local_cid)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user