Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
# Include
/include/*.h @nrfconnect/ncs-bm
/include/bluetooth/ @nrfconnect/ncs-bm
/include/settings/ @nrfconnect/ncs-pluto

# Libraries
/lib/ble_adv/ @nrfconnect/ncs-bm
Expand Down Expand Up @@ -75,6 +76,7 @@
/subsys/bm_installs/ @nrfconnect/ncs-pluto
/subsys/logging/ @nrfconnect/ncs-bm
/subsys/mgmt/mcumgr/ @nrfconnect/ncs-pluto
/subsys/settings/ @nrfconnect/ncs-pluto
/subsys/softdevice/ @nrfconnect/ncs-bm
/subsys/softdevice_handler/ @nrfconnect/ncs-bm
/subsys/storage/flash_map/ @nrfconnect/ncs-pluto
Expand Down
14 changes: 14 additions & 0 deletions include/settings/bluetooth_name.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include <stdint.h>

/**
* @brief Retrieve the variable which holds the desired device advertising name.
*
* @retval Address of device name setting.
*/
const char *bluetooth_name_value_get(void);
6 changes: 6 additions & 0 deletions samples/boot/mcuboot_recovery_entry/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,9 @@ CONFIG_NRF_SDH_BLE_GATT_MAX_MTU_SIZE=498
CONFIG_BLE_CONN_PARAMS_MAX_CONN_INTERVAL=24
CONFIG_BLE_CONN_PARAMS_SUP_TIMEOUT=20
CONFIG_BLE_CONN_PARAMS_MAX_SUP_TIMEOUT_DEVIATION=20

CONFIG_SETTINGS=y
CONFIG_SETTINGS_RETENTION=y
CONFIG_SETTINGS_RUNTIME=y
CONFIG_MCUMGR_GRP_SETTINGS=y
CONFIG_NCS_BM_SETTINGS_BLUETOOTH_NAME=y
9 changes: 9 additions & 0 deletions samples/boot/mcuboot_recovery_entry/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <zephyr/logging/log_ctrl.h>
#include <zephyr/mgmt/mcumgr/mgmt/callbacks.h>
#include <bluetooth/services/ble_mcumgr.h>
#include <zephyr/settings/settings.h>

LOG_MODULE_REGISTER(app, CONFIG_APP_LOG_LEVEL);

Expand Down Expand Up @@ -180,6 +181,14 @@ int main(void)
return 0;
}

err = settings_subsys_init();

if (err) {
LOG_ERR("Failed to enable settings: %d", err);
}

/* settings_load(); */

LOG_INF("Bluetooth enabled");

err = ble_mcumgr_init();
Expand Down
7 changes: 7 additions & 0 deletions samples/mcumgr/ble_mcumgr/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,10 @@ CONFIG_BLE_MCUMGR=y

CONFIG_LOG=y
CONFIG_LOG_MODE_MINIMAL=y

CONFIG_RETAINED_MEM=y
CONFIG_RETENTION=y
CONFIG_SETTINGS=y
CONFIG_SETTINGS_RETENTION=y
#CONFIG_SETTINGS_RUNTIME=y
CONFIG_NCS_BM_SETTINGS_BLUETOOTH_NAME=y
47 changes: 46 additions & 1 deletion samples/mcumgr/ble_mcumgr/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#include <zephyr/logging/log_ctrl.h>
#include <ble_conn_params.h>
#include <bluetooth/services/ble_mcumgr.h>
#include <zephyr/settings/settings.h>
#include <zephyr/retention/retention.h>
#include <settings/bluetooth_name.h>

LOG_MODULE_REGISTER(app, CONFIG_APP_LOG_LEVEL);

Expand Down Expand Up @@ -175,6 +178,9 @@ static int ble_change_address(void)
int main(void)
{
int err;
const char *custom_advertising_name;
uint8_t custom_advertising_name_size;
ble_gap_conn_sec_mode_t sec_mode = {0};
struct ble_adv_config ble_adv_cfg = {
.conn_cfg_tag = CONFIG_NRF_SDH_BLE_CONN_TAG,
.evt_handler = ble_adv_evt_handler,
Expand Down Expand Up @@ -210,6 +216,13 @@ int main(void)

LOG_INF("Bluetooth enabled");

err = settings_subsys_init();

if (err) {
LOG_ERR("Failed to enable settings, err %d", err);
}

settings_load();
err = ble_mcumgr_init();

if (err) {
Expand Down Expand Up @@ -237,14 +250,46 @@ int main(void)
return 0;
}

custom_advertising_name = bluetooth_name_value_get();
custom_advertising_name_size = strlen(custom_advertising_name);

if (custom_advertising_name_size > 0) {
/* Change advertising name to one from application */
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
err = sd_ble_gap_device_name_set(&sec_mode, custom_advertising_name,
custom_advertising_name_size);

if (err) {
LOG_ERR("Failed to change advertising name, err %d", err);
return 0;
}

err = ble_adv_data_encode(&ble_adv_cfg.adv_data, ble_adv.enc_adv_data[0],
&ble_adv.adv_data.adv_data.len);

if (err) {
LOG_ERR("Failed to update advertising data, err %d", err);
return 0;
}

/* Clear settings after device name has been set so it does not persist */
err = retention_clear(DEVICE_DT_GET(DT_CHOSEN(zephyr_settings_partition)));

if (err) {
LOG_ERR("Failed to clear retention area, err %d", err);
return 0;
}
}

err = ble_adv_start(&ble_adv, BLE_ADV_MODE_FAST);

if (err) {
LOG_ERR("Failed to start advertising, err %d", err);
return 0;
}

LOG_INF("Advertising as %s", CONFIG_BLE_ADV_NAME);
LOG_INF("Advertising as %s", (custom_advertising_name_size > 0 ? custom_advertising_name :
CONFIG_BLE_ADV_NAME));

while (notification_sent == false && device_disconnected == false) {
while (LOG_PROCESS()) {
Expand Down
2 changes: 2 additions & 0 deletions scripts/ci/license_allow_list.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ Apache-2.0: |
^nrf-bm/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig
^nrf-bm/subsys/mgmt/mcumgr/grp/os_mgmt/CMakeLists.txt
^nrf-bm/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig
^nrf-bm/subsys/mgmt/mcumgr/grp/settings_mgmt/CMakeLists.txt
^nrf-bm/subsys/mgmt/mcumgr/grp/settings_mgmt/Kconfig
^nrf-bm/subsys/mgmt/mcumgr/mgmt/CMakeLists.txt
^nrf-bm/subsys/mgmt/mcumgr/mgmt/Kconfig
^nrf-bm/subsys/mgmt/mcumgr/smp/CMakeLists.txt
Expand Down
1 change: 1 addition & 0 deletions subsys/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ add_subdirectory(bm_installs)
add_subdirectory(logging)
add_subdirectory_ifdef(CONFIG_NCS_BM_MCUMGR mgmt/mcumgr)
add_subdirectory_ifdef(CONFIG_NRF_SDH softdevice_handler)
add_subdirectory_ifdef(CONFIG_SETTINGS settings)
add_subdirectory_ifdef(CONFIG_SOFTDEVICE softdevice)
add_subdirectory_ifdef(CONFIG_FLASH_MAP storage/flash_map)
# zephyr-keep-sorted-stop
1 change: 1 addition & 0 deletions subsys/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ rsource "logging/Kconfig"
rsource "mgmt/mcumgr/Kconfig"
rsource "softdevice/Kconfig"
rsource "softdevice_handler/Kconfig"
rsource "settings/Kconfig"
rsource "storage/flash_map/Kconfig"
# zephyr-keep-sorted-stop

Expand Down
1 change: 1 addition & 0 deletions subsys/mgmt/mcumgr/grp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@

add_subdirectory_ifdef(CONFIG_MCUMGR_GRP_IMG img_mgmt)
add_subdirectory_ifdef(CONFIG_MCUMGR_GRP_OS os_mgmt)
add_subdirectory_ifdef(CONFIG_MCUMGR_GRP_SETTINGS settings_mgmt)
2 changes: 2 additions & 0 deletions subsys/mgmt/mcumgr/grp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
rsource "img_mgmt/Kconfig"

rsource "os_mgmt/Kconfig"

rsource "settings_mgmt/Kconfig"
18 changes: 18 additions & 0 deletions subsys/mgmt/mcumgr/grp/settings_mgmt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#
# Copyright (c) 2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0
#

# Settings management group public API is exposed by MCUmgr API
# interface, when settings management is enabled.
zephyr_library()
zephyr_library_sources(${ZEPHYR_BASE}/subsys/mgmt/mcumgr/grp/settings_mgmt/src/settings_mgmt.c)

if(CONFIG_MCUMGR_GRP_SETTINGS AND NOT CONFIG_MCUMGR_GRP_SETTINGS_ACCESS_HOOK)
message(WARNING "Note: MCUmgr settings management is enabled but settings access hooks are "
"disabled, this is an insecure configuration and not recommended for production "
"use, as all settings on the device can be manipulated by a remote device. See "
"https://docs.zephyrproject.org/latest/services/device_mgmt/mcumgr_callbacks.html "
"for details on enabling and using MCUmgr hooks.")
endif()
68 changes: 68 additions & 0 deletions subsys/mgmt/mcumgr/grp/settings_mgmt/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright Nordic Semiconductor ASA 2023. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

menuconfig MCUMGR_GRP_SETTINGS
bool "MCUmgr handlers for settings management"
depends on SETTINGS
depends on SETTINGS_RUNTIME
select MCUMGR_SMP_CBOR_MIN_DECODING_LEVEL_2
select MCUMGR_SMP_CBOR_MIN_ENCODING_LEVEL_2 if ZCBOR_CANONICAL
select MCUMGR_SMP_CBOR_MIN_ENCODING_LEVEL_1
help
Enables MCUmgr handlers for settings manipulation.

if MCUMGR_GRP_SETTINGS

choice MCUMGR_GRP_SETTINGS_BUFFER_TYPE
prompt "Buffer type"
default MCUMGR_GRP_SETTINGS_BUFFER_TYPE_STACK
help
Selects if the stack or heap will be used for variables that are
needed when processing requests.

config MCUMGR_GRP_SETTINGS_BUFFER_TYPE_STACK
bool "Stack (fixed size)"
help
Use a fixed size stack buffer, any user-supplied values longer than
this will be rejected.

Note that stack usage for parameter storage alone will be
MCUMGR_GRP_SETTINGS_NAME_LEN + MCUMGR_GRP_SETTINGS_VALUE_LEN,
therefore the MCUmgr stack should be appropriately sized.

config MCUMGR_GRP_SETTINGS_BUFFER_TYPE_HEAP
bool "Heap (dynamic size)"
depends on COMMON_LIBC_MALLOC_ARENA_SIZE > 0
help
Use dynamic heap memory allocation through malloc, if there is
insufficient heap memory for the allocation then the request will be
rejected.

endchoice

config MCUMGR_GRP_SETTINGS_NAME_LEN
int "Maximum setting name length"
default 32
help
Maximum length of a key to lookup, this will be the size of the
variable if placed on the stack or the maximum allocated size of the
variable if placed on the heap.

config MCUMGR_GRP_SETTINGS_VALUE_LEN
int "Maximum setting value length"
default 32
help
Maximum length of a value to read, this will be the size of the
variable if placed on the stack or the allocated size of the
variable if placed on the heap (settings does not support getting
the size of a value prior to looking it up).

config MCUMGR_GRP_SETTINGS_ACCESS_HOOK
bool "Settings access hook"
depends on MCUMGR_MGMT_NOTIFICATION_HOOKS
help
Allows applications to control settings management access by
registering for a callback which is then triggered whenever a
settings read or write attempt is made.

endif
7 changes: 7 additions & 0 deletions subsys/settings/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#
# Copyright (c) 2025 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

zephyr_sources_ifdef(CONFIG_NCS_BM_SETTINGS_BLUETOOTH_NAME src/bluetooth_name.c)
13 changes: 13 additions & 0 deletions subsys/settings/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#
# Copyright (c) 2025 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

menu "Settings"
depends on SETTINGS

menuconfig NCS_BM_SETTINGS_BLUETOOTH_NAME
bool "Bluetooth name"

endmenu
92 changes: 92 additions & 0 deletions subsys/settings/src/bluetooth_name.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright (c) 2025 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include <zephyr/kernel.h>
#include <zephyr/settings/settings.h>
#include <zephyr/logging/log.h>
#include <settings/bluetooth_name.h>

LOG_MODULE_REGISTER(settings_bluetooth_name, CONFIG_SETTINGS_LOG_LEVEL);

static char bluetooth_name_val[32] = "";

static int bluetooth_name_handle_set(const char *name, size_t len, settings_read_cb read_cb,
void *cb_arg);
static int bluetooth_name_handle_export(int (*cb)(const char *name, const void *value,
size_t val_len));
static int bluetooth_name_handle_commit(void);
static int bluetooth_name_handle_get(const char *name, char *val, int val_len_max);

SETTINGS_STATIC_HANDLER_DEFINE(bluetooth_name, "bluetooth_name", bluetooth_name_handle_get,
bluetooth_name_handle_set, bluetooth_name_handle_commit,
bluetooth_name_handle_export);

static int bluetooth_name_handle_set(const char *name, size_t len, settings_read_cb read_cb,
void *cb_arg)
{
const char *next;
size_t name_len;
int rc;

name_len = settings_name_next(name, &next);

if (!next) {
if (!strncmp(name, "name", name_len)) {
if (len > (sizeof(bluetooth_name_val) - 1)) {
LOG_ERR("Invalid settings value for bluetooth_name/name");
return -EINVAL;
}

rc = read_cb(cb_arg, bluetooth_name_val, sizeof(bluetooth_name_val));

if (rc < 0) {
return rc;
} else if (rc > 0) {
LOG_ERR("Config set to %s", bluetooth_name_val);
}

return 0;
}
}

return -ENOENT;
}

static int bluetooth_name_handle_export(int (*cb)(const char *name, const void *value,
size_t val_len))
{
(void)cb("bluetooth_name/name", bluetooth_name_val, strlen(bluetooth_name_val) + 1);
LOG_ERR("export_done");
return 0;
}

static int bluetooth_name_handle_commit(void)
{
LOG_ERR("loading_done");
return 0;
}

static int bluetooth_name_handle_get(const char *name, char *val, int val_len_max)
{
const char *next;

if (name == NULL || val == NULL) {
return -EINVAL;
}

if (settings_name_steq(name, "name", &next) && !next) {
val_len_max = MIN(val_len_max, strlen(bluetooth_name_val));
memcpy(val, bluetooth_name_val, val_len_max);
return val_len_max;
}

return -ENOENT;
}

const char *bluetooth_name_value_get(void)
{
return bluetooth_name_val;
}