/** @file * @brief Bluetooth Audio shell * */ /* * Copyright (c) 2020 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include #include #include #include #include #include "bt.h" static void iso_recv(struct bt_iso_chan *chan, struct net_buf *buf) { printk("Incoming data channel %p len %u\n", chan, buf->len); } static void iso_connected(struct bt_iso_chan *chan) { printk("ISO Channel %p connected\n", chan); } static void iso_disconnected(struct bt_iso_chan *chan) { printk("ISO Channel %p disconnected\n", chan); } static struct bt_iso_chan_ops iso_ops = { .recv = iso_recv, .connected = iso_connected, .disconnected = iso_disconnected, }; static struct bt_iso_chan_qos iso_qos = { .sca = 0x07, }; static struct bt_iso_chan iso_chan = { .ops = &iso_ops, .qos = &iso_qos, }; static int iso_accept(struct bt_conn *conn, struct bt_iso_chan **chan) { printk("Incoming conn %p\n", conn); if (iso_chan.conn) { printk("No channels available\n"); return -ENOMEM; } *chan = &iso_chan; return 0; } struct bt_iso_server iso_server = { .sec_level = BT_SECURITY_L1, .accept = iso_accept, }; static int cmd_listen(const struct shell *shell, size_t argc, char *argv[]) { int err; if (argc > 1) { iso_server.sec_level = *argv[1] - '0'; } err = bt_iso_server_register(&iso_server); if (err) { shell_error(shell, "Unable to register ISO cap (err %d)", err); } return err; } static int cmd_bind(const struct shell *shell, size_t argc, char *argv[]) { struct bt_conn *conns[1]; struct bt_iso_chan *chans[1]; int err; if (!default_conn) { shell_error(shell, "Not connected"); return 0; } if (iso_chan.conn) { shell_error(shell, "Already bound"); return 0; } conns[0] = default_conn; chans[0] = &iso_chan; if (argc > 1) { chans[0]->qos->dir = strtol(argv[1], NULL, 0); } if (argc > 2) { chans[0]->qos->interval = strtol(argv[2], NULL, 0); } if (argc > 3) { chans[0]->qos->packing = strtol(argv[3], NULL, 0); } if (argc > 4) { chans[0]->qos->framing = strtol(argv[4], NULL, 0); } if (argc > 5) { chans[0]->qos->latency = strtol(argv[5], NULL, 0); } if (argc > 6) { chans[0]->qos->sdu = strtol(argv[6], NULL, 0); } if (argc > 7) { chans[0]->qos->phy = strtol(argv[7], NULL, 0); } if (argc > 8) { chans[0]->qos->rtn = strtol(argv[8], NULL, 0); } err = bt_iso_chan_bind(conns, 1, chans); if (err) { shell_error(shell, "Unable to bind (err %d)", err); return 0; } shell_print(shell, "ISO Channel bound"); return 0; } static int cmd_connect(const struct shell *shell, size_t argc, char *argv[]) { struct bt_iso_chan *chans[1]; int err; if (!iso_chan.conn) { shell_error(shell, "Not bound"); return 0; } chans[0] = &iso_chan; err = bt_iso_chan_connect(chans, 1); if (err) { shell_error(shell, "Unable to connect (err %d)", err); return 0; } shell_print(shell, "ISO Connect pending..."); return 0; } #define DATA_MTU CONFIG_BT_ISO_TX_MTU NET_BUF_POOL_FIXED_DEFINE(tx_pool, 1, DATA_MTU, NULL); static int cmd_send(const struct shell *shell, size_t argc, char *argv[]) { static uint8_t buf_data[DATA_MTU] = { [0 ... (DATA_MTU - 1)] = 0xff }; int ret, len, count = 1; struct net_buf *buf; if (argc > 1) { count = strtoul(argv[1], NULL, 10); } if (!iso_chan.conn) { shell_error(shell, "Not bound"); return 0; } len = MIN(iso_chan.qos->sdu, DATA_MTU - BT_ISO_CHAN_SEND_RESERVE); while (count--) { buf = net_buf_alloc(&tx_pool, K_FOREVER); net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); net_buf_add_mem(buf, buf_data, len); ret = bt_iso_chan_send(&iso_chan, buf); if (ret < 0) { shell_print(shell, "Unable to send: %d", -ret); net_buf_unref(buf); return -ENOEXEC; } } shell_print(shell, "ISO sending..."); return 0; } static int cmd_disconnect(const struct shell *shell, size_t argc, char *argv[]) { int err; err = bt_iso_chan_disconnect(&iso_chan); if (err) { shell_error(shell, "Unable to disconnect (err %d)", err); return 0; } shell_print(shell, "ISO Disconnect pending..."); return 0; } SHELL_STATIC_SUBCMD_SET_CREATE(iso_cmds, SHELL_CMD_ARG(bind, NULL, "[dir] [interval] [packing] [framing] " "[latency] [sdu] [phy] [rtn]", cmd_bind, 1, 8), SHELL_CMD_ARG(connect, NULL, "Connect ISO Channel", cmd_connect, 1, 0), SHELL_CMD_ARG(listen, NULL, "[security level]", cmd_listen, 1, 1), SHELL_CMD_ARG(send, NULL, "Send to ISO Channel", cmd_send, 1, 0), SHELL_CMD_ARG(disconnect, NULL, "Disconnect ISO Channel", cmd_disconnect, 1, 0), SHELL_SUBCMD_SET_END ); static int cmd_iso(const struct shell *shell, size_t argc, char **argv) { if (argc > 1) { shell_error(shell, "%s unknown parameter: %s", argv[0], argv[1]); } else { shell_error(shell, "%s Missing subcommand", argv[0]); } return -ENOEXEC; } SHELL_CMD_ARG_REGISTER(iso, &iso_cmds, "Bluetooth ISO shell commands", cmd_iso, 1, 1);