aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_db.c143
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_db.h118
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_meas.c248
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_meas.h103
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_racp.c866
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_racp.h99
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_socp.c431
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_socp.h107
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_sst.c235
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_sst.h115
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/nrf_ble_cgms.c504
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/nrf_ble_cgms.h453
12 files changed, 3422 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_db.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_db.c
new file mode 100644
index 0000000..e5f6240
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_db.c
@@ -0,0 +1,143 @@
+/**
+ * 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 "cgms_db.h"
+
+typedef struct
+{
+ bool in_use_flag;
+ ble_cgms_rec_t record;
+} database_entry_t;
+
+static database_entry_t m_database[CGMS_DB_MAX_RECORDS];
+static uint8_t m_database_crossref[CGMS_DB_MAX_RECORDS];
+static uint16_t m_num_records;
+
+
+ret_code_t cgms_db_init(void)
+{
+ int i;
+
+ for (i = 0; i < CGMS_DB_MAX_RECORDS; i++)
+ {
+ m_database[i].in_use_flag = false;
+ m_database_crossref[i] = 0xFF;
+ }
+
+ m_num_records = 0;
+
+ return NRF_SUCCESS;
+}
+
+
+uint16_t cgms_db_num_records_get(void)
+{
+ return m_num_records;
+}
+
+
+ret_code_t cgms_db_record_get(uint8_t record_num, ble_cgms_rec_t * p_rec)
+{
+ if ((record_num >= m_num_records) || (m_num_records == 0))
+ {
+ return NRF_ERROR_NOT_FOUND;
+ }
+ // copy record to the specified memory
+ *p_rec = m_database[m_database_crossref[record_num]].record;
+
+ return NRF_SUCCESS;
+}
+
+
+ret_code_t cgms_db_record_add(ble_cgms_rec_t * p_rec)
+{
+ int i;
+
+ if (m_num_records == CGMS_DB_MAX_RECORDS)
+ {
+ return NRF_ERROR_NO_MEM;
+ }
+
+ // find next available database entry
+ for (i = 0; i < CGMS_DB_MAX_RECORDS; i++)
+ {
+ if (!m_database[i].in_use_flag)
+ {
+ m_database[i].in_use_flag = true;
+ m_database[i].record = *p_rec;
+
+ m_database_crossref[m_num_records] = i;
+ m_num_records++;
+
+ return NRF_SUCCESS;
+ }
+ }
+
+ return NRF_ERROR_NO_MEM;
+}
+
+
+ret_code_t cgms_db_record_delete(uint8_t record_num)
+{
+ int i;
+
+ if (record_num >= m_num_records)
+ {
+ // Deleting a non-existent record is not an error
+ return NRF_SUCCESS;
+ }
+
+ // free entry
+ m_database[m_database_crossref[record_num]].in_use_flag = false;
+
+ // decrease number of records
+ m_num_records--;
+
+ // remove cross reference index
+ for (i = record_num; i < m_num_records; i++)
+ {
+ m_database_crossref[i] = m_database_crossref[i + 1];
+ }
+
+ return NRF_SUCCESS;
+}
+
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_db.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_db.h
new file mode 100644
index 0000000..6928057
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_db.h
@@ -0,0 +1,118 @@
+/**
+ * Copyright (c) 2012 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/** @file
+ *
+ * @defgroup ble_sdk_srv_cgms_db Continuous Glucose Monitoring Service database
+ * @{
+ * @ingroup ble_cgms
+ *
+ * @brief Continuous Glucose Monitoring Service database module.
+ *
+ * @details This module implements a database of stored glucose measurement values.
+ * This database is meant as an example of a database that the @ref ble_cgms can use.
+ * Replace this module if this implementation does not suit
+ * your application. Any replacement implementation should follow the API below to ensure
+ * that the qualification of the @ref ble_cgms is not compromised.
+ */
+
+#ifndef BLE_CGMS_DB_H__
+#define BLE_CGMS_DB_H__
+
+#include "sdk_errors.h"
+#include "nrf_ble_cgms.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define CGMS_DB_MAX_RECORDS 100 // !< Number of records that can be stored in the database.
+
+
+/**@brief Function for initializing the glucose record database.
+ *
+ * @retval NRF_SUCCESS If the database was successfully initialized.
+ */
+ret_code_t cgms_db_init(void);
+
+
+/**@brief Function for getting the number of records in the database.
+ *
+ * @return The number of records in the database.
+ */
+uint16_t cgms_db_num_records_get(void);
+
+
+/**@brief Function for getting a specific record from the database.
+ *
+ * @param[in] record_num Index of the record to retrieve.
+ * @param[out] p_rec Pointer to the record structure to which the retrieved record is copied.
+ *
+ * @retval NRF_SUCCESS If the record was successfully retrieved.
+ */
+ret_code_t cgms_db_record_get(uint8_t record_num, ble_cgms_rec_t * p_rec);
+
+
+/**@brief Function for adding a record at the end of the database.
+ *
+ * @param[in] p_rec Pointer to the record to add to the database.
+ *
+ * @retval NRF_SUCCESS If the record was successfully added to the database.
+ */
+ret_code_t cgms_db_record_add(ble_cgms_rec_t * p_rec);
+
+
+/**@brief Function for deleting a database entry.
+ *
+ * @details This call deletes an record from the database.
+ *
+ * @param[in] record_num Index of the record to delete.
+ *
+ * @retval NRF_SUCCESS If the record was successfully deleted from the database.
+ */
+ret_code_t cgms_db_record_delete(uint8_t record_num);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // BLE_CGMS_DB_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_meas.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_meas.c
new file mode 100644
index 0000000..50d6416
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_meas.c
@@ -0,0 +1,248 @@
+/**
+ * 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 "ble.h"
+#include "sdk_macros.h"
+#include "ble_srv_common.h"
+#include "nrf_ble_cgms.h"
+#include "cgms_meas.h"
+#include "cgms_db.h"
+
+/**@brief Function for encoding a Glucose measurement.
+ *
+ * @param[in] p_meas Measurement to be encoded.
+ * @param[out] p_encoded_buffer Pointer to buffer where the encoded measurement is to be stored.
+ *
+ * @return Size of encoded measurement.
+ */
+static uint8_t cgms_meas_encode(nrf_ble_cgms_t * p_cgms,
+ const nrf_ble_cgms_meas_t * p_meas,
+ uint8_t * p_encoded_buffer)
+{
+ uint8_t len = 2;
+
+ uint8_t flags = p_meas->flags;
+
+ len += uint16_encode(p_meas->glucose_concentration,
+ &p_encoded_buffer[len]);
+ len += uint16_encode(p_meas->time_offset,
+ &p_encoded_buffer[len]);
+
+ if (p_meas->sensor_status_annunciation.warning != 0)
+ {
+ p_encoded_buffer[len++] = p_meas->sensor_status_annunciation.warning;
+ flags |= NRF_BLE_CGMS_STATUS_FLAGS_WARNING_OCT_PRESENT;
+ }
+
+ if (p_meas->sensor_status_annunciation.calib_temp != 0)
+ {
+ p_encoded_buffer[len++] = p_meas->sensor_status_annunciation.calib_temp;
+ flags |= NRF_BLE_CGMS_STATUS_FLAGS_CALTEMP_OCT_PRESENT;
+ }
+
+ if (p_meas->sensor_status_annunciation.status != 0)
+ {
+ p_encoded_buffer[len++] = p_meas->sensor_status_annunciation.status;
+ flags |= NRF_BLE_CGMS_STATUS_FLAGS_STATUS_OCT_PRESENT;
+ }
+
+ // Trend field
+ if (p_cgms->feature.feature & NRF_BLE_CGMS_FEAT_CGM_TREND_INFORMATION_SUPPORTED)
+ {
+ if (flags & NRF_BLE_CGMS_FLAG_TREND_INFO_PRESENT)
+ {
+ len += uint16_encode(p_meas->trend, &p_encoded_buffer[len]);
+ }
+ }
+
+ // Quality field
+ if (p_cgms->feature.feature & NRF_BLE_CGMS_FEAT_CGM_QUALITY_SUPPORTED)
+ {
+ if (flags & NRF_BLE_CGMS_FLAGS_QUALITY_PRESENT)
+ {
+ len += uint16_encode(p_meas->quality, &p_encoded_buffer[len]);
+ }
+ }
+
+ p_encoded_buffer[1] = flags;
+ p_encoded_buffer[0] = len;
+ return len;
+}
+
+
+/**@brief Function for adding a characteristic for the Continuous Glucose Meter Measurement.
+ *
+ * @param[in] p_cgms Service instance.
+ *
+ * @return NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
+ */
+ret_code_t cgms_meas_char_add(nrf_ble_cgms_t * p_cgms)
+{
+ uint8_t num_recs;
+ uint8_t encoded_cgms_meas[NRF_BLE_CGMS_MEAS_LEN_MAX];
+ ble_add_char_params_t add_char_params;
+ ble_cgms_rec_t initial_cgms_rec_value;
+
+ memset(&add_char_params, 0, sizeof(add_char_params));
+ memset(&initial_cgms_rec_value, 0, sizeof(ble_cgms_rec_t));
+
+ num_recs = cgms_db_num_records_get();
+ if (num_recs > 0)
+ {
+ uint32_t err_code = cgms_db_record_get(num_recs - 1, &initial_cgms_rec_value);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ }
+
+ add_char_params.uuid = BLE_UUID_CGM_MEASUREMENT;
+ add_char_params.max_len = NRF_BLE_CGMS_MEAS_LEN_MAX;
+ add_char_params.init_len = cgms_meas_encode(p_cgms,
+ &initial_cgms_rec_value.meas,
+ encoded_cgms_meas);
+ add_char_params.p_init_value = encoded_cgms_meas;
+ add_char_params.is_var_len = true;
+ add_char_params.char_props.notify = true;
+ add_char_params.cccd_write_access = SEC_JUST_WORKS;
+
+
+ return characteristic_add(p_cgms->service_handle,
+ &add_char_params,
+ &p_cgms->char_handles.measurment);
+}
+
+
+ret_code_t cgms_meas_send(nrf_ble_cgms_t * p_cgms, ble_cgms_rec_t * p_rec, uint8_t * p_count)
+{
+
+ uint32_t err_code;
+ uint8_t encoded_meas[NRF_BLE_CGMS_MEAS_LEN_MAX + NRF_BLE_CGMS_MEAS_REC_LEN_MAX];
+ uint16_t len = 0;
+ uint16_t hvx_len = NRF_BLE_CGMS_MEAS_LEN_MAX;
+ int i;
+ ble_gatts_hvx_params_t hvx_params;
+
+ for (i = 0; i < *p_count; i++)
+ {
+ uint8_t meas_len = cgms_meas_encode(p_cgms, &(p_rec[i].meas), (encoded_meas + len));
+ if (len + meas_len >= NRF_BLE_CGMS_MEAS_LEN_MAX)
+ {
+ break;
+ }
+ len += meas_len;
+ }
+ *p_count = i;
+ hvx_len = len;
+
+ memset(&hvx_params, 0, sizeof(hvx_params));
+
+ hvx_params.handle = p_cgms->char_handles.measurment.value_handle;
+ hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
+ hvx_params.offset = 0;
+ hvx_params.p_len = &hvx_len;
+ hvx_params.p_data = encoded_meas;
+
+ err_code = sd_ble_gatts_hvx(p_cgms->conn_handle, &hvx_params);
+ if (err_code == NRF_SUCCESS)
+ {
+ if (hvx_len != len)
+ {
+ err_code = NRF_ERROR_DATA_SIZE;
+ }
+ else
+ {
+ // Measurement successfully sent
+ p_cgms->racp_data.racp_proc_records_reported += *p_count;
+ p_cgms->racp_data.racp_proc_records_reported_since_txcomplete++;
+ }
+ }
+
+ return err_code;
+}
+
+
+/**@brief Function for handling the Glucose measurement CCCD write event.
+ *
+ * @param[in] p_cgms Service instance.
+ * @param[in] p_evt_write WRITE event to be handled.
+ */
+static void on_meas_cccd_write(nrf_ble_cgms_t * p_cgms, ble_gatts_evt_write_t const * p_evt_write)
+{
+ if (p_evt_write->len == 2)
+ {
+ // CCCD written, update notification state
+ if (p_cgms->evt_handler != NULL)
+ {
+ nrf_ble_cgms_evt_t evt;
+
+ if (ble_srv_is_notification_enabled(p_evt_write->data))
+ {
+ evt.evt_type = NRF_BLE_CGMS_EVT_NOTIFICATION_ENABLED;
+ }
+ else
+ {
+ evt.evt_type = NRF_BLE_CGMS_EVT_NOTIFICATION_DISABLED;
+ }
+
+ p_cgms->evt_handler(p_cgms, &evt);
+ }
+ }
+}
+
+
+/**@brief Function for handling the WRITE event.
+ *
+ * @details Handles WRITE events from the BLE stack.
+ *
+ * @param[in] p_cgms Glucose Service structure.
+ * @param[in] p_ble_evt Event received from the BLE stack.
+ */
+void cgms_meas_on_write(nrf_ble_cgms_t * p_cgms, ble_gatts_evt_write_t const * p_evt_write)
+{
+
+ if (p_evt_write->handle == p_cgms->char_handles.measurment.cccd_handle)
+ {
+ on_meas_cccd_write(p_cgms, p_evt_write);
+ }
+}
+
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_meas.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_meas.h
new file mode 100644
index 0000000..d56c704
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_meas.h
@@ -0,0 +1,103 @@
+/**
+ * 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.
+ *
+ */
+/** @file
+ *
+ * @defgroup ble_sdk_srv_cgms_meas Continuous Glucose Monitoring Service Measurement
+ * @{
+ * @ingroup ble_cgms
+ * @brief Continuous Glucose Monitoring Service Measurement module.
+ *
+ * @details This module implements parts of the Continuous Glucose Monitoring that relate to the
+ * Measurement characteristic. Events are propagated to this module from @ref ble_cgms
+ * using @ref cgms_meas_on_write.
+ *
+ */
+
+
+#ifndef NRF_BLE_CGMS_MEAS_H__
+#define NRF_BLE_CGMS_MEAS_H__
+
+#include "ble.h"
+#include "ble_srv_common.h"
+#include "sdk_errors.h"
+#include "nrf_ble_cgms.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**@brief Function for adding a characteristic for the Continuous Glucose Monitoring Measurement.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ *
+ * @retval NRF_SUCCESS If the characteristic was successfully added.
+ * @return If functions from other modules return errors to this function,
+ * the @ref nrf_error are propagated.
+ */
+ret_code_t cgms_meas_char_add(nrf_ble_cgms_t * p_cgms);
+
+/**@brief Function for sending a CGM Measurement.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ * @param[in] p_rec Measurement to be sent.
+ * @param[in] count Number of measurements to encode.
+ *
+ * @retval NRF_SUCCESS If the measurement was successfully sent.
+ * @return If functions from other modules return errors to this function,
+ * the @ref nrf_error are propagated.
+ */
+ret_code_t cgms_meas_send(nrf_ble_cgms_t * p_cgms, ble_cgms_rec_t * p_rec, uint8_t * count);
+
+
+/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the BLE stack.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ * @param[in] p_evt_write Event received from the BLE stack.
+ */
+void cgms_meas_on_write(nrf_ble_cgms_t * p_cgms, ble_gatts_evt_write_t const * p_evt_write);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRF_BLE_CGMS_MEAS_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_racp.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_racp.c
new file mode 100644
index 0000000..0327383
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_racp.c
@@ -0,0 +1,866 @@
+/**
+ * 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 "ble.h"
+#include "ble_srv_common.h"
+#include "cgms_racp.h"
+#include "cgms_db.h"
+#include "cgms_meas.h"
+
+#define OPERAND_LESS_GREATER_FILTER_TYPE_SIZE 1 // !< 1 byte.
+#define OPERAND_LESS_GREATER_FILTER_PARAM_SIZE 2 // !< 2 bytes.
+#define OPERAND_LESS_GREATER_SIZE OPERAND_LESS_GREATER_FILTER_TYPE_SIZE \
+ + OPERAND_LESS_GREATER_FILTER_PARAM_SIZE // !< Total size of the operand.
+
+/**@brief Function for adding a characteristic for the Record Access Control Point.
+ *
+ * @param[in] p_cgms Service instance.
+ *
+ * @return NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
+ */
+ret_code_t cgms_racp_char_add(nrf_ble_cgms_t * p_cgms)
+{
+ ble_add_char_params_t add_char_params;
+
+ memset(&add_char_params, 0, sizeof(add_char_params));
+
+ add_char_params.uuid = BLE_UUID_RECORD_ACCESS_CONTROL_POINT_CHAR;
+ add_char_params.max_len = BLE_GATT_ATT_MTU_DEFAULT;
+ add_char_params.init_len = 0;
+ add_char_params.p_init_value = 0;
+ add_char_params.is_var_len = true;
+ add_char_params.write_access = SEC_JUST_WORKS;
+ add_char_params.char_props.write = true;
+ add_char_params.char_props.indicate = true;
+ add_char_params.cccd_write_access = SEC_JUST_WORKS;
+ add_char_params.is_defered_write = 1;
+
+ return characteristic_add(p_cgms->service_handle,
+ &add_char_params,
+ &p_cgms->char_handles.racp);
+}
+
+
+/**@brief Function for sending response from Specific Operation Control Point.
+ *
+ * @param[in] p_cgms Service instance.
+ * @param[in] p_racp_val RACP value to be sent.
+ */
+static void racp_send(nrf_ble_cgms_t * p_cgms, ble_racp_value_t * p_racp_val)
+{
+ uint32_t err_code;
+ uint8_t encoded_resp[25];
+ uint8_t len;
+ uint16_t hvx_len;
+ ble_gatts_hvx_params_t hvx_params;
+
+ if (
+ (p_cgms->cgms_com_state != STATE_RACP_RESPONSE_PENDING)
+ &&
+ (p_cgms->racp_data.racp_proc_records_reported_since_txcomplete > 0)
+ )
+ {
+ p_cgms->cgms_com_state = STATE_RACP_RESPONSE_PENDING;
+ return;
+ }
+
+ // Send indication
+ len = ble_racp_encode(p_racp_val, encoded_resp);
+ hvx_len = len;
+
+ memset(&hvx_params, 0, sizeof(hvx_params));
+
+ hvx_params.handle = p_cgms->char_handles.racp.value_handle;
+ hvx_params.type = BLE_GATT_HVX_INDICATION;
+ hvx_params.offset = 0;
+ hvx_params.p_len = &hvx_len;
+ hvx_params.p_data = encoded_resp;
+
+ err_code = sd_ble_gatts_hvx(p_cgms->conn_handle, &hvx_params);
+
+ // Error handling
+ if ((err_code == NRF_SUCCESS) && (hvx_len != len))
+ {
+ err_code = NRF_ERROR_DATA_SIZE;
+ }
+
+ switch (err_code)
+ {
+ case NRF_SUCCESS:
+ // Wait for HVC event.
+ p_cgms->cgms_com_state = STATE_RACP_RESPONSE_IND_VERIF;
+ break;
+
+ case NRF_ERROR_RESOURCES:
+ // Wait for TX_COMPLETE event to retry transmission.
+ p_cgms->cgms_com_state = STATE_RACP_RESPONSE_PENDING;
+ break;
+
+ case NRF_ERROR_INVALID_STATE:
+ // Make sure state machine returns to the default state.
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ break;
+
+ default:
+ // Report error to application.
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(err_code);
+ }
+
+ // Make sure state machine returns to the default state.
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ break;
+ }
+}
+
+
+/**@brief Function for sending a RACP response containing a Response Code Op Code and Response Code Value.
+ *
+ * @param[in] p_cgms Service instance.
+ * @param[in] opcode RACP Op Code.
+ * @param[in] value RACP Response Code Value.
+ */
+static void racp_response_code_send(nrf_ble_cgms_t * p_cgms, uint8_t opcode, uint8_t value)
+{
+ p_cgms->racp_data.pending_racp_response.opcode = RACP_OPCODE_RESPONSE_CODE;
+ p_cgms->racp_data.pending_racp_response.operator = RACP_OPERATOR_NULL;
+ p_cgms->racp_data.pending_racp_response.operand_len = 2;
+ p_cgms->racp_data.pending_racp_response.p_operand =
+ p_cgms->racp_data.pending_racp_response_operand;
+
+ p_cgms->racp_data.pending_racp_response_operand[0] = opcode;
+ p_cgms->racp_data.pending_racp_response_operand[1] = value;
+
+ racp_send(p_cgms, &p_cgms->racp_data.pending_racp_response);
+}
+
+
+/**@brief Function for responding to the ALL operation.
+ *
+ * @param[in] p_cgms Service instance.
+ *
+ * @return NRF_SUCCESS on success, otherwise an error code.
+ */
+static uint32_t racp_report_records_all(nrf_ble_cgms_t * p_cgms)
+{
+ uint16_t total_records = cgms_db_num_records_get();
+ uint16_t cur_nb_rec;
+ uint8_t i;
+ uint8_t nb_rec_to_send;
+
+ if (p_cgms->racp_data.racp_proc_record_ndx >= total_records)
+ {
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ }
+ else
+ {
+ uint32_t err_code;
+ ble_cgms_rec_t rec[NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX];
+
+ cur_nb_rec = total_records - p_cgms->racp_data.racp_proc_record_ndx;
+ if (cur_nb_rec > NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX)
+ {
+ cur_nb_rec = NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX;
+ }
+ nb_rec_to_send = (uint8_t)cur_nb_rec;
+
+ for (i = 0; i < cur_nb_rec; i++)
+ {
+ err_code = cgms_db_record_get(p_cgms->racp_data.racp_proc_record_ndx + i, &(rec[i]));
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ }
+ err_code = cgms_meas_send(p_cgms, rec, &nb_rec_to_send);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ p_cgms->racp_data.racp_proc_record_ndx += nb_rec_to_send;
+ }
+
+ return NRF_SUCCESS;
+}
+
+
+/**@brief Function for responding to the FIRST or the LAST operation.
+ *
+ * @param[in] p_cgms Service instance.
+ *
+ * @return NRF_SUCCESS on success, otherwise an error code.
+ */
+static uint32_t racp_report_records_first_last(nrf_ble_cgms_t * p_cgms)
+{
+ uint32_t err_code;
+ ble_cgms_rec_t rec;
+ uint16_t total_records;
+ uint8_t nb_rec_to_send = 1;
+
+ total_records = cgms_db_num_records_get();
+
+ if ((p_cgms->racp_data.racp_proc_records_reported != 0) || (total_records == 0))
+ {
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ }
+ else
+ {
+ if (p_cgms->racp_data.racp_proc_operator == RACP_OPERATOR_FIRST)
+ {
+ err_code = cgms_db_record_get(0, &rec);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ }
+ else if (p_cgms->racp_data.racp_proc_operator == RACP_OPERATOR_LAST)
+ {
+ err_code = cgms_db_record_get(total_records - 1, &rec);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ }
+
+ err_code = cgms_meas_send(p_cgms, &rec, &nb_rec_to_send);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ p_cgms->racp_data.racp_proc_record_ndx++;
+ }
+
+ return NRF_SUCCESS;
+}
+
+
+/**@brief Function for responding to the LESS OR EQUAL operation.
+ *
+ * @param[in] p_cgms Service instance.
+ *
+ * @return NRF_SUCCESS on success, otherwise an error code.
+ */
+static ret_code_t racp_report_records_less_equal(nrf_ble_cgms_t * p_cgms)
+{
+ uint16_t total_rec_nb_to_send;
+ uint16_t rec_nb_left_to_send;
+ uint8_t nb_rec_to_send;
+ uint16_t i;
+
+ total_rec_nb_to_send = p_cgms->racp_data.racp_proc_records_ndx_last_to_send +1;
+
+ if (p_cgms->racp_data.racp_proc_record_ndx >= total_rec_nb_to_send)
+ {
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ }
+ else
+ {
+ ret_code_t err_code;
+ ble_cgms_rec_t rec[NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX];
+
+ rec_nb_left_to_send = total_rec_nb_to_send - p_cgms->racp_data.racp_proc_records_reported;
+
+ if (rec_nb_left_to_send > NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX)
+ {
+ nb_rec_to_send = NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX;
+ }
+ else
+ {
+ nb_rec_to_send = (uint8_t)rec_nb_left_to_send;
+ }
+
+ for (i = 0; i < nb_rec_to_send; i++)
+ {
+ err_code = cgms_db_record_get(p_cgms->racp_data.racp_proc_record_ndx + i, &(rec[i]));
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ }
+ err_code = cgms_meas_send(p_cgms, rec, &nb_rec_to_send);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ p_cgms->racp_data.racp_proc_record_ndx += nb_rec_to_send;
+ }
+
+ return NRF_SUCCESS;
+}
+
+
+/**@brief Function for responding to the GREATER OR EQUAL operation.
+ *
+ * @param[in] p_cgms Service instance.
+ *
+ * @return NRF_SUCCESS on success, otherwise an error code.
+ */
+static ret_code_t racp_report_records_greater_equal(nrf_ble_cgms_t * p_cgms)
+{
+ ret_code_t err_code;
+ uint16_t total_rec_nb = cgms_db_num_records_get();
+ uint16_t rec_nb_left_to_send;
+ uint8_t nb_rec_to_send;
+ uint16_t i;
+
+
+ total_rec_nb = cgms_db_num_records_get();
+ if (p_cgms->racp_data.racp_proc_record_ndx >= total_rec_nb)
+ {
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ return NRF_SUCCESS;
+ }
+
+ ble_cgms_rec_t rec[NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX];
+
+ rec_nb_left_to_send = total_rec_nb - p_cgms->racp_data.racp_proc_record_ndx;
+ if (rec_nb_left_to_send > NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX)
+ {
+ nb_rec_to_send = NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX;
+ }
+ else
+ {
+ nb_rec_to_send = (uint8_t)rec_nb_left_to_send;
+ }
+
+ for (i = 0; i < nb_rec_to_send; i++)
+ {
+ err_code = cgms_db_record_get(p_cgms->racp_data.racp_proc_record_ndx + i, &(rec[i]));
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ }
+ err_code = cgms_meas_send(p_cgms, rec, &nb_rec_to_send);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ p_cgms->racp_data.racp_proc_record_ndx += nb_rec_to_send;
+
+ return NRF_SUCCESS;
+}
+
+
+/**@brief Function for informing that the REPORT RECORDS procedure is completed.
+ *
+ * @param[in] p_cgms Service instance.
+ */
+static void racp_report_records_completed(nrf_ble_cgms_t * p_cgms)
+{
+ uint8_t resp_code_value;
+
+ if (p_cgms->racp_data.racp_proc_records_reported > 0)
+ {
+ resp_code_value = RACP_RESPONSE_SUCCESS;
+ }
+ else
+ {
+ resp_code_value = RACP_RESPONSE_NO_RECORDS_FOUND;
+ }
+
+ racp_response_code_send(p_cgms, RACP_OPCODE_REPORT_RECS, resp_code_value);
+}
+
+
+/**@brief Function for the RACP report records procedure.
+ *
+ * @param[in] p_cgms Service instance.
+ */
+static void racp_report_records_procedure(nrf_ble_cgms_t * p_cgms)
+{
+ ret_code_t err_code = NRF_SUCCESS;
+
+ while (p_cgms->cgms_com_state == STATE_RACP_PROC_ACTIVE)
+ {
+ // Execute requested procedure
+ switch (p_cgms->racp_data.racp_proc_operator)
+ {
+ case RACP_OPERATOR_ALL:
+ err_code = racp_report_records_all(p_cgms);
+ break;
+
+ case RACP_OPERATOR_FIRST:
+ // Fall through.
+ case RACP_OPERATOR_LAST:
+ err_code = racp_report_records_first_last(p_cgms);
+ break;
+ case RACP_OPERATOR_GREATER_OR_EQUAL:
+ err_code = racp_report_records_greater_equal(p_cgms);
+ break;
+ case RACP_OPERATOR_LESS_OR_EQUAL:
+ err_code = racp_report_records_less_equal(p_cgms);
+ break;
+ default:
+ // Report error to application
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(NRF_ERROR_INTERNAL);
+ }
+
+ // Make sure state machine returns to the default state
+ // state_set(STATE_NO_COMM);
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ return;
+ }
+
+ // Error handling
+ switch (err_code)
+ {
+ case NRF_SUCCESS:
+ if (p_cgms->cgms_com_state != STATE_RACP_PROC_ACTIVE)
+ {
+ racp_report_records_completed(p_cgms);
+ }
+ break;
+
+ case NRF_ERROR_RESOURCES:
+ // Wait for TX_COMPLETE event to resume transmission.
+ return;
+
+ case NRF_ERROR_INVALID_STATE:
+ // Notification is probably not enabled. Ignore request.
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ return;
+
+ default:
+ // Report error to application.
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(err_code);
+ }
+
+ // Make sure state machine returns to the default state.
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ return;
+ }
+ }
+}
+
+
+/**@brief Function for testing if the received request is to be executed.
+ *
+ * @param[in] p_racp_request Request to be checked.
+ * @param[out] p_response_code Response code to be sent in case the request is rejected.
+ * RACP_RESPONSE_RESERVED is returned if the received message is
+ * to be rejected without sending a respone.
+ *
+ * @return TRUE if the request is to be executed, FALSE if it is to be rejected.
+ * If it is to be rejected, p_response_code will contain the response code to be
+ * returned to the central.
+ */
+static bool is_request_to_be_executed(nrf_ble_cgms_t * p_cgms,
+ const ble_racp_value_t * p_racp_request,
+ uint8_t * p_response_code)
+{
+ *p_response_code = RACP_RESPONSE_RESERVED;
+
+ if (p_racp_request->opcode == RACP_OPCODE_ABORT_OPERATION)
+ {
+ if (p_cgms->cgms_com_state == STATE_RACP_PROC_ACTIVE)
+ {
+ if (p_racp_request->operator != RACP_OPERATOR_NULL)
+ {
+ *p_response_code = RACP_RESPONSE_INVALID_OPERATOR;
+ }
+ else if (p_racp_request->operand_len != 0)
+ {
+ *p_response_code = RACP_RESPONSE_INVALID_OPERAND;
+ }
+ else
+ {
+ *p_response_code = RACP_RESPONSE_SUCCESS;
+ }
+ }
+ else
+ {
+ *p_response_code = RACP_RESPONSE_ABORT_FAILED;
+ }
+ }
+ else if (p_cgms->cgms_com_state != STATE_NO_COMM)
+ {
+ return false;
+ }
+ // Supported opcodes
+ else if ((p_racp_request->opcode == RACP_OPCODE_REPORT_RECS) ||
+ (p_racp_request->opcode == RACP_OPCODE_REPORT_NUM_RECS))
+ {
+ switch (p_racp_request->operator)
+ {
+ // Operators without a filter.
+ case RACP_OPERATOR_ALL:
+ // Fall through.
+ case RACP_OPERATOR_FIRST:
+ // Fall through.
+ case RACP_OPERATOR_LAST:
+ if (p_racp_request->operand_len != 0)
+ {
+ *p_response_code = RACP_RESPONSE_INVALID_OPERAND;
+ }
+ break;
+
+ // Operators with a filter as part of the operand.
+ case RACP_OPERATOR_LESS_OR_EQUAL:
+ // Fall Through.
+ case RACP_OPERATOR_GREATER_OR_EQUAL:
+ if (*(p_racp_request->p_operand) == RACP_OPERAND_FILTER_TYPE_FACING_TIME)
+ {
+ *p_response_code = RACP_RESPONSE_PROCEDURE_NOT_DONE;
+ }
+ if (p_racp_request->operand_len != OPERAND_LESS_GREATER_SIZE)
+ {
+ *p_response_code = RACP_RESPONSE_INVALID_OPERAND;
+ }
+ break;
+
+ case RACP_OPERATOR_RANGE:
+ *p_response_code = RACP_RESPONSE_OPERATOR_UNSUPPORTED;
+ break;
+
+ // Invalid operators.
+ case RACP_OPERATOR_NULL:
+ // Fall through.
+ default:
+ *p_response_code = RACP_RESPONSE_INVALID_OPERATOR;
+ break;
+ }
+ }
+ // Unsupported opcodes.
+ else if (p_racp_request->opcode == RACP_OPCODE_DELETE_RECS)
+ {
+ *p_response_code = RACP_RESPONSE_OPCODE_UNSUPPORTED;
+ }
+ // Unknown opcodes.
+ else
+ {
+ *p_response_code = RACP_RESPONSE_OPCODE_UNSUPPORTED;
+ }
+
+ return (*p_response_code == RACP_RESPONSE_RESERVED);
+}
+
+
+
+
+/**@brief Function for getting a record with time offset less or equal to the input param.
+ *
+ * @param[in] offset The record that this function returns must have an time offset less or greater to this.
+ * @param[out] record_num Pointer to the record index of the record that has the desired time offset.
+ *
+ * @retval NRF_SUCCESS If the record was successfully retrieved.
+ * @retval NRF_ERROR_NOT_FOUND A record with the desired offset does not exist in the database.
+ * @return If functions from other modules return errors to this function,
+ * the @ref nrf_error are propagated.
+ */
+static ret_code_t record_index_offset_less_or_equal_get(uint16_t offset, uint16_t * record_num)
+{
+ ret_code_t err_code;
+ ble_cgms_rec_t rec;
+ uint16_t upper_bound = cgms_db_num_records_get();
+
+ for((*record_num) = upper_bound; (*record_num)-- >0;)
+ {
+ err_code = cgms_db_record_get(*record_num, &rec);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ if (rec.meas.time_offset <= offset)
+ {
+ return NRF_SUCCESS;
+ }
+ }
+ return NRF_ERROR_NOT_FOUND;
+}
+
+
+
+/**@brief Function for getting a record with time offset greater or equal to the input param.
+ *
+ * @param[in] offset The record that this function returns must have an time offset equal or
+ * greater to this.
+ * @param[out] record_num Pointer to the record index of the record that has the desired time offset.
+ *
+ * @retval NRF_SUCCESS If the record was successfully retrieved.
+ * @retval NRF_ERROR_NOT_FOUND A record with the desired offset does not exist in the database.
+ * @return If functions from other modules return errors to this function,
+ * the @ref nrf_error are propagated.
+ */
+static ret_code_t record_index_offset_greater_or_equal_get(uint16_t offset, uint16_t * record_num)
+{
+ ret_code_t err_code;
+ ble_cgms_rec_t rec;
+ uint16_t upper_bound = cgms_db_num_records_get();
+
+ for(*record_num = 0; *record_num < upper_bound; (*record_num)++)
+ {
+ err_code = cgms_db_record_get(*record_num, &rec);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ if (rec.meas.time_offset >= offset)
+ {
+ return NRF_SUCCESS;
+ }
+ }
+ return NRF_ERROR_NOT_FOUND;
+}
+
+
+/**@brief Function for processing a REPORT RECORDS request.
+ *
+ * @details Set initial values before entering the state machine of racp_report_records_procedure().
+ *
+ * @param[in] p_cgms Service instance.
+ * @param[in] p_racp_request Request to be executed.
+ */
+static void report_records_request_execute(nrf_ble_cgms_t * p_cgms,
+ ble_racp_value_t * p_racp_request)
+{
+ p_cgms->cgms_com_state = STATE_RACP_PROC_ACTIVE;
+
+ p_cgms->racp_data.racp_proc_record_ndx = 0;
+ p_cgms->racp_data.racp_proc_operator = p_racp_request->operator;
+ p_cgms->racp_data.racp_proc_records_reported = 0;
+ p_cgms->racp_data.racp_proc_records_ndx_last_to_send = 0;
+
+ if (p_cgms->racp_data.racp_proc_operator == RACP_OPERATOR_GREATER_OR_EQUAL)
+ {
+ uint16_t offset_requested = uint16_decode(&p_cgms->racp_data.racp_request.p_operand[OPERAND_LESS_GREATER_FILTER_TYPE_SIZE]);
+ ret_code_t err_code = record_index_offset_greater_or_equal_get(offset_requested, &p_cgms->racp_data.racp_proc_record_ndx);
+ if (err_code != NRF_SUCCESS)
+ {
+ racp_report_records_completed(p_cgms);
+ }
+
+ }
+ if (p_cgms->racp_data.racp_proc_operator == RACP_OPERATOR_LESS_OR_EQUAL)
+ {
+ uint16_t offset_requested = uint16_decode(&p_cgms->racp_data.racp_request.p_operand[OPERAND_LESS_GREATER_FILTER_TYPE_SIZE]);
+ ret_code_t err_code = record_index_offset_less_or_equal_get(offset_requested,
+ &p_cgms->racp_data.racp_proc_records_ndx_last_to_send);
+ if (err_code != NRF_SUCCESS)
+ {
+ racp_report_records_completed(p_cgms);
+ }
+ }
+ racp_report_records_procedure(p_cgms);
+}
+
+
+/**@brief Function for processing a REPORT NUM RECORDS request.
+ *
+ * @param[in] p_cgms Service instance.
+ * @param[in] p_racp_request Request to be executed.
+ */
+static void report_num_records_request_execute(nrf_ble_cgms_t * p_cgms,
+ ble_racp_value_t * p_racp_request)
+{
+ uint16_t total_records;
+ uint16_t num_records;
+
+ total_records = cgms_db_num_records_get();
+ num_records = 0;
+
+ if (p_racp_request->operator == RACP_OPERATOR_ALL)
+ {
+ num_records = total_records;
+ }
+ else if ((p_racp_request->operator == RACP_OPERATOR_FIRST) ||
+ (p_racp_request->operator == RACP_OPERATOR_LAST))
+ {
+ if (total_records > 0)
+ {
+ num_records = 1;
+ }
+ }
+ else if (p_racp_request->operator == RACP_OPERATOR_GREATER_OR_EQUAL)
+ {
+ uint16_t index_of_offset;
+ uint16_t offset_requested = uint16_decode(&p_cgms->racp_data.racp_request.p_operand[OPERAND_LESS_GREATER_FILTER_TYPE_SIZE]);
+ ret_code_t err_code = record_index_offset_greater_or_equal_get(offset_requested, &index_of_offset);
+
+ if (err_code != NRF_SUCCESS)
+ {
+ num_records = 0;
+ }
+ else
+ {
+ num_records = total_records - index_of_offset;
+ }
+ }
+
+ p_cgms->racp_data.pending_racp_response.opcode = RACP_OPCODE_NUM_RECS_RESPONSE;
+ p_cgms->racp_data.pending_racp_response.operator = RACP_OPERATOR_NULL;
+ p_cgms->racp_data.pending_racp_response.operand_len = sizeof(uint16_t);
+ p_cgms->racp_data.pending_racp_response.p_operand =
+ p_cgms->racp_data.pending_racp_response_operand;
+
+ p_cgms->racp_data.pending_racp_response_operand[0] = num_records & 0xFF;
+ p_cgms->racp_data.pending_racp_response_operand[1] = num_records >> 8;
+
+ racp_send(p_cgms, &p_cgms->racp_data.pending_racp_response);
+}
+
+
+/**@brief Function for handling a write event to the Record Access Control Point.
+ *
+ * @param[in] p_cgms Service instance.
+ * @param[in] p_evt_write WRITE event to be handled.
+ */
+static void on_racp_value_write(nrf_ble_cgms_t * p_cgms, ble_gatts_evt_write_t const * p_evt_write)
+{
+ uint8_t response_code;
+
+ // set up reply to authorized write.
+ ble_gatts_rw_authorize_reply_params_t auth_reply;
+ uint32_t err_code;
+
+ auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
+ auth_reply.params.write.offset = 0;
+ auth_reply.params.write.len = 0;
+ auth_reply.params.write.p_data = NULL;
+
+ // Decode request.
+ ble_racp_decode(p_evt_write->len, p_evt_write->data, &p_cgms->racp_data.racp_request);
+
+ // Check if request is to be executed
+ if (is_request_to_be_executed(p_cgms, &p_cgms->racp_data.racp_request, &response_code))
+ {
+ auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
+ auth_reply.params.write.update = 1;
+
+ err_code = sd_ble_gatts_rw_authorize_reply(p_cgms->conn_handle,
+ &auth_reply);
+ if (err_code != NRF_SUCCESS)
+ {
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(err_code);
+ }
+ return;
+ }
+
+ // Execute request
+ if (p_cgms->racp_data.racp_request.opcode == RACP_OPCODE_REPORT_RECS)
+ {
+ report_records_request_execute(p_cgms, &p_cgms->racp_data.racp_request);
+ }
+ else if (p_cgms->racp_data.racp_request.opcode == RACP_OPCODE_REPORT_NUM_RECS)
+ {
+ report_num_records_request_execute(p_cgms, &p_cgms->racp_data.racp_request);
+ }
+ }
+ else if (response_code != RACP_RESPONSE_RESERVED)
+ {
+ auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
+ auth_reply.params.write.update = 1;
+ err_code = sd_ble_gatts_rw_authorize_reply(p_cgms->conn_handle,
+ &auth_reply);
+
+ if (err_code != NRF_SUCCESS)
+ {
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(err_code);
+ }
+ return;
+ }
+ // Abort any running procedure
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+
+ // Respond with error code
+ racp_response_code_send(p_cgms, p_cgms->racp_data.racp_request.opcode, response_code);
+ }
+ else
+ {
+ // ignore request
+ auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
+ auth_reply.params.write.update = 1;
+ err_code = sd_ble_gatts_rw_authorize_reply(p_cgms->conn_handle,
+ &auth_reply);
+
+ if (err_code != NRF_SUCCESS)
+ {
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(err_code);
+ }
+ return;
+ }
+ }
+}
+
+
+void cgms_racp_on_rw_auth_req(nrf_ble_cgms_t * p_cgms,
+ ble_gatts_evt_rw_authorize_request_t const * p_auth_req)
+{
+ if (p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
+ {
+ if (p_auth_req->request.write.handle == p_cgms->char_handles.racp.value_handle)
+ {
+ on_racp_value_write(p_cgms, &p_auth_req->request.write);
+ }
+ }
+}
+
+
+/**@brief Function for handling BLE_GATTS_EVT_HVN_TX_COMPLETE events.
+ *
+ * @param[in] p_cgms Glucose Service structure.
+ */
+void cgms_racp_on_tx_complete(nrf_ble_cgms_t * p_cgms)
+{
+ p_cgms->racp_data.racp_proc_records_reported_since_txcomplete = 0;
+
+ if (p_cgms->cgms_com_state == STATE_RACP_RESPONSE_PENDING)
+ {
+ racp_send(p_cgms, &p_cgms->racp_data.pending_racp_response);
+ }
+ else if (p_cgms->cgms_com_state == STATE_RACP_PROC_ACTIVE)
+ {
+ racp_report_records_procedure(p_cgms);
+ }
+}
+
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_racp.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_racp.h
new file mode 100644
index 0000000..e1d92af
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_racp.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.
+ *
+ */
+/** @file
+ *
+ * @defgroup ble_sdk_srv_cgms_racp Record Access Control Point
+ * @{
+ * @ingroup ble_cgms
+ * @brief Continuous Glucose Monitoring Service RACP module.
+ *
+ * @details This module implements parts of the Continuous Glucose Monitoring that relate to the
+ * Record Access Control Point. Events are propagated to this module from @ref ble_cgms
+ * using @ref cgms_racp_on_rw_auth_req and @ref cgms_racp_on_tx_complete.
+ *
+ */
+
+#ifndef NRF_BLE_CGMS_RACP_H__
+#define NRF_BLE_CGMS_RACP_H__
+
+#include "ble.h"
+#include "ble_srv_common.h"
+#include "sdk_errors.h"
+#include "nrf_ble_cgms.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**@brief Function for adding a characteristic for the Record Access Control Point.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ *
+ * @retval NRF_SUCCESS If the characteristic was successfully added.
+ * @retval NRF_ERROR_NULL If any of the input parameters are NULL.
+ * @return If functions from other modules return errors to this function,
+ * the @ref nrf_error are propagated.
+ */
+ret_code_t cgms_racp_char_add(nrf_ble_cgms_t * p_cgms);
+
+
+/**@brief Function for handling @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST events.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ * @param[in] p_auth_req Authorize request event to be handled.
+ */
+void cgms_racp_on_rw_auth_req(nrf_ble_cgms_t * p_cgms,
+ ble_gatts_evt_rw_authorize_request_t const * p_auth_req);
+
+
+/**@brief Function for handling @ref BLE_GATTS_EVT_HVN_TX_COMPLETE events.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ */
+void cgms_racp_on_tx_complete(nrf_ble_cgms_t * p_cgms);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRF_BLE_CGMS_RACP_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_socp.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_socp.c
new file mode 100644
index 0000000..2ade378
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_socp.c
@@ -0,0 +1,431 @@
+/**
+ * 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 "ble.h"
+#include "ble_srv_common.h"
+#include "cgms_sst.h"
+#include "cgms_socp.h"
+
+
+#define NRF_BLE_CGMS_PLUS_INFINTE 0x07FE
+#define NRF_BLE_CGMS_MINUS_INFINTE 0x0802
+
+/**@brief Specific Operation Control Point opcodes. */
+#define SOCP_OPCODE_RESERVED 0x00 /**< Specific Operation Control Point opcode - Reserved for future use. */
+#define SOCP_WRITE_CGM_COMMUNICATION_INTERVAL 0x01
+#define SOCP_READ_CGM_COMMUNICATION_INTERVAL 0x02
+#define SOCP_READ_CGM_COMMUNICATION_INTERVAL_RESPONSE 0x03
+#define SOCP_WRITE_GLUCOSE_CALIBRATION_VALUE 0x04
+#define SOCP_READ_GLUCOSE_CALIBRATION_VALUE 0x05
+#define SOCP_READ_GLUCOSE_CALIBRATION_VALUE_RESPONSE 0x06
+#define SOCP_WRITE_PATIENT_HIGH_ALERT_LEVEL 0x07
+#define SOCP_READ_PATIENT_HIGH_ALERT_LEVEL 0x08
+#define SOCP_READ_PATIENT_HIGH_ALERT_LEVEL_RESPONSE 0x09
+#define SOCP_WRITE_PATIENT_LOW_ALERT_LEVEL 0x0A
+#define SOCP_READ_PATIENT_LOW_ALERT_LEVEL 0x0B
+#define SOCP_READ_PATIENT_LOW_ALERT_LEVEL_RESPONSE 0x0C
+#define SOCP_SET_HYPO_ALERT_LEVEL 0x0D /**Set Hypo Alert Level Hypo Alert Level value in mg/dL The response to this control point is Response Code. */
+#define SOCP_GET_HYPO_ALERT_LEVEL 0x0E /**Get Hypo Alert Level N/A The normal response to this control point is Op Code 0x0F. For error conditions, the response is Response Code */
+#define SOCP_HYPO_ALERT_LEVEL_RESPONSE 0x0F /**Hypo Alert Level Response Hypo Alert Level value in mg/dL This is the normal response to Op Code 0x0E */
+#define SOCP_SET_HYPER_ALERT_LEVEL 0x10 /**Set Hyper Alert Level Hyper Alert Level value in mg/dL The response to this control point is Response Code. */
+#define SOCP_GET_HYPER_ALERT_LEVEL 0x11 /**Get Hyper Alert Level N/A The normal response to this control point is Op Code 0x12. For error conditions, the response is Response Code */
+#define SOCP_HYPER_ALERT_LEVEL_RESPONSE 0x12 /**Hyper Alert Level Response Hyper Alert Level value in mg/dL This is the normal response to Op Code 0x11 */
+#define SOCP_SET_RATE_OF_DECREASE_ALERT_LEVEL 0x13 /**Set Rate of Decrease Alert Level Rate of Decrease Alert Level value in mg/dL/min The response to this control point is Response Code. */
+#define SOCP_GET_RATE_OF_DECREASE_ALERT_LEVEL 0x14 /**Get Rate of Decrease Alert Level N/A The normal response to this control point is Op Code 0x15. For error conditions, the response is Response Code */
+#define SOCP_RATE_OF_DECREASE_ALERT_LEVEL_RESPONSE 0x15 /**Rate of Decrease Alert Level Response Rate of Decrease Alert Level value in mg/dL/min This is the normal response to Op Code 0x14 */
+#define SOCP_SET_RATE_OF_INCREASE_ALERT_LEVEL 0x16 /**Set Rate of Increase Alert Level Rate of Increase Alert Level value in mg/dL/min The response to this control point is Response Code. */
+#define SOCP_GET_RATE_OF_INCREASE_ALERT_LEVEL 0x17 /**Get Rate of Increase Alert Level N/A The normal response to this control point is Op Code 0x18. For error conditions, the response is Response Code */
+#define SOCP_RATE_OF_INCREASE_ALERT_LEVEL_RESPONSE 0x18 /**Rate of Increase Alert Level Response Rate of Increase Alert Level value in mg/dL/min This is the normal response to Op Code 0x17 */
+#define SOCP_RESET_DEVICE_SPECIFIC_ALERT 0x19 /**Reset Device Specific Alert N/A The response to this control point is Response Code. */
+
+#define SOCP_START_THE_SESSION 0x1A
+#define SOCP_STOP_THE_SESSION 0x1B
+#define SOCP_RESPONSE_CODE 0x1C
+
+#define SOCP_RSP_RESERVED_FOR_FUTURE_USE 0x00
+#define SOCP_RSP_SUCCESS 0x01
+#define SOCP_RSP_OP_CODE_NOT_SUPPORTED 0x02
+#define SOCP_RSP_INVALID_OPERAND 0x03
+#define SOCP_RSP_PROCEDURE_NOT_COMPLETED 0x04
+#define SOCP_RSP_OUT_OF_RANGE 0x05
+
+static void ble_socp_decode(uint8_t data_len, uint8_t const * p_data, ble_cgms_socp_value_t * p_socp_val)
+{
+ p_socp_val->opcode = 0xFF;
+ p_socp_val->operand_len = 0;
+ p_socp_val->p_operand = NULL;
+
+ if (data_len > 0)
+ {
+ p_socp_val->opcode = p_data[0];
+ }
+ if (data_len > 1)
+ {
+ p_socp_val->operand_len = data_len - 1;
+ p_socp_val->p_operand = (uint8_t*)&p_data[1]; // lint !e416
+ }
+}
+
+
+uint8_t ble_socp_encode(const ble_socp_rsp_t * p_socp_rsp, uint8_t * p_data)
+{
+ uint8_t len = 0;
+ int i;
+
+
+ if (p_data != NULL)
+ {
+ p_data[len++] = p_socp_rsp->opcode;
+
+ if (
+ (p_socp_rsp->opcode != SOCP_READ_CGM_COMMUNICATION_INTERVAL_RESPONSE)
+ && (p_socp_rsp->opcode != SOCP_READ_PATIENT_HIGH_ALERT_LEVEL_RESPONSE)
+ && (p_socp_rsp->opcode != SOCP_READ_PATIENT_LOW_ALERT_LEVEL_RESPONSE)
+ && (p_socp_rsp->opcode != SOCP_HYPO_ALERT_LEVEL_RESPONSE)
+ && (p_socp_rsp->opcode != SOCP_HYPER_ALERT_LEVEL_RESPONSE)
+ && (p_socp_rsp->opcode != SOCP_RATE_OF_DECREASE_ALERT_LEVEL_RESPONSE)
+ && (p_socp_rsp->opcode != SOCP_RATE_OF_INCREASE_ALERT_LEVEL_RESPONSE)
+ && (p_socp_rsp->opcode != SOCP_READ_GLUCOSE_CALIBRATION_VALUE_RESPONSE)
+ )
+ {
+ p_data[len++] = p_socp_rsp->req_opcode;
+ p_data[len++] = p_socp_rsp->rsp_code;
+ }
+
+ for (i = 0; i < p_socp_rsp->size_val; i++)
+ {
+ p_data[len++] = p_socp_rsp->resp_val[i];
+ }
+ }
+
+ return len;
+}
+
+
+/**@brief Function for adding a characteristic for the Specific Operations Control Point.
+ *
+ * @param[in] p_cgms Service instance.
+ *
+ * @return NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
+ */
+ret_code_t cgms_socp_char_add(nrf_ble_cgms_t * p_cgms)
+{
+ ble_add_char_params_t add_char_params;
+
+ memset(&add_char_params, 0, sizeof(add_char_params));
+
+ add_char_params.uuid = BLE_UUID_CGM_SPECIFIC_OPS_CTRLPT;
+ add_char_params.max_len = BLE_GATT_ATT_MTU_DEFAULT;
+ add_char_params.init_len = 0;
+ add_char_params.p_init_value = 0;
+ add_char_params.is_var_len = true;
+ add_char_params.char_props.indicate = true;
+ add_char_params.char_props.write = true;
+ add_char_params.write_access = SEC_JUST_WORKS;
+ add_char_params.cccd_write_access = SEC_JUST_WORKS;
+ add_char_params.is_defered_write = 1;
+
+ return characteristic_add(p_cgms->service_handle,
+ &add_char_params,
+ &p_cgms->char_handles.socp);
+}
+
+
+/**@brief Function for sending a response from the Specific Operation Control Point.
+ *
+ * @param[in] p_cgms Service instance.
+ */
+static void socp_send(nrf_ble_cgms_t * p_cgms)
+{
+ uint32_t err_code;
+ uint8_t encoded_resp[25];
+ uint8_t len;
+ uint16_t hvx_len;
+ ble_gatts_hvx_params_t hvx_params;
+
+ // Send indication
+ len = ble_socp_encode(&(p_cgms->socp_response), encoded_resp);
+ hvx_len = len;
+
+ memset(&hvx_params, 0, sizeof(hvx_params));
+
+ hvx_params.handle = p_cgms->char_handles.socp.value_handle;
+ hvx_params.type = BLE_GATT_HVX_INDICATION;
+ hvx_params.offset = 0;
+ hvx_params.p_len = &hvx_len;
+ hvx_params.p_data = encoded_resp;
+
+ err_code = sd_ble_gatts_hvx(p_cgms->conn_handle, &hvx_params);
+
+ // Error handling
+ if ((err_code == NRF_SUCCESS) && (hvx_len != len))
+ {
+ err_code = NRF_ERROR_DATA_SIZE;
+ }
+
+ switch (err_code)
+ {
+ case NRF_SUCCESS:
+ // Wait for HVC event.
+ p_cgms->cgms_com_state = STATE_SOCP_RESPONSE_IND_VERIF;
+ break;
+
+ case NRF_ERROR_RESOURCES:
+ // Wait for TX_COMPLETE event to retry transmission.
+ p_cgms->cgms_com_state = STATE_SOCP_RESPONSE_PENDING;
+ break;
+
+ case NRF_ERROR_INVALID_STATE:
+ // Make sure state machine returns to the default state.
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ break;
+
+ default:
+ // Report error to application.
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(err_code);
+ }
+
+ // Make sure state machine returns to the default state.
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ break;
+ }
+}
+
+
+void encode_get_response(uint8_t rsp_code, ble_socp_rsp_t * p_rsp, uint16_t in_val)
+{
+ p_rsp->opcode = rsp_code;
+ p_rsp->rsp_code = SOCP_RSP_SUCCESS;
+ p_rsp->size_val += uint16_encode(in_val, &(p_rsp->resp_val[p_rsp->size_val]));
+}
+
+
+void decode_set_opcode(nrf_ble_cgms_t * p_cgms,
+ ble_cgms_socp_value_t * rcv_val,
+ uint16_t min,
+ uint16_t max,
+ uint16_t * p_val)
+{
+ uint16_t rcvd_val = uint16_decode(rcv_val->p_operand);
+
+ if ((rcvd_val == NRF_BLE_CGMS_PLUS_INFINTE)
+ || (rcvd_val == NRF_BLE_CGMS_MINUS_INFINTE)
+ || (rcvd_val > max)
+ || (rcvd_val < min))
+ {
+ p_cgms->socp_response.rsp_code = SOCP_RSP_OUT_OF_RANGE;
+ }
+ else
+ {
+ p_cgms->socp_response.rsp_code = SOCP_RSP_SUCCESS;
+ *p_val = rcvd_val;
+ }
+}
+
+
+static bool is_feature_present(nrf_ble_cgms_t * p_cgms, uint32_t feature)
+{
+ return (p_cgms->feature.feature & feature);
+}
+
+
+/**@brief Function for handling a write event to the Specific Operation Control Point.
+ *
+ * @param[in] p_cgms Service instance.
+ * @param[in] p_evt_write WRITE event to be handled.
+ */
+static void on_socp_value_write(nrf_ble_cgms_t * p_cgms, ble_gatts_evt_write_t const * p_evt_write)
+{
+ ble_cgms_socp_value_t socp_request;
+ nrf_ble_cgms_evt_t evt;
+ ble_gatts_rw_authorize_reply_params_t auth_reply;
+ uint32_t err_code;
+
+ memset(&auth_reply, 0, sizeof(auth_reply));
+
+ auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
+
+ auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
+ auth_reply.params.write.update = 1;
+
+ err_code = sd_ble_gatts_rw_authorize_reply(p_cgms->conn_handle, &auth_reply);
+ if (err_code != NRF_SUCCESS)
+ {
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(err_code);
+ }
+ return;
+ }
+
+ // Decode request
+ ble_socp_decode(p_evt_write->len, p_evt_write->data, &socp_request);
+
+ p_cgms->socp_response.opcode = SOCP_RESPONSE_CODE;
+ p_cgms->socp_response.req_opcode = socp_request.opcode;
+ p_cgms->socp_response.rsp_code = SOCP_RSP_OP_CODE_NOT_SUPPORTED;
+ p_cgms->socp_response.size_val = 0;
+
+
+ switch (socp_request.opcode)
+ {
+ case SOCP_WRITE_CGM_COMMUNICATION_INTERVAL:
+ p_cgms->socp_response.rsp_code = SOCP_RSP_SUCCESS;
+ p_cgms->comm_interval = socp_request.p_operand[0];
+ evt.evt_type = NRF_BLE_CGMS_EVT_WRITE_COMM_INTERVAL;
+ p_cgms->evt_handler(p_cgms, &evt);
+ break;
+
+ case SOCP_READ_CGM_COMMUNICATION_INTERVAL:
+ p_cgms->socp_response.opcode = SOCP_READ_CGM_COMMUNICATION_INTERVAL_RESPONSE;
+ p_cgms->socp_response.resp_val[0] = p_cgms->comm_interval;
+ p_cgms->socp_response.size_val++;
+ break;
+
+ case SOCP_START_THE_SESSION:
+ if (p_cgms->is_session_started)
+ {
+ p_cgms->socp_response.rsp_code = SOCP_RSP_PROCEDURE_NOT_COMPLETED;
+ }
+ else if ((p_cgms->nb_run_session != 0) &&
+ !(is_feature_present(p_cgms, NRF_BLE_CGMS_FEAT_MULTIPLE_SESSIONS_SUPPORTED)))
+ {
+ p_cgms->socp_response.rsp_code = SOCP_RSP_PROCEDURE_NOT_COMPLETED;
+ }
+ else
+ {
+ p_cgms->socp_response.rsp_code = SOCP_RSP_SUCCESS;
+ p_cgms->is_session_started = true;
+ p_cgms->nb_run_session++;
+
+ if (p_cgms->evt_handler != NULL)
+ {
+ evt.evt_type = NRF_BLE_CGMS_EVT_START_SESSION;
+ p_cgms->evt_handler(p_cgms, &evt);
+ }
+
+ ble_cgms_sst_t sst;
+ memset(&sst, 0, sizeof(ble_cgms_sst_t));
+
+ err_code = cgms_sst_set(p_cgms, &sst);
+ if (err_code != NRF_SUCCESS)
+ {
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(err_code);
+ }
+ }
+ p_cgms->sensor_status.time_offset = 0;
+ p_cgms->sensor_status.status.status &= (~NRF_BLE_CGMS_STATUS_SESSION_STOPPED);
+
+ err_code = nrf_ble_cgms_update_status(p_cgms, &p_cgms->sensor_status);
+ if (err_code != NRF_SUCCESS)
+ {
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(err_code);
+ }
+ }
+ }
+ break;
+
+ case SOCP_STOP_THE_SESSION:
+ {
+ nrf_ble_cgm_status_t status;
+ memset(&status, 0, sizeof(nrf_ble_cgm_status_t));
+
+ p_cgms->evt_handler(p_cgms, &evt);
+ p_cgms->socp_response.rsp_code = SOCP_RSP_SUCCESS;
+ p_cgms->is_session_started = false;
+
+ status.time_offset = p_cgms->sensor_status.time_offset;
+ status.status.status = p_cgms->sensor_status.status.status |
+ NRF_BLE_CGMS_STATUS_SESSION_STOPPED;
+
+ if (p_cgms->evt_handler != NULL)
+ {
+ evt.evt_type = NRF_BLE_CGMS_EVT_STOP_SESSION;
+ p_cgms->evt_handler(p_cgms, &evt);
+ }
+ err_code = nrf_ble_cgms_update_status(p_cgms, &status);
+ if (err_code != NRF_SUCCESS)
+ {
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(err_code);
+ }
+ }
+ break;
+ }
+
+ default:
+ p_cgms->socp_response.rsp_code = SOCP_RSP_OP_CODE_NOT_SUPPORTED;
+ break;
+ }
+
+ socp_send(p_cgms);
+}
+
+
+void cgms_socp_on_rw_auth_req(nrf_ble_cgms_t * p_cgms,
+ ble_gatts_evt_rw_authorize_request_t const * p_auth_req)
+{
+ if (p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
+ {
+ if (p_auth_req->request.write.handle == p_cgms->char_handles.socp.value_handle)
+ {
+ on_socp_value_write(p_cgms, &p_auth_req->request.write);
+ }
+ }
+}
+
+
+void cgms_socp_on_tx_complete(nrf_ble_cgms_t * p_cgms)
+{
+ if (p_cgms->cgms_com_state == STATE_SOCP_RESPONSE_PENDING)
+ {
+ socp_send(p_cgms);
+ }
+}
+
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_socp.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_socp.h
new file mode 100644
index 0000000..80cb35b
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_socp.h
@@ -0,0 +1,107 @@
+/**
+ * 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.
+ *
+ */
+/** @file
+ *
+ * @defgroup ble_sdk_srv_cgms_socp Specific Operations Control Point
+ * @{
+ * @ingroup ble_cgms
+ * @brief Continuous Glucose Monitoring Service SOCP module.
+ *
+ * @details This module implements parts of the Continuous Glucose Monitoring that relate to the
+ * Specific Operations Control Point. Events are propagated to this module from @ref ble_cgms
+ * using @ref cgms_socp_on_rw_auth_req and @ref cgms_socp_on_tx_complete.
+ *
+ */
+
+#ifndef NRF_BLE_CGMS_SOCP_H__
+#define NRF_BLE_CGMS_SOCP_H__
+
+#include "ble.h"
+#include "ble_srv_common.h"
+#include "sdk_errors.h"
+#include "nrf_ble_cgms.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**@brief Specific Operation Control Point value. */
+typedef struct
+{
+ uint8_t opcode; /**< Opcode. */
+ uint8_t operand_len; /**< Length of the operand. */
+ uint8_t * p_operand; /**< Pointer to the operand. */
+} ble_cgms_socp_value_t;
+
+
+/**@brief Function for adding a characteristic for the Specific Operations Control Point.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ *
+ * @retval NRF_SUCCESS If the characteristic was successfully added.
+ * @return If functions from other modules return errors to this function,
+ * the @ref nrf_error are propagated.
+ */
+ret_code_t cgms_socp_char_add(nrf_ble_cgms_t * p_cgms);
+
+
+/**@brief Function for handling @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST events.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ * @param[in] p_auth_req Authorize request event to be handled.
+ */
+void cgms_socp_on_rw_auth_req(nrf_ble_cgms_t * p_cgms,
+ ble_gatts_evt_rw_authorize_request_t const * p_auth_req);
+
+
+/**@brief Function for handling @ref BLE_GATTS_EVT_HVN_TX_COMPLETE events.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ */
+void cgms_socp_on_tx_complete(nrf_ble_cgms_t * p_cgms);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRF_BLE_CGMS_SOCP_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_sst.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_sst.c
new file mode 100644
index 0000000..b6b2fcd
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_sst.c
@@ -0,0 +1,235 @@
+/**
+ * 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 <time.h>
+#include "ble.h"
+#include "ble_srv_common.h"
+#include "nrf_ble_cgms.h"
+#include "cgms_sst.h"
+
+
+void sst_decode(ble_cgms_sst_t * p_sst, const uint8_t * p_data, const uint16_t len)
+{
+ uint32_t index;
+
+ if (len != NRF_BLE_CGMS_SST_LEN)
+ {
+ return;
+ }
+
+ index = ble_date_time_decode(&p_sst->date_time, p_data);
+
+ p_sst->time_zone = p_data[index++];
+ p_sst->dst = p_data[index++];
+}
+
+
+void convert_ble_time_c_time(ble_cgms_sst_t * p_sst, struct tm * p_c_time_date)
+{
+ p_c_time_date->tm_sec = p_sst->date_time.seconds;
+ p_c_time_date->tm_min = p_sst->date_time.minutes;
+ p_c_time_date->tm_hour = p_sst->date_time.hours;
+ p_c_time_date->tm_mday = p_sst->date_time.day;
+ p_c_time_date->tm_mon = p_sst->date_time.month;
+ p_c_time_date->tm_year = p_sst->date_time.year - 1900;
+
+ // Ignore daylight saving for this conversion.
+ p_c_time_date->tm_isdst = 0;
+}
+
+
+void calc_sst(uint16_t offset, struct tm * p_c_time_date)
+{
+ time_t c_time_in_sec;
+
+ c_time_in_sec = mktime(p_c_time_date);
+ c_time_in_sec = c_time_in_sec - (offset * 60);
+ *p_c_time_date = *(localtime(&c_time_in_sec));
+
+ if (p_c_time_date->tm_isdst == 1)
+ {
+ // Daylight saving time is not used and must be removed.
+ p_c_time_date->tm_hour = p_c_time_date->tm_hour - 1;
+ p_c_time_date->tm_isdst = 0;
+ }
+}
+
+
+static void convert_c_time_ble_time(ble_cgms_sst_t * p_sst, struct tm * p_c_time_date)
+{
+ p_sst->date_time.seconds = p_c_time_date->tm_sec;
+ p_sst->date_time.minutes = p_c_time_date->tm_min;
+ p_sst->date_time.hours = p_c_time_date->tm_hour;
+ p_sst->date_time.day = p_c_time_date->tm_mday;
+ p_sst->date_time.month = p_c_time_date->tm_mon;
+ p_sst->date_time.year = p_c_time_date->tm_year + 1900;
+}
+
+
+static uint8_t sst_encode(ble_cgms_sst_t * p_sst, uint8_t * p_encoded_sst)
+{
+ uint8_t len;
+
+ len = ble_date_time_encode(&p_sst->date_time, p_encoded_sst);
+
+ p_encoded_sst[len++] = p_sst->time_zone;
+ p_encoded_sst[len++] = p_sst->dst;
+
+ return len;
+}
+
+
+static ret_code_t cgm_update_sst(nrf_ble_cgms_t * p_cgms, ble_gatts_evt_write_t const * p_evt_write)
+{
+ ble_cgms_sst_t sst;
+ struct tm c_time_and_date;
+
+ memset(&sst, 0, sizeof(ble_cgms_sst_t));
+
+ sst_decode(&sst, p_evt_write->data, p_evt_write->len);
+ convert_ble_time_c_time(&sst, &c_time_and_date);
+ calc_sst(p_cgms->sensor_status.time_offset, &c_time_and_date);
+ convert_c_time_ble_time(&sst, &c_time_and_date);
+
+ return cgms_sst_set(p_cgms, &sst);
+}
+
+
+/**@brief Function for handling the Glucose session start time write event.
+ *
+ * @param[in] p_cgms Service instance.
+ * @param[in] p_evt_write WRITE event to be handled.
+ */
+static void on_sst_value_write(nrf_ble_cgms_t * p_cgms, ble_gatts_evt_write_t const * p_evt_write)
+{
+ ble_gatts_rw_authorize_reply_params_t auth_reply;
+ uint32_t err_code;
+
+ memset(&auth_reply, 0, sizeof(auth_reply));
+
+ auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
+ auth_reply.params.write.update = 1;
+ auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
+
+ err_code = sd_ble_gatts_rw_authorize_reply(p_cgms->conn_handle, &auth_reply);
+ if (err_code != NRF_SUCCESS)
+ {
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(err_code);
+ }
+ }
+
+ err_code = cgm_update_sst(p_cgms, p_evt_write);
+ if (err_code != NRF_SUCCESS)
+ {
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(err_code);
+ }
+ }
+}
+
+
+/**@brief Function for adding a characteristic for the Session Start Time.
+ *
+ * @param[in] p_cgms Service instance.
+ *
+ * @return NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
+ */
+ret_code_t cgms_sst_char_add(nrf_ble_cgms_t * p_cgms)
+{
+ ble_add_char_params_t add_char_params;
+ uint8_t init_value[NRF_BLE_CGMS_SST_LEN] = {0};
+
+ memset(&add_char_params, 0, sizeof(add_char_params));
+
+ add_char_params.uuid = BLE_UUID_CGM_SESSION_START_TIME;
+ add_char_params.max_len = NRF_BLE_CGMS_SST_LEN;
+
+ add_char_params.init_len = NRF_BLE_CGMS_SST_LEN;
+ add_char_params.p_init_value = init_value;
+
+ add_char_params.read_access = SEC_JUST_WORKS;
+ add_char_params.write_access = SEC_JUST_WORKS;
+ add_char_params.is_defered_write = 1;
+ add_char_params.char_props.write = true;
+ add_char_params.char_props.read = true;
+
+ return characteristic_add(p_cgms->service_handle,
+ &add_char_params,
+ &p_cgms->char_handles.sst);
+}
+
+
+ret_code_t cgms_sst_set(nrf_ble_cgms_t * p_cgms, ble_cgms_sst_t * p_sst)
+{
+ uint16_t conn_handle;
+ uint16_t value_handle;
+ ble_gatts_value_t sst_val;
+ uint8_t encoded_start_session_time[NRF_BLE_CGMS_SST_LEN];
+ uint8_t gatts_value_set_len = 0;
+
+ gatts_value_set_len = sst_encode(p_sst, encoded_start_session_time);
+ conn_handle = p_cgms->conn_handle;
+ value_handle = p_cgms->char_handles.sst.value_handle;
+ memset(&sst_val, 0, sizeof(ble_gatts_value_t));
+ sst_val.len = gatts_value_set_len;
+ sst_val.p_value = encoded_start_session_time;
+ sst_val.offset = 0;
+
+ return (sd_ble_gatts_value_set(conn_handle, value_handle, &sst_val));
+}
+
+
+void cgms_sst_on_rw_auth_req(nrf_ble_cgms_t * p_cgms,
+ ble_gatts_evt_rw_authorize_request_t const * p_auth_req)
+{
+ if (p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
+ {
+ if (p_auth_req->request.write.handle == p_cgms->char_handles.sst.value_handle)
+ {
+ on_sst_value_write(p_cgms, &p_auth_req->request.write);
+ }
+ }
+}
+
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_sst.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_sst.h
new file mode 100644
index 0000000..800c81c
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/cgms_sst.h
@@ -0,0 +1,115 @@
+/**
+ * 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.
+ *
+ */
+/** @file
+ *
+ * @defgroup ble_sdk_srv_cgms_sst Session Start Time
+ * @{
+ * @ingroup ble_cgms
+ *
+ * @brief Continuous Glucose Monitoring Service SST module.
+ *
+ * @details This module implements parts of the Continuous Glucose Monitoring that relate to the
+ * Session Start Time characteristic. Events are propagated to this module from @ref ble_cgms
+ * using @ref cgms_sst_on_rw_auth_req.
+ *
+ */
+
+#ifndef NRF_BLE_CGMS_SST_H__
+#define NRF_BLE_CGMS_SST_H__
+
+
+#include "ble.h"
+#include "ble_srv_common.h"
+#include "ble_date_time.h"
+#include "sdk_errors.h"
+#include "nrf_ble_cgms.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**@brief Required data for setting the SST characteristic value. */
+typedef struct
+{
+ ble_date_time_t date_time; /**< Date and time. */
+ uint8_t time_zone; /**< Time zone. */
+ uint8_t dst; /**< Daylight saving time. */
+}ble_cgms_sst_t;
+
+/**@brief Function for adding a characteristic for the Session Start Time.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ *
+ * @retval NRF_SUCCESS If the characteristic was successfully added.
+ * @return If functions from other modules return errors to this function,
+ * the @ref nrf_error are propagated.
+ */
+ret_code_t cgms_sst_char_add(nrf_ble_cgms_t * p_cgms);
+
+
+/**@brief Function for setting the Session Run Time attribute.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ * @param[in] p_sst Time and date that will be displayed in the session start time attribute.
+ *
+ * @retval NRF_SUCCESS If the Session Run Time Attribute was successfully set.
+ * @return If functions from other modules return errors to this function,
+ * the @ref nrf_error are propagated.
+ */
+ret_code_t cgms_sst_set(nrf_ble_cgms_t * p_cgms, ble_cgms_sst_t * p_sst);
+
+
+/**@brief Function for handling @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST events.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ * @param[in] p_auth_req Authorize request event to be handled.
+ */
+void cgms_sst_on_rw_auth_req(nrf_ble_cgms_t * p_cgms,
+ ble_gatts_evt_rw_authorize_request_t const * p_auth_req);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRF_BLE_CGMS_SST_H__
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/nrf_ble_cgms.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/nrf_ble_cgms.c
new file mode 100644
index 0000000..f895edb
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/nrf_ble_cgms.c
@@ -0,0 +1,504 @@
+/**
+ * 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 "ble_racp.h"
+#include "ble_srv_common.h"
+
+#include "ble_date_time.h"
+#include "sdk_common.h"
+
+#include "nrf_ble_cgms.h"
+#include "cgms_db.h"
+#include "cgms_meas.h"
+#include "cgms_racp.h"
+#include "cgms_socp.h"
+#include "cgms_sst.h"
+
+#define OPERAND_FILTER_TYPE_RESV 0x00 /**< Filter type value reserved for future use. */
+#define OPERAND_FILTER_TYPE_SEQ_NUM 0x01 /**< Filter data using Sequence Number criteria. */
+#define OPERAND_FILTER_TYPE_FACING_TIME 0x02 /**< Filter data using User Facing Time criteria. */
+
+
+/**@brief Function for setting next sequence number by reading the last record in the data base.
+ *
+ * @return NRF_SUCCESS on successful initialization of service, otherwise an error code.
+ */
+static uint32_t next_sequence_number_set(void)
+{
+ uint16_t num_records;
+ ble_cgms_rec_t rec;
+
+ num_records = cgms_db_num_records_get();
+ if (num_records > 0)
+ {
+ // Get last record
+ uint32_t err_code = cgms_db_record_get(num_records - 1, &rec);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ }
+
+ return NRF_SUCCESS;
+}
+
+
+uint8_t encode_feature_location_type(uint8_t * p_out_buffer, nrf_ble_cgms_feature_t * p_in_feature)
+{
+ uint8_t len = 0;
+
+ len += uint24_encode(p_in_feature->feature, &p_out_buffer[len]);
+ p_out_buffer[len++] = (p_in_feature->sample_location << 4) | (p_in_feature->type & 0x0F);
+ len += uint16_encode(0xFFFF, &p_out_buffer[len]);
+
+ return len;
+}
+
+
+/**@brief Function for adding a characteristic for the glucose feature.
+ *
+ * @param[in] p_cgms Service instance.
+ *
+ * @return NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
+ */
+static uint32_t glucose_feature_char_add(nrf_ble_cgms_t * p_cgms)
+{
+ uint8_t init_value_len;
+ uint8_t encoded_initial_feature[NRF_BLE_CGMS_FEATURE_LEN];
+ ble_add_char_params_t add_char_params;
+
+ memset(&add_char_params, 0, sizeof(add_char_params));
+
+ init_value_len = encode_feature_location_type(encoded_initial_feature, &(p_cgms->feature));
+
+ add_char_params.uuid = BLE_UUID_CGM_FEATURE;
+ add_char_params.max_len = init_value_len;
+ add_char_params.init_len = init_value_len;
+ add_char_params.p_init_value = encoded_initial_feature;
+ add_char_params.read_access = SEC_JUST_WORKS;
+ add_char_params.write_access = SEC_NO_ACCESS;
+
+
+ return characteristic_add(p_cgms->service_handle,
+ &add_char_params,
+ &p_cgms->char_handles.feature);
+}
+
+
+uint8_t encode_status(uint8_t * p_out_buffer, nrf_ble_cgms_t * p_cgms)
+{
+ uint8_t len = 0;
+
+ len += uint16_encode(p_cgms->sensor_status.time_offset, &p_out_buffer[len]);
+
+ p_out_buffer[len++] = p_cgms->sensor_status.status.status;
+ p_out_buffer[len++] = p_cgms->sensor_status.status.calib_temp;
+ p_out_buffer[len++] = p_cgms->sensor_status.status.warning;
+
+ return len;
+}
+
+
+/**@brief Function for adding a status characteristic for the CGMS.
+ *
+ * @param[in] p_cgms Service instance.
+ *
+ * @return NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
+ */
+static uint32_t status_char_add(nrf_ble_cgms_t * p_cgms)
+{
+ uint8_t init_value_len;
+ uint8_t encoded_initial_status[NRF_BLE_CGMS_STATUS_LEN];
+ ble_add_char_params_t add_char_params;
+
+ memset(&add_char_params, 0, sizeof(add_char_params));
+
+ init_value_len = encode_status(encoded_initial_status, p_cgms);
+
+ add_char_params.uuid = BLE_UUID_CGM_STATUS;
+ add_char_params.max_len = init_value_len;
+ add_char_params.init_len = init_value_len;
+ add_char_params.p_init_value = encoded_initial_status;
+ add_char_params.read_access = SEC_JUST_WORKS;
+ add_char_params.write_access = SEC_NO_ACCESS;
+
+ return characteristic_add(p_cgms->service_handle,
+ &add_char_params,
+ &p_cgms->char_handles.status);
+}
+
+
+/**@brief Function for adding a characteristic for the Session Run Time.
+ *
+ * @param[in] p_cgms Service instance.
+ *
+ * @return NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
+ */
+static uint32_t srt_char_add(nrf_ble_cgms_t * p_cgms)
+{
+ uint8_t len = 0;
+ uint8_t encoded_initial_srt[NRF_BLE_CGMS_SRT_LEN];
+ ble_add_char_params_t add_char_params;
+
+ memset(&add_char_params, 0, sizeof(add_char_params));
+
+
+ len += uint16_encode(p_cgms->session_run_time, &(encoded_initial_srt[len]));
+
+ add_char_params.uuid = BLE_UUID_CGM_SESSION_RUN_TIME;
+ add_char_params.max_len = NRF_BLE_CGMS_SRT_LEN;
+ add_char_params.init_len = len;
+ add_char_params.p_init_value = encoded_initial_srt;
+ add_char_params.read_access = SEC_JUST_WORKS;
+ add_char_params.write_access = SEC_NO_ACCESS;
+ add_char_params.char_props.read = true;
+
+ return characteristic_add(p_cgms->service_handle,
+ &add_char_params,
+ &p_cgms->char_handles.srt);
+}
+
+
+uint8_t init_calib_val[] = {
+ 0x3E,
+ 0x00,
+ 0x07,
+ 0x00,
+ 0x06,
+ 0x07,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+};
+ret_code_t nrf_ble_cgms_init(nrf_ble_cgms_t * p_cgms, const nrf_ble_cgms_init_t * p_cgms_init)
+{
+ VERIFY_PARAM_NOT_NULL(p_cgms);
+ VERIFY_PARAM_NOT_NULL(p_cgms_init);
+ VERIFY_PARAM_NOT_NULL(p_cgms_init->evt_handler);
+
+ uint32_t err_code;
+ ble_uuid_t ble_uuid;
+
+ // Initialize data base
+ err_code = cgms_db_init();
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ err_code = next_sequence_number_set();
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ // Initialize service structure
+ p_cgms->evt_handler = p_cgms_init->evt_handler;
+ p_cgms->error_handler = p_cgms_init->error_handler;
+ p_cgms->feature = p_cgms_init->feature;
+ p_cgms->sensor_status = p_cgms_init->initial_sensor_status;
+ p_cgms->session_run_time = p_cgms_init->initial_run_time;
+ p_cgms->is_session_started = false;
+ p_cgms->nb_run_session = 0;
+ p_cgms->conn_handle = BLE_CONN_HANDLE_INVALID;
+
+ p_cgms->feature.feature = 0;
+ p_cgms->feature.feature |= NRF_BLE_CGMS_FEAT_MULTIPLE_BOND_SUPPORTED;
+ p_cgms->feature.feature |= NRF_BLE_CGMS_FEAT_MULTIPLE_SESSIONS_SUPPORTED;
+ p_cgms->feature.type = NRF_BLE_CGMS_MEAS_TYPE_VEN_BLOOD;
+ p_cgms->feature.sample_location = NRF_BLE_CGMS_MEAS_LOC_AST;
+ p_cgms->feature.feature |= NRF_BLE_CGMS_FEAT_MULTIPLE_BOND_SUPPORTED;
+
+ memcpy(p_cgms->calibration_val[0].value, init_calib_val, NRF_BLE_CGMS_MAX_CALIB_LEN);
+
+ // Initialize global variables
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ p_cgms->racp_data.racp_proc_records_reported_since_txcomplete = 0;
+
+ // Add service
+ BLE_UUID_BLE_ASSIGN(ble_uuid, BLE_UUID_CGM_SERVICE);
+
+ err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
+ &ble_uuid,
+ &p_cgms->service_handle);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ // Add glucose measurement characteristic
+ err_code = cgms_meas_char_add(p_cgms);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ // Add glucose measurement feature characteristic
+ err_code = glucose_feature_char_add(p_cgms);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ // Add glucose measurement status characteristic
+ err_code = status_char_add(p_cgms);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ // Add record control access point characteristic
+ err_code = cgms_racp_char_add(p_cgms);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ // Add Start Session Time characteristic
+ err_code = cgms_sst_char_add(p_cgms);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ // Add Session Run Time characteristic
+ err_code = srt_char_add(p_cgms);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ // Add Specific Operations Control Point characteristic
+ err_code = cgms_socp_char_add(p_cgms);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ return NRF_SUCCESS;
+}
+
+
+/**@brief Function for handling the WRITE event.
+ *
+ * @details Handles WRITE events from the BLE stack.
+ *
+ * @param[in] p_cgms Glucose Service structure.
+ * @param[in] p_ble_evt Event received from the BLE stack.
+ */
+static void on_write(nrf_ble_cgms_t * p_cgms, ble_evt_t const * p_ble_evt)
+{
+ ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
+
+ cgms_meas_on_write(p_cgms, p_evt_write);
+}
+
+
+/**@brief Function for handling the TX_COMPLETE event.
+ *
+ * @details Handles TX_COMPLETE events from the BLE stack.
+ *
+ * @param[in] p_cgms Glucose Service structure.
+ * @param[in] p_ble_evt Event received from the BLE stack.
+ */
+static void on_tx_complete(nrf_ble_cgms_t * p_cgms, ble_evt_t const * p_ble_evt)
+{
+ p_cgms->racp_data.racp_proc_records_reported_since_txcomplete = 0;
+
+ cgms_racp_on_tx_complete(p_cgms);
+ cgms_socp_on_tx_complete(p_cgms);
+}
+
+
+/**@brief Function for handling the HVC event.
+ *
+ * @details Handles HVC events from the BLE stack.
+ *
+ * @param[in] p_cgms Glucose Service structure.
+ * @param[in] p_ble_evt Event received from the BLE stack.
+ */
+static void on_hvc(nrf_ble_cgms_t * p_cgms, ble_evt_t const * p_ble_evt)
+{
+ ble_gatts_evt_hvc_t const * p_hvc = &p_ble_evt->evt.gatts_evt.params.hvc;
+
+ if (p_hvc->handle == p_cgms->char_handles.racp.value_handle)
+ {
+ if (p_cgms->cgms_com_state == STATE_RACP_RESPONSE_IND_VERIF)
+ {
+ // Indication has been acknowledged. Return to default state.
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ }
+ else
+ {
+ // We did not expect this event in this state. Report error to application.
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(NRF_ERROR_INVALID_STATE);
+ }
+ }
+ }
+ if (p_hvc->handle == p_cgms->char_handles.socp.value_handle)
+ {
+ if (p_cgms->cgms_com_state == STATE_SOCP_RESPONSE_IND_VERIF)
+ {
+ // Indication has been acknowledged. Return to default state.
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ }
+ else
+ {
+ // We did not expect this event in this state. Report error to application.
+ if (p_cgms->error_handler != NULL)
+ {
+ p_cgms->error_handler(NRF_ERROR_INVALID_STATE);
+ }
+ }
+ }
+}
+
+
+static void on_rw_authorize_request(nrf_ble_cgms_t * p_cgms, ble_gatts_evt_t const * p_gatts_evt)
+{
+ ble_gatts_evt_rw_authorize_request_t const * p_auth_req =
+ &p_gatts_evt->params.authorize_request;
+
+ cgms_racp_on_rw_auth_req(p_cgms, p_auth_req);
+ cgms_socp_on_rw_auth_req(p_cgms, p_auth_req);
+ cgms_sst_on_rw_auth_req(p_cgms, p_auth_req);
+}
+
+
+void nrf_ble_cgms_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
+{
+ nrf_ble_cgms_t * p_cgms = (nrf_ble_cgms_t *)p_context;
+
+ switch (p_ble_evt->header.evt_id)
+ {
+ case BLE_GAP_EVT_CONNECTED:
+ p_cgms->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
+ p_cgms->cgms_com_state = STATE_NO_COMM;
+ break;
+
+ case BLE_GAP_EVT_DISCONNECTED:
+ p_cgms->conn_handle = BLE_CONN_HANDLE_INVALID;
+ break;
+
+ case BLE_GATTS_EVT_WRITE:
+ on_write(p_cgms, p_ble_evt);
+ break;
+
+ case BLE_GATTS_EVT_HVN_TX_COMPLETE:
+ on_tx_complete(p_cgms, p_ble_evt);
+ break;
+
+ case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
+ on_rw_authorize_request(p_cgms, &p_ble_evt->evt.gatts_evt);
+ break;
+
+ case BLE_GATTS_EVT_HVC:
+ on_hvc(p_cgms, p_ble_evt);
+ break;
+
+ default:
+ // No implementation needed.
+ break;
+ }
+}
+
+
+ret_code_t nrf_ble_cgms_meas_create(nrf_ble_cgms_t * p_cgms, ble_cgms_rec_t * p_rec)
+{
+ uint32_t err_code = NRF_SUCCESS;
+ uint8_t nb_rec_to_send = 1;
+
+ err_code = cgms_db_record_add(p_rec);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ if ((p_cgms->conn_handle != BLE_CONN_HANDLE_INVALID) && (p_cgms->comm_interval != 0))
+ {
+ err_code = cgms_meas_send(p_cgms, p_rec, &nb_rec_to_send);
+ }
+ return err_code;
+}
+
+
+ret_code_t nrf_ble_cgms_update_status(nrf_ble_cgms_t * p_cgms, nrf_ble_cgm_status_t * p_status)
+{
+ uint8_t encoded_status[NRF_BLE_CGMS_STATUS_LEN];
+ ble_gatts_value_t status_val;
+
+ memset(&status_val, 0, sizeof(status_val));
+ p_cgms->sensor_status = *p_status;
+ status_val.len = encode_status(encoded_status, p_cgms);
+ status_val.p_value = encoded_status;
+ status_val.offset = 0;
+
+ return (sd_ble_gatts_value_set(p_cgms->conn_handle, p_cgms->char_handles.status.value_handle,
+ &status_val));
+}
+
+
+ret_code_t nrf_ble_cgms_conn_handle_assign(nrf_ble_cgms_t * p_cgms, uint16_t conn_handle)
+{
+ VERIFY_PARAM_NOT_NULL(p_cgms);
+ p_cgms->conn_handle = conn_handle;
+ return NRF_SUCCESS;
+}
+
+
+ret_code_t nrf_ble_cgms_srt_set(nrf_ble_cgms_t * p_cgms, uint16_t run_time)
+{
+ ble_gatts_value_t srt_val;
+ uint8_t encoded_session_run_time[NRF_BLE_CGMS_SRT_LEN];
+ uint8_t gatts_value_set_len = 0;
+
+ gatts_value_set_len = uint16_encode(run_time, encoded_session_run_time); // (p_sst, encoded_start_session_time);
+
+ memset(&srt_val, 0, sizeof(ble_gatts_value_t));
+ srt_val.len = gatts_value_set_len;
+ srt_val.p_value = encoded_session_run_time;
+ srt_val.offset = 0;
+
+ return (sd_ble_gatts_value_set(p_cgms->conn_handle, p_cgms->char_handles.srt.value_handle,
+ &srt_val));
+}
+
+
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/nrf_ble_cgms.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/nrf_ble_cgms.h
new file mode 100644
index 0000000..dbac766
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/ble/ble_services/experimental_nrf_ble_cgms/nrf_ble_cgms.h
@@ -0,0 +1,453 @@
+/**
+ * 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.
+ *
+ */
+/** @file
+ *
+ * @defgroup ble_cgms Continuous Glucose Monitoring Service
+ * @{
+ * @ingroup ble_sdk_srv
+ * @brief Continuous Glucose Monitoring Service (CGMS) module.
+ *
+ * @details This module implements a sensor for the Continuous Glucose Monitoring Service.
+ * The sensor is a GATT Server that sends CGM measurements to a connected CGMS
+ * Collector. The CGMS Sensor stores records that can be accessed with the
+ * Record Access Control Point (RACP). The collector can access the features and status
+ * of the sensor. Session Run Time and Session Start Time can be used to convey timing
+ * information between the sensor and the collector. The Specific Operations Control Point
+ * is used to stop and start monitoring sessions, among other things.
+ *
+ * @note The application must register this module as BLE event observer using the
+ * NRF_SDH_BLE_OBSERVER macro. Example:
+ * @code
+ * nrf_ble_cgms_t instance;
+ * NRF_SDH_BLE_OBSERVER(anything, NRF_BLE_CGMS_BLE_OBSERVER_PRIO,
+ * nrf_ble_cgms_on_ble_evt, &instance);
+ * @endcode
+ */
+
+#ifndef NRF_BLE_CGMS_H__
+#define NRF_BLE_CGMS_H__
+
+#include "ble_srv_common.h"
+#include "sdk_errors.h"
+#include "ble_racp.h"
+#include "nrf_sdh_ble.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@brief Macro for defining a nrf_ble_cgms instance.
+ *
+ * @param _name Name of the instance.
+ * @hideinitializer
+ */
+#define NRF_BLE_CGMS_DEF(_name) \
+static nrf_ble_cgms_t _name; \
+NRF_SDH_BLE_OBSERVER(_name ## _obs, \
+ NRF_BLE_CGMS_BLE_OBSERVER_PRIO, \
+ nrf_ble_cgms_on_ble_evt, &_name)
+
+/**@name CGM Feature characteristic defines
+ * @{ */
+#define NRF_BLE_CGMS_FEAT_CALIBRATION_SUPPORTED (0x01 << 0) //!< Calibration supported.
+#define NRF_BLE_CGMS_FEAT_PATIENT_HIGH_LOW_ALERTS_SUPPORTED (0x01 << 1) //!< Patient High/Low Alerts supported.
+#define NRF_BLE_CGMS_FEAT_HYPO_ALERTS_SUPPORTED (0x01 << 2) //!< Hypo Alerts supported.
+#define NRF_BLE_CGMS_FEAT_HYPER_ALERTS_SUPPORTED (0x01 << 3) //!< Hyper Alerts supported.
+#define NRF_BLE_CGMS_FEAT_RATE_OF_INCREASE_DECREASE_ALERTS_SUPPORTED (0x01 << 4) //!< Rate of Increase/Decrease Alerts supported.
+#define NRF_BLE_CGMS_FEAT_DEVICE_SPECIFIC_ALERT_SUPPORTED (0x01 << 5) //!< Device Specific Alert supported.
+#define NRF_BLE_CGMS_FEAT_SENSOR_MALFUNCTION_DETECTION_SUPPORTED (0x01 << 6) //!< Sensor Malfunction Detection supported.
+#define NRF_BLE_CGMS_FEAT_SENSOR_TEMPERATURE_HIGH_LOW_DETECTION_SUPPORTED (0x01 << 7) //!< Sensor Temperature High-Low Detection supported.
+#define NRF_BLE_CGMS_FEAT_SENSOR_RESULT_HIGH_LOW_DETECTION_SUPPORTED (0x01 << 8) //!< Sensor Result High-Low Detection supported.
+#define NRF_BLE_CGMS_FEAT_LOW_BATTERY_DETECTION_SUPPORTED (0x01 << 9) //!< Low Battery Detection supported.
+#define NRF_BLE_CGMS_FEAT_SENSOR_TYPE_ERROR_DETECTION_SUPPORTED (0x01 << 10) //!< Sensor Type Error Detection supported.
+#define NRF_BLE_CGMS_FEAT_GENERAL_DEVICE_FAULT_SUPPORTED (0x01 << 11) //!< General Device Fault supported.
+#define NRF_BLE_CGMS_FEAT_E2E_CRC_SUPPORTED (0x01 << 12) //!< E2E-CRC supported.
+#define NRF_BLE_CGMS_FEAT_MULTIPLE_BOND_SUPPORTED (0x01 << 13) //!< Multiple Bond supported.
+#define NRF_BLE_CGMS_FEAT_MULTIPLE_SESSIONS_SUPPORTED (0x01 << 14) //!< Multiple Sessions supported.
+#define NRF_BLE_CGMS_FEAT_CGM_TREND_INFORMATION_SUPPORTED (0x01 << 15) //!< CGM Trend Information supported.
+#define NRF_BLE_CGMS_FEAT_CGM_QUALITY_SUPPORTED (0x01 << 16) //!< CGM Quality supported.
+/** @} */
+
+/**@name Continuous Glucose Monitoring type
+ * @{ */
+#define NRF_BLE_CGMS_MEAS_TYPE_CAP_BLOOD 0x01 //!< Capillary Whole blood.
+#define NRF_BLE_CGMS_MEAS_TYPE_CAP_PLASMA 0x02 //!< Capillary Plasma.
+#define NRF_BLE_CGMS_MEAS_TYPE_VEN_BLOOD 0x03 //!< Venous Whole blood.
+#define NRF_BLE_CGMS_MEAS_TYPE_VEN_PLASMA 0x04 //!< Venous Plasma.
+#define NRF_BLE_CGMS_MEAS_TYPE_ART_BLOOD 0x05 //!< Arterial Whole blood.
+#define NRF_BLE_CGMS_MEAS_TYPE_ART_PLASMA 0x06 //!< Arterial Plasma.
+#define NRF_BLE_CGMS_MEAS_TYPE_UNDET_BLOOD 0x07 //!< Undetermined Whole blood.
+#define NRF_BLE_CGMS_MEAS_TYPE_UNDET_PLASMA 0x08 //!< Undetermined Plasma.
+#define NRF_BLE_CGMS_MEAS_TYPE_FLUID 0x09 //!< Interstitial Fluid (ISF).
+#define NRF_BLE_CGMS_MEAS_TYPE_CONTROL 0x0A //!< Control Solution.
+/** @} */
+
+/**@name CGM sample location
+ * @{ */
+#define NRF_BLE_CGMS_MEAS_LOC_FINGER 0x01 //!< Finger.
+#define NRF_BLE_CGMS_MEAS_LOC_AST 0x02 //!< Alternate Site Test (AST).
+#define NRF_BLE_CGMS_MEAS_LOC_EAR 0x03 //!< Earlobe.
+#define NRF_BLE_CGMS_MEAS_LOC_CONTROL 0x04 //!< Control solution.
+#define NRF_BLE_CGMS_MEAS_LOC_SUB_TISSUE 0x05 //!< Subcutaneous tissue.
+#define NRF_BLE_CGMS_MEAS_LOC_NOT_AVAIL 0x0F //!< Sample Location value not available.
+/** @} */
+
+/**@name CGM Measurement Sensor Status Annunciation
+ * @{ */
+#define NRF_BLE_CGMS_STATUS_SESSION_STOPPED (0x01 << 0) //!< Status: Session Stopped.
+#define NRF_BLE_CGMS_STATUS_DEVICE_BATTERY_LOW (0x01 << 1) //!< Status: Device Battery Low.
+#define NRF_BLE_CGMS_STATUS_SENSOR_TYPE_INCORRECT_FOR_DEVICE (0x01 << 2) //!< Status: Sensor type incorrect for device.
+#define NRF_BLE_CGMS_STATUS_SENSOR_MALFUNCTION (0x01 << 3) //!< Status: Sensor malfunction.
+#define NRF_BLE_CGMS_STATUS_DEVICE_SPECIFIC_ALERT (0x01 << 4) //!< Status: Device Specific Alert.
+#define NRF_BLE_CGMS_STATUS_GENERAL_DEVICE_FAULT (0x01 << 5) //!< Status: General device fault has occurred in the sensor.
+/** @} */
+
+/**@name CGM Measurement flags
+ * @{ */
+#define NRF_BLE_CGMS_FLAG_TREND_INFO_PRESENT 0x01 //!< CGM Trend Information Present.
+#define NRF_BLE_CGMS_FLAGS_QUALITY_PRESENT 0x02 //!< CGM Quality Present.
+#define NRF_BLE_CGMS_STATUS_FLAGS_WARNING_OCT_PRESENT 0x20 //!< Sensor Status Annunciation Field, Warning-Octet present.
+#define NRF_BLE_CGMS_STATUS_FLAGS_CALTEMP_OCT_PRESENT 0x40 //!< Sensor Status Annunciation Field, Cal/Temp-Octet present.
+#define NRF_BLE_CGMS_STATUS_FLAGS_STATUS_OCT_PRESENT 0x80 //!< Sensor Status Annunciation Field, Status-Octet present.
+/** @} */
+
+/**@name Byte length of various commands (used for validating, encoding, and decoding data).
+ * @{ */
+#define NRF_BLE_CGMS_MEAS_OP_LEN 1 //!< Length of the opcode inside the Glucose Measurement packet.
+#define NRF_BLE_CGMS_MEAS_HANDLE_LEN 2 //!< Length of the handle inside the Glucose Measurement packet.
+#define NRF_BLE_CGMS_MEAS_LEN_MAX (BLE_GATT_ATT_MTU_DEFAULT - \
+ NRF_BLE_CGMS_MEAS_OP_LEN - \
+ NRF_BLE_CGMS_MEAS_HANDLE_LEN) //!< Maximum size of a transmitted Glucose Measurement.
+
+#define NRF_BLE_CGMS_MEAS_REC_LEN_MAX 15 //!< Maximum length of one measurement record. Size 1 byte, flags 1 byte, glucose concentration 2 bytes, offset 2 bytes, status 3 bytes, trend 2 bytes, quality 2 bytes, CRC 2 bytes.
+#define NRF_BLE_CGMS_MEAS_REC_LEN_MIN 6 //!< Minimum length of one measurement record. Size 1 byte, flags 1 byte, glucose concentration 2 bytes, offset 2 bytes.
+#define NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX (NRF_BLE_CGMS_MEAS_LEN_MAX / \
+ NRF_BLE_CGMS_MEAS_REC_LEN_MIN) //!< Maximum number of records per notification. We can send more than one measurement record per notification, but we do not want a a single record split over two notifications.
+
+#define NRF_BLE_CGMS_SOCP_RESP_CODE_LEN 2 //!< Length of a response. Response code 1 byte, response value 1 byte.
+#define NRF_BLE_CGMS_FEATURE_LEN 6 //!< Length of a feature. Feature 3 bytes, type 4 bits, sample location 4 bits, CRC 2 bytes.
+#define NRF_BLE_CGMS_STATUS_LEN 7 //!< Length of a status. Offset 2 bytes, status 3 bytes, CRC 2 bytes.
+#define NRF_BLE_CGMS_MAX_CALIB_LEN 10 //!< Length of a calibration record. Concentration 2 bytes, time 2 bytes, calibration 4 bits, calibration sample location 4 bits, next calibration time 2 bytes, record number 2 bytes, calibration status 1 byte.
+#define NRF_BLE_CGMS_CALIBS_NB_MAX 5 //!< Maximum number of calibration values that can be stored.
+#define NRF_BLE_CGMS_SST_LEN 9 //!< Length of the start time. Date time 7 bytes, time zone 1 byte, DST 1 byte.
+#define NRF_BLE_CGMS_CRC_LEN 2 //!< Length of the CRC bytes (if used).
+#define NRF_BLE_CGMS_SRT_LEN 2 //!< Length of the Session Run Time attribute.
+
+#define NRF_BLE_CGMS_SOCP_RESP_LEN (NRF_BLE_CGMS_MEAS_LEN_MAX - \
+ NRF_BLE_CGMS_SOCP_RESP_CODE_LEN) //!< Max lenth of a SOCP response.
+
+#define NRF_BLE_CGMS_RACP_PENDING_OPERANDS_MAX 2 // !< Maximum number of pending Record Access Control Point operations.
+/** @} */
+
+/**
+ * @defgroup nrf_ble_cgms_enums Enumerations
+ * @{
+ */
+
+/**@brief CGM Service events. */
+typedef enum
+{
+ NRF_BLE_CGMS_EVT_NOTIFICATION_ENABLED, /**< Glucose value notification enabled. */
+ NRF_BLE_CGMS_EVT_NOTIFICATION_DISABLED, /**< Glucose value notification disabled. */
+ NRF_BLE_CGMS_EVT_START_SESSION, /**< Glucose value notification start session. */
+ NRF_BLE_CGMS_EVT_STOP_SESSION, /**< Glucose value notification stop session. */
+ NRF_BLE_CGMS_EVT_WRITE_COMM_INTERVAL, /**< Glucose value write communication interval. */
+} nrf_ble_cgms_evt_type_t;
+
+
+/**@brief CGM Service communication states. */
+typedef enum
+{
+ STATE_NO_COMM, /**< The service is not in a communicating state. */
+ STATE_RACP_PROC_ACTIVE, /**< Processing requested data. */
+ STATE_RACP_RESPONSE_PENDING, /**< There is an RACP indication waiting to be sent. */
+ STATE_RACP_RESPONSE_IND_VERIF, /**< Waiting for a verification of an RACP indication. */
+ STATE_SOCP_RESPONSE_PENDING, /**< There is an SOCP indication waiting to be sent. */
+ STATE_SOCP_RESPONSE_IND_VERIF /**< Waiting for a verification of an SOCP indication. */
+} nrf_ble_cgms_com_state_t;
+
+/** @} */ // End tag for Enumeration group.
+
+/**
+ * @defgroup nrf_ble_cgms_structs Structures
+ * @{
+ */
+
+/**@brief CGM Service event. */
+typedef struct
+{
+ nrf_ble_cgms_evt_type_t evt_type; /**< Type of event. */
+} nrf_ble_cgms_evt_t;
+
+/** @} */ // End tag for Structure group.
+
+/**
+ * @defgroup nrf_ble_cgms_types Types
+ * @{
+ */
+
+/**@brief Forward declaration of the nrf_ble_cgms_t type. */
+typedef struct ble_cgms_s nrf_ble_cgms_t;
+
+
+/**@brief CGM Service event handler type. */
+typedef void (* ble_cgms_evt_handler_t) (nrf_ble_cgms_t * p_cgms, nrf_ble_cgms_evt_t * p_evt);
+
+/** @} */ // End tag for Types group.
+
+/**
+ * @addtogroup nrf_ble_cgms_structs
+ * @{
+ */
+
+/**@brief CGM Measurement Sensor Status Annunciation. */
+typedef struct
+{
+ uint8_t warning; /**< Warning annunciation. */
+ uint8_t calib_temp; /**< Calibration and Temperature annunciation. */
+ uint8_t status; /**< Status annunciation. */
+} nrf_ble_cgms_sensor_annunc_t;
+
+
+/**@brief CGM measurement. */
+typedef struct
+{
+ uint8_t flags; /**< Indicates the presence of optional fields and the Sensor Status Annunciation field. */
+ uint16_t glucose_concentration; /**< Glucose concentration. 16-bit word comprising 4-bit exponent and signed 12-bit mantissa. */
+ uint16_t time_offset; /**< Time offset. Represents the time difference between measurements. */
+ nrf_ble_cgms_sensor_annunc_t sensor_status_annunciation; /**< Sensor Status Annunciation. Variable length, can include Status, Cal/Temp, and Warning. */
+ uint16_t trend; /**< Optional field that can include Trend Information. */
+ uint16_t quality; /**< Optional field that includes the Quality of the measurement. */
+} nrf_ble_cgms_meas_t;
+
+
+/**@brief CGM Measurement record. */
+typedef struct
+{
+ nrf_ble_cgms_meas_t meas; /**< CGM measurement. */
+} ble_cgms_rec_t;
+
+
+/**@brief Features supported by the CGM Service. */
+typedef struct
+{
+ uint32_t feature; /**< Information on supported features in the CGM Service. */
+ uint8_t type; /**< Type. */
+ uint8_t sample_location; /**< Sample location. */
+}nrf_ble_cgms_feature_t;
+
+
+/**@brief Status of the CGM measurement. */
+typedef struct
+{
+ uint16_t time_offset; /**< Time offset. */
+ nrf_ble_cgms_sensor_annunc_t status; /**< Status. */
+} nrf_ble_cgm_status_t;
+
+
+/**@brief CGM Service initialization structure that contains all options and data needed for
+ * initializing the service. */
+typedef struct
+{
+ ble_cgms_evt_handler_t evt_handler; /**< Event handler to be called for handling events in the CGM Service. */
+ ble_srv_error_handler_t error_handler; /**< Function to be called when an error occurs. */
+ nrf_ble_cgms_feature_t feature; /**< Features supported by the service. */
+ nrf_ble_cgm_status_t initial_sensor_status; /**< Sensor status. */
+ uint16_t initial_run_time; /**< Run time. */
+} nrf_ble_cgms_init_t;
+
+
+/**@brief Specific Operation Control Point response structure. */
+typedef struct
+{
+ uint8_t opcode; /**< Opcode describing the response. */
+ uint8_t req_opcode; /**< The original opcode for the request to which this response belongs. */
+ uint8_t rsp_code; /**< Response code. */
+ uint8_t resp_val[NRF_BLE_CGMS_SOCP_RESP_LEN]; /**< Array containing the response value. */
+ uint8_t size_val; /**< Length of the response value. */
+} ble_socp_rsp_t;
+
+
+/**@brief Calibration value. */
+typedef struct
+{
+ uint8_t value[NRF_BLE_CGMS_MAX_CALIB_LEN]; /**< Array containing the calibration value. */
+} nrf_ble_cgms_calib_t;
+
+
+/**@brief Record Access Control Point transaction data. */
+typedef struct
+{
+ uint8_t racp_proc_operator; /**< Operator of the current request. */
+ uint16_t racp_proc_record_ndx; /**< Current record index. */
+ uint16_t racp_proc_records_ndx_last_to_send; /**< The last record to send, can be used together with racp_proc_record_ndx to determine a range of records to send. (used by greater/less filters). */
+ uint16_t racp_proc_records_reported; /**< Number of reported records. */
+ uint16_t racp_proc_records_reported_since_txcomplete; /**< Number of reported records since the last TX_COMPLETE event. */
+ ble_racp_value_t racp_request; /**< RACP procedure that has been requested from the peer. */
+ ble_racp_value_t pending_racp_response; /**< RACP response to be sent. */
+ uint8_t pending_racp_response_operand[NRF_BLE_CGMS_RACP_PENDING_OPERANDS_MAX]; /**< Operand of the RACP response to be sent. */
+} nrf_ble_cgms_racp_t;
+
+
+/** @brief Handles related to CGM characteristics. */
+typedef struct
+{
+ ble_gatts_char_handles_t measurment; /**< Handles related to the CGM Measurement characteristic. */
+ ble_gatts_char_handles_t feature; /**< Handles related to the CGM Feature characteristic. */
+ ble_gatts_char_handles_t sst; /**< Handles related to the CGM Session Start Time characteristic. */
+ ble_gatts_char_handles_t racp; /**< Handles related to the CGM Record Access Control Point characteristic. */
+ ble_gatts_char_handles_t srt; /**< Handles related to the CGM Session Run Time characteristic. */
+ ble_gatts_char_handles_t socp; /**< Handles related to the CGM Specific Operations Control Point characteristic. */
+ ble_gatts_char_handles_t status; /**< Handles related to the CGM Status characteristic. */
+} nrf_ble_cgms_char_handler_t;
+
+
+/**@brief Status information for the CGM Service. */
+struct ble_cgms_s
+{
+ ble_cgms_evt_handler_t evt_handler; /**< Event handler to be called for handling events in the CGM Service. */
+ ble_srv_error_handler_t error_handler; /**< Function to be called if an error occurs. */
+ uint16_t service_handle; /**< Handle of the CGM Service (as provided by the BLE stack). */
+ nrf_ble_cgms_char_handler_t char_handles; /**< GATTS characteristic handles for the different characteristics in the service. */
+ uint16_t conn_handle; /**< Handle of the current connection (as provided by the BLE stack; @ref BLE_CONN_HANDLE_INVALID if not in a connection). */
+ nrf_ble_cgms_feature_t feature; /**< Structure to store the value of the feature characteristic. */
+ uint8_t comm_interval; /**< Variable to keep track of the communication interval. */
+ ble_socp_rsp_t socp_response; /**< Structure containing reponse data to be indicated to the peer device. */
+ nrf_ble_cgms_calib_t calibration_val[NRF_BLE_CGMS_CALIBS_NB_MAX]; /**< Calibration value. Can be read from and written to SOCP. */
+ bool is_session_started; /**< Indicator if we are currently in a session. */
+ uint8_t nb_run_session; /**< Variable to keep track of the number of sessions that were run. */
+ uint16_t session_run_time; /**< Variable to store the expected run time of a session. */
+ nrf_ble_cgm_status_t sensor_status; /**< Structure to keep track of the sensor status. */
+ nrf_ble_cgms_com_state_t cgms_com_state; /**< Current communication state. */
+ nrf_ble_cgms_racp_t racp_data; /**< Structure to manage Record Access requests. */
+};
+
+/** @} */
+
+
+/**
+ * @defgroup nrf_ble_cgms_functions Functions
+ * @{
+ */
+
+/**@brief Function for updating the status.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ * @param[in] p_status New status.
+ *
+ * @retval NRF_SUCCESS If the status was updated successfully.
+ * @return If functions from other modules return errors to this function,
+ * the @ref nrf_error are propagated.
+ */
+ret_code_t nrf_ble_cgms_update_status(nrf_ble_cgms_t * p_cgms, nrf_ble_cgm_status_t * p_status);
+
+
+/**@brief Function for initializing the CGM Service.
+ *
+ * @param[out] p_cgms CGM Service structure. This structure must be supplied by
+ * the application. It is initialized by this function and will later
+ * be used to identify this particular service instance.
+ * @param[in] p_cgms_init Information needed to initialize the service.
+ *
+ * @retval NRF_SUCCESS If the service was initialized successfully.
+ * @retval NRF_ERROR_NULL If any of the input parameters are NULL.
+ * @return If functions from other modules return errors to this function,
+ * the @ref nrf_error are propagated.
+ */
+ret_code_t nrf_ble_cgms_init(nrf_ble_cgms_t * p_cgms, const nrf_ble_cgms_init_t * p_cgms_init);
+
+
+/**@brief Function for handling the application's BLE stack events.
+ *
+ * @details Handles all events from the BLE stack that are of interest to the CGM Service.
+ *
+ * @param[in] p_ble_evt Event received from the BLE stack.
+ * @param[in] p_context Instance of the CGM Service.
+ */
+void nrf_ble_cgms_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context);
+
+
+/**@brief Function for reporting a new glucose measurement to the CGM Service module.
+ *
+ * @details The application calls this function after having performed a new glucose measurement.
+ * The new measurement is recorded in the RACP database.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ * @param[in] p_rec Pointer to the glucose record (measurement plus context).
+ *
+ * @retval NRF_SUCCESS If a measurement was successfully created.
+ * @return If functions from other modules return errors to this function,
+ * the @ref nrf_error are propagated.
+ */
+ret_code_t nrf_ble_cgms_meas_create(nrf_ble_cgms_t * p_cgms, ble_cgms_rec_t * p_rec);
+
+
+/**@brief Function for assigning a connection handle to a CGM Service instance.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ * @param[in] conn_handle Connection Handle to use for this instance of the CGM Service.
+ *
+ * @retval NRF_SUCCESS If the connection handle was successfully stored in the CGM Service instance.
+ * @retval NRF_ERROR_NULL If any of the input parameters are NULL.
+ */
+ret_code_t nrf_ble_cgms_conn_handle_assign(nrf_ble_cgms_t * p_cgms, uint16_t conn_handle);
+
+
+/**@brief Function for setting the Session Run Time attribute value.
+ *
+ * @param[in] p_cgms Instance of the CGM Service.
+ * @param[in] run_time Run Time that will be displayed in the Session Run Time
+ * attribute value.
+ *
+ * @retval NRF_SUCCESS If the Session Run Time attribute value was set successfully.
+ * @return If functions from other modules return errors to this function,
+ * the @ref nrf_error are propagated.
+ */
+ret_code_t nrf_ble_cgms_srt_set(nrf_ble_cgms_t * p_cgms, uint16_t run_time);
+
+/** @} */ // End tag for Function group.
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NRF_BLE_CGMS_H__
+
+/** @} */