diff --git a/include/linker/common-rom.ld b/include/linker/common-rom.ld index 43e8a2eec08..4b987cec62c 100644 --- a/include/linker/common-rom.ld +++ b/include/linker/common-rom.ld @@ -50,3 +50,12 @@ KEEP(*(SORT_BY_NAME(".net_l2.init*"))) __net_l2_end = .; } GROUP_LINK_IN(ROMABLE_REGION) + +#if defined(CONFIG_BT_SETTINGS) + SECTION_DATA_PROLOGUE(_bt_settings_area, (OPTIONAL), SUBALIGN(4)) + { + _bt_settings_start = .; + KEEP(*(SORT_BY_NAME("._bt_settings.static.*"))) + _bt_settings_end = .; + } GROUP_LINK_IN(ROMABLE_REGION) +#endif diff --git a/subsys/bluetooth/host/settings.c b/subsys/bluetooth/host/settings.c index 23d3e1264b0..4f5406fe400 100644 --- a/subsys/bluetooth/host/settings.c +++ b/subsys/bluetooth/host/settings.c @@ -18,13 +18,28 @@ #include "hci_core.h" #include "settings.h" +/* Linker-defined symbols bound to the bt_settings_handler structs */ +extern const struct bt_settings_handler _bt_settings_start[]; +extern const struct bt_settings_handler _bt_settings_end[]; + 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) { + if (argc > 1) { + const struct bt_settings_handler *h; + + for (h = _bt_settings_start; h < _bt_settings_end; h++) { + if (!strcmp(argv[0], h->name)) { + argc--; + argv++; + + return h->set(argc, argv, val); + } + } + return -ENOENT; } @@ -102,6 +117,8 @@ static void generate_irk(void) static int commit(void) { + const struct bt_settings_handler *h; + BT_DBG(""); if (!bt_addr_le_cmp(&bt_dev.id_addr, BT_ADDR_LE_ANY) || @@ -119,15 +136,41 @@ static int commit(void) } #endif /* CONFIG_BT_PRIVACY */ + for (h = _bt_settings_start; h < _bt_settings_end; h++) { + if (h->commit) { + h->commit(); + } + } + bt_dev_show_info(); return 0; } +static int export(int (*func)(const char *name, char *val), + enum settings_export_tgt tgt) +{ + const struct bt_settings_handler *h; + + if (tgt != SETTINGS_EXPORT_PERSIST) { + BT_WARN("Only persist target supported"); + return -ENOTSUP; + } + + for (h = _bt_settings_start; h < _bt_settings_end; h++) { + if (h->export) { + h->export(func); + } + } + + return 0; +} + static struct settings_handler bt_settings = { .name = "bt", .h_set = set, .h_commit = commit, + .h_export = export, }; int bt_settings_init(void) diff --git a/subsys/bluetooth/host/settings.h b/subsys/bluetooth/host/settings.h index 6f14f32a1ab..aa10097d9e8 100644 --- a/subsys/bluetooth/host/settings.h +++ b/subsys/bluetooth/host/settings.h @@ -4,4 +4,20 @@ * SPDX-License-Identifier: Apache-2.0 */ +struct bt_settings_handler { + const char *name; + int (*set)(int argc, char **argv, char *val); + int (*commit)(void); + int (*export)(int (*func)(const char *name, char *val)); +}; + +#define BT_SETTINGS_DEFINE(_name, _set, _commit, _export) \ + const struct bt_settings_handler _name __aligned(4) \ + __in_section(_bt_settings, static, _name) = { \ + .name = STRINGIFY(_name), \ + .set = _set, \ + .commit = _commit, \ + .export = _export, \ + } + int bt_settings_init(void);