tests: bluetooth: tester: Add support for L2CAP Credits command
This allows IUT to return credits on specified L2CAP channel when requested by Upper Tester. Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl>
This commit is contained in:
parent
6020afe46a
commit
6cfc6fa8e1
2 changed files with 53 additions and 0 deletions
|
@ -787,6 +787,11 @@ struct l2cap_accept_connection_cmd {
|
||||||
uint16_t result;
|
uint16_t result;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
#define L2CAP_CREDITS 0x08
|
||||||
|
struct l2cap_credits_cmd {
|
||||||
|
uint8_t chan_id;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
#define L2CAP_DISCONNECT_EATT_CHANS 0x09
|
#define L2CAP_DISCONNECT_EATT_CHANS 0x09
|
||||||
struct l2cap_disconnect_eatt_chans_cmd {
|
struct l2cap_disconnect_eatt_chans_cmd {
|
||||||
uint8_t address_type;
|
uint8_t address_type;
|
||||||
|
|
|
@ -34,6 +34,7 @@ static struct channel {
|
||||||
uint8_t chan_id; /* Internal number that identifies L2CAP channel. */
|
uint8_t chan_id; /* Internal number that identifies L2CAP channel. */
|
||||||
struct bt_l2cap_le_chan le;
|
struct bt_l2cap_le_chan le;
|
||||||
bool in_use;
|
bool in_use;
|
||||||
|
struct net_buf *pending_credit;
|
||||||
} channels[CHANNELS];
|
} channels[CHANNELS];
|
||||||
|
|
||||||
/* TODO Extend to support multiple servers */
|
/* TODO Extend to support multiple servers */
|
||||||
|
@ -58,6 +59,14 @@ static int recv_cb(struct bt_l2cap_chan *l2cap_chan, struct net_buf *buf)
|
||||||
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DATA_RECEIVED,
|
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DATA_RECEIVED,
|
||||||
CONTROLLER_INDEX, recv_cb_buf, sizeof(*ev) + buf->len);
|
CONTROLLER_INDEX, recv_cb_buf, sizeof(*ev) + buf->len);
|
||||||
|
|
||||||
|
if (!chan->pending_credit) {
|
||||||
|
/* no need for extra ref, as when returning EINPROGRESS user
|
||||||
|
* becomes owner of the netbuf
|
||||||
|
*/
|
||||||
|
chan->pending_credit = buf;
|
||||||
|
return -EINPROGRESS;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +106,12 @@ static void disconnected_cb(struct bt_l2cap_chan *l2cap_chan)
|
||||||
struct channel *chan = CONTAINER_OF(l2cap_chan, struct channel, le);
|
struct channel *chan = CONTAINER_OF(l2cap_chan, struct channel, le);
|
||||||
struct bt_conn_info info;
|
struct bt_conn_info info;
|
||||||
|
|
||||||
|
/* release netbuf on premature disconnection */
|
||||||
|
if (chan->pending_credit) {
|
||||||
|
net_buf_unref(chan->pending_credit);
|
||||||
|
chan->pending_credit = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
(void)memset(&ev, 0, sizeof(struct l2cap_disconnected_ev));
|
(void)memset(&ev, 0, sizeof(struct l2cap_disconnected_ev));
|
||||||
|
|
||||||
/* TODO: ev.result */
|
/* TODO: ev.result */
|
||||||
|
@ -138,6 +153,8 @@ static struct channel *get_free_channel()
|
||||||
}
|
}
|
||||||
|
|
||||||
chan = &channels[i];
|
chan = &channels[i];
|
||||||
|
|
||||||
|
(void)memset(chan, 0, sizeof(*chan));
|
||||||
chan->chan_id = i;
|
chan->chan_id = i;
|
||||||
|
|
||||||
channels[i].in_use = true;
|
channels[i].in_use = true;
|
||||||
|
@ -404,6 +421,33 @@ fail:
|
||||||
BTP_STATUS_FAILED);
|
BTP_STATUS_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void credits(uint8_t *data, uint16_t len)
|
||||||
|
{
|
||||||
|
const struct l2cap_credits_cmd *cmd = (void *)data;
|
||||||
|
struct channel *chan = &channels[cmd->chan_id];
|
||||||
|
|
||||||
|
if (!chan->in_use) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chan->pending_credit) {
|
||||||
|
if (bt_l2cap_chan_recv_complete(&chan->le.chan,
|
||||||
|
chan->pending_credit) < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
chan->pending_credit = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_CREDITS, CONTROLLER_INDEX,
|
||||||
|
BTP_STATUS_SUCCESS);
|
||||||
|
return;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_CREDITS, CONTROLLER_INDEX,
|
||||||
|
BTP_STATUS_FAILED);
|
||||||
|
}
|
||||||
|
|
||||||
static void supported_commands(uint8_t *data, uint16_t len)
|
static void supported_commands(uint8_t *data, uint16_t len)
|
||||||
{
|
{
|
||||||
uint8_t cmds[2];
|
uint8_t cmds[2];
|
||||||
|
@ -416,6 +460,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_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);
|
||||||
#endif
|
#endif
|
||||||
|
@ -442,6 +487,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_CREDITS:
|
||||||
|
credits(data, len);
|
||||||
|
return;
|
||||||
#if defined(CONFIG_BT_EATT)
|
#if defined(CONFIG_BT_EATT)
|
||||||
case L2CAP_DISCONNECT_EATT_CHANS:
|
case L2CAP_DISCONNECT_EATT_CHANS:
|
||||||
disconnect_eatt_chans(data, len);
|
disconnect_eatt_chans(data, len);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue