tests: bluetooth: tester: Add support for L2CAP channel reconfiguration
This allows UT to reconfigure MTU of a channel and get notfied when channel configuration changed. Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
This commit is contained in:
parent
c589994dc0
commit
ab6c090d74
2 changed files with 93 additions and 2 deletions
|
@ -787,6 +787,15 @@ struct l2cap_accept_connection_cmd {
|
||||||
uint16_t result;
|
uint16_t result;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
#define L2CAP_RECONFIGURE 0x07
|
||||||
|
struct l2cap_reconfigure_cmd {
|
||||||
|
uint8_t address_type;
|
||||||
|
uint8_t address[6];
|
||||||
|
uint16_t mtu;
|
||||||
|
uint8_t num;
|
||||||
|
uint8_t chan_id[];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
#define L2CAP_CREDITS 0x08
|
#define L2CAP_CREDITS 0x08
|
||||||
struct l2cap_credits_cmd {
|
struct l2cap_credits_cmd {
|
||||||
uint8_t chan_id;
|
uint8_t chan_id;
|
||||||
|
@ -836,6 +845,15 @@ struct l2cap_data_received_ev {
|
||||||
uint8_t data[];
|
uint8_t data[];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
#define L2CAP_EV_RECONFIGURED 0x84
|
||||||
|
struct l2cap_reconfigured_ev {
|
||||||
|
uint8_t chan_id;
|
||||||
|
uint16_t mtu_remote;
|
||||||
|
uint16_t mps_remote;
|
||||||
|
uint16_t mtu_local;
|
||||||
|
uint16_t mps_local;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
/* MESH Service */
|
/* MESH Service */
|
||||||
/* commands */
|
/* commands */
|
||||||
#define MESH_READ_SUPPORTED_COMMANDS 0x01
|
#define MESH_READ_SUPPORTED_COMMANDS 0x01
|
||||||
|
|
|
@ -20,6 +20,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
||||||
#include "bttester.h"
|
#include "bttester.h"
|
||||||
|
|
||||||
#define CONTROLLER_INDEX 0
|
#define CONTROLLER_INDEX 0
|
||||||
|
#define DATA_MTU_INITIAL 128
|
||||||
#define DATA_MTU 256
|
#define DATA_MTU 256
|
||||||
#define DATA_BUF_SIZE BT_L2CAP_SDU_BUF_SIZE(DATA_MTU)
|
#define DATA_BUF_SIZE BT_L2CAP_SDU_BUF_SIZE(DATA_MTU)
|
||||||
#define CHANNELS 2
|
#define CHANNELS 2
|
||||||
|
@ -135,11 +136,29 @@ static void disconnected_cb(struct bt_l2cap_chan *l2cap_chan)
|
||||||
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
|
CONTROLLER_INDEX, (uint8_t *) &ev, sizeof(ev));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reconfigured_cb(struct bt_l2cap_chan *l2cap_chan)
|
||||||
|
{
|
||||||
|
struct l2cap_reconfigured_ev ev;
|
||||||
|
struct channel *chan = CONTAINER_OF(l2cap_chan, struct channel, le);
|
||||||
|
|
||||||
|
(void)memset(&ev, 0, sizeof(struct l2cap_disconnected_ev));
|
||||||
|
|
||||||
|
ev.chan_id = chan->chan_id;
|
||||||
|
ev.mtu_remote = sys_cpu_to_le16(chan->le.tx.mtu);
|
||||||
|
ev.mps_remote = sys_cpu_to_le16(chan->le.tx.mps);
|
||||||
|
ev.mtu_local = sys_cpu_to_le16(chan->le.rx.mtu);
|
||||||
|
ev.mps_local = sys_cpu_to_le16(chan->le.rx.mps);
|
||||||
|
|
||||||
|
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_RECONFIGURED,
|
||||||
|
CONTROLLER_INDEX, (uint8_t *)&ev, sizeof(ev));
|
||||||
|
}
|
||||||
|
|
||||||
static const struct bt_l2cap_chan_ops l2cap_ops = {
|
static const struct bt_l2cap_chan_ops l2cap_ops = {
|
||||||
.alloc_buf = alloc_buf_cb,
|
.alloc_buf = alloc_buf_cb,
|
||||||
.recv = recv_cb,
|
.recv = recv_cb,
|
||||||
.connected = connected_cb,
|
.connected = connected_cb,
|
||||||
.disconnected = disconnected_cb,
|
.disconnected = disconnected_cb,
|
||||||
|
.reconfigured = reconfigured_cb,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct channel *get_free_channel()
|
static struct channel *get_free_channel()
|
||||||
|
@ -178,7 +197,7 @@ static void connect(uint8_t *data, uint16_t len)
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (cmd->num > CHANNELS || mtu > DATA_MTU) {
|
if (cmd->num > CHANNELS || mtu > DATA_MTU_INITIAL) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,6 +274,56 @@ rsp:
|
||||||
status);
|
status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reconfigure(uint8_t *data, uint16_t len)
|
||||||
|
{
|
||||||
|
const struct l2cap_reconfigure_cmd *cmd = (void *)data;
|
||||||
|
uint16_t mtu = sys_le16_to_cpu(cmd->mtu);
|
||||||
|
struct bt_conn *conn;
|
||||||
|
uint8_t status;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
struct bt_l2cap_chan *reconf_channels[CHANNELS + 1] = {};
|
||||||
|
|
||||||
|
/* address is first in data */
|
||||||
|
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, (bt_addr_le_t *)cmd);
|
||||||
|
if (!conn) {
|
||||||
|
LOG_ERR("Unknown connection");
|
||||||
|
status = BTP_STATUS_FAILED;
|
||||||
|
goto rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->num > CHANNELS) {
|
||||||
|
status = BTP_STATUS_FAILED;
|
||||||
|
goto rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtu > DATA_MTU) {
|
||||||
|
status = BTP_STATUS_FAILED;
|
||||||
|
goto rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < cmd->num; i++) {
|
||||||
|
if (cmd->chan_id[i] > CHANNELS) {
|
||||||
|
status = BTP_STATUS_FAILED;
|
||||||
|
goto rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
reconf_channels[i] = &channels[cmd->chan_id[i]].le.chan;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_l2cap_ecred_chan_reconfigure(reconf_channels, mtu);
|
||||||
|
if (err) {
|
||||||
|
status = BTP_STATUS_FAILED;
|
||||||
|
goto rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = BTP_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
rsp:
|
||||||
|
tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_RECONFIGURE, CONTROLLER_INDEX,
|
||||||
|
status);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_BT_EATT)
|
#if defined(CONFIG_BT_EATT)
|
||||||
void disconnect_eatt_chans(uint8_t *data, uint16_t len)
|
void disconnect_eatt_chans(uint8_t *data, uint16_t len)
|
||||||
{
|
{
|
||||||
|
@ -372,7 +441,7 @@ static int accept(struct bt_conn *conn, struct bt_l2cap_chan **l2cap_chan)
|
||||||
}
|
}
|
||||||
|
|
||||||
chan->le.chan.ops = &l2cap_ops;
|
chan->le.chan.ops = &l2cap_ops;
|
||||||
chan->le.rx.mtu = DATA_MTU;
|
chan->le.rx.mtu = DATA_MTU_INITIAL;
|
||||||
|
|
||||||
*l2cap_chan = &chan->le.chan;
|
*l2cap_chan = &chan->le.chan;
|
||||||
|
|
||||||
|
@ -460,6 +529,7 @@ static void supported_commands(uint8_t *data, uint16_t len)
|
||||||
tester_set_bit(cmds, L2CAP_DISCONNECT);
|
tester_set_bit(cmds, L2CAP_DISCONNECT);
|
||||||
tester_set_bit(cmds, L2CAP_LISTEN);
|
tester_set_bit(cmds, L2CAP_LISTEN);
|
||||||
tester_set_bit(cmds, L2CAP_SEND_DATA);
|
tester_set_bit(cmds, L2CAP_SEND_DATA);
|
||||||
|
tester_set_bit(cmds, L2CAP_RECONFIGURE);
|
||||||
tester_set_bit(cmds, L2CAP_CREDITS);
|
tester_set_bit(cmds, L2CAP_CREDITS);
|
||||||
#if defined(CONFIG_BT_EATT)
|
#if defined(CONFIG_BT_EATT)
|
||||||
tester_set_bit(cmds, L2CAP_DISCONNECT_EATT_CHANS);
|
tester_set_bit(cmds, L2CAP_DISCONNECT_EATT_CHANS);
|
||||||
|
@ -487,6 +557,9 @@ void tester_handle_l2cap(uint8_t opcode, uint8_t index, uint8_t *data,
|
||||||
case L2CAP_LISTEN:
|
case L2CAP_LISTEN:
|
||||||
listen(data, len);
|
listen(data, len);
|
||||||
return;
|
return;
|
||||||
|
case L2CAP_RECONFIGURE:
|
||||||
|
reconfigure(data, len);
|
||||||
|
return;
|
||||||
case L2CAP_CREDITS:
|
case L2CAP_CREDITS:
|
||||||
credits(data, len);
|
credits(data, len);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue