Bluetooth: Tester: Use BT_L2CAP_SEG_RECV for L2CAP tests

This API gives better control on L2CAP COC credits and suits better
for Upper Tester implementation.

Co-authored-by: Szymon Janc <szymon.janc@codecoup.pl>
Signed-off-by: Aleksander Wasaznik <aleksander.wasaznik@nordicsemi.no>
This commit is contained in:
Aleksander Wasaznik 2024-11-12 16:04:41 +01:00 committed by Benjamin Cabé
commit 5a8daffc32
7 changed files with 276 additions and 35 deletions

View file

@ -16,6 +16,8 @@ CONFIG_BT_BONDABLE=y
CONFIG_BT_ATT_PREPARE_COUNT=12
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y
CONFIG_BT_L2CAP_SEG_RECV=y
CONFIG_BT_L2CAP_RECONFIGURE_EXPLICIT=y
CONFIG_BT_DEVICE_NAME="Tester"
CONFIG_BT_DEVICE_NAME_MAX=32
CONFIG_BT_DEVICE_NAME_DYNAMIC=y
@ -35,7 +37,6 @@ CONFIG_BT_GATT_DYNAMIC_DB=y
CONFIG_BT_EXT_ADV=y
CONFIG_BT_PER_ADV=y
CONFIG_BT_PER_ADV_SYNC=y
CONFIG_BT_BUF_ACL_RX_SIZE=100
CONFIG_BT_RX_STACK_SIZE=4096
CONFIG_BT_TESTING=y

View file

@ -19,14 +19,15 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
#include "btp/btp.h"
#define DATA_MTU_INITIAL 128
#define DATA_MTU 256
#define DATA_BUF_SIZE BT_L2CAP_SDU_BUF_SIZE(DATA_MTU)
#define L2CAP_MPS 96
#define DATA_MTU (3 * L2CAP_MPS)
#define DATA_MTU_INITIAL (2 * L2CAP_MPS)
#define CHANNELS 2
#define SERVERS 1
NET_BUF_POOL_FIXED_DEFINE(data_pool, CHANNELS, DATA_BUF_SIZE, CONFIG_BT_CONN_TX_USER_DATA_SIZE,
NULL);
NET_BUF_POOL_FIXED_DEFINE(data_pool, CHANNELS, BT_L2CAP_SDU_BUF_SIZE(DATA_MTU),
CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
static bool authorize_flag;
static uint8_t req_keysize;
@ -36,18 +37,51 @@ static struct channel {
struct bt_l2cap_le_chan le;
bool in_use;
bool hold_credit;
#if defined(CONFIG_BT_L2CAP_SEG_RECV)
unsigned int pending_credits;
uint8_t recv_cb_buf[DATA_MTU + sizeof(struct btp_l2cap_data_received_ev)];
#else
struct net_buf *pending_credit;
#endif
} channels[CHANNELS];
/* TODO Extend to support multiple servers */
static struct bt_l2cap_server servers[SERVERS];
#if defined(CONFIG_BT_L2CAP_SEG_RECV)
static void seg_recv_cb(struct bt_l2cap_chan *l2cap_chan, size_t sdu_len, off_t seg_offset,
struct net_buf_simple *seg)
{
struct btp_l2cap_data_received_ev *ev;
struct bt_l2cap_le_chan *l2cap_le_chan =
CONTAINER_OF(l2cap_chan, struct bt_l2cap_le_chan, chan);
struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
ev = (void *)chan->recv_cb_buf;
memcpy(&ev->data[seg_offset], seg->data, seg->len);
/* complete SDU received */
if (seg_offset + seg->len == sdu_len) {
ev->chan_id = chan->chan_id;
ev->data_length = sys_cpu_to_le16(sdu_len);
tester_event(BTP_SERVICE_ID_L2CAP, BTP_L2CAP_EV_DATA_RECEIVED, chan->recv_cb_buf,
sizeof(*ev) + sdu_len);
}
if (chan->hold_credit) {
chan->pending_credits++;
} else {
bt_l2cap_chan_give_credits(l2cap_chan, 1);
}
}
#else
static struct net_buf *alloc_buf_cb(struct bt_l2cap_chan *chan)
{
return net_buf_alloc(&data_pool, K_FOREVER);
}
static uint8_t recv_cb_buf[DATA_BUF_SIZE + sizeof(struct btp_l2cap_data_received_ev)];
static uint8_t recv_cb_buf[DATA_MTU + sizeof(struct btp_l2cap_data_received_ev)];
static int recv_cb(struct bt_l2cap_chan *l2cap_chan, struct net_buf *buf)
{
@ -73,6 +107,7 @@ static int recv_cb(struct bt_l2cap_chan *l2cap_chan, struct net_buf *buf)
return 0;
}
#endif
static void connected_cb(struct bt_l2cap_chan *l2cap_chan)
{
@ -111,11 +146,13 @@ static void disconnected_cb(struct bt_l2cap_chan *l2cap_chan)
struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
struct bt_conn_info info;
#if !defined(CONFIG_BT_L2CAP_SEG_RECV)
/* release netbuf on premature disconnection */
if (chan->pending_credit) {
net_buf_unref(chan->pending_credit);
chan->pending_credit = NULL;
}
#endif
(void)memset(&ev, 0, sizeof(struct btp_l2cap_disconnected_ev));
@ -160,12 +197,16 @@ static void reconfigured_cb(struct bt_l2cap_chan *l2cap_chan)
#endif
static const struct bt_l2cap_chan_ops l2cap_ops = {
.alloc_buf = alloc_buf_cb,
.recv = recv_cb,
.connected = connected_cb,
.disconnected = disconnected_cb,
#if defined(CONFIG_BT_L2CAP_SEG_RECV)
.seg_recv = seg_recv_cb,
#else
.alloc_buf = alloc_buf_cb,
.recv = recv_cb,
#endif
.connected = connected_cb,
.disconnected = disconnected_cb,
#if defined(CONFIG_BT_L2CAP_ECRED)
.reconfigured = reconfigured_cb,
.reconfigured = reconfigured_cb,
#endif
};
@ -222,10 +263,15 @@ static uint8_t connect(const void *cmd, uint16_t cmd_len,
}
chan->le.chan.ops = &l2cap_ops;
chan->le.rx.mtu = mtu;
#if defined(CONFIG_BT_L2CAP_SEG_RECV)
chan->le.rx.mps = L2CAP_MPS;
#endif
rp->chan_id[i] = chan->chan_id;
allocated_channels[i] = &chan->le.chan;
chan->hold_credit = cp->options & BTP_L2CAP_CONNECT_OPT_HOLD_CREDIT;
bt_l2cap_chan_give_credits(&chan->le.chan, 1);
}
if (cp->num == 1 && !ecfc) {
@ -289,6 +335,7 @@ static uint8_t reconfigure(const void *cmd, uint16_t cmd_len,
{
const struct btp_l2cap_reconfigure_cmd *cp = cmd;
uint16_t mtu;
uint16_t mps;
struct bt_conn *conn;
int err;
struct bt_l2cap_chan *reconf_channels[CHANNELS + 1] = {};
@ -321,7 +368,8 @@ static uint8_t reconfigure(const void *cmd, uint16_t cmd_len,
return BTP_STATUS_FAILED;
}
err = bt_l2cap_ecred_chan_reconfigure(reconf_channels, mtu);
mps = MIN(L2CAP_MPS, BT_L2CAP_RX_MTU);
err = bt_l2cap_ecred_chan_reconfigure_explicit(reconf_channels, cp->num, mtu, mps);
if (err) {
bt_conn_unref(conn);
return BTP_STATUS_FAILED;
@ -454,9 +502,14 @@ static int accept(struct bt_conn *conn, struct bt_l2cap_server *server,
chan->le.chan.ops = &l2cap_ops;
chan->le.rx.mtu = DATA_MTU_INITIAL;
#if defined(CONFIG_BT_L2CAP_SEG_RECV)
chan->le.rx.mps = L2CAP_MPS;
#endif
*l2cap_chan = &chan->le.chan;
bt_l2cap_chan_give_credits(&chan->le.chan, 1);
return 0;
}
@ -524,7 +577,15 @@ static uint8_t credits(const void *cmd, uint16_t cmd_len,
if (!chan->in_use) {
return BTP_STATUS_FAILED;
}
#if defined(CONFIG_BT_L2CAP_SEG_RECV)
if (chan->pending_credits) {
if (bt_l2cap_chan_give_credits(&chan->le.chan, chan->pending_credits) < 0) {
return BTP_STATUS_FAILED;
}
chan->pending_credits = 0;
}
#else
if (chan->pending_credit) {
if (bt_l2cap_chan_recv_complete(&chan->le.chan,
chan->pending_credit) < 0) {
@ -533,6 +594,7 @@ static uint8_t credits(const void *cmd, uint16_t cmd_len,
chan->pending_credit = NULL;
}
#endif
return BTP_STATUS_SUCCESS;
}