ble_db_discovery.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030
  1. /**
  2. * Copyright (c) 2013 - 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_DB_DISCOVERY)
  42. #include "ble_db_discovery.h"
  43. #include <stdlib.h>
  44. #include "ble_srv_common.h"
  45. #define NRF_LOG_MODULE_NAME ble_db_disc
  46. #include "nrf_log.h"
  47. NRF_LOG_MODULE_REGISTER();
  48. #define SRV_DISC_START_HANDLE 0x0001 /**< The start handle value used during service discovery. */
  49. #define DB_DISCOVERY_MAX_USERS BLE_DB_DISCOVERY_MAX_SRV /**< The maximum number of users/registrations allowed by this module. */
  50. #define MODULE_INITIALIZED (m_initialized == true) /**< Macro designating whether the module has been initialized properly. */
  51. /**@brief Array of structures containing information about the registered application modules. */
  52. static ble_uuid_t m_registered_handlers[DB_DISCOVERY_MAX_USERS];
  53. static ble_db_discovery_evt_handler_t m_evt_handler;
  54. static nrf_ble_gq_t * mp_gatt_queue; /**< Pointer to BLE GATT Queue instance. */
  55. static uint32_t m_num_of_handlers_reg; /**< The number of handlers registered with the DB Discovery module. */
  56. static bool m_initialized = false; /**< This variable Indicates if the module is initialized or not. */
  57. /**@brief Function for fetching the event handler provided by a registered application module.
  58. *
  59. * @param[in] srv_uuid UUID of the service.
  60. *
  61. * @retval evt_handler Event handler of the module, registered for the given service UUID.
  62. * @retval NULL If no event handler is found.
  63. */
  64. static ble_db_discovery_evt_handler_t registered_handler_get(ble_uuid_t const * p_srv_uuid)
  65. {
  66. for (uint32_t i = 0; i < m_num_of_handlers_reg; i++)
  67. {
  68. if (BLE_UUID_EQ(&(m_registered_handlers[i]), p_srv_uuid))
  69. {
  70. return (m_evt_handler);
  71. }
  72. }
  73. return NULL;
  74. }
  75. /**@brief Function for storing the event handler provided by a registered application module.
  76. *
  77. * @param[in] p_srv_uuid The UUID of the service.
  78. * @param[in] p_evt_handler The event handler provided by the application.
  79. *
  80. * @retval NRF_SUCCESS If the handler was stored or already present in the list.
  81. * @retval NRF_ERROR_NO_MEM If there is no space left to store the handler.
  82. */
  83. static uint32_t registered_handler_set(ble_uuid_t const * p_srv_uuid,
  84. ble_db_discovery_evt_handler_t p_evt_handler)
  85. {
  86. if (registered_handler_get(p_srv_uuid) != NULL)
  87. {
  88. return NRF_SUCCESS;
  89. }
  90. if (m_num_of_handlers_reg < DB_DISCOVERY_MAX_USERS)
  91. {
  92. m_registered_handlers[m_num_of_handlers_reg] = *p_srv_uuid;
  93. m_num_of_handlers_reg++;
  94. return NRF_SUCCESS;
  95. }
  96. else
  97. {
  98. return NRF_ERROR_NO_MEM;
  99. }
  100. }
  101. /**@brief Function for sending all pending discovery events to the corresponding user modules.
  102. */
  103. static void pending_user_evts_send(ble_db_discovery_t * p_db_discovery)
  104. {
  105. for (uint32_t i = 0; i < m_num_of_handlers_reg; i++)
  106. {
  107. // Pass the event to the corresponding event handler.
  108. p_db_discovery->pending_usr_evts[i].evt_handler(&(p_db_discovery->pending_usr_evts[i].evt));
  109. }
  110. p_db_discovery->pending_usr_evt_index = 0;
  111. }
  112. /**@brief Function for indicating availability of DB discovery instance.
  113. *
  114. * @details This function triggers an event indicating the finish of a discovery process.
  115. * If the event has happened, then the application can perform the next discovery
  116. * procedure on this DB discovery instance.
  117. *
  118. * @param[in] p_db_discovery Pointer to the DB discovery structure.
  119. * @param[in] conn_handle Connection Handle.
  120. */
  121. static void discovery_available_evt_trigger(ble_db_discovery_t * const p_db_discovery,
  122. uint16_t const conn_handle)
  123. {
  124. ble_db_discovery_evt_t evt;
  125. memset(&evt, 0, sizeof(evt));
  126. evt.conn_handle = conn_handle;
  127. evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE;
  128. evt.params.p_db_instance = (void *)p_db_discovery;
  129. if (m_evt_handler)
  130. {
  131. m_evt_handler(&evt);
  132. }
  133. }
  134. /**@brief Function for indicating error to the application.
  135. *
  136. * @details This function will fetch the event handler based on the UUID of the service being
  137. * discovered. (The event handler is registered by the application beforehand).
  138. * The error code is added to the pending events together with the event handler.
  139. * If no event handler was found, then this function will do nothing.
  140. *
  141. * @param[in] p_db_discovery Pointer to the DB discovery structure.
  142. * @param[in] err_code Error code that should be provided to the application.
  143. * @param[in] conn_handle Connection Handle.
  144. *
  145. */
  146. static void discovery_error_evt_trigger(ble_db_discovery_t * p_db_discovery,
  147. uint32_t err_code,
  148. uint16_t conn_handle)
  149. {
  150. ble_db_discovery_evt_handler_t p_evt_handler;
  151. ble_gatt_db_srv_t * p_srv_being_discovered;
  152. p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
  153. p_evt_handler = registered_handler_get(&(p_srv_being_discovered->srv_uuid));
  154. if (p_evt_handler != NULL)
  155. {
  156. ble_db_discovery_evt_t evt =
  157. {
  158. .conn_handle = conn_handle,
  159. .evt_type = BLE_DB_DISCOVERY_ERROR,
  160. .params.err_code = err_code,
  161. };
  162. p_evt_handler(&evt);
  163. }
  164. }
  165. /**@brief Function for interception of GATTC and @ref nrf_ble_gq errors.
  166. *
  167. * @param[in] nrf_error Error code.
  168. * @param[in] p_ctx Parameter from the event handler.
  169. * @param[in] conn_handle Connection handle.
  170. */
  171. static void discovery_error_handler(uint32_t nrf_error,
  172. void * p_ctx,
  173. uint16_t conn_handle)
  174. {
  175. ble_db_discovery_t * p_db_discovery = (ble_db_discovery_t *)p_ctx;
  176. p_db_discovery->discovery_in_progress = false;
  177. discovery_error_evt_trigger(p_db_discovery, nrf_error, conn_handle);
  178. discovery_available_evt_trigger(p_db_discovery, conn_handle);
  179. }
  180. /**@brief Function for triggering a Discovery Complete or Service Not Found event to the
  181. * application.
  182. *
  183. * @details This function will fetch the event handler based on the UUID of the service being
  184. * discovered. (The event handler is registered by the application beforehand).
  185. * It then triggers an event indicating the completion of the service discovery.
  186. * If no event handler was found, then this function will do nothing.
  187. *
  188. * @param[in] p_db_discovery Pointer to the DB discovery structure.
  189. * @param[in] is_srv_found Variable to indicate if the service was found at the peer.
  190. * @param[in] conn_handle Connection Handle.
  191. */
  192. static void discovery_complete_evt_trigger(ble_db_discovery_t * p_db_discovery,
  193. bool is_srv_found,
  194. uint16_t conn_handle)
  195. {
  196. ble_db_discovery_evt_handler_t p_evt_handler;
  197. ble_gatt_db_srv_t * p_srv_being_discovered;
  198. p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
  199. p_evt_handler = registered_handler_get(&(p_srv_being_discovered->srv_uuid));
  200. if (p_evt_handler != NULL)
  201. {
  202. if (p_db_discovery->pending_usr_evt_index < DB_DISCOVERY_MAX_USERS)
  203. {
  204. // Insert an event into the pending event list.
  205. p_db_discovery->pending_usr_evts[p_db_discovery->pending_usr_evt_index].evt.conn_handle = conn_handle;
  206. p_db_discovery->pending_usr_evts[p_db_discovery->pending_usr_evt_index].evt.params.discovered_db =
  207. *p_srv_being_discovered;
  208. if (is_srv_found)
  209. {
  210. p_db_discovery->pending_usr_evts[p_db_discovery->pending_usr_evt_index].evt.evt_type =
  211. BLE_DB_DISCOVERY_COMPLETE;
  212. }
  213. else
  214. {
  215. p_db_discovery->pending_usr_evts[p_db_discovery->pending_usr_evt_index].evt.evt_type =
  216. BLE_DB_DISCOVERY_SRV_NOT_FOUND;
  217. }
  218. p_db_discovery->pending_usr_evts[p_db_discovery->pending_usr_evt_index].evt_handler = p_evt_handler;
  219. p_db_discovery->pending_usr_evt_index++;
  220. if (p_db_discovery->pending_usr_evt_index == m_num_of_handlers_reg)
  221. {
  222. // All registered modules have pending events. Send all pending events to the user
  223. // modules.
  224. pending_user_evts_send(p_db_discovery);
  225. }
  226. else
  227. {
  228. // Too many events pending. Do nothing. (Ideally this should not happen.)
  229. }
  230. }
  231. }
  232. }
  233. /**@brief Function for handling service discovery completion.
  234. *
  235. * @details This function will be used to determine if there are more services to be discovered,
  236. * and if so, initiate the discovery of the next service.
  237. *
  238. * @param[in] p_db_discovery Pointer to the DB Discovery Structure.
  239. * @param[in] conn_handle Connection Handle.
  240. */
  241. static void on_srv_disc_completion(ble_db_discovery_t * p_db_discovery,
  242. uint16_t conn_handle)
  243. {
  244. nrf_ble_gq_req_t db_srv_disc_req;
  245. memset(&db_srv_disc_req, 0, sizeof(nrf_ble_gq_req_t));
  246. p_db_discovery->discoveries_count++;
  247. // Check if more services need to be discovered.
  248. if (p_db_discovery->discoveries_count < m_num_of_handlers_reg)
  249. {
  250. // Reset the current characteristic index since a new service discovery is about to start.
  251. p_db_discovery->curr_char_ind = 0;
  252. // Initiate discovery of the next service.
  253. p_db_discovery->curr_srv_ind++;
  254. ble_gatt_db_srv_t * p_srv_being_discovered;
  255. p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
  256. p_srv_being_discovered->srv_uuid = m_registered_handlers[p_db_discovery->curr_srv_ind];
  257. // Reset the characteristic count in the current service to zero since a new service
  258. // discovery is about to start.
  259. p_srv_being_discovered->char_count = 0;
  260. NRF_LOG_DEBUG("Starting discovery of service with UUID 0x%x on connection handle 0x%x.",
  261. p_srv_being_discovered->srv_uuid.uuid, conn_handle);
  262. uint32_t err_code;
  263. db_srv_disc_req.type = NRF_BLE_GQ_REQ_SRV_DISCOVERY;
  264. db_srv_disc_req.params.gattc_srv_disc.start_handle = SRV_DISC_START_HANDLE;
  265. db_srv_disc_req.params.gattc_srv_disc.srvc_uuid = p_srv_being_discovered->srv_uuid;
  266. db_srv_disc_req.error_handler.p_ctx = p_db_discovery;
  267. db_srv_disc_req.error_handler.cb = discovery_error_handler;
  268. err_code = nrf_ble_gq_item_add(mp_gatt_queue, &db_srv_disc_req, conn_handle);
  269. if (err_code != NRF_SUCCESS)
  270. {
  271. discovery_error_handler(err_code, p_db_discovery, conn_handle);
  272. return;
  273. }
  274. }
  275. else
  276. {
  277. // No more service discovery is needed.
  278. p_db_discovery->discovery_in_progress = false;
  279. discovery_available_evt_trigger(p_db_discovery, conn_handle);
  280. }
  281. }
  282. /**@brief Function for finding out if a characteristic discovery should be performed after the
  283. * last discovered characteristic.
  284. *
  285. * @details This function is used during the time of database discovery to find out if there is
  286. * a need to do more characteristic discoveries. The value handles of the
  287. * last discovered characteristic is compared with the end handle of the service.
  288. * If the service handle is greater than one of the former characteristic handles,
  289. * it means that a characteristic discovery is required.
  290. *
  291. * @param[in] p_db_discovery The pointer to the DB Discovery structure.
  292. * @param[in] p_after_char The pointer to the last discovered characteristic.
  293. *
  294. * @retval True if a characteristic discovery is required.
  295. * @retval False if a characteristic discovery is NOT required.
  296. */
  297. static bool is_char_discovery_reqd(ble_db_discovery_t * p_db_discovery,
  298. ble_gattc_char_t * p_after_char)
  299. {
  300. if (p_after_char->handle_value <
  301. p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle)
  302. {
  303. // Handle value of the characteristic being discovered is less than the end handle of
  304. // the service being discovered. There is a possibility of more characteristics being
  305. // present. Hence a characteristic discovery is required.
  306. return true;
  307. }
  308. return false;
  309. }
  310. /**@brief Function to find out if a descriptor discovery is required.
  311. *
  312. * @details This function finds out if there is a possibility of existence of descriptors between
  313. * current characteristic and the next characteristic. If so, this function will compute
  314. * the handle range on which the descriptors may be present and will return it.
  315. * If the current characteristic is the last known characteristic, then this function
  316. * will use the service end handle to find out if the current characteristic can have
  317. * descriptors.
  318. *
  319. * @param[in] p_db_discovery Pointer to the DB Discovery structure.
  320. * @param[in] p_curr_char Pointer to the current characteristic.
  321. * @param[in] p_next_char Pointer to the next characteristic. This should be NULL if the
  322. * caller knows that there is no characteristic after the current
  323. * characteristic at the peer.
  324. * @param[out] p_handle_range Pointer to the handle range in which descriptors may exist at the
  325. * the peer.
  326. *
  327. * @retval True If a descriptor discovery is required.
  328. * @retval False If a descriptor discovery is NOT required.
  329. */
  330. static bool is_desc_discovery_reqd(ble_db_discovery_t * p_db_discovery,
  331. ble_gatt_db_char_t * p_curr_char,
  332. ble_gatt_db_char_t * p_next_char,
  333. ble_gattc_handle_range_t * p_handle_range)
  334. {
  335. if (p_next_char == NULL)
  336. {
  337. // Current characteristic is the last characteristic in the service. Check if the value
  338. // handle of the current characteristic is equal to the service end handle.
  339. if (
  340. p_curr_char->characteristic.handle_value ==
  341. p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle
  342. )
  343. {
  344. // No descriptors can be present for the current characteristic. p_curr_char is the last
  345. // characteristic with no descriptors.
  346. return false;
  347. }
  348. p_handle_range->start_handle = p_curr_char->characteristic.handle_value + 1;
  349. // Since the current characteristic is the last characteristic in the service, the end
  350. // handle should be the end handle of the service.
  351. p_handle_range->end_handle =
  352. p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle;
  353. return true;
  354. }
  355. // p_next_char != NULL. Check for existence of descriptors between the current and the next
  356. // characteristic.
  357. if ((p_curr_char->characteristic.handle_value + 1) == p_next_char->characteristic.handle_decl)
  358. {
  359. // No descriptors can exist between the two characteristic.
  360. return false;
  361. }
  362. p_handle_range->start_handle = p_curr_char->characteristic.handle_value + 1;
  363. p_handle_range->end_handle = p_next_char->characteristic.handle_decl - 1;
  364. return true;
  365. }
  366. /**@brief Function for performing characteristic discovery.
  367. *
  368. * @param[in] p_db_discovery Pointer to the DB Discovery structure.
  369. * @param[in] conn_handle Connection Handle.
  370. *
  371. * @return NRF_SUCCESS if the SoftDevice was successfully requested to perform the characteristic
  372. * discovery. Otherwise an error code. This function returns the error code returned
  373. * by the SoftDevice API @ref sd_ble_gattc_characteristics_discover.
  374. */
  375. static uint32_t characteristics_discover(ble_db_discovery_t * p_db_discovery,
  376. uint16_t conn_handle)
  377. {
  378. ble_gatt_db_srv_t * p_srv_being_discovered;
  379. ble_gattc_handle_range_t handle_range;
  380. nrf_ble_gq_req_t db_char_disc_req;
  381. memset(&db_char_disc_req, 0, sizeof(nrf_ble_gq_req_t));
  382. memset(&handle_range, 0, sizeof(ble_gattc_handle_range_t));
  383. p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
  384. if (p_db_discovery->curr_char_ind != 0)
  385. {
  386. // This is not the first characteristic being discovered. Hence the 'start handle' to be
  387. // used must be computed using the handle_value of the previous characteristic.
  388. ble_gattc_char_t * p_prev_char;
  389. uint8_t prev_char_ind = p_db_discovery->curr_char_ind - 1;
  390. p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
  391. p_prev_char = &(p_srv_being_discovered->charateristics[prev_char_ind].characteristic);
  392. handle_range.start_handle = p_prev_char->handle_value + 1;
  393. }
  394. else
  395. {
  396. // This is the first characteristic of this service being discovered.
  397. handle_range.start_handle = p_srv_being_discovered->handle_range.start_handle;
  398. }
  399. handle_range.end_handle = p_srv_being_discovered->handle_range.end_handle;
  400. db_char_disc_req.type = NRF_BLE_GQ_REQ_CHAR_DISCOVERY;
  401. db_char_disc_req.params.gattc_char_disc = handle_range;
  402. db_char_disc_req.error_handler.p_ctx = p_db_discovery;
  403. db_char_disc_req.error_handler.cb = discovery_error_handler;
  404. return nrf_ble_gq_item_add(mp_gatt_queue, &db_char_disc_req, conn_handle);
  405. }
  406. /**@brief Function for performing descriptor discovery, if required.
  407. *
  408. * @details This function will check if descriptor discovery is required and then perform it if
  409. * needed. If no more descriptor discovery is required for the service, then the output
  410. * parameter p_raise_discov_complete is set to true, indicating to the caller that a
  411. * discovery complete event can be triggered to the application.
  412. *
  413. * @param[in] p_db_discovery Pointer to the DB Discovery structure.
  414. * @param[out] p_raise_discov_complete The value pointed to by this pointer will be set to true if
  415. * the Discovery Complete event can be triggered to the
  416. * application.
  417. * @param[in] conn_handle Connection Handle.
  418. *
  419. * @return NRF_SUCCESS if the SoftDevice was successfully requested to perform the descriptor
  420. * discovery, or if no more descriptor discovery is required. Otherwise an error code.
  421. * This function returns the error code returned by the SoftDevice API @ref
  422. * sd_ble_gattc_descriptors_discover.
  423. */
  424. static uint32_t descriptors_discover(ble_db_discovery_t * p_db_discovery,
  425. bool * p_raise_discov_complete,
  426. uint16_t conn_handle)
  427. {
  428. ble_gattc_handle_range_t handle_range;
  429. ble_gatt_db_char_t * p_curr_char_being_discovered;
  430. ble_gatt_db_srv_t * p_srv_being_discovered;
  431. nrf_ble_gq_req_t db_desc_disc_req;
  432. bool is_discovery_reqd = false;
  433. memset(&db_desc_disc_req, 0, sizeof(nrf_ble_gq_req_t));
  434. p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
  435. p_curr_char_being_discovered =
  436. &(p_srv_being_discovered->charateristics[p_db_discovery->curr_char_ind]);
  437. if ((p_db_discovery->curr_char_ind + 1) == p_srv_being_discovered->char_count)
  438. {
  439. // This is the last characteristic of this service.
  440. is_discovery_reqd = is_desc_discovery_reqd(p_db_discovery,
  441. p_curr_char_being_discovered,
  442. NULL,
  443. &handle_range);
  444. }
  445. else
  446. {
  447. uint8_t i;
  448. ble_gatt_db_char_t * p_next_char;
  449. for (i = p_db_discovery->curr_char_ind; i < p_srv_being_discovered->char_count; i++)
  450. {
  451. if (i == (p_srv_being_discovered->char_count - 1))
  452. {
  453. // The current characteristic is the last characteristic in the service.
  454. p_next_char = NULL;
  455. }
  456. else
  457. {
  458. p_next_char = &(p_srv_being_discovered->charateristics[i + 1]);
  459. }
  460. // Check if it is possible for the current characteristic to have a descriptor.
  461. if (is_desc_discovery_reqd(p_db_discovery,
  462. p_curr_char_being_discovered,
  463. p_next_char,
  464. &handle_range))
  465. {
  466. is_discovery_reqd = true;
  467. break;
  468. }
  469. else
  470. {
  471. // No descriptors can exist.
  472. p_curr_char_being_discovered = p_next_char;
  473. p_db_discovery->curr_char_ind++;
  474. }
  475. }
  476. }
  477. if (!is_discovery_reqd)
  478. {
  479. // No more descriptor discovery required. Discovery is complete.
  480. // This informs the caller that a discovery complete event can be triggered.
  481. *p_raise_discov_complete = true;
  482. return NRF_SUCCESS;
  483. }
  484. *p_raise_discov_complete = false;
  485. db_desc_disc_req.type = NRF_BLE_GQ_REQ_DESC_DISCOVERY;
  486. db_desc_disc_req.params.gattc_desc_disc = handle_range;
  487. db_desc_disc_req.error_handler.p_ctx = p_db_discovery;
  488. db_desc_disc_req.error_handler.cb = discovery_error_handler;
  489. return nrf_ble_gq_item_add(mp_gatt_queue, &db_desc_disc_req, conn_handle);
  490. }
  491. /**@brief Function for handling primary service discovery response.
  492. *
  493. * @details This function will handle the primary service discovery response and start the
  494. * discovery of characteristics within that service.
  495. *
  496. * @param[in] p_db_discovery Pointer to the DB Discovery structure.
  497. * @param[in] p_ble_gattc_evt Pointer to the GATT Client event.
  498. */
  499. static void on_primary_srv_discovery_rsp(ble_db_discovery_t * p_db_discovery,
  500. ble_gattc_evt_t const * p_ble_gattc_evt)
  501. {
  502. ble_gatt_db_srv_t * p_srv_being_discovered;
  503. p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
  504. if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle)
  505. {
  506. return;
  507. }
  508. if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS)
  509. {
  510. uint32_t err_code;
  511. ble_gattc_evt_prim_srvc_disc_rsp_t const * p_prim_srvc_disc_rsp_evt;
  512. NRF_LOG_DEBUG("Found service UUID 0x%x.", p_srv_being_discovered->srv_uuid.uuid);
  513. p_prim_srvc_disc_rsp_evt = &(p_ble_gattc_evt->params.prim_srvc_disc_rsp);
  514. p_srv_being_discovered->handle_range = p_prim_srvc_disc_rsp_evt->services[0].handle_range;
  515. // Number of services, previously discovered.
  516. uint8_t num_srv_previous_disc = p_db_discovery->srv_count;
  517. // Number of services, currently discovered.
  518. uint8_t current_srv_disc = p_prim_srvc_disc_rsp_evt->count;
  519. if ((num_srv_previous_disc + current_srv_disc) <= BLE_DB_DISCOVERY_MAX_SRV)
  520. {
  521. p_db_discovery->srv_count += current_srv_disc;
  522. }
  523. else
  524. {
  525. p_db_discovery->srv_count = BLE_DB_DISCOVERY_MAX_SRV;
  526. NRF_LOG_WARNING("Not enough space for services.");
  527. NRF_LOG_WARNING("Increase BLE_DB_DISCOVERY_MAX_SRV to be able to store more "
  528. "services!");
  529. }
  530. err_code = characteristics_discover(p_db_discovery, p_ble_gattc_evt->conn_handle);
  531. if (err_code != NRF_SUCCESS)
  532. {
  533. discovery_error_handler(err_code, p_db_discovery, p_ble_gattc_evt->conn_handle);
  534. }
  535. }
  536. else
  537. {
  538. NRF_LOG_DEBUG("Service UUID 0x%x not found.", p_srv_being_discovered->srv_uuid.uuid);
  539. // Trigger Service Not Found event to the application.
  540. discovery_complete_evt_trigger(p_db_discovery, false, p_ble_gattc_evt->conn_handle);
  541. on_srv_disc_completion(p_db_discovery, p_ble_gattc_evt->conn_handle);
  542. }
  543. }
  544. /**@brief Function for handling characteristic discovery response.
  545. *
  546. * @param[in] p_db_discovery Pointer to the DB Discovery structure.
  547. * @param[in] p_ble_gattc_evt Pointer to the GATT Client event.
  548. */
  549. static void on_characteristic_discovery_rsp(ble_db_discovery_t * p_db_discovery,
  550. ble_gattc_evt_t const * p_ble_gattc_evt)
  551. {
  552. uint32_t err_code;
  553. ble_gatt_db_srv_t * p_srv_being_discovered;
  554. bool perform_desc_discov = false;
  555. if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle)
  556. {
  557. return;
  558. }
  559. p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
  560. if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS)
  561. {
  562. ble_gattc_evt_char_disc_rsp_t const * p_char_disc_rsp_evt;
  563. p_char_disc_rsp_evt = &(p_ble_gattc_evt->params.char_disc_rsp);
  564. // Find out the number of characteristics that were previously discovered (in earlier
  565. // characteristic discovery responses, if any).
  566. uint8_t num_chars_prev_disc = p_srv_being_discovered->char_count;
  567. // Find out the number of characteristics that are currently discovered (in the
  568. // characteristic discovery response being handled).
  569. uint8_t num_chars_curr_disc = p_char_disc_rsp_evt->count;
  570. // Check if the total number of discovered characteristics are supported by this module.
  571. if ((num_chars_prev_disc + num_chars_curr_disc) <= BLE_GATT_DB_MAX_CHARS)
  572. {
  573. // Update the characteristics count.
  574. p_srv_being_discovered->char_count += num_chars_curr_disc;
  575. }
  576. else
  577. {
  578. // The number of characteristics discovered at the peer is more than the supported
  579. // maximum. This module will store only the characteristics found up to this point.
  580. p_srv_being_discovered->char_count = BLE_GATT_DB_MAX_CHARS;
  581. NRF_LOG_WARNING("Not enough space for characteristics associated with "
  582. "service 0x%04X !", p_srv_being_discovered->srv_uuid.uuid);
  583. NRF_LOG_WARNING("Increase BLE_GATT_DB_MAX_CHARS to be able to store more "
  584. "characteristics for each service!");
  585. }
  586. uint32_t i;
  587. uint32_t j;
  588. for (i = num_chars_prev_disc, j = 0; i < p_srv_being_discovered->char_count; i++, j++)
  589. {
  590. p_srv_being_discovered->charateristics[i].characteristic =
  591. p_char_disc_rsp_evt->chars[j];
  592. p_srv_being_discovered->charateristics[i].cccd_handle = BLE_GATT_HANDLE_INVALID;
  593. p_srv_being_discovered->charateristics[i].ext_prop_handle = BLE_GATT_HANDLE_INVALID;
  594. p_srv_being_discovered->charateristics[i].user_desc_handle = BLE_GATT_HANDLE_INVALID;
  595. p_srv_being_discovered->charateristics[i].report_ref_handle = BLE_GATT_HANDLE_INVALID;
  596. }
  597. ble_gattc_char_t * p_last_known_char;
  598. p_last_known_char = &(p_srv_being_discovered->charateristics[i - 1].characteristic);
  599. // If no more characteristic discovery is required, or if the maximum number of supported
  600. // characteristic per service has been reached, descriptor discovery will be performed.
  601. if ( !is_char_discovery_reqd(p_db_discovery, p_last_known_char)
  602. || (p_srv_being_discovered->char_count == BLE_GATT_DB_MAX_CHARS))
  603. {
  604. perform_desc_discov = true;
  605. }
  606. else
  607. {
  608. // Update the current characteristic index.
  609. p_db_discovery->curr_char_ind = p_srv_being_discovered->char_count;
  610. // Perform another round of characteristic discovery.
  611. err_code = characteristics_discover(p_db_discovery, p_ble_gattc_evt->conn_handle);
  612. if (err_code != NRF_SUCCESS)
  613. {
  614. discovery_error_handler(err_code, p_db_discovery, p_ble_gattc_evt->conn_handle);
  615. return;
  616. }
  617. }
  618. }
  619. else
  620. {
  621. // The previous characteristic discovery resulted in no characteristics.
  622. // descriptor discovery should be performed.
  623. perform_desc_discov = true;
  624. }
  625. if (perform_desc_discov)
  626. {
  627. bool raise_discov_complete;
  628. p_db_discovery->curr_char_ind = 0;
  629. err_code = descriptors_discover(p_db_discovery,
  630. &raise_discov_complete,
  631. p_ble_gattc_evt->conn_handle);
  632. if (err_code != NRF_SUCCESS)
  633. {
  634. discovery_error_handler(err_code, p_db_discovery, p_ble_gattc_evt->conn_handle);
  635. return;
  636. }
  637. if (raise_discov_complete)
  638. {
  639. // No more characteristics and descriptors need to be discovered. Discovery is complete.
  640. // Send a discovery complete event to the user application.
  641. NRF_LOG_DEBUG("Discovery of service with UUID 0x%x completed with success"
  642. " on connection handle 0x%x.",
  643. p_srv_being_discovered->srv_uuid.uuid,
  644. p_ble_gattc_evt->conn_handle);
  645. discovery_complete_evt_trigger(p_db_discovery, true, p_ble_gattc_evt->conn_handle);
  646. on_srv_disc_completion(p_db_discovery, p_ble_gattc_evt->conn_handle);
  647. }
  648. }
  649. }
  650. /**@brief Function for handling descriptor discovery response.
  651. *
  652. * @param[in] p_db_discovery Pointer to the DB Discovery structure.
  653. * @param[in] p_ble_gattc_evt Pointer to the GATT Client event.
  654. */
  655. static void on_descriptor_discovery_rsp(ble_db_discovery_t * const p_db_discovery,
  656. const ble_gattc_evt_t * const p_ble_gattc_evt)
  657. {
  658. const ble_gattc_evt_desc_disc_rsp_t * p_desc_disc_rsp_evt;
  659. ble_gatt_db_srv_t * p_srv_being_discovered;
  660. if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle)
  661. {
  662. return;
  663. }
  664. p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
  665. p_desc_disc_rsp_evt = &(p_ble_gattc_evt->params.desc_disc_rsp);
  666. ble_gatt_db_char_t * p_char_being_discovered =
  667. &(p_srv_being_discovered->charateristics[p_db_discovery->curr_char_ind]);
  668. if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS)
  669. {
  670. // The descriptor was found at the peer.
  671. // Iterate through and collect CCCD, Extended Properties,
  672. // User Description & Report Reference descriptor handles.
  673. for (uint32_t i = 0; i < p_desc_disc_rsp_evt->count; i++)
  674. {
  675. switch (p_desc_disc_rsp_evt->descs[i].uuid.uuid)
  676. {
  677. case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG:
  678. p_char_being_discovered->cccd_handle =
  679. p_desc_disc_rsp_evt->descs[i].handle;
  680. break;
  681. case BLE_UUID_DESCRIPTOR_CHAR_EXT_PROP:
  682. p_char_being_discovered->ext_prop_handle =
  683. p_desc_disc_rsp_evt->descs[i].handle;
  684. break;
  685. case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC:
  686. p_char_being_discovered->user_desc_handle =
  687. p_desc_disc_rsp_evt->descs[i].handle;
  688. break;
  689. case BLE_UUID_REPORT_REF_DESCR:
  690. p_char_being_discovered->report_ref_handle =
  691. p_desc_disc_rsp_evt->descs[i].handle;
  692. break;
  693. }
  694. /* Break if we've found all the descriptors we are looking for. */
  695. if (p_char_being_discovered->cccd_handle != BLE_GATT_HANDLE_INVALID &&
  696. p_char_being_discovered->ext_prop_handle != BLE_GATT_HANDLE_INVALID &&
  697. p_char_being_discovered->user_desc_handle != BLE_GATT_HANDLE_INVALID &&
  698. p_char_being_discovered->report_ref_handle != BLE_GATT_HANDLE_INVALID)
  699. {
  700. break;
  701. }
  702. }
  703. }
  704. bool raise_discov_complete = false;
  705. if ((p_db_discovery->curr_char_ind + 1) == p_srv_being_discovered->char_count)
  706. {
  707. // No more characteristics and descriptors need to be discovered. Discovery is complete.
  708. // Send a discovery complete event to the user application.
  709. raise_discov_complete = true;
  710. }
  711. else
  712. {
  713. // Begin discovery of descriptors for the next characteristic.
  714. uint32_t err_code;
  715. p_db_discovery->curr_char_ind++;
  716. err_code = descriptors_discover(p_db_discovery,
  717. &raise_discov_complete,
  718. p_ble_gattc_evt->conn_handle);
  719. if (err_code != NRF_SUCCESS)
  720. {
  721. discovery_error_handler(err_code, p_db_discovery, p_ble_gattc_evt->conn_handle);
  722. return;
  723. }
  724. }
  725. if (raise_discov_complete)
  726. {
  727. NRF_LOG_DEBUG("Discovery of service with UUID 0x%x completed with success"
  728. " on connection handle 0x%x.",
  729. p_srv_being_discovered->srv_uuid.uuid,
  730. p_ble_gattc_evt->conn_handle);
  731. discovery_complete_evt_trigger(p_db_discovery, true, p_ble_gattc_evt->conn_handle);
  732. on_srv_disc_completion(p_db_discovery, p_ble_gattc_evt->conn_handle);
  733. }
  734. }
  735. uint32_t ble_db_discovery_init(ble_db_discovery_init_t * p_db_init)
  736. {
  737. uint32_t err_code = NRF_SUCCESS;
  738. VERIFY_PARAM_NOT_NULL(p_db_init);
  739. VERIFY_PARAM_NOT_NULL(p_db_init->evt_handler);
  740. VERIFY_PARAM_NOT_NULL(p_db_init->p_gatt_queue);
  741. m_num_of_handlers_reg = 0;
  742. m_initialized = true;
  743. m_evt_handler = p_db_init->evt_handler;
  744. mp_gatt_queue = p_db_init->p_gatt_queue;
  745. return err_code;
  746. }
  747. uint32_t ble_db_discovery_close(ble_db_discovery_t * const p_db_discovery)
  748. {
  749. m_num_of_handlers_reg = 0;
  750. m_initialized = false;
  751. p_db_discovery->pending_usr_evt_index = 0;
  752. return NRF_SUCCESS;
  753. }
  754. uint32_t ble_db_discovery_evt_register(ble_uuid_t const * p_uuid)
  755. {
  756. VERIFY_PARAM_NOT_NULL(p_uuid);
  757. VERIFY_MODULE_INITIALIZED();
  758. return registered_handler_set(p_uuid, m_evt_handler);
  759. }
  760. static uint32_t discovery_start(ble_db_discovery_t * const p_db_discovery, uint16_t conn_handle)
  761. {
  762. ret_code_t err_code;
  763. ble_gatt_db_srv_t * p_srv_being_discovered;
  764. nrf_ble_gq_req_t db_srv_disc_req;
  765. memset(p_db_discovery, 0x00, sizeof(ble_db_discovery_t));
  766. memset(&db_srv_disc_req, 0x00, sizeof(nrf_ble_gq_req_t));
  767. err_code = nrf_ble_gq_conn_handle_register(mp_gatt_queue, conn_handle);
  768. VERIFY_SUCCESS(err_code);
  769. p_db_discovery->conn_handle = conn_handle;
  770. p_db_discovery->pending_usr_evt_index = 0;
  771. p_db_discovery->discoveries_count = 0;
  772. p_db_discovery->curr_srv_ind = 0;
  773. p_db_discovery->curr_char_ind = 0;
  774. p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
  775. p_srv_being_discovered->srv_uuid = m_registered_handlers[p_db_discovery->curr_srv_ind];
  776. NRF_LOG_DEBUG("Starting discovery of service with UUID 0x%x on connection handle 0x%x.",
  777. p_srv_being_discovered->srv_uuid.uuid, conn_handle);
  778. db_srv_disc_req.type = NRF_BLE_GQ_REQ_SRV_DISCOVERY;
  779. db_srv_disc_req.params.gattc_srv_disc.start_handle = SRV_DISC_START_HANDLE;
  780. db_srv_disc_req.params.gattc_srv_disc.srvc_uuid = p_srv_being_discovered->srv_uuid;
  781. db_srv_disc_req.error_handler.p_ctx = p_db_discovery;
  782. db_srv_disc_req.error_handler.cb = discovery_error_handler;
  783. err_code = nrf_ble_gq_item_add(mp_gatt_queue, &db_srv_disc_req, conn_handle);
  784. if (err_code == NRF_SUCCESS)
  785. {
  786. p_db_discovery->discovery_in_progress = true;
  787. }
  788. return err_code;
  789. }
  790. uint32_t ble_db_discovery_start(ble_db_discovery_t * const p_db_discovery, uint16_t conn_handle)
  791. {
  792. VERIFY_PARAM_NOT_NULL(p_db_discovery);
  793. VERIFY_MODULE_INITIALIZED();
  794. if (m_num_of_handlers_reg == 0)
  795. {
  796. // No user modules were registered. There are no services to discover.
  797. return NRF_ERROR_INVALID_STATE;
  798. }
  799. if (p_db_discovery->discovery_in_progress)
  800. {
  801. return NRF_ERROR_BUSY;
  802. }
  803. return discovery_start(p_db_discovery, conn_handle);
  804. }
  805. /**@brief Function for handling disconnected event.
  806. *
  807. * @param[in] p_db_discovery Pointer to the DB Discovery structure.
  808. * @param[in] p_ble_gattc_evt Pointer to the GAP event.
  809. */
  810. static void on_disconnected(ble_db_discovery_t * p_db_discovery,
  811. ble_gap_evt_t const * p_evt)
  812. {
  813. if (p_evt->conn_handle == p_db_discovery->conn_handle)
  814. {
  815. p_db_discovery->discovery_in_progress = false;
  816. p_db_discovery->conn_handle = BLE_CONN_HANDLE_INVALID;
  817. }
  818. }
  819. void ble_db_discovery_on_ble_evt(ble_evt_t const * p_ble_evt,
  820. void * p_context)
  821. {
  822. VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
  823. VERIFY_PARAM_NOT_NULL_VOID(p_context);
  824. VERIFY_MODULE_INITIALIZED_VOID();
  825. ble_db_discovery_t * p_db_discovery = (ble_db_discovery_t *)p_context;
  826. switch (p_ble_evt->header.evt_id)
  827. {
  828. case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
  829. on_primary_srv_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));
  830. break;
  831. case BLE_GATTC_EVT_CHAR_DISC_RSP:
  832. on_characteristic_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));
  833. break;
  834. case BLE_GATTC_EVT_DESC_DISC_RSP:
  835. on_descriptor_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));
  836. break;
  837. case BLE_GAP_EVT_DISCONNECTED:
  838. on_disconnected(p_db_discovery, &(p_ble_evt->evt.gap_evt));
  839. break;
  840. default:
  841. break;
  842. }
  843. }
  844. #endif // NRF_MODULE_ENABLED(BLE_DB_DISCOVERY)