mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-02-20 18:40:31 +00:00
l2cap: introduce parameter object l2cap_ertm_config_t for l2cap_create_ertm_channel and l2cap_accept_ertm_connection
This commit is contained in:
parent
671fb338cc
commit
9c0e62d33a
61
src/l2cap.c
61
src/l2cap.c
@ -394,51 +394,49 @@ static int l2cap_ertm_send_supervisor_frame(l2cap_channel_t * channel, uint16_t
|
||||
return l2cap_send_prepared(channel->local_cid, 2);
|
||||
}
|
||||
|
||||
static uint8_t l2cap_ertm_validate_local_config(uint8_t max_transmit, uint16_t retransmission_timeout_ms, uint16_t monitor_timeout_ms,
|
||||
uint16_t local_mtu, uint8_t num_tx_buffers, uint8_t num_rx_buffers, uint8_t * buffer, uint32_t size){
|
||||
static uint8_t l2cap_ertm_validate_local_config(l2cap_ertm_config_t * ertm_config, uint8_t * buffer, uint32_t size){
|
||||
|
||||
UNUSED(buffer);
|
||||
UNUSED(size);
|
||||
|
||||
uint8_t result = ERROR_CODE_SUCCESS;
|
||||
if (max_transmit < 1){
|
||||
if (ertm_config->max_transmit < 1){
|
||||
log_error("max_transmit must be >= 1");
|
||||
result = ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
|
||||
}
|
||||
if (retransmission_timeout_ms < 2000){
|
||||
if (ertm_config->retransmission_timeout_ms < 2000){
|
||||
log_error("retransmission_timeout_ms must be >= 2000 ms");
|
||||
result = ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
|
||||
}
|
||||
if (monitor_timeout_ms < 12000){
|
||||
if (ertm_config->monitor_timeout_ms < 12000){
|
||||
log_error("monitor_timeout_ms must be >= 12000 ms");
|
||||
result = ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
|
||||
}
|
||||
if (local_mtu < 48){
|
||||
if (ertm_config->local_mtu < 48){
|
||||
log_error("local_mtu must be >= 48");
|
||||
result = ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
|
||||
}
|
||||
if (num_rx_buffers < 1){
|
||||
if (ertm_config->num_rx_buffers < 1){
|
||||
log_error("num_rx_buffers must be >= 1");
|
||||
result = ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
|
||||
}
|
||||
if (num_tx_buffers < 1){
|
||||
if (ertm_config->num_tx_buffers < 1){
|
||||
log_error("num_rx_buffers must be >= 1");
|
||||
result = ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void l2cap_ertm_configure_channel(l2cap_channel_t * channel, int ertm_mandatory, uint8_t max_transmit, uint16_t retransmission_timeout_ms,
|
||||
uint16_t monitor_timeout_ms, uint16_t local_mtu, uint8_t num_tx_buffers, uint8_t num_rx_buffers, uint8_t * buffer, uint32_t size){
|
||||
static void l2cap_ertm_configure_channel(l2cap_channel_t * channel, l2cap_ertm_config_t * ertm_config, uint8_t * buffer, uint32_t size){
|
||||
|
||||
channel->mode = L2CAP_CHANNEL_MODE_ENHANCED_RETRANSMISSION;
|
||||
channel->ertm_mandatory = ertm_mandatory;
|
||||
channel->local_max_transmit = max_transmit;
|
||||
channel->local_retransmission_timeout_ms = retransmission_timeout_ms;
|
||||
channel->local_monitor_timeout_ms = monitor_timeout_ms;
|
||||
channel->local_mtu = local_mtu;
|
||||
channel->num_rx_buffers = num_rx_buffers;
|
||||
channel->num_tx_buffers = num_tx_buffers;
|
||||
channel->ertm_mandatory = ertm_config->ertm_mandatory;
|
||||
channel->local_max_transmit = ertm_config->max_transmit;
|
||||
channel->local_retransmission_timeout_ms = ertm_config->retransmission_timeout_ms;
|
||||
channel->local_monitor_timeout_ms = ertm_config->monitor_timeout_ms;
|
||||
channel->local_mtu = ertm_config->local_mtu;
|
||||
channel->num_rx_buffers = ertm_config->num_rx_buffers;
|
||||
channel->num_tx_buffers = ertm_config->num_tx_buffers;
|
||||
|
||||
// align buffer to 16-byte boundary, just in case
|
||||
int bytes_till_alignment = 16 - (((uintptr_t) buffer) & 0x0f);
|
||||
@ -448,40 +446,38 @@ static void l2cap_ertm_configure_channel(l2cap_channel_t * channel, int ertm_man
|
||||
// setup state buffers
|
||||
uint32_t pos = 0;
|
||||
channel->rx_packets_state = (l2cap_ertm_rx_packet_state_t *) &buffer[pos];
|
||||
pos += num_rx_buffers * sizeof(l2cap_ertm_rx_packet_state_t);
|
||||
pos += ertm_config->num_rx_buffers * sizeof(l2cap_ertm_rx_packet_state_t);
|
||||
channel->tx_packets_state = (l2cap_ertm_tx_packet_state_t *) &buffer[pos];
|
||||
pos += num_tx_buffers * sizeof(l2cap_ertm_tx_packet_state_t);
|
||||
pos += ertm_config->num_tx_buffers * sizeof(l2cap_ertm_tx_packet_state_t);
|
||||
|
||||
// setup reassembly buffer
|
||||
channel->reassembly_buffer = &buffer[pos];
|
||||
pos += local_mtu;
|
||||
pos += ertm_config->local_mtu;
|
||||
|
||||
// divide rest of data equally
|
||||
channel->local_mps = (size - pos) / (num_rx_buffers + num_tx_buffers);
|
||||
channel->local_mps = (size - pos) / (ertm_config->num_rx_buffers + ertm_config->num_tx_buffers);
|
||||
log_info("Local MPS: %u", channel->local_mtu);
|
||||
channel->rx_packets_data = &buffer[pos];
|
||||
pos += num_rx_buffers * channel->local_mtu;
|
||||
pos += ertm_config->num_rx_buffers * channel->local_mtu;
|
||||
channel->tx_packets_data = &buffer[pos];
|
||||
}
|
||||
|
||||
uint8_t l2cap_create_ertm_channel(btstack_packet_handler_t packet_handler, bd_addr_t address, uint16_t psm,
|
||||
int ertm_mandatory, uint8_t max_transmit, uint16_t retransmission_timeout_ms, uint16_t monitor_timeout_ms,
|
||||
uint16_t local_mtu, uint8_t num_tx_buffers, uint8_t num_rx_buffers, uint8_t * buffer, uint32_t size, uint16_t * out_local_cid){
|
||||
l2cap_ertm_config_t * ertm_config, uint8_t * buffer, uint32_t size, uint16_t * out_local_cid){
|
||||
|
||||
log_info("L2CAP_CREATE_CHANNEL addr %s, psm 0x%x, local mtu %u", bd_addr_to_str(address), psm, local_mtu);
|
||||
log_info("L2CAP_CREATE_ERTM_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(max_transmit, retransmission_timeout_ms, monitor_timeout_ms, local_mtu, num_tx_buffers, num_rx_buffers, buffer, size);
|
||||
uint8_t result = l2cap_ertm_validate_local_config(ertm_config, buffer, size);
|
||||
if (result) return result;
|
||||
|
||||
l2cap_channel_t * channel = l2cap_create_channel_entry(packet_handler, address, BD_ADDR_TYPE_CLASSIC, psm, local_mtu, LEVEL_0);
|
||||
l2cap_channel_t * channel = l2cap_create_channel_entry(packet_handler, address, BD_ADDR_TYPE_CLASSIC, psm, ertm_config->local_mtu, LEVEL_0);
|
||||
if (!channel) {
|
||||
return BTSTACK_MEMORY_ALLOC_FAILED;
|
||||
}
|
||||
|
||||
// configure ERTM
|
||||
l2cap_ertm_configure_channel(channel, ertm_mandatory, max_transmit, retransmission_timeout_ms,
|
||||
local_mtu, monitor_timeout_ms, num_tx_buffers, num_rx_buffers, buffer, size);
|
||||
l2cap_ertm_configure_channel(channel, ertm_config, buffer, size);
|
||||
|
||||
// add to connections list
|
||||
btstack_linked_list_add(&l2cap_channels, (btstack_linked_item_t *) channel);
|
||||
@ -514,8 +510,7 @@ static void l2cap_ertm_notify_channel_can_send(l2cap_channel_t * channel){
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t l2cap_accept_ertm_connection(uint16_t local_cid, int ertm_mandatory, uint8_t max_transmit, uint16_t retransmission_timeout_ms,
|
||||
uint16_t monitor_timeout_ms, uint16_t local_mtu, uint8_t num_tx_buffers, uint8_t num_rx_buffers, uint8_t * buffer, uint32_t size){
|
||||
uint8_t l2cap_accept_ertm_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);
|
||||
l2cap_channel_t * channel = l2cap_get_channel_for_local_cid(local_cid);
|
||||
@ -525,11 +520,11 @@ uint8_t l2cap_accept_ertm_connection(uint16_t local_cid, int ertm_mandatory, uin
|
||||
}
|
||||
|
||||
// validate local config
|
||||
uint8_t result = l2cap_ertm_validate_local_config(max_transmit, retransmission_timeout_ms, monitor_timeout_ms, local_mtu, num_tx_buffers, num_rx_buffers, buffer, size);
|
||||
uint8_t result = l2cap_ertm_validate_local_config(ertm_config, buffer, size);
|
||||
if (result) return result;
|
||||
|
||||
// configure L2CAP ERTM
|
||||
l2cap_ertm_configure_channel(channel, ertm_mandatory, max_transmit, retransmission_timeout_ms, monitor_timeout_ms, local_mtu, num_tx_buffers, num_rx_buffers, buffer, size);
|
||||
l2cap_ertm_configure_channel(channel, ertm_config, buffer, size);
|
||||
|
||||
// continue
|
||||
channel->state = L2CAP_STATE_WILL_SEND_CONNECTION_RESPONSE_ACCEPT;
|
||||
|
47
src/l2cap.h
47
src/l2cap.h
@ -129,6 +129,29 @@ typedef struct {
|
||||
uint8_t retransmission_requested;
|
||||
} l2cap_ertm_tx_packet_state_t;
|
||||
|
||||
typedef struct {
|
||||
// If not mandatory, the use of ERTM can be decided by the remote
|
||||
uint8_t ertm_mandatory;
|
||||
|
||||
// Number of retransmissions that L2CAP is allowed to try before accepting that a packet and the channel is lost.
|
||||
uint8_t max_transmit;
|
||||
|
||||
// time before retransmission of i-frame / Recommended : 2000 ms (ACL Flush timeout not used)
|
||||
uint16_t retransmission_timeout_ms;
|
||||
|
||||
// time after withc s-frames are sent / Recommended: 12000 ms (ACL Flush timeout not used)
|
||||
uint16_t monitor_timeout_ms;
|
||||
|
||||
// MTU for incoming SDUs
|
||||
uint16_t local_mtu;
|
||||
|
||||
// Number of buffers for outgoing data
|
||||
uint8_t num_tx_buffers;
|
||||
|
||||
// Number of packets that can be received out of order (-> our tx_window size)
|
||||
uint8_t num_rx_buffers;
|
||||
|
||||
} l2cap_ertm_config_t;
|
||||
|
||||
// info regarding an actual connection
|
||||
typedef struct {
|
||||
@ -382,22 +405,14 @@ uint8_t l2cap_create_channel(btstack_packet_handler_t packet_handler, bd_addr_t
|
||||
* @param packet_handler
|
||||
* @param address
|
||||
* @param psm
|
||||
* @param ertm_mandatory If not mandatory, the use of ERTM can be decided by the remote
|
||||
* @param max_transmit Number of retransmissions that L2CAP is allowed to try before accepting that a packet and the channel is lost.
|
||||
* @param retransmission_timeout_ms Recommended : 2000 ms (ACL Flush timeout not used)
|
||||
* @param monitor_timeout_ms Recommended: 12000 ms (ACL Flush timeout not used)
|
||||
* @param local_mtu
|
||||
* @param num_tx_buffers Number of unacknowledged packets stored in buffer
|
||||
* @param num_rx_buffers Number of packets that can be received out of order (-> our tx_window size)
|
||||
* @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,
|
||||
int ertm_mandatory, uint8_t max_transmit, uint16_t retransmission_timeout_ms, uint16_t monitor_timeout_ms,
|
||||
uint16_t local_mtu, uint8_t num_tx_buffers, uint8_t num_rx_buffers, uint8_t * buffer, uint32_t size,
|
||||
uint16_t * out_local_cid);
|
||||
l2cap_ertm_config_t * ertm_contig, uint8_t * buffer, uint32_t size, uint16_t * out_local_cid);
|
||||
|
||||
/**
|
||||
* @brief Disconnects L2CAP channel with given identifier.
|
||||
@ -431,19 +446,13 @@ void l2cap_accept_connection(uint16_t local_cid);
|
||||
|
||||
/**
|
||||
* @brief Accepts incoming L2CAP connection for Enhanced Retransmission Mode
|
||||
* @param ertm_mandatory If not mandatory, the use of ERTM can be decided by the remote
|
||||
* @param max_transmit Number of retransmissions that L2CAP is allowed to try before accepting that a packet and the channel is lost. Recommended: 1
|
||||
* @param retransmission_timeout_ms Recommended : 2000 ms (ACL Flush timeout not used)
|
||||
* @param monitor_timeout_ms Recommended: 12000 ms (ACL Flush timeout not used)
|
||||
* @param local_mtu
|
||||
* @param num_tx_buffers Number of unacknowledged packets stored in buffer
|
||||
* @param num_rx_buffers Number of packets that can be received out of order (-> our tx_window size)
|
||||
* @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, int ertm_mandatory, uint8_t max_transmit,
|
||||
uint16_t retransmission_timeout_ms, uint16_t monitor_timeout_ms, uint16_t local_mtu, uint8_t num_tx_buffers, uint8_t num_rx_buffers, uint8_t * buffer, uint32_t size);
|
||||
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.
|
||||
|
@ -68,12 +68,18 @@ static bd_addr_t remote = {0x00, 0x1B, 0xDC, 0x07, 0x32, 0xef};;
|
||||
static uint16_t handle;
|
||||
static uint16_t local_cid;
|
||||
static int l2cap_ertm;
|
||||
static int l2cap_ertm_mandatory;
|
||||
static int l2cap_max_transmit = 2; // some tests require > 1
|
||||
static int l2cap_local_mtu = 144;
|
||||
|
||||
static btstack_packet_callback_registration_t hci_event_callback_registration;
|
||||
static uint8_t ertm_buffer[10000];
|
||||
static l2cap_ertm_config_t ertm_config = {
|
||||
0, // ertm mandatory
|
||||
2, // max transmit, some tests require > 1
|
||||
2000,
|
||||
12000,
|
||||
144, // l2cap ertm mtu
|
||||
4,
|
||||
4,
|
||||
};
|
||||
|
||||
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
|
||||
|
||||
@ -115,7 +121,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, l2cap_ertm_mandatory, l2cap_max_transmit, 2000, 12000, l2cap_local_mtu, 4, 4, ertm_buffer, sizeof(ertm_buffer));
|
||||
l2cap_accept_ertm_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);
|
||||
@ -139,7 +145,7 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
||||
|
||||
static void show_usage(void){
|
||||
printf("\n--- CLI for L2CAP TEST ---\n");
|
||||
printf("L2CAP Channel Mode %s\n", l2cap_ertm ? "Enahnced Retransmission" : "Basic");
|
||||
printf("L2CAP Channel Mode %s\n", l2cap_ertm ? "Enhanced Retransmission" : "Basic");
|
||||
printf("c - create connection to SDP at addr %s\n", bd_addr_to_str(remote));
|
||||
printf("s - send some data\n");
|
||||
printf("S - send more data\n");
|
||||
@ -159,7 +165,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_PROTOCOL_SDP, l2cap_ertm_mandatory, l2cap_max_transmit, 2000, 12000, l2cap_local_mtu, 4, 4, ertm_buffer, sizeof(ertm_buffer), &local_cid);
|
||||
l2cap_create_ertm_channel(packet_handler, remote, BLUETOOTH_PROTOCOL_SDP, &ertm_config, ertm_buffer, sizeof(ertm_buffer), &local_cid);
|
||||
} else {
|
||||
l2cap_create_channel(packet_handler, remote, BLUETOOTH_PROTOCOL_SDP, 100, &local_cid);
|
||||
}
|
||||
@ -187,12 +193,12 @@ static void stdin_process(char buffer){
|
||||
case 'e':
|
||||
printf("L2CAP Enhanced Retransmission Mode (ERTM) optional\n");
|
||||
l2cap_ertm = 1;
|
||||
l2cap_ertm_mandatory = 0;
|
||||
ertm_config.ertm_mandatory = 0;
|
||||
break;
|
||||
case 'E':
|
||||
printf("L2CAP Enhanced Retransmission Mode (ERTM) mandatory\n");
|
||||
l2cap_ertm = 1;
|
||||
l2cap_ertm_mandatory = 1;
|
||||
ertm_config.ertm_mandatory = 1;
|
||||
break;
|
||||
case 'p':
|
||||
printf("Send L2CAP ECHO Request\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user