aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2018-08-23 17:08:59 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2018-08-23 17:12:21 +0200
commit3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a (patch)
treeab49cc16ed0b853452c5c2ed2d3042416d628986 /thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium
downloadiot-sensors-3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a.tar.gz
iot-sensors-3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a.tar.bz2
iot-sensors-3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a.tar.xz
iot-sensors-3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a.zip
o Initial import.HEADmaster
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ble_ncfgs/ble_ncfgs.c516
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ble_ncfgs/ble_ncfgs.h194
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/commissioning/commissioning.c1077
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/commissioning/commissioning.h207
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium.h238
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium_ble.c689
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium_ble.h100
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium_platform_dummy.h54
8 files changed, 3075 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ble_ncfgs/ble_ncfgs.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ble_ncfgs/ble_ncfgs.c
new file mode 100644
index 0000000..241ec48
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ble_ncfgs/ble_ncfgs.c
@@ -0,0 +1,516 @@
+/**
+ * Copyright (c) 2015-2017 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifdef COMMISSIONING_ENABLED
+
+#include <string.h>
+#include "ble_ncfgs.h"
+#include "app_error.h"
+#include "ble.h"
+#include "nordic_common.h"
+
+/**@brief NCFGS database encapsulation. */
+typedef struct
+{
+ uint16_t service_handle;
+ ble_gatts_char_handles_t ssid_handles;
+ ble_gatts_char_handles_t keys_store_handles;
+ ble_gatts_char_handles_t ctrlp_handles;
+} ble_database_t;
+
+static ble_ncfgs_state_t m_service_state = NCFGS_STATE_IDLE; /**< Module state value. */
+static ble_ncfgs_evt_handler_t m_app_evt_handler; /**< Parent module callback function. */
+static ble_database_t m_database; /**< GATT handles database. */
+static uint8_t m_ctrlp_value_buffer[NCFGS_CTRLP_VALUE_LEN]; /**< Stores received Control Point value before parsing. */
+static ble_ncfgs_data_t m_ncfgs_data; /**< Stores all values written by the peer device. */
+
+#if NCFGS_CONFIG_LOG_ENABLED
+
+#define NRF_LOG_MODULE_NAME ble_ncfgs
+
+#define NRF_LOG_LEVEL NCFGS_CONFIG_LOG_LEVEL
+#define NRF_LOG_INFO_COLOR NCFGS_CONFIG_INFO_COLOR
+#define NRF_LOG_DEBUG_COLOR NCFGS_CONFIG_DEBUG_COLOR
+
+#include "nrf_log.h"
+NRF_LOG_MODULE_REGISTER();
+
+#define NCFGS_TRC NRF_LOG_DEBUG /**< Used for getting trace of execution in the module. */
+#define NCFGS_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */
+#define NCFGS_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */
+
+#define NCFGS_ENTRY() NCFGS_TRC(">> %s", __func__)
+#define NCFGS_EXIT() NCFGS_TRC("<< %s", __func__)
+
+#else // NCFGS_CONFIG_LOG_ENABLED
+
+#define NCFGS_TRC(...) /**< Disables traces. */
+#define NCFGS_DUMP(...) /**< Disables dumping of octet streams. */
+#define NCFGS_ERR(...) /**< Disables error logs. */
+
+#define NCFGS_ENTRY(...)
+#define NCFGS_EXIT(...)
+
+#endif // NCFGS_CONFIG_LOG_ENABLED
+
+/**@brief Function for adding the SSID Store characteristic.
+ *
+ * @return NRF_SUCCESS on success, otherwise an error code.
+ */
+static uint32_t add_ssid_characteristic(ble_uuid_t * p_srv_uuid)
+{
+ ble_gatts_char_md_t char_md;
+ ble_gatts_attr_t attr_char_value;
+ ble_uuid_t char_uuid;
+ ble_gatts_attr_md_t attr_md;
+
+ memset(&char_md, 0x00, sizeof(char_md));
+
+ char_md.char_props.read = 1;
+ char_md.char_props.write = 1;
+
+ memset(&attr_md, 0x00, sizeof(attr_md));
+
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
+ attr_md.wr_auth = 1;
+ attr_md.vloc = BLE_GATTS_VLOC_USER;
+
+ memset(&attr_char_value, 0x00, sizeof(attr_char_value));
+
+ char_uuid.type = p_srv_uuid->type;
+ char_uuid.uuid = BLE_UUID_NCFGS_SSID_CHAR;
+
+ attr_char_value.p_uuid = &char_uuid;
+ attr_char_value.p_attr_md = &attr_md;
+ attr_char_value.init_len = NCFGS_SSID_MAX_LEN;
+ attr_char_value.init_offs = 0;
+ attr_char_value.max_len = NCFGS_SSID_MAX_LEN;
+ attr_char_value.p_value = &m_ncfgs_data.ssid_from_router.ssid[0];
+
+ return sd_ble_gatts_characteristic_add(m_database.service_handle,
+ &char_md,
+ &attr_char_value,
+ &m_database.ssid_handles);
+}
+
+
+/**@brief Function for adding the Keys Store characteristic.
+ *
+ * @return NRF_SUCCESS on success, otherwise an error code.
+ */
+static uint32_t add_keys_store_characteristic(ble_uuid_t * p_srv_uuid)
+{
+ ble_gatts_char_md_t char_md;
+ ble_gatts_attr_t attr_char_value;
+ ble_uuid_t char_uuid;
+ ble_gatts_attr_md_t attr_md;
+
+ memset(&char_md, 0x00, sizeof(char_md));
+
+ char_md.char_props.read = 1;
+ char_md.char_props.write = 1;
+
+ memset(&attr_md, 0x00, sizeof(attr_md));
+
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
+ attr_md.wr_auth = 1;
+ attr_md.vloc = BLE_GATTS_VLOC_USER;
+
+ memset(&attr_char_value, 0x00, sizeof(attr_char_value));
+
+ char_uuid.type = p_srv_uuid->type;
+ char_uuid.uuid = BLE_UUID_NCFGS_KEYS_STORE_CHAR;
+
+ attr_char_value.p_uuid = &char_uuid;
+ attr_char_value.p_attr_md = &attr_md;
+ attr_char_value.init_len = NCFGS_KEYS_MAX_LEN;
+ attr_char_value.init_offs = 0;
+ attr_char_value.max_len = NCFGS_KEYS_MAX_LEN;
+ attr_char_value.p_value = &m_ncfgs_data.keys_from_router.keys[0];
+
+ return sd_ble_gatts_characteristic_add(m_database.service_handle,
+ &char_md,
+ &attr_char_value,
+ &m_database.keys_store_handles);
+}
+
+
+/**@brief Function for adding the Control Point characteristic.
+ *
+ * @return NRF_SUCCESS on success, otherwise an error code.
+ */
+static uint32_t add_ip_cfg_cp_characteristic(ble_uuid_t * p_srv_uuid)
+{
+ ble_gatts_char_md_t char_md;
+ ble_gatts_attr_t attr_char_value;
+ ble_uuid_t char_uuid;
+ ble_gatts_attr_md_t attr_md;
+
+ memset(&char_md, 0x00, sizeof(char_md));
+
+ char_md.char_props.read = 1;
+ char_md.char_props.write = 1;
+
+ memset(&attr_md, 0x00, sizeof(attr_md));
+
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
+ attr_md.wr_auth = 1;
+ attr_md.vloc = BLE_GATTS_VLOC_USER;
+
+ memset(&attr_char_value, 0x00, sizeof(attr_char_value));
+
+ char_uuid.type = p_srv_uuid->type;
+ char_uuid.uuid = BLE_UUID_NCFGS_CTRLPT_CHAR;
+
+ attr_char_value.p_uuid = &char_uuid;
+ attr_char_value.p_attr_md = &attr_md;
+ attr_char_value.init_len = NCFGS_CTRLP_VALUE_LEN;
+ attr_char_value.init_offs = 0;
+ attr_char_value.max_len = NCFGS_CTRLP_VALUE_LEN;
+ attr_char_value.p_value = &m_ctrlp_value_buffer[0];
+
+ return sd_ble_gatts_characteristic_add(m_database.service_handle,
+ &char_md,
+ &attr_char_value,
+ &m_database.ctrlp_handles);
+}
+
+
+/**@brief Function for creating the GATT database.
+ *
+ * @return NRF_SUCCESS on success, otherwise an error code.
+ */
+static uint32_t ble_ncfgs_create_database(void)
+{
+ uint32_t err_code = NRF_SUCCESS;
+
+ // Add service.
+ ble_uuid_t service_uuid;
+
+ const ble_uuid128_t base_uuid128 =
+ {
+ {
+ 0x73, 0x3E, 0x2D, 0x02, 0xB7, 0x6B, 0xBE, 0xBE, \
+ 0xE5, 0x4F, 0x40, 0x8F, 0x00, 0x00, 0x20, 0x54
+ }
+ };
+
+ service_uuid.uuid = BLE_UUID_NODE_CFG_SERVICE;
+
+ err_code = sd_ble_uuid_vs_add(&base_uuid128, &(service_uuid.type));
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, \
+ &service_uuid, \
+ &m_database.service_handle);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ err_code = add_ssid_characteristic(&service_uuid);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ err_code = add_keys_store_characteristic(&service_uuid);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ err_code = add_ip_cfg_cp_characteristic(&service_uuid);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ return err_code;
+}
+
+
+uint32_t ble_ncfgs_init(ble_ncfgs_evt_handler_t ble_ncfgs_cb)
+{
+ NCFGS_ENTRY();
+ uint32_t err_code;
+ memset(&m_ncfgs_data, 0x00, sizeof(m_ncfgs_data));
+
+ m_app_evt_handler = ble_ncfgs_cb;
+
+ err_code = ble_ncfgs_create_database();
+ NCFGS_EXIT();
+ return err_code;
+}
+
+
+/**@brief Function for decoding the Control Point characteristic value.
+ *
+ * @return NRF_SUCCESS on success, otherwise an error code.
+ */
+static uint32_t ctrlp_value_decode(const ble_evt_t * p_ble_evt)
+{
+ uint16_t wr_req_value_len = \
+ p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.len;
+
+ memcpy(m_ctrlp_value_buffer, \
+ p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.data, \
+ wr_req_value_len);
+
+ m_ncfgs_data.ctrlp_value.opcode = \
+ (ble_ncfgs_opcode_t)m_ctrlp_value_buffer[0];
+ memcpy((void *)&m_ncfgs_data.ctrlp_value.delay_sec, \
+ &m_ctrlp_value_buffer[NCFGS_CTRLP_OPCODE_LEN], \
+ sizeof(uint32_t));
+ m_ncfgs_data.ctrlp_value.delay_sec = \
+ HTONL(m_ncfgs_data.ctrlp_value.delay_sec);
+ memcpy((void *)&m_ncfgs_data.ctrlp_value.duration_sec, \
+ &m_ctrlp_value_buffer[NCFGS_CTRLP_OPCODE_LEN+NCFGS_CTRLP_DELAY_LEN], \
+ sizeof(uint32_t));
+ m_ncfgs_data.ctrlp_value.duration_sec = \
+ HTONL(m_ncfgs_data.ctrlp_value.duration_sec);
+ m_ncfgs_data.ctrlp_value.state_on_failure = \
+ (state_on_failure_t)m_ctrlp_value_buffer[NCFGS_CTRLP_OPCODE_LEN+ \
+ NCFGS_CTRLP_DELAY_LEN+ \
+ NCFGS_CTRLP_DURATION_LEN];
+
+ if ((m_ncfgs_data.ctrlp_value.state_on_failure != NCFGS_SOF_NO_CHANGE) && \
+ (m_ncfgs_data.ctrlp_value.state_on_failure != NCFGS_SOF_PWR_OFF) && \
+ (m_ncfgs_data.ctrlp_value.state_on_failure != NCFGS_SOF_CONFIG_MODE))
+ {
+ return NRF_ERROR_INVALID_DATA;
+ }
+
+ uint16_t id_data_len = wr_req_value_len - NCFGS_CTRLP_ALL_BUT_ID_DATA_LEN;
+ if (id_data_len != 0)
+ {
+ m_ncfgs_data.id_data.identity_data_len = id_data_len;
+
+ memcpy(m_ncfgs_data.id_data.identity_data, \
+ &m_ctrlp_value_buffer[NCFGS_CTRLP_ALL_BUT_ID_DATA_LEN], \
+ id_data_len);
+ }
+
+ return NRF_SUCCESS;
+}
+
+
+void ble_ncfgs_ble_evt_handler(const ble_evt_t * p_ble_evt)
+{
+ switch (p_ble_evt->header.evt_id)
+ {
+ case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
+ {
+ if (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == \
+ BLE_GATTS_OP_WRITE_REQ)
+ {
+ uint16_t wr_req_handle = \
+ p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.handle;
+ uint16_t wr_req_value_len = \
+ p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.len;
+
+ ble_gatts_rw_authorize_reply_params_t reply_params;
+ memset(&reply_params, 0x00, sizeof(reply_params));
+
+ reply_params.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
+ reply_params.params.write.update = 1;
+ reply_params.params.write.offset = p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.offset;
+ reply_params.params.write.len = p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.len;
+ reply_params.params.write.p_data = p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.data;
+
+ if (wr_req_handle == m_database.ssid_handles.value_handle)
+ {
+ NCFGS_TRC("> wr_req: ssid_handle");
+
+ if ((wr_req_value_len > NCFGS_SSID_MAX_LEN) || \
+ (wr_req_value_len < NCFGS_SSID_MIN_LEN))
+ {
+ reply_params.params.write.gatt_status = \
+ BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH;
+ }
+ else
+ {
+ m_ncfgs_data.ssid_from_router.ssid_len = wr_req_value_len;
+ m_service_state |= NCFGS_STATE_SSID_WRITTEN;
+
+ reply_params.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
+ }
+
+ UNUSED_RETURN_VALUE( \
+ sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gap_evt.conn_handle, \
+ &reply_params));
+ NCFGS_TRC("< wr_req: ssid_handle");
+ return;
+ }
+
+ else if (wr_req_handle == m_database.keys_store_handles.value_handle)
+ {
+ NCFGS_TRC("> wr_req: keys_store_handle");
+
+ if (wr_req_value_len > NCFGS_KEYS_MAX_LEN)
+ {
+ reply_params.params.write.gatt_status = \
+ BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH;
+ }
+ else
+ {
+ m_ncfgs_data.keys_from_router.keys_len = wr_req_value_len;
+ m_service_state |= NCFGS_STATE_KEYS_STORE_WRITTEN;
+ reply_params.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
+ }
+
+ UNUSED_RETURN_VALUE( \
+ sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gap_evt.conn_handle, \
+ &reply_params));
+ NCFGS_TRC("< wr_req: keys_store_handle");
+ return;
+ }
+
+ else if (wr_req_handle == m_database.ctrlp_handles.value_handle)
+ {
+ NCFGS_TRC("> wr_req: ctrlp_handle");
+
+ bool notify_app = false;
+
+ if ((wr_req_value_len > NCFGS_CTRLP_VALUE_LEN) || \
+ (wr_req_value_len < NCFGS_CTRLP_ALL_BUT_ID_DATA_LEN))
+ {
+ reply_params.params.write.gatt_status = \
+ BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH;
+ }
+ else
+ {
+ ble_ncfgs_opcode_t opcode_in = (ble_ncfgs_opcode_t) \
+ p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.data[0];
+
+ reply_params.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
+
+ if ((opcode_in != NCFGS_OPCODE_GOTO_JOINING_MODE) && \
+ (opcode_in != NCFGS_OPCODE_GOTO_CONFIG_MODE) && \
+ (opcode_in != NCFGS_OPCODE_GOTO_IDENTITY_MODE))
+ {
+ reply_params.params.write.gatt_status = APP_GATTERR_UNKNOWN_OPCODE;
+ }
+
+ if (opcode_in == NCFGS_OPCODE_GOTO_JOINING_MODE)
+ {
+ if (!((m_service_state & NCFGS_STATE_SSID_WRITTEN) && \
+ (m_service_state & NCFGS_STATE_KEYS_STORE_WRITTEN)))
+ {
+ reply_params.params.write.gatt_status = APP_GATTERR_NOT_CONFIGURED;
+ }
+ }
+
+ if (reply_params.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS)
+ {
+ uint32_t err_code = ctrlp_value_decode(p_ble_evt);
+ if (err_code != NRF_SUCCESS)
+ {
+ reply_params.params.write.gatt_status = \
+ APP_GATTERR_INVALID_ATTR_VALUE;
+ }
+ else
+ {
+ notify_app = true;
+ }
+ }
+ }
+
+ UNUSED_RETURN_VALUE(sd_ble_gatts_rw_authorize_reply(
+ p_ble_evt->evt.gap_evt.conn_handle,
+ &reply_params));
+
+ if (notify_app == true)
+ {
+ NCFGS_TRC("> do notify parent");
+
+ m_app_evt_handler(&m_ncfgs_data);
+
+ NCFGS_TRC("< do notify parent");
+ }
+ NCFGS_TRC("< wr_req: ctrlp_handle");
+ }
+ else
+ {
+ // Invalid handle.
+ reply_params.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_INVALID_HANDLE;
+ UNUSED_RETURN_VALUE(sd_ble_gatts_rw_authorize_reply(
+ p_ble_evt->evt.gap_evt.conn_handle, &reply_params));
+ }
+ }
+
+ break;
+ }
+
+ case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
+ {
+ ble_gap_data_length_params_t dl_params;
+
+ // Clearing the struct will effectively set members to @ref BLE_GAP_DATA_LENGTH_AUTO.
+ memset(&dl_params, 0, sizeof(ble_gap_data_length_params_t));
+ UNUSED_RETURN_VALUE(sd_ble_gap_data_length_update(p_ble_evt->evt.gap_evt.conn_handle, &dl_params, NULL));
+ break;
+ }
+
+ case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
+ {
+ NCFGS_TRC("> PHY update request.");
+
+ ble_gap_phys_t const phys =
+ {
+ .rx_phys = BLE_GAP_PHY_AUTO,
+ .tx_phys = BLE_GAP_PHY_AUTO,
+ };
+
+ UNUSED_RETURN_VALUE(sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
+
+ NCFGS_TRC("< PHY update request.");
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+}
+
+#endif // COMMISSIONING_ENABLED
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ble_ncfgs/ble_ncfgs.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ble_ncfgs/ble_ncfgs.h
new file mode 100644
index 0000000..b59495d
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ble_ncfgs/ble_ncfgs.h
@@ -0,0 +1,194 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/** @file
+ *
+ * @defgroup ble_ncfgs Node Configuration Service
+ * @{
+ * @ingroup iot_sdk_common
+ * @brief Node Configuration Service module.
+ *
+ * @details The Node Configuration Service allows configuration of the node during commissioning.
+ * During initialization it adds the Node Configuration Service and the corresponding
+ * characteristics to the BLE GATT database. It decodes and checks the received values
+ * and then passes them to the parent module.
+ */
+
+#ifndef BLE_NODE_CFG_H__
+#define BLE_NODE_CFG_H__
+
+#include <stdint.h>
+#include "ble.h"
+#include "app_util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BLE_UUID_NODE_CFG_SERVICE 0x7799
+#define BLE_UUID_NCFGS_SSID_CHAR 0x77A9
+#define BLE_UUID_NCFGS_KEYS_STORE_CHAR 0x77B9
+#define BLE_UUID_NCFGS_CTRLPT_CHAR 0x77C9
+
+#define APP_GATTERR_NOT_CONFIGURED BLE_GATT_STATUS_ATTERR_APP_BEGIN + 1 /**< ATT Error: Node configuration incomplete. */
+#define APP_GATTERR_UNKNOWN_OPCODE BLE_GATT_STATUS_ATTERR_APP_BEGIN + 2 /**< ATT Error: Unknown opcode. */
+#define APP_GATTERR_INVALID_ATTR_VALUE BLE_GATT_STATUS_ATTERR_APP_BEGIN + 3 /**< ATT Error: Invalid attribute value. */
+
+#define NCFGS_SSID_MIN_LEN 6 /**< SSID minimum length. */
+#define NCFGS_SSID_MAX_LEN 16 /**< SSID maximum length. */
+#define NCFGS_KEYS_MAX_LEN 16 /**< Keys maximum length. */
+#define NCFGS_IDENTITY_DATA_MAX_LEN 8 /**< Identity data maximum length. */
+
+#define NCFGS_CTRLP_OPCODE_LEN 1 /**< Ctrlp: Opcode value length. */
+#define NCFGS_CTRLP_DELAY_LEN 4 /**< Ctrlp: Length of action delay value. */
+#define NCFGS_CTRLP_DURATION_LEN 4 /**< Ctrlp: Length of next mode duration value. */
+#define NCFGS_CTRLP_STATE_ON_FAILURE_LEN 1 /**< Ctrlp: Length of state-on-failure value. */
+
+#define NCFGS_CTRLP_ALL_BUT_ID_DATA_LEN (NCFGS_CTRLP_OPCODE_LEN + \
+ NCFGS_CTRLP_DELAY_LEN + \
+ NCFGS_CTRLP_DURATION_LEN + \
+ NCFGS_CTRLP_STATE_ON_FAILURE_LEN) /**< Ctrlp: Total length of all values except identity data. */
+#define NCFGS_CTRLP_VALUE_LEN (NCFGS_CTRLP_OPCODE_LEN + \
+ NCFGS_CTRLP_DELAY_LEN + \
+ NCFGS_CTRLP_DURATION_LEN + \
+ NCFGS_CTRLP_STATE_ON_FAILURE_LEN + \
+ NCFGS_IDENTITY_DATA_MAX_LEN) /**< Ctrlp: Total length of all values. */
+
+#define HTONL(val) ((((uint32_t) (val) & 0xff000000) >> 24) | \
+ (((uint32_t) (val) & 0x00ff0000) >> 8) | \
+ (((uint32_t) (val) & 0x0000ff00) << 8) | \
+ (((uint32_t) (val) & 0x000000ff) << 24))
+
+/**@brief Node Configuration Service control point opcode values. */
+typedef enum
+{
+ NCFGS_OPCODE_GOTO_JOINING_MODE = 0x01,
+ NCFGS_OPCODE_GOTO_CONFIG_MODE = 0x02,
+ NCFGS_OPCODE_GOTO_IDENTITY_MODE = 0x03
+} ble_ncfgs_opcode_t;
+
+/**@brief Node Configuration Service configuration states. */
+typedef enum
+{
+ NCFGS_STATE_IDLE = 0x00,
+ NCFGS_STATE_SSID_WRITTEN = 0x01,
+ NCFGS_STATE_KEYS_STORE_WRITTEN = 0x02
+} ble_ncfgs_state_t;
+
+/**@brief Node Configuration Service state-on-failure values. */
+typedef enum
+{
+ NCFGS_SOF_NO_CHANGE = 0x00,
+ NCFGS_SOF_PWR_OFF = 0x01,
+ NCFGS_SOF_CONFIG_MODE = 0x02
+} state_on_failure_t;
+
+/**@brief Structure for storing keys received from the peer. */
+typedef struct __attribute__ ((__packed__))
+{
+ uint8_t keys_len;
+ uint8_t keys[NCFGS_KEYS_MAX_LEN]; // Keys received from the router.
+} keys_store_t;
+
+/**@brief Structure for storing the SSID received from the peer. */
+typedef struct __attribute__ ((__packed__))
+{
+ uint8_t ssid_len;
+ uint8_t ssid[NCFGS_SSID_MAX_LEN]; // SSID received from the router.
+} ssid_store_t;
+
+/**@brief Structure for storing the identity data from the peer. */
+typedef struct __attribute__ ((__packed__))
+{
+ uint8_t identity_data_len;
+ uint8_t identity_data[NCFGS_IDENTITY_DATA_MAX_LEN]; // Custom node identifier data.
+} id_data_store_t;
+
+/**@brief Structure for control point value. */
+typedef struct __attribute__ ((__packed__))
+{
+ ble_ncfgs_opcode_t opcode; // Mode to start.
+ uint32_t delay_sec; // Delay before entering >Opcode< mode.
+ uint32_t duration_sec; // General timeout for >Opcode< mode.
+ state_on_failure_t state_on_failure; // Mode to enter if >Opcode< mode fails (times out).
+} ble_ncfgs_ctrlp_value_t;
+
+/**@brief Structure for storing Node Configuration Service characteristic values. */
+typedef struct __attribute__ ((__packed__))
+{
+ ble_ncfgs_ctrlp_value_t ctrlp_value;
+ ssid_store_t ssid_from_router; // SSID received from the peer.
+ keys_store_t keys_from_router; // Keys received from the peer.
+ id_data_store_t id_data; // Identity data received from the peer.
+} ble_ncfgs_data_t;
+
+/**@brief Function for handling BLE events.
+ *
+ * @details This function must be called from the BLE stack event dispatcher
+ * to handle BLE events that are relevant for the Node Configuration Service module.
+ * It propagates an event to the parent layer if the Control Point characteristic
+ * was successfully written.
+ *
+ * @param[in] p_ble_evt BLE stack event.
+ */
+void ble_ncfgs_ble_evt_handler(const ble_evt_t * p_ble_evt);
+
+/**@brief Node Configuration Service event handler type. */
+typedef void (*ble_ncfgs_evt_handler_t) (ble_ncfgs_data_t * ncfgs_data);
+
+/**@brief Function for initializing the Node Configuration Service module.
+ *
+ * @details Interface for the Commissioning module to create a GATT database to
+ * allow for node configuration.
+ *
+ * @param[in] ble_ncfgs_cb Function to be called in case of an error.
+ *
+ * @retval NRF_SUCCESS If initialization was successful. Otherwise, a propagated
+ * error code is returned.
+ *
+ */
+uint32_t ble_ncfgs_init(ble_ncfgs_evt_handler_t ble_ncfgs_cb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // BLE_NODE_CFG_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/commissioning/commissioning.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/commissioning/commissioning.c
new file mode 100644
index 0000000..4ea6884
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/commissioning/commissioning.c
@@ -0,0 +1,1077 @@
+/**
+ * Copyright (c) 2015-2017 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifdef COMMISSIONING_ENABLED
+
+#include <string.h>
+#include "boards.h"
+#include "ble_hci.h"
+#include "nrf_soc.h"
+#include "app_error.h"
+#include "fds.h"
+#include "ble_advdata.h"
+#include "commissioning.h"
+#include "nordic_common.h"
+#include "ble_srv_common.h"
+#include "sdk_config.h"
+
+#define MINIMUM_ACTION_DELAY 2 /**< Delay before executing an action after the control point was written (in seconds). */
+
+#define SEC_PARAM_BOND 0 /**< Perform bonding. */
+#define SEC_PARAM_MITM 1 /**< Man In The Middle protection required (applicable when display module is detected). */
+#define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_KEYBOARD_ONLY /**< Display I/O capabilities. */
+#define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */
+#define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */
+#define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */
+
+#define COMM_FDS_FILE_ID 0xCAFE /**< The ID of the file that the record belongs to. */
+#define COMM_FDS_RECORD_KEY 0xBEAF /**< The record key of FDS record that keeps node settings. */
+
+#define NUMBER_OF_COMMISSIONING_TIMERS 4
+#define TIMER_INDEX_DELAYED_ACTION 0
+#define TIMER_INDEX_CONFIG_MODE 1
+#define TIMER_INDEX_JOINING_MODE 2
+#define TIMER_INDEX_IDENTITY_MODE 3
+
+#define SEC_TO_MILLISEC(PARAM) (PARAM * 1000)
+
+static commissioning_settings_t m_node_settings; /**< All node settings as configured through the Node Configuration Service. */
+static commissioning_evt_handler_t m_commissioning_evt_handler; /**< Commissioning event handler of the parent layer. */
+static bool m_power_off_on_failure = false; /**< Power off on failure setting from the last NCFGS event. */
+static commissioning_timer_t m_commissioning_timers[NUMBER_OF_COMMISSIONING_TIMERS];
+
+static ipv6_medium_ble_gap_params_t m_config_mode_gap_params; /**< Advertising parameters in Config mode. */
+static ipv6_medium_ble_adv_params_t m_config_mode_adv_params; /**< GAP parameters in Config mode. */
+
+static ipv6_medium_ble_gap_params_t m_joining_mode_gap_params; /**< Advertising parameters in Joining mode. */
+static ipv6_medium_ble_adv_params_t m_joining_mode_adv_params; /**< GAP parameters in Joining mode. */
+
+static ble_uuid_t m_config_mode_adv_uuids[] = \
+ {
+ {BLE_UUID_NODE_CFG_SERVICE, \
+ BLE_UUID_TYPE_VENDOR_BEGIN}
+ }; /**< Config mode: List of available service UUIDs in advertisement data. */
+
+static ble_uuid_t m_joining_mode_adv_uuids[] = \
+ {
+ {BLE_UUID_IPSP_SERVICE, BLE_UUID_TYPE_BLE}
+ }; /**< Joining mode: List of available service UUIDs in advertisement data. */
+
+static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the active connection. */
+static uint8_t m_current_mode = NODE_MODE_NONE; /**< Current mode value. */
+static uint8_t m_next_mode = NODE_MODE_NONE; /**< Value of the mode the node will enter when the timeout handler of m_delayed_action_timer is triggered. */
+
+#if (FDS_ENABLED == 1)
+static fds_record_desc_t m_fds_record_desc; /**< Descriptor of FDS record. */
+#endif
+
+#define COMM_ENABLE_LOGS 1 /**< Set to 0 to disable debug trace in the module. */
+
+#if COMMISSIONING_CONFIG_LOG_ENABLED
+
+#define NRF_LOG_MODULE_NAME commissioning
+
+#define NRF_LOG_LEVEL COMMISSIONING_CONFIG_LOG_LEVEL
+#define NRF_LOG_INFO_COLOR COMMISSIONING_CONFIG_INFO_COLOR
+#define NRF_LOG_DEBUG_COLOR COMMISSIONING_CONFIG_DEBUG_COLOR
+
+#include "nrf_log.h"
+NRF_LOG_MODULE_REGISTER();
+
+#define COMM_TRC NRF_LOG_DEBUG /**< Used for getting trace of execution in the module. */
+#define COMM_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */
+#define COMM_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */
+
+#define COMM_ENTRY() COMM_TRC(">> %s", __func__)
+#define COMM_EXIT() COMM_TRC("<< %s", __func__)
+
+#else // COMMISSIONING_CONFIG_LOG_ENABLED
+
+#define COMM_TRC(...) /**< Disables traces. */
+#define COMM_DUMP(...) /**< Disables dumping of octet streams. */
+#define COMM_ERR(...) /**< Disables error logs. */
+
+#define COMM_ENTRY(...)
+#define COMM_EXIT(...)
+
+#endif // COMMISSIONING_CONFIG_LOG_ENABLED
+
+
+/**@brief Function for validating all node settings.
+ */
+static bool settings_are_valid()
+{
+ uint8_t tmp = m_node_settings.poweron_mode;
+ if (tmp == 0xFF)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+#if (FDS_ENABLED == 1)
+/**@brief Function for updating the node settings in persistent memory.
+ */
+static uint32_t persistent_settings_update(void)
+{
+ uint32_t err_code;
+
+ fds_find_token_t token;
+ memset(&token, 0, sizeof(token));
+
+ fds_record_t record;
+ memset(&record, 0, sizeof(record));
+
+ record.file_id = COMM_FDS_FILE_ID;
+ record.key = COMM_FDS_RECORD_KEY;
+ record.data.p_data = &m_node_settings;
+ record.data.length_words = ALIGN_NUM(4, sizeof(commissioning_settings_t))/sizeof(uint32_t);
+
+ // Try to find FDS record with node settings.
+ err_code = fds_record_find(COMM_FDS_FILE_ID, COMM_FDS_RECORD_KEY, &m_fds_record_desc, &token);
+ if (err_code == FDS_SUCCESS)
+ {
+ err_code = fds_record_update(&m_fds_record_desc, &record);
+ }
+ else
+ {
+
+ err_code = fds_record_write(&m_fds_record_desc, &record);
+ }
+
+ if (err_code == FDS_ERR_NO_SPACE_IN_FLASH)
+ {
+ // Run garbage collector to reclaim the flash space that is occupied by records that have been deleted,
+ // or that failed to be completely written due to, for example, a power loss.
+ err_code = fds_gc();
+ }
+
+ return err_code;
+}
+
+
+/**@brief Function for loading node settings from the persistent memory.
+ */
+static void persistent_settings_load(void)
+{
+ uint32_t err_code = FDS_SUCCESS;
+ fds_flash_record_t record;
+
+ fds_find_token_t token;
+ memset(&token, 0, sizeof(token));
+
+ // Try to find FDS record with node settings.
+ err_code = fds_record_find(COMM_FDS_FILE_ID, COMM_FDS_RECORD_KEY, &m_fds_record_desc, &token);
+ if (err_code == FDS_SUCCESS)
+ {
+ err_code = fds_record_open(&m_fds_record_desc, &record);
+ if (err_code == FDS_SUCCESS)
+ {
+ if (record.p_data)
+ {
+ memcpy(&m_node_settings, record.p_data, sizeof(m_node_settings));
+ }
+ }
+ }
+}
+
+
+/**@brief Function for clearing node settings from the persistent memory.
+ */
+static void persistent_settings_clear(void)
+{
+ fds_record_delete(&m_fds_record_desc);
+}
+
+/**@brief Function for handling File Data Storage events.
+ */
+static void persistent_settings_cb(fds_evt_t const * p_evt)
+{
+ if (p_evt->id == FDS_EVT_GC)
+ {
+ if (settings_are_valid())
+ {
+ persistent_settings_update();
+ }
+ }
+}
+
+
+/**@brief Function for initializing the File Data Storage module.
+ */
+static uint32_t persistent_settings_init(void)
+{
+ uint32_t err_code;
+
+ err_code = fds_init();
+ if (err_code == FDS_SUCCESS)
+ {
+ err_code = fds_register(persistent_settings_cb);
+ }
+
+ return err_code;
+}
+#endif
+
+
+/**@brief Function for setting advertisement parameters in Config mode.
+ */
+static void config_mode_adv_params_set(void)
+{
+ COMM_ENTRY();
+ memset(&m_config_mode_adv_params, 0x00, sizeof(m_config_mode_adv_params));
+
+ m_config_mode_adv_params.advdata.name_type = BLE_ADVDATA_FULL_NAME;
+ m_config_mode_adv_params.advdata.include_appearance = false;
+ m_config_mode_adv_params.advdata.flags = \
+ BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
+ m_config_mode_adv_params.advdata.uuids_complete.uuid_cnt = \
+ sizeof(m_config_mode_adv_uuids) / sizeof(m_config_mode_adv_uuids[0]);
+ m_config_mode_adv_params.advdata.uuids_complete.p_uuids = m_config_mode_adv_uuids;
+ m_config_mode_adv_params.advdata.p_manuf_specific_data = NULL;
+
+ if (m_node_settings.id_data_store.identity_data_len > 0)
+ {
+ m_config_mode_adv_params.sr_man_specific_data.data.size = \
+ m_node_settings.id_data_store.identity_data_len;
+ m_config_mode_adv_params.sr_man_specific_data.data.p_data = \
+ m_node_settings.id_data_store.identity_data;
+ m_config_mode_adv_params.sr_man_specific_data.company_identifier = \
+ COMPANY_IDENTIFIER;
+ m_config_mode_adv_params.srdata.p_manuf_specific_data = \
+ &m_config_mode_adv_params.sr_man_specific_data;
+ }
+ else
+ {
+ m_config_mode_adv_params.srdata.p_manuf_specific_data = NULL;
+ }
+
+ m_config_mode_adv_params.advparams.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
+ m_config_mode_adv_params.advparams.p_peer_addr = NULL; // Undirected advertisement.
+ m_config_mode_adv_params.advparams.filter_policy = BLE_GAP_ADV_FP_ANY;
+ m_config_mode_adv_params.advparams.interval = CONFIG_MODE_ADV_ADV_INTERVAL;
+ m_config_mode_adv_params.advparams.duration = CONFIG_MODE_ADV_TIMEOUT;
+
+ COMM_EXIT();
+}
+
+
+/**@brief Function for setting GAP parameters in Config mode.
+ */
+static void config_mode_gap_params_set(void)
+{
+ COMM_ENTRY();
+
+ memset(&m_config_mode_gap_params, 0x00, sizeof(m_config_mode_gap_params));
+
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&m_config_mode_gap_params.sec_mode);
+
+ m_config_mode_gap_params.p_dev_name = (const uint8_t *)CONFIG_MODE_DEVICE_NAME;
+ m_config_mode_gap_params.dev_name_len = strlen(CONFIG_MODE_DEVICE_NAME);
+
+ m_config_mode_gap_params.gap_conn_params.min_conn_interval = \
+ (uint16_t)CONFIG_MODE_MIN_CONN_INTERVAL;
+ m_config_mode_gap_params.gap_conn_params.max_conn_interval = \
+ (uint16_t)CONFIG_MODE_MAX_CONN_INTERVAL;
+ m_config_mode_gap_params.gap_conn_params.slave_latency = CONFIG_MODE_SLAVE_LATENCY;
+ m_config_mode_gap_params.gap_conn_params.conn_sup_timeout = CONFIG_MODE_CONN_SUP_TIMEOUT;
+
+ COMM_EXIT();
+}
+
+
+/**@brief Function for setting advertisement parameters in Joining mode.
+ */
+static void joining_mode_adv_params_set(void)
+{
+ COMM_ENTRY();
+
+ memset(&m_joining_mode_adv_params, 0x00, sizeof(m_joining_mode_adv_params));
+
+ if (m_node_settings.ssid_store.ssid_len > 0)
+ {
+ m_joining_mode_adv_params.adv_man_specific_data.data.size = \
+ m_node_settings.ssid_store.ssid_len;
+ m_joining_mode_adv_params.adv_man_specific_data.data.p_data = \
+ m_node_settings.ssid_store.ssid;
+ m_joining_mode_adv_params.adv_man_specific_data.company_identifier = \
+ COMPANY_IDENTIFIER;
+ }
+
+ m_joining_mode_adv_params.advdata.name_type = BLE_ADVDATA_NO_NAME;
+ m_joining_mode_adv_params.advdata.include_appearance = false;
+ m_joining_mode_adv_params.advdata.flags = \
+ BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
+ m_joining_mode_adv_params.advdata.uuids_complete.uuid_cnt = \
+ sizeof(m_joining_mode_adv_uuids) / sizeof(m_joining_mode_adv_uuids[0]);
+ m_joining_mode_adv_params.advdata.uuids_complete.p_uuids = m_joining_mode_adv_uuids;
+ if (m_node_settings.ssid_store.ssid_len > 0)
+ {
+ m_joining_mode_adv_params.advdata.p_manuf_specific_data = \
+ &m_joining_mode_adv_params.adv_man_specific_data;
+ }
+ else
+ {
+ m_joining_mode_adv_params.advdata.p_manuf_specific_data = NULL;
+ }
+
+ if (m_node_settings.id_data_store.identity_data_len > 0)
+ {
+ m_joining_mode_adv_params.sr_man_specific_data.data.size = \
+ m_node_settings.id_data_store.identity_data_len;
+ m_joining_mode_adv_params.sr_man_specific_data.data.p_data = \
+ m_node_settings.id_data_store.identity_data;
+ m_joining_mode_adv_params.sr_man_specific_data.company_identifier = \
+ COMPANY_IDENTIFIER;
+ m_joining_mode_adv_params.srdata.p_manuf_specific_data = \
+ &m_joining_mode_adv_params.sr_man_specific_data;
+ }
+ else
+ {
+ m_joining_mode_adv_params.srdata.p_manuf_specific_data = NULL;
+ }
+
+ m_joining_mode_adv_params.advparams.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
+ m_joining_mode_adv_params.advparams.p_peer_addr = NULL; // Undirected advertisement.
+ m_joining_mode_adv_params.advparams.filter_policy = BLE_GAP_ADV_FP_ANY;
+ m_joining_mode_adv_params.advparams.interval = APP_ADV_ADV_INTERVAL;
+ m_joining_mode_adv_params.advparams.duration = APP_ADV_DURATION;
+
+ COMM_EXIT();
+}
+
+
+/**@brief Function for setting GAP parameters in Joining mode.
+ */
+static void joining_mode_gap_params_set(void)
+{
+ COMM_ENTRY();
+
+ memset(&m_joining_mode_gap_params, 0x00, sizeof(m_joining_mode_gap_params));
+
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&m_joining_mode_gap_params.sec_mode);
+
+ m_joining_mode_gap_params.appearance = BLE_APPEARANCE_UNKNOWN;
+
+ m_joining_mode_gap_params.p_dev_name = (const uint8_t *)DEVICE_NAME;
+ m_joining_mode_gap_params.dev_name_len = strlen(DEVICE_NAME);
+
+ m_joining_mode_gap_params.gap_conn_params.min_conn_interval = \
+ (uint16_t)JOINING_MODE_MIN_CONN_INTERVAL;
+ m_joining_mode_gap_params.gap_conn_params.max_conn_interval = \
+ (uint16_t)JOINING_MODE_MAX_CONN_INTERVAL;
+ m_joining_mode_gap_params.gap_conn_params.slave_latency = JOINING_MODE_SLAVE_LATENCY;
+ m_joining_mode_gap_params.gap_conn_params.conn_sup_timeout = JOINING_MODE_CONN_SUP_TIMEOUT;
+
+ COMM_EXIT();
+}
+
+
+/**@brief Function for starting a timer in the Commissioning module.
+ *
+ */
+static void commissioning_timer_start(uint8_t index, uint32_t timeout_sec)
+{
+ m_commissioning_timers[index].is_timer_running = true;
+ m_commissioning_timers[index].current_value_sec = timeout_sec;
+}
+
+
+/**@brief Function for stopping and re-setting a timer in the Commissioning module.
+ *
+ */
+static void commissioning_timer_stop_reset(uint8_t index)
+{
+ m_commissioning_timers[index].is_timer_running = false;
+ m_commissioning_timers[index].current_value_sec = 0x00;
+}
+
+
+void commissioning_node_mode_change(uint8_t new_mode)
+{
+ COMM_ENTRY();
+
+ commissioning_evt_t commissioning_evt;
+ memset(&commissioning_evt, 0x00, sizeof(commissioning_evt));
+ commissioning_evt.p_commissioning_settings = &m_node_settings;
+ commissioning_evt.power_off_enable_requested = m_power_off_on_failure;
+
+ commissioning_timer_stop_reset(TIMER_INDEX_DELAYED_ACTION);
+ commissioning_timer_stop_reset(TIMER_INDEX_CONFIG_MODE);
+ commissioning_timer_stop_reset(TIMER_INDEX_JOINING_MODE);
+
+ config_mode_gap_params_set();
+ config_mode_adv_params_set();
+ joining_mode_gap_params_set();
+ joining_mode_adv_params_set();
+
+ m_current_mode = new_mode;
+
+ switch (m_current_mode)
+ {
+ case NODE_MODE_CONFIG:
+ {
+ commissioning_evt.commissioning_evt_id = COMMISSIONING_EVT_CONFIG_MODE_ENTER;
+ m_commissioning_evt_handler(&commissioning_evt);
+
+ // Start Configuration mode timer.
+ COMM_TRC("Config mode timeout: %ld seconds", m_node_settings.config_mode_to);
+ commissioning_timer_start(TIMER_INDEX_CONFIG_MODE, m_node_settings.config_mode_to);
+
+ break;
+ }
+ case NODE_MODE_JOINING:
+ {
+ commissioning_evt.commissioning_evt_id = COMMISSIONING_EVT_JOINING_MODE_ENTER;
+ m_commissioning_evt_handler(&commissioning_evt);
+
+ // Start Joining mode timer.
+ COMM_TRC("Joining mode timeout: %ld seconds", m_node_settings.joining_mode_to);
+ commissioning_timer_start(TIMER_INDEX_JOINING_MODE, m_node_settings.joining_mode_to);
+
+ break;
+ }
+ case NODE_MODE_IDENTITY:
+ {
+ commissioning_evt.commissioning_evt_id = COMMISSIONING_EVT_IDENTITY_MODE_ENTER;
+ m_commissioning_evt_handler(&commissioning_evt);
+
+ // Start Identity mode timer.
+ COMM_TRC("Identity mode timeout: %ld seconds", m_node_settings.id_mode_to);
+ commissioning_timer_start(TIMER_INDEX_IDENTITY_MODE, m_node_settings.id_mode_to);
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ COMM_EXIT();
+}
+
+
+/**@brief Function for handling the Delayed action timer timeout.
+ *
+ * @details This function will be called each time the delayed action timer expires.
+ *
+ */
+static void action_timeout_handler(void)
+{
+ COMM_ENTRY();
+
+ commissioning_node_mode_change(m_next_mode);
+
+ COMM_EXIT();
+}
+
+
+/**@brief Function for handling the Config mode timer timeout.
+ *
+ * @details This function will be called each time the Config mode timer expires.
+ *
+ */
+static void config_mode_timeout_handler(void)
+{
+ COMM_ENTRY();
+
+ switch (m_node_settings.config_mode_failure)
+ {
+ case NCFGS_SOF_NO_CHANGE:
+ // Fall-through.
+ case NCFGS_SOF_CONFIG_MODE:
+ {
+ commissioning_node_mode_change(NODE_MODE_CONFIG);
+
+ break;
+ }
+ case NCFGS_SOF_PWR_OFF:
+ {
+ LEDS_OFF(LEDS_MASK);
+ // The main timer in Config mode timed out, power off.
+ UNUSED_VARIABLE(sd_power_system_off());
+
+ break;
+ }
+ }
+
+ COMM_EXIT();
+}
+
+
+/**@brief Function for handling the Joining mode timer timeout.
+ *
+ * @details This function will be called each time the Joining mode timer expires.
+ *
+ */
+void joining_mode_timeout_handler(void)
+{
+ COMM_ENTRY();
+
+ switch (m_node_settings.joining_mode_failure)
+ {
+ case NCFGS_SOF_NO_CHANGE:
+ {
+ commissioning_node_mode_change(NODE_MODE_JOINING);
+ break;
+ }
+ case NCFGS_SOF_PWR_OFF:
+ {
+ LEDS_OFF(LEDS_MASK);
+
+ UNUSED_VARIABLE(sd_power_system_off());
+ break;
+ }
+ case NCFGS_SOF_CONFIG_MODE:
+ {
+ commissioning_node_mode_change(NODE_MODE_CONFIG);
+ break;
+ }
+ }
+
+ COMM_EXIT();
+}
+
+
+/**@brief Function for handling the Identity mode timer timeout.
+ *
+ * @details This function will be called each time the Identity mode timer expires.
+ *
+ */
+void identity_mode_timeout_handler(void)
+{
+ COMM_ENTRY();
+
+ commissioning_evt_t commissioning_evt;
+ memset(&commissioning_evt, 0x00, sizeof(commissioning_evt));
+ commissioning_evt.commissioning_evt_id = COMMISSIONING_EVT_IDENTITY_MODE_EXIT;
+
+ m_commissioning_evt_handler(&commissioning_evt);
+
+ COMM_EXIT();
+}
+
+
+void commissioning_joining_mode_timer_ctrl( \
+ joining_mode_timer_ctrl_cmd_t joining_mode_timer_ctrl_cmd)
+{
+ switch (joining_mode_timer_ctrl_cmd)
+ {
+ case JOINING_MODE_TIMER_STOP_RESET:
+ {
+ commissioning_timer_stop_reset(TIMER_INDEX_JOINING_MODE);
+
+ break;
+ }
+ case JOINING_MODE_TIMER_START:
+ {
+ commissioning_timer_start(TIMER_INDEX_JOINING_MODE, m_node_settings.joining_mode_to);
+
+ break;
+ }
+ }
+}
+
+
+void commissioning_gap_params_get(ipv6_medium_ble_gap_params_t ** pp_node_gap_params)
+{
+ switch (m_current_mode)
+ {
+ case NODE_MODE_JOINING:
+ {
+ *pp_node_gap_params = &m_joining_mode_gap_params;
+
+ break;
+ }
+ case NODE_MODE_IDENTITY:
+ // Fall-through.
+ case NODE_MODE_CONFIG:
+ {
+ *pp_node_gap_params = &m_config_mode_gap_params;
+
+ break;
+ }
+ }
+}
+
+
+void commissioning_adv_params_get(ipv6_medium_ble_adv_params_t ** pp_node_adv_params)
+{
+ switch (m_current_mode)
+ {
+ case NODE_MODE_JOINING:
+ {
+ *pp_node_adv_params = &m_joining_mode_adv_params;
+
+ break;
+ }
+ case NODE_MODE_IDENTITY:
+ // Fall-through.
+ case NODE_MODE_CONFIG:
+ {
+ *pp_node_adv_params = &m_config_mode_adv_params;
+
+ break;
+ }
+ }
+}
+
+
+/**@brief Function for reading all node settings from the persistent storage.
+ */
+static void read_node_settings(void)
+{
+ memset(&m_node_settings, 0x00, sizeof(m_node_settings));
+
+#if (FDS_ENABLED == 1)
+ persistent_settings_load();
+#endif // FDS_ENABLED
+
+ if (m_node_settings.ssid_store.ssid_len > NCFGS_SSID_MAX_LEN)
+ {
+ m_node_settings.ssid_store.ssid_len = 0;
+ }
+ if (m_node_settings.keys_store.keys_len > NCFGS_KEYS_MAX_LEN)
+ {
+ m_node_settings.keys_store.keys_len = 0;
+ }
+ if (m_node_settings.id_data_store.identity_data_len > NCFGS_IDENTITY_DATA_MAX_LEN)
+ {
+ m_node_settings.id_data_store.identity_data_len = 0;
+ }
+
+ // The duration of each mode needs to be at least 10 second.
+ m_node_settings.joining_mode_to = \
+ (m_node_settings.joining_mode_to < 10) ? 10 : m_node_settings.joining_mode_to;
+ m_node_settings.config_mode_to = \
+ (m_node_settings.config_mode_to < 10) ? 10 : m_node_settings.config_mode_to;
+ m_node_settings.id_mode_to = \
+ (m_node_settings.id_mode_to < 10) ? 10 : m_node_settings.id_mode_to;
+}
+
+#if (COMM_ENABLE_LOGS == 1)
+/**@brief Function for printing all node settings.
+ */
+static void print_node_settings(void)
+{
+ COMM_TRC("");
+ COMM_TRC(" Commissioning settings in memory:");
+ COMM_TRC(" Start mode: %5d", m_node_settings.poweron_mode);
+ COMM_TRC(" Mode if Joining Mode fails: %5d", m_node_settings.joining_mode_failure);
+ COMM_TRC(" General timeout in Joining Mode: %5ld", m_node_settings.joining_mode_to);
+ COMM_TRC(" Mode if Configuration Mode fails: %5d", m_node_settings.config_mode_failure);
+ COMM_TRC("General timeout in Configuration Mode: %5ld", m_node_settings.config_mode_to);
+ COMM_TRC(" Identity Mode duration: %5ld", m_node_settings.id_mode_to);
+ COMM_TRC(" Stored Keys length: %5d", m_node_settings.keys_store.keys_len);
+ COMM_TRC(" Stored Keys:");
+ uint8_t ii;
+ for (ii=0; ii<m_node_settings.keys_store.keys_len; ++ii)
+ {
+ COMM_TRC("0x%02X", m_node_settings.keys_store.keys[ii]);
+ }
+ COMM_TRC("");
+ COMM_TRC(" Stored SSID length: %5d", m_node_settings.ssid_store.ssid_len);
+ COMM_TRC(" Stored SSID:");
+ for (ii=0; ii<m_node_settings.ssid_store.ssid_len; ++ii)
+ {
+ COMM_TRC("0x%02X", m_node_settings.ssid_store.ssid[ii]);
+ }
+ COMM_TRC("");
+ COMM_TRC(" Stored Identity Data length: %5d", m_node_settings.id_data_store.identity_data_len);
+ COMM_TRC(" Stored Identity Data:");
+ for (ii=0; ii<m_node_settings.id_data_store.identity_data_len; ++ii)
+ {
+ COMM_TRC("0x%02X", m_node_settings.id_data_store.identity_data[ii]);
+ }
+ COMM_TRC("");
+}
+#endif // (COMM_ENABLE_LOGS == 1)
+
+
+void commissioning_settings_clear(void)
+{
+ COMM_ENTRY();
+ memset(&m_node_settings, 0x00, sizeof(m_node_settings));
+
+#if (FDS_ENABLED == 1)
+ persistent_settings_clear();
+#endif // FDS_ENABLED
+
+ COMM_EXIT();
+}
+
+
+void commissioning_ble_evt_handler(const ble_evt_t * p_ble_evt)
+{
+ uint32_t err_code;
+
+ switch (p_ble_evt->header.evt_id)
+ {
+ case BLE_GAP_EVT_CONNECTED:
+ {
+ m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
+ commissioning_timer_stop_reset(TIMER_INDEX_DELAYED_ACTION);
+ commissioning_timer_stop_reset(TIMER_INDEX_CONFIG_MODE);
+
+ break;
+ }
+ case BLE_GAP_EVT_DISCONNECTED:
+ {
+ m_conn_handle = BLE_CONN_HANDLE_INVALID;
+ if (m_current_mode == NODE_MODE_CONFIG)
+ {
+ commissioning_timer_start(TIMER_INDEX_CONFIG_MODE, \
+ m_node_settings.config_mode_to);
+ }
+ if (m_current_mode == NODE_MODE_JOINING)
+ {
+ commissioning_timer_start(TIMER_INDEX_JOINING_MODE, \
+ m_node_settings.joining_mode_to);
+ }
+
+ break;
+ }
+ case BLE_GAP_EVT_AUTH_KEY_REQUEST:
+ {
+ if (m_current_mode == NODE_MODE_JOINING)
+ {
+ // If passkey is shorter than BLE_GAP_PASSKEY_LEN, add '0' character.
+ if (m_node_settings.keys_store.keys_len < BLE_GAP_PASSKEY_LEN)
+ {
+ memset(&m_node_settings.keys_store.keys[m_node_settings.keys_store.keys_len], \
+ '0', BLE_GAP_PASSKEY_LEN - m_node_settings.keys_store.keys_len);
+ }
+
+ // Short passkey to 6-length character.
+ m_node_settings.keys_store.keys[BLE_GAP_PASSKEY_LEN] = 0;
+
+ COMM_TRC("Stored passkey is: %s", m_node_settings.keys_store.keys);
+
+ err_code = sd_ble_gap_auth_key_reply(m_conn_handle, \
+ BLE_GAP_AUTH_KEY_TYPE_PASSKEY, \
+ m_node_settings.keys_store.keys);
+ APP_ERROR_CHECK(err_code);
+ }
+
+ break;
+ }
+ case BLE_GAP_EVT_AUTH_STATUS:
+ {
+ if (m_current_mode == NODE_MODE_JOINING)
+ {
+ COMM_TRC("Status of authentication: %08x", \
+ p_ble_evt->evt.gap_evt.params.auth_status.auth_status);
+ }
+
+ break;
+ }
+ case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
+ {
+ if (m_current_mode == NODE_MODE_JOINING)
+ {
+ ble_gap_sec_params_t sec_param;
+ ble_gap_sec_keyset_t keys_exchanged;
+
+ memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));
+ memset(&keys_exchanged, 0, sizeof(ble_gap_sec_keyset_t));
+
+ sec_param.bond = SEC_PARAM_BOND;
+ sec_param.oob = SEC_PARAM_OOB;
+ sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
+ sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
+ sec_param.mitm = SEC_PARAM_MITM;
+ sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES;
+
+ err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle,
+ BLE_GAP_SEC_STATUS_SUCCESS,
+ &sec_param,
+ &keys_exchanged);
+ APP_ERROR_CHECK(err_code);
+ }
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+
+void on_ble_ncfgs_evt(ble_ncfgs_data_t * ncfgs_data)
+{
+ COMM_ENTRY();
+
+ commissioning_timer_stop_reset(TIMER_INDEX_DELAYED_ACTION);
+ commissioning_timer_stop_reset(TIMER_INDEX_CONFIG_MODE);
+
+ uint32_t mode_duration_sec;
+ mode_duration_sec = ncfgs_data->ctrlp_value.duration_sec;
+ mode_duration_sec = (mode_duration_sec == 0) ? 1 : mode_duration_sec;
+
+ switch (ncfgs_data->ctrlp_value.opcode)
+ {
+ case NCFGS_OPCODE_GOTO_JOINING_MODE:
+ {
+ m_next_mode = NODE_MODE_JOINING;
+
+ m_node_settings.joining_mode_to = mode_duration_sec;
+ m_node_settings.joining_mode_failure = ncfgs_data->ctrlp_value.state_on_failure;
+
+ /* This code will get executed in two scenarios:
+ - if the previous mode was Config mode and now we are ready to connect to the router, or
+ - if the previous mode was Joining mode and the state on failure was set to No Change.
+ */
+ if (m_node_settings.joining_mode_failure == NCFGS_SOF_NO_CHANGE)
+ {
+ m_node_settings.poweron_mode = NODE_MODE_JOINING;
+ }
+ else
+ {
+ // If the state on failure is NOT No Change, start next time in Config mode.
+ m_node_settings.poweron_mode = NODE_MODE_CONFIG;
+ }
+
+ if (m_node_settings.joining_mode_failure == NCFGS_SOF_PWR_OFF)
+ {
+ COMM_TRC("Will power off on failure.");
+ m_power_off_on_failure = true; // The assert handler will power off the system.
+ }
+
+ break;
+ }
+ case NCFGS_OPCODE_GOTO_CONFIG_MODE:
+ {
+ m_next_mode = NODE_MODE_CONFIG;
+
+ m_node_settings.config_mode_to = mode_duration_sec;
+ m_node_settings.config_mode_failure = ncfgs_data->ctrlp_value.state_on_failure;
+
+ /* The node is about to enter Config mode. Regardless of what the state on failure
+ setting is (No Change or Pwr Off or Cfg Mode), the poweron_mode value should be Cfg Mode. */
+ m_node_settings.poweron_mode = NODE_MODE_CONFIG;
+
+ if (m_node_settings.config_mode_failure == NCFGS_SOF_PWR_OFF)
+ {
+ COMM_TRC("Will power off on failure.");
+ m_power_off_on_failure = true; // The assert handler will power off the system.
+ }
+
+ break;
+ }
+ case NCFGS_OPCODE_GOTO_IDENTITY_MODE:
+ {
+ m_next_mode = NODE_MODE_IDENTITY;
+
+ m_node_settings.id_mode_to = mode_duration_sec;
+
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ memcpy(&m_node_settings.ssid_store, &ncfgs_data->ssid_from_router, sizeof(ssid_store_t));
+ memcpy(&m_node_settings.keys_store, &ncfgs_data->keys_from_router, sizeof(keys_store_t));
+ memcpy(&m_node_settings.id_data_store, &ncfgs_data->id_data, sizeof(id_data_store_t));
+
+#if (COMM_ENABLE_LOGS == 1)
+ print_node_settings();
+#endif // (COMM_ENABLE_LOGS == 1)
+
+#if (FDS_ENABLED == 1)
+ uint32_t err_code = persistent_settings_update();
+ APP_ERROR_CHECK(err_code);
+#endif // FDS_ENABLED
+
+ uint32_t action_delay_written = ncfgs_data->ctrlp_value.delay_sec;
+ // Set the timeout value to at least MINIMUM_ACTION_DELAY second(s).
+ // This is to make sure that storing settings in the persistent
+ // storage completes before activating the next mode.
+ action_delay_written = (action_delay_written < MINIMUM_ACTION_DELAY) ? \
+ MINIMUM_ACTION_DELAY : action_delay_written;
+
+ COMM_TRC("Action delay: %ld seconds.", action_delay_written);
+ commissioning_timer_start(TIMER_INDEX_DELAYED_ACTION, action_delay_written);
+
+ COMM_EXIT();
+}
+
+
+void commissioning_time_tick(iot_timer_time_in_ms_t wall_clock_value)
+{
+ UNUSED_PARAMETER(wall_clock_value);
+ uint8_t index;
+
+ for (index=0; index<NUMBER_OF_COMMISSIONING_TIMERS; ++index)
+ {
+ if (m_commissioning_timers[index].is_timer_running == true)
+ {
+ m_commissioning_timers[index].current_value_sec -= COMMISSIONING_TICK_INTERVAL_SEC;
+
+ if (m_commissioning_timers[index].current_value_sec == 0)
+ {
+ commissioning_timer_stop_reset(index);
+ m_commissioning_timers[index].timeout_handler();
+ }
+ }
+ }
+}
+
+
+static void commissioning_timers_init(void)
+{
+ memset(m_commissioning_timers, 0x00, sizeof(m_commissioning_timers));
+ m_commissioning_timers[TIMER_INDEX_DELAYED_ACTION].timeout_handler = \
+ action_timeout_handler;
+ m_commissioning_timers[TIMER_INDEX_CONFIG_MODE].timeout_handler = \
+ config_mode_timeout_handler;
+ m_commissioning_timers[TIMER_INDEX_JOINING_MODE].timeout_handler = \
+ joining_mode_timeout_handler;
+ m_commissioning_timers[TIMER_INDEX_IDENTITY_MODE].timeout_handler = \
+ identity_mode_timeout_handler;
+}
+
+uint32_t commissioning_init(commissioning_init_params_t * p_init_param, \
+ uint8_t * p_poweron_state)
+{
+ COMM_ENTRY();
+ uint32_t err_code = NRF_SUCCESS;
+
+ m_commissioning_evt_handler = p_init_param->commissioning_evt_handler;
+ m_power_off_on_failure = false;
+
+ // Initialize Commissioning timers.
+
+ commissioning_timers_init();
+
+ // Initialize GATT server.
+
+ err_code = ble_ncfgs_init(on_ble_ncfgs_evt);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+#if (FDS_ENABLED == 1)
+ err_code = persistent_settings_init();
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+#endif
+
+ // Read application settings from persistent storage.
+ read_node_settings();
+
+#if (COMM_ENABLE_LOGS == 1)
+ print_node_settings();
+#endif // (COMM_ENABLE_LOGS == 1)
+
+ if (!settings_are_valid()) // If the settings are invalid for any reason go to Config mode.
+ {
+ COMM_ERR("Invalid settings!");
+
+ commissioning_settings_clear();
+
+ memset(&m_node_settings, 0x00, sizeof(m_node_settings));
+ m_node_settings.config_mode_to = 300;
+
+ *p_poweron_state = NODE_MODE_CONFIG;
+ }
+ else
+ {
+ if (m_node_settings.poweron_mode == NODE_MODE_JOINING)
+ {
+ /* This code will get executed in two scenarios:
+ - if the previous mode was Config mode and now we are ready to connect to the router, or
+ - if the previous mode was Joining mode and the state on failure was set to No Change.
+ */
+ if ((m_node_settings.joining_mode_failure == NCFGS_SOF_PWR_OFF) || \
+ (m_node_settings.joining_mode_failure == NCFGS_SOF_CONFIG_MODE))
+ {
+ // If the state on failure is NOT No Change, start next time in Config mode.
+ m_node_settings.poweron_mode = NODE_MODE_CONFIG;
+#if (FDS_ENABLED == 1)
+ err_code = persistent_settings_update();
+ APP_ERROR_CHECK(err_code);
+#endif // FDS_ENABLED
+ }
+
+ if (m_node_settings.joining_mode_failure == NCFGS_SOF_PWR_OFF)
+ {
+ COMM_TRC("Will power off on failure.");
+ m_power_off_on_failure = true; // The assert handler will power off the system.
+ }
+
+ *p_poweron_state = NODE_MODE_JOINING;
+ }
+ else
+ {
+ /* The app is about to enter Config mode. Regardless of what the state on failure
+ setting is (No Change or Pwr Off or Cfg Mode), the poweron_mode value should remain the same. */
+
+ if (m_node_settings.config_mode_failure == NCFGS_SOF_PWR_OFF)
+ {
+ COMM_TRC("Will power off on failure.");
+ m_power_off_on_failure = true; // The assert handler will power off the system.
+ }
+
+ *p_poweron_state = NODE_MODE_CONFIG;
+ }
+ }
+
+ // Set advertising and GAP parameters.
+ config_mode_gap_params_set();
+ config_mode_adv_params_set();
+ joining_mode_gap_params_set();
+ joining_mode_adv_params_set();
+
+ COMM_EXIT();
+ return err_code;
+}
+
+#endif // COMMISSIONING_ENABLED
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/commissioning/commissioning.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/commissioning/commissioning.h
new file mode 100644
index 0000000..777f60e
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/commissioning/commissioning.h
@@ -0,0 +1,207 @@
+/**
+ * Copyright (c) 2015-2017 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/** @file
+ *
+ * @defgroup commissioning_module Commissioning Module
+ * @{
+ * @ingroup iot_sdk_common
+ * @brief Commissioning module.
+ *
+ * @details Enables commissioning of the node by managing transitions between the Config, Joining, and
+ * Identity modes. In Config mode the node can be configured with the settings required to
+ * join the network in Joining mode. The Identity mode can be requested to make the node
+ * easily recognizable for the user.
+ * The settings managed by the module are stored in persistent storage.
+ */
+
+#ifndef COMMISSIONING_H__
+#define COMMISSIONING_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "ble_ncfgs.h"
+#include "iot_timer.h"
+#include "ipv6_medium_ble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define COMMISSIONING_TICK_INTERVAL_SEC 1 /**< Interval between periodic callbacks to the Commissioning module. */
+
+#define COMMISSIONING_EVT_CONFIG_MODE_ENTER 0x01 /**< Indicates that the medium entered mode for commissioning configuration. */
+#define COMMISSIONING_EVT_JOINING_MODE_ENTER 0x02 /**< Indicates that the medium exited mode for commissioning configuration. */
+#define COMMISSIONING_EVT_IDENTITY_MODE_ENTER 0x03 /**< Indicates that identity mode was requested. */
+#define COMMISSIONING_EVT_IDENTITY_MODE_EXIT 0x04 /**< Indicates that the node should stop using any features associated with the Identity mode. */
+
+#define NODE_MODE_NONE 0x00 /**< Node mode: before initialization. */
+#define NODE_MODE_JOINING 0x01 /**< Node mode: joining the network. */
+#define NODE_MODE_CONFIG 0x02 /**< Node mode: configuration. */
+#define NODE_MODE_IDENTITY 0x03 /**< Node mode: conspicuous for the user. */
+
+/**@brief Joining mode timer control commands. */
+typedef enum
+{
+ JOINING_MODE_TIMER_START = 0x01,
+ JOINING_MODE_TIMER_STOP_RESET = 0x02
+} joining_mode_timer_ctrl_cmd_t;
+
+/**@brief Structure for storing all settings necessary for commissioning. */
+typedef struct __attribute__ ((__packed__)) __attribute__((aligned))
+{
+ uint8_t poweron_mode; // Checked at startup to enter correct mode.
+ state_on_failure_t joining_mode_failure; // Mode to enter if Joining mode fails.
+ uint32_t joining_mode_to; // General timeout in Joining mode.
+ state_on_failure_t config_mode_failure; // Mode to enter if Config mode fails.
+ uint32_t config_mode_to; // General timeout in Config mode.
+ uint32_t id_mode_to; // Duration of Identity Mode.
+ ssid_store_t ssid_store; // SSID received from the router.
+ keys_store_t keys_store; // Keys received from the router.
+ id_data_store_t id_data_store; // Custom node identifier data.
+} commissioning_settings_t;
+
+/**@brief Commissioning module event handler type. */
+typedef void (*commissioning_timeout_handler_t)(void);
+
+/**@brief Structure for creating timers in the Commissioning module. */
+typedef struct
+{
+ bool is_timer_running;
+ uint32_t current_value_sec;
+ commissioning_timeout_handler_t timeout_handler;
+} commissioning_timer_t;
+
+/**@brief Structure of events passed by the Commissioning module to the parent layer. */
+typedef struct
+{
+ uint8_t commissioning_evt_id;
+ bool power_off_enable_requested;
+ commissioning_settings_t * p_commissioning_settings;
+} commissioning_evt_t;
+
+/**@brief Function for handling BLE events.
+ *
+ * @details This function must be called from the BLE stack event dispatcher
+ * to handle BLE events that are relevant for the Commissioning module.
+ *
+ * @param[in] p_ble_evt BLE stack event.
+ */
+void commissioning_ble_evt_handler(const ble_evt_t * p_ble_evt);
+
+/**@brief Commissioning module event handler type. */
+typedef void (*commissioning_evt_handler_t)(commissioning_evt_t * p_commissioning_evt);
+
+/**@brief Structure for initialization parameters of the Commissioning module. */
+typedef struct
+{
+ commissioning_evt_handler_t commissioning_evt_handler;
+} commissioning_init_params_t;
+
+/**@brief Function for initializing the Commissioning module.
+ *
+ * @details Initializes the Node Configuration Service module to create the GATT database.
+ * Loads previously stored node settings from the persistent storage and if
+ * the settings are valid, sets up the node to start in the right mode.
+ *
+ * @param[in] p_init_param Pointer to the initialization parameters.
+ * @param[out] p_poweron_state Pointer to the value of the mode that should be started.
+ *
+ * @retval NRF_SUCCESS If initialization was successful. Otherwise, a propagated
+ * error code is returned.
+ *
+ */
+uint32_t commissioning_init(commissioning_init_params_t * p_init_param,
+ uint8_t * p_poweron_state);
+
+/**@brief Function for advancing the node to a new mode.
+ *
+ * @details Stops and starts app timers appropriate for the mode requested.
+ * Propagates the mode change event to the parent layer.
+ *
+ * @param[in] new_mode New mode to start.
+ *
+ */
+void commissioning_node_mode_change(uint8_t new_mode);
+
+/**@brief Function for getting the address of GAP parameters for the active mode.
+ *
+ * @param[out] pp_node_gap_params Address of GAP parameters for the active mode.
+ *
+ */
+void commissioning_gap_params_get(ipv6_medium_ble_gap_params_t ** pp_node_gap_params);
+
+/**@brief Function for getting the address of advertising parameters for the active mode.
+ *
+ * @param[out] pp_node_adv_params Address of advertising parameters for the active mode.
+ *
+ */
+void commissioning_adv_params_get(ipv6_medium_ble_adv_params_t ** pp_node_adv_params);
+
+/**@brief Function for clearing all node settings from the persistent storage.
+ *
+ * @details Calls the appropriate persistent storage interface function to clear
+ * all commissioning-related settings from the persistent storage.
+ *
+ */
+void commissioning_settings_clear(void);
+
+/**@brief Function for controlling the joining mode timer from the parent layer(s).
+ *
+ * @details If the Joining mode timer reaches zero, the node must enter the
+ * state-on-failure, as set by the user. This function allows the
+ * application designer to control the Joining mode timer from the
+ * application layer.
+ */
+void commissioning_joining_mode_timer_ctrl(
+ joining_mode_timer_ctrl_cmd_t joining_mode_timer_ctrl_cmd);
+
+/**@brief Commissioning time tick used for measuring delays and time between events.
+ *
+ * @param[in] wall_clock_value Wall clock value from the IoT Timer module.
+ */
+void commissioning_time_tick(iot_timer_time_in_ms_t wall_clock_value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // COMMISSIONING_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium.h
new file mode 100644
index 0000000..064737d
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium.h
@@ -0,0 +1,238 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/** @file
+ *
+ * @defgroup ipv6_medium IPv6 Medium
+ * @{
+ * @ingroup iot_sdk_common
+ * @brief IPv6 Medium Interface.
+ *
+ * @details Implementation-agnostic interface of the physical transport that
+ * facilitates IPv6 traffic.
+ */
+
+#ifndef IPV6_MEDIUM_H__
+#define IPV6_MEDIUM_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "ipv6_medium_platform.h"
+#include "iot_defines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EUI_48_SIZE 6 /**< Size of a 48-bit Extended Unique Identifier in bytes. */
+
+#define IPV6_MEDIUM_ID_ANY 0x00 /**< Indicates invalid physical transport type. */
+#define IPV6_MEDIUM_ID_BLE 0x01 /**< Indicates that the physical transport is BLE. */
+#define IPV6_MEDIUM_ID_802154 0x02 /**< Indicates that the physical transport is 802.15.4. */
+
+#define IPV6_MEDIUM_EVT_CONN_DOWN 0x01 /**< Indicates that a connection is established. */
+#define IPV6_MEDIUM_EVT_CONN_UP 0x02 /**< Indicates that a connection is torn down. */
+#define IPV6_MEDIUM_EVT_CONNECTABLE_MODE_ENTER 0x01 /**< Indicates that the medium entered connectable mode. */
+#define IPV6_MEDIUM_EVT_CONNECTABLE_MODE_EXIT 0x02 /**< Indicates that the medium exited connectable mode. */
+#define IPV6_MEDIUM_EVT_MAC_ADDRESS_CHANGED 0x03 /**< Indicates that the device has a new MAC address. */
+#define IPV6_MEDIUM_EVT_PHY_SPECIFIC 0xFF /**< Indicates miscellaneous event from the physical layer. */
+
+/**@brief IPv6 medium instance identifier type. */
+typedef uint32_t ipv6_medium_instance_id_t;
+
+/**@brief Type of IPv6 medium type. */
+typedef uint8_t ipv6_medium_type_t;
+
+/**@brief IPv6 medium instance type. */
+typedef struct
+{
+ ipv6_medium_instance_id_t ipv6_medium_instance_id;
+ ipv6_medium_type_t ipv6_medium_instance_type;
+} ipv6_medium_instance_t;
+
+/**@brief EUI-48 value type. */
+typedef struct
+{
+ uint8_t identifier[EUI_48_SIZE]; /**< 48-bit identifier. */
+} eui48_t;
+
+/**@brief Type of IPv6 medium event parameters. */
+typedef struct
+{
+ ipv6_medium_instance_t ipv6_medium_instance_id;
+ uint8_t ipv6_medium_evt_id;
+ ipv6_medium_cb_params_union_t medium_specific;
+} ipv6_medium_evt_t;
+
+/**@brief Type of IPv6 medium error parameters. */
+typedef struct
+{
+ ipv6_medium_instance_t ipv6_medium_instance_id;
+ uint32_t error_label;
+ ipv6_medium_err_params_union_t medium_specific;
+} ipv6_medium_error_t;
+
+/**@brief IPv6 medium event handler type. */
+typedef void (*ipv6_medium_evt_handler_t)(ipv6_medium_evt_t * p_ipv6_medium_evt);
+
+/**@brief IPv6 medium error handler type. */
+typedef void (*ipv6_medium_error_handler_t)(ipv6_medium_error_t * p_ipv6_medium_error);
+
+#ifdef COMMISSIONING_ENABLED
+/**@brief Commissioning mode control commands. */
+typedef enum
+{
+ CMD_IDENTITY_MODE_EXIT = 0x00,
+ CMD_IDENTITY_MODE_ENTER = 0x01
+} mode_control_cmd_t;
+
+/**@brief Commissioning: Identity mode control callback function type. */
+typedef void (*commissioning_id_mode_cb_t)(mode_control_cmd_t control_command);
+
+/**@brief Commissioning: Power off on failure control callback function type. */
+typedef void (*commissioning_poweroff_cb_t)(bool do_poweroff_on_failure);
+#endif // COMMISSIONING_ENABLED
+
+/**@brief Structure for initialization parameters of the IPv6 medium. */
+typedef struct
+{
+ ipv6_medium_evt_handler_t ipv6_medium_evt_handler;
+ ipv6_medium_error_handler_t ipv6_medium_error_handler;
+#ifdef COMMISSIONING_ENABLED
+ commissioning_id_mode_cb_t commissioning_id_mode_cb;
+ commissioning_poweroff_cb_t commissioning_power_off_cb;
+#endif // COMMISSIONING_ENABLED
+} ipv6_medium_init_params_t;
+
+/**@brief Function for initializing the IPv6 medium.
+ *
+ * @details Initializes the IPv6 medium module.
+ * Performs all setup necessary that is specific to the implementation.
+ *
+ * @param[in] p_init_param Pointer to the initialization parameters.
+ * @param[in] desired_medium_type Value of the desired medium type.
+ * @param[out] p_new_medium_instance Pointer to the new medium instance initialized.
+ *
+ * @retval NRF_SUCCESS If initialization was successful. Otherwise, a propagated
+ * error code is returned.
+ *
+ */
+uint32_t ipv6_medium_init(ipv6_medium_init_params_t * p_init_param,
+ ipv6_medium_type_t desired_medium_type,
+ ipv6_medium_instance_t * p_new_medium_instance);
+
+/**@brief Function for entering connectible mode.
+ *
+ * @details Requests the IPv6 medium to enter connectible mode.
+ *
+ * @param[in] ipv6_medium_instance_id Specifies the IPv6 medium instance.
+ *
+ * @retval NRF_SUCCESS If the procedure was successful. Otherwise, a propagated
+ * error code is returned.
+ *
+ */
+uint32_t ipv6_medium_connectable_mode_enter(ipv6_medium_instance_id_t ipv6_medium_instance_id);
+
+/**@brief Function for exiting connectible mode.
+ *
+ * @details Requests the IPv6 medium to exit connectible mode.
+ *
+ * @param[in] ipv6_medium_instance_id Specifies the IPv6 medium instance.
+ *
+ * @retval NRF_SUCCESS If the procedure was successful. Otherwise, a propagated
+ * error code is returned.
+ *
+ */
+uint32_t ipv6_medium_connectable_mode_exit(ipv6_medium_instance_id_t ipv6_medium_instance_id);
+
+/**@brief Function for getting the 48-bit Extended Unique Identifier.
+ *
+ * @param[in] ipv6_medium_instance_id Specifies the IPv6 medium instance.
+ * @param[out] p_ipv6_medium_eui48 Pointer to the EUI-48 value.
+ *
+ * @retval NRF_SUCCESS If the procedure was successful. Otherwise, a propagated
+ * error code is returned.
+ *
+ */
+uint32_t ipv6_medium_eui48_get(ipv6_medium_instance_id_t ipv6_medium_instance_id,
+ eui48_t * p_ipv6_medium_eui48);
+
+/**@brief Function for setting the 48-bit Extended Unique Identifier.
+ *
+ * @param[in] ipv6_medium_instance_id Specifies the IPv6 medium instance.
+ * @param[in] p_ipv6_medium_eui48 Pointer to the EUI-48 value.
+ *
+ * @retval NRF_SUCCESS If the procedure was successful. Otherwise, a propagated
+ * error code is returned.
+ *
+ */
+uint32_t ipv6_medium_eui48_set(ipv6_medium_instance_id_t ipv6_medium_instance_id,
+ eui48_t * p_ipv6_medium_eui48);
+
+/**@brief Function for getting the 64-bit Extended Unique Identifier.
+ *
+ * @param[in] ipv6_medium_instance_id Specifies the IPv6 medium instance.
+ * @param[out] p_ipv6_medium_eui64 Pointer to the EUI-64 value.
+ *
+ * @retval NRF_SUCCESS If the procedure was successful. Otherwise, a propagated
+ * error code is returned.
+ *
+ */
+uint32_t ipv6_medium_eui64_get(ipv6_medium_instance_id_t ipv6_medium_instance_id,
+ eui64_t * p_ipv6_medium_eui64);
+
+/**@brief Function for setting the 64-bit Extended Unique Identifier.
+ *
+ * @param[in] ipv6_medium_instance_id Specifies the IPv6 medium instance.
+ * @param[in] p_ipv6_medium_eui64 Pointer to the EUI-64 value.
+ *
+ * @retval NRF_SUCCESS If the procedure was successful. Otherwise, a propagated
+ * error code is returned.
+ *
+ */
+uint32_t ipv6_medium_eui64_set(ipv6_medium_instance_id_t ipv6_medium_instance_id,
+ eui64_t * p_ipv6_medium_eui64);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // IPV6_MEDIUM_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium_ble.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium_ble.c
new file mode 100644
index 0000000..0d0a415
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium_ble.c
@@ -0,0 +1,689 @@
+/**
+ * Copyright (c) 2015-2018 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <stdint.h>
+#include "boards.h"
+#include "ipv6_medium.h"
+#include "ipv6_medium_ble.h"
+#include "ble_advdata.h"
+#include "ble_hci.h"
+#include "ble_srv_common.h"
+#include "ble_ipsp.h"
+#include "sdk_config.h"
+#include "nrf_sdm.h"
+#include "nrf_sdh.h"
+#include "nrf_sdh_ble.h"
+#ifdef COMMISSIONING_ENABLED
+#include "commissioning.h"
+#endif // COMMISSIONING_ENABLED
+
+#define PUBLIC_BLE_GAP_ADDR_CREATE_FROM_EUI64(ble_gap_addr, eui64, ble_gap_addr_type) \
+ ble_gap_addr[0] = eui64[7]; \
+ ble_gap_addr[1] = eui64[6]; \
+ ble_gap_addr[2] = eui64[5]; \
+ ble_gap_addr[3] = eui64[2]; \
+ ble_gap_addr[4] = eui64[1]; \
+ ble_gap_addr[5] = 0x00; \
+ ble_gap_addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;
+
+#define IOT_TIMER_DISABLE_API_PARAM_CHECK 0
+
+#if (IOT_TIMER_DISABLE_API_PARAM_CHECK == 0)
+
+#define NULL_PARAM_CHECK(PARAM) \
+ if ((PARAM) == NULL) \
+ { \
+ return (NRF_ERROR_NULL); \
+ }
+
+#else // IOT_TIMER_DISABLE_API_PARAM_CHECK
+
+#define NULL_PARAM_CHECK(PARAM)
+
+#endif //IOT_TIMER_DISABLE_API_PARAM_CHECK
+
+#define BLE_IPV6_MEDIUM_BLE_OBSERVER_PRIO 1 /**< BLE observer priority. */
+#define BLE_IPSP_TAG 35 /**< Identifies the L2CAP configuration used with SoftDevice. */
+
+
+static ipv6_medium_instance_id_t m_module_instance_id = 0x01; /**< Module instance identifier. As of today, only a single instance is supported. */
+static ipv6_medium_evt_handler_t m_ipv6_medium_evt_handler; /**< Pointer to the event handler procedure of the parent layer. */
+static ipv6_medium_error_handler_t m_ipv6_medium_error_handler; /**< Pointer to the error handler procedure of the parent layer. */
+static ble_gap_addr_t m_local_ble_addr; /**< Local BT device address. */
+static ipv6_medium_ble_gap_params_t * m_p_node_gap_params; /**< Pointer to advertising parameters to be used. */
+static ipv6_medium_ble_adv_params_t * m_p_node_adv_params; /**< Pointer to GAP parameters to be used. */
+
+#ifndef COMMISSIONING_ENABLED
+static ipv6_medium_ble_gap_params_t m_gap_params; /**< Advertising parameters w/o commissioning. */
+static ipv6_medium_ble_adv_params_t m_adv_params; /**< GAP parameters w/o commissioning. */
+static ble_uuid_t m_adv_uuids[] =
+ {
+ {BLE_UUID_IPSP_SERVICE, BLE_UUID_TYPE_BLE}
+ }; /**< List of available service UUIDs in advertisement data. */
+#else // COMMISSIONING_ENABLED
+static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the active connection. */
+static bool m_connectable_mode_active = false; /**< Indicates if the node is in connectable mode. */
+static commissioning_id_mode_cb_t m_commissioning_id_mode_cb;
+static commissioning_poweroff_cb_t m_commissioning_power_off_cb;
+static bool m_adv_params_applied = false; /**< Indicates if advertising (and GAP) parameters have been applied. */
+#endif // COMMISSIONING_ENABLED
+
+static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; /**< Advertising handle used to identify an advertising set. */
+static uint8_t m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX]; /**< Buffer for storing an encoded advertising set. */
+
+/**@brief Struct that contains pointers to the encoded advertising data. */
+static ble_gap_adv_data_t m_adv_data =
+{
+ .adv_data =
+ {
+ .p_data = m_enc_advdata,
+ .len = BLE_GAP_ADV_SET_DATA_SIZE_MAX
+ },
+ .scan_rsp_data =
+ {
+ .p_data = NULL,
+ .len = 0
+
+ }
+};
+
+#if IPV6_MEDIUM_CONFIG_LOG_ENABLED
+
+#define NRF_LOG_MODULE_NAME ipv6_medium
+
+#define NRF_LOG_LEVEL IPV6_MEDIUM_CONFIG_LOG_LEVEL
+#define NRF_LOG_INFO_COLOR IPV6_MEDIUM_CONFIG_INFO_COLOR
+#define NRF_LOG_DEBUG_COLOR IPV6_MEDIUM_CONFIG_DEBUG_COLOR
+
+#include "nrf_log.h"
+NRF_LOG_MODULE_REGISTER();
+
+#define IPV6M_TRC NRF_LOG_DEBUG /**< Used for getting trace of execution in the module. */
+#define IPV6M_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */
+#define IPV6M_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */
+
+#define IPV6M_ENTRY() IPV6M_TRC(">> %s", __func__)
+#define IPV6M_EXIT() IPV6M_TRC("<< %s", __func__)
+
+#else // IPV6_MEDIUM_CONFIG_LOG_ENABLED
+
+#define IPV6M_TRC(...) /**< Disables traces. */
+#define IPV6M_DUMP(...) /**< Disables dumping of octet streams. */
+#define IPV6M_ERR(...) /**< Disables error logs. */
+
+#define IPV6M_ENTRY(...)
+#define IPV6M_EXIT(...)
+
+#endif // IPV6_MEDIUM_CONFIG_LOG_ENABLED
+
+
+#ifndef COMMISSIONING_ENABLED
+
+/**@brief Function for setting advertisement parameters.
+ *
+ * @details These parameters are applied if the Commissioning module is
+ * not used or in Joining mode.
+ */
+static void adv_params_set(void)
+{
+ IPV6M_ENTRY();
+ memset(&m_adv_params, 0x00, sizeof(m_adv_params));
+
+ m_adv_params.advdata.name_type = BLE_ADVDATA_FULL_NAME;
+ m_adv_params.advdata.flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
+ m_adv_params.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
+ m_adv_params.advdata.uuids_complete.p_uuids = m_adv_uuids;
+
+ m_adv_params.advparams.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
+ m_adv_params.advparams.p_peer_addr = NULL; // Undirected advertisement.
+ m_adv_params.advparams.filter_policy = BLE_GAP_ADV_FP_ANY;
+ m_adv_params.advparams.interval = APP_ADV_ADV_INTERVAL;
+ m_adv_params.advparams.duration = APP_ADV_DURATION;
+
+ IPV6M_EXIT();
+}
+
+/**@brief Function for setting GAP parameters.
+ *
+ * @details These parameters are applied if the Commissioning module is
+ * not used or in Joining mode.
+ */
+static void gap_params_set(void)
+{
+ memset(&m_gap_params, 0x00, sizeof(m_gap_params));
+
+ BLE_GAP_CONN_SEC_MODE_SET_OPEN(&m_gap_params.sec_mode);
+
+ m_gap_params.appearance = BLE_APPEARANCE_UNKNOWN;
+
+ m_gap_params.p_dev_name = (const uint8_t *)DEVICE_NAME;
+ m_gap_params.dev_name_len = strlen(DEVICE_NAME);
+
+ m_gap_params.gap_conn_params.min_conn_interval = (uint16_t)MIN_CONN_INTERVAL;
+ m_gap_params.gap_conn_params.max_conn_interval = (uint16_t)MAX_CONN_INTERVAL;
+ m_gap_params.gap_conn_params.slave_latency = SLAVE_LATENCY;
+ m_gap_params.gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT;
+}
+
+#endif // COMMISSIONING_ENABLED
+
+
+/**@brief Function for applying the advertisement parameters.
+ *
+ * @details Encodes the required advertising data and passes it to the stack.
+ */
+static void adv_params_apply(void)
+{
+ uint32_t err_code;
+
+
+ err_code = ble_advdata_encode(&m_p_node_adv_params->advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
+ APP_ERROR_CHECK(err_code);
+#ifndef COMMISSIONING_ENABLED
+ err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params.advparams);
+ APP_ERROR_CHECK(err_code);
+#else
+ err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_p_node_adv_params->advparams);
+ APP_ERROR_CHECK(err_code);
+#endif
+}
+
+
+/**@brief Function for applying the GAP configuration.
+ *
+ * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
+ * device including the device name, appearance, and the preferred connection parameters.
+ */
+static void gap_params_apply(void)
+{
+ uint32_t err_code;
+
+ err_code = sd_ble_gap_device_name_set(&m_p_node_gap_params->sec_mode, \
+ m_p_node_gap_params->p_dev_name, \
+ m_p_node_gap_params->dev_name_len);
+ APP_ERROR_CHECK(err_code);
+
+ err_code = sd_ble_gap_appearance_set(m_p_node_gap_params->appearance);
+ APP_ERROR_CHECK(err_code);
+
+ err_code = sd_ble_gap_ppcp_set(&m_p_node_gap_params->gap_conn_params);
+ APP_ERROR_CHECK(err_code);
+}
+
+
+/**@brief Function for handling the application's BLE Stack events and
+ * passing them on to the applications as generic transport medium events.
+ *
+ * @param[in] p_ble_evt Bluetooth stack event.
+ */
+static void on_ble_evt(ble_evt_t const * p_ble_evt)
+{
+ ipv6_medium_evt_t ipv6_medium_evt;
+
+ memset(&ipv6_medium_evt, 0x00, sizeof(ipv6_medium_evt));
+ ipv6_medium_evt.ipv6_medium_instance_id.ipv6_medium_instance_id = m_module_instance_id;
+ ipv6_medium_evt.ipv6_medium_instance_id.ipv6_medium_instance_type = IPV6_MEDIUM_ID_BLE;
+ ipv6_medium_evt.medium_specific.ble.p_ble_evt = (ble_evt_t*)p_ble_evt;
+
+ ipv6_medium_error_t ipv6_medium_error;
+ memset(&ipv6_medium_error, 0x00, sizeof(ipv6_medium_error));
+ ipv6_medium_error.ipv6_medium_instance_id.ipv6_medium_instance_id = m_module_instance_id;
+ ipv6_medium_error.ipv6_medium_instance_id.ipv6_medium_instance_type = IPV6_MEDIUM_ID_BLE;
+
+ bool do_notify_event = false;
+ bool do_notify_error = false;
+
+ switch (p_ble_evt->header.evt_id)
+ {
+ case BLE_GAP_EVT_CONNECTED:
+ {
+#ifdef COMMISSIONING_ENABLED
+ m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
+#endif // COMMISSIONING_ENABLED
+ ipv6_medium_evt.ipv6_medium_evt_id = IPV6_MEDIUM_EVT_CONN_UP;
+ do_notify_event = true;
+
+ break;
+ }
+ case BLE_GAP_EVT_DISCONNECTED:
+ {
+#ifdef COMMISSIONING_ENABLED
+ m_conn_handle = BLE_CONN_HANDLE_INVALID;
+#endif // COMMISSIONING_ENABLED
+ ipv6_medium_evt.ipv6_medium_evt_id = IPV6_MEDIUM_EVT_CONN_DOWN;
+ do_notify_event = true;
+
+ break;
+ }
+ case BLE_GAP_EVT_ADV_SET_TERMINATED:
+ {
+ if (p_ble_evt->evt.gap_evt.params.adv_set_terminated.reason == BLE_GAP_EVT_ADV_SET_TERMINATED_REASON_TIMEOUT)
+ {
+ ipv6_medium_evt.ipv6_medium_evt_id = IPV6_MEDIUM_EVT_CONNECTABLE_MODE_EXIT;
+ do_notify_event = true;
+ }
+ else
+ {
+ // This is not necessarily an error, only added here to show error handler usage.
+ ipv6_medium_error.medium_specific.ble.dummy_value = 0x13;
+ do_notify_error = true;
+ }
+ break;
+ }
+ default:
+ {
+ ipv6_medium_evt.ipv6_medium_evt_id = IPV6_MEDIUM_EVT_PHY_SPECIFIC;
+ do_notify_event = true;
+
+ break;
+ }
+ }
+
+ ble_ipsp_evt_handler(p_ble_evt);
+
+ if (do_notify_event == true)
+ {
+ m_ipv6_medium_evt_handler(&ipv6_medium_evt);
+ }
+ if (do_notify_error == true)
+ {
+ m_ipv6_medium_error_handler(&ipv6_medium_error);
+ }
+}
+
+/*
+ * @brief Function for handling BLE events.
+ *
+ * @param[in] p_ble_evt Event received from the BLE stack.
+ * @param[in] p_context Context.
+ */
+static void ble_evt_handler(const ble_evt_t * p_ble_evt, void * p_context)
+{
+ UNUSED_PARAMETER(p_context);
+#ifdef COMMISSIONING_ENABLED
+ commissioning_ble_evt_handler(p_ble_evt);
+ ble_ncfgs_ble_evt_handler(p_ble_evt);
+#endif // COMMISSIONING_ENABLED
+
+ on_ble_evt(p_ble_evt);
+}
+
+
+
+
+/**@brief Function for initializing the BLE stack.
+ *
+ * @details Initializes the SoftDevice and the BLE event interrupt.
+ */
+static uint32_t ble_stack_init(void)
+{
+ ret_code_t err_code;
+ uint32_t ram_start = 0;
+ ble_cfg_t ble_cfg;
+
+ err_code = nrf_sdh_enable_request();
+
+ if (err_code == NRF_SUCCESS)
+ {
+ // Fetch the start address of the application RAM.
+ err_code = nrf_sdh_ble_app_ram_start_get(&ram_start);
+ }
+
+ if (err_code == NRF_SUCCESS)
+ {
+ // Configure the maximum number of connections.
+ memset(&ble_cfg, 0, sizeof(ble_cfg));
+ ble_cfg.gap_cfg.role_count_cfg.periph_role_count = BLE_IPSP_MAX_CHANNELS;
+ ble_cfg.gap_cfg.role_count_cfg.central_role_count = 0;
+ ble_cfg.gap_cfg.role_count_cfg.central_sec_count = 0;
+ err_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_cfg, ram_start);
+ }
+
+ if (err_code == NRF_SUCCESS)
+ {
+ memset(&ble_cfg, 0, sizeof(ble_cfg));
+
+ // Configure total number of connections.
+ ble_cfg.conn_cfg.conn_cfg_tag = BLE_IPSP_TAG;
+ ble_cfg.conn_cfg.params.gap_conn_cfg.conn_count = BLE_IPSP_MAX_CHANNELS;
+ ble_cfg.conn_cfg.params.gap_conn_cfg.event_length = BLE_GAP_EVENT_LENGTH_DEFAULT;
+ err_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_cfg, ram_start);
+
+ }
+
+ if (err_code == NRF_SUCCESS)
+ {
+ memset(&ble_cfg, 0, sizeof(ble_cfg));
+
+ // Configure the number of custom UUIDS.
+#ifdef COMMISSIONING_ENABLED
+ ble_cfg.common_cfg.vs_uuid_cfg.vs_uuid_count = 1;
+#else
+ ble_cfg.common_cfg.vs_uuid_cfg.vs_uuid_count = 0;
+#endif // COMMISSIONING_ENABLED
+
+ err_code = sd_ble_cfg_set(BLE_COMMON_CFG_VS_UUID, &ble_cfg, ram_start);
+ }
+
+ if (err_code == NRF_SUCCESS)
+ {
+ memset(&ble_cfg, 0, sizeof(ble_cfg));
+
+ // Set L2CAP channel configuration
+ ble_cfg.conn_cfg.conn_cfg_tag = BLE_IPSP_TAG;
+ ble_cfg.conn_cfg.params.l2cap_conn_cfg.rx_mps = BLE_IPSP_RX_MPS;
+ ble_cfg.conn_cfg.params.l2cap_conn_cfg.rx_queue_size = BLE_IPSP_RX_BUFFER_COUNT;
+ ble_cfg.conn_cfg.params.l2cap_conn_cfg.tx_mps = BLE_IPSP_TX_MPS;
+ ble_cfg.conn_cfg.params.l2cap_conn_cfg.tx_queue_size = 1;
+ ble_cfg.conn_cfg.params.l2cap_conn_cfg.ch_count = 1; // One IPSP channel per link.
+ err_code = sd_ble_cfg_set(BLE_CONN_CFG_L2CAP, &ble_cfg, ram_start);
+ }
+
+ if (err_code == NRF_SUCCESS)
+ {
+ memset(&ble_cfg, 0, sizeof(ble_cfg));
+
+ // Set the ATT table size.
+#ifdef COMMISSIONING_ENABLED
+ ble_cfg.gatts_cfg.attr_tab_size.attr_tab_size = 1024;
+#else
+ ble_cfg.gatts_cfg.attr_tab_size.attr_tab_size = 256;
+#endif // COMMISSIONING_ENABLED
+ err_code = sd_ble_cfg_set(BLE_GATTS_CFG_ATTR_TAB_SIZE, &ble_cfg, ram_start);
+ }
+
+ if (err_code == NRF_SUCCESS)
+ {
+ err_code = nrf_sdh_ble_enable(&ram_start);
+ }
+
+ NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, BLE_IPV6_MEDIUM_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
+
+ return err_code;
+}
+
+
+uint32_t ipv6_medium_connectable_mode_enter(ipv6_medium_instance_id_t ipv6_medium_instance_id)
+{
+ IPV6M_ENTRY();
+
+ if (ipv6_medium_instance_id != m_module_instance_id)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+
+#ifdef COMMISSIONING_ENABLED
+ if (m_adv_params_applied == false)
+ {
+ // Apply advertising (and GAP) parameters, if not applied when node mode changed.
+ commissioning_gap_params_get(&m_p_node_gap_params);
+ commissioning_adv_params_get(&m_p_node_adv_params);
+ gap_params_apply();
+ adv_params_apply();
+ }
+ m_adv_params_applied = false;
+#endif // COMMISSIONING_ENABLED
+
+ adv_params_apply();
+
+ uint32_t err_code = sd_ble_gap_adv_start(m_adv_handle, BLE_IPSP_TAG);
+#ifdef COMMISSIONING_ENABLED
+ if (err_code == NRF_SUCCESS)
+ {
+ m_connectable_mode_active = true;
+ }
+#endif // COMMISSIONING_ENABLED
+ IPV6M_EXIT();
+ return err_code;
+}
+
+
+uint32_t ipv6_medium_connectable_mode_exit(ipv6_medium_instance_id_t ipv6_medium_instance_id)
+{
+ if (ipv6_medium_instance_id != m_module_instance_id)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+
+ uint32_t err_code = sd_ble_gap_adv_stop(m_adv_handle);
+#ifdef COMMISSIONING_ENABLED
+ if (err_code == NRF_SUCCESS)
+ {
+ m_connectable_mode_active = false;
+ }
+#endif // COMMISSIONING_ENABLED
+ return err_code;
+}
+
+
+uint32_t ipv6_medium_eui48_get(ipv6_medium_instance_id_t ipv6_medium_instance_id, \
+ eui48_t * p_ipv6_medium_eui48)
+{
+ if (ipv6_medium_instance_id != m_module_instance_id)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+ ble_gap_addr_t local_ble_addr;
+ uint32_t err_code = sd_ble_gap_addr_get(&local_ble_addr);
+
+ memcpy(p_ipv6_medium_eui48->identifier, local_ble_addr.addr, EUI_48_SIZE);
+
+ return err_code;
+}
+
+
+uint32_t ipv6_medium_eui48_set(ipv6_medium_instance_id_t ipv6_medium_instance_id, \
+ eui48_t * p_ipv6_medium_eui48)
+{
+ if (ipv6_medium_instance_id != m_module_instance_id)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+ if (p_ipv6_medium_eui48->identifier[5] != 0x00)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+
+ m_local_ble_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;
+ memcpy(m_local_ble_addr.addr, p_ipv6_medium_eui48->identifier, EUI_48_SIZE);
+
+ return sd_ble_gap_addr_set(&m_local_ble_addr);
+}
+
+
+uint32_t ipv6_medium_eui64_get(ipv6_medium_instance_id_t ipv6_medium_instance_id, \
+ eui64_t * p_ipv6_medium_eui64)
+{
+ if (ipv6_medium_instance_id != m_module_instance_id)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+ ble_gap_addr_t local_ble_addr;
+
+ uint32_t err_code = sd_ble_gap_addr_get(&local_ble_addr);
+ APP_ERROR_CHECK(err_code);
+
+ IPV6_EUI64_CREATE_FROM_EUI48(p_ipv6_medium_eui64->identifier,
+ local_ble_addr.addr,
+ local_ble_addr.addr_type);
+ return NRF_SUCCESS;
+}
+
+
+uint32_t ipv6_medium_eui64_set(ipv6_medium_instance_id_t ipv6_medium_instance_id, \
+ eui64_t * p_ipv6_medium_eui64)
+{
+ if (ipv6_medium_instance_id != m_module_instance_id)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+ if ((p_ipv6_medium_eui64->identifier[0] != 0x02) ||
+ (p_ipv6_medium_eui64->identifier[3] != 0xFF) ||
+ (p_ipv6_medium_eui64->identifier[4] != 0xFE))
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+
+ ble_gap_addr_t local_ble_addr;
+
+ PUBLIC_BLE_GAP_ADDR_CREATE_FROM_EUI64(local_ble_addr.addr, \
+ p_ipv6_medium_eui64->identifier, \
+ local_ble_addr.addr_type);
+
+ return sd_ble_gap_addr_set(&local_ble_addr);
+}
+
+
+#ifdef COMMISSIONING_ENABLED
+
+void commissioning_evt_handler(commissioning_evt_t * p_commissioning_evt)
+{
+ IPV6M_ENTRY();
+
+ switch (p_commissioning_evt->commissioning_evt_id)
+ {
+ case COMMISSIONING_EVT_CONFIG_MODE_ENTER:
+ // Fall-through.
+ case COMMISSIONING_EVT_JOINING_MODE_ENTER:
+ {
+ m_commissioning_power_off_cb(p_commissioning_evt->power_off_enable_requested);
+
+ if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
+ {
+ // Making sure that advertising (and GAP) parameters are
+ // applied when entering connectable mode the next time.
+ m_adv_params_applied = false;
+ UNUSED_VARIABLE(sd_ble_gap_disconnect(m_conn_handle, \
+ BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION));
+ }
+ else
+ {
+ bool do_return_to_connectable_mode = m_connectable_mode_active;
+ UNUSED_VARIABLE(ipv6_medium_connectable_mode_exit(m_module_instance_id));
+
+ commissioning_gap_params_get(&m_p_node_gap_params);
+ commissioning_adv_params_get(&m_p_node_adv_params);
+ gap_params_apply();
+ adv_params_apply();
+ // Advertising and GAP parameters applied, making sure that
+ // it is not repeated when entering connectable mode the next time.
+ m_adv_params_applied = true;
+
+ if (do_return_to_connectable_mode == true)
+ {
+ // Restart connectable mode, if the node was in connectable mode applying
+ // the new parameters.
+ UNUSED_VARIABLE(ipv6_medium_connectable_mode_enter(m_module_instance_id));
+ }
+ }
+
+ break;
+ }
+ case COMMISSIONING_EVT_IDENTITY_MODE_ENTER:
+ {
+ m_commissioning_id_mode_cb(CMD_IDENTITY_MODE_ENTER);
+
+ break;
+ }
+ case COMMISSIONING_EVT_IDENTITY_MODE_EXIT:
+ {
+ m_commissioning_id_mode_cb(CMD_IDENTITY_MODE_EXIT);
+
+ break;
+ }
+ default:
+ {
+ // No implementation needed.
+ break;
+ }
+ }
+
+ IPV6M_EXIT();
+}
+
+#endif // COMMISSIONING_ENABLED
+
+
+uint32_t ipv6_medium_init(ipv6_medium_init_params_t * p_init_param, \
+ ipv6_medium_type_t desired_medium_type, \
+ ipv6_medium_instance_t * p_new_medium_instance)
+{
+ IPV6M_ENTRY();
+ uint32_t err_code = NRF_SUCCESS;
+ NULL_PARAM_CHECK(p_init_param->ipv6_medium_evt_handler);
+ if (desired_medium_type != IPV6_MEDIUM_ID_BLE)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+
+ m_ipv6_medium_evt_handler = p_init_param->ipv6_medium_evt_handler;
+ m_ipv6_medium_error_handler = p_init_param->ipv6_medium_error_handler;
+
+ p_new_medium_instance->ipv6_medium_instance_type = IPV6_MEDIUM_ID_BLE;
+ p_new_medium_instance->ipv6_medium_instance_id = m_module_instance_id;
+
+ err_code = ble_stack_init();
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+#ifndef COMMISSIONING_ENABLED
+ gap_params_set();
+ adv_params_set();
+ m_p_node_gap_params = &m_gap_params;
+ m_p_node_adv_params = &m_adv_params;
+ gap_params_apply();
+#else // COMMISSIONING_ENABLED
+ m_commissioning_id_mode_cb = p_init_param->commissioning_id_mode_cb;
+ m_commissioning_power_off_cb = p_init_param->commissioning_power_off_cb;
+
+ commissioning_init_params_t init_param;
+ memset(&init_param, 0x00, sizeof(init_param));
+ init_param.commissioning_evt_handler = commissioning_evt_handler;
+ uint8_t new_mode;
+ err_code = commissioning_init(&init_param, \
+ &new_mode);
+
+ commissioning_node_mode_change(new_mode);
+#endif // COMMISSIONING_ENABLED
+
+ IPV6M_EXIT();
+ return err_code;
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium_ble.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium_ble.h
new file mode 100644
index 0000000..492afe4
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium_ble.h
@@ -0,0 +1,100 @@
+/**
+ * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/** @file
+ *
+ * @defgroup ipv6_medium_ble BLE IPv6 Medium Implementation
+ * @{
+ * @ingroup iot_sdk_common
+ * @brief Bluetooth Low Energy implementation of the IPv6 medium interface.
+ *
+ * @details Type definitions for the BLE implementation of the IPv6 medium interface.
+ * This header also includes the header with BLE-specific configuration.
+ */
+
+#ifndef IPV6_MEDIUM_BLE_H__
+#define IPV6_MEDIUM_BLE_H__
+
+#include <stdint.h>
+#include "ble.h"
+#include "ble_advdata.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@brief Structure for storing all GAP parameters. */
+typedef struct
+{
+ uint16_t appearance;
+ uint8_t const * p_dev_name;
+ uint16_t dev_name_len;
+ ble_gap_conn_sec_mode_t sec_mode;
+ ble_gap_conn_params_t gap_conn_params;
+} ipv6_medium_ble_gap_params_t;
+
+/**@brief Structure for storing all advertisement parameters. */
+typedef struct
+{
+ ble_advdata_t advdata;
+ ble_advdata_manuf_data_t adv_man_specific_data;
+ ble_advdata_t srdata;
+ ble_advdata_manuf_data_t sr_man_specific_data;
+ ble_gap_adv_params_t advparams;
+} ipv6_medium_ble_adv_params_t;
+
+/**@brief Structure of BLE-specific parameters of events passed to the parent layer by the IPv6 medium. */
+typedef struct
+{
+ ble_evt_t * p_ble_evt;
+} ipv6_medium_ble_cb_params_t;
+
+/**@brief Structure of BLE-specific parameters of errors passed to the parent layer by the IPv6 medium. */
+typedef struct
+{
+ uint8_t dummy_value; // Parameters to be added.
+} ipv6_medium_ble_error_params_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // IPV6_MEDIUM_BLE_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium_platform_dummy.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium_platform_dummy.h
new file mode 100644
index 0000000..341d326
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ipv6_medium_platform_dummy.h
@@ -0,0 +1,54 @@
+/**
+ * Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef IPV6_MEDIUM_PLATFORM_DUMMY_H__
+#define IPV6_MEDIUM_PLATFORM_DUMMY_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int ipv6_medium_cb_params_union_t;
+typedef int ipv6_medium_err_params_union_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // IPV6_MEDIUM_PLATFORM_DUMMY_H__