| /** @file |
| * @brief Bluetooth Link Layer functions |
| * |
| */ |
| |
| /* |
| * Copyright (c) 2017-2018 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <stdlib.h> |
| #include <string.h> |
| #include <zephyr.h> |
| |
| #include <bluetooth/hci.h> |
| #include <bluetooth/bluetooth.h> |
| #include <bluetooth/conn.h> |
| |
| #include <shell/shell.h> |
| |
| #include "../controller/util/memq.h" |
| #include "../controller/include/ll.h" |
| |
| #include "bt.h" |
| |
| int cmd_ll_addr_get(const struct shell *shell, size_t argc, char *argv[]) |
| { |
| u8_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_get(addr_type, addr.val); |
| bt_addr_to_str(&addr, str_addr, sizeof(str_addr)); |
| |
| shell_print(shell, "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 *shell, size_t argc, char *argv[]) |
| { |
| u8_t chan, len, type, phy; |
| u32_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); |
| if (err) { |
| return -EINVAL; |
| } |
| |
| shell_print(shell, "test_tx..."); |
| |
| return 0; |
| } |
| |
| int cmd_test_rx(const struct shell *shell, size_t argc, char *argv[]) |
| { |
| u8_t chan, phy, mod_idx; |
| u32_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); |
| if (err) { |
| return -EINVAL; |
| } |
| |
| shell_print(shell, "test_rx..."); |
| |
| return 0; |
| } |
| |
| int cmd_test_end(const struct shell *shell, size_t argc, char *argv[]) |
| { |
| u16_t num_rx; |
| u32_t err; |
| |
| err = ll_test_end(&num_rx); |
| if (err) { |
| return -EINVAL; |
| } |
| |
| shell_print(shell, "num_rx= %u.", num_rx); |
| |
| return 0; |
| } |
| #endif /* CONFIG_BT_CTLR_DTM */ |
| |
| #if defined(CONFIG_BT_CTLR_ADV_EXT) |
| #include "../controller/ll_sw/ll_adv_aux.h" |
| #include "../controller/ll_sw/lll.h" |
| |
| #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 |
| #define AD_LEN 0x00 |
| #define AD_DATA NULL |
| |
| #define SCAN_INTERVAL 0x0004 |
| #define SCAN_WINDOW 0x0004 |
| #define SCAN_OWN_ADDR_TYPE 1 |
| #define SCAN_FILTER_POLICY 0 |
| |
| #if defined(CONFIG_BT_BROADCASTER) |
| int cmd_advx(const struct shell *shell, size_t argc, char *argv[]) |
| { |
| u16_t adv_interval = 0x20; |
| u16_t handle = 0U; |
| u16_t evt_prop = 0U; |
| u8_t adv_type; |
| u8_t enable; |
| u8_t phy_p; |
| s32_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")) { |
| } else { |
| handle = strtoul(argv[2], NULL, 16); |
| if (handle >= BT_CTLR_ADV_MAX) { |
| 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")) { |
| } else { |
| handle = strtoul(argv[3], NULL, 16); |
| if (handle >= BT_CTLR_ADV_MAX) { |
| return -EINVAL; |
| } |
| } |
| } |
| |
| if (argc > 4) { |
| if (!strcmp(argv[4], "txp")) { |
| evt_prop |= BIT(6); |
| } else if (!strcmp(argv[4], "ad")) { |
| } else { |
| handle = strtoul(argv[4], NULL, 16); |
| if (handle >= BT_CTLR_ADV_MAX) { |
| return -EINVAL; |
| } |
| } |
| } |
| |
| if (argc > 5) { |
| if (!strcmp(argv[5], "ad")) { |
| } else { |
| handle = strtoul(argv[5], NULL, 16); |
| if (handle >= BT_CTLR_ADV_MAX) { |
| return -EINVAL; |
| } |
| } |
| } |
| |
| if (argc > 6) { |
| handle = strtoul(argv[6], NULL, 16); |
| if (handle >= BT_CTLR_ADV_MAX) { |
| return -EINVAL; |
| } |
| } |
| |
| if (!enable) { |
| goto disable; |
| } |
| |
| do_enable: |
| shell_print(shell, "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 defined(CONFIG_BT_LL_SW_SPLIT) |
| shell_print(shell, "ad data set..."); |
| err = ll_adv_aux_ad_data_set(handle, AD_OP, AD_FRAG_PREF, AD_LEN, |
| AD_DATA); |
| if (err) { |
| goto exit; |
| } |
| #endif |
| |
| disable: |
| shell_print(shell, "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); |
| #endif /* !CONFIG_BT_HCI_MESH_EXT */ |
| if (err) { |
| goto exit; |
| } |
| |
| exit: |
| shell_print(shell, "done (err= %d).", err); |
| |
| return 0; |
| } |
| #endif /* CONFIG_BT_BROADCASTER */ |
| |
| #if defined(CONFIG_BT_OBSERVER) |
| int cmd_scanx(const struct shell *shell, size_t argc, char *argv[]) |
| { |
| u8_t type = 0U; |
| u8_t enable; |
| s32_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(shell, "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(shell, "scan enable (%u)...", enable); |
| err = ll_scan_enable(enable); |
| if (err) { |
| goto exit; |
| } |
| |
| exit: |
| shell_print(shell, "done (err= %d).", err); |
| |
| return err; |
| } |
| #endif /* CONFIG_BT_OBSERVER */ |
| #endif /* CONFIG_BT_CTLR_ADV_EXT */ |
| |
| #if defined(CONFIG_BT_LL_SW_SPLIT) |
| int cmd_ull_reset(const struct shell *shell, size_t argc, char *argv[]) |
| { |
| ll_reset(); |
| |
| return 0; |
| } |
| |
| #endif /* CONFIG_BT_LL_SW_SPLIT */ |