cgms_racp.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  1. /**
  2. * Copyright (c) 2016 - 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 <stdint.h>
  41. #include <string.h>
  42. #include "ble.h"
  43. #include "ble_srv_common.h"
  44. #include "cgms_racp.h"
  45. #include "cgms_db.h"
  46. #include "nrf_ble_gq.h"
  47. #include "cgms_meas.h"
  48. #define OPERAND_LESS_GREATER_FILTER_TYPE_SIZE 1 // !< 1 byte.
  49. #define OPERAND_LESS_GREATER_FILTER_PARAM_SIZE 2 // !< 2 bytes.
  50. #define OPERAND_LESS_GREATER_SIZE OPERAND_LESS_GREATER_FILTER_TYPE_SIZE \
  51. + OPERAND_LESS_GREATER_FILTER_PARAM_SIZE // !< Total size of the operand.
  52. /**@brief Function for adding a characteristic for the Record Access Control Point.
  53. *
  54. * @param[in] p_cgms Service instance.
  55. *
  56. * @return NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
  57. */
  58. ret_code_t cgms_racp_char_add(nrf_ble_cgms_t * p_cgms)
  59. {
  60. ble_add_char_params_t add_char_params;
  61. memset(&add_char_params, 0, sizeof(add_char_params));
  62. add_char_params.uuid = BLE_UUID_RECORD_ACCESS_CONTROL_POINT_CHAR;
  63. add_char_params.max_len = BLE_GATT_ATT_MTU_DEFAULT;
  64. add_char_params.init_len = 0;
  65. add_char_params.p_init_value = 0;
  66. add_char_params.is_var_len = true;
  67. add_char_params.write_access = SEC_JUST_WORKS;
  68. add_char_params.char_props.write = true;
  69. add_char_params.char_props.indicate = true;
  70. add_char_params.cccd_write_access = SEC_JUST_WORKS;
  71. add_char_params.is_defered_write = 1;
  72. return characteristic_add(p_cgms->service_handle,
  73. &add_char_params,
  74. &p_cgms->char_handles.racp);
  75. }
  76. /**@brief Function for sending response from Specific Operation Control Point.
  77. *
  78. * @param[in] p_cgms Service instance.
  79. * @param[in] p_racp_val RACP value to be sent.
  80. */
  81. static void racp_send(nrf_ble_cgms_t * p_cgms, ble_racp_value_t * p_racp_val)
  82. {
  83. uint32_t err_code;
  84. uint8_t encoded_resp[25];
  85. uint16_t len;
  86. nrf_ble_gq_req_t cgms_req;
  87. memset(&cgms_req, 0, sizeof(nrf_ble_gq_req_t));
  88. // Send indication
  89. len = ble_racp_encode(p_racp_val, encoded_resp);
  90. cgms_req.type = NRF_BLE_GQ_REQ_GATTS_HVX;
  91. cgms_req.error_handler.cb = p_cgms->gatt_err_handler;
  92. cgms_req.error_handler.p_ctx = p_cgms;
  93. cgms_req.params.gatts_hvx.type = BLE_GATT_HVX_INDICATION;
  94. cgms_req.params.gatts_hvx.handle = p_cgms->char_handles.racp.value_handle;
  95. cgms_req.params.gatts_hvx.offset = 0;
  96. cgms_req.params.gatts_hvx.p_data = encoded_resp;
  97. cgms_req.params.gatts_hvx.p_len = &len;
  98. err_code = nrf_ble_gq_item_add(p_cgms->p_gatt_queue, &cgms_req, p_cgms->conn_handle);
  99. // Report error to application
  100. if ((p_cgms->error_handler != NULL) &&
  101. (err_code != NRF_SUCCESS) &&
  102. (err_code != NRF_ERROR_INVALID_STATE))
  103. {
  104. p_cgms->error_handler(err_code);
  105. }
  106. }
  107. /**@brief Function for sending a RACP response containing a Response Code Op Code and Response Code Value.
  108. *
  109. * @param[in] p_cgms Service instance.
  110. * @param[in] opcode RACP Op Code.
  111. * @param[in] value RACP Response Code Value.
  112. */
  113. static void racp_response_code_send(nrf_ble_cgms_t * p_cgms, uint8_t opcode, uint8_t value)
  114. {
  115. p_cgms->racp_data.pending_racp_response.opcode = RACP_OPCODE_RESPONSE_CODE;
  116. p_cgms->racp_data.pending_racp_response.operator = RACP_OPERATOR_NULL;
  117. p_cgms->racp_data.pending_racp_response.operand_len = 2;
  118. p_cgms->racp_data.pending_racp_response.p_operand =
  119. p_cgms->racp_data.pending_racp_response_operand;
  120. p_cgms->racp_data.pending_racp_response_operand[0] = opcode;
  121. p_cgms->racp_data.pending_racp_response_operand[1] = value;
  122. racp_send(p_cgms, &p_cgms->racp_data.pending_racp_response);
  123. }
  124. /**@brief Function for responding to the ALL operation.
  125. *
  126. * @param[in] p_cgms Service instance.
  127. *
  128. * @return NRF_SUCCESS on success, otherwise an error code.
  129. */
  130. static uint32_t racp_report_records_all(nrf_ble_cgms_t * p_cgms)
  131. {
  132. uint16_t total_records = cgms_db_num_records_get();
  133. uint16_t cur_nb_rec;
  134. uint8_t i;
  135. uint8_t nb_rec_to_send;
  136. if (p_cgms->racp_data.racp_proc_record_ndx >= total_records)
  137. {
  138. p_cgms->racp_data.racp_procesing_active = false;
  139. }
  140. else
  141. {
  142. uint32_t err_code;
  143. ble_cgms_rec_t rec[NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX];
  144. cur_nb_rec = total_records - p_cgms->racp_data.racp_proc_record_ndx;
  145. if (cur_nb_rec > NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX)
  146. {
  147. cur_nb_rec = NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX;
  148. }
  149. nb_rec_to_send = (uint8_t)cur_nb_rec;
  150. for (i = 0; i < cur_nb_rec; i++)
  151. {
  152. err_code = cgms_db_record_get(p_cgms->racp_data.racp_proc_record_ndx + i, &(rec[i]));
  153. if (err_code != NRF_SUCCESS)
  154. {
  155. return err_code;
  156. }
  157. }
  158. err_code = cgms_meas_send(p_cgms, rec, &nb_rec_to_send);
  159. if (err_code != NRF_SUCCESS)
  160. {
  161. return err_code;
  162. }
  163. p_cgms->racp_data.racp_proc_record_ndx += nb_rec_to_send;
  164. }
  165. return NRF_SUCCESS;
  166. }
  167. /**@brief Function for responding to the FIRST or the LAST operation.
  168. *
  169. * @param[in] p_cgms Service instance.
  170. *
  171. * @return NRF_SUCCESS on success, otherwise an error code.
  172. */
  173. static uint32_t racp_report_records_first_last(nrf_ble_cgms_t * p_cgms)
  174. {
  175. uint32_t err_code;
  176. ble_cgms_rec_t rec;
  177. uint16_t total_records;
  178. uint8_t nb_rec_to_send = 1;
  179. total_records = cgms_db_num_records_get();
  180. if ((p_cgms->racp_data.racp_proc_records_reported != 0) || (total_records == 0))
  181. {
  182. p_cgms->racp_data.racp_procesing_active = false;
  183. }
  184. else
  185. {
  186. if (p_cgms->racp_data.racp_proc_operator == RACP_OPERATOR_FIRST)
  187. {
  188. err_code = cgms_db_record_get(0, &rec);
  189. if (err_code != NRF_SUCCESS)
  190. {
  191. return err_code;
  192. }
  193. }
  194. else if (p_cgms->racp_data.racp_proc_operator == RACP_OPERATOR_LAST)
  195. {
  196. err_code = cgms_db_record_get(total_records - 1, &rec);
  197. if (err_code != NRF_SUCCESS)
  198. {
  199. return err_code;
  200. }
  201. }
  202. err_code = cgms_meas_send(p_cgms, &rec, &nb_rec_to_send);
  203. if (err_code != NRF_SUCCESS)
  204. {
  205. return err_code;
  206. }
  207. p_cgms->racp_data.racp_proc_record_ndx++;
  208. }
  209. return NRF_SUCCESS;
  210. }
  211. /**@brief Function for responding to the LESS OR EQUAL operation.
  212. *
  213. * @param[in] p_cgms Service instance.
  214. *
  215. * @return NRF_SUCCESS on success, otherwise an error code.
  216. */
  217. static ret_code_t racp_report_records_less_equal(nrf_ble_cgms_t * p_cgms)
  218. {
  219. uint16_t total_rec_nb_to_send;
  220. uint16_t rec_nb_left_to_send;
  221. uint8_t nb_rec_to_send;
  222. uint16_t i;
  223. total_rec_nb_to_send = p_cgms->racp_data.racp_proc_records_ndx_last_to_send +1;
  224. if (p_cgms->racp_data.racp_proc_record_ndx >= total_rec_nb_to_send)
  225. {
  226. p_cgms->racp_data.racp_procesing_active = false;
  227. }
  228. else
  229. {
  230. ret_code_t err_code;
  231. ble_cgms_rec_t rec[NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX];
  232. rec_nb_left_to_send = total_rec_nb_to_send - p_cgms->racp_data.racp_proc_records_reported;
  233. if (rec_nb_left_to_send > NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX)
  234. {
  235. nb_rec_to_send = NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX;
  236. }
  237. else
  238. {
  239. nb_rec_to_send = (uint8_t)rec_nb_left_to_send;
  240. }
  241. for (i = 0; i < nb_rec_to_send; i++)
  242. {
  243. err_code = cgms_db_record_get(p_cgms->racp_data.racp_proc_record_ndx + i, &(rec[i]));
  244. if (err_code != NRF_SUCCESS)
  245. {
  246. return err_code;
  247. }
  248. }
  249. err_code = cgms_meas_send(p_cgms, rec, &nb_rec_to_send);
  250. if (err_code != NRF_SUCCESS)
  251. {
  252. return err_code;
  253. }
  254. p_cgms->racp_data.racp_proc_record_ndx += nb_rec_to_send;
  255. }
  256. return NRF_SUCCESS;
  257. }
  258. /**@brief Function for responding to the GREATER OR EQUAL operation.
  259. *
  260. * @param[in] p_cgms Service instance.
  261. *
  262. * @return NRF_SUCCESS on success, otherwise an error code.
  263. */
  264. static ret_code_t racp_report_records_greater_equal(nrf_ble_cgms_t * p_cgms)
  265. {
  266. ret_code_t err_code;
  267. uint16_t total_rec_nb = cgms_db_num_records_get();
  268. uint16_t rec_nb_left_to_send;
  269. uint8_t nb_rec_to_send;
  270. uint16_t i;
  271. total_rec_nb = cgms_db_num_records_get();
  272. if (p_cgms->racp_data.racp_proc_record_ndx >= total_rec_nb)
  273. {
  274. p_cgms->racp_data.racp_procesing_active = false;
  275. return NRF_SUCCESS;
  276. }
  277. ble_cgms_rec_t rec[NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX];
  278. rec_nb_left_to_send = total_rec_nb - p_cgms->racp_data.racp_proc_record_ndx;
  279. if (rec_nb_left_to_send > NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX)
  280. {
  281. nb_rec_to_send = NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX;
  282. }
  283. else
  284. {
  285. nb_rec_to_send = (uint8_t)rec_nb_left_to_send;
  286. }
  287. for (i = 0; i < nb_rec_to_send; i++)
  288. {
  289. err_code = cgms_db_record_get(p_cgms->racp_data.racp_proc_record_ndx + i, &(rec[i]));
  290. if (err_code != NRF_SUCCESS)
  291. {
  292. return err_code;
  293. }
  294. }
  295. err_code = cgms_meas_send(p_cgms, rec, &nb_rec_to_send);
  296. if (err_code != NRF_SUCCESS)
  297. {
  298. return err_code;
  299. }
  300. p_cgms->racp_data.racp_proc_record_ndx += nb_rec_to_send;
  301. return NRF_SUCCESS;
  302. }
  303. /**@brief Function for informing that the REPORT RECORDS procedure is completed.
  304. *
  305. * @param[in] p_cgms Service instance.
  306. */
  307. static void racp_report_records_completed(nrf_ble_cgms_t * p_cgms)
  308. {
  309. uint8_t resp_code_value;
  310. if (p_cgms->racp_data.racp_proc_records_reported > 0)
  311. {
  312. resp_code_value = RACP_RESPONSE_SUCCESS;
  313. }
  314. else
  315. {
  316. resp_code_value = RACP_RESPONSE_NO_RECORDS_FOUND;
  317. }
  318. racp_response_code_send(p_cgms, RACP_OPCODE_REPORT_RECS, resp_code_value);
  319. }
  320. /**@brief Function for the RACP report records procedure.
  321. *
  322. * @param[in] p_cgms Service instance.
  323. */
  324. static void racp_report_records_procedure(nrf_ble_cgms_t * p_cgms)
  325. {
  326. ret_code_t err_code = NRF_SUCCESS;
  327. while (p_cgms->racp_data.racp_procesing_active)
  328. {
  329. // Execute requested procedure
  330. switch (p_cgms->racp_data.racp_proc_operator)
  331. {
  332. case RACP_OPERATOR_ALL:
  333. err_code = racp_report_records_all(p_cgms);
  334. break;
  335. case RACP_OPERATOR_FIRST:
  336. // Fall through.
  337. case RACP_OPERATOR_LAST:
  338. err_code = racp_report_records_first_last(p_cgms);
  339. break;
  340. case RACP_OPERATOR_GREATER_OR_EQUAL:
  341. err_code = racp_report_records_greater_equal(p_cgms);
  342. break;
  343. case RACP_OPERATOR_LESS_OR_EQUAL:
  344. err_code = racp_report_records_less_equal(p_cgms);
  345. break;
  346. default:
  347. // Report error to application
  348. if (p_cgms->error_handler != NULL)
  349. {
  350. p_cgms->error_handler(NRF_ERROR_INTERNAL);
  351. }
  352. p_cgms->racp_data.racp_procesing_active = false;
  353. return;
  354. }
  355. // Error handling
  356. switch (err_code)
  357. {
  358. case NRF_SUCCESS:
  359. if (!p_cgms->racp_data.racp_procesing_active)
  360. {
  361. racp_report_records_completed(p_cgms);
  362. }
  363. break;
  364. case NRF_ERROR_RESOURCES:
  365. // Wait for TX_COMPLETE event to resume transmission.
  366. return;
  367. case NRF_ERROR_INVALID_STATE:
  368. // Notification is probably not enabled. Ignore request.
  369. p_cgms->racp_data.racp_procesing_active = false;;
  370. return;
  371. default:
  372. // Report error to application.
  373. if (p_cgms->error_handler != NULL)
  374. {
  375. p_cgms->error_handler(err_code);
  376. }
  377. // Make sure state machine returns to the default state.
  378. p_cgms->racp_data.racp_procesing_active = false;
  379. return;
  380. }
  381. }
  382. }
  383. /**@brief Function for testing if the received request is to be executed.
  384. *
  385. * @param[in] p_racp_request Request to be checked.
  386. * @param[out] p_response_code Response code to be sent in case the request is rejected.
  387. * RACP_RESPONSE_RESERVED is returned if the received message is
  388. * to be rejected without sending a respone.
  389. *
  390. * @return TRUE if the request is to be executed, FALSE if it is to be rejected.
  391. * If it is to be rejected, p_response_code will contain the response code to be
  392. * returned to the central.
  393. */
  394. static bool is_request_to_be_executed(nrf_ble_cgms_t * p_cgms,
  395. const ble_racp_value_t * p_racp_request,
  396. uint8_t * p_response_code)
  397. {
  398. *p_response_code = RACP_RESPONSE_RESERVED;
  399. if (p_racp_request->opcode == RACP_OPCODE_ABORT_OPERATION)
  400. {
  401. if (p_cgms->racp_data.racp_procesing_active)
  402. {
  403. if (p_racp_request->operator != RACP_OPERATOR_NULL)
  404. {
  405. *p_response_code = RACP_RESPONSE_INVALID_OPERATOR;
  406. }
  407. else if (p_racp_request->operand_len != 0)
  408. {
  409. *p_response_code = RACP_RESPONSE_INVALID_OPERAND;
  410. }
  411. else
  412. {
  413. *p_response_code = RACP_RESPONSE_SUCCESS;
  414. }
  415. }
  416. else
  417. {
  418. *p_response_code = RACP_RESPONSE_ABORT_FAILED;
  419. }
  420. }
  421. else if (p_cgms->racp_data.racp_procesing_active)
  422. {
  423. return false;
  424. }
  425. // Supported opcodes
  426. else if ((p_racp_request->opcode == RACP_OPCODE_REPORT_RECS) ||
  427. (p_racp_request->opcode == RACP_OPCODE_REPORT_NUM_RECS))
  428. {
  429. switch (p_racp_request->operator)
  430. {
  431. // Operators without a filter.
  432. case RACP_OPERATOR_ALL:
  433. // Fall through.
  434. case RACP_OPERATOR_FIRST:
  435. // Fall through.
  436. case RACP_OPERATOR_LAST:
  437. if (p_racp_request->operand_len != 0)
  438. {
  439. *p_response_code = RACP_RESPONSE_INVALID_OPERAND;
  440. }
  441. break;
  442. // Operators with a filter as part of the operand.
  443. case RACP_OPERATOR_LESS_OR_EQUAL:
  444. // Fall Through.
  445. case RACP_OPERATOR_GREATER_OR_EQUAL:
  446. if (*(p_racp_request->p_operand) == RACP_OPERAND_FILTER_TYPE_FACING_TIME)
  447. {
  448. *p_response_code = RACP_RESPONSE_PROCEDURE_NOT_DONE;
  449. }
  450. if (p_racp_request->operand_len != OPERAND_LESS_GREATER_SIZE)
  451. {
  452. *p_response_code = RACP_RESPONSE_INVALID_OPERAND;
  453. }
  454. break;
  455. case RACP_OPERATOR_RANGE:
  456. *p_response_code = RACP_RESPONSE_OPERATOR_UNSUPPORTED;
  457. break;
  458. // Invalid operators.
  459. case RACP_OPERATOR_NULL:
  460. // Fall through.
  461. default:
  462. *p_response_code = RACP_RESPONSE_INVALID_OPERATOR;
  463. break;
  464. }
  465. }
  466. // Unsupported opcodes.
  467. else if (p_racp_request->opcode == RACP_OPCODE_DELETE_RECS)
  468. {
  469. *p_response_code = RACP_RESPONSE_OPCODE_UNSUPPORTED;
  470. }
  471. // Unknown opcodes.
  472. else
  473. {
  474. *p_response_code = RACP_RESPONSE_OPCODE_UNSUPPORTED;
  475. }
  476. return (*p_response_code == RACP_RESPONSE_RESERVED);
  477. }
  478. /**@brief Function for getting a record with time offset less or equal to the input param.
  479. *
  480. * @param[in] offset The record that this function returns must have an time offset less or greater to this.
  481. * @param[out] record_num Pointer to the record index of the record that has the desired time offset.
  482. *
  483. * @retval NRF_SUCCESS If the record was successfully retrieved.
  484. * @retval NRF_ERROR_NOT_FOUND A record with the desired offset does not exist in the database.
  485. * @return If functions from other modules return errors to this function,
  486. * the @ref nrf_error are propagated.
  487. */
  488. static ret_code_t record_index_offset_less_or_equal_get(uint16_t offset, uint16_t * record_num)
  489. {
  490. ret_code_t err_code;
  491. ble_cgms_rec_t rec;
  492. uint16_t upper_bound = cgms_db_num_records_get();
  493. for((*record_num) = upper_bound; (*record_num)-- >0;)
  494. {
  495. err_code = cgms_db_record_get(*record_num, &rec);
  496. if (err_code != NRF_SUCCESS)
  497. {
  498. return err_code;
  499. }
  500. if (rec.meas.time_offset <= offset)
  501. {
  502. return NRF_SUCCESS;
  503. }
  504. }
  505. return NRF_ERROR_NOT_FOUND;
  506. }
  507. /**@brief Function for getting a record with time offset greater or equal to the input param.
  508. *
  509. * @param[in] offset The record that this function returns must have an time offset equal or
  510. * greater to this.
  511. * @param[out] record_num Pointer to the record index of the record that has the desired time offset.
  512. *
  513. * @retval NRF_SUCCESS If the record was successfully retrieved.
  514. * @retval NRF_ERROR_NOT_FOUND A record with the desired offset does not exist in the database.
  515. * @return If functions from other modules return errors to this function,
  516. * the @ref nrf_error are propagated.
  517. */
  518. static ret_code_t record_index_offset_greater_or_equal_get(uint16_t offset, uint16_t * record_num)
  519. {
  520. ret_code_t err_code;
  521. ble_cgms_rec_t rec;
  522. uint16_t upper_bound = cgms_db_num_records_get();
  523. for(*record_num = 0; *record_num < upper_bound; (*record_num)++)
  524. {
  525. err_code = cgms_db_record_get(*record_num, &rec);
  526. if (err_code != NRF_SUCCESS)
  527. {
  528. return err_code;
  529. }
  530. if (rec.meas.time_offset >= offset)
  531. {
  532. return NRF_SUCCESS;
  533. }
  534. }
  535. return NRF_ERROR_NOT_FOUND;
  536. }
  537. /**@brief Function for processing a REPORT RECORDS request.
  538. *
  539. * @details Set initial values before entering the state machine of racp_report_records_procedure().
  540. *
  541. * @param[in] p_cgms Service instance.
  542. * @param[in] p_racp_request Request to be executed.
  543. */
  544. static void report_records_request_execute(nrf_ble_cgms_t * p_cgms,
  545. ble_racp_value_t * p_racp_request)
  546. {
  547. p_cgms->racp_data.racp_procesing_active = true;
  548. p_cgms->racp_data.racp_proc_record_ndx = 0;
  549. p_cgms->racp_data.racp_proc_operator = p_racp_request->operator;
  550. p_cgms->racp_data.racp_proc_records_reported = 0;
  551. p_cgms->racp_data.racp_proc_records_ndx_last_to_send = 0;
  552. if (p_cgms->racp_data.racp_proc_operator == RACP_OPERATOR_GREATER_OR_EQUAL)
  553. {
  554. uint16_t offset_requested = uint16_decode(&p_cgms->racp_data.racp_request.p_operand[OPERAND_LESS_GREATER_FILTER_TYPE_SIZE]);
  555. ret_code_t err_code = record_index_offset_greater_or_equal_get(offset_requested, &p_cgms->racp_data.racp_proc_record_ndx);
  556. if (err_code != NRF_SUCCESS)
  557. {
  558. racp_report_records_completed(p_cgms);
  559. }
  560. }
  561. if (p_cgms->racp_data.racp_proc_operator == RACP_OPERATOR_LESS_OR_EQUAL)
  562. {
  563. uint16_t offset_requested = uint16_decode(&p_cgms->racp_data.racp_request.p_operand[OPERAND_LESS_GREATER_FILTER_TYPE_SIZE]);
  564. ret_code_t err_code = record_index_offset_less_or_equal_get(offset_requested,
  565. &p_cgms->racp_data.racp_proc_records_ndx_last_to_send);
  566. if (err_code != NRF_SUCCESS)
  567. {
  568. racp_report_records_completed(p_cgms);
  569. }
  570. }
  571. racp_report_records_procedure(p_cgms);
  572. }
  573. /**@brief Function for processing a REPORT NUM RECORDS request.
  574. *
  575. * @param[in] p_cgms Service instance.
  576. * @param[in] p_racp_request Request to be executed.
  577. */
  578. static void report_num_records_request_execute(nrf_ble_cgms_t * p_cgms,
  579. ble_racp_value_t * p_racp_request)
  580. {
  581. uint16_t total_records;
  582. uint16_t num_records;
  583. total_records = cgms_db_num_records_get();
  584. num_records = 0;
  585. if (p_racp_request->operator == RACP_OPERATOR_ALL)
  586. {
  587. num_records = total_records;
  588. }
  589. else if ((p_racp_request->operator == RACP_OPERATOR_FIRST) ||
  590. (p_racp_request->operator == RACP_OPERATOR_LAST))
  591. {
  592. if (total_records > 0)
  593. {
  594. num_records = 1;
  595. }
  596. }
  597. else if (p_racp_request->operator == RACP_OPERATOR_GREATER_OR_EQUAL)
  598. {
  599. uint16_t index_of_offset;
  600. uint16_t offset_requested = uint16_decode(&p_cgms->racp_data.racp_request.p_operand[OPERAND_LESS_GREATER_FILTER_TYPE_SIZE]);
  601. ret_code_t err_code = record_index_offset_greater_or_equal_get(offset_requested, &index_of_offset);
  602. if (err_code != NRF_SUCCESS)
  603. {
  604. num_records = 0;
  605. }
  606. else
  607. {
  608. num_records = total_records - index_of_offset;
  609. }
  610. }
  611. p_cgms->racp_data.pending_racp_response.opcode = RACP_OPCODE_NUM_RECS_RESPONSE;
  612. p_cgms->racp_data.pending_racp_response.operator = RACP_OPERATOR_NULL;
  613. p_cgms->racp_data.pending_racp_response.operand_len = sizeof(uint16_t);
  614. p_cgms->racp_data.pending_racp_response.p_operand =
  615. p_cgms->racp_data.pending_racp_response_operand;
  616. p_cgms->racp_data.pending_racp_response_operand[0] = num_records & 0xFF;
  617. p_cgms->racp_data.pending_racp_response_operand[1] = num_records >> 8;
  618. racp_send(p_cgms, &p_cgms->racp_data.pending_racp_response);
  619. }
  620. /**@brief Function for handling a write event to the Record Access Control Point.
  621. *
  622. * @param[in] p_cgms Service instance.
  623. * @param[in] p_evt_write WRITE event to be handled.
  624. */
  625. static void on_racp_value_write(nrf_ble_cgms_t * p_cgms, ble_gatts_evt_write_t const * p_evt_write)
  626. {
  627. uint8_t response_code;
  628. // set up reply to authorized write.
  629. ble_gatts_rw_authorize_reply_params_t auth_reply;
  630. uint32_t err_code;
  631. auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
  632. auth_reply.params.write.offset = 0;
  633. auth_reply.params.write.len = 0;
  634. auth_reply.params.write.p_data = NULL;
  635. // Decode request.
  636. ble_racp_decode(p_evt_write->len, p_evt_write->data, &p_cgms->racp_data.racp_request);
  637. // Check if request is to be executed
  638. if (is_request_to_be_executed(p_cgms, &p_cgms->racp_data.racp_request, &response_code))
  639. {
  640. auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
  641. auth_reply.params.write.update = 1;
  642. err_code = sd_ble_gatts_rw_authorize_reply(p_cgms->conn_handle,
  643. &auth_reply);
  644. if (err_code != NRF_SUCCESS)
  645. {
  646. if (p_cgms->error_handler != NULL)
  647. {
  648. p_cgms->error_handler(err_code);
  649. }
  650. return;
  651. }
  652. // Execute request
  653. if (p_cgms->racp_data.racp_request.opcode == RACP_OPCODE_REPORT_RECS)
  654. {
  655. report_records_request_execute(p_cgms, &p_cgms->racp_data.racp_request);
  656. }
  657. else if (p_cgms->racp_data.racp_request.opcode == RACP_OPCODE_REPORT_NUM_RECS)
  658. {
  659. report_num_records_request_execute(p_cgms, &p_cgms->racp_data.racp_request);
  660. }
  661. }
  662. else if (response_code != RACP_RESPONSE_RESERVED)
  663. {
  664. auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
  665. auth_reply.params.write.update = 1;
  666. err_code = sd_ble_gatts_rw_authorize_reply(p_cgms->conn_handle,
  667. &auth_reply);
  668. if (err_code != NRF_SUCCESS)
  669. {
  670. if (p_cgms->error_handler != NULL)
  671. {
  672. p_cgms->error_handler(err_code);
  673. }
  674. return;
  675. }
  676. // Abort any running procedure
  677. p_cgms->racp_data.racp_procesing_active = false;
  678. // Respond with error code
  679. racp_response_code_send(p_cgms, p_cgms->racp_data.racp_request.opcode, response_code);
  680. }
  681. else
  682. {
  683. // ignore request
  684. auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
  685. auth_reply.params.write.update = 1;
  686. err_code = sd_ble_gatts_rw_authorize_reply(p_cgms->conn_handle,
  687. &auth_reply);
  688. if (err_code != NRF_SUCCESS)
  689. {
  690. if (p_cgms->error_handler != NULL)
  691. {
  692. p_cgms->error_handler(err_code);
  693. }
  694. return;
  695. }
  696. }
  697. }
  698. void cgms_racp_on_rw_auth_req(nrf_ble_cgms_t * p_cgms,
  699. ble_gatts_evt_rw_authorize_request_t const * p_auth_req)
  700. {
  701. if (p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
  702. {
  703. if (p_auth_req->request.write.handle == p_cgms->char_handles.racp.value_handle)
  704. {
  705. on_racp_value_write(p_cgms, &p_auth_req->request.write);
  706. }
  707. }
  708. }
  709. /**@brief Function for handling BLE_GATTS_EVT_HVN_TX_COMPLETE events.
  710. *
  711. * @param[in] p_cgms Glucose Service structure.
  712. */
  713. void cgms_racp_on_tx_complete(nrf_ble_cgms_t * p_cgms)
  714. {
  715. if (p_cgms->racp_data.racp_procesing_active)
  716. {
  717. racp_report_records_procedure(p_cgms);
  718. }
  719. }