Skip to content

Commit 6cfc6fa

Browse files
sjanccfriedt
authored andcommitted
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 <[email protected]>
1 parent 6020afe commit 6cfc6fa

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

tests/bluetooth/tester/src/bttester.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,11 @@ struct l2cap_accept_connection_cmd {
787787
uint16_t result;
788788
} __packed;
789789

790+
#define L2CAP_CREDITS 0x08
791+
struct l2cap_credits_cmd {
792+
uint8_t chan_id;
793+
} __packed;
794+
790795
#define L2CAP_DISCONNECT_EATT_CHANS 0x09
791796
struct l2cap_disconnect_eatt_chans_cmd {
792797
uint8_t address_type;

tests/bluetooth/tester/src/l2cap.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ static struct channel {
3434
uint8_t chan_id; /* Internal number that identifies L2CAP channel. */
3535
struct bt_l2cap_le_chan le;
3636
bool in_use;
37+
struct net_buf *pending_credit;
3738
} channels[CHANNELS];
3839

3940
/* TODO Extend to support multiple servers */
@@ -58,6 +59,14 @@ static int recv_cb(struct bt_l2cap_chan *l2cap_chan, struct net_buf *buf)
5859
tester_send(BTP_SERVICE_ID_L2CAP, L2CAP_EV_DATA_RECEIVED,
5960
CONTROLLER_INDEX, recv_cb_buf, sizeof(*ev) + buf->len);
6061

62+
if (!chan->pending_credit) {
63+
/* no need for extra ref, as when returning EINPROGRESS user
64+
* becomes owner of the netbuf
65+
*/
66+
chan->pending_credit = buf;
67+
return -EINPROGRESS;
68+
}
69+
6170
return 0;
6271
}
6372

@@ -97,6 +106,12 @@ static void disconnected_cb(struct bt_l2cap_chan *l2cap_chan)
97106
struct channel *chan = CONTAINER_OF(l2cap_chan, struct channel, le);
98107
struct bt_conn_info info;
99108

109+
/* release netbuf on premature disconnection */
110+
if (chan->pending_credit) {
111+
net_buf_unref(chan->pending_credit);
112+
chan->pending_credit = NULL;
113+
}
114+
100115
(void)memset(&ev, 0, sizeof(struct l2cap_disconnected_ev));
101116

102117
/* TODO: ev.result */
@@ -138,6 +153,8 @@ static struct channel *get_free_channel()
138153
}
139154

140155
chan = &channels[i];
156+
157+
(void)memset(chan, 0, sizeof(*chan));
141158
chan->chan_id = i;
142159

143160
channels[i].in_use = true;
@@ -404,6 +421,33 @@ static void listen(uint8_t *data, uint16_t len)
404421
BTP_STATUS_FAILED);
405422
}
406423

424+
static void credits(uint8_t *data, uint16_t len)
425+
{
426+
const struct l2cap_credits_cmd *cmd = (void *)data;
427+
struct channel *chan = &channels[cmd->chan_id];
428+
429+
if (!chan->in_use) {
430+
goto fail;
431+
}
432+
433+
if (chan->pending_credit) {
434+
if (bt_l2cap_chan_recv_complete(&chan->le.chan,
435+
chan->pending_credit) < 0) {
436+
goto fail;
437+
}
438+
439+
chan->pending_credit = NULL;
440+
}
441+
442+
tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_CREDITS, CONTROLLER_INDEX,
443+
BTP_STATUS_SUCCESS);
444+
return;
445+
446+
fail:
447+
tester_rsp(BTP_SERVICE_ID_L2CAP, L2CAP_CREDITS, CONTROLLER_INDEX,
448+
BTP_STATUS_FAILED);
449+
}
450+
407451
static void supported_commands(uint8_t *data, uint16_t len)
408452
{
409453
uint8_t cmds[2];
@@ -416,6 +460,7 @@ static void supported_commands(uint8_t *data, uint16_t len)
416460
tester_set_bit(cmds, L2CAP_DISCONNECT);
417461
tester_set_bit(cmds, L2CAP_LISTEN);
418462
tester_set_bit(cmds, L2CAP_SEND_DATA);
463+
tester_set_bit(cmds, L2CAP_CREDITS);
419464
#if defined(CONFIG_BT_EATT)
420465
tester_set_bit(cmds, L2CAP_DISCONNECT_EATT_CHANS);
421466
#endif
@@ -442,6 +487,9 @@ void tester_handle_l2cap(uint8_t opcode, uint8_t index, uint8_t *data,
442487
case L2CAP_LISTEN:
443488
listen(data, len);
444489
return;
490+
case L2CAP_CREDITS:
491+
credits(data, len);
492+
return;
445493
#if defined(CONFIG_BT_EATT)
446494
case L2CAP_DISCONNECT_EATT_CHANS:
447495
disconnect_eatt_chans(data, len);

0 commit comments

Comments
 (0)