Skip to content

Commit 4450c9b

Browse files
lylezhu2012kartben
authored andcommitted
Bluetooth: tester: Classic: L2CAP: Support local busy
If the option BTP_L2CAP_CONNECT_V2_OPT_HOLD_CREDIT or BTP_L2CAP_LISTEN_V2_OPT_HOLD_CREDIT is set, set the local flag `hold_credit`. When the data received, holds the buffer and returns the error code `-EINPROGRESS`. The held buffers will be released if the L2CAP channel disconnect callback is triggered. Or only of the held buffers will be released if the L2CAP BTP command `credits` is received. Signed-off-by: Lyle Zhu <[email protected]>
1 parent 1e94933 commit 4450c9b

File tree

1 file changed

+67
-1
lines changed

1 file changed

+67
-1
lines changed

tests/bluetooth/tester/src/btp_l2cap.c

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ static struct br_channel {
6666
uint8_t chan_id; /* Internal number that identifies L2CAP channel. */
6767
struct bt_l2cap_br_chan br;
6868
bool in_use;
69+
bool hold_credit;
70+
struct net_buf *pending_credit[DATA_POOL_COUNT];
6971
} br_channels[CHANNELS];
7072
#endif /* CONFIG_BT_CLASSIC */
7173

@@ -305,6 +307,14 @@ static void br_disconnected_cb(struct bt_l2cap_chan *l2cap_chan)
305307
struct br_channel *chan = CONTAINER_OF(l2cap_br_chan, struct br_channel, br);
306308
struct bt_conn_info info;
307309

310+
/* release netbuf on premature disconnection */
311+
ARRAY_FOR_EACH(chan->pending_credit, i) {
312+
if (chan->pending_credit[i] != NULL) {
313+
net_buf_unref(chan->pending_credit[i]);
314+
chan->pending_credit[i] = NULL;
315+
}
316+
}
317+
308318
(void)memset(&ev, 0, sizeof(struct btp_l2cap_disconnected_ev));
309319

310320
/* TODO: ev.result */
@@ -332,7 +342,7 @@ static void br_disconnected_cb(struct bt_l2cap_chan *l2cap_chan)
332342

333343
static struct net_buf *br_alloc_buf_cb(struct bt_l2cap_chan *chan)
334344
{
335-
return net_buf_alloc(&data_pool, K_FOREVER);
345+
return net_buf_alloc(&data_pool, K_NO_WAIT);
336346
}
337347

338348
static uint8_t br_recv_cb_buf[DATA_MTU + sizeof(struct btp_l2cap_data_received_ev)];
@@ -351,6 +361,11 @@ static int br_recv_cb(struct bt_l2cap_chan *l2cap_chan, struct net_buf *buf)
351361
tester_event(BTP_SERVICE_ID_L2CAP, BTP_L2CAP_EV_DATA_RECEIVED,
352362
br_recv_cb_buf, sizeof(*ev) + buf->len);
353363

364+
if (chan->hold_credit && (net_buf_id(buf) < (int)ARRAY_SIZE(chan->pending_credit))) {
365+
chan->pending_credit[net_buf_id(buf)] = buf;
366+
return -EINPROGRESS;
367+
}
368+
354369
return 0;
355370
}
356371

@@ -448,6 +463,8 @@ static uint8_t br_connect(const struct btp_l2cap_connect_v2_cmd *cp,
448463
} else {
449464
br_chan->br.rx.fcs = BT_L2CAP_BR_FCS_16BIT;
450465
}
466+
467+
br_chan->hold_credit = (cp->options & BTP_L2CAP_CONNECT_V2_OPT_HOLD_CREDIT) != 0;
451468
#endif /* CONFIG_BT_L2CAP_RET_FC */
452469

453470
err = bt_l2cap_chan_connect(conn, &br_chan->br.chan, sys_le16_to_cpu(cp->psm));
@@ -998,6 +1015,8 @@ static int br_accept(struct bt_conn *conn, struct bt_l2cap_server *server,
9981015
} else {
9991016
chan->br.rx.fcs = BT_L2CAP_BR_FCS_16BIT;
10001017
}
1018+
1019+
chan->hold_credit = (options & BTP_L2CAP_LISTEN_V2_OPT_HOLD_CREDIT) != 0;
10011020
#endif /* CONFIG_BT_L2CAP_RET_FC */
10021021

10031022
*l2cap_chan = &chan->br.chan;
@@ -1103,12 +1122,59 @@ static uint8_t listen_v2(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t
11031122
return _listen(psm, cp->transport, response, cp->mode, options);
11041123
}
11051124

1125+
#if defined(CONFIG_BT_CLASSIC)
1126+
static uint8_t br_credits(uint8_t chan_id, void *rsp, uint16_t *rsp_len)
1127+
{
1128+
struct br_channel *chan;
1129+
1130+
if (chan_id >= CHANNELS) {
1131+
return BTP_STATUS_FAILED;
1132+
}
1133+
1134+
chan = &br_channels[chan_id];
1135+
1136+
if (!chan->in_use) {
1137+
return BTP_STATUS_FAILED;
1138+
}
1139+
1140+
ARRAY_FOR_EACH(chan->pending_credit, i) {
1141+
if (chan->pending_credit[i] != NULL) {
1142+
if (bt_l2cap_chan_recv_complete(&chan->br.chan,
1143+
chan->pending_credit[i]) < 0) {
1144+
return BTP_STATUS_FAILED;
1145+
}
1146+
1147+
chan->pending_credit[i] = NULL;
1148+
1149+
return BTP_STATUS_SUCCESS;
1150+
}
1151+
}
1152+
1153+
return BTP_STATUS_SUCCESS;
1154+
}
1155+
#else
1156+
static uint8_t br_credits(uint8_t chan_id, void *rsp, uint16_t *rsp_len)
1157+
{
1158+
return BTP_STATUS_FAILED;
1159+
}
1160+
#endif /* CONFIG_BT_CLASSIC */
1161+
11061162
static uint8_t credits(const void *cmd, uint16_t cmd_len,
11071163
void *rsp, uint16_t *rsp_len)
11081164
{
11091165
const struct btp_l2cap_credits_cmd *cp = cmd;
11101166
struct channel *chan;
11111167

1168+
if (IS_ENABLED(CONFIG_BT_CLASSIC)) {
1169+
uint8_t chan_id;
1170+
1171+
chan_id = cp->chan_id;
1172+
if (chan_id >= ARRAY_SIZE(channels)) {
1173+
chan_id = chan_id - ARRAY_SIZE(channels);
1174+
return br_credits(chan_id, rsp, rsp_len);
1175+
}
1176+
}
1177+
11121178
if (cp->chan_id >= CHANNELS) {
11131179
return BTP_STATUS_FAILED;
11141180
}

0 commit comments

Comments
 (0)