Bluetooth: shell: Support a non-connectable build

Add conditional compilation and move code to support
building a non-connectable Bluetooth shell application.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2018-01-04 11:44:50 +01:00 committed by Johan Hedberg
commit 5f4a7ea119
4 changed files with 268 additions and 238 deletions

View file

@ -1,10 +1,17 @@
zephyr_library()
zephyr_library_sources(
bt.c
)
zephyr_library_sources_ifdef(
CONFIG_BT_CONN
gatt.c
)
zephyr_library_sources_ifdef(CONFIG_BT_CTLR
zephyr_library_sources_ifdef(
CONFIG_BT_CTLR
ll.c
ticker.c
)
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NRF5 flash.c)
zephyr_library_sources_ifdef(
CONFIG_SOC_FLASH_NRF5
flash.c
)

View file

@ -39,11 +39,14 @@
#define DATA_BREDR_MTU 48
#define BT_SHELL_MODULE "bt"
struct bt_conn *default_conn;
static bt_addr_le_t id_addr;
#if defined(CONFIG_BT_CONN)
struct bt_conn *default_conn;
/* Connection context for BR/EDR legacy pairing in sec mode 3 */
static struct bt_conn *pairing_conn;
#endif /* CONFIG_BT_CONN */
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
NET_BUF_POOL_DEFINE(data_tx_pool, 1, DATA_MTU, BT_BUF_USER_DATA_MIN, NULL);
@ -127,28 +130,6 @@ static struct bt_sdp_record spp_rec = BT_SDP_RECORD(spp_attrs);
#endif /* CONFIG_BT_RFCOMM */
static const char *current_prompt(void)
{
static char str[BT_ADDR_LE_STR_LEN + 2];
static struct bt_conn_info info;
if (!default_conn) {
return NULL;
}
if (bt_conn_get_info(default_conn, &info) < 0) {
return NULL;
}
if (info.type != BT_CONN_TYPE_LE) {
return NULL;
}
bt_addr_le_to_str(info.le.dst, str, sizeof(str) - 2);
strcat(str, "> ");
return str;
}
static void device_found(const bt_addr_le_t *addr, s8_t rssi, u8_t evtype,
struct net_buf_simple *buf)
{
@ -192,6 +173,36 @@ static void device_found(const bt_addr_le_t *addr, s8_t rssi, u8_t evtype,
rssi, name);
}
#if !defined(CONFIG_BT_CONN)
static const char *current_prompt(void)
{
return NULL;
}
#endif /* !CONFIG_BT_CONN */
#if defined(CONFIG_BT_CONN)
static const char *current_prompt(void)
{
static char str[BT_ADDR_LE_STR_LEN + 2];
static struct bt_conn_info info;
if (!default_conn) {
return NULL;
}
if (bt_conn_get_info(default_conn, &info) < 0) {
return NULL;
}
if (info.type != BT_CONN_TYPE_LE) {
return NULL;
}
bt_addr_le_to_str(info.le.dst, str, sizeof(str) - 2);
strcat(str, "> ");
return str;
}
static void conn_addr_str(struct bt_conn *conn, char *addr, size_t len)
{
struct bt_conn_info info;
@ -213,6 +224,60 @@ static void conn_addr_str(struct bt_conn *conn, char *addr, size_t len)
}
}
static void connected(struct bt_conn *conn, u8_t err)
{
char addr[BT_ADDR_LE_STR_LEN];
conn_addr_str(conn, addr, sizeof(addr));
if (err) {
printk("Failed to connect to %s (%u)\n", addr, err);
goto done;
}
printk("Connected: %s\n", addr);
if (!default_conn) {
default_conn = bt_conn_ref(conn);
}
done:
/* clear connection reference for sec mode 3 pairing */
if (pairing_conn) {
bt_conn_unref(pairing_conn);
pairing_conn = NULL;
}
}
static void disconnected(struct bt_conn *conn, u8_t reason)
{
char addr[BT_ADDR_LE_STR_LEN];
conn_addr_str(conn, addr, sizeof(addr));
printk("Disconnected: %s (reason %u)\n", addr, reason);
if (default_conn == conn) {
bt_conn_unref(default_conn);
default_conn = NULL;
}
}
static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
{
printk("LE conn param req: int (0x%04x, 0x%04x) lat %d to %d\n",
param->interval_min, param->interval_max, param->latency,
param->timeout);
return true;
}
static void le_param_updated(struct bt_conn *conn, u16_t interval,
u16_t latency, u16_t timeout)
{
printk("LE conn param updated: int 0x%04x lat %d to %d\n", interval,
latency, timeout);
}
#if defined(CONFIG_BT_BREDR)
static u8_t sdp_hfp_ag_user(struct bt_conn *conn,
struct bt_sdp_client_result *result)
@ -339,60 +404,6 @@ static struct bt_sdp_discover_params discov_a2src = {
static struct bt_sdp_discover_params discov;
#endif
static void connected(struct bt_conn *conn, u8_t err)
{
char addr[BT_ADDR_LE_STR_LEN];
conn_addr_str(conn, addr, sizeof(addr));
if (err) {
printk("Failed to connect to %s (%u)\n", addr, err);
goto done;
}
printk("Connected: %s\n", addr);
if (!default_conn) {
default_conn = bt_conn_ref(conn);
}
done:
/* clear connection reference for sec mode 3 pairing */
if (pairing_conn) {
bt_conn_unref(pairing_conn);
pairing_conn = NULL;
}
}
static void disconnected(struct bt_conn *conn, u8_t reason)
{
char addr[BT_ADDR_LE_STR_LEN];
conn_addr_str(conn, addr, sizeof(addr));
printk("Disconnected: %s (reason %u)\n", addr, reason);
if (default_conn == conn) {
bt_conn_unref(default_conn);
default_conn = NULL;
}
}
static bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param)
{
printk("LE conn param req: int (0x%04x, 0x%04x) lat %d to %d\n",
param->interval_min, param->interval_max, param->latency,
param->timeout);
return true;
}
static void le_param_updated(struct bt_conn *conn, u16_t interval,
u16_t latency, u16_t timeout)
{
printk("LE conn param updated: int 0x%04x lat %d to %d\n", interval,
latency, timeout);
}
#if defined(CONFIG_BT_SMP)
static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa,
const bt_addr_le_t *identity)
@ -429,6 +440,7 @@ static struct bt_conn_cb conn_callbacks = {
.security_changed = security_changed,
#endif
};
#endif /* CONFIG_BT_CONN */
static int char2hex(const char *c, u8_t *x)
{
@ -539,9 +551,11 @@ static void bt_ready(int err)
printk("Bluetooth initialized\n");
#if defined(CONFIG_BT_CONN)
default_conn = NULL;
bt_conn_cb_register(&conn_callbacks);
#endif /* CONFIG_BT_CONN */
}
static int cmd_init(int argc, char *argv[])
@ -667,6 +681,87 @@ static int cmd_scan(int argc, char *argv[])
return 0;
}
static const struct bt_data ad_discov[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
};
static const struct bt_data sd[] = {
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};
static int cmd_advertise(int argc, char *argv[])
{
struct bt_le_adv_param param;
const struct bt_data *ad, *scan_rsp;
size_t ad_len, scan_rsp_len;
int err;
if (argc < 2) {
goto fail;
}
if (!strcmp(argv[1], "off")) {
if (bt_le_adv_stop() < 0) {
printk("Failed to stop advertising\n");
} else {
printk("Advertising stopped\n");
}
return 0;
}
param.own_addr = NULL;
param.interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
param.interval_max = BT_GAP_ADV_FAST_INT_MAX_2;
if (!strcmp(argv[1], "on")) {
param.options = BT_LE_ADV_OPT_CONNECTABLE;
scan_rsp = sd;
scan_rsp_len = ARRAY_SIZE(sd);
} else if (!strcmp(argv[1], "scan")) {
param.options = 0;
scan_rsp = sd;
scan_rsp_len = ARRAY_SIZE(sd);
} else if (!strcmp(argv[1], "nconn")) {
param.options = 0;
scan_rsp = NULL;
scan_rsp_len = 0;
} else {
goto fail;
}
/* Parse advertisement data */
if (argc >= 3) {
const char *mode = argv[2];
if (!strcmp(mode, "discov")) {
ad = ad_discov;
ad_len = ARRAY_SIZE(ad_discov);
} else if (!strcmp(mode, "non_discov")) {
ad = NULL;
ad_len = 0;
} else {
goto fail;
}
} else {
ad = ad_discov;
ad_len = ARRAY_SIZE(ad_discov);
}
err = bt_le_adv_start(&param, ad, ad_len, scan_rsp, scan_rsp_len);
if (err < 0) {
printk("Failed to start advertising (err %d)\n", err);
} else {
printk("Advertising started\n");
}
return 0;
fail:
return -EINVAL;
}
#if defined(CONFIG_BT_CONN)
static int cmd_connect_le(int argc, char *argv[])
{
int err;
@ -819,6 +914,75 @@ static int cmd_conn_update(int argc, char *argv[])
return 0;
}
static int cmd_oob(int argc, char *argv[])
{
char addr[BT_ADDR_LE_STR_LEN];
struct bt_le_oob oob;
int err;
err = bt_le_oob_get_local(&oob);
if (err) {
printk("OOB data failed\n");
return 0;
}
bt_addr_le_to_str(&oob.addr, addr, sizeof(addr));
printk("OOB data:\n");
printk(" addr %s\n", addr);
return 0;
}
static int cmd_clear(int argc, char *argv[])
{
bt_addr_le_t addr;
int err;
if (argc < 2) {
printk("Specify remote address or \"all\"\n");
return 0;
}
if (strcmp(argv[1], "all") == 0) {
err = bt_storage_clear(NULL);
if (err) {
printk("Failed to clear storage (err %d)\n", err);
} else {
printk("Storage successfully cleared\n");
}
return 0;
}
if (argc < 3) {
#if defined(CONFIG_BT_BREDR)
addr.type = BT_ADDR_LE_PUBLIC;
err = str2bt_addr(argv[1], &addr.a);
#else
printk("Both address and address type needed\n");
return 0;
#endif
} else {
err = str2bt_addr_le(argv[1], argv[2], &addr);
}
if (err) {
printk("Invalid address\n");
return 0;
}
err = bt_storage_clear(&addr);
if (err) {
printk("Failed to clear storage (err %d)\n", err);
} else {
printk("Storage successfully cleared\n");
}
return 0;
}
#endif /* CONFIG_BT_CONN */
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
static int cmd_security(int argc, char *argv[])
{
@ -842,109 +1006,7 @@ static int cmd_security(int argc, char *argv[])
return 0;
}
#endif
static const struct bt_data ad_discov[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
};
static const struct bt_data sd[] = {
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};
static int cmd_advertise(int argc, char *argv[])
{
struct bt_le_adv_param param;
const struct bt_data *ad, *scan_rsp;
size_t ad_len, scan_rsp_len;
int err;
if (argc < 2) {
goto fail;
}
if (!strcmp(argv[1], "off")) {
if (bt_le_adv_stop() < 0) {
printk("Failed to stop advertising\n");
} else {
printk("Advertising stopped\n");
}
return 0;
}
param.own_addr = NULL;
param.interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
param.interval_max = BT_GAP_ADV_FAST_INT_MAX_2;
if (!strcmp(argv[1], "on")) {
param.options = BT_LE_ADV_OPT_CONNECTABLE;
scan_rsp = sd;
scan_rsp_len = ARRAY_SIZE(sd);
} else if (!strcmp(argv[1], "scan")) {
param.options = 0;
scan_rsp = sd;
scan_rsp_len = ARRAY_SIZE(sd);
} else if (!strcmp(argv[1], "nconn")) {
param.options = 0;
scan_rsp = NULL;
scan_rsp_len = 0;
} else {
goto fail;
}
/* Parse advertisement data */
if (argc >= 3) {
const char *mode = argv[2];
if (!strcmp(mode, "discov")) {
ad = ad_discov;
ad_len = ARRAY_SIZE(ad_discov);
} else if (!strcmp(mode, "non_discov")) {
ad = NULL;
ad_len = 0;
} else {
goto fail;
}
} else {
ad = ad_discov;
ad_len = ARRAY_SIZE(ad_discov);
}
err = bt_le_adv_start(&param, ad, ad_len, scan_rsp, scan_rsp_len);
if (err < 0) {
printk("Failed to start advertising (err %d)\n", err);
} else {
printk("Advertising started\n");
}
return 0;
fail:
return -EINVAL;
}
static int cmd_oob(int argc, char *argv[])
{
char addr[BT_ADDR_LE_STR_LEN];
struct bt_le_oob oob;
int err;
err = bt_le_oob_get_local(&oob);
if (err) {
printk("OOB data failed\n");
return 0;
}
bt_addr_le_to_str(&oob.addr, addr, sizeof(addr));
printk("OOB data:\n");
printk(" addr %s\n", addr);
return 0;
}
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
{
char addr[BT_ADDR_LE_STR_LEN];
@ -1346,54 +1408,6 @@ static int cmd_bredr_discovery(int argc, char *argv[])
#endif /* CONFIG_BT_BREDR */
static int cmd_clear(int argc, char *argv[])
{
bt_addr_le_t addr;
int err;
if (argc < 2) {
printk("Specify remote address or \"all\"\n");
return 0;
}
if (strcmp(argv[1], "all") == 0) {
err = bt_storage_clear(NULL);
if (err) {
printk("Failed to clear storage (err %d)\n", err);
} else {
printk("Storage successfully cleared\n");
}
return 0;
}
if (argc < 3) {
#if defined(CONFIG_BT_BREDR)
addr.type = BT_ADDR_LE_PUBLIC;
err = str2bt_addr(argv[1], &addr.a);
#else
printk("Both address and address type needed\n");
return 0;
#endif
} else {
err = str2bt_addr_le(argv[1], argv[2], &addr);
}
if (err) {
printk("Invalid address\n");
return 0;
}
err = bt_storage_clear(&addr);
if (err) {
printk("Failed to clear storage (err %d)\n", err);
} else {
printk("Storage successfully cleared\n");
}
return 0;
}
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
static void hexdump(const u8_t *data, size_t len)
{
@ -1972,6 +1986,7 @@ static const struct shell_cmd bt_commands[] = {
"<value: on, passive, off> <dup filter: dups, nodups>" },
{ "advertise", cmd_advertise,
"<type: off, on, scan, nconn> <mode: discov, non_discov>" },
#if defined(CONFIG_BT_CONN)
{ "connect", cmd_connect_le, HELP_ADDR_LE },
{ "disconnect", cmd_disconnect, HELP_NONE },
{ "auto-conn", cmd_auto_conn, HELP_ADDR_LE },
@ -2043,7 +2058,8 @@ static const struct shell_cmd bt_commands[] = {
{ "br-rfcomm-send", cmd_rfcomm_send, "<number of packets>"},
{ "br-rfcomm-disconnect", cmd_rfcomm_disconnect, HELP_NONE },
#endif /* CONFIG_BT_RFCOMM */
#endif
#endif /* CONFIG_BT_BREDR */
#endif /* CONFIG_BT_CONN */
#if defined(CONFIG_BT_CTLR_ADV_EXT)
{ "advx", cmd_advx, "<on off> [coded] [anon] [txp]" },
{ "scanx", cmd_scanx, "<on passive off> [coded]" },

View file

@ -2,5 +2,6 @@ include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
project(NONE)
zephyr_library_include_directories($ENV{ZEPHYR_BASE}/samples/bluetooth)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
target_sources(app PRIVATE src/main.c)
target_sources_ifdef(CONFIG_BT_CONN app PRIVATE src/hrs.c)

View file

@ -29,6 +29,7 @@
#define MY_SHELL_MODULE "btshell"
#if defined(CONFIG_BT_CONN)
static bool hrs_simulate;
static int cmd_hrs_simulate(int argc, char *argv[])
@ -58,13 +59,16 @@ static int cmd_hrs_simulate(int argc, char *argv[])
return 0;
}
#endif /* CONFIG_BT_CONN */
#define HELP_NONE "[none]"
#define HELP_ADDR_LE "<address: XX:XX:XX:XX:XX:XX> <type: (public|random)>"
static const struct shell_cmd commands[] = {
#if defined(CONFIG_BT_CONN)
{ "hrs-simulate", cmd_hrs_simulate,
"register and simulate Heart Rate Service <value: on, off>" },
#endif /* CONFIG_BT_CONN */
{ NULL, NULL }
};
@ -80,9 +84,11 @@ void main(void)
while (1) {
k_sleep(MSEC_PER_SEC);
#if defined(CONFIG_BT_CONN)
/* Heartrate measurements simulation */
if (hrs_simulate) {
hrs_notify();
}
#endif /* CONFIG_BT_CONN */
}
}