Skip to content

Commit f34d776

Browse files
lylezhu2012nashif
authored andcommitted
Bluetooth: Classic: L2CAP: Add echo command set
Add echo test shell commands, `register`, `unregister`, `req`, and `rsp`. Signed-off-by: Lyle Zhu <lyle.zhu@nxp.com>
1 parent 6f2b8f8 commit f34d776

File tree

1 file changed

+128
-0
lines changed
  • subsys/bluetooth/host/classic/shell

1 file changed

+128
-0
lines changed

subsys/bluetooth/host/classic/shell/bredr.c

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <zephyr/bluetooth/l2cap.h>
2727
#include <zephyr/bluetooth/classic/rfcomm.h>
2828
#include <zephyr/bluetooth/classic/sdp.h>
29+
#include <zephyr/bluetooth/classic/l2cap_br.h>
2930

3031
#include <zephyr/shell/shell.h>
3132

@@ -646,6 +647,124 @@ static int cmd_l2cap_credits(const struct shell *sh, size_t argc, char *argv[])
646647
}
647648
#endif /* CONFIG_BT_L2CAP_RET_FC */
648649

650+
static void l2cap_br_echo_req(struct bt_conn *conn, uint8_t identifier, struct net_buf *buf)
651+
{
652+
bt_shell_print("Incoming ECHO REQ data identifier %u len %u", identifier, buf->len);
653+
654+
if (buf->len > 0) {
655+
bt_shell_hexdump(buf->data, buf->len);
656+
}
657+
}
658+
659+
static void l2cap_br_echo_rsp(struct bt_conn *conn, struct net_buf *buf)
660+
{
661+
bt_shell_print("Incoming ECHO RSP data len %u", buf->len);
662+
663+
if (buf->len > 0) {
664+
bt_shell_hexdump(buf->data, buf->len);
665+
}
666+
}
667+
668+
static struct bt_l2cap_br_echo_cb echo_cb = {
669+
.req = l2cap_br_echo_req,
670+
.rsp = l2cap_br_echo_rsp,
671+
};
672+
673+
static int cmd_l2cap_echo_reg(const struct shell *sh, size_t argc, char *argv[])
674+
{
675+
int err;
676+
677+
err = bt_l2cap_br_echo_cb_register(&echo_cb);
678+
if (err) {
679+
shell_error(sh, "Failed to register echo callback: %d", -err);
680+
return err;
681+
}
682+
683+
return 0;
684+
}
685+
686+
static int cmd_l2cap_echo_unreg(const struct shell *sh, size_t argc, char *argv[])
687+
{
688+
int err;
689+
690+
err = bt_l2cap_br_echo_cb_unregister(&echo_cb);
691+
if (err) {
692+
shell_error(sh, "Failed to unregister echo callback: %d", -err);
693+
return err;
694+
}
695+
696+
return 0;
697+
}
698+
699+
static int cmd_l2cap_echo_req(const struct shell *sh, size_t argc, char *argv[])
700+
{
701+
static uint8_t buf_data[DATA_BREDR_MTU];
702+
int err, len = DATA_BREDR_MTU;
703+
struct net_buf *buf;
704+
705+
len = strtoul(argv[1], NULL, 10);
706+
if (len > DATA_BREDR_MTU) {
707+
shell_error(sh, "Length exceeds TX MTU for the channel");
708+
return -ENOEXEC;
709+
}
710+
711+
buf = net_buf_alloc(&data_tx_pool, K_SECONDS(2));
712+
if (!buf) {
713+
shell_error(sh, "Allocation timeout, stopping TX");
714+
return -EAGAIN;
715+
}
716+
net_buf_reserve(buf, BT_L2CAP_BR_ECHO_REQ_RESERVE);
717+
for (int i = 0; i < len; i++) {
718+
buf_data[i] = (uint8_t)i;
719+
}
720+
721+
net_buf_add_mem(buf, buf_data, len);
722+
err = bt_l2cap_br_echo_req(default_conn, buf);
723+
if (err < 0) {
724+
shell_error(sh, "Unable to send ECHO REQ: %d", -err);
725+
net_buf_unref(buf);
726+
return -ENOEXEC;
727+
}
728+
729+
return 0;
730+
}
731+
732+
static int cmd_l2cap_echo_rsp(const struct shell *sh, size_t argc, char *argv[])
733+
{
734+
static uint8_t buf_data[DATA_BREDR_MTU];
735+
int err, len = DATA_BREDR_MTU;
736+
uint8_t identifier;
737+
struct net_buf *buf;
738+
739+
identifier = (uint8_t)strtoul(argv[1], NULL, 10);
740+
741+
len = strtoul(argv[2], NULL, 10);
742+
if (len > DATA_BREDR_MTU) {
743+
shell_error(sh, "Length exceeds TX MTU for the channel");
744+
return -ENOEXEC;
745+
}
746+
747+
buf = net_buf_alloc(&data_tx_pool, K_SECONDS(2));
748+
if (!buf) {
749+
shell_error(sh, "Allocation timeout, stopping TX");
750+
return -EAGAIN;
751+
}
752+
net_buf_reserve(buf, BT_L2CAP_BR_ECHO_RSP_RESERVE);
753+
for (int i = 0; i < len; i++) {
754+
buf_data[i] = (uint8_t)i;
755+
}
756+
757+
net_buf_add_mem(buf, buf_data, len);
758+
err = bt_l2cap_br_echo_rsp(default_conn, identifier, buf);
759+
if (err < 0) {
760+
shell_error(sh, "Unable to send ECHO RSP: %d", -err);
761+
net_buf_unref(buf);
762+
return -ENOEXEC;
763+
}
764+
765+
return 0;
766+
}
767+
649768
static int cmd_discoverable(const struct shell *sh, size_t argc, char *argv[])
650769
{
651770
int err = 0;
@@ -1110,6 +1229,14 @@ static int cmd_default_handler(const struct shell *sh, size_t argc, char **argv)
11101229
"<psm> <mode: none, ret, fc, eret, stream> [hold_credit] " \
11111230
"[mode_optional] [extended_control]"
11121231

1232+
SHELL_STATIC_SUBCMD_SET_CREATE(echo_cmds,
1233+
SHELL_CMD_ARG(register, NULL, HELP_NONE, cmd_l2cap_echo_reg, 1, 0),
1234+
SHELL_CMD_ARG(unregister, NULL, HELP_NONE, cmd_l2cap_echo_unreg, 1, 0),
1235+
SHELL_CMD_ARG(req, NULL, "<length of data>", cmd_l2cap_echo_req, 2, 0),
1236+
SHELL_CMD_ARG(rsp, NULL, "<identifier> <length of data>", cmd_l2cap_echo_rsp, 3, 0),
1237+
SHELL_SUBCMD_SET_END
1238+
);
1239+
11131240
SHELL_STATIC_SUBCMD_SET_CREATE(l2cap_cmds,
11141241
#if defined(CONFIG_BT_L2CAP_RET_FC)
11151242
SHELL_CMD_ARG(register, NULL, HELP_REG, cmd_l2cap_register, 3, 3),
@@ -1124,6 +1251,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(l2cap_cmds,
11241251
#if defined(CONFIG_BT_L2CAP_RET_FC)
11251252
SHELL_CMD_ARG(credits, NULL, HELP_NONE, cmd_l2cap_credits, 1, 0),
11261253
#endif /* CONFIG_BT_L2CAP_RET_FC */
1254+
SHELL_CMD(echo, &echo_cmds, "L2CAP BR ECHO commands", cmd_default_handler),
11271255
SHELL_SUBCMD_SET_END
11281256
);
11291257

0 commit comments

Comments
 (0)