diff --git a/components/bt/Kconfig b/components/bt/Kconfig index d417c1ef1a..d71e1fe85f 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -1858,6 +1858,37 @@ if BLE_MESH if BLE_MESH_SETTINGS + if BLE_MESH_PROVISIONER + + config BLE_MESH_USE_MULTIPLE_NAMESPACE + bool "Provisioner uses multiple NVS namespaces for BLE Mesh" + default n + help + When selected, Provisioner can use different namespaces to store + different instances of mesh information. For example, if in the + first area, Provisioner uses NetKey A, AppKey A, etc. and provisions + three devices, these information will be treated as mesh information + instance A. When Provisioner is in the second area, it uses NetKey + B, AppKey B, etc. and provisions two devices, then these information + will be treated as mesh information instance B. Here instance A and + instance B will be stored in different namespaces. + And when this option is enabled, Provisioner needs to use specific + functions to open the corresponding namespace, restore the mesh + information or erase the mesh information. + + if BLE_MESH_USE_MULTIPLE_NAMESPACE + + config BLE_MESH_MAX_NVS_NAMESPACE + int "Maximum NVS namespaces supported by Provisioner" + default 3 + range 1 255 + help + This option specifies the maximum nvs namespaces supported by Provisioner. + + endif # BLE_MESH_USE_MULTIPLE_NAMESPACE + + endif # BLE_MESH_PROVISIONER + config BLE_MESH_SPECIFIC_PARTITION bool "Use a specific NVS partition for BLE Mesh" default n @@ -1873,7 +1904,7 @@ if BLE_MESH config BLE_MESH_PARTITION_NAME string "Name of the NVS partition for BLE Mesh" - default "BLE-MESH" + default "ble_mesh" help This value defines the name of the specified NVS partition used by the mesh stack. diff --git a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c index 7d30b3a646..67f4c352d5 100644 --- a/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c +++ b/components/bt/esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c @@ -500,6 +500,225 @@ uint16_t esp_ble_mesh_provisioner_get_prov_node_count(void) return btc_ble_mesh_provisioner_get_prov_node_count(); } +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE +esp_err_t esp_ble_mesh_provisioner_open_settings_with_index(uint8_t index) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (index >= CONFIG_BLE_MESH_MAX_NVS_NAMESPACE) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PROV; + msg.act = BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_INDEX; + + arg.open_settings_with_index.index = index; + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_mesh_provisioner_open_settings_with_user_id(const char *user_id) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (!user_id || strlen(user_id) > ESP_BLE_MESH_SETTINGS_USER_ID_SIZE) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PROV; + msg.act = BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_USER_ID; + + strncpy(arg.open_settings_with_user_id.user_id, user_id, strlen(user_id)); + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_mesh_provisioner_close_settings_with_index(uint8_t index) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (index >= CONFIG_BLE_MESH_MAX_NVS_NAMESPACE) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PROV; + msg.act = BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX; + + arg.close_settings_with_index.index = index; + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_mesh_provisioner_close_settings_with_user_id(const char *user_id) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (!user_id || strlen(user_id) > ESP_BLE_MESH_SETTINGS_USER_ID_SIZE) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PROV; + msg.act = BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_USER_ID; + + strncpy(arg.close_settings_with_user_id.user_id, user_id, strlen(user_id)); + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_mesh_provisioner_restore_settings_with_index(uint8_t index) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (index >= CONFIG_BLE_MESH_MAX_NVS_NAMESPACE) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PROV; + msg.act = BTC_BLE_MESH_ACT_PROVISIONER_RESTORE_SETTINGS_WITH_INDEX; + + arg.restore_settings_with_index.index = index; + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_mesh_provisioner_restore_settings_with_user_id(const char *user_id) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (!user_id || strlen(user_id) > ESP_BLE_MESH_SETTINGS_USER_ID_SIZE) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PROV; + msg.act = BTC_BLE_MESH_ACT_PROVISIONER_RESTORE_SETTINGS_WITH_USER_ID; + + strncpy(arg.restore_settings_with_user_id.user_id, user_id, strlen(user_id)); + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_mesh_provisioner_release_settings_with_index(uint8_t index, bool erase) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (index >= CONFIG_BLE_MESH_MAX_NVS_NAMESPACE) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PROV; + msg.act = BTC_BLE_MESH_ACT_PROVISIONER_RELEASE_SETTINGS_WITH_INDEX; + + arg.release_settings_with_index.index = index; + arg.release_settings_with_index.erase = erase; + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_mesh_provisioner_release_settings_with_user_id(const char *user_id, bool erase) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (!user_id || strlen(user_id) > ESP_BLE_MESH_SETTINGS_USER_ID_SIZE) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PROV; + msg.act = BTC_BLE_MESH_ACT_PROVISIONER_RELEASE_SETTINGS_WITH_USER_ID; + + strncpy(arg.release_settings_with_user_id.user_id, user_id, strlen(user_id)); + arg.release_settings_with_user_id.erase = erase; + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_mesh_provisioner_delete_settings_with_index(uint8_t index) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (index >= CONFIG_BLE_MESH_MAX_NVS_NAMESPACE) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PROV; + msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_INDEX; + + arg.delete_settings_with_index.index = index; + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_ble_mesh_provisioner_delete_settings_with_user_id(const char *user_id) +{ + btc_ble_mesh_prov_args_t arg = {0}; + btc_msg_t msg = {0}; + + if (!user_id || strlen(user_id) > ESP_BLE_MESH_SETTINGS_USER_ID_SIZE) { + return ESP_ERR_INVALID_ARG; + } + + ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED); + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_PROV; + msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_USER_ID; + + strncpy(arg.delete_settings_with_user_id.user_id, user_id, strlen(user_id)); + return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) + == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +const char *esp_ble_mesh_provisioner_get_settings_user_id(uint8_t index) +{ + return btc_ble_mesh_provisioner_get_settings_user_id(index); +} + +uint8_t esp_ble_mesh_provisioner_get_settings_index(const char *user_id) +{ + return btc_ble_mesh_provisioner_get_settings_index(user_id); +} + +uint8_t esp_ble_mesh_provisioner_get_free_settings_user_id_count(void) +{ + return btc_ble_mesh_provisioner_get_free_settings_user_id_count(); +} +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ + #endif /* CONFIG_BLE_MESH_PROVISIONER */ #if (CONFIG_BLE_MESH_FAST_PROV) diff --git a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_networking_api.h b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_networking_api.h index 0d5bcec30b..8a572bf812 100644 --- a/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_networking_api.h +++ b/components/bt/esp_ble_mesh/api/core/include/esp_ble_mesh_networking_api.h @@ -370,6 +370,237 @@ const uint8_t *esp_ble_mesh_provisioner_get_local_net_key(uint16_t net_idx); */ uint16_t esp_ble_mesh_provisioner_get_prov_node_count(void); +/** + * @brief This function is called by Provisioner to open the corresponding + * flash section for storing mesh provisioning information. + * + * @note 1. Provisioner can use this function to open a flash section for + * storing mesh information. + * 2. And before calling any of restore, release and close functions, + * the open function must be called firstly. + * + * @param[in] index: Provisioner settings index. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_provisioner_open_settings_with_index(uint8_t index); + +/** + * @brief This function is called by Provisioner to open the corresponding + * flash section for storing mesh provisioning information. + * + * @note 1. Provisioner can use this function to open a flash section for + * storing mesh information. + * 2. And before calling any of restore, release and close functions, + * the open function must be called firstly. + * + * @param[in] user_id: User id of Provisioner settings. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_provisioner_open_settings_with_user_id(const char *user_id); + +/** + * @brief This function is called by Provisioner to close the corresponding + * flash section which has been opened previously for storing mesh + * provisioning information. + * + * @note 1. Before closing the flash section, it must has been opened previously. + * 2. When the release function is invoked, and the "erase" flag is set to + * false, then calling the close function will only close the flash section. + * And if the "erase" flag is set to true, besides closing the flash section, + * the corresponding settings user_id will also be cleaned and erased. + * + * @param[in] index: Provisioner settings index. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_provisioner_close_settings_with_index(uint8_t index); + +/** + * @brief This function is called by Provisioner to close the corresponding + * flash section which has been opened previously for storing mesh + * provisioning information. + * + * @note 1. Before closing the flash section, it must has been opened previously. + * 2. When the release function is invoked, and the "erase" flag is set to + * false, then calling the close function will only close the flash section. + * And if the "erase" flag is set to true, besides closing the flash section, + * the corresponding settings user_id will also be cleaned and erased. + * + * @param[in] user_id: User id of Provisioner settings. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_provisioner_close_settings_with_user_id(const char *user_id); + +/** + * @brief This function is called by Provisioner to restore the mesh provisioning + * information from the corresponding flash section which has been opened + * previously. + * + * @note 1. Before calling this function to restore corresponding mesh information, + * the previously restored mesh information must be released using the release + * function. + * 2. And the flash section must has been opened using the open function. + * + * @param[in] index: Provisioner settings index. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_provisioner_restore_settings_with_index(uint8_t index); + +/** + * @brief This function is called by Provisioner to restore the mesh provisioning + * information from the corresponding flash section which has been opened + * previously. + * + * @note 1. Before calling this function to restore corresponding mesh information, + * the previously restored mesh information must be released using the release + * function. + * 2. And the flash section must has been opened using the open function. + * + * @param[in] user_id: User id of Provisioner settings. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_provisioner_restore_settings_with_user_id(const char *user_id); + +/** + * @brief This function is called by Provisioner to release the mesh provisioning + * information which has been restored from the corresponding flash section. + * + * @note 1. When this function is called, if the "erase" flag is set to false, the + * restored mesh information will be cleaned (e.g. removing the NetKey, etc). + * If the "erase" flag is set to true, besides cleaning the mesh information, + * the mesh information stored in the flash section will also be erased. And + * this function will also disable the Provisioner functionality internally. + * 2. If Provisioner tries to work properly again, the restored function must + * be invoked to restore mesh information from this flash section if the mesh + * information is not erased, or from another flash section if erased. + * Before calling this, the open and restore functions must be invoked. + * 3. The whole working process of Provisioner settings should be as following: + * a) open settings A + * b) restore settings A + * c) start to provision and control nodes + * d) release settings A + * e) close settings A + * f) open settings B + * g) restore settings B + * h) start to provision and control other nodes + * i) release settings B + * j) close settings B + * k) ...... + * + * @param[in] index: Provisioner settings index. + * @param[in] erase: Indicate whether erase the information from flash. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_provisioner_release_settings_with_index(uint8_t index, bool erase); + +/** + * @brief This function is called by Provisioner to release the mesh provisioning + * information which has been restored from the corresponding flash section. + * + * @note 1. When this function is called, if the "erase" flag is set to false, the + * restored mesh information will be cleaned (e.g. removing the NetKey, etc). + * If the "erase" flag is set to true, besides cleaning the mesh information, + * the mesh information stored in the flash section will also be erased. And + * this function will also disable the Provisioner functionality internally. + * 2. If Provisioner tries to work properly again, the restored function must + * be invoked to restore mesh information from this flash section if the mesh + * information is not erased, or from another flash section if erased. + * Before calling this, the open and restore functions must be invoked. + * 3. The whole working process of Provisioner settings should be as following: + * a) open settings A + * b) restore settings A + * c) start to provision and control nodes + * d) release settings A + * e) close settings A + * f) open settings B + * g) restore settings B + * h) start to provision and control other nodes + * i) release settings B + * j) close settings B + * k) ...... + * + * @param[in] user_id: User id of Provisioner settings. + * @param[in] erase: Indicate whether erase the information from flash. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_provisioner_release_settings_with_user_id(const char *user_id, bool erase); + +/** + * @brief This function is called by Provisioner to erase the mesh provisioning + * information which is not been restored, and the corrseponding settings + * user_id from the flash section. + * + * @note When this function is called, the corresponding nvs namespace must not + * be open and restored. This function is used to erase the mesh information + * and settings user_id which are not been used currently. + * + * @param[in] index: Provisioner settings index. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_provisioner_delete_settings_with_index(uint8_t index); + +/** + * @brief This function is called by Provisioner to erase the mesh provisioning + * information which is not been restored, and the corrseponding settings + * user_id from the flash section. + * + * @note When this function is called, the corresponding nvs namespace must not + * be open and restored. This function is used to erase the mesh information + * and settings user_id which are not been used currently. + * + * @param[in] index: Provisioner settings index. + * + * @return ESP_OK on success or error code otherwise. + * + */ +esp_err_t esp_ble_mesh_provisioner_delete_settings_with_user_id(const char *user_id); + +/** + * @brief This function is called by Provisioner to get the settings user id. + * + * @param[in] index: Provisioner settings index. + * + * @return User id on success or NULL on failure. + * + */ +const char *esp_ble_mesh_provisioner_get_settings_user_id(uint8_t index); + +/** + * @brief This function is called by Provisioner to get the settings index. + * + * @param[in] user_id: User id of Provisioner settings. + * + * @return Provisioner Settings index. + * + */ +uint8_t esp_ble_mesh_provisioner_get_settings_index(const char *user_id); + +/** + * @brief This function is called by Provisioner to get the number of free + * settings user_id. + * + * @return Number of free Provisioner Settings. + * + */ +uint8_t esp_ble_mesh_provisioner_get_free_settings_user_id_count(void); + /** * @brief This function is called to get fast provisioning application key. * diff --git a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h index bdc1c7fdb7..2ac81a6c82 100644 --- a/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h +++ b/components/bt/esp_ble_mesh/api/esp_ble_mesh_defs.h @@ -40,6 +40,12 @@ /*!< The maximum length of a BLE Mesh unprovisioned device name */ #define ESP_BLE_MESH_DEVICE_NAME_MAX_LEN DEVICE_NAME_SIZE +/*!< The maximum length of the settings user_id of Provisioner */ +#define ESP_BLE_MESH_SETTINGS_USER_ID_SIZE 20 + +/*!< Invalid settings index of Provisioner */ +#define ESP_BLE_MESH_INVALID_SETTINGS_INDEX 0xFF + /*!< Define the BLE Mesh octet 16 bytes size */ #define ESP_BLE_MESH_OCTET16_LEN 16 typedef uint8_t esp_ble_mesh_octet16_t[ESP_BLE_MESH_OCTET16_LEN]; @@ -773,6 +779,16 @@ typedef enum { ESP_BLE_MESH_PROVISIONER_STORE_NODE_COMP_DATA_COMP_EVT, /*!< Provisioner store node composition data completion event */ ESP_BLE_MESH_PROVISIONER_DELETE_NODE_WITH_UUID_COMP_EVT, /*!< Provisioner delete node with uuid completion event */ ESP_BLE_MESH_PROVISIONER_DELETE_NODE_WITH_ADDR_COMP_EVT, /*!< Provisioner delete node with unicast address completion event */ + ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_INDEX_COMP_EVT, /*!< Provisioner open settings with index completion event */ + ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_USER_ID_COMP_EVT, /*!< Provisioner open settings with user_id completion event */ + ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX_COMP_EVT, /*!< Provisioner close settings with index completion event */ + ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_USER_ID_COMP_EVT, /*!< Provisioner close settings with user_id completion event */ + ESP_BLE_MESH_PROVISIONER_RESTORE_SETTINGS_WITH_INDEX_COMP_EVT, /*!< Provisioner restore settings with index completion event */ + ESP_BLE_MESH_PROVISIONER_RESTORE_SETTINGS_WITH_USER_ID_COMP_EVT, /*!< Provisioner restore settings with user_id completion event */ + ESP_BLE_MESH_PROVISIONER_RELEASE_SETTINGS_WITH_INDEX_COMP_EVT, /*!< Provisioner release settings with index completion event */ + ESP_BLE_MESH_PROVISIONER_RELEASE_SETTINGS_WITH_USER_ID_COMP_EVT, /*!< Provisioner release settings with user_id completion event */ + ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_INDEX_COMP_EVT, /*!< Provisioner delete settings with index completion event */ + ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_USER_ID_COMP_EVT, /*!< Provisioner delete settings with user_id completion event */ ESP_BLE_MESH_SET_FAST_PROV_INFO_COMP_EVT, /*!< Set fast provisioning information (e.g. unicast address range, net_idx, etc.) completion event */ ESP_BLE_MESH_SET_FAST_PROV_ACTION_COMP_EVT, /*!< Set fast provisioning action completion event */ ESP_BLE_MESH_HEARTBEAT_MESSAGE_RECV_EVT, /*!< Receive Heartbeat message event */ @@ -1098,17 +1114,87 @@ typedef union { /** * @brief ESP_BLE_MESH_PROVISIONER_DELETE_NODE_WITH_UUID_COMP_EVT */ - struct ble_mesh_provisioner_delete_node_with_uuid_comp_data_comp_param { + struct ble_mesh_provisioner_delete_node_with_uuid_comp_param { int err_code; /*!< Indicate the result of deleting node with uuid by the Provisioner */ uint8_t uuid[16]; /*!< Node device uuid */ } provisioner_delete_node_with_uuid_comp; /*!< Event parameter of ESP_BLE_MESH_PROVISIONER_DELETE_NODE_WITH_UUID_COMP_EVT */ /** * @brief ESP_BLE_MESH_PROVISIONER_DELETE_NODE_WITH_ADDR_COMP_EVT */ - struct ble_mesh_provisioner_delete_node_with_addr_comp_data_comp_param { + struct ble_mesh_provisioner_delete_node_with_addr_comp_param { int err_code; /*!< Indicate the result of deleting node with unicast address by the Provisioner */ uint16_t unicast_addr; /*!< Node unicast address */ } provisioner_delete_node_with_addr_comp; /*!< Event parameter of ESP_BLE_MESH_PROVISIONER_DELETE_NODE_WITH_ADDR_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_INDEX_COMP_EVT + */ + struct ble_mesh_provisioner_open_settings_with_index_comp_param { + int err_code; /*!< Indicate the result of opening settings with index by the Provisioner */ + uint8_t index; /*!< Index of Provisioner settings */ + } provisioner_open_settings_with_index_comp; /*!< Event parameter of ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_INDEX_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_USER_ID_COMP_EVT + */ + struct ble_mesh_provisioner_open_settings_with_user_id_comp_param { + int err_code; /*!< Indicate the result of opening settings with user_id by the Provisioner */ + uint8_t index; /*!< Index of Provisioner settings */ + } provisioner_open_settings_with_user_id_comp; /* !< Event parameters of ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_USER_ID_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX_COMP_EVT + */ + struct ble_mesh_provisioner_close_settings_with_index_comp_param { + int err_code; /*!< Indicate the result of closing settings with index by the Provisioner */ + uint8_t index; /*!< Index of Provisioner settings */ + } provisioner_close_settings_with_index_comp; /*!< Event parameter of ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_USER_ID_COMP_EVT + */ + struct ble_mesh_provisioner_close_settings_with_user_id_comp_param { + int err_code; /*!< Indicate the result of closing settings with user_id by the Provisioner */ + uint8_t index; /*!< Index of Provisioner settings */ + } provisioner_close_settings_with_user_id_comp; /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_USER_ID_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROVISIONER_RESTORE_SETTINGS_WITH_INDEX_COMP_EVT + */ + struct ble_mesh_provisioner_restore_settings_with_index_comp_param { + int err_code; /*!< Indicate the result of restoring settings with index by the Provisioner */ + uint8_t index; /*!< Index of Provisioner settings */ + } provisioner_restore_settings_with_index_comp; /*!< Event parameter of ESP_BLE_MESH_PROVISIONER_RESTORE_SETTINGS_WITH_INDEX_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROVISIONER_RESTORE_SETTINGS_WITH_USER_ID_COMP_EVT + */ + struct ble_mesh_provisioner_restore_settings_with_user_id_comp_param { + int err_code; /*!< Indicate the result of restoring settings with user_id by the Provisioner */ + uint8_t index; /*!< Index of Provisioner settings */ + } provisioner_restore_settings_with_user_id_comp; /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_RESTORE_SETTINGS_WITH_USER_ID_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROVISIONER_RELEASE_SETTINGS_WITH_INDEX_COMP_EVT + */ + struct ble_mesh_provisioner_release_settings_with_index_comp_param { + int err_code; /*!< Indicate the result of releasing settings with index by the Provisioner */ + uint8_t index; /*!< Index of Provisioner settings */ + } provisioner_release_settings_with_index_comp; /*!< Event parameter of ESP_BLE_MESH_PROVISIONER_RELEASE_SETTINGS_WITH_INDEX_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROVISIONER_RELEASE_SETTINGS_WITH_USER_ID_COMP_EVT + */ + struct ble_mesh_provisioner_release_settings_with_user_id_comp_param { + int err_code; /*!< Indicate the result of releasing settings with user_id by the Provisioner */ + uint8_t index; /*!< Index of Provisioner settings */ + } provisioner_release_settings_with_user_id_comp; /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_RELEASE_SETTINGS_WITH_USER_ID_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_INDEX_COMP_EVT + */ + struct ble_mesh_provisioner_delete_settings_with_index_comp_param { + int err_code; /*!< Indicate the result of deleting settings with index by the Provisioner */ + uint8_t index; /*!< Index of Provisioner settings */ + } provisioner_delete_settings_with_index_comp; /*!< Event parameter of ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_INDEX_COMP_EVT */ + /** + * @brief ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_USER_ID_COMP_EVT + */ + struct ble_mesh_provisioner_delete_settings_with_user_id_comp_param { + int err_code; /*!< Indicate the result of deleting settings with user_id by the Provisioner */ + uint8_t index; /*!< Index of Provisioner settings */ + } provisioner_delete_settings_with_user_id_comp; /*!< Event parameters of ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_USER_ID_COMP_EVT */ /** * @brief ESP_BLE_MESH_SET_FAST_PROV_INFO_COMP_EVT */ diff --git a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c index 28e64b767e..eb7e543368 100644 --- a/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c +++ b/components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c @@ -37,6 +37,7 @@ #include "time_scene_client.h" #include "client_common.h" #include "state_binding.h" +#include "settings.h" #include "btc_ble_mesh_prov.h" #include "btc_ble_mesh_config_model.h" @@ -782,6 +783,27 @@ esp_ble_mesh_node_t *btc_ble_mesh_provisioner_get_node_with_addr(uint16_t unicas return (esp_ble_mesh_node_t *)bt_mesh_provisioner_get_node_with_addr(unicast_addr); } +u16_t btc_ble_mesh_provisioner_get_prov_node_count(void) +{ + return bt_mesh_provisioner_get_prov_node_count(); +} + +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE +const char *btc_ble_mesh_provisioner_get_settings_user_id(uint8_t index) +{ + return bt_mesh_provisioner_get_settings_user_id(index); +} + +uint8_t btc_ble_mesh_provisioner_get_settings_index(const char *user_id) +{ + return bt_mesh_provisioner_get_settings_index(user_id); +} + +uint8_t btc_ble_mesh_provisioner_get_free_settings_user_id_count(void) +{ + return bt_mesh_provisioner_get_free_settings_user_id_count(); +} +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ #endif /* CONFIG_BLE_MESH_PROVISIONER */ static void btc_ble_mesh_heartbeat_msg_recv_cb(u8_t hops, u16_t feature) @@ -996,11 +1018,6 @@ const esp_ble_mesh_comp_t *btc_ble_mesh_comp_get(void) return (const esp_ble_mesh_comp_t *)bt_mesh_comp_get(); } -u16_t btc_ble_mesh_provisioner_get_prov_node_count(void) -{ - return bt_mesh_provisioner_get_prov_node_count(); -} - /* Configuration Models */ extern const struct bt_mesh_model_op bt_mesh_cfg_srv_op[]; extern const struct bt_mesh_model_op bt_mesh_cfg_cli_op[]; @@ -1789,6 +1806,71 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg) param.provisioner_delete_node_with_addr_comp.err_code = bt_mesh_provisioner_delete_node_with_addr(arg->delete_node_with_addr.unicast_addr); break; +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE + case BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_INDEX: + act = ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_INDEX_COMP_EVT; + param.provisioner_open_settings_with_index_comp.index = arg->open_settings_with_index.index; + param.provisioner_open_settings_with_index_comp.err_code = + bt_mesh_provisioner_open_settings_with_index(arg->open_settings_with_index.index); + break; + case BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_USER_ID: + act = ESP_BLE_MESH_PROVISIONER_OPEN_SETTINGS_WITH_USER_ID_COMP_EVT; + param.provisioner_open_settings_with_user_id_comp.err_code = + bt_mesh_provisioner_open_settings_with_user_id(arg->open_settings_with_user_id.user_id, + ¶m.provisioner_open_settings_with_user_id_comp.index); + break; + case BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX: + act = ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX_COMP_EVT; + param.provisioner_close_settings_with_index_comp.index = arg->close_settings_with_index.index; + param.provisioner_close_settings_with_index_comp.err_code = + bt_mesh_provisioner_close_settings_with_index(arg->close_settings_with_index.index); + break; + case BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_USER_ID: + act = ESP_BLE_MESH_PROVISIONER_CLOSE_SETTINGS_WITH_USER_ID_COMP_EVT; + param.provisioner_close_settings_with_user_id_comp.err_code = + bt_mesh_provisioner_close_settings_with_user_id(arg->close_settings_with_user_id.user_id, + ¶m.provisioner_close_settings_with_user_id_comp.index); + break; + case BTC_BLE_MESH_ACT_PROVISIONER_RESTORE_SETTINGS_WITH_INDEX: + act = ESP_BLE_MESH_PROVISIONER_RESTORE_SETTINGS_WITH_INDEX_COMP_EVT; + param.provisioner_restore_settings_with_index_comp.index = arg->restore_settings_with_index.index; + param.provisioner_restore_settings_with_index_comp.err_code = + bt_mesh_provisioner_restore_settings_with_index(arg->restore_settings_with_index.index); + break; + case BTC_BLE_MESH_ACT_PROVISIONER_RESTORE_SETTINGS_WITH_USER_ID: + act = ESP_BLE_MESH_PROVISIONER_RESTORE_SETTINGS_WITH_USER_ID_COMP_EVT; + param.provisioner_restore_settings_with_user_id_comp.err_code = + bt_mesh_provisioner_restore_settings_with_user_id(arg->restore_settings_with_user_id.user_id, + ¶m.provisioner_restore_settings_with_user_id_comp.index); + break; + case BTC_BLE_MESH_ACT_PROVISIONER_RELEASE_SETTINGS_WITH_INDEX: + act = ESP_BLE_MESH_PROVISIONER_RELEASE_SETTINGS_WITH_INDEX_COMP_EVT; + param.provisioner_release_settings_with_index_comp.index = arg->release_settings_with_index.index; + param.provisioner_release_settings_with_index_comp.err_code = + bt_mesh_provisioner_release_settings_with_index( + arg->release_settings_with_index.index, arg->release_settings_with_index.erase); + break; + case BTC_BLE_MESH_ACT_PROVISIONER_RELEASE_SETTINGS_WITH_USER_ID: + act = ESP_BLE_MESH_PROVISIONER_RELEASE_SETTINGS_WITH_USER_ID_COMP_EVT; + param.provisioner_release_settings_with_user_id_comp.err_code = + bt_mesh_provisioner_release_settings_with_user_id( + arg->release_settings_with_user_id.user_id, arg->release_settings_with_user_id.erase, + ¶m.provisioner_release_settings_with_user_id_comp.index); + break; + case BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_INDEX: + act = ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_INDEX_COMP_EVT; + param.provisioner_delete_settings_with_index_comp.index = arg->delete_settings_with_index.index; + param.provisioner_delete_settings_with_index_comp.err_code = + bt_mesh_provisioner_delete_settings_with_index(arg->delete_settings_with_index.index); + break; + case BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_USER_ID: + act = ESP_BLE_MESH_PROVISIONER_DELETE_SETTINGS_WITH_USER_ID_COMP_EVT; + param.provisioner_delete_settings_with_user_id_comp.err_code = + bt_mesh_provisioner_delete_settings_with_user_id( + arg->delete_settings_with_user_id.user_id, + ¶m.provisioner_delete_settings_with_user_id_comp.index); + break; +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ #endif /* CONFIG_BLE_MESH_PROVISIONER */ #if CONFIG_BLE_MESH_FAST_PROV case BTC_BLE_MESH_ACT_SET_FAST_PROV_INFO: diff --git a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h index c55de21356..bef060305e 100644 --- a/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h +++ b/components/bt/esp_ble_mesh/btc/include/btc_ble_mesh_prov.h @@ -53,6 +53,16 @@ typedef enum { BTC_BLE_MESH_ACT_PROVISIONER_STORE_NODE_COMP_DATA, BTC_BLE_MESH_ACT_PROVISIONER_DELETE_NODE_WITH_UUID, BTC_BLE_MESH_ACT_PROVISIONER_DELETE_NODE_WITH_ADDR, + BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_INDEX, + BTC_BLE_MESH_ACT_PROVISIONER_OPEN_SETTINGS_WITH_USER_ID, + BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_INDEX, + BTC_BLE_MESH_ACT_PROVISIONER_CLOSE_SETTINGS_WITH_USER_ID, + BTC_BLE_MESH_ACT_PROVISIONER_RESTORE_SETTINGS_WITH_INDEX, + BTC_BLE_MESH_ACT_PROVISIONER_RESTORE_SETTINGS_WITH_USER_ID, + BTC_BLE_MESH_ACT_PROVISIONER_RELEASE_SETTINGS_WITH_INDEX, + BTC_BLE_MESH_ACT_PROVISIONER_RELEASE_SETTINGS_WITH_USER_ID, + BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_INDEX, + BTC_BLE_MESH_ACT_PROVISIONER_DELETE_SETTINGS_WITH_USER_ID, BTC_BLE_MESH_ACT_SET_FAST_PROV_INFO, BTC_BLE_MESH_ACT_SET_FAST_PROV_ACTION, BTC_BLE_MESH_ACT_LPN_ENABLE, @@ -187,6 +197,38 @@ typedef union { struct ble_mesh_provisioner_delete_node_with_addr_args { uint16_t unicast_addr; } delete_node_with_addr; + struct ble_mesh_provisioner_open_settings_with_index_args { + uint8_t index; + } open_settings_with_index; + struct ble_mesh_provisioner_open_settings_with_user_id_args { + char user_id[ESP_BLE_MESH_SETTINGS_USER_ID_SIZE + 1]; + } open_settings_with_user_id; + struct ble_mesh_provisioner_close_settings_with_index_args { + uint8_t index; + } close_settings_with_index; + struct ble_mesh_provisioner_close_settings_with_user_id_args { + char user_id[ESP_BLE_MESH_SETTINGS_USER_ID_SIZE + 1]; + } close_settings_with_user_id; + struct ble_mesh_provisioner_restore_settings_with_index_args { + uint8_t index; + } restore_settings_with_index; + struct ble_mesh_provisioner_restore_settings_with_user_id_args { + char user_id[ESP_BLE_MESH_SETTINGS_USER_ID_SIZE + 1]; + } restore_settings_with_user_id; + struct ble_mesh_provisioner_release_settings_with_index_args { + uint8_t index; + bool erase; + } release_settings_with_index; + struct ble_mesh_provisioner_release_settings_with_user_id_args { + char user_id[ESP_BLE_MESH_SETTINGS_USER_ID_SIZE + 1]; + bool erase; + } release_settings_with_user_id; + struct ble_mesh_provisioner_delete_settings_with_index_args { + uint8_t index; + } delete_settings_with_index; + struct ble_mesh_provisioner_delete_settings_with_user_id_args { + char user_id[ESP_BLE_MESH_SETTINGS_USER_ID_SIZE + 1]; + } delete_settings_with_user_id; struct ble_mesh_set_fast_prov_info_args { uint16_t unicast_min; uint16_t unicast_max; @@ -292,6 +334,10 @@ const esp_ble_mesh_comp_t *btc_ble_mesh_comp_get(void); u16_t btc_ble_mesh_provisioner_get_prov_node_count(void); +const char *btc_ble_mesh_provisioner_get_settings_user_id(uint8_t index); +uint8_t btc_ble_mesh_provisioner_get_settings_index(const char *user_id); +uint8_t btc_ble_mesh_provisioner_get_free_settings_user_id_count(void); + void btc_ble_mesh_model_call_handler(btc_msg_t *msg); void btc_ble_mesh_model_cb_handler(btc_msg_t *msg); diff --git a/components/bt/esp_ble_mesh/mesh_core/access.c b/components/bt/esp_ble_mesh/mesh_core/access.c index d37f0c4df7..042a6b8cd6 100644 --- a/components/bt/esp_ble_mesh/mesh_core/access.c +++ b/components/bt/esp_ble_mesh/mesh_core/access.c @@ -244,6 +244,11 @@ void bt_mesh_model_foreach(void (*func)(struct bt_mesh_model *mod, { int i, j; + if (dev_comp == NULL) { + BT_ERR("%s, NULL dev_comp", __func__); + return; + } + for (i = 0; i < dev_comp->elem_count; i++) { struct bt_mesh_elem *elem = &dev_comp->elem[i]; diff --git a/components/bt/esp_ble_mesh/mesh_core/adv.c b/components/bt/esp_ble_mesh/mesh_core/adv.c index 4448feab4b..b28ea4e80a 100644 --- a/components/bt/esp_ble_mesh/mesh_core/adv.c +++ b/components/bt/esp_ble_mesh/mesh_core/adv.c @@ -62,10 +62,10 @@ static const u8_t adv_type[] = { [BLE_MESH_ADV_URI] = BLE_MESH_DATA_URI, }; -NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BLE_MESH_ADV_BUF_COUNT + 3 * CONFIG_BLE_MESH_PBA_SAME_TIME, +NET_BUF_POOL_DEFINE(adv_buf_pool, CONFIG_BLE_MESH_ADV_BUF_COUNT, BLE_MESH_ADV_DATA_SIZE, BLE_MESH_ADV_USER_DATA_SIZE, NULL); -static struct bt_mesh_adv adv_pool[CONFIG_BLE_MESH_ADV_BUF_COUNT + 3 * CONFIG_BLE_MESH_PBA_SAME_TIME]; +static struct bt_mesh_adv adv_pool[CONFIG_BLE_MESH_ADV_BUF_COUNT]; struct bt_mesh_queue { QueueHandle_t queue; @@ -76,7 +76,8 @@ struct bt_mesh_queue { }; static struct bt_mesh_queue xBleMeshQueue; -#define BLE_MESH_QUEUE_SIZE 150 +/* We reserve one queue for bt_mesh_adv_update() */ +#define BLE_MESH_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + 1) #if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) NET_BUF_POOL_DEFINE(relay_adv_buf_pool, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT, @@ -85,7 +86,7 @@ NET_BUF_POOL_DEFINE(relay_adv_buf_pool, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT, static struct bt_mesh_adv relay_adv_pool[CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT]; static struct bt_mesh_queue xBleMeshRelayQueue; -#define BLE_MESH_RELAY_QUEUE_SIZE 150 +#define BLE_MESH_RELAY_QUEUE_SIZE CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT static QueueSetHandle_t xBleMeshQueueSet; #define BLE_MESH_QUEUE_SET_SIZE (BLE_MESH_QUEUE_SIZE + BLE_MESH_RELAY_QUEUE_SIZE) diff --git a/components/bt/esp_ble_mesh/mesh_core/beacon.c b/components/bt/esp_ble_mesh/mesh_core/beacon.c index 1e720eb08c..4b0f7363a9 100644 --- a/components/bt/esp_ble_mesh/mesh_core/beacon.c +++ b/components/bt/esp_ble_mesh/mesh_core/beacon.c @@ -42,6 +42,8 @@ static struct k_delayed_work beacon_timer; +static bool ready_to_send(void); + static struct bt_mesh_subnet *cache_check(u8_t data[21]) { size_t subnet_size = 0U; @@ -75,6 +77,16 @@ static void beacon_complete(int err, void *user_data) BT_DBG("err %d", err); + /* Care should be taken here, since the user_data is the + * pointer of a subnet. When the device is a Provisioner, + * its subnet is allocated dynamically. And if the + * corresponding subnet has been removed, this will cause + * exception here. + */ + if (ready_to_send() == false) { + return; + } + sub->beacon_sent = k_uptime_get_32(); } diff --git a/components/bt/esp_ble_mesh/mesh_core/lpn.c b/components/bt/esp_ble_mesh/mesh_core/lpn.c index 69d428ad40..50bfd9d965 100644 --- a/components/bt/esp_ble_mesh/mesh_core/lpn.c +++ b/components/bt/esp_ble_mesh/mesh_core/lpn.c @@ -218,7 +218,7 @@ static void clear_friendship(bool force, bool disable) return; } - bt_mesh_rx_reset(); + bt_mesh_rx_reset(true); k_delayed_work_cancel(&lpn->timer); diff --git a/components/bt/esp_ble_mesh/mesh_core/main.c b/components/bt/esp_ble_mesh/mesh_core/main.c index dcec933db3..1ab12e6606 100644 --- a/components/bt/esp_ble_mesh/mesh_core/main.c +++ b/components/bt/esp_ble_mesh/mesh_core/main.c @@ -107,7 +107,7 @@ void bt_mesh_reset(void) bt_mesh_cfg_reset(); - bt_mesh_rx_reset(); + bt_mesh_rx_reset(true); bt_mesh_tx_reset(); if (IS_ENABLED(CONFIG_BLE_MESH_LOW_POWER)) { @@ -459,18 +459,15 @@ int bt_mesh_deinit(struct bt_mesh_deinit_param *param) bt_mesh_adv_deinit(); + if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { + bt_mesh_settings_deinit(param->erase); + } + err = bt_mesh_comp_deregister(); if (err) { return err; } - if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { - if (param->erase) { - bt_mesh_clear_role(); - } - bt_mesh_settings_deinit(); - } - bt_mesh_k_deinit(); return 0; diff --git a/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c b/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c index dcf3421f45..02ce5fb19a 100644 --- a/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c +++ b/components/bt/esp_ble_mesh/mesh_core/provisioner_main.c @@ -163,11 +163,11 @@ done: return 0; } -int bt_mesh_provisioner_deinit(bool erase) +void bt_mesh_provisioner_release_netkey(bool erase) { int i; - for (i = 0; i < CONFIG_BLE_MESH_PROVISIONER_SUBNET_COUNT; i++) { + for (i = 0; i < ARRAY_SIZE(bt_mesh.p_sub); i++) { if (bt_mesh.p_sub[i]) { if (erase && IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { bt_mesh_clear_p_subnet(bt_mesh.p_sub[i]); @@ -177,7 +177,18 @@ int bt_mesh_provisioner_deinit(bool erase) } } - for (i = 0; i < CONFIG_BLE_MESH_PROVISIONER_APP_KEY_COUNT; i++) { + if (erase && IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { + bt_mesh_clear_p_net_idx(); + } + bt_mesh.p_net_idx_next = 0U; + return; +} + +void bt_mesh_provisioner_release_appkey(bool erase) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(bt_mesh.p_app_keys); i++) { if (bt_mesh.p_app_keys[i]) { if (erase && IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { bt_mesh_clear_p_app_key(bt_mesh.p_app_keys[i]); @@ -187,22 +198,32 @@ int bt_mesh_provisioner_deinit(bool erase) } } - bt_mesh.p_net_idx_next = 0U; - bt_mesh.p_app_idx_next = 0U; if (erase && IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { - bt_mesh_clear_p_net_idx(); bt_mesh_clear_p_app_idx(); } + bt_mesh.p_app_idx_next = 0U; + return; +} - for (i = 0; i < CONFIG_BLE_MESH_MAX_STORED_NODES; i++) { +void bt_mesh_provisioner_release_node(bool erase) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mesh_nodes); i++) { provisioner_remove_node(i, erase); } all_node_count = 0U; prov_node_count = 0U; + return; +} +int bt_mesh_provisioner_deinit(bool erase) +{ + bt_mesh_provisioner_release_netkey(erase); + bt_mesh_provisioner_release_appkey(erase); + bt_mesh_provisioner_release_node(erase); bt_mesh_provisioner_mutex_free(); - return 0; } diff --git a/components/bt/esp_ble_mesh/mesh_core/provisioner_main.h b/components/bt/esp_ble_mesh/mesh_core/provisioner_main.h index fabe9399eb..302d022dc3 100644 --- a/components/bt/esp_ble_mesh/mesh_core/provisioner_main.h +++ b/components/bt/esp_ble_mesh/mesh_core/provisioner_main.h @@ -47,6 +47,9 @@ int bt_mesh_provisioner_init(void); int bt_mesh_provisioner_net_create(void); +void bt_mesh_provisioner_release_netkey(bool erase); +void bt_mesh_provisioner_release_appkey(bool erase); +void bt_mesh_provisioner_release_node(bool erase); int bt_mesh_provisioner_deinit(bool erase); bool bt_mesh_provisioner_check_is_addr_dup(u16_t addr, u8_t elem_num, bool comp_with_own); diff --git a/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c b/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c index 8df45ed4cd..5f239ecff1 100644 --- a/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c +++ b/components/bt/esp_ble_mesh/mesh_core/provisioner_prov.c @@ -1126,6 +1126,11 @@ int bt_mesh_provisioner_set_prov_info(void) /* If unicast address of primary element of Provisioner has not been set * before, then the following initilization procedure will be used. */ + if (prov == NULL) { + BT_ERR("%s, NULL provisioning", __func__); + return -EINVAL; + } + if (!BLE_MESH_ADDR_IS_UNICAST(prov->prov_unicast_addr) || !BLE_MESH_ADDR_IS_UNICAST(prov->prov_start_address)) { BT_ERR("%s, Invalid address, own 0x%04x, start 0x%04x", diff --git a/components/bt/esp_ble_mesh/mesh_core/settings.c b/components/bt/esp_ble_mesh/mesh_core/settings.c index 2792d893d0..b58ae32efa 100644 --- a/components/bt/esp_ble_mesh/mesh_core/settings.c +++ b/components/bt/esp_ble_mesh/mesh_core/settings.c @@ -167,8 +167,48 @@ struct node_info { u8_t dev_key[16]; } __packed; +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE +#define SETTINGS_USER_ID_SIZE 20 +#define SETTINGS_NVS_NAME_SIZE 15 +#define INVALID_SETTINGS_INDEX 0xFF +#define INVALID_SETTINGS_HANDLE UINT32_MAX + +static struct settings_namespace { + u8_t open:1, /* Settings is open */ + restore:1, /* Settings is restored */ + erase:1; /* Settings is erased */ + char user_id[SETTINGS_USER_ID_SIZE + 1]; + char nvs_name[SETTINGS_NVS_NAME_SIZE + 1]; + nvs_handle handle; +} settings_name[CONFIG_BLE_MESH_MAX_NVS_NAMESPACE]; +#endif + #define DEVICE_ROLE_BITS (BIT(BLE_MESH_NODE) | BIT(BLE_MESH_PROVISIONER)) +static bt_mesh_mutex_t settings_lock; + +static void bt_mesh_settings_mutex_new(void) +{ + if (!settings_lock.mutex) { + bt_mesh_mutex_create(&settings_lock); + } +} + +static void bt_mesh_settings_mutex_free(void) +{ + bt_mesh_mutex_free(&settings_lock); +} + +void bt_mesh_settings_lock(void) +{ + bt_mesh_mutex_lock(&settings_lock); +} + +void bt_mesh_settings_unlock(void) +{ + bt_mesh_mutex_unlock(&settings_lock); +} + static int role_set(const char *name) { bool exist = false; @@ -1187,44 +1227,46 @@ const struct bt_mesh_setting { const char *name; int (*func)(const char *name); } settings[] = { - { "mesh/role", role_set }, - { "mesh/net", net_set }, - { "mesh/iv", iv_set }, - { "mesh/seq", seq_set }, - { "mesh/rpl", rpl_set }, - { "mesh/netkey", net_key_set }, - { "mesh/appkey", app_key_set }, - { "mesh/hb_pub", hb_pub_set }, - { "mesh/cfg", cfg_set }, - { "mesh/sig", sig_mod_set }, - { "mesh/vnd", vnd_mod_set }, + { "mesh/role", role_set }, /* For node & Provisioner */ + { "mesh/net", net_set }, /* For node */ + { "mesh/iv", iv_set }, /* For node & Provisioner */ + { "mesh/seq", seq_set }, /* For node & Provisioner */ + { "mesh/rpl", rpl_set }, /* For node & Provisioner */ + { "mesh/netkey", net_key_set }, /* For node */ + { "mesh/appkey", app_key_set }, /* For node */ + { "mesh/hb_pub", hb_pub_set }, /* For node */ + { "mesh/cfg", cfg_set }, /* For node */ + { "mesh/sig", sig_mod_set }, /* For node & Provisioner */ + { "mesh/vnd", vnd_mod_set }, /* For node & Provisioner */ #if CONFIG_BLE_MESH_LABEL_COUNT > 0 - { "mesh/vaddr", va_set }, + { "mesh/vaddr", va_set }, /* For node */ #endif #if CONFIG_BLE_MESH_PROVISIONER - { "mesh/p_prov", p_prov_set }, - { "mesh/p_netidx", p_net_idx_set }, - { "mesh/p_appidx", p_app_idx_set }, - { "mesh/p_netkey", p_net_key_set }, - { "mesh/p_appkey", p_app_key_set }, - { "mesh/p_pnode", p_node_set }, - { "mesh/p_snode", p_node_set }, + { "mesh/p_prov", p_prov_set }, /* For Provisioner */ + { "mesh/p_netidx", p_net_idx_set }, /* For Provisioner */ + { "mesh/p_appidx", p_app_idx_set }, /* For Provisioner */ + { "mesh/p_netkey", p_net_key_set }, /* For Provisioner */ + { "mesh/p_appkey", p_app_key_set }, /* For Provisioner */ + { "mesh/p_pnode", p_node_set }, /* For Provisioner */ + { "mesh/p_snode", p_node_set }, /* For Provisioner */ #endif }; /** * For Provisioner, the load operation needs the following actions: + * role_set: Need, restore the device role * net_set: Not needed * iv_set: Need, although Provisioner will do some initialization of IV Index * during startup, but we need to restore the last IV Index status * seq_set: Need, restore the previous sequence number * rpl_set: Need, restore the previous Replay Protection List - * net_key_set: Need, restore the previous network keys - * app_key_set: Need, restore the previous application keys + * net_key_set: Not needed + * app_key_set: Not needed * hb_pub_set: Not needed currently * cfg_set: Not needed currently * sig_mod_set: Need, restore SIG models related info (app, sub, pub) * vnd_mod_set: Need, restore vendor models related info (app, sub, pub) + * va_set: Not needed currently */ int settings_core_load(void) { @@ -1237,7 +1279,8 @@ int settings_core_load(void) !strcmp(settings[i].name, "mesh/netkey") || !strcmp(settings[i].name, "mesh/appkey") || !strcmp(settings[i].name, "mesh/hb_pub") || - !strcmp(settings[i].name, "mesh/cfg")) && + !strcmp(settings[i].name, "mesh/cfg") || + !strcmp(settings[i].name, "mesh/vaddr")) && (!IS_ENABLED(CONFIG_BLE_MESH_NODE) || bt_mesh_is_provisioner())) { BT_DBG("Not restoring %s for Provisioner", settings[i].name); continue; @@ -1358,7 +1401,7 @@ int settings_core_commit(void) return 0; } - BT_INFO("p_sub[0]->net_idx 0x%03x", bt_mesh.p_sub[0]->net_idx); + BT_INFO("Settings commit, p_sub[0]->net_idx 0x%03x", bt_mesh.p_sub[0]->net_idx); bt_mesh_comp_provision(bt_mesh_provisioner_get_primary_elem_addr()); @@ -1378,11 +1421,13 @@ int settings_core_commit(void) } #endif /* CONFIG_BLE_MESH_PROVISIONER */ - if (bt_mesh.ivu_duration < BLE_MESH_IVU_MIN_HOURS) { - k_delayed_work_submit(&bt_mesh.ivu_timer, BLE_MESH_IVU_TIMEOUT); - } + if (bt_mesh_is_node() || bt_mesh_is_provisioner()) { + if (bt_mesh.ivu_duration < BLE_MESH_IVU_MIN_HOURS) { + k_delayed_work_submit(&bt_mesh.ivu_timer, BLE_MESH_IVU_TIMEOUT); + } - bt_mesh_model_foreach(commit_model, NULL); + bt_mesh_model_foreach(commit_model, NULL); + } #if defined(CONFIG_BLE_MESH_NODE) if (bt_mesh_is_node()) { @@ -1412,12 +1457,6 @@ int settings_core_commit(void) } #endif /* CONFIG_BLE_MESH_NODE */ -#if defined(CONFIG_BLE_MESH_PROVISIONER) - if (bt_mesh_is_provisioner()) { - bt_mesh_provisioner_net_start(BLE_MESH_PROV_ADV | BLE_MESH_PROV_GATT); - } -#endif /* CONFIG_BLE_MESH_PROVISIONER */ - return 0; } @@ -1593,7 +1632,7 @@ static void clear_rpl(void) buf = bt_mesh_get_core_settings_item("mesh/rpl"); if (!buf) { - BT_WARN("%s, Erase RPL", __func__); + BT_INFO("%s, Erase mesh/rpl", __func__); bt_mesh_save_core_settings("mesh/rpl", NULL, 0); return; } @@ -2217,7 +2256,12 @@ void bt_mesh_clear_app_key(struct bt_mesh_app_key *key) void bt_mesh_clear_rpl(void) { - schedule_store(BLE_MESH_RPL_PENDING); + if (bt_mesh_is_node()) { + schedule_store(BLE_MESH_RPL_PENDING); + } else { + /* For Provisioner, clear rpl directly */ + clear_rpl(); + } } void bt_mesh_store_mod_bind(struct bt_mesh_model *model) @@ -2238,6 +2282,130 @@ void bt_mesh_store_mod_pub(struct bt_mesh_model *model) schedule_store(BLE_MESH_MOD_PENDING); } +static void clear_mod_bind(struct bt_mesh_model *model, + struct bt_mesh_elem *elem, bool vnd, + bool primary, void *user_data) +{ + char name[16] = {'\0'}; + u16_t model_key = 0U; + int err = 0; + + model_key = BLE_MESH_GET_MODEL_KEY(model->elem_idx, model->model_idx); + + sprintf(name, "mesh/%s/%04x/b", vnd ? "v" : "s", model_key); + bt_mesh_save_core_settings(name, NULL, 0); + + err = bt_mesh_remove_core_settings_item(vnd ? "mesh/vnd" : "mesh/sig", model_key); + if (err) { + BT_ERR("%s, Failed to remove 0x%04x to %s", __func__, model_key, + vnd ? "mesh/vnd" : "mesh/sig"); + } +} + +static void clear_mod_sub(struct bt_mesh_model *model, + struct bt_mesh_elem *elem, bool vnd, + bool primary, void *user_data) +{ + char name[16] = {'\0'}; + u16_t model_key = 0U; + int err = 0; + + model_key = BLE_MESH_GET_MODEL_KEY(model->elem_idx, model->model_idx); + + sprintf(name, "mesh/%s/%04x/s", vnd ? "v" : "s", model_key); + bt_mesh_save_core_settings(name, NULL, 0); + + err = bt_mesh_remove_core_settings_item(vnd ? "mesh/vnd" : "mesh/sig", model_key); + if (err) { + BT_ERR("%s, Failed to remove 0x%04x to %s", __func__, model_key, + vnd ? "mesh/vnd" : "mesh/sig"); + } +} + +static void clear_mod_pub(struct bt_mesh_model *model, + struct bt_mesh_elem *elem, bool vnd, + bool primary, void *user_data) +{ + char name[16] = {'\0'}; + u16_t model_key = 0U; + int err = 0; + + model_key = BLE_MESH_GET_MODEL_KEY(model->elem_idx, model->model_idx); + + sprintf(name, "mesh/%s/%04x/p", vnd ? "v" : "s", model_key); + bt_mesh_save_core_settings(name, NULL, 0); + + err = bt_mesh_remove_core_settings_item(vnd ? "mesh/vnd" : "mesh/sig", model_key); + if (err) { + BT_ERR("%s, Failed to remove 0x%04x to %s", __func__, model_key, + vnd ? "mesh/vnd" : "mesh/sig"); + } +} + +void bt_mesh_clear_mod_bind(void) +{ + bt_mesh_model_foreach(clear_mod_bind, NULL); +} + +void bt_mesh_clear_mod_sub(void) +{ + bt_mesh_model_foreach(clear_mod_sub, NULL); +} + +void bt_mesh_clear_mod_pub(void) +{ + bt_mesh_model_foreach(clear_mod_pub, NULL); +} + +static void reset_mod_bind(struct bt_mesh_model *model, + struct bt_mesh_elem *elem, bool vnd, + bool primary, void *user_data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(model->keys); i++) { + if (model->keys[i] != BLE_MESH_KEY_DEV) { + model->keys[i] = BLE_MESH_KEY_UNUSED; + } + } +} + +static void reset_mod_sub(struct bt_mesh_model *model, + struct bt_mesh_elem *elem, bool vnd, + bool primary, void *user_data) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(model->groups); i++) { + model->groups[i] = BLE_MESH_ADDR_UNASSIGNED; + } +} + +static void reset_mod_pub(struct bt_mesh_model *model, + struct bt_mesh_elem *elem, bool vnd, + bool primary, void *user_data) +{ + if (model->pub) { + model->pub->addr = BLE_MESH_ADDR_UNASSIGNED; + k_delayed_work_cancel(&model->pub->timer); + } +} + +void bt_mesh_reset_mod_bind(void) +{ + bt_mesh_model_foreach(reset_mod_bind, NULL); +} + +void bt_mesh_reset_mod_sub(void) +{ + bt_mesh_model_foreach(reset_mod_sub, NULL); +} + +void bt_mesh_reset_mod_pub(void) +{ + bt_mesh_model_foreach(reset_mod_pub, NULL); +} + void bt_mesh_store_label(void) { schedule_store(BLE_MESH_VA_PENDING); @@ -2555,6 +2723,922 @@ void bt_mesh_store_node_comp_data(struct bt_mesh_node *node, bool prov) BT_ERR("%s, Failed to save node comp data %s", __func__, name); } } + +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE +/* + * key: "mesh/uid" -> write/read to set/get all the user_ids. + * key: "mesh/id/xxxx" -> write/read to set/get the "xxxx" user_id + */ +static int settings_user_id_delete(u8_t index); + +int settings_user_id_init(void) +{ + struct settings_namespace *item = NULL; + int i; + + for (i = 0; i < ARRAY_SIZE(settings_name); i++) { + item = &settings_name[i]; + memset(item, 0, sizeof(struct settings_namespace)); + } + + return 0; +} + +int settings_user_id_load(void) +{ + struct settings_namespace *item = NULL; + struct net_buf_simple *buf = NULL; + char get[16] = {'\0'}; + size_t length = 0U; + bool exist = false; + int err = 0; + int i; + + /* Before users can use user_id to search settings, we need to + * restore all the settings user_ids properly. + */ + + buf = bt_mesh_get_user_id_settings_item("mesh/uid"); + if (!buf) { + return 0; + } + + length = buf->len; + + for (i = 0; i < length / SETTINGS_ITEM_SIZE; i++) { + u16_t index = net_buf_simple_pull_le16(buf); + sprintf(get, "mesh/id/%04x", index); + + item = &settings_name[index]; + err = bt_mesh_load_user_id_settings(get, (u8_t *)item->user_id, SETTINGS_USER_ID_SIZE, &exist); + if (err) { + BT_ERR("%s, Failed to load user_id %s", __func__, get); + goto free; + } + + if (exist == false) { + continue; + } + + BT_INFO("Restored settings %d, user_id %s", index, item->user_id); + } + +free: + bt_mesh_free_buf(buf); + return err; +} + +static inline bool settings_user_id_empty(struct settings_namespace *item) +{ + return (item->user_id[0] == '\0') ? true : false; +} + +int settings_user_id_deinit(bool erase) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(settings_name); i++) { + struct settings_namespace *item = &settings_name[i]; + + if (item->open == true) { + /* When the nvs namespace is open, which means it is currently + * been used. And its information will be erased when the deinit + * function is invoked, no need to erase it again here. + */ + bt_mesh_settings_nvs_close(item->handle); + } else if (settings_user_id_empty(item) == false) { + /* When the settings user_id is not empty, when means the nvs + * namespace may contains some mesh information, need to erase + * it here. + */ + if (erase) { + settings_user_id_delete(i); + } + } + + memset(item, 0, sizeof(struct settings_namespace)); + } + + if (erase) { + bt_mesh_save_user_id_settings("mesh/uid", NULL, 0); + } + + return 0; +} + +u32_t bt_mesh_provisioner_get_settings_handle(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(settings_name); i++) { + if (settings_name[i].open) { + return settings_name[i].handle; + } + } + + BT_ERR("%s, Failed to get nvs handle", __func__); + return INVALID_SETTINGS_HANDLE; +} + +static u8_t settings_index_get(const char *user_id, u8_t *index) +{ + u8_t idx = 0U; + int i; + + if (!user_id || strlen(user_id) > SETTINGS_USER_ID_SIZE) { + BT_ERR("%s, Invalid settings user_id", __func__); + idx = INVALID_SETTINGS_INDEX; + goto done; + } + + for (i = 0; i < ARRAY_SIZE(settings_name); i++) { + if (strlen(settings_name[i].user_id) != strlen(user_id)) { + continue; + } + if (!strncmp(settings_name[i].user_id, user_id, strlen(user_id))) { + idx = i; + goto done; + } + } + + BT_ERR("%s, Settings user_id %s not exists", __func__, user_id); + idx = INVALID_SETTINGS_INDEX; + +done: + if (index) { + *index = idx; + } + return idx; +} + +static u8_t settings_user_id_set(const char *user_id, u8_t *index) +{ + struct settings_namespace *item = NULL; + u8_t idx = 0U; + int i; + + if (!user_id || strlen(user_id) > SETTINGS_USER_ID_SIZE) { + BT_ERR("%s, Invalid settings user_id", __func__); + idx = INVALID_SETTINGS_INDEX; + goto done; + } + + /* Find if the same settings user_id exists */ + for (i = 0; i < ARRAY_SIZE(settings_name); i++) { + item = &settings_name[i]; + if (strlen(settings_name[i].user_id) != strlen(user_id)) { + continue; + } + if (!strncmp(item->user_id, user_id, strlen(user_id))) { + idx = i; + goto done; + } + } + + for (i = 0; i < ARRAY_SIZE(settings_name); i++) { + item = &settings_name[i]; + if (settings_user_id_empty(item)) { + strncpy(item->user_id, user_id, strlen(user_id)); + idx = i; + goto done; + } + } + + BT_ERR("%s, No empty settings user_id", __func__); + idx = INVALID_SETTINGS_INDEX; + +done: + if (index) { + *index = idx; + } + return idx; +} + +static int provisioner_settings_open(u8_t index) +{ + struct settings_namespace *item = NULL; + char name[16] = {'\0'}; + int err = 0; + int i; + + if (index >= ARRAY_SIZE(settings_name)) { + BT_ERR("%s, Invalid settings index %d", __func__, index); + return -EINVAL; + } + + item = &settings_name[index]; + + /* Corresponding nvs namespace is already open */ + if (item->open == true) { + BT_ERR("%s, Settings %d is already open", __func__, index); + return -EALREADY; + } + + memset(item->nvs_name, 0, sizeof(item->nvs_name)); + sprintf(item->nvs_name, "%s_%02x", "mesh_core", index); + + err = bt_mesh_settings_nvs_open(item->nvs_name, &item->handle); + if (err) { + BT_ERR("%s, Open nvs failed, name %s, err %d", __func__, item->nvs_name, err); + return -EIO; + } + + if (settings_user_id_empty(item)) { + /* If the settings is not open with user_id, then we use + * the index as the user_id. Or when the device restarts, + * the user_id may be restored, in this case the user_id + * shall not be updated. + */ + sprintf(item->user_id, "%04x", index); + } + + sprintf(name, "mesh/id/%04x", index); + err = bt_mesh_save_user_id_settings(name, (const u8_t *)item->user_id, SETTINGS_USER_ID_SIZE); + if (err) { + BT_ERR("%s, Failed to save user_id %s", __func__, name); + return err; + } + + err = bt_mesh_add_user_id_settings_item("mesh/uid", index); + if (err) { + BT_ERR("%s, Failed to add 0x%04x to mesh/uid", __func__, index); + return err; + } + + for (i = 0; i < ARRAY_SIZE(settings_name); i++) { + if (settings_name[i].open == true) { + /* Only close corresponding nvs namespace here */ + bt_mesh_settings_nvs_close(settings_name[i].handle); + settings_name[i].open = false; + } + } + + BT_INFO("Open settings %d, user_id %s", index, item->user_id); + + item->open = true; + return 0; +} + +int bt_mesh_provisioner_open_settings_with_index(u8_t index) +{ + return provisioner_settings_open(index); +} + +int bt_mesh_provisioner_open_settings_with_user_id(const char *user_id, u8_t *index) +{ + u8_t idx = settings_user_id_set(user_id, index); + + if (idx >= ARRAY_SIZE(settings_name)) { + return -EIO; + } + + return provisioner_settings_open(idx); +} + +static int provisioner_settings_close(u8_t index) +{ + struct settings_namespace *item = NULL; + char name[16] = {'\0'}; + int err = 0; + + if (index >= ARRAY_SIZE(settings_name)) { + BT_ERR("%s, Invalid settings index %d", __func__, index); + return -EINVAL; + } + + item = &settings_name[index]; + + /* Corresponding nvs namespace is not open */ + if (item->open == false) { + BT_ERR("%s, Settings %d is not open", __func__, index); + return -EIO; + } + + if (item->erase == true) { + /* Only when the corresponding mesh information is erased, + * then invoking the settings close function will reset and + * erase the settings user_id. And if opening the settings + * again with the same user_id, the settings index will be + * reallocated. + * Otherwise only the nvs namespace will be closed, and when + * opened again, the previous settings index will be used. + */ + sprintf(name, "mesh/id/%04x", index); + bt_mesh_save_user_id_settings(name, NULL, 0); + + err = bt_mesh_remove_user_id_settings_item("mesh/uid", index); + if (err) { + BT_ERR("%s, Failed to remove user_id 0x%04x", __func__, index); + return err; + } + memset(item->user_id, 0, sizeof(item->user_id)); + } + + BT_INFO("Close settings %d, user_id %s", index, item->user_id); + + bt_mesh_settings_nvs_close(item->handle); + item->open = false; + return 0; +} + +int bt_mesh_provisioner_close_settings_with_index(u8_t index) +{ + return provisioner_settings_close(index); +} + +int bt_mesh_provisioner_close_settings_with_user_id(const char *user_id, u8_t *index) +{ + u8_t idx = settings_index_get(user_id, index); + + if (idx >= ARRAY_SIZE(settings_name)) { + return -EIO; + } + + return provisioner_settings_close(idx); +} + +static int provisioner_settings_restore(u8_t index) +{ + struct settings_namespace *item = NULL; + int err = 0; + int i; + + if (index >= ARRAY_SIZE(settings_name)) { + BT_ERR("%s, Invalid settings index %d", __func__, index); + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(settings_name); i++) { + item = &settings_name[i]; + if (item->restore == true) { + BT_ERR("%s, Settings %d is restored, release first", __func__, index); + return -EIO; + } + } + + item = &settings_name[index]; + + if (item->open == false) { + BT_ERR("%s, Settings %d is not open", __func__, index); + return -EIO; + } + + BT_INFO("Restore settings %d, user_id %s", index, item->user_id); + + err = settings_core_load(); + if (err) { + BT_ERR("%s, Load settings failed, name %s", __func__, item->nvs_name); + return err; + } + + err = settings_core_commit(); + if (err) { + BT_ERR("%s, Commit settings failed, name %s", __func__, item->nvs_name); + return err; + } + + item->restore = true; + return 0; +} + +int bt_mesh_provisioner_restore_settings_with_index(u8_t index) +{ + return provisioner_settings_restore(index); +} + +int bt_mesh_provisioner_restore_settings_with_user_id(const char *user_id, u8_t *index) +{ + u8_t idx = settings_index_get(user_id, index); + + if (idx >= ARRAY_SIZE(settings_name)) { + return -EIO; + } + + return provisioner_settings_restore(idx); +} + +static int provisioner_settings_release(u8_t index, bool erase) +{ + struct settings_namespace *item = NULL; + int err = 0; + + if (index >= ARRAY_SIZE(settings_name)) { + BT_ERR("%s, Invalid name index %d", __func__, index); + return -EINVAL; + } + + item = &settings_name[index]; + + if (item->open == false) { + BT_ERR("%s, Settings %d is not open", __func__, index); + return -EIO; + } + + if (item->restore == false) { + BT_ERR("%s, Settings %d is not restored, restore first", __func__, index); + return -EIO; + } + + BT_INFO("Release settings %d, user_id %s", index, item->user_id); + + /* Disable Provisioner firstly */ + err = bt_mesh_provisioner_disable(BLE_MESH_PROV_ADV | BLE_MESH_PROV_GATT); + if (err && err != -EALREADY) { + BT_ERR("%s, Failed to disable Provisioner", __func__); + return err; + } + + /* Release all the dynamic allocated memory for NetKey, AppKey, + * provisioned nodes, etc. + */ + bt_mesh_provisioner_release_node(erase); + bt_mesh_provisioner_release_netkey(erase); + bt_mesh_provisioner_release_appkey(erase); + bt_mesh_rx_reset(erase); + bt_mesh_tx_reset(); + bt_mesh_reset_mod_bind(); + bt_mesh_reset_mod_sub(); + bt_mesh_reset_mod_pub(); + if (erase) { + bt_mesh_clear_role(); + bt_mesh_clear_prov_info(); + bt_mesh_clear_seq(); + bt_mesh_clear_iv(); + bt_mesh_clear_mod_bind(); + bt_mesh_clear_mod_sub(); + bt_mesh_clear_mod_pub(); + } + + item->restore = false; + item->erase = erase; + return 0; +} + +int bt_mesh_provisioner_release_settings_with_index(u8_t index, bool erase) +{ + return provisioner_settings_release(index, erase); +} + +int bt_mesh_provisioner_release_settings_with_user_id(const char *user_id, bool erase, u8_t *index) +{ + u8_t idx = settings_index_get(user_id, index); + + if (idx >= ARRAY_SIZE(settings_name)) { + return -EIO; + } + + return provisioner_settings_release(idx, erase); +} + +static int role_erase(nvs_handle handle, const char *name) +{ + return bt_mesh_save_settings(handle, name, NULL, 0); +} + +static int iv_erase(nvs_handle handle, const char *name) +{ + return bt_mesh_save_settings(handle, name, NULL, 0); +} + +static int seq_erase(nvs_handle handle, const char *name) +{ + return bt_mesh_save_settings(handle, name, NULL, 0); +} + +static int rpl_erase(nvs_handle handle, const char *name) +{ + struct net_buf_simple *buf = NULL; + char get[16] = {'\0'}; + size_t length = 0U; + int err = 0; + int i; + + buf = bt_mesh_get_settings_item(handle, name); + if (!buf) { + return 0; + } + + length = buf->len; + + for (i = 0; i < length / SETTINGS_ITEM_SIZE; i++) { + u16_t src = net_buf_simple_pull_le16(buf); + + sprintf(get, "mesh/rpl/%04x", src); + err = bt_mesh_save_settings(handle, get, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, get); + goto free; + } + } + + err = bt_mesh_save_settings(handle, name, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, name); + } + +free: + bt_mesh_free_buf(buf); + return 0; +} + +static int model_erase_bind(nvs_handle handle, bool vnd, u16_t model_key) +{ + char get[16] = {'\0'}; + int err = 0; + + sprintf(get, "mesh/%s/%04x/b", vnd ? "v" : "s", model_key); + err = bt_mesh_save_settings(handle, get, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, get); + } + + return err; +} + +static int model_erase_sub(nvs_handle handle, bool vnd, u16_t model_key) +{ + char get[16] = {'\0'}; + int err = 0; + + sprintf(get, "mesh/%s/%04x/s", vnd ? "v" : "s", model_key); + err = bt_mesh_save_settings(handle, get, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, get); + } + + return err; +} + +static int model_erase_pub(nvs_handle handle, bool vnd, u16_t model_key) +{ + char get[16] = {'\0'}; + int err = 0; + + sprintf(get, "mesh/%s/%04x/p", vnd ? "v" : "s", model_key); + err = bt_mesh_save_settings(handle, get, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, get); + } + + return err; +} + +static int model_erase(nvs_handle handle, bool vnd, const char *name) +{ + struct net_buf_simple *buf = NULL; + size_t length = 0U; + int err = 0; + int i; + + BT_DBG("%s", __func__); + + buf = bt_mesh_get_settings_item(handle, name); + if (!buf) { + return 0; + } + + length = buf->len; + + for (i = 0; i < length / SETTINGS_ITEM_SIZE; i++) { + u16_t model_key = net_buf_simple_pull_le16(buf); + + err = model_erase_bind(handle, vnd, model_key); + if (err) { + BT_ERR("%s, Failed to erase model binding", __func__); + goto free; + } + + err = model_erase_sub(handle, vnd, model_key); + if (err) { + BT_ERR("%s, Failed to erase model subscrption", __func__); + goto free; + } + + err = model_erase_pub(handle, vnd, model_key); + if (err) { + BT_ERR("%s, Failed to erase model publication", __func__); + goto free; + } + } + + err = bt_mesh_save_settings(handle, name, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, name); + } + +free: + bt_mesh_free_buf(buf); + return err; +} + +static int sig_mod_erase(nvs_handle handle, const char *name) +{ + return model_erase(handle, false, name); +} + +static int vnd_mod_erase(nvs_handle handle, const char *name) +{ + return model_erase(handle, true, name); +} + +static int p_prov_erase(nvs_handle handle, const char *name) +{ + return bt_mesh_save_settings(handle, name, NULL, 0); +} + +static int p_net_idx_erase(nvs_handle handle, const char *name) +{ + return bt_mesh_save_settings(handle, name, NULL, 0); +} + +static int p_app_idx_erase(nvs_handle handle, const char *name) +{ + return bt_mesh_save_settings(handle, name, NULL, 0); +} + +static int p_net_key_erase(nvs_handle handle, const char *name) +{ + struct net_buf_simple *buf = NULL; + char get[16] = {'\0'}; + size_t length = 0U; + int err = 0; + int i; + + buf = bt_mesh_get_settings_item(handle, name); + if (!buf) { + return 0; + } + + length = buf->len; + + for (i = 0; i < length / SETTINGS_ITEM_SIZE; i++) { + u16_t net_idx = net_buf_simple_pull_le16(buf); + + sprintf(get, "mesh/pnk/%04x", net_idx); + err = bt_mesh_save_settings(handle, get, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, get); + goto free; + } + } + + err = bt_mesh_save_settings(handle, name, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, name); + } + +free: + bt_mesh_free_buf(buf); + return err; +} + +static int p_app_key_erase(nvs_handle handle, const char *name) +{ + struct net_buf_simple *buf = NULL; + char get[16] = {'\0'}; + size_t length = 0U; + int err = 0; + int i; + + buf = bt_mesh_get_settings_item(handle, name); + if (!buf) { + return 0; + } + + length = buf->len; + + for (i = 0; i < length / SETTINGS_ITEM_SIZE; i++) { + u16_t app_idx = net_buf_simple_pull_le16(buf); + + sprintf(get, "mesh/pak/%04x", app_idx); + err = bt_mesh_save_settings(handle, get, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, get); + goto free; + } + } + + err = bt_mesh_save_settings(handle, name, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, name); + } + +free: + bt_mesh_free_buf(buf); + return err; +} + +static int p_node_erase(nvs_handle handle, const char *name) +{ + struct net_buf_simple *buf = NULL; + char get[16] = {'\0'}; + size_t length = 0U; + bool prov = false; + int err = 0; + int i; + + buf = bt_mesh_get_settings_item(handle, name); + if (!buf) { + return 0; + } + + prov = strcmp(name, "mesh/p_pnode") ? false : true; + length = buf->len; + + for (i = 0; i < length / SETTINGS_ITEM_SIZE; i++) { + u16_t addr = net_buf_simple_pull_le16(buf); + + /* Clear node information */ + sprintf(get, prov ? "mesh/pn/%04x/i" : "mesh/sn/%04x/i", addr); + err = bt_mesh_save_settings(handle, get, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, get); + goto free; + } + + /* Clear node name */ + sprintf(get, prov ? "mesh/pn/%04x/n" : "mesh/sn/%04x/n", addr); + err = bt_mesh_save_settings(handle, get, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, get); + goto free; + } + + /* Clear node composition data */ + sprintf(get, prov ? "mesh/pn/%04x/c" : "mesh/sn/%04x/c", addr); + err = bt_mesh_save_settings(handle, get, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, get); + goto free; + } + } + + err = bt_mesh_save_settings(handle, name, NULL, 0); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, name); + } + +free: + bt_mesh_free_buf(buf); + return err; +} + +const struct bt_mesh_setting_erase { + const char *name; + int (*func)(nvs_handle handle, const char *name); +} settings_erase[] = { + { "mesh/role", role_erase }, + { "mesh/iv", iv_erase }, + { "mesh/seq", seq_erase }, + { "mesh/rpl", rpl_erase }, + { "mesh/sig", sig_mod_erase }, + { "mesh/vnd", vnd_mod_erase }, + { "mesh/p_prov", p_prov_erase }, + { "mesh/p_netidx", p_net_idx_erase }, + { "mesh/p_appidx", p_app_idx_erase }, + { "mesh/p_netkey", p_net_key_erase }, + { "mesh/p_appkey", p_app_key_erase }, + { "mesh/p_pnode", p_node_erase }, + { "mesh/p_snode", p_node_erase }, +}; + +int bt_mesh_settings_erase_by_handle(nvs_handle handle) +{ + int err = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(settings_erase); i++) { + err = settings_erase[i].func(handle, settings_erase[i].name); + if (err) { + BT_ERR("%s, Failed to erase %s", __func__, settings_erase[i].name); + return err; + } + } + + return 0; +} + +static int settings_user_id_delete(u8_t index) +{ + char nvs_name[16] = {'\0'}; + char name[16] = {'\0'}; + nvs_handle handle = 0U; + int err = 0; + + sprintf(nvs_name, "%s_%02x", "mesh_core", index); + + err = bt_mesh_settings_nvs_open(nvs_name, &handle); + if (err) { + BT_ERR("%s, Open nvs failed, name %s, err %d", __func__, nvs_name, err); + return -EIO; + } + + /* Erase mesh information */ + err = bt_mesh_settings_erase_by_handle(handle); + if (err) { + BT_ERR("%s, Failed to erase settings by handle", __func__); + return err; + } + + bt_mesh_settings_nvs_close(handle); + + /* Erase settings user_id */ + sprintf(name, "mesh/id/%04x", index); + bt_mesh_save_user_id_settings(name, NULL, 0); + + err = bt_mesh_remove_user_id_settings_item("mesh/uid", index); + if (err) { + BT_ERR("%s, Failed to remove 0x%04x from mesh/uid", __func__, index); + return err; + } + + return 0; +} + +static int provisioner_settings_delete(u8_t index) +{ + /* This function is used to erase the mesh information from + * the corresponding nvs namespace when it is not restored. + */ + struct settings_namespace *item = NULL; + int err = 0; + + if (index >= ARRAY_SIZE(settings_name)) { + BT_ERR("%s, Invalid name index %d", __func__, index); + return -EINVAL; + } + + item = &settings_name[index]; + + if (item->open == true) { + BT_ERR("%s, Settings %d is currently been used", __func__, index); + return -EIO; + } + + if (item->restore == true) { + BT_ERR("%s, Settings %d is restored, release instead", __func__, index); + return -EIO; + } + + BT_INFO("Delete settings %d, user_id %s", index, item->user_id); + + err = settings_user_id_delete(index); + if (err) { + BT_ERR("%s, Failed to delete settings %d, user_id %s", __func__, index, item->user_id); + return err; + } + + memset(item, 0, sizeof(struct settings_namespace)); + + return 0; +} + +int bt_mesh_provisioner_delete_settings_with_index(u8_t index) +{ + return provisioner_settings_delete(index); +} + +int bt_mesh_provisioner_delete_settings_with_user_id(const char *user_id, u8_t *index) +{ + u8_t idx = settings_index_get(user_id, index); + + if (idx >= ARRAY_SIZE(settings_name)) { + return -EIO; + } + + return provisioner_settings_delete(idx); +} + +const char *bt_mesh_provisioner_get_settings_user_id(u8_t index) +{ + if (index >= ARRAY_SIZE(settings_name)) { + BT_ERR("%s, Invalid settings index %d", __func__, index); + return NULL; + } + return settings_name[index].user_id; +} + +u8_t bt_mesh_provisioner_get_settings_index(const char *user_id) +{ + u8_t idx = 0U; + settings_index_get(user_id, &idx); + return idx; +} + +u8_t bt_mesh_provisioner_get_free_settings_user_id_count(void) +{ + u8_t count = 0U; + int i; + + for (i = 0; i < ARRAY_SIZE(settings_name); i++) { + if (settings_name[i].user_id[0] == '\0') { + count++; + } + } + + return count; +} +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ #endif /* CONFIG_BLE_MESH_PROVISIONER */ int settings_core_init(void) @@ -2570,21 +3654,30 @@ int bt_mesh_settings_init(void) { BT_DBG("%s", __func__); + bt_mesh_settings_mutex_new(); bt_mesh_settings_foreach(); return 0; } -int settings_core_deinit(void) +int settings_core_deinit(bool erase) { k_delayed_work_free(&pending_store); + if (erase) { + bt_mesh_clear_role(); + bt_mesh_clear_mod_bind(); + bt_mesh_clear_mod_sub(); + bt_mesh_clear_mod_pub(); + } + return 0; } -int bt_mesh_settings_deinit(void) +int bt_mesh_settings_deinit(bool erase) { - bt_mesh_settings_deforeach(); + bt_mesh_settings_deforeach(erase); + bt_mesh_settings_mutex_free(); return 0; } diff --git a/components/bt/esp_ble_mesh/mesh_core/settings.h b/components/bt/esp_ble_mesh/mesh_core/settings.h index a02db9e550..09ce73905a 100644 --- a/components/bt/esp_ble_mesh/mesh_core/settings.h +++ b/components/bt/esp_ble_mesh/mesh_core/settings.h @@ -13,7 +13,7 @@ int settings_core_init(void); int settings_core_load(void); int settings_core_commit(void); -int settings_core_deinit(void); +int settings_core_deinit(bool erase); void bt_mesh_store_role(void); void bt_mesh_store_net(void); @@ -29,6 +29,12 @@ void bt_mesh_store_cfg(void); void bt_mesh_store_mod_bind(struct bt_mesh_model *mod); void bt_mesh_store_mod_sub(struct bt_mesh_model *mod); void bt_mesh_store_mod_pub(struct bt_mesh_model *mod); +void bt_mesh_clear_mod_bind(void); +void bt_mesh_clear_mod_sub(void); +void bt_mesh_clear_mod_pub(void); +void bt_mesh_reset_mod_bind(void); +void bt_mesh_reset_mod_sub(void); +void bt_mesh_reset_mod_pub(void); void bt_mesh_store_label(void); void bt_mesh_clear_role(void); @@ -53,9 +59,31 @@ void bt_mesh_store_node_info(struct bt_mesh_node *node, bool prov); void bt_mesh_clear_node_info(u16_t unicast_addr, bool prov); void bt_mesh_store_node_name(struct bt_mesh_node *node, bool prov); void bt_mesh_store_node_comp_data(struct bt_mesh_node *node, bool prov); -#endif +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE +int settings_user_id_init(void); +int settings_user_id_load(void); +int settings_user_id_deinit(bool erase); +u32_t bt_mesh_provisioner_get_settings_handle(void); +int bt_mesh_provisioner_open_settings_with_index(u8_t index); +int bt_mesh_provisioner_open_settings_with_user_id(const char *user_id, u8_t *index); +int bt_mesh_provisioner_close_settings_with_index(u8_t index); +int bt_mesh_provisioner_close_settings_with_user_id(const char *user_id, u8_t *index); +int bt_mesh_provisioner_restore_settings_with_index(u8_t index); +int bt_mesh_provisioner_restore_settings_with_user_id(const char *user_id, u8_t *index); +int bt_mesh_provisioner_release_settings_with_index(u8_t index, bool erase); +int bt_mesh_provisioner_release_settings_with_user_id(const char *user_id, bool erase, u8_t *index); +int bt_mesh_provisioner_delete_settings_with_index(u8_t index); +int bt_mesh_provisioner_delete_settings_with_user_id(const char *user_id, u8_t *index); +const char *bt_mesh_provisioner_get_settings_user_id(u8_t index); +u8_t bt_mesh_provisioner_get_settings_index(const char *user_id); +u8_t bt_mesh_provisioner_get_free_settings_user_id_count(void); +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ +#endif /* CONFIG_BLE_MESH_PROVISIONER */ + +void bt_mesh_settings_lock(void); +void bt_mesh_settings_unlock(void); int bt_mesh_settings_init(void); -int bt_mesh_settings_deinit(void); +int bt_mesh_settings_deinit(bool erase); #endif /* _SETTINGS_H_ */ diff --git a/components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.c b/components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.c index 400eac9ce2..84645d4cec 100644 --- a/components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.c +++ b/components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.c @@ -15,9 +15,6 @@ #include #include -#include "nvs.h" -#include "nvs_flash.h" - #include "mesh_common.h" #include "settings_nvs.h" #include "settings.h" @@ -27,6 +24,9 @@ enum settings_type { SETTINGS_CORE, SETTINGS_SERVER, +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE + SETTINGS_USER_ID, +#endif }; struct settings_context { @@ -36,8 +36,7 @@ struct settings_context { int (*settings_init)(void); int (*settings_load)(void); int (*settings_commit)(void); - int (*settings_deinit)(void); - int (*settings_erase)(void); + int (*settings_deinit)(bool erase); }; static struct settings_context settings_ctx[] = { @@ -54,12 +53,36 @@ static struct settings_context settings_ctx[] = { .settings_load = NULL, .settings_commit = NULL, }, +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE + [SETTINGS_USER_ID] = { + .nvs_name = "mesh_user_id", + .settings_init = settings_user_id_init, + .settings_load = settings_user_id_load, + .settings_commit = NULL, + .settings_deinit = settings_user_id_deinit, + }, +#endif }; /* API used to initialize, load and commit BLE Mesh related settings */ +int bt_mesh_settings_nvs_open(const char* name, nvs_handle *handle) +{ +#if CONFIG_BLE_MESH_SPECIFIC_PARTITION + return nvs_open_from_partition(CONFIG_BLE_MESH_PARTITION_NAME, name, NVS_READWRITE, handle); +#else + return nvs_open(name, NVS_READWRITE, handle); +#endif +} + +void bt_mesh_settings_nvs_close(nvs_handle handle) +{ + nvs_close(handle); +} + void bt_mesh_settings_foreach(void) { + struct settings_context *ctx = NULL; int err = 0; int i; @@ -72,48 +95,67 @@ void bt_mesh_settings_foreach(void) #endif for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) { - struct settings_context *ctx = &settings_ctx[i]; - -#if CONFIG_BLE_MESH_SPECIFIC_PARTITION - err = nvs_open_from_partition(CONFIG_BLE_MESH_PARTITION_NAME, ctx->nvs_name, NVS_READWRITE, &ctx->handle); -#else - err = nvs_open(ctx->nvs_name, NVS_READWRITE, &ctx->handle); -#endif - if (err != ESP_OK) { - BT_ERR("%s, Open nvs failed, name %s, err %d", __func__, ctx->nvs_name, err); - continue; - } + ctx = &settings_ctx[i]; if (ctx->settings_init && ctx->settings_init()) { BT_ERR("%s, Init settings failed, name %s", __func__, ctx->nvs_name); - continue; + return; + } + } + +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE + /* If using multiple nvs namespaces, we will only restore user_id */ + ctx = &settings_ctx[SETTINGS_USER_ID]; + + err = bt_mesh_settings_nvs_open(ctx->nvs_name, &ctx->handle); + if (err) { + BT_ERR("%s, Open nvs failed, name %s, err %d", __func__, ctx->nvs_name, err); + return; + } + + if (ctx->settings_load && ctx->settings_load()) { + BT_ERR("%s, Load settings failed, name %s", __func__, ctx->nvs_name); + return; + } +#else /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ + /* If not using multiple nvs namespaces, we will follow the normal procedure, + * i.e. restoring all the mesh information. + */ + for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) { + ctx = &settings_ctx[i]; + + err = bt_mesh_settings_nvs_open(ctx->nvs_name, &ctx->handle); + if (err) { + BT_ERR("%s, Open nvs failed, name %s, err %d", __func__, ctx->nvs_name, err); + return; } if (ctx->settings_load && ctx->settings_load()) { BT_ERR("%s, Load settings failed, name %s", __func__, ctx->nvs_name); - continue; + return; } if (ctx->settings_commit && ctx->settings_commit()) { BT_ERR("%s, Commit settings failed, name %s", __func__, ctx->nvs_name); - continue; + return; } } +#endif /* CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE */ } -void bt_mesh_settings_deforeach(void) +void bt_mesh_settings_deforeach(bool erase) { int i; for (i = 0; i < ARRAY_SIZE(settings_ctx); i++) { struct settings_context *ctx = &settings_ctx[i]; - if (ctx->settings_deinit && ctx->settings_deinit()) { + if (ctx->settings_deinit && ctx->settings_deinit(erase)) { BT_ERR("%s, Deinit settings failed, name %s", __func__, ctx->nvs_name); continue; } - nvs_close(ctx->handle); + bt_mesh_settings_nvs_close(ctx->handle); } #if CONFIG_BLE_MESH_SPECIFIC_PARTITION @@ -125,6 +167,11 @@ void bt_mesh_settings_deforeach(void) static inline nvs_handle settings_get_nvs_handle(enum settings_type type) { +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE + if (type == SETTINGS_CORE) { + return bt_mesh_provisioner_get_settings_handle(); + } +#endif return settings_ctx[type].handle; } @@ -165,12 +212,29 @@ static int settings_save(nvs_handle handle, const char *key, const u8_t *val, si return 0; } +int bt_mesh_save_settings(nvs_handle handle, const char *key, const u8_t *val, size_t len) +{ + int err = 0; + bt_mesh_settings_lock(); + err = settings_save(handle, key, val, len); + bt_mesh_settings_unlock(); + return err; +} + int bt_mesh_save_core_settings(const char *key, const u8_t *val, size_t len) { nvs_handle handle = settings_get_nvs_handle(SETTINGS_CORE); - return settings_save(handle, key, val, len); + return bt_mesh_save_settings(handle, key, val, len); } +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE +int bt_mesh_save_user_id_settings(const char *key, const u8_t *val, size_t len) +{ + nvs_handle handle = settings_get_nvs_handle(SETTINGS_USER_ID); + return bt_mesh_save_settings(handle, key, val, len); +} +#endif + /* API used to load BLE Mesh related settings */ static int settings_load(nvs_handle handle, const char *key, @@ -199,12 +263,30 @@ static int settings_load(nvs_handle handle, const char *key, return 0; } +int bt_mesh_load_settings(nvs_handle handle, const char *key, u8_t *buf, + size_t buf_len, bool *exist) +{ + int err = 0; + bt_mesh_settings_lock(); + err = settings_load(handle, key, buf, buf_len, exist); + bt_mesh_settings_unlock(); + return err; +} + int bt_mesh_load_core_settings(const char *key, u8_t *buf, size_t buf_len, bool *exist) { nvs_handle handle = settings_get_nvs_handle(SETTINGS_CORE); - return settings_load(handle, key, buf, buf_len, exist); + return bt_mesh_load_settings(handle, key, buf, buf_len, exist); } +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE +int bt_mesh_load_user_id_settings(const char *key, u8_t *buf, size_t buf_len, bool *exist) +{ + nvs_handle handle = settings_get_nvs_handle(SETTINGS_USER_ID); + return bt_mesh_load_settings(handle, key, buf, buf_len, exist); +} +#endif + /* API used to get length of BLE Mesh related settings */ static size_t settings_get_length(nvs_handle handle, const char *key) @@ -270,12 +352,29 @@ static struct net_buf_simple *settings_get_item(nvs_handle handle, const char *k return buf; } +struct net_buf_simple *bt_mesh_get_settings_item(nvs_handle handle, const char *key) +{ + struct net_buf_simple *buf = NULL; + bt_mesh_settings_lock(); + buf = settings_get_item(handle, key); + bt_mesh_settings_unlock(); + return buf; +} + struct net_buf_simple *bt_mesh_get_core_settings_item(const char *key) { nvs_handle handle = settings_get_nvs_handle(SETTINGS_CORE); - return settings_get_item(handle, key); + return bt_mesh_get_settings_item(handle, key); } +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE +struct net_buf_simple *bt_mesh_get_user_id_settings_item(const char *key) +{ + nvs_handle handle = settings_get_nvs_handle(SETTINGS_USER_ID); + return bt_mesh_get_settings_item(handle, key); +} +#endif + /* API used to check if the settings item exists */ static bool is_settings_item_exist(struct net_buf_simple *buf, const u16_t val) @@ -342,12 +441,29 @@ static int settings_add_item(nvs_handle handle, const char *key, const u16_t val return err; } +int bt_mesh_add_settings_item(nvs_handle handle, const char *key, const u16_t val) +{ + int err = 0; + bt_mesh_settings_lock(); + err = settings_add_item(handle, key, val); + bt_mesh_settings_unlock(); + return err; +} + int bt_mesh_add_core_settings_item(const char *key, const u16_t val) { nvs_handle handle = settings_get_nvs_handle(SETTINGS_CORE); - return settings_add_item(handle, key, val); + return bt_mesh_add_settings_item(handle, key, val); } +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE +int bt_mesh_add_user_id_settings_item(const char *key, const u16_t val) +{ + nvs_handle handle = settings_get_nvs_handle(SETTINGS_USER_ID); + return bt_mesh_add_settings_item(handle, key, val); +} +#endif + /* API used to remove the settings item */ static int settings_remove_item(nvs_handle handle, const char *key, const u16_t val) @@ -397,10 +513,27 @@ static int settings_remove_item(nvs_handle handle, const char *key, const u16_t return err; } +int bt_mesh_remove_settings_item(nvs_handle handle, const char *key, const u16_t val) +{ + int err = 0; + bt_mesh_settings_lock(); + err = settings_remove_item(handle, key, val); + bt_mesh_settings_unlock(); + return err; +} + int bt_mesh_remove_core_settings_item(const char *key, const u16_t val) { nvs_handle handle = settings_get_nvs_handle(SETTINGS_CORE); - return settings_remove_item(handle, key, val); + return bt_mesh_remove_settings_item(handle, key, val); } +#if CONFIG_BLE_MESH_USE_MULTIPLE_NAMESPACE +int bt_mesh_remove_user_id_settings_item(const char *key, const u16_t val) +{ + nvs_handle handle = settings_get_nvs_handle(SETTINGS_USER_ID); + return bt_mesh_remove_settings_item(handle, key, val); +} +#endif + #endif /* CONFIG_BLE_MESH_SETTINGS */ diff --git a/components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.h b/components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.h index 099efa54d8..4e15bfadcf 100644 --- a/components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.h +++ b/components/bt/esp_ble_mesh/mesh_core/storage/settings_nvs.h @@ -15,6 +15,8 @@ #ifndef _BLE_MESH_SETTINGS_NVS_H_ #define _BLE_MESH_SETTINGS_NVS_H_ +#include "nvs.h" +#include "nvs_flash.h" #include "mesh_buf.h" #ifdef __cplusplus @@ -28,18 +30,29 @@ extern "C" { #define BLE_MESH_GET_MODEL_KEY(a, b) ((u16_t)(((u16_t)((a) << 8)) | b)) void bt_mesh_settings_foreach(void); -void bt_mesh_settings_deforeach(void); +void bt_mesh_settings_deforeach(bool erase); + +int bt_mesh_settings_nvs_open(const char* name, nvs_handle *handle); +void bt_mesh_settings_nvs_close(nvs_handle handle); + +int bt_mesh_save_settings(nvs_handle handle, const char *key, const u8_t *val, size_t len); +int bt_mesh_load_settings(nvs_handle handle, const char *key, u8_t *buf, size_t buf_len, bool *exist); +struct net_buf_simple *bt_mesh_get_settings_item(nvs_handle handle, const char *key); +int bt_mesh_add_settings_item(nvs_handle handle, const char *key, const u16_t val); +int bt_mesh_remove_settings_item(nvs_handle handle, const char *key, const u16_t val); int bt_mesh_save_core_settings(const char *key, const u8_t *val, size_t len); - int bt_mesh_load_core_settings(const char *key, u8_t *buf, size_t buf_len, bool *exist); - struct net_buf_simple *bt_mesh_get_core_settings_item(const char *key); - int bt_mesh_add_core_settings_item(const char *key, const u16_t val); - int bt_mesh_remove_core_settings_item(const char *key, const u16_t val); +int bt_mesh_save_user_id_settings(const char *key, const u8_t *val, size_t len); +int bt_mesh_load_user_id_settings(const char *key, u8_t *buf, size_t buf_len, bool *exist); +struct net_buf_simple *bt_mesh_get_user_id_settings_item(const char *key); +int bt_mesh_add_user_id_settings_item(const char *key, const u16_t val); +int bt_mesh_remove_user_id_settings_item(const char *key, const u16_t val); + #ifdef __cplusplus } #endif diff --git a/components/bt/esp_ble_mesh/mesh_core/transport.c b/components/bt/esp_ble_mesh/mesh_core/transport.c index 3d78e4365c..c75daeedb8 100644 --- a/components/bt/esp_ble_mesh/mesh_core/transport.c +++ b/components/bt/esp_ble_mesh/mesh_core/transport.c @@ -1556,7 +1556,7 @@ int bt_mesh_trans_recv(struct net_buf_simple *buf, struct bt_mesh_net_rx *rx) return err; } -void bt_mesh_rx_reset(void) +void bt_mesh_rx_reset(bool erase) { int i; @@ -1566,7 +1566,11 @@ void bt_mesh_rx_reset(void) seg_rx_reset(&seg_rx[i], true); } - if (IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { + /* For node, the "erase" flag shall always be true. And + * only the macro CONFIG_BLE_MESH_SETTINGS will be used + * to decide whether to erase the RPL list from flash. + */ + if (erase && IS_ENABLED(CONFIG_BLE_MESH_SETTINGS)) { bt_mesh_clear_rpl(); } else { (void)memset(bt_mesh.rpl, 0, sizeof(bt_mesh.rpl)); diff --git a/components/bt/esp_ble_mesh/mesh_core/transport.h b/components/bt/esp_ble_mesh/mesh_core/transport.h index 028b62be85..0f31e3b439 100644 --- a/components/bt/esp_ble_mesh/mesh_core/transport.h +++ b/components/bt/esp_ble_mesh/mesh_core/transport.h @@ -86,7 +86,7 @@ struct bt_mesh_app_key *bt_mesh_app_key_find(u16_t app_idx); bool bt_mesh_tx_in_progress(void); -void bt_mesh_rx_reset(void); +void bt_mesh_rx_reset(bool erase); void bt_mesh_tx_reset(void); int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, u8_t ctl_op, void *data,