*/
int bt_gatt_disable_data_batching(const char *remote_address);
+/* Mesh API */
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Initializes the Mesh API
+ *
+ * @remarks This function must be called before starting use BT Mesh API's.
+ * You must free all resources of the BT Mesh service by
+ * calling bt_mesh_deinitialize()
+ * if Mesh service is no longer needed.
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_initialize(void);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Must be called if BT Mesh service is no longer needed
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_deinitialize(void);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief API to create a arbitrary node.
+ * Primary element is mandatory element for any node
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_node_create(bt_mesh_node_features_s *features,
+ bt_mesh_node_h *node_handle);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Destroys the locally created mesh node
+ * & all resources contained in it
+ *
+ * @remarks: It is not allowed to arbitrarily destroy a locally created node,
+ * if it is part of a mesh network already.
+ * @remarks: Destroying a remote node is not supported.
+ * @remarks: In order to reset a remote provisioned node, use bt_mesh_node_reset() API
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_node_destroy(bt_mesh_node_h node_handle);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief API to create a mesh element. In case of Mesh Provisioner,
+ * it will serve as a element of the local node of a Mesh Provisioner.
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_node_create_element(bt_mesh_node_h node_handle,
+ bt_mesh_element_h *element_handle);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Destroys the locally created mesh element &
+ * all resources contained in it (Ex: models)
+ *
+ * @remarks: It is not allowed to arbitrarily destroy a
+ * locally created element, if it is part of a mesh network already.
+ * @remarks: Destroying element of a remote node is not supported.
+ * @remarks: In order to reset a remote provisioned node,
+ * use bt_mesh_node_reset() API
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_element_destroy(bt_mesh_element_h element_handle);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief API to create a mesh Model instance.
+ * In case of Mesh Provisioner, it will serve as a
+ * Model of one of the elements of the local node of a Mesh Provisioner.
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_element_create_model(bt_mesh_element_h element_handle,
+ bt_mesh_model_id_s *model_id,
+ bt_mesh_model_h *model_handle);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Destroys the locally created mesh Model
+ *
+ * @remarks: It is not allowed to arbitrarily destroy a locally created model,
+ * if it is part of a mesh network already.
+ * @remarks: Destroying model of a remote element is not supported.
+ * @remarks: In order to reset a remote provisioned node,
+ * use bt_mesh_node_reset() API
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_model_destroy(bt_mesh_model_h model);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief API to get Model ID from handle.
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_model_get_id(bt_mesh_model_h model,
+ bt_mesh_model_id_s *model_id);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Get Network instance in which node is contained.
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_node_get_network(bt_mesh_node_h node,
+ bt_mesh_network_h *netkwork);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Get node instance in which element is contained.
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_element_get_node(bt_mesh_element_h element,
+ bt_mesh_node_h *node);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Get element instance in which model is contained.
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_model_get_element(bt_mesh_model_h model,
+ bt_mesh_element_h *element);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Get Network instance in which node is contained.
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_appkey_get_netkey(bt_mesh_appkey_h appkey,
+ bt_mesh_netkey_h *netkey);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Call to create a fresh Local Mesh Provisioner.
+ * Each Mesh Network will be characterisized
+ * by only one Mesh Provisioner. Mesh Provisioner will
+ * contain a Mesh Node which be called "local node".
+ * CAPI user(application) can create multiple Mesh Network.
+ * Each network will have a unique Mesh Provisioner
+ *
+ * @param: in: config_client, local Mesh Provisioner node
+ * @param: in: network_name, Mesh Network user friendly Name
+ * @param: out: token, The token parameter is a hexadecimal string
+ * of 8 bytes has been assigned to
+ * the application when it first got provisioned/joined mesh.
+ * order to authenticate itself and attach to the network as a mesh node.
+ * @param: out: network, created Mesh Network instance
+ *
+ * Note: Once the Mesh Network is successfully created
+ * OR the 'local Node' is attached, it is *NOT* allowed to
+ * change Local Node Hierarchy (Add/Delete Element(s), Add/Delete Model(s) etc.)
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_create(bt_mesh_node_h config_client,
+ const char *network_name,
+ bt_mesh_network_h *network,
+ char **token);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Call to load a previously created Local Mesh Provisioner.
+ * Each Mesh Network will be characterisized
+ * by only one Mesh Provisioner. Mesh Provisioner will contain a
+ * Mesh Config Node which be called "local node".
+ * CAPI user(application) can create multiple Mesh Network.
+ * Each network will have a unique Mesh Provisioner
+ *
+ * @param: in: token, The token parameter is a 8 byte hexadecimal
+ * string that has been assigned to the application when it first
+ * got provisioned/joined mesh. The API will use the token to
+ * authenticate itself and attach to the network as a mesh node.
+ * Application should use a valid token to authenticate itself
+ * as a Mesh Network Provisioner.
+ * @param: out: network, created Mesh Network instance
+ *
+ * Note: Once the Mesh Network is successfully created OR the
+ * 'local Node' is attached,
+ * it is *NOT* allowed to change Local Node Hierarchy
+ * (Add/Delete Element(s), Add/Delete Model(s) etc.)
+ *
+ * @see bt_mesh_network_create
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_load(const char *token,
+ bt_mesh_network_h *network);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Set Mesh Network's user fiendly name.
+ *
+ * @see bt_mesh_network_create
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_set_name(bt_mesh_network_h network,
+ const char *network_name);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Get Mesh Network's user fiendly name.
+ *
+ * @see bt_mesh_network_create
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_get_name(bt_mesh_network_h network,
+ char **network_name);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Call to create and associate a mesh Network Key to Mesh Network
+ *
+ * @see bt_mesh_network_create
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_add_netkey(bt_mesh_network_h network,
+ bt_mesh_netkey_h *netkey);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Get all NetKey(s) attached to the Local Network.
+ *
+ * @see bt_mesh_network_create
+ * @see bt_mesh_network_add_netkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_foreach_netkeys(bt_mesh_network_h network,
+ bt_mesh_network_netkey_info_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Get global Netkey index from NetKey instance
+ *
+ * @see bt_mesh_network_add_netkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_netkey_get_index(bt_mesh_netkey_h netkey,
+ uint16_t *index);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Call to update a mesh Network Key.
+ *
+ * @see bt_mesh_network_add_netkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_netkey_update(bt_mesh_netkey_h netkey);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Call to delete a mesh Network Key.
+ *
+ * @remarks It is not allowed to destroy a netkey if it is already
+ * added to any of nodes in the Mesh Network
+ *
+ * @see bt_mesh_network_add_netkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_netkey_delete(bt_mesh_netkey_h netkey);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Call to create & associate a Application Key to a Network Key
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_netkey_add_appkey(bt_mesh_netkey_h netkey,
+ bt_mesh_appkey_h *appkey);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Get all appkeys associated with a NetKey.
+ *
+ * @see bt_mesh_netkey_add_appkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_netkey_foreach_appkeys(bt_mesh_netkey_h netkey,
+ bt_mesh_appkey_info_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Get global AppKey index from AppKey instance.
+ *
+ * @see bt_mesh_netkey_add_appkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_appkey_get_index(bt_mesh_appkey_h netkey,
+ uint16_t *index);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Call to update a mesh Network Key.
+ *
+ * @see bt_mesh_netkey_add_appkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_appkey_update(bt_mesh_appkey_h appkey);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Call to delete a mesh Application Key.
+ *
+ * @remarks It is not allowed to destroy an AppKey if it is already
+ * added to any of nodes in the Mesh Network
+ *
+ * @see bt_mesh_netkey_add_appkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_appkey_delete(bt_mesh_appkey_h appkey);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Call to get all devices attached to the network.
+ * Node handle along with its primary unicast address will be returned
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_foreach_devices(bt_mesh_network_h network,
+ bt_mesh_network_device_info_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Call to get primary unicast address of the node from its handle
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_node_get_primary_address(bt_mesh_node_h node,
+ uint16_t *primary_address);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Find each element present in a node
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_node_foreach_element(bt_mesh_node_h node,
+ bt_mesh_node_element_info_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Find each models present in an element
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_element_foreach_models(bt_mesh_element_h element,
+ bt_mesh_element_model_info_cb callback,
+ void *user_data);
+
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Async call to discover unprovisioned device.
+ * Each unprovisioned device will advertise itself with a unique Device UUID
+ *
+ * @remarks scan result will be NULL when scan state is started or finished.
+ * scan result is valid only when scan state is 'device found'
+ *
+ * @see bt_mesh_scanning_state_e
+ * @see bt_mesh_network_scan_unprovisioned_device_result_cb
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_unprovisioned_device_scan(bt_mesh_network_h network,
+ bt_mesh_scan_params_s *scan_params,
+ bt_mesh_network_scan_unprovisioned_device_result_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Stop discovring unprovisioned device.
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_stop_unprovisioned_device_scan(bt_mesh_network_h network);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Set capabilities of a provisioner application.
+ * Provisioning capabilities will as per Input/Output capabilities of the
+ * device/application creating the provisioner.
+ * For e.g, if device/application has Wi-Fi/NFC connectivity and can
+ * procure Provisioning keys Out-Of-Band over Wi-Fi network/Remote Web URL/NFC Connectivity,
+ * then following capabilities can be set to true, otherwise left false
+ * a/ bool public_oob b/ bool static_oob
+ * Above capabilities indicate whether, Public Key for ECC exchange & Static Key for
+ * authentication can be procured out-of-band or not
+ *
+ * @param: in: network Mesh network instance which represents a provisioner node
+ * @param: in: capabilities Provisioner capabilities structure
+ *
+ * @remarks: A single provisioner network can provision multiple remote devices.
+ * During security provisioning, capabilities are selected *By Provisioner*
+ * based on combination of supported capabilities of provisioner & remote nodes together.
+ *
+ * @remarks: A mesh network instance represents a single Mesh provisioning node
+ * & multiple remote provisioned nodes.
+ * Therefore, setting capabilities one time, for a network or a provisioner node is sufficient.
+ * Normally, Input/output capabilities do not change over time for a device
+ * or an application. Incase, it is changed, application is free to refresh the
+ * capabilities of the Provisioner at any point of time.
+ * The next provisioning process will automatically consider the refreshed capabilities.
+ * @remarks: Capabilities can be set one time after local provisioner node is attached to a network.
+ *
+ * @see: bt_mesh_provisioner_capabilities_s structure
+ * @see: bt_mesh_network_create()
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_set_provisioning_capabilities(
+ bt_mesh_network_h network,
+ bt_mesh_provisioner_capabilities_s *capabilities);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Async call to provision a device to the Mesh Network
+ *
+ * @remarks: In Tizen, only one provisioning process is allowed,
+ * irrespective of Provisioner or node role.
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_provision_device(bt_mesh_network_h network,
+ const char *dev_uuid,
+ bt_mesh_network_device_provision_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Registers a callback that will be invoked when remote
+ * device requests authentication, during the provisioning process.
+ *
+ * @pre Either bt_mesh_network_provision_device() in case of Provisioner role
+ * or bt_mesh_node_network_join() in case of Node role must be
+ * called (Node role API is not defined yet)
+ *
+ * @param[in] callback callback function which is set, for receiving
+ * authentication request during provisioning process.
+ * @param[in] user_data data from application which will be provided in callback.
+ *
+ * @remarks: This method is designed common for both Provisioner & Node role.
+ * @remarks: This callback is not invoked without the local device initiating the process
+ * of either Provisioning(in case of local provisioner) or
+ * Joining Network(in case of local node role).
+ * Therefore, application will be completely aware, when the callback is invoked.
+ * @remarks: In Tizen, only one provisioning process is allowed, irrespective of Provisioner or node role.
+ * Therefore, when the callback is invoked, aplication exactly knows following
+ * a/ whether the process is for provisioner role trying to provision a remote device
+ * b/ Or process if for local node role, which is inviting remote provisioners
+ * to join itself to a Mesh Network
+ *
+ * @see bt_network_provision_device()
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_authentication_set_request_cb(
+ bt_mesh_authentication_request_cb callback,
+ void *user_data);
+
+/**
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Un-registers a callback that will be invoked when
+ * remote device requests authentication,during the provisioning process
+ *
+ * @param[in] callback callback function to be set when
+ * authentication request is received.
+ *
+ * @remarks: This method is designed common for both Provisioner & Node role.
+ * @see bt_mesh_authentication_set_request_cb()
+ * @see bt_mesh_authentication_request_cb()
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_authentication_unset_request_cb(
+ bt_mesh_authentication_request_cb callback);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief API to reply authentication request.
+ * @remarks This function can be called by application when remote
+ * device requests authentication due to either of following process
+ * a/ Local provisioner role trying to provision a remote device
+ * b/ Local node role, inviting remote provisioners to join itself to a Mesh Network
+ * @param[in] auth_type Specific authentiation type, for which reply is being sent
+ * @param[in] value Reply string corresponding to authentication type
+ * @param[in] auth_reply Accept or cancel ongoing provisioning process
+ * @pre This function can only be called when application receieves authentication
+ * callback bt_mesh_authentication_request_cb
+ * @remarks: value string is valid, when autnetication type is of following
+ * a/ BT_MESH_AUTH_REQ_ALPHANUMERIC_INPUT
+ * b/ BT_MESH_AUTH_REQ_NUMERIC_INPUT
+ * c/ BT_MESH_AUTH_REQ_BLINK_COUNT_INPUT
+ * d/ BT_MESH_AUTH_REQ_BEEP_COUNT_INPUT
+ * e/ BT_MESH_AUTH_REQ_VIBRATE_COUNT_INPUT
+ * f/ BT_MESH_AUTH_REQ_OOB_PUBLIC_KEY_INPUT
+ * g/ BT_MESH_AUTH_REQ_OOB_STATIC_KEY_INPUT
+ *
+ * @remarks: This method is designed common for both Provisioner & Node role.
+ * @see bt_mesh_authentication_set_request_cb()
+ * @see bt_mesh_authentication_request_cb()
+ * @see bt_mesh_authentication_type_e
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_authentication_reply(
+ bt_mesh_authentication_type_e auth_type,
+ const char *value, bool auth_reply);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Async call to identify the newly provisioned device
+ *
+ * @remarks: After provisioning is done, device must be
+ * discovered first of all in order to
+ * use it. If device is successfully discovered, node handle
+ * will be returned in the callback.
+ * @see bt_mesh_network_provision_device
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_discover_node(bt_mesh_network_h network,
+ const char *dev_uuid,
+ bt_mesh_node_discover_status_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Async call to browse the features of a node.
+ * Features of the node are returned in callback
+ *
+ * @see bt_mesh_network_provision_device
+ * @see bt_mesh_network_discover_node
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_node_get_features(bt_mesh_node_h node,
+ bt_mesh_node_features_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Async call to Add/Update/Delete a NetKey to a node
+ *
+ * @see bt_mesh_network_add_netkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_node_configure_netkey(bt_mesh_node_h node,
+ bt_mesh_node_key_configuration_e netkey_op,
+ bt_mesh_netkey_h netkey,
+ bt_mesh_netkey_status_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Async call to add/update/delete an Application to a node
+ *
+ * @see bt_mesh_netkey_add_appkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_node_configure_appkey(bt_mesh_node_h node,
+ bt_mesh_node_key_configuration_e appkey_op,
+ bt_mesh_appkey_h appkey,
+ bt_mesh_appkey_status_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Find all NetKey(s) attached to a node
+ *
+ * @see bt_mesh_node_configure_netkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_node_foreach_netkeys(bt_mesh_node_h node,
+ bt_mesh_node_netkey_info_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Find all AppKey(s) bound to a NetKey in a node
+ *
+ * @see bt_mesh_node_configure_appkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_node_foreach_appkeys(bt_mesh_node_h node,
+ bt_mesh_netkey_h netkey,
+ bt_mesh_node_appkey_info_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Query TTL set to a node in the network
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_node_get_ttl(bt_mesh_node_h node,
+ bt_mesh_node_ttl_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Query TTL set to a node in the network
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_node_set_ttl(bt_mesh_node_h node, uint8_t ttl,
+ bt_mesh_node_ttl_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Async call to bind a locally created application key
+ * to a Model of a node
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_model_bind_appkey(bt_mesh_model_h model,
+ bt_mesh_appkey_h appkey, bt_mesh_model_bind_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Async call to Unbind a locally created application key
+ * to a Model of a node
+ *
+ * @see bt_mesh_model_bind_appkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_model_unbind_appkey(bt_mesh_model_h model,
+ bt_mesh_appkey_h appkey,
+ bt_mesh_model_unbind_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Async call to find all AppKey(s) bound to a model of a node
+ *
+ * @see bt_mesh_model_bind_appkey
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_model_get_appkey_list(bt_mesh_model_h model,
+ bt_mesh_model_appkey_list_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Create a Mesh group with a given group address in the Local Network
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_create_group(bt_mesh_network_h network,
+ uint16_t group_addr,
+ bt_mesh_group_h *group);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Create a Mesh Virtual group in the Local Network.
+ *
+ * @remarks Virtual group label (128-bit UUID) is internally managed by Framework.
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_create_virtual_group(bt_mesh_network_h network,
+ bt_mesh_group_h *group);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Remove a create Mesh group in the Local Network.
+ *
+ * @see bt_mesh_network_create_group
+ * @see bt_mesh_network_create_virtual_group
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_remove_group(bt_mesh_group_h group);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Find all Mesh group(s), that are created in the Local Network.
+ *
+ * @remarks Group handles will be returned for each created group.
+ * @see bt_mesh_network_create_group
+ * @see bt_mesh_network_create_virtual_group
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_network_foreach_groups(bt_mesh_network_h network,
+ bt_mesh_network_group_info_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Subscription Add/Delete/Overwrite request to a Model of an element.
+ *
+ * @param: in: model_op: Add/Delete/Overwrite
+ * @param: in: model Model on which subscription operation will be applied
+ * @param: in: group Mesh Group handle.
+ * @param: in: callback result of model subscription operation
+ * request from remote node
+ * @param: in: user_data async callback data
+ *
+ * @see bt_mesh_network_create_group
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_model_configure_group_subscription(
+ bt_mesh_model_subscription_op_e model_op,
+ bt_mesh_model_h model, bt_mesh_group_h group,
+ bt_mesh_model_subscription_op_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Subscription Add/Delete/Overwrite request of a
+ * Virtual Group, to Model of an element.
+ *
+ * @param: in: model_op: Add/Delete/Overwrite
+ * @param: in: model Model on which subscription operation will be applied
+ * @param: in: group Mesh Group handle.
+ * @param: in: callback result of model subscription operation
+ * request from remote node
+ * @param: in: user_data async callback data
+ *
+ * @see bt_mesh_network_create_virtual_group
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_model_configure_virtual_group_subscription(
+ bt_mesh_model_subscription_op_e model_op,
+ bt_mesh_model_h model, bt_mesh_group_h group,
+ bt_mesh_model_subscription_op_cb callback,
+ void *user_data);
+
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Find all Subscription list of a model in a node.
+ * A List of all groups handles will be returned in callback, if success
+ *
+ * @remarks Group handles will be returned for each created group.
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_model_get_subscription_list(bt_mesh_model_h model,
+ bt_mesh_model_subscription_list_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Add a publiation to a Model of a node.
+ *
+ * @param: in: model Model which will generate the Publication message
+ * @param: in: appkey application key handle which will be used to
+ * encrypt publication message
+ * @param: in: group Mesh Group handle.
+ * @param: in: param Model Publication Parameters
+ * @param: in: callback result of model publication set request,
+ * from remote node
+ * @param: in: user_data async callback data
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_model_set_publication(bt_mesh_model_h model,
+ bt_mesh_appkey_h appkey, bt_mesh_group_h group,
+ bt_mesh_model_pub_params_s *params,
+ bt_mesh_model_publication_status_cb callback,
+ void *user_data);
+
+/**
+ * @internal
+ * @ingroup CAPI_NETWORK_BLUETOOTH_MESH_MODULE
+ * @brief Find Publication, set in model of a node, attached to a Network.
+ * Publication group handle will be returned in callback, if success
+ *
+ * @since_tizen 6.0
+ * @privlevel platform
+ */
+int bt_mesh_model_get_publication(bt_mesh_model_h model,
+ bt_mesh_model_publication_status_cb callback,
+ void *user_data);
+
/**
* @}
*/
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * @author: Anupam Roy <anupam.r@samsung.com>
+ *
+ * Licensed 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 <glib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <dlog.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <arpa/inet.h>
+#include <bluetooth-api.h>
+
+#include "bluetooth.h"
+#include "bluetooth_internal.h"
+#include "bluetooth_private.h"
+#include "bluetooth-mesh-api.h"
+
+#define BT_MESH_MAX_NETWORKS 5
+#define BT_MESH_MAX_ELEMENTS 32767
+#define BT_MESH_MAX_MODELS 32767
+#define BT_MESH_MAX_NODES 32767
+#define BT_MESH_MAX_SUBNETS 4096
+
+static bool is_mesh_initialized = false;
+
+/**< List of Local handles >*/
+GSList *networks;
+GSList *node_list;
+GSList *element_list;
+GSList *model_list;
+GSList *appkey_list;
+GSList *netkey_list;
+GSList *group_list;
+
+
+#define BT_CHECK_MESH_SUPPORT() \
+{ \
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_COMMON); \
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_LE); \
+ BT_CHECK_SUPPORTED_FEATURE(BT_FEATURE_MESH); \
+}
+
+#define BT_CHECK_MESH_INIT_STATUS() \
+ if (__bt_check_mesh_init_status() == BT_ERROR_NOT_INITIALIZED) { \
+ LOGE("[%s] NOT_INITIALIZED(0x%08x)", __FUNCTION__, BT_ERROR_NOT_INITIALIZED); \
+ return BT_ERROR_NOT_INITIALIZED; \
+ }
+
+
+#define BT_CHECK_MESH_REMOTE(handle) \
+{ if (handle->is_local) return BT_ERROR_OPERATION_FAILED; }
+
+
+#define BT_CHECK_MESH_LOCAL(handle) \
+{ if (!handle->is_local) return BT_ERROR_OPERATION_FAILED; }
+
+
+#define BT_CHECK_MESH_IS_ATTACHED(handle) \
+{ if (handle->is_attached) return BT_ERROR_OPERATION_FAILED; }
+
+#define BT_MESH_VALIDATE_HANDLE(h1, list) \
+{ \
+ GSList *l; \
+ bool valid = FALSE; \
+ for (l = list; l; l = g_slist_next(l)) { \
+ void *h2 = (void *)l->data; \
+ if (h1 == h2) { \
+ BT_INFO("Handle matched [%p]", h2); \
+ valid = TRUE; break; \
+ } \
+ } \
+ if (valid == FALSE) { \
+ BT_ERR("Handle [%p] did not match with any stored handles!!", h1); \
+ return BT_ERROR_INVALID_PARAMETER; \
+ } \
+} \
+
+size_t __bt_mesh_util_convert_hex_to_string(uint8_t *in,
+ size_t in_len, char *out, size_t out_len)
+{
+ static const char hexdigits[] = "0123456789abcdef";
+ size_t i;
+
+ if (in_len * 2 > (out_len - 1))
+ return 0;
+
+ for (i = 0; i < in_len; i++) {
+ out[i * 2] = hexdigits[in[i] >> 4];
+ out[i * 2 + 1] = hexdigits[in[i] & 0xf];
+ }
+
+ out[in_len * 2] = '\0';
+ return i;
+}
+
+static int __compare_node_primary_unicast(gconstpointer a, gconstpointer b)
+{
+ const bt_mesh_node_s *node = a;
+ uint16_t index = GPOINTER_TO_UINT(b);
+
+ return (node->unicast - index);
+}
+
+static int __compare_node_element_index(gconstpointer a, gconstpointer b)
+{
+ const bt_mesh_element_s *element = a;
+ int index = GPOINTER_TO_UINT(b);
+
+ return (element->index - index);
+}
+
+static int __compare_network_group_address(gconstpointer a, gconstpointer b)
+{
+ const bt_mesh_group_s *group = a;
+ uint16_t group_addr = GPOINTER_TO_UINT(b);
+
+ return (group->addr - group_addr);
+}
+
+static int __compare_model_id(gconstpointer a, gconstpointer b)
+{
+ const bt_mesh_model_s *model_s = a;
+ uint32_t model = GPOINTER_TO_UINT(b);
+
+ return (model_s->id - model);
+}
+
+static int __compare_netkey_index(gconstpointer a, gconstpointer b)
+{
+ const bt_mesh_netkey_s *nk = a;
+ uint16_t netkey_index = GPOINTER_TO_UINT(b);
+
+ return (nk->netkey_index - netkey_index);
+}
+
+static int __simple_compare(gconstpointer a, gconstpointer b)
+{
+ if (a == b)
+ return 0;
+ else
+ return 1;
+}
+
+static int __compare_appkey_index(gconstpointer a, gconstpointer b)
+{
+ const bt_mesh_appkey_s *ak = a;
+ uint16_t appkey_index = GPOINTER_TO_UINT(b);
+
+ return (ak->appkey_index - appkey_index);
+}
+
+static int __compare_element_index(gconstpointer a, gconstpointer b)
+{
+ const bt_mesh_element_s *elem = a;
+ uint16_t element_index = GPOINTER_TO_UINT(b);
+
+ return (elem->index - element_index);
+}
+
+static bt_mesh_netkey_s * __bt_mesh_network_is_netkey_added(
+ bt_mesh_network_s *network_s, uint16_t netkey_idx)
+{
+ GSList *l;
+
+ l = g_slist_find_custom(network_s->netkeys, GUINT_TO_POINTER(netkey_idx),
+ (GCompareFunc)__compare_netkey_index);
+ if (!l)
+ return NULL;
+
+ return (bt_mesh_netkey_s*) l->data;
+}
+
+bt_mesh_element_s *_bt_mesh_get_element_from_index(
+ bt_mesh_node_s *node_s, int element_index)
+{
+ GSList *l;
+
+ l = g_slist_find_custom(node_s->elements, GUINT_TO_POINTER(element_index),
+ (GCompareFunc)__compare_element_index);
+ if (!l)
+ return NULL;
+
+ return (bt_mesh_element_s*) l->data;
+}
+
+bt_mesh_appkey_s *_bt_mesh_network_get_appkey_from_index(
+ bt_mesh_network_s *network_s, uint16_t appkey_idx)
+{
+ GSList *l, *l1;
+
+ for (l = network_s->netkeys; l; l = l->next) {
+ bt_mesh_netkey_s *netkey_s = l->data;
+
+ l1 = g_slist_find_custom(netkey_s->appkeys, GUINT_TO_POINTER(appkey_idx),
+ (GCompareFunc)__compare_appkey_index);
+
+ if (l1)
+ return l1->data;
+ }
+ return NULL;
+}
+
+bt_mesh_model_s *_bt_mesh_get_model_from_modelid(
+ bt_mesh_element_s *element_s, uint32_t modelid)
+{
+ GSList *l;
+
+ l = g_slist_find_custom(element_s->models, GUINT_TO_POINTER(modelid),
+ (GCompareFunc)__compare_model_id);
+ if (!l)
+ return NULL;
+
+ return (bt_mesh_model_s*) l->data;
+}
+
+bt_mesh_group_s* _bt_mesh_network_get_group(
+ bt_mesh_network_s *network_s, uint16_t group_addr)
+{
+ GSList *l;
+ bt_mesh_group_s *group_s = NULL;
+
+ /* Unassigned address */
+ if (group_addr == 0x0000)
+ return NULL;
+
+ l = g_slist_find_custom(network_s->groups, GUINT_TO_POINTER(group_addr),
+ (GCompareFunc) __compare_network_group_address);
+ if (!l) {
+ group_s = g_malloc0(sizeof(bt_mesh_group_s));
+ group_s->addr = group_addr;
+ if (group_addr >= 0x8000 && group_addr <= 0xbfff)
+ group_s->is_virtual = true;
+ else
+ group_s->is_virtual = false;
+ group_s->parent = network_s;
+
+ if (g_slist_append(network_s->groups, group_s))
+ BT_INFO("Mesh: Group created");
+
+ group_list = g_slist_append(group_list, group_s);
+ } else
+ group_s = l->data;
+
+ return group_s;
+}
+
+bt_mesh_appkey_s* _bt_mesh_node_get_appkey(
+ bt_mesh_node_s *node_s, uint16_t appkey_idx)
+{
+ GSList *l;
+
+ l = g_slist_find_custom(node_s->appkeys, GUINT_TO_POINTER(appkey_idx),
+ (GCompareFunc)__compare_appkey_index);
+ if (!l)
+ return NULL;
+
+ return (bt_mesh_appkey_s*) l->data;
+}
+
+static bt_mesh_appkey_s *__bt_mesh_network_is_appkey_added(
+ bt_mesh_network_s *network_s,
+ uint16_t netkey_idx,
+ uint16_t appkey_idx)
+{
+ GSList *l, *l1;
+ const bt_mesh_netkey_s *netkey;
+
+ l = g_slist_find_custom(network_s->netkeys, GUINT_TO_POINTER(netkey_idx),
+ (GCompareFunc)__compare_netkey_index);
+ if (!l)
+ return NULL;
+ netkey = l->data;
+
+ l1 = g_slist_find_custom(netkey->appkeys, GUINT_TO_POINTER(appkey_idx),
+ (GCompareFunc)__compare_appkey_index);
+ if (!l1)
+ return NULL;
+
+ return (bt_mesh_appkey_s*) l1->data;
+}
+
+int __bt_check_mesh_init_status(void)
+{
+ if (is_mesh_initialized != true) {
+ BT_ERR("NOT_INITIALIZED(0x%08x)", BT_ERROR_NOT_INITIALIZED);
+ return BT_ERROR_NOT_INITIALIZED;
+ }
+
+ return BT_ERROR_NONE;
+}
+
+/* Local static */
+static void __bt_mesh_free_models(void *data)
+{
+ bt_mesh_model_s *model = (bt_mesh_model_s*)data;
+ model_list = g_slist_remove(model_list, model);
+ g_free(model);
+}
+
+static void __bt_mesh_free_elements(void *data)
+{
+ bt_mesh_element_s *elem = (bt_mesh_element_s*)data;
+ element_list = g_slist_remove(element_list, elem);
+ g_slist_free_full(elem->models, __bt_mesh_free_models);
+ g_free(elem);
+}
+
+static gint __bt_mesh_compare_net_uuid(gpointer *a, gpointer *b)
+{
+ bt_mesh_network_s *net = (bt_mesh_network_s *)a;
+ char *net_uuid = (char *)b;
+ return g_strcmp0(net->uuid, net_uuid);
+}
+
+
+static void __bt_mesh_insert_elements_in_node(
+ bt_mesh_node_s *node, uint16_t unicast,
+ int num_elements, bool is_local)
+{
+ bt_mesh_element_s *element_s;
+
+ for (int i = 0; i < num_elements; i++) {
+ element_s = g_malloc0(sizeof(bt_mesh_element_s));
+ element_s->is_local = is_local;
+ element_s->parent = node;
+ element_s->index = i;
+ node->elements = g_slist_append(node->elements, element_s);
+ element_list = g_slist_append(element_list, element_s);
+ }
+}
+
+bt_mesh_appkey_s *_bt_mesh_handle_node_appkey_configure(
+ bt_mesh_network_s *network_s,
+ bt_mesh_node_s *node_s, uint16_t netkey_idx,
+ uint16_t appkey_idx,
+ bt_mesh_node_key_configuration_e op)
+{
+ bt_mesh_appkey_s *appkey_s;
+
+ appkey_s = __bt_mesh_network_is_appkey_added(
+ network_s, netkey_idx, appkey_idx);
+
+ /* AppKey with index not found in network */
+ if (!appkey_s) {
+ BT_ERR("Mesh: Exceptional case: AppKey not found in Network");
+ return NULL;
+ }
+
+ if (op == BT_MESH_NODE_KEY_ADD) {
+ if (!g_slist_find_custom(node_s->appkeys,(gconstpointer) appkey_s,
+ (GCompareFunc)__simple_compare)) {
+ node_s->appkeys = g_slist_append(node_s->appkeys, appkey_s);
+ } else
+ BT_INFO("Mesh: AppKey Already added");
+ return appkey_s;
+ } else if (op == BT_MESH_NODE_KEY_DELETE) {
+ node_s->appkeys = g_slist_remove(node_s->appkeys, appkey_s);
+ return NULL;
+ } else /* Node NetKey update */
+ return appkey_s;
+}
+
+bt_mesh_netkey_s *_bt_mesh_handle_node_netkey_configure(
+ bt_mesh_network_s *network_s,
+ bt_mesh_node_s *node_s, uint16_t netkey_idx,
+ bt_mesh_node_key_configuration_e op)
+{
+ bt_mesh_netkey_s *netkey_s;
+
+ netkey_s = __bt_mesh_network_is_netkey_added(network_s, netkey_idx);
+
+ /* Netkey with index not found in network */
+ if (!netkey_s) {
+ BT_ERR("Mesh: Exceptional case: Netkey not found in Network");
+ return NULL;
+ }
+
+ if (op == BT_MESH_NODE_KEY_ADD) {
+ if (!g_slist_find_custom(node_s->netkeys,(gconstpointer) netkey_s,
+ (GCompareFunc)__simple_compare)) {
+ node_s->netkeys = g_slist_append(node_s->netkeys, netkey_s);
+ } else
+ BT_INFO("Mesh: NetKey Already added");
+ return netkey_s;
+ } else if (op == BT_MESH_NODE_KEY_DELETE) {
+ node_s->netkeys = g_slist_remove(node_s->netkeys, netkey_s);
+ return NULL;
+ } else /* Node NetKey update */
+ return netkey_s;
+}
+
+bt_mesh_group_s * _bt_mesh_get_group_from_sub(
+ bt_mesh_network_s *network_s, bt_mesh_model_s *model_s,
+ bt_mesh_model_subscription_op_e op, uint16_t sub_addr)
+{
+ GSList *l;
+ bt_mesh_group_s *group_s = NULL;
+ l = g_slist_find_custom(network_s->groups, GUINT_TO_POINTER(sub_addr),
+ (GCompareFunc) __compare_network_group_address);
+ if (l)
+ group_s = l->data;
+
+ if (op == BT_MESH_MODEL_SUBSCRIPTION_DELETE_ALL)
+ BT_INFO("Mesh: Event for BT_MESH_MODEL_SUBSCRIPTION_DELETE_ALL");
+ if (op == BT_MESH_MODEL_SUBSCRIPTION_ADD)
+ BT_INFO("Mesh: Event for BT_MESH_MODEL_SUBSCRIPTION_ADD");
+ if (op == BT_MESH_MODEL_SUBSCRIPTION_DELETE)
+ BT_INFO("Mesh: Event for BT_MESH_MODEL_SUBSCRIPTION_DELETE");
+ if (op == BT_MESH_MODEL_SUBSCRIPTION_OVERWRITE)
+ BT_INFO("Mesh: Event for BT_MESH_MODEL_SUBSCRIPTION_OVERWRITE");
+
+ return group_s;
+}
+
+bt_mesh_model_s *_bt_mesh_get_node_get_model_from_element(
+ char *net_uuid, uint16_t unicast,
+ int elem_idx, uint32_t model)
+{
+ GSList *l, *l1, *l2, *l3;
+ bt_mesh_network_s *network_s;
+ bt_mesh_node_s *node_s;
+ bt_mesh_element_s *element_s;
+
+ l = g_slist_find_custom(networks, net_uuid,
+ (GCompareFunc)__bt_mesh_compare_net_uuid);
+ if (!l)
+ return NULL;
+
+ network_s = l->data;
+
+ l1 = g_slist_find_custom(network_s->nodes, GUINT_TO_POINTER(unicast),
+ (GCompareFunc)__compare_node_primary_unicast);
+ if (!l1)
+ return NULL;
+
+ node_s = l1->data;
+
+ l2 = g_slist_find_custom(node_s->elements, GUINT_TO_POINTER(elem_idx),
+ (GCompareFunc)__compare_node_element_index);
+ if (!l2)
+ return NULL;
+
+ element_s = (bt_mesh_element_s*) l->data;
+
+
+ l3 = g_slist_find_custom(element_s->models, GUINT_TO_POINTER(model),
+ (GCompareFunc) __compare_model_id);
+ if (!l3)
+ return NULL;
+
+ return (bt_mesh_model_s*) l->data;
+}
+
+bt_mesh_element_s * _bt_mesh_get_node_get_element_from_index(char *net_uuid,
+ uint16_t unicast, int elem_idx)
+{
+ GSList *l, *l1, *l2;
+ bt_mesh_network_s *network_s;
+ bt_mesh_node_s *node_s;
+
+ l = g_slist_find_custom(networks, net_uuid,
+ (GCompareFunc)__bt_mesh_compare_net_uuid);
+ if (!l)
+ return NULL;
+
+ network_s = l->data;
+
+ l1 = g_slist_find_custom(network_s->nodes, GUINT_TO_POINTER(unicast),
+ (GCompareFunc)__compare_node_primary_unicast);
+ if (!l1)
+ return NULL;
+
+ node_s = l1->data;
+
+ l2 = g_slist_find_custom(node_s->elements, GUINT_TO_POINTER(elem_idx),
+ (GCompareFunc)__compare_node_element_index);
+ if (!l2)
+ return NULL;
+
+ return (bt_mesh_element_s*) l->data;
+}
+
+bt_mesh_node_s *_bt_mesh_get_node_from_unicast(char *net_uuid, uint16_t unicast)
+{
+ GSList *l, *l1;
+ bt_mesh_network_s *network_s;
+ bt_mesh_node_s *node_s;
+
+ l = g_slist_find_custom(networks, net_uuid, (GCompareFunc)__bt_mesh_compare_net_uuid);
+ if (!l)
+ return NULL;
+
+ network_s = l->data;
+
+ l1 = g_slist_find_custom(network_s->nodes, GUINT_TO_POINTER(unicast),
+ (GCompareFunc)__compare_node_primary_unicast);
+ if (!l1)
+ return NULL;
+
+ node_s = l1->data;
+ return node_s;
+}
+
+bt_mesh_node_s *_bt_mesh_remote_node_browsed(char *net_uuid, char *dev_uuid,
+ uint16_t unicast, int count)
+{
+ GSList *l, *l1;
+ bt_mesh_network_s *network_s;
+ bt_mesh_node_s *node_s;
+
+ l = g_slist_find_custom(networks, net_uuid, (GCompareFunc)__bt_mesh_compare_net_uuid);
+ if (!l)
+ return NULL;
+
+ network_s = l->data;
+
+ l1 = g_slist_find_custom(network_s->nodes, GUINT_TO_POINTER(unicast),
+ (GCompareFunc)__compare_node_primary_unicast);
+ if (l1) {
+ node_s = l1->data;
+ g_strlcpy(node_s->uuid, dev_uuid, sizeof(node_s->uuid));
+ } else {
+ node_s = g_malloc0(sizeof(bt_mesh_node_s));
+ node_s->parent = network_s;
+ node_s->unicast = unicast;
+ node_s->is_attached = true;
+ if (node_s->unicast == 0x0001) {
+ node_s->is_local = true;
+ node_s->is_provisioner = true;
+ }
+ g_strlcpy(node_s->uuid, dev_uuid, sizeof(node_s->uuid));
+ __bt_mesh_insert_elements_in_node(node_s, unicast,
+ count, node_s->is_local? true : false);
+ network_s->nodes = g_slist_append(network_s->nodes, node_s);
+ node_list = g_slist_append(node_list, node_s);
+ }
+ return node_s;
+}
+
+bt_mesh_network_s * _bt_mesh_get_network_handle_info(char *net_uuid)
+{
+ GSList *l;
+
+ l = g_slist_find_custom(networks, net_uuid, (GCompareFunc)__bt_mesh_compare_net_uuid);
+ if (!l)
+ return NULL;
+
+ return (bt_mesh_network_s*)l->data;
+}
+
+char * _bt_mesh_get_auth_string_from_value(int auth)
+{
+ switch(auth) {
+ case BT_MESH_AUTH_ALPHANUMERIC_DISPLAY:
+ BT_INFO("Mesh: ALPHANUMERIC_DISPLAY");
+ return "ALPHANUMERIC_DISPLAY";
+ case BT_MESH_AUTH_NUMERIC_DISPLAY:
+ BT_INFO("Mesh: NUMERIC_DISPLAY");
+ return "NUMERIC_DISPLAY";
+ case BT_MESH_AUTH_PUSH_COUNT_DISPLAY:
+ BT_INFO("Mesh: PUSH_COUNT_DISPLAY");
+ return "PUSH_COUNT_DISPLAY";
+ case BT_MESH_AUTH_TWIST_COUNT_DISPLAY:
+ BT_INFO("Mesh: TWIST_COUNT_DISPLAY");
+ return "TWIST_COUNT_DISPLAY";
+
+ /*< Input authentication request types */
+ case BT_MESH_AUTH_REQ_ALPHANUMERIC_INPUT:
+ BT_INFO("Mesh: REQ_ALPHANUMERIC_INPUT");
+ return "REQ_ALPHANUMERIC_INPUT";
+ case BT_MESH_AUTH_REQ_NUMERIC_INPUT:
+ BT_INFO("Mesh: REQ_NUMERIC_INPUT");
+ return "REQ_NUMERIC_INPUT";
+ case BT_MESH_AUTH_REQ_BLINK_COUNT_INPUT:
+ BT_INFO("Mesh: REQ_BLINK_COUNT_INPUT");
+ return "REQ_BLINK_COUNT_INPUT";
+ case BT_MESH_AUTH_REQ_BEEP_COUNT_INPUT:
+ BT_INFO("Mesh: REQ_BEEP_COUNT_INPUT");
+ return "REQ_BEEP_COUNT_INPUT";
+ case BT_MESH_AUTH_REQ_VIBRATE_COUNT_INPUT:
+ BT_INFO("Mesh: REQ_VIBRATE_COUNT_INPUT");
+ return "REQ_VIBRATE_COUNT_INPUT";
+
+ /**< OOB Key Inputs */
+ case BT_MESH_AUTH_REQ_OOB_PUBLIC_KEY_INPUT:
+ BT_INFO("Mesh: OOB_PUBLIC_KEY_INPUT");
+ return "OOB_PUBLIC_KEY_INPUT";
+ case BT_MESH_AUTH_REQ_OOB_STATIC_KEY_INPUT:
+ BT_INFO("Mesh: OOB_STATIC_KEY_INPUT");
+ return "OOB_STATIC_KEY_INPUT";
+ default:
+ return "";
+ }
+}
+
+/* Mesh API */
+int bt_mesh_initialize(void)
+{
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+
+ int ret = BT_ERROR_NONE;
+
+ BT_INFO("Is Mesh initialized:[%s]",
+ is_mesh_initialized ? "TRUE": "FALSE");
+
+ if (is_mesh_initialized) {
+ BT_ERR("Mesh is initialized");
+ return BT_ERROR_NONE;
+ }
+
+ if (!is_mesh_initialized) {
+ ret = _bt_get_error_code(bluetooth_mesh_init(
+ _bt_mesh_event_proxy, NULL));
+
+ if (ret != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)",
+ _bt_convert_error_to_string(ret), ret);
+ return BT_ERROR_OPERATION_FAILED;
+ }
+
+ is_mesh_initialized = true;
+ return BT_ERROR_NONE;
+ }
+
+ BT_INFO("Mesh is already initialized");
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_deinitialize(void)
+{
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ int error;
+
+ error = bluetooth_mesh_deinit();
+ error = _bt_get_error_code(error);
+ if (BT_ERROR_NONE != error)
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error), error);
+
+ is_mesh_initialized = false;
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_node_create(bt_mesh_node_features_s *features,
+ bt_mesh_node_h *node_handle)
+{
+ FUNC_ENTRY;
+ bt_mesh_node_s *node = NULL;
+
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(node_handle);
+ BT_CHECK_INPUT_PARAMETER(features);
+
+ node = g_malloc0(sizeof(bt_mesh_node_s));
+ if (!node) {
+ BT_ERR("g_malloc0 failed");
+ return BT_ERROR_OUT_OF_MEMORY;
+ }
+
+ node->is_local = true;
+ node->features = *features;
+ node->unicast = 0x0001;
+
+ node_list = g_slist_append(node_list, node);
+ *node_handle = (bt_mesh_node_h)node;
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_node_destroy(bt_mesh_node_h node_handle)
+{
+ FUNC_ENTRY;
+
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(node_handle);
+
+ bt_mesh_node_s *node = (bt_mesh_node_s*)node_handle;
+
+ BT_MESH_VALIDATE_HANDLE(node, node_list);
+
+ /* It is NOT allowed to destroy attached node: Do Reset */
+ BT_CHECK_MESH_IS_ATTACHED(node);
+
+ node_list = g_slist_remove(node_list, node);
+ g_slist_free_full(node->elements, __bt_mesh_free_elements);
+ g_free(node);
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+static void __bt_mesh_generate_element(bt_mesh_node_s *node_s,
+ bt_mesh_element_s *elem_s)
+{
+ GSList *l;
+ uint16_t index = 0;
+
+ for (l = node_s->elements; l; l = l->next) {
+ bt_mesh_element_s *el = (bt_mesh_element_s*)l->data;
+ if (el->index != index)
+ break;
+ index++;
+ }
+ elem_s->index = index;
+ node_s->elements = g_slist_insert(node_s->elements, elem_s, index);
+}
+
+int bt_mesh_node_create_element(bt_mesh_node_h node_handle,
+ bt_mesh_element_h *element_handle)
+{
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(node_handle);
+ BT_CHECK_INPUT_PARAMETER(element_handle);
+
+ bt_mesh_node_s *node = (bt_mesh_node_s*)node_handle;
+ bt_mesh_element_s *element = NULL;
+
+ BT_INFO("Mesh: Element creation request");
+ BT_MESH_VALIDATE_HANDLE(node, node_list);
+
+ /* It is NOT allowed to add an element to a already attached node */
+ BT_CHECK_MESH_IS_ATTACHED(node);
+
+ /* Check num elements already present in the node */
+ if (g_slist_length(node->elements) >= BT_MESH_MAX_ELEMENTS)
+ return BT_ERROR_QUOTA_EXCEEDED;
+
+
+ element = g_malloc0(sizeof(bt_mesh_element_s));
+ if (!element) {
+ BT_ERR("g_malloc0 failed");
+ return BT_ERROR_OUT_OF_MEMORY;
+ }
+
+ element->is_local = true;
+ element->parent = node;
+
+ __bt_mesh_generate_element(node, element);
+ element_list = g_slist_append(element_list, element);
+ *element_handle = (bt_mesh_element_h)element;
+
+ BT_INFO("Mesh: Element created successfully: element index [%d]", element->index);
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_element_destroy(bt_mesh_element_h element_handle)
+{
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(element_handle);
+ BT_MESH_VALIDATE_HANDLE(element_handle, element_list);
+
+ bt_mesh_node_s *node = (bt_mesh_node_s*)((bt_mesh_element_s*)element_handle)->parent;
+ bt_mesh_element_s *element = (bt_mesh_element_s*)element_handle;
+
+ /* It is NOT allowed to destroy remote element */
+ BT_CHECK_MESH_LOCAL(node);
+
+ /* It is NOT allowed to destroy an attahced element */
+ BT_CHECK_MESH_IS_ATTACHED(node);
+
+ element_list = g_slist_remove(element_list, element);
+ node->elements = g_slist_remove(node->elements, element);
+
+ g_slist_free_full(element->models, __bt_mesh_free_models);
+ g_free(element);
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_element_create_model(
+ bt_mesh_element_h element_handle,
+ bt_mesh_model_id_s *model_id,
+ bt_mesh_model_h *model_handle)
+{
+ FUNC_ENTRY;
+ uint32_t mod_id;
+ bt_mesh_element_s *element = (bt_mesh_element_s*)element_handle;
+ bt_mesh_model_s *model = NULL;
+
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(element_handle);
+ BT_CHECK_INPUT_PARAMETER(model_id);
+ BT_CHECK_INPUT_PARAMETER(model_handle);
+ BT_MESH_VALIDATE_HANDLE(element_handle, element_list);
+
+ bt_mesh_node_s *node = (bt_mesh_node_s*)((bt_mesh_element_s*)element_handle)->parent;
+
+ /* It is NOT allowed to add model to a remote element */
+ BT_CHECK_MESH_LOCAL(node);
+
+ /* It is NOT allowed to add a Model to a already attached node */
+ BT_CHECK_MESH_IS_ATTACHED(node);
+
+ BT_INFO("Mesh: Model creation request: Company ID [0x%2.2x] Model ID [0x%2.2x]",
+ model_id->company_id, model_id->model_id);
+
+ mod_id = model_id->company_id;
+ mod_id <<= 16;
+ mod_id |= model_id->model_id;
+ /* Allow configuration server model only in primary element */
+ if ((model_id->model_id == BT_MESH_MODEL_ID_CFG_SRV) &&
+ element->index != 0)
+ return BT_ERROR_OPERATION_FAILED;
+
+ /* Check num models already present in the element */
+ if (g_slist_length(element->models) >= BT_MESH_MAX_MODELS)
+ return BT_ERROR_QUOTA_EXCEEDED;
+
+ /* Don't allow multiple instance of same model in an element */
+ if (g_slist_find_custom(element->models, GUINT_TO_POINTER(mod_id),
+ (GCompareFunc)__compare_model_id))
+ return BT_ERROR_ALREADY_DONE;
+
+ model = g_malloc0(sizeof(bt_mesh_model_s));
+ if (!model) {
+ BT_ERR("g_malloc0 failed");
+ return BT_ERROR_OUT_OF_MEMORY;
+ }
+
+ model->is_local = true;
+ model->parent = element;
+ model->id = mod_id;
+
+ BT_INFO("Mesh: Model ID [0x%2.2x]", model_id->model_id);
+ BT_INFO("Mesh: Company ID [0x%2.2x]", model_id->company_id);
+ BT_INFO("Mesh: MOD [0x%4.4x]", model->id);
+
+ model_list = g_slist_append(model_list, model);
+ element->models = g_slist_append(element->models, model);
+ *model_handle = (bt_mesh_model_h)model;
+
+ BT_INFO("Mesh: Model created successfully");
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_model_destroy(bt_mesh_model_h model_handle)
+{
+ FUNC_ENTRY;
+
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(model_handle);
+
+ bt_mesh_node_s *node = (bt_mesh_node_s*)((bt_mesh_element_s*)((bt_mesh_model_s*)model_handle)->parent)->parent;
+ bt_mesh_model_s *model = (bt_mesh_model_s*)model_handle;
+ bt_mesh_element_s *element = model->parent;
+
+ BT_MESH_VALIDATE_HANDLE(model, model_list);
+ BT_MESH_VALIDATE_HANDLE(element, element_list);
+
+ /* It is NOT allowed to destroy remote model */
+ BT_CHECK_MESH_LOCAL(node);
+
+ /* It is NOT allowed to destroy an attahced model */
+ BT_CHECK_MESH_IS_ATTACHED(node);
+
+ model_list = g_slist_remove(model_list, model);
+ element->models = g_slist_remove(element->models, model);
+ g_free(model);
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_model_get_id(bt_mesh_model_h model_handle,
+ bt_mesh_model_id_s *model_id)
+{
+ FUNC_ENTRY;
+
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(model_handle);
+ BT_CHECK_INPUT_PARAMETER(model_id);
+
+ bt_mesh_model_s *model = (bt_mesh_model_s*)model_handle;
+ BT_MESH_VALIDATE_HANDLE(model, model_list);
+
+ BT_INFO("Mesh: Model ID [0x%4.4x]", model->id);
+ model_id->company_id = model->id >> 16;
+ model_id->model_id = model->id;
+ BT_INFO("Mesh: CID [0x%2.2x]", model_id->company_id);
+ BT_INFO("Mesh: MID [0x%2.2x]", model_id->model_id);
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_node_get_network(bt_mesh_node_h node_handle, bt_mesh_network_h *network)
+{
+ FUNC_ENTRY;
+
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(node_handle);
+ BT_CHECK_INPUT_PARAMETER(network);
+
+ bt_mesh_node_s *node = (bt_mesh_node_s*)node_handle;
+ BT_MESH_VALIDATE_HANDLE(node_handle, node_list);
+
+ *network = node->parent;
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_element_get_node(bt_mesh_element_h element_handle,
+ bt_mesh_node_h *node)
+{
+ FUNC_ENTRY;
+
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(element_handle);
+ BT_CHECK_INPUT_PARAMETER(node);
+
+ bt_mesh_element_s *element = (bt_mesh_element_s*)element_handle;
+ BT_MESH_VALIDATE_HANDLE(element, element_list);
+
+ *node = element->parent;
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_model_get_element(bt_mesh_model_h model_handle,
+ bt_mesh_element_h *element)
+{
+ FUNC_ENTRY;
+
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(model_handle);
+ BT_CHECK_INPUT_PARAMETER(element);
+
+ bt_mesh_model_s *model = (bt_mesh_model_s*)model_handle;
+ BT_MESH_VALIDATE_HANDLE(model, model_list);
+
+ *element = model->parent;
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_appkey_get_netkey(bt_mesh_appkey_h appkey_handle,
+ bt_mesh_netkey_h *netkey)
+{
+ FUNC_ENTRY;
+
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(appkey_handle);
+ BT_CHECK_INPUT_PARAMETER(netkey);
+
+ bt_mesh_appkey_s *appkey = (bt_mesh_appkey_s*)appkey_handle;
+ BT_MESH_VALIDATE_HANDLE(appkey, appkey_list);
+
+ *netkey = appkey->parent;
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+/* Async API's to bt-service & stack */
+int bt_mesh_network_create(bt_mesh_node_h config_client,
+ const char *network_name,
+ bt_mesh_network_h *network, char **token)
+{
+ FUNC_ENTRY;
+ int error_code = BT_ERROR_NONE;
+ GSList *l1, *l2;
+ int i, j;
+ int offset = 0;
+ int num_models = 0;
+ bluetooth_mesh_network_t net;
+ bluetooth_mesh_node_t param_node;
+ bluetooth_mesh_model_t **param_model;
+ bt_mesh_network_s *network_s;
+ bt_mesh_netkey_s *netkey_s;
+
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(config_client);
+ BT_CHECK_INPUT_PARAMETER(network_name);
+ BT_CHECK_INPUT_PARAMETER(network);
+ BT_CHECK_INPUT_PARAMETER(token);
+
+ BT_INFO("Mesh: Create Network: Name [%s]", network_name);
+ bt_mesh_node_s *node = (bt_mesh_node_s*)config_client;
+
+ BT_MESH_VALIDATE_HANDLE(node, node_list);
+
+ /* Error if remote node*/
+ BT_CHECK_MESH_LOCAL(node);
+
+ /* It is NOT allowed to create network out of a already attahced node */
+ BT_CHECK_MESH_IS_ATTACHED(node);
+
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ if (strlen(network_name) >= BT_MESH_NETWORK_NAME_STRING_MAX_LEN)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ /* Node in network should contain at-least one element */
+ if (!g_slist_length(node->elements)) {
+ BT_INFO("Mesh: No element present in Node: NOT ALLOWED!!");
+ return BT_ERROR_INVALID_PARAMETER;
+ }
+
+ /* Element in Node should contain at-least one Model */
+ for (l1 = node->elements; l1 != NULL; l1 = l1->next) {
+ bt_mesh_element_s *el = l1->data;
+ int models = 0;
+ models = g_slist_length(el->models);
+ BT_INFO("Mesh: Num models element [%u] has is [%d]", el->index, models);
+ if (!models) {
+ BT_INFO("Mesh: No Model present in element: NOT ALLOWED!!");
+ return BT_ERROR_INVALID_PARAMETER;
+ }
+ /* If Primary element does not contain CFG SRV model, create and append */
+ if (el->index == 0x0000) {
+ uint32_t mod_id = 0xFFFF0000; /* CFG SRV */
+
+ if (!g_slist_find_custom(el->models, GUINT_TO_POINTER(mod_id),
+ (GCompareFunc)__compare_model_id)) {
+ bt_mesh_model_s *model_s;
+ BT_ERR("Mesh: Primary element does not contain CFG SRV Model:Add it!");
+ model_s = g_malloc0(sizeof(bt_mesh_model_s));
+
+ model_s->is_local = true;
+ model_s->parent = el;
+ model_s->id = mod_id;
+
+ model_list = g_slist_append(model_list, model_s);
+ el->models = g_slist_append(el->models, model_s);
+ num_models++;
+ } else
+ BT_INFO("Mesh: CFG SRV model is already added in primary element");
+ }
+ num_models += models;
+ }
+
+ /* Check currently created network */
+ if (g_slist_length(networks) >= BT_MESH_MAX_NETWORKS)
+ return BT_ERROR_QUOTA_EXCEEDED;
+
+ memset(¶m_node, 0x00, sizeof(bluetooth_mesh_node_t));
+ memcpy(¶m_node.vendor_info, &(node->features), sizeof(node->features));
+ param_node.num_elements = g_slist_length(node->elements);
+ param_node.primary_unicast = 0x0001;
+ _bt_get_random_bytes(param_node.uuid, 16);
+
+ BT_INFO("Mesh: Total Models [%d]", num_models);
+ param_model = (bluetooth_mesh_model_t**)g_malloc0(num_models * sizeof(bluetooth_mesh_model_t*));
+
+ for (l1 = node->elements, i = 0; l1 != NULL; l1 = l1->next, i++) {
+ bt_mesh_element_s *e = l1->data;
+
+ for (l2 = e->models, j = 0; l2 != NULL; l2 = l2->next, j++) {
+ bt_mesh_model_s *m = l2->data;
+ param_model[j+offset] = g_malloc0(sizeof(bluetooth_mesh_model_t));
+ param_model[j+offset]->elem_index = i;
+ param_model[j+offset]->model_id = m->id;
+
+ }
+ offset += g_slist_length(e->models);
+ }
+
+ BT_INFO("Mesh: Send Network create Request to FRWK");
+ error_code = _bt_get_error_code(bluetooth_mesh_network_create(network_name, ¶m_node,
+ num_models, param_model, &net));
+ if (error_code != BT_ERROR_NONE) {
+ BT_INFO("Mesh: Network could not be created!!");
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+
+ /* Cleanup */
+ for (int i = 0; i < num_models; i++)
+ g_free(param_model[i]);
+
+ return error_code;
+ }
+
+ BT_INFO("Mesh: Network created successfully");
+
+ /* Create Network object & fill data in network */
+ network_s = g_malloc0(sizeof(bt_mesh_network_s));
+ network_s->num_nodes = 1;
+ network_s->is_local = true;
+ network_s->is_discovered = true;
+
+ /* Fill network name, token & UUID */
+ __bt_mesh_util_convert_hex_to_string((uint8_t *)param_node.uuid, 16,
+ network_s->uuid, sizeof(network_s->uuid));
+ g_strlcpy(network_s->token, net.token.token, 17);
+ g_strlcpy(network_s->name, network_name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+ network_s->nodes = g_slist_append(network_s->nodes, node);
+ BT_INFO("Mesh: Network Name [%s]", network_s->name);
+ BT_INFO("Mesh: Network Token[%s]", network_s->token);
+ BT_INFO("Mesh: Network UUID [%s]", network_s->uuid);
+
+ /* Create primary Netkey object */
+ netkey_s = g_malloc0(sizeof(bt_mesh_netkey_s));
+ netkey_s->parent = network_s;
+ netkey_s->netkey_index = 0x0000; /* Primary index */
+ network_s->netkeys = g_slist_append(network_s->netkeys, netkey_s);
+ netkey_list = g_slist_append(netkey_list, netkey_s);
+
+ /* Fill Config Client Node Data */
+ node->is_attached = true;
+ node->is_provisioner = true;
+ __bt_mesh_util_convert_hex_to_string((uint8_t *)param_node.uuid,
+ 16, node->uuid, sizeof(node->uuid));
+ node->unicast = 0x0001;
+ node->parent = network_s;
+
+ /* Prepare Out parameters */
+ *token = network_s->token;
+ *network = (bt_mesh_network_h)network_s;
+
+ /* Save network in list */
+ networks = g_slist_append(networks, network_s);
+
+ /* Clean up memory */
+ for (int i = 0; i < num_models; i++)
+ g_free(param_model[i]);
+
+ FUNC_EXIT;
+ return error_code;
+}
+
+int bt_mesh_network_load(const char *token, bt_mesh_network_h *network)
+{
+ int error_code = BT_ERROR_NONE;
+ bluetooth_mesh_network_t net;
+ bt_mesh_network_s *network_s;
+
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(token);
+ BT_CHECK_INPUT_PARAMETER(network);
+
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+ error_code = _bt_get_error_code(bluetooth_mesh_network_load(token, &net));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ /* Create Network object */
+ network_s = g_malloc0(sizeof(bt_mesh_network_s));
+ network_s->is_local = true;
+ g_strlcpy(network_s->uuid, net.uuid, 33);
+ g_strlcpy(network_s->token, token, 17);
+ g_strlcpy(network_s->name, net.name.name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+ networks = g_slist_append(networks, network_s);
+
+ FUNC_EXIT;
+ return error_code;
+}
+
+int bt_mesh_network_get_name(bt_mesh_network_h network, char **network_name)
+{
+ bt_mesh_network_s *network_s;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(network);
+ BT_CHECK_INPUT_PARAMETER(network_name);
+
+ BT_MESH_VALIDATE_HANDLE(network, networks);
+
+ network_s = (bt_mesh_network_s*)network;
+ *network_name = strdup(network_s->name);
+ if (*network_name == NULL) {
+ BT_ERR("OUT_OF_MEMORY(0x%08x)",
+ BT_ERROR_OUT_OF_MEMORY);
+ return BT_ERROR_OUT_OF_MEMORY;
+ }
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_network_set_name(bt_mesh_network_h network, const char *network_name)
+{
+ int error_code = BT_ERROR_NONE;
+ bluetooth_mesh_network_t net;
+ bt_mesh_network_s* network_s;
+ FUNC_ENTRY;
+
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(network);
+ BT_CHECK_INPUT_PARAMETER(network_name);
+
+ network_s = (bt_mesh_network_s*)network;
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ BT_INFO("Mesh: Set Network Name [%s]", network_name);
+ error_code = _bt_get_error_code(bluetooth_mesh_network_set_name(&net));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ BT_INFO("Mesh: Network Name set successfully [%s]", network_name);
+ g_strlcpy(network_s->name, network_name, sizeof(network_s->name));
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_network_add_netkey(bt_mesh_network_h network,
+ bt_mesh_netkey_h *netkey)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_network_s *network_s;
+ bt_mesh_netkey_s *netkey_s;
+ bluetooth_mesh_network_t net;
+ uint16_t netkey_idx;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(network);
+ BT_CHECK_INPUT_PARAMETER(netkey);
+
+ BT_MESH_VALIDATE_HANDLE(network, networks);
+
+ network_s = (bt_mesh_network_s*)network;
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_add_netkey(&net, &netkey_idx));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ BT_INFO("Mesh: Subnet Key created: Index [%d]", netkey_idx);
+ /* Create Netkey object */
+ netkey_s = g_malloc0(sizeof(bt_mesh_netkey_s));
+ netkey_s->parent = network_s;
+ netkey_s->netkey_index = netkey_idx;
+ network_s->netkeys = g_slist_append(network_s->netkeys, netkey_s);
+ netkey_list = g_slist_append(netkey_list, netkey_s);
+ *netkey = (bt_mesh_netkey_h)netkey_s;
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_network_foreach_netkeys(bt_mesh_network_h network,
+ bt_mesh_network_netkey_info_cb callback, void *user_data)
+{
+ bluetooth_mesh_network_t net;
+ GPtrArray *netkeys = NULL;
+ GSList *l;
+ int error_code = BT_ERROR_NONE;
+ uint16_t *netkey_idx = NULL;
+ int i;
+ int total;
+ bt_mesh_network_s *network_s;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(network);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ BT_MESH_VALIDATE_HANDLE(network, networks);
+
+ netkeys = g_ptr_array_new();
+ if (netkeys == NULL) {
+ BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY);
+ return BT_ERROR_OUT_OF_MEMORY;
+ }
+
+ network_s = (bt_mesh_network_s*)network;
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_get_all_netkey(&net, &netkeys));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ g_ptr_array_free(netkeys, TRUE);
+ return error_code;
+ }
+
+ for (i = 0; i < netkeys->len; i++) {
+ netkey_idx = g_ptr_array_index(netkeys, i);
+ if (netkey_idx) {
+ /* Create and insert netkey object in list */
+ if (!__bt_mesh_network_is_netkey_added(network_s, *netkey_idx)) {
+ bt_mesh_netkey_s *nk;
+ nk = g_malloc0(sizeof(bt_mesh_netkey_s));
+ nk->parent = network_s;
+ nk->netkey_index = *netkey_idx;
+ network_s->netkeys = g_slist_append(network_s->netkeys, nk);
+ netkey_list = g_slist_append(netkey_list, nk);
+ }
+
+ } else {
+ BT_ERR("Mesh: OPERATION_FAILED(0x%08x)",
+ BT_ERROR_OPERATION_FAILED);
+ error_code = BT_ERROR_OPERATION_FAILED;
+ break;
+ }
+ }
+
+ total = g_slist_length(network_s->netkeys);
+ if (total == 0) {
+ BT_INFO("Mesh: No netkey added in network");
+ callback(BT_ERROR_NONE, (bt_mesh_network_h)network_s, total,
+ NULL, 0xFFFF, user_data);
+ }
+ for (l = network_s->netkeys; l != NULL; l = g_slist_next(l)) {
+ bt_mesh_netkey_s *netkey;
+ netkey = l->data;
+
+ if (!callback(BT_ERROR_NONE, (bt_mesh_network_h)network_s, total,
+ (bt_mesh_netkey_h) netkey,
+ netkey->netkey_index, user_data)) {
+ break;
+ }
+ }
+
+ g_ptr_array_foreach(netkeys, (GFunc)g_free, NULL);
+ g_ptr_array_free(netkeys, TRUE);
+
+ FUNC_EXIT;
+ return error_code;
+}
+
+int bt_mesh_netkey_get_index(bt_mesh_netkey_h netkey, uint16_t *index)
+{
+ bt_mesh_netkey_s *netkey_s;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(netkey);
+ BT_CHECK_INPUT_PARAMETER(index);
+
+ BT_MESH_VALIDATE_HANDLE(netkey, netkey_list);
+
+ netkey_s = (bt_mesh_netkey_s*)netkey;
+ *index = netkey_s->netkey_index;
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_netkey_update(bt_mesh_netkey_h netkey)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_network_s *network_s;
+ bt_mesh_netkey_s *netkey_s;
+ bluetooth_mesh_network_t net;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(netkey);
+
+ netkey_s = (bt_mesh_netkey_s*)netkey;
+ network_s = netkey_s->parent;
+
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+ BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list);
+
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_update_netkey(
+ &net, netkey_s->netkey_index));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_netkey_delete(bt_mesh_netkey_h netkey)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_network_s *network_s;
+ bt_mesh_netkey_s *netkey_s;
+ bluetooth_mesh_network_t net;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(netkey);
+
+ netkey_s = (bt_mesh_netkey_s*)netkey;
+ network_s = netkey_s->parent;
+
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+ BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list);
+
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_delete_netkey(&net, netkey_s->netkey_index));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ network_s->netkeys = g_slist_remove(network_s->netkeys, netkey_s);
+ netkey_list = g_slist_remove(netkey_list, netkey_s);
+ g_slist_free_full(netkey_s->appkeys, g_free);
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_netkey_add_appkey(bt_mesh_netkey_h netkey,
+ bt_mesh_appkey_h *appkey)
+{
+ int error_code = BT_ERROR_NONE;
+ uint16_t appkey_idx;
+ bt_mesh_network_s *network_s;
+ bt_mesh_netkey_s *netkey_s;
+ bt_mesh_appkey_s *appkey_s;
+ bluetooth_mesh_network_t net;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(netkey);
+ BT_CHECK_INPUT_PARAMETER(appkey);
+
+ netkey_s = (bt_mesh_netkey_s*)netkey;
+ network_s = netkey_s->parent;
+
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+ BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list);
+
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_add_appkey(
+ &net, netkey_s->netkey_index, &appkey_idx));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ /* Create Appkey object */
+ appkey_s = g_malloc0(sizeof(bt_mesh_appkey_s));
+ appkey_s->parent = netkey_s;
+ appkey_s->appkey_index = appkey_idx;
+ netkey_s->appkeys = g_slist_append(netkey_s->appkeys, appkey_s);
+ appkey_list = g_slist_append(appkey_list, appkey_s);
+ *appkey = (bt_mesh_appkey_h)appkey_s;
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_appkey_update(bt_mesh_appkey_h appkey)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_network_s *network_s;
+ bt_mesh_netkey_s *netkey_s;
+ bt_mesh_appkey_s *appkey_s;
+ bluetooth_mesh_network_t net;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(appkey);
+
+ appkey_s = (bt_mesh_appkey_s*)appkey;
+ netkey_s = appkey_s->parent;
+ network_s = netkey_s->parent;
+
+ BT_MESH_VALIDATE_HANDLE(appkey_s, appkey_list);
+
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_update_appkey(
+ &net, netkey_s->netkey_index, appkey_s->appkey_index));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_appkey_delete(bt_mesh_appkey_h appkey)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_network_s *network_s;
+ bt_mesh_netkey_s *netkey_s;
+ bt_mesh_appkey_s *appkey_s;
+ bluetooth_mesh_network_t net;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(appkey);
+
+ appkey_s = (bt_mesh_appkey_s*)appkey;
+ netkey_s = appkey_s->parent;
+ network_s = netkey_s->parent;
+
+ BT_MESH_VALIDATE_HANDLE(appkey_s, appkey_list);
+
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_delete_appkey(
+ &net, netkey_s->netkey_index, appkey_s->appkey_index));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ /* Delete Appkey Object */
+ netkey_s->appkeys = g_slist_remove(netkey_s->appkeys, appkey_s);
+ appkey_list = g_slist_remove(appkey_list, appkey_s);
+ g_free(appkey_s);
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_netkey_foreach_appkeys(bt_mesh_netkey_h netkey,
+ bt_mesh_appkey_info_cb callback, void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_netkey_s *netkey_s;
+ bt_mesh_network_s *network_s;
+ bluetooth_mesh_network_t net;
+ int total;
+ int i;
+ GSList *l;
+ GPtrArray *appkeys = NULL;
+ uint16_t *appkey_idx = NULL;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(netkey);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ BT_MESH_VALIDATE_HANDLE(netkey, netkey_list);
+
+ netkey_s = (bt_mesh_netkey_s*)netkey;
+ network_s = netkey_s->parent;
+
+ appkeys = g_ptr_array_new();
+ if (appkeys == NULL) {
+ BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY);
+ return BT_ERROR_OUT_OF_MEMORY;
+ }
+
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ BT_INFO("Mesh: Find all Appkeys for Netkey : index [%d]", netkey_s->netkey_index);
+ error_code = _bt_get_error_code(bluetooth_mesh_netkey_get_all_appkey(
+ &net, netkey_s->netkey_index, &appkeys));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ g_ptr_array_free(appkeys, TRUE);
+ return error_code;
+ }
+ for (i = 0; i < appkeys->len; i++) {
+ appkey_idx = g_ptr_array_index(appkeys, i);
+ if (appkey_idx) {
+ /* Create and insert netkey object in list */
+ if (!__bt_mesh_network_is_appkey_added(network_s, netkey_s->netkey_index, *appkey_idx)) {
+ bt_mesh_appkey_s *key;
+ key = g_malloc0(sizeof(bt_mesh_appkey_s));
+ key->parent = netkey_s;
+ key->appkey_index = *appkey_idx;
+ netkey_s->appkeys = g_slist_append(netkey_s->appkeys, key);
+ appkey_list = g_slist_append(appkey_list, key);
+ }
+
+ } else {
+ BT_ERR("Mesh: OPERATION_FAILED(0x%08x)",
+ BT_ERROR_OPERATION_FAILED);
+ error_code = BT_ERROR_OPERATION_FAILED;
+ break;
+ }
+ }
+
+ total = g_slist_length(netkey_s->appkeys);
+ BT_INFO("Mesh: Total appkeys [%d]", total);
+
+ if (!total) {
+ BT_INFO("Mesh: No AppKey added in NetKey yet!");
+ callback(BT_ERROR_NONE, (bt_mesh_network_h) network_s, total,
+ (bt_mesh_netkey_h) netkey_s, NULL,
+ 0xFFFF, user_data);
+ return BT_ERROR_NONE;
+ }
+
+
+ for (l = netkey_s->appkeys; l; l = g_slist_next(l)) {
+ bt_mesh_appkey_s *appkey_s;
+ appkey_s = l->data;
+ if (!callback(BT_ERROR_NONE, (bt_mesh_network_h) network_s, total,
+ (bt_mesh_netkey_h) netkey_s, (bt_mesh_appkey_h) appkey_s,
+ appkey_s->appkey_index, user_data))
+ break;
+ }
+
+ g_ptr_array_foreach(appkeys, (GFunc)g_free, NULL);
+ g_ptr_array_free(appkeys, TRUE);
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_appkey_get_index(bt_mesh_appkey_h appkey, uint16_t *index)
+{
+ bt_mesh_appkey_s *appkey_s;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(appkey);
+ BT_CHECK_INPUT_PARAMETER(index);
+
+ BT_MESH_VALIDATE_HANDLE(appkey, appkey_list);
+
+ appkey_s = (bt_mesh_appkey_s*)appkey;
+ *index = appkey_s->appkey_index;
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+/* Sync API's to bt-service: Discovery API's */
+int bt_mesh_network_foreach_devices(bt_mesh_network_h network,
+ bt_mesh_network_device_info_cb callback, void *user_data)
+{
+ bluetooth_mesh_network_t net;
+ bluetooth_mesh_node_info_t *node_info;
+ GPtrArray *nodes = NULL;
+ int error_code = BT_ERROR_NONE;
+ int i;
+ bt_mesh_network_s *network_s;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(network);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ BT_MESH_VALIDATE_HANDLE(network, networks);
+
+ nodes = g_ptr_array_new();
+ if (nodes == NULL) {
+ BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY);
+ return BT_ERROR_OUT_OF_MEMORY;
+ }
+
+ network_s = (bt_mesh_network_s*)network;
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_get_all_nodes(&net, &nodes));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ g_ptr_array_free(nodes, TRUE);
+ return error_code;
+ }
+
+ BT_INFO("Mesh: Total number of Devices found [%d]", nodes->len);
+ for (i = 0; i < nodes->len; i++) {
+ node_info = g_ptr_array_index(nodes, i);
+ if (node_info) {
+ if (!callback(BT_ERROR_NONE, (bt_mesh_network_h)network_s, nodes->len,
+ node_info->dev_uuid, node_info->primary_unicast, user_data)) {
+ break;
+ }
+ } else {
+ BT_ERR("Mesh: OPERATION_FAILED(0x%08x)",
+ BT_ERROR_OPERATION_FAILED);
+ error_code = BT_ERROR_OPERATION_FAILED;
+ break;
+ }
+ }
+
+ g_ptr_array_foreach(nodes, (GFunc)g_free, NULL);
+ g_ptr_array_free(nodes, TRUE);
+
+ FUNC_EXIT;
+ return error_code;
+}
+
+int bt_mesh_node_get_primary_address(bt_mesh_node_h node,
+ uint16_t *primary_address)
+{
+ bt_mesh_node_s *node_s;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(node);
+ BT_CHECK_INPUT_PARAMETER(primary_address);
+
+ BT_MESH_VALIDATE_HANDLE(node, node_list);
+
+ node_s = (bt_mesh_node_s*) node;
+ *primary_address = node_s->unicast;
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_node_foreach_element(bt_mesh_node_h node,
+ bt_mesh_node_element_info_cb callback, void *user_data)
+{
+ bt_mesh_node_s *node_s;
+ int total = 0;
+ GSList *l;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(node);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ BT_MESH_VALIDATE_HANDLE(node, node_list);
+ node_s = (bt_mesh_node_s*) node;
+
+ /* Only for Node which is attached to the Network */
+#if 0
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+#endif
+ total = g_slist_length(node_s->elements);
+ if (!total) {
+ callback(BT_ERROR_NONE, (bt_mesh_node_h) node, total,
+ (bt_mesh_element_h) NULL, -1, 0xFFFF, user_data);
+
+ }
+
+ for (l = node_s->elements; l; l = g_slist_next(l)) {
+ bt_mesh_element_s *element_s;
+ element_s = l->data;
+ if (!callback(BT_ERROR_NONE, (bt_mesh_node_h) node, total,
+ (bt_mesh_element_h)element_s, element_s->index,
+ (node_s->unicast + element_s->index), user_data))
+ break;
+ }
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_element_foreach_models(bt_mesh_element_h element,
+ bt_mesh_element_model_info_cb callback, void *user_data)
+{
+ bluetooth_mesh_network_t net;
+ bt_mesh_network_s *network_s;
+ bt_mesh_node_s *node_s;
+ bt_mesh_element_s *element_s;
+
+ GPtrArray *models = NULL;
+ uint32_t *model_info;
+ int error_code = BT_ERROR_NONE;
+ int i;
+ int total;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(element);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ BT_MESH_VALIDATE_HANDLE(element, element_list);
+
+ element_s = (bt_mesh_element_s*) element;
+ node_s = (bt_mesh_node_s*) element_s->parent;
+ network_s = (bt_mesh_network_s*) node_s->parent;
+
+ /* Only for local Node */
+ if (node_s->is_local) {
+ GSList *l;
+ BT_INFO("Mesh: Local element");
+
+ total = g_slist_length(element_s->models);
+ if (!total)
+ callback(BT_ERROR_NONE, (bt_mesh_element_h)element_s, 0,
+ (bt_mesh_model_h) NULL, NULL, user_data);
+
+ for (l = element_s->models; l; l = l->next) {
+ bt_mesh_model_s *model_s = l->data;
+ bt_mesh_model_id_s modid;
+
+ modid.company_id = model_s->id >> 16;
+ modid.model_id = model_s->id;
+
+ if (!callback(BT_ERROR_NONE, (bt_mesh_element_h)element_s, total,
+ (bt_mesh_model_h) model_s,
+ &modid, user_data)) {
+ break;
+ }
+ }
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+ }
+
+ models = g_ptr_array_new();
+ if (models == NULL) {
+ BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY);
+ return BT_ERROR_OUT_OF_MEMORY;
+ }
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_element_get_all_models(&net,
+ /* Node identity */node_s->unicast,
+ /* eleement identity */element_s->index,
+ /*Output*/ &models));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ g_ptr_array_free(models, TRUE);
+ return error_code;
+ }
+
+ total = models->len;
+ for (i = 0; i < models->len; i++) {
+ model_info = g_ptr_array_index(models, i);
+ if (model_info) {
+ /* Create and insert model object in list */
+ bt_mesh_model_s *mod;
+ bt_mesh_model_id_s modid;
+ mod = g_malloc0(sizeof(bt_mesh_model_s));
+ mod->parent = element_s;
+ if (node_s->unicast == 0x0001) {
+ mod->is_local = true;
+ }
+ mod->id = *model_info;
+ element_s->models = g_slist_append(element_s->models, mod);
+ model_list = g_slist_append(model_list, mod);
+
+ modid.company_id = *model_info >> 16;
+ modid.model_id = *model_info;
+ /* Send Callback */
+ if (!callback(BT_ERROR_NONE, (bt_mesh_element_h)element_s, total,
+ (bt_mesh_model_h) mod,
+ &modid, user_data)) {
+ break;
+ }
+ } else {
+ BT_ERR("Mesh: OPERATION_FAILED(0x%08x)",
+ BT_ERROR_OPERATION_FAILED);
+ error_code = BT_ERROR_OPERATION_FAILED;
+ break;
+ }
+ }
+
+ g_ptr_array_foreach(models, (GFunc)g_free, NULL);
+ g_ptr_array_free(models, TRUE);
+
+ FUNC_EXIT;
+ return error_code;
+}
+
+/* Provisioning & capabilities related*/
+int bt_mesh_network_unprovisioned_device_scan(bt_mesh_network_h network,
+ bt_mesh_scan_params_s *scan_params,
+ bt_mesh_network_scan_unprovisioned_device_result_cb callback,
+ void *user_data)
+{
+ bt_mesh_network_s *network_s;
+ bluetooth_mesh_network_t net;
+ int error_code = BT_ERROR_NONE;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(network);
+ BT_CHECK_INPUT_PARAMETER(scan_params);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ BT_MESH_VALIDATE_HANDLE(network, networks);
+
+ network_s = (bt_mesh_network_s*)network;
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_scan(
+ &net, (bluetooth_mesh_scan_param_t*) scan_params));
+
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ _bt_set_cb(BT_EVENT_MESH_NETWORK_SCAN_STATE_CHANGED, callback, user_data);
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_stop_unprovisioned_device_scan(bt_mesh_network_h network)
+{
+ bt_mesh_network_s *network_s;
+ bluetooth_mesh_network_t net;
+ int error_code = BT_ERROR_NONE;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(network);
+
+ BT_MESH_VALIDATE_HANDLE(network, networks);
+
+ network_s = (bt_mesh_network_s*)network;
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_cancel_scan(&net));
+
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_network_set_provisioning_capabilities(bt_mesh_network_h network,
+ bt_mesh_provisioner_capabilities_s *capabilities)
+{
+ bt_mesh_network_s *network_s;
+ bluetooth_mesh_network_t net;
+ bluetooth_mesh_provisioner_caps_t caps;
+ int error_code = BT_ERROR_NONE;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(network);
+ BT_CHECK_INPUT_PARAMETER(capabilities);
+
+ BT_MESH_VALIDATE_HANDLE(network, networks);
+
+ network_s = (bt_mesh_network_s*)network;
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+ memset(&caps, 0x00, sizeof(bluetooth_mesh_provisioner_caps_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ caps.public_oob = capabilities->public_oob;
+ caps.static_oob = capabilities->static_oob;
+ caps.out_oob = capabilities->out_oob;
+ caps.in_oob = capabilities->in_oob;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_set_capabilities(
+ &net,(bluetooth_mesh_provisioner_caps_t*) &caps));
+
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_network_provision_device(bt_mesh_network_h network,
+ const char *dev_uuid,
+ bt_mesh_network_device_provision_cb callback,
+ void *user_data)
+{
+ bt_mesh_network_s *network_s;
+ bluetooth_mesh_provisioning_request_t req;
+ int error_code = BT_ERROR_NONE;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(network);
+ BT_CHECK_INPUT_PARAMETER(dev_uuid);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ BT_MESH_VALIDATE_HANDLE(network, networks);
+
+ network_s = (bt_mesh_network_s*)network;
+ memset(&req, 0x00, sizeof(bluetooth_mesh_provisioning_request_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ g_strlcpy(req.dev_uuid, dev_uuid, 33);
+
+ BT_INFO("Mesh: Provision Device [%s]", dev_uuid);
+ error_code = _bt_get_error_code(bluetooth_mesh_network_provision_device(&req));
+
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ _bt_set_cb(BT_EVENT_MESH_NETWORK_PROVISIONING_RESULT, callback, user_data);
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_authentication_set_request_cb(bt_mesh_authentication_request_cb callback, void *user_data)
+{
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ _bt_set_cb(BT_EVENT_MESH_AUTHENTICATION_REQUEST, callback, user_data);
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_authentication_unset_request_cb(bt_mesh_authentication_request_cb callback)
+{
+ FUNC_ENTRY;
+
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ _bt_unset_cb(BT_EVENT_MESH_AUTHENTICATION_REQUEST);
+
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_authentication_reply(bt_mesh_authentication_type_e auth_type, const char *value, bool auth_reply)
+{
+ int error_code = BT_ERROR_NONE;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(value);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_authentication_reply(auth_type, value, auth_reply));
+ if (error_code != BT_ERROR_NONE)
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+
+ FUNC_EXIT;
+ return error_code;
+}
+
+int bt_mesh_network_discover_node(bt_mesh_network_h network,
+ const char *dev_uuid, bt_mesh_node_discover_status_cb callback, void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_network_s *network_s;
+ bluetooth_mesh_node_discover_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(network);
+ BT_CHECK_INPUT_PARAMETER(dev_uuid);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ BT_MESH_VALIDATE_HANDLE(network, networks);
+
+
+ /* Check if node with dev_uuid is already created */
+ network_s = (bt_mesh_network_s*)network;
+ memset(&req, 0x00, sizeof(bluetooth_mesh_node_discover_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ g_strlcpy(req.dev_uuid, dev_uuid, 33);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_browse_remote_node(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_BROWSING_COMPLETED, callback, user_data);
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_node_configure_netkey(bt_mesh_node_h node, bt_mesh_node_key_configuration_e netkey_op,
+ bt_mesh_netkey_h netkey, bt_mesh_netkey_status_cb callback, void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_network_s *network_s;
+ bt_mesh_node_s *node_s;
+ bt_mesh_netkey_s *netkey_s;
+ bluetooth_mesh_key_configure_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(node);
+ BT_CHECK_INPUT_PARAMETER(netkey);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ node_s = (bt_mesh_node_s*) node;
+ network_s = node_s->parent;
+ netkey_s = (bt_mesh_netkey_s*) netkey;
+
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+ BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ /* Return error, if netkey is not present in the specific network */
+ if (netkey_s->parent != network_s)
+ return BT_ERROR_INVALID_PARAMETER;
+
+#if 0
+ /* Return Already done, if netkey is present in the node */
+ if (g_slist_find_custom(node_s->netkeys,(gconstpointer) netkey_s,
+ (GCompareFunc)__simple_compare))
+ return BT_ERROR_ALREADY_DONE;
+#endif
+ memset(&req, 0x00, sizeof(bluetooth_mesh_key_configure_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ req.primary_unicast = node_s->unicast;
+ req.netkey_idx = netkey_s->netkey_index;
+ req.is_netkey = true;
+ req.op = (bluetooth_mesh_node_key_conf_e) netkey_op;
+
+ BT_INFO("Mesh: Add NetKey Idx [%d] to node", req.netkey_idx);
+ error_code = _bt_get_error_code(bluetooth_mesh_node_configure_key(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_KEY_CONFIGURATION_COMPLETED, callback, user_data);
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_node_configure_appkey(bt_mesh_node_h node, bt_mesh_node_key_configuration_e appkey_op,
+ bt_mesh_appkey_h appkey, bt_mesh_appkey_status_cb callback, void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_network_s *network_s;
+ bt_mesh_node_s *node_s;
+ bt_mesh_netkey_s *netkey_s;
+ bt_mesh_appkey_s *appkey_s;
+ bluetooth_mesh_key_configure_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(node);
+ BT_CHECK_INPUT_PARAMETER(appkey);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ node_s = (bt_mesh_node_s*) node;
+ network_s = node_s->parent;
+ appkey_s = (bt_mesh_appkey_s*) appkey;
+ netkey_s = (bt_mesh_netkey_s*) appkey_s->parent;
+
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+ BT_MESH_VALIDATE_HANDLE(appkey_s, appkey_list);
+ BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ /* Return error, if netkey is not present in the specific network */
+ if (netkey_s->parent != network_s)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ /* Return Already done, if appkey is present in the node */
+ if (g_slist_find_custom(node_s->appkeys,(gconstpointer) appkey_s,
+ (GCompareFunc)__simple_compare))
+ return BT_ERROR_ALREADY_DONE;
+
+ memset(&req, 0x00, sizeof(bluetooth_mesh_key_configure_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ req.primary_unicast = node_s->unicast;
+ req.netkey_idx = netkey_s->netkey_index;
+ req.appkey_idx = appkey_s->appkey_index;
+ req.is_netkey = false;
+ req.op = (bluetooth_mesh_node_key_conf_e) appkey_op;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_node_configure_key(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_KEY_CONFIGURATION_COMPLETED, callback, user_data);
+ return BT_ERROR_NONE;
+}
+
+
+/* Remote Node Operations: CONFIG: Non Key */
+int bt_mesh_node_get_features(bt_mesh_node_h node, bt_mesh_node_features_cb callback, void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_network_s *network_s;
+ bt_mesh_node_s *node_s;
+ bluetooth_mesh_node_features_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(node);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ node_s = (bt_mesh_node_s*) node;
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ network_s = (bt_mesh_network_s*) node_s->parent;
+
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+
+ memset(&req, 0x00, sizeof(bluetooth_mesh_node_features_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ req.unicast = node_s->unicast;
+ req.elem_count = node_s->unicast;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_node_browse_vendor_features(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_VENDOR_FEATURES, callback, user_data);
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_node_get_ttl(bt_mesh_node_h node, bt_mesh_node_ttl_cb callback, void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_network_s *network_s;
+ bt_mesh_node_s *node_s;
+ bluetooth_mesh_node_ttl_info_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(node);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ node_s = (bt_mesh_node_s*) node;
+ network_s = node_s->parent;
+
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ memset(&req, 0x00, sizeof(bluetooth_mesh_node_ttl_info_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ req.unicast = node_s->unicast;
+ req.is_set = false;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_node_ttl_execute(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_TTL_EXECUTE_COMPLETED, callback, user_data);
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_node_set_ttl(bt_mesh_node_h node, uint8_t ttl, bt_mesh_node_ttl_cb callback, void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_network_s *network_s;
+ bt_mesh_node_s *node_s;
+ bluetooth_mesh_node_ttl_info_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(node);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ node_s = (bt_mesh_node_s*) node;
+ network_s = node_s->parent;
+ BT_CHECK_INPUT_PARAMETER(network_s);
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ memset(&req, 0x00, sizeof(bluetooth_mesh_node_ttl_info_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ req.unicast = node_s->unicast;
+ req.is_set = true;
+ req.ttl = ttl;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_node_ttl_execute(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_TTL_EXECUTE_COMPLETED, callback, user_data);
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_node_foreach_netkeys(bt_mesh_node_h node, bt_mesh_node_netkey_info_cb callback, void *user_data)
+{
+ GPtrArray *netkeys = NULL;
+ GSList *l;
+ int error_code = BT_ERROR_NONE;
+ uint16_t *netkey_idx = NULL;
+ int i;
+ int total;
+ bluetooth_mesh_node_discover_t req;
+ bt_mesh_network_s *network_s;
+ bt_mesh_node_s *node_s;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(node);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ node_s = (bt_mesh_node_s*) node;
+ network_s = node_s->parent;
+
+ BT_CHECK_INPUT_PARAMETER(network_s);
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ netkeys = g_ptr_array_new();
+ if (netkeys == NULL) {
+ BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY);
+ return BT_ERROR_OUT_OF_MEMORY;
+ }
+
+ memset(&req, 0x00, sizeof(bluetooth_mesh_node_discover_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ req.unicast = node_s->unicast;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_node_get_all_netkeys(&req, &netkeys));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ g_ptr_array_free(netkeys, TRUE);
+ return error_code;
+ }
+
+ BT_INFO("Mesh: Total netkeys added in node is [%d]", netkeys->len);
+ for (i = 0; i < netkeys->len; i++) {
+ bt_mesh_netkey_s *netkey_local;
+ netkey_idx = g_ptr_array_index(netkeys, i);
+ BT_INFO("Mesh: NetKey IDX [0x%2.2x]", *netkey_idx);
+ if (netkey_idx) {
+ /* Check if netkey index is present in network or not */
+ netkey_local = __bt_mesh_network_is_netkey_added(network_s, *netkey_idx);
+ if (!netkey_local) {
+ BT_ERR("Mesh: Network does not contain the netKey index, possibly reloaded");
+ /* Create Netkey object */
+ netkey_local = g_malloc0(sizeof(bt_mesh_netkey_s));
+ netkey_local->parent = network_s;
+ netkey_local->netkey_index = *netkey_idx;
+ network_s->netkeys = g_slist_append(network_s->netkeys, netkey_local);
+ netkey_list = g_slist_append(netkey_list, netkey_local);
+
+ if (!g_slist_find_custom(node_s->netkeys, GUINT_TO_POINTER(*netkey_idx),
+ (GCompareFunc)__compare_netkey_index))
+ node_s->netkeys = g_slist_append(node_s->netkeys, netkey_local);
+ } else {
+ /* Check if netkey index is present in target node or not */
+ if (!g_slist_find_custom(node_s->netkeys,(gconstpointer) netkey_local,
+ (GCompareFunc)__simple_compare)) {
+ node_s->netkeys = g_slist_append(node_s->netkeys, netkey_local);
+ } else {
+ /* DO NOTHING*/
+ BT_INFO("Mesh: Netkey is already added in node");
+ }
+ }
+ } else {
+ BT_ERR("Mesh: OPERATION_FAILED(0x%08x)",
+ BT_ERROR_OPERATION_FAILED);
+ error_code = BT_ERROR_OPERATION_FAILED;
+ break;
+ }
+ }
+
+ total = g_slist_length(node_s->netkeys);
+ if (total == 0) {
+ BT_ERR("Mesh: Unexpcted: No netkey added in node!!");
+ callback(BT_ERROR_NONE, (bt_mesh_node_h)node_s, total,
+ NULL, 0xFFFF, user_data);
+ }
+ for (l = node_s->netkeys; l != NULL; l = g_slist_next(l)) {
+ bt_mesh_netkey_s *netkey;
+ netkey = l->data;
+
+ if (!callback(BT_ERROR_NONE, (bt_mesh_node_h)node_s, total,
+ (bt_mesh_netkey_h) netkey,
+ netkey->netkey_index, user_data)) {
+ break;
+ }
+ }
+
+ g_ptr_array_foreach(netkeys, (GFunc)g_free, NULL);
+ g_ptr_array_free(netkeys, TRUE);
+
+ FUNC_EXIT;
+ return error_code;
+}
+
+int bt_mesh_node_foreach_appkeys(bt_mesh_node_h node, bt_mesh_netkey_h netkey,
+ bt_mesh_node_appkey_info_cb callback, void *user_data)
+{
+ GPtrArray *appkeys = NULL;
+ GSList *l;
+ int error_code = BT_ERROR_NONE;
+ int i;
+ int total;
+ bluetooth_mesh_node_discover_t req;
+ uint16_t *appkey_idx = NULL;
+ bt_mesh_network_s *network_s;
+ bt_mesh_node_s *node_s;
+ bt_mesh_netkey_s *netkey_s;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(node);
+ BT_CHECK_INPUT_PARAMETER(netkey);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ node_s = (bt_mesh_node_s*) node;
+ network_s = node_s->parent;
+ netkey_s = (bt_mesh_netkey_s*) netkey;
+
+ BT_CHECK_INPUT_PARAMETER(network_s);
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+ BT_MESH_VALIDATE_HANDLE(netkey_s, netkey_list);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ appkeys = g_ptr_array_new();
+ if (appkeys == NULL) {
+ BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY);
+ return BT_ERROR_OUT_OF_MEMORY;
+ }
+
+ memset(&req, 0x00, sizeof(bluetooth_mesh_node_discover_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ req.unicast = node_s->unicast;
+ req.netkey_idx = netkey_s->netkey_index;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_node_get_all_appkeys(&req, &appkeys));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ g_ptr_array_free(appkeys, TRUE);
+ return error_code;
+ }
+
+ BT_INFO("Mesh: Total appkeys found in Node [%d]", appkeys->len);
+ for (i = 0; i < appkeys->len; i++) {
+ bt_mesh_appkey_s *appkey_local;
+ appkey_idx = g_ptr_array_index(appkeys, i);
+ BT_INFO("Mesh: AppKey index [0x%2.2x]", *appkey_idx);
+ if (appkey_idx) {
+ /* Check if netkey index is present in network or not */
+ appkey_local = __bt_mesh_network_is_appkey_added(network_s, netkey_s->netkey_index, *appkey_idx);
+
+ if (!appkey_local) {
+ BT_ERR("Mesh: Network does not AppKey index, possibly Network reloaded!!");
+ /* Create Netkey object */
+ appkey_local = g_malloc0(sizeof(bt_mesh_netkey_s));
+ appkey_local->parent = netkey_s;
+ appkey_local->appkey_index = *appkey_idx;
+ netkey_s->appkeys = g_slist_append(netkey_s->appkeys, appkey_local);
+ appkey_list = g_slist_append(appkey_list, appkey_local);
+
+ if (!g_slist_find_custom(node_s->appkeys, GUINT_TO_POINTER(*appkey_idx),
+ (GCompareFunc)__compare_appkey_index))
+ node_s->appkeys = g_slist_append(node_s->appkeys, appkey_local);
+ } else {
+ /* Check if netkey index is present in target node or not */
+ if (!g_slist_find_custom(node_s->appkeys, GUINT_TO_POINTER(*appkey_idx),
+ (GCompareFunc)__compare_appkey_index)) {
+ node_s->appkeys = g_slist_append(node_s->appkeys, appkey_local);
+ } else {
+ /* DO NOTHING*/
+ BT_INFO("Mesh: AppKey is already added in node");
+ }
+ }
+ } else {
+ BT_ERR("Mesh: OPERATION_FAILED(0x%08x)",
+ BT_ERROR_OPERATION_FAILED);
+ error_code = BT_ERROR_OPERATION_FAILED;
+ break;
+ }
+ }
+
+ total = g_slist_length(node_s->appkeys);
+ if (total == 0) {
+ BT_ERR("Mesh:Possible: No appkey added in node!!");
+ callback(BT_ERROR_NONE, (bt_mesh_node_h)node_s, total,
+ (bt_mesh_netkey_h) netkey_s, NULL, 0xFFFF, user_data);
+ }
+ for (l = node_s->appkeys; l != NULL; l = g_slist_next(l)) {
+ bt_mesh_appkey_s *appkey_s;
+ appkey_s = l->data;
+
+ if (!callback(BT_ERROR_NONE, (bt_mesh_node_h)node_s, total,
+ (bt_mesh_netkey_h) netkey, (bt_mesh_appkey_h) appkey_s,
+ appkey_s->appkey_index, user_data)) {
+ break;
+ }
+ }
+
+ g_ptr_array_foreach(appkeys, (GFunc)g_free, NULL);
+ g_ptr_array_free(appkeys, TRUE);
+
+ FUNC_EXIT;
+ return error_code;
+}
+
+int bt_mesh_model_bind_appkey(bt_mesh_model_h model,
+ bt_mesh_appkey_h appkey, bt_mesh_model_bind_cb callback,
+ void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_model_s *model_s;
+ bt_mesh_element_s *element_s;
+ bt_mesh_node_s *node_s;
+ bt_mesh_network_s *network_s;
+ bt_mesh_appkey_s *appkey_s;
+ bluetooth_mesh_model_configure_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(model);
+ BT_CHECK_INPUT_PARAMETER(appkey);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ model_s = (bt_mesh_model_s*) model;
+ element_s = (bt_mesh_element_s*) model_s->parent;
+ node_s = (bt_mesh_node_s*) element_s->parent;
+ appkey_s = (bt_mesh_appkey_s*) appkey;
+ network_s = (bt_mesh_network_s*) node_s->parent;
+
+ BT_MESH_VALIDATE_HANDLE(model_s, model_list);
+ BT_MESH_VALIDATE_HANDLE(element_s, element_list);
+ BT_MESH_VALIDATE_HANDLE(appkey_s, appkey_list);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ memset(&req, 0x00, sizeof(bluetooth_mesh_model_configure_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ req.primary_unicast = node_s->unicast;
+ req.elem_index = element_s->index;
+ req.model = model_s->id;
+ req.appkey_idx = appkey_s->appkey_index;
+ req.is_bind = true;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_model_configure_appkey(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_BIND_APPKEY_COMPLETED, callback, user_data);
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_model_unbind_appkey(bt_mesh_model_h model, bt_mesh_appkey_h appkey,
+ bt_mesh_model_unbind_cb callback, void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_model_s *model_s;
+ bt_mesh_element_s *element_s;
+ bt_mesh_node_s *node_s;
+ bt_mesh_appkey_s *appkey_s;
+ bt_mesh_network_s *network_s;
+ bluetooth_mesh_model_configure_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(model);
+ BT_CHECK_INPUT_PARAMETER(appkey);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ model_s = (bt_mesh_model_s*) model;
+ element_s = (bt_mesh_element_s*) model_s->parent;
+ node_s = (bt_mesh_node_s*) element_s->parent;
+ appkey_s = (bt_mesh_appkey_s*) appkey;
+ network_s = (bt_mesh_network_s*) node_s->parent;
+
+ BT_MESH_VALIDATE_HANDLE(model_s, model_list);
+ BT_MESH_VALIDATE_HANDLE(appkey_s, appkey_list);
+ BT_MESH_VALIDATE_HANDLE(element_s, element_list);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ memset(&req, 0x00, sizeof(bluetooth_mesh_model_configure_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ req.primary_unicast = node_s->unicast;
+ req.elem_index = element_s->index;
+ req.model = model_s->id;
+ req.appkey_idx = appkey_s->appkey_index;
+ req.is_bind = false;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_model_configure_appkey(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_BIND_APPKEY_COMPLETED, callback, user_data);
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_model_get_appkey_list(bt_mesh_model_h model,
+ bt_mesh_model_appkey_list_cb callback, void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_model_s *model_s;
+ bt_mesh_element_s *element_s;
+ bt_mesh_node_s *node_s;
+ bt_mesh_network_s *network_s;
+ bluetooth_mesh_model_configure_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(model);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ model_s = (bt_mesh_model_s*) model;
+ element_s = (bt_mesh_element_s*) model_s->parent;
+ node_s = (bt_mesh_node_s*) element_s->parent;
+ network_s = (bt_mesh_network_s*) node_s->parent;
+
+ BT_CHECK_INPUT_PARAMETER(model_s);
+ BT_CHECK_INPUT_PARAMETER(element_s);
+ BT_CHECK_INPUT_PARAMETER(node_s);
+ BT_CHECK_INPUT_PARAMETER(network_s);
+
+ BT_MESH_VALIDATE_HANDLE(model_s, model_list);
+ BT_MESH_VALIDATE_HANDLE(element_s, element_list);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ memset(&req, 0x00, sizeof(bluetooth_mesh_model_configure_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ req.primary_unicast = node_s->unicast;
+ req.elem_index = element_s->index;
+ req.model = model_s->id;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_model_get_all_appkeys(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_APPKEY_LIST, callback, user_data);
+ return error_code;
+}
+
+int bt_mesh_network_foreach_groups(bt_mesh_network_h network,
+ bt_mesh_network_group_info_cb callback, void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bluetooth_mesh_network_t net;
+ bt_mesh_network_s *network_s;
+ GPtrArray *groups = NULL;
+ GSList *l;
+ uint16_t *group_addr = NULL;
+ int i;
+ int total;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(network);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ BT_MESH_VALIDATE_HANDLE(network, networks);
+
+ groups = g_ptr_array_new();
+ if (groups == NULL) {
+ BT_ERR("Mesh: OUT_OF_MEMORY(0x%08x)", BT_ERROR_OUT_OF_MEMORY);
+ return BT_ERROR_OUT_OF_MEMORY;
+ }
+
+ network_s = (bt_mesh_network_s*)network;
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_get_all_groups(&net, &groups));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ g_ptr_array_free(groups, TRUE);
+ return error_code;
+ }
+
+ for (i = 0; i < groups->len; i++) {
+ group_addr = g_ptr_array_index(groups, i);
+ if (group_addr) {
+ /* Find or create group in network list */
+ if (!_bt_mesh_network_get_group(network_s, *group_addr)) {
+ BT_ERR("Mesh: OPERATION_FAILED(0x%08x)",
+ BT_ERROR_OPERATION_FAILED);
+ error_code = BT_ERROR_OPERATION_FAILED;
+ break;
+ }
+ } else {
+ BT_ERR("Mesh: OPERATION_FAILED(0x%08x)",
+ BT_ERROR_OPERATION_FAILED);
+ error_code = BT_ERROR_OPERATION_FAILED;
+ break;
+ }
+ }
+
+ total = g_slist_length(network_s->groups);
+ if (total == 0) {
+ BT_INFO("Mesh: No Groups added in network");
+ callback(BT_ERROR_NONE, (bt_mesh_network_h)network_s, total,
+ NULL, user_data);
+ }
+ for (l = network_s->groups; l != NULL; l = g_slist_next(l)) {
+ bt_mesh_group_s *group_s;
+ group_s = l->data;
+
+ if (!callback(BT_ERROR_NONE, (bt_mesh_network_h)network_s, total,
+ (bt_mesh_group_h) group_s,
+ user_data))
+ break;
+ }
+
+ g_ptr_array_foreach(groups, (GFunc)g_free, NULL);
+ g_ptr_array_free(groups, TRUE);
+
+ FUNC_EXIT;
+ return error_code;
+}
+
+int bt_mesh_network_create_virtual_group(bt_mesh_network_h network,
+ bt_mesh_group_h *group)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_network_s *network_s;
+ bt_mesh_group_s *group_s;
+ bluetooth_mesh_network_group_info_t req;
+ bluetooth_mesh_network_t net;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(network);
+
+ network_s = (bt_mesh_network_s*) network;
+
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+ memset(&req, 0x00, sizeof(bluetooth_mesh_network_group_info_t));
+
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_create_group(&net, true, 0x0000, &req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ group_s = g_malloc0(sizeof(bt_mesh_group_s));
+ group_s->addr = req.group_addr;
+ group_s->is_virtual = true;
+ group_s->parent = network_s;
+ if (g_slist_append(network_s->groups, group_s))
+ BT_INFO("Mesh: Group created");
+
+ __bt_mesh_util_convert_hex_to_string((uint8_t *)req.label_uuid, 16,
+ group_s->label_uuid, sizeof(group_s->label_uuid));
+
+ group_list = g_slist_append(group_list, group_s);
+ *group = (bt_mesh_group_h) group_s;
+ FUNC_EXIT;
+ return error_code;
+}
+
+int bt_mesh_network_remove_group(bt_mesh_group_h group)
+{
+ bt_mesh_network_s *network_s;
+ bt_mesh_group_s *group_s;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_INPUT_PARAMETER(group);
+
+ group_s = (bt_mesh_group_s*) group;
+ network_s = group_s->parent;
+
+ BT_MESH_VALIDATE_HANDLE(group_s, group_list);
+
+ network_s->groups = g_slist_remove(network_s->groups, group_s);
+ group_list = g_slist_remove(group_list, group_s);
+
+ g_free(group_s);
+ FUNC_EXIT;
+ return BT_ERROR_NONE;
+}
+
+int bt_mesh_network_create_group(bt_mesh_network_h network,
+ uint16_t grp_addr, bt_mesh_group_h *group)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_network_s *network_s;
+ bt_mesh_group_s *group_s;
+ bluetooth_mesh_network_t net;
+ bluetooth_mesh_network_group_info_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(network);
+
+ network_s = (bt_mesh_network_s*) network;
+
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+
+ memset(&net, 0x00, sizeof(bluetooth_mesh_network_t));
+ memset(&req, 0x00, sizeof(bluetooth_mesh_network_group_info_t));
+
+ /* Fill Network Info */
+ g_strlcpy(net.uuid, network_s->uuid, 33);
+ g_strlcpy(net.token.token, network_s->token, 17);
+ g_strlcpy(net.name.name, network_s->name, BT_MESH_NETWORK_NAME_STRING_MAX_LEN + 1);
+
+ error_code = _bt_get_error_code(bluetooth_mesh_network_create_group(&net, false, grp_addr, &req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ group_s = g_malloc0(sizeof(bt_mesh_group_s));
+ group_s->addr = grp_addr;
+ group_s->is_virtual = false;
+ group_s->parent = network_s;
+ if (g_slist_append(network_s->groups, group_s))
+ BT_INFO("Mesh: Group created");
+
+ group_list = g_slist_append(group_list, group_s);
+ *group = (bt_mesh_group_h) group_s;
+ FUNC_EXIT;
+ return error_code;
+}
+
+
+int bt_mesh_model_configure_group_subscription(bt_mesh_model_subscription_op_e model_op,
+ bt_mesh_model_h model, bt_mesh_group_h group,
+ bt_mesh_model_subscription_op_cb callback, void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_model_s *model_s;
+ bt_mesh_element_s *element_s;
+ bt_mesh_node_s *node_s;
+ bt_mesh_network_s *network_s;
+ bt_mesh_group_s *group_s;
+ bluetooth_mesh_model_configure_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(model);
+ BT_CHECK_INPUT_PARAMETER(group);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ model_s = (bt_mesh_model_s*) model;
+ group_s = (bt_mesh_group_s*) model;
+ element_s = (bt_mesh_element_s*) model_s->parent;
+ node_s = (bt_mesh_node_s*) element_s->parent;
+ network_s = (bt_mesh_network_s*) node_s->parent;
+
+ /* Check group belongs to the same network */
+ if (network_s != group_s->parent)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ /* Check group is non virtual */
+ if (group_s->is_virtual)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ BT_CHECK_INPUT_PARAMETER(element_s);
+ BT_CHECK_INPUT_PARAMETER(node_s);
+ BT_CHECK_INPUT_PARAMETER(network_s);
+
+ BT_MESH_VALIDATE_HANDLE(model_s, model_list);
+ BT_MESH_VALIDATE_HANDLE(group_s, group_list);
+ BT_MESH_VALIDATE_HANDLE(element_s, element_list);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ if (model_op != BT_MESH_MODEL_SUBSCRIPTION_DELETE_ALL)
+ req.sub_addr = group_s->addr;
+ req.is_virtual_sub = false;
+ req.op = model_op;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_model_configure_group_sub(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_GROUP_SUB, callback, user_data);
+ return error_code;
+}
+
+int bt_mesh_model_configure_virtual_group_subscription(bt_mesh_model_subscription_op_e model_op,
+ bt_mesh_model_h model, bt_mesh_group_h group,
+ bt_mesh_model_subscription_op_cb callback,
+ void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_model_s *model_s;
+ bt_mesh_element_s *element_s;
+ bt_mesh_node_s *node_s;
+ bt_mesh_network_s *network_s;
+ bt_mesh_group_s *group_s;
+ bluetooth_mesh_model_configure_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(model);
+ BT_CHECK_INPUT_PARAMETER(group);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ model_s = (bt_mesh_model_s*) model;
+ group_s = (bt_mesh_group_s*) model;
+ element_s = (bt_mesh_element_s*) model_s->parent;
+ node_s = (bt_mesh_node_s*) element_s->parent;
+ network_s = (bt_mesh_network_s*) node_s->parent;
+
+ /* Check group belongs to the same network */
+ if (network_s != group_s->parent)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ /* Check group is non virtual */
+ if (!group_s->is_virtual)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ BT_CHECK_INPUT_PARAMETER(element_s);
+ BT_CHECK_INPUT_PARAMETER(node_s);
+ BT_CHECK_INPUT_PARAMETER(network_s);
+
+ BT_MESH_VALIDATE_HANDLE(model_s, model_list);
+ BT_MESH_VALIDATE_HANDLE(group_s, group_list);
+ BT_MESH_VALIDATE_HANDLE(element_s, element_list);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ if (model_op != BT_MESH_MODEL_SUBSCRIPTION_DELETE_ALL)
+ req.sub_addr = group_s->addr;
+
+ req.is_virtual_sub = true;
+ req.op = model_op;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_model_configure_virtual_group_sub(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_GROUP_VIR_SUB, callback, user_data);
+ return error_code;
+}
+
+int bt_mesh_model_get_subscription_list(bt_mesh_model_h model,
+ bt_mesh_model_subscription_list_cb callback, void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_model_s *model_s;
+ bt_mesh_element_s *element_s;
+ bt_mesh_node_s *node_s;
+ bt_mesh_network_s *network_s;
+ bluetooth_mesh_model_configure_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(model);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ model_s = (bt_mesh_model_s*) model;
+ element_s = (bt_mesh_element_s*) model_s->parent;
+ node_s = (bt_mesh_node_s*) element_s->parent;
+ network_s = (bt_mesh_network_s*) node_s->parent;
+
+ BT_CHECK_INPUT_PARAMETER(model_s);
+ BT_CHECK_INPUT_PARAMETER(element_s);
+ BT_CHECK_INPUT_PARAMETER(node_s);
+ BT_CHECK_INPUT_PARAMETER(network_s);
+
+ BT_MESH_VALIDATE_HANDLE(model_s, model_list);
+ BT_MESH_VALIDATE_HANDLE(element_s, element_list);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ memset(&req, 0x00, sizeof(bluetooth_mesh_model_configure_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ req.primary_unicast = node_s->unicast;
+ req.elem_index = element_s->index;
+ req.model = model_s->id;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_model_get_subscriptopn_list(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_APPKEY_LIST, callback, user_data);
+ return error_code;
+}
+
+int bt_mesh_model_set_publication(bt_mesh_model_h model, bt_mesh_appkey_h appkey,
+ bt_mesh_group_h group,
+ bt_mesh_model_pub_params_s *params,
+ bt_mesh_model_publication_status_cb callback,
+ void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_model_s *model_s;
+ bt_mesh_element_s *element_s;
+ bt_mesh_node_s *node_s;
+ bt_mesh_appkey_s *appkey_s;
+ bt_mesh_network_s *network_s;
+ bt_mesh_group_s *group_s;
+ bluetooth_mesh_model_configure_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(model);
+ BT_CHECK_INPUT_PARAMETER(appkey);
+ BT_CHECK_INPUT_PARAMETER(group);
+ BT_CHECK_INPUT_PARAMETER(params);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ model_s = (bt_mesh_model_s*) model;
+ appkey_s = (bt_mesh_appkey_s*) appkey;
+ group_s = (bt_mesh_group_s*) group;
+ element_s = (bt_mesh_element_s*) model_s->parent;
+ node_s = (bt_mesh_node_s*) element_s->parent;
+ network_s = (bt_mesh_network_s*) node_s->parent;
+
+ if (group_s->parent != network_s)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ if (params->num_steps > BT_MESH_MAX_PUBISH_PERIOD_STEPS)
+ return BT_ERROR_INVALID_PARAMETER;
+ if (params->retrans_cnt > BT_MESH_MAX_PUBISH_RETRANSMIT_COUNT)
+ return BT_ERROR_INVALID_PARAMETER;
+ if (params->retrans_step > BT_MESH_MAX_PUBISH_RETRANSMIT_INTERVAL_STEPS)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ BT_CHECK_INPUT_PARAMETER(element_s);
+ BT_CHECK_INPUT_PARAMETER(node_s);
+ BT_CHECK_INPUT_PARAMETER(network_s);
+
+ BT_MESH_VALIDATE_HANDLE(model_s, model_list);
+ BT_MESH_VALIDATE_HANDLE(element_s, element_list);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+ BT_MESH_VALIDATE_HANDLE(appkey_s, appkey_list);
+ BT_MESH_VALIDATE_HANDLE(group_s, group_list);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ memset(&req, 0x00, sizeof(bluetooth_mesh_model_configure_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ req.primary_unicast = node_s->unicast;
+ req.elem_index = element_s->index;
+ req.model = model_s->id;
+ req.appkey_idx = appkey_s->appkey_index;
+ req.pub_addr = group_s->addr;
+
+ req.ttl = params->ttl;
+ req.period = params->num_steps;
+ req.period = req.period << 2;
+ req.period |= params->per_res;
+ req.retransmit = params->retrans_cnt;
+ req.retransmit = req.retransmit << 5;
+ req.retransmit |= params->retrans_step;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_model_set_publication(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_PUBLICATION, callback, user_data);
+ return error_code;
+}
+
+int bt_mesh_model_get_publication(bt_mesh_model_h model,
+ bt_mesh_model_publication_status_cb callback, void *user_data)
+{
+ int error_code = BT_ERROR_NONE;
+ bt_mesh_model_s *model_s;
+ bt_mesh_element_s *element_s;
+ bt_mesh_node_s *node_s;
+ bt_mesh_network_s *network_s;
+ bluetooth_mesh_model_configure_t req;
+
+ FUNC_ENTRY;
+ BT_CHECK_MESH_SUPPORT();
+ BT_CHECK_MESH_INIT_STATUS();
+ BT_CHECK_INPUT_PARAMETER(model);
+ BT_CHECK_INPUT_PARAMETER(callback);
+
+ model_s = (bt_mesh_model_s*) model;
+ element_s = (bt_mesh_element_s*) model_s->parent;
+ node_s = (bt_mesh_node_s*) element_s->parent;
+ network_s = (bt_mesh_network_s*) node_s->parent;
+
+ BT_CHECK_INPUT_PARAMETER(model_s);
+ BT_CHECK_INPUT_PARAMETER(element_s);
+ BT_CHECK_INPUT_PARAMETER(node_s);
+ BT_CHECK_INPUT_PARAMETER(network_s);
+
+ BT_MESH_VALIDATE_HANDLE(model_s, model_list);
+ BT_MESH_VALIDATE_HANDLE(element_s, element_list);
+ BT_MESH_VALIDATE_HANDLE(node_s, node_list);
+ BT_MESH_VALIDATE_HANDLE(network_s, networks);
+
+ /* Return error, if node is not attached */
+ if (!node_s->is_attached)
+ return BT_ERROR_INVALID_PARAMETER;
+
+ memset(&req, 0x00, sizeof(bluetooth_mesh_model_configure_t));
+
+ g_strlcpy(req.net_uuid, network_s->uuid, 33);
+ req.primary_unicast = node_s->unicast;
+ req.elem_index = element_s->index;
+ req.model = model_s->id;
+
+ error_code = _bt_get_error_code(bluetooth_mesh_model_get_publication(&req));
+ if (error_code != BT_ERROR_NONE) {
+ BT_ERR("%s(0x%08x)", _bt_convert_error_to_string(error_code), error_code);
+ return error_code;
+ }
+
+ FUNC_EXIT;
+ _bt_set_cb(BT_EVENT_MESH_NODE_MODEL_PUBLICATION, callback, user_data);
+ return error_code;
+}