1 /** @file
2 * @brief Bluetooth shell module
3 *
4 * Provide some Bluetooth shell commands that can be useful to applications.
5 */
6
7 /*
8 * Copyright (c) 2017 Intel Corporation
9 *
10 * SPDX-License-Identifier: Apache-2.0
11 */
12
13 #include <errno.h>
14 #include <stddef.h>
15 #include <stdint.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 #include <zephyr/bluetooth/hci.h>
20 #include <zephyr/bluetooth/bluetooth.h>
21 #include <zephyr/bluetooth/conn.h>
22 #include <zephyr/bluetooth/hci_types.h>
23 #include <zephyr/bluetooth/l2cap.h>
24 #include <zephyr/bluetooth/classic/rfcomm.h>
25 #include <zephyr/bluetooth/classic/sdp.h>
26 #include <zephyr/net_buf.h>
27 #include <zephyr/settings/settings.h>
28 #include <zephyr/shell/shell.h>
29 #include <zephyr/shell/shell_string_conv.h>
30 #include <zephyr/sys/atomic_types.h>
31 #include <zephyr/sys/byteorder.h>
32 #include <zephyr/sys_clock.h>
33 #include <zephyr/kernel.h>
34 #include <zephyr/sys/time_units.h>
35 #include <zephyr/sys/util.h>
36
37 #include "common/bt_shell_private.h"
38 #include "host/shell/bt.h"
39
40 #define CREDITS 10
41 #define DATA_MTU (23 * CREDITS)
42
43 #define L2CAP_POLICY_NONE 0x00
44 #define L2CAP_POLICY_ALLOWLIST 0x01
45 #define L2CAP_POLICY_16BYTE_KEY 0x02
46
47 NET_BUF_POOL_FIXED_DEFINE(data_tx_pool, 1, BT_L2CAP_SDU_BUF_SIZE(DATA_MTU),
48 CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
49 NET_BUF_POOL_FIXED_DEFINE(data_rx_pool, 1, DATA_MTU, 8, NULL);
50
51 static uint8_t l2cap_policy;
52 static struct bt_conn *l2cap_allowlist[CONFIG_BT_MAX_CONN];
53
54 static uint32_t l2cap_rate;
55 static uint32_t l2cap_recv_delay_ms;
56 static K_FIFO_DEFINE(l2cap_recv_fifo);
57 struct l2ch {
58 struct k_work_delayable recv_work;
59 struct bt_l2cap_le_chan ch;
60 };
61 #define L2CH_CHAN(_chan) CONTAINER_OF(_chan, struct l2ch, ch.chan)
62 #define L2CH_WORK(_work) CONTAINER_OF(k_work_delayable_from_work(_work), \
63 struct l2ch, recv_work)
64 #define L2CAP_CHAN(_chan) _chan->ch.chan
65
66 static bool metrics;
67
l2cap_recv_metrics(struct bt_l2cap_chan * chan,struct net_buf * buf)68 static int l2cap_recv_metrics(struct bt_l2cap_chan *chan, struct net_buf *buf)
69 {
70 static uint32_t len;
71 static uint32_t cycle_stamp;
72 uint32_t delta;
73
74 delta = k_cycle_get_32() - cycle_stamp;
75 delta = (uint32_t)k_cyc_to_ns_floor64(delta);
76
77 /* if last data rx-ed was greater than 1 second in the past,
78 * reset the metrics.
79 */
80 if (delta > NSEC_PER_SEC) {
81 len = 0U;
82 l2cap_rate = 0U;
83 cycle_stamp = k_cycle_get_32();
84 } else {
85 len += buf->len;
86 l2cap_rate = ((uint64_t)len << 3) * NSEC_PER_SEC / delta;
87 }
88
89 return 0;
90 }
91
l2cap_recv_cb(struct k_work * work)92 static void l2cap_recv_cb(struct k_work *work)
93 {
94 struct l2ch *c = L2CH_WORK(work);
95 struct net_buf *buf;
96
97 while ((buf = k_fifo_get(&l2cap_recv_fifo, K_NO_WAIT))) {
98 bt_shell_print("Confirming reception");
99 bt_l2cap_chan_recv_complete(&c->ch.chan, buf);
100 }
101 }
102
l2cap_recv(struct bt_l2cap_chan * chan,struct net_buf * buf)103 static int l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
104 {
105 struct l2ch *l2ch = L2CH_CHAN(chan);
106
107 if (metrics) {
108 return l2cap_recv_metrics(chan, buf);
109 }
110
111 bt_shell_print("Incoming data channel %p len %u",
112 chan, buf->len);
113
114 if (buf->len) {
115 bt_shell_hexdump(buf->data, buf->len);
116 }
117
118 if (l2cap_recv_delay_ms > 0) {
119 /* Submit work only if queue is empty */
120 if (k_fifo_is_empty(&l2cap_recv_fifo)) {
121 bt_shell_print("Delaying response in %u ms...",
122 l2cap_recv_delay_ms);
123 }
124
125 k_fifo_put(&l2cap_recv_fifo, buf);
126 k_work_schedule(&l2ch->recv_work, K_MSEC(l2cap_recv_delay_ms));
127
128 return -EINPROGRESS;
129 }
130
131 return 0;
132 }
133
l2cap_sent(struct bt_l2cap_chan * chan)134 static void l2cap_sent(struct bt_l2cap_chan *chan)
135 {
136 bt_shell_print("Outgoing data channel %p transmitted", chan);
137 }
138
l2cap_status(struct bt_l2cap_chan * chan,atomic_t * status)139 static void l2cap_status(struct bt_l2cap_chan *chan, atomic_t *status)
140 {
141 bt_shell_print("Channel %p status %u", chan, (uint32_t)*status);
142 }
143
l2cap_connected(struct bt_l2cap_chan * chan)144 static void l2cap_connected(struct bt_l2cap_chan *chan)
145 {
146 struct l2ch *c = L2CH_CHAN(chan);
147
148 k_work_init_delayable(&c->recv_work, l2cap_recv_cb);
149
150 bt_shell_print("Channel %p connected", chan);
151 }
152
l2cap_disconnected(struct bt_l2cap_chan * chan)153 static void l2cap_disconnected(struct bt_l2cap_chan *chan)
154 {
155 bt_shell_print("Channel %p disconnected", chan);
156 }
157
l2cap_alloc_buf(struct bt_l2cap_chan * chan)158 static struct net_buf *l2cap_alloc_buf(struct bt_l2cap_chan *chan)
159 {
160 /* print if metrics is disabled */
161 if (!metrics) {
162 bt_shell_print("Channel %p requires buffer", chan);
163 }
164
165 return net_buf_alloc(&data_rx_pool, K_FOREVER);
166 }
167
168 static const struct bt_l2cap_chan_ops l2cap_ops = {
169 .alloc_buf = l2cap_alloc_buf,
170 .recv = l2cap_recv,
171 .sent = l2cap_sent,
172 .status = l2cap_status,
173 .connected = l2cap_connected,
174 .disconnected = l2cap_disconnected,
175 };
176
177 static struct l2ch l2ch_chan = {
178 .ch.chan.ops = &l2cap_ops,
179 .ch.rx.mtu = DATA_MTU,
180 };
181
l2cap_allowlist_remove(struct bt_conn * conn,uint8_t reason)182 static void l2cap_allowlist_remove(struct bt_conn *conn, uint8_t reason)
183 {
184 int i;
185
186 for (i = 0; i < ARRAY_SIZE(l2cap_allowlist); i++) {
187 if (l2cap_allowlist[i] == conn) {
188 bt_conn_unref(l2cap_allowlist[i]);
189 l2cap_allowlist[i] = NULL;
190 }
191 }
192 }
193
194 BT_CONN_CB_DEFINE(l2cap_conn_callbacks) = {
195 .disconnected = l2cap_allowlist_remove,
196 };
197
l2cap_accept_policy(struct bt_conn * conn)198 static int l2cap_accept_policy(struct bt_conn *conn)
199 {
200 int i;
201
202 if (l2cap_policy == L2CAP_POLICY_16BYTE_KEY) {
203 uint8_t enc_key_size = bt_conn_enc_key_size(conn);
204
205 if (enc_key_size && enc_key_size < BT_ENC_KEY_SIZE_MAX) {
206 return -EPERM;
207 }
208 } else if (l2cap_policy == L2CAP_POLICY_ALLOWLIST) {
209 for (i = 0; i < ARRAY_SIZE(l2cap_allowlist); i++) {
210 if (l2cap_allowlist[i] == conn) {
211 return 0;
212 }
213 }
214
215 return -EACCES;
216 }
217
218 return 0;
219 }
220
l2cap_accept(struct bt_conn * conn,struct bt_l2cap_server * server,struct bt_l2cap_chan ** chan)221 static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_server *server,
222 struct bt_l2cap_chan **chan)
223 {
224 int err;
225
226 bt_shell_print("Incoming conn %p", conn);
227
228 err = l2cap_accept_policy(conn);
229 if (err < 0) {
230 return err;
231 }
232
233 if (l2ch_chan.ch.chan.conn) {
234 bt_shell_print("No channels available");
235 return -ENOMEM;
236 }
237
238 *chan = &l2ch_chan.ch.chan;
239
240 return 0;
241 }
242
243 static struct bt_l2cap_server server = {
244 .accept = l2cap_accept,
245 };
246
cmd_register(const struct shell * sh,size_t argc,char * argv[])247 static int cmd_register(const struct shell *sh, size_t argc, char *argv[])
248 {
249 const char *policy;
250
251 if (server.psm) {
252 shell_error(sh, "Already registered");
253 return -ENOEXEC;
254 }
255
256 server.psm = strtoul(argv[1], NULL, 16);
257
258 if (argc > 2) {
259 server.sec_level = strtoul(argv[2], NULL, 10);
260 }
261
262 if (argc > 3) {
263 policy = argv[3];
264
265 if (!strcmp(policy, "allowlist")) {
266 l2cap_policy = L2CAP_POLICY_ALLOWLIST;
267 } else if (!strcmp(policy, "16byte_key")) {
268 l2cap_policy = L2CAP_POLICY_16BYTE_KEY;
269 } else {
270 return -EINVAL;
271 }
272 }
273
274 if (bt_l2cap_server_register(&server) < 0) {
275 shell_error(sh, "Unable to register psm");
276 server.psm = 0U;
277 return -ENOEXEC;
278 } else {
279 shell_print(sh, "L2CAP psm %u sec_level %u registered",
280 server.psm, server.sec_level);
281 }
282
283 return 0;
284 }
285
286 #if defined(CONFIG_BT_L2CAP_ECRED)
cmd_ecred_reconfigure(const struct shell * sh,size_t argc,char * argv[])287 static int cmd_ecred_reconfigure(const struct shell *sh, size_t argc, char *argv[])
288 {
289 struct bt_l2cap_chan *l2cap_ecred_chans[] = { &l2ch_chan.ch.chan, NULL };
290 uint16_t mtu;
291 int err = 0;
292
293 if (!default_conn) {
294 shell_error(sh, "Not connected");
295 return -ENOEXEC;
296 }
297
298 if (!l2ch_chan.ch.chan.conn) {
299 shell_error(sh, "Channel not connected");
300 return -ENOEXEC;
301 }
302
303 mtu = shell_strtoul(argv[1], 10, &err);
304 if (err) {
305 shell_error(sh, "Unable to parse MTU (err %d)", err);
306
307 return -ENOEXEC;
308 }
309
310 err = bt_l2cap_ecred_chan_reconfigure(l2cap_ecred_chans, mtu);
311 if (err < 0) {
312 shell_error(sh, "Unable to reconfigure channel (err %d)", err);
313 } else {
314 shell_print(sh, "L2CAP reconfiguration pending");
315 }
316
317 return err;
318 }
319
cmd_ecred_connect(const struct shell * sh,size_t argc,char * argv[])320 static int cmd_ecred_connect(const struct shell *sh, size_t argc, char *argv[])
321 {
322 struct bt_l2cap_chan *l2cap_ecred_chans[] = { &l2ch_chan.ch.chan, NULL };
323 uint16_t psm;
324 int err = 0;
325
326 if (!default_conn) {
327 shell_error(sh, "Not connected");
328
329 return -ENOEXEC;
330 }
331
332 if (l2ch_chan.ch.chan.conn) {
333 shell_error(sh, "Channel already in use");
334
335 return -ENOEXEC;
336 }
337
338 psm = shell_strtoul(argv[1], 16, &err);
339 if (err) {
340 shell_error(sh, "Unable to parse PSM (err %d)", err);
341
342 return err;
343 }
344
345 if (argc > 2) {
346 int sec;
347
348 sec = shell_strtoul(argv[2], 10, &err);
349 if (err) {
350 shell_error(sh, "Unable to parse security level (err %d)", err);
351
352 return err;
353 }
354
355 l2ch_chan.ch.required_sec_level = sec;
356 }
357
358 err = bt_l2cap_ecred_chan_connect(default_conn, l2cap_ecred_chans, psm);
359 if (err < 0) {
360 shell_error(sh, "Unable to connect to psm %u (err %d)", psm, err);
361 } else {
362 shell_print(sh, "L2CAP connection pending");
363 }
364
365 return err;
366 }
367 #endif /* CONFIG_BT_L2CAP_ECRED */
368
cmd_connect(const struct shell * sh,size_t argc,char * argv[])369 static int cmd_connect(const struct shell *sh, size_t argc, char *argv[])
370 {
371 uint16_t psm;
372 int err;
373
374 if (!default_conn) {
375 shell_error(sh, "Not connected");
376 return -ENOEXEC;
377 }
378
379 if (l2ch_chan.ch.chan.conn) {
380 shell_error(sh, "Channel already in use");
381 return -ENOEXEC;
382 }
383
384 psm = strtoul(argv[1], NULL, 16);
385
386 if (argc > 2) {
387 int sec;
388
389 sec = *argv[2] - '0';
390
391 l2ch_chan.ch.required_sec_level = sec;
392 }
393
394 err = bt_l2cap_chan_connect(default_conn, &l2ch_chan.ch.chan, psm);
395 if (err < 0) {
396 shell_error(sh, "Unable to connect to psm %u (err %d)", psm, err);
397 } else {
398 shell_print(sh, "L2CAP connection pending");
399 }
400
401 return err;
402 }
403
cmd_disconnect(const struct shell * sh,size_t argc,char * argv[])404 static int cmd_disconnect(const struct shell *sh, size_t argc, char *argv[])
405 {
406 int err;
407
408 err = bt_l2cap_chan_disconnect(&l2ch_chan.ch.chan);
409 if (err) {
410 shell_print(sh, "Unable to disconnect: %u", -err);
411 }
412
413 return err;
414 }
415
cmd_send(const struct shell * sh,size_t argc,char * argv[])416 static int cmd_send(const struct shell *sh, size_t argc, char *argv[])
417 {
418 static uint8_t buf_data[DATA_MTU] = { [0 ... (DATA_MTU - 1)] = 0xff };
419 int ret, len = DATA_MTU, count = 1;
420 struct net_buf *buf;
421
422 if (argc > 1) {
423 count = strtoul(argv[1], NULL, 10);
424 }
425
426 if (argc > 2) {
427 len = strtoul(argv[2], NULL, 10);
428 if (len > DATA_MTU) {
429 shell_print(sh, "Length exceeds TX MTU for the channel");
430 return -ENOEXEC;
431 }
432 }
433
434 len = MIN(l2ch_chan.ch.tx.mtu, len);
435
436 while (count--) {
437 shell_print(sh, "Rem %d", count);
438 buf = net_buf_alloc(&data_tx_pool, K_SECONDS(2));
439 if (!buf) {
440 if (l2ch_chan.ch.state != BT_L2CAP_CONNECTED) {
441 shell_print(sh, "Channel disconnected, stopping TX");
442
443 return -EAGAIN;
444 }
445 shell_print(sh, "Allocation timeout, stopping TX");
446
447 return -EAGAIN;
448 }
449 net_buf_reserve(buf, BT_L2CAP_SDU_CHAN_SEND_RESERVE);
450
451 net_buf_add_mem(buf, buf_data, len);
452 ret = bt_l2cap_chan_send(&l2ch_chan.ch.chan, buf);
453 if (ret < 0) {
454 shell_print(sh, "Unable to send: %d", -ret);
455 net_buf_unref(buf);
456 return -ENOEXEC;
457 }
458 }
459
460 return 0;
461 }
462
cmd_recv(const struct shell * sh,size_t argc,char * argv[])463 static int cmd_recv(const struct shell *sh, size_t argc, char *argv[])
464 {
465 if (argc > 1) {
466 l2cap_recv_delay_ms = strtoul(argv[1], NULL, 10);
467 } else {
468 shell_print(sh, "l2cap receive delay: %u ms",
469 l2cap_recv_delay_ms);
470 }
471
472 return 0;
473 }
474
cmd_metrics(const struct shell * sh,size_t argc,char * argv[])475 static int cmd_metrics(const struct shell *sh, size_t argc, char *argv[])
476 {
477 const char *action;
478
479 if (argc < 2) {
480 shell_print(sh, "l2cap rate: %u bps.", l2cap_rate);
481
482 return 0;
483 }
484
485 action = argv[1];
486
487 if (!strcmp(action, "on")) {
488 metrics = true;
489 } else if (!strcmp(action, "off")) {
490 metrics = false;
491 } else {
492 shell_help(sh);
493 return 0;
494 }
495
496 shell_print(sh, "l2cap metrics %s.", action);
497 return 0;
498 }
499
cmd_allowlist_add(const struct shell * sh,size_t argc,char * argv[])500 static int cmd_allowlist_add(const struct shell *sh, size_t argc, char *argv[])
501 {
502 int i;
503
504 if (!default_conn) {
505 shell_error(sh, "Not connected");
506 return 0;
507 }
508
509 for (i = 0; i < ARRAY_SIZE(l2cap_allowlist); i++) {
510 if (l2cap_allowlist[i] == NULL) {
511 l2cap_allowlist[i] = bt_conn_ref(default_conn);
512 return 0;
513 }
514 }
515
516 return -ENOMEM;
517 }
518
cmd_allowlist_remove(const struct shell * sh,size_t argc,char * argv[])519 static int cmd_allowlist_remove(const struct shell *sh, size_t argc, char *argv[])
520 {
521 if (!default_conn) {
522 shell_error(sh, "Not connected");
523 return 0;
524 }
525
526 l2cap_allowlist_remove(default_conn, 0);
527
528 return 0;
529 }
530
531 #define HELP_NONE "[none]"
532
533 SHELL_STATIC_SUBCMD_SET_CREATE(allowlist_cmds,
534 SHELL_CMD_ARG(add, NULL, HELP_NONE, cmd_allowlist_add, 1, 0),
535 SHELL_CMD_ARG(remove, NULL, HELP_NONE, cmd_allowlist_remove, 1, 0),
536 SHELL_SUBCMD_SET_END
537 );
538
539 SHELL_STATIC_SUBCMD_SET_CREATE(l2cap_cmds,
540 SHELL_CMD_ARG(connect, NULL, "<psm> [sec_level]", cmd_connect, 2, 1),
541 SHELL_CMD_ARG(disconnect, NULL, HELP_NONE, cmd_disconnect, 1, 0),
542 SHELL_CMD_ARG(metrics, NULL, "<value on, off>", cmd_metrics, 2, 0),
543 SHELL_CMD_ARG(recv, NULL, "[delay (in milliseconds)", cmd_recv, 1, 1),
544 SHELL_CMD_ARG(register, NULL, "<psm> [sec_level] "
545 "[policy: allowlist, 16byte_key]", cmd_register, 2, 2),
546 SHELL_CMD_ARG(send, NULL, "[number of packets] [length of packet(s)]",
547 cmd_send, 1, 2),
548 SHELL_CMD_ARG(allowlist, &allowlist_cmds, HELP_NONE, NULL, 1, 0),
549 #if defined(CONFIG_BT_L2CAP_ECRED)
550 SHELL_CMD_ARG(ecred-connect, NULL, "<psm (hex)> [sec_level (dec)]",
551 cmd_ecred_connect, 2, 1),
552 SHELL_CMD_ARG(ecred-reconfigure, NULL, "<mtu (dec)>",
553 cmd_ecred_reconfigure, 1, 1),
554 #endif /* CONFIG_BT_L2CAP_ECRED */
555 SHELL_SUBCMD_SET_END
556 );
557
cmd_l2cap(const struct shell * sh,size_t argc,char ** argv)558 static int cmd_l2cap(const struct shell *sh, size_t argc, char **argv)
559 {
560 if (argc == 1) {
561 shell_help(sh);
562 /* shell returns 1 when help is printed */
563 return 1;
564 }
565
566 shell_error(sh, "%s unknown parameter: %s", argv[0], argv[1]);
567
568 return -ENOEXEC;
569 }
570
571 SHELL_CMD_ARG_REGISTER(l2cap, &l2cap_cmds, "Bluetooth L2CAP shell commands",
572 cmd_l2cap, 1, 1);
573