26
26
#include <zephyr/bluetooth/l2cap.h>
27
27
#include <zephyr/bluetooth/classic/rfcomm.h>
28
28
#include <zephyr/bluetooth/classic/sdp.h>
29
+ #include <zephyr/bluetooth/classic/l2cap_br.h>
29
30
30
31
#include <zephyr/shell/shell.h>
31
32
@@ -646,6 +647,124 @@ static int cmd_l2cap_credits(const struct shell *sh, size_t argc, char *argv[])
646
647
}
647
648
#endif /* CONFIG_BT_L2CAP_RET_FC */
648
649
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
+
649
768
static int cmd_discoverable (const struct shell * sh , size_t argc , char * argv [])
650
769
{
651
770
int err = 0 ;
@@ -1110,6 +1229,14 @@ static int cmd_default_handler(const struct shell *sh, size_t argc, char **argv)
1110
1229
"<psm> <mode: none, ret, fc, eret, stream> [hold_credit] " \
1111
1230
"[mode_optional] [extended_control]"
1112
1231
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
+
1113
1240
SHELL_STATIC_SUBCMD_SET_CREATE (l2cap_cmds ,
1114
1241
#if defined(CONFIG_BT_L2CAP_RET_FC )
1115
1242
SHELL_CMD_ARG (register , NULL , HELP_REG , cmd_l2cap_register , 3 , 3 ),
@@ -1124,6 +1251,7 @@ SHELL_STATIC_SUBCMD_SET_CREATE(l2cap_cmds,
1124
1251
#if defined(CONFIG_BT_L2CAP_RET_FC )
1125
1252
SHELL_CMD_ARG (credits , NULL , HELP_NONE , cmd_l2cap_credits , 1 , 0 ),
1126
1253
#endif /* CONFIG_BT_L2CAP_RET_FC */
1254
+ SHELL_CMD (echo , & echo_cmds , "L2CAP BR ECHO commands" , cmd_default_handler ),
1127
1255
SHELL_SUBCMD_SET_END
1128
1256
);
1129
1257
0 commit comments