Bluetooth/tester: connect L2CAP using Enhanced Credit Flow Control
This change adds field to L2CAP connect command allowing to choose ECFC in L2CAP connect() function and adds required logic to perform such connection. Signed-off-by: Krzysztof Kopyściński <krzysztof.kopyscinski@codecoup.pl>
This commit is contained in:
parent
4d85426688
commit
97f992c470
1 changed files with 46 additions and 20 deletions
|
@ -29,6 +29,7 @@ NET_BUF_POOL_FIXED_DEFINE(data_pool, CHANNELS, DATA_BUF_SIZE, NULL);
|
|||
static struct channel {
|
||||
uint8_t chan_id; /* Internal number that identifies L2CAP channel. */
|
||||
struct bt_l2cap_le_chan le;
|
||||
bool in_use;
|
||||
} channels[CHANNELS];
|
||||
|
||||
/* TODO Extend to support multiple servers */
|
||||
|
@ -128,30 +129,35 @@ static struct channel *get_free_channel()
|
|||
struct channel *chan;
|
||||
|
||||
for (i = 0U; i < CHANNELS; i++) {
|
||||
if (channels[i].le.chan.state != BT_L2CAP_DISCONNECTED) {
|
||||
if (channels[i].in_use) {
|
||||
continue;
|
||||
}
|
||||
|
||||
chan = &channels[i];
|
||||
chan->chan_id = i;
|
||||
|
||||
channels[i].in_use = true;
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void connect(uint8_t *data, uint16_t len)
|
||||
{
|
||||
const struct l2cap_connect_cmd *cmd = (void *) data;
|
||||
struct l2cap_connect_rp *rp;
|
||||
struct bt_conn *conn;
|
||||
struct channel *chan;
|
||||
struct channel *chan = NULL;
|
||||
struct bt_l2cap_chan *allocated_channels[5] = {};
|
||||
uint16_t mtu = sys_le16_to_cpu(cmd->mtu);
|
||||
uint8_t buf[sizeof(*rp) + 1];
|
||||
uint8_t buf[sizeof(*rp) + CHANNELS];
|
||||
uint8_t i = 0;
|
||||
int err;
|
||||
|
||||
if (cmd->num > 1 || mtu > DATA_MTU) {
|
||||
if (cmd->num > CHANNELS || mtu > DATA_MTU) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -160,29 +166,49 @@ static void connect(uint8_t *data, uint16_t len)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
chan = get_free_channel();
|
||||
if (!chan) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
chan->le.chan.ops = &l2cap_ops;
|
||||
chan->le.rx.mtu = mtu;
|
||||
|
||||
err = bt_l2cap_chan_connect(conn, &chan->le.chan, cmd->psm);
|
||||
if (err < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rp = (void *)buf;
|
||||
rp->num = 1U;
|
||||
rp->chan_id[0] = chan->chan_id;
|
||||
|
||||
for (i = 0U; i < cmd->num; i++) {
|
||||
chan = get_free_channel();
|
||||
if (!chan) {
|
||||
goto fail;
|
||||
}
|
||||
chan->le.chan.ops = &l2cap_ops;
|
||||
chan->le.rx.mtu = mtu;
|
||||
rp->chan_id[i] = chan->chan_id;
|
||||
allocated_channels[i] = &chan->le.chan;
|
||||
}
|
||||
|
||||
if (cmd->num == 1) {
|
||||
err = bt_l2cap_chan_connect(conn, &chan->le.chan, cmd->psm);
|
||||
if (err < 0) {
|
||||
goto fail;
|
||||
}
|
||||
} else if (cmd->num > 1) {
|
||||
#if defined(CONFIG_BT_L2CAP_ECRED)
|
||||
err = bt_l2cap_ecred_chan_connect(conn, allocated_channels,
|
||||
cmd->psm);
|
||||
if (err < 0) {
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
LOG_ERR("Invalid 'num' parameter value");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rp->num = cmd->num;
|
||||
|
||||
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_CONNECT, CONTROLLER_INDEX,
|
||||
(uint8_t *)rp, sizeof(buf));
|
||||
(uint8_t *)rp, sizeof(*rp) + rp->num);
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
while (i >= 0) {
|
||||
channels[i].in_use = false;
|
||||
i--;
|
||||
}
|
||||
tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_CONNECT, CONTROLLER_INDEX,
|
||||
BTP_STATUS_FAILED);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue