mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-04 15:39:59 +00:00
l2cap: send/receive le data channel SDUs that fit into single packet
This commit is contained in:
parent
991fea48d1
commit
64e11ca9ae
46
src/l2cap.c
46
src/l2cap.c
@ -756,6 +756,8 @@ static void l2cap_run(void){
|
|||||||
// TODO: support larger MPS
|
// TODO: support larger MPS
|
||||||
channel->state = L2CAP_STATE_OPEN;
|
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);
|
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;
|
break;
|
||||||
case L2CAP_STATE_WILL_SEND_LE_CONNECTION_RESPONSE_DECLINE:
|
case L2CAP_STATE_WILL_SEND_LE_CONNECTION_RESPONSE_DECLINE:
|
||||||
if (!hci_can_send_acl_packet_now(channel->con_handle)) break;
|
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: {
|
default: {
|
||||||
// Find channel for this channel_id and connection handle
|
// 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) {
|
if (l2cap_channel) {
|
||||||
l2cap_dispatch_to_channel(l2cap_channel, L2CAP_DATA_PACKET, &packet[COMPLETE_L2CAP_HEADER], size-COMPLETE_L2CAP_HEADER);
|
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;
|
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 local_cid L2CAP LE Data Channel Identifier
|
||||||
* @param credits Number additional credits for peer
|
* @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
|
// get channel
|
||||||
// bail if missing
|
// bail if missing
|
||||||
// check state
|
// 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
|
* @brief Check if outgoing buffer is available and that there's space on the Bluetooth module
|
||||||
* @param local_cid L2CAP LE Data Channel Identifier
|
* @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
|
// check if data can be sent via le at all
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1989,7 +1998,7 @@ int l2cap_le_can_send_now(uint16_t cid){
|
|||||||
* so packet handler should be ready to handle it
|
* so packet handler should be ready to handle it
|
||||||
* @param local_cid L2CAP LE Data Channel Identifier
|
* @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
|
// same as for non-le
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2001,11 +2010,30 @@ uint8_t l2cap_le_request_can_send_now_event(uint16_t cid){
|
|||||||
* @param data data to send
|
* @param data data to send
|
||||||
* @param size data size
|
* @param size data size
|
||||||
*/
|
*/
|
||||||
uint8_t l2cap_le_send_data(uint16_t cid, uint8_t * data, uint16_t size){
|
uint8_t l2cap_le_send_data(uint16_t local_cid, uint8_t * data, uint16_t len){
|
||||||
// check if no outgoing data is pending
|
|
||||||
// store info
|
l2cap_channel_t * channel = l2cap_le_get_channel_for_local_cid(local_cid);
|
||||||
// l2cap_le_run()
|
if (!channel) {
|
||||||
return 0;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,6 +73,7 @@ static int master_addr_type = 0;
|
|||||||
static hci_con_handle_t handle;
|
static hci_con_handle_t handle;
|
||||||
static uint32_t ui_passkey;
|
static uint32_t ui_passkey;
|
||||||
static int ui_digits_for_passkey;
|
static int ui_digits_for_passkey;
|
||||||
|
static uint16_t local_cid;
|
||||||
|
|
||||||
// general discoverable flags
|
// general discoverable flags
|
||||||
static uint8_t adv_general_discoverable[] = { 2, 01, 02 };
|
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){
|
static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||||
bd_addr_t event_address;
|
bd_addr_t event_address;
|
||||||
uint16_t psm;
|
uint16_t psm;
|
||||||
uint16_t local_cid;
|
uint16_t cid;
|
||||||
|
|
||||||
switch (packet_type) {
|
switch (packet_type) {
|
||||||
|
|
||||||
|
case L2CAP_DATA_PACKET:
|
||||||
|
printf("L2CAP data cid 0x%02x: ", channel);
|
||||||
|
printf_hexdump(packet, size);
|
||||||
|
break;
|
||||||
|
|
||||||
case HCI_EVENT_PACKET:
|
case HCI_EVENT_PACKET:
|
||||||
switch (packet[0]) {
|
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:
|
case HCI_EVENT_DISCONNECTION_COMPLETE:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case L2CAP_EVENT_INCOMING_CONNECTION: {
|
case L2CAP_EVENT_INCOMING_CONNECTION:
|
||||||
local_cid = little_endian_read_16(packet, 12);
|
cid = little_endian_read_16(packet, 12);
|
||||||
#if 1
|
printf("L2CAP: Accepting incoming connection request for 0x%02x\n", cid);
|
||||||
printf("L2CAP: Accepting incoming connection request for 0x%02x\n", local_cid);
|
l2cap_le_accept_connection(cid, receive_buffer_X, sizeof(receive_buffer_X), 1);
|
||||||
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
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case L2CAP_EVENT_CHANNEL_OPENED:
|
case L2CAP_EVENT_CHANNEL_OPENED:
|
||||||
// inform about new l2cap connection
|
// inform about new l2cap connection
|
||||||
@ -142,8 +142,8 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case L2CAP_EVENT_CHANNEL_CLOSED:
|
case L2CAP_EVENT_CHANNEL_CLOSED:
|
||||||
local_cid = l2cap_event_channel_closed_get_local_cid(packet);
|
cid = l2cap_event_channel_closed_get_local_cid(packet);
|
||||||
printf("L2CAP: Channel closed 0x%02x\n", local_cid);
|
printf("L2CAP: Channel closed 0x%02x\n", cid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SM_EVENT_JUST_WORKS_REQUEST:
|
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("\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("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("---\n");
|
||||||
printf("Ctrl-c - exit\n");
|
printf("Ctrl-c - exit\n");
|
||||||
printf("---\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);
|
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;
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
printf("Send L2CAP Data\n");
|
||||||
|
l2cap_le_send_data(local_cid, (uint8_t *) "0123456789", 10);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
show_usage();
|
show_usage();
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user