| 1 | /** |
1 | /** |
| 2 | * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA |
2 | * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA |
| 3 | * |
3 | * |
| 4 | * All rights reserved. |
4 | * All rights reserved. |
| 5 | * |
5 | * |
| 6 | * Redistribution and use in source and binary forms, with or without modification, |
6 | * Redistribution and use in source and binary forms, with or without modification, |
| 7 | * are permitted provided that the following conditions are met: |
7 | * are permitted provided that the following conditions are met: |
| 8 | * |
8 | * |
| 9 | * 1. Redistributions of source code must retain the above copyright notice, this |
9 | * 1. Redistributions of source code must retain the above copyright notice, this |
| 10 | * list of conditions and the following disclaimer. |
10 | * list of conditions and the following disclaimer. |
| 11 | * |
11 | * |
| 12 | * 2. Redistributions in binary form, except as embedded into a Nordic |
12 | * 2. Redistributions in binary form, except as embedded into a Nordic |
| 13 | * Semiconductor ASA integrated circuit in a product or a software update for |
13 | * Semiconductor ASA integrated circuit in a product or a software update for |
| 14 | * such product, must reproduce the above copyright notice, this list of |
14 | * such product, must reproduce the above copyright notice, this list of |
| 15 | * conditions and the following disclaimer in the documentation and/or other |
15 | * conditions and the following disclaimer in the documentation and/or other |
| 16 | * materials provided with the distribution. |
16 | * materials provided with the distribution. |
| 17 | * |
17 | * |
| 18 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of its |
18 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of its |
| 19 | * contributors may be used to endorse or promote products derived from this |
19 | * contributors may be used to endorse or promote products derived from this |
| 20 | * software without specific prior written permission. |
20 | * software without specific prior written permission. |
| 21 | * |
21 | * |
| 22 | * 4. This software, with or without modification, must only be used with a |
22 | * 4. This software, with or without modification, must only be used with a |
| 23 | * Nordic Semiconductor ASA integrated circuit. |
23 | * Nordic Semiconductor ASA integrated circuit. |
| 24 | * |
24 | * |
| 25 | * 5. Any software provided in binary form under this license must not be reverse |
25 | * 5. Any software provided in binary form under this license must not be reverse |
| 26 | * engineered, decompiled, modified and/or disassembled. |
26 | * engineered, decompiled, modified and/or disassembled. |
| 27 | * |
27 | * |
| 28 | * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS |
28 | * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS |
| 29 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
29 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| 30 | * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE |
30 | * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 31 | * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE |
31 | * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE |
| 32 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
32 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 33 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
33 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| 34 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
34 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| 37 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
37 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 38 | * |
38 | * |
| 39 | */ |
39 | */ |
| 40 | /** @file |
40 | /** @file |
| 41 | * |
41 | * |
| 42 | * @defgroup ble_sdk_app_gls_main main.c |
42 | * @defgroup ble_sdk_app_gls_main main.c |
| 43 | * @{ |
43 | * @{ |
| 44 | * @ingroup ble_sdk_app_gls |
44 | * @ingroup ble_sdk_app_gls |
| 45 | * @brief Glucose Meter service Sample Application |
45 | * @brief Glucose Meter service Sample Application |
| 46 | * |
46 | * |
| 47 | * This file contains the source code for a sample application using the Glucose Meter service |
47 | * This file contains the source code for a sample application using the Glucose Meter service |
| 48 | * (and also Battery and Device Information services). This application uses the |
48 | * (and also Battery and Device Information services). This application uses the |
| 49 | * @ref srvlib_conn_params module. |
49 | * @ref srvlib_conn_params module. |
| 50 | */ |
50 | */ |
| 51 | |
51 | |
| 52 | #include <stdint.h> |
52 | #include <stdint.h> |
| 53 | #include <string.h> |
53 | #include <string.h> |
| 54 | #include "nordic_common.h" |
54 | #include "nordic_common.h" |
| 55 | #include "nrf.h" |
55 | #include "nrf.h" |
| 56 | #include "app_error.h" |
56 | #include "app_error.h" |
| 57 | #include "ble.h" |
57 | #include "ble.h" |
| 58 | #include "ble_err.h" |
58 | #include "ble_err.h" |
| 59 | #include "ble_hci.h" |
59 | #include "ble_hci.h" |
| 60 | #include "ble_srv_common.h" |
60 | #include "ble_srv_common.h" |
| 61 | #include "ble_advdata.h" |
61 | #include "ble_advdata.h" |
| 62 | #include "ble_advertising.h" |
62 | #include "ble_advertising.h" |
| 63 | #include "ble_dis.h" |
63 | #include "ble_dis.h" |
| 64 | #include "ble_bas.h" |
64 | #include "ble_bas.h" |
| 65 | #include "ble_gls.h" |
65 | #include "ble_gls.h" |
| 66 | #include "ble_racp.h" |
66 | #include "ble_racp.h" |
| 67 | #include "ble_conn_params.h" |
67 | #include "ble_conn_params.h" |
| 68 | #include "sensorsim.h" |
68 | #include "sensorsim.h" |
| 69 | #include "nrf_sdh.h" |
69 | #include "nrf_sdh.h" |
| 70 | #include "nrf_sdh_soc.h" |
70 | #include "nrf_sdh_soc.h" |
| 71 | #include "nrf_sdh_ble.h" |
71 | #include "nrf_sdh_ble.h" |
| 72 | #include "app_timer.h" |
72 | #include "app_timer.h" |
| 73 | #include "peer_manager.h" |
73 | #include "peer_manager.h" |
| 74 | #include "peer_manager_handler.h" |
74 | #include "peer_manager_handler.h" |
| 75 | #include "bsp_btn_ble.h" |
75 | #include "bsp_btn_ble.h" |
| 76 | #include "fds.h" |
76 | #include "fds.h" |
| 77 | #include "ble_conn_state.h" |
77 | #include "ble_conn_state.h" |
| 78 | #include "nrf_ble_gatt.h" |
78 | #include "nrf_ble_gatt.h" |
| 79 | #include "nrf_ble_lesc.h" |
79 | #include "nrf_ble_lesc.h" |
| 80 | #include "nrf_ble_qwr.h" |
80 | #include "nrf_ble_qwr.h" |
| 81 | #include "nrf_pwr_mgmt.h" |
81 | #include "nrf_pwr_mgmt.h" |
| 82 | |
82 | |
| 83 | #include "nrf_log.h" |
83 | #include "nrf_log.h" |
| 84 | #include "nrf_log_ctrl.h" |
84 | #include "nrf_log_ctrl.h" |
| 85 | #include "nrf_log_default_backends.h" |
85 | #include "nrf_log_default_backends.h" |
| 86 | |
86 | |
| 87 | |
87 | |
| 88 | #define DEVICE_NAME "Nordic_Glucose" /**< Name of device. Will be included in the advertising data. */ |
88 | #define DEVICE_NAME "Nordic_Glucose" /**< Name of device. Will be included in the advertising data. */ |
| 89 | #define MANUFACTURER_NAME "NordicSemiconductor" /**< Manufacturer. Will be passed to Device Information Service. */ |
89 | #define MANUFACTURER_NAME "NordicSemiconductor" /**< Manufacturer. Will be passed to Device Information Service. */ |
| 90 | #define MODEL_NUMBER "nRF51" /**< Model Number string. Will be passed to Device Information Service. */ |
90 | #define MODEL_NUMBER "nRF51" /**< Model Number string. Will be passed to Device Information Service. */ |
| 91 | #define MANUFACTURER_ID 0x55AA55AA55 /**< DUMMY Manufacturer ID. Will be passed to Device Information Service. You shall use the ID for your Company*/ |
91 | #define MANUFACTURER_ID 0x55AA55AA55 /**< DUMMY Manufacturer ID. Will be passed to Device Information Service. You shall use the ID for your Company*/ |
| 92 | #define ORG_UNIQUE_ID 0xEEBBEE /**< DUMMY Organisation Unique ID. Will be passed to Device Information Service. You shall use the Organisation Unique ID relevant for your Company */ |
92 | #define ORG_UNIQUE_ID 0xEEBBEE /**< DUMMY Organisation Unique ID. Will be passed to Device Information Service. You shall use the Organisation Unique ID relevant for your Company */ |
| 93 | |
93 | |
| 94 | #define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */ |
94 | #define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */ |
| 95 | #define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */ |
95 | #define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */ |
| 96 | |
96 | |
| 97 | #define APP_ADV_INTERVAL 40 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 25 ms). */ |
97 | #define APP_ADV_INTERVAL 40 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 25 ms). */ |
| 98 | #define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */ |
98 | #define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */ |
| 99 | |
99 | |
| 100 | #define BATTERY_LEVEL_MEAS_INTERVAL APP_TIMER_TICKS(10000) /**< Battery level measurement interval (ticks). */ |
100 | #define BATTERY_LEVEL_MEAS_INTERVAL APP_TIMER_TICKS(10000) /**< Battery level measurement interval (ticks). */ |
| 101 | #define MIN_BATTERY_LEVEL 81 /**< Minimum battery level as returned by the simulated measurement function. */ |
101 | #define MIN_BATTERY_LEVEL 81 /**< Minimum battery level as returned by the simulated measurement function. */ |
| 102 | #define MAX_BATTERY_LEVEL 100 /**< Maximum battery level as returned by the simulated measurement function. */ |
102 | #define MAX_BATTERY_LEVEL 100 /**< Maximum battery level as returned by the simulated measurement function. */ |
| 103 | #define BATTERY_LEVEL_INCREMENT 1 /**< Value by which the battery level is incremented/decremented for each call to the simulated measurement function. */ |
103 | #define BATTERY_LEVEL_INCREMENT 1 /**< Value by which the battery level is incremented/decremented for each call to the simulated measurement function. */ |
| 104 | |
104 | |
| 105 | #define MIN_CONN_INTERVAL MSEC_TO_UNITS(10, UNIT_1_25_MS) /**< Minimum acceptable connection interval (10 ms). */ |
105 | #define MIN_CONN_INTERVAL MSEC_TO_UNITS(10, UNIT_1_25_MS) /**< Minimum acceptable connection interval (10 ms). */ |
| 106 | #define MAX_CONN_INTERVAL MSEC_TO_UNITS(100, UNIT_1_25_MS) /**< Maximum acceptable connection interval (100 ms) */ |
106 | #define MAX_CONN_INTERVAL MSEC_TO_UNITS(100, UNIT_1_25_MS) /**< Maximum acceptable connection interval (100 ms) */ |
| 107 | #define SLAVE_LATENCY 0 /**< Slave latency. */ |
107 | #define SLAVE_LATENCY 0 /**< Slave latency. */ |
| 108 | #define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds). */ |
108 | #define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds). */ |
| 109 | #define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */ |
109 | #define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */ |
| 110 | #define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */ |
110 | #define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */ |
| 111 | #define MAX_CONN_PARAM_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */ |
111 | #define MAX_CONN_PARAM_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */ |
| 112 | |
112 | |
| 113 | #define LESC_DEBUG_MODE 0 /**< Set to 1 to use LESC debug keys, allows you to use a sniffer to inspect traffic. */ |
113 | #define LESC_DEBUG_MODE 0 /**< Set to 1 to use LESC debug keys, allows you to use a sniffer to inspect traffic. */ |
| 114 | |
114 | |
| 115 | #define SEC_PARAM_BOND 1 /**< Perform bonding. */ |
115 | #define SEC_PARAM_BOND 1 /**< Perform bonding. */ |
| 116 | #define SEC_PARAM_MITM 1 /**< Man In The Middle protection required (applicable when display module is detected). */ |
116 | #define SEC_PARAM_MITM 1 /**< Man In The Middle protection required (applicable when display module is detected). */ |
| 117 | #define SEC_PARAM_LESC 1 /**< LE Secure Connections enabled. */ |
117 | #define SEC_PARAM_LESC 1 /**< LE Secure Connections enabled. */ |
| 118 | #define SEC_PARAM_KEYPRESS 0 /**< Keypress notifications not enabled. */ |
118 | #define SEC_PARAM_KEYPRESS 0 /**< Keypress notifications not enabled. */ |
| 119 | #define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_DISPLAY_ONLY /**< Display I/O capabilities. */ |
119 | #define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_DISPLAY_ONLY /**< Display I/O capabilities. */ |
| 120 | #define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */ |
120 | #define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */ |
| 121 | #define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */ |
121 | #define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */ |
| 122 | #define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */ |
122 | #define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */ |
| 123 | |
123 | |
| 124 | #define PASSKEY_TXT "Passkey:" /**< Message to be displayed together with the pass-key. */ |
124 | #define PASSKEY_TXT "Passkey:" /**< Message to be displayed together with the pass-key. */ |
| 125 | #define PASSKEY_TXT_LENGTH 8 /**< Length of message to be displayed together with the pass-key. */ |
125 | #define PASSKEY_TXT_LENGTH 8 /**< Length of message to be displayed together with the pass-key. */ |
| 126 | #define PASSKEY_LENGTH 6 /**< Length of pass-key received by the stack for display. */ |
126 | #define PASSKEY_LENGTH 6 /**< Length of pass-key received by the stack for display. */ |
| 127 | |
127 | |
| 128 | #define DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */ |
128 | #define DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */ |
| 129 | |
129 | |
| 130 | |
130 | |
| 131 | BLE_BAS_DEF(m_bas); /**< Structure used to identify the battery service. */ |
131 | BLE_BAS_DEF(m_bas); /**< Structure used to identify the battery service. */ |
| 132 | BLE_GLS_DEF(m_gls); /**< Structure used to identify the glucose service. */ |
132 | BLE_GLS_DEF(m_gls); /**< Structure used to identify the glucose service. */ |
| 133 | NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ |
133 | NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ |
| 134 | NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/ |
134 | NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/ |
| 135 | BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ |
135 | BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ |
| 136 | APP_TIMER_DEF(m_battery_timer_id); /**< Battery timer. */ |
136 | APP_TIMER_DEF(m_battery_timer_id); /**< Battery timer. */ |
| 137 | NRF_BLE_GQ_DEF(m_ble_gatt_queue, /**< BLE GATT Queue instance. */ |
137 | NRF_BLE_GQ_DEF(m_ble_gatt_queue, /**< BLE GATT Queue instance. */ |
| 138 | NRF_SDH_BLE_PERIPHERAL_LINK_COUNT, |
138 | NRF_SDH_BLE_PERIPHERAL_LINK_COUNT, |
| 139 | NRF_BLE_GQ_QUEUE_SIZE); |
139 | NRF_BLE_GQ_QUEUE_SIZE); |
| 140 | |
140 | |
| 141 | static pm_peer_id_t m_peer_to_be_deleted = PM_PEER_ID_INVALID; |
141 | static pm_peer_id_t m_peer_to_be_deleted = PM_PEER_ID_INVALID; |
| 142 | static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */ |
142 | static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */ |
| 143 | static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifiers. */ |
143 | static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifiers. */ |
| 144 | { |
144 | { |
| 145 | {BLE_UUID_GLUCOSE_SERVICE, BLE_UUID_TYPE_BLE}, |
145 | {BLE_UUID_GLUCOSE_SERVICE, BLE_UUID_TYPE_BLE}, |
| 146 | {BLE_UUID_BATTERY_SERVICE, BLE_UUID_TYPE_BLE}, |
146 | {BLE_UUID_BATTERY_SERVICE, BLE_UUID_TYPE_BLE}, |
| 147 | {BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE} |
147 | {BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE} |
| 148 | }; |
148 | }; |
| 149 | static sensorsim_cfg_t m_battery_sim_cfg; /**< Battery Level sensor simulator configuration. */ |
149 | static sensorsim_cfg_t m_battery_sim_cfg; /**< Battery Level sensor simulator configuration. */ |
| 150 | static sensorsim_state_t m_battery_sim_state; /**< Battery Level sensor simulator state. */ |
150 | static sensorsim_state_t m_battery_sim_state; /**< Battery Level sensor simulator state. */ |
| 151 | |
151 | |
| 152 | static bool peer_to_create = false; |
| |
| 153 | |
152 | |
| 154 | static void advertising_start(bool erase_bonds); |
153 | static void advertising_start(bool erase_bonds); |
| 155 | |
154 | |
| 156 | |
155 | |
| 157 | /**@brief Callback function for asserts in the SoftDevice. |
156 | /**@brief Callback function for asserts in the SoftDevice. |
| 158 | * |
157 | * |
| 159 | * @details This function will be called in case of an assert in the SoftDevice. |
158 | * @details This function will be called in case of an assert in the SoftDevice. |
| 160 | * |
159 | * |
| 161 | * @warning This handler is an example only and does not fit a final product. You need to analyze |
160 | * @warning This handler is an example only and does not fit a final product. You need to analyze |
| 162 | * how your product is supposed to react in case of Assert. |
161 | * how your product is supposed to react in case of Assert. |
| 163 | * @warning On assert from the SoftDevice, the system can only recover on reset. |
162 | * @warning On assert from the SoftDevice, the system can only recover on reset. |
| 164 | * |
163 | * |
| 165 | * @param[in] line_num Line number of the failing ASSERT call. |
164 | * @param[in] line_num Line number of the failing ASSERT call. |
| 166 | * @param[in] file_name File name of the failing ASSERT call. |
165 | * @param[in] file_name File name of the failing ASSERT call. |
| 167 | */ |
166 | */ |
| 168 | void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name) |
167 | void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name) |
| 169 | { |
168 | { |
| 170 | app_error_handler(DEAD_BEEF, line_num, p_file_name); |
169 | app_error_handler(DEAD_BEEF, line_num, p_file_name); |
| 171 | } |
170 | } |
| 172 | |
171 | |
| 173 | /**@brief Function for handling Peer Manager events. |
172 | /**@brief Function for handling Peer Manager events. |
| 174 | * |
173 | * |
| 175 | * @param[in] p_evt Peer Manager event. |
174 | * @param[in] p_evt Peer Manager event. |
| 176 | */ |
175 | */ |
| 177 | static void pm_evt_handler(pm_evt_t const * p_evt) |
176 | static void pm_evt_handler(pm_evt_t const * p_evt) |
| 178 | { |
177 | { |
| 179 | ret_code_t err_code; |
178 | ret_code_t err_code; |
| 180 | |
179 | |
| 181 | pm_handler_on_pm_evt(p_evt); |
180 | pm_handler_on_pm_evt(p_evt); |
| 182 | pm_handler_disconnect_on_sec_failure(p_evt); |
181 | pm_handler_disconnect_on_sec_failure(p_evt); |
| 183 | pm_handler_flash_clean(p_evt); |
182 | pm_handler_flash_clean(p_evt); |
| 184 | |
183 | |
| 185 | switch (p_evt->evt_id) |
184 | switch (p_evt->evt_id) |
| 186 | { |
185 | { |
| 187 | case PM_EVT_CONN_SEC_SUCCEEDED: |
186 | case PM_EVT_CONN_SEC_SUCCEEDED: |
| 188 | { |
187 | { |
| 189 | pm_conn_sec_status_t conn_sec_status; |
188 | pm_conn_sec_status_t conn_sec_status; |
| 190 | |
189 | |
| 191 | // Check if the link is authenticated (meaning at least MITM). |
190 | // Check if the link is authenticated (meaning at least MITM). |
| 192 | err_code = pm_conn_sec_status_get(p_evt->conn_handle, &conn_sec_status); |
191 | err_code = pm_conn_sec_status_get(p_evt->conn_handle, &conn_sec_status); |
| 193 | APP_ERROR_CHECK(err_code); |
192 | APP_ERROR_CHECK(err_code); |
| 194 | |
193 | |
| 195 | if (conn_sec_status.mitm_protected) |
194 | if (conn_sec_status.mitm_protected) |
| 196 | { |
195 | { |
| 197 | NRF_LOG_INFO("Link secured. Role: %d. conn_handle: %d, Procedure: %d", |
196 | NRF_LOG_INFO("Link secured. Role: %d. conn_handle: %d, Procedure: %d", |
| 198 | ble_conn_state_role(p_evt->conn_handle), |
197 | ble_conn_state_role(p_evt->conn_handle), |
| 199 | p_evt->conn_handle, |
198 | p_evt->conn_handle, |
| 200 | p_evt->params.conn_sec_succeeded.procedure); |
199 | p_evt->params.conn_sec_succeeded.procedure); |
| 201 | } |
200 | } |
| 202 | else |
201 | else |
| 203 | { |
202 | { |
| 204 | // The peer did not use MITM, disconnect. |
203 | // The peer did not use MITM, disconnect. |
| 205 | NRF_LOG_INFO("Collector did not use MITM, disconnecting"); |
204 | NRF_LOG_INFO("Collector did not use MITM, disconnecting"); |
| 206 | err_code = pm_peer_id_get(m_conn_handle, &m_peer_to_be_deleted); |
205 | err_code = pm_peer_id_get(m_conn_handle, &m_peer_to_be_deleted); |
| 207 | APP_ERROR_CHECK(err_code); |
206 | APP_ERROR_CHECK(err_code); |
| 208 | err_code = sd_ble_gap_disconnect(m_conn_handle, |
207 | err_code = sd_ble_gap_disconnect(m_conn_handle, |
| 209 | BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); |
208 | BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); |
| 210 | APP_ERROR_CHECK(err_code); |
209 | APP_ERROR_CHECK(err_code); |
| 211 | } |
210 | } |
| 212 | } break; |
211 | } break; |
| 213 | |
212 | |
| 214 | case PM_EVT_CONN_SEC_FAILED: |
213 | case PM_EVT_CONN_SEC_FAILED: |
| 215 | m_conn_handle = BLE_CONN_HANDLE_INVALID; |
214 | m_conn_handle = BLE_CONN_HANDLE_INVALID; |
| 216 | break; |
215 | break; |
| 217 | |
216 | |
| 218 | case PM_EVT_PEERS_DELETE_SUCCEEDED: |
217 | case PM_EVT_PEERS_DELETE_SUCCEEDED: |
| 219 | advertising_start(false); |
218 | advertising_start(false); |
| 220 | break; |
219 | break; |
| 221 | |
220 | |
| 222 | case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: |
| |
| 223 | { |
| |
| 224 | peer_to_create = true; |
| |
| 225 | //err_code = pm_peer_rank_highest( p_evt->peer_id ); |
| |
| 226 | } |
| |
| 227 | break; |
| |
| 228 | |
| |
| 229 | default: |
221 | default: |
| 230 | break; |
222 | break; |
| 231 | } |
223 | } |
| 232 | } |
224 | } |
| 233 | |
225 | |
| 234 | |
226 | |
| 235 | /**@brief Function for handling Service errors. |
227 | /**@brief Function for handling Service errors. |
| 236 | * |
228 | * |
| 237 | * @details A pointer to this function will be passed to each service which may need to inform the |
229 | * @details A pointer to this function will be passed to each service which may need to inform the |
| 238 | * application about an error. |
230 | * application about an error. |
| 239 | * |
231 | * |
| 240 | * @param[in] nrf_error Error code containing information about what went wrong. |
232 | * @param[in] nrf_error Error code containing information about what went wrong. |
| 241 | */ |
233 | */ |
| 242 | static void service_error_handler(uint32_t nrf_error) |
234 | static void service_error_handler(uint32_t nrf_error) |
| 243 | { |
235 | { |
| 244 | APP_ERROR_HANDLER(nrf_error); |
236 | APP_ERROR_HANDLER(nrf_error); |
| 245 | } |
237 | } |
| 246 | |
238 | |
| 247 | |
239 | |
| 248 | /**@brief Function for performing battery measurement and updating the Battery Level characteristic |
240 | /**@brief Function for performing battery measurement and updating the Battery Level characteristic |
| 249 | * in Battery Service. |
241 | * in Battery Service. |
| 250 | */ |
242 | */ |
| 251 | static void battery_level_update(void) |
243 | static void battery_level_update(void) |
| 252 | { |
244 | { |
| 253 | ret_code_t err_code; |
245 | ret_code_t err_code; |
| 254 | uint8_t battery_level; |
246 | uint8_t battery_level; |
| 255 | |
247 | |
| 256 | battery_level = (uint8_t)sensorsim_measure(&m_battery_sim_state, &m_battery_sim_cfg); |
248 | battery_level = (uint8_t)sensorsim_measure(&m_battery_sim_state, &m_battery_sim_cfg); |
| 257 | |
249 | |
| 258 | err_code = ble_bas_battery_level_update(&m_bas, battery_level, BLE_CONN_HANDLE_ALL); |
250 | err_code = ble_bas_battery_level_update(&m_bas, battery_level, BLE_CONN_HANDLE_ALL); |
| 259 | if ((err_code != NRF_SUCCESS) && |
251 | if ((err_code != NRF_SUCCESS) && |
| 260 | (err_code != NRF_ERROR_INVALID_STATE) && |
252 | (err_code != NRF_ERROR_INVALID_STATE) && |
| 261 | (err_code != NRF_ERROR_RESOURCES) && |
253 | (err_code != NRF_ERROR_RESOURCES) && |
| 262 | (err_code != NRF_ERROR_BUSY) && |
254 | (err_code != NRF_ERROR_BUSY) && |
| 263 | (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING) |
255 | (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING) |
| 264 | ) |
256 | ) |
| 265 | { |
257 | { |
| 266 | APP_ERROR_HANDLER(err_code); |
258 | APP_ERROR_HANDLER(err_code); |
| 267 | } |
259 | } |
| 268 | } |
260 | } |
| 269 | |
261 | |
| 270 | |
262 | |
| 271 | /**@brief Function for handling the Battery measurement timer timeout. |
263 | /**@brief Function for handling the Battery measurement timer timeout. |
| 272 | * |
264 | * |
| 273 | * @details This function will be called each time the battery level measurement timer expires. |
265 | * @details This function will be called each time the battery level measurement timer expires. |
| 274 | * |
266 | * |
| 275 | * @param[in] p_context Pointer used for passing some arbitrary information (context) from the |
267 | * @param[in] p_context Pointer used for passing some arbitrary information (context) from the |
| 276 | * app_start_timer() call to the timeout handler. |
268 | * app_start_timer() call to the timeout handler. |
| 277 | */ |
269 | */ |
| 278 | static void battery_level_meas_timeout_handler(void * p_context) |
270 | static void battery_level_meas_timeout_handler(void * p_context) |
| 279 | { |
271 | { |
| 280 | UNUSED_PARAMETER(p_context); |
272 | UNUSED_PARAMETER(p_context); |
| 281 | battery_level_update(); |
273 | battery_level_update(); |
| 282 | } |
274 | } |
| 283 | |
275 | |
| 284 | |
276 | |
| 285 | /**@brief Function for updating glucose measurement and updating glucose characteristic in Glucose. |
277 | /**@brief Function for updating glucose measurement and updating glucose characteristic in Glucose. |
| 286 | Service. |
278 | Service. |
| 287 | */ |
279 | */ |
| 288 | static void read_glucose_measurement(void) |
280 | static void read_glucose_measurement(void) |
| 289 | { |
281 | { |
| 290 | ble_gls_rec_t rec; |
282 | ble_gls_rec_t rec; |
| 291 | uint32_t err_code; |
283 | uint32_t err_code; |
| 292 | |
284 | |
| 293 | static int16_t s_mantissa = 550; |
285 | static int16_t s_mantissa = 550; |
| 294 | static int16_t s_exponent = -3; |
286 | static int16_t s_exponent = -3; |
| 295 | static uint8_t s_secs = 5; |
287 | static uint8_t s_secs = 5; |
| 296 | |
288 | |
| 297 | // simulate the reading of a glucose measurement. |
289 | // simulate the reading of a glucose measurement. |
| 298 | rec.meas.flags = BLE_GLS_MEAS_FLAG_TIME_OFFSET | |
290 | rec.meas.flags = BLE_GLS_MEAS_FLAG_TIME_OFFSET | |
| 299 | BLE_GLS_MEAS_FLAG_CONC_TYPE_LOC | |
291 | BLE_GLS_MEAS_FLAG_CONC_TYPE_LOC | |
| 300 | BLE_GLS_MEAS_FLAG_UNITS_MOL_L; |
292 | BLE_GLS_MEAS_FLAG_UNITS_MOL_L; |
| 301 | rec.meas.base_time.year = 2012; |
293 | rec.meas.base_time.year = 2012; |
| 302 | rec.meas.base_time.month = 1; |
294 | rec.meas.base_time.month = 1; |
| 303 | rec.meas.base_time.day = 1; |
295 | rec.meas.base_time.day = 1; |
| 304 | rec.meas.base_time.hours = 12; |
296 | rec.meas.base_time.hours = 12; |
| 305 | rec.meas.base_time.minutes = 30; |
297 | rec.meas.base_time.minutes = 30; |
| 306 | rec.meas.base_time.seconds = s_secs; |
298 | rec.meas.base_time.seconds = s_secs; |
| 307 | rec.meas.glucose_concentration.exponent = s_exponent; |
299 | rec.meas.glucose_concentration.exponent = s_exponent; |
| 308 | rec.meas.glucose_concentration.mantissa = s_mantissa; |
300 | rec.meas.glucose_concentration.mantissa = s_mantissa; |
| 309 | rec.meas.time_offset = 0; |
301 | rec.meas.time_offset = 0; |
| 310 | rec.meas.type = BLE_GLS_MEAS_TYPE_CAP_BLOOD; |
302 | rec.meas.type = BLE_GLS_MEAS_TYPE_CAP_BLOOD; |
| 311 | rec.meas.sample_location = BLE_GLS_MEAS_LOC_FINGER; |
303 | rec.meas.sample_location = BLE_GLS_MEAS_LOC_FINGER; |
| 312 | rec.meas.sensor_status_annunciation = 0; |
304 | rec.meas.sensor_status_annunciation = 0; |
| 313 | |
305 | |
| 314 | // change values for next read. |
306 | // change values for next read. |
| 315 | s_mantissa += 23; |
307 | s_mantissa += 23; |
| 316 | if (s_mantissa > 939) |
308 | if (s_mantissa > 939) |
| 317 | { |
309 | { |
| 318 | s_mantissa -= 434; |
310 | s_mantissa -= 434; |
| 319 | } |
311 | } |
| 320 | |
312 | |
| 321 | s_secs += 3; |
313 | s_secs += 3; |
| 322 | if (s_secs > 59) |
314 | if (s_secs > 59) |
| 323 | { |
315 | { |
| 324 | s_secs = 0; |
316 | s_secs = 0; |
| 325 | } |
317 | } |
| 326 | |
318 | |
| 327 | err_code = ble_gls_glucose_new_meas(&m_gls, &rec); |
319 | err_code = ble_gls_glucose_new_meas(&m_gls, &rec); |
| 328 | if (err_code != NRF_SUCCESS) |
320 | if (err_code != NRF_SUCCESS) |
| 329 | { |
321 | { |
| 330 | // Do nothing. |
322 | // Do nothing. |
| 331 | } |
323 | } |
| 332 | } |
324 | } |
| 333 | |
325 | |
| 334 | |
326 | |
| 335 | /**@brief Function for the Timer initialization. |
327 | /**@brief Function for the Timer initialization. |
| 336 | * |
328 | * |
| 337 | * @details Initializes the timer module. This creates and starts application timers. |
329 | * @details Initializes the timer module. This creates and starts application timers. |
| 338 | */ |
330 | */ |
| 339 | static void timers_init(void) |
331 | static void timers_init(void) |
| 340 | { |
332 | { |
| 341 | ret_code_t err_code; |
333 | ret_code_t err_code; |
| 342 | |
334 | |
| 343 | // Initialize timer module. |
335 | // Initialize timer module. |
| 344 | err_code = app_timer_init(); |
336 | err_code = app_timer_init(); |
| 345 | APP_ERROR_CHECK(err_code); |
337 | APP_ERROR_CHECK(err_code); |
| 346 | |
338 | |
| 347 | // Create timers. |
339 | // Create timers. |
| 348 | err_code = app_timer_create(&m_battery_timer_id, |
340 | err_code = app_timer_create(&m_battery_timer_id, |
| 349 | APP_TIMER_MODE_REPEATED, |
341 | APP_TIMER_MODE_REPEATED, |
| 350 | battery_level_meas_timeout_handler); |
342 | battery_level_meas_timeout_handler); |
| 351 | APP_ERROR_CHECK(err_code); |
343 | APP_ERROR_CHECK(err_code); |
| 352 | } |
344 | } |
| 353 | |
345 | |
| 354 | |
346 | |
| 355 | /**@brief Function for the GAP initialization. |
347 | /**@brief Function for the GAP initialization. |
| 356 | * |
348 | * |
| 357 | * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the |
349 | * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the |
| 358 | * device including the device name, appearance, and the preferred connection parameters. |
350 | * device including the device name, appearance, and the preferred connection parameters. |
| 359 | */ |
351 | */ |
| 360 | static void gap_params_init(void) |
352 | static void gap_params_init(void) |
| 361 | { |
353 | { |
| 362 | ret_code_t err_code; |
354 | ret_code_t err_code; |
| 363 | ble_gap_conn_params_t gap_conn_params; |
355 | ble_gap_conn_params_t gap_conn_params; |
| 364 | ble_gap_conn_sec_mode_t sec_mode; |
356 | ble_gap_conn_sec_mode_t sec_mode; |
| 365 | |
357 | |
| 366 | BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); |
358 | BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); |
| 367 | |
359 | |
| 368 | err_code = sd_ble_gap_device_name_set(&sec_mode, |
360 | err_code = sd_ble_gap_device_name_set(&sec_mode, |
| 369 | (const uint8_t *)DEVICE_NAME, |
361 | (const uint8_t *)DEVICE_NAME, |
| 370 | strlen(DEVICE_NAME)); |
362 | strlen(DEVICE_NAME)); |
| 371 | APP_ERROR_CHECK(err_code); |
363 | APP_ERROR_CHECK(err_code); |
| 372 | |
364 | |
| 373 | err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_GENERIC_GLUCOSE_METER); |
365 | err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_GENERIC_GLUCOSE_METER); |
| 374 | APP_ERROR_CHECK(err_code); |
366 | APP_ERROR_CHECK(err_code); |
| 375 | |
367 | |
| 376 | memset(&gap_conn_params, 0, sizeof(gap_conn_params)); |
368 | memset(&gap_conn_params, 0, sizeof(gap_conn_params)); |
| 377 | |
369 | |
| 378 | gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; |
370 | gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; |
| 379 | gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; |
371 | gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; |
| 380 | gap_conn_params.slave_latency = SLAVE_LATENCY; |
372 | gap_conn_params.slave_latency = SLAVE_LATENCY; |
| 381 | gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; |
373 | gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; |
| 382 | |
374 | |
| 383 | err_code = sd_ble_gap_ppcp_set(&gap_conn_params); |
375 | err_code = sd_ble_gap_ppcp_set(&gap_conn_params); |
| 384 | APP_ERROR_CHECK(err_code); |
376 | APP_ERROR_CHECK(err_code); |
| 385 | } |
377 | } |
| 386 | |
378 | |
| 387 | |
379 | |
| 388 | /**@brief Function for initializing the GATT module. |
380 | /**@brief Function for initializing the GATT module. |
| 389 | */ |
381 | */ |
| 390 | static void gatt_init(void) |
382 | static void gatt_init(void) |
| 391 | { |
383 | { |
| 392 | ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL); |
384 | ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL); |
| 393 | APP_ERROR_CHECK(err_code); |
385 | APP_ERROR_CHECK(err_code); |
| 394 | } |
386 | } |
| 395 | |
387 | |
| 396 | |
388 | |
| 397 | /**@brief Function for handling Queued Write Module errors. |
389 | /**@brief Function for handling Queued Write Module errors. |
| 398 | * |
390 | * |
| 399 | * @details A pointer to this function will be passed to each service which may need to inform the |
391 | * @details A pointer to this function will be passed to each service which may need to inform the |
| 400 | * application about an error. |
392 | * application about an error. |
| 401 | * |
393 | * |
| 402 | * @param[in] nrf_error Error code containing information about what went wrong. |
394 | * @param[in] nrf_error Error code containing information about what went wrong. |
| 403 | */ |
395 | */ |
| 404 | static void nrf_qwr_error_handler(uint32_t nrf_error) |
396 | static void nrf_qwr_error_handler(uint32_t nrf_error) |
| 405 | { |
397 | { |
| 406 | APP_ERROR_HANDLER(nrf_error); |
398 | APP_ERROR_HANDLER(nrf_error); |
| 407 | } |
399 | } |
| 408 | |
400 | |
| 409 | |
401 | |
| 410 | /**@brief Function for initializing services that will be used by the application. |
402 | /**@brief Function for initializing services that will be used by the application. |
| 411 | * |
403 | * |
| 412 | * @details Initialize the Glucose, Battery and Device Information services. |
404 | * @details Initialize the Glucose, Battery and Device Information services. |
| 413 | */ |
405 | */ |
| 414 | static void services_init(void) |
406 | static void services_init(void) |
| 415 | { |
407 | { |
| 416 | ret_code_t err_code; |
408 | ret_code_t err_code; |
| 417 | ble_gls_init_t gls_init; |
409 | ble_gls_init_t gls_init; |
| 418 | ble_dis_init_t dis_init; |
410 | ble_dis_init_t dis_init; |
| 419 | ble_bas_init_t bas_init; |
411 | ble_bas_init_t bas_init; |
| 420 | nrf_ble_qwr_init_t qwr_init = {0}; |
412 | nrf_ble_qwr_init_t qwr_init = {0}; |
| 421 | |
413 | |
| 422 | // Initialize Queued Write Module. |
414 | // Initialize Queued Write Module. |
| 423 | qwr_init.error_handler = nrf_qwr_error_handler; |
415 | qwr_init.error_handler = nrf_qwr_error_handler; |
| 424 | |
416 | |
| 425 | err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init); |
417 | err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init); |
| 426 | APP_ERROR_CHECK(err_code); |
418 | APP_ERROR_CHECK(err_code); |
| 427 | |
419 | |
| 428 | // Initialize Glucose Service - sample selection of feature bits. |
420 | // Initialize Glucose Service - sample selection of feature bits. |
| 429 | memset(&gls_init, 0, sizeof(gls_init)); |
421 | memset(&gls_init, 0, sizeof(gls_init)); |
| 430 | |
422 | |
| 431 | gls_init.evt_handler = NULL; |
423 | gls_init.evt_handler = NULL; |
| 432 | gls_init.p_gatt_queue = &m_ble_gatt_queue; |
424 | gls_init.p_gatt_queue = &m_ble_gatt_queue; |
| 433 | gls_init.error_handler = service_error_handler; |
425 | gls_init.error_handler = service_error_handler; |
| 434 | gls_init.feature = 0; |
426 | gls_init.feature = 0; |
| 435 | gls_init.feature |= BLE_GLS_FEATURE_LOW_BATT; |
427 | gls_init.feature |= BLE_GLS_FEATURE_LOW_BATT; |
| 436 | gls_init.feature |= BLE_GLS_FEATURE_TEMP_HIGH_LOW; |
428 | gls_init.feature |= BLE_GLS_FEATURE_TEMP_HIGH_LOW; |
| 437 | gls_init.feature |= BLE_GLS_FEATURE_GENERAL_FAULT; |
429 | gls_init.feature |= BLE_GLS_FEATURE_GENERAL_FAULT; |
| 438 | gls_init.is_context_supported = false; |
430 | gls_init.is_context_supported = false; |
| 439 | |
431 | |
| 440 | // Here the sec level for the Glucose Service can be changed/increased. |
432 | // Here the sec level for the Glucose Service can be changed/increased. |
| 441 | gls_init.gl_meas_cccd_wr_sec = SEC_JUST_WORKS; |
433 | gls_init.gl_meas_cccd_wr_sec = SEC_JUST_WORKS; |
| 442 | gls_init.gl_feature_rd_sec = SEC_JUST_WORKS; |
434 | gls_init.gl_feature_rd_sec = SEC_JUST_WORKS; |
| 443 | gls_init.racp_cccd_wr_sec = SEC_JUST_WORKS; |
435 | gls_init.racp_cccd_wr_sec = SEC_JUST_WORKS; |
| 444 | gls_init.racp_wr_sec = SEC_JUST_WORKS; |
436 | gls_init.racp_wr_sec = SEC_JUST_WORKS; |
| 445 | |
437 | |
| 446 | err_code = ble_gls_init(&m_gls, &gls_init); |
438 | err_code = ble_gls_init(&m_gls, &gls_init); |
| 447 | APP_ERROR_CHECK(err_code); |
439 | APP_ERROR_CHECK(err_code); |
| 448 | |
440 | |
| 449 | // Initialize Battery Service. |
441 | // Initialize Battery Service. |
| 450 | memset(&bas_init, 0, sizeof(bas_init)); |
442 | memset(&bas_init, 0, sizeof(bas_init)); |
| 451 | |
443 | |
| 452 | // Here the sec level for the Battery Service can be changed/increased. |
444 | // Here the sec level for the Battery Service can be changed/increased. |
| 453 | bas_init.bl_rd_sec = SEC_OPEN; |
445 | bas_init.bl_rd_sec = SEC_OPEN; |
| 454 | bas_init.bl_cccd_wr_sec = SEC_OPEN; |
446 | bas_init.bl_cccd_wr_sec = SEC_OPEN; |
| 455 | bas_init.bl_report_rd_sec = SEC_OPEN; |
447 | bas_init.bl_report_rd_sec = SEC_OPEN; |
| 456 | |
448 | |
| 457 | bas_init.evt_handler = NULL; |
449 | bas_init.evt_handler = NULL; |
| 458 | bas_init.support_notification = true; |
450 | bas_init.support_notification = true; |
| 459 | bas_init.p_report_ref = NULL; |
451 | bas_init.p_report_ref = NULL; |
| 460 | bas_init.initial_batt_level = 100; |
452 | bas_init.initial_batt_level = 100; |
| 461 | |
453 | |
| 462 | err_code = ble_bas_init(&m_bas, &bas_init); |
454 | err_code = ble_bas_init(&m_bas, &bas_init); |
| 463 | APP_ERROR_CHECK(err_code); |
455 | APP_ERROR_CHECK(err_code); |
| 464 | |
456 | |
| 465 | // Initialize Device Information Service. |
457 | // Initialize Device Information Service. |
| 466 | memset(&dis_init, 0, sizeof(dis_init)); |
458 | memset(&dis_init, 0, sizeof(dis_init)); |
| 467 | |
459 | |
| 468 | ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, MANUFACTURER_NAME); |
460 | ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, MANUFACTURER_NAME); |
| 469 | |
461 | |
| 470 | ble_srv_ascii_to_utf8(&dis_init.serial_num_str, MODEL_NUMBER); |
462 | ble_srv_ascii_to_utf8(&dis_init.serial_num_str, MODEL_NUMBER); |
| 471 | |
463 | |
| 472 | ble_dis_sys_id_t system_id; |
464 | ble_dis_sys_id_t system_id; |
| 473 | system_id.manufacturer_id = MANUFACTURER_ID; |
465 | system_id.manufacturer_id = MANUFACTURER_ID; |
| 474 | system_id.organizationally_unique_id = ORG_UNIQUE_ID; |
466 | system_id.organizationally_unique_id = ORG_UNIQUE_ID; |
| 475 | dis_init.p_sys_id = &system_id; |
467 | dis_init.p_sys_id = &system_id; |
| 476 | |
468 | |
| 477 | dis_init.dis_char_rd_sec = SEC_OPEN; |
469 | dis_init.dis_char_rd_sec = SEC_OPEN; |
| 478 | |
470 | |
| 479 | err_code = ble_dis_init(&dis_init); |
471 | err_code = ble_dis_init(&dis_init); |
| 480 | APP_ERROR_CHECK(err_code); |
472 | APP_ERROR_CHECK(err_code); |
| 481 | } |
473 | } |
| 482 | |
474 | |
| 483 | |
475 | |
| 484 | /**@brief Function for initializing the sensor simulators. |
476 | /**@brief Function for initializing the sensor simulators. |
| 485 | */ |
477 | */ |
| 486 | static void sensor_simulator_init(void) |
478 | static void sensor_simulator_init(void) |
| 487 | { |
479 | { |
| 488 | m_battery_sim_cfg.min = MIN_BATTERY_LEVEL; |
480 | m_battery_sim_cfg.min = MIN_BATTERY_LEVEL; |
| 489 | m_battery_sim_cfg.max = MAX_BATTERY_LEVEL; |
481 | m_battery_sim_cfg.max = MAX_BATTERY_LEVEL; |
| 490 | m_battery_sim_cfg.incr = BATTERY_LEVEL_INCREMENT; |
482 | m_battery_sim_cfg.incr = BATTERY_LEVEL_INCREMENT; |
| 491 | m_battery_sim_cfg.start_at_max = true; |
483 | m_battery_sim_cfg.start_at_max = true; |
| 492 | |
484 | |
| 493 | sensorsim_init(&m_battery_sim_state, &m_battery_sim_cfg); |
485 | sensorsim_init(&m_battery_sim_state, &m_battery_sim_cfg); |
| 494 | } |
486 | } |
| 495 | |
487 | |
| 496 | |
488 | |
| 497 | /**@brief Function for starting application timers. |
489 | /**@brief Function for starting application timers. |
| 498 | */ |
490 | */ |
| 499 | static void application_timers_start(void) |
491 | static void application_timers_start(void) |
| 500 | { |
492 | { |
| 501 | ret_code_t err_code; |
493 | ret_code_t err_code; |
| 502 | |
494 | |
| 503 | // Start application timers. |
495 | // Start application timers. |
| 504 | err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL); |
496 | err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL); |
| 505 | APP_ERROR_CHECK(err_code); |
497 | APP_ERROR_CHECK(err_code); |
| 506 | } |
498 | } |
| 507 | |
499 | |
| 508 | |
500 | |
| 509 | /**@brief Function for handling the Connection Parameter events. |
501 | /**@brief Function for handling the Connection Parameter events. |
| 510 | * |
502 | * |
| 511 | * @details This function will be called for all events in the Connection Parameters Module which |
503 | * @details This function will be called for all events in the Connection Parameters Module which |
| 512 | * are passed to the application. |
504 | * are passed to the application. |
| 513 | * @note All this function does is to disconnect. This could have been done by simply |
505 | * @note All this function does is to disconnect. This could have been done by simply |
| 514 | * setting the disconnect_on_fail configuration parameter, but instead we use the |
506 | * setting the disconnect_on_fail configuration parameter, but instead we use the |
| 515 | * event handler mechanism to demonstrate its use. |
507 | * event handler mechanism to demonstrate its use. |
| 516 | * |
508 | * |
| 517 | * @param[in] p_evt Event received from the Connection Parameters Module. |
509 | * @param[in] p_evt Event received from the Connection Parameters Module. |
| 518 | */ |
510 | */ |
| 519 | static void on_conn_params_evt(ble_conn_params_evt_t * p_evt) |
511 | static void on_conn_params_evt(ble_conn_params_evt_t * p_evt) |
| 520 | { |
512 | { |
| 521 | ret_code_t err_code; |
513 | ret_code_t err_code; |
| 522 | |
514 | |
| 523 | if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) |
515 | if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) |
| 524 | { |
516 | { |
| 525 | err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); |
517 | err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); |
| 526 | APP_ERROR_CHECK(err_code); |
518 | APP_ERROR_CHECK(err_code); |
| 527 | } |
519 | } |
| 528 | } |
520 | } |
| 529 | |
521 | |
| 530 | |
522 | |
| 531 | /**@brief Function for handling a Connection Parameters error. |
523 | /**@brief Function for handling a Connection Parameters error. |
| 532 | * |
524 | * |
| 533 | * @param[in] nrf_error Error code containing information about what went wrong. |
525 | * @param[in] nrf_error Error code containing information about what went wrong. |
| 534 | */ |
526 | */ |
| 535 | static void conn_params_error_handler(uint32_t nrf_error) |
527 | static void conn_params_error_handler(uint32_t nrf_error) |
| 536 | { |
528 | { |
| 537 | APP_ERROR_HANDLER(nrf_error); |
529 | APP_ERROR_HANDLER(nrf_error); |
| 538 | } |
530 | } |
| 539 | |
531 | |
| 540 | |
532 | |
| 541 | /**@brief Function for initializing the Connection Parameters module. |
533 | /**@brief Function for initializing the Connection Parameters module. |
| 542 | */ |
534 | */ |
| 543 | static void conn_params_init(void) |
535 | static void conn_params_init(void) |
| 544 | { |
536 | { |
| 545 | ret_code_t err_code; |
537 | ret_code_t err_code; |
| 546 | ble_conn_params_init_t cp_init; |
538 | ble_conn_params_init_t cp_init; |
| 547 | |
539 | |
| 548 | memset(&cp_init, 0, sizeof(cp_init)); |
540 | memset(&cp_init, 0, sizeof(cp_init)); |
| 549 | |
541 | |
| 550 | cp_init.p_conn_params = NULL; |
542 | cp_init.p_conn_params = NULL; |
| 551 | cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; |
543 | cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; |
| 552 | cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; |
544 | cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; |
| 553 | cp_init.max_conn_params_update_count = MAX_CONN_PARAM_UPDATE_COUNT; |
545 | cp_init.max_conn_params_update_count = MAX_CONN_PARAM_UPDATE_COUNT; |
| 554 | cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; |
546 | cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; |
| 555 | cp_init.disconnect_on_fail = false; |
547 | cp_init.disconnect_on_fail = false; |
| 556 | cp_init.evt_handler = on_conn_params_evt; |
548 | cp_init.evt_handler = on_conn_params_evt; |
| 557 | cp_init.error_handler = conn_params_error_handler; |
549 | cp_init.error_handler = conn_params_error_handler; |
| 558 | |
550 | |
| 559 | err_code = ble_conn_params_init(&cp_init); |
551 | err_code = ble_conn_params_init(&cp_init); |
| 560 | APP_ERROR_CHECK(err_code); |
552 | APP_ERROR_CHECK(err_code); |
| 561 | } |
553 | } |
| 562 | |
554 | |
| 563 | |
555 | |
| 564 | /**@brief Function for putting the chip into sleep mode. |
556 | /**@brief Function for putting the chip into sleep mode. |
| 565 | * |
557 | * |
| 566 | * @note This function will not return. |
558 | * @note This function will not return. |
| 567 | */ |
559 | */ |
| 568 | static void sleep_mode_enter(void) |
560 | static void sleep_mode_enter(void) |
| 569 | { |
561 | { |
| 570 | ret_code_t err_code;; |
562 | ret_code_t err_code;; |
| 571 | err_code = bsp_indication_set(BSP_INDICATE_IDLE); |
563 | err_code = bsp_indication_set(BSP_INDICATE_IDLE); |
| 572 | APP_ERROR_CHECK(err_code); |
564 | APP_ERROR_CHECK(err_code); |
| 573 | |
565 | |
| 574 | // Prepare wakeup buttons. |
566 | // Prepare wakeup buttons. |
| 575 | err_code = bsp_btn_ble_sleep_mode_prepare(); |
567 | err_code = bsp_btn_ble_sleep_mode_prepare(); |
| 576 | APP_ERROR_CHECK(err_code); |
568 | APP_ERROR_CHECK(err_code); |
| 577 | |
569 | |
| 578 | // Go to system-off mode (this function will not return; wakeup will cause a reset). |
570 | // Go to system-off mode (this function will not return; wakeup will cause a reset). |
| 579 | err_code = sd_power_system_off(); |
571 | err_code = sd_power_system_off(); |
| 580 | APP_ERROR_CHECK(err_code); |
572 | APP_ERROR_CHECK(err_code); |
| 581 | } |
573 | } |
| 582 | |
574 | |
| 583 | |
575 | |
| 584 | /**@brief Function for handling advertising events. |
576 | /**@brief Function for handling advertising events. |
| 585 | * |
577 | * |
| 586 | * @param[in] ble_adv_evt Advertising event. |
578 | * @param[in] ble_adv_evt Advertising event. |
| 587 | */ |
579 | */ |
| 588 | static void on_adv_evt(ble_adv_evt_t ble_adv_evt) |
580 | static void on_adv_evt(ble_adv_evt_t ble_adv_evt) |
| 589 | { |
581 | { |
| 590 | ret_code_t err_code; |
582 | ret_code_t err_code; |
| 591 | |
583 | |
| 592 | switch (ble_adv_evt) |
584 | switch (ble_adv_evt) |
| 593 | { |
585 | { |
| 594 | case BLE_ADV_EVT_FAST: |
586 | case BLE_ADV_EVT_FAST: |
| 595 | NRF_LOG_INFO("Fast advertising"); |
587 | NRF_LOG_INFO("Fast advertising"); |
| 596 | err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); |
588 | err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); |
| 597 | APP_ERROR_CHECK(err_code); |
589 | APP_ERROR_CHECK(err_code); |
| 598 | break; // BLE_ADV_EVT_FAST |
590 | break; // BLE_ADV_EVT_FAST |
| 599 | |
591 | |
| 600 | case BLE_ADV_EVT_IDLE: |
592 | case BLE_ADV_EVT_IDLE: |
| 601 | sleep_mode_enter(); |
593 | sleep_mode_enter(); |
| 602 | break; // BLE_ADV_EVT_IDLE |
594 | break; // BLE_ADV_EVT_IDLE |
| 603 | |
595 | |
| 604 | default: |
596 | default: |
| 605 | break; |
597 | break; |
| 606 | } |
598 | } |
| 607 | } |
599 | } |
| 608 | |
600 | |
| 609 | |
601 | |
| 610 | /**@brief Function for handling BLE events. |
602 | /**@brief Function for handling BLE events. |
| 611 | * |
603 | * |
| 612 | * @param[in] p_ble_evt Bluetooth stack event. |
604 | * @param[in] p_ble_evt Bluetooth stack event. |
| 613 | * @param[in] p_context Unused. |
605 | * @param[in] p_context Unused. |
| 614 | */ |
606 | */ |
| 615 | static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) |
607 | static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) |
| 616 | { |
608 | { |
| 617 | ret_code_t err_code; |
609 | ret_code_t err_code; |
| 618 | |
610 | |
| 619 | pm_handler_secure_on_connection(p_ble_evt); |
611 | pm_handler_secure_on_connection(p_ble_evt); |
| 620 | |
612 | |
| 621 | switch (p_ble_evt->header.evt_id) |
613 | switch (p_ble_evt->header.evt_id) |
| 622 | { |
614 | { |
| 623 | case BLE_GAP_EVT_DISCONNECTED: |
615 | case BLE_GAP_EVT_DISCONNECTED: |
| 624 | { |
616 | { |
| 625 | NRF_LOG_INFO("Disconnected"); |
617 | NRF_LOG_INFO("Disconnected"); |
| 626 | m_conn_handle = BLE_CONN_HANDLE_INVALID; |
618 | m_conn_handle = BLE_CONN_HANDLE_INVALID; |
| 627 | // Check if the last connected peer had not used MITM, if so, delete its bond information. |
619 | // Check if the last connected peer had not used MITM, if so, delete its bond information. |
| 628 | if (m_peer_to_be_deleted != PM_PEER_ID_INVALID) |
620 | if (m_peer_to_be_deleted != PM_PEER_ID_INVALID) |
| 629 | { |
621 | { |
| 630 | err_code = pm_peer_delete(m_peer_to_be_deleted); |
622 | err_code = pm_peer_delete(m_peer_to_be_deleted); |
| 631 | APP_ERROR_CHECK(err_code); |
623 | APP_ERROR_CHECK(err_code); |
| 632 | NRF_LOG_DEBUG("Collector's bond deleted"); |
624 | NRF_LOG_DEBUG("Collector's bond deleted"); |
| 633 | m_peer_to_be_deleted = PM_PEER_ID_INVALID; |
625 | m_peer_to_be_deleted = PM_PEER_ID_INVALID; |
| 634 | } |
626 | } |
| 635 | } break; |
627 | } break; |
| 636 | |
628 | |
| 637 | case BLE_GAP_EVT_CONNECTED: |
629 | case BLE_GAP_EVT_CONNECTED: |
| 638 | { |
630 | { |
| 639 | NRF_LOG_INFO("Connected"); |
631 | NRF_LOG_INFO("Connected"); |
| 640 | m_peer_to_be_deleted = PM_PEER_ID_INVALID; |
632 | m_peer_to_be_deleted = PM_PEER_ID_INVALID; |
| 641 | err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); |
633 | err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); |
| 642 | APP_ERROR_CHECK(err_code); |
634 | APP_ERROR_CHECK(err_code); |
| 643 | m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; |
635 | m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; |
| 644 | err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle); |
636 | err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle); |
| 645 | APP_ERROR_CHECK(err_code); |
637 | APP_ERROR_CHECK(err_code); |
| 646 | // Start Security Request timer. |
638 | // Start Security Request timer. |
| 647 | } break; |
639 | } break; |
| 648 | |
640 | |
| 649 | case BLE_GAP_EVT_PHY_UPDATE_REQUEST: |
641 | case BLE_GAP_EVT_PHY_UPDATE_REQUEST: |
| 650 | { |
642 | { |
| 651 | NRF_LOG_DEBUG("PHY update request."); |
643 | NRF_LOG_DEBUG("PHY update request."); |
| 652 | ble_gap_phys_t const phys = |
644 | ble_gap_phys_t const phys = |
| 653 | { |
645 | { |
| 654 | .rx_phys = BLE_GAP_PHY_AUTO, |
646 | .rx_phys = BLE_GAP_PHY_AUTO, |
| 655 | .tx_phys = BLE_GAP_PHY_AUTO, |
647 | .tx_phys = BLE_GAP_PHY_AUTO, |
| 656 | }; |
648 | }; |
| 657 | err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys); |
649 | err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys); |
| 658 | APP_ERROR_CHECK(err_code); |
650 | APP_ERROR_CHECK(err_code); |
| 659 | } break; |
651 | } break; |
| 660 | |
652 | |
| 661 | case BLE_GATTC_EVT_TIMEOUT: |
653 | case BLE_GATTC_EVT_TIMEOUT: |
| 662 | // Disconnect on GATT Client timeout event. |
654 | // Disconnect on GATT Client timeout event. |
| 663 | NRF_LOG_DEBUG("GATT Client Timeout."); |
655 | NRF_LOG_DEBUG("GATT Client Timeout."); |
| 664 | err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, |
656 | err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, |
| 665 | BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); |
657 | BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); |
| 666 | APP_ERROR_CHECK(err_code); |
658 | APP_ERROR_CHECK(err_code); |
| 667 | break; |
659 | break; |
| 668 | |
660 | |
| 669 | case BLE_GATTS_EVT_TIMEOUT: |
661 | case BLE_GATTS_EVT_TIMEOUT: |
| 670 | // Disconnect on GATT Server timeout event. |
662 | // Disconnect on GATT Server timeout event. |
| 671 | NRF_LOG_DEBUG("GATT Server Timeout."); |
663 | NRF_LOG_DEBUG("GATT Server Timeout."); |
| 672 | err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, |
664 | err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, |
| 673 | BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); |
665 | BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); |
| 674 | APP_ERROR_CHECK(err_code); |
666 | APP_ERROR_CHECK(err_code); |
| 675 | break; |
667 | break; |
| 676 | |
668 | |
| 677 | case BLE_GAP_EVT_SEC_PARAMS_REQUEST: |
669 | case BLE_GAP_EVT_SEC_PARAMS_REQUEST: |
| 678 | NRF_LOG_DEBUG("BLE_GAP_EVT_SEC_PARAMS_REQUEST"); |
670 | NRF_LOG_DEBUG("BLE_GAP_EVT_SEC_PARAMS_REQUEST"); |
| 679 | break; |
671 | break; |
| 680 | |
672 | |
| 681 | case BLE_GAP_EVT_PASSKEY_DISPLAY: |
673 | case BLE_GAP_EVT_PASSKEY_DISPLAY: |
| 682 | { |
674 | { |
| 683 | char passkey[PASSKEY_LENGTH + 1]; |
675 | char passkey[PASSKEY_LENGTH + 1]; |
| 684 | memcpy(passkey, p_ble_evt->evt.gap_evt.params.passkey_display.passkey, PASSKEY_LENGTH); |
676 | memcpy(passkey, p_ble_evt->evt.gap_evt.params.passkey_display.passkey, PASSKEY_LENGTH); |
| 685 | passkey[PASSKEY_LENGTH] = 0; |
677 | passkey[PASSKEY_LENGTH] = 0; |
| 686 | |
678 | |
| 687 | NRF_LOG_INFO("Passkey: %s", nrf_log_push(passkey)); |
679 | NRF_LOG_INFO("Passkey: %s", nrf_log_push(passkey)); |
| 688 | } break; |
680 | } break; |
| 689 | |
681 | |
| 690 | case BLE_GAP_EVT_AUTH_KEY_REQUEST: |
682 | case BLE_GAP_EVT_AUTH_KEY_REQUEST: |
| 691 | NRF_LOG_INFO("BLE_GAP_EVT_AUTH_KEY_REQUEST"); |
683 | NRF_LOG_INFO("BLE_GAP_EVT_AUTH_KEY_REQUEST"); |
| 692 | break; |
684 | break; |
| 693 | |
685 | |
| 694 | case BLE_GAP_EVT_LESC_DHKEY_REQUEST: |
686 | case BLE_GAP_EVT_LESC_DHKEY_REQUEST: |
| 695 | NRF_LOG_INFO("BLE_GAP_EVT_LESC_DHKEY_REQUEST"); |
687 | NRF_LOG_INFO("BLE_GAP_EVT_LESC_DHKEY_REQUEST"); |
| 696 | break; |
688 | break; |
| 697 | |
689 | |
| 698 | case BLE_GAP_EVT_AUTH_STATUS: |
690 | case BLE_GAP_EVT_AUTH_STATUS: |
| 699 | NRF_LOG_INFO("BLE_GAP_EVT_AUTH_STATUS: status=0x%x bond=0x%x lv4: %d kdist_own:0x%x kdist_peer:0x%x", |
691 | NRF_LOG_INFO("BLE_GAP_EVT_AUTH_STATUS: status=0x%x bond=0x%x lv4: %d kdist_own:0x%x kdist_peer:0x%x", |
| 700 | p_ble_evt->evt.gap_evt.params.auth_status.auth_status, |
692 | p_ble_evt->evt.gap_evt.params.auth_status.auth_status, |
| 701 | p_ble_evt->evt.gap_evt.params.auth_status.bonded, |
693 | p_ble_evt->evt.gap_evt.params.auth_status.bonded, |
| 702 | p_ble_evt->evt.gap_evt.params.auth_status.sm1_levels.lv4, |
694 | p_ble_evt->evt.gap_evt.params.auth_status.sm1_levels.lv4, |
| 703 | *((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status.kdist_own), |
695 | *((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status.kdist_own), |
| 704 | *((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status.kdist_peer)); |
696 | *((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status.kdist_peer)); |
| 705 | break; |
697 | break; |
| 706 | |
698 | |
| 707 | default: |
699 | default: |
| 708 | // No implementation needed. |
700 | // No implementation needed. |
| 709 | break; |
701 | break; |
| 710 | } |
702 | } |
| 711 | } |
703 | } |
| 712 | |
704 | |
| 713 | |
705 | |
| 714 | /**@brief Function for initializing the BLE stack. |
706 | /**@brief Function for initializing the BLE stack. |
| 715 | * |
707 | * |
| 716 | * @details Initializes the SoftDevice and the BLE event interrupt. |
708 | * @details Initializes the SoftDevice and the BLE event interrupt. |
| 717 | */ |
709 | */ |
| 718 | static void ble_stack_init(void) |
710 | static void ble_stack_init(void) |
| 719 | { |
711 | { |
| 720 | ret_code_t err_code; |
712 | ret_code_t err_code; |
| 721 | |
713 | |
| 722 | err_code = nrf_sdh_enable_request(); |
714 | err_code = nrf_sdh_enable_request(); |
| 723 | APP_ERROR_CHECK(err_code); |
715 | APP_ERROR_CHECK(err_code); |
| 724 | |
716 | |
| 725 | // Configure the BLE stack using the default settings. |
717 | // Configure the BLE stack using the default settings. |
| 726 | // Fetch the start address of the application RAM. |
718 | // Fetch the start address of the application RAM. |
| 727 | uint32_t ram_start = 0; |
719 | uint32_t ram_start = 0; |
| 728 | err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start); |
720 | err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start); |
| 729 | APP_ERROR_CHECK(err_code); |
721 | APP_ERROR_CHECK(err_code); |
| 730 | |
722 | |
| 731 | // Enable BLE stack. |
723 | // Enable BLE stack. |
| 732 | err_code = nrf_sdh_ble_enable(&ram_start); |
724 | err_code = nrf_sdh_ble_enable(&ram_start); |
| 733 | APP_ERROR_CHECK(err_code); |
725 | APP_ERROR_CHECK(err_code); |
| 734 | |
726 | |
| 735 | // Register a handler for BLE events. |
727 | // Register a handler for BLE events. |
| 736 | NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); |
728 | NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); |
| 737 | } |
729 | } |
| 738 | |
730 | |
| 739 | |
731 | |
| 740 | /**@brief Function for handling events from the BSP module. |
732 | /**@brief Function for handling events from the BSP module. |
| 741 | * |
733 | * |
| 742 | * @param[in] event Event generated by button press. |
734 | * @param[in] event Event generated by button press. |
| 743 | */ |
735 | */ |
| 744 | static void bsp_event_handler(bsp_event_t event) |
736 | static void bsp_event_handler(bsp_event_t event) |
| 745 | { |
737 | { |
| 746 | ret_code_t err_code; |
738 | ret_code_t err_code; |
| 747 | |
739 | |
| 748 | switch (event) |
740 | switch (event) |
| 749 | { |
741 | { |
| 750 | case BSP_EVENT_SLEEP: |
742 | case BSP_EVENT_SLEEP: |
| 751 | sleep_mode_enter(); |
743 | sleep_mode_enter(); |
| 752 | break; // BSP_EVENT_SLEEP |
744 | break; // BSP_EVENT_SLEEP |
| 753 | |
745 | |
| 754 | case BSP_EVENT_DISCONNECT: |
746 | case BSP_EVENT_DISCONNECT: |
| 755 | err_code = sd_ble_gap_disconnect(m_conn_handle, |
747 | err_code = sd_ble_gap_disconnect(m_conn_handle, |
| 756 | BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); |
748 | BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); |
| 757 | if (err_code != NRF_ERROR_INVALID_STATE) |
749 | if (err_code != NRF_ERROR_INVALID_STATE) |
| 758 | { |
750 | { |
| 759 | APP_ERROR_CHECK(err_code); |
751 | APP_ERROR_CHECK(err_code); |
| 760 | } |
752 | } |
| 761 | break; // BSP_EVENT_DISCONNECT |
753 | break; // BSP_EVENT_DISCONNECT |
| 762 | |
754 | |
| 763 | case BSP_EVENT_WHITELIST_OFF: |
755 | case BSP_EVENT_WHITELIST_OFF: |
| 764 | if (m_conn_handle == BLE_CONN_HANDLE_INVALID) |
756 | if (m_conn_handle == BLE_CONN_HANDLE_INVALID) |
| 765 | { |
757 | { |
| 766 | err_code = ble_advertising_restart_without_whitelist(&m_advertising); |
758 | err_code = ble_advertising_restart_without_whitelist(&m_advertising); |
| 767 | if (err_code != NRF_ERROR_INVALID_STATE) |
759 | if (err_code != NRF_ERROR_INVALID_STATE) |
| 768 | { |
760 | { |
| 769 | APP_ERROR_CHECK(err_code); |
761 | APP_ERROR_CHECK(err_code); |
| 770 | } |
762 | } |
| 771 | } |
763 | } |
| 772 | break; // BSP_EVENT_WHITELIST_OFF |
764 | break; // BSP_EVENT_WHITELIST_OFF |
| 773 | |
765 | |
| 774 | case BSP_EVENT_KEY_1: |
766 | case BSP_EVENT_KEY_1: |
| 775 | read_glucose_measurement(); |
767 | read_glucose_measurement(); |
| 776 | break; // BSP_EVENT_KEY_1 |
768 | break; // BSP_EVENT_KEY_1 |
| 777 | |
769 | |
| 778 | default: |
770 | default: |
| 779 | break; |
771 | break; |
| 780 | } |
772 | } |
| 781 | } |
773 | } |
| 782 | |
774 | |
| 783 | |
775 | |
| 784 | /**@brief Function for the Peer Manager initialization. |
776 | /**@brief Function for the Peer Manager initialization. |
| 785 | */ |
777 | */ |
| 786 | static void peer_manager_init(void) |
778 | static void peer_manager_init(void) |
| 787 | { |
779 | { |
| 788 | ble_gap_sec_params_t sec_param; |
780 | ble_gap_sec_params_t sec_param; |
| 789 | ret_code_t err_code; |
781 | ret_code_t err_code; |
| 790 | |
782 | |
| 791 | err_code = pm_init(); |
783 | err_code = pm_init(); |
| 792 | APP_ERROR_CHECK(err_code); |
784 | APP_ERROR_CHECK(err_code); |
| 793 | |
785 | |
| 794 | memset(&sec_param, 0, sizeof(ble_gap_sec_params_t)); |
786 | memset(&sec_param, 0, sizeof(ble_gap_sec_params_t)); |
| 795 | |
787 | |
| 796 | // Security parameters to be used for all security procedures. |
788 | // Security parameters to be used for all security procedures. |
| 797 | sec_param.bond = SEC_PARAM_BOND; |
789 | sec_param.bond = SEC_PARAM_BOND; |
| 798 | sec_param.mitm = SEC_PARAM_MITM; |
790 | sec_param.mitm = SEC_PARAM_MITM; |
| 799 | sec_param.lesc = SEC_PARAM_LESC; |
791 | sec_param.lesc = SEC_PARAM_LESC; |
| 800 | sec_param.keypress = SEC_PARAM_KEYPRESS; |
792 | sec_param.keypress = SEC_PARAM_KEYPRESS; |
| 801 | sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; |
793 | sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; |
| 802 | sec_param.oob = SEC_PARAM_OOB; |
794 | sec_param.oob = SEC_PARAM_OOB; |
| 803 | sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; |
795 | sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; |
| 804 | sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; |
796 | sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; |
| 805 | sec_param.kdist_own.enc = 1; |
797 | sec_param.kdist_own.enc = 1; |
| 806 | sec_param.kdist_own.id = 1; |
798 | sec_param.kdist_own.id = 1; |
| 807 | sec_param.kdist_peer.enc = 1; |
799 | sec_param.kdist_peer.enc = 1; |
| 808 | sec_param.kdist_peer.id = 1; |
800 | sec_param.kdist_peer.id = 1; |
| 809 | |
801 | |
| 810 | err_code = pm_sec_params_set(&sec_param); |
802 | err_code = pm_sec_params_set(&sec_param); |
| 811 | APP_ERROR_CHECK(err_code); |
803 | APP_ERROR_CHECK(err_code); |
| 812 | |
804 | |
| 813 | err_code = pm_register(pm_evt_handler); |
805 | err_code = pm_register(pm_evt_handler); |
| 814 | APP_ERROR_CHECK(err_code); |
806 | APP_ERROR_CHECK(err_code); |
| 815 | } |
807 | } |
| 816 | |
808 | |
| 817 | |
809 | |
| 818 | /**@brief Clear bond information from persistent storage. |
810 | /**@brief Clear bond information from persistent storage. |
| 819 | */ |
811 | */ |
| 820 | static void delete_bonds(void) |
812 | static void delete_bonds(void) |
| 821 | { |
813 | { |
| 822 | ret_code_t err_code; |
814 | ret_code_t err_code; |
| 823 | |
815 | |
| 824 | NRF_LOG_INFO("Erase bonds!"); |
816 | NRF_LOG_INFO("Erase bonds!"); |
| 825 | |
817 | |
| 826 | err_code = pm_peers_delete(); |
818 | err_code = pm_peers_delete(); |
| 827 | APP_ERROR_CHECK(err_code); |
819 | APP_ERROR_CHECK(err_code); |
| 828 | } |
820 | } |
| 829 | |
821 | |
| 830 | |
822 | |
| 831 | /**@brief Function for initializing the Advertising functionality. |
823 | /**@brief Function for initializing the Advertising functionality. |
| 832 | * |
824 | * |
| 833 | * @details Encodes the required advertising data and passes it to the stack. |
825 | * @details Encodes the required advertising data and passes it to the stack. |
| 834 | * Also builds a structure to be passed to the stack when starting advertising. |
826 | * Also builds a structure to be passed to the stack when starting advertising. |
| 835 | */ |
827 | */ |
| 836 | static void advertising_init(void) |
828 | static void advertising_init(void) |
| 837 | { |
829 | { |
| 838 | uint32_t err_code; |
830 | uint32_t err_code; |
| 839 | ble_advertising_init_t init; |
831 | ble_advertising_init_t init; |
| 840 | |
832 | |
| 841 | memset(&init, 0, sizeof(init)); |
833 | memset(&init, 0, sizeof(init)); |
| 842 | |
834 | |
| 843 | init.advdata.name_type = BLE_ADVDATA_FULL_NAME; |
835 | init.advdata.name_type = BLE_ADVDATA_FULL_NAME; |
| 844 | init.advdata.include_appearance = true; |
836 | init.advdata.include_appearance = true; |
| 845 | init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; |
837 | init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; |
| 846 | init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); |
838 | init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); |
| 847 | init.advdata.uuids_complete.p_uuids = m_adv_uuids; |
839 | init.advdata.uuids_complete.p_uuids = m_adv_uuids; |
| 848 | |
840 | |
| 849 | init.config.ble_adv_fast_enabled = true; |
841 | init.config.ble_adv_fast_enabled = true; |
| 850 | init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; |
842 | init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; |
| 851 | init.config.ble_adv_fast_timeout = APP_ADV_DURATION; |
843 | init.config.ble_adv_fast_timeout = APP_ADV_DURATION; |
| 852 | |
844 | |
| 853 | init.evt_handler = on_adv_evt; |
845 | init.evt_handler = on_adv_evt; |
| 854 | |
846 | |
| 855 | err_code = ble_advertising_init(&m_advertising, &init); |
847 | err_code = ble_advertising_init(&m_advertising, &init); |
| 856 | APP_ERROR_CHECK(err_code); |
848 | APP_ERROR_CHECK(err_code); |
| 857 | |
849 | |
| 858 | ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); |
850 | ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); |
| 859 | } |
851 | } |
| 860 | |
852 | |
| 861 | |
853 | |
| 862 | /**@brief Function for initializing buttons and leds. |
854 | /**@brief Function for initializing buttons and leds. |
| 863 | * |
855 | * |
| 864 | * @param[out] p_erase_bonds Will be true if the clear bonding button was pressed to wake the application up. |
856 | * @param[out] p_erase_bonds Will be true if the clear bonding button was pressed to wake the application up. |
| 865 | */ |
857 | */ |
| 866 | static void buttons_leds_init(bool * p_erase_bonds) |
858 | static void buttons_leds_init(bool * p_erase_bonds) |
| 867 | { |
859 | { |
| 868 | ret_code_t err_code; |
860 | ret_code_t err_code; |
| 869 | bsp_event_t startup_event; |
861 | bsp_event_t startup_event; |
| 870 | |
862 | |
| 871 | err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler); |
863 | err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler); |
| 872 | APP_ERROR_CHECK(err_code); |
864 | APP_ERROR_CHECK(err_code); |
| 873 | |
865 | |
| 874 | err_code = bsp_btn_ble_init(NULL, &startup_event); |
866 | err_code = bsp_btn_ble_init(NULL, &startup_event); |
| 875 | APP_ERROR_CHECK(err_code); |
867 | APP_ERROR_CHECK(err_code); |
| 876 | |
868 | |
| 877 | *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA); |
869 | *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA); |
| 878 | } |
870 | } |
| 879 | |
871 | |
| 880 | |
872 | |
| 881 | /**@brief Function for initializing the nrf log module. |
873 | /**@brief Function for initializing the nrf log module. |
| 882 | */ |
874 | */ |
| 883 | static void log_init(void) |
875 | static void log_init(void) |
| 884 | { |
876 | { |
| 885 | ret_code_t err_code = NRF_LOG_INIT(NULL); |
877 | ret_code_t err_code = NRF_LOG_INIT(NULL); |
| 886 | APP_ERROR_CHECK(err_code); |
878 | APP_ERROR_CHECK(err_code); |
| 887 | |
879 | |
| 888 | NRF_LOG_DEFAULT_BACKENDS_INIT(); |
880 | NRF_LOG_DEFAULT_BACKENDS_INIT(); |
| 889 | } |
881 | } |
| 890 | |
882 | |
| 891 | |
883 | |
| 892 | /**@brief Function for initializing power management. |
884 | /**@brief Function for initializing power management. |
| 893 | */ |
885 | */ |
| 894 | static void power_management_init(void) |
886 | static void power_management_init(void) |
| 895 | { |
887 | { |
| 896 | ret_code_t err_code; |
888 | ret_code_t err_code; |
| 897 | err_code = nrf_pwr_mgmt_init(); |
889 | err_code = nrf_pwr_mgmt_init(); |
| 898 | APP_ERROR_CHECK(err_code); |
890 | APP_ERROR_CHECK(err_code); |
| 899 | } |
891 | } |
| 900 | |
892 | |
| 901 | |
893 | |
| 902 | /**@brief Function for handling the idle state (main loop). |
894 | /**@brief Function for handling the idle state (main loop). |
| 903 | * |
895 | * |
| 904 | * @details If there is no pending log operation, then sleep until next the next event occurs. |
896 | * @details If there is no pending log operation, then sleep until next the next event occurs. |
| 905 | */ |
897 | */ |
| 906 | static void idle_state_handle(void) |
898 | static void idle_state_handle(void) |
| 907 | { |
899 | { |
| 908 | ret_code_t err_code; |
900 | ret_code_t err_code; |
| 909 | |
901 | |
| 910 | err_code = nrf_ble_lesc_request_handler(); |
902 | err_code = nrf_ble_lesc_request_handler(); |
| 911 | APP_ERROR_CHECK(err_code); |
903 | APP_ERROR_CHECK(err_code); |
| 912 | |
904 | |
| 913 | if (NRF_LOG_PROCESS() == false) |
905 | if (NRF_LOG_PROCESS() == false) |
| 914 | { |
906 | { |
| 915 | nrf_pwr_mgmt_run(); |
907 | nrf_pwr_mgmt_run(); |
| 916 | } |
908 | } |
| 917 | } |
909 | } |
| 918 | |
910 | |
| 919 | |
911 | |
| 920 | /**@brief Function for starting advertising. |
912 | /**@brief Function for starting advertising. |
| 921 | */ |
913 | */ |
| 922 | static void advertising_start(bool erase_bonds) |
914 | static void advertising_start(bool erase_bonds) |
| 923 | { |
915 | { |
| 924 | if (erase_bonds == true) |
916 | if (erase_bonds == true) |
| 925 | { |
917 | { |
| 926 | delete_bonds(); |
918 | delete_bonds(); |
| 927 | // Advertising is started by PM_EVT_PEERS_DELETE_SUCCEEDED event. |
919 | // Advertising is started by PM_EVT_PEERS_DELETE_SUCCEEDED event. |
| 928 | } |
920 | } |
| 929 | else |
921 | else |
| 930 | { |
922 | { |
| 931 | ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); |
923 | ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); |
| 932 | |
924 | |
| 933 | APP_ERROR_CHECK(err_code); |
925 | APP_ERROR_CHECK(err_code); |
| 934 | } |
926 | } |
| 935 | } |
927 | } |
| 936 | |
928 | |
| 937 | |
929 | |
| 938 | /**@brief Function for application main entry. |
930 | /**@brief Function for application main entry. |
| 939 | */ |
931 | */ |
| 940 | int main(void) |
932 | int main(void) |
| 941 | { |
933 | { |
| 942 | bool erase_bonds; |
934 | bool erase_bonds; |
| 943 | |
935 | |
| 944 | // Initialize. |
936 | // Initialize. |
| 945 | log_init(); |
937 | log_init(); |
| 946 | timers_init(); |
938 | timers_init(); |
| 947 | buttons_leds_init(&erase_bonds); |
939 | buttons_leds_init(&erase_bonds); |
| 948 | power_management_init(); |
940 | power_management_init(); |
| 949 | ble_stack_init(); |
941 | ble_stack_init(); |
| 950 | gap_params_init(); |
942 | gap_params_init(); |
| 951 | gatt_init(); |
943 | gatt_init(); |
| 952 | advertising_init(); |
944 | advertising_init(); |
| 953 | services_init(); |
945 | services_init(); |
| 954 | sensor_simulator_init(); |
946 | sensor_simulator_init(); |
| 955 | conn_params_init(); |
947 | conn_params_init(); |
| 956 | peer_manager_init(); |
948 | peer_manager_init(); |
| 957 | |
949 | |
| 958 | // Start execution. |
950 | // Start execution. |
| 959 | NRF_LOG_INFO("Glucose example started."); |
951 | NRF_LOG_INFO("Glucose example started."); |
| 960 | application_timers_start(); |
952 | application_timers_start(); |
| 961 | advertising_start(erase_bonds); |
953 | advertising_start(erase_bonds); |
| 962 | |
954 | |
| 963 | // Enter main loop. |
955 | // Enter main loop. |
| 964 | for (;;) |
956 | for (;;) |
| 965 | { |
957 | { |
| 966 | idle_state_handle(); |
958 | idle_state_handle(); |
| 967 | |
| |
| 968 | if( ( peer_to_create ) ) |
| |
| 969 | { |
| |
| 970 | peer_to_create = false; |
| |
| 971 | |
| |
| 972 | ret_code_t err_code; |
| |
| 973 | uint32_t peer_rank = 0; |
| |
| 974 | uint32_t length = sizeof(peer_rank); |
| |
| 975 | pm_peer_data_t peer_data = {.p_peer_rank = &peer_rank}; |
| |
| 976 | pm_peer_id_t peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID); |
| |
| 977 | |
| |
| 978 | while( peer_id != PM_PEER_ID_INVALID) |
| |
| 979 | { |
| |
| 980 | |
| |
| 981 | |
| |
| 982 | err_code = pm_peer_data_load(peer_id, |
| |
| 983 | PM_PEER_DATA_ID_PEER_RANK, |
| |
| 984 | &peer_data, |
| |
| 985 | &length); |
| |
| 986 | NRF_LOG_INFO("Peer ID %d, rank %d", peer_id, peer_rank ); |
| |
| 987 | peer_id = pm_next_peer_id_get( peer_id ); |
| |
| 988 | } |
| |
| 989 | |
| |
| 990 | } |
| |
| 991 | |
| |
| 992 | NRF_LOG_PROCESS(); |
| |
| 993 | } |
959 | } |
| 994 | } |
960 | } |
| 995 | |
961 | |
| 996 | |
962 | |
| 997 | /** |
963 | /** |
| 998 | * @} |
964 | * @} |
| 999 | */ |
965 | */ |
| 1000 | |
966 | |