aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es.h198
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv.c342
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv.h129
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_frame.c120
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_frame.h73
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing.c220
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing.h97
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing_resolver.c145
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_adv_timing_resolver.h96
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_battery_voltage.h66
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_battery_voltage_saadc.c104
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_flash.c340
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_flash.h177
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts.c188
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts.h109
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_read.c246
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_read.h73
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_write.c254
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_gatts_write.h71
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_security.c596
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_security.h238
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot.c440
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot.h202
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot_reg.c181
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_slot_reg.h90
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_stopwatch.c106
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_stopwatch.h71
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_tlm.c140
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_tlm.h76
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/es_util.h137
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/nrf_ble_es.c438
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/eddystone/nrf_ble_es.h99
32 files changed, 5862 insertions, 0 deletions
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 <stdint.h>
+#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 <stdint.h>
+#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 <stdint.h>
+
+/**
+ * @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 <stdbool.h>
+#include <stdint.h>
+#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 <stdint.h>
+
+/**
+ * @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 <string.h>
+#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(&params);
+}
+
+
+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(&params);
+
+ 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(&params);
+}
+
+
+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(&params);
+}
+
+
+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 <stdbool.h>
+#include <stdint.h>
+#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 <stdint.h>
+#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 <stdint.h>
+#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 <stdint.h>
+#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 <stdbool.h>
+#include <stdint.h>
+#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 <stdint.h>
+#include <string.h>
+#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 <stdint.h>
+#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 <stdint.h>
+#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 <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#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 <stdint.h>
+#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 <string.h>
+#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 <string.h>
+#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 <stdint.h>
+#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