Bluetooth: Remove bt_storage API
The same functionality is now supported by the settings-based solution, so remove bt_storage out of the way. There were stubs in bt_storage to handle per-peer information (e.g. pairing keys) but this was never actually implemented in full. The next step is to add this support to the settings-based solution. Leave the code for generating temporary IRK and identity address in case BT_SETTINGS is not enabled. Also leave the code for using vendor HCI to read the identity address, in which case the settings implementation will not touch it. Introduce a new bt_unpair() API to replace the removed bt_storage_clear(), since the latter was actually doing more than just storage management: it was also handling runtime storage of pairing information. Later, the bt_unpair() implementation will be extended to clear settings-based pairing storage. There is one feature that the bt shell module looses: the ability to give a specific identity address to the "init" command as a parameter. We might look later in the future if this is really needed, and add a separate API for this. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
parent
b997a283f7
commit
d22b7c9f2d
|
@ -126,12 +126,6 @@ Logical Link Control and Adaptation Protocol (L2CAP)
|
|||
.. doxygengroup:: bt_l2cap
|
||||
:project: Zephyr
|
||||
|
||||
Persistent Storage
|
||||
******************
|
||||
|
||||
.. doxygengroup:: bt_storage
|
||||
:project: Zephyr
|
||||
|
||||
Serial Port Emulation (RFCOMM)
|
||||
******************************
|
||||
|
||||
|
|
|
@ -474,6 +474,15 @@ int bt_br_set_discoverable(bool enable);
|
|||
*/
|
||||
int bt_br_set_connectable(bool enable);
|
||||
|
||||
/** Clear pairing information.
|
||||
*
|
||||
* @param addr Remote address, NULL or BT_ADDR_LE_ANY to clear all remote
|
||||
* devices.
|
||||
*
|
||||
* @return 0 on success or negative error value on failure.
|
||||
*/
|
||||
int bt_unpair(const bt_addr_le_t *addr);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -1,146 +0,0 @@
|
|||
/** @file
|
||||
* @brief Bluetooth subsystem persistent storage APIs.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __BT_STORAGE_H
|
||||
#define __BT_STORAGE_H
|
||||
|
||||
/**
|
||||
* @brief Persistent Storage
|
||||
* @defgroup bt_storage Persistent Storage
|
||||
* @ingroup bluetooth
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Well known storage keys */
|
||||
enum {
|
||||
/** Identity Address.
|
||||
* Type: bt_addr_le_t (7 bytes)
|
||||
*/
|
||||
BT_STORAGE_ID_ADDR,
|
||||
|
||||
/** Local Identity Resolving Key.
|
||||
* Type: u8_t key[16]
|
||||
*/
|
||||
BT_STORAGE_LOCAL_IRK,
|
||||
|
||||
/** List of addresses of remote devices.
|
||||
* Type: bt_addr_le_t addrs[n] (length is variable).
|
||||
*
|
||||
* This is only used for reading. Modification of the list happens
|
||||
* implicitly by writing entries for each remote device. This value
|
||||
* is only used with the local storage, i.e. NULL as the target
|
||||
* bt_addr_le_t passed to the read callback.
|
||||
*/
|
||||
BT_STORAGE_ADDRESSES,
|
||||
|
||||
/** Slave Long Term Key for legacy pairing.
|
||||
* Type: struct bt_storage_ltk
|
||||
*/
|
||||
BT_STORAGE_SLAVE_LTK,
|
||||
|
||||
/** Long Term Key for legacy pairing.
|
||||
* Type: struct bt_storage_ltk
|
||||
*/
|
||||
BT_STORAGE_LTK,
|
||||
|
||||
/** Identity Resolving Key
|
||||
* Type: u8_t key[16]
|
||||
*/
|
||||
BT_STORAGE_IRK,
|
||||
};
|
||||
|
||||
/** LTK key flags */
|
||||
enum {
|
||||
/* Key has been generated with MITM protection */
|
||||
BT_STORAGE_LTK_AUTHENTICATED = BIT(0),
|
||||
|
||||
/* Key has been generated using the LE Secure Connection pairing */
|
||||
BT_STORAGE_LTK_SC = BIT(1),
|
||||
};
|
||||
|
||||
struct bt_storage_ltk {
|
||||
u8_t flags;
|
||||
/* Encryption key size used to generate key */
|
||||
u8_t size;
|
||||
u16_t ediv;
|
||||
u8_t rand[8];
|
||||
u8_t val[16];
|
||||
};
|
||||
|
||||
struct bt_storage {
|
||||
/** Read the value of a key from storage.
|
||||
*
|
||||
* @param addr Remote address or NULL for local storage
|
||||
* @param key BT_STORAGE_* key to read
|
||||
* @param data Memory location to place the data
|
||||
* @param length Maximum number of bytes to read
|
||||
*
|
||||
* @return Number of bytes read or negative error value on
|
||||
* failure.
|
||||
*/
|
||||
ssize_t (*read)(const bt_addr_le_t *addr, u16_t key,
|
||||
void *data, size_t length);
|
||||
|
||||
/** Write the value of a key to storage.
|
||||
*
|
||||
* @param addr Remote address or NULL for local storage
|
||||
* @param key BT_STORAGE_* key to write
|
||||
* @param data Memory location of the data
|
||||
* @param length Number of bytes to write
|
||||
*
|
||||
* @return Number of bytes written or negative error value on
|
||||
* failure.
|
||||
*/
|
||||
ssize_t (*write)(const bt_addr_le_t *addr, u16_t key,
|
||||
const void *data, size_t length);
|
||||
|
||||
/** Clear all keys for a specific address
|
||||
*
|
||||
* @param addr Remote address, BT_ADDR_LE_ANY for all
|
||||
* remote devices, or NULL for local storage.
|
||||
*
|
||||
* @return 0 on success or negative error value on failure.
|
||||
*/
|
||||
int (*clear)(const bt_addr_le_t *addr);
|
||||
|
||||
};
|
||||
|
||||
/** Register callbacks for storage handling.
|
||||
*
|
||||
* @param storage Callback struct.
|
||||
*/
|
||||
void bt_storage_register(const struct bt_storage *storage);
|
||||
|
||||
/** Clear all storage keys for a specific address
|
||||
*
|
||||
* @param addr Remote address, NULL for local storage or
|
||||
* BT_ADDR_LE_ANY to clear all remote devices.
|
||||
*
|
||||
* @return 0 on success or negative error value on failure.
|
||||
*/
|
||||
int bt_storage_clear(const bt_addr_le_t *addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* __BT_STORAGE_H */
|
|
@ -1,11 +1,6 @@
|
|||
zephyr_library()
|
||||
zephyr_library_link_libraries(subsys__bluetooth)
|
||||
|
||||
if(CONFIG_BT_INTERNAL_STORAGE)
|
||||
zephyr_library_sources(storage.c)
|
||||
zephyr_library_link_libraries(subsys__fs)
|
||||
endif()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_HCI_RAW hci_raw.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_DEBUG_MONITOR monitor.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_TINYCRYPT_ECC hci_ecc.c)
|
||||
|
|
|
@ -148,15 +148,6 @@ config BT_SETTINGS
|
|||
which case it's more efficient to load all settings in one go,
|
||||
instead of each subsystem doing it independently.
|
||||
|
||||
config BT_INTERNAL_STORAGE
|
||||
bool "Use an internal persistent storage handler"
|
||||
depends on FILE_SYSTEM
|
||||
depends on PRINTK
|
||||
help
|
||||
When selected the application doesn't need to register its own
|
||||
persistent storage handlers through the bt_storage API, rather
|
||||
an internal default handler is used for this.
|
||||
|
||||
if BT_CONN
|
||||
|
||||
if BT_HCI_ACL_FLOW_CONTROL
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/hci_vs.h>
|
||||
#include <bluetooth/hci_driver.h>
|
||||
#include <bluetooth/storage.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
|
||||
#include "common/log.h"
|
||||
|
@ -78,8 +77,6 @@ struct bt_dev bt_dev = {
|
|||
|
||||
static bt_ready_cb_t ready_cb;
|
||||
|
||||
const struct bt_storage *bt_storage;
|
||||
|
||||
static bt_le_scan_cb_t *scan_dev_found_cb;
|
||||
|
||||
static u8_t pub_key[64];
|
||||
|
@ -1272,6 +1269,53 @@ static int set_flow_control(void)
|
|||
return bt_hci_cmd_send_sync(BT_HCI_OP_SET_CTL_TO_HOST_FLOW, buf, NULL);
|
||||
}
|
||||
#endif /* CONFIG_BT_HCI_ACL_FLOW_CONTROL */
|
||||
|
||||
static int bt_clear_all_pairings(void)
|
||||
{
|
||||
bt_conn_disconnect_all();
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SMP)) {
|
||||
bt_keys_clear_all();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_BREDR)) {
|
||||
bt_keys_link_key_clear_addr(NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_unpair(const bt_addr_le_t *addr)
|
||||
{
|
||||
struct bt_conn *conn;
|
||||
|
||||
if (!addr || !bt_addr_le_cmp(addr, BT_ADDR_LE_ANY)) {
|
||||
return bt_clear_all_pairings();
|
||||
}
|
||||
|
||||
conn = bt_conn_lookup_addr_le(addr);
|
||||
if (conn) {
|
||||
bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_BREDR)) {
|
||||
/* LE Public may indicate BR/EDR as well */
|
||||
if (addr->type == BT_ADDR_LE_PUBLIC) {
|
||||
bt_keys_link_key_clear_addr(&addr->a);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SMP)) {
|
||||
struct bt_keys *keys = bt_keys_find_addr(addr);
|
||||
if (keys) {
|
||||
bt_keys_clear(keys);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BT_CONN */
|
||||
|
||||
#if defined(CONFIG_BT_BREDR)
|
||||
|
@ -4050,20 +4094,30 @@ int bt_addr_le_create_static(bt_addr_le_t *addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int set_static_addr(void)
|
||||
int bt_set_static_addr(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (bt_storage) {
|
||||
ssize_t ret;
|
||||
|
||||
ret = bt_storage->read(NULL, BT_STORAGE_ID_ADDR,
|
||||
&bt_dev.id_addr, sizeof(bt_dev.id_addr));
|
||||
if (ret == sizeof(bt_dev.id_addr)) {
|
||||
goto set_addr;
|
||||
}
|
||||
if (bt_dev.id_addr.type != BT_ADDR_LE_RANDOM ||
|
||||
(bt_dev.id_addr.a.val[5] & 0xc0) != 0xc0) {
|
||||
BT_ERR("Only static random address supported as identity");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = set_random_address(&bt_dev.id_addr.a);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
atomic_set_bit(bt_dev.flags, BT_DEV_ID_STATIC_RANDOM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_id_addr(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
#if defined(CONFIG_BT_HCI_VS_EXT)
|
||||
/* Check for VS_Read_Static_Addresses support */
|
||||
if (bt_dev.vs_commands[1] & BIT(0)) {
|
||||
|
@ -4082,7 +4136,7 @@ static int set_static_addr(void)
|
|||
bt_dev.id_addr.type = BT_ADDR_LE_RANDOM;
|
||||
bt_addr_copy(&bt_dev.id_addr.a, &rp->a[0].bdaddr);
|
||||
net_buf_unref(rsp);
|
||||
goto set_addr;
|
||||
return bt_set_static_addr();
|
||||
}
|
||||
|
||||
BT_WARN("No static addresses stored in controller");
|
||||
|
@ -4093,40 +4147,21 @@ static int set_static_addr(void)
|
|||
|
||||
generate:
|
||||
#endif
|
||||
BT_DBG("Generating new static random address");
|
||||
|
||||
err = bt_addr_le_create_static(&bt_dev.id_addr);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (bt_storage) {
|
||||
ssize_t ret;
|
||||
|
||||
ret = bt_storage->write(NULL, BT_STORAGE_ID_ADDR,
|
||||
&bt_dev.id_addr,
|
||||
sizeof(bt_dev.id_addr));
|
||||
if (ret != sizeof(bt_dev.id_addr)) {
|
||||
BT_ERR("Unable to store static address");
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
BT_DBG("Expecing identity addr to be handled by settings");
|
||||
return 0;
|
||||
} else {
|
||||
BT_WARN("Using temporary static random address");
|
||||
}
|
||||
err = bt_addr_le_create_static(&bt_dev.id_addr);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
set_addr:
|
||||
if (bt_dev.id_addr.type != BT_ADDR_LE_RANDOM ||
|
||||
(bt_dev.id_addr.a.val[5] & 0xc0) != 0xc0) {
|
||||
BT_ERR("Only static random address supported as identity");
|
||||
return -EINVAL;
|
||||
}
|
||||
BT_WARN("Using temporary static random address %s",
|
||||
bt_addr_str(&bt_dev.id_addr.a));
|
||||
|
||||
err = set_random_address(&bt_dev.id_addr.a);
|
||||
if (err) {
|
||||
return err;
|
||||
return bt_set_static_addr();
|
||||
}
|
||||
|
||||
atomic_set_bit(bt_dev.flags, BT_DEV_ID_STATIC_RANDOM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_DEBUG)
|
||||
|
@ -4314,7 +4349,7 @@ static int hci_init(void)
|
|||
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)) {
|
||||
BT_DBG("No public address. Trying to set static random.");
|
||||
err = set_static_addr();
|
||||
err = setup_id_addr();
|
||||
if (err) {
|
||||
BT_ERR("Unable to set identity address");
|
||||
return err;
|
||||
|
@ -4429,30 +4464,16 @@ int bt_hci_driver_register(const struct bt_hci_driver *drv)
|
|||
#if defined(CONFIG_BT_PRIVACY)
|
||||
static int irk_init(void)
|
||||
{
|
||||
ssize_t err;
|
||||
|
||||
if (bt_storage) {
|
||||
err = bt_storage->read(NULL, BT_STORAGE_LOCAL_IRK, &bt_dev.irk,
|
||||
sizeof(bt_dev.irk));
|
||||
if (err == sizeof(bt_dev.irk)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
BT_DBG("Generating new IRK");
|
||||
|
||||
err = bt_rand(bt_dev.irk, sizeof(bt_dev.irk));
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (bt_storage) {
|
||||
err = bt_storage->write(NULL, BT_STORAGE_LOCAL_IRK, bt_dev.irk,
|
||||
sizeof(bt_dev.irk));
|
||||
if (err != sizeof(bt_dev.irk)) {
|
||||
BT_ERR("Unable to store IRK");
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
|
||||
BT_DBG("Expecting settings to handle local IRK");
|
||||
} else {
|
||||
int err;
|
||||
|
||||
err = bt_rand(bt_dev.irk, sizeof(bt_dev.irk));
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
BT_WARN("Using temporary IRK");
|
||||
}
|
||||
|
||||
|
@ -5133,68 +5154,6 @@ int bt_br_set_discoverable(bool enable)
|
|||
}
|
||||
#endif /* CONFIG_BT_BREDR */
|
||||
|
||||
void bt_storage_register(const struct bt_storage *storage)
|
||||
{
|
||||
bt_storage = storage;
|
||||
}
|
||||
|
||||
static int bt_storage_clear_all(void)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_BT_CONN)) {
|
||||
bt_conn_disconnect_all();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SMP)) {
|
||||
bt_keys_clear_all();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_BREDR)) {
|
||||
bt_keys_link_key_clear_addr(NULL);
|
||||
}
|
||||
|
||||
if (bt_storage) {
|
||||
return bt_storage->clear(NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_storage_clear(const bt_addr_le_t *addr)
|
||||
{
|
||||
if (!addr) {
|
||||
return bt_storage_clear_all();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CONN)) {
|
||||
struct bt_conn *conn = bt_conn_lookup_addr_le(addr);
|
||||
if (conn) {
|
||||
bt_conn_disconnect(conn,
|
||||
BT_HCI_ERR_REMOTE_USER_TERM_CONN);
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_BREDR)) {
|
||||
/* LE Public may indicate BR/EDR as well */
|
||||
if (addr->type == BT_ADDR_LE_PUBLIC) {
|
||||
bt_keys_link_key_clear_addr(&addr->a);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_SMP)) {
|
||||
struct bt_keys *keys = bt_keys_find_addr(addr);
|
||||
if (keys) {
|
||||
bt_keys_clear(keys);
|
||||
}
|
||||
}
|
||||
|
||||
if (bt_storage) {
|
||||
return bt_storage->clear(addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u16_t bt_hci_get_cmd_opcode(struct net_buf *buf)
|
||||
{
|
||||
return cmd(buf)->opcode;
|
||||
|
|
|
@ -166,7 +166,6 @@ struct bt_dev {
|
|||
};
|
||||
|
||||
extern struct bt_dev bt_dev;
|
||||
extern const struct bt_storage *bt_storage;
|
||||
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
|
||||
extern const struct bt_conn_auth_cb *bt_auth;
|
||||
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
|
||||
|
@ -191,4 +190,6 @@ struct bt_keys;
|
|||
int bt_id_add(struct bt_keys *keys);
|
||||
int bt_id_del(struct bt_keys *keys);
|
||||
|
||||
int bt_set_static_addr(void);
|
||||
|
||||
void bt_dev_show_info(void);
|
||||
|
|
|
@ -59,7 +59,7 @@ static void generate_static_addr(void)
|
|||
return;
|
||||
}
|
||||
|
||||
atomic_set_bit(bt_dev.flags, BT_DEV_ID_STATIC_RANDOM);
|
||||
bt_set_static_addr();
|
||||
|
||||
BT_DBG("New ID Addr: %s", bt_addr_le_str(&bt_dev.id_addr));
|
||||
|
||||
|
|
|
@ -1,229 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <misc/printk.h>
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <init.h>
|
||||
#include <fs.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/storage.h>
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_CORE)
|
||||
#include "common/log.h"
|
||||
|
||||
#define STORAGE_ROOT "/bt"
|
||||
|
||||
/* Required file name length for full storage support. If the maximum
|
||||
* file name length supported by the chosen file system is less than
|
||||
* this value, then only local keys are supported (/bt/abcd).
|
||||
*/
|
||||
#define STORAGE_FILE_NAME_LEN 13
|
||||
|
||||
#if MAX_FILE_NAME >= STORAGE_FILE_NAME_LEN
|
||||
/* /bt/aabbccddeeff0/abcd */
|
||||
#define STORAGE_PATH_MAX 23
|
||||
#else
|
||||
/* /bt/abcd */
|
||||
#define STORAGE_PATH_MAX 9
|
||||
#endif
|
||||
|
||||
enum storage_access {
|
||||
STORAGE_READ,
|
||||
STORAGE_WRITE
|
||||
};
|
||||
|
||||
static int storage_open(const bt_addr_le_t *addr, u16_t key,
|
||||
enum storage_access access, struct fs_file_t *file)
|
||||
{
|
||||
char path[STORAGE_PATH_MAX];
|
||||
|
||||
if (addr) {
|
||||
#if MAX_FILE_NAME >= STORAGE_FILE_NAME_LEN
|
||||
int len;
|
||||
|
||||
len = snprintk(path, sizeof(path),
|
||||
STORAGE_ROOT "/%02X%02X%02X%02X%02X%02X%u",
|
||||
addr->a.val[5], addr->a.val[4], addr->a.val[3],
|
||||
addr->a.val[2], addr->a.val[1], addr->a.val[0],
|
||||
addr->type);
|
||||
|
||||
/* Create the subdirectory if necessary */
|
||||
if (access == STORAGE_WRITE) {
|
||||
struct fs_dirent entry;
|
||||
int err;
|
||||
|
||||
err = fs_stat(path, &entry);
|
||||
if (err) {
|
||||
err = fs_mkdir(path);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snprintk(path + len, sizeof(path) - len, "/%04x", key);
|
||||
#else
|
||||
return -ENAMETOOLONG;
|
||||
#endif
|
||||
} else {
|
||||
snprintk(path, sizeof(path), STORAGE_ROOT "/%04x", key);
|
||||
}
|
||||
|
||||
return fs_open(file, path);
|
||||
}
|
||||
|
||||
static ssize_t storage_read(const bt_addr_le_t *addr, u16_t key, void *data,
|
||||
size_t length)
|
||||
{
|
||||
struct fs_file_t file;
|
||||
ssize_t ret;
|
||||
|
||||
ret = storage_open(addr, key, STORAGE_READ, &file);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fs_read(&file, data, length);
|
||||
fs_close(&file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t storage_write(const bt_addr_le_t *addr, u16_t key,
|
||||
const void *data, size_t length)
|
||||
{
|
||||
struct fs_file_t file;
|
||||
ssize_t ret;
|
||||
|
||||
ret = storage_open(addr, key, STORAGE_WRITE, &file);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = fs_write(&file, data, length);
|
||||
fs_close(&file);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int unlink_recursive(char path[STORAGE_PATH_MAX])
|
||||
{
|
||||
size_t path_len;
|
||||
struct fs_dir_t dir;
|
||||
int err;
|
||||
|
||||
err = fs_opendir(&dir, path);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* We calculate this up-front so we can keep reusing the same
|
||||
* buffer for the path when recursing.
|
||||
*/
|
||||
path_len = strlen(path);
|
||||
|
||||
while (1) {
|
||||
struct fs_dirent entry;
|
||||
|
||||
err = fs_readdir(&dir, &entry);
|
||||
if (err) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (entry.name[0] == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
snprintk(path + path_len, STORAGE_PATH_MAX - path_len, "/%s",
|
||||
entry.name);
|
||||
|
||||
if (entry.type == FS_DIR_ENTRY_DIR) {
|
||||
err = unlink_recursive(path);
|
||||
} else {
|
||||
err = fs_unlink(path);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fs_closedir(&dir);
|
||||
|
||||
/* Return to the original value */
|
||||
path[path_len] = '\0';
|
||||
|
||||
fs_unlink(path);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int storage_clear(const bt_addr_le_t *addr)
|
||||
{
|
||||
char path[STORAGE_PATH_MAX];
|
||||
int err;
|
||||
|
||||
if (addr) {
|
||||
#if MAX_FILE_NAME >= STORAGE_FILE_NAME_LEN
|
||||
snprintk(path, STORAGE_PATH_MAX,
|
||||
STORAGE_ROOT "/%02X%02X%02X%02X%02X%02X%u",
|
||||
addr->a.val[5], addr->a.val[4], addr->a.val[3],
|
||||
addr->a.val[2], addr->a.val[1], addr->a.val[0],
|
||||
addr->type);
|
||||
|
||||
return unlink_recursive(path);
|
||||
#else
|
||||
return -ENAMETOOLONG;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* unlink_recursive() uses the given path as a buffer for
|
||||
* constructing sub-paths, so we can't give it a string literal
|
||||
* such as STORAGE_ROOT directly.
|
||||
*/
|
||||
strcpy(path, STORAGE_ROOT);
|
||||
|
||||
err = unlink_recursive(path);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return fs_mkdir(STORAGE_ROOT);
|
||||
}
|
||||
|
||||
static int storage_init(struct device *unused)
|
||||
{
|
||||
static const struct bt_storage storage = {
|
||||
.read = storage_read,
|
||||
.write = storage_write,
|
||||
.clear = storage_clear
|
||||
};
|
||||
struct fs_dirent entry;
|
||||
int err;
|
||||
|
||||
err = fs_stat(STORAGE_ROOT, &entry);
|
||||
if (err) {
|
||||
BT_WARN("%s doesn't seem to exist (err %d). Creating it.",
|
||||
STORAGE_ROOT, err);
|
||||
|
||||
err = fs_mkdir(STORAGE_ROOT);
|
||||
if (err) {
|
||||
BT_ERR("Unable to create %s (err %d)",
|
||||
STORAGE_ROOT, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
bt_storage_register(&storage);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(storage_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
|
@ -23,7 +23,6 @@
|
|||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/l2cap.h>
|
||||
#include <bluetooth/rfcomm.h>
|
||||
#include <bluetooth/storage.h>
|
||||
#include <bluetooth/sdp.h>
|
||||
|
||||
#include <shell/shell.h>
|
||||
|
@ -39,7 +38,6 @@
|
|||
#define DATA_BREDR_MTU 48
|
||||
|
||||
#define BT_SHELL_MODULE "bt"
|
||||
static bt_addr_le_t id_addr;
|
||||
|
||||
#if defined(CONFIG_BT_CONN)
|
||||
struct bt_conn *default_conn;
|
||||
|
@ -506,42 +504,6 @@ static int str2bt_addr_le(const char *str, const char *type, bt_addr_le_t *addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t storage_read(const bt_addr_le_t *addr, u16_t key, void *data,
|
||||
size_t length)
|
||||
{
|
||||
if (addr) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (key == BT_STORAGE_ID_ADDR && length == sizeof(id_addr) &&
|
||||
bt_addr_le_cmp(&id_addr, BT_ADDR_LE_ANY)) {
|
||||
bt_addr_le_copy(data, &id_addr);
|
||||
return sizeof(id_addr);
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static ssize_t storage_write(const bt_addr_le_t *addr, u16_t key,
|
||||
const void *data, size_t length)
|
||||
{
|
||||
if (addr) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (key == BT_STORAGE_ID_ADDR && length == sizeof(id_addr)) {
|
||||
bt_addr_le_copy(&id_addr, data);
|
||||
return sizeof(id_addr);
|
||||
}
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int storage_clear(const bt_addr_le_t *addr)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static void bt_ready(int err)
|
||||
{
|
||||
if (err) {
|
||||
|
@ -560,29 +522,8 @@ static void bt_ready(int err)
|
|||
|
||||
static int cmd_init(int argc, char *argv[])
|
||||
{
|
||||
static const struct bt_storage storage = {
|
||||
.read = storage_read,
|
||||
.write = storage_write,
|
||||
.clear = storage_clear,
|
||||
};
|
||||
int err;
|
||||
|
||||
if (argc > 1) {
|
||||
if (argc < 3) {
|
||||
printk("Invalid address\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = str2bt_addr_le(argv[1], argv[2], &id_addr);
|
||||
if (err) {
|
||||
printk("Invalid address (err %d)\n", err);
|
||||
bt_addr_le_cmp(&id_addr, BT_ADDR_LE_ANY);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bt_storage_register(&storage);
|
||||
}
|
||||
|
||||
err = bt_enable(bt_ready);
|
||||
if (err) {
|
||||
printk("Bluetooth init failed (err %d)\n", err);
|
||||
|
@ -944,11 +885,11 @@ static int cmd_clear(int argc, char *argv[])
|
|||
}
|
||||
|
||||
if (strcmp(argv[1], "all") == 0) {
|
||||
err = bt_storage_clear(NULL);
|
||||
err = bt_unpair(NULL);
|
||||
if (err) {
|
||||
printk("Failed to clear storage (err %d)\n", err);
|
||||
printk("Failed to clear pairings (err %d)\n", err);
|
||||
} else {
|
||||
printk("Storage successfully cleared\n");
|
||||
printk("Pairings successfully cleared\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -971,11 +912,11 @@ static int cmd_clear(int argc, char *argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
err = bt_storage_clear(&addr);
|
||||
err = bt_unpair(&addr);
|
||||
if (err) {
|
||||
printk("Failed to clear storage (err %d)\n", err);
|
||||
printk("Failed to clear pairing (err %d)\n", err);
|
||||
} else {
|
||||
printk("Storage successfully cleared\n");
|
||||
printk("Pairing successfully cleared\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <toolchain.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/storage.h>
|
||||
|
||||
#include <misc/byteorder.h>
|
||||
#include <net/buf.h>
|
||||
|
@ -608,7 +607,7 @@ static void unpair(const u8_t *data, u16_t len)
|
|||
goto rsp;
|
||||
}
|
||||
keys:
|
||||
err = bt_storage_clear(&addr);
|
||||
err = bt_unpair(&addr);
|
||||
|
||||
status = err < 0 ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS;
|
||||
rsp:
|
||||
|
|
Loading…
Reference in a new issue