From fdaeb0d4a8fd61aec403f5dc4d04e3ce2ea7b511 Mon Sep 17 00:00:00 2001 From: raiden00pl Date: Fri, 30 Oct 2026 08:38:31 +0100 Subject: [PATCH 1/3] wireless/bluetooth/nimble: Bump NimBLE to 3932e99f. Picks up from e00b85cc..3932e99f: - porting/npl: atomic operations API, used by mesh instead of its own atomic helpers (fixes the atomic_t clash with nuttx/atomic.h) - nimble/transport/socket: LE advertising reports allocated from the discardable pool so Command Complete events are not dropped - nimble/transport: double free fix in ble_hci_emspi_rx_acl() - nimble/ll: connection parameters request and instant handling fixes - nimble/drivers/dialog_cmac: precomputed AES tables - mesh doxygen fixes, CI changes Assisted-by: Claude:claude-fable-5-1 Signed-off-by: raiden00pl --- wireless/bluetooth/nimble/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wireless/bluetooth/nimble/Kconfig b/wireless/bluetooth/nimble/Kconfig index 9a84dcb2fc2..85c7f51d790 100644 --- a/wireless/bluetooth/nimble/Kconfig +++ b/wireless/bluetooth/nimble/Kconfig @@ -21,7 +21,7 @@ if NIMBLE config NIMBLE_REF string "Version" - default "e00b85ccfc49abbaf1731bb3eddaa6340d07ab52" + default "3932e99f43041f28dcf25c42a0f06e4584774dd8" ---help--- Git ref name to use when downloading from NimBLE repo From 50f317428074e681c7fbd66391a7013c854629d0 Mon Sep 17 00:00:00 2001 From: raiden00pl Date: Fri, 2 Oct 2026 13:41:21 +0200 Subject: [PATCH 2/3] wireless/bluetooth/nimble: Add Bluetooth Mesh support. Build the NimBLE mesh host sources and map mesh features and resource limits to Kconfig. With legacy TinyCrypt, export its headers because the mesh headers include them. Requires NimBLE 3932e99f or later, whose mesh uses the NPL atomic API instead of its own atomic_t, which clashed with nuttx/atomic.h. Tested: nrf54lm20-dk and nrf54l15-tag mesh provisioning, sensor publication and link test against BlueZ bluetooth-meshd. Assisted-by: Codex:GPT-6 Signed-off-by: raiden00pl --- wireless/bluetooth/nimble/CMakeLists.txt | 35 ++- wireless/bluetooth/nimble/Kconfig | 70 ++++- .../bluetooth/nimble/include/syscfg/syscfg.h | 250 ++++++++++++++++++ 3 files changed, 351 insertions(+), 4 deletions(-) diff --git a/wireless/bluetooth/nimble/CMakeLists.txt b/wireless/bluetooth/nimble/CMakeLists.txt index 6d4620668c3..1c02e172736 100644 --- a/wireless/bluetooth/nimble/CMakeLists.txt +++ b/wireless/bluetooth/nimble/CMakeLists.txt @@ -156,11 +156,10 @@ if(CONFIG_NIMBLE) mynewt-nimble/ext/tinycrypt/src/sha256.c mynewt-nimble/ext/tinycrypt/src/utils.c) target_include_directories(nimble - PRIVATE mynewt-nimble/ext/tinycrypt/include) + PUBLIC mynewt-nimble/ext/tinycrypt/include) endif() if(CONFIG_NIMBLE_MESH) - # TODO list( APPEND SRCS @@ -169,7 +168,37 @@ if(CONFIG_NIMBLE) mynewt-nimble/nimble/host/mesh/src/adv_ext.c mynewt-nimble/nimble/host/mesh/src/adv_legacy.c mynewt-nimble/nimble/host/mesh/src/aes-ccm.c - mynewt-nimble/nimble/host/mesh/src/app_keys.c) + mynewt-nimble/nimble/host/mesh/src/app_keys.c + mynewt-nimble/nimble/host/mesh/src/beacon.c + mynewt-nimble/nimble/host/mesh/src/cdb.c + mynewt-nimble/nimble/host/mesh/src/cfg.c + mynewt-nimble/nimble/host/mesh/src/cfg_cli.c + mynewt-nimble/nimble/host/mesh/src/cfg_srv.c + mynewt-nimble/nimble/host/mesh/src/crypto.c + mynewt-nimble/nimble/host/mesh/src/friend.c + mynewt-nimble/nimble/host/mesh/src/glue.c + mynewt-nimble/nimble/host/mesh/src/health_cli.c + mynewt-nimble/nimble/host/mesh/src/health_srv.c + mynewt-nimble/nimble/host/mesh/src/heartbeat.c + mynewt-nimble/nimble/host/mesh/src/light_model.c + mynewt-nimble/nimble/host/mesh/src/lpn.c + mynewt-nimble/nimble/host/mesh/src/mesh.c + mynewt-nimble/nimble/host/mesh/src/model_cli.c + mynewt-nimble/nimble/host/mesh/src/model_srv.c + mynewt-nimble/nimble/host/mesh/src/msg.c + mynewt-nimble/nimble/host/mesh/src/net.c + mynewt-nimble/nimble/host/mesh/src/pb_adv.c + mynewt-nimble/nimble/host/mesh/src/pb_gatt.c + mynewt-nimble/nimble/host/mesh/src/pb_gatt_srv.c + mynewt-nimble/nimble/host/mesh/src/prov.c + mynewt-nimble/nimble/host/mesh/src/prov_device.c + mynewt-nimble/nimble/host/mesh/src/provisioner.c + mynewt-nimble/nimble/host/mesh/src/proxy_msg.c + mynewt-nimble/nimble/host/mesh/src/proxy_srv.c + mynewt-nimble/nimble/host/mesh/src/rpl.c + mynewt-nimble/nimble/host/mesh/src/settings.c + mynewt-nimble/nimble/host/mesh/src/subnet.c + mynewt-nimble/nimble/host/mesh/src/transport.c) target_include_directories(nimble PUBLIC mynewt-nimble/nimble/host/mesh/include) endif() diff --git a/wireless/bluetooth/nimble/Kconfig b/wireless/bluetooth/nimble/Kconfig index 85c7f51d790..9df1105ecd3 100644 --- a/wireless/bluetooth/nimble/Kconfig +++ b/wireless/bluetooth/nimble/Kconfig @@ -66,7 +66,75 @@ config NIMBLE_TINYCRYPT config NIMBLE_MESH bool "Apache NimBLE mesh support" default n - depends on EXPERIMENTAL + +if NIMBLE_MESH + +config NIMBLE_MESH_DEVICE_NAME + string "NimBLE Mesh device name" + default "nimble-mesh-node" + ---help--- + Device name sent in the PB-GATT and GATT Proxy scan response. + +config NIMBLE_MESH_PB_ADV + bool "NimBLE Mesh PB-ADV provisioning bearer" + default y + depends on NIMBLE_ROLE_BROADCASTER && NIMBLE_ROLE_OBSERVER + +config NIMBLE_MESH_PB_GATT + bool "NimBLE Mesh PB-GATT provisioning bearer" + default y + depends on NIMBLE_ROLE_PERIPHERAL + +config NIMBLE_MESH_RELAY + bool "NimBLE Mesh relay support" + default n + +config NIMBLE_MESH_GATT_PROXY + bool "NimBLE Mesh GATT Proxy support" + default y if NIMBLE_MESH_PB_GATT + depends on NIMBLE_ROLE_PERIPHERAL + +config NIMBLE_MESH_FRIEND + bool "NimBLE Mesh Friend support" + default n + +config NIMBLE_MESH_LOW_POWER + bool "NimBLE Mesh Low Power Node support" + default n + +config NIMBLE_MESH_PROVISIONER + bool "NimBLE Mesh provisioner support" + default n + +config NIMBLE_MESH_MODEL_KEY_COUNT + int "NimBLE Mesh model key slots" + default 2 + +config NIMBLE_MESH_MODEL_GROUP_COUNT + int "NimBLE Mesh model group slots" + default 4 + +config NIMBLE_MESH_SUBNET_COUNT + int "NimBLE Mesh subnet count" + default 2 + +config NIMBLE_MESH_APP_KEY_COUNT + int "NimBLE Mesh application key count" + default 2 + +config NIMBLE_MESH_ADV_BUF_COUNT + int "NimBLE Mesh advertising buffer count" + default 8 + +config NIMBLE_MESH_TX_SEG_MAX + int "NimBLE Mesh maximum outbound segments" + default 4 + +config NIMBLE_MESH_RX_SEG_MAX + int "NimBLE Mesh maximum inbound segments" + default 4 + +endif # NIMBLE_MESH menu "NimBLE role configuration" diff --git a/wireless/bluetooth/nimble/include/syscfg/syscfg.h b/wireless/bluetooth/nimble/include/syscfg/syscfg.h index 75a9d416a91..45ba8ba04c4 100644 --- a/wireless/bluetooth/nimble/include/syscfg/syscfg.h +++ b/wireless/bluetooth/nimble/include/syscfg/syscfg.h @@ -138,6 +138,256 @@ # define MYNEWT_VAL_BLE_MESH (0) #endif +#ifdef CONFIG_NIMBLE_MESH_PB_ADV +# define MYNEWT_VAL_BLE_MESH_PB_ADV (1) +#else +# define MYNEWT_VAL_BLE_MESH_PB_ADV (0) +#endif + +#ifdef CONFIG_NIMBLE_MESH_PB_GATT +# define MYNEWT_VAL_BLE_MESH_PB_GATT (1) +# define CONFIG_BT_MESH_PB_GATT_USE_DEVICE_NAME (1) +#else +# define MYNEWT_VAL_BLE_MESH_PB_GATT (0) +#endif + +#ifdef CONFIG_NIMBLE_MESH_RELAY +# define MYNEWT_VAL_BLE_MESH_RELAY (1) +# define MYNEWT_VAL_BLE_MESH_RELAY_ENABLED (1) +#else +# define MYNEWT_VAL_BLE_MESH_RELAY (0) +# define MYNEWT_VAL_BLE_MESH_RELAY_ENABLED (0) +#endif + +#ifdef CONFIG_NIMBLE_MESH_GATT_PROXY +# define MYNEWT_VAL_BLE_MESH_GATT_PROXY (1) +# define MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED (1) +# define MYNEWT_VAL_BLE_MESH_PROXY (1) +#else +# define MYNEWT_VAL_BLE_MESH_GATT_PROXY (0) +# define MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED (0) +# define MYNEWT_VAL_BLE_MESH_PROXY (0) +#endif + +#ifdef CONFIG_NIMBLE_MESH_FRIEND +# define MYNEWT_VAL_BLE_MESH_FRIEND (1) +# define MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED (1) +#else +# define MYNEWT_VAL_BLE_MESH_FRIEND (0) +# define MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED (0) +#endif + +#ifdef CONFIG_NIMBLE_MESH_LOW_POWER +# define MYNEWT_VAL_BLE_MESH_LOW_POWER (1) +# define MYNEWT_VAL_BLE_MESH_LPN_AUTO (1) +#else +# define MYNEWT_VAL_BLE_MESH_LOW_POWER (0) +# define MYNEWT_VAL_BLE_MESH_LPN_AUTO (0) +#endif + +#ifdef CONFIG_NIMBLE_MESH_PROVISIONER +# define MYNEWT_VAL_BLE_MESH_PROVISIONER (1) +#else +# define MYNEWT_VAL_BLE_MESH_PROVISIONER (0) +#endif + +#define CONFIG_BT_MESH_DEBUG_USE_ID_ADDR (0) + +#define MYNEWT_VAL_BLE_MESH_PROV (MYNEWT_VAL_BLE_MESH) +#define MYNEWT_VAL_BLE_MESH_PROV_DEVICE (MYNEWT_VAL_BLE_MESH) +#define MYNEWT_VAL_BLE_MESH_MODEL_KEY_COUNT (CONFIG_NIMBLE_MESH_MODEL_KEY_COUNT) +#define MYNEWT_VAL_BLE_MESH_MODEL_GROUP_COUNT (CONFIG_NIMBLE_MESH_MODEL_GROUP_COUNT) +#define MYNEWT_VAL_BLE_MESH_MODEL_EXTENSIONS (1) +#define MYNEWT_VAL_BLE_MESH_MODEL_VND_MSG_CID_FORCE (0) +#define MYNEWT_VAL_BLE_MESH_SUBNET_COUNT (CONFIG_NIMBLE_MESH_SUBNET_COUNT) +#define MYNEWT_VAL_BLE_MESH_APP_KEY_COUNT (CONFIG_NIMBLE_MESH_APP_KEY_COUNT) +#define MYNEWT_VAL_BLE_MESH_CRPL (10) +#define MYNEWT_VAL_BLE_MESH_MSG_CACHE_SIZE (10) +#define MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT (CONFIG_NIMBLE_MESH_ADV_BUF_COUNT) +#define MYNEWT_VAL_BLE_MESH_ADV_LEGACY (1) +#define MYNEWT_VAL_BLE_MESH_ADV_EXT (0) +#define MYNEWT_VAL_BLE_MESH_ADV_STACK_SIZE (768) +#define MYNEWT_VAL_BLE_MESH_ADV_TASK_PRIO (9) +#define MYNEWT_VAL_BLE_MESH_LABEL_COUNT (0) +#define MYNEWT_VAL_BLE_MESH_CDB_NODE_COUNT (1) +#define MYNEWT_VAL_BLE_MESH_DEFAULT_TTL (7) +#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_COUNT (2) +#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL (20) +#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT (2) +#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL (20) +#define MYNEWT_VAL_BLE_MESH_TX_SEG_MAX (CONFIG_NIMBLE_MESH_TX_SEG_MAX) +#define MYNEWT_VAL_BLE_MESH_RX_SEG_MAX (CONFIG_NIMBLE_MESH_RX_SEG_MAX) +#define MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT (1) +#define MYNEWT_VAL_BLE_MESH_SEG_BUFS (8) +#define MYNEWT_VAL_BLE_MESH_PROXY_MSG_LEN (66) +#define MYNEWT_VAL_BLE_MESH_PROXY_FILTER_SIZE (3) +#define MYNEWT_VAL_BLE_MESH_GATT_SERVER (1) +#define MYNEWT_VAL_BLE_MESH_BEACON_ENABLED (1) +#define MYNEWT_VAL_BLE_MESH_CDB (0) +#define MYNEWT_VAL_BLE_MESH_FRIEND_QUEUE_SIZE (16) +#define MYNEWT_VAL_BLE_MESH_FRIEND_RECV_WIN (255) +#define MYNEWT_VAL_BLE_MESH_IV_UPDATE_SEQ_LIMIT (0x800000) +#define MYNEWT_VAL_BLE_MESH_IV_UPDATE_TEST (0) +#define MYNEWT_VAL_BLE_MESH_IVU_DIVIDER (4) +#define MYNEWT_VAL_BLE_MESH_LPN_ESTABLISHMENT (1) +#define MYNEWT_VAL_BLE_MESH_LPN_GROUPS (8) +#define MYNEWT_VAL_BLE_MESH_LPN_POLL_TIMEOUT (300) +#define MYNEWT_VAL_BLE_MESH_LPN_SUB_ALL_NODES_ADDR (0) +#define MYNEWT_VAL_BLE_MESH_NODE_ID_TIMEOUT (60) +#define MYNEWT_VAL_BLE_MESH_RPL_STORE_TIMEOUT (5) +#define MYNEWT_VAL_BLE_MESH_STORE_TIMEOUT (2) +#define MYNEWT_VAL_BLE_MESH_SEQ_STORE_RATE (128) +#define MYNEWT_VAL_BLE_MESH_DEBUG_CFG (0) +#define MYNEWT_VAL_BLE_MESH_DEBUG_ADV (0) +#define MYNEWT_VAL_BLE_MESH_SETTINGS (0) +#define MYNEWT_VAL_BLE_MESH_TESTING (0) +#define MYNEWT_VAL_BLE_MESH_DEVICE_NAME CONFIG_NIMBLE_MESH_DEVICE_NAME +#define MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG (0) +#define MYNEWT_VAL_BLE_MESH_NET_BUF_USER_DATA_SIZE (4) +#define MYNEWT_VAL_BLE_MESH_LOOPBACK_BUFS (3) +#define MYNEWT_VAL_BLE_MESH_PROV_OOB_PUBLIC_KEY (0) +#define MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT (500) +#define MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT (10) +#define MYNEWT_VAL_BLE_MESH_SEG_RETRANSMIT_ATTEMPTS (3) +#define MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT (1) +#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST (200) +#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP (200) +#define MYNEWT_VAL_BLE_MESH_SHELL (0) +#define MYNEWT_VAL_BLE_MESH_SHELL_MODELS (0) +#define MYNEWT_VAL_BLE_MESH_CFG_CLI (0) +#define MYNEWT_VAL_BLE_MESH_HEALTH_CLI (0) +#define MYNEWT_VAL_BLE_MESH_DEV_UUID \ + {0xdd, 0xaa, 0x00, 0x00, 0x4d, 0x45, 0x53, 0x48, \ + 0x00, 0x00, 0x00, 0x00, 0x4e, 0x4f, 0x44, 0x45} +#define MYNEWT_VAL_BLE_MESH_OOB_OUTPUT_SIZE (0) +#define MYNEWT_VAL_BLE_MESH_OOB_OUTPUT_ACTIONS (0) +#define MYNEWT_VAL_BLE_MESH_OOB_INPUT_SIZE (0) +#define MYNEWT_VAL_BLE_MESH_OOB_INPUT_ACTIONS (0) +#define MYNEWT_VAL_BLE_MESH_CDB_SUBNET_COUNT (CONFIG_NIMBLE_MESH_SUBNET_COUNT) +#define MYNEWT_VAL_BLE_MESH_CDB_APP_KEY_COUNT (CONFIG_NIMBLE_MESH_APP_KEY_COUNT) +#define MYNEWT_VAL_BLE_MESH_FRIEND_SEG_RX (0) +#define MYNEWT_VAL_BLE_MESH_FRIEND_SUB_LIST_SIZE (0) +#define MYNEWT_VAL_BLE_MESH_FRIEND_LPN_COUNT (0) +#define MYNEWT_VAL_BLE_MESH_LPN_AUTO_TIMEOUT (10) +#define MYNEWT_VAL_BLE_MESH_LPN_RECV_DELAY (100) +#define MYNEWT_VAL_BLE_MESH_LPN_SCAN_LATENCY (10) +#define MYNEWT_VAL_BLE_MESH_LPN_RETRY_TIMEOUT (8) +#define MYNEWT_VAL_BLE_MESH_LPN_INIT_POLL_TIMEOUT (300) +#define MYNEWT_VAL_BLE_MESH_LPN_MIN_QUEUE_SIZE (1) +#define MYNEWT_VAL_BLE_MESH_LPN_RSSI_FACTOR (0) +#define MYNEWT_VAL_BLE_MESH_LPN_RECV_WIN_FACTOR (0) + +#define LOG_LEVEL_DEBUG (0) +#define LOG_LEVEL_INFO (1) +#define MYNEWT_VAL_BLE_MESH_ACCESS_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_ADV_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_BEACON_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_CRYPTO_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_FRIEND_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_LOW_POWER_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_MODEL_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_NET_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_PROV_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_PROXY_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_SETTINGS_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_TRANS_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_RPL_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_NET_KEYS_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_PROV_DEVICE_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_PROVISIONER_LOG_LVL LOG_LEVEL_INFO +#define MYNEWT_VAL_BLE_MESH_HEARTBEAT_LOG_LVL LOG_LEVEL_INFO + +#define BLE_MESH_ACCESS_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_ACCESS_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_ACCESS_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_ACCESS_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_ACCESS_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_ADV_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_ADV_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_ADV_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_ADV_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_ADV_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_BEACON_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_BEACON_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_BEACON_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_BEACON_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_BEACON_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_CRYPTO_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_CRYPTO_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_CRYPTO_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_CRYPTO_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_CRYPTO_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_FRIEND_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_FRIEND_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_FRIEND_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_FRIEND_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_FRIEND_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_LOW_POWER_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_LOW_POWER_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_LOW_POWER_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_LOW_POWER_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_LOW_POWER_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_MODEL_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_MODEL_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_MODEL_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_MODEL_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_MODEL_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_NET_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_NET_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_NET_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_NET_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_NET_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_PROV_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_PROV_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_PROV_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_PROV_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_PROV_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_PROXY_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_PROXY_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_PROXY_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_PROXY_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_PROXY_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_SETTINGS_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_SETTINGS_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_SETTINGS_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_SETTINGS_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_SETTINGS_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_TRANS_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_TRANS_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_TRANS_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_TRANS_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_TRANS_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_RPL_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_RPL_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_RPL_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_RPL_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_RPL_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_NET_KEYS_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_NET_KEYS_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_NET_KEYS_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_NET_KEYS_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_NET_KEYS_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_PROV_DEVICE_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_PROV_DEVICE_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_PROV_DEVICE_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_PROV_DEVICE_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_PROV_DEVICE_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_PROVISIONER_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_PROVISIONER_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_PROVISIONER_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_PROVISIONER_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_PROVISIONER_LOG_CRITICAL DFLT_LOG_CRITICAL +#define BLE_MESH_HEARTBEAT_LOG_DEBUG DFLT_LOG_DEBUG +#define BLE_MESH_HEARTBEAT_LOG_INFO DFLT_LOG_INFO +#define BLE_MESH_HEARTBEAT_LOG_WARN DFLT_LOG_WARN +#define BLE_MESH_HEARTBEAT_LOG_ERROR DFLT_LOG_ERROR +#define BLE_MESH_HEARTBEAT_LOG_CRITICAL DFLT_LOG_CRITICAL + #ifdef CONFIG_NIMBLE_BLE_CONN_SUBRATING # define MYNEWT_VAL_BLE_CONN_SUBRATING (1) #else From 81c9a548468972e23d3c55a959e0d0dba11788ea Mon Sep 17 00:00:00 2001 From: raiden00pl Date: Fri, 2 Oct 2026 13:41:21 +0200 Subject: [PATCH 3/3] examples: Add NimBLE mesh node, sensor and vendor examples. Provisionable mesh nodes over PB-ADV and PB-GATT. The node example answers Generic OnOff Get and Set with Status, the sensor example serves one Present Ambient Temperature property with its descriptor, and the vendor example stores a byte through vendor Get, Set and Status opcodes. Assisted-by: Codex:GPT-6 Assisted-by: Claude:claude-fable-5-1 Signed-off-by: raiden00pl --- examples/nimble_mesh_node/CMakeLists.txt | 37 ++ examples/nimble_mesh_node/Kconfig | 27 ++ examples/nimble_mesh_node/Make.defs | 25 ++ examples/nimble_mesh_node/Makefile | 34 ++ .../nimble_mesh_node/nimble_mesh_node_main.c | 336 +++++++++++++++ examples/nimble_mesh_sensor/CMakeLists.txt | 37 ++ examples/nimble_mesh_sensor/Kconfig | 27 ++ examples/nimble_mesh_sensor/Make.defs | 25 ++ examples/nimble_mesh_sensor/Makefile | 34 ++ .../nimble_mesh_sensor_main.c | 400 ++++++++++++++++++ examples/nimble_mesh_vendor/CMakeLists.txt | 37 ++ examples/nimble_mesh_vendor/Kconfig | 27 ++ examples/nimble_mesh_vendor/Make.defs | 25 ++ examples/nimble_mesh_vendor/Makefile | 34 ++ .../nimble_mesh_vendor_main.c | 322 ++++++++++++++ 15 files changed, 1427 insertions(+) create mode 100644 examples/nimble_mesh_node/CMakeLists.txt create mode 100644 examples/nimble_mesh_node/Kconfig create mode 100644 examples/nimble_mesh_node/Make.defs create mode 100644 examples/nimble_mesh_node/Makefile create mode 100644 examples/nimble_mesh_node/nimble_mesh_node_main.c create mode 100644 examples/nimble_mesh_sensor/CMakeLists.txt create mode 100644 examples/nimble_mesh_sensor/Kconfig create mode 100644 examples/nimble_mesh_sensor/Make.defs create mode 100644 examples/nimble_mesh_sensor/Makefile create mode 100644 examples/nimble_mesh_sensor/nimble_mesh_sensor_main.c create mode 100644 examples/nimble_mesh_vendor/CMakeLists.txt create mode 100644 examples/nimble_mesh_vendor/Kconfig create mode 100644 examples/nimble_mesh_vendor/Make.defs create mode 100644 examples/nimble_mesh_vendor/Makefile create mode 100644 examples/nimble_mesh_vendor/nimble_mesh_vendor_main.c diff --git a/examples/nimble_mesh_node/CMakeLists.txt b/examples/nimble_mesh_node/CMakeLists.txt new file mode 100644 index 00000000000..957fa4ab8e7 --- /dev/null +++ b/examples/nimble_mesh_node/CMakeLists.txt @@ -0,0 +1,37 @@ +# ############################################################################## +# apps/examples/nimble_mesh_node/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +if(CONFIG_EXAMPLES_NIMBLE_MESH_NODE) + nuttx_add_application( + NAME + ${CONFIG_EXAMPLES_NIMBLE_MESH_NODE_PROGNAME} + PRIORITY + ${CONFIG_EXAMPLES_NIMBLE_MESH_NODE_PRIORITY} + STACKSIZE + ${CONFIG_EXAMPLES_NIMBLE_MESH_NODE_STACKSIZE} + MODULE + ${CONFIG_EXAMPLES_NIMBLE_MESH_NODE} + SRCS + nimble_mesh_node_main.c + DEPENDS + nimble) +endif() diff --git a/examples/nimble_mesh_node/Kconfig b/examples/nimble_mesh_node/Kconfig new file mode 100644 index 00000000000..f879698708c --- /dev/null +++ b/examples/nimble_mesh_node/Kconfig @@ -0,0 +1,27 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config EXAMPLES_NIMBLE_MESH_NODE + tristate "NimBLE Mesh Generic OnOff node example" + default n + depends on NIMBLE_MESH + ---help--- + Provisionable NimBLE Mesh node with a Generic OnOff Server. + +if EXAMPLES_NIMBLE_MESH_NODE + +config EXAMPLES_NIMBLE_MESH_NODE_PROGNAME + string "Program name" + default "nimble_mesh_node" + +config EXAMPLES_NIMBLE_MESH_NODE_PRIORITY + int "Task priority" + default 100 + +config EXAMPLES_NIMBLE_MESH_NODE_STACKSIZE + int "Stack size" + default 4096 + +endif diff --git a/examples/nimble_mesh_node/Make.defs b/examples/nimble_mesh_node/Make.defs new file mode 100644 index 00000000000..b95fb8bbd6d --- /dev/null +++ b/examples/nimble_mesh_node/Make.defs @@ -0,0 +1,25 @@ +############################################################################ +# apps/examples/nimble_mesh_node/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifneq ($(CONFIG_EXAMPLES_NIMBLE_MESH_NODE),) +CONFIGURED_APPS += $(APPDIR)/examples/nimble_mesh_node +endif diff --git a/examples/nimble_mesh_node/Makefile b/examples/nimble_mesh_node/Makefile new file mode 100644 index 00000000000..c1e3fcf8e10 --- /dev/null +++ b/examples/nimble_mesh_node/Makefile @@ -0,0 +1,34 @@ +############################################################################ +# apps/examples/nimble_mesh_node/Makefile +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(APPDIR)/Make.defs + +PROGNAME = $(CONFIG_EXAMPLES_NIMBLE_MESH_NODE_PROGNAME) +PRIORITY = $(CONFIG_EXAMPLES_NIMBLE_MESH_NODE_PRIORITY) +STACKSIZE = $(CONFIG_EXAMPLES_NIMBLE_MESH_NODE_STACKSIZE) +MODULE = $(CONFIG_EXAMPLES_NIMBLE_MESH_NODE) + +MAINSRC = nimble_mesh_node_main.c + +include $(APPDIR)/wireless/bluetooth/nimble/Makefile.nimble + +include $(APPDIR)/Application.mk diff --git a/examples/nimble_mesh_node/nimble_mesh_node_main.c b/examples/nimble_mesh_node/nimble_mesh_node_main.c new file mode 100644 index 00000000000..a8ebbb67cae --- /dev/null +++ b/examples/nimble_mesh_node/nimble_mesh_node_main.c @@ -0,0 +1,336 @@ +/**************************************************************************** + * apps/examples/nimble_mesh_node/nimble_mesh_node_main.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "host/ble_hs.h" +#include "netutils/netinit.h" +#include "nimble/nimble_port.h" +#include "services/gap/ble_svc_gap.h" +#include "services/gatt/ble_svc_gatt.h" +#include "mesh/glue.h" +#include "mesh/access.h" +#include "mesh/cfg_srv.h" +#include "mesh/health_srv.h" +#include "mesh/main.h" +#include "mesh/msg.h" +#include "mesh/porting.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define COMPANY_ID 0x05f1 + +/* Generic OnOff opcodes */ + +#define ONOFF_GET BT_MESH_MODEL_OP_2(0x82, 0x01) +#define ONOFF_SET BT_MESH_MODEL_OP_2(0x82, 0x02) +#define ONOFF_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x03) +#define ONOFF_STATUS BT_MESH_MODEL_OP_2(0x82, 0x04) + +/**************************************************************************** + * External Functions Prototypes + ****************************************************************************/ + +void ble_hci_sock_ack_handler(FAR void *param); + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int onoff_get(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf); +static int onoff_set(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf); +static int onoff_set_unack(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint8_t g_dev_uuid[16] = +{ + 0xdd, 0xaa, 0x00, 0x01, 0x4d, 0x45, 0x53, 0x48, + 0x4f, 0x4e, 0x4f, 0x46, 0x46, 0x00, 0x00, 0x01 +}; + +static const struct bt_mesh_model_op g_onoff_ops[] = +{ + { ONOFF_GET, BT_MESH_LEN_EXACT(0), onoff_get }, + { ONOFF_SET, BT_MESH_LEN_MIN(2), onoff_set }, + { ONOFF_SET_UNACK, BT_MESH_LEN_MIN(2), onoff_set_unack }, + BT_MESH_MODEL_OP_END, +}; + +static struct bt_mesh_health_srv g_health_srv; +static struct bt_mesh_model_pub g_health_pub; +static uint8_t g_onoff_state; + +static struct bt_mesh_model g_root_models[] = +{ + BT_MESH_MODEL_CFG_SRV, + BT_MESH_MODEL_HEALTH_SRV(&g_health_srv, &g_health_pub), + BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, g_onoff_ops, NULL, NULL), +}; + +static struct bt_mesh_elem g_elements[] = +{ + { + .loc = 0x0000, + .model_count = sizeof(g_root_models) / sizeof(g_root_models[0]), + .models = g_root_models, + .vnd_model_count = 0, + .vnd_models = BT_MESH_MODEL_NONE, + }, +}; + +static const struct bt_mesh_comp g_comp = +{ + .cid = COMPANY_ID, + .elem_count = sizeof(g_elements) / sizeof(g_elements[0]), + .elem = g_elements, +}; + +static const struct bt_mesh_prov g_prov = +{ + .uuid = g_dev_uuid, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: onoff_status + * + * Description: + * Send a Generic OnOff Status with the present state. + * + ****************************************************************************/ + +static int onoff_status(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx) +{ + FAR struct os_mbuf *msg; + int ret; + + msg = NET_BUF_SIMPLE(BT_MESH_MODEL_BUF_LEN(ONOFF_STATUS, 1)); + if (msg == NULL) + { + return -ENOMEM; + } + + bt_mesh_model_msg_init(msg, ONOFF_STATUS); + net_buf_simple_add_u8(msg, g_onoff_state); + + ret = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (ret != 0) + { + printf("nimble_mesh_node: status send failed: %d\n", ret); + } + + os_mbuf_free_chain(msg); + return ret; +} + +/**************************************************************************** + * Name: onoff_get + ****************************************************************************/ + +static int onoff_get(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf) +{ + UNUSED(buf); + + printf("nimble_mesh_node: onoff get from 0x%04x\n", ctx->addr); + return onoff_status(model, ctx); +} + +/**************************************************************************** + * Name: onoff_set_unack + ****************************************************************************/ + +static int onoff_set_unack(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf) +{ + UNUSED(model); + + g_onoff_state = net_buf_simple_pull_u8(buf) ? 1 : 0; + printf("nimble_mesh_node: onoff set %u from 0x%04x\n", + g_onoff_state, ctx->addr); + return 0; +} + +/**************************************************************************** + * Name: onoff_set + ****************************************************************************/ + +static int onoff_set(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf) +{ + onoff_set_unack(model, ctx, buf); + return onoff_status(model, ctx); +} + +/**************************************************************************** + * Name: mesh_hci_task + ****************************************************************************/ + +static FAR void *mesh_hci_task(FAR void *arg) +{ + ble_hci_sock_ack_handler(arg); + return NULL; +} + +/**************************************************************************** + * Name: mesh_adv_task + ****************************************************************************/ + +static FAR void *mesh_adv_task(FAR void *arg) +{ + mesh_adv_thread(arg); + return NULL; +} + +/**************************************************************************** + * Name: mesh_on_sync + * + * Description: + * Host is synced with the controller: set a random address, initialize + * the mesh stack, start the mesh advertising thread and enable + * provisioning. + * + ****************************************************************************/ + +static void mesh_on_sync(void) +{ + pthread_attr_t attr; + pthread_t thread; + ble_addr_t addr; + int ret; + + ret = ble_hs_id_gen_rnd(1, &addr); + if (ret == 0) + { + ret = ble_hs_id_set_rnd(addr.val); + } + + if (ret != 0) + { + printf("nimble_mesh_node: address setup failed: %d\n", ret); + return; + } + + ret = bt_mesh_init(addr.type, &g_prov, &g_comp); + if (ret < 0) + { + printf("nimble_mesh_node: bt_mesh_init failed: %d\n", ret); + return; + } + + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, + CONFIG_EXAMPLES_NIMBLE_MESH_NODE_STACKSIZE); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + ret = pthread_create(&thread, &attr, mesh_adv_task, NULL); + pthread_attr_destroy(&attr); + if (ret != 0) + { + printf("nimble_mesh_node: advertising thread failed: %d\n", ret); + return; + } + + ret = bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT); + if (ret < 0) + { + printf("nimble_mesh_node: bt_mesh_prov_enable failed: %d\n", ret); + return; + } + + printf("nimble_mesh_node: provisioning enabled\n"); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: main + ****************************************************************************/ + +int main(int argc, FAR char *argv[]) +{ + struct ble_npl_task hci_task; + int ret; + + UNUSED(argc); + UNUSED(argv); + +#ifndef CONFIG_NSH_NETINIT + /* Bring up the network */ + + netinit_bringup(); +#endif + + nimble_port_init(); + + /* Initialize services */ + + ble_svc_gap_init(); + ble_svc_gatt_init(); + bt_mesh_register_gatt(); + g_health_pub.msg = BT_MESH_HEALTH_FAULT_MSG(0); + + ble_hs_cfg.sync_cb = mesh_on_sync; + + /* Create task which handles HCI socket */ + + ret = ble_npl_task_init(&hci_task, "hci_sock", mesh_hci_task, NULL, + CONFIG_EXAMPLES_NIMBLE_MESH_NODE_PRIORITY, + BLE_NPL_TIME_FOREVER, NULL, 0); + if (ret != 0) + { + printf("nimble_mesh_node: hci task failed: %d\n", ret); + return ret; + } + + /* Run the host event queue on this task */ + + nimble_port_run(); + return 0; +} diff --git a/examples/nimble_mesh_sensor/CMakeLists.txt b/examples/nimble_mesh_sensor/CMakeLists.txt new file mode 100644 index 00000000000..903ac5e72aa --- /dev/null +++ b/examples/nimble_mesh_sensor/CMakeLists.txt @@ -0,0 +1,37 @@ +# ############################################################################## +# apps/examples/nimble_mesh_sensor/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +if(CONFIG_EXAMPLES_NIMBLE_MESH_SENSOR) + nuttx_add_application( + NAME + ${CONFIG_EXAMPLES_NIMBLE_MESH_SENSOR_PROGNAME} + PRIORITY + ${CONFIG_EXAMPLES_NIMBLE_MESH_SENSOR_PRIORITY} + STACKSIZE + ${CONFIG_EXAMPLES_NIMBLE_MESH_SENSOR_STACKSIZE} + MODULE + ${CONFIG_EXAMPLES_NIMBLE_MESH_SENSOR} + SRCS + nimble_mesh_sensor_main.c + DEPENDS + nimble) +endif() diff --git a/examples/nimble_mesh_sensor/Kconfig b/examples/nimble_mesh_sensor/Kconfig new file mode 100644 index 00000000000..93078558c06 --- /dev/null +++ b/examples/nimble_mesh_sensor/Kconfig @@ -0,0 +1,27 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config EXAMPLES_NIMBLE_MESH_SENSOR + tristate "NimBLE Mesh Sensor Server node example" + default n + depends on NIMBLE_MESH + ---help--- + Provisionable NimBLE Mesh node with a Sensor Server model. + +if EXAMPLES_NIMBLE_MESH_SENSOR + +config EXAMPLES_NIMBLE_MESH_SENSOR_PROGNAME + string "Program name" + default "nimble_mesh_sensor" + +config EXAMPLES_NIMBLE_MESH_SENSOR_PRIORITY + int "Task priority" + default 100 + +config EXAMPLES_NIMBLE_MESH_SENSOR_STACKSIZE + int "Stack size" + default 4096 + +endif diff --git a/examples/nimble_mesh_sensor/Make.defs b/examples/nimble_mesh_sensor/Make.defs new file mode 100644 index 00000000000..e482d0f3e84 --- /dev/null +++ b/examples/nimble_mesh_sensor/Make.defs @@ -0,0 +1,25 @@ +############################################################################ +# apps/examples/nimble_mesh_sensor/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifneq ($(CONFIG_EXAMPLES_NIMBLE_MESH_SENSOR),) +CONFIGURED_APPS += $(APPDIR)/examples/nimble_mesh_sensor +endif diff --git a/examples/nimble_mesh_sensor/Makefile b/examples/nimble_mesh_sensor/Makefile new file mode 100644 index 00000000000..bd959af2558 --- /dev/null +++ b/examples/nimble_mesh_sensor/Makefile @@ -0,0 +1,34 @@ +############################################################################ +# apps/examples/nimble_mesh_sensor/Makefile +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(APPDIR)/Make.defs + +PROGNAME = $(CONFIG_EXAMPLES_NIMBLE_MESH_SENSOR_PROGNAME) +PRIORITY = $(CONFIG_EXAMPLES_NIMBLE_MESH_SENSOR_PRIORITY) +STACKSIZE = $(CONFIG_EXAMPLES_NIMBLE_MESH_SENSOR_STACKSIZE) +MODULE = $(CONFIG_EXAMPLES_NIMBLE_MESH_SENSOR) + +MAINSRC = nimble_mesh_sensor_main.c + +include $(APPDIR)/wireless/bluetooth/nimble/Makefile.nimble + +include $(APPDIR)/Application.mk diff --git a/examples/nimble_mesh_sensor/nimble_mesh_sensor_main.c b/examples/nimble_mesh_sensor/nimble_mesh_sensor_main.c new file mode 100644 index 00000000000..8fbb4fe244d --- /dev/null +++ b/examples/nimble_mesh_sensor/nimble_mesh_sensor_main.c @@ -0,0 +1,400 @@ +/**************************************************************************** + * apps/examples/nimble_mesh_sensor/nimble_mesh_sensor_main.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "host/ble_hs.h" +#include "netutils/netinit.h" +#include "nimble/nimble_port.h" +#include "services/gap/ble_svc_gap.h" +#include "services/gatt/ble_svc_gatt.h" +#include "mesh/glue.h" +#include "mesh/access.h" +#include "mesh/cfg_srv.h" +#include "mesh/health_srv.h" +#include "mesh/main.h" +#include "mesh/msg.h" +#include "mesh/porting.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define COMPANY_ID 0x05f1 + +/* Sensor Server opcodes */ + +#define SENSOR_DESC_GET BT_MESH_MODEL_OP_2(0x82, 0x30) +#define SENSOR_GET BT_MESH_MODEL_OP_2(0x82, 0x31) +#define SENSOR_DESC_STATUS BT_MESH_MODEL_OP_1(0x51) +#define SENSOR_STATUS BT_MESH_MODEL_OP_1(0x52) + +/* Present Ambient Temperature, Temperature 8 characteristic (0.5 C) */ + +#define SENSOR_PROPERTY 0x004f +#define SENSOR_VALUE_LEN 1 +#define SENSOR_DESC_LEN 8 + +/* Marshalled Sensor Data, Format A header: property in bits 5-15, + * length minus one in bits 1-4, format bit clear. + */ + +#define SENSOR_HDR_A(prop, len) (((prop) << 5) | (((len) - 1) << 1)) + +/* Format B header for an unknown property: zero length */ + +#define SENSOR_HDR_B_EMPTY 0xff + +/**************************************************************************** + * External Functions Prototypes + ****************************************************************************/ + +void ble_hci_sock_ack_handler(FAR void *param); + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int sensor_desc_get(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf); +static int sensor_get(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint8_t g_dev_uuid[16] = +{ + 0xdd, 0xaa, 0x00, 0x02, 0x4d, 0x45, 0x53, 0x48, + 0x53, 0x45, 0x4e, 0x53, 0x00, 0x00, 0x00, 0x01 +}; + +static const struct bt_mesh_model_op g_sensor_ops[] = +{ + { SENSOR_DESC_GET, BT_MESH_LEN_MIN(0), sensor_desc_get }, + { SENSOR_GET, BT_MESH_LEN_MIN(0), sensor_get }, + BT_MESH_MODEL_OP_END, +}; + +static struct bt_mesh_health_srv g_health_srv; +static struct bt_mesh_model_pub g_health_pub; + +/* Simulated temperature in 0.5 C steps, incremented on every read */ + +static int8_t g_temperature = 44; + +static struct bt_mesh_model g_root_models[] = +{ + BT_MESH_MODEL_CFG_SRV, + BT_MESH_MODEL_HEALTH_SRV(&g_health_srv, &g_health_pub), + BT_MESH_MODEL(BT_MESH_MODEL_ID_SENSOR_SRV, g_sensor_ops, NULL, NULL), +}; + +static struct bt_mesh_elem g_elements[] = +{ + { + .loc = 0x0000, + .model_count = sizeof(g_root_models) / sizeof(g_root_models[0]), + .models = g_root_models, + .vnd_model_count = 0, + .vnd_models = BT_MESH_MODEL_NONE, + }, +}; + +static const struct bt_mesh_comp g_comp = +{ + .cid = COMPANY_ID, + .elem_count = sizeof(g_elements) / sizeof(g_elements[0]), + .elem = g_elements, +}; + +static const struct bt_mesh_prov g_prov = +{ + .uuid = g_dev_uuid, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sensor_property + * + * Description: + * Return the optional Property ID from a Get message, or -1 for all. + * + ****************************************************************************/ + +static int sensor_property(FAR struct os_mbuf *buf) +{ + if (buf->om_len < 2) + { + return -1; + } + + return net_buf_simple_pull_le16(buf); +} + +/**************************************************************************** + * Name: sensor_desc_get + * + * Description: + * Reply with the Sensor Descriptor Status. Tolerances, sampling + * function, measurement period and update interval are unspecified. + * + ****************************************************************************/ + +static int sensor_desc_get(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf) +{ + FAR struct os_mbuf *msg; + int property; + int ret; + + property = sensor_property(buf); + printf("nimble_mesh_sensor: descriptor get %d from 0x%04x\n", + property, ctx->addr); + + msg = NET_BUF_SIMPLE(BT_MESH_MODEL_BUF_LEN(SENSOR_DESC_STATUS, + SENSOR_DESC_LEN)); + if (msg == NULL) + { + return -ENOMEM; + } + + bt_mesh_model_msg_init(msg, SENSOR_DESC_STATUS); + if (property < 0 || property == SENSOR_PROPERTY) + { + net_buf_simple_add_le16(msg, SENSOR_PROPERTY); + net_buf_simple_add_le24(msg, 0); + net_buf_simple_add_u8(msg, 0); + net_buf_simple_add_u8(msg, 0); + net_buf_simple_add_u8(msg, 0); + } + else + { + /* Unknown property: the Property ID alone */ + + net_buf_simple_add_le16(msg, property); + } + + ret = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (ret != 0) + { + printf("nimble_mesh_sensor: status send failed: %d\n", ret); + } + + os_mbuf_free_chain(msg); + return ret; +} + +/**************************************************************************** + * Name: sensor_get + * + * Description: + * Reply with the Sensor Status carrying the present temperature. + * + ****************************************************************************/ + +static int sensor_get(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf) +{ + FAR struct os_mbuf *msg; + int property; + int ret; + + property = sensor_property(buf); + printf("nimble_mesh_sensor: get %d from 0x%04x\n", property, ctx->addr); + + msg = NET_BUF_SIMPLE(BT_MESH_MODEL_BUF_LEN(SENSOR_STATUS, + 2 + SENSOR_VALUE_LEN)); + if (msg == NULL) + { + return -ENOMEM; + } + + bt_mesh_model_msg_init(msg, SENSOR_STATUS); + if (property < 0 || property == SENSOR_PROPERTY) + { + net_buf_simple_add_le16(msg, SENSOR_HDR_A(SENSOR_PROPERTY, + SENSOR_VALUE_LEN)); + net_buf_simple_add_u8(msg, (uint8_t)g_temperature); + g_temperature++; + } + else + { + /* Unknown property: Format B header without a value */ + + net_buf_simple_add_u8(msg, SENSOR_HDR_B_EMPTY); + net_buf_simple_add_le16(msg, property); + } + + ret = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (ret != 0) + { + printf("nimble_mesh_sensor: status send failed: %d\n", ret); + } + + os_mbuf_free_chain(msg); + return ret; +} + +/**************************************************************************** + * Name: mesh_hci_task + ****************************************************************************/ + +static FAR void *mesh_hci_task(FAR void *arg) +{ + ble_hci_sock_ack_handler(arg); + return NULL; +} + +/**************************************************************************** + * Name: mesh_adv_task + ****************************************************************************/ + +static FAR void *mesh_adv_task(FAR void *arg) +{ + mesh_adv_thread(arg); + return NULL; +} + +/**************************************************************************** + * Name: mesh_on_sync + * + * Description: + * Host is synced with the controller: set a random address, initialize + * the mesh stack, start the mesh advertising thread and enable + * provisioning. + * + ****************************************************************************/ + +static void mesh_on_sync(void) +{ + pthread_attr_t attr; + pthread_t thread; + ble_addr_t addr; + int ret; + + ret = ble_hs_id_gen_rnd(1, &addr); + if (ret == 0) + { + ret = ble_hs_id_set_rnd(addr.val); + } + + if (ret != 0) + { + printf("nimble_mesh_sensor: address setup failed: %d\n", ret); + return; + } + + ret = bt_mesh_init(addr.type, &g_prov, &g_comp); + if (ret < 0) + { + printf("nimble_mesh_sensor: bt_mesh_init failed: %d\n", ret); + return; + } + + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, + CONFIG_EXAMPLES_NIMBLE_MESH_SENSOR_STACKSIZE); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + ret = pthread_create(&thread, &attr, mesh_adv_task, NULL); + pthread_attr_destroy(&attr); + if (ret != 0) + { + printf("nimble_mesh_sensor: advertising thread failed: %d\n", ret); + return; + } + + ret = bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT); + if (ret < 0) + { + printf("nimble_mesh_sensor: bt_mesh_prov_enable failed: %d\n", ret); + return; + } + + printf("nimble_mesh_sensor: provisioning enabled\n"); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: main + ****************************************************************************/ + +int main(int argc, FAR char *argv[]) +{ + struct ble_npl_task hci_task; + int ret; + + UNUSED(argc); + UNUSED(argv); + +#ifndef CONFIG_NSH_NETINIT + /* Bring up the network */ + + netinit_bringup(); +#endif + + nimble_port_init(); + + /* Initialize services */ + + ble_svc_gap_init(); + ble_svc_gatt_init(); + bt_mesh_register_gatt(); + g_health_pub.msg = BT_MESH_HEALTH_FAULT_MSG(0); + + ble_hs_cfg.sync_cb = mesh_on_sync; + + /* Create task which handles HCI socket */ + + ret = ble_npl_task_init(&hci_task, "hci_sock", mesh_hci_task, NULL, + CONFIG_EXAMPLES_NIMBLE_MESH_SENSOR_PRIORITY, + BLE_NPL_TIME_FOREVER, NULL, 0); + if (ret != 0) + { + printf("nimble_mesh_sensor: hci task failed: %d\n", ret); + return ret; + } + + /* Run the host event queue on this task */ + + nimble_port_run(); + return 0; +} diff --git a/examples/nimble_mesh_vendor/CMakeLists.txt b/examples/nimble_mesh_vendor/CMakeLists.txt new file mode 100644 index 00000000000..2cf2325f4c0 --- /dev/null +++ b/examples/nimble_mesh_vendor/CMakeLists.txt @@ -0,0 +1,37 @@ +# ############################################################################## +# apps/examples/nimble_mesh_vendor/CMakeLists.txt +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more contributor +# license agreements. See the NOTICE file distributed with this work for +# additional information regarding copyright ownership. The ASF licenses this +# file to you under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# +# ############################################################################## + +if(CONFIG_EXAMPLES_NIMBLE_MESH_VENDOR) + nuttx_add_application( + NAME + ${CONFIG_EXAMPLES_NIMBLE_MESH_VENDOR_PROGNAME} + PRIORITY + ${CONFIG_EXAMPLES_NIMBLE_MESH_VENDOR_PRIORITY} + STACKSIZE + ${CONFIG_EXAMPLES_NIMBLE_MESH_VENDOR_STACKSIZE} + MODULE + ${CONFIG_EXAMPLES_NIMBLE_MESH_VENDOR} + SRCS + nimble_mesh_vendor_main.c + DEPENDS + nimble) +endif() diff --git a/examples/nimble_mesh_vendor/Kconfig b/examples/nimble_mesh_vendor/Kconfig new file mode 100644 index 00000000000..7e3d653055e --- /dev/null +++ b/examples/nimble_mesh_vendor/Kconfig @@ -0,0 +1,27 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config EXAMPLES_NIMBLE_MESH_VENDOR + tristate "NimBLE Mesh vendor model node example" + default n + depends on NIMBLE_MESH + ---help--- + Provisionable NimBLE Mesh node with a simple vendor model. + +if EXAMPLES_NIMBLE_MESH_VENDOR + +config EXAMPLES_NIMBLE_MESH_VENDOR_PROGNAME + string "Program name" + default "nimble_mesh_vendor" + +config EXAMPLES_NIMBLE_MESH_VENDOR_PRIORITY + int "Task priority" + default 100 + +config EXAMPLES_NIMBLE_MESH_VENDOR_STACKSIZE + int "Stack size" + default 4096 + +endif diff --git a/examples/nimble_mesh_vendor/Make.defs b/examples/nimble_mesh_vendor/Make.defs new file mode 100644 index 00000000000..7ec920964e0 --- /dev/null +++ b/examples/nimble_mesh_vendor/Make.defs @@ -0,0 +1,25 @@ +############################################################################ +# apps/examples/nimble_mesh_vendor/Make.defs +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifneq ($(CONFIG_EXAMPLES_NIMBLE_MESH_VENDOR),) +CONFIGURED_APPS += $(APPDIR)/examples/nimble_mesh_vendor +endif diff --git a/examples/nimble_mesh_vendor/Makefile b/examples/nimble_mesh_vendor/Makefile new file mode 100644 index 00000000000..784efd77c50 --- /dev/null +++ b/examples/nimble_mesh_vendor/Makefile @@ -0,0 +1,34 @@ +############################################################################ +# apps/examples/nimble_mesh_vendor/Makefile +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(APPDIR)/Make.defs + +PROGNAME = $(CONFIG_EXAMPLES_NIMBLE_MESH_VENDOR_PROGNAME) +PRIORITY = $(CONFIG_EXAMPLES_NIMBLE_MESH_VENDOR_PRIORITY) +STACKSIZE = $(CONFIG_EXAMPLES_NIMBLE_MESH_VENDOR_STACKSIZE) +MODULE = $(CONFIG_EXAMPLES_NIMBLE_MESH_VENDOR) + +MAINSRC = nimble_mesh_vendor_main.c + +include $(APPDIR)/wireless/bluetooth/nimble/Makefile.nimble + +include $(APPDIR)/Application.mk diff --git a/examples/nimble_mesh_vendor/nimble_mesh_vendor_main.c b/examples/nimble_mesh_vendor/nimble_mesh_vendor_main.c new file mode 100644 index 00000000000..2345197551d --- /dev/null +++ b/examples/nimble_mesh_vendor/nimble_mesh_vendor_main.c @@ -0,0 +1,322 @@ +/**************************************************************************** + * apps/examples/nimble_mesh_vendor/nimble_mesh_vendor_main.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "host/ble_hs.h" +#include "netutils/netinit.h" +#include "nimble/nimble_port.h" +#include "services/gap/ble_svc_gap.h" +#include "services/gatt/ble_svc_gatt.h" +#include "mesh/glue.h" +#include "mesh/access.h" +#include "mesh/cfg_srv.h" +#include "mesh/health_srv.h" +#include "mesh/main.h" +#include "mesh/msg.h" +#include "mesh/porting.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define COMPANY_ID 0x05f1 +#define VENDOR_MODEL_ID 0x0001 + +/* Vendor opcodes: Get and Set carry a one byte value in Status */ + +#define VENDOR_GET BT_MESH_MODEL_OP_3(0x01, COMPANY_ID) +#define VENDOR_STATUS BT_MESH_MODEL_OP_3(0x02, COMPANY_ID) +#define VENDOR_SET BT_MESH_MODEL_OP_3(0x03, COMPANY_ID) + +/**************************************************************************** + * External Functions Prototypes + ****************************************************************************/ + +void ble_hci_sock_ack_handler(FAR void *param); + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int vendor_get(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf); +static int vendor_set(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint8_t g_dev_uuid[16] = +{ + 0xdd, 0xaa, 0x00, 0x03, 0x4d, 0x45, 0x53, 0x48, + 0x56, 0x4e, 0x44, 0x00, 0x00, 0x00, 0x00, 0x01 +}; + +static const struct bt_mesh_model_op g_vendor_ops[] = +{ + { VENDOR_GET, BT_MESH_LEN_EXACT(0), vendor_get }, + { VENDOR_SET, BT_MESH_LEN_EXACT(1), vendor_set }, + BT_MESH_MODEL_OP_END, +}; + +static struct bt_mesh_health_srv g_health_srv; +static struct bt_mesh_model_pub g_health_pub; +static uint8_t g_vendor_value; + +static struct bt_mesh_model g_root_models[] = +{ + BT_MESH_MODEL_CFG_SRV, + BT_MESH_MODEL_HEALTH_SRV(&g_health_srv, &g_health_pub), +}; + +static struct bt_mesh_model g_vendor_models[] = +{ + BT_MESH_MODEL_VND(COMPANY_ID, VENDOR_MODEL_ID, g_vendor_ops, NULL, NULL), +}; + +static struct bt_mesh_elem g_elements[] = +{ + { + .loc = 0x0000, + .model_count = sizeof(g_root_models) / sizeof(g_root_models[0]), + .models = g_root_models, + .vnd_model_count = sizeof(g_vendor_models) / sizeof(g_vendor_models[0]), + .vnd_models = g_vendor_models, + }, +}; + +static const struct bt_mesh_comp g_comp = +{ + .cid = COMPANY_ID, + .elem_count = sizeof(g_elements) / sizeof(g_elements[0]), + .elem = g_elements, +}; + +static const struct bt_mesh_prov g_prov = +{ + .uuid = g_dev_uuid, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vendor_status + * + * Description: + * Send a vendor Status with the stored value. + * + ****************************************************************************/ + +static int vendor_status(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx) +{ + FAR struct os_mbuf *msg; + int ret; + + msg = NET_BUF_SIMPLE(BT_MESH_MODEL_BUF_LEN(VENDOR_STATUS, 1)); + if (msg == NULL) + { + return -ENOMEM; + } + + bt_mesh_model_msg_init(msg, VENDOR_STATUS); + net_buf_simple_add_u8(msg, g_vendor_value); + + ret = bt_mesh_model_send(model, ctx, msg, NULL, NULL); + if (ret != 0) + { + printf("nimble_mesh_vendor: status send failed: %d\n", ret); + } + + os_mbuf_free_chain(msg); + return ret; +} + +/**************************************************************************** + * Name: vendor_get + ****************************************************************************/ + +static int vendor_get(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf) +{ + UNUSED(buf); + + printf("nimble_mesh_vendor: get from 0x%04x\n", ctx->addr); + return vendor_status(model, ctx); +} + +/**************************************************************************** + * Name: vendor_set + ****************************************************************************/ + +static int vendor_set(FAR struct bt_mesh_model *model, + FAR struct bt_mesh_msg_ctx *ctx, + FAR struct os_mbuf *buf) +{ + g_vendor_value = net_buf_simple_pull_u8(buf); + printf("nimble_mesh_vendor: set %u from 0x%04x\n", + g_vendor_value, ctx->addr); + return vendor_status(model, ctx); +} + +/**************************************************************************** + * Name: mesh_hci_task + ****************************************************************************/ + +static FAR void *mesh_hci_task(FAR void *arg) +{ + ble_hci_sock_ack_handler(arg); + return NULL; +} + +/**************************************************************************** + * Name: mesh_adv_task + ****************************************************************************/ + +static FAR void *mesh_adv_task(FAR void *arg) +{ + mesh_adv_thread(arg); + return NULL; +} + +/**************************************************************************** + * Name: mesh_on_sync + * + * Description: + * Host is synced with the controller: set a random address, initialize + * the mesh stack, start the mesh advertising thread and enable + * provisioning. + * + ****************************************************************************/ + +static void mesh_on_sync(void) +{ + pthread_attr_t attr; + pthread_t thread; + ble_addr_t addr; + int ret; + + ret = ble_hs_id_gen_rnd(1, &addr); + if (ret == 0) + { + ret = ble_hs_id_set_rnd(addr.val); + } + + if (ret != 0) + { + printf("nimble_mesh_vendor: address setup failed: %d\n", ret); + return; + } + + ret = bt_mesh_init(addr.type, &g_prov, &g_comp); + if (ret < 0) + { + printf("nimble_mesh_vendor: bt_mesh_init failed: %d\n", ret); + return; + } + + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, + CONFIG_EXAMPLES_NIMBLE_MESH_VENDOR_STACKSIZE); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + ret = pthread_create(&thread, &attr, mesh_adv_task, NULL); + pthread_attr_destroy(&attr); + if (ret != 0) + { + printf("nimble_mesh_vendor: advertising thread failed: %d\n", ret); + return; + } + + ret = bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT); + if (ret < 0) + { + printf("nimble_mesh_vendor: bt_mesh_prov_enable failed: %d\n", ret); + return; + } + + printf("nimble_mesh_vendor: provisioning enabled\n"); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: main + ****************************************************************************/ + +int main(int argc, FAR char *argv[]) +{ + struct ble_npl_task hci_task; + int ret; + + UNUSED(argc); + UNUSED(argv); + +#ifndef CONFIG_NSH_NETINIT + /* Bring up the network */ + + netinit_bringup(); +#endif + + nimble_port_init(); + + /* Initialize services */ + + ble_svc_gap_init(); + ble_svc_gatt_init(); + bt_mesh_register_gatt(); + g_health_pub.msg = BT_MESH_HEALTH_FAULT_MSG(0); + + ble_hs_cfg.sync_cb = mesh_on_sync; + + /* Create task which handles HCI socket */ + + ret = ble_npl_task_init(&hci_task, "hci_sock", mesh_hci_task, NULL, + CONFIG_EXAMPLES_NIMBLE_MESH_VENDOR_PRIORITY, + BLE_NPL_TIME_FOREVER, NULL, 0); + if (ret != 0) + { + printf("nimble_mesh_vendor: hci task failed: %d\n", ret); + return ret; + } + + /* Run the host event queue on this task */ + + nimble_port_run(); + return 0; +}