add LE Data Channel Events (L2CAP_EVENT_LE_*). implement can send now logic

This commit is contained in:
Matthias Ringwald 2016-10-18 11:49:04 +02:00
parent cab29d481b
commit 4427624894
5 changed files with 410 additions and 58 deletions

View File

@ -426,6 +426,53 @@ typedef uint8_t sm_key_t[16];
*/
#define L2CAP_EVENT_CAN_SEND_NOW 0x78
// LE Data Channels
/**
* @format 1BH2222
* @param address_type
* @param address
* @param handle
* @param psm
* @param local_cid
* @param remote_cid
* @param remote_mtu
*/
#define L2CAP_EVENT_LE_INCOMING_CONNECTION 0x79
/**
* @format 11BH22222
* @param status
* @param address_type
* @param address
* @param handle
* @param psm
* @param local_cid
* @param remote_cid
* @param local_mtu
* @param remote_mtu
*/
#define L2CAP_EVENT_LE_CHANNEL_OPENED 0x7a
/*
* @format 2
* @param local_cid
*/
#define L2CAP_EVENT_LE_CHANNEL_CLOSED 0x7b
/*
* @format 2
* @param local_cid
*/
#define L2CAP_EVENT_LE_CAN_SEND_NOW 0x7c
/*
* @format 2
* @param local_cid
*/
#define L2CAP_EVENT_LE_PACKET_SENT 0x7d
// RFCOMM EVENTS
/**

View File

@ -1157,6 +1157,182 @@ static inline uint16_t l2cap_event_can_send_now_get_local_cid(const uint8_t * ev
return little_endian_read_16(event, 2);
}
/**
* @brief Get field address_type from event L2CAP_EVENT_LE_INCOMING_CONNECTION
* @param event packet
* @return address_type
* @note: btstack_type 1
*/
static inline uint8_t l2cap_event_le_incoming_connection_get_address_type(const uint8_t * event){
return event[2];
}
/**
* @brief Get field address from event L2CAP_EVENT_LE_INCOMING_CONNECTION
* @param event packet
* @param Pointer to storage for address
* @note: btstack_type B
*/
static inline void l2cap_event_le_incoming_connection_get_address(const uint8_t * event, bd_addr_t address){
reverse_bd_addr(&event[3], address);
}
/**
* @brief Get field handle from event L2CAP_EVENT_LE_INCOMING_CONNECTION
* @param event packet
* @return handle
* @note: btstack_type H
*/
static inline hci_con_handle_t l2cap_event_le_incoming_connection_get_handle(const uint8_t * event){
return little_endian_read_16(event, 9);
}
/**
* @brief Get field psm from event L2CAP_EVENT_LE_INCOMING_CONNECTION
* @param event packet
* @return psm
* @note: btstack_type 2
*/
static inline uint16_t l2cap_event_le_incoming_connection_get_psm(const uint8_t * event){
return little_endian_read_16(event, 11);
}
/**
* @brief Get field local_cid from event L2CAP_EVENT_LE_INCOMING_CONNECTION
* @param event packet
* @return local_cid
* @note: btstack_type 2
*/
static inline uint16_t l2cap_event_le_incoming_connection_get_local_cid(const uint8_t * event){
return little_endian_read_16(event, 13);
}
/**
* @brief Get field remote_cid from event L2CAP_EVENT_LE_INCOMING_CONNECTION
* @param event packet
* @return remote_cid
* @note: btstack_type 2
*/
static inline uint16_t l2cap_event_le_incoming_connection_get_remote_cid(const uint8_t * event){
return little_endian_read_16(event, 15);
}
/**
* @brief Get field remote_mtu from event L2CAP_EVENT_LE_INCOMING_CONNECTION
* @param event packet
* @return remote_mtu
* @note: btstack_type 2
*/
static inline uint16_t l2cap_event_le_incoming_connection_get_remote_mtu(const uint8_t * event){
return little_endian_read_16(event, 17);
}
/**
* @brief Get field status from event L2CAP_EVENT_LE_CHANNEL_OPENED
* @param event packet
* @return status
* @note: btstack_type 1
*/
static inline uint8_t l2cap_event_le_channel_opened_get_status(const uint8_t * event){
return event[2];
}
/**
* @brief Get field address_type from event L2CAP_EVENT_LE_CHANNEL_OPENED
* @param event packet
* @return address_type
* @note: btstack_type 1
*/
static inline uint8_t l2cap_event_le_channel_opened_get_address_type(const uint8_t * event){
return event[3];
}
/**
* @brief Get field address from event L2CAP_EVENT_LE_CHANNEL_OPENED
* @param event packet
* @param Pointer to storage for address
* @note: btstack_type B
*/
static inline void l2cap_event_le_channel_opened_get_address(const uint8_t * event, bd_addr_t address){
reverse_bd_addr(&event[4], address);
}
/**
* @brief Get field handle from event L2CAP_EVENT_LE_CHANNEL_OPENED
* @param event packet
* @return handle
* @note: btstack_type H
*/
static inline hci_con_handle_t l2cap_event_le_channel_opened_get_handle(const uint8_t * event){
return little_endian_read_16(event, 10);
}
/**
* @brief Get field psm from event L2CAP_EVENT_LE_CHANNEL_OPENED
* @param event packet
* @return psm
* @note: btstack_type 2
*/
static inline uint16_t l2cap_event_le_channel_opened_get_psm(const uint8_t * event){
return little_endian_read_16(event, 12);
}
/**
* @brief Get field local_cid from event L2CAP_EVENT_LE_CHANNEL_OPENED
* @param event packet
* @return local_cid
* @note: btstack_type 2
*/
static inline uint16_t l2cap_event_le_channel_opened_get_local_cid(const uint8_t * event){
return little_endian_read_16(event, 14);
}
/**
* @brief Get field remote_cid from event L2CAP_EVENT_LE_CHANNEL_OPENED
* @param event packet
* @return remote_cid
* @note: btstack_type 2
*/
static inline uint16_t l2cap_event_le_channel_opened_get_remote_cid(const uint8_t * event){
return little_endian_read_16(event, 16);
}
/**
* @brief Get field local_mtu from event L2CAP_EVENT_LE_CHANNEL_OPENED
* @param event packet
* @return local_mtu
* @note: btstack_type 2
*/
static inline uint16_t l2cap_event_le_channel_opened_get_local_mtu(const uint8_t * event){
return little_endian_read_16(event, 18);
}
/**
* @brief Get field remote_mtu from event L2CAP_EVENT_LE_CHANNEL_OPENED
* @param event packet
* @return remote_mtu
* @note: btstack_type 2
*/
static inline uint16_t l2cap_event_le_channel_opened_get_remote_mtu(const uint8_t * event){
return little_endian_read_16(event, 20);
}
/**
* @brief Get field local_cid from event L2CAP_EVENT_LE_CHANNEL_CLOSED
* @param event packet
* @return local_cid
* @note: btstack_type 2
*/
static inline uint16_t l2cap_event_le_channel_closed_get_local_cid(const uint8_t * event){
return little_endian_read_16(event, 2);
}
/**
* @brief Get field local_cid from event L2CAP_EVENT_LE_CAN_SEND_NOW
* @param event packet
* @return local_cid
* @note: btstack_type 2
*/
static inline uint16_t l2cap_event_le_can_send_now_get_local_cid(const uint8_t * event){
return little_endian_read_16(event, 2);
}
/**
* @brief Get field local_cid from event L2CAP_EVENT_LE_PACKET_SENT
* @param event packet
* @return local_cid
* @note: btstack_type 2
*/
static inline uint16_t l2cap_event_le_packet_sent_get_local_cid(const uint8_t * event){
return little_endian_read_16(event, 2);
}
/**
* @brief Get field status from event RFCOMM_EVENT_CHANNEL_OPENED
* @param event packet

View File

@ -87,12 +87,13 @@ 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_connection_request(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);
#ifdef ENABLE_LE_DATA_CHANNELS
static void l2cap_le_notify_channel_can_send(l2cap_channel_t *channel);
static void l2cap_le_finialize_channel_close(l2cap_channel_t *channel);
static inline l2cap_service_t * l2cap_le_get_service(uint16_t psm);
#endif
@ -180,6 +181,15 @@ static void l2cap_dispatch_to_channel(l2cap_channel_t *channel, uint8_t type, ui
(* (channel->packet_handler))(type, channel->local_cid, data, size);
}
static void l2cap_emit_simple_event_with_cid(l2cap_channel_t * channel, uint8_t event_code){
uint8_t event[4];
event[0] = event_code;
event[1] = sizeof(event) - 2;
little_endian_store_16(event, 2, channel->local_cid);
hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event));
}
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,
@ -200,17 +210,23 @@ void l2cap_emit_channel_opened(l2cap_channel_t *channel, uint8_t status) {
l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event));
}
void l2cap_emit_channel_closed(l2cap_channel_t *channel) {
static void l2cap_emit_channel_closed(l2cap_channel_t *channel) {
log_info("L2CAP_EVENT_CHANNEL_CLOSED local_cid 0x%x", channel->local_cid);
uint8_t event[4];
event[0] = L2CAP_EVENT_CHANNEL_CLOSED;
event[1] = sizeof(event) - 2;
little_endian_store_16(event, 2, channel->local_cid);
hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event));
l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_CHANNEL_CLOSED);
}
void l2cap_emit_connection_request(l2cap_channel_t *channel) {
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);
uint8_t event[16];
@ -225,16 +241,6 @@ void l2cap_emit_connection_request(l2cap_channel_t *channel) {
l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event));
}
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_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;
@ -246,6 +252,46 @@ static void l2cap_emit_connection_parameter_update_response(hci_con_handle_t con
(*l2cap_event_packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
}
#ifdef ENABLE_LE_DATA_CHANNELS
// 1BH2222
static void l2cap_emit_le_incoming_connection(l2cap_channel_t *channel) {
log_info("L2CAP_EVENT_LE_INCOMING_CONNECTION addr_type %u, addr %s handle 0x%x psm 0x%x local_cid 0x%x remote_cid 0x%x, remote_mtu %u",
channel->address_type, bd_addr_to_str(channel->address), channel->con_handle, channel->psm, channel->local_cid, channel->remote_cid, channel->remote_mtu);
uint8_t event[19];
event[0] = L2CAP_EVENT_LE_INCOMING_CONNECTION;
event[1] = sizeof(event) - 2;
event[2] = channel->address_type;
reverse_bd_addr(channel->address, &event[3]);
little_endian_store_16(event, 9, channel->con_handle);
little_endian_store_16(event, 11, channel->psm);
little_endian_store_16(event, 13, channel->local_cid);
little_endian_store_16(event, 15, channel->remote_cid);
little_endian_store_16(event, 17, channel->remote_mtu);
hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event));
}
// 11BH22222
static void l2cap_emit_le_channel_opened(l2cap_channel_t *channel, uint8_t status) {
log_info("L2CAP_EVENT_LE_CHANNEL_OPENED status 0x%x addr_type %u addr %s handle 0x%x psm 0x%x local_cid 0x%x remote_cid 0x%x local_mtu %u, remote_mtu %u",
status, channel->address_type, bd_addr_to_str(channel->address), channel->con_handle, channel->psm,
channel->local_cid, channel->remote_cid, channel->local_mtu, channel->remote_mtu);
uint8_t event[22];
event[0] = L2CAP_EVENT_LE_CHANNEL_OPENED;
event[1] = sizeof(event) - 2;
event[2] = status;
event[3] = channel->address_type;
reverse_bd_addr(channel->address, &event[4]);
little_endian_store_16(event, 10, channel->con_handle);
little_endian_store_16(event, 12, channel->psm);
little_endian_store_16(event, 14, channel->local_cid);
little_endian_store_16(event, 16, channel->remote_cid);
little_endian_store_16(event, 18, channel->local_mtu);
little_endian_store_16(event, 20, channel->remote_mtu);
hci_dump_packet( HCI_EVENT_PACKET, 0, event, sizeof(event));
l2cap_dispatch_to_channel(channel, HCI_EVENT_PACKET, event, sizeof(event));
}
#endif
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);
@ -756,7 +802,7 @@ static void l2cap_run(void){
channel->new_credits_incoming = 0;
l2cap_send_le_signaling_packet(channel->con_handle, LE_CREDIT_BASED_CONNECTION_RESPONSE, channel->remote_sig_id, channel->local_cid, channel->local_mtu, 23, channel->credits_incoming, 0);
// notify client
l2cap_emit_channel_opened(channel, 0);
l2cap_emit_le_channel_opened(channel, 0);
break;
case L2CAP_STATE_WILL_SEND_LE_CONNECTION_RESPONSE_DECLINE:
if (!hci_can_send_acl_packet_now(channel->con_handle)) break;
@ -808,7 +854,10 @@ static void l2cap_run(void){
if (channel->send_sdu_pos >= channel->send_sdu_len + 2){
channel->send_sdu_buffer = NULL;
// TODO: send done event
// send done event
l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_LE_PACKET_SENT);
// inform about can send now
l2cap_le_notify_channel_can_send(channel);
}
hci_send_acl_packet_buffer(8 + pos);
break;
@ -1017,6 +1066,17 @@ static void l2cap_handle_connection_success_for_addr(bd_addr_t address, hci_con_
l2cap_run();
}
#ifdef ENABLE_LE_DATA_CHANNELS
static void l2cap_le_notify_channel_can_send(l2cap_channel_t *channel){
if (!channel->waiting_for_can_send_now) return;
if (channel->send_sdu_buffer) return;
channel->waiting_for_can_send_now = 0;
log_info("L2CAP_EVENT_CHANNEL_LE_CAN_SEND_NOW local_cid 0x%x", channel->local_cid);
l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_LE_CAN_SEND_NOW);
}
#endif
static void l2cap_notify_channel_can_send(void){
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, &l2cap_channels);
@ -1028,6 +1088,7 @@ static void l2cap_notify_channel_can_send(void){
l2cap_emit_can_send_now(channel->packet_handler, channel->local_cid);
}
int i;
for (i=0;i<L2CAP_FIXED_CHANNEL_TABLE_SIZE;i++){
if (!fixed_channels[i].callback) continue;
@ -1158,7 +1219,7 @@ static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *
case L2CAP_STATE_WAIT_INCOMING_SECURITY_LEVEL_UPDATE:
if (actual_level >= required_level){
channel->state = L2CAP_STATE_WAIT_CLIENT_ACCEPT_OR_REJECT;
l2cap_emit_connection_request(channel);
l2cap_emit_incoming_connection(channel);
} else {
channel->reason = 0x0003; // security block
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_DECLINE;
@ -1605,7 +1666,7 @@ static int l2cap_le_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t
if (channel->state == L2CAP_STATE_WAIT_LE_CONNECTION_RESPONSE){
channel->state = L2CAP_STATE_CLOSED;
// no official value for this, use: Connection refused LE_PSM not supported - 0x0002
l2cap_emit_channel_opened(channel, 0x0002);
l2cap_emit_le_channel_opened(channel, 0x0002);
// discard channel
btstack_linked_list_remove(&l2cap_le_channels, (btstack_linked_item_t *) channel);
@ -1701,7 +1762,7 @@ static int l2cap_le_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t
btstack_linked_list_add(&l2cap_le_channels, (btstack_linked_item_t *) channel);
// post connection request event
l2cap_emit_connection_request(channel);
l2cap_emit_le_incoming_connection(channel);
} else {
// Connection refused LE_PSM not supported
@ -1727,7 +1788,7 @@ static int l2cap_le_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t
if (result){
channel->state = L2CAP_STATE_CLOSED;
// map l2cap connection response result to BTstack status enumeration
l2cap_emit_channel_opened(channel, result);
l2cap_emit_le_channel_opened(channel, result);
// discard channel
btstack_linked_list_remove(&l2cap_le_channels, (btstack_linked_item_t *) channel);
@ -1741,7 +1802,7 @@ static int l2cap_le_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t
channel->remote_mps = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 4);
channel->credits_outgoing = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET + 6);
channel->state = L2CAP_STATE_OPEN;
l2cap_emit_channel_opened(channel, result);
l2cap_emit_le_channel_opened(channel, result);
break;
case LE_FLOW_CONTROL_CREDIT:
@ -1901,9 +1962,8 @@ void l2cap_finialize_channel_close(l2cap_channel_t * channel){
// finalize closed channel - l2cap_handle_disconnect_request & DISCONNECTION_RESPONSE
void l2cap_le_finialize_channel_close(l2cap_channel_t * channel){
channel->state = L2CAP_STATE_CLOSED;
l2cap_emit_channel_closed(channel);
l2cap_emit_simple_event_with_cid(channel, L2CAP_EVENT_CHANNEL_CLOSED);
// discard channel
l2cap_stop_rtx(channel);
btstack_linked_list_remove(&l2cap_le_channels, (btstack_linked_item_t *) channel);
btstack_memory_l2cap_channel_free(channel);
}
@ -2156,8 +2216,20 @@ uint8_t l2cap_le_provide_credits(uint16_t local_cid, uint16_t credits){
* @param local_cid L2CAP LE Data Channel Identifier
*/
int l2cap_le_can_send_now(uint16_t local_cid){
// check if data can be sent via le at all
return 0;
l2cap_channel_t * channel = l2cap_le_get_channel_for_local_cid(local_cid);
if (!channel) {
log_error("l2cap_le_provide_credits no channel for cid 0x%02x", local_cid);
return 0;
}
// check state
if (channel->state != L2CAP_STATE_OPEN) return 0;
// check queue
if (channel->send_sdu_buffer) return 0;
// fine, go ahead
return 1;
}
/**
@ -2167,7 +2239,13 @@ int l2cap_le_can_send_now(uint16_t local_cid){
* @param local_cid L2CAP LE Data Channel Identifier
*/
uint8_t l2cap_le_request_can_send_now_event(uint16_t local_cid){
// same as for non-le
l2cap_channel_t * channel = l2cap_le_get_channel_for_local_cid(local_cid);
if (!channel) {
log_error("l2cap_le_request_can_send_now_event no channel for cid 0x%02x", local_cid);
return 0;
}
channel->waiting_for_can_send_now = 1;
l2cap_le_notify_channel_can_send(channel);
return 0;
}

View File

@ -374,7 +374,7 @@ uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, hci_con
uint8_t l2cap_le_provide_credits(uint16_t cid, uint16_t credits);
/**
* @brief Check if outgoing buffer is available and that there's space on the Bluetooth module
* @brief Check if packet can be scheduled for transmission
* @param local_cid L2CAP LE Data Channel Identifier
*/
int l2cap_le_can_send_now(uint16_t cid);

View File

@ -87,6 +87,8 @@ static uint16_t initial_credits = L2CAP_LE_AUTOMATIC_CREDITS;
const char * data_short = "a";
const char * data_long = "0123456789abcdefghijklmnopqrstuvwxyz";
const char * data_classic = "ABCDEF";
static int todo_send_short;
static int todo_send_long;
static uint8_t buffer_x[1000];
@ -141,31 +143,60 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
case HCI_EVENT_DISCONNECTION_COMPLETE:
break;
// Classic
case L2CAP_EVENT_INCOMING_CONNECTION:
psm = little_endian_read_16(packet, 10);
cid = little_endian_read_16(packet, 12);
switch (psm){
case TSPX_psm:
printf("L2CAP: Accepting incoming Classic connection request for 0x%02x, PSM %02x\n", cid, psm);
l2cap_accept_connection(cid);
break;
case TSPX_le_psm:
printf("L2CAP: Accepting incoming LE connection request for 0x%02x, PSM %02x\n", cid, psm);
l2cap_le_accept_connection(cid, receive_buffer_X, sizeof(receive_buffer_X), initial_credits);
break;
default:
break;
}
psm = l2cap_event_incoming_connection_get_psm(packet);
cid = l2cap_event_incoming_connection_get_local_cid(packet);
if (psm != TSPX_psm) break;
printf("L2CAP: Accepting incoming Classic connection request for 0x%02x, PSM %02x\n", cid, psm);
l2cap_le_accept_connection(cid, receive_buffer_X, sizeof(receive_buffer_X), initial_credits);
break;
case L2CAP_EVENT_CHANNEL_OPENED:
// inform about new l2cap connection
reverse_bd_addr(&packet[3], event_address);
psm = little_endian_read_16(packet, 11);
cid = little_endian_read_16(packet, 13);
handle = little_endian_read_16(packet, 9);
l2cap_event_channel_opened_get_address(packet, event_address);
psm = l2cap_event_channel_opened_get_psm(packet);
cid = l2cap_event_channel_opened_get_local_cid(packet);
handle = l2cap_event_channel_opened_get_handle(packet);
if (packet[2] == 0) {
printf("L2CAP: Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n",
printf("L2CAP: Classic Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n",
bd_addr_to_str(event_address), handle, psm, cid, l2cap_event_channel_opened_get_remote_cid(packet));
switch (psm){
case TSPX_le_psm:
cid_le = cid;
break;
case TSPX_psm:
cid_classic = cid;
break;
default:
break;
}
} else {
printf("L2CAP: classic connection to device %s failed. status code %u\n", bd_addr_to_str(event_address), packet[2]);
}
break;
case L2CAP_EVENT_CHANNEL_CLOSED:
cid = l2cap_event_channel_closed_get_local_cid(packet);
printf("L2CAP: Clasic Channel closed 0x%02x\n", cid);
break;
// LE Data Channels
case L2CAP_EVENT_LE_INCOMING_CONNECTION:
psm = l2cap_event_le_incoming_connection_get_psm(packet);
cid = l2cap_event_le_incoming_connection_get_local_cid(packet);
if (psm != TSPX_le_psm) break;
printf("L2CAP: Accepting incoming LE connection request for 0x%02x, PSM %02x\n", cid, psm);
l2cap_le_accept_connection(cid, receive_buffer_X, sizeof(receive_buffer_X), initial_credits);
break;
case L2CAP_EVENT_LE_CHANNEL_OPENED:
// inform about new l2cap connection
l2cap_event_le_channel_opened_get_address(packet, event_address);
psm = l2cap_event_le_channel_opened_get_psm(packet);
cid = l2cap_event_le_channel_opened_get_local_cid(packet);
handle = l2cap_event_le_channel_opened_get_handle(packet);
if (packet[2] == 0) {
printf("L2CAP: LE Data Channel successfully opened: %s, handle 0x%02x, psm 0x%02x, local cid 0x%02x, remote cid 0x%02x\n",
bd_addr_to_str(event_address), handle, psm, cid, little_endian_read_16(packet, 15));
switch (psm){
case TSPX_le_psm:
@ -178,13 +209,30 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
break;
}
} else {
printf("L2CAP: connection to device %s failed. status code %u\n", bd_addr_to_str(event_address), packet[2]);
printf("L2CAP: LE Data Channel connection to device %s failed. status code %u\n", bd_addr_to_str(event_address), packet[2]);
}
break;
case L2CAP_EVENT_CHANNEL_CLOSED:
cid = l2cap_event_channel_closed_get_local_cid(packet);
printf("L2CAP: Channel closed 0x%02x\n", cid);
case L2CAP_EVENT_LE_CAN_SEND_NOW:
if (todo_send_short){
todo_send_short = 0;
l2cap_le_send_data(cid_le, (uint8_t *) data_short, strlen(data_short));
break;
}
if (todo_send_long){
todo_send_long = 0;
l2cap_le_send_data(cid_le, (uint8_t *) data_long, strlen(data_long));
}
break;
case L2CAP_EVENT_LE_CHANNEL_CLOSED:
cid = l2cap_event_le_channel_closed_get_local_cid(packet);
printf("L2CAP: LE Data Channel closed 0x%02x\n", cid);
break;
case L2CAP_EVENT_LE_PACKET_SENT:
cid = l2cap_event_le_packet_sent_get_local_cid(packet);
printf("L2CAP: LE Data Channel Packet sent0x%02x\n", cid);
break;
case SM_EVENT_JUST_WORKS_REQUEST:
@ -267,6 +315,7 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
switch (buffer){
case 'a':
printf("Direct Connection Establishment to type %u, addr %s\n", pts_address_type, bd_addr_to_str(pts_address));
gap_advertisements_enable(0); // controller with single role cannot create connection while advertising
gap_connect(pts_address, pts_address_type);
break;
@ -294,12 +343,14 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
case 's':
printf("Send L2CAP Data Short %s\n", data_short);
l2cap_le_send_data(cid_le, (uint8_t *) data_short, strlen(data_short));
todo_send_short = 1;
l2cap_le_request_can_send_now_event(cid_le);
break;
case 'S':
printf("Send L2CAP Data Long %s\n", data_long);
l2cap_le_send_data(cid_le, (uint8_t *) data_long, strlen(data_long));
todo_send_long = 1;
l2cap_le_request_can_send_now_event(cid_le);
break;
case 'y':