/** @file * @brief Bluetooth Link Layer functions * */ /* * Copyright (c) 2017-2018 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include #include "controller/util/memq.h" #include "controller/include/ll.h" #include "host/shell/bt.h" int cmd_ll_addr_read(const struct shell *sh, size_t argc, char *argv[]) { uint8_t addr_type; const char *str_type; bt_addr_t addr; char str_addr[BT_ADDR_STR_LEN]; if (argc < 2) { return -EINVAL; } str_type = argv[1]; if (!strcmp(str_type, "random")) { addr_type = 1U; } else if (!strcmp(str_type, "public")) { addr_type = 0U; } else { return -EINVAL; } (void)ll_addr_read(addr_type, addr.val); bt_addr_to_str(&addr, str_addr, sizeof(str_addr)); shell_print(sh, "Current %s address: %s", str_type, str_addr); return 0; } #if defined(CONFIG_BT_CTLR_DTM) #include "controller/ll_sw/ll_test.h" int cmd_test_tx(const struct shell *sh, size_t argc, char *argv[]) { uint8_t chan, len, type, phy; uint8_t err; if (argc < 5) { return -EINVAL; } chan = strtoul(argv[1], NULL, 16); len = strtoul(argv[2], NULL, 16); type = strtoul(argv[3], NULL, 16); phy = strtoul(argv[4], NULL, 16); err = ll_test_tx(chan, len, type, phy, BT_HCI_LE_TEST_CTE_DISABLED, BT_HCI_LE_TEST_CTE_TYPE_ANY, BT_HCI_LE_TEST_SWITCH_PATTERN_LEN_ANY, NULL, BT_HCI_TX_TEST_POWER_MAX_SET); if (err) { return -EINVAL; } shell_print(sh, "test_tx..."); return 0; } int cmd_test_rx(const struct shell *sh, size_t argc, char *argv[]) { uint8_t chan, phy, mod_idx; uint8_t err; if (argc < 4) { return -EINVAL; } chan = strtoul(argv[1], NULL, 16); phy = strtoul(argv[2], NULL, 16); mod_idx = strtoul(argv[3], NULL, 16); err = ll_test_rx(chan, phy, mod_idx, BT_HCI_LE_TEST_CTE_DISABLED, BT_HCI_LE_TEST_CTE_TYPE_ANY, BT_HCI_LE_TEST_SLOT_DURATION_ANY, BT_HCI_LE_TEST_SWITCH_PATTERN_LEN_ANY, NULL); if (err) { return -EINVAL; } shell_print(sh, "test_rx..."); return 0; } int cmd_test_end(const struct shell *sh, size_t argc, char *argv[]) { uint16_t num_rx; uint8_t err; err = ll_test_end(&num_rx); if (err) { return -EINVAL; } shell_print(sh, "num_rx= %u.", num_rx); return 0; } #endif /* CONFIG_BT_CTLR_DTM */ #if defined(CONFIG_BT_CTLR_ADV_EXT) #include "controller/ll_sw/lll.h" #if defined(CONFIG_BT_BROADCASTER) #define OWN_ADDR_TYPE 1 #define PEER_ADDR_TYPE 0 #define PEER_ADDR NULL #define ADV_CHAN_MAP 0x07 #define FILTER_POLICY 0x00 #define ADV_TX_PWR NULL #define ADV_SEC_SKIP 0 #define ADV_PHY_S 0x01 #define ADV_SID 0 #define SCAN_REQ_NOT 0 #define AD_OP 0x03 #define AD_FRAG_PREF 0x00 static const struct bt_data adv_data[] = { BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR), }; int cmd_advx(const struct shell *sh, size_t argc, char *argv[]) { uint16_t adv_interval = 0x20; uint16_t handle = 0U; uint16_t evt_prop = 0U; uint8_t adv_type; uint8_t enable; uint8_t ad = 0; uint8_t phy_p; int32_t err; if (argc < 2) { return -EINVAL; } if (argc > 1) { if (!strcmp(argv[1], "on")) { adv_type = 0x05; /* Adv. Ext. */ enable = 1U; } else if (!strcmp(argv[1], "hdcd")) { adv_type = 0x01; /* Directed */ adv_interval = 0U; /* High Duty Cycle */ phy_p = BIT(0); enable = 1U; goto do_enable; } else if (!strcmp(argv[1], "ldcd")) { adv_type = 0x04; /* Directed */ enable = 1U; } else if (!strcmp(argv[1], "off")) { enable = 0U; } else { return -EINVAL; } } phy_p = BIT(0); if (argc > 2) { if (!strcmp(argv[2], "coded")) { phy_p = BIT(2); } else if (!strcmp(argv[2], "anon")) { evt_prop |= BIT(5); } else if (!strcmp(argv[2], "txp")) { evt_prop |= BIT(6); } else if (!strcmp(argv[2], "ad")) { ad = 1; } else { handle = strtoul(argv[2], NULL, 16); if (handle >= CONFIG_BT_CTLR_ADV_SET) { return -EINVAL; } } } if (argc > 3) { if (!strcmp(argv[3], "anon")) { evt_prop |= BIT(5); } else if (!strcmp(argv[3], "txp")) { evt_prop |= BIT(6); } else if (!strcmp(argv[3], "ad")) { ad = 1; } else { handle = strtoul(argv[3], NULL, 16); if (handle >= CONFIG_BT_CTLR_ADV_SET) { return -EINVAL; } } } if (argc > 4) { if (!strcmp(argv[4], "txp")) { evt_prop |= BIT(6); } else if (!strcmp(argv[4], "ad")) { ad = 1; } else { handle = strtoul(argv[4], NULL, 16); if (handle >= CONFIG_BT_CTLR_ADV_SET) { return -EINVAL; } } } if (argc > 5) { if (!strcmp(argv[5], "ad")) { ad = 1; } else { handle = strtoul(argv[5], NULL, 16); if (handle >= CONFIG_BT_CTLR_ADV_SET) { return -EINVAL; } } } if (argc > 6) { handle = strtoul(argv[6], NULL, 16); if (handle >= CONFIG_BT_CTLR_ADV_SET) { return -EINVAL; } } if (!enable) { goto disable; } do_enable: shell_print(sh, "adv param set..."); err = ll_adv_params_set(handle, evt_prop, adv_interval, adv_type, OWN_ADDR_TYPE, PEER_ADDR_TYPE, PEER_ADDR, ADV_CHAN_MAP, FILTER_POLICY, ADV_TX_PWR, phy_p, ADV_SEC_SKIP, ADV_PHY_S, ADV_SID, SCAN_REQ_NOT); if (err) { goto exit; } if (ad) { shell_print(sh, "ad data set..."); err = ll_adv_aux_ad_data_set(handle, AD_OP, AD_FRAG_PREF, ARRAY_SIZE(adv_data), (void *)adv_data); if (err) { goto exit; } } disable: shell_print(sh, "adv enable (%u)...", enable); #if defined(CONFIG_BT_HCI_MESH_EXT) err = ll_adv_enable(handle, enable, 0, 0, 0, 0, 0); #else /* !CONFIG_BT_HCI_MESH_EXT */ err = ll_adv_enable(handle, enable, 0, 0); #endif /* !CONFIG_BT_HCI_MESH_EXT */ if (err) { goto exit; } if (!enable) { err = ll_adv_aux_set_remove(handle); if (err) { goto exit; } } exit: shell_print(sh, "done (err= %d).", err); return 0; } #endif /* CONFIG_BT_BROADCASTER */ #if defined(CONFIG_BT_OBSERVER) #define SCAN_INTERVAL 0x0004 #define SCAN_WINDOW 0x0004 #define SCAN_OWN_ADDR_TYPE 1 #define SCAN_FILTER_POLICY 0 int cmd_scanx(const struct shell *sh, size_t argc, char *argv[]) { uint8_t type = 0U; uint8_t enable; int32_t err; if (argc < 2) { return -EINVAL; } if (argc > 1) { if (!strcmp(argv[1], "on")) { enable = 1U; type = 1U; } else if (!strcmp(argv[1], "passive")) { enable = 1U; type = 0U; } else if (!strcmp(argv[1], "off")) { enable = 0U; goto disable; } else { return -EINVAL; } } type |= BIT(1); if (argc > 2) { if (!strcmp(argv[2], "coded")) { type &= BIT(0); type |= BIT(3); } else { return -EINVAL; } } shell_print(sh, "scan param set..."); err = ll_scan_params_set(type, SCAN_INTERVAL, SCAN_WINDOW, SCAN_OWN_ADDR_TYPE, SCAN_FILTER_POLICY); if (err) { goto exit; } disable: shell_print(sh, "scan enable (%u)...", enable); err = ll_scan_enable(enable, 0, 0); if (err) { goto exit; } exit: shell_print(sh, "done (err= %d).", err); return err; } #endif /* CONFIG_BT_OBSERVER */ #endif /* CONFIG_BT_CTLR_ADV_EXT */