aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ble_ncfgs/ble_ncfgs.c
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ble_ncfgs/ble_ncfgs.c')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/iot/medium/ble_ncfgs/ble_ncfgs.c516
1 files changed, 516 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