commissioning.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077
  1. /**
  2. * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  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
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  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
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  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
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  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
  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.
  38. *
  39. */
  40. #ifdef COMMISSIONING_ENABLED
  41. #include <string.h>
  42. #include "boards.h"
  43. #include "ble_hci.h"
  44. #include "nrf_soc.h"
  45. #include "app_error.h"
  46. #include "fds.h"
  47. #include "ble_advdata.h"
  48. #include "commissioning.h"
  49. #include "nordic_common.h"
  50. #include "ble_srv_common.h"
  51. #include "sdk_config.h"
  52. #define MINIMUM_ACTION_DELAY 2 /**< Delay before executing an action after the control point was written (in seconds). */
  53. #define SEC_PARAM_BOND 0 /**< Perform bonding. */
  54. #define SEC_PARAM_MITM 1 /**< Man In The Middle protection required (applicable when display module is detected). */
  55. #define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_KEYBOARD_ONLY /**< Display I/O capabilities. */
  56. #define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */
  57. #define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */
  58. #define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */
  59. #define COMM_FDS_FILE_ID 0xCAFE /**< The ID of the file that the record belongs to. */
  60. #define COMM_FDS_RECORD_KEY 0xBEAF /**< The record key of FDS record that keeps node settings. */
  61. #define NUMBER_OF_COMMISSIONING_TIMERS 4
  62. #define TIMER_INDEX_DELAYED_ACTION 0
  63. #define TIMER_INDEX_CONFIG_MODE 1
  64. #define TIMER_INDEX_JOINING_MODE 2
  65. #define TIMER_INDEX_IDENTITY_MODE 3
  66. #define SEC_TO_MILLISEC(PARAM) (PARAM * 1000)
  67. static commissioning_settings_t m_node_settings; /**< All node settings as configured through the Node Configuration Service. */
  68. static commissioning_evt_handler_t m_commissioning_evt_handler; /**< Commissioning event handler of the parent layer. */
  69. static bool m_power_off_on_failure = false; /**< Power off on failure setting from the last NCFGS event. */
  70. static commissioning_timer_t m_commissioning_timers[NUMBER_OF_COMMISSIONING_TIMERS];
  71. static ipv6_medium_ble_gap_params_t m_config_mode_gap_params; /**< Advertising parameters in Config mode. */
  72. static ipv6_medium_ble_adv_params_t m_config_mode_adv_params; /**< GAP parameters in Config mode. */
  73. static ipv6_medium_ble_gap_params_t m_joining_mode_gap_params; /**< Advertising parameters in Joining mode. */
  74. static ipv6_medium_ble_adv_params_t m_joining_mode_adv_params; /**< GAP parameters in Joining mode. */
  75. static ble_uuid_t m_config_mode_adv_uuids[] = \
  76. {
  77. {BLE_UUID_NODE_CFG_SERVICE, \
  78. BLE_UUID_TYPE_VENDOR_BEGIN}
  79. }; /**< Config mode: List of available service UUIDs in advertisement data. */
  80. static ble_uuid_t m_joining_mode_adv_uuids[] = \
  81. {
  82. {BLE_UUID_IPSP_SERVICE, BLE_UUID_TYPE_BLE}
  83. }; /**< Joining mode: List of available service UUIDs in advertisement data. */
  84. static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the active connection. */
  85. static uint8_t m_current_mode = NODE_MODE_NONE; /**< Current mode value. */
  86. static uint8_t m_next_mode = NODE_MODE_NONE; /**< Value of the mode the node will enter when the timeout handler of m_delayed_action_timer is triggered. */
  87. #if (FDS_ENABLED == 1)
  88. static fds_record_desc_t m_fds_record_desc; /**< Descriptor of FDS record. */
  89. #endif
  90. #define COMM_ENABLE_LOGS 1 /**< Set to 0 to disable debug trace in the module. */
  91. #if COMMISSIONING_CONFIG_LOG_ENABLED
  92. #define NRF_LOG_MODULE_NAME commissioning
  93. #define NRF_LOG_LEVEL COMMISSIONING_CONFIG_LOG_LEVEL
  94. #define NRF_LOG_INFO_COLOR COMMISSIONING_CONFIG_INFO_COLOR
  95. #define NRF_LOG_DEBUG_COLOR COMMISSIONING_CONFIG_DEBUG_COLOR
  96. #include "nrf_log.h"
  97. NRF_LOG_MODULE_REGISTER();
  98. #define COMM_TRC NRF_LOG_DEBUG /**< Used for getting trace of execution in the module. */
  99. #define COMM_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */
  100. #define COMM_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */
  101. #define COMM_ENTRY() COMM_TRC(">> %s", __func__)
  102. #define COMM_EXIT() COMM_TRC("<< %s", __func__)
  103. #else // COMMISSIONING_CONFIG_LOG_ENABLED
  104. #define COMM_TRC(...) /**< Disables traces. */
  105. #define COMM_DUMP(...) /**< Disables dumping of octet streams. */
  106. #define COMM_ERR(...) /**< Disables error logs. */
  107. #define COMM_ENTRY(...)
  108. #define COMM_EXIT(...)
  109. #endif // COMMISSIONING_CONFIG_LOG_ENABLED
  110. /**@brief Function for validating all node settings.
  111. */
  112. static bool settings_are_valid()
  113. {
  114. uint8_t tmp = m_node_settings.poweron_mode;
  115. if (tmp == 0xFF)
  116. {
  117. return false;
  118. }
  119. else
  120. {
  121. return true;
  122. }
  123. }
  124. #if (FDS_ENABLED == 1)
  125. /**@brief Function for updating the node settings in persistent memory.
  126. */
  127. static uint32_t persistent_settings_update(void)
  128. {
  129. uint32_t err_code;
  130. fds_find_token_t token;
  131. memset(&token, 0, sizeof(token));
  132. fds_record_t record;
  133. memset(&record, 0, sizeof(record));
  134. record.file_id = COMM_FDS_FILE_ID;
  135. record.key = COMM_FDS_RECORD_KEY;
  136. record.data.p_data = &m_node_settings;
  137. record.data.length_words = ALIGN_NUM(4, sizeof(commissioning_settings_t))/sizeof(uint32_t);
  138. // Try to find FDS record with node settings.
  139. err_code = fds_record_find(COMM_FDS_FILE_ID, COMM_FDS_RECORD_KEY, &m_fds_record_desc, &token);
  140. if (err_code == FDS_SUCCESS)
  141. {
  142. err_code = fds_record_update(&m_fds_record_desc, &record);
  143. }
  144. else
  145. {
  146. err_code = fds_record_write(&m_fds_record_desc, &record);
  147. }
  148. if (err_code == FDS_ERR_NO_SPACE_IN_FLASH)
  149. {
  150. // Run garbage collector to reclaim the flash space that is occupied by records that have been deleted,
  151. // or that failed to be completely written due to, for example, a power loss.
  152. err_code = fds_gc();
  153. }
  154. return err_code;
  155. }
  156. /**@brief Function for loading node settings from the persistent memory.
  157. */
  158. static void persistent_settings_load(void)
  159. {
  160. uint32_t err_code = FDS_SUCCESS;
  161. fds_flash_record_t record;
  162. fds_find_token_t token;
  163. memset(&token, 0, sizeof(token));
  164. // Try to find FDS record with node settings.
  165. err_code = fds_record_find(COMM_FDS_FILE_ID, COMM_FDS_RECORD_KEY, &m_fds_record_desc, &token);
  166. if (err_code == FDS_SUCCESS)
  167. {
  168. err_code = fds_record_open(&m_fds_record_desc, &record);
  169. if (err_code == FDS_SUCCESS)
  170. {
  171. if (record.p_data)
  172. {
  173. memcpy(&m_node_settings, record.p_data, sizeof(m_node_settings));
  174. }
  175. }
  176. }
  177. }
  178. /**@brief Function for clearing node settings from the persistent memory.
  179. */
  180. static void persistent_settings_clear(void)
  181. {
  182. fds_record_delete(&m_fds_record_desc);
  183. }
  184. /**@brief Function for handling File Data Storage events.
  185. */
  186. static void persistent_settings_cb(fds_evt_t const * p_evt)
  187. {
  188. if (p_evt->id == FDS_EVT_GC)
  189. {
  190. if (settings_are_valid())
  191. {
  192. persistent_settings_update();
  193. }
  194. }
  195. }
  196. /**@brief Function for initializing the File Data Storage module.
  197. */
  198. static uint32_t persistent_settings_init(void)
  199. {
  200. uint32_t err_code;
  201. err_code = fds_init();
  202. if (err_code == FDS_SUCCESS)
  203. {
  204. err_code = fds_register(persistent_settings_cb);
  205. }
  206. return err_code;
  207. }
  208. #endif
  209. /**@brief Function for setting advertisement parameters in Config mode.
  210. */
  211. static void config_mode_adv_params_set(void)
  212. {
  213. COMM_ENTRY();
  214. memset(&m_config_mode_adv_params, 0x00, sizeof(m_config_mode_adv_params));
  215. m_config_mode_adv_params.advdata.name_type = BLE_ADVDATA_FULL_NAME;
  216. m_config_mode_adv_params.advdata.include_appearance = false;
  217. m_config_mode_adv_params.advdata.flags = \
  218. BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
  219. m_config_mode_adv_params.advdata.uuids_complete.uuid_cnt = \
  220. sizeof(m_config_mode_adv_uuids) / sizeof(m_config_mode_adv_uuids[0]);
  221. m_config_mode_adv_params.advdata.uuids_complete.p_uuids = m_config_mode_adv_uuids;
  222. m_config_mode_adv_params.advdata.p_manuf_specific_data = NULL;
  223. if (m_node_settings.id_data_store.identity_data_len > 0)
  224. {
  225. m_config_mode_adv_params.sr_man_specific_data.data.size = \
  226. m_node_settings.id_data_store.identity_data_len;
  227. m_config_mode_adv_params.sr_man_specific_data.data.p_data = \
  228. m_node_settings.id_data_store.identity_data;
  229. m_config_mode_adv_params.sr_man_specific_data.company_identifier = \
  230. COMPANY_IDENTIFIER;
  231. m_config_mode_adv_params.srdata.p_manuf_specific_data = \
  232. &m_config_mode_adv_params.sr_man_specific_data;
  233. }
  234. else
  235. {
  236. m_config_mode_adv_params.srdata.p_manuf_specific_data = NULL;
  237. }
  238. m_config_mode_adv_params.advparams.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
  239. m_config_mode_adv_params.advparams.p_peer_addr = NULL; // Undirected advertisement.
  240. m_config_mode_adv_params.advparams.filter_policy = BLE_GAP_ADV_FP_ANY;
  241. m_config_mode_adv_params.advparams.interval = CONFIG_MODE_ADV_ADV_INTERVAL;
  242. m_config_mode_adv_params.advparams.duration = CONFIG_MODE_ADV_TIMEOUT;
  243. COMM_EXIT();
  244. }
  245. /**@brief Function for setting GAP parameters in Config mode.
  246. */
  247. static void config_mode_gap_params_set(void)
  248. {
  249. COMM_ENTRY();
  250. memset(&m_config_mode_gap_params, 0x00, sizeof(m_config_mode_gap_params));
  251. BLE_GAP_CONN_SEC_MODE_SET_OPEN(&m_config_mode_gap_params.sec_mode);
  252. m_config_mode_gap_params.p_dev_name = (const uint8_t *)CONFIG_MODE_DEVICE_NAME;
  253. m_config_mode_gap_params.dev_name_len = strlen(CONFIG_MODE_DEVICE_NAME);
  254. m_config_mode_gap_params.gap_conn_params.min_conn_interval = \
  255. (uint16_t)CONFIG_MODE_MIN_CONN_INTERVAL;
  256. m_config_mode_gap_params.gap_conn_params.max_conn_interval = \
  257. (uint16_t)CONFIG_MODE_MAX_CONN_INTERVAL;
  258. m_config_mode_gap_params.gap_conn_params.slave_latency = CONFIG_MODE_SLAVE_LATENCY;
  259. m_config_mode_gap_params.gap_conn_params.conn_sup_timeout = CONFIG_MODE_CONN_SUP_TIMEOUT;
  260. COMM_EXIT();
  261. }
  262. /**@brief Function for setting advertisement parameters in Joining mode.
  263. */
  264. static void joining_mode_adv_params_set(void)
  265. {
  266. COMM_ENTRY();
  267. memset(&m_joining_mode_adv_params, 0x00, sizeof(m_joining_mode_adv_params));
  268. if (m_node_settings.ssid_store.ssid_len > 0)
  269. {
  270. m_joining_mode_adv_params.adv_man_specific_data.data.size = \
  271. m_node_settings.ssid_store.ssid_len;
  272. m_joining_mode_adv_params.adv_man_specific_data.data.p_data = \
  273. m_node_settings.ssid_store.ssid;
  274. m_joining_mode_adv_params.adv_man_specific_data.company_identifier = \
  275. COMPANY_IDENTIFIER;
  276. }
  277. m_joining_mode_adv_params.advdata.name_type = BLE_ADVDATA_NO_NAME;
  278. m_joining_mode_adv_params.advdata.include_appearance = false;
  279. m_joining_mode_adv_params.advdata.flags = \
  280. BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
  281. m_joining_mode_adv_params.advdata.uuids_complete.uuid_cnt = \
  282. sizeof(m_joining_mode_adv_uuids) / sizeof(m_joining_mode_adv_uuids[0]);
  283. m_joining_mode_adv_params.advdata.uuids_complete.p_uuids = m_joining_mode_adv_uuids;
  284. if (m_node_settings.ssid_store.ssid_len > 0)
  285. {
  286. m_joining_mode_adv_params.advdata.p_manuf_specific_data = \
  287. &m_joining_mode_adv_params.adv_man_specific_data;
  288. }
  289. else
  290. {
  291. m_joining_mode_adv_params.advdata.p_manuf_specific_data = NULL;
  292. }
  293. if (m_node_settings.id_data_store.identity_data_len > 0)
  294. {
  295. m_joining_mode_adv_params.sr_man_specific_data.data.size = \
  296. m_node_settings.id_data_store.identity_data_len;
  297. m_joining_mode_adv_params.sr_man_specific_data.data.p_data = \
  298. m_node_settings.id_data_store.identity_data;
  299. m_joining_mode_adv_params.sr_man_specific_data.company_identifier = \
  300. COMPANY_IDENTIFIER;
  301. m_joining_mode_adv_params.srdata.p_manuf_specific_data = \
  302. &m_joining_mode_adv_params.sr_man_specific_data;
  303. }
  304. else
  305. {
  306. m_joining_mode_adv_params.srdata.p_manuf_specific_data = NULL;
  307. }
  308. m_joining_mode_adv_params.advparams.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
  309. m_joining_mode_adv_params.advparams.p_peer_addr = NULL; // Undirected advertisement.
  310. m_joining_mode_adv_params.advparams.filter_policy = BLE_GAP_ADV_FP_ANY;
  311. m_joining_mode_adv_params.advparams.interval = APP_ADV_ADV_INTERVAL;
  312. m_joining_mode_adv_params.advparams.duration = APP_ADV_DURATION;
  313. COMM_EXIT();
  314. }
  315. /**@brief Function for setting GAP parameters in Joining mode.
  316. */
  317. static void joining_mode_gap_params_set(void)
  318. {
  319. COMM_ENTRY();
  320. memset(&m_joining_mode_gap_params, 0x00, sizeof(m_joining_mode_gap_params));
  321. BLE_GAP_CONN_SEC_MODE_SET_OPEN(&m_joining_mode_gap_params.sec_mode);
  322. m_joining_mode_gap_params.appearance = BLE_APPEARANCE_UNKNOWN;
  323. m_joining_mode_gap_params.p_dev_name = (const uint8_t *)DEVICE_NAME;
  324. m_joining_mode_gap_params.dev_name_len = strlen(DEVICE_NAME);
  325. m_joining_mode_gap_params.gap_conn_params.min_conn_interval = \
  326. (uint16_t)JOINING_MODE_MIN_CONN_INTERVAL;
  327. m_joining_mode_gap_params.gap_conn_params.max_conn_interval = \
  328. (uint16_t)JOINING_MODE_MAX_CONN_INTERVAL;
  329. m_joining_mode_gap_params.gap_conn_params.slave_latency = JOINING_MODE_SLAVE_LATENCY;
  330. m_joining_mode_gap_params.gap_conn_params.conn_sup_timeout = JOINING_MODE_CONN_SUP_TIMEOUT;
  331. COMM_EXIT();
  332. }
  333. /**@brief Function for starting a timer in the Commissioning module.
  334. *
  335. */
  336. static void commissioning_timer_start(uint8_t index, uint32_t timeout_sec)
  337. {
  338. m_commissioning_timers[index].is_timer_running = true;
  339. m_commissioning_timers[index].current_value_sec = timeout_sec;
  340. }
  341. /**@brief Function for stopping and re-setting a timer in the Commissioning module.
  342. *
  343. */
  344. static void commissioning_timer_stop_reset(uint8_t index)
  345. {
  346. m_commissioning_timers[index].is_timer_running = false;
  347. m_commissioning_timers[index].current_value_sec = 0x00;
  348. }
  349. void commissioning_node_mode_change(uint8_t new_mode)
  350. {
  351. COMM_ENTRY();
  352. commissioning_evt_t commissioning_evt;
  353. memset(&commissioning_evt, 0x00, sizeof(commissioning_evt));
  354. commissioning_evt.p_commissioning_settings = &m_node_settings;
  355. commissioning_evt.power_off_enable_requested = m_power_off_on_failure;
  356. commissioning_timer_stop_reset(TIMER_INDEX_DELAYED_ACTION);
  357. commissioning_timer_stop_reset(TIMER_INDEX_CONFIG_MODE);
  358. commissioning_timer_stop_reset(TIMER_INDEX_JOINING_MODE);
  359. config_mode_gap_params_set();
  360. config_mode_adv_params_set();
  361. joining_mode_gap_params_set();
  362. joining_mode_adv_params_set();
  363. m_current_mode = new_mode;
  364. switch (m_current_mode)
  365. {
  366. case NODE_MODE_CONFIG:
  367. {
  368. commissioning_evt.commissioning_evt_id = COMMISSIONING_EVT_CONFIG_MODE_ENTER;
  369. m_commissioning_evt_handler(&commissioning_evt);
  370. // Start Configuration mode timer.
  371. COMM_TRC("Config mode timeout: %ld seconds", m_node_settings.config_mode_to);
  372. commissioning_timer_start(TIMER_INDEX_CONFIG_MODE, m_node_settings.config_mode_to);
  373. break;
  374. }
  375. case NODE_MODE_JOINING:
  376. {
  377. commissioning_evt.commissioning_evt_id = COMMISSIONING_EVT_JOINING_MODE_ENTER;
  378. m_commissioning_evt_handler(&commissioning_evt);
  379. // Start Joining mode timer.
  380. COMM_TRC("Joining mode timeout: %ld seconds", m_node_settings.joining_mode_to);
  381. commissioning_timer_start(TIMER_INDEX_JOINING_MODE, m_node_settings.joining_mode_to);
  382. break;
  383. }
  384. case NODE_MODE_IDENTITY:
  385. {
  386. commissioning_evt.commissioning_evt_id = COMMISSIONING_EVT_IDENTITY_MODE_ENTER;
  387. m_commissioning_evt_handler(&commissioning_evt);
  388. // Start Identity mode timer.
  389. COMM_TRC("Identity mode timeout: %ld seconds", m_node_settings.id_mode_to);
  390. commissioning_timer_start(TIMER_INDEX_IDENTITY_MODE, m_node_settings.id_mode_to);
  391. break;
  392. }
  393. default:
  394. {
  395. break;
  396. }
  397. }
  398. COMM_EXIT();
  399. }
  400. /**@brief Function for handling the Delayed action timer timeout.
  401. *
  402. * @details This function will be called each time the delayed action timer expires.
  403. *
  404. */
  405. static void action_timeout_handler(void)
  406. {
  407. COMM_ENTRY();
  408. commissioning_node_mode_change(m_next_mode);
  409. COMM_EXIT();
  410. }
  411. /**@brief Function for handling the Config mode timer timeout.
  412. *
  413. * @details This function will be called each time the Config mode timer expires.
  414. *
  415. */
  416. static void config_mode_timeout_handler(void)
  417. {
  418. COMM_ENTRY();
  419. switch (m_node_settings.config_mode_failure)
  420. {
  421. case NCFGS_SOF_NO_CHANGE:
  422. // Fall-through.
  423. case NCFGS_SOF_CONFIG_MODE:
  424. {
  425. commissioning_node_mode_change(NODE_MODE_CONFIG);
  426. break;
  427. }
  428. case NCFGS_SOF_PWR_OFF:
  429. {
  430. LEDS_OFF(LEDS_MASK);
  431. // The main timer in Config mode timed out, power off.
  432. UNUSED_VARIABLE(sd_power_system_off());
  433. break;
  434. }
  435. }
  436. COMM_EXIT();
  437. }
  438. /**@brief Function for handling the Joining mode timer timeout.
  439. *
  440. * @details This function will be called each time the Joining mode timer expires.
  441. *
  442. */
  443. void joining_mode_timeout_handler(void)
  444. {
  445. COMM_ENTRY();
  446. switch (m_node_settings.joining_mode_failure)
  447. {
  448. case NCFGS_SOF_NO_CHANGE:
  449. {
  450. commissioning_node_mode_change(NODE_MODE_JOINING);
  451. break;
  452. }
  453. case NCFGS_SOF_PWR_OFF:
  454. {
  455. LEDS_OFF(LEDS_MASK);
  456. UNUSED_VARIABLE(sd_power_system_off());
  457. break;
  458. }
  459. case NCFGS_SOF_CONFIG_MODE:
  460. {
  461. commissioning_node_mode_change(NODE_MODE_CONFIG);
  462. break;
  463. }
  464. }
  465. COMM_EXIT();
  466. }
  467. /**@brief Function for handling the Identity mode timer timeout.
  468. *
  469. * @details This function will be called each time the Identity mode timer expires.
  470. *
  471. */
  472. void identity_mode_timeout_handler(void)
  473. {
  474. COMM_ENTRY();
  475. commissioning_evt_t commissioning_evt;
  476. memset(&commissioning_evt, 0x00, sizeof(commissioning_evt));
  477. commissioning_evt.commissioning_evt_id = COMMISSIONING_EVT_IDENTITY_MODE_EXIT;
  478. m_commissioning_evt_handler(&commissioning_evt);
  479. COMM_EXIT();
  480. }
  481. void commissioning_joining_mode_timer_ctrl( \
  482. joining_mode_timer_ctrl_cmd_t joining_mode_timer_ctrl_cmd)
  483. {
  484. switch (joining_mode_timer_ctrl_cmd)
  485. {
  486. case JOINING_MODE_TIMER_STOP_RESET:
  487. {
  488. commissioning_timer_stop_reset(TIMER_INDEX_JOINING_MODE);
  489. break;
  490. }
  491. case JOINING_MODE_TIMER_START:
  492. {
  493. commissioning_timer_start(TIMER_INDEX_JOINING_MODE, m_node_settings.joining_mode_to);
  494. break;
  495. }
  496. }
  497. }
  498. void commissioning_gap_params_get(ipv6_medium_ble_gap_params_t ** pp_node_gap_params)
  499. {
  500. switch (m_current_mode)
  501. {
  502. case NODE_MODE_JOINING:
  503. {
  504. *pp_node_gap_params = &m_joining_mode_gap_params;
  505. break;
  506. }
  507. case NODE_MODE_IDENTITY:
  508. // Fall-through.
  509. case NODE_MODE_CONFIG:
  510. {
  511. *pp_node_gap_params = &m_config_mode_gap_params;
  512. break;
  513. }
  514. }
  515. }
  516. void commissioning_adv_params_get(ipv6_medium_ble_adv_params_t ** pp_node_adv_params)
  517. {
  518. switch (m_current_mode)
  519. {
  520. case NODE_MODE_JOINING:
  521. {
  522. *pp_node_adv_params = &m_joining_mode_adv_params;
  523. break;
  524. }
  525. case NODE_MODE_IDENTITY:
  526. // Fall-through.
  527. case NODE_MODE_CONFIG:
  528. {
  529. *pp_node_adv_params = &m_config_mode_adv_params;
  530. break;
  531. }
  532. }
  533. }
  534. /**@brief Function for reading all node settings from the persistent storage.
  535. */
  536. static void read_node_settings(void)
  537. {
  538. memset(&m_node_settings, 0x00, sizeof(m_node_settings));
  539. #if (FDS_ENABLED == 1)
  540. persistent_settings_load();
  541. #endif // FDS_ENABLED
  542. if (m_node_settings.ssid_store.ssid_len > NCFGS_SSID_MAX_LEN)
  543. {
  544. m_node_settings.ssid_store.ssid_len = 0;
  545. }
  546. if (m_node_settings.keys_store.keys_len > NCFGS_KEYS_MAX_LEN)
  547. {
  548. m_node_settings.keys_store.keys_len = 0;
  549. }
  550. if (m_node_settings.id_data_store.identity_data_len > NCFGS_IDENTITY_DATA_MAX_LEN)
  551. {
  552. m_node_settings.id_data_store.identity_data_len = 0;
  553. }
  554. // The duration of each mode needs to be at least 10 second.
  555. m_node_settings.joining_mode_to = \
  556. (m_node_settings.joining_mode_to < 10) ? 10 : m_node_settings.joining_mode_to;
  557. m_node_settings.config_mode_to = \
  558. (m_node_settings.config_mode_to < 10) ? 10 : m_node_settings.config_mode_to;
  559. m_node_settings.id_mode_to = \
  560. (m_node_settings.id_mode_to < 10) ? 10 : m_node_settings.id_mode_to;
  561. }
  562. #if (COMM_ENABLE_LOGS == 1)
  563. /**@brief Function for printing all node settings.
  564. */
  565. static void print_node_settings(void)
  566. {
  567. COMM_TRC("");
  568. COMM_TRC(" Commissioning settings in memory:");
  569. COMM_TRC(" Start mode: %5d", m_node_settings.poweron_mode);
  570. COMM_TRC(" Mode if Joining Mode fails: %5d", m_node_settings.joining_mode_failure);
  571. COMM_TRC(" General timeout in Joining Mode: %5ld", m_node_settings.joining_mode_to);
  572. COMM_TRC(" Mode if Configuration Mode fails: %5d", m_node_settings.config_mode_failure);
  573. COMM_TRC("General timeout in Configuration Mode: %5ld", m_node_settings.config_mode_to);
  574. COMM_TRC(" Identity Mode duration: %5ld", m_node_settings.id_mode_to);
  575. COMM_TRC(" Stored Keys length: %5d", m_node_settings.keys_store.keys_len);
  576. COMM_TRC(" Stored Keys:");
  577. uint8_t ii;
  578. for (ii=0; ii<m_node_settings.keys_store.keys_len; ++ii)
  579. {
  580. COMM_TRC("0x%02X", m_node_settings.keys_store.keys[ii]);
  581. }
  582. COMM_TRC("");
  583. COMM_TRC(" Stored SSID length: %5d", m_node_settings.ssid_store.ssid_len);
  584. COMM_TRC(" Stored SSID:");
  585. for (ii=0; ii<m_node_settings.ssid_store.ssid_len; ++ii)
  586. {
  587. COMM_TRC("0x%02X", m_node_settings.ssid_store.ssid[ii]);
  588. }
  589. COMM_TRC("");
  590. COMM_TRC(" Stored Identity Data length: %5d", m_node_settings.id_data_store.identity_data_len);
  591. COMM_TRC(" Stored Identity Data:");
  592. for (ii=0; ii<m_node_settings.id_data_store.identity_data_len; ++ii)
  593. {
  594. COMM_TRC("0x%02X", m_node_settings.id_data_store.identity_data[ii]);
  595. }
  596. COMM_TRC("");
  597. }
  598. #endif // (COMM_ENABLE_LOGS == 1)
  599. void commissioning_settings_clear(void)
  600. {
  601. COMM_ENTRY();
  602. memset(&m_node_settings, 0x00, sizeof(m_node_settings));
  603. #if (FDS_ENABLED == 1)
  604. persistent_settings_clear();
  605. #endif // FDS_ENABLED
  606. COMM_EXIT();
  607. }
  608. void commissioning_ble_evt_handler(const ble_evt_t * p_ble_evt)
  609. {
  610. uint32_t err_code;
  611. switch (p_ble_evt->header.evt_id)
  612. {
  613. case BLE_GAP_EVT_CONNECTED:
  614. {
  615. m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
  616. commissioning_timer_stop_reset(TIMER_INDEX_DELAYED_ACTION);
  617. commissioning_timer_stop_reset(TIMER_INDEX_CONFIG_MODE);
  618. break;
  619. }
  620. case BLE_GAP_EVT_DISCONNECTED:
  621. {
  622. m_conn_handle = BLE_CONN_HANDLE_INVALID;
  623. if (m_current_mode == NODE_MODE_CONFIG)
  624. {
  625. commissioning_timer_start(TIMER_INDEX_CONFIG_MODE, \
  626. m_node_settings.config_mode_to);
  627. }
  628. if (m_current_mode == NODE_MODE_JOINING)
  629. {
  630. commissioning_timer_start(TIMER_INDEX_JOINING_MODE, \
  631. m_node_settings.joining_mode_to);
  632. }
  633. break;
  634. }
  635. case BLE_GAP_EVT_AUTH_KEY_REQUEST:
  636. {
  637. if (m_current_mode == NODE_MODE_JOINING)
  638. {
  639. // If passkey is shorter than BLE_GAP_PASSKEY_LEN, add '0' character.
  640. if (m_node_settings.keys_store.keys_len < BLE_GAP_PASSKEY_LEN)
  641. {
  642. memset(&m_node_settings.keys_store.keys[m_node_settings.keys_store.keys_len], \
  643. '0', BLE_GAP_PASSKEY_LEN - m_node_settings.keys_store.keys_len);
  644. }
  645. // Short passkey to 6-length character.
  646. m_node_settings.keys_store.keys[BLE_GAP_PASSKEY_LEN] = 0;
  647. COMM_TRC("Stored passkey is: %s", m_node_settings.keys_store.keys);
  648. err_code = sd_ble_gap_auth_key_reply(m_conn_handle, \
  649. BLE_GAP_AUTH_KEY_TYPE_PASSKEY, \
  650. m_node_settings.keys_store.keys);
  651. APP_ERROR_CHECK(err_code);
  652. }
  653. break;
  654. }
  655. case BLE_GAP_EVT_AUTH_STATUS:
  656. {
  657. if (m_current_mode == NODE_MODE_JOINING)
  658. {
  659. COMM_TRC("Status of authentication: %08x", \
  660. p_ble_evt->evt.gap_evt.params.auth_status.auth_status);
  661. }
  662. break;
  663. }
  664. case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
  665. {
  666. if (m_current_mode == NODE_MODE_JOINING)
  667. {
  668. ble_gap_sec_params_t sec_param;
  669. ble_gap_sec_keyset_t keys_exchanged;
  670. memset(&sec_param, 0, sizeof(ble_gap_sec_params_t));
  671. memset(&keys_exchanged, 0, sizeof(ble_gap_sec_keyset_t));
  672. sec_param.bond = SEC_PARAM_BOND;
  673. sec_param.oob = SEC_PARAM_OOB;
  674. sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
  675. sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
  676. sec_param.mitm = SEC_PARAM_MITM;
  677. sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES;
  678. err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle,
  679. BLE_GAP_SEC_STATUS_SUCCESS,
  680. &sec_param,
  681. &keys_exchanged);
  682. APP_ERROR_CHECK(err_code);
  683. }
  684. break;
  685. }
  686. default:
  687. {
  688. break;
  689. }
  690. }
  691. }
  692. void on_ble_ncfgs_evt(ble_ncfgs_data_t * ncfgs_data)
  693. {
  694. COMM_ENTRY();
  695. commissioning_timer_stop_reset(TIMER_INDEX_DELAYED_ACTION);
  696. commissioning_timer_stop_reset(TIMER_INDEX_CONFIG_MODE);
  697. uint32_t mode_duration_sec;
  698. mode_duration_sec = ncfgs_data->ctrlp_value.duration_sec;
  699. mode_duration_sec = (mode_duration_sec == 0) ? 1 : mode_duration_sec;
  700. switch (ncfgs_data->ctrlp_value.opcode)
  701. {
  702. case NCFGS_OPCODE_GOTO_JOINING_MODE:
  703. {
  704. m_next_mode = NODE_MODE_JOINING;
  705. m_node_settings.joining_mode_to = mode_duration_sec;
  706. m_node_settings.joining_mode_failure = ncfgs_data->ctrlp_value.state_on_failure;
  707. /* This code will get executed in two scenarios:
  708. - if the previous mode was Config mode and now we are ready to connect to the router, or
  709. - if the previous mode was Joining mode and the state on failure was set to No Change.
  710. */
  711. if (m_node_settings.joining_mode_failure == NCFGS_SOF_NO_CHANGE)
  712. {
  713. m_node_settings.poweron_mode = NODE_MODE_JOINING;
  714. }
  715. else
  716. {
  717. // If the state on failure is NOT No Change, start next time in Config mode.
  718. m_node_settings.poweron_mode = NODE_MODE_CONFIG;
  719. }
  720. if (m_node_settings.joining_mode_failure == NCFGS_SOF_PWR_OFF)
  721. {
  722. COMM_TRC("Will power off on failure.");
  723. m_power_off_on_failure = true; // The assert handler will power off the system.
  724. }
  725. break;
  726. }
  727. case NCFGS_OPCODE_GOTO_CONFIG_MODE:
  728. {
  729. m_next_mode = NODE_MODE_CONFIG;
  730. m_node_settings.config_mode_to = mode_duration_sec;
  731. m_node_settings.config_mode_failure = ncfgs_data->ctrlp_value.state_on_failure;
  732. /* The node is about to enter Config mode. Regardless of what the state on failure
  733. setting is (No Change or Pwr Off or Cfg Mode), the poweron_mode value should be Cfg Mode. */
  734. m_node_settings.poweron_mode = NODE_MODE_CONFIG;
  735. if (m_node_settings.config_mode_failure == NCFGS_SOF_PWR_OFF)
  736. {
  737. COMM_TRC("Will power off on failure.");
  738. m_power_off_on_failure = true; // The assert handler will power off the system.
  739. }
  740. break;
  741. }
  742. case NCFGS_OPCODE_GOTO_IDENTITY_MODE:
  743. {
  744. m_next_mode = NODE_MODE_IDENTITY;
  745. m_node_settings.id_mode_to = mode_duration_sec;
  746. break;
  747. }
  748. default:
  749. {
  750. break;
  751. }
  752. }
  753. memcpy(&m_node_settings.ssid_store, &ncfgs_data->ssid_from_router, sizeof(ssid_store_t));
  754. memcpy(&m_node_settings.keys_store, &ncfgs_data->keys_from_router, sizeof(keys_store_t));
  755. memcpy(&m_node_settings.id_data_store, &ncfgs_data->id_data, sizeof(id_data_store_t));
  756. #if (COMM_ENABLE_LOGS == 1)
  757. print_node_settings();
  758. #endif // (COMM_ENABLE_LOGS == 1)
  759. #if (FDS_ENABLED == 1)
  760. uint32_t err_code = persistent_settings_update();
  761. APP_ERROR_CHECK(err_code);
  762. #endif // FDS_ENABLED
  763. uint32_t action_delay_written = ncfgs_data->ctrlp_value.delay_sec;
  764. // Set the timeout value to at least MINIMUM_ACTION_DELAY second(s).
  765. // This is to make sure that storing settings in the persistent
  766. // storage completes before activating the next mode.
  767. action_delay_written = (action_delay_written < MINIMUM_ACTION_DELAY) ? \
  768. MINIMUM_ACTION_DELAY : action_delay_written;
  769. COMM_TRC("Action delay: %ld seconds.", action_delay_written);
  770. commissioning_timer_start(TIMER_INDEX_DELAYED_ACTION, action_delay_written);
  771. COMM_EXIT();
  772. }
  773. void commissioning_time_tick(iot_timer_time_in_ms_t wall_clock_value)
  774. {
  775. UNUSED_PARAMETER(wall_clock_value);
  776. uint8_t index;
  777. for (index=0; index<NUMBER_OF_COMMISSIONING_TIMERS; ++index)
  778. {
  779. if (m_commissioning_timers[index].is_timer_running == true)
  780. {
  781. m_commissioning_timers[index].current_value_sec -= COMMISSIONING_TICK_INTERVAL_SEC;
  782. if (m_commissioning_timers[index].current_value_sec == 0)
  783. {
  784. commissioning_timer_stop_reset(index);
  785. m_commissioning_timers[index].timeout_handler();
  786. }
  787. }
  788. }
  789. }
  790. static void commissioning_timers_init(void)
  791. {
  792. memset(m_commissioning_timers, 0x00, sizeof(m_commissioning_timers));
  793. m_commissioning_timers[TIMER_INDEX_DELAYED_ACTION].timeout_handler = \
  794. action_timeout_handler;
  795. m_commissioning_timers[TIMER_INDEX_CONFIG_MODE].timeout_handler = \
  796. config_mode_timeout_handler;
  797. m_commissioning_timers[TIMER_INDEX_JOINING_MODE].timeout_handler = \
  798. joining_mode_timeout_handler;
  799. m_commissioning_timers[TIMER_INDEX_IDENTITY_MODE].timeout_handler = \
  800. identity_mode_timeout_handler;
  801. }
  802. uint32_t commissioning_init(commissioning_init_params_t * p_init_param, \
  803. uint8_t * p_poweron_state)
  804. {
  805. COMM_ENTRY();
  806. uint32_t err_code = NRF_SUCCESS;
  807. m_commissioning_evt_handler = p_init_param->commissioning_evt_handler;
  808. m_power_off_on_failure = false;
  809. // Initialize Commissioning timers.
  810. commissioning_timers_init();
  811. // Initialize GATT server.
  812. err_code = ble_ncfgs_init(on_ble_ncfgs_evt);
  813. if (err_code != NRF_SUCCESS)
  814. {
  815. return err_code;
  816. }
  817. #if (FDS_ENABLED == 1)
  818. err_code = persistent_settings_init();
  819. if (err_code != NRF_SUCCESS)
  820. {
  821. return err_code;
  822. }
  823. #endif
  824. // Read application settings from persistent storage.
  825. read_node_settings();
  826. #if (COMM_ENABLE_LOGS == 1)
  827. print_node_settings();
  828. #endif // (COMM_ENABLE_LOGS == 1)
  829. if (!settings_are_valid()) // If the settings are invalid for any reason go to Config mode.
  830. {
  831. COMM_ERR("Invalid settings!");
  832. commissioning_settings_clear();
  833. memset(&m_node_settings, 0x00, sizeof(m_node_settings));
  834. m_node_settings.config_mode_to = 300;
  835. *p_poweron_state = NODE_MODE_CONFIG;
  836. }
  837. else
  838. {
  839. if (m_node_settings.poweron_mode == NODE_MODE_JOINING)
  840. {
  841. /* This code will get executed in two scenarios:
  842. - if the previous mode was Config mode and now we are ready to connect to the router, or
  843. - if the previous mode was Joining mode and the state on failure was set to No Change.
  844. */
  845. if ((m_node_settings.joining_mode_failure == NCFGS_SOF_PWR_OFF) || \
  846. (m_node_settings.joining_mode_failure == NCFGS_SOF_CONFIG_MODE))
  847. {
  848. // If the state on failure is NOT No Change, start next time in Config mode.
  849. m_node_settings.poweron_mode = NODE_MODE_CONFIG;
  850. #if (FDS_ENABLED == 1)
  851. err_code = persistent_settings_update();
  852. APP_ERROR_CHECK(err_code);
  853. #endif // FDS_ENABLED
  854. }
  855. if (m_node_settings.joining_mode_failure == NCFGS_SOF_PWR_OFF)
  856. {
  857. COMM_TRC("Will power off on failure.");
  858. m_power_off_on_failure = true; // The assert handler will power off the system.
  859. }
  860. *p_poweron_state = NODE_MODE_JOINING;
  861. }
  862. else
  863. {
  864. /* The app is about to enter Config mode. Regardless of what the state on failure
  865. setting is (No Change or Pwr Off or Cfg Mode), the poweron_mode value should remain the same. */
  866. if (m_node_settings.config_mode_failure == NCFGS_SOF_PWR_OFF)
  867. {
  868. COMM_TRC("Will power off on failure.");
  869. m_power_off_on_failure = true; // The assert handler will power off the system.
  870. }
  871. *p_poweron_state = NODE_MODE_CONFIG;
  872. }
  873. }
  874. // Set advertising and GAP parameters.
  875. config_mode_gap_params_set();
  876. config_mode_adv_params_set();
  877. joining_mode_gap_params_set();
  878. joining_mode_adv_params_set();
  879. COMM_EXIT();
  880. return err_code;
  881. }
  882. #endif // COMMISSIONING_ENABLED