2017-05-22 10:17:22 +03:00
|
|
|
/** @file
|
|
|
|
* @brief Bluetooth shell module
|
|
|
|
*
|
|
|
|
* Provide some Bluetooth shell commands that can be useful to applications.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2017 Intel Corporation
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
#include <errno.h>
|
|
|
|
#include <zephyr/types.h>
|
|
|
|
#include <stddef.h>
|
2017-05-22 10:17:22 +03:00
|
|
|
#include <stdlib.h>
|
2017-05-22 11:49:31 +03:00
|
|
|
#include <string.h>
|
|
|
|
#include <misc/printk.h>
|
|
|
|
#include <misc/byteorder.h>
|
|
|
|
#include <zephyr.h>
|
|
|
|
|
2018-04-28 21:08:06 +03:00
|
|
|
#include <settings/settings.h>
|
|
|
|
|
2018-07-09 13:33:07 +03:00
|
|
|
#include <bluetooth/hci.h>
|
2017-05-22 11:49:31 +03:00
|
|
|
#include <bluetooth/bluetooth.h>
|
|
|
|
#include <bluetooth/conn.h>
|
|
|
|
#include <bluetooth/l2cap.h>
|
|
|
|
#include <bluetooth/rfcomm.h>
|
|
|
|
#include <bluetooth/sdp.h>
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
#include <shell/shell.h>
|
2017-05-22 10:17:22 +03:00
|
|
|
|
2017-05-29 12:54:56 +03:00
|
|
|
#include "bt.h"
|
2017-06-06 13:58:55 +02:00
|
|
|
#include "ll.h"
|
2017-05-29 12:54:56 +03:00
|
|
|
|
2017-08-09 09:21:11 +03:00
|
|
|
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
|
2017-05-22 11:49:31 +03:00
|
|
|
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
|
|
|
|
#define CREDITS 10
|
|
|
|
#define DATA_MTU (23 * CREDITS)
|
|
|
|
|
2018-07-16 15:11:08 +03:00
|
|
|
static u8_t selected_id = BT_ID_DEFAULT;
|
2018-09-24 10:59:23 +03:00
|
|
|
const struct shell *ctx_shell;
|
2018-07-16 15:11:08 +03:00
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
#if defined(CONFIG_BT_CONN)
|
|
|
|
struct bt_conn *default_conn;
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
/* Connection context for BR/EDR legacy pairing in sec mode 3 */
|
|
|
|
static struct bt_conn *pairing_conn;
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif /* CONFIG_BT_CONN */
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
|
2017-05-22 11:49:31 +03:00
|
|
|
NET_BUF_POOL_DEFINE(data_tx_pool, 1, DATA_MTU, BT_BUF_USER_DATA_MIN, NULL);
|
|
|
|
NET_BUF_POOL_DEFINE(data_rx_pool, 1, DATA_MTU, BT_BUF_USER_DATA_MIN, NULL);
|
|
|
|
#endif
|
|
|
|
|
2018-06-26 13:50:14 +03:00
|
|
|
#define NAME_LEN 30
|
|
|
|
|
|
|
|
static bool data_cb(struct bt_data *data, void *user_data)
|
|
|
|
{
|
|
|
|
char *name = user_data;
|
|
|
|
|
|
|
|
switch (data->type) {
|
|
|
|
case BT_DATA_NAME_SHORTENED:
|
|
|
|
case BT_DATA_NAME_COMPLETE:
|
|
|
|
memcpy(name, data->data, min(data->data_len, NAME_LEN - 1));
|
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
static void device_found(const bt_addr_le_t *addr, s8_t rssi, u8_t evtype,
|
|
|
|
struct net_buf_simple *buf)
|
|
|
|
{
|
|
|
|
char le_addr[BT_ADDR_LE_STR_LEN];
|
2018-06-26 13:50:14 +03:00
|
|
|
char name[NAME_LEN];
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-09-11 19:09:03 -07:00
|
|
|
(void)memset(name, 0, sizeof(name));
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-06-26 13:50:14 +03:00
|
|
|
bt_data_parse(buf, data_cb, name);
|
2017-05-22 11:49:31 +03:00
|
|
|
|
|
|
|
bt_addr_le_to_str(addr, le_addr, sizeof(le_addr));
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "[DEVICE]: %s, AD evt type %u, RSSI %i %s\n",
|
|
|
|
le_addr, evtype, rssi, name);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
#if !defined(CONFIG_BT_CONN)
|
2018-09-24 10:59:23 +03:00
|
|
|
#if 0 /* FIXME: Add support for changing prompt */
|
2018-01-04 11:44:50 +01:00
|
|
|
static const char *current_prompt(void)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-09-24 10:59:23 +03:00
|
|
|
#endif
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif /* !CONFIG_BT_CONN */
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CONN)
|
2018-09-24 10:59:23 +03:00
|
|
|
#if 0 /* FIXME: Add support for changing prompt */
|
2018-01-04 11:44:50 +01:00
|
|
|
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;
|
|
|
|
}
|
2018-09-24 10:59:23 +03:00
|
|
|
#endif
|
2018-01-04 11:44:50 +01:00
|
|
|
|
2018-09-25 14:24:25 +03:00
|
|
|
void conn_addr_str(struct bt_conn *conn, char *addr, size_t len)
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
struct bt_conn_info info;
|
|
|
|
|
|
|
|
if (bt_conn_get_info(conn, &info) < 0) {
|
|
|
|
addr[0] = '\0';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (info.type) {
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
case BT_CONN_TYPE_BR:
|
|
|
|
bt_addr_to_str(info.br.dst, addr, len);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case BT_CONN_TYPE_LE:
|
2018-08-23 12:07:56 +02:00
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, len);
|
2017-05-22 11:49:31 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
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) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(NULL, "Failed to connect to %s (%u)\n", addr,
|
|
|
|
err);
|
2018-01-04 11:44:50 +01:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Connected: %s\n", addr);
|
2018-01-04 11:44:50 +01:00
|
|
|
|
|
|
|
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));
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Disconnected: %s (reason %u)\n", addr, reason);
|
2018-01-04 11:44:50 +01:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "LE conn param req: int (0x%04x, 0x%04x) lat %d "
|
|
|
|
"to %d\n", param->interval_min, param->interval_max,
|
|
|
|
param->latency, param->timeout);
|
2018-01-04 11:44:50 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void le_param_updated(struct bt_conn *conn, u16_t interval,
|
|
|
|
u16_t latency, u16_t timeout)
|
|
|
|
{
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "LE conn param updated: int 0x%04x lat %d "
|
|
|
|
"to %d\n", interval, latency, timeout);
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
|
|
|
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_SMP)
|
2017-05-22 11:49:31 +03:00
|
|
|
static void identity_resolved(struct bt_conn *conn, const bt_addr_le_t *rpa,
|
|
|
|
const bt_addr_le_t *identity)
|
|
|
|
{
|
|
|
|
char addr_identity[BT_ADDR_LE_STR_LEN];
|
|
|
|
char addr_rpa[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(identity, addr_identity, sizeof(addr_identity));
|
|
|
|
bt_addr_le_to_str(rpa, addr_rpa, sizeof(addr_rpa));
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Identity resolved %s -> %s\n", addr_rpa,
|
|
|
|
addr_identity);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
static void security_changed(struct bt_conn *conn, bt_security_t level)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
conn_addr_str(conn, addr, sizeof(addr));
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Security changed: %s level %u\n", addr, level);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static struct bt_conn_cb conn_callbacks = {
|
|
|
|
.connected = connected,
|
|
|
|
.disconnected = disconnected,
|
|
|
|
.le_param_req = le_param_req,
|
|
|
|
.le_param_updated = le_param_updated,
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_SMP)
|
2017-05-22 11:49:31 +03:00
|
|
|
.identity_resolved = identity_resolved,
|
|
|
|
#endif
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
.security_changed = security_changed,
|
|
|
|
#endif
|
|
|
|
};
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif /* CONFIG_BT_CONN */
|
2017-05-22 11:49:31 +03:00
|
|
|
|
|
|
|
static int char2hex(const char *c, u8_t *x)
|
|
|
|
{
|
|
|
|
if (*c >= '0' && *c <= '9') {
|
|
|
|
*x = *c - '0';
|
|
|
|
} else if (*c >= 'a' && *c <= 'f') {
|
|
|
|
*x = *c - 'a' + 10;
|
|
|
|
} else if (*c >= 'A' && *c <= 'F') {
|
|
|
|
*x = *c - 'A' + 10;
|
|
|
|
} else {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-09-13 13:28:56 +02:00
|
|
|
static int hexstr2array(const char *str, u8_t *array, u8_t size)
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
u8_t tmp;
|
|
|
|
|
2018-09-13 13:28:56 +02:00
|
|
|
if (strlen(str) != ((size * 2) + (size - 1))) {
|
2017-05-22 11:49:31 +03:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2018-09-13 13:28:56 +02:00
|
|
|
for (i = size - 1, j = 1; *str != '\0'; str++, j++) {
|
2017-05-22 11:49:31 +03:00
|
|
|
if (!(j % 3) && (*str != ':')) {
|
|
|
|
return -EINVAL;
|
|
|
|
} else if (*str == ':') {
|
|
|
|
i--;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-09-13 13:28:56 +02:00
|
|
|
array[i] = array[i] << 4;
|
2017-05-22 11:49:31 +03:00
|
|
|
|
|
|
|
if (char2hex(str, &tmp) < 0) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2018-09-13 13:28:56 +02:00
|
|
|
array[i] |= tmp;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-09-25 14:24:25 +03:00
|
|
|
int str2bt_addr(const char *str, bt_addr_t *addr)
|
2018-09-13 13:28:56 +02:00
|
|
|
{
|
|
|
|
return hexstr2array(str, addr->val, 6);
|
|
|
|
}
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
static int str2bt_addr_le(const char *str, const char *type, bt_addr_le_t *addr)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = str2bt_addr(str, &addr->a);
|
|
|
|
if (err < 0) {
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(type, "public") || !strcmp(type, "(public)")) {
|
|
|
|
addr->type = BT_ADDR_LE_PUBLIC;
|
|
|
|
} else if (!strcmp(type, "random") || !strcmp(type, "(random)")) {
|
|
|
|
addr->type = BT_ADDR_LE_RANDOM;
|
|
|
|
} else {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void bt_ready(int err)
|
|
|
|
{
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(NULL, "Bluetooth init failed (err %d)\n", err);
|
2017-05-22 11:49:31 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Bluetooth initialized\n");
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-04-28 21:08:06 +03:00
|
|
|
if (IS_ENABLED(CONFIG_SETTINGS)) {
|
|
|
|
settings_load();
|
|
|
|
}
|
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
#if defined(CONFIG_BT_CONN)
|
2017-05-29 12:54:56 +03:00
|
|
|
default_conn = NULL;
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
bt_conn_cb_register(&conn_callbacks);
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif /* CONFIG_BT_CONN */
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_init(const struct shell *shell, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = bt_enable(bt_ready);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Bluetooth init failed (err %d)\n", err);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
ctx_shell = shell;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-07-09 13:33:07 +03:00
|
|
|
#if defined(CONFIG_BT_HCI) || defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
|
2018-09-24 10:59:23 +03:00
|
|
|
static void hexdump(const struct shell *shell, const u8_t *data, size_t len)
|
2018-07-09 13:33:07 +03:00
|
|
|
{
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
while (len--) {
|
|
|
|
if (n % 16 == 0) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "%08X ", n);
|
2018-07-09 13:33:07 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "%02X ", *data++);
|
2018-07-09 13:33:07 +03:00
|
|
|
|
|
|
|
n++;
|
|
|
|
if (n % 8 == 0) {
|
|
|
|
if (n % 16 == 0) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "\n");
|
2018-07-09 13:33:07 +03:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, " ");
|
2018-07-09 13:33:07 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n % 16) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "\n");
|
2018-07-09 13:33:07 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BT_HCI || CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_HCI)
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_hci_cmd(const struct shell *shell, size_t argc, char *argv[])
|
2018-07-09 13:33:07 +03:00
|
|
|
{
|
|
|
|
u8_t ogf;
|
|
|
|
u16_t ocf;
|
|
|
|
struct net_buf *buf = NULL, *rsp;
|
|
|
|
int err;
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
if (!shell_cmd_precheck(shell, (argc == 3), NULL, 0)) {
|
|
|
|
return;
|
2018-07-09 13:33:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
ogf = strtoul(argv[1], NULL, 16);
|
|
|
|
ocf = strtoul(argv[2], NULL, 16);
|
|
|
|
|
|
|
|
if (argc > 3) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
buf = bt_hci_cmd_create(BT_OP(ogf, ocf), argc - 3);
|
|
|
|
|
|
|
|
for (i = 3; i < argc; i++) {
|
|
|
|
net_buf_add_u8(buf, strtoul(argv[i], NULL, 16));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_hci_cmd_send_sync(BT_OP(ogf, ocf), buf, &rsp);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "HCI command failed (err %d)\n", err);
|
2018-07-09 13:33:07 +03:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
hexdump(shell, rsp->data, rsp->len);
|
2018-07-09 13:33:07 +03:00
|
|
|
net_buf_unref(rsp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_BT_HCI */
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_name(const struct shell *shell, size_t argc, char *argv[])
|
2018-07-17 13:55:47 +03:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argc < 2) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Bluetooth Local Name: %s\n", bt_get_name());
|
2018-07-17 13:55:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_set_name(argv[1]);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Unable to set name %s (err %d)", argv[1], err);
|
2018-07-17 13:55:47 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_id_create(const struct shell *shell, size_t argc, char *argv[])
|
2018-07-16 15:11:08 +03:00
|
|
|
{
|
|
|
|
bt_addr_le_t addr;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argc > 1) {
|
|
|
|
err = str2bt_addr_le(argv[1], "random", &addr);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Invalid address\n");
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
bt_addr_le_copy(&addr, BT_ADDR_LE_ANY);
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_id_create(&addr, NULL);
|
|
|
|
if (err < 0) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Creating new ID failed (err %d)\n", err);
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "New identity (%d) created: %s\n", err,
|
|
|
|
bt_addr_le_str(&addr));
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_id_reset(const struct shell *shell, size_t argc, char *argv[])
|
2018-07-16 15:11:08 +03:00
|
|
|
{
|
|
|
|
bt_addr_le_t addr;
|
|
|
|
u8_t id;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argc < 2) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Identity identifier not specified\n");
|
|
|
|
return;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
id = strtol(argv[1], NULL, 10);
|
|
|
|
|
|
|
|
if (argc > 2) {
|
|
|
|
err = str2bt_addr_le(argv[2], "random", &addr);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Invalid address\n");
|
|
|
|
return;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
bt_addr_le_copy(&addr, BT_ADDR_LE_ANY);
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_id_reset(id, &addr, NULL);
|
|
|
|
if (err < 0) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Resetting ID %u failed (err %d)\n", id, err);
|
|
|
|
return;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Identity %u reset: %s\n", id, bt_addr_le_str(&addr));
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_id_delete(const struct shell *shell, size_t argc, char *argv[])
|
2018-08-02 12:34:39 +03:00
|
|
|
{
|
|
|
|
u8_t id;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argc < 2) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Identity identifier not specified\n");
|
|
|
|
return;
|
2018-08-02 12:34:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
id = strtol(argv[1], NULL, 10);
|
|
|
|
|
|
|
|
err = bt_id_delete(id);
|
|
|
|
if (err < 0) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Deleting ID %u failed (err %d)\n", id, err);
|
|
|
|
return;
|
2018-08-02 12:34:39 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Identity %u deleted\n", id);
|
2018-08-02 12:34:39 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_id_show(const struct shell *shell, size_t argc, char *argv[])
|
2018-07-16 15:11:08 +03:00
|
|
|
{
|
|
|
|
bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
|
|
|
|
size_t i, count = CONFIG_BT_ID_MAX;
|
|
|
|
|
|
|
|
bt_id_get(addrs, &count);
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "%s%zu: %s\n", i == selected_id ? "*" : " ", i,
|
|
|
|
bt_addr_le_str(&addrs[i]));
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_id_select(const struct shell *shell, size_t argc, char *argv[])
|
2018-07-16 15:11:08 +03:00
|
|
|
{
|
|
|
|
bt_addr_le_t addrs[CONFIG_BT_ID_MAX];
|
|
|
|
size_t count = CONFIG_BT_ID_MAX;
|
|
|
|
u8_t id;
|
|
|
|
|
|
|
|
if (argc < 2) {
|
2018-09-24 10:59:23 +03:00
|
|
|
shell_help_print(shell, NULL, 0);
|
|
|
|
return;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
id = strtol(argv[1], NULL, 10);
|
|
|
|
|
|
|
|
bt_id_get(addrs, &count);
|
|
|
|
if (count <= id) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Invalid identity\n");
|
|
|
|
return;
|
2018-07-16 15:11:08 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Selected identity: %s\n",
|
|
|
|
bt_addr_le_str(&addrs[id]));
|
2018-07-16 15:11:08 +03:00
|
|
|
selected_id = id;
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_active_scan_on(const struct shell *shell, int dups)
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
struct bt_le_scan_param param = {
|
2017-05-28 23:11:54 +02:00
|
|
|
.type = BT_HCI_LE_SCAN_ACTIVE,
|
2017-05-22 11:49:31 +03:00
|
|
|
.filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE,
|
|
|
|
.interval = BT_GAP_SCAN_FAST_INTERVAL,
|
|
|
|
.window = BT_GAP_SCAN_FAST_WINDOW };
|
|
|
|
|
|
|
|
if (dups >= 0) {
|
|
|
|
param.filter_dup = dups;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_le_scan_start(¶m, device_found);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Bluetooth set active scan failed "
|
|
|
|
"(err %d)\n", err);
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Bluetooth active scan enabled\n");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_passive_scan_on(const struct shell *shell, int dups)
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
struct bt_le_scan_param param = {
|
|
|
|
.type = BT_HCI_LE_SCAN_PASSIVE,
|
|
|
|
.filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE,
|
|
|
|
.interval = 0x10,
|
|
|
|
.window = 0x10 };
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (dups >= 0) {
|
|
|
|
param.filter_dup = dups;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_le_scan_start(¶m, device_found);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Bluetooth set passive scan failed "
|
|
|
|
"(err %d)\n", err);
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Bluetooth passive scan enabled\n");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_scan_off(const struct shell *shell)
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = bt_le_scan_stop();
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Stopping scanning failed (err %d)\n", err);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Scan successfully stopped\n");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_scan(const struct shell *shell, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
const char *action;
|
|
|
|
int dups = -1;
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
if (!shell_cmd_precheck(shell, (argc >= 2), NULL, 0)) {
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse duplicate filtering data */
|
|
|
|
if (argc >= 3) {
|
|
|
|
const char *dup_filter = argv[2];
|
|
|
|
|
|
|
|
if (!strcmp(dup_filter, "dups")) {
|
|
|
|
dups = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE;
|
|
|
|
} else if (!strcmp(dup_filter, "nodups")) {
|
|
|
|
dups = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE;
|
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
shell_help_print(shell, NULL, 0);
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
action = argv[1];
|
|
|
|
if (!strcmp(action, "on")) {
|
2018-09-24 10:59:23 +03:00
|
|
|
cmd_active_scan_on(shell, dups);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else if (!strcmp(action, "off")) {
|
2018-09-24 10:59:23 +03:00
|
|
|
cmd_scan_off(shell);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else if (!strcmp(action, "passive")) {
|
2018-09-24 10:59:23 +03:00
|
|
|
cmd_passive_scan_on(shell, dups);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
shell_help_print(shell, NULL, 0);
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
static const struct bt_data ad_discov[] = {
|
|
|
|
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
|
|
|
};
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_advertise(const struct shell *shell, size_t argc, char *argv[])
|
2018-01-04 11:44:50 +01:00
|
|
|
{
|
|
|
|
struct bt_le_adv_param param;
|
|
|
|
const struct bt_data *ad, *scan_rsp;
|
|
|
|
size_t ad_len, scan_rsp_len;
|
|
|
|
int err;
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
if (!shell_cmd_precheck(shell, (argc >= 2), NULL, 0)) {
|
|
|
|
return;
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(argv[1], "off")) {
|
|
|
|
if (bt_le_adv_stop() < 0) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Failed to stop advertising\n");
|
2018-01-04 11:44:50 +01:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Advertising stopped\n");
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
return;
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
|
|
|
|
2018-07-16 15:11:08 +03:00
|
|
|
param.id = selected_id;
|
2018-01-04 11:44:50 +01:00
|
|
|
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")) {
|
2018-07-17 13:34:27 +03:00
|
|
|
param.options = (BT_LE_ADV_OPT_CONNECTABLE |
|
|
|
|
BT_LE_ADV_OPT_USE_NAME);
|
2018-01-04 11:44:50 +01:00
|
|
|
} else if (!strcmp(argv[1], "scan")) {
|
2018-07-17 13:34:27 +03:00
|
|
|
param.options = BT_LE_ADV_OPT_USE_NAME;
|
2018-01-04 11:44:50 +01:00
|
|
|
} 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(¶m, ad, ad_len, scan_rsp, scan_rsp_len);
|
|
|
|
if (err < 0) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Failed to start advertising (err %d)\n",
|
|
|
|
err);
|
2018-01-04 11:44:50 +01:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Advertising started\n");
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
return;
|
2018-01-04 11:44:50 +01:00
|
|
|
|
|
|
|
fail:
|
2018-09-24 10:59:23 +03:00
|
|
|
shell_help_print(shell, NULL, 0);
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(CONFIG_BT_CONN)
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_connect_le(const struct shell *shell, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
bt_addr_le_t addr;
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
if (argc < 3) {
|
2018-09-24 10:59:23 +03:00
|
|
|
shell_help_print(shell, NULL, 0);
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
err = str2bt_addr_le(argv[1], argv[2], &addr);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Invalid peer address (err %d)\n", err);
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
conn = bt_conn_create_le(&addr, BT_LE_CONN_PARAM_DEFAULT);
|
|
|
|
|
|
|
|
if (!conn) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Connection failed\n");
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Connection pending\n");
|
2017-05-22 11:49:31 +03:00
|
|
|
|
|
|
|
/* unref connection obj in advance as app user */
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_disconnect(const struct shell *shell, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
struct bt_conn *conn;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (default_conn && argc < 3) {
|
|
|
|
conn = bt_conn_ref(default_conn);
|
|
|
|
} else {
|
|
|
|
bt_addr_le_t addr;
|
|
|
|
|
|
|
|
if (argc < 3) {
|
2018-09-24 10:59:23 +03:00
|
|
|
shell_help_print(shell, NULL, 0);
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
err = str2bt_addr_le(argv[1], argv[2], &addr);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Invalid peer address (err %d)\n",
|
|
|
|
err);
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-07-16 15:11:08 +03:00
|
|
|
conn = bt_conn_lookup_addr_le(selected_id, &addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!conn) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Not connected\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Disconnection failed (err %d)\n", err);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_auto_conn(const struct shell *shell, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
bt_addr_le_t addr;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argc < 3) {
|
2018-09-24 10:59:23 +03:00
|
|
|
shell_help_print(shell, NULL, 0);
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
err = str2bt_addr_le(argv[1], argv[2], &addr);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Invalid peer address (err %d)\n", err);
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (argc < 4) {
|
|
|
|
bt_le_set_auto_conn(&addr, BT_LE_CONN_PARAM_DEFAULT);
|
|
|
|
} else if (!strcmp(argv[3], "on")) {
|
|
|
|
bt_le_set_auto_conn(&addr, BT_LE_CONN_PARAM_DEFAULT);
|
|
|
|
} else if (!strcmp(argv[3], "off")) {
|
|
|
|
bt_le_set_auto_conn(&addr, NULL);
|
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
shell_help_print(shell, NULL, 0);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_directed_adv(const struct shell *shell,
|
|
|
|
size_t argc, char *argv[])
|
2018-08-23 12:07:56 +02:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
bt_addr_le_t addr;
|
|
|
|
struct bt_conn *conn;
|
|
|
|
struct bt_le_adv_param *param = BT_LE_ADV_CONN_DIR;
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
if (!shell_cmd_precheck(shell, (argc >= 2), NULL, 0)) {
|
|
|
|
return;
|
2018-08-23 12:07:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
err = str2bt_addr_le(argv[1], argv[2], &addr);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Invalid peer address (err %d)\n", err);
|
|
|
|
return;
|
2018-08-23 12:07:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (argc > 3) {
|
|
|
|
if (!strcmp(argv[3], "low")) {
|
|
|
|
param = BT_LE_ADV_CONN_DIR_LOW_DUTY;
|
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
shell_help_print(shell, NULL, 0);
|
|
|
|
return;
|
2018-08-23 12:07:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
conn = bt_conn_create_slave_le(&addr, param);
|
|
|
|
if (!conn) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Failed to start directed advertising\n");
|
2018-08-23 12:07:56 +02:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Started directed advertising\n");
|
2018-08-23 12:07:56 +02:00
|
|
|
|
|
|
|
/* unref connection obj in advance as app user */
|
|
|
|
bt_conn_unref(conn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_select(const struct shell *shell, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
struct bt_conn *conn;
|
|
|
|
bt_addr_le_t addr;
|
|
|
|
int err;
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
if (!shell_cmd_precheck(shell, argc == 3, NULL, 0)) {
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
err = str2bt_addr_le(argv[1], argv[2], &addr);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Invalid peer address (err %d)\n", err);
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-07-04 12:58:10 +03:00
|
|
|
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, &addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
if (!conn) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "No matching connection found\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (default_conn) {
|
|
|
|
bt_conn_unref(default_conn);
|
|
|
|
}
|
|
|
|
|
|
|
|
default_conn = conn;
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_conn_update(const struct shell *shell,
|
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
struct bt_le_conn_param param;
|
|
|
|
int err;
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
if (!shell_cmd_precheck(shell, argc == 5, NULL, 0)) {
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
param.interval_min = strtoul(argv[1], NULL, 16);
|
|
|
|
param.interval_max = strtoul(argv[2], NULL, 16);
|
|
|
|
param.latency = strtoul(argv[3], NULL, 16);
|
|
|
|
param.timeout = strtoul(argv[4], NULL, 16);
|
|
|
|
|
|
|
|
err = bt_conn_le_param_update(default_conn, ¶m);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "conn update failed (err %d).\n", err);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "conn update initiated.\n");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_oob(const struct shell *shell, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
2018-01-04 11:44:50 +01:00
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
struct bt_le_oob oob;
|
|
|
|
int err;
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-07-16 15:11:08 +03:00
|
|
|
err = bt_le_oob_get_local(selected_id, &oob);
|
2018-01-04 11:44:50 +01:00
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "OOB data failed\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
bt_addr_le_to_str(&oob.addr, addr, sizeof(addr));
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "OOB data:\n");
|
|
|
|
print(shell, " addr %s\n", addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_clear(const struct shell *shell, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
2018-01-04 11:44:50 +01:00
|
|
|
bt_addr_le_t addr;
|
2017-05-22 11:49:31 +03:00
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argc < 2) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Specify remote address or \"all\"\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
if (strcmp(argv[1], "all") == 0) {
|
2018-07-16 15:11:08 +03:00
|
|
|
err = bt_unpair(selected_id, NULL);
|
2018-01-04 11:44:50 +01:00
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Failed to clear pairings (err %d)\n",
|
|
|
|
err);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Pairings successfully cleared\n");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
if (argc < 3) {
|
|
|
|
#if defined(CONFIG_BT_BREDR)
|
|
|
|
addr.type = BT_ADDR_LE_PUBLIC;
|
|
|
|
err = str2bt_addr(argv[1], &addr.a);
|
|
|
|
#else
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Both address and address type needed\n");
|
|
|
|
return;
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2018-01-04 11:44:50 +01:00
|
|
|
err = str2bt_addr_le(argv[1], argv[2], &addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Invalid address\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-07-16 15:11:08 +03:00
|
|
|
err = bt_unpair(selected_id, &addr);
|
2018-01-04 11:44:50 +01:00
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Failed to clear pairing (err %d)\n", err);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Pairing successfully cleared\n");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
2018-09-13 13:28:56 +02:00
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_chan_map(const struct shell *shell, size_t argc, char *argv[])
|
2018-09-13 13:28:56 +02:00
|
|
|
{
|
|
|
|
u8_t chan_map[5];
|
|
|
|
int err;
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
if (!shell_cmd_precheck(shell, argc == 2, NULL, 0)) {
|
|
|
|
return;
|
2018-09-13 13:28:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
err = hexstr2array(argv[1], chan_map, 5);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Invalid channel map\n");
|
|
|
|
return;
|
2018-09-13 13:28:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_le_set_chan_map(chan_map);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Failed to set channel map (err %d)\n", err);
|
2018-09-13 13:28:56 +02:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Channel map set\n");
|
2018-09-13 13:28:56 +02:00
|
|
|
}
|
|
|
|
}
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif /* CONFIG_BT_CONN */
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_security(const struct shell *shell, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
2018-01-04 11:44:50 +01:00
|
|
|
int err, sec;
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
if (!default_conn) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Not connected\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
if (!shell_cmd_precheck(shell, argc == 2, NULL, 0)) {
|
|
|
|
return;
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-01-04 11:44:50 +01:00
|
|
|
sec = *argv[1] - '0';
|
|
|
|
|
|
|
|
err = bt_conn_security(default_conn, sec);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Setting security failed (err %d)\n", err);
|
2018-01-04 11:44:50 +01:00
|
|
|
}
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_bondable(const struct shell *shell, size_t argc, char *argv[])
|
2018-09-18 09:44:57 +02:00
|
|
|
{
|
|
|
|
const char *bondable;
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
if (!shell_cmd_precheck(shell, argc == 2, NULL, 0)) {
|
|
|
|
return;
|
2018-09-18 09:44:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bondable = argv[1];
|
|
|
|
if (!strcmp(bondable, "on")) {
|
|
|
|
bt_set_bondable(true);
|
|
|
|
} else if (!strcmp(bondable, "off")) {
|
|
|
|
bt_set_bondable(false);
|
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
shell_help_print(shell, NULL, 0);
|
2018-09-18 09:44:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
char passkey_str[7];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, passkey_str, 7, "%06u", passkey);
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Passkey for %s: %s\n", addr, passkey_str);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void auth_passkey_confirm(struct bt_conn *conn, unsigned int passkey)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
char passkey_str[7];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, passkey_str, 7, "%06u", passkey);
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Confirm passkey for %s: %s\n", addr, passkey_str);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void auth_passkey_entry(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Enter passkey for %s\n", addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void auth_cancel(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
conn_addr_str(conn, addr, sizeof(addr));
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Pairing cancelled: %s\n", addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
|
|
|
|
/* clear connection reference for sec mode 3 pairing */
|
|
|
|
if (pairing_conn) {
|
|
|
|
bt_conn_unref(pairing_conn);
|
|
|
|
pairing_conn = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void auth_pairing_confirm(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Confirm pairing for %s\n", addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-07-31 10:48:32 +03:00
|
|
|
static void auth_pairing_complete(struct bt_conn *conn, bool bonded)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "%s with %s\n", bonded ? "Bonded" : "Paired", addr);
|
2018-07-31 10:48:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void auth_pairing_failed(struct bt_conn *conn)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_LE_STR_LEN];
|
|
|
|
|
|
|
|
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Pairing failed with %s\n", addr);
|
2018-07-31 10:48:32 +03:00
|
|
|
}
|
|
|
|
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
static void auth_pincode_entry(struct bt_conn *conn, bool highsec)
|
|
|
|
{
|
|
|
|
char addr[BT_ADDR_STR_LEN];
|
|
|
|
struct bt_conn_info info;
|
|
|
|
|
|
|
|
if (bt_conn_get_info(conn, &info) < 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info.type != BT_CONN_TYPE_BR) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bt_addr_to_str(info.br.dst, addr, sizeof(addr));
|
|
|
|
|
|
|
|
if (highsec) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Enter 16 digits wide PIN code for %s\n",
|
|
|
|
addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Enter PIN code for %s\n", addr);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Save connection info since in security mode 3 (link level enforced
|
|
|
|
* security) PIN request callback is called before connected callback
|
|
|
|
*/
|
|
|
|
if (!default_conn && !pairing_conn) {
|
|
|
|
pairing_conn = bt_conn_ref(conn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static struct bt_conn_auth_cb auth_cb_display = {
|
|
|
|
.passkey_display = auth_passkey_display,
|
|
|
|
.passkey_entry = NULL,
|
|
|
|
.passkey_confirm = NULL,
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
.pincode_entry = auth_pincode_entry,
|
|
|
|
#endif
|
|
|
|
.cancel = auth_cancel,
|
|
|
|
.pairing_confirm = auth_pairing_confirm,
|
2018-07-31 10:48:32 +03:00
|
|
|
.pairing_failed = auth_pairing_failed,
|
|
|
|
.pairing_complete = auth_pairing_complete,
|
2017-05-22 11:49:31 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct bt_conn_auth_cb auth_cb_display_yes_no = {
|
|
|
|
.passkey_display = auth_passkey_display,
|
|
|
|
.passkey_entry = NULL,
|
|
|
|
.passkey_confirm = auth_passkey_confirm,
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
.pincode_entry = auth_pincode_entry,
|
|
|
|
#endif
|
|
|
|
.cancel = auth_cancel,
|
|
|
|
.pairing_confirm = auth_pairing_confirm,
|
2018-07-31 10:48:32 +03:00
|
|
|
.pairing_failed = auth_pairing_failed,
|
|
|
|
.pairing_complete = auth_pairing_complete,
|
2017-05-22 11:49:31 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct bt_conn_auth_cb auth_cb_input = {
|
|
|
|
.passkey_display = NULL,
|
|
|
|
.passkey_entry = auth_passkey_entry,
|
|
|
|
.passkey_confirm = NULL,
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
.pincode_entry = auth_pincode_entry,
|
|
|
|
#endif
|
|
|
|
.cancel = auth_cancel,
|
|
|
|
.pairing_confirm = auth_pairing_confirm,
|
2018-07-31 10:48:32 +03:00
|
|
|
.pairing_failed = auth_pairing_failed,
|
|
|
|
.pairing_complete = auth_pairing_complete,
|
2017-05-22 11:49:31 +03:00
|
|
|
};
|
|
|
|
|
2018-07-31 10:50:54 +03:00
|
|
|
static struct bt_conn_auth_cb auth_cb_confirm = {
|
|
|
|
#if defined(CONFIG_BT_BREDR)
|
|
|
|
.pincode_entry = auth_pincode_entry,
|
|
|
|
#endif
|
|
|
|
.cancel = auth_cancel,
|
|
|
|
.pairing_confirm = auth_pairing_confirm,
|
|
|
|
.pairing_failed = auth_pairing_failed,
|
|
|
|
.pairing_complete = auth_pairing_complete,
|
|
|
|
};
|
|
|
|
|
2017-05-22 11:49:31 +03:00
|
|
|
static struct bt_conn_auth_cb auth_cb_all = {
|
|
|
|
.passkey_display = auth_passkey_display,
|
|
|
|
.passkey_entry = auth_passkey_entry,
|
|
|
|
.passkey_confirm = auth_passkey_confirm,
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_BREDR)
|
2017-05-22 11:49:31 +03:00
|
|
|
.pincode_entry = auth_pincode_entry,
|
|
|
|
#endif
|
|
|
|
.cancel = auth_cancel,
|
|
|
|
.pairing_confirm = auth_pairing_confirm,
|
2018-07-31 10:48:32 +03:00
|
|
|
.pairing_failed = auth_pairing_failed,
|
|
|
|
.pairing_complete = auth_pairing_complete,
|
2017-05-22 11:49:31 +03:00
|
|
|
};
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_auth(const struct shell *shell, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
2018-09-24 10:59:23 +03:00
|
|
|
if (!shell_cmd_precheck(shell, argc == 2, NULL, 0)) {
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(argv[1], "all")) {
|
|
|
|
bt_conn_auth_cb_register(&auth_cb_all);
|
|
|
|
} else if (!strcmp(argv[1], "input")) {
|
|
|
|
bt_conn_auth_cb_register(&auth_cb_input);
|
|
|
|
} else if (!strcmp(argv[1], "display")) {
|
|
|
|
bt_conn_auth_cb_register(&auth_cb_display);
|
|
|
|
} else if (!strcmp(argv[1], "yesno")) {
|
|
|
|
bt_conn_auth_cb_register(&auth_cb_display_yes_no);
|
2018-07-31 10:50:54 +03:00
|
|
|
} else if (!strcmp(argv[1], "confirm")) {
|
|
|
|
bt_conn_auth_cb_register(&auth_cb_confirm);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else if (!strcmp(argv[1], "none")) {
|
|
|
|
bt_conn_auth_cb_register(NULL);
|
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
shell_help_print(shell, NULL, 0);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_auth_cancel(const struct shell *shell,
|
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
struct bt_conn *conn;
|
|
|
|
|
|
|
|
if (default_conn) {
|
|
|
|
conn = default_conn;
|
|
|
|
} else if (pairing_conn) {
|
|
|
|
conn = pairing_conn;
|
|
|
|
} else {
|
|
|
|
conn = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!conn) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Not connected\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_auth_cancel(conn);
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_auth_passkey_confirm(const struct shell *shell,
|
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
if (!default_conn) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Not connected\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_auth_passkey_confirm(default_conn);
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_auth_pairing_confirm(const struct shell *shell,
|
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
if (!default_conn) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Not connected\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_auth_pairing_confirm(default_conn);
|
|
|
|
}
|
|
|
|
|
2018-07-30 20:30:26 +03:00
|
|
|
#if defined(CONFIG_BT_FIXED_PASSKEY)
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_fixed_passkey(const struct shell *shell,
|
|
|
|
size_t argc, char *argv[])
|
2018-07-30 20:30:26 +03:00
|
|
|
{
|
|
|
|
unsigned int passkey;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (argc < 2) {
|
|
|
|
bt_passkey_set(BT_PASSKEY_INVALID);
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Fixed passkey cleared\n");
|
|
|
|
return;
|
2018-07-30 20:30:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
passkey = atoi(argv[1]);
|
|
|
|
if (passkey > 999999) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Passkey should be between 0-999999\n");
|
|
|
|
return;
|
2018-07-30 20:30:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
err = bt_passkey_set(passkey);
|
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Setting fixed passkey failed (err %d)\n", err);
|
2018-07-30 20:30:26 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_auth_passkey(const struct shell *shell,
|
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
unsigned int passkey;
|
|
|
|
|
|
|
|
if (!default_conn) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Not connected\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
if (!shell_cmd_precheck(shell, argc == 2, NULL, 0)) {
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
passkey = atoi(argv[1]);
|
|
|
|
if (passkey > 999999) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Passkey should be between 0-999999\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bt_conn_auth_passkey_entry(default_conn, passkey);
|
|
|
|
}
|
2017-08-09 09:21:11 +03:00
|
|
|
#endif /* CONFIG_BT_SMP) || CONFIG_BT_BREDR */
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
|
2017-05-22 11:49:31 +03:00
|
|
|
static u32_t l2cap_rate;
|
2018-09-17 14:30:35 +03:00
|
|
|
static u32_t l2cap_recv_delay;
|
|
|
|
static K_FIFO_DEFINE(l2cap_recv_fifo);
|
|
|
|
struct l2ch {
|
|
|
|
struct k_delayed_work recv_work;
|
|
|
|
struct bt_l2cap_le_chan ch;
|
|
|
|
};
|
|
|
|
#define L2CH_CHAN(_chan) CONTAINER_OF(_chan, struct l2ch, ch.chan)
|
|
|
|
#define L2CH_WORK(_work) CONTAINER_OF(_work, struct l2ch, recv_work)
|
|
|
|
#define L2CAP_CHAN(_chan) _chan->ch.chan
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-08-22 13:16:14 +03:00
|
|
|
static int l2cap_recv_metrics(struct bt_l2cap_chan *chan, struct net_buf *buf)
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
static u32_t len;
|
|
|
|
static u32_t cycle_stamp;
|
|
|
|
u32_t delta;
|
|
|
|
|
|
|
|
delta = k_cycle_get_32() - cycle_stamp;
|
|
|
|
delta = SYS_CLOCK_HW_CYCLES_TO_NS(delta);
|
|
|
|
|
|
|
|
/* if last data rx-ed was greater than 1 second in the past,
|
|
|
|
* reset the metrics.
|
|
|
|
*/
|
|
|
|
if (delta > 1000000000) {
|
|
|
|
len = 0;
|
|
|
|
l2cap_rate = 0;
|
|
|
|
cycle_stamp = k_cycle_get_32();
|
|
|
|
} else {
|
|
|
|
len += buf->len;
|
|
|
|
l2cap_rate = ((u64_t)len << 3) * 1000000000 / delta;
|
|
|
|
}
|
2018-08-22 13:16:14 +03:00
|
|
|
|
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-09-17 14:30:35 +03:00
|
|
|
static void l2cap_recv_cb(struct k_work *work)
|
|
|
|
{
|
|
|
|
struct l2ch *c = L2CH_WORK(work);
|
|
|
|
struct net_buf *buf;
|
|
|
|
|
|
|
|
while ((buf = net_buf_get(&l2cap_recv_fifo, K_NO_WAIT))) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Confirming reception\n");
|
2018-09-17 14:30:35 +03:00
|
|
|
bt_l2cap_chan_recv_complete(&c->ch.chan, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-22 13:16:14 +03:00
|
|
|
static int l2cap_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
2018-09-17 14:30:35 +03:00
|
|
|
struct l2ch *l2ch = L2CH_CHAN(chan);
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Incoming data channel %p len %u\n", chan, buf->len);
|
2017-05-22 11:49:31 +03:00
|
|
|
|
|
|
|
if (buf->len) {
|
2018-09-24 10:59:23 +03:00
|
|
|
hexdump(ctx_shell, buf->data, buf->len);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
2018-08-22 13:16:14 +03:00
|
|
|
|
2018-09-17 14:30:35 +03:00
|
|
|
if (l2cap_recv_delay) {
|
|
|
|
/* Submit work only if queue is empty */
|
|
|
|
if (k_fifo_is_empty(&l2cap_recv_fifo)) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Delaying response in %u ms...\n",
|
|
|
|
l2cap_recv_delay);
|
2018-09-17 14:30:35 +03:00
|
|
|
k_delayed_work_submit(&l2ch->recv_work,
|
|
|
|
l2cap_recv_delay);
|
|
|
|
}
|
|
|
|
net_buf_put(&l2cap_recv_fifo, buf);
|
|
|
|
return -EINPROGRESS;
|
|
|
|
}
|
|
|
|
|
2018-08-22 13:16:14 +03:00
|
|
|
return 0;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void l2cap_connected(struct bt_l2cap_chan *chan)
|
|
|
|
{
|
2018-09-17 14:30:35 +03:00
|
|
|
struct l2ch *c = L2CH_CHAN(chan);
|
|
|
|
|
|
|
|
k_delayed_work_init(&c->recv_work, l2cap_recv_cb);
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Channel %p connected\n", chan);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void l2cap_disconnected(struct bt_l2cap_chan *chan)
|
|
|
|
{
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Channel %p disconnected\n", chan);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct net_buf *l2cap_alloc_buf(struct bt_l2cap_chan *chan)
|
|
|
|
{
|
|
|
|
/* print if metrics is disabled */
|
|
|
|
if (chan->ops->recv != l2cap_recv_metrics) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Channel %p requires buffer\n", chan);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return net_buf_alloc(&data_rx_pool, K_FOREVER);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct bt_l2cap_chan_ops l2cap_ops = {
|
|
|
|
.alloc_buf = l2cap_alloc_buf,
|
|
|
|
.recv = l2cap_recv,
|
|
|
|
.connected = l2cap_connected,
|
|
|
|
.disconnected = l2cap_disconnected,
|
|
|
|
};
|
|
|
|
|
2018-09-17 14:30:35 +03:00
|
|
|
|
|
|
|
static struct l2ch l2ch_chan = {
|
|
|
|
.ch.chan.ops = &l2cap_ops,
|
|
|
|
.ch.rx.mtu = DATA_MTU,
|
2017-05-22 11:49:31 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static int l2cap_accept(struct bt_conn *conn, struct bt_l2cap_chan **chan)
|
|
|
|
{
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "Incoming conn %p\n", conn);
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-09-17 14:30:35 +03:00
|
|
|
if (l2ch_chan.ch.chan.conn) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(NULL, "No channels available\n");
|
2017-05-22 11:49:31 +03:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2018-09-17 14:30:35 +03:00
|
|
|
*chan = &l2ch_chan.ch.chan;
|
2017-05-22 11:49:31 +03:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct bt_l2cap_server server = {
|
|
|
|
.accept = l2cap_accept,
|
|
|
|
};
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_l2cap_register(const struct shell *shell,
|
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
2018-09-24 10:59:23 +03:00
|
|
|
|
|
|
|
if (!shell_cmd_precheck(shell, argc >= 2, NULL, 0)) {
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (server.psm) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Already registered\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
server.psm = strtoul(argv[1], NULL, 16);
|
|
|
|
|
|
|
|
if (argc > 2) {
|
|
|
|
server.sec_level = strtoul(argv[2], NULL, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bt_l2cap_server_register(&server) < 0) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Unable to register psm\n");
|
2017-05-22 11:49:31 +03:00
|
|
|
server.psm = 0;
|
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "L2CAP psm %u sec_level %u registered\n",
|
|
|
|
server.psm, server.sec_level);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_l2cap_connect(const struct shell *shell,
|
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
u16_t psm;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
if (!default_conn) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Not connected\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
if (!shell_cmd_precheck(shell, argc == 2, NULL, 0)) {
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-09-17 14:30:35 +03:00
|
|
|
if (l2ch_chan.ch.chan.conn) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Channel already in use\n");
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
psm = strtoul(argv[1], NULL, 16);
|
|
|
|
|
2018-09-17 14:30:35 +03:00
|
|
|
err = bt_l2cap_chan_connect(default_conn, &l2ch_chan.ch.chan, psm);
|
2017-05-22 11:49:31 +03:00
|
|
|
if (err < 0) {
|
2018-09-24 10:59:23 +03:00
|
|
|
error(shell, "Unable to connect to psm %u (err %u)\n", psm,
|
|
|
|
err);
|
2017-05-22 11:49:31 +03:00
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "L2CAP connection pending\n");
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_l2cap_disconnect(const struct shell *shell,
|
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
2018-09-17 14:30:35 +03:00
|
|
|
err = bt_l2cap_chan_disconnect(&l2ch_chan.ch.chan);
|
2017-05-22 11:49:31 +03:00
|
|
|
if (err) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Unable to disconnect: %u\n", -err);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_l2cap_send(const struct shell *shell, size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
static u8_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);
|
|
|
|
}
|
|
|
|
|
2018-09-17 14:30:35 +03:00
|
|
|
len = min(l2ch_chan.ch.tx.mtu, DATA_MTU - BT_L2CAP_CHAN_SEND_RESERVE);
|
2017-05-22 11:49:31 +03:00
|
|
|
|
|
|
|
while (count--) {
|
|
|
|
buf = net_buf_alloc(&data_tx_pool, K_FOREVER);
|
|
|
|
net_buf_reserve(buf, BT_L2CAP_CHAN_SEND_RESERVE);
|
|
|
|
|
|
|
|
net_buf_add_mem(buf, buf_data, len);
|
2018-09-17 14:30:35 +03:00
|
|
|
ret = bt_l2cap_chan_send(&l2ch_chan.ch.chan, buf);
|
2017-05-22 11:49:31 +03:00
|
|
|
if (ret < 0) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "Unable to send: %d\n", -ret);
|
2017-05-22 11:49:31 +03:00
|
|
|
net_buf_unref(buf);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_l2cap_recv(const struct shell *shell, size_t argc, char *argv[])
|
2018-09-17 14:30:35 +03:00
|
|
|
{
|
|
|
|
if (argc > 1) {
|
|
|
|
l2cap_recv_delay = strtoul(argv[1], NULL, 10);
|
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "l2cap receive delay: %u ms\n",
|
|
|
|
l2cap_recv_delay);
|
2018-09-17 14:30:35 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_l2cap_metrics(const struct shell *shell,
|
|
|
|
size_t argc, char *argv[])
|
2017-05-22 11:49:31 +03:00
|
|
|
{
|
|
|
|
const char *action;
|
|
|
|
|
|
|
|
if (argc < 2) {
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "l2cap rate: %u bps.\n", l2cap_rate);
|
2017-05-22 11:49:31 +03:00
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
action = argv[1];
|
|
|
|
|
|
|
|
if (!strcmp(action, "on")) {
|
|
|
|
l2cap_ops.recv = l2cap_recv_metrics;
|
|
|
|
} else if (!strcmp(action, "off")) {
|
|
|
|
l2cap_ops.recv = l2cap_recv;
|
|
|
|
} else {
|
2018-09-24 10:59:23 +03:00
|
|
|
shell_help_print(shell, NULL, 0);
|
|
|
|
return;
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
print(shell, "l2cap metrics %s.\n", action);
|
2017-05-22 11:49:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define HELP_NONE "[none]"
|
|
|
|
#define HELP_ADDR_LE "<address: XX:XX:XX:XX:XX:XX> <type: (public|random)>"
|
2017-05-22 10:17:22 +03:00
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
SHELL_CREATE_STATIC_SUBCMD_SET(bt_cmds) {
|
|
|
|
SHELL_CMD(init, NULL, HELP_ADDR_LE, cmd_init),
|
2018-07-09 13:33:07 +03:00
|
|
|
#if defined(CONFIG_BT_HCI)
|
2018-09-24 10:59:23 +03:00
|
|
|
SHELL_CMD(hci-cmd, NULL, "<ogf> <ocf> [data]", cmd_hci_cmd),
|
2018-07-09 13:33:07 +03:00
|
|
|
#endif
|
2018-09-24 10:59:23 +03:00
|
|
|
SHELL_CMD(id-create, NULL, "[addr]", cmd_id_create),
|
|
|
|
SHELL_CMD(id-reset, NULL, "<id> [addr]", cmd_id_reset),
|
|
|
|
SHELL_CMD(id-delete, NULL, "<id>", cmd_id_delete),
|
|
|
|
SHELL_CMD(id-show, NULL, HELP_NONE, cmd_id_show),
|
|
|
|
SHELL_CMD(id-select, NULL, "<id>", cmd_id_select),
|
|
|
|
SHELL_CMD(name, NULL, "[name]", cmd_name),
|
|
|
|
SHELL_CMD(scan, NULL,
|
|
|
|
"<value: on, passive, off> <dup filter: dups, nodups>",
|
|
|
|
cmd_scan),
|
|
|
|
SHELL_CMD(advertise, NULL,
|
|
|
|
"<type: off, on, scan, nconn> <mode: discov, non_discov>",
|
|
|
|
cmd_advertise),
|
2018-01-04 11:44:50 +01:00
|
|
|
#if defined(CONFIG_BT_CONN)
|
2018-09-24 10:59:23 +03:00
|
|
|
SHELL_CMD(connect, NULL, HELP_ADDR_LE, cmd_connect_le),
|
|
|
|
SHELL_CMD(disconnect, NULL, HELP_NONE, cmd_disconnect),
|
|
|
|
SHELL_CMD(auto-conn, NULL, HELP_ADDR_LE, cmd_auto_conn),
|
|
|
|
SHELL_CMD(directed-adv, NULL, HELP_ADDR_LE " [mode: low]",
|
|
|
|
cmd_directed_adv),
|
|
|
|
SHELL_CMD(select, NULL, HELP_ADDR_LE, cmd_select),
|
|
|
|
SHELL_CMD(conn-update, NULL, "<min> <max> <latency> <timeout>",
|
|
|
|
cmd_conn_update),
|
|
|
|
SHELL_CMD(oob, NULL, NULL, cmd_oob),
|
|
|
|
SHELL_CMD(clear, NULL, NULL, cmd_clear),
|
|
|
|
SHELL_CMD(channel-map, NULL, "<channel-map: XX:XX:XX:XX:XX> (36-0)",
|
|
|
|
cmd_chan_map),
|
2017-08-09 09:21:11 +03:00
|
|
|
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
2018-09-24 10:59:23 +03:00
|
|
|
SHELL_CMD(security, NULL, "<security level: 0, 1, 2, 3>", cmd_security),
|
|
|
|
SHELL_CMD(bondable, NULL, "<bondable: on, off>", cmd_bondable),
|
|
|
|
SHELL_CMD(auth, NULL,
|
|
|
|
"<auth method: all, input, display, yesno, confirm, none>",
|
|
|
|
cmd_auth),
|
|
|
|
SHELL_CMD(auth-cancel, NULL, HELP_NONE, cmd_auth_cancel),
|
|
|
|
SHELL_CMD(auth-passkey, NULL, "<passkey>", cmd_auth_passkey),
|
|
|
|
SHELL_CMD(auth-passkey-confirm, NULL, HELP_NONE,
|
|
|
|
cmd_auth_passkey_confirm),
|
|
|
|
SHELL_CMD(auth-pairing-confirm, NULL, HELP_NONE,
|
|
|
|
cmd_auth_pairing_confirm),
|
2018-07-30 20:30:26 +03:00
|
|
|
#if defined(CONFIG_BT_FIXED_PASSKEY)
|
2018-09-24 10:59:23 +03:00
|
|
|
SHELL_CMD(fixed-passkey, NULL, "[passkey]", cmd_fixed_passkey),
|
2018-07-30 20:30:26 +03:00
|
|
|
#endif
|
2017-08-09 09:21:11 +03:00
|
|
|
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR) */
|
|
|
|
#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL)
|
2018-09-24 10:59:23 +03:00
|
|
|
SHELL_CMD(l2cap-register, NULL, "<psm> [sec_level]",
|
|
|
|
cmd_l2cap_register),
|
|
|
|
SHELL_CMD(l2cap-connect, NULL, "<psm>", cmd_l2cap_connect),
|
|
|
|
SHELL_CMD(l2cap-disconnect, NULL, HELP_NONE, cmd_l2cap_disconnect),
|
|
|
|
SHELL_CMD(l2cap-send, NULL, "<number of packets>", cmd_l2cap_send),
|
|
|
|
SHELL_CMD(l2cap-recv, NULL, "[delay (in miliseconds)", cmd_l2cap_recv),
|
|
|
|
SHELL_CMD(l2cap-metrics, NULL, "<value on, off>", cmd_l2cap_metrics),
|
2017-05-22 11:49:31 +03:00
|
|
|
#endif
|
2018-01-04 11:44:50 +01:00
|
|
|
#endif /* CONFIG_BT_CONN */
|
2017-08-14 13:45:13 +02:00
|
|
|
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
2018-09-24 10:59:23 +03:00
|
|
|
SHELL_CMD(advx, NULL, "<on off> [coded] [anon] [txp]", cmd_advx),
|
|
|
|
SHELL_CMD(scanx, NULL, "<on passive off> [coded]", cmd_scanx),
|
2017-09-27 13:00:38 +02:00
|
|
|
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
|
|
|
#if defined(CONFIG_BT_CTLR_DTM)
|
2018-09-24 10:59:23 +03:00
|
|
|
SHELL_CMD(test_tx, NULL, "<chan> <len> <type> <phy>", cmd_test_tx),
|
|
|
|
SHELL_CMD(test_rx, NULL, "<chan> <phy> <mod_idx>", cmd_test_rx),
|
|
|
|
SHELL_CMD(test_end, NULL, HELP_NONE, cmd_test_end),
|
2017-08-14 13:45:13 +02:00
|
|
|
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
2018-09-24 10:59:23 +03:00
|
|
|
SHELL_SUBCMD_SET_END
|
2017-05-22 10:17:22 +03:00
|
|
|
};
|
|
|
|
|
2018-09-24 10:59:23 +03:00
|
|
|
static void cmd_bt(const struct shell *shell, size_t argc, char **argv)
|
|
|
|
{
|
|
|
|
if (argc == 1) {
|
|
|
|
shell_help_print(shell, NULL, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!shell_cmd_precheck(shell, (argc == 2), NULL, 0)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
error(shell, "%s:%s%s\r\n", argv[0], "unknown parameter: ", argv[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
SHELL_CMD_REGISTER(bt, &bt_cmds, "Bluetooth shell commands", cmd_bt);
|