ble_dis_c.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. /**
  2. * Copyright (c) 2017 - 2020, 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. #include "sdk_common.h"
  41. #if NRF_MODULE_ENABLED(BLE_DIS_C)
  42. #include <stdlib.h>
  43. #include "ble.h"
  44. #include "ble_dis_c.h"
  45. #include "ble_gattc.h"
  46. #include "nrf_bitmask.h"
  47. #include "app_error.h"
  48. #define NRF_LOG_MODULE_NAME ble_dis
  49. #include "nrf_log.h"
  50. NRF_LOG_MODULE_REGISTER();
  51. // Value Field lengths for System ID characteristic.
  52. #define BLE_DIS_C_MANUF_ID_LEN 5 /**< Length of Manufacturer ID field inside System ID characteristic. */
  53. #define BLE_DIS_C_OU_ID_LEN 3 /**< Length of Organizationally Unique ID field inside System ID characteristic. */
  54. // Value Field lengths for PnP ID characteristic.
  55. #define BLE_DIS_C_VENDOR_ID_SRC_LEN 1 /**< Length of Vendor ID Source field inside PnP ID characteristic. */
  56. #define BLE_DIS_C_VENDOR_ID_LEN 2 /**< Length of Vendor ID field inside PnP ID characteristic. */
  57. #define BLE_DIS_C_PRODUCT_ID_LEN 2 /**< Length of Product ID field inside PnP ID characteristic. */
  58. #define BLE_DIS_C_PRODUCT_VER_LEN 2 /**< Length of Product Version field inside PnP ID characteristic. */
  59. #define BLE_DIS_C_ALL_CHARS_DISABLED_MASK 0x0000 /**< All DIS characteristics should be disabled. */
  60. #define BLE_DIS_C_ALL_CHARS_ENABLED_MASK 0xFFFF /**< All DIS characteristics should be enabled. */
  61. /**@brief Function for interception of gattc errors.
  62. *
  63. * @param[in] nrf_error Error code returned by SoftDevice.
  64. * @param[in] p_contex Parameter from the event handler.
  65. * @param[in] conn_handle Connection handle.
  66. */
  67. static void gatt_error_handler(uint32_t nrf_error, void * p_contex, uint16_t conn_handle)
  68. {
  69. UNUSED_PARAMETER(conn_handle);
  70. ble_dis_c_t const * const p_ble_disc_c = (ble_dis_c_t *)p_contex;
  71. if (p_ble_disc_c != NULL)
  72. {
  73. p_ble_disc_c->error_handler(nrf_error);
  74. }
  75. }
  76. /**@brief Function for decoding System ID characteristic value.
  77. *
  78. * @param[in] p_data Pointer to System ID characteristic data.
  79. * @param[in] len Length of the System ID characteristic data.
  80. * @param[out] p_sys_id Decoded System ID characteristic.
  81. *
  82. * @retval NRF_SUCCESS If the characteristic was initialized successfully.
  83. * @retval NRF_ERROR_INVALID_LENGTH Any parameter is NULL.
  84. */
  85. static ret_code_t system_id_decode(uint8_t const * p_data,
  86. uint16_t len,
  87. ble_dis_sys_id_t * const p_sys_id)
  88. {
  89. uint16_t const expected_len = (BLE_DIS_C_MANUF_ID_LEN + BLE_DIS_C_OU_ID_LEN);
  90. // Validate response length.
  91. if (expected_len != len)
  92. {
  93. NRF_LOG_ERROR("System ID characteristic data cannot be decoded.");
  94. NRF_LOG_ERROR("Expected data length != Received data length: %d != %d", expected_len, len);
  95. return NRF_ERROR_INVALID_LENGTH;
  96. }
  97. // Decode Manufacturer ID.
  98. p_sys_id->manufacturer_id = uint40_decode(p_data);
  99. p_data += BLE_DIS_C_MANUF_ID_LEN;
  100. // Decode Organizationally unique ID.
  101. p_sys_id->organizationally_unique_id = uint24_decode(p_data);
  102. return NRF_SUCCESS;
  103. }
  104. /**@brief Function for decoding PnP ID characteristic value.
  105. *
  106. * @param[in] p_data Pointer to PnP ID characteristic data.
  107. * @param[in] len Length of the PnP ID characteristic data.
  108. * @param[out] p_pnp_id Decoded PnP ID characteristic.
  109. *
  110. * @retval NRF_SUCCESS If the characteristic was initialized successfully.
  111. * @retval NRF_ERROR_INVALID_LENGTH Any parameter is NULL.
  112. */
  113. static ret_code_t pnp_id_decode(uint8_t const * p_data,
  114. uint16_t len,
  115. ble_dis_pnp_id_t * const p_pnp_id)
  116. {
  117. uint16_t const expected_len = (BLE_DIS_C_VENDOR_ID_SRC_LEN + BLE_DIS_C_VENDOR_ID_LEN +
  118. BLE_DIS_C_PRODUCT_ID_LEN + BLE_DIS_C_PRODUCT_VER_LEN);
  119. // Validate response length.
  120. if (expected_len != len)
  121. {
  122. NRF_LOG_ERROR("PnP ID characteristic data cannot be decoded.");
  123. NRF_LOG_ERROR("Expected data length != Received data length: %d != %d", expected_len, len);
  124. return NRF_ERROR_INVALID_LENGTH;
  125. }
  126. // Decode Vendor ID Source.
  127. p_pnp_id->vendor_id_source = p_data[0];
  128. p_data += BLE_DIS_C_VENDOR_ID_SRC_LEN;
  129. // Decode Vendor ID.
  130. p_pnp_id->vendor_id = uint16_decode(p_data);
  131. p_data += BLE_DIS_C_VENDOR_ID_LEN;
  132. // Decode Product ID.
  133. p_pnp_id->product_id = uint16_decode(p_data);
  134. p_data += BLE_DIS_C_PRODUCT_ID_LEN;
  135. // Decode Product Version.
  136. p_pnp_id->product_version = uint16_decode(p_data);
  137. return NRF_SUCCESS;
  138. }
  139. /**@brief Function for matching DIS Client characteristic type with the provided response handle.
  140. *
  141. * @param[in] p_ble_dis_c Pointer to the Device Information Client Structure.
  142. * @param[in] response_handle Attribute handle from the response event.
  143. */
  144. static ble_dis_c_char_type_t char_type_get(ble_dis_c_t * p_ble_dis_c, uint16_t response_handle)
  145. {
  146. for (ble_dis_c_char_type_t char_type = (ble_dis_c_char_type_t) 0;
  147. char_type < BLE_DIS_C_CHAR_TYPES_NUM;
  148. char_type++)
  149. {
  150. if (response_handle == p_ble_dis_c->handles[char_type])
  151. {
  152. return char_type;
  153. }
  154. }
  155. return BLE_DIS_C_CHAR_TYPES_NUM;
  156. }
  157. /**@brief Function for handling read response events.
  158. *
  159. * @details This function will validate the read response and raise the appropriate
  160. * event to the application.
  161. *
  162. * @param[in] p_ble_dis_c Pointer to the Device Information Client Structure.
  163. * @param[in] p_ble_evt Pointer to the SoftDevice event.
  164. */
  165. static void on_read_rsp(ble_dis_c_t * p_ble_dis_c, ble_evt_t const * p_ble_evt)
  166. {
  167. ret_code_t err_code;
  168. ble_gattc_evt_read_rsp_t const * p_response = &p_ble_evt->evt.gattc_evt.params.read_rsp;
  169. ble_dis_c_evt_t ble_dis_c_evt;
  170. ble_dis_c_char_type_t char_type;
  171. // Check if the event is on the link for this instance and the event handler is present.
  172. if ((p_ble_dis_c->evt_handler == NULL) ||
  173. (p_ble_dis_c->conn_handle != p_ble_evt->evt.gattc_evt.conn_handle))
  174. {
  175. return;
  176. }
  177. char_type = char_type_get(p_ble_dis_c, p_response->handle);
  178. if (char_type < BLE_DIS_C_CHAR_TYPES_NUM) // Characteristic type is valid.
  179. {
  180. memset(&ble_dis_c_evt, 0, sizeof(ble_dis_c_evt_t));
  181. ble_dis_c_evt.conn_handle = p_ble_evt->evt.gattc_evt.conn_handle;
  182. if (p_ble_evt->evt.gattc_evt.gatt_status == BLE_GATT_STATUS_SUCCESS)
  183. {
  184. ble_dis_c_evt_read_rsp_t * const p_dis_rsp = &ble_dis_c_evt.params.read_rsp;
  185. ble_dis_c_evt.evt_type = BLE_DIS_C_EVT_DIS_C_READ_RSP;
  186. p_dis_rsp->char_type = char_type;
  187. p_dis_rsp->handle = p_response->handle;
  188. // Decode characteristic value.
  189. switch (char_type)
  190. {
  191. case BLE_DIS_C_MANUF_NAME:
  192. case BLE_DIS_C_MODEL_NUM:
  193. case BLE_DIS_C_SERIAL_NUM:
  194. case BLE_DIS_C_HW_REV:
  195. case BLE_DIS_C_FW_REV:
  196. case BLE_DIS_C_SW_REV:
  197. p_dis_rsp->content.string.p_data = (uint8_t *) p_response->data;
  198. p_dis_rsp->content.string.len = p_response->len;
  199. break;
  200. case BLE_DIS_C_SYS_ID:
  201. err_code = system_id_decode(p_response->data,
  202. p_response->len,
  203. &p_dis_rsp->content.sys_id);
  204. if ((p_ble_dis_c->error_handler != NULL) && (err_code != NRF_SUCCESS))
  205. {
  206. p_ble_dis_c->error_handler(err_code);
  207. }
  208. break;
  209. case BLE_DIS_C_CERT_LIST:
  210. p_dis_rsp->content.cert_list.p_list = (uint8_t *) p_response->data;
  211. p_dis_rsp->content.cert_list.list_len = p_response->len;
  212. break;
  213. case BLE_DIS_C_PNP_ID:
  214. err_code = pnp_id_decode(p_response->data,
  215. p_response->len,
  216. &p_dis_rsp->content.pnp_id);
  217. if ((p_ble_dis_c->error_handler != NULL) && (err_code != NRF_SUCCESS))
  218. {
  219. p_ble_dis_c->error_handler(err_code);
  220. }
  221. break;
  222. default:
  223. break;
  224. }
  225. p_ble_dis_c->evt_handler(p_ble_dis_c, &ble_dis_c_evt);
  226. NRF_LOG_DEBUG("Received correct read response.");
  227. }
  228. else // Generate error event.
  229. {
  230. ble_dis_c_evt.evt_type = BLE_DIS_C_EVT_DIS_C_READ_RSP_ERROR;
  231. ble_dis_c_evt.params.read_rsp_err.char_type = char_type;
  232. ble_dis_c_evt.params.read_rsp_err.err_handle = p_ble_evt->evt.gattc_evt.error_handle;
  233. ble_dis_c_evt.params.read_rsp_err.gatt_status = p_ble_evt->evt.gattc_evt.gatt_status;
  234. p_ble_dis_c->evt_handler(p_ble_dis_c, &ble_dis_c_evt);
  235. NRF_LOG_ERROR("Read request failed: 0x%04X.", p_ble_evt->evt.gattc_evt.gatt_status);
  236. }
  237. }
  238. }
  239. /**@brief Function for handling Disconnected event received from the SoftDevice.
  240. *
  241. * @details This function checks if the disconnect event is happening on the link
  242. * associated with the current instance of the module. If so, it will set its
  243. * conn_handle to invalid.
  244. *
  245. * @param[in] p_ble_dis_c Pointer to the Device Information Client Structure.
  246. * @param[in] p_ble_evt Pointer to the BLE event received.
  247. */
  248. static void on_disconnected(ble_dis_c_t * p_ble_dis_c, const ble_evt_t * p_ble_evt)
  249. {
  250. if (p_ble_dis_c->conn_handle == p_ble_evt->evt.gap_evt.conn_handle)
  251. {
  252. p_ble_dis_c->conn_handle = BLE_CONN_HANDLE_INVALID;
  253. if (p_ble_dis_c->evt_handler != NULL)
  254. {
  255. ble_dis_c_evt_t dis_c_evt =
  256. {
  257. .evt_type = BLE_DIS_C_EVT_DISCONNECTED,
  258. .conn_handle = p_ble_evt->evt.gap_evt.conn_handle
  259. };
  260. p_ble_dis_c->evt_handler(p_ble_dis_c, &dis_c_evt);
  261. }
  262. }
  263. }
  264. ret_code_t ble_dis_c_init(ble_dis_c_t * p_ble_dis_c, ble_dis_c_init_t * p_ble_dis_c_init)
  265. {
  266. ble_uuid_t dis_uuid;
  267. VERIFY_PARAM_NOT_NULL(p_ble_dis_c);
  268. VERIFY_PARAM_NOT_NULL(p_ble_dis_c_init);
  269. dis_uuid.type = BLE_UUID_TYPE_BLE;
  270. dis_uuid.uuid = BLE_UUID_DEVICE_INFORMATION_SERVICE;
  271. p_ble_dis_c->conn_handle = BLE_CONN_HANDLE_INVALID;
  272. p_ble_dis_c->p_gatt_queue = p_ble_dis_c_init->p_gatt_queue;
  273. p_ble_dis_c->evt_handler = p_ble_dis_c_init->evt_handler;
  274. p_ble_dis_c->error_handler = p_ble_dis_c_init->error_handler;
  275. memset(p_ble_dis_c->handles, BLE_GATT_HANDLE_INVALID, sizeof(p_ble_dis_c->handles));
  276. // Enable only selected characteristics if characteristic group is defined.
  277. if (p_ble_dis_c_init->char_group.p_char_type != NULL)
  278. {
  279. p_ble_dis_c->char_mask = BLE_DIS_C_ALL_CHARS_DISABLED_MASK;
  280. for (uint8_t i = 0; i < p_ble_dis_c_init->char_group.size; i++)
  281. {
  282. nrf_bitmask_bit_set(p_ble_dis_c_init->char_group.p_char_type[i],
  283. &p_ble_dis_c->char_mask);
  284. }
  285. }
  286. else
  287. {
  288. p_ble_dis_c->char_mask = BLE_DIS_C_ALL_CHARS_ENABLED_MASK;
  289. }
  290. return ble_db_discovery_evt_register(&dis_uuid);
  291. }
  292. void ble_dis_c_on_db_disc_evt(ble_dis_c_t * p_ble_dis_c, ble_db_discovery_evt_t * p_evt)
  293. {
  294. ble_gatt_db_char_t * p_chars = p_evt->params.discovered_db.charateristics;
  295. ble_dis_c_evt_t ble_dis_c_evt;
  296. // Check if the service discovery is necessary for the link and if the event handler is present.
  297. if ((p_ble_dis_c->evt_handler == NULL) ||
  298. (p_ble_dis_c->conn_handle == p_evt->conn_handle))
  299. {
  300. return;
  301. }
  302. // Check if the DIS was discovered.
  303. if ((p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE) &&
  304. (p_evt->params.discovered_db.srv_uuid.uuid == BLE_UUID_DEVICE_INFORMATION_SERVICE) &&
  305. (p_evt->params.discovered_db.srv_uuid.type == BLE_UUID_TYPE_BLE))
  306. {
  307. memset(&ble_dis_c_evt, 0, sizeof(ble_dis_c_evt_t));
  308. ble_dis_c_evt.evt_type = BLE_DIS_C_EVT_DISCOVERY_COMPLETE;
  309. ble_dis_c_evt.conn_handle = p_evt->conn_handle;
  310. for (uint32_t i = 0; i < p_evt->params.discovered_db.char_count; i++)
  311. {
  312. switch (p_chars[i].characteristic.uuid.uuid)
  313. {
  314. case BLE_UUID_MANUFACTURER_NAME_STRING_CHAR:
  315. ble_dis_c_evt.params.disc_complete.handles[BLE_DIS_C_MANUF_NAME] =
  316. p_chars[i].characteristic.handle_value;
  317. break;
  318. case BLE_UUID_MODEL_NUMBER_STRING_CHAR:
  319. ble_dis_c_evt.params.disc_complete.handles[BLE_DIS_C_MODEL_NUM] =
  320. p_chars[i].characteristic.handle_value;
  321. break;
  322. case BLE_UUID_SERIAL_NUMBER_STRING_CHAR:
  323. ble_dis_c_evt.params.disc_complete.handles[BLE_DIS_C_SERIAL_NUM] =
  324. p_chars[i].characteristic.handle_value;
  325. break;
  326. case BLE_UUID_HARDWARE_REVISION_STRING_CHAR:
  327. ble_dis_c_evt.params.disc_complete.handles[BLE_DIS_C_HW_REV] =
  328. p_chars[i].characteristic.handle_value;
  329. break;
  330. case BLE_UUID_FIRMWARE_REVISION_STRING_CHAR:
  331. ble_dis_c_evt.params.disc_complete.handles[BLE_DIS_C_FW_REV] =
  332. p_chars[i].characteristic.handle_value;
  333. break;
  334. case BLE_UUID_SOFTWARE_REVISION_STRING_CHAR:
  335. ble_dis_c_evt.params.disc_complete.handles[BLE_DIS_C_SW_REV] =
  336. p_chars[i].characteristic.handle_value;
  337. break;
  338. case BLE_UUID_SYSTEM_ID_CHAR:
  339. ble_dis_c_evt.params.disc_complete.handles[BLE_DIS_C_SYS_ID] =
  340. p_chars[i].characteristic.handle_value;
  341. break;
  342. case BLE_UUID_IEEE_REGULATORY_CERTIFICATION_DATA_LIST_CHAR:
  343. ble_dis_c_evt.params.disc_complete.handles[BLE_DIS_C_CERT_LIST] =
  344. p_chars[i].characteristic.handle_value;
  345. break;
  346. case BLE_UUID_PNP_ID_CHAR:
  347. ble_dis_c_evt.params.disc_complete.handles[BLE_DIS_C_PNP_ID] =
  348. p_chars[i].characteristic.handle_value;
  349. break;
  350. default:
  351. break;
  352. }
  353. }
  354. // Forget handle values for disabled characteristics
  355. for (ble_dis_c_char_type_t char_type = (ble_dis_c_char_type_t) 0;
  356. char_type < BLE_DIS_C_CHAR_TYPES_NUM;
  357. char_type++)
  358. {
  359. if (!nrf_bitmask_bit_is_set(char_type, &p_ble_dis_c->char_mask))
  360. {
  361. ble_dis_c_evt.params.disc_complete.handles[char_type] = BLE_GATT_HANDLE_INVALID;
  362. }
  363. }
  364. p_ble_dis_c->evt_handler(p_ble_dis_c, &ble_dis_c_evt);
  365. }
  366. }
  367. void ble_dis_c_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
  368. {
  369. ble_dis_c_t * p_ble_dis_c = (ble_dis_c_t *) p_context;
  370. if ((p_ble_dis_c == NULL) || (p_ble_evt == NULL))
  371. {
  372. return;
  373. }
  374. if (p_ble_dis_c->conn_handle == BLE_CONN_HANDLE_INVALID)
  375. {
  376. return;
  377. }
  378. switch (p_ble_evt->header.evt_id)
  379. {
  380. case BLE_GATTC_EVT_READ_RSP:
  381. on_read_rsp(p_ble_dis_c, p_ble_evt);
  382. break;
  383. case BLE_GAP_EVT_DISCONNECTED:
  384. on_disconnected(p_ble_dis_c, p_ble_evt);
  385. break;
  386. default:
  387. // No implementation needed.
  388. break;
  389. }
  390. }
  391. ret_code_t ble_dis_c_read(ble_dis_c_t * p_ble_dis_c, ble_dis_c_char_type_t char_type)
  392. {
  393. ret_code_t err_code;
  394. nrf_ble_gq_req_t dis_c_req;
  395. VERIFY_PARAM_NOT_NULL(p_ble_dis_c);
  396. VERIFY_TRUE(char_type < BLE_DIS_C_CHAR_TYPES_NUM, NRF_ERROR_INVALID_PARAM);
  397. if ((p_ble_dis_c->conn_handle == BLE_CONN_HANDLE_INVALID) ||
  398. (p_ble_dis_c->handles[char_type] == BLE_GATT_HANDLE_INVALID))
  399. {
  400. return NRF_ERROR_INVALID_STATE;
  401. }
  402. memset(&dis_c_req, 0, sizeof(dis_c_req));
  403. dis_c_req.type = NRF_BLE_GQ_REQ_GATTC_READ;
  404. dis_c_req.error_handler.cb = gatt_error_handler;
  405. dis_c_req.error_handler.p_ctx = p_ble_dis_c;
  406. dis_c_req.params.gattc_read.handle = p_ble_dis_c->handles[char_type];
  407. err_code = nrf_ble_gq_item_add(p_ble_dis_c->p_gatt_queue, &dis_c_req, p_ble_dis_c->conn_handle);
  408. return err_code;
  409. }
  410. ret_code_t ble_dis_c_handles_assign(ble_dis_c_t * p_ble_dis_c,
  411. uint16_t conn_handle,
  412. ble_dis_c_handle_t const * p_peer_handles)
  413. {
  414. VERIFY_PARAM_NOT_NULL(p_ble_dis_c);
  415. p_ble_dis_c->conn_handle = conn_handle;
  416. if (p_peer_handles != NULL)
  417. {
  418. memcpy(p_ble_dis_c->handles, p_peer_handles, sizeof(p_ble_dis_c->handles));
  419. }
  420. else
  421. {
  422. memset(p_ble_dis_c->handles, BLE_GATT_HANDLE_INVALID, sizeof(p_ble_dis_c->handles));
  423. }
  424. return nrf_ble_gq_conn_handle_register(p_ble_dis_c->p_gatt_queue, conn_handle);
  425. }
  426. #endif // NRF_MODULE_ENABLED(BLE_DIS_C)