Bluetooth: Introduce skeleton for settings-based storage

Introduce a basic skeleton for peristent storage based on the settings
subsystem. Also enable support for this to the peripheral sample
application, so the new code gets exersized by CI. For now, the
implementation provides the same level support as the bt_storage API
ever did, i.e. for the identity address and the IRK.

Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Johan Hedberg 2018-04-26 22:05:26 +03:00 committed by Anas Nashif
commit b997a283f7
8 changed files with 216 additions and 3 deletions

View file

@ -1,3 +1,6 @@
# Incresed stack due to settings API usage
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_BT=y CONFIG_BT=y
CONFIG_BT_DEBUG_LOG=y CONFIG_BT_DEBUG_LOG=y
CONFIG_BT_SMP=y CONFIG_BT_SMP=y
@ -7,3 +10,11 @@ CONFIG_BT_ATT_PREPARE_COUNT=2
CONFIG_BT_PRIVACY=y CONFIG_BT_PRIVACY=y
CONFIG_BT_DEVICE_NAME="Test peripheral" CONFIG_BT_DEVICE_NAME="Test peripheral"
CONFIG_BT_DEVICE_APPEARANCE=833 CONFIG_BT_DEVICE_APPEARANCE=833
CONFIG_BT_SETTINGS=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_FCB=y
CONFIG_SETTINGS=y
CONFIG_SETTINGS_FCB=y

View file

@ -14,6 +14,8 @@
#include <misc/byteorder.h> #include <misc/byteorder.h>
#include <zephyr.h> #include <zephyr.h>
#include <settings/settings.h>
#include <bluetooth/bluetooth.h> #include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h> #include <bluetooth/hci.h>
#include <bluetooth/conn.h> #include <bluetooth/conn.h>
@ -242,6 +244,10 @@ static void bt_ready(int err)
dis_init(CONFIG_SOC, "Manufacturer"); dis_init(CONFIG_SOC, "Manufacturer");
bt_gatt_service_register(&vnd_svc); bt_gatt_service_register(&vnd_svc);
if (IS_ENABLED(CONFIG_SETTINGS)) {
settings_load();
}
err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
sd, ARRAY_SIZE(sd)); sd, ARRAY_SIZE(sd));
if (err) { if (err) {

View file

@ -13,6 +13,7 @@ zephyr_library_sources_ifdef(CONFIG_BT_A2DP a2dp.c)
zephyr_library_sources_ifdef(CONFIG_BT_AVDTP avdtp.c) zephyr_library_sources_ifdef(CONFIG_BT_AVDTP avdtp.c)
zephyr_library_sources_ifdef(CONFIG_BT_RFCOMM rfcomm.c) zephyr_library_sources_ifdef(CONFIG_BT_RFCOMM rfcomm.c)
zephyr_library_sources_ifdef(CONFIG_BT_TESTING testing.c) zephyr_library_sources_ifdef(CONFIG_BT_TESTING testing.c)
zephyr_library_sources_ifdef(CONFIG_BT_SETTINGS settings.c)
zephyr_library_sources_ifdef( zephyr_library_sources_ifdef(
CONFIG_BT_BREDR CONFIG_BT_BREDR

View file

@ -95,6 +95,7 @@ config BT_RX_STACK_SIZE
int "Size of the receiving thread stack" int "Size of the receiving thread stack"
depends on BT_HCI_HOST || BT_RECV_IS_RX_THREAD depends on BT_HCI_HOST || BT_RECV_IS_RX_THREAD
default 1024 default 1024
default 2048 if BT_SETTINGS
default 2048 if BT_MESH default 2048 if BT_MESH
default 512 if BT_HCI_RAW default 512 if BT_HCI_RAW
range 512 65536 if BT_HCI_RAW range 512 65536 if BT_HCI_RAW
@ -130,6 +131,23 @@ config BT_HOST_CRYPTO
select TINYCRYPT_SHA256_HMAC select TINYCRYPT_SHA256_HMAC
select TINYCRYPT_SHA256_HMAC_PRNG select TINYCRYPT_SHA256_HMAC_PRNG
config BT_SETTINGS
bool "Store Bluetooth state and configuration persistently"
depends on SETTINGS
select MPU_ALLOW_FLASH_WRITE if ARM_MPU
help
When selected, the Bluetooth stack will take care of storing
(and restoring) the Bluetooth state (e.g. pairing keys) and
configuration persistently in flash.
When this option has been enabled, it's important that the
application makes a call to settings_load() after having done
all necessary initialization (e.g. calling bt_enable). The
reason settings_load() is handled externally to the stack, is
that there may be other subsystems using the settings API, in
which case it's more efficient to load all settings in one go,
instead of each subsystem doing it independently.
config BT_INTERNAL_STORAGE config BT_INTERNAL_STORAGE
bool "Use an internal persistent storage handler" bool "Use an internal persistent storage handler"
depends on FILE_SYSTEM depends on FILE_SYSTEM
@ -350,6 +368,12 @@ config BT_TINYCRYPT_ECC
Connections so that Hosts can make use of those. Connections so that Hosts can make use of those.
if BT_DEBUG if BT_DEBUG
config BT_DEBUG_SETTINGS
bool "Bluetooth storage debug"
depends on BT_SETTINGS
help
This option enables debug support for Bluetooth storage.
config BT_DEBUG_HCI_CORE config BT_DEBUG_HCI_CORE
bool "Bluetooth HCI core debug" bool "Bluetooth HCI core debug"
help help

View file

@ -41,6 +41,7 @@
#include "l2cap_internal.h" #include "l2cap_internal.h"
#include "smp.h" #include "smp.h"
#include "crypto.h" #include "crypto.h"
#include "settings.h"
/* Peripheral timeout to initialize Connection Parameter Update procedure */ /* Peripheral timeout to initialize Connection Parameter Update procedure */
#define CONN_UPDATE_TIMEOUT K_SECONDS(5) #define CONN_UPDATE_TIMEOUT K_SECONDS(5)
@ -4143,7 +4144,7 @@ static const char *ver_str(u8_t ver)
return "unknown"; return "unknown";
} }
static void show_dev_info(void) void bt_dev_show_info(void)
{ {
BT_INFO("Identity: %s", bt_addr_le_str(&bt_dev.id_addr)); BT_INFO("Identity: %s", bt_addr_le_str(&bt_dev.id_addr));
BT_INFO("HCI: version %s (0x%02x) revision 0x%04x, manufacturer 0x%04x", BT_INFO("HCI: version %s (0x%02x) revision 0x%04x, manufacturer 0x%04x",
@ -4154,7 +4155,7 @@ static void show_dev_info(void)
bt_dev.lmp_subversion); bt_dev.lmp_subversion);
} }
#else #else
static inline void show_dev_info(void) void bt_dev_show_info(void)
{ {
} }
#endif /* CONFIG_BT_DEBUG */ #endif /* CONFIG_BT_DEBUG */
@ -4320,7 +4321,9 @@ static int hci_init(void)
} }
} }
show_dev_info(); if (!IS_ENABLED(CONFIG_BT_SETTINGS)) {
bt_dev_show_info();
}
return 0; return 0;
} }
@ -4549,6 +4552,13 @@ int bt_enable(bt_ready_cb_t cb)
return -EALREADY; return -EALREADY;
} }
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
err = bt_settings_init();
if (err) {
return err;
}
}
ready_cb = cb; ready_cb = cb;
/* TX thread */ /* TX thread */

View file

@ -190,3 +190,5 @@ u16_t bt_hci_get_cmd_opcode(struct net_buf *buf);
struct bt_keys; struct bt_keys;
int bt_id_add(struct bt_keys *keys); int bt_id_add(struct bt_keys *keys);
int bt_id_del(struct bt_keys *keys); int bt_id_del(struct bt_keys *keys);
void bt_dev_show_info(void);

View file

@ -0,0 +1,152 @@
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <zephyr.h>
#include <settings/settings.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/conn.h>
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_SETTINGS)
#include "common/log.h"
#include "hci_core.h"
#include "settings.h"
static int set(int argc, char **argv, char *val)
{
int len;
BT_DBG("argc %d argv[0] %s val %s", argc, argv[0], val);
if (argc != 1) {
return -ENOENT;
}
if (!strcmp(argv[0], "id")) {
len = sizeof(bt_dev.id_addr);
settings_bytes_from_str(val, &bt_dev.id_addr, &len);
BT_DBG("ID Addr set to %s", bt_addr_le_str(&bt_dev.id_addr));
return 0;
}
#if defined(CONFIG_BT_PRIVACY)
if (!strcmp(argv[0], "irk")) {
len = sizeof(bt_dev.irk);
settings_bytes_from_str(val, bt_dev.irk, &len);
BT_DBG("IRK set to %s", bt_hex(bt_dev.irk, 16));
return 0;
}
#endif /* CONFIG_BT_PRIVACY */
return 0;
}
static void generate_static_addr(void)
{
char buf[13];
char *str;
BT_DBG("Generating new static random address");
if (bt_addr_le_create_static(&bt_dev.id_addr)) {
BT_ERR("Failed to generate static addr");
return;
}
atomic_set_bit(bt_dev.flags, BT_DEV_ID_STATIC_RANDOM);
BT_DBG("New ID Addr: %s", bt_addr_le_str(&bt_dev.id_addr));
str = settings_str_from_bytes(&bt_dev.id_addr, sizeof(bt_dev.id_addr),
buf, sizeof(buf));
if (!str) {
BT_ERR("Unable to encode ID Addr as value");
return;
}
BT_DBG("Saving ID addr as value %s", str);
settings_save_one("bt/id", str);
}
#if defined(CONFIG_BT_PRIVACY)
static void generate_irk(void)
{
char buf[25];
char *str;
BT_DBG("Generating new IRK");
if (bt_rand(bt_dev.irk, sizeof(bt_dev.irk))) {
BT_ERR("Failed to generate IRK");
return;
}
BT_DBG("New local IRK: %s", bt_hex(bt_dev.irk, 16));
str = settings_str_from_bytes(bt_dev.irk, 16, buf, sizeof(buf));
if (!str) {
BT_ERR("Unable to encode IRK as value");
return;
}
BT_DBG("Saving IRK as value %s", str);
settings_save_one("bt/irk", str);
}
#endif /* CONFIG_BT_PRIVACY */
static int commit(void)
{
BT_DBG("");
if (!bt_addr_le_cmp(&bt_dev.id_addr, BT_ADDR_LE_ANY) ||
!bt_addr_le_cmp(&bt_dev.id_addr, BT_ADDR_LE_NONE)) {
generate_static_addr();
}
#if defined(CONFIG_BT_PRIVACY)
{
u8_t zero[16] = { 0 };
if (!memcmp(bt_dev.irk, zero, 16)) {
generate_irk();
}
}
#endif /* CONFIG_BT_PRIVACY */
bt_dev_show_info();
return 0;
}
static struct settings_handler bt_settings = {
.name = "bt",
.h_set = set,
.h_commit = commit,
};
int bt_settings_init(void)
{
int err;
BT_DBG("");
err = settings_subsys_init();
if (err) {
BT_ERR("settings_subsys_init failed (err %d)", err);
return err;
}
err = settings_register(&bt_settings);
if (err) {
BT_ERR("settings_register failed (err %d)", err);
return err;
}
return 0;
}

View file

@ -0,0 +1,7 @@
/*
* Copyright (c) 2018 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
int bt_settings_init(void);