require hci connection for l2cap le data channels

This commit is contained in:
Matthias Ringwald 2016-10-12 12:27:20 +02:00
parent e5b5b3745f
commit 7dafa7502d
3 changed files with 46 additions and 103 deletions

View File

@ -268,18 +268,6 @@ static l2cap_channel_t * l2cap_le_get_channel_for_local_cid(uint16_t local_cid){
}
#endif
static l2cap_channel_t * l2cap_get_le_channel_for_address_and_addr_type(bd_addr_t address, bd_addr_type_t address_type){
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, &l2cap_le_channels);
while (btstack_linked_list_iterator_has_next(&it)){
l2cap_channel_t * channel = (l2cap_channel_t *) btstack_linked_list_iterator_next(&it);
if (channel->address_type != address_type) continue;
if (bd_addr_cmp(channel->address, address)) continue;
return channel;
}
return NULL;
}
///
void l2cap_request_can_send_now_event(uint16_t local_cid){
@ -883,20 +871,6 @@ static void l2cap_handle_connection_complete(hci_con_handle_t con_handle, l2cap_
}
}
#ifdef ENABLE_BLE
static void l2cap_handle_le_connection_complete(l2cap_channel_t * channel, uint8_t status, hci_con_handle_t con_handle){
if (channel->state == L2CAP_STATE_WAIT_CONNECTION_COMPLETE || channel->state == L2CAP_STATE_WILL_SEND_CREATE_CONNECTION) {
log_info("l2cap_le_handle_connection_complete expected state");
// TODO: bail if status != 0
// success, start l2cap handshake
channel->con_handle = con_handle;
channel->state = L2CAP_STATE_WILL_SEND_LE_CONNECTION_REQUEST;
}
}
#endif
static void l2cap_handle_remote_supported_features_received(l2cap_channel_t * channel){
if (channel->state != L2CAP_STATE_WAIT_REMOTE_SUPPORTED_FEATURES) return;
@ -1161,28 +1135,6 @@ static void l2cap_hci_event_handler(uint8_t packet_type, uint16_t cid, uint8_t *
}
break;
#ifdef ENABLE_BLE
case HCI_EVENT_LE_META:
switch (packet[2]){
int addr_type;
l2cap_channel_t * channel;
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
// Connection management
reverse_bd_addr(&packet[8], address);
addr_type = (bd_addr_type_t)packet[7];
log_info("L2CAP - LE Connection_complete (status=%u) type %u, %s", packet[3], addr_type, bd_addr_to_str(address));
// get l2cap_channel
// also pass in status
channel = l2cap_get_le_channel_for_address_and_addr_type(address, addr_type);
if (!channel) break;
l2cap_handle_le_connection_complete(channel, packet[3], little_endian_read_16(packet, 4));
break;
default:
break;
}
break;
#endif
case GAP_EVENT_SECURITY_LEVEL:
handle = little_endian_read_16(packet, 2);
log_info("l2cap - security level update");
@ -2081,13 +2033,20 @@ uint8_t l2cap_le_decline_connection(uint16_t local_cid){
return 0;
}
uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, bd_addr_t address, bd_addr_type_t address_type,
uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, hci_con_handle_t con_handle,
uint16_t psm, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits, gap_security_level_t security_level,
uint16_t * out_local_cid) {
log_info("L2CAP_LE_CREATE_CHANNEL addr %s psm 0x%x mtu %u", bd_addr_to_str(address), psm, mtu);
l2cap_channel_t * channel = l2cap_create_channel_entry(packet_handler, address, address_type, psm, mtu, security_level);
log_info("L2CAP_LE_CREATE_CHANNEL handle 0x%04x psm 0x%x mtu %u", con_handle, psm, mtu);
hci_connection_t * connection = hci_connection_for_handle(con_handle);
if (!connection) {
log_error("no hci_connection for handle 0x%04x", con_handle);
return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
}
l2cap_channel_t * channel = l2cap_create_channel_entry(packet_handler, connection->address, connection->address_type, psm, mtu, security_level);
if (!channel) {
return BTSTACK_MEMORY_ALLOC_FAILED;
}
@ -2098,41 +2057,18 @@ uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, bd_addr
*out_local_cid = channel->local_cid;
}
// provdide buffer
// provide buffer
channel->con_handle = con_handle;
channel->receive_sdu_buffer = receive_sdu_buffer;
channel->state = L2CAP_STATE_WAIT_CONNECTION_COMPLETE;
channel->state = L2CAP_STATE_WILL_SEND_LE_CONNECTION_REQUEST;
channel->new_credits_incoming = initial_credits;
channel->automatic_credits = initial_credits == L2CAP_LE_AUTOMATIC_CREDITS;
// test
// channel->new_credits_incoming = 1;
// add to connections list
btstack_linked_list_add(&l2cap_le_channels, (btstack_linked_item_t *) channel);
// check if hci connection is already usable
hci_connection_t * conn = hci_connection_for_bd_addr_and_type(address, address_type);
if (conn){
log_info("l2cap_le_create_channel, hci connection already exists");
l2cap_handle_le_connection_complete(channel, 0, conn->con_handle);
l2cap_run();
} else {
//
// TODO: start timer
// ..
// start connection
uint8_t res = gap_auto_connection_start(address_type, address);
if (res){
// discard channel object
log_info("gap_auto_connection_start failed! 0x%02x", res);
btstack_linked_list_remove(&l2cap_le_channels, (btstack_linked_item_t *) channel);
btstack_memory_l2cap_channel_free(channel);
return res;
}
}
// go
l2cap_run();
return 0;
}

View File

@ -354,8 +354,7 @@ uint8_t l2cap_le_decline_connection(uint16_t local_cid);
/**
* @brief Create LE Data Channel
* @param packet_handler Packet handler for this connection
* @param address Peer address
* @param address_type Peer address type
* @param con_handle ACL-LE HCI Connction Handle
* @param psm Service PSM to connect to
* @param receive_buffer buffer used for reassembly of L2CAP LE Information Frames into service data unit (SDU) with given MTU
* @param receive_buffer_size buffer size equals MTU
@ -363,7 +362,7 @@ uint8_t l2cap_le_decline_connection(uint16_t local_cid);
* @param security_level Minimum required security level
* @param out_local_cid L2CAP LE Channel Identifier is stored here
*/
uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, bd_addr_t address, bd_addr_type_t address_type,
uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, hci_con_handle_t con_handle,
uint16_t psm, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits, gap_security_level_t security_level,
uint16_t * out_local_cid);

View File

@ -66,10 +66,13 @@
static btstack_packet_callback_registration_t hci_event_callback_registration;
static btstack_packet_callback_registration_t sm_event_callback_registration;
static bd_addr_t pts_address = { 0x00, 0x1a, 0x7d, 0xda, 0x71, 0x0a};
// static bd_addr_t pts_address = { 0x00, 0x1a, 0x7d, 0xda, 0x71, 0x0a};
static bd_addr_t pts_address = { 0x00, 0x1b, 0xdc, 0x08, 0x0a, 0xa5};
static int pts_address_type = 0;
static int master_addr_type = 0;
static hci_con_handle_t handle;
static hci_con_handle_t handle_le;
static hci_con_handle_t handle_classic;
static uint32_t ui_passkey;
static int ui_digits_for_passkey;
static uint16_t local_cid;
@ -100,6 +103,7 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
bd_addr_t event_address;
uint16_t psm;
uint16_t cid;
hci_con_handle_t handle;
switch (packet_type) {
@ -121,8 +125,8 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
case HCI_EVENT_LE_META:
switch (hci_event_le_meta_get_subevent_code(packet)) {
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
handle = little_endian_read_16(packet, 4);
printf("HCI: LE Connection Complete, connection handle 0x%04x\n", handle);
handle_le = little_endian_read_16(packet, 4);
printf("HCI: LE Connection Complete, connection handle 0x%04x\n", handle_le);
break;
default:
@ -131,8 +135,8 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
break;
case HCI_EVENT_CONNECTION_COMPLETE:
handle = little_endian_read_16(packet, 3);
printf("HCI: ACL Connection Complete, connection handle 0x%04x\n", handle);
handle_classic = little_endian_read_16(packet, 3);
printf("HCI: ACL Connection Complete, connection handle 0x%04x\n", handle_classic);
break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
@ -228,13 +232,14 @@ void show_usage(void){
gap_advertisements_get_address(&uit_addr_type, 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 (TSPX_le_psm - LE)\n", pts_address_type, bd_addr_to_str(pts_address), TSPX_le_psm);
printf("A - connect to type %u address %s PSM 0x%02x (TSPX_psm_unsupported - LE)\n", pts_address_type, bd_addr_to_str(pts_address), TSPX_psm_unsupported);
printf("b - connect to type %u address %s PSM 0x%02x (TSPX_psm - Classic)\n", pts_address_type, bd_addr_to_str(pts_address), TSPX_psm);
printf("a - create HCI connection to type %u address %s\n", pts_address_type, bd_addr_to_str(pts_address));
printf("b - connect to PSM 0x%02x (TSPX_le_psm - LE)\n", TSPX_le_psm);
printf("B - connect to PSM 0x%02x (TSPX_psm_unsupported - LE)\n", TSPX_psm_unsupported);
printf("c - send 10 credits\n");
printf("m - enable manual credit managment (incoming connections only)\n");
printf("s - send short data %s\n", data_short);
printf("S - send long data %s\n", data_long);
printf("y - connect to address %s PSM 0x%02x (TSPX_psm - Classic)\n", bd_addr_to_str(pts_address), TSPX_psm);
printf("z - send classic data Classic %s\n", data_classic);
printf("t - disconnect channel\n");
printf("---\n");
@ -255,31 +260,29 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
ui_digits_for_passkey--;
if (ui_digits_for_passkey == 0){
printf("\nSending Passkey '%06x'\n", ui_passkey);
sm_passkey_input(handle, ui_passkey);
sm_passkey_input(handle_le, ui_passkey);
}
return;
}
switch (buffer){
case 'a':
printf("Creating connection to %s 0x%02x - LE\n", bd_addr_to_str(pts_address), TSPX_le_psm);
gap_advertisements_enable(0);
l2cap_le_create_channel(&app_packet_handler,pts_address, pts_address_type, TSPX_le_psm, buffer_x,
printf("Direct Connection Establishment to type %u, addr %s\n", pts_address_type, bd_addr_to_str(pts_address));
gap_connect(pts_address, pts_address_type);
break;
case 'b':
printf("Connect to PSM 0x%02x - LE\n", TSPX_le_psm);
l2cap_le_create_channel(&app_packet_handler, handle_le, TSPX_le_psm, buffer_x,
sizeof(buffer_x), L2CAP_LE_AUTOMATIC_CREDITS, LEVEL_0, &cid_le);
break;
case 'A':
printf("Creating connection to %s 0x%02x - LE\n", bd_addr_to_str(pts_address), TSPX_psm_unsupported);
gap_advertisements_enable(0);
l2cap_le_create_channel(&app_packet_handler,pts_address, pts_address_type, TSPX_psm_unsupported, buffer_x,
l2cap_le_create_channel(&app_packet_handler, handle_le, TSPX_psm_unsupported, buffer_x,
sizeof(buffer_x), L2CAP_LE_AUTOMATIC_CREDITS, LEVEL_0, &cid_le);
break;
case 'b':
printf("Creating connection to %s 0x%02x - Classic\n", bd_addr_to_str(pts_address), TSPX_psm);
l2cap_create_channel(&app_packet_handler, pts_address, TSPX_psm, 100, &cid_classic);
break;
case 'c':
printf("Provide 10 credits\n");
l2cap_le_provide_credits(cid_le, 10);
@ -300,6 +303,11 @@ static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callbac
l2cap_le_send_data(cid_le, (uint8_t *) data_long, strlen(data_long));
break;
case 'y':
printf("Creating connection to %s 0x%02x - Classic\n", bd_addr_to_str(pts_address), TSPX_psm);
l2cap_create_channel(&app_packet_handler, pts_address, TSPX_psm, 100, &cid_classic);
break;
case 'z':
printf("Send L2CAP Data Classic %s\n", data_classic);
l2cap_send(cid_classic, (uint8_t *) data_classic, strlen(data_classic));