l2cap: send/receive le data channel SDUs that fit into single packet

This commit is contained in:
Matthias Ringwald 2016-10-05 11:01:26 +02:00
parent 991fea48d1
commit 64e11ca9ae
2 changed files with 57 additions and 23 deletions

View File

@ -756,6 +756,8 @@ static void l2cap_run(void){
// TODO: support larger MPS
channel->state = L2CAP_STATE_OPEN;
l2cap_send_le_signaling_packet(channel->con_handle, LE_CREDIT_BASED_CONNECTION_RESPONSE, channel->remote_sig_id, channel->remote_cid, channel->local_mtu, 23, channel->credits_incoming, 0);
// notify client
l2cap_emit_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;
@ -1729,10 +1731,17 @@ static void l2cap_acl_handler(uint8_t packet_type, uint16_t channel, uint8_t *pa
default: {
// Find channel for this channel_id and connection handle
l2cap_channel_t * l2cap_channel = l2cap_get_channel_for_local_cid(channel_id);
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);
}
#ifdef ENABLE_BLE
l2cap_channel = l2cap_le_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
break;
}
}
@ -1964,7 +1973,7 @@ l2cap_channel_t * channel = l2cap_create_channel_entry(packet_handler, address,
* @param local_cid L2CAP LE Data Channel Identifier
* @param credits Number additional credits for peer
*/
uint8_t l2cap_le_provide_credits(uint16_t cid, uint16_t credits){
uint8_t l2cap_le_provide_credits(uint16_t local_cid, uint16_t credits){
// get channel
// bail if missing
// check state
@ -1978,7 +1987,7 @@ 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
* @param local_cid L2CAP LE Data Channel Identifier
*/
int l2cap_le_can_send_now(uint16_t cid){
int l2cap_le_can_send_now(uint16_t local_cid){
// check if data can be sent via le at all
return 0;
}
@ -1989,7 +1998,7 @@ int l2cap_le_can_send_now(uint16_t cid){
* so packet handler should be ready to handle it
* @param local_cid L2CAP LE Data Channel Identifier
*/
uint8_t l2cap_le_request_can_send_now_event(uint16_t cid){
uint8_t l2cap_le_request_can_send_now_event(uint16_t local_cid){
// same as for non-le
return 0;
}
@ -2001,11 +2010,30 @@ uint8_t l2cap_le_request_can_send_now_event(uint16_t cid){
* @param data data to send
* @param size data size
*/
uint8_t l2cap_le_send_data(uint16_t cid, uint8_t * data, uint16_t size){
// check if no outgoing data is pending
// store info
// l2cap_le_run()
return 0;
uint8_t l2cap_le_send_data(uint16_t local_cid, uint8_t * data, uint16_t len){
l2cap_channel_t * channel = l2cap_le_get_channel_for_local_cid(local_cid);
if (!channel) {
log_error("l2cap_send no channel for cid 0x%02x", local_cid);
return -1; // TODO: define error
}
if (len > channel->remote_mtu){
log_error("l2cap_send cid 0x%02x, data length exceeds remote MTU.", local_cid);
return L2CAP_DATA_LEN_EXCEEDS_REMOTE_MTU;
}
if (!hci_can_send_acl_packet_now(channel->con_handle)){
log_info("l2cap_send cid 0x%02x, cannot send", local_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(channel->con_handle, local_cid, len);
}
/**

View File

@ -73,6 +73,7 @@ static int master_addr_type = 0;
static hci_con_handle_t handle;
static uint32_t ui_passkey;
static int ui_digits_for_passkey;
static uint16_t local_cid;
// general discoverable flags
static uint8_t adv_general_discoverable[] = { 2, 01, 02 };
@ -87,10 +88,15 @@ static void gap_run(void){
static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
bd_addr_t event_address;
uint16_t psm;
uint16_t local_cid;
uint16_t cid;
switch (packet_type) {
case L2CAP_DATA_PACKET:
printf("L2CAP data cid 0x%02x: ", channel);
printf_hexdump(packet, size);
break;
case HCI_EVENT_PACKET:
switch (packet[0]) {
@ -116,17 +122,11 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
case HCI_EVENT_DISCONNECTION_COMPLETE:
break;
case L2CAP_EVENT_INCOMING_CONNECTION: {
local_cid = little_endian_read_16(packet, 12);
#if 1
printf("L2CAP: Accepting incoming connection request for 0x%02x\n", local_cid);
l2cap_le_accept_connection(local_cid, receive_buffer_X, sizeof(receive_buffer_X), 1);
#else
printf("L2CAP Decline incoming connection request\n");
l2cap_le_decline_connection(local_cid);
#endif
case L2CAP_EVENT_INCOMING_CONNECTION:
cid = little_endian_read_16(packet, 12);
printf("L2CAP: Accepting incoming connection request for 0x%02x\n", cid);
l2cap_le_accept_connection(cid, receive_buffer_X, sizeof(receive_buffer_X), 1);
break;
}
case L2CAP_EVENT_CHANNEL_OPENED:
// inform about new l2cap connection
@ -142,8 +142,8 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
}
break;
case L2CAP_EVENT_CHANNEL_CLOSED:
local_cid = l2cap_event_channel_closed_get_local_cid(packet);
printf("L2CAP: Channel closed 0x%02x\n", local_cid);
cid = l2cap_event_channel_closed_get_local_cid(packet);
printf("L2CAP: Channel closed 0x%02x\n", cid);
break;
case SM_EVENT_JUST_WORKS_REQUEST:
@ -191,6 +191,7 @@ void show_usage(void){
printf("\n--- CLI for LE Data Channel %s ---\n", bd_addr_to_str(iut_address));
printf("a - connect to type %u address %s PSM 0x%02x\n", pts_address_type, bd_addr_to_str(pts_address), psm_x);
printf("s - send data\n");
printf("---\n");
printf("Ctrl-c - exit\n");
printf("---\n");
@ -223,6 +224,11 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
l2cap_le_create_channel(&app_packet_handler,pts_address, pts_address_type, psm_x, buffer_x, sizeof(buffer_x), 1, LEVEL_0, &cid_x);
break;
case 's':
printf("Send L2CAP Data\n");
l2cap_le_send_data(local_cid, (uint8_t *) "0123456789", 10);
break;
default:
show_usage();
break;