From 3061ecca3d0fdfb87dabbf5f63c9e06c2a30f53a Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Thu, 23 Aug 2018 17:08:59 +0200 Subject: o Initial import. --- .../components/ble/ble_services/eddystone/es.h | 198 +++++++ .../components/ble/ble_services/eddystone/es_adv.c | 342 ++++++++++++ .../components/ble/ble_services/eddystone/es_adv.h | 129 +++++ .../ble/ble_services/eddystone/es_adv_frame.c | 120 +++++ .../ble/ble_services/eddystone/es_adv_frame.h | 73 +++ .../ble/ble_services/eddystone/es_adv_timing.c | 220 ++++++++ .../ble/ble_services/eddystone/es_adv_timing.h | 97 ++++ .../eddystone/es_adv_timing_resolver.c | 145 +++++ .../eddystone/es_adv_timing_resolver.h | 96 ++++ .../ble_services/eddystone/es_battery_voltage.h | 66 +++ .../eddystone/es_battery_voltage_saadc.c | 104 ++++ .../ble/ble_services/eddystone/es_flash.c | 340 ++++++++++++ .../ble/ble_services/eddystone/es_flash.h | 177 ++++++ .../ble/ble_services/eddystone/es_gatts.c | 188 +++++++ .../ble/ble_services/eddystone/es_gatts.h | 109 ++++ .../ble/ble_services/eddystone/es_gatts_read.c | 246 +++++++++ .../ble/ble_services/eddystone/es_gatts_read.h | 73 +++ .../ble/ble_services/eddystone/es_gatts_write.c | 254 +++++++++ .../ble/ble_services/eddystone/es_gatts_write.h | 71 +++ .../ble/ble_services/eddystone/es_security.c | 596 +++++++++++++++++++++ .../ble/ble_services/eddystone/es_security.h | 238 ++++++++ .../ble/ble_services/eddystone/es_slot.c | 440 +++++++++++++++ .../ble/ble_services/eddystone/es_slot.h | 202 +++++++ .../ble/ble_services/eddystone/es_slot_reg.c | 181 +++++++ .../ble/ble_services/eddystone/es_slot_reg.h | 90 ++++ .../ble/ble_services/eddystone/es_stopwatch.c | 106 ++++ .../ble/ble_services/eddystone/es_stopwatch.h | 71 +++ .../components/ble/ble_services/eddystone/es_tlm.c | 140 +++++ .../components/ble/ble_services/eddystone/es_tlm.h | 76 +++ .../ble/ble_services/eddystone/es_util.h | 137 +++++ .../ble/ble_services/eddystone/nrf_ble_es.c | 438 +++++++++++++++ .../ble/ble_services/eddystone/nrf_ble_es.h | 99 ++++ 32 files changed, 5862 insertions(+) create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_frame.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_frame.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing_resolver.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing_resolver.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_battery_voltage.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_battery_voltage_saadc.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_flash.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_flash.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_read.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_read.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_write.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_write.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_security.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_security.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot_reg.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot_reg.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_stopwatch.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_stopwatch.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_tlm.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_tlm.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_util.h create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/nrf_ble_es.c create mode 100644 thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/nrf_ble_es.h (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone') diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es.h new file mode 100644 index 0000000..ce4221d --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es.h @@ -0,0 +1,198 @@ +/** + * 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 ES_H__ +#define ES_H__ + +#include +#include "app_util_platform.h" + +/** + * @file + * + * @defgroup eddystone_types Frame types and data formats + * @brief Definitions specific to Eddystone frame types and data formats. + * @ingroup eddystone + * @{ + */ + +/** @brief Swap 2 bytes. + */ +#define BYTES_SWAP_16BIT(x) (x << 8 | x >> 8) + +/** @brief Reverse 4 bytes. + */ +#define BYTES_REVERSE_32BIT(x) \ + ((x << 24 | ((x << 8) & 0x00FF0000)) | (((x >> 8) & 0x0000FF00) | x >> 24)) + +/** @brief Check if the error code is equal to NRF_SUCCESS. If it is not, return the error code. + */ +#define RETURN_IF_ERROR(PARAM) \ + if ((PARAM) != NRF_SUCCESS) \ + { \ + return (PARAM); \ + } + +#define ES_UUID 0xFEAA //!< UUID for Eddystone beacons according to specification. + +#define ES_UID_FRAME_TYPE 0x00 //!< UID frame type (fixed at 0x00). +#define ES_UID_RFU 0x00, 0x00 //!< Reserved for future use according to specification. + +#define ES_URL_FRAME_TYPE 0x10 //!< URL frame type (fixed at 0x10). +#define ES_URL_SCHEME 0x00 //!< URL prefix scheme according to specification (0x00 = "http://www"). + +#define ES_TLM_FRAME_TYPE 0x20 //!< TLM frame type (fixed at 0x20). +#define ES_EID_FRAME_TYPE 0x30 //!< EID frame type (fixed at 0x30). + +#define ES_FRAME_TYPE_LENGTH (1) //!< Length of a frame type field. + +#define ES_UID_LENGTH (20) //!< Length of a UID frame. +#define ES_UID_NAMESPACE_LENGTH (10) //!< Length of a UID frame namespace field. +#define ES_UID_INSTANCE_LENGTH (6) //!< Length of a UID frame instance field. +#define ES_UID_RFU_LENGTH (2) //!< Length of a UID frame RFU field. + +#define ES_URL_LENGTH (20) //!< Length of a URL frame. +#define ES_URL_URL_SCHEME_LENGTH (1) //!< Length of a URL frame URL scheme field. +#define ES_URL_ENCODED_URL_LENGTH (17) //!< Maximum length of a URL frame encoded URL field. + +#define ES_TLM_LENGTH (14) //!< Length of a TLM frame. +#define ES_TLM_VBATT_LENGTH (2) //!< Length of a TLM frame VBATT field. +#define ES_TLM_TEMP_LENGTH (2) //!< Length of a TLM frame TEMP field. +#define ES_TLM_ADV_CNT_LENGTH (4) //!< Length of a TLM frame ADV count field. +#define ES_TLM_SEC_CNT_LENGTH (4) //!< Length of a TLM frame seconds field. + +#define ES_EID_LENGTH (10) //!< Length of an EID frame. +#define ES_EID_ID_LENGTH (8) //!< Length of an EID frame ephemeral ID field. +#define ES_EID_GATTS_READ_LENGTH (14) +#define ES_EID_GATTS_READ_FRAME_TYPE_IDX (0) +#define ES_EID_GATTS_READ_EXPONENT_IDX (1) +#define ES_EID_GATTS_READ_CLCK_VALUE_IDX (2) +#define ES_EID_GATTS_READ_EID_IDX (6) + +#define ES_ETLM_LENGTH (18) //!< Length of an eTLM frame. +#define ES_ETLM_ECRYPTED_LENGTH (ES_TLM_VBATT_LENGTH + \ + ES_TLM_TEMP_LENGTH + \ + ES_TLM_ADV_CNT_LENGTH + \ + ES_TLM_SEC_CNT_LENGTH) //!< Length of an eTLM frame encrypted TLM field. + +#define ES_ETLM_RFU (0x00) //!< eTLM frame RFU field value. +#define ES_SPEC_VERSION_BYTE (0x00) //!< eTLM frame specification version field value. + +/** @brief Eddystone frame type values. These values are advertised as frame types. */ +typedef enum +{ + ES_FRAME_TYPE_UID = ES_UID_FRAME_TYPE, /**< UID frame type. */ + ES_FRAME_TYPE_URL = ES_URL_FRAME_TYPE, /**< URL frame type. */ + ES_FRAME_TYPE_TLM = ES_TLM_FRAME_TYPE, /**< TLM frame type. */ + ES_FRAME_TYPE_EID = ES_EID_FRAME_TYPE /**< EID frame type. */ +} es_frame_type_t; + +/** @brief TLM version values. */ +typedef enum +{ + ES_TLM_VERSION_TLM = 0x00, /**< TLM. */ + ES_TLM_VERSION_ETLM = 0x01 /**< Encrypted TLM (eTLM). */ +} es_tlm_version_t; + +/** @brief UID frame data representation. + * @note This is a packed structure. Therefore, you should not change it. + */ +typedef PACKED_STRUCT +{ + es_frame_type_t frame_type; //!< Frame type (see @ref es_frame_type_t). + int8_t ranging_data; //!< Calibrated TX power at 0 m. + int8_t namespace[ES_UID_NAMESPACE_LENGTH]; //!< UID namespace. + int8_t instance[ES_UID_INSTANCE_LENGTH]; //!< UID instance. + int8_t rfu[ES_UID_RFU_LENGTH]; //!< RFU. +} es_uid_frame_t; + + +/** @brief URL frame data representation. + * @note This is a packed structure. Therefore, you should not change it. +*/ +typedef PACKED_STRUCT +{ + es_frame_type_t frame_type; //!< Frame type (see @ref es_frame_type_t). + int8_t ranging_data; //!< Calibrated TX power at 0 m. + uint8_t url_scheme; //!< URL scheme. + uint8_t encoded_url[ES_URL_ENCODED_URL_LENGTH]; //!< Encoded URL (variable length). +} es_url_frame_t; + + +/** @brief TLM frame data representation. + * @note This is a packed structure. Therefore, you should not change it. +*/ +typedef PACKED_STRUCT +{ + es_frame_type_t frame_type; //!< Frame type (see @ref es_frame_type_t). + es_tlm_version_t version; //!< TLM version (see @ref es_tlm_version_t). + int8_t vbatt[ES_TLM_VBATT_LENGTH]; //!< Battery voltage (in 1 mV units). + int8_t temp[ES_TLM_TEMP_LENGTH]; //!< Beacon temperature. + int8_t adv_cnt[ES_TLM_ADV_CNT_LENGTH]; //!< Advertising PDU count. + int8_t sec_cnt[ES_TLM_SEC_CNT_LENGTH]; //!< Time since power-on or reboot. +} es_tlm_frame_t; + +/** @brief EID frame data representation. + * @note This is a packed structure. Therefore, you should not change it. +*/ +typedef PACKED_STRUCT +{ + es_frame_type_t frame_type; //!< Frame type (see @ref es_frame_type_t). + int8_t ranging_data; //!< Calibrated TX power at 0 m. + int8_t eid[ES_EID_ID_LENGTH]; //!< 8-byte ephemeral identifier. +} es_eid_frame_t; + + +/** @brief eTLM frame data representation. + * @note This is a packed structure. Therefore, you should not change it. +*/ +typedef PACKED_STRUCT +{ + es_frame_type_t frame_type; //!< Frame type (see @ref es_frame_type_t). + es_tlm_version_t version; //!< TLM version (see @ref es_tlm_version_t). + int8_t encrypted_tlm[ES_ETLM_ECRYPTED_LENGTH]; //!< Encrypted TLM data. + int16_t random_salt; //!< Salt + int16_t msg_integrity_check; //!< Message integrity check. +} es_etlm_frame_t; + +/** + * @} + */ + +#endif // ES_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv.c new file mode 100644 index 0000000..bf6913f --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv.c @@ -0,0 +1,342 @@ +/** + * 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. + * + */ +#include "es_adv.h" +#include "app_error.h" +#include "es_adv_frame.h" +#include "es_adv_timing.h" +#include "es_tlm.h" +#include "es_slot.h" + +static es_adv_evt_handler_t m_adv_evt_handler; //!< Eddystone advertisement event handler. +static bool m_is_connected = false; //!< Is the Eddystone beacon in a connected state. +static bool m_remain_connectable = false; //!< Should the Eddystone beacon remain connectable. +static uint8_t m_ecs_uuid_type = 0; //!< UUID type of the Eddystone Configuration Service. +static uint16_t m_adv_interval = APP_CFG_NON_CONN_ADV_INTERVAL_MS; //!< Current advertisement interval. + +static uint8_t m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX]; //!< Buffer for storing an encoded advertising set. +static uint8_t m_enc_scan_response_data[BLE_GAP_ADV_SET_DATA_SIZE_MAX]; //!< Buffer for storing an encoded scan data. +static uint8_t *mp_adv_handle; //!< Pointer to the advertising handle. + +/**@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 = m_enc_scan_response_data, + .len = BLE_GAP_ADV_SET_DATA_SIZE_MAX + + } +}; + +/**@brief Function for invoking registered callback. + * + * @param[in] evt Event to issue to callback. + */ +static void invoke_callback(es_adv_evt_t evt) +{ + if (m_adv_evt_handler != NULL) + { + m_adv_evt_handler(evt); + } +} + +/**@brief Starting advertising. + * @param[in] p_adv_params Advertisement parameters to use. + */ +static void adv_start(ble_gap_adv_params_t * p_adv_params) +{ + ret_code_t err_code = NRF_SUCCESS; + + es_tlm_adv_cnt_inc(); + + err_code = sd_ble_gap_adv_set_configure(mp_adv_handle, &m_adv_data, p_adv_params); + APP_ERROR_CHECK(err_code); + + err_code = sd_ble_gap_adv_start(*mp_adv_handle, BLE_CONN_CFG_TAG_DEFAULT); + + if (err_code != NRF_ERROR_BUSY && err_code != NRF_SUCCESS) + { + APP_ERROR_CHECK(err_code); + } +} + + +/**@brief Given state of Eddystone beacon, get advertisement parameters. */ +static void get_adv_params(ble_gap_adv_params_t * p_adv_params, + bool non_connectable, + bool remain_connectable) +{ + // Initialize advertising parameters (used when starting advertising). + memset(p_adv_params, 0, sizeof(ble_gap_adv_params_t)); + + // Non-connectable + p_adv_params->properties.type = non_connectable + ? BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED + : BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; + p_adv_params->p_peer_addr = NULL; // Undirected advertisement. + p_adv_params->filter_policy = BLE_GAP_ADV_FP_ANY; + p_adv_params->interval = non_connectable ? BLE_GAP_ADV_INTERVAL_MAX : 1000; + p_adv_params->duration = non_connectable + ? APP_CFG_NON_CONN_ADV_TIMEOUT + : (remain_connectable ? 0 : APP_CFG_CONNECTABLE_ADV_TIMEOUT); + p_adv_params->primary_phy = BLE_GAP_PHY_1MBPS; +} + + +/**@brief Update advertisement data and start connectable advertisements. */ +static void connectable_adv_start(void) +{ + ble_gap_adv_params_t connectable_adv_params; + ble_advdata_t scrsp_data; + ble_uuid_t scrp_uuids[] = {{BLE_UUID_ESCS_SERVICE, m_ecs_uuid_type}}; + + memset(&scrsp_data, 0, sizeof(scrsp_data)); + scrsp_data.name_type = BLE_ADVDATA_FULL_NAME; + scrsp_data.include_appearance = false; + scrsp_data.uuids_complete.uuid_cnt = sizeof(scrp_uuids) / sizeof(scrp_uuids[0]); + scrsp_data.uuids_complete.p_uuids = scrp_uuids; + + m_adv_data.scan_rsp_data.p_data = m_enc_scan_response_data; + m_adv_data.scan_rsp_data.len = BLE_GAP_ADV_SET_DATA_SIZE_MAX; + + // As the data to be written does not depend on the slot_no, we can safely send + es_adv_frame_fill_connectable_adv_data(&scrsp_data, &m_adv_data); + + get_adv_params(&connectable_adv_params, false, m_remain_connectable); + adv_start(&connectable_adv_params); + + invoke_callback(ES_ADV_EVT_CONNECTABLE_ADV_STARTED); +} + + +static void adv_stop(void) +{ + ret_code_t err_code; + + err_code = sd_ble_gap_adv_stop(*mp_adv_handle); + if (err_code != NRF_ERROR_INVALID_STATE) + { + APP_ERROR_CHECK(err_code); + } + + es_adv_timing_stop(); +} + + +static void adv_restart(void) +{ + if (!m_remain_connectable) + { + es_adv_start_non_connctable_adv(); + } + + else + { + connectable_adv_start(); + } +} + + +/**@brief Function handling events from @ref es_adv_timing.c. + * + * @param[in] p_evt Advertisement timing event. + */ +static void adv_timing_callback(const es_adv_timing_evt_t * p_evt) +{ + ret_code_t err_code; + ble_gap_adv_params_t non_connectable_adv_params; + const es_slot_reg_t * p_reg = es_slot_get_registry(); + + // As new advertisement data will be loaded, stop advertising. + err_code = sd_ble_gap_adv_stop(*mp_adv_handle); + if (err_code != NRF_ERROR_INVALID_STATE && err_code != BLE_ERROR_INVALID_ADV_HANDLE) + { + APP_ERROR_CHECK(err_code); + } + + // If a non-eTLM frame is to be advertised. + if (p_evt->evt_id == ES_ADV_TIMING_EVT_ADV_SLOT) + { + err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, 0, p_reg->slots[p_evt->slot_no].radio_tx_pwr); + if (err_code != BLE_ERROR_INVALID_ADV_HANDLE) + { + APP_ERROR_CHECK(err_code); + } + es_adv_frame_fill_non_connectable_adv_data(p_evt->slot_no, false, &m_adv_data); + } + + // If an eTLM frame is to be advertised + else if (p_evt->evt_id == ES_ADV_TIMING_EVT_ADV_ETLM) + { + err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, 0, p_reg->slots[p_reg->tlm_slot].radio_tx_pwr); + APP_ERROR_CHECK(err_code); + + es_adv_frame_fill_non_connectable_adv_data(p_evt->slot_no, true, &m_adv_data); + } + + invoke_callback(ES_ADV_EVT_NON_CONN_ADV); + + get_adv_params(&non_connectable_adv_params, true, m_remain_connectable); + adv_start(&non_connectable_adv_params); +} + + +void es_adv_start_connectable_adv(void) +{ + if (!m_is_connected) + { + adv_stop(); + + connectable_adv_start(); + } +} + + +void es_adv_start_non_connctable_adv(void) +{ + es_adv_timing_start(m_adv_interval); +} + + +void es_adv_remain_connectable_set(bool remain_connectable) +{ + m_remain_connectable = remain_connectable; +} + + +bool es_adv_remain_connectable_get(void) +{ + return m_remain_connectable; +} + + +void es_adv_on_ble_evt(ble_evt_t const * p_ble_evt) +{ + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + m_is_connected = true; + + // The beacon must provide these advertisements for the client to see updated values + // during the connection. + es_adv_start_non_connctable_adv(); + break; + + case BLE_GAP_EVT_DISCONNECTED: + m_is_connected = false; + + // Stop all advertising to give some time for writing to flash. + adv_stop(); + adv_restart(); + 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 && + !m_is_connected) + { + invoke_callback(ES_ADV_EVT_CONNECTABLE_ADV_STOPPED); + + adv_restart(); + } + break; + + default: + break; + } +} + + +void es_adv_interval_set(nrf_ble_escs_adv_interval_t interval) +{ + const es_slot_reg_t * p_reg = es_slot_get_registry(); + uint16_t min_valid_adv_interval; + + bool eTLM_required = (p_reg->num_configured_eid_slots > 0) && (p_reg->tlm_configured); + + min_valid_adv_interval = eTLM_required ? \ + p_reg->num_configured_slots * (APP_CONFIG_ADV_FRAME_SPACING_MS_MIN + \ + APP_CONFIG_ADV_FRAME_ETLM_SPACING_MS) \ + : \ + p_reg->num_configured_slots * APP_CONFIG_ADV_FRAME_SPACING_MS_MIN; + + m_adv_interval = (interval > min_valid_adv_interval) ? interval : min_valid_adv_interval; + +#ifdef APP_CONFIG_ADV_INTERVAL_MS_MAX + if (m_adv_interval > APP_CONFIG_ADV_INTERVAL_MS_MAX) + { + m_adv_interval = APP_CONFIG_ADV_INTERVAL_MS_MAX; + } +#endif // APP_CONFIG_ADV_INTERVAL_MS_MAX +} + + +nrf_ble_escs_adv_interval_t es_adv_interval_get(void) +{ + return m_adv_interval; +} + + +void es_adv_init(uint8_t ecs_uuid_type, + es_adv_evt_handler_t adv_event_handler, + nrf_ble_escs_adv_interval_t adv_interval, + bool remain_connectable, + uint8_t * const p_adv_handle) +{ + m_ecs_uuid_type = ecs_uuid_type; + m_adv_evt_handler = adv_event_handler; + m_is_connected = false; + m_remain_connectable = remain_connectable; + m_adv_interval = adv_interval; + mp_adv_handle = p_adv_handle; + + es_tlm_init(); + + es_adv_timing_init(adv_timing_callback); +} + +void es_adv_timers_init(void) +{ + es_adv_timing_timers_init(); +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv.h new file mode 100644 index 0000000..bb0177c --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv.h @@ -0,0 +1,129 @@ +/** + * 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 ES_ADV_H__ +#define ES_ADV_H__ + +#include "nrf_ble_escs.h" + +/** + * @file + * @defgroup eddystone_adv Eddystone advertising module + * @brief Types and functions for handling advertising in Eddystone beacons. + * @ingroup eddystone + * @{ + */ + +/** @brief Eddystone Advertiser events. */ +typedef enum +{ + ES_ADV_EVT_NON_CONN_ADV, + ES_ADV_EVT_CONNECTABLE_ADV_STARTED, + ES_ADV_EVT_CONNECTABLE_ADV_STOPPED, +} es_adv_evt_t; + +/** @brief Eddystone Advertiser event handler. */ +typedef void (*es_adv_evt_handler_t)(es_adv_evt_t evt); + +/** @brief Function for initializing the module. + * + * @param[in] ecs_uuid_type ECS UUID type used for advertising the Eddystone Configuration Service UUID. + * @param[in] adv_event_handler Eddystone advertiser event handler. + * @param[in] adv_interval Advertisement interval to use. + * @param[in] remain_connectable Flag that specifies if advertisements should remain connectable. + * @param[in] p_adv_handle Pointer to the advertising handle used to start and stop advertising. + */ +void es_adv_init(uint8_t ecs_uuid_type, + es_adv_evt_handler_t adv_event_handler, + nrf_ble_escs_adv_interval_t adv_interval, + bool remain_connectable, + uint8_t * const p_adv_handle); + +/** @brief Function for passing BLE events to this module. + * + * @param[in] p_ble_evt Pointer to the BLE evt. + */ +void es_adv_on_ble_evt(ble_evt_t const * p_ble_evt); + +/** @brief Function for starting the advertisements. + */ +void es_adv_start_non_connctable_adv(void); + +/** @brief Function for specifying if the beacon should remain connectable. + * + * @param[in] remain_connectable Value to be set. + */ +void es_adv_remain_connectable_set(bool remain_connectable); + +/** @brief Function for starting connectable advertisements. + */ +void es_adv_start_connectable_adv(void); + +/** @brief Function for setting the base advertisement interval for non-connectable advertisements. + * + * The minimum allowed advertisement interval is calculated based on the configured minimum advertisement + * frame spacings and the number of configured slots. If eTLM slots are configured a separate minimum + * advertisement frame spacing is used for those. If @p interval is outside of range, the closest valid value + * is set. + * + * @param interval The new advertisement interval. + */ +void es_adv_interval_set(nrf_ble_escs_adv_interval_t interval); + +/** @brief Function for getting a pointer to the current advertisement interval. + * + * @retval Pointer to the current advertisement interval. + */ +nrf_ble_escs_adv_interval_t es_adv_interval_get(void); + +/** @brief Function for getting the value of the 'remain_connectable' field. + * + * @retval Value of 'remain_connectable'. + */ +bool es_adv_remain_connectable_get(void); + +/** @brief Function for initializing the Eddystone advertisement timers. + */ +void es_adv_timers_init(void); + +/** + * @} + */ + +#endif // ES_ADV_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_frame.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_frame.c new file mode 100644 index 0000000..0333c43 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_frame.c @@ -0,0 +1,120 @@ +/** + * 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. + * + */ +#include "es_adv_frame.h" +#include "es_slot.h" + + +/**@brief Function for setting advertisement data, using 'ble_advdata_encode'. + * + * @param[in] p_scrsp_data Scan response data. + * @param[in] p_es_data_array Eddystone service data array. + */ +static void fill_adv_data(ble_advdata_t * p_scrsp_data, uint8_array_t * p_es_data_array, ble_gap_adv_data_t * const p_adv_data) +{ + ble_advdata_t adv_data; + ret_code_t err_code; + ble_uuid_t adv_uuids[] = {{ES_UUID, BLE_UUID_TYPE_BLE}}; + uint8_array_t es_data_array = {0}; + + ble_advdata_service_data_t service_data; // Structure to hold Service Data. + + service_data.service_uuid = APP_ES_UUID; // Eddystone UUID to allow discoverability on iOS devices. + + service_data.data = (p_es_data_array != NULL) ? *p_es_data_array : es_data_array; + + // Build and set advertising data. + memset(&adv_data, 0, sizeof(ble_advdata_t)); + + adv_data.name_type = BLE_ADVDATA_NO_NAME; + adv_data.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; + adv_data.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]); + adv_data.uuids_complete.p_uuids = adv_uuids; + adv_data.p_service_data_array = &service_data; + adv_data.service_data_count = (p_es_data_array != NULL) ? 1 : 0; + + err_code = ble_advdata_encode(&adv_data, + p_adv_data->adv_data.p_data, + &p_adv_data->adv_data.len); + APP_ERROR_CHECK(err_code); + if (p_scrsp_data != NULL) + { + err_code = ble_advdata_encode(p_scrsp_data, + p_adv_data->scan_rsp_data.p_data, + &p_adv_data->scan_rsp_data.len); + APP_ERROR_CHECK(err_code); + } + else + { + p_adv_data->scan_rsp_data.p_data = NULL; + p_adv_data->scan_rsp_data.len = 0; + } +} + + +void es_adv_frame_fill_connectable_adv_data(ble_advdata_t * p_scrsp_data, ble_gap_adv_data_t * const p_adv_data) +{ + fill_adv_data(p_scrsp_data, NULL, p_adv_data); +} + + +void es_adv_frame_fill_non_connectable_adv_data(uint8_t slot_no, bool etlm, ble_gap_adv_data_t * const p_adv_data) +{ + uint8_array_t es_data_array = {0}; + const es_slot_reg_t * p_reg = es_slot_get_registry(); + + if (etlm) + { + es_slot_etlm_update(slot_no); + + // If eTLM, the incoming slot_no points to the corresponding EID slot, update to point to TLM slot. + slot_no = p_reg->tlm_slot; + } + + // If TLM, update the TLM data. + else if (p_reg->slots[slot_no].adv_frame.type == ES_FRAME_TYPE_TLM) + { + es_slot_tlm_update(); + } + + es_data_array.p_data = (uint8_t *)&p_reg->slots[slot_no].adv_frame.frame; + es_data_array.size = p_reg->slots[slot_no].adv_frame.length; + + fill_adv_data(NULL, &es_data_array, p_adv_data); +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_frame.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_frame.h new file mode 100644 index 0000000..0facf5d --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_frame.h @@ -0,0 +1,73 @@ +/** + * 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 ES_ADV_FRAME_H__ +#define ES_ADV_FRAME_H__ + +#include +#include "ble_advdata.h" + +/** + * @file + * @addtogroup eddystone_adv + * @{ + */ + +/**@brief Function for setting up connectable advertisement data using @ref + * ble_advdata_encode. + * + * @param[in] p_scrsp_data Pointer to the scan response data that will be encoded. + * @param[in,out] p_adv_data Pointer to the encoded advertising data (including scan response). + */ +void es_adv_frame_fill_connectable_adv_data(ble_advdata_t * p_scrsp_data, ble_gap_adv_data_t * const p_adv_data); + +/**@brief Function for setting up non-connectable advertisement data using @ref + * ble_advdata_encode. + * + * @param[in] slot_no Slot to fill in data for. + * @param[in] etlm Flag that specifies if Eddystone-TLM is required. + * @param[in,out] p_adv_data Pointer to the encoded advertising data (including scan response). + */ +void es_adv_frame_fill_non_connectable_adv_data(uint8_t slot_no, bool etlm, ble_gap_adv_data_t * const p_adv_data); + +/** + * @} + */ + +#endif // ES_ADV_FRAME_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing.c new file mode 100644 index 0000000..d575ba8 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing.c @@ -0,0 +1,220 @@ +/** + * 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. + * + */ +#include "app_timer.h" +#include "es_adv_timing.h" +#include "es_adv_timing_resolver.h" +#include "es_slot.h" + + +APP_TIMER_DEF(m_es_adv_interval_timer); //!< Timer for advertising the set of slots. +APP_TIMER_DEF(m_es_slot_timer); //!< Timer for advertising individual slots. + +static nrf_ble_escs_adv_interval_t m_current_adv_interval; //!< Current advertisement interval. +static es_adv_timing_callback_t m_timing_mgr_callback; //!< Registered callback. +static es_adv_timing_resolver_result_t m_adv_timing_result; //!< Current advertising timing result. +static bool m_non_conn_adv_active; //!< Is the beacon advertising non-conn advertisements? + +/**@brief Function for invoking registered callback. + * + * @param[in] p_evt Event to issue to callback. + */ +static void invoke_callback(const es_adv_timing_evt_t * p_evt) +{ + if (m_timing_mgr_callback != NULL && m_non_conn_adv_active) + { + m_timing_mgr_callback(p_evt); + } +} + + +#if APP_CONFIG_TLM_ADV_INTERLEAVE_RATIO > 1 +static bool frame_to_adv_is_tlm(const es_adv_timing_evt_t * p_evt) +{ + const es_slot_reg_t * p_reg = es_slot_get_registry(); + + return (p_reg->tlm_configured && + (p_evt->slot_no == p_reg->tlm_slot || p_evt->evt_id == ES_ADV_TIMING_EVT_ADV_ETLM)); +} + + +static bool tlm_should_be_advertised(uint32_t adv_event_cnt) +{ + return (adv_event_cnt % APP_CONFIG_TLM_ADV_INTERLEAVE_RATIO) == 0; +} +#endif // APP_CONFIG_TLM_ADV_INTERLEAVE_RATIO > 1 + + +/**@brief Timeout handler for the advertisement slot timer. */ +static void adv_slot_timeout(void * p_context) +{ + + ret_code_t err_code; + uint32_t active_slot_index = (uint32_t)p_context; + + es_adv_timing_evt_t evt; + + evt.slot_no = m_adv_timing_result.timing_results[active_slot_index].slot_no; + + evt.evt_id = m_adv_timing_result.timing_results[active_slot_index].is_etlm + ? ES_ADV_TIMING_EVT_ADV_ETLM + : ES_ADV_TIMING_EVT_ADV_SLOT; + + // Trigger an event for the next slot if this slot is not the last to be advertised in this event. + // Note: since we check 'm_adv_timing_result.len_timing_results > 1' we can safely cast the result of + // the subtraction to a uint32. + if (m_non_conn_adv_active && \ + m_adv_timing_result.len_timing_results > 1 && \ + active_slot_index < (uint32_t)(m_adv_timing_result.len_timing_results - 1)) + { + err_code = app_timer_start( m_es_slot_timer, + APP_TIMER_TICKS(m_adv_timing_result.timing_results[active_slot_index].delay_ms), + (void*)(active_slot_index + 1)); + APP_ERROR_CHECK(err_code); + } + +#if APP_CONFIG_TLM_ADV_INTERLEAVE_RATIO > 1 + static uint32_t adv_event_cnt = 0; + + if (active_slot_index == 0) + { + adv_event_cnt++; + } + + if (frame_to_adv_is_tlm(&evt) && !tlm_should_be_advertised(adv_event_cnt)) + { + return; + } +#endif // APP_CONFIG_TLM_ADV_INTERLEAVE_RATIO > 1 + + invoke_callback(&evt); +} + + +/**@brief Timeout handler for the advertisement interval timer. */ +static void adv_interval_timeout(void * p_context) +{ + if (es_slot_get_registry()->num_configured_slots > 0) + { + // Trigger slot timeout for advertising the first slot. + // Note: The slot number is not the index in the slot registry, it is the index of the active slots. + adv_slot_timeout(NULL); + } + + if (m_non_conn_adv_active) + { + uint32_t err_code = app_timer_start(m_es_adv_interval_timer, + APP_TIMER_TICKS(m_current_adv_interval), + NULL); + APP_ERROR_CHECK(err_code); + } +} + + +void es_adv_timing_timers_init(void) +{ + ret_code_t err_code; + + err_code = app_timer_create(&m_es_adv_interval_timer, + APP_TIMER_MODE_SINGLE_SHOT, + adv_interval_timeout); + APP_ERROR_CHECK(err_code); + + err_code = app_timer_create(&m_es_slot_timer, + APP_TIMER_MODE_SINGLE_SHOT, + adv_slot_timeout); + APP_ERROR_CHECK(err_code); +} + + +/**@brief Function for finding and setting advertisement timing configuration. */ +static void adv_timing_set(void) +{ + ret_code_t err_code; + const es_slot_reg_t * p_reg = es_slot_get_registry(); + + es_adv_timing_resolver_input_t resolver_input = { + .adv_interval = m_current_adv_interval, + .p_result = &m_adv_timing_result, + .num_slots_configured = p_reg->num_configured_slots, + .p_slots_configured = p_reg->slots_configured, + .num_eid_slots_configured = p_reg->num_configured_eid_slots, + .p_eid_slots_configured = p_reg->eid_slots_configured, + .tlm_configured = p_reg->tlm_configured, + .tlm_slot = p_reg->tlm_slot}; + + err_code = es_adv_timing_resolve(&resolver_input); + APP_ERROR_CHECK(err_code); +} + + +void es_adv_timing_start(uint16_t adv_interval) +{ + ret_code_t err_code; + + const es_slot_reg_t * p_reg = es_slot_get_registry(); + + m_non_conn_adv_active = true; + + if (p_reg->num_configured_slots > 0) + { + m_current_adv_interval = adv_interval; + + err_code = app_timer_start(m_es_adv_interval_timer, + APP_TIMER_TICKS(m_current_adv_interval), + NULL); + APP_ERROR_CHECK(err_code); + + adv_timing_set(); + } +} + + +void es_adv_timing_stop(void) +{ + m_non_conn_adv_active = false; // Stops timers from being re-fired. +} + + +void es_adv_timing_init(es_adv_timing_callback_t p_handler) +{ + m_non_conn_adv_active = false; + m_timing_mgr_callback = p_handler; + memset(&m_adv_timing_result, 0, sizeof(m_adv_timing_result)); +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing.h new file mode 100644 index 0000000..6728de5 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing.h @@ -0,0 +1,97 @@ +/** + * 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 ES_ADV_TIMING_H__ +#define ES_ADV_TIMING_H__ + +#include + +/** + * @file + * @defgroup eddystone_adv_timing Timing + * @brief Events and functions for advertisement timing. + * @ingroup eddystone_adv + * @{ + */ + +/**@brief Eddystone advertisement timing event types. */ +typedef enum +{ + ES_ADV_TIMING_EVT_ADV_SLOT, //!< Advertising non-eTLM slot. + ES_ADV_TIMING_EVT_ADV_ETLM //!< Advertising eTLM slot. +} es_adv_timing_evt_id_t; + +/**@brief Eddystone advertisement timing event. */ +typedef struct +{ + es_adv_timing_evt_id_t evt_id; //!< Event type ID. + uint8_t slot_no; /**< @brief Slot number. + * @details For non-eTLM events: The slot number to advertise. + * + * For eTLM events: The slot number of the corresponding EID slot. */ +} es_adv_timing_evt_t; + +/**@brief Eddystone advertisement timing event callback. + * + * @param[in] p_evt Pointer to the Eddystone advertisement timing event. + */ +typedef void (*es_adv_timing_callback_t)(const es_adv_timing_evt_t * p_evt); + +/**@brief Function for starting Eddystone advertisement timing event generation. */ +void es_adv_timing_start(uint16_t adv_interval); + + +/**@brief Function for stopping Eddystone advertisement timing event generation. */ +void es_adv_timing_stop(void); + +/**@brief Function for initializing the Eddystone advertisement timers. + */ +void es_adv_timing_timers_init(void); + +/**@brief Function for initializing the Eddystone advertisement timing module. + * + * @param[in] handler Eddystone advertisement timing event handler to register. + */ +void es_adv_timing_init(es_adv_timing_callback_t handler); + +/** + * @} + */ + +#endif // ES_ADV_TIMING_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing_resolver.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing_resolver.c new file mode 100644 index 0000000..35c29c9 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing_resolver.c @@ -0,0 +1,145 @@ +/** + * 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. + * + */ + +#include "es_adv_timing_resolver.h" +#include "sdk_macros.h" + +/**@brief Function for finding delay to use after each non-eTLM advertisement. + * + * @param[in] adv_interval Configured advertisement interval. + * @param[in] num_slots_configured Number of configured slots. + * @param[in] eTLM_required Is there an eTLM slot. + */ +static uint16_t get_adv_delay(uint16_t adv_interval, + uint8_t num_slots_configured, + bool eTLM_required) +{ + // If eTLM is required, don't count this when calculating delay. + return adv_interval / (num_slots_configured - (eTLM_required ? 1 : 0)); +} + + +/**@brief Function for checking if given slot_no is an EID slot. + * + * @param[in] slot_no Slot number to check. + * @param[in] p_eid_slots_configured Pointer to list of configured EID slots. + * @param[in] num_eid_slots_configured Number of EID slots configured. + */ +static bool is_eid(uint8_t slot_no, const uint8_t * p_eid_slots_configured, uint8_t num_eid_slots_configured) +{ + for (uint32_t i = 0; i < num_eid_slots_configured; ++i) + { + if (slot_no == p_eid_slots_configured[i]) + { + return true; + } + } + + return false; +} + +ret_code_t es_adv_timing_resolve(es_adv_timing_resolver_input_t * p_input) +{ + VERIFY_PARAM_NOT_NULL(p_input); + + uint8_t result_index = 0; + bool eTLM_required = p_input->tlm_configured && p_input->num_eid_slots_configured > 0; + uint16_t base_delay; + + if (p_input->num_slots_configured == 0) + { + return NRF_ERROR_INVALID_PARAM; + } + + base_delay = get_adv_delay(p_input->adv_interval, p_input->num_slots_configured, eTLM_required); + + for (uint32_t i = 0; i < p_input->num_slots_configured; ++i) + { + uint8_t slot_no = p_input->p_slots_configured[i]; + + if (!(eTLM_required && slot_no == p_input->tlm_slot)) + { + es_adv_timing_resolver_adv_timing_t * p_current_result = &p_input->p_result->timing_results[result_index]; + p_current_result->slot_no = slot_no; + p_current_result->is_etlm = false; + + // If an eTLM is to be advertised for this frame, this value will be changed. + p_current_result->delay_ms = base_delay; + + result_index++; + + if (eTLM_required && + is_eid(slot_no, p_input->p_eid_slots_configured, p_input->num_eid_slots_configured)) + { + es_adv_timing_resolver_adv_timing_t * p_eTLM_timing_result = + &p_input->p_result->timing_results[result_index]; + + p_current_result->delay_ms = APP_CONFIG_ADV_FRAME_ETLM_SPACING_MS; // Update delay from EID to eTLM frame. + + p_eTLM_timing_result->slot_no = slot_no; // Point to EID slot-no, as this will be + // used for finding the correct EIK. + p_eTLM_timing_result->is_etlm = true; // Configure as eTLM frame. + + if (base_delay > APP_CONFIG_ADV_FRAME_ETLM_SPACING_MS) + { + p_eTLM_timing_result->delay_ms = + base_delay - + APP_CONFIG_ADV_FRAME_ETLM_SPACING_MS; // Set delay of eTLM frame. + } + + else + { + p_eTLM_timing_result->delay_ms = APP_CONFIG_ADV_FRAME_SPACING_MS_MIN; + } + + result_index++; + } + } + } + + p_input->p_result->len_timing_results = result_index; // Note: index has been increased to equal length of result. + + if (p_input->p_result->len_timing_results > 0) + { + p_input->p_result->timing_results[p_input->p_result->len_timing_results - 1].delay_ms = 0; // Last Slot does not need delay. + } + + return NRF_SUCCESS; +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing_resolver.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing_resolver.h new file mode 100644 index 0000000..303ec53 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing_resolver.h @@ -0,0 +1,96 @@ +/** + * 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 ES_ADV_TIMING_RESOLVER_H__ +#define ES_ADV_TIMING_RESOLVER_H__ + +#include +#include +#include "es_app_config.h" + +/** + * @file + * @addtogroup eddystone_adv_timing + * @{ + */ + +/** @brief Timing parameters for a single slot. */ +typedef struct +{ + bool is_etlm; //!< Flag that specifies if the slot is an eTLM. + uint8_t slot_no; /**< @brief Slot number. @details + * For non-eTLM slots: The slot number of the given frame. + * + * For eTLM slots: The slot number of the corresponding EID frame. */ + uint16_t delay_ms; //!< Delay from this frame to the next. +} es_adv_timing_resolver_adv_timing_t; + +/**@brief Results of calculating advertisement delays. */ +typedef struct +{ + es_adv_timing_resolver_adv_timing_t timing_results[APP_MAX_ADV_SLOTS - APP_MAX_EID_SLOTS + + (APP_MAX_EID_SLOTS * 2)]; //!< List of timing results. + uint8_t len_timing_results; //!< Length of results. +} es_adv_timing_resolver_result_t; + +/**@brief Input to the timing resolver. */ +typedef struct +{ + uint16_t adv_interval; //!< Global advertisement interval. + uint8_t num_slots_configured; //!< Number of configured slots. + const uint8_t * p_slots_configured; //!< Pointer to the list of configured slots. + uint8_t num_eid_slots_configured; //!< Number of configured EID slots. + const uint8_t * p_eid_slots_configured; //!< Pointer to the list of configured EID slots. + bool tlm_configured; //!< Flag that specifies if TLM slot is configured. + uint8_t tlm_slot; //!< Slot number of the TLM slot (if @p tlm_configured is true). + es_adv_timing_resolver_result_t * p_result; //!< Output result. +} es_adv_timing_resolver_input_t; + +/**@brief Function for getting the input for advertisement interval calculation. + * + * @param[in,out] p_input Input to advertisement interval calculation (see @ref es_adv_timing_resolver_input_t). + * @retval NRF_SUCCESS If the operation was successful. Otherwise, an error code is returned. + */ +ret_code_t es_adv_timing_resolve(es_adv_timing_resolver_input_t * p_input); + +/** + * @} + */ + +#endif // ES_ADV_TIMING_RESOLVER_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_battery_voltage.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_battery_voltage.h new file mode 100644 index 0000000..2125f00 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_battery_voltage.h @@ -0,0 +1,66 @@ +/** + * 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 ES_BATTERY_VOLTAGE_H__ +#define ES_BATTERY_VOLTAGE_H__ + +#include + +/** + * @file + * + * @addtogroup eddystone_tlm + * @{ + */ + +/**@brief Function for initializing the battery voltage module. + */ +void es_battery_voltage_init(void); + +/**@brief Function for reading the battery voltage. + * + * @param[out] p_vbatt Pointer to the battery voltage value. + */ +void es_battery_voltage_get(uint16_t * p_vbatt); + +/** + * @} + */ + +#endif // ES_BATTERY_VOLTAGE_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_battery_voltage_saadc.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_battery_voltage_saadc.c new file mode 100644 index 0000000..71502da --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_battery_voltage_saadc.c @@ -0,0 +1,104 @@ +/** + * 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. + * + */ +#include "es_battery_voltage.h" +#include "nrf_drv_saadc.h" +#include "sdk_macros.h" + +#define ADC_REF_VOLTAGE_IN_MILLIVOLTS 600 //!< Reference voltage (in milli volts) used by ADC while doing conversion. +#define DIODE_FWD_VOLT_DROP_MILLIVOLTS 270 //!< Typical forward voltage drop of the diode (Part no: SD103ATW-7-F) that is connected in series with the voltage supply. This is the voltage drop when the forward current is 1mA. Source: Data sheet of 'SURFACE MOUNT SCHOTTKY BARRIER DIODE ARRAY' available at www.diodes.com. +#define ADC_RES_10BIT 1024 //!< Maximum digital value for 10-bit ADC conversion. +#define ADC_PRE_SCALING_COMPENSATION 6 //!< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage. +#define ADC_RESULT_IN_MILLI_VOLTS(ADC_VALUE) \ + ((((ADC_VALUE) *ADC_REF_VOLTAGE_IN_MILLIVOLTS) / ADC_RES_10BIT) * ADC_PRE_SCALING_COMPENSATION) + +static nrf_saadc_value_t adc_buf; //!< Buffer used for storing ADC value. +static uint16_t m_batt_lvl_in_milli_volts; //!< Current battery level. + +/**@brief Function handling events from 'nrf_drv_saadc.c'. + * + * @param[in] p_evt SAADC event. + */ +static void saadc_event_handler(nrf_drv_saadc_evt_t const * p_evt) +{ + if (p_evt->type == NRF_DRV_SAADC_EVT_DONE) + { + nrf_saadc_value_t adc_result; + + adc_result = p_evt->data.done.p_buffer[0]; + + m_batt_lvl_in_milli_volts = + ADC_RESULT_IN_MILLI_VOLTS(adc_result) + DIODE_FWD_VOLT_DROP_MILLIVOLTS; + } +} + + +void es_battery_voltage_init(void) +{ + ret_code_t err_code = nrf_drv_saadc_init(NULL, saadc_event_handler); + + APP_ERROR_CHECK(err_code); + + nrf_saadc_channel_config_t config = + NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_VDD); + err_code = nrf_drv_saadc_channel_init(0, &config); + APP_ERROR_CHECK(err_code); + + err_code = nrf_drv_saadc_buffer_convert(&adc_buf, 1); + APP_ERROR_CHECK(err_code); + + err_code = nrf_drv_saadc_sample(); + APP_ERROR_CHECK(err_code); +} + + +void es_battery_voltage_get(uint16_t * p_vbatt) +{ + VERIFY_PARAM_NOT_NULL_VOID(p_vbatt); + + *p_vbatt = m_batt_lvl_in_milli_volts; + if (!nrf_drv_saadc_is_busy()) + { + ret_code_t err_code = nrf_drv_saadc_buffer_convert(&adc_buf, 1); + APP_ERROR_CHECK(err_code); + + err_code = nrf_drv_saadc_sample(); + APP_ERROR_CHECK(err_code); + } +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_flash.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_flash.c new file mode 100644 index 0000000..2e408bb --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_flash.c @@ -0,0 +1,340 @@ +/** + * 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. + * + */ +#include +#include "es_flash.h" +#include "es_util.h" +#include "app_scheduler.h" +#include "ble_hci.h" +#include "fds.h" +#include "nrf_nvic.h" + +#define SIZE_OF_PRIV_KEY ESCS_ECDH_KEY_SIZE //!< Size of ECDH private key. +#define SIZE_OF_PUB_KEY ESCS_ECDH_KEY_SIZE //!< Size of ECDH public key. +#define SIZE_OF_LOCK_KEY ESCS_AES_KEY_SIZE //!< Size of lock key. +#define FILE_ID_ES_FLASH 0x1337 //!< File ID used for all flash access EXCEPT lock code. +#define FILE_ID_ES_FLASH_LOCK_KEY 0x1338 //!< File ID used for lock code flash access. +#define RECORD_KEY_FLAGS 0x1 //!< File record for flash flags. +#define RECORD_KEY_PRIV_KEY 0x2 //!< File record for private key. +#define RECORD_KEY_PUB_KEY 0x3 //!< File record for public key. +#define RECORD_KEY_LOCK_KEY 0x4 //!< File record for lock key. +#define RECORD_KEY_BEACON_CONFIG 0x5 //!< File record for lock key. + +static uint16_t RECORD_KEY_SLOTS[5] = {0x6, 0x7, 0x8, 0x9, 0xa}; //!< File record for slots. + +/**@brief Structure used for invoking flash access function. */ +typedef struct +{ + uint16_t record_key; + uint16_t file_id; + uint8_t * p_data_buf; + uint8_t * p_data; + uint16_t size_bytes; + es_flash_access_t access_type; +} flash_access_params_t; + +static volatile uint32_t m_num_pending_ops; //!< Current number of outstanding FDS operations. +static volatile bool m_factory_reset; //!< Should factory reset be performed. +static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; //!< Current connection handle. + + +#if APP_MAX_ADV_SLOTS > 32 +#error "APP_MAX_ADV_SLOTS must be <= 32" +#endif + +#define SLOT_DECL(i, _) __ALIGN(4) static uint8_t slot## i ##_buf[sizeof(es_slot_t)]; +EVAL(REPEAT(APP_MAX_ADV_SLOTS, SLOT_DECL, ~)) + +__ALIGN(4) static uint8_t lock_key_buf[SIZE_OF_LOCK_KEY]; //!< Buffer for lock key flash access. + +#define SLOT(i, _) slot## i ##_buf, +static uint8_t * slots_buf_p[APP_MAX_ADV_SLOTS] = { + EVAL(REPEAT(APP_MAX_ADV_SLOTS, SLOT, ~)) +}; + +__ALIGN(4) static uint8_t flash_flags_buf[sizeof(es_flash_flags_t)]; //!< Buffer for flash flags flash access. +__ALIGN(4) static uint8_t beacon_config_buf[sizeof(es_flash_beacon_config_t)]; //!< Buffer for beacon config flash access. + +/**@brief Function handling scheduled FDS garbage collection. */ +static void fds_gc_event(void * p_event_data, uint16_t event_size) +{ + ret_code_t fds_err_code; + + fds_err_code = fds_gc(); + if (fds_err_code != FDS_SUCCESS) + APP_ERROR_CHECK_BOOL(NRF_ERROR_INTERNAL); + m_num_pending_ops++; +} + + +/**@brief Function handling FDS events. + * + * @param[in] p_evt FDS event. + */ +static void fds_cb(fds_evt_t const * const p_evt) +{ + ret_code_t err_code; + + switch (p_evt->id) + { + case FDS_EVT_INIT: + m_num_pending_ops = 0; + break; + + case FDS_EVT_DEL_FILE: + case FDS_EVT_DEL_RECORD: + // Schedule garbage collection + err_code = app_sched_event_put(NULL, 0, fds_gc_event); + APP_ERROR_CHECK(err_code); + break; + + case FDS_EVT_GC: + if (m_factory_reset && m_conn_handle != BLE_CONN_HANDLE_INVALID) + { + err_code = + sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + APP_ERROR_CHECK(err_code); + } + + // Fall through: + case FDS_EVT_UPDATE: + case FDS_EVT_WRITE: + if (m_num_pending_ops > 0) + { + m_num_pending_ops--; + } + break; + } +} + + +/**@brief Function performing flash access (read/write/clear). + * + * @param[in] p_params Flash access parameters. + */ +static ret_code_t access_flash_data(const flash_access_params_t * p_params) +{ + ret_code_t err_code; + fds_flash_record_t record = {0}; + fds_record_desc_t desc = {0}; + fds_find_token_t ft = {0}; + fds_record_t record_to_write = + { + .data.p_data = p_params->p_data_buf, + .file_id = p_params->file_id + }; + + err_code = fds_record_find_by_key(p_params->record_key, &desc, &ft); + + // If its a read or clear, we can not accept errors on lookup + if (p_params->access_type == ES_FLASH_ACCESS_READ) + { + RETURN_IF_ERROR(err_code); + } + + if (p_params->access_type == ES_FLASH_ACCESS_CLEAR && err_code == FDS_ERR_NOT_FOUND) + { + return NRF_SUCCESS; + } + + switch (p_params->access_type) + { + case ES_FLASH_ACCESS_READ: + err_code = fds_record_open(&desc, &record); + RETURN_IF_ERROR(err_code); + + memcpy(p_params->p_data, record.p_data, p_params->size_bytes); + + err_code = fds_record_close(&desc); + RETURN_IF_ERROR(err_code); + + break; + + case ES_FLASH_ACCESS_WRITE: + memcpy(p_params->p_data_buf, p_params->p_data, p_params->size_bytes); + + record_to_write.data.length_words = (p_params->size_bytes +3) / 4; + record_to_write.key = p_params->record_key; + + if (err_code == FDS_ERR_NOT_FOUND) + { + err_code = fds_record_write(&desc, &record_to_write); + } + + else + { + err_code = fds_record_update(&desc, &record_to_write); + } + + RETURN_IF_ERROR(err_code); + m_num_pending_ops++; + break; + + case ES_FLASH_ACCESS_CLEAR: + err_code = fds_record_delete(&desc); + RETURN_IF_ERROR(err_code); + m_num_pending_ops++; + break; + + default: + break; + } + return NRF_SUCCESS; +} + + +ret_code_t es_flash_access_lock_key(uint8_t * p_lock_key, es_flash_access_t access_type) +{ + flash_access_params_t params = {.record_key = RECORD_KEY_LOCK_KEY, + .file_id = FILE_ID_ES_FLASH_LOCK_KEY, + .p_data_buf = lock_key_buf, + .p_data = (uint8_t *)p_lock_key, + .size_bytes = SIZE_OF_LOCK_KEY, + .access_type = access_type}; + + return access_flash_data(¶ms); +} + + +ret_code_t es_flash_access_beacon_config(es_flash_beacon_config_t * p_config, + es_flash_access_t access_type) +{ + ret_code_t err_code; + + flash_access_params_t params = {.record_key = RECORD_KEY_BEACON_CONFIG, + .file_id = FILE_ID_ES_FLASH, + .p_data_buf = beacon_config_buf, + .p_data = (uint8_t *)p_config, + .size_bytes = sizeof(es_flash_beacon_config_t), + .access_type = access_type}; + + err_code = access_flash_data(¶ms); + + return err_code; +} + + +ret_code_t es_flash_access_slot_configs(uint8_t slot_no, + es_slot_t * p_slot, + es_flash_access_t access_type) +{ + if (slot_no >= APP_MAX_ADV_SLOTS) + { + return NRF_ERROR_INVALID_PARAM; + } + + flash_access_params_t params = {.record_key = RECORD_KEY_SLOTS[slot_no], + .file_id = FILE_ID_ES_FLASH, + .p_data_buf = slots_buf_p[slot_no], + .p_data = (uint8_t *)p_slot, + .size_bytes = sizeof(es_slot_t), + .access_type = access_type}; + + return access_flash_data(¶ms); +} + + +ret_code_t es_flash_access_flags(es_flash_flags_t * p_flags, es_flash_access_t access_type) +{ + flash_access_params_t params = {.record_key = RECORD_KEY_FLAGS, + .file_id = FILE_ID_ES_FLASH, + .p_data_buf = flash_flags_buf, + .p_data = (uint8_t *)p_flags, + .size_bytes = sizeof(es_flash_flags_t), + .access_type = access_type}; + + return access_flash_data(¶ms); +} + + +ret_code_t es_flash_factory_reset(void) +{ + // Delete everything except the lock key: + ret_code_t ret_code = fds_file_delete(FILE_ID_ES_FLASH); + + if (ret_code == FDS_SUCCESS) + m_factory_reset = true; + return ret_code; +} + + +uint32_t es_flash_num_pending_ops(void) +{ + return m_num_pending_ops; +} + + +void es_flash_on_ble_evt(ble_evt_t const * p_evt) +{ + switch (p_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + m_conn_handle = p_evt->evt.common_evt.conn_handle; + break; + + case BLE_GAP_EVT_DISCONNECTED: + m_conn_handle = BLE_CONN_HANDLE_INVALID; + if (m_factory_reset) + { + (void)sd_nvic_SystemReset(); + } + break; + } +} + + +ret_code_t es_flash_init(void) +{ + ret_code_t err_code; + + m_num_pending_ops = 1; // Will be set to 0 when getting FDS_EVT_INIT event + + m_conn_handle = BLE_CONN_HANDLE_INVALID; + + m_factory_reset = false; + + err_code = fds_register(fds_cb); + RETURN_IF_ERROR(err_code); + + err_code = fds_init(); + RETURN_IF_ERROR(err_code); + + return NRF_SUCCESS; +} + diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_flash.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_flash.h new file mode 100644 index 0000000..d896669 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_flash.h @@ -0,0 +1,177 @@ +/** + * 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 ES_FLASH_H__ +#define ES_FLASH_H__ + +#include +#include +#include "es_slot.h" + + +/** + * @file + * @defgroup eddystone_flash Flash access + * @brief Types and functions to access the flash of the Eddystone beacon. + * @ingroup eddystone + * @{ + */ + +#define WORD_SIZE 4 + +#define FLASH_ACCES_ERROR_CHECK_ALLOW_NOT_FOUND(err_code) \ + if (err_code != (FDS_ERR_NOT_FOUND)) \ + APP_ERROR_CHECK(err_code); + +#define FLASH_OP_WAIT() \ + uint32_t pending_ops = es_flash_num_pending_ops(); \ + while (pending_ops != 0) \ + { \ + pending_ops = es_flash_num_pending_ops(); \ + } + +/**@brief Beacon configuration. */ +typedef struct +{ + nrf_ble_escs_adv_interval_t adv_interval; //!< Advertising interval. + bool remain_connectable; //!< Flag that specifies if the beacon should remain connectable. +} es_flash_beacon_config_t; + +/**@brief Structure for keeping track of which slot has a configuration that must be restored upon reboot. + * @details The size of this structure must be word aligned and match the flash block size of 32 bytes. + */ +typedef struct +{ + bool slot_is_empty[APP_MAX_ADV_SLOTS]; //!< Flag that indicates whether the slot is empty. + uint8_t padding[WORD_SIZE - ((APP_MAX_ADV_SLOTS + 1) % WORD_SIZE)]; //!< Padding used to ensure word alignment. +} es_flash_flags_t; + +/**@brief Flash access types. + */ +typedef enum +{ + ES_FLASH_ACCESS_READ, //!< Read data. + ES_FLASH_ACCESS_WRITE, //!< Write data. + ES_FLASH_ACCESS_CLEAR //!< Clear data. +} es_flash_access_t; + +/**@brief Function for accessing beacon configurations. + * + * @param[out,in] p_config Pointer to the beacon configuration buffer. + * @param[in] access_type Access type (see @ref es_flash_access_t). + * @return For possible return values, see: + * - @ref fds_record_find_by_key + * - @ref fds_record_open + * - @ref fds_record_close + * - @ref fds_record_write + * - @ref fds_record_update + * - @ref fds_record_delete + */ +ret_code_t es_flash_access_beacon_config(es_flash_beacon_config_t * p_config, + es_flash_access_t access_type); + +/**@brief Function for accessing slot configuration from flash. + * + * @param[in] slot_no Slot index. + * @param[out,in] p_slot Pointer to the slot configuration buffer. + * @param[in] access_type Access type (see @ref es_flash_access_t). + * @return For possible return values, see: + * - @ref fds_record_find_by_key + * - @ref fds_record_open + * - @ref fds_record_close + * - @ref fds_record_write + * - @ref fds_record_update + * - @ref fds_record_delete + */ +ret_code_t es_flash_access_slot_configs(uint8_t slot_no, + es_slot_t * p_slot, + es_flash_access_t access_type); + + +/**@brief Function for accessing the beacon lock key from flash. + * + * @param[out,in] p_lock_key Pointer to the lock key buffer. + * @param[in] access_type Access type (see @ref es_flash_access_t). + * @return For possible return values, see: + * - @ref fds_record_find_by_key + * - @ref fds_record_open + * - @ref fds_record_close + * - @ref fds_record_write + * - @ref fds_record_update + * - @ref fds_record_delete + */ +ret_code_t es_flash_access_lock_key(uint8_t * p_lock_key, es_flash_access_t access_type); + +/**@brief Function for accessing the flash configuration flag from flash. + * + * @param[out,in] p_flags Pointer to the flag buffer. + * @param[in] access_type Access type (see @ref es_flash_access_t). + * @return For possible return values, see: + * - @ref fds_record_find_by_key + * - @ref fds_record_open + * - @ref fds_record_close + * - @ref fds_record_write + * - @ref fds_record_update + * - @ref fds_record_delete + */ +ret_code_t es_flash_access_flags(es_flash_flags_t * p_flags, es_flash_access_t access_type); + +/**@brief Function for retrieving the number of queued operations. + * @return The number of operations that are queued. + */ +uint32_t es_flash_num_pending_ops(void); + +/**@brief Function for performing a factory reset. + * @return FDS return code. + */ +ret_code_t es_flash_factory_reset(void); + +void es_flash_on_ble_evt(ble_evt_t const * p_evt); + +/**@brief Function for initializing the flash module. + * + * @return See @ref fds_init for possible return values. + */ +ret_code_t es_flash_init(void); + +/** + * @} + */ + +#endif // ES_FLASH_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts.c new file mode 100644 index 0000000..c6280e2 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts.c @@ -0,0 +1,188 @@ +/** + * 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. + * + */ + +#include "es_gatts.h" +#include "es_gatts_read.h" +#include "es_gatts_write.h" +#include "es_slot.h" + +static nrf_ble_escs_lock_state_read_t m_lock_state; +static uint8_t m_active_slot; + +/**@brief Function checking if beacon is unlocked. + * + * @param[in] p_escs Pointer to Eddystone Configuration Service. + * + * @retval true If beacon is unlocked. + * @retval false If beacon is locked. + */ +static bool is_beacon_unlocked(const nrf_ble_escs_t * p_escs) +{ + return m_lock_state != NRF_BLE_ESCS_LOCK_STATE_LOCKED; +} + + +ret_code_t es_gatts_send_reply(nrf_ble_escs_t * p_escs, + ble_gatts_rw_authorize_reply_params_t * p_reply) +{ + VERIFY_PARAM_NOT_NULL(p_escs); + VERIFY_PARAM_NOT_NULL(p_reply); + + if (p_escs->conn_handle != BLE_CONN_HANDLE_INVALID) + { + return sd_ble_gatts_rw_authorize_reply(p_escs->conn_handle, p_reply); + } + + return NRF_ERROR_INVALID_STATE; +} + + +ret_code_t es_gatts_send_op_not_permitted(nrf_ble_escs_t * p_escs, bool read) +{ + ble_gatts_rw_authorize_reply_params_t reply = {0}; + + VERIFY_PARAM_NOT_NULL(p_escs); + + if (read) + { + reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; + reply.params.read.gatt_status = BLE_GATT_STATUS_ATTERR_READ_NOT_PERMITTED; + } + + else + { + reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; + reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED; + } + + return es_gatts_send_reply(p_escs, &reply); +} + + + +void es_gatts_handle_write(nrf_ble_escs_t * p_escs, + uint16_t uuid, + uint16_t val_handle, + uint8_t const * p_data, + uint16_t length) +{ + ret_code_t err_code; + + if (is_beacon_unlocked(p_escs)) + { + if (uuid == BLE_UUID_ESCS_UNLOCK_CHAR) + { + err_code = es_gatts_send_op_not_permitted(p_escs, false); + APP_ERROR_CHECK(err_code); + } + + else + { + err_code = es_gatts_write_handle_unlocked_write( + p_escs, uuid, val_handle, p_data, length, m_active_slot); + APP_ERROR_CHECK(err_code); + } + } + + else + { + if (uuid == BLE_UUID_ESCS_UNLOCK_CHAR) + { + err_code = es_gatts_write_handle_unlock(p_escs, p_data, length, val_handle); + APP_ERROR_CHECK(err_code); + } + + else + { + err_code = es_gatts_send_op_not_permitted(p_escs, false); + APP_ERROR_CHECK(err_code); + } + } +} + + +void es_gatts_handle_read(nrf_ble_escs_t * p_escs, uint16_t uuid, uint16_t val_handle) +{ + ret_code_t err_code; + + if (is_beacon_unlocked(p_escs)) + { + if (uuid == BLE_UUID_ESCS_UNLOCK_CHAR) + { + err_code = es_gatts_send_op_not_permitted(p_escs, true); + APP_ERROR_CHECK(err_code); + } + + else + { + err_code = es_gatts_read_handle_unlocked_read(p_escs, uuid, val_handle, m_active_slot, m_lock_state); + APP_ERROR_CHECK(err_code); + } + } + + else // Beacon is locked. + { + if (uuid == BLE_UUID_ESCS_UNLOCK_CHAR) + { + err_code = es_gatts_read_handle_unlock(p_escs); + APP_ERROR_CHECK(err_code); + } + + else + { + err_code = es_gatts_read_handle_locked_read(p_escs, uuid, m_lock_state); + APP_ERROR_CHECK(err_code); + } + } +} + + +ret_code_t es_gatts_init(nrf_ble_escs_t * p_ble_escs) +{ + VERIFY_PARAM_NOT_NULL(p_ble_escs); + + m_active_slot = 0; + m_lock_state = NRF_BLE_ESCS_LOCK_STATE_LOCKED; + + p_ble_escs->p_active_slot = &m_active_slot; + p_ble_escs->p_lock_state = &m_lock_state; + + return NRF_SUCCESS; +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts.h new file mode 100644 index 0000000..b5da232 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts.h @@ -0,0 +1,109 @@ +/** + * 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 ES_GATTS_H__ +#define ES_GATTS_H__ + +#include +#include "nrf_ble_escs.h" + +/** + * @file + * @defgroup eddystone_gatts GATTS + * @brief Functions for handling GATTS write and read requests. + * @ingroup eddystone + * @{ + */ + +ret_code_t es_gatts_init(nrf_ble_escs_t * p_ble_escs); + +/**@brief Function for handling all write requests from the Central. + * + * @param[in] p_escs Pointer to the Eddystone Configuration Service. + * @param[in] uuid The UUID of the characteristic that is being written to. + * @param[in] val_handle Value handle field of the characteristic handle of the characteristic that is being written to. + * @param[in] p_data Pointer to the data to be written. + * @param[in] length Length of the data to be written. + * + */ +void es_gatts_handle_write(nrf_ble_escs_t * p_escs, + uint16_t uuid, + uint16_t val_handle, + uint8_t const * p_data, + uint16_t length); + + +/**@brief Function for handling all read requests from the Central. + * + * @param[in] p_escs Pointer to the Eddystone Configuration Service. + * @param[in] uuid The UUID of the characteristic that is being read from. + * @param[in] val_handle Value handle field of the characteristic handle of the characteristic that is being read from. + * + */ +void es_gatts_handle_read(nrf_ble_escs_t * p_escs, uint16_t uuid, uint16_t val_handle); + +/**@brief Function for sending an RW-authorization reply. + * + * @param[in] p_escs Pointer to the Eddystone Configuration Service. + * @param[in] p_reply Pointer to the reply to send. + * + * @retval NRF_SUCCESS If the reply was successfully issued to the SoftDevice. + * @retval NRF_ERROR_NULL If either of the pointers @p p_escs or @p p_reply is NULL. + * @retval NRF_ERROR_INVALID_STATE If the connection handle of @p p_escs is invalid. + * @return Otherwise, an error code from sd_ble_gatts_rw_authorize_reply() is returned. + */ +ret_code_t es_gatts_send_reply(nrf_ble_escs_t * p_escs, ble_gatts_rw_authorize_reply_params_t * p_reply); + +/**@brief Function for sending an RW-authorization reply with status 'Operation not permitted'. + * + * @param[in] p_escs Pointer to the Eddystone Configuration Service. + * @param[in] op_is_read Flag that specifies if the operation being responded to is a 'read' operation. + If false, a 'write' operation is assumed. + * + * @retval NRF_ERROR_NULL If @p p_escs is NULL. + * @return Otherwise, the error code from es_gatts_send_reply() is returned. + */ +ret_code_t es_gatts_send_op_not_permitted(nrf_ble_escs_t * p_escs, bool op_is_read); + +/** + * @} + */ + +#endif // ES_GATTS_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_read.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_read.c new file mode 100644 index 0000000..6ab51de --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_read.c @@ -0,0 +1,246 @@ +/** + * 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. + * + */ + +#include "es_gatts_read.h" +#include "es_adv.h" +#include "es_gatts.h" +#include "es_security.h" +#include "es_slot.h" + +static ret_code_t send_read_reply(nrf_ble_escs_t * p_escs, ble_gatts_rw_authorize_reply_params_t * p_reply) +{ + VERIFY_PARAM_NOT_NULL(p_escs); + VERIFY_PARAM_NOT_NULL(p_reply); + + p_reply->type = BLE_GATTS_AUTHORIZE_TYPE_READ; + p_reply->params.read.update = 1; + p_reply->params.read.offset = 0; + + return es_gatts_send_reply(p_escs, p_reply); +} + + +static ret_code_t read_value(nrf_ble_escs_t * p_escs, uint8_t length, const void * p_value) +{ + VERIFY_PARAM_NOT_NULL(p_escs); + VERIFY_PARAM_NOT_NULL(p_value); + + ble_gatts_rw_authorize_reply_params_t reply = {0}; + reply.params.read.len = length; + reply.params.read.p_data = p_value; + reply.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS; + + return send_read_reply(p_escs, &reply); +} + + +static ret_code_t read_from_gattdb(nrf_ble_escs_t * p_escs, uint16_t val_handle) +{ + VERIFY_PARAM_NOT_NULL(p_escs); + + ret_code_t err_code; + + // Go straight to the characteristic + uint8_t value_buffer[ESCS_ADV_SLOT_CHAR_LENGTH_MAX] = {0}; + ble_gatts_value_t value = {.len = sizeof(value_buffer), + .offset = 0, + .p_value = &(value_buffer[0])}; + + err_code = sd_ble_gatts_value_get(p_escs->conn_handle, val_handle, &value); + RETURN_IF_ERROR(err_code); + + return read_value(p_escs, value.len, value.p_value); +} + + +static ret_code_t read_adv_slot(nrf_ble_escs_t * p_escs, uint8_t active_slot, const es_slot_reg_t * p_reg) +{ + VERIFY_PARAM_NOT_NULL(p_escs); + + ble_gatts_rw_authorize_reply_params_t reply = {0}; + uint8_t eid_buf[14]; + + // If an EID slot is read, load scaler, clock value and ephemeral ID. + if (p_reg->slots[active_slot].adv_frame.type == ES_FRAME_TYPE_EID) + { + /*lint -save -e666 */ + uint32_t clock_value = es_security_clock_get(active_slot); + clock_value = BYTES_REVERSE_32BIT(clock_value); + /*lint -restore */ + + reply.params.read.len = ES_EID_GATTS_READ_LENGTH; + + // Fill EID buffer with data + eid_buf[ES_EID_GATTS_READ_FRAME_TYPE_IDX] = ES_FRAME_TYPE_EID; + eid_buf[ES_EID_GATTS_READ_EXPONENT_IDX] = es_security_scaler_get(active_slot); + + memcpy(&eid_buf[ES_EID_GATTS_READ_CLCK_VALUE_IDX], &clock_value, sizeof(clock_value)); + /*lint -save -e545 */ + memcpy(&eid_buf[ES_EID_GATTS_READ_EID_IDX], + &p_reg->slots[active_slot].adv_frame.frame.eid.eid, + ES_EID_ID_LENGTH); + /*lint -restore */ + reply.params.read.p_data = eid_buf; + } + + // Otherwise, simply load the contents of the frame. + else + { + // Check if slot being read is an eTLM slot. + if ((p_reg->num_configured_eid_slots > 0) && p_reg->tlm_configured && (p_reg->tlm_slot == active_slot)) + { + // Fill eTLM slot using EID key from first EID slot. + es_slot_etlm_update(p_reg->eid_slots_configured[0]); + } + reply.params.read.len = p_reg->slots[active_slot].adv_frame.length; + reply.params.read.p_data = (uint8_t *)&p_reg->slots[active_slot].adv_frame.frame; + } + + reply.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS; + + return send_read_reply(p_escs, &reply); +} + + +ret_code_t es_gatts_read_handle_locked_read(nrf_ble_escs_t * p_escs, uint16_t uuid, uint8_t lock_state) +{ + VERIFY_PARAM_NOT_NULL(p_escs); + + if (uuid == BLE_UUID_ESCS_REMAIN_CONNECTABLE_CHAR) + { + uint8_t retval = APP_IS_REMAIN_CONNECTABLE_SUPPORTED; + return read_value(p_escs, sizeof(retval), &retval); + } + + else if (uuid == BLE_UUID_ESCS_LOCK_STATE_CHAR) + { + return read_value(p_escs, sizeof(lock_state), &lock_state); + } + + else + { + return es_gatts_send_op_not_permitted(p_escs, true); + } +} + + +ret_code_t es_gatts_read_handle_unlock(nrf_ble_escs_t * p_escs) +{ + VERIFY_PARAM_NOT_NULL(p_escs); + + ret_code_t err_code; + uint8_t key_buff[ESCS_AES_KEY_SIZE]; + + err_code = es_security_random_challenge_generate(key_buff); + RETURN_IF_ERROR(err_code); + + es_security_unlock_prepare(key_buff); + + return read_value(p_escs, ESCS_AES_KEY_SIZE, key_buff); +} + + +ret_code_t es_gatts_read_handle_unlocked_read(nrf_ble_escs_t * p_escs, + uint16_t uuid, + uint16_t val_handle, + uint8_t active_slot, + uint8_t lock_state) +{ + VERIFY_PARAM_NOT_NULL(p_escs); + + const es_slot_reg_t * p_reg = es_slot_get_registry(); + + switch (uuid) + { + case BLE_UUID_ESCS_BROADCAST_CAP_CHAR: + case BLE_UUID_ESCS_UNLOCK_CHAR: + case BLE_UUID_ESCS_PUBLIC_ECDH_KEY_CHAR: + case BLE_UUID_ESCS_ACTIVE_SLOT_CHAR: + return read_from_gattdb(p_escs, val_handle); + + case BLE_UUID_ESCS_LOCK_STATE_CHAR: + return read_value(p_escs, sizeof(lock_state), &lock_state); + + case BLE_UUID_ESCS_ADV_INTERVAL_CHAR: + { + nrf_ble_escs_adv_interval_t adv_interval = es_adv_interval_get(); + adv_interval = BYTES_SWAP_16BIT(adv_interval); + return read_value(p_escs, sizeof(adv_interval), &adv_interval); + } + + case BLE_UUID_ESCS_RADIO_TX_PWR_CHAR: + return read_value(p_escs, + sizeof(nrf_ble_escs_radio_tx_pwr_t), + &p_reg->slots[active_slot].radio_tx_pwr); + + case BLE_UUID_ESCS_ADV_TX_PWR_CHAR: + return read_value(p_escs, + sizeof(nrf_ble_escs_radio_tx_pwr_t), + p_reg->slots[active_slot].adv_custom_tx_power + ? (uint8_t *)(&p_reg->slots[active_slot].custom_tx_power) + : (uint8_t *)(&p_reg->slots[active_slot].radio_tx_pwr)); + + case BLE_UUID_ESCS_REMAIN_CONNECTABLE_CHAR: + { + uint8_t retval = APP_IS_REMAIN_CONNECTABLE_SUPPORTED; + return read_value(p_escs, sizeof(retval), &retval); + } + + case BLE_UUID_ESCS_EID_ID_KEY_CHAR: + if (p_reg->slots[active_slot].configured && + (p_reg->slots[active_slot].adv_frame.type == ES_FRAME_TYPE_EID)) + { + return read_value(p_escs, + sizeof(nrf_ble_escs_eid_id_key_t), + &p_reg->slots[active_slot].encrypted_eid_id_key); + } + + else + { + return es_gatts_send_op_not_permitted(p_escs, true); + } + + case BLE_UUID_ESCS_RW_ADV_SLOT_CHAR: + return read_adv_slot(p_escs, active_slot, p_reg); + + default: + return NRF_ERROR_INVALID_PARAM; + } +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_read.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_read.h new file mode 100644 index 0000000..32cc818 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_read.h @@ -0,0 +1,73 @@ +/** + * 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 ES_GATTS_READ_H__ +#define ES_GATTS_READ_H__ + +#include +#include "nrf_ble_escs.h" + +/** + * @file + * @defgroup eddystone_gatts_read GATTS read + * @brief Functions for handling GATTS read requests. + * @ingroup eddystone_gatts + * @{ + */ + +ret_code_t es_gatts_read_send_not_permitted(nrf_ble_escs_t * p_escs); + +ret_code_t es_gatts_read_handle_unlocked_read(nrf_ble_escs_t * p_escs, + uint16_t uuid, + uint16_t val_handle, + uint8_t active_slot, + uint8_t lock_state); + +ret_code_t es_gatts_read_handle_unlock(nrf_ble_escs_t * p_escs); + +ret_code_t es_gatts_read_handle_locked_read(nrf_ble_escs_t * p_escs, + uint16_t uuid, + uint8_t lock_state); + +/** + * @} + */ + +#endif // ES_GATTS_READ_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_write.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_write.c new file mode 100644 index 0000000..8a66493 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_write.c @@ -0,0 +1,254 @@ +/** + * 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. + * + */ + +#include "es_gatts_write.h" +#include "es_adv.h" +#include "es_flash.h" +#include "es_gatts.h" +#include "es_security.h" + + +static ret_code_t send_write_reply(nrf_ble_escs_t * p_escs, ble_gatts_rw_authorize_reply_params_t * p_reply) +{ + VERIFY_PARAM_NOT_NULL(p_escs); + VERIFY_PARAM_NOT_NULL(p_reply); + + p_reply->type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; + p_reply->params.write.update = 1; + p_reply->params.write.offset = 0; + + return es_gatts_send_reply(p_escs, p_reply); +} + + +/**@brief Function checking if length of event is correct, given the frame data. + * + * @param[in] p_data Written ADV Slot data. + * @param[in] length Written length. + * + * @retval true If length is valid. + * @retval false If length is not valid. + */ +static bool length_is_valid(uint8_t const * p_data, uint8_t length) +{ + if (length == 0 || (length == 1 && p_data[0] == 0)) + { + return true; + } + + else + { + switch ((es_frame_type_t)p_data[0]) + { + case ES_FRAME_TYPE_UID: + return length == ESCS_UID_WRITE_LENGTH; + + case ES_FRAME_TYPE_URL: + return ((length >= ESCS_URL_MIN_WRITE_LENGTH) && (length <= ESCS_URL_WRITE_LENGTH)); + + case ES_FRAME_TYPE_TLM: + return (length == ESCS_TLM_WRITE_LENGTH); + + case ES_FRAME_TYPE_EID: + return ((length == ESCS_EID_WRITE_ECDH_LENGTH) || + (length == ESCS_EID_WRITE_IDK_LENGTH)); + + default: + return false; + } + } +} + + +ret_code_t es_gatts_write_handle_unlocked_write(nrf_ble_escs_t * p_escs, + uint16_t uuid, + uint16_t val_handle, + uint8_t const * p_data, + uint16_t length, + uint8_t active_slot) +{ + VERIFY_PARAM_NOT_NULL(p_escs); + VERIFY_PARAM_NOT_NULL(p_data); + + ret_code_t err_code; + ble_gatts_rw_authorize_reply_params_t reply = {0}; + bool long_write = false; + + reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + + switch (uuid) + { + case BLE_UUID_ESCS_ACTIVE_SLOT_CHAR: + if (*p_data > APP_MAX_ADV_SLOTS - 1) + { + // Invalid Attribute Length: for an attempt to write illegal values. + // The beacon will list the total number of available slots in the + // max_supported_total_slots field in the Capabilities characteristic. + reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH; + length = 0; + } + break; + + case BLE_UUID_ESCS_ADV_INTERVAL_CHAR: + es_adv_interval_set(BYTES_SWAP_16BIT(*(nrf_ble_escs_adv_interval_t *)p_data)); + break; + + case BLE_UUID_ESCS_RADIO_TX_PWR_CHAR: + es_slot_radio_tx_pwr_set(active_slot, *(nrf_ble_escs_radio_tx_pwr_t *)(p_data)); + break; + + case BLE_UUID_ESCS_ADV_TX_PWR_CHAR: + // Update slot info so that ADV data will only be read from what is written by client. + es_slot_set_adv_custom_tx_power(active_slot, *(nrf_ble_escs_radio_tx_pwr_t *)(p_data)); + break; + + case BLE_UUID_ESCS_LOCK_STATE_CHAR: + if (length == 1 && (*p_data == NRF_BLE_ESCS_LOCK_BYTE_LOCK || + *p_data == NRF_BLE_ESCS_LOCK_BYTE_DISABLE_AUTO_RELOCK)) + { + // Do nothing special, allow the write. + } + else if (length == ESCS_LOCK_STATE_NEW_LOCK_CODE_WRITE_LENGTH && + *p_data == NRF_BLE_ESCS_LOCK_BYTE_LOCK) + { + // 0x00 + key[16] : transition to lock state and update the lock code. + err_code = es_security_lock_code_update((uint8_t*)(p_data) + 1); + RETURN_IF_ERROR(err_code); + + // Only write the lock byte (0x00) to the characteristic, so set length to 1. + length = 1; + } + else + { + // Any invalid values locks the characteristic by default. + (*(uint8_t*)p_data) = NRF_BLE_ESCS_LOCK_BYTE_LOCK; + length = 1; + } + break; + + case BLE_UUID_ESCS_RW_ADV_SLOT_CHAR: + if (length > 20) + { + long_write = true; + } + reply.params.write.gatt_status = length_is_valid(p_data, length) + ? BLE_GATT_STATUS_SUCCESS + : BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH; + + if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) + { + es_slot_on_write(active_slot, length, p_data); + es_adv_interval_set(es_adv_interval_get()); // Ensure that valid advertisement interval is used. + } + break; + + case BLE_UUID_ESCS_FACTORY_RESET_CHAR: + if (*p_data == 0x0B) + { + err_code = es_flash_factory_reset(); + RETURN_IF_ERROR(err_code); + } + break; + + case BLE_UUID_ESCS_REMAIN_CONNECTABLE_CHAR: +#if APP_IS_REMAIN_CONNECTABLE_SUPPORTED == ESCS_FUNCT_REMAIN_CONNECTABLE_SUPPORTED_Yes + if (*p_data != 0) + { + es_adv_remain_connectable_set(true); + } + + else + { + es_adv_remain_connectable_set(false); + } +#endif + break; + + default: + break; + } + reply.params.write.len = length; + reply.params.write.p_data = p_data; + + if (!long_write) + { + return send_write_reply(p_escs, &reply); + } + + else + { + return NRF_SUCCESS; + } +} + + +ret_code_t es_gatts_write_handle_unlock(nrf_ble_escs_t * p_escs, + uint8_t const * p_data, + uint16_t length, + uint16_t val_handle) +{ + VERIFY_PARAM_NOT_NULL(p_escs); + VERIFY_PARAM_NOT_NULL(p_data); + + ret_code_t err_code; + ble_gatts_rw_authorize_reply_params_t reply = {0}; + ble_gatts_value_t value = {.len = length, .offset = 0, .p_value = (uint8_t*)p_data}; + + if (length == ESCS_AES_KEY_SIZE) + { + err_code = sd_ble_gatts_value_set(p_escs->conn_handle, val_handle, &value); + + if (err_code == NRF_SUCCESS) + { + reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; + es_security_unlock_verify((value.p_value)); + } + + else + { + reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED; + } + } + + reply.params.write.len = length; + reply.params.write.p_data = (const uint8_t *)value.p_value; + + return send_write_reply(p_escs, &reply); +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_write.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_write.h new file mode 100644 index 0000000..2bcbce1 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_write.h @@ -0,0 +1,71 @@ +/** + * 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 ES_GATTS_WRITE_H__ +#define ES_GATTS_WRITE_H__ + +#include +#include "nrf_ble_escs.h" + +/** + * @file + * @defgroup eddystone_gatts_write GATTS write + * @brief Functions for handling GATTS write requests. + * @ingroup eddystone_gatts + * @{ + */ + +ret_code_t es_gatts_write_handle_unlocked_write(nrf_ble_escs_t * p_escs, + uint16_t uuid, + uint16_t val_handle, + uint8_t const * p_data, + uint16_t length, + uint8_t active_slot); + +ret_code_t es_gatts_write_handle_unlock(nrf_ble_escs_t * p_escs, + uint8_t const * p_data, + uint16_t length, + uint16_t val_handle); + +/** + * @} + */ + +#endif // ES_GATTS_WRITE_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_security.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_security.c new file mode 100644 index 0000000..303556a --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_security.c @@ -0,0 +1,596 @@ +/** + * 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. + * + */ +#include +#include +#include "es_security.h" +#include "app_timer.h" +#include "es_flash.h" +#include "es_stopwatch.h" +#include "fds.h" +#include "modes.h" +#include "nrf_crypto.h" + +#define TK_ROLLOVER 0x10000 + +#define NONCE_SIZE (6) +#define TAG_SIZE (2) +#define SALT_SIZE (2) +#define TLM_DATA_SIZE (ES_TLM_LENGTH - 2) +#define EIK_SIZE (ESCS_AES_KEY_SIZE) +#define AES_ECB_CIPHERTEXT_LENGTH (16) +#define AES_ECB_CLEARTEXT_LENGTH (16) + +/**@brief Timing structure. */ +typedef struct +{ + uint32_t time_counter; + uint8_t k_scaler; +} es_security_timing_t; + +/**@brief Security slot structure. */ +typedef struct +{ + nrf_ecb_hal_data_t aes_ecb_ik; + nrf_ecb_hal_data_t aes_ecb_tk; + uint8_t eid[ES_EID_ID_LENGTH]; + es_security_timing_t timing; + bool is_occupied; +} es_security_slot_t; + +/**@brief Key pair structure. */ +typedef struct +{ + nrf_crypto_ecc_private_key_t private; + nrf_crypto_ecc_public_key_t public; +} ecdh_key_pair_t; + +/**@brief ECDH structure. */ +typedef struct +{ + ecdh_key_pair_t ecdh_key_pair; +} es_security_ecdh_t; + +static nrf_ecb_hal_data_t m_aes_ecb_lk; +static es_security_slot_t m_security_slot[APP_MAX_EID_SLOTS]; +static es_security_ecdh_t m_ecdh; +static es_security_msg_cb_t m_security_callback; +static es_stopwatch_id_t m_seconds_passed_sw_id; + +// Use static context variables to avoid stack allocation. +static nrf_crypto_aes_context_t m_aes_context; +static nrf_crypto_hmac_context_t m_hmac_context; +static nrf_crypto_aead_context_t m_aead_context; +static nrf_crypto_ecc_key_pair_generate_context_t ecc_key_pair_generate_context; +static nrf_crypto_ecdh_context_t ecdh_context; + +/**@brief Generates a EID with the Temporary Key*/ +static void eid_generate(uint8_t slot_no) +{ + ret_code_t err_code; + size_t ciphertext_size = AES_ECB_CIPHERTEXT_LENGTH; + + memset(m_security_slot[slot_no].aes_ecb_tk.cleartext, 0, ESCS_AES_KEY_SIZE); + m_security_slot[slot_no].aes_ecb_tk.cleartext[11] = m_security_slot[slot_no].timing.k_scaler; + + uint32_t k_bits_cleared_time = + (m_security_slot[slot_no].timing.time_counter >> m_security_slot[slot_no].timing.k_scaler) + << m_security_slot[slot_no].timing.k_scaler; + + m_security_slot[slot_no].aes_ecb_tk.cleartext[12] = + (uint8_t)((k_bits_cleared_time >> 24) & 0xff); + m_security_slot[slot_no].aes_ecb_tk.cleartext[13] = + (uint8_t)((k_bits_cleared_time >> 16) & 0xff); + m_security_slot[slot_no].aes_ecb_tk.cleartext[14] = (uint8_t)((k_bits_cleared_time >> 8) & 0xff); + m_security_slot[slot_no].aes_ecb_tk.cleartext[15] = (uint8_t)((k_bits_cleared_time) & 0xff); + + err_code = nrf_crypto_aes_crypt(&m_aes_context, + &g_nrf_crypto_aes_ecb_128_info, + NRF_CRYPTO_ENCRYPT, // Operation + m_security_slot[slot_no].aes_ecb_tk.key, // Key + NULL, // IV + m_security_slot[slot_no].aes_ecb_tk.cleartext, // Data in + AES_ECB_CLEARTEXT_LENGTH, // Data in size + m_security_slot[slot_no].aes_ecb_tk.ciphertext, // Data out + &ciphertext_size); // Data out size + + APP_ERROR_CHECK(err_code); + + memcpy(m_security_slot[slot_no].eid, + m_security_slot[slot_no].aes_ecb_tk.ciphertext, + ES_EID_ID_LENGTH); + + m_security_callback(slot_no, ES_SECURITY_MSG_EID); +} + + +/**@brief Generates a temporary key with the Identity key. */ +static void temp_key_generate(uint8_t slot_no) +{ + ret_code_t err_code; + size_t ciphertext_size = AES_ECB_CIPHERTEXT_LENGTH; + + memset(m_security_slot[slot_no].aes_ecb_ik.cleartext, 0, ESCS_AES_KEY_SIZE); + m_security_slot[slot_no].aes_ecb_ik.cleartext[11] = 0xFF; + m_security_slot[slot_no].aes_ecb_ik.cleartext[14] = + (uint8_t)((m_security_slot[slot_no].timing.time_counter >> 24) & 0xff); + m_security_slot[slot_no].aes_ecb_ik.cleartext[15] = + (uint8_t)((m_security_slot[slot_no].timing.time_counter >> 16) & 0xff); + + err_code = nrf_crypto_aes_crypt(&m_aes_context, + &g_nrf_crypto_aes_ecb_128_info, + NRF_CRYPTO_ENCRYPT, // Operation + m_security_slot[slot_no].aes_ecb_ik.key, // Key + NULL, // IV + m_security_slot[slot_no].aes_ecb_ik.cleartext, // Data in + AES_ECB_CLEARTEXT_LENGTH, // Data in size + m_security_slot[slot_no].aes_ecb_ik.ciphertext, // Data out + &ciphertext_size); // Data out size + + APP_ERROR_CHECK(err_code); + + memcpy(m_security_slot[slot_no].aes_ecb_tk.key, + m_security_slot[slot_no].aes_ecb_ik.ciphertext, + ESCS_AES_KEY_SIZE); +} + + +static void check_rollovers_and_update_eid(uint8_t slot_no) +{ + if (m_security_slot[slot_no].timing.time_counter % TK_ROLLOVER == 0) + { + temp_key_generate(slot_no); + } + /*lint -save -e573 */ + if ((m_security_slot[slot_no].timing.time_counter % + (2 << (m_security_slot[slot_no].timing.k_scaler - 1))) == 0) + { + eid_generate(slot_no); + } + /*lint -restore */ +} + + +/**@brief Initialize lock code from flash. If it does not exist, copy from APP_CONFIG_LOCK_CODE. + */ +static void lock_code_init(uint8_t * p_lock_buff) +{ + ret_code_t err_code; + + err_code = es_flash_access_lock_key(p_lock_buff, ES_FLASH_ACCESS_READ); + FLASH_ACCES_ERROR_CHECK_ALLOW_NOT_FOUND(err_code); + + // If no lock keys exist, then generate one and copy it to buffer. + if (err_code == FDS_ERR_NOT_FOUND) + { + uint8_t lock_code[16] = APP_CONFIG_LOCK_CODE; + + memcpy(p_lock_buff, lock_code, sizeof(lock_code)); + + err_code = es_flash_access_lock_key(p_lock_buff, ES_FLASH_ACCESS_WRITE); + APP_ERROR_CHECK(err_code); + } +} + + +void es_security_update_time(void) +{ + static uint32_t timer_persist; + uint32_t second_since_last_invocation = es_stopwatch_check(m_seconds_passed_sw_id); + + if (second_since_last_invocation > 0) + { + for (uint32_t i = 0; i < APP_MAX_EID_SLOTS; ++i) + { + if (m_security_slot[i].is_occupied) + { + m_security_slot[i].timing.time_counter += second_since_last_invocation; + check_rollovers_and_update_eid(i); + } + } + + // Every 24 hr, write the new EID timer to flash. + timer_persist += second_since_last_invocation; + const uint32_t TWENTY_FOUR_HOURS = 60 * 60 * 24; + if (timer_persist >= TWENTY_FOUR_HOURS) + { + for (uint32_t i = 0; i < APP_MAX_EID_SLOTS; ++i) + { + if (m_security_slot[i].is_occupied) + { + m_security_callback(i, ES_SECURITY_MSG_STORE_TIME); + } + } + timer_persist = 0; + } + } +} + + +void es_security_eid_slots_restore(uint8_t slot_no, + uint8_t k_scaler, + uint32_t time_counter, + const uint8_t * p_ik) +{ + m_security_slot[slot_no].timing.k_scaler = k_scaler; + m_security_slot[slot_no].timing.time_counter = time_counter; + memcpy(m_security_slot[slot_no].aes_ecb_ik.key, p_ik, ESCS_AES_KEY_SIZE); + m_security_slot[slot_no].is_occupied = true; + m_security_callback(slot_no, ES_SECURITY_MSG_IK); + temp_key_generate(slot_no); + eid_generate(slot_no); +} + + +ret_code_t es_security_lock_code_update(uint8_t * p_ecrypted_key) +{ + ret_code_t err_code; + uint8_t temp_buff[ESCS_AES_KEY_SIZE] = {0}; + size_t temp_buff_size = sizeof(temp_buff); + + err_code = nrf_crypto_aes_crypt(&m_aes_context, + &g_nrf_crypto_aes_ecb_128_info, + NRF_CRYPTO_DECRYPT, // Operation + m_aes_ecb_lk.key, // Key + NULL, // IV + p_ecrypted_key, // Data in + 16, // Data in size + temp_buff, // Data out + &temp_buff_size); // Data out size + + VERIFY_SUCCESS(err_code); + + memcpy(m_aes_ecb_lk.key, temp_buff, ESCS_AES_KEY_SIZE); + return es_flash_access_lock_key(m_aes_ecb_lk.key, ES_FLASH_ACCESS_WRITE); +} + + +void es_security_unlock_prepare(uint8_t * p_challenge) +{ + ret_code_t err_code; + size_t ciphertext_size = AES_ECB_CIPHERTEXT_LENGTH; + + memcpy(m_aes_ecb_lk.cleartext, p_challenge, ESCS_AES_KEY_SIZE); + + err_code = nrf_crypto_aes_crypt(&m_aes_context, + &g_nrf_crypto_aes_ecb_128_info, + NRF_CRYPTO_ENCRYPT, // Operation + m_aes_ecb_lk.key, // Key + NULL, // IV + m_aes_ecb_lk.cleartext, // Data in + AES_ECB_CLEARTEXT_LENGTH, // Data in size + m_aes_ecb_lk.ciphertext, // Data out + &ciphertext_size); // Data out size + + APP_ERROR_CHECK(err_code); +} + + +void es_security_unlock_verify(uint8_t * p_unlock_token) +{ + if (memcmp(p_unlock_token, m_aes_ecb_lk.ciphertext, ESCS_AES_KEY_SIZE) == 0) + { + m_security_callback(0, ES_SECURITY_MSG_UNLOCKED); + } +} + + +ret_code_t es_security_random_challenge_generate(uint8_t * p_rand_chlg_buff) +{ + return nrf_crypto_rng_vector_generate(p_rand_chlg_buff, ESCS_AES_KEY_SIZE); +} + + +void es_security_shared_ik_receive(uint8_t slot_no, uint8_t * p_encrypted_ik, uint8_t scaler_k) +{ + ret_code_t err_code; + size_t cleartext_size = AES_ECB_CLEARTEXT_LENGTH; + + m_security_slot[slot_no].is_occupied = true; + m_security_slot[slot_no].timing.k_scaler = scaler_k; + m_security_slot[slot_no].timing.time_counter = APP_CONFIG_TIMING_INIT_VALUE; + + err_code = nrf_crypto_aes_crypt(&m_aes_context, + &g_nrf_crypto_aes_ecb_128_info, + NRF_CRYPTO_DECRYPT, // Operation + m_aes_ecb_lk.key, // Key + NULL, // IV + p_encrypted_ik, // Data in + 16, // Data in size + m_security_slot[slot_no].aes_ecb_ik.key, // Data out + &cleartext_size); // Data out size + + APP_ERROR_CHECK(err_code); + + temp_key_generate(slot_no); + eid_generate(slot_no); + + m_security_callback(slot_no, ES_SECURITY_MSG_IK); +} + + +void es_security_client_pub_ecdh_receive(uint8_t slot_no, uint8_t * p_pub_ecdh, uint8_t scaler_k) +{ + ret_code_t err_code; + nrf_crypto_ecc_public_key_t phone_public; // Phone public ECDH key + uint8_t beacon_public[ESCS_ECDH_KEY_SIZE]; // Beacon public ECDH key + uint8_t shared[ESCS_ECDH_KEY_SIZE]; // Shared secret ECDH key + uint8_t public_keys[64]; // Buffer for concatenated public keys + uint8_t key_material[64]; // Buffer for holding key material + uint8_t empty_check[ESCS_ECDH_KEY_SIZE] = {0}; + size_t beacon_public_size = sizeof(beacon_public); + size_t shared_size = sizeof(shared); + size_t key_material_size = sizeof(key_material); + + m_security_slot[slot_no].is_occupied = true; + m_security_slot[slot_no].timing.k_scaler = scaler_k; + m_security_slot[slot_no].timing.time_counter = APP_CONFIG_TIMING_INIT_VALUE; + + // Get public 32-byte service ECDH key from phone. + err_code = nrf_crypto_ecc_public_key_from_raw(&g_nrf_crypto_ecc_curve25519_curve_info, + &phone_public, + p_pub_ecdh, + ESCS_ECDH_KEY_SIZE); + + APP_ERROR_CHECK(err_code); + + // Generate key pair. + err_code = nrf_crypto_ecc_key_pair_generate(&ecc_key_pair_generate_context, + &g_nrf_crypto_ecc_curve25519_curve_info, + &m_ecdh.ecdh_key_pair.private, + &m_ecdh.ecdh_key_pair.public); + + APP_ERROR_CHECK(err_code); + + // Generate shared 32-byte ECDH secret from beacon private service ECDH key and phone public ECDH key. + err_code = nrf_crypto_ecdh_compute(&ecdh_context, + &m_ecdh.ecdh_key_pair.private, + &phone_public, + shared, + &shared_size); + + APP_ERROR_CHECK(err_code); + + // Verify that the shared secret is not zero at this point, and report an error/reset if it is. + if (memcmp(empty_check, shared, ESCS_ECDH_KEY_SIZE) == 0) + { + APP_ERROR_CHECK(NRF_ERROR_INTERNAL); + } + + // Concatenate the resolver's public key and beacon's public key + err_code = nrf_crypto_ecc_public_key_to_raw(&m_ecdh.ecdh_key_pair.public, + beacon_public, + &beacon_public_size); + + APP_ERROR_CHECK(err_code); + + memcpy(public_keys, p_pub_ecdh, 32); + memcpy(public_keys + 32, beacon_public, 32); + + // Convert the shared secret to key material using HKDF-SHA256. HKDF is used with the salt set + // to a concatenation of the resolver's public key and beacon's public key + err_code = nrf_crypto_hkdf_calculate(&m_hmac_context, + &g_nrf_crypto_hmac_sha256_info, + key_material, // Output key + &key_material_size, // Output key size + shared, // Input key + sizeof(shared), // Input key size + public_keys, // Salt + sizeof(public_keys), // Salt size + NULL, // Additional info + 0, // Additional info size + NRF_CRYPTO_HKDF_EXTRACT_AND_EXPAND); // Mode + + APP_ERROR_CHECK(err_code); + + // Truncate the key material to 128 bits to convert it to an AES-128 secret key (Identity key). + memcpy(m_security_slot[slot_no].aes_ecb_ik.key, key_material, ESCS_AES_KEY_SIZE); + + temp_key_generate(slot_no); + eid_generate(slot_no); + + m_security_callback(slot_no, ES_SECURITY_MSG_ECDH); + m_security_callback(slot_no, ES_SECURITY_MSG_IK); +} + + +void es_security_pub_ecdh_get(uint8_t slot_no, uint8_t * p_edch_buffer) +{ + ret_code_t err_code; + size_t buffer_size = ESCS_ECDH_KEY_SIZE; + + err_code = nrf_crypto_ecc_public_key_to_raw(&m_ecdh.ecdh_key_pair.public, + p_edch_buffer, + &buffer_size); + + APP_ERROR_CHECK(err_code); +} + + +uint32_t es_security_clock_get(uint8_t slot_no) +{ + return m_security_slot[slot_no].timing.time_counter; +} + + +void es_security_eid_slot_destroy(uint8_t slot_no) +{ + memset(&m_security_slot[slot_no], 0, sizeof(es_security_slot_t)); +} + + +uint8_t es_security_scaler_get(uint8_t slot_no) +{ + return m_security_slot[slot_no].timing.k_scaler; +} + + +void es_security_eid_get(uint8_t slot_no, uint8_t * p_eid_buffer) +{ + memcpy(p_eid_buffer, m_security_slot[slot_no].eid, ES_EID_ID_LENGTH); +} + + +void es_security_encrypted_eid_id_key_get(uint8_t slot_no, uint8_t * p_key_buffer) +{ + ret_code_t err_code; + size_t ciphertext_size = AES_ECB_CIPHERTEXT_LENGTH; + + memcpy(m_aes_ecb_lk.cleartext, m_security_slot[slot_no].aes_ecb_ik.key, ESCS_AES_KEY_SIZE); + + err_code = nrf_crypto_aes_crypt(&m_aes_context, + &g_nrf_crypto_aes_ecb_128_info, + NRF_CRYPTO_ENCRYPT, // Operation + m_aes_ecb_lk.key, // Key + NULL, // IV + m_aes_ecb_lk.cleartext, // Data in + AES_ECB_CLEARTEXT_LENGTH, // Data in size + m_aes_ecb_lk.ciphertext, // Data out + &ciphertext_size); // Data out size + + APP_ERROR_CHECK(err_code); + + memcpy(p_key_buffer, m_aes_ecb_lk.ciphertext, ESCS_AES_KEY_SIZE); +} + + +void es_security_plain_eid_id_key_get(uint8_t slot_no, uint8_t * p_key_buffer) +{ + memcpy(p_key_buffer, m_security_slot[slot_no].aes_ecb_ik.key, ESCS_AES_KEY_SIZE); +} + + +void es_security_tlm_to_etlm(uint8_t ik_slot_no, es_tlm_frame_t * p_tlm, es_etlm_frame_t * p_etlm) +{ + ret_code_t err_code; + uint8_t plain[TLM_DATA_SIZE] = {0}; // Plaintext tlm, without the frame byte and version. + size_t nplain = TLM_DATA_SIZE; // Length of message plaintext. + + /*lint -save -e420 */ + memcpy(plain, &p_tlm->vbatt[0], sizeof(plain)); + + uint8_t key[EIK_SIZE] = {0}; // Encryption/decryption key: EIK. + + memcpy(key, &m_security_slot[ik_slot_no].aes_ecb_ik.key[0], EIK_SIZE); + /*lint -restore */ + + uint8_t nonce[NONCE_SIZE] = {0}; // Nonce. This must not repeat for a given key. + size_t nnonce = NONCE_SIZE; // Length of nonce.First 4 bytes are beacon time base with k-bits cleared. + // Last two bits are randomly generated + + // Take the current timestamp and clear the lowest K bits, use it as nonce. + uint32_t k_bits_cleared_time = (m_security_slot[ik_slot_no].timing.time_counter + >> m_security_slot[ik_slot_no].timing.k_scaler) + << m_security_slot[ik_slot_no].timing.k_scaler; + + nonce[0] = (uint8_t)((k_bits_cleared_time >> 24) & 0xff); + nonce[1] = (uint8_t)((k_bits_cleared_time >> 16) & 0xff); + nonce[2] = (uint8_t)((k_bits_cleared_time >> 8) & 0xff); + nonce[3] = (uint8_t)((k_bits_cleared_time) & 0xff); + + // Generate random salt. + uint8_t salt[SALT_SIZE] = {0}; + err_code = nrf_crypto_rng_vector_generate(salt, SALT_SIZE); + APP_ERROR_CHECK(err_code); + memcpy(&nonce[4], salt, SALT_SIZE); + + uint8_t cipher[ES_ETLM_ECRYPTED_LENGTH]; // Ciphertext output. nplain bytes are written. + uint8_t tag[TAG_SIZE] = {0}; // Authentication tag. ntag bytes are written. + size_t ntag = TAG_SIZE; // Length of authentication tag. + + // Encryption + // -------------------------------------------------------------------------- + err_code = nrf_crypto_aead_init(&m_aead_context, &g_nrf_crypto_aes_eax_128_info, key); + APP_ERROR_CHECK(err_code); + + err_code = nrf_crypto_aead_crypt(&m_aead_context, + NRF_CRYPTO_ENCRYPT, // Operation + nonce, // Nonce + nnonce, // Nonce size + NULL, // Additional authenticated data (adata) + 0, // Additional authenticated data size + plain, // Input data + nplain, // Input data size + cipher, // Output data + tag, // MAC result output + ntag); // MAC size + + APP_ERROR_CHECK(err_code); + + err_code = nrf_crypto_aead_uninit(&m_aead_context); + APP_ERROR_CHECK(err_code); + + // Construct the eTLM. + // -------------------------------------------------------------------------- + p_etlm->frame_type = p_tlm->frame_type; + p_etlm->version = ES_TLM_VERSION_ETLM; + memcpy(p_etlm->encrypted_tlm, cipher, ES_ETLM_ECRYPTED_LENGTH); + memcpy((uint8_t *)&p_etlm->random_salt, salt, SALT_SIZE); + memcpy((uint8_t *)&p_etlm->msg_integrity_check, tag, TAG_SIZE); +} + + +ret_code_t es_security_init(es_security_msg_cb_t security_callback) +{ + ret_code_t err_code; + + if (security_callback == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Get lock code from 'es_app_config.h', or fetch it from flash if exists. + lock_code_init(m_aes_ecb_lk.key); + + m_security_callback = security_callback; + + memset(&m_ecdh, 0, sizeof(es_security_ecdh_t)); + + for (uint32_t i = 0; i < APP_MAX_EID_SLOTS; ++i) + { + m_security_slot[i].timing.time_counter = APP_CONFIG_TIMING_INIT_VALUE; + } + err_code = es_stopwatch_create(&m_seconds_passed_sw_id, APP_TIMER_TICKS(1000)); + APP_ERROR_CHECK(err_code); + + err_code = nrf_crypto_init(); + APP_ERROR_CHECK(err_code); + + return NRF_SUCCESS; +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_security.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_security.h new file mode 100644 index 0000000..e518ebe --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_security.h @@ -0,0 +1,238 @@ +/** + * 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 ES_SECURITY_H__ +#define ES_SECURITY_H__ + +#include "app_error.h" +#include "nrf_ble_escs.h" + +/** + * @file + * @defgroup eddystone_security Security + * @brief Types and functions for dealing with security of Eddystone beacons. + * @ingroup eddystone + * @{ + */ + +/**@brief Security events. + */ +typedef enum +{ + ES_SECURITY_MSG_UNLOCKED, //!< Beacon is unlocked. + ES_SECURITY_MSG_EID, //!< EID has been generated. + ES_SECURITY_MSG_IK, //!< IK has been generated. + ES_SECURITY_MSG_ECDH, //!< Public ECDH has been generated. + ES_SECURITY_MSG_STORE_TIME //!< EID slot time must be stored. +} es_security_msg_t; + +/* @brief Callback for security events. */ +typedef void (*es_security_msg_cb_t)(uint8_t slot_no, es_security_msg_t msg_type); + +/**@brief EID configuration. + * + * @details This structure is used to preserve or restore an EID slot. + * + * @note This is a packed structure. Therefore, you should not change it. +*/ +typedef PACKED_STRUCT +{ + es_frame_type_t frame_type; + uint8_t k_scaler; + uint32_t time_counter; + uint8_t ik[ESCS_AES_KEY_SIZE]; +} es_eid_config_t; + +/**@brief Eddystone beacon lock state. + */ +typedef nrf_ble_escs_lock_state_read_t es_security_lock_state_t; + +/**@brief Function for initializing the security module. + * + * @param[in] msg_cb Callback function. + * + * @return See @ref app_timer_start for possible return values. + */ +ret_code_t es_security_init(es_security_msg_cb_t msg_cb); + +/**@brief Function for updating the lock code and storing it to flash. + * + * @param[in] p_encrypted_key Pointer to the new lock code. + * + * @return See @ref es_flash_access_lock_key for possible return values. + */ +ret_code_t es_security_lock_code_update(uint8_t * p_encrypted_key); + +/**@brief Function for reading the challenge and encrypting it with AES_ECB. + * + * @details The result of the encryption is compared with the provided unlock token + * in @ref es_security_unlock_verify. + * + * @param[in] p_challenge Pointer to the challenge buffer. + * + * @return See @ref sd_ecb_block_encrypt for possible return values. + */ +void es_security_unlock_prepare(uint8_t * p_challenge); + +/**@brief Function for unlocking the beacon. + * + * @details This function compares the result from @ref es_security_unlock_prepare to the input + * unlock token and unlocks the beacon if matching. + * + * @param[in] p_unlock_token The unlock token written by the client. + */ +void es_security_unlock_verify(uint8_t * p_unlock_token); + +/**@brief Function for generating a random challenge for the unlock characteristic. + * + * @param[out] p_rand_chlg_buff Pointer to a buffer to which the random challenge is copied. + * + * @return See @ref sd_rand_application_vector_get for possible return values. + */ +ret_code_t es_security_random_challenge_generate(uint8_t * p_rand_chlg_buff); + +/**@brief Function for storing the public ECDH key from the client in the beacon registration process. + * + * @details This function starts a series of cryptographic activities, including the generation of temporary keys and EIDs. + * + * @param[in] slot_no The index of the slot whose public ECDH key is retrieved. + * @param[in] p_pub_ecdh Pointer to the public ECDH. + * @param[in] scaler_k K rotation scaler. + */ +void es_security_client_pub_ecdh_receive(uint8_t slot_no, uint8_t * p_pub_ecdh, uint8_t scaler_k); + + +/**@brief Function for storing the shared IK from the client in the beacon registration process. + * + * @details This function starts a series of cryptographic activities, including the generation of temporary keys and EIDs. + * + * @param[in] slot_no The index of the slot whose public ECDH key is retrieved. + * @param[in] p_encrypted_ik Pointer to the received IK. + * @param[in] scaler_k K rotation scaler. + */ +void es_security_shared_ik_receive(uint8_t slot_no, uint8_t * p_encrypted_ik, uint8_t scaler_k); + +/**@brief Function for copying the 32-byte ECDH key into the provided buffer. + * + * @param[in] slot_no The index of the slot whose public ECDH key is retrieved. + * @param[out] p_edch_buffer Pointer to the buffer. + */ +void es_security_pub_ecdh_get(uint8_t slot_no, uint8_t * p_edch_buffer); + +/**@brief Function for returning the beacon clock value (in little endian). + * + * @param[in] slot_no The index of the slot. + * + * @return 32-bit clock value. + */ +uint32_t es_security_clock_get(uint8_t slot_no); + +/**@brief Function for updating the beacon time counter. + * + * @details This function checks how much time has passed since the last + * invocation and, if required, updates the EID, the temporary key, or both. + * The function generates an @ref ES_SECURITY_MSG_STORE_TIME event + * for each active security slot every 24 hours. + */ +void es_security_update_time(void); + +/**@brief Function for returning the rotation exponent scaler value. + * + * @param[in] slot_no The index of the slot. + * + * @return K rotation scaler. + */ +uint8_t es_security_scaler_get(uint8_t slot_no); + +/**@brief Function for copying the 8-byte EID into the provided buffer. + * + * @param[in] slot_no The index of the slot whose EID is retrieved. + * @param[out] p_eid_buffer Pointer to the buffer. + */ +void es_security_eid_get(uint8_t slot_no, uint8_t * p_eid_buffer); + +/**@brief Function for restoring an EID slot. + * + * @param[in] slot_no The index of the slot to restore. + * @param[in] k_scaler K rotation scaler. + * @param[in] time_counter EID slot time counter value (in seconds). + * @param[in] p_ik Pointer to the identity key of the specified slot. + */ +void es_security_eid_slots_restore(uint8_t slot_no, + uint8_t k_scaler, + uint32_t time_counter, + const uint8_t * p_ik); + +/**@brief Function for destroying stored EID states. + * + * @details This function should be called when the slot is either overwritten as another slot or + * cleared by writing an empty byte or a single 0. + * + * @param[in] slot_no The index of the slot to destroy. + */ +void es_security_eid_slot_destroy(uint8_t slot_no); + +/**@brief Function for copying the 16-byte EID ID key into the provided buffer. + * + * @param[in] slot_no The index of the EID slot whose IK is retrieved. + * @param[out] p_key_buffer Buffer for the key. + */ +void es_security_plain_eid_id_key_get(uint8_t slot_no, uint8_t * p_key_buffer); + +/**@brief Function for copying the 16-byte LK encrypted EID ID key into the provided buffer. + * + * @param[in] slot_no The index of the EID slot whose encrypted IK is retrieved. + * @param[out] p_key_buffer Buffer for the key. + */ +void es_security_encrypted_eid_id_key_get(uint8_t slot_no, uint8_t * p_key_buffer); + + +/**@brief Function for converting a TLM frame into an eTLM frame using the EIK of the specified slot. + * + * @param[in] ik_slot_no The index of the EID slot whose IK is paired with the eTLM. + * @param[in] p_tlm Pointer to the TLM frame buffer. + * @param[out] p_etlm Pointer to the eTLM frame buffer. + */ +void es_security_tlm_to_etlm(uint8_t ik_slot_no, es_tlm_frame_t * p_tlm, es_etlm_frame_t * p_etlm); + +/** + * @} + */ + +#endif // ES_SECURITY_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot.c new file mode 100644 index 0000000..55590a7 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot.c @@ -0,0 +1,440 @@ +/** + * 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. + * + */ +#include +#include +#include "es_slot.h" +#include "es_flash.h" +#include "es_security.h" +#include "es_slot_reg.h" +#include "es_tlm.h" +#include "fds.h" + +static es_slot_reg_t m_reg; //!< Slot registry. +static bool m_eid_loaded_from_flash; //!< Set to true if EID slot has been loaded from flash. + +#define RANGING_DATA_INDEX (1) //!< Index of ranging data within frames that contain ranging data. +#define RANGING_DATA_LENGTH (1) //!< Length of ranging data. + +/**@brief Enforce legal slot number. + * + * @param[in] p_slot Pointer to the slot number variable to check. + */ +static void slot_boundary_check(uint8_t * p_slot) +{ + if (*p_slot > (APP_MAX_ADV_SLOTS - 1)) + { + *p_slot = (APP_MAX_ADV_SLOTS - 1); + } +} + + +/**@brief Function loading slot data from flash. + * + * @param[in] slot_no Slot number to be used. + */ +static void load_slot_from_flash(uint8_t slot_no) +{ + ret_code_t err_code; + + err_code = es_flash_access_slot_configs(slot_no, &m_reg.slots[slot_no], ES_FLASH_ACCESS_READ); + if (err_code != FDS_ERR_NOT_FOUND) + { + APP_ERROR_CHECK(err_code); + + if (m_reg.slots[slot_no].adv_frame.type == ES_FRAME_TYPE_EID) + { + m_eid_loaded_from_flash = true; + + es_security_eid_slots_restore(slot_no, + m_reg.slots[slot_no].k_scaler, + m_reg.slots[slot_no].seconds, + (const uint8_t *)m_reg.slots[slot_no].ik); + } + + else + { + // If a non-EID slot has been loaded, update the state of m_reg immediately. + es_slot_reg_update_slot_list_info_on_add(&m_reg, slot_no, m_reg.slots[slot_no].adv_frame.type, true); + } + } +} + + +/**@brief Function for setting the ranging data field to be broadcast in the frame. + * + * @param[in] slot_no The slot index. + * @param[in] tx_power The radio tx power to be calibrated to ranging data. + */ +static void set_ranging_data_for_slot(uint8_t slot_no, nrf_ble_escs_radio_tx_pwr_t tx_power) +{ + int8_t ranging_data_array[ESCS_NUM_OF_SUPPORTED_TX_POWER] = APP_CONFIG_CALIBRATED_RANGING_DATA; + nrf_ble_escs_radio_tx_pwr_t supported_tx[ESCS_NUM_OF_SUPPORTED_TX_POWER] = + ESCS_SUPPORTED_TX_POWER; + + int8_t ranging_data = 0; + + if (m_reg.slots[slot_no].adv_custom_tx_power) + { + ranging_data = m_reg.slots[slot_no].custom_tx_power; + } + + else + { + for (uint32_t i = 0; i < ESCS_NUM_OF_SUPPORTED_TX_POWER; ++i) + { + if (supported_tx[i] >= tx_power) + { + ranging_data = ranging_data_array[i]; + break; + } + } + } + es_adv_frame_t * frame = &m_reg.slots[slot_no].adv_frame; + switch (frame->type) + { + case ES_FRAME_TYPE_UID: + { + es_uid_frame_t * uid = &frame->frame.uid; + uid->ranging_data = ranging_data; + break; + } + + case ES_FRAME_TYPE_URL: + { + es_url_frame_t * url = &frame->frame.url; + url->ranging_data = ranging_data; + break; + } + + case ES_FRAME_TYPE_EID: + { + es_eid_frame_t * eid = &frame->frame.eid; + eid->ranging_data = ranging_data; + break; + } + + case ES_FRAME_TYPE_TLM: + APP_ERROR_CHECK(NRF_ERROR_INVALID_PARAM); + break; + } +} + + +/**@brief Function configuring a non-EID slot. + * + * @param[in] slot_no Slot number to be used. + * @param[in] length Length of write operation. + * @param[in] p_frame_data Pointer to written data. + */ +static void configure_slot(uint8_t slot_no, uint8_t length, uint8_t const * p_frame_data) +{ + // If a TLM slot is being configured and there already exists a TLM. + if ((es_frame_type_t)p_frame_data[0] == ES_FRAME_TYPE_TLM && m_reg.tlm_configured) + { + return; // Silently ignore any attempts to create more than one TLM slot as there is no point. + } + + es_slot_reg_update_slot_list_info_on_add(&m_reg, slot_no, (es_frame_type_t)p_frame_data[0], false); + + // For convenience, frame_type is stored in two places, set both. + m_reg.slots[slot_no].adv_frame.type = (es_frame_type_t)p_frame_data[0]; + memcpy(&m_reg.slots[slot_no].adv_frame.frame, &m_reg.slots[slot_no].adv_frame.type, 1); + + uint8_t * p_data_after_ranging_data = ((uint8_t *)(&m_reg.slots[slot_no].adv_frame.frame) + + RANGING_DATA_INDEX + RANGING_DATA_LENGTH); + + switch (m_reg.slots[slot_no].adv_frame.type) + { + case ES_FRAME_TYPE_UID: + // Fall through. + case ES_FRAME_TYPE_URL: + memcpy(p_data_after_ranging_data, &p_frame_data[1], length - 1); + set_ranging_data_for_slot(slot_no, APP_CFG_DEFAULT_RADIO_TX_POWER); + m_reg.slots[slot_no].adv_frame.length = length + 1; // + 1 for ranging data + break; + + case ES_FRAME_TYPE_TLM: + es_tlm_tlm_get(&m_reg.slots[slot_no].adv_frame.frame.tlm); + m_reg.slots[slot_no].adv_frame.length = ES_TLM_LENGTH; + break; + + default: + break; + } +} + + +/**@brief Function configuring an EID slot. + * + * @param[in] slot_no Slot number to be used. + * @param[in] length Length of write operation. + * @param[in] p_frame_data Pointer to written data. + */ +static void configure_eid_slot(uint8_t slot_no, uint8_t length, uint8_t const * p_frame_data) +{ + bool clear_eid_slot = false; + + // Do not update slot count, as this will be done when in the callback invoked when the EID data + // is ready. + // As it takes a while to do the calculation, temporarily remove the slot being overwritten. + // The slot will be re-added in the callback invoked when the EID data is ready. + clear_eid_slot = es_slot_reg_clear_slot(&m_reg, slot_no); + + if (clear_eid_slot) + { + es_security_eid_slot_destroy(slot_no); + } + + if (p_frame_data[0] != ES_FRAME_TYPE_EID) + { + APP_ERROR_CHECK(NRF_ERROR_INVALID_STATE); + } + + if (length == ESCS_EID_WRITE_ECDH_LENGTH) + { + es_security_client_pub_ecdh_receive(slot_no, + (uint8_t*)&p_frame_data[ESCS_EID_WRITE_PUB_KEY_INDEX], + p_frame_data[ESCS_EID_WRITE_ECDH_LENGTH -1]); + } + + else if (length == ESCS_EID_WRITE_IDK_LENGTH) + { + es_security_shared_ik_receive(slot_no, + (uint8_t*)&p_frame_data[ESCS_EID_WRITE_ENC_ID_KEY_INDEX], + p_frame_data[ESCS_EID_WRITE_IDK_LENGTH - 1]); + } + + else + { + // Invalid length being written. + APP_ERROR_CHECK(NRF_ERROR_INVALID_PARAM); + } +} + + +ret_code_t es_slot_write_to_flash(uint8_t slot_no) +{ + if (m_reg.slots[slot_no].configured) + { + // If its an EID, we need to store some metadata in order to re-initialize the EID. + if (m_reg.slots[slot_no].adv_frame.type == ES_FRAME_TYPE_EID) + { + m_reg.slots[slot_no].seconds = es_security_clock_get(slot_no); + m_reg.slots[slot_no].k_scaler = es_security_scaler_get(slot_no); + es_security_plain_eid_id_key_get(slot_no, m_reg.slots[slot_no].ik); + } + return es_flash_access_slot_configs(slot_no, &m_reg.slots[slot_no], ES_FLASH_ACCESS_WRITE); + } + + else + { + return es_flash_access_slot_configs(slot_no, NULL, ES_FLASH_ACCESS_CLEAR); + } +} + + +void es_slot_radio_tx_pwr_set(uint8_t slot_no, nrf_ble_escs_radio_tx_pwr_t radio_tx_pwr) +{ + slot_boundary_check(&slot_no); + + m_reg.slots[slot_no].radio_tx_pwr = radio_tx_pwr; + + if (!m_reg.slots[slot_no].adv_custom_tx_power) // Only update TX power in ADV if custom TX power is not set + { + set_ranging_data_for_slot(slot_no, radio_tx_pwr); + } +} + + +void es_slot_set_adv_custom_tx_power(uint8_t slot_no, nrf_ble_escs_adv_tx_pwr_t tx_pwr) +{ + slot_boundary_check(&slot_no); + + m_reg.slots[slot_no].adv_custom_tx_power = true; + m_reg.slots[slot_no].custom_tx_power = tx_pwr; + set_ranging_data_for_slot(slot_no, tx_pwr); +} + + +void es_slot_on_write(uint8_t slot_no, uint8_t length, uint8_t const * p_frame_data) +{ + slot_boundary_check(&slot_no); + + if (p_frame_data == NULL) + { + APP_ERROR_CHECK(NRF_ERROR_NULL); + } + + // Cleared + if (length == 0 || (length == 1 && p_frame_data[0] == 0)) + { + (void)es_slot_reg_clear_slot(&m_reg, slot_no); + } + // EID slot being configured + else if (p_frame_data[0] == ES_FRAME_TYPE_EID && + (length == ESCS_EID_WRITE_ECDH_LENGTH || length == ESCS_EID_WRITE_IDK_LENGTH)) + { + if (m_reg.slots[slot_no].configured) + (void)es_slot_reg_clear_slot(&m_reg, slot_no); + configure_eid_slot(slot_no, length, p_frame_data); + } + // Non-EID slot configured. + else + { + if (m_reg.slots[slot_no].configured) + (void)es_slot_reg_clear_slot(&m_reg, slot_no); + configure_slot(slot_no, length, p_frame_data); + } +} + + +void es_slot_encrypted_eid_id_key_set(uint8_t slot_no, nrf_ble_escs_eid_id_key_t * p_eid_id_key) +{ + slot_boundary_check(&slot_no); + if (p_eid_id_key != NULL) + { + memcpy(&(m_reg.slots[slot_no].encrypted_eid_id_key), p_eid_id_key, + sizeof(nrf_ble_escs_eid_id_key_t)); + } +} + + +void es_slot_eid_ready(uint8_t slot_no) +{ + m_reg.slots[slot_no].adv_frame.type = ES_FRAME_TYPE_EID; + m_reg.slots[slot_no].adv_frame.length = ES_EID_LENGTH; + es_security_eid_get(slot_no, (uint8_t *)m_reg.slots[slot_no].adv_frame.frame.eid.eid); + m_reg.slots[slot_no].adv_frame.frame.eid.frame_type = ES_FRAME_TYPE_EID; + set_ranging_data_for_slot(slot_no, m_reg.slots[slot_no].radio_tx_pwr); + + if (m_eid_loaded_from_flash) + { + es_slot_reg_update_slot_list_info_on_add(&m_reg, slot_no, ES_FRAME_TYPE_EID, true); + m_eid_loaded_from_flash = false; + } + + else + { + es_slot_reg_update_slot_list_info_on_add(&m_reg, slot_no, ES_FRAME_TYPE_EID, false); + } +} + + +static bool slot_is_eid(uint8_t eid_slot_no) +{ + for (uint32_t i = 0; i < m_reg.num_configured_eid_slots; ++i) + { + if (m_reg.eid_slots_configured[i] == eid_slot_no) + { + return true; + } + } + + return false; +} + + +void es_slot_tlm_update(void) +{ + if (m_reg.tlm_configured) + { + es_tlm_tlm_get(&m_reg.slots[m_reg.tlm_slot].adv_frame.frame.tlm); + } +} + + +void es_slot_etlm_update(uint8_t eid_slot_no) +{ + es_tlm_frame_t tlm; + es_etlm_frame_t etlm; + + // Ignore the request if eTLM is not required or slot no does not correspond to an EID slot. + if (!es_slot_reg_etlm_required(&m_reg) || !slot_is_eid(eid_slot_no)) + { + return; + } + + es_tlm_tlm_get(&tlm); + + es_security_tlm_to_etlm(eid_slot_no, &tlm, &etlm); + + memcpy(&m_reg.slots[m_reg.tlm_slot].adv_frame.frame.etlm, &etlm, sizeof(es_etlm_frame_t)); + m_reg.slots[m_reg.tlm_slot].adv_frame.length = sizeof(es_etlm_frame_t); +} + + +const es_slot_reg_t * es_slot_get_registry(void) +{ + return (const es_slot_reg_t *)&m_reg; +} + + +void es_slots_init(const es_slot_t * p_default_slot) +{ + ret_code_t err_code; + es_flash_flags_t flash_flags = {{0}}; + + es_slot_reg_init(&m_reg); + + m_eid_loaded_from_flash = false; + + // Read the flash flags to see if there are any previously stored slot configs + err_code = es_flash_access_flags(&flash_flags, ES_FLASH_ACCESS_READ); + + if (err_code == FDS_ERR_NOT_FOUND) + { + // Factory reset or initial boot, load default data + memcpy(&m_reg.slots[0], p_default_slot, sizeof(*p_default_slot)); + es_slot_reg_update_slot_list_info_on_add(&m_reg, 0, p_default_slot->adv_frame.type, true); + } + + else + { + APP_ERROR_CHECK(err_code); + + for (uint32_t i = 0; i < APP_MAX_ADV_SLOTS; ++i) + { + if (!flash_flags.slot_is_empty[i]) + { + load_slot_from_flash(i); + } + } + } +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot.h new file mode 100644 index 0000000..5b7482e --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot.h @@ -0,0 +1,202 @@ +/** + * 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 ES_SLOT_H__ +#define ES_SLOT_H__ + +#include +#include "es_app_config.h" +#include "nrf_ble_escs.h" + +/** + * @file + * @defgroup eddystone_slot Slots + * @brief Types and functions for handling Eddystone slots. + * @ingroup eddystone + * @{ + */ + +/**@brief Advertisable frame types that can be passed in to the advertising + * data during non-connectable slot advertising. */ + +typedef struct +{ + union + { + es_uid_frame_t uid; //!< UID frame. + es_url_frame_t url; //!< URL frame. + es_tlm_frame_t tlm; //!< TLM frame. + es_eid_frame_t eid; //!< EID frame. + es_etlm_frame_t etlm; //!< eTLM frame. + } frame; + es_frame_type_t type; //!< Type defined twice for convenience (because the other one is inside a union). + uint8_t length; +}es_adv_frame_t; + +/**@brief Slot. */ +typedef struct +{ + uint8_t slot_no; //!< Identifier for the slot, indexed at 0. + nrf_ble_escs_radio_tx_pwr_t radio_tx_pwr; //!< Radio TX power (in dB). + nrf_ble_escs_eid_id_key_t encrypted_eid_id_key; //!< EID key for the slot. + es_adv_frame_t adv_frame; //!< Frame structure to be passed in for advertising data. + bool adv_custom_tx_power; //!< Flag that specifies if the client has written to the 'Advertised TX Power' field of this slot. + nrf_ble_escs_radio_tx_pwr_t custom_tx_power; //!< Custom TX power to advertise (only if @ref adv_custom_tx_power is true). + bool configured; //!< Is this slot configured and active. + uint8_t k_scaler; + uint32_t seconds; + uint8_t ik[ESCS_AES_KEY_SIZE]; +} es_slot_t; + +/**@brief Slot registry. */ +typedef struct +{ + es_slot_t slots[APP_MAX_ADV_SLOTS]; + uint8_t num_configured_slots; + uint8_t num_configured_eid_slots; + uint8_t slots_configured[APP_MAX_ADV_SLOTS]; + uint8_t eid_slots_configured[APP_MAX_EID_SLOTS]; + uint8_t tlm_slot; + bool tlm_configured; + uint8_t scaler_k; + uint8_t enc_key[ESCS_AES_KEY_SIZE]; +} es_slot_reg_t; + +/**@brief Function for initializing the Eddystone slots with default values. + * + * @details This function synchronizes all slots with the initial values. + * + * @param[in] p_default_slot Pointer to the default parameters for a slot. + */ +void es_slots_init(const es_slot_t * p_default_slot); + +/**@brief Function for setting the advertising interval of the specified slot. + * + * For compatibility with the Eddystone specifications, @p p_adv_interval must point to + * a 16-bit big endian value (coming from the characteristic write request), + * which is then converted to a little endian value inside the function before + * it is written into the variable in the slot. + * + * @parameternoteslot + * @parameternoteadv + * + * @param[in] slot_no The index of the slot. + * @param[in,out] p_adv_interval Pointer to the advertisement interval (in ms) to set. + * @param[in] global Flag that should be set if the beacon does not support variable advertising intervals. + */ +void es_slot_adv_interval_set(uint8_t slot_no, + nrf_ble_escs_adv_interval_t * p_adv_interval, + bool global); + +/**@brief Function for setting the TX power of the specified slot. + * + * @parameternoteslot + * @parameternotetxpower + * + * @param[in] slot_no The index of the slot. + * @param[in,out] radio_tx_pwr TX power value to set. + */ +void es_slot_radio_tx_pwr_set(uint8_t slot_no, nrf_ble_escs_radio_tx_pwr_t radio_tx_pwr); + +/**@brief Function for setting the R/W ADV of the specified slot. + * + * @parameternoteslot + * + * @param[in] slot_no The index of the slot. + * @param[in,out] length The length of the data written or read. + * @param[in,out] p_frame_data Pointer to the data. + * + */ +void es_slot_on_write(uint8_t slot_no, uint8_t length, uint8_t const * p_frame_data); + +/**@brief Function for writing the slot's configuration to flash. + * + * @param[in] slot_no The index of the slot. + */ +ret_code_t es_slot_write_to_flash(uint8_t slot_no); + +/**@brief Function for setting the slot's encrypted EID Identity Key to be displayed in the EID Identity Key characteristic. + * + * @parameternoteslot + * + * @param[in] slot_no The index of the slot. + * @param[in,out] p_eid_id_key Pointer to a @ref nrf_ble_escs_eid_id_key_t structure from where the key will be written. + */ +void es_slot_encrypted_eid_id_key_set(uint8_t slot_no, nrf_ble_escs_eid_id_key_t * p_eid_id_key); + +/**@brief Function for marking an EID slot as ready for populating. + * + * @details Call this function when an EID has been generated and the advertisement frame can be populated with the EID. + * + * @param[in] slot_no The index of the slot. + */ +void es_slot_eid_ready(uint8_t slot_no); + +/**@brief Function for updating the TLM slot with updated data. */ +void es_slot_tlm_update(void); + +/**@brief Function for updating the TLM slot with eTLM data. + * + * @details This function uses the EID identity key from the given EID slot number to update the TLM slot. + * + * @param[in] eid_slot_no EID slot to get EID identity key from. + */ +void es_slot_etlm_update(uint8_t eid_slot_no); + +/**@brief Function for getting a pointer to the slot registry. + * + * @return A pointer to the slot registry. + */ +const es_slot_reg_t * es_slot_get_registry(void); + +/**@brief Function for setting a custom advertisement TX power for a given slot. + * + * @parameternoteslot + * @parameternotetxpower + * + * @param[in] slot_no The index of the slot. + * @param[in] tx_pwr Advertised TX power to be set. + */ +void es_slot_set_adv_custom_tx_power(uint8_t slot_no, nrf_ble_escs_adv_tx_pwr_t tx_pwr); + +/** + * @} + */ + +#endif // ES_SLOT_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot_reg.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot_reg.c new file mode 100644 index 0000000..f789e6b --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot_reg.c @@ -0,0 +1,181 @@ +/** + * 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. + * + */ +#include "es_slot_reg.h" + +#define ES_SLOT_NOT_CONFIGURED 0xab /** Value set in configured lists to indicate not configured slot. */ + +/**@brief Function updating 'tlm_configured' property of slot registry when slot is being cleared. + * + * @param[in] p_reg Pointer to slot registry. + * @param[in] slot_no Slot number to be used. + */ +static void update_tlm_configured_on_clearing(es_slot_reg_t * p_reg, uint8_t slot_no) +{ + if (p_reg->tlm_configured && slot_no == p_reg->tlm_slot) + { + p_reg->tlm_configured = false; + } +} + + +/**@brief Function updating 'num_configured_slots' and 'slots_configured' properties of slot registry when slot is being cleared. + * + * @param[in] p_configured Pointer to list of configured slots. + * @param[in] p_num_configured_slots Pointer to number of configured slots. + * @param[in] slot_no Slot number to clear. + */ +static void configured_slots_on_clear_update(uint8_t * p_configured, uint8_t * p_num_configured_slots, uint8_t slot_no) +{ + uint8_t index_of_last_configured_slot = *p_num_configured_slots - 1; + + for (uint32_t i = 0; i < APP_MAX_ADV_SLOTS; ++i) + { + if (p_configured[i] == slot_no) + { + // Copy all values 'to the right' of the cleared slot one step to the left. + if (i < index_of_last_configured_slot) + { + for (uint32_t j = i; j < index_of_last_configured_slot; ++j) + { + p_configured[j] = p_configured[j + 1]; + } + // Write ES_SLOT_NOT_CONFIGURED to all rightmost not configured indexes. + memset(&p_configured[index_of_last_configured_slot], + ES_SLOT_NOT_CONFIGURED, + APP_MAX_ADV_SLOTS - index_of_last_configured_slot); + } + + else + { + // There are no values 'to the right', simply overwrite with ES_SLOT_NOT_CONFIGURED + p_configured[i] = ES_SLOT_NOT_CONFIGURED; + } + + *p_num_configured_slots -= 1; + + return; + } + } +} + + +bool es_slot_reg_etlm_required(const es_slot_reg_t * p_reg) +{ + return (p_reg->num_configured_eid_slots > 0 && p_reg->tlm_configured); +} + + +bool es_slot_reg_clear_slot(es_slot_reg_t * p_reg, uint8_t slot_no) +{ + bool eid_has_been_cleared = false; + + if (p_reg->slots[slot_no].configured) + { + update_tlm_configured_on_clearing(p_reg, slot_no); + + configured_slots_on_clear_update(p_reg->slots_configured, + &p_reg->num_configured_slots, + slot_no); + + if (p_reg->slots[slot_no].adv_frame.type == ES_FRAME_TYPE_EID) + { + configured_slots_on_clear_update(p_reg->eid_slots_configured, + &p_reg->num_configured_eid_slots, + slot_no); + + eid_has_been_cleared = true; + } + + p_reg->slots[slot_no].configured = false; + } + + memset(&p_reg->slots[slot_no], 0, sizeof(p_reg->slots[slot_no])); + + return eid_has_been_cleared; +} + + +void es_slot_reg_update_slot_list_info_on_add(es_slot_reg_t * p_reg, + uint8_t slot_no, + es_frame_type_t frame_type, + bool init) +{ + if (frame_type == ES_FRAME_TYPE_TLM) + { + p_reg->tlm_configured = true; + p_reg->tlm_slot = slot_no; + } + + if (!p_reg->slots[slot_no].configured || init) + { + p_reg->slots[slot_no].configured = true; + + // Note, we use 'num_configured_slots' before incrementing it, so it is pointing to the correct index. + p_reg->slots_configured[p_reg->num_configured_slots] = slot_no; + + p_reg->num_configured_slots++; + + if (frame_type == ES_FRAME_TYPE_EID) + { + p_reg->eid_slots_configured[p_reg->num_configured_eid_slots] = slot_no; + + p_reg->num_configured_eid_slots++; + } + } + + // If an already configured slot has changed from anything TO an EID slot. + else if (frame_type == ES_FRAME_TYPE_EID && + p_reg->slots[slot_no].adv_frame.type != ES_FRAME_TYPE_EID) + { + p_reg->eid_slots_configured[p_reg->num_configured_eid_slots] = slot_no; + + p_reg->num_configured_eid_slots++; + } +} + + +void es_slot_reg_init(es_slot_reg_t * p_reg) +{ + p_reg->tlm_configured = false; + memset(p_reg->slots_configured, ES_SLOT_NOT_CONFIGURED, APP_MAX_ADV_SLOTS); + memset(p_reg->eid_slots_configured, ES_SLOT_NOT_CONFIGURED, APP_MAX_EID_SLOTS); + p_reg->num_configured_eid_slots = 0; + p_reg->num_configured_slots = 0; +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot_reg.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot_reg.h new file mode 100644 index 0000000..5f34d55 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot_reg.h @@ -0,0 +1,90 @@ +/** + * 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 ES_SLOT_REG_H__ +#define ES_SLOT_REG_H__ + +#include +#include "es_slot.h" + +/** + * @file + * @addtogroup eddystone_slot + * @{ + */ + +/** @brief Function for checking if an eTLM frame is required. + * + * @param[in] p_reg Pointer to the slot registry. + * + * @retval true If an eTLM frame is required. + * @retval false Otherwise. + */ +bool es_slot_reg_etlm_required(const es_slot_reg_t * p_reg); + +/** @brief Function for clearing a slot. + * + * @param[in] p_reg Pointer to the slot registry. + * @param[in] slot_no The slot number to clear. + * + * @retval true If an EID slot was cleared. + */ +bool es_slot_reg_clear_slot(es_slot_reg_t * p_reg, uint8_t slot_no); + +/** @brief Function for updating the state of the slot registry after adding a slot. + * + * @param[in] p_reg Pointer to the slot registry. + * @param[in] slot_no The slot number that was added. + * @param[in] frame_type The frame type that was added. + * @param[in] init Information if the data is loaded during initialization. Set this + * parameter to false if the call is a result of a write to the Eddystone Configuration Service. + */ +void es_slot_reg_update_slot_list_info_on_add(es_slot_reg_t * p_reg, uint8_t slot_no, es_frame_type_t frame_type, bool init); + +/** @brief Function for initializing the slot registry. + * + * @param[in] p_reg Pointer to the slot registry to initialize. + */ +void es_slot_reg_init(es_slot_reg_t * p_reg); + +/** + * @} + */ + +#endif // ES_SLOT_REG_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_stopwatch.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_stopwatch.c new file mode 100644 index 0000000..0f022bf --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_stopwatch.c @@ -0,0 +1,106 @@ +/** + * 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. + * + */ + +#include +#include +#include +#include "es_stopwatch.h" +#include "sdk_macros.h" +#include "app_timer.h" +#include "es_app_config.h" + +static uint32_t m_ticks_last_returned[ES_STOPWATCH_MAX_USERS]; +static uint32_t m_ids_ticks_wrap[ES_STOPWATCH_MAX_USERS]; +static uint8_t m_nof_ids = 0; +static bool m_initialized = false; + +uint32_t es_stopwatch_check(es_stopwatch_id_t id) +{ + uint32_t ticks_current = app_timer_cnt_get(); + uint32_t ticks_diff; + + if (m_ids_ticks_wrap[id] == 0) + { + APP_ERROR_CHECK(NRF_ERROR_INVALID_STATE); + } + + ticks_diff = app_timer_cnt_diff_compute(ticks_current, m_ticks_last_returned[id]); + + if (ticks_diff >= m_ids_ticks_wrap[id]) + { + m_ticks_last_returned[id] = (ticks_current / m_ids_ticks_wrap[id]) * m_ids_ticks_wrap[id]; + + return ticks_diff / m_ids_ticks_wrap[id]; + } + + return 0; +} + +ret_code_t es_stopwatch_create(es_stopwatch_id_t * p_sw_id, uint32_t ticks_wrap) +{ + VERIFY_PARAM_NOT_NULL(p_sw_id); + + if (m_nof_ids == ES_STOPWATCH_MAX_USERS) + { + return NRF_ERROR_INVALID_STATE; + } + + if (!m_initialized) + { + return NRF_ERROR_MODULE_NOT_INITIALIZED; + } + + *p_sw_id = m_nof_ids; + + m_ids_ticks_wrap[m_nof_ids] = ticks_wrap; + + m_nof_ids++; + + return NRF_SUCCESS; +} + + +void es_stopwatch_init(void) +{ + m_nof_ids = 0; + memset(m_ticks_last_returned, 0, sizeof(m_ticks_last_returned)); + memset(m_ids_ticks_wrap, 0, sizeof(m_ids_ticks_wrap)); + m_initialized = true; +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_stopwatch.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_stopwatch.h new file mode 100644 index 0000000..1318861 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_stopwatch.h @@ -0,0 +1,71 @@ +/** + * 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 ES_SECURITY_TIMING_H__ +#define ES_SECURITY_TIMING_H__ + +#include +#include "app_error.h" + +/** + * @file + * @addtogroup eddystone_security + * @{ + */ + +typedef uint8_t es_stopwatch_id_t; + +/**@brief Function for getting the number of seconds passed since the last invocation. + * @details If the function returns zero, the 'last time called' state is not updated. If a non-zero value + * is returned, the 'last time called' state will point to the last whole second. + * @return Number of seconds passed since the last invocation. + */ +uint32_t es_stopwatch_check(es_stopwatch_id_t id); + +ret_code_t es_stopwatch_create(es_stopwatch_id_t * p_sw_id, uint32_t ticks_wrap); + +/**@brief Function for initializing the security timing module. + */ +void es_stopwatch_init(void); + +/** + * @} + */ + +#endif // ES_SECURITY_TIMING_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_tlm.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_tlm.c new file mode 100644 index 0000000..dec4b6e --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_tlm.c @@ -0,0 +1,140 @@ +/** + * 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. + * + */ + +#include +#include "app_timer.h" +#include "es_tlm.h" +#include "es_app_config.h" +#include "es_battery_voltage.h" +#include "es_stopwatch.h" +#include "nrf_soc.h" + +#define TICKS_100_MS APP_TIMER_TICKS(100) //!< Tick count for 100ms. + +static es_tlm_frame_t m_tlm; +static uint32_t m_le_adv_cnt; +static es_stopwatch_id_t m_time_sec_sw_id; +static es_stopwatch_id_t m_tlm_refresh_sw_id; + +/**@brief Function for updating the ADV_SEC field of TLM*/ +static void update_time(void) +{ + static uint32_t time_total_100_ms = 0; + uint32_t be_time_100_ms; // Big endian version of 0.1 second counter. + + time_total_100_ms += es_stopwatch_check(m_time_sec_sw_id); + + be_time_100_ms = BYTES_REVERSE_32BIT(time_total_100_ms); + + memcpy(m_tlm.sec_cnt, &be_time_100_ms, ES_TLM_SEC_CNT_LENGTH); +} + + +/**@brief Function for updating the TEMP field of TLM*/ +static void update_temp(void) +{ + int32_t temp; // variable to hold temp reading + (void)sd_temp_get(&temp); // get new temperature + int16_t temp_new = (int16_t) temp; // convert from int32_t to int16_t + m_tlm.temp[0] = (uint8_t)((temp_new >> 2) & 0xFFUL); // Right-shift by two to remove decimal part + m_tlm.temp[1] = (uint8_t)((temp_new << 6) & 0xFFUL); // Left-shift 6 to get fractional part with 0.25 degrees C resolution +} + + +/**@brief Function for updating the VBATT field of TLM*/ +static void update_vbatt(void) +{ + uint16_t vbatt; // Variable to hold voltage reading + es_battery_voltage_get(&vbatt); // Get new battery voltage + m_tlm.vbatt[0] = (uint8_t)(vbatt >> 8); + m_tlm.vbatt[1] = (uint8_t)vbatt; +} + + +static void update_adv_cnt(void) +{ + uint32_t be_adv_cnt = BYTES_REVERSE_32BIT(m_le_adv_cnt); + memcpy(m_tlm.adv_cnt, (uint8_t *)(&be_adv_cnt), ES_TLM_ADV_CNT_LENGTH); +} + + +void es_tlm_tlm_get(es_tlm_frame_t * p_tlm_frame) +{ + // Note that frame type and TLM version fields are set in initialization. + update_time(); + update_adv_cnt(); + + if (es_stopwatch_check(m_tlm_refresh_sw_id) > 0) + { + update_temp(); + update_vbatt(); + } + + memcpy(p_tlm_frame, &m_tlm, sizeof(es_tlm_frame_t)); +} + + +void es_tlm_adv_cnt_inc(void) +{ + m_le_adv_cnt++; +} + + +void es_tlm_init(void) +{ + ret_code_t err_code; + + memset(&m_tlm, 0, sizeof(m_tlm)); + m_tlm.frame_type = ES_FRAME_TYPE_TLM; + m_tlm.version = ES_TLM_VERSION_TLM; + m_le_adv_cnt = 0; + + update_time(); + update_vbatt(); + update_temp(); + + err_code = es_stopwatch_create(&m_time_sec_sw_id, APP_TIMER_TICKS(100)); + APP_ERROR_CHECK(err_code); + + err_code = es_stopwatch_create( + &m_tlm_refresh_sw_id, + APP_TIMER_TICKS(APP_CONFIG_TLM_TEMP_VBATT_UPDATE_INTERVAL_SECONDS * 1000)); + APP_ERROR_CHECK(err_code); +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_tlm.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_tlm.h new file mode 100644 index 0000000..055d22b --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_tlm.h @@ -0,0 +1,76 @@ +/** + * 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 ES_TLM_H__ +#define ES_TLM_H__ + +#include "es.h" + +/** + * @file + * @defgroup eddystone_tlm TLM + * @brief Functions for the Eddystone telemetry (TLM) manager. + * @ingroup eddystone_adv + * @{ + */ + +/**@brief Function for initializing the TLM manager. + * + * @return See @ref app_timer_start for possible return values. + */ +void es_tlm_init(void); + +/**@brief Function for getting the current TLM. + * + * @param[in] p_tlm_frame Pointer to the TLM frame to which the frame is retrieved. + */ +void es_tlm_tlm_get(es_tlm_frame_t * p_tlm_frame); + +/**@brief Function for incrementing the ADV_CNT field of the TLM frame. + * + * @details This function should be called every time a frame is advertised. + * + */ +void es_tlm_adv_cnt_inc(void); + +/** + * @} + */ + +#endif // ES_TLM_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_util.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_util.h new file mode 100644 index 0000000..36e33d9 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_util.h @@ -0,0 +1,137 @@ +/** + * 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. + * + */ + +// See https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms + +#ifndef ES_UTIL_H__ +#define ES_UTIL_H__ + +#define BOOL(x) COMPL(NOT(x)) +#define IF(c) IIF(BOOL(c)) + +#define CHECK_N(x, n, ...) n +#define CHECK(...) CHECK_N(__VA_ARGS__, 0,) +#define PROBE(x) x, 1, + +#define EAT(...) +#define EXPAND(...) __VA_ARGS__ +#define WHEN(c) IF(c)(EXPAND, EAT) + +#define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x)) +#define NOT_0 PROBE(~) + +#define COMPL(b) PRIMITIVE_CAT(COMPL_, b) +#define COMPL_0 1 +#define COMPL_1 0 + +#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) +#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ + +#define IIF(c) PRIMITIVE_CAT(IIF_, c) +#define IIF_0(t, ...) __VA_ARGS__ +#define IIF_1(t, ...) t + +#define DEC(x) PRIMITIVE_CAT(DEC_, x) +#define DEC_0 0 +#define DEC_1 0 +#define DEC_2 1 +#define DEC_3 2 +#define DEC_4 3 +#define DEC_5 4 +#define DEC_6 5 +#define DEC_7 6 +#define DEC_8 7 +#define DEC_9 8 +#define DEC_10 9 +#define DEC_11 10 +#define DEC_12 11 +#define DEC_13 12 +#define DEC_14 13 +#define DEC_15 14 +#define DEC_16 15 +#define DEC_17 16 +#define DEC_18 17 +#define DEC_19 18 +#define DEC_20 19 +#define DEC_21 20 +#define DEC_22 21 +#define DEC_23 22 +#define DEC_24 23 +#define DEC_25 24 +#define DEC_26 25 +#define DEC_27 26 +#define DEC_28 27 +#define DEC_29 28 +#define DEC_30 29 +#define DEC_31 30 +#define DEC_32 31 + +#define EMPTY() +#define DEFER(id) id EMPTY() +#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)() +#define EXPAND(...) __VA_ARGS__ + +#define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__))) +#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__))) +#define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__))) +#define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__))) +#define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__))) +#define EVAL5(...) __VA_ARGS__ + +#define REPEAT(count, macro, ...) \ + WHEN(count) \ + ( \ + OBSTRUCT(REPEAT_INDIRECT) () \ + ( \ + DEC(count), macro, __VA_ARGS__ \ + ) \ + OBSTRUCT(macro) \ + ( \ + DEC(count), __VA_ARGS__ \ + ) \ + ) +#define REPEAT_INDIRECT() REPEAT + + +/** + * @} + */ + +#endif // ES_UTIL_H__ diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/nrf_ble_es.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/nrf_ble_es.c new file mode 100644 index 0000000..67fdb3f --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/nrf_ble_es.c @@ -0,0 +1,438 @@ +/** + * 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. + * + */ + +#include +#include "nrf_ble_es.h" +#include "app_error.h" +#include "fds.h" +#include "es_adv.h" +#include "es_battery_voltage.h" +#include "es_flash.h" +#include "es_gatts.h" +#include "es_security.h" +#include "es_slot.h" +#include "es_stopwatch.h" +#include "escs_defs.h" +#include "nrf_sdh_ble.h" + +static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; //!< Connection handle. +static nrf_ble_escs_t m_ble_ecs; //!< Struct identifying the Eddystone Config Service. +static nrf_ble_es_evt_handler_t m_evt_handler; //!< Event handler. + +uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; //!< Advertising handle used to identify an advertising set. + +/**@brief Function for invoking registered callback. + * + * @param[in] evt Event to issue to callback. + */ +static void handle_evt(nrf_ble_es_evt_t evt) +{ + if (m_evt_handler != NULL) + { + m_evt_handler(evt); + } +} + + +/**@brief Function resetting MAC address. Will resume advertisement. */ +static void new_address_set(void) +{ + + ret_code_t err_code; + uint8_t bytes_available; + ble_gap_addr_t new_address; + + new_address.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; + + // Randomize the MAC address on every EID generation + (void)sd_rand_application_bytes_available_get(&bytes_available); + + while (bytes_available < BLE_GAP_ADDR_LEN) + { + // wait for SD to acquire enough RNs + (void)sd_rand_application_bytes_available_get(&bytes_available); + } + + (void)sd_rand_application_vector_get(new_address.addr, BLE_GAP_ADDR_LEN); + + // Stop advertising to ensure that it is possible to change the address. + (void)sd_ble_gap_adv_stop(m_adv_handle); + + do + { + err_code = sd_ble_gap_addr_set(&new_address); + } while (err_code == NRF_ERROR_INVALID_STATE); + + APP_ERROR_CHECK(err_code); + + if (es_adv_remain_connectable_get()) + { + es_adv_start_connectable_adv(); + } + else + { + es_adv_start_non_connctable_adv(); + } +} + + +/**@brief Function updating MAC address if required. + * + * @param[in] demand_new_mac If 'true', mac address will be updated on next invocation when not connected. + * If 'false', simply check if we have an outstanding demand for new MAC and update if not connected. + */ +static void check_and_update_mac_address(bool demand_new_mac) +{ + static bool reset_mac_address = false; + + if (demand_new_mac) + { + reset_mac_address = true; + } + + // Not possible to update MAC address while in a connection + if (m_conn_handle != BLE_CONN_HANDLE_INVALID) + { + return; + } + + else if (reset_mac_address) + { + reset_mac_address = false; + + new_address_set(); + } +} + + +/**@brief Function to lock the beacon (change lock state characteristic to LOCKED) + */ +static void lock_beacon(void) +{ + *(m_ble_ecs.p_lock_state) = NRF_BLE_ESCS_LOCK_STATE_LOCKED; +} + + +/**@brief Function for handling BLE event from the SoftDevice. + * + * @param[in] p_ble_evt Pointer to BLE event. + */ +static void on_ble_evt(ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + es_flash_flags_t flash_flag = {{0}}; + const es_slot_reg_t * p_reg = es_slot_get_registry(); + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + m_conn_handle = p_ble_evt->evt.common_evt.conn_handle; + *(m_ble_ecs.p_active_slot) = 0; + break; + + case BLE_GAP_EVT_DISCONNECTED: + m_conn_handle = BLE_CONN_HANDLE_INVALID; + + for (uint32_t i = 0; i < APP_MAX_ADV_SLOTS; ++i) + { + err_code = es_slot_write_to_flash(i); + APP_ERROR_CHECK(err_code); + + flash_flag.slot_is_empty[i] = !p_reg->slots[i].configured; + } + + err_code = es_flash_access_flags(&flash_flag, ES_FLASH_ACCESS_WRITE); + APP_ERROR_CHECK(err_code); + + es_flash_beacon_config_t beacon_config; + beacon_config.adv_interval = es_adv_interval_get(); + beacon_config.remain_connectable = es_adv_remain_connectable_get(); + + err_code = es_flash_access_beacon_config(&beacon_config, ES_FLASH_ACCESS_WRITE); + APP_ERROR_CHECK(err_code); + + if (*m_ble_ecs.p_lock_state == NRF_BLE_ESCS_LOCK_STATE_UNLOCKED) + { + lock_beacon(); + } + + check_and_update_mac_address(false); + + break; + + default: + // No implementation needed. + break; + } +} + + +/**@brief Callback function to receive messages from the security module + * + * @details Need to be passed in during es_security_init(). The security + * module will callback anytime a particular security process is completed + * + * @params[in] slot_no Index of the slot + * @params[in] msg_type Message type corersponding to different security components + */ +static void nrf_ble_escs_security_cb(uint8_t slot_no, es_security_msg_t msg_type) +{ + nrf_ble_escs_eid_id_key_t encrypted_id_key; + nrf_ble_escs_public_ecdh_key_t pub_ecdh_key; + + ret_code_t err_code; + static ble_gatts_value_t value; + + switch (msg_type) + { + case ES_SECURITY_MSG_UNLOCKED: + *(m_ble_ecs.p_lock_state) = NRF_BLE_ESCS_LOCK_STATE_UNLOCKED; + break; + + case ES_SECURITY_MSG_EID: + es_slot_eid_ready(slot_no); +#ifdef MAC_RANDOMIZED + check_and_update_mac_address(true); +#endif // MAC_RANDOMIZED + break; + + case ES_SECURITY_MSG_IK: + es_security_encrypted_eid_id_key_get(slot_no, (uint8_t *)encrypted_id_key.key); + // Set the EID ID key in the slot so it can be exposed in the characteristic + es_slot_encrypted_eid_id_key_set(slot_no, &encrypted_id_key); + break; + + case ES_SECURITY_MSG_ECDH: + es_security_pub_ecdh_get(slot_no, (uint8_t *)pub_ecdh_key.key); + + // Set the characteristic to the ECDH key value + value.len = sizeof(nrf_ble_escs_public_ecdh_key_t); + value.offset = 0; + value.p_value = (uint8_t *)pub_ecdh_key.key; + + if (m_conn_handle != BLE_CONN_HANDLE_INVALID) + { + err_code = sd_ble_gatts_value_set(m_ble_ecs.conn_handle, + m_ble_ecs.pub_ecdh_key_handles.value_handle, + &value); + if (err_code != NRF_SUCCESS) + { + APP_ERROR_CHECK(err_code); + } + } + break; + + case ES_SECURITY_MSG_STORE_TIME: + // Every 24 hours any EID slots time is stored to flash to allow for power lock_state_handles + // recovery. Only time needs to be stored, but just store the entire slot anyway for API simplicity. + err_code = es_slot_write_to_flash(slot_no); + APP_ERROR_CHECK(err_code); + + break; + + default: + APP_ERROR_CHECK(NRF_ERROR_INVALID_PARAM); // Should never happen + break; + } +} + + +/**@brief Function for handling advertisement events from 'es_adv'. + * + * @param[in] evt Advertisement event to handle. + */ +static void adv_evt_handler(es_adv_evt_t evt) +{ + switch (evt) + { + case ES_ADV_EVT_NON_CONN_ADV: + handle_evt(NRF_BLE_ES_EVT_ADVERTISEMENT_SENT); + es_security_update_time(); + break; + + case ES_ADV_EVT_CONNECTABLE_ADV_STARTED: + handle_evt(NRF_BLE_ES_EVT_CONNECTABLE_ADV_STARTED); + break; + + case ES_ADV_EVT_CONNECTABLE_ADV_STOPPED: + handle_evt(NRF_BLE_ES_EVT_CONNECTABLE_ADV_STOPPED); + break; + + default: + break; + } +} + + +/**@brief Initialize the ECS with initial values for the characteristics and other necessary modules */ +static void ble_escs_init(void) +{ + ret_code_t err_code; + nrf_ble_escs_init_t ecs_init; + nrf_ble_escs_init_params_t init_params; + int8_t tx_powers[ESCS_NUM_OF_SUPPORTED_TX_POWER] = ESCS_SUPPORTED_TX_POWER; + + /*Init the broadcast capabilities characteristic*/ + memset(&init_params.broadcast_cap, 0, sizeof(init_params.broadcast_cap)); + init_params.broadcast_cap.vers_byte = ES_SPEC_VERSION_BYTE; + init_params.broadcast_cap.max_supp_total_slots = APP_MAX_ADV_SLOTS; + init_params.broadcast_cap.max_supp_eid_slots = APP_MAX_EID_SLOTS; + init_params.broadcast_cap.cap_bitfield = ( (APP_IS_VARIABLE_ADV_SUPPORTED << ESCS_BROADCAST_VAR_ADV_SUPPORTED_Pos) + | (APP_IS_VARIABLE_TX_POWER_SUPPORTED << ESCS_BROADCAST_VAR_TX_POWER_SUPPORTED_Pos)) + & (ESCS_BROADCAST_VAR_RFU_MASK); + init_params.broadcast_cap.supp_frame_types = ( (APP_IS_URL_SUPPORTED << ESCS_FRAME_TYPE_URL_SUPPORTED_Pos) + | (APP_IS_UID_SUPPORTED << ESCS_FRAME_TYPE_UID_SUPPORTED_Pos) + | (APP_IS_TLM_SUPPORTED << ESCS_FRAME_TYPE_TLM_SUPPORTED_Pos) + | (APP_IS_EID_SUPPORTED << ESCS_FRAME_TYPE_EID_SUPPORTED_Pos)) + & (ESCS_FRAME_TYPE_RFU_MASK); + memcpy(init_params.broadcast_cap.supp_radio_tx_power, tx_powers, ESCS_NUM_OF_SUPPORTED_TX_POWER); + + init_params.adv_interval = APP_CFG_NON_CONN_ADV_INTERVAL_MS; + init_params.adv_tx_pwr = APP_CFG_DEFAULT_RADIO_TX_POWER; + init_params.radio_tx_pwr = 0x00; + init_params.factory_reset = 0; + init_params.remain_connectable.r_is_non_connectable_supported = APP_IS_REMAIN_CONNECTABLE_SUPPORTED; + + // Initialize evt handlers and the service + memset(&ecs_init, 0, sizeof(ecs_init)); + ecs_init.write_evt_handler = es_gatts_handle_write; + ecs_init.read_evt_handler = es_gatts_handle_read; + ecs_init.p_init_vals = &(init_params); + + err_code = nrf_ble_escs_init(&m_ble_ecs, &ecs_init); + APP_ERROR_CHECK(err_code); +} + + +/**@brief Function for initializing 'es_adv' module. */ +static void adv_init(void) +{ + ret_code_t err_code; + es_flash_beacon_config_t beacon_config; + + err_code = es_flash_access_beacon_config(&beacon_config, ES_FLASH_ACCESS_READ); + + if (err_code == FDS_ERR_NOT_FOUND) + { + beacon_config.adv_interval = APP_CFG_NON_CONN_ADV_INTERVAL_MS; + beacon_config.remain_connectable = false; + } + + else + { + APP_ERROR_CHECK(err_code); + } + + es_adv_init(m_ble_ecs.uuid_type, + adv_evt_handler, + beacon_config.adv_interval, + beacon_config.remain_connectable, + &m_adv_handle); +} + + +/**@brief Function for initializing es_slots module. */ +static void adv_slots_init(void) +{ + uint8_t default_frame_data[DEFAULT_FRAME_LENGTH] = DEFAULT_FRAME_DATA; + + es_slot_t default_adv_slot = {.slot_no = 0, + .radio_tx_pwr = 0, + .adv_frame.type = DEFAULT_FRAME_TYPE, + .adv_frame.length = DEFAULT_FRAME_LENGTH, + .adv_custom_tx_power = false, + .configured = true}; + + memcpy(&default_adv_slot.adv_frame.frame, default_frame_data, DEFAULT_FRAME_LENGTH); + + es_slots_init(&default_adv_slot); +} + + +void nrf_ble_es_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) +{ + ret_code_t err_code; + + es_adv_on_ble_evt(p_ble_evt); + err_code = nrf_ble_escs_on_ble_evt(&m_ble_ecs, p_ble_evt); + APP_ERROR_CHECK(err_code); + on_ble_evt(p_ble_evt); + es_flash_on_ble_evt(p_ble_evt); +} + +NRF_SDH_BLE_OBSERVER(m_es_observer, NRF_BLE_ES_BLE_OBSERVER_PRIO, nrf_ble_es_on_ble_evt, NULL); + + +void nrf_ble_es_on_start_connectable_advertising(void) +{ + es_adv_start_connectable_adv(); +} + + +void nrf_ble_es_init(nrf_ble_es_evt_handler_t evt_handler) +{ + ret_code_t err_code; + + m_evt_handler = evt_handler; + m_conn_handle = BLE_CONN_HANDLE_INVALID; + + es_stopwatch_init(); + + err_code = es_gatts_init(&m_ble_ecs); + APP_ERROR_CHECK(err_code); + + err_code = es_flash_init(); + APP_ERROR_CHECK(err_code); + + while (es_flash_num_pending_ops() > 0) + { + ; // Busy wait while initialization of FDS module completes + } + + err_code = es_security_init(nrf_ble_escs_security_cb); + APP_ERROR_CHECK(err_code); + + es_adv_timers_init(); + ble_escs_init(); + adv_slots_init(); + es_battery_voltage_init(); + adv_init(); + es_adv_start_non_connctable_adv(); +} diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/nrf_ble_es.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/nrf_ble_es.h new file mode 100644 index 0000000..3262136 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/nrf_ble_es.h @@ -0,0 +1,99 @@ +/** + * 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 NRF_ES_H__ +#define NRF_ES_H__ + +#include +#include "ble.h" + +/** + * @file + * @defgroup eddystone Eddystone library + * @ingroup app_common + * @{ + * + * @brief Library for Eddystone beacons. This library is used in the @ref ble_sdk_app_es. + * + * @note The API documentation is provided for reference only. You should + * not modify this library, and you should not use any functions + * except for the main level functions defined in @c nrf_ble_es.h + * in different contexts. + */ + +/** @brief Eddystone event types. */ +typedef enum +{ + NRF_BLE_ES_EVT_ADVERTISEMENT_SENT, //!< A non-connectable Eddystone frame advertisement was sent. + NRF_BLE_ES_EVT_CONNECTABLE_ADV_STARTED, //!< Advertising in connectable mode was started. + NRF_BLE_ES_EVT_CONNECTABLE_ADV_STOPPED, //!< Advertising in connectable mode was stopped. +} nrf_ble_es_evt_t; + +/**@brief Eddystone event handler type. */ +typedef void (*nrf_ble_es_evt_handler_t)(nrf_ble_es_evt_t evt); + +/**@brief Function for handling the application's BLE stack events. + * + * @details This function handles all events from the BLE stack that are of + * interest to the Eddystone library. + * + * @param[in] p_ble_evt Event received from the BLE stack. + * @param[in] p_context User parameter. + */ +void nrf_ble_es_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context); + +/**@brief Function for putting the beacon in connectable mode. + * + * @details This function makes the beacon advertise connectable advertisements. + * If the beacon is in a connected state, the request is ignored. + */ +void nrf_ble_es_on_start_connectable_advertising(void); + +/** @brief Function for initializing the Eddystone library. + * + * @param[in] evt_handler Event handler to be called for handling BLE events. + */ +void nrf_ble_es_init(nrf_ble_es_evt_handler_t evt_handler); + +/** + * @} + */ + +#endif -- cgit v1.2.3