cgms_socp.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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_sst.h"
  45. #include "cgms_socp.h"
  46. #include "nrf_ble_gq.h"
  47. #define NRF_BLE_CGMS_PLUS_INFINTE 0x07FE
  48. #define NRF_BLE_CGMS_MINUS_INFINTE 0x0802
  49. /**@brief Specific Operation Control Point opcodes. */
  50. #define SOCP_OPCODE_RESERVED 0x00 /**< Specific Operation Control Point opcode - Reserved for future use. */
  51. #define SOCP_WRITE_CGM_COMMUNICATION_INTERVAL 0x01
  52. #define SOCP_READ_CGM_COMMUNICATION_INTERVAL 0x02
  53. #define SOCP_READ_CGM_COMMUNICATION_INTERVAL_RESPONSE 0x03
  54. #define SOCP_WRITE_GLUCOSE_CALIBRATION_VALUE 0x04
  55. #define SOCP_READ_GLUCOSE_CALIBRATION_VALUE 0x05
  56. #define SOCP_READ_GLUCOSE_CALIBRATION_VALUE_RESPONSE 0x06
  57. #define SOCP_WRITE_PATIENT_HIGH_ALERT_LEVEL 0x07
  58. #define SOCP_READ_PATIENT_HIGH_ALERT_LEVEL 0x08
  59. #define SOCP_READ_PATIENT_HIGH_ALERT_LEVEL_RESPONSE 0x09
  60. #define SOCP_WRITE_PATIENT_LOW_ALERT_LEVEL 0x0A
  61. #define SOCP_READ_PATIENT_LOW_ALERT_LEVEL 0x0B
  62. #define SOCP_READ_PATIENT_LOW_ALERT_LEVEL_RESPONSE 0x0C
  63. #define SOCP_SET_HYPO_ALERT_LEVEL 0x0D /**Set Hypo Alert Level Hypo Alert Level value in mg/dL The response to this control point is Response Code. */
  64. #define SOCP_GET_HYPO_ALERT_LEVEL 0x0E /**Get Hypo Alert Level N/A The normal response to this control point is Op Code 0x0F. For error conditions, the response is Response Code */
  65. #define SOCP_HYPO_ALERT_LEVEL_RESPONSE 0x0F /**Hypo Alert Level Response Hypo Alert Level value in mg/dL This is the normal response to Op Code 0x0E */
  66. #define SOCP_SET_HYPER_ALERT_LEVEL 0x10 /**Set Hyper Alert Level Hyper Alert Level value in mg/dL The response to this control point is Response Code. */
  67. #define SOCP_GET_HYPER_ALERT_LEVEL 0x11 /**Get Hyper Alert Level N/A The normal response to this control point is Op Code 0x12. For error conditions, the response is Response Code */
  68. #define SOCP_HYPER_ALERT_LEVEL_RESPONSE 0x12 /**Hyper Alert Level Response Hyper Alert Level value in mg/dL This is the normal response to Op Code 0x11 */
  69. #define SOCP_SET_RATE_OF_DECREASE_ALERT_LEVEL 0x13 /**Set Rate of Decrease Alert Level Rate of Decrease Alert Level value in mg/dL/min The response to this control point is Response Code. */
  70. #define SOCP_GET_RATE_OF_DECREASE_ALERT_LEVEL 0x14 /**Get Rate of Decrease Alert Level N/A The normal response to this control point is Op Code 0x15. For error conditions, the response is Response Code */
  71. #define SOCP_RATE_OF_DECREASE_ALERT_LEVEL_RESPONSE 0x15 /**Rate of Decrease Alert Level Response Rate of Decrease Alert Level value in mg/dL/min This is the normal response to Op Code 0x14 */
  72. #define SOCP_SET_RATE_OF_INCREASE_ALERT_LEVEL 0x16 /**Set Rate of Increase Alert Level Rate of Increase Alert Level value in mg/dL/min The response to this control point is Response Code. */
  73. #define SOCP_GET_RATE_OF_INCREASE_ALERT_LEVEL 0x17 /**Get Rate of Increase Alert Level N/A The normal response to this control point is Op Code 0x18. For error conditions, the response is Response Code */
  74. #define SOCP_RATE_OF_INCREASE_ALERT_LEVEL_RESPONSE 0x18 /**Rate of Increase Alert Level Response Rate of Increase Alert Level value in mg/dL/min This is the normal response to Op Code 0x17 */
  75. #define SOCP_RESET_DEVICE_SPECIFIC_ALERT 0x19 /**Reset Device Specific Alert N/A The response to this control point is Response Code. */
  76. #define SOCP_START_THE_SESSION 0x1A
  77. #define SOCP_STOP_THE_SESSION 0x1B
  78. #define SOCP_RESPONSE_CODE 0x1C
  79. #define SOCP_RSP_RESERVED_FOR_FUTURE_USE 0x00
  80. #define SOCP_RSP_SUCCESS 0x01
  81. #define SOCP_RSP_OP_CODE_NOT_SUPPORTED 0x02
  82. #define SOCP_RSP_INVALID_OPERAND 0x03
  83. #define SOCP_RSP_PROCEDURE_NOT_COMPLETED 0x04
  84. #define SOCP_RSP_OUT_OF_RANGE 0x05
  85. static void ble_socp_decode(uint8_t data_len, uint8_t const * p_data, ble_cgms_socp_value_t * p_socp_val)
  86. {
  87. p_socp_val->opcode = 0xFF;
  88. p_socp_val->operand_len = 0;
  89. p_socp_val->p_operand = NULL;
  90. if (data_len > 0)
  91. {
  92. p_socp_val->opcode = p_data[0];
  93. }
  94. if (data_len > 1)
  95. {
  96. p_socp_val->operand_len = data_len - 1;
  97. p_socp_val->p_operand = (uint8_t*)&p_data[1]; // lint !e416
  98. }
  99. }
  100. uint8_t ble_socp_encode(const ble_socp_rsp_t * p_socp_rsp, uint8_t * p_data)
  101. {
  102. uint8_t len = 0;
  103. int i;
  104. if (p_data != NULL)
  105. {
  106. p_data[len++] = p_socp_rsp->opcode;
  107. if (
  108. (p_socp_rsp->opcode != SOCP_READ_CGM_COMMUNICATION_INTERVAL_RESPONSE)
  109. && (p_socp_rsp->opcode != SOCP_READ_PATIENT_HIGH_ALERT_LEVEL_RESPONSE)
  110. && (p_socp_rsp->opcode != SOCP_READ_PATIENT_LOW_ALERT_LEVEL_RESPONSE)
  111. && (p_socp_rsp->opcode != SOCP_HYPO_ALERT_LEVEL_RESPONSE)
  112. && (p_socp_rsp->opcode != SOCP_HYPER_ALERT_LEVEL_RESPONSE)
  113. && (p_socp_rsp->opcode != SOCP_RATE_OF_DECREASE_ALERT_LEVEL_RESPONSE)
  114. && (p_socp_rsp->opcode != SOCP_RATE_OF_INCREASE_ALERT_LEVEL_RESPONSE)
  115. && (p_socp_rsp->opcode != SOCP_READ_GLUCOSE_CALIBRATION_VALUE_RESPONSE)
  116. )
  117. {
  118. p_data[len++] = p_socp_rsp->req_opcode;
  119. p_data[len++] = p_socp_rsp->rsp_code;
  120. }
  121. for (i = 0; i < p_socp_rsp->size_val; i++)
  122. {
  123. p_data[len++] = p_socp_rsp->resp_val[i];
  124. }
  125. }
  126. return len;
  127. }
  128. /**@brief Function for adding a characteristic for the Specific Operations Control Point.
  129. *
  130. * @param[in] p_cgms Service instance.
  131. *
  132. * @return NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
  133. */
  134. ret_code_t cgms_socp_char_add(nrf_ble_cgms_t * p_cgms)
  135. {
  136. ble_add_char_params_t add_char_params;
  137. memset(&add_char_params, 0, sizeof(add_char_params));
  138. add_char_params.uuid = BLE_UUID_CGM_SPECIFIC_OPS_CTRLPT;
  139. add_char_params.max_len = BLE_GATT_ATT_MTU_DEFAULT;
  140. add_char_params.init_len = 0;
  141. add_char_params.p_init_value = 0;
  142. add_char_params.is_var_len = true;
  143. add_char_params.char_props.indicate = true;
  144. add_char_params.char_props.write = true;
  145. add_char_params.write_access = SEC_JUST_WORKS;
  146. add_char_params.cccd_write_access = SEC_JUST_WORKS;
  147. add_char_params.is_defered_write = 1;
  148. return characteristic_add(p_cgms->service_handle,
  149. &add_char_params,
  150. &p_cgms->char_handles.socp);
  151. }
  152. /**@brief Function for sending a response from the Specific Operation Control Point.
  153. *
  154. * @param[in] p_cgms Service instance.
  155. */
  156. static void socp_send(nrf_ble_cgms_t * p_cgms)
  157. {
  158. uint32_t err_code;
  159. uint8_t encoded_resp[25];
  160. uint16_t len;
  161. nrf_ble_gq_req_t cgms_req;
  162. memset(&cgms_req, 0, sizeof(nrf_ble_gq_req_t));
  163. // Send indication
  164. len = ble_socp_encode(&(p_cgms->socp_response), encoded_resp);
  165. cgms_req.type = NRF_BLE_GQ_REQ_GATTS_HVX;
  166. cgms_req.error_handler.cb = p_cgms->gatt_err_handler;
  167. cgms_req.error_handler.p_ctx = p_cgms;
  168. cgms_req.params.gatts_hvx.type = BLE_GATT_HVX_INDICATION;
  169. cgms_req.params.gatts_hvx.handle = p_cgms->char_handles.socp.value_handle;
  170. cgms_req.params.gatts_hvx.offset = 0;
  171. cgms_req.params.gatts_hvx.p_data = encoded_resp;
  172. cgms_req.params.gatts_hvx.p_len = &len;
  173. err_code = nrf_ble_gq_item_add(p_cgms->p_gatt_queue, &cgms_req, p_cgms->conn_handle);
  174. // Report error to application
  175. if ((p_cgms->error_handler != NULL) &&
  176. (err_code != NRF_SUCCESS) &&
  177. (err_code != NRF_ERROR_INVALID_STATE))
  178. {
  179. p_cgms->error_handler(err_code);
  180. }
  181. }
  182. void encode_get_response(uint8_t rsp_code, ble_socp_rsp_t * p_rsp, uint16_t in_val)
  183. {
  184. p_rsp->opcode = rsp_code;
  185. p_rsp->rsp_code = SOCP_RSP_SUCCESS;
  186. p_rsp->size_val += uint16_encode(in_val, &(p_rsp->resp_val[p_rsp->size_val]));
  187. }
  188. void decode_set_opcode(nrf_ble_cgms_t * p_cgms,
  189. ble_cgms_socp_value_t * rcv_val,
  190. uint16_t min,
  191. uint16_t max,
  192. uint16_t * p_val)
  193. {
  194. uint16_t rcvd_val = uint16_decode(rcv_val->p_operand);
  195. if ((rcvd_val == NRF_BLE_CGMS_PLUS_INFINTE)
  196. || (rcvd_val == NRF_BLE_CGMS_MINUS_INFINTE)
  197. || (rcvd_val > max)
  198. || (rcvd_val < min))
  199. {
  200. p_cgms->socp_response.rsp_code = SOCP_RSP_OUT_OF_RANGE;
  201. }
  202. else
  203. {
  204. p_cgms->socp_response.rsp_code = SOCP_RSP_SUCCESS;
  205. *p_val = rcvd_val;
  206. }
  207. }
  208. static bool is_feature_present(nrf_ble_cgms_t * p_cgms, uint32_t feature)
  209. {
  210. return (p_cgms->feature.feature & feature);
  211. }
  212. /**@brief Function for handling a write event to the Specific Operation Control Point.
  213. *
  214. * @param[in] p_cgms Service instance.
  215. * @param[in] p_evt_write WRITE event to be handled.
  216. */
  217. static void on_socp_value_write(nrf_ble_cgms_t * p_cgms, ble_gatts_evt_write_t const * p_evt_write)
  218. {
  219. ble_cgms_socp_value_t socp_request;
  220. nrf_ble_cgms_evt_t evt;
  221. ble_gatts_rw_authorize_reply_params_t auth_reply;
  222. uint32_t err_code;
  223. memset(&auth_reply, 0, sizeof(auth_reply));
  224. auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
  225. auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
  226. auth_reply.params.write.update = 1;
  227. err_code = sd_ble_gatts_rw_authorize_reply(p_cgms->conn_handle, &auth_reply);
  228. if (err_code != NRF_SUCCESS)
  229. {
  230. if (p_cgms->error_handler != NULL)
  231. {
  232. p_cgms->error_handler(err_code);
  233. }
  234. return;
  235. }
  236. // Decode request
  237. ble_socp_decode(p_evt_write->len, p_evt_write->data, &socp_request);
  238. p_cgms->socp_response.opcode = SOCP_RESPONSE_CODE;
  239. p_cgms->socp_response.req_opcode = socp_request.opcode;
  240. p_cgms->socp_response.rsp_code = SOCP_RSP_OP_CODE_NOT_SUPPORTED;
  241. p_cgms->socp_response.size_val = 0;
  242. switch (socp_request.opcode)
  243. {
  244. case SOCP_WRITE_CGM_COMMUNICATION_INTERVAL:
  245. p_cgms->socp_response.rsp_code = SOCP_RSP_SUCCESS;
  246. p_cgms->comm_interval = socp_request.p_operand[0];
  247. evt.evt_type = NRF_BLE_CGMS_EVT_WRITE_COMM_INTERVAL;
  248. p_cgms->evt_handler(p_cgms, &evt);
  249. break;
  250. case SOCP_READ_CGM_COMMUNICATION_INTERVAL:
  251. p_cgms->socp_response.opcode = SOCP_READ_CGM_COMMUNICATION_INTERVAL_RESPONSE;
  252. p_cgms->socp_response.resp_val[0] = p_cgms->comm_interval;
  253. p_cgms->socp_response.size_val++;
  254. break;
  255. case SOCP_START_THE_SESSION:
  256. if (p_cgms->is_session_started)
  257. {
  258. p_cgms->socp_response.rsp_code = SOCP_RSP_PROCEDURE_NOT_COMPLETED;
  259. }
  260. else if ((p_cgms->nb_run_session != 0) &&
  261. !(is_feature_present(p_cgms, NRF_BLE_CGMS_FEAT_MULTIPLE_SESSIONS_SUPPORTED)))
  262. {
  263. p_cgms->socp_response.rsp_code = SOCP_RSP_PROCEDURE_NOT_COMPLETED;
  264. }
  265. else
  266. {
  267. p_cgms->socp_response.rsp_code = SOCP_RSP_SUCCESS;
  268. p_cgms->is_session_started = true;
  269. p_cgms->nb_run_session++;
  270. if (p_cgms->evt_handler != NULL)
  271. {
  272. evt.evt_type = NRF_BLE_CGMS_EVT_START_SESSION;
  273. p_cgms->evt_handler(p_cgms, &evt);
  274. }
  275. ble_cgms_sst_t sst;
  276. memset(&sst, 0, sizeof(ble_cgms_sst_t));
  277. err_code = cgms_sst_set(p_cgms, &sst);
  278. if (err_code != NRF_SUCCESS)
  279. {
  280. if (p_cgms->error_handler != NULL)
  281. {
  282. p_cgms->error_handler(err_code);
  283. }
  284. }
  285. p_cgms->sensor_status.time_offset = 0;
  286. p_cgms->sensor_status.status.status &= (~NRF_BLE_CGMS_STATUS_SESSION_STOPPED);
  287. err_code = nrf_ble_cgms_update_status(p_cgms, &p_cgms->sensor_status);
  288. if (err_code != NRF_SUCCESS)
  289. {
  290. if (p_cgms->error_handler != NULL)
  291. {
  292. p_cgms->error_handler(err_code);
  293. }
  294. }
  295. }
  296. break;
  297. case SOCP_STOP_THE_SESSION:
  298. {
  299. nrf_ble_cgm_status_t status;
  300. memset(&status, 0, sizeof(nrf_ble_cgm_status_t));
  301. p_cgms->evt_handler(p_cgms, &evt);
  302. p_cgms->socp_response.rsp_code = SOCP_RSP_SUCCESS;
  303. p_cgms->is_session_started = false;
  304. status.time_offset = p_cgms->sensor_status.time_offset;
  305. status.status.status = p_cgms->sensor_status.status.status |
  306. NRF_BLE_CGMS_STATUS_SESSION_STOPPED;
  307. if (p_cgms->evt_handler != NULL)
  308. {
  309. evt.evt_type = NRF_BLE_CGMS_EVT_STOP_SESSION;
  310. p_cgms->evt_handler(p_cgms, &evt);
  311. }
  312. err_code = nrf_ble_cgms_update_status(p_cgms, &status);
  313. if (err_code != NRF_SUCCESS)
  314. {
  315. if (p_cgms->error_handler != NULL)
  316. {
  317. p_cgms->error_handler(err_code);
  318. }
  319. }
  320. break;
  321. }
  322. default:
  323. p_cgms->socp_response.rsp_code = SOCP_RSP_OP_CODE_NOT_SUPPORTED;
  324. break;
  325. }
  326. socp_send(p_cgms);
  327. }
  328. void cgms_socp_on_rw_auth_req(nrf_ble_cgms_t * p_cgms,
  329. ble_gatts_evt_rw_authorize_request_t const * p_auth_req)
  330. {
  331. if (p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
  332. {
  333. if (p_auth_req->request.write.handle == p_cgms->char_handles.socp.value_handle)
  334. {
  335. on_socp_value_write(p_cgms, &p_auth_req->request.write);
  336. }
  337. }
  338. }