l2cap: streamline ertm, cbm, ecbm function names

This commit is contained in:
Matthias Ringwald 2021-11-19 11:04:16 +01:00
parent 1c0aefe992
commit f25e60dece
13 changed files with 222 additions and 219 deletions

View File

@ -314,18 +314,18 @@ The full title for LE Data Channels is actually LE Connection-Oriented Channels
LE Data Channels are similar to Classic L2CAP Channels but also provide a credit-based flow control similar to RFCOMM Channels.
Unless the LE Data Packet Extension of Bluetooth Core 4.2 specification is used, the maximum packet size for LE ACL packets is 27 bytes. In order to send larger packets, each packet will be split into multiple ACL LE packets and recombined on the receiving side.
Since multiple SDUs can be transmitted at the same time and the individual ACL LE packets can be sent interleaved, BTstack requires a dedicated receive buffer per channel that has to be passed when creating the channel or accepting it. Similarly, when sending SDUs, the data provided to the *l2cap_le_send_data* must stay valid until the *L2CAP_EVENT_LE_PACKET_SENT* is received.
Since multiple SDUs can be transmitted at the same time and the individual ACL LE packets can be sent interleaved, BTstack requires a dedicated receive buffer per channel that has to be passed when creating the channel or accepting it. Similarly, when sending SDUs, the data provided to the *l2cap_cbm_send_data* must stay valid until the *L2CAP_EVENT_LE_PACKET_SENT* is received.
When creating an outgoing connection of accepting an incoming, the *initial_credits* allows to provide a fixed number of credits to the remote side. Further credits can be provided anytime with *l2cap_le_provide_credits*. If *L2CAP_LE_AUTOMATIC_CREDITS* is used, BTstack automatically provides credits as needed - effectively trading in the flow-control functionality for convenience.
When creating an outgoing connection of accepting an incoming, the *initial_credits* allows to provide a fixed number of credits to the remote side. Further credits can be provided anytime with *l2cap_cbm_provide_credits*. If *L2CAP_LE_AUTOMATIC_CREDITS* is used, BTstack automatically provides credits as needed - effectively trading in the flow-control functionality for convenience.
The remainder of the API is similar to the one of L2CAP:
* *l2cap_le_register_service* and *l2cap_le_unregister_service* are used to manage local services.
* *l2cap_le_accept_connection* and *l2cap_le_decline_connection* are used to accept or deny an incoming connection request.
* *l2cap_le_create_channel* creates an outgoing connections.
* *l2cap_le_can_send_now* checks if a packet can be scheduled for transmission now.
* *l2cap_le_request_can_send_now_event* requests an *L2CAP_EVENT_LE_CAN_SEND_NOW* event as soon as possible.
* *l2cap_le_disconnect* closes the connection.
* *l2cap_cbm_register_service* and *l2cap_cbm_unregister_service* are used to manage local services.
* *l2cap_cbm_accept_connection* and *l2cap_cbm_decline_connection* are used to accept or deny an incoming connection request.
* *l2cap_cbm_create_channel* creates an outgoing connections.
* *l2cap_cbm_can_send_now* checks if a packet can be scheduled for transmission now.
* *l2cap_cbm_request_can_send_now_event* requests an *L2CAP_EVENT_LE_CAN_SEND_NOW* event as soon as possible.
* *l2cap_cbm_disconnect* closes the connection.
## RFCOMM - Radio Frequency Communication Protocol

View File

@ -172,13 +172,13 @@ static void streamer(void){
memset(le_data_channel_connection.test_data, le_data_channel_connection.counter, le_data_channel_connection.test_data_len);
// send
l2cap_le_send_data(le_data_channel_connection.cid, (uint8_t *) le_data_channel_connection.test_data, le_data_channel_connection.test_data_len);
l2cap_cbm_send_data(le_data_channel_connection.cid, (uint8_t *) le_data_channel_connection.test_data, le_data_channel_connection.test_data_len);
// track
test_track_data(&le_data_channel_connection, le_data_channel_connection.test_data_len);
// request another packet
l2cap_le_request_can_send_now_event(le_data_channel_connection.cid);
l2cap_cbm_request_can_send_now_event(le_data_channel_connection.cid);
}
/* LISTING_END */
#endif
@ -245,7 +245,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
// query primary services
printf("Connect to performance test channel.\n");
state = TC_W4_CHANNEL;
l2cap_le_create_channel(&packet_handler, connection_handle, TSPX_le_psm, data_channel_buffer,
l2cap_cbm_create_channel(&packet_handler, connection_handle, TSPX_le_psm, data_channel_buffer,
sizeof(data_channel_buffer), L2CAP_LE_AUTOMATIC_CREDITS, LEVEL_0, &le_data_channel_connection.cid);
break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
@ -274,7 +274,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
printf("Test packet size: %u\n", le_data_channel_connection.test_data_len);
test_reset(&le_data_channel_connection);
#ifdef TEST_STREAM_DATA
l2cap_le_request_can_send_now_event(le_data_channel_connection.cid);
l2cap_cbm_request_can_send_now_event(le_data_channel_connection.cid);
#endif
} else {
printf("L2CAP: LE Data Channel connection to device %s failed. status code 0x%02x\n", bd_addr_to_str(event_address), status);

View File

@ -130,7 +130,7 @@ static void le_data_channel_setup(void){
l2cap_add_event_handler(&l2cap_event_callback_registration);
// le data channel setup
l2cap_le_register_service(&packet_handler, TSPX_le_psm, LEVEL_0);
l2cap_cbm_register_service(&packet_handler, TSPX_le_psm, LEVEL_0);
// setup advertisements
uint16_t adv_int_min = 0x0030;
@ -194,13 +194,13 @@ static void streamer(void){
memset(le_data_channel_connection.test_data, le_data_channel_connection.counter, le_data_channel_connection.test_data_len);
// send
l2cap_le_send_data(le_data_channel_connection.cid, (uint8_t *) le_data_channel_connection.test_data, le_data_channel_connection.test_data_len);
l2cap_cbm_send_data(le_data_channel_connection.cid, (uint8_t *) le_data_channel_connection.test_data, le_data_channel_connection.test_data_len);
// track
test_track_data(&le_data_channel_connection, le_data_channel_connection.test_data_len);
// request another packet
l2cap_le_request_can_send_now_event(le_data_channel_connection.cid);
l2cap_cbm_request_can_send_now_event(le_data_channel_connection.cid);
}
/* LISTING_END */
#endif
@ -276,7 +276,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
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, data_channel_buffer, sizeof(data_channel_buffer), initial_credits);
l2cap_cbm_accept_connection(cid, data_channel_buffer, sizeof(data_channel_buffer), initial_credits);
break;
case L2CAP_EVENT_LE_CHANNEL_OPENED:
@ -297,7 +297,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
printf("Test packet size: %u\n", le_data_channel_connection.test_data_len);
test_reset(&le_data_channel_connection);
#ifdef TEST_STREAM_DATA
l2cap_le_request_can_send_now_event(le_data_channel_connection.cid);
l2cap_cbm_request_can_send_now_event(le_data_channel_connection.cid);
#endif
} else {
printf("L2CAP: LE Data Channel connection to device %s failed. status code %u\n", bd_addr_to_str(event_address), status);

View File

@ -88,7 +88,7 @@ static void avrcp_retry_timer_timeout_handler(btstack_timer_source_t * timer){
connection_controller->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
connection_target->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
l2cap_create_ertm_channel(avrcp_browsing_packet_handler, connection_controller->remote_addr, connection_controller->browsing_l2cap_psm,
l2cap_ertm_create_channel(avrcp_browsing_packet_handler, connection_controller->remote_addr, connection_controller->browsing_l2cap_psm,
&connection_controller->browsing_connection->ertm_config,
connection_controller->browsing_connection->ertm_buffer,
connection_controller->browsing_connection->ertm_buffer_size, NULL);
@ -445,7 +445,7 @@ static void avrcp_browsing_handle_sdp_client_query_result(uint8_t packet_type, u
break;
}
l2cap_create_ertm_channel(avrcp_browsing_packet_handler, avrcp_browsing_sdp_addr, browsing_l2cap_psm,
l2cap_ertm_create_channel(avrcp_browsing_packet_handler, avrcp_browsing_sdp_addr, browsing_l2cap_psm,
&avrcp_controller_connection->browsing_connection->ertm_config,
avrcp_controller_connection->browsing_connection->ertm_buffer,
avrcp_controller_connection->browsing_connection->ertm_buffer_size, NULL);
@ -549,7 +549,7 @@ uint8_t avrcp_browsing_connect(bd_addr_t remote_addr, uint8_t * ertm_buffer, uin
connection_controller->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
connection_target->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
return l2cap_create_ertm_channel(avrcp_browsing_packet_handler, remote_addr, connection_controller->browsing_l2cap_psm,
return l2cap_ertm_create_channel(avrcp_browsing_packet_handler, remote_addr, connection_controller->browsing_l2cap_psm,
&connection_controller->browsing_connection->ertm_config,
connection_controller->browsing_connection->ertm_buffer,
connection_controller->browsing_connection->ertm_buffer_size, NULL);
@ -583,7 +583,7 @@ uint8_t avrcp_browsing_configure_incoming_connection(uint16_t avrcp_browsing_cid
connection_controller->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
connection_target->browsing_connection->state = AVCTP_CONNECTION_W4_L2CAP_CONNECTED;
l2cap_accept_ertm_connection(connection_controller->browsing_connection->l2cap_browsing_cid,
l2cap_ertm_accept_connection(connection_controller->browsing_connection->l2cap_browsing_cid,
&connection_controller->browsing_connection->ertm_config,
connection_controller->browsing_connection->ertm_buffer,
connection_controller->browsing_connection->ertm_buffer_size);

View File

@ -332,7 +332,7 @@ static void goep_client_handle_sdp_query_event(uint8_t packet_type, uint16_t cha
#ifdef ENABLE_GOEP_L2CAP
if (context->l2cap_psm){
log_info("Remote GOEP L2CAP PSM: %u", context->l2cap_psm);
l2cap_create_ertm_channel(&goep_client_packet_handler, context->bd_addr, context->l2cap_psm,
l2cap_ertm_create_channel(&goep_client_packet_handler, context->bd_addr, context->l2cap_psm,
&ertm_config, ertm_buffer, sizeof(ertm_buffer), &context->bearer_cid);
return;
}

View File

@ -1083,7 +1083,7 @@ static int rfcomm_hci_event_handler(uint8_t *packet, uint16_t size){
}
if (request.ertm_config && request.ertm_buffer && request.ertm_buffer_size){
multiplexer->ertm_id = request.ertm_id;
l2cap_accept_ertm_connection(l2cap_cid, request.ertm_config, request.ertm_buffer, request.ertm_buffer_size);
l2cap_ertm_accept_connection(l2cap_cid, request.ertm_config, request.ertm_buffer, request.ertm_buffer_size);
return 1;
}
#endif
@ -2515,7 +2515,7 @@ static uint8_t rfcomm_channel_create_internal(btstack_packet_handler_t packet_ha
}
if (request.ertm_config && request.ertm_buffer && request.ertm_buffer_size){
multiplexer->ertm_id = request.ertm_id;
status = l2cap_create_ertm_channel(rfcomm_packet_handler, addr, BLUETOOTH_PROTOCOL_RFCOMM,
status = l2cap_ertm_create_channel(rfcomm_packet_handler, addr, BLUETOOTH_PROTOCOL_RFCOMM,
request.ertm_config, request.ertm_buffer, request.ertm_buffer_size, &l2cap_cid);
}
else

View File

@ -630,10 +630,10 @@ static void l2cap_ertm_configure_channel(l2cap_channel_t * channel, l2cap_ertm_c
channel->fcs_option = ertm_config->fcs_option;
}
uint8_t l2cap_create_ertm_channel(btstack_packet_handler_t packet_handler, bd_addr_t address, uint16_t psm,
uint8_t l2cap_ertm_create_channel(btstack_packet_handler_t packet_handler, bd_addr_t address, uint16_t psm,
l2cap_ertm_config_t * ertm_config, uint8_t * buffer, uint32_t size, uint16_t * out_local_cid){
log_info("L2CAP_CREATE_ERTM_CHANNEL addr %s, psm 0x%x, local mtu %u", bd_addr_to_str(address), psm, ertm_config->local_mtu);
log_info("l2cap_ertm_create_channel addr %s, psm 0x%x, local mtu %u", bd_addr_to_str(address), psm, ertm_config->local_mtu);
// validate local config
uint8_t result = l2cap_ertm_validate_local_config(ertm_config);
@ -683,9 +683,9 @@ static void l2cap_ertm_notify_channel_can_send(l2cap_channel_t * channel){
}
}
uint8_t l2cap_accept_ertm_connection(uint16_t local_cid, l2cap_ertm_config_t * ertm_config, uint8_t * buffer, uint32_t size){
uint8_t l2cap_ertm_accept_connection(uint16_t local_cid, l2cap_ertm_config_t * ertm_config, uint8_t * buffer, uint32_t size){
log_info("L2CAP_ACCEPT_ERTM_CONNECTION local_cid 0x%x", local_cid);
log_info("l2cap_ertm_accept_connection local_cid 0x%x", local_cid);
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
if (!channel) {
log_error("l2cap_accept_connection called but local_cid 0x%x not found", local_cid);
@ -5007,9 +5007,9 @@ static inline l2cap_service_t * l2cap_le_get_service(uint16_t le_psm){
return l2cap_get_service_internal(&l2cap_le_services, le_psm);
}
uint8_t l2cap_le_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, gap_security_level_t security_level){
uint8_t l2cap_cbm_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, gap_security_level_t security_level){
log_info("L2CAP_LE_REGISTER_SERVICE psm 0x%x", psm);
log_info("l2cap_cbm_register_service psm 0x%x", psm);
// check for alread registered psm
l2cap_service_t *service = l2cap_le_get_service(psm);
@ -5037,8 +5037,8 @@ uint8_t l2cap_le_register_service(btstack_packet_handler_t packet_handler, uint1
return ERROR_CODE_SUCCESS;
}
uint8_t l2cap_le_unregister_service(uint16_t psm) {
log_info("L2CAP_LE_UNREGISTER_SERVICE psm 0x%x", psm);
uint8_t l2cap_cbm_unregister_service(uint16_t psm) {
log_info("l2cap_cbm_unregister_service psm 0x%x", psm);
l2cap_service_t *service = l2cap_le_get_service(psm);
if (!service) return L2CAP_SERVICE_DOES_NOT_EXIST;
@ -5047,7 +5047,7 @@ uint8_t l2cap_le_unregister_service(uint16_t psm) {
return ERROR_CODE_SUCCESS;
}
uint8_t l2cap_le_accept_connection(uint16_t local_cid, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits){
uint8_t l2cap_cbm_accept_connection(uint16_t local_cid, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits){
// get channel
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
if (!channel) return L2CAP_LOCAL_CID_DOES_NOT_EXIST;
@ -5074,7 +5074,7 @@ uint8_t l2cap_le_accept_connection(uint16_t local_cid, uint8_t * receive_sdu_buf
* @param local_cid L2CAP LE Data Channel Identifier
*/
uint8_t l2cap_le_decline_connection(uint16_t local_cid){
uint8_t l2cap_cbm_decline_connection(uint16_t local_cid){
// get channel
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
if (!channel) return L2CAP_LOCAL_CID_DOES_NOT_EXIST;
@ -5132,7 +5132,7 @@ static void l2cap_sm_packet_handler(uint8_t packet_type, uint16_t channel_nr, ui
}
}
uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, hci_con_handle_t con_handle,
uint8_t l2cap_cbm_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) {
@ -5193,7 +5193,7 @@ uint8_t l2cap_le_create_channel(btstack_packet_handler_t packet_handler, hci_con
* @param local_cid L2CAP LE Data Channel Identifier
* @param credits Number additional credits for peer
*/
uint8_t l2cap_le_provide_credits(uint16_t local_cid, uint16_t credits){
uint8_t l2cap_cbm_provide_credits(uint16_t local_cid, uint16_t credits){
return l2cap_credit_based_provide_credits(local_cid, credits);
}
@ -5201,7 +5201,7 @@ uint8_t l2cap_le_provide_credits(uint16_t local_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
*/
bool l2cap_le_can_send_now(uint16_t local_cid){
bool l2cap_cbm_can_send_now(uint16_t local_cid){
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
if (!channel) {
log_error("le can send now, no channel for cid 0x%02x", local_cid);
@ -5224,7 +5224,7 @@ bool l2cap_le_can_send_now(uint16_t local_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 local_cid){
uint8_t l2cap_cbm_request_can_send_now_event(uint16_t local_cid){
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
if (!channel) {
log_error("can send now, no channel for cid 0x%02x", local_cid);
@ -5242,7 +5242,7 @@ uint8_t l2cap_le_request_can_send_now_event(uint16_t local_cid){
* @param data data to send
* @param size data size
*/
uint8_t l2cap_le_send_data(uint16_t local_cid, uint8_t * data, uint16_t size){
uint8_t l2cap_cbm_send_data(uint16_t local_cid, uint8_t * data, uint16_t size){
return l2cap_credit_based_send_data(local_cid, data, size);
}
@ -5251,14 +5251,14 @@ uint8_t l2cap_le_send_data(uint16_t local_cid, uint8_t * data, uint16_t size){
* @brief Disconnect from LE Data Channel
* @param local_cid L2CAP LE Data Channel Identifier
*/
uint8_t l2cap_le_disconnect(uint16_t local_cid){
uint8_t l2cap_cbm_disconnect(uint16_t local_cid){
return l2cap_credit_based_disconnect(local_cid);
}
#endif
#ifdef ENABLE_L2CAP_ENHANCED_CREDIT_BASED_FLOW_CONTROL_MODE
uint8_t l2cap_enhanced_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, uint16_t min_remote_mtu, gap_security_level_t security_level){
uint8_t l2cap_ecbm_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, uint16_t min_remote_mtu, gap_security_level_t security_level){
// check for already registered psm
l2cap_service_t *service = l2cap_le_get_service(psm);
@ -5286,7 +5286,7 @@ uint8_t l2cap_enhanced_register_service(btstack_packet_handler_t packet_handler,
return ERROR_CODE_SUCCESS;
}
uint8_t l2cap_enhanced_unregister_service(uint16_t psm) {
uint8_t l2cap_ecbm_unregister_service(uint16_t psm) {
l2cap_service_t *service = l2cap_le_get_service(psm);
if (!service) return L2CAP_SERVICE_DOES_NOT_EXIST;
@ -5295,11 +5295,11 @@ uint8_t l2cap_enhanced_unregister_service(uint16_t psm) {
return ERROR_CODE_SUCCESS;
}
void l2cap_enhanced_mps_set_min(uint16_t mps_min){
void l2cap_ecbm_mps_set_min(uint16_t mps_min){
l2cap_enhanced_mps_min = mps_min;
}
void l2cap_enhanced_mps_set_max(uint16_t mps_max){
void l2cap_ecbm_mps_set_max(uint16_t mps_max){
l2cap_enhanced_mps_max = mps_max;
}
@ -5367,7 +5367,7 @@ uint8_t l2cap_enhanced_create_channels(btstack_packet_handler_t packet_handler,
return status;
}
uint8_t l2cap_enhanced_accept_data_channels(uint16_t local_cid, uint8_t num_channels, uint16_t initial_credits,
uint8_t l2cap_ecbm_accept_data_channels(uint16_t local_cid, uint8_t num_channels, uint16_t initial_credits,
uint16_t receive_buffer_size, uint8_t ** receive_buffers, uint16_t * out_local_cids){
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
@ -5414,7 +5414,7 @@ uint8_t l2cap_enhanced_accept_data_channels(uint16_t local_cid, uint8_t num_chan
uint8_t l2cap_enhanced_decline_data_channels(uint16_t local_cid, uint16_t result){
uint8_t l2cap_ecbm_decline_data_channels(uint16_t local_cid, uint16_t result){
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
if (!channel) {
return L2CAP_LOCAL_CID_DOES_NOT_EXIST;
@ -5440,7 +5440,7 @@ uint8_t l2cap_enhanced_decline_data_channels(uint16_t local_cid, uint16_t result
return ERROR_CODE_SUCCESS;
}
uint8_t l2cap_enhanced_data_channel_request_can_send_now_event(uint16_t local_cid){
uint8_t l2cap_ecbm_data_channel_request_can_send_now_event(uint16_t local_cid){
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
if (!channel) {
log_error("can send now, no channel for cid 0x%02x", local_cid);
@ -5451,7 +5451,7 @@ uint8_t l2cap_enhanced_data_channel_request_can_send_now_event(uint16_t local_ci
return ERROR_CODE_SUCCESS;
}
uint8_t l2cap_enhanced_reconfigure(uint8_t num_cids, uint16_t * local_cids, int16_t receive_buffer_size, uint8_t ** receive_buffers){
uint8_t l2cap_ecbm_reconfigure(uint8_t num_cids, uint16_t * local_cids, int16_t receive_buffer_size, uint8_t ** receive_buffers){
btstack_assert(receive_buffers != NULL);
btstack_assert(local_cids != NULL);
@ -5493,15 +5493,15 @@ uint8_t l2cap_enhanced_reconfigure(uint8_t num_cids, uint16_t * local_cids, int1
return ERROR_CODE_SUCCESS;
}
uint8_t l2cap_enhanced_send_data(uint16_t local_cid, const uint8_t * data, uint16_t size){
uint8_t l2cap_ecbm_send_data(uint16_t local_cid, const uint8_t * data, uint16_t size){
return l2cap_credit_based_send_data(local_cid, data, size);
}
uint8_t l2cap_enhanced_provide_credits(uint16_t local_cid, uint16_t credits){
uint8_t l2cap_ecbm_provide_credits(uint16_t local_cid, uint16_t credits){
return l2cap_credit_based_provide_credits(local_cid, credits);
}
uint8_t l2cap_enhanced_disconnect(uint16_t local_cid){
uint8_t l2cap_ecbm_disconnect(uint16_t local_cid){
return l2cap_credit_based_disconnect(local_cid);
}

View File

@ -499,21 +499,6 @@ void l2cap_set_max_le_mtu(uint16_t max_mtu);
*/
uint8_t l2cap_create_channel(btstack_packet_handler_t packet_handler, bd_addr_t address, uint16_t psm, uint16_t mtu, uint16_t * out_local_cid);
/**
* @brief Creates L2CAP channel to the PSM of a remote device with baseband address using Enhanced Retransmission Mode.
* A new baseband connection will be initiated if necessary.
* @param packet_handler
* @param address
* @param psm
* @param ertm_config
* @param buffer to store reassembled rx packet, out-of-order packets and unacknowledged outgoing packets with their tretransmission timers
* @param size of buffer
* @param local_cid
* @return status
*/
uint8_t l2cap_create_ertm_channel(btstack_packet_handler_t packet_handler, bd_addr_t address, uint16_t psm,
l2cap_ertm_config_t * ertm_contig, uint8_t * buffer, uint32_t size, uint16_t * out_local_cid);
/**
* @brief Disconnects L2CAP channel with given identifier.
*/
@ -549,16 +534,6 @@ uint8_t l2cap_unregister_service(uint16_t psm);
*/
void l2cap_accept_connection(uint16_t local_cid);
/**
* @brief Accepts incoming L2CAP connection for Enhanced Retransmission Mode
* @param local_cid
* @param ertm_config
* @param buffer to store reassembled rx packet, out-of-order packets and unacknowledged outgoing packets with their tretransmission timers
* @param size of buffer
* @return status
*/
uint8_t l2cap_accept_ertm_connection(uint16_t local_cid, l2cap_ertm_config_t * ertm_contig, uint8_t * buffer, uint32_t size);
/**
* @brief Deny incoming L2CAP connection.
*/
@ -603,49 +578,93 @@ uint8_t l2cap_send_prepared(uint16_t local_cid, uint16_t len);
*/
void l2cap_release_packet_buffer(void);
//
// LE Connection Oriented Channels feature with the LE Credit Based Flow Control Mode == LE Data Channel
// Connection-Oriented Channels in Enhanced Retransmission Mode - ERTM
//
/**
* @brief Register L2CAP LE Data Channel service
* @note MTU and initial credits are specified in l2cap_le_accept_connection(..) call
* @brief Creates L2CAP channel to the PSM of a remote device with baseband address using Enhanced Retransmission Mode.
* A new baseband connection will be initiated if necessary.
* @param packet_handler
* @param address
* @param psm
* @param ertm_config
* @param buffer to store reassembled rx packet, out-of-order packets and unacknowledged outgoing packets with their tretransmission timers
* @param size of buffer
* @param local_cid
* @return status
*/
uint8_t l2cap_ertm_create_channel(btstack_packet_handler_t packet_handler, bd_addr_t address, uint16_t psm,
l2cap_ertm_config_t * ertm_contig, uint8_t * buffer, uint32_t size, uint16_t * out_local_cid);
/**
* @brief Accepts incoming L2CAP connection for Enhanced Retransmission Mode
* @param local_cid
* @param ertm_config
* @param buffer to store reassembled rx packet, out-of-order packets and unacknowledged outgoing packets with their tretransmission timers
* @param size of buffer
* @return status
*/
uint8_t l2cap_ertm_accept_connection(uint16_t local_cid, l2cap_ertm_config_t * ertm_contig, uint8_t * buffer, uint32_t size);
/**
* @brief ERTM Set channel as busy.
* @note Can be cleared by l2cap_ertm_set_ready
* @param local_cid
* @return status
*/
uint8_t l2cap_ertm_set_busy(uint16_t local_cid);
/**
* @brief ERTM Set channel as ready
* @note Used after l2cap_ertm_set_busy
* @param local_cid
* @return status
*/
uint8_t l2cap_ertm_set_ready(uint16_t local_cid);
//
// L2CAP Connection-Oriented Channels in LE Credit-Based Flow-Control Mode - CBM
//
/**
* @brief Register L2CAP service in LE Credit-Based Flow-Control Mode
* @note MTU and initial credits are specified in l2cap_cbm_accept_connection(..) call
* @param packet_handler
* @param psm
* @param security_level
*/
uint8_t l2cap_le_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, gap_security_level_t security_level);
uint8_t l2cap_cbm_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, gap_security_level_t security_level);
/**
* @brief Unregister L2CAP LE Data Channel service
* @brief Unregister L2CAP service in LE Credit-Based Flow-Control Mode
* @param psm
*/
uint8_t l2cap_le_unregister_service(uint16_t psm);
uint8_t l2cap_cbm_unregister_service(uint16_t psm);
/*
* @brief Accept incoming LE Data Channel connection
* @param local_cid L2CAP LE Data Channel Identifier
* @brief Accept incoming connection LE Credit-Based Flow-Control Mode
* @param local_cid L2CAP Channel Identifier
* @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
* @param initial_credits Number of initial credits provided to peer or L2CAP_LE_AUTOMATIC_CREDITS to enable automatic credits
*/
uint8_t l2cap_le_accept_connection(uint16_t local_cid, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits);
uint8_t l2cap_cbm_accept_connection(uint16_t local_cid, uint8_t * receive_sdu_buffer, uint16_t mtu, uint16_t initial_credits);
/**
* @brief Deny incoming LE Data Channel connection due to resource constraints
* @param local_cid L2CAP LE Data Channel Identifier
* @brief Deecline connection in LE Credit-Based Flow-Control Mode
* @param local_cid L2CAP Channel Identifier
*/
uint8_t l2cap_le_decline_connection(uint16_t local_cid);
uint8_t l2cap_cbm_decline_connection(uint16_t local_cid);
/**
* @brief Create LE Data Channel
* @brief Create outgoing channel in LE Credit-Based Flow-Control Mode
* @param packet_handler Packet handler for this connection
* @param con_handle ACL-LE HCI Connction Handle
* @param con_handle HCI Connection Handle, LE transport
* @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
@ -653,53 +672,53 @@ 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, hci_con_handle_t con_handle,
uint8_t l2cap_cbm_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);
/**
* @brief Provide credtis for LE Data Channel
* @param local_cid L2CAP LE Data Channel Identifier
* @brief Provide credits for channel in LE Credit-Based Flow-Control Mode
* @param local_cid L2CAP Channel Identifier
* @param credits Number additional credits for peer
*/
uint8_t l2cap_le_provide_credits(uint16_t local_cid, uint16_t credits);
uint8_t l2cap_cbm_provide_credits(uint16_t local_cid, uint16_t credits);
/**
* @brief Check if packet can be scheduled for transmission
* @param local_cid L2CAP LE Data Channel Identifier
* @param local_cid L2CAP Channel Identifier
* @return true if packet can be sent on local_cid
*/
bool l2cap_le_can_send_now(uint16_t local_cid);
bool l2cap_cbm_can_send_now(uint16_t local_cid);
/**
* @brief Request emission of L2CAP_EVENT_LE_CAN_SEND_NOW as soon as possible
* @note L2CAP_EVENT_CAN_SEND_NOW might be emitted during call to this function
* so packet handler should be ready to handle it
* @param local_cid L2CAP LE Data Channel Identifier
* @param local_cid L2CAP Channel Identifier
*/
uint8_t l2cap_le_request_can_send_now_event(uint16_t local_cid);
uint8_t l2cap_cbm_request_can_send_now_event(uint16_t local_cid);
/**
* @brief Send data via LE Data Channel
* @brief Send data for channel in LE Credit-Based Flow-Control Mode
* @note Since data larger then the maximum PDU needs to be segmented into multiple PDUs, data needs to stay valid until ... event
* @param local_cid L2CAP LE Data Channel Identifier
* @param local_cid L2CAP Channel Identifier
* @param data data to send
* @param size data size
*/
uint8_t l2cap_le_send_data(uint16_t local_cid, uint8_t * data, uint16_t size);
uint8_t l2cap_cbm_send_data(uint16_t local_cid, uint8_t * data, uint16_t size);
/**
* @brief Disconnect from LE Data Channel
* @param local_cid L2CAP LE Data Channel Identifier
* @brief Disconnect channel in LE Credit-Based Flow-Control Mode
* @param local_cid L2CAP Channel Identifier
*/
uint8_t l2cap_le_disconnect(uint16_t local_cid);
uint8_t l2cap_cbm_disconnect(uint16_t local_cid);
//
// L2CAP Connection Oriented Channels feature with the Enhanced Credit Based Flow Control Mode == L2CAP Enhanced Data Channel
// L2CAP Connection-Oriented Channels in Enhanced Credit-Based Flow-Control Mode - ECBM
//
/**
* @brief Register L2CAP Enhanced Data Channel service
* @brief Register L2CAP service in Enhanced Credit-Based Flow-Control Mode
* @note MTU and initial credits are specified in l2cap_enhanced_accept_connection(..) call
* @param packet_handler
* @param psm
@ -707,34 +726,34 @@ uint8_t l2cap_le_disconnect(uint16_t local_cid);
* @param security_level
* @return status
*/
uint8_t l2cap_enhanced_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, uint16_t min_remote_mtu, gap_security_level_t security_level);
uint8_t l2cap_ecbm_register_service(btstack_packet_handler_t packet_handler, uint16_t psm, uint16_t min_remote_mtu, gap_security_level_t security_level);
/**
* @brief Unregister L2CAP Enhanced Data Channel service
* @brief Unregister L2CAP service in Enhanced Credit-Based Flow-Control Mode
* @param psm
* @return status
*/
uint8_t l2cap_enhanced_unregister_service(uint16_t psm);
uint8_t l2cap_ecbm_unregister_service(uint16_t psm);
/**
* @brief Set Minimal MPS for Enhanced Data Channels
* @brief Set Minimal MPS for channel in Enhanced Credit-Based Flow-Control Mode
* @param mps_min
*/
void l2cap_enhanced_mps_set_min(uint16_t mps_min);
void l2cap_ecbm_mps_set_min(uint16_t mps_min);
/**
* @brief Set Minimal MPS for Enhanced Data Channels
* @brief Set Minimal MPS for channel in Enhanced Credit-Based Flow-Control Mode
* @param mps_max
*/
void l2cap_enhanced_mps_set_max(uint16_t mps_max);
void l2cap_ecbm_mps_set_max(uint16_t mps_max);
/**
* @brief Create Enhanced Data Channel
* @brief Create outgoing channel in Enhanced Credit-Based Flow-Control Mode
* @note receive_buffer points to an array of receive buffers with num_channels elements
* @note out_local_cid points to an array where CID is stored with num_channel elements
* @param packet_handler Packet handler for this connection
* @param con_handle ACL-LE HCI Connction Handle
* @param con_handle HCI Connection Handle
* @param security_level Minimum required security level
* @param psm Service PSM to connect to
* @param num_channels number of channels to create
@ -750,41 +769,41 @@ uint8_t l2cap_enhanced_create_channels(btstack_packet_handler_t packet_handler,
uint8_t ** receive_buffers, uint16_t * out_local_cids);
/**
* @brief Accept incoming Enhanced Data Channel
* @param local_cid from L2CAP_EVENT_INCOMING_DATA_CONNECTION
* @brief Accept incoming connection Enhanced Credit-Based Flow-Control Mode
* @param local_cid from L2CAP_EVENT_INCOMING_DATA_CONNECTION
* @param num_channels
* @param initial_credits Number of initial credits provided to peer per channel or L2CAP_LE_AUTOMATIC_CREDITS to enable automatic credits
* @param initial_credits Number of initial credits provided to peer per channel or L2CAP_LE_AUTOMATIC_CREDITS to enable automatic credits
* @param receive_buffer_size
* @param receive_buffers Array of buffers used for reassembly of L2CAP Information Frames into service data unit (SDU) with given MTU
* @param out_local_cids Array of L2CAP Channel Identifiers is stored here on success
* @return status
*/
uint8_t l2cap_enhanced_accept_data_channels(uint16_t local_cid, uint8_t num_channels, uint16_t initial_credits,
uint8_t l2cap_ecbm_accept_data_channels(uint16_t local_cid, uint8_t num_channels, uint16_t initial_credits,
uint16_t receive_buffer_size, uint8_t ** receive_buffers, uint16_t * out_local_cids);
/**
* @brief Accept/Reject incoming Enhanced Data Channel
* @brief Decline connection in Enhanced Credit-Based Flow-Control Mode
* @param local_cid from L2CAP_EVENT_INCOMING_DATA_CONNECTION
* @param result 0x0004 - insufficient resources, 0x0006 - insufficient authorization
* @param result 0x0004 - insufficient resources, 0x0006 - insufficient authorization
* @return status
*/
uint8_t l2cap_enhanced_decline_data_channels(uint16_t local_cid, uint16_t result);
uint8_t l2cap_ecbm_decline_data_channels(uint16_t local_cid, uint16_t result);
/**
* @brief Provide credits for Enhanced Data Channel
* @param local_cid L2CAP LE Data Channel Identifier
* @brief Provide credits for channel in Enhanced Credit-Based Flow-Control Mode
* @param local_cid L2CAP Channel Identifier
* @param credits Number additional credits for peer
* @return status
*/
uint8_t l2cap_enhanced_provide_credits(uint16_t local_cid, uint16_t credits);
uint8_t l2cap_ecbm_provide_credits(uint16_t local_cid, uint16_t credits);
/**
* @brief Request emission of L2CAP_EVENT_DATA_CHANNEL_CAN_SEND_NOW as soon as possible
* @note L2CAP_EVENT_DATA_CHANNEL_CAN_SEND_NOW might be emitted during call to this function
* so packet handler should be ready to handle it
* @param local_cid L2CAP LE Data Channel Identifier
* @param local_cid L2CAP Channel Identifier
* @return status
*/
uint8_t l2cap_enhanced_data_channel_request_can_send_now_event(uint16_t local_cid);
uint8_t l2cap_ecbm_data_channel_request_can_send_now_event(uint16_t local_cid);
/**
* @brief Reconfigure MPS/MTU of local channels
@ -794,40 +813,24 @@ uint8_t l2cap_enhanced_data_channel_request_can_send_now_event(uint16_t local_ci
* @param receive_buffers Array of buffers used for reassembly of L2CAP Information Frames into service data unit (SDU) with given MTU
* @return status
*/
uint8_t l2cap_enhanced_reconfigure(uint8_t num_cids, uint16_t * local_cids, int16_t receive_buffer_size, uint8_t ** receive_buffers);
uint8_t l2cap_ecbm_reconfigure(uint8_t num_cids, uint16_t * local_cids, int16_t receive_buffer_size, uint8_t ** receive_buffers);
/**
* @brief Send data via Enhanced Data Channel
* @brief Send data for channel in Enhanced Credit-Based Flow-Control Mode
* @note Since data larger then the maximum PDU needs to be segmented into multiple PDUs, data needs to stay valid until ... event
* @param local_cid L2CAP Enhanced Data Channel Identifier
* @param local_cid L2CAP Channel Identifier
* @param data data to send
* @param size data size
* @return status
*/
uint8_t l2cap_enhanced_send_data(uint16_t local_cid, const uint8_t * data, uint16_t size);
uint8_t l2cap_ecbm_send_data(uint16_t local_cid, const uint8_t * data, uint16_t size);
/**
* @brief Disconnect from Enhanced Data Channel
* @param local_cid L2CAP LE Data Channel Identifier
* @brief Disconnect channel in Enhanced Credit-Based Flow-Control Mode
* @param local_cid L2CAP Channel Identifier
* @return status
*/
uint8_t l2cap_enhanced_disconnect(uint16_t local_cid);
/**
* @brief ERTM Set channel as busy.
* @note Can be cleared by l2cap_ertm_set_ready
* @param local_cid
* @return status
*/
uint8_t l2cap_ertm_set_busy(uint16_t local_cid);
/**
* @brief ERTM Set channel as ready
* @note Used after l2cap_ertm_set_busy
* @param local_cid
* @return status
*/
uint8_t l2cap_ertm_set_ready(uint16_t local_cid);
uint8_t l2cap_ecbm_disconnect(uint16_t local_cid);
/**
* @brief De-Init L2CAP

View File

@ -228,10 +228,10 @@ static void l2cap_channel_packet_handler(uint8_t packet_type, uint16_t channel,
printf("L2CAP_EVENT_DATA_CHANNEL_INCOMING\n");
cid = l2cap_event_data_channel_incoming_get_local_cid(packet);
if (l2cap_channel_accept_incoming){
l2cap_enhanced_accept_data_channels(cid, 2, initial_credits, TEST_PACKET_SIZE, receive_buffers_2, cids);
l2cap_ecbm_accept_data_channels(cid, 2, initial_credits, TEST_PACKET_SIZE, receive_buffers_2, cids);
} else {
// reject request by providing zero buffers
l2cap_enhanced_accept_data_channels(cid, 0, 0, 0,NULL, NULL);
l2cap_ecbm_accept_data_channels(cid, 0, 0, 0,NULL, NULL);
}
break;
case L2CAP_EVENT_DATA_CHANNEL_OPENED:
@ -324,7 +324,7 @@ TEST(L2CAP_CHANNELS, incoming_classic_no_service){
TEST(L2CAP_CHANNELS, incoming_1){
hci_setup_test_connections_fuzz();
l2cap_enhanced_register_service(&l2cap_channel_packet_handler, TEST_PSM, TEST_PACKET_SIZE, LEVEL_0);
l2cap_ecbm_register_service(&l2cap_channel_packet_handler, TEST_PSM, TEST_PACKET_SIZE, LEVEL_0);
l2cap_channel_accept_incoming = false;
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_le_conn_request_1, sizeof(l2cap_enhanced_data_channel_le_conn_request_1));
CHECK_EQUAL(0, num_l2cap_channel_opened);
@ -332,7 +332,7 @@ TEST(L2CAP_CHANNELS, incoming_1){
TEST(L2CAP_CHANNELS, incoming_2){
hci_setup_test_connections_fuzz();
l2cap_enhanced_register_service(&l2cap_channel_packet_handler, TEST_PSM, TEST_PACKET_SIZE, LEVEL_0);
l2cap_ecbm_register_service(&l2cap_channel_packet_handler, TEST_PSM, TEST_PACKET_SIZE, LEVEL_0);
l2cap_channel_accept_incoming = true;
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_le_conn_request_1, sizeof(l2cap_enhanced_data_channel_le_conn_request_1));
CHECK_EQUAL(2, num_l2cap_channel_opened);
@ -369,7 +369,7 @@ TEST(L2CAP_CHANNELS, outgoing_le_send_packet){
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_le_conn_response_2_success, sizeof(l2cap_enhanced_data_channel_le_conn_response_2_success));
CHECK_EQUAL(2, num_l2cap_channel_opened);
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_le_credits, sizeof(l2cap_enhanced_data_channel_le_credits));
status = l2cap_enhanced_send_data(l2cap_cids[0], (const uint8_t *) "hello", 5);
status = l2cap_ecbm_send_data(l2cap_cids[0], (const uint8_t *) "hello", 5);
}
TEST(L2CAP_CHANNELS, outgoing_classic_send_packet){
@ -381,7 +381,7 @@ TEST(L2CAP_CHANNELS, outgoing_classic_send_packet){
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_classic_conn_response_2_success, sizeof(l2cap_enhanced_data_channel_classic_conn_response_2_success));
CHECK_EQUAL(2, num_l2cap_channel_opened);
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_classic_credits, sizeof(l2cap_enhanced_data_channel_classic_credits));
status = l2cap_enhanced_send_data(l2cap_cids[0], (const uint8_t *) "hello", 5);
status = l2cap_ecbm_send_data(l2cap_cids[0], (const uint8_t *) "hello", 5);
}
TEST(L2CAP_CHANNELS, outgoing_le_receive_packet){
@ -416,7 +416,7 @@ TEST(L2CAP_CHANNELS, outgoing_le_provide_credits){
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_le_conn_response_2_success, sizeof(l2cap_enhanced_data_channel_le_conn_response_2_success));
CHECK_EQUAL(2, num_l2cap_channel_opened);
status = l2cap_enhanced_provide_credits(l2cap_cids[0], 5);
status = l2cap_ecbm_provide_credits(l2cap_cids[0], 5);
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
}
@ -428,7 +428,7 @@ TEST(L2CAP_CHANNELS, outgoing_classic_provide_credits){
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_classic_conn_response_2_success, sizeof(l2cap_enhanced_data_channel_classic_conn_response_2_success));
CHECK_EQUAL(2, num_l2cap_channel_opened);
status = l2cap_enhanced_provide_credits(l2cap_cids[0], 5);
status = l2cap_ecbm_provide_credits(l2cap_cids[0], 5);
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
}
@ -441,7 +441,7 @@ TEST(L2CAP_CHANNELS, outgoing_le_renegotiate_initiator){
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_le_conn_response_2_success, sizeof(l2cap_enhanced_data_channel_le_conn_response_2_success));
CHECK_EQUAL(2, num_l2cap_channel_opened);
status = l2cap_enhanced_reconfigure(2, l2cap_cids, TEST_PACKET_SIZE/2, reconfigure_buffers_2);
status = l2cap_ecbm_reconfigure(2, l2cap_cids, TEST_PACKET_SIZE/2, reconfigure_buffers_2);
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_le_renegotiate_response, sizeof(l2cap_enhanced_data_channel_le_renegotiate_response));
CHECK_EQUAL(0, reconfigure_result);
@ -456,7 +456,7 @@ TEST(L2CAP_CHANNELS, outgoing_classic_renegotiate_initiator){
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_classic_conn_response_2_success, sizeof(l2cap_enhanced_data_channel_classic_conn_response_2_success));
CHECK_EQUAL(2, num_l2cap_channel_opened);
status = l2cap_enhanced_reconfigure(2, l2cap_cids, TEST_PACKET_SIZE/2, reconfigure_buffers_2);
status = l2cap_ecbm_reconfigure(2, l2cap_cids, TEST_PACKET_SIZE/2, reconfigure_buffers_2);
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_classic_renegotiate_response, sizeof(l2cap_enhanced_data_channel_classic_renegotiate_response));
CHECK_EQUAL(0, reconfigure_result);
@ -496,8 +496,8 @@ TEST(L2CAP_CHANNELS, outgoing_le_disconnect_initiator){
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_le_conn_response_2_success, sizeof(l2cap_enhanced_data_channel_le_conn_response_2_success));
CHECK_EQUAL(2, num_l2cap_channel_opened);
l2cap_enhanced_disconnect(l2cap_cids[0]);
l2cap_enhanced_disconnect(l2cap_cids[1]);
l2cap_ecbm_disconnect(l2cap_cids[0]);
l2cap_ecbm_disconnect(l2cap_cids[1]);
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_le_disconnect_response_1, sizeof(l2cap_enhanced_data_channel_le_disconnect_response_1));
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_le_disconnect_response_2, sizeof(l2cap_enhanced_data_channel_le_disconnect_response_2));
CHECK_EQUAL(2, num_l2cap_channel_closed);
@ -524,8 +524,8 @@ TEST(L2CAP_CHANNELS, outgoing_classic_disconnect_initiator){
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_classic_conn_response_2_success, sizeof(l2cap_enhanced_data_channel_classic_conn_response_2_success));
CHECK_EQUAL(2, num_l2cap_channel_opened);
l2cap_enhanced_disconnect(l2cap_cids[0]);
l2cap_enhanced_disconnect(l2cap_cids[1]);
l2cap_ecbm_disconnect(l2cap_cids[0]);
l2cap_ecbm_disconnect(l2cap_cids[1]);
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_classic_disconnect_response_1, sizeof(l2cap_enhanced_data_channel_classic_disconnect_response_1));
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, l2cap_enhanced_data_channel_classic_disconnect_response_2, sizeof(l2cap_enhanced_data_channel_classic_disconnect_response_2));
CHECK_EQUAL(2, num_l2cap_channel_closed);

View File

@ -132,9 +132,9 @@ static void l2cap_channel_packet_handler(uint8_t packet_type, uint16_t channel,
psm = l2cap_event_le_incoming_connection_get_psm(packet);
cid = l2cap_event_le_incoming_connection_get_local_cid(packet);
if (l2cap_channel_accept_incoming){
l2cap_le_accept_connection(cid, data_channel_buffer, sizeof(data_channel_buffer), initial_credits);
l2cap_cbm_accept_connection(cid, data_channel_buffer, sizeof(data_channel_buffer), initial_credits);
} else {
l2cap_le_decline_connection(cid);
l2cap_cbm_decline_connection(cid);
}
break;
case L2CAP_EVENT_LE_CHANNEL_OPENED:
@ -196,28 +196,28 @@ TEST(L2CAP_CHANNELS, some_functions){
l2cap_release_packet_buffer();
l2cap_set_max_le_mtu(30);
l2cap_set_max_le_mtu(30);
l2cap_le_unregister_service(TEST_PSM);
l2cap_le_accept_connection(0X01, NULL, 0, 0);
l2cap_le_decline_connection(0x01);
l2cap_le_disconnect(0x01);
l2cap_cbm_unregister_service(TEST_PSM);
l2cap_cbm_accept_connection(0X01, NULL, 0, 0);
l2cap_cbm_decline_connection(0x01);
l2cap_cbm_disconnect(0x01);
}
TEST(L2CAP_CHANNELS, outgoing_no_connection){
l2cap_le_create_channel(&l2cap_channel_packet_handler, HCI_CON_HANDLE_TEST_LE, TEST_PSM, data_channel_buffer,
l2cap_cbm_create_channel(&l2cap_channel_packet_handler, HCI_CON_HANDLE_TEST_LE, TEST_PSM, data_channel_buffer,
sizeof(data_channel_buffer), L2CAP_LE_AUTOMATIC_CREDITS, LEVEL_0, &l2cap_cid);
}
TEST(L2CAP_CHANNELS, outgoing_security_1){
hci_setup_test_connections_fuzz();
l2cap_le_create_channel(&l2cap_channel_packet_handler, HCI_CON_HANDLE_TEST_LE, TEST_PSM, data_channel_buffer,
l2cap_cbm_create_channel(&l2cap_channel_packet_handler, HCI_CON_HANDLE_TEST_LE, TEST_PSM, data_channel_buffer,
sizeof(data_channel_buffer), L2CAP_LE_AUTOMATIC_CREDITS, LEVEL_2, NULL);
l2cap_le_create_channel(&l2cap_channel_packet_handler, HCI_CON_HANDLE_TEST_LE, TEST_PSM, data_channel_buffer,
l2cap_cbm_create_channel(&l2cap_channel_packet_handler, HCI_CON_HANDLE_TEST_LE, TEST_PSM, data_channel_buffer,
sizeof(data_channel_buffer), L2CAP_LE_AUTOMATIC_CREDITS, LEVEL_2, &l2cap_cid);
}
TEST(L2CAP_CHANNELS, outgoing_1){
hci_setup_test_connections_fuzz();
l2cap_le_create_channel(&l2cap_channel_packet_handler, HCI_CON_HANDLE_TEST_LE, TEST_PSM, data_channel_buffer,
l2cap_cbm_create_channel(&l2cap_channel_packet_handler, HCI_CON_HANDLE_TEST_LE, TEST_PSM, data_channel_buffer,
sizeof(data_channel_buffer), L2CAP_LE_AUTOMATIC_CREDITS, LEVEL_0, &l2cap_cid);
// fix_boundary_flags(mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
// print_acl("le_data_channel_conn_request_1", mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
@ -225,34 +225,34 @@ TEST(L2CAP_CHANNELS, outgoing_1){
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, le_data_channel_conn_response_1, sizeof(le_data_channel_conn_response_1));
CHECK(l2cap_channel_opened);
CHECK(hci_number_free_acl_slots_for_handle(HCI_CON_HANDLE_TEST_LE) > 0);
bool can_send_now = l2cap_le_can_send_now(l2cap_cid);
bool can_send_now = l2cap_cbm_can_send_now(l2cap_cid);
CHECK(can_send_now);
l2cap_le_request_can_send_now_event(l2cap_cid);
l2cap_cbm_request_can_send_now_event(l2cap_cid);
CHECK(hci_number_free_acl_slots_for_handle(HCI_CON_HANDLE_TEST_LE) > 0);
l2cap_le_send_data(l2cap_cid, (uint8_t *) "hallo", 5);
l2cap_cbm_send_data(l2cap_cid, (uint8_t *) "hallo", 5);
// CHECK(hci_number_free_acl_slots_for_handle(HCI_CON_HANDLE_TEST) > 0);
// fix_boundary_flags(mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
// print_acl("le_data_channel_data_1", mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
// simulate data
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, le_data_channel_data_1, sizeof(le_data_channel_data_1));
l2cap_le_disconnect(l2cap_cid);
l2cap_cbm_disconnect(l2cap_cid);
}
TEST(L2CAP_CHANNELS, incoming_1){
hci_setup_test_connections_fuzz();
l2cap_le_register_service(&l2cap_channel_packet_handler, TEST_PSM, LEVEL_0);
l2cap_cbm_register_service(&l2cap_channel_packet_handler, TEST_PSM, LEVEL_0);
// simulate conn request
l2cap_channel_accept_incoming = true;
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, le_data_channel_conn_request_1, sizeof(le_data_channel_conn_request_1));
// fix_boundary_flags(mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
// print_acl("le_data_channel_conn_response_1", mock_hci_transport_outgoing_packet_buffer, mock_hci_transport_outgoing_packet_size);
// TODO: verify data
l2cap_le_unregister_service(TEST_PSM);
l2cap_cbm_unregister_service(TEST_PSM);
}
TEST(L2CAP_CHANNELS, incoming_2){
hci_setup_test_connections_fuzz();
l2cap_le_register_service(&l2cap_channel_packet_handler, TEST_PSM, LEVEL_2);
l2cap_cbm_register_service(&l2cap_channel_packet_handler, TEST_PSM, LEVEL_2);
// simulate conn request
l2cap_channel_accept_incoming = true;
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, le_data_channel_conn_request_1, sizeof(le_data_channel_conn_request_1));
@ -260,7 +260,7 @@ TEST(L2CAP_CHANNELS, incoming_2){
TEST(L2CAP_CHANNELS, incoming_3){
hci_setup_test_connections_fuzz();
l2cap_le_register_service(&l2cap_channel_packet_handler, TEST_PSM, LEVEL_0);
l2cap_cbm_register_service(&l2cap_channel_packet_handler, TEST_PSM, LEVEL_0);
// simulate conn request
l2cap_channel_accept_incoming = true;
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, le_data_channel_invalid_pdu, sizeof(le_data_channel_invalid_pdu));
@ -268,7 +268,7 @@ TEST(L2CAP_CHANNELS, incoming_3){
TEST(L2CAP_CHANNELS, incoming_decline){
hci_setup_test_connections_fuzz();
l2cap_le_register_service(&l2cap_channel_packet_handler, TEST_PSM, LEVEL_0);
l2cap_cbm_register_service(&l2cap_channel_packet_handler, TEST_PSM, LEVEL_0);
// simulate conn request
l2cap_channel_accept_incoming = false;
mock_hci_transport_receive_packet(HCI_ACL_DATA_PACKET, le_data_channel_conn_request_1, sizeof(le_data_channel_conn_request_1));

View File

@ -124,7 +124,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
uint16_t l2cap_cid = little_endian_read_16(packet, 12);
if (l2cap_ertm){
printf("L2CAP Accepting incoming connection request in ERTM\n");
l2cap_accept_ertm_connection(l2cap_cid, &ertm_config, ertm_buffer, sizeof(ertm_buffer));
l2cap_ertm_accept_connection(l2cap_cid, &ertm_config, ertm_buffer, sizeof(ertm_buffer));
} else {
printf("L2CAP Accepting incoming connection request in Basic Mode\n");
l2cap_accept_connection(l2cap_cid);
@ -169,7 +169,7 @@ static void stdin_process(char buffer){
case 'c':
printf("Creating L2CAP Connection to %s, PSM SDP\n", bd_addr_to_str(remote));
if (l2cap_ertm){
l2cap_create_ertm_channel(packet_handler, remote, BLUETOOTH_PSM_SDP, &ertm_config, ertm_buffer, sizeof(ertm_buffer), &local_cid);
l2cap_ertm_create_channel(packet_handler, remote, BLUETOOTH_PSM_SDP, &ertm_config, ertm_buffer, sizeof(ertm_buffer), &local_cid);
} else {
l2cap_create_channel(packet_handler, remote, BLUETOOTH_PSM_SDP, 100, &local_cid);
}

View File

@ -216,7 +216,7 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
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);
l2cap_cbm_accept_connection(cid, receive_buffer_X, sizeof(receive_buffer_X), initial_credits);
break;
@ -249,20 +249,20 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
if (todo_send_short){
todo_send_short = 0;
if (enhanced_data_channel){
l2cap_enhanced_send_data(cid_enhanced, (uint8_t *) data_short, strlen(data_short));
l2cap_ecbm_send_data(cid_enhanced, (uint8_t *) data_short, strlen(data_short));
} else {
l2cap_le_send_data(cid_le, (uint8_t *) data_short, strlen(data_short));
l2cap_cbm_send_data(cid_le, (uint8_t *) data_short, strlen(data_short));
}
break;
}
if (todo_send_long){
todo_send_long = 0;
if (enhanced_data_channel){
// l2cap_enhanced_send_data(cid_enhanced, (uint8_t *) data_long, strlen(data_long));
// l2cap_ecbm_send_data(cid_enhanced, (uint8_t *) data_long, strlen(data_long));
memset(receive_buffer_X, 0x33, enhanced_remote_mtu);
l2cap_enhanced_send_data(cid_enhanced, (uint8_t *) receive_buffer_X, enhanced_remote_mtu);
l2cap_ecbm_send_data(cid_enhanced, (uint8_t *) receive_buffer_X, enhanced_remote_mtu);
} else {
l2cap_le_send_data(cid_le, (uint8_t *) data_long, strlen(data_long));
l2cap_cbm_send_data(cid_le, (uint8_t *) data_long, strlen(data_long));
}
}
break;
@ -293,15 +293,15 @@ static void app_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *
cid = l2cap_event_data_channel_incoming_get_local_cid(packet);
if (enhanced_authorization_required){
enhanced_authorization_required = false;
l2cap_enhanced_decline_data_channels(cid, 0x0006);
l2cap_ecbm_decline_data_channels(cid, 0x0006);
break;
}
if (enhanced_insufficient_key_size){
enhanced_insufficient_key_size = false;
l2cap_enhanced_decline_data_channels(cid, 0x0007);
l2cap_ecbm_decline_data_channels(cid, 0x0007);
break;
}
l2cap_enhanced_accept_data_channels(cid, 2, initial_credits, ENHANCED_MTU_INITIAL, receive_buffers_2, cids);
l2cap_ecbm_accept_data_channels(cid, 2, initial_credits, ENHANCED_MTU_INITIAL, receive_buffers_2, cids);
break;
case L2CAP_EVENT_DATA_CHANNEL_RECONFIGURED:
@ -406,13 +406,13 @@ static void stdin_process(char buffer){
case 'b':
printf("Connect to PSM 0x%02x - CFC LE\n", TSPX_LE_PSM);
l2cap_le_create_channel(&app_packet_handler, handle_le, TSPX_LE_PSM, buffer_x,
l2cap_cbm_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 'B':
printf("Creating connection to %s 0x%02x - CFC LE\n", bd_addr_to_str(pts_address), TSPX_PSM_UNSUPPORTED);
l2cap_le_create_channel(&app_packet_handler, handle_le, TSPX_PSM_UNSUPPORTED, buffer_x,
l2cap_cbm_create_channel(&app_packet_handler, handle_le, TSPX_PSM_UNSUPPORTED, buffer_x,
sizeof(buffer_x), L2CAP_LE_AUTOMATIC_CREDITS, LEVEL_0, &cid_le);
break;
@ -441,29 +441,29 @@ static void stdin_process(char buffer){
case 'c':
printf("Provide 10 credits\n");
if (enhanced_data_channel){
l2cap_enhanced_provide_credits(cid_enhanced, 10);
l2cap_ecbm_provide_credits(cid_enhanced, 10);
} else {
l2cap_le_provide_credits(cid_le, 10);
l2cap_cbm_provide_credits(cid_le, 10);
}
break;
case 'e':
printf("Re-register L2CAP ECFC channel as LEVEL_2 / insufficient key size\n");
l2cap_enhanced_unregister_service(TSPX_ENHANCED_PSM);
l2cap_enhanced_register_service(&app_packet_handler, TSPX_ENHANCED_PSM, MTU_MIN, LEVEL_2);
l2cap_ecbm_unregister_service(TSPX_ENHANCED_PSM);
l2cap_ecbm_register_service(&app_packet_handler, TSPX_ENHANCED_PSM, MTU_MIN, LEVEL_2);
enhanced_insufficient_key_size = true;
break;
case 'E':
printf("Re-register L2CAP ECFC channel as LEVEL_3\n");
l2cap_enhanced_unregister_service(TSPX_ENHANCED_PSM);
l2cap_enhanced_register_service(&app_packet_handler, TSPX_ENHANCED_PSM, MTU_MIN, LEVEL_3);
l2cap_ecbm_unregister_service(TSPX_ENHANCED_PSM);
l2cap_ecbm_register_service(&app_packet_handler, TSPX_ENHANCED_PSM, MTU_MIN, LEVEL_3);
break;
case 'f':
printf("Require Authentication for ECFC\n");
l2cap_enhanced_unregister_service(TSPX_ENHANCED_PSM);
l2cap_enhanced_register_service(&app_packet_handler, TSPX_ENHANCED_PSM, MTU_MIN, LEVEL_2);
l2cap_ecbm_unregister_service(TSPX_ENHANCED_PSM);
l2cap_ecbm_register_service(&app_packet_handler, TSPX_ENHANCED_PSM, MTU_MIN, LEVEL_2);
enhanced_authorization_required = true;
break;
@ -474,8 +474,8 @@ static void stdin_process(char buffer){
case 'r':
printf("Reconfigure MTU = %u, MPS = %u\n", ENHANCED_MTU_RECONFIGURE, enhanced_reconfigure_mps[enhanced_reconfigure_index]);
l2cap_enhanced_mps_set_max(enhanced_reconfigure_mps[enhanced_reconfigure_index++]);
l2cap_enhanced_reconfigure(1, &cid_enhanced, ENHANCED_MTU_RECONFIGURE, receive_buffers_2);
l2cap_ecbm_mps_set_max(enhanced_reconfigure_mps[enhanced_reconfigure_index++]);
l2cap_ecbm_reconfigure(1, &cid_enhanced, ENHANCED_MTU_RECONFIGURE, receive_buffers_2);
if (enhanced_reconfigure_index == enhanced_reconfigure_choices){
enhanced_reconfigure_index = 0;
}
@ -485,9 +485,9 @@ static void stdin_process(char buffer){
printf("Send L2CAP Data Short %s\n", data_short);
todo_send_short = 1;
if (enhanced_data_channel){
l2cap_enhanced_data_channel_request_can_send_now_event(cid_enhanced);
l2cap_ecbm_data_channel_request_can_send_now_event(cid_enhanced);
} else {
l2cap_le_request_can_send_now_event(cid_le);
l2cap_cbm_request_can_send_now_event(cid_le);
}
break;
@ -495,9 +495,9 @@ static void stdin_process(char buffer){
printf("Send L2CAP Data Long %s\n", data_long);
todo_send_long = 1;
if (enhanced_data_channel){
l2cap_enhanced_data_channel_request_can_send_now_event(cid_enhanced);
l2cap_ecbm_data_channel_request_can_send_now_event(cid_enhanced);
} else {
l2cap_le_request_can_send_now_event(cid_le);
l2cap_cbm_request_can_send_now_event(cid_le);
}
break;
@ -514,10 +514,10 @@ static void stdin_process(char buffer){
case 't':
if (enhanced_data_channel){
printf("Disconnect channel 0x%02x\n", cid_enhanced);
l2cap_enhanced_disconnect(cid_enhanced);
l2cap_ecbm_disconnect(cid_enhanced);
} else {
printf("Disconnect channel 0x%02x\n", cid_le);
l2cap_le_disconnect(cid_le);
l2cap_cbm_disconnect(cid_le);
}
break;
@ -564,12 +564,12 @@ int btstack_main(int argc, const char * argv[]){
sm_set_authentication_requirements(0);
// le data channel setup
l2cap_le_register_service(&app_packet_handler, TSPX_LE_PSM, LEVEL_0);
l2cap_cbm_register_service(&app_packet_handler, TSPX_LE_PSM, LEVEL_0);
// l2cap data channel setup
l2cap_enhanced_register_service(&app_packet_handler, TSPX_ENHANCED_PSM, MTU_MIN, LEVEL_0);
l2cap_ecbm_register_service(&app_packet_handler, TSPX_ENHANCED_PSM, MTU_MIN, LEVEL_0);
l2cap_enhanced_mps_set_min(TSPX_L2CA_CBMPS_MIN);
l2cap_ecbm_mps_set_min(TSPX_L2CA_CBMPS_MIN);
// classic data channel setup
l2cap_register_service(&app_packet_handler, TSPX_PSM, 100, LEVEL_0);

View File

@ -52,8 +52,8 @@ s/l2cap_accept_connection_internal/l2cap_accept_connection/g
s/l2cap_create_channel_internal/l2cap_create_channel/g
s/l2cap_decline_connection_internal/l2cap_decline_connection/g
s/l2cap_disconnect_internal/l2cap_disconnect/g
s/l2cap_le_register_service_internal/l2cap_le_register_service/g
s/l2cap_le_unregister_service_internal/l2cap_le_unregister_service/g
s/l2cap_le_register_service_internal/l2cap_cbm_register_service/g
s/l2cap_le_unregister_service_internal/l2cap_cbm_unregister_service/g
s/l2cap_register_service_internal/l2cap_register_service/g
s/l2cap_send_internal/l2cap_send/g
s/l2cap_unregister_service_internal/l2cap_unregister_service/g