serial: bluetooth: Maximize notification payload size based on ATT MTU
By keeping track of run-time ATT MTU of all connected peers, it's possible to increase the notification payload size; thus increasing data-throughput sent over Bluetooth. Note that this assumes the Bluetooth connection is properly configured (with the corresponding connection parameters) to optimize performance. This is application-specific and shall be examined on each scenario for optimal performance. Signed-off-by: Luis Ubieda <luisf@croxel.com>
This commit is contained in:
parent
aa9446ca6b
commit
53f547b737
1 changed files with 39 additions and 5 deletions
|
|
@ -18,6 +18,8 @@ LOG_MODULE_REGISTER(uart_nus, CONFIG_UART_LOG_LEVEL);
|
|||
K_THREAD_STACK_DEFINE(nus_work_queue_stack, CONFIG_UART_BT_WORKQUEUE_STACK_SIZE);
|
||||
static struct k_work_q nus_work_queue;
|
||||
|
||||
#define UART_BT_MTU_INVALID 0xFFFF
|
||||
|
||||
struct uart_bt_data {
|
||||
struct {
|
||||
struct bt_nus_inst *inst;
|
||||
|
|
@ -78,6 +80,38 @@ static void bt_received(struct bt_conn *conn, const void *data, uint16_t len, vo
|
|||
k_work_submit_to_queue(&nus_work_queue, &dev_data->uart.cb_work);
|
||||
}
|
||||
|
||||
static void foreach_conn_handler_get_att_mtu(struct bt_conn *conn, void *data)
|
||||
{
|
||||
uint16_t *min_att_mtu = (uint16_t *)data;
|
||||
uint16_t conn_att_mtu = 0;
|
||||
struct bt_conn_info conn_info;
|
||||
int err;
|
||||
|
||||
err = bt_conn_get_info(conn, &conn_info);
|
||||
if (!err && conn_info.state == BT_CONN_STATE_CONNECTED) {
|
||||
conn_att_mtu = bt_gatt_get_uatt_mtu(conn);
|
||||
|
||||
if (conn_att_mtu > 0) {
|
||||
*min_att_mtu = MIN(*min_att_mtu, conn_att_mtu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint16_t get_max_chunk_size(void)
|
||||
{
|
||||
uint16_t min_att_mtu = UART_BT_MTU_INVALID;
|
||||
|
||||
bt_conn_foreach(BT_CONN_TYPE_LE, foreach_conn_handler_get_att_mtu, &min_att_mtu);
|
||||
|
||||
if (min_att_mtu == UART_BT_MTU_INVALID) {
|
||||
/** Default ATT MTU */
|
||||
min_att_mtu = 23;
|
||||
}
|
||||
|
||||
/** ATT NTF Payload overhead: opcode (1 octet) + attribute (2 octets) */
|
||||
return (min_att_mtu - 1 - 2);
|
||||
}
|
||||
|
||||
static void cb_work_handler(struct k_work *work)
|
||||
{
|
||||
struct uart_bt_data *dev_data = CONTAINER_OF(work, struct uart_bt_data, uart.cb_work);
|
||||
|
|
@ -99,13 +133,13 @@ static void tx_work_handler(struct k_work *work)
|
|||
|
||||
__ASSERT_NO_MSG(dev_data);
|
||||
|
||||
uint16_t chunk_size = get_max_chunk_size();
|
||||
do {
|
||||
/** Using Minimum MTU at this point to guarantee all connected
|
||||
* peers will receive the data, without keeping track of MTU
|
||||
* size per-connection. This has the trade-off of limiting
|
||||
* throughput but allows multi-connection support.
|
||||
/** The chunk size is based on the smallest MTU among all
|
||||
* peers, and the same chunk is sent to everyone. This avoids
|
||||
* managing separate read pointers: one per connection.
|
||||
*/
|
||||
len = ring_buf_get_claim(dev_data->uart.tx_ringbuf, &data, 20);
|
||||
len = ring_buf_get_claim(dev_data->uart.tx_ringbuf, &data, chunk_size);
|
||||
if (len > 0) {
|
||||
err = bt_nus_inst_send(NULL, dev_data->bt.inst, data, len);
|
||||
if (err) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue