ble_ncfgs.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /**
  2. * Copyright (c) 2015 - 2019, 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 "ble_ncfgs.h"
  43. #include "app_error.h"
  44. #include "ble.h"
  45. #include "nordic_common.h"
  46. /**@brief NCFGS database encapsulation. */
  47. typedef struct
  48. {
  49. uint16_t service_handle;
  50. ble_gatts_char_handles_t ssid_handles;
  51. ble_gatts_char_handles_t keys_store_handles;
  52. ble_gatts_char_handles_t ctrlp_handles;
  53. } ble_database_t;
  54. static ble_ncfgs_state_t m_service_state = NCFGS_STATE_IDLE; /**< Module state value. */
  55. static ble_ncfgs_evt_handler_t m_app_evt_handler; /**< Parent module callback function. */
  56. static ble_database_t m_database; /**< GATT handles database. */
  57. static uint8_t m_ctrlp_value_buffer[NCFGS_CTRLP_VALUE_LEN]; /**< Stores received Control Point value before parsing. */
  58. static ble_ncfgs_data_t m_ncfgs_data; /**< Stores all values written by the peer device. */
  59. #if NCFGS_CONFIG_LOG_ENABLED
  60. #define NRF_LOG_MODULE_NAME ble_ncfgs
  61. #define NRF_LOG_LEVEL NCFGS_CONFIG_LOG_LEVEL
  62. #define NRF_LOG_INFO_COLOR NCFGS_CONFIG_INFO_COLOR
  63. #define NRF_LOG_DEBUG_COLOR NCFGS_CONFIG_DEBUG_COLOR
  64. #include "nrf_log.h"
  65. NRF_LOG_MODULE_REGISTER();
  66. #define NCFGS_TRC NRF_LOG_DEBUG /**< Used for getting trace of execution in the module. */
  67. #define NCFGS_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */
  68. #define NCFGS_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */
  69. #define NCFGS_ENTRY() NCFGS_TRC(">> %s", __func__)
  70. #define NCFGS_EXIT() NCFGS_TRC("<< %s", __func__)
  71. #else // NCFGS_CONFIG_LOG_ENABLED
  72. #define NCFGS_TRC(...) /**< Disables traces. */
  73. #define NCFGS_DUMP(...) /**< Disables dumping of octet streams. */
  74. #define NCFGS_ERR(...) /**< Disables error logs. */
  75. #define NCFGS_ENTRY(...)
  76. #define NCFGS_EXIT(...)
  77. #endif // NCFGS_CONFIG_LOG_ENABLED
  78. /**@brief Function for adding the SSID Store characteristic.
  79. *
  80. * @return NRF_SUCCESS on success, otherwise an error code.
  81. */
  82. static uint32_t add_ssid_characteristic(ble_uuid_t * p_srv_uuid)
  83. {
  84. ble_gatts_char_md_t char_md;
  85. ble_gatts_attr_t attr_char_value;
  86. ble_uuid_t char_uuid;
  87. ble_gatts_attr_md_t attr_md;
  88. memset(&char_md, 0x00, sizeof(char_md));
  89. char_md.char_props.read = 1;
  90. char_md.char_props.write = 1;
  91. memset(&attr_md, 0x00, sizeof(attr_md));
  92. BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
  93. BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
  94. attr_md.wr_auth = 1;
  95. attr_md.vloc = BLE_GATTS_VLOC_USER;
  96. memset(&attr_char_value, 0x00, sizeof(attr_char_value));
  97. char_uuid.type = p_srv_uuid->type;
  98. char_uuid.uuid = BLE_UUID_NCFGS_SSID_CHAR;
  99. attr_char_value.p_uuid = &char_uuid;
  100. attr_char_value.p_attr_md = &attr_md;
  101. attr_char_value.init_len = NCFGS_SSID_MAX_LEN;
  102. attr_char_value.init_offs = 0;
  103. attr_char_value.max_len = NCFGS_SSID_MAX_LEN;
  104. attr_char_value.p_value = &m_ncfgs_data.ssid_from_router.ssid[0];
  105. return sd_ble_gatts_characteristic_add(m_database.service_handle,
  106. &char_md,
  107. &attr_char_value,
  108. &m_database.ssid_handles);
  109. }
  110. /**@brief Function for adding the Keys Store characteristic.
  111. *
  112. * @return NRF_SUCCESS on success, otherwise an error code.
  113. */
  114. static uint32_t add_keys_store_characteristic(ble_uuid_t * p_srv_uuid)
  115. {
  116. ble_gatts_char_md_t char_md;
  117. ble_gatts_attr_t attr_char_value;
  118. ble_uuid_t char_uuid;
  119. ble_gatts_attr_md_t attr_md;
  120. memset(&char_md, 0x00, sizeof(char_md));
  121. char_md.char_props.read = 1;
  122. char_md.char_props.write = 1;
  123. memset(&attr_md, 0x00, sizeof(attr_md));
  124. BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
  125. BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
  126. attr_md.wr_auth = 1;
  127. attr_md.vloc = BLE_GATTS_VLOC_USER;
  128. memset(&attr_char_value, 0x00, sizeof(attr_char_value));
  129. char_uuid.type = p_srv_uuid->type;
  130. char_uuid.uuid = BLE_UUID_NCFGS_KEYS_STORE_CHAR;
  131. attr_char_value.p_uuid = &char_uuid;
  132. attr_char_value.p_attr_md = &attr_md;
  133. attr_char_value.init_len = NCFGS_KEYS_MAX_LEN;
  134. attr_char_value.init_offs = 0;
  135. attr_char_value.max_len = NCFGS_KEYS_MAX_LEN;
  136. attr_char_value.p_value = &m_ncfgs_data.keys_from_router.keys[0];
  137. return sd_ble_gatts_characteristic_add(m_database.service_handle,
  138. &char_md,
  139. &attr_char_value,
  140. &m_database.keys_store_handles);
  141. }
  142. /**@brief Function for adding the Control Point characteristic.
  143. *
  144. * @return NRF_SUCCESS on success, otherwise an error code.
  145. */
  146. static uint32_t add_ip_cfg_cp_characteristic(ble_uuid_t * p_srv_uuid)
  147. {
  148. ble_gatts_char_md_t char_md;
  149. ble_gatts_attr_t attr_char_value;
  150. ble_uuid_t char_uuid;
  151. ble_gatts_attr_md_t attr_md;
  152. memset(&char_md, 0x00, sizeof(char_md));
  153. char_md.char_props.read = 1;
  154. char_md.char_props.write = 1;
  155. memset(&attr_md, 0x00, sizeof(attr_md));
  156. BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
  157. BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
  158. attr_md.wr_auth = 1;
  159. attr_md.vloc = BLE_GATTS_VLOC_USER;
  160. memset(&attr_char_value, 0x00, sizeof(attr_char_value));
  161. char_uuid.type = p_srv_uuid->type;
  162. char_uuid.uuid = BLE_UUID_NCFGS_CTRLPT_CHAR;
  163. attr_char_value.p_uuid = &char_uuid;
  164. attr_char_value.p_attr_md = &attr_md;
  165. attr_char_value.init_len = NCFGS_CTRLP_VALUE_LEN;
  166. attr_char_value.init_offs = 0;
  167. attr_char_value.max_len = NCFGS_CTRLP_VALUE_LEN;
  168. attr_char_value.p_value = &m_ctrlp_value_buffer[0];
  169. return sd_ble_gatts_characteristic_add(m_database.service_handle,
  170. &char_md,
  171. &attr_char_value,
  172. &m_database.ctrlp_handles);
  173. }
  174. /**@brief Function for creating the GATT database.
  175. *
  176. * @return NRF_SUCCESS on success, otherwise an error code.
  177. */
  178. static uint32_t ble_ncfgs_create_database(void)
  179. {
  180. uint32_t err_code = NRF_SUCCESS;
  181. // Add service.
  182. ble_uuid_t service_uuid;
  183. const ble_uuid128_t base_uuid128 =
  184. {
  185. {
  186. 0x73, 0x3E, 0x2D, 0x02, 0xB7, 0x6B, 0xBE, 0xBE, \
  187. 0xE5, 0x4F, 0x40, 0x8F, 0x00, 0x00, 0x20, 0x54
  188. }
  189. };
  190. service_uuid.uuid = BLE_UUID_NODE_CFG_SERVICE;
  191. err_code = sd_ble_uuid_vs_add(&base_uuid128, &(service_uuid.type));
  192. if (err_code != NRF_SUCCESS)
  193. {
  194. return err_code;
  195. }
  196. err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, \
  197. &service_uuid, \
  198. &m_database.service_handle);
  199. if (err_code != NRF_SUCCESS)
  200. {
  201. return err_code;
  202. }
  203. err_code = add_ssid_characteristic(&service_uuid);
  204. if (err_code != NRF_SUCCESS)
  205. {
  206. return err_code;
  207. }
  208. err_code = add_keys_store_characteristic(&service_uuid);
  209. if (err_code != NRF_SUCCESS)
  210. {
  211. return err_code;
  212. }
  213. err_code = add_ip_cfg_cp_characteristic(&service_uuid);
  214. if (err_code != NRF_SUCCESS)
  215. {
  216. return err_code;
  217. }
  218. return err_code;
  219. }
  220. uint32_t ble_ncfgs_init(ble_ncfgs_evt_handler_t ble_ncfgs_cb)
  221. {
  222. NCFGS_ENTRY();
  223. uint32_t err_code;
  224. memset(&m_ncfgs_data, 0x00, sizeof(m_ncfgs_data));
  225. m_app_evt_handler = ble_ncfgs_cb;
  226. err_code = ble_ncfgs_create_database();
  227. NCFGS_EXIT();
  228. return err_code;
  229. }
  230. /**@brief Function for decoding the Control Point characteristic value.
  231. *
  232. * @return NRF_SUCCESS on success, otherwise an error code.
  233. */
  234. static uint32_t ctrlp_value_decode(const ble_evt_t * p_ble_evt)
  235. {
  236. uint16_t wr_req_value_len = \
  237. p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.len;
  238. memcpy(m_ctrlp_value_buffer, \
  239. p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.data, \
  240. wr_req_value_len);
  241. m_ncfgs_data.ctrlp_value.opcode = \
  242. (ble_ncfgs_opcode_t)m_ctrlp_value_buffer[0];
  243. memcpy((void *)&m_ncfgs_data.ctrlp_value.delay_sec, \
  244. &m_ctrlp_value_buffer[NCFGS_CTRLP_OPCODE_LEN], \
  245. sizeof(uint32_t));
  246. m_ncfgs_data.ctrlp_value.delay_sec = \
  247. HTONL(m_ncfgs_data.ctrlp_value.delay_sec);
  248. memcpy((void *)&m_ncfgs_data.ctrlp_value.duration_sec, \
  249. &m_ctrlp_value_buffer[NCFGS_CTRLP_OPCODE_LEN+NCFGS_CTRLP_DELAY_LEN], \
  250. sizeof(uint32_t));
  251. m_ncfgs_data.ctrlp_value.duration_sec = \
  252. HTONL(m_ncfgs_data.ctrlp_value.duration_sec);
  253. m_ncfgs_data.ctrlp_value.state_on_failure = \
  254. (state_on_failure_t)m_ctrlp_value_buffer[NCFGS_CTRLP_OPCODE_LEN+ \
  255. NCFGS_CTRLP_DELAY_LEN+ \
  256. NCFGS_CTRLP_DURATION_LEN];
  257. if ((m_ncfgs_data.ctrlp_value.state_on_failure != NCFGS_SOF_NO_CHANGE) && \
  258. (m_ncfgs_data.ctrlp_value.state_on_failure != NCFGS_SOF_PWR_OFF) && \
  259. (m_ncfgs_data.ctrlp_value.state_on_failure != NCFGS_SOF_CONFIG_MODE))
  260. {
  261. return NRF_ERROR_INVALID_DATA;
  262. }
  263. uint16_t id_data_len = wr_req_value_len - NCFGS_CTRLP_ALL_BUT_ID_DATA_LEN;
  264. if (id_data_len != 0)
  265. {
  266. m_ncfgs_data.id_data.identity_data_len = id_data_len;
  267. memcpy(m_ncfgs_data.id_data.identity_data, \
  268. &m_ctrlp_value_buffer[NCFGS_CTRLP_ALL_BUT_ID_DATA_LEN], \
  269. id_data_len);
  270. }
  271. return NRF_SUCCESS;
  272. }
  273. void ble_ncfgs_ble_evt_handler(const ble_evt_t * p_ble_evt)
  274. {
  275. switch (p_ble_evt->header.evt_id)
  276. {
  277. case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
  278. {
  279. if (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == \
  280. BLE_GATTS_OP_WRITE_REQ)
  281. {
  282. uint16_t wr_req_handle = \
  283. p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.handle;
  284. uint16_t wr_req_value_len = \
  285. p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.len;
  286. ble_gatts_rw_authorize_reply_params_t reply_params;
  287. memset(&reply_params, 0x00, sizeof(reply_params));
  288. reply_params.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
  289. reply_params.params.write.update = 1;
  290. reply_params.params.write.offset = p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.offset;
  291. reply_params.params.write.len = p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.len;
  292. reply_params.params.write.p_data = p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.data;
  293. if (wr_req_handle == m_database.ssid_handles.value_handle)
  294. {
  295. NCFGS_TRC("> wr_req: ssid_handle");
  296. if ((wr_req_value_len > NCFGS_SSID_MAX_LEN) || \
  297. (wr_req_value_len < NCFGS_SSID_MIN_LEN))
  298. {
  299. reply_params.params.write.gatt_status = \
  300. BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH;
  301. }
  302. else
  303. {
  304. m_ncfgs_data.ssid_from_router.ssid_len = wr_req_value_len;
  305. m_service_state |= NCFGS_STATE_SSID_WRITTEN;
  306. reply_params.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
  307. }
  308. UNUSED_RETURN_VALUE( \
  309. sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gap_evt.conn_handle, \
  310. &reply_params));
  311. NCFGS_TRC("< wr_req: ssid_handle");
  312. return;
  313. }
  314. else if (wr_req_handle == m_database.keys_store_handles.value_handle)
  315. {
  316. NCFGS_TRC("> wr_req: keys_store_handle");
  317. if (wr_req_value_len > NCFGS_KEYS_MAX_LEN)
  318. {
  319. reply_params.params.write.gatt_status = \
  320. BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH;
  321. }
  322. else
  323. {
  324. m_ncfgs_data.keys_from_router.keys_len = wr_req_value_len;
  325. m_service_state |= NCFGS_STATE_KEYS_STORE_WRITTEN;
  326. reply_params.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
  327. }
  328. UNUSED_RETURN_VALUE( \
  329. sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gap_evt.conn_handle, \
  330. &reply_params));
  331. NCFGS_TRC("< wr_req: keys_store_handle");
  332. return;
  333. }
  334. else if (wr_req_handle == m_database.ctrlp_handles.value_handle)
  335. {
  336. NCFGS_TRC("> wr_req: ctrlp_handle");
  337. bool notify_app = false;
  338. if ((wr_req_value_len > NCFGS_CTRLP_VALUE_LEN) || \
  339. (wr_req_value_len < NCFGS_CTRLP_ALL_BUT_ID_DATA_LEN))
  340. {
  341. reply_params.params.write.gatt_status = \
  342. BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH;
  343. }
  344. else
  345. {
  346. ble_ncfgs_opcode_t opcode_in = (ble_ncfgs_opcode_t) \
  347. p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.data[0];
  348. reply_params.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
  349. if ((opcode_in != NCFGS_OPCODE_GOTO_JOINING_MODE) && \
  350. (opcode_in != NCFGS_OPCODE_GOTO_CONFIG_MODE) && \
  351. (opcode_in != NCFGS_OPCODE_GOTO_IDENTITY_MODE))
  352. {
  353. reply_params.params.write.gatt_status = APP_GATTERR_UNKNOWN_OPCODE;
  354. }
  355. if (opcode_in == NCFGS_OPCODE_GOTO_JOINING_MODE)
  356. {
  357. if (!((m_service_state & NCFGS_STATE_SSID_WRITTEN) && \
  358. (m_service_state & NCFGS_STATE_KEYS_STORE_WRITTEN)))
  359. {
  360. reply_params.params.write.gatt_status = APP_GATTERR_NOT_CONFIGURED;
  361. }
  362. }
  363. if (reply_params.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS)
  364. {
  365. uint32_t err_code = ctrlp_value_decode(p_ble_evt);
  366. if (err_code != NRF_SUCCESS)
  367. {
  368. reply_params.params.write.gatt_status = \
  369. APP_GATTERR_INVALID_ATTR_VALUE;
  370. }
  371. else
  372. {
  373. notify_app = true;
  374. }
  375. }
  376. }
  377. UNUSED_RETURN_VALUE(sd_ble_gatts_rw_authorize_reply(
  378. p_ble_evt->evt.gap_evt.conn_handle,
  379. &reply_params));
  380. if (notify_app == true)
  381. {
  382. NCFGS_TRC("> do notify parent");
  383. m_app_evt_handler(&m_ncfgs_data);
  384. NCFGS_TRC("< do notify parent");
  385. }
  386. NCFGS_TRC("< wr_req: ctrlp_handle");
  387. }
  388. else
  389. {
  390. // Invalid handle.
  391. reply_params.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_INVALID_HANDLE;
  392. UNUSED_RETURN_VALUE(sd_ble_gatts_rw_authorize_reply(
  393. p_ble_evt->evt.gap_evt.conn_handle, &reply_params));
  394. }
  395. }
  396. break;
  397. }
  398. case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
  399. {
  400. ble_gap_data_length_params_t dl_params;
  401. // Clearing the struct will effectively set members to @ref BLE_GAP_DATA_LENGTH_AUTO.
  402. memset(&dl_params, 0, sizeof(ble_gap_data_length_params_t));
  403. UNUSED_RETURN_VALUE(sd_ble_gap_data_length_update(p_ble_evt->evt.gap_evt.conn_handle, &dl_params, NULL));
  404. break;
  405. }
  406. case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
  407. {
  408. NCFGS_TRC("> PHY update request.");
  409. ble_gap_phys_t const phys =
  410. {
  411. .rx_phys = BLE_GAP_PHY_AUTO,
  412. .tx_phys = BLE_GAP_PHY_AUTO,
  413. };
  414. UNUSED_RETURN_VALUE(sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
  415. NCFGS_TRC("< PHY update request.");
  416. break;
  417. }
  418. default:
  419. {
  420. break;
  421. }
  422. }
  423. }
  424. #endif // COMMISSIONING_ENABLED