123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826 |
- /**
- * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form, except as embedded into a Nordic
- * Semiconductor ASA integrated circuit in a product or a software update for
- * such product, must reproduce the above copyright notice, this list of
- * conditions and the following disclaimer in the documentation and/or other
- * materials provided with the distribution.
- *
- * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * 4. This software, with or without modification, must only be used with a
- * Nordic Semiconductor ASA integrated circuit.
- *
- * 5. Any software provided in binary form under this license must not be reverse
- * engineered, decompiled, modified and/or disassembled.
- *
- * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- #include <stdint.h>
- #include <string.h>
- #include "ble.h"
- #include "ble_srv_common.h"
- #include "cgms_racp.h"
- #include "cgms_db.h"
- #include "nrf_ble_gq.h"
- #include "cgms_meas.h"
- #define OPERAND_LESS_GREATER_FILTER_TYPE_SIZE 1 // !< 1 byte.
- #define OPERAND_LESS_GREATER_FILTER_PARAM_SIZE 2 // !< 2 bytes.
- #define OPERAND_LESS_GREATER_SIZE OPERAND_LESS_GREATER_FILTER_TYPE_SIZE \
- + OPERAND_LESS_GREATER_FILTER_PARAM_SIZE // !< Total size of the operand.
- /**@brief Function for adding a characteristic for the Record Access Control Point.
- *
- * @param[in] p_cgms Service instance.
- *
- * @return NRF_SUCCESS if characteristic was successfully added, otherwise an error code.
- */
- ret_code_t cgms_racp_char_add(nrf_ble_cgms_t * p_cgms)
- {
- ble_add_char_params_t add_char_params;
- memset(&add_char_params, 0, sizeof(add_char_params));
- add_char_params.uuid = BLE_UUID_RECORD_ACCESS_CONTROL_POINT_CHAR;
- add_char_params.max_len = BLE_GATT_ATT_MTU_DEFAULT;
- add_char_params.init_len = 0;
- add_char_params.p_init_value = 0;
- add_char_params.is_var_len = true;
- add_char_params.write_access = SEC_JUST_WORKS;
- add_char_params.char_props.write = true;
- add_char_params.char_props.indicate = true;
- add_char_params.cccd_write_access = SEC_JUST_WORKS;
- add_char_params.is_defered_write = 1;
- return characteristic_add(p_cgms->service_handle,
- &add_char_params,
- &p_cgms->char_handles.racp);
- }
- /**@brief Function for sending response from Specific Operation Control Point.
- *
- * @param[in] p_cgms Service instance.
- * @param[in] p_racp_val RACP value to be sent.
- */
- static void racp_send(nrf_ble_cgms_t * p_cgms, ble_racp_value_t * p_racp_val)
- {
- uint32_t err_code;
- uint8_t encoded_resp[25];
- uint16_t len;
- nrf_ble_gq_req_t cgms_req;
- memset(&cgms_req, 0, sizeof(nrf_ble_gq_req_t));
- // Send indication
- len = ble_racp_encode(p_racp_val, encoded_resp);
- cgms_req.type = NRF_BLE_GQ_REQ_GATTS_HVX;
- cgms_req.error_handler.cb = p_cgms->gatt_err_handler;
- cgms_req.error_handler.p_ctx = p_cgms;
- cgms_req.params.gatts_hvx.type = BLE_GATT_HVX_INDICATION;
- cgms_req.params.gatts_hvx.handle = p_cgms->char_handles.racp.value_handle;
- cgms_req.params.gatts_hvx.offset = 0;
- cgms_req.params.gatts_hvx.p_data = encoded_resp;
- cgms_req.params.gatts_hvx.p_len = &len;
- err_code = nrf_ble_gq_item_add(p_cgms->p_gatt_queue, &cgms_req, p_cgms->conn_handle);
- // Report error to application
- if ((p_cgms->error_handler != NULL) &&
- (err_code != NRF_SUCCESS) &&
- (err_code != NRF_ERROR_INVALID_STATE))
- {
- p_cgms->error_handler(err_code);
- }
- }
- /**@brief Function for sending a RACP response containing a Response Code Op Code and Response Code Value.
- *
- * @param[in] p_cgms Service instance.
- * @param[in] opcode RACP Op Code.
- * @param[in] value RACP Response Code Value.
- */
- static void racp_response_code_send(nrf_ble_cgms_t * p_cgms, uint8_t opcode, uint8_t value)
- {
- p_cgms->racp_data.pending_racp_response.opcode = RACP_OPCODE_RESPONSE_CODE;
- p_cgms->racp_data.pending_racp_response.operator = RACP_OPERATOR_NULL;
- p_cgms->racp_data.pending_racp_response.operand_len = 2;
- p_cgms->racp_data.pending_racp_response.p_operand =
- p_cgms->racp_data.pending_racp_response_operand;
- p_cgms->racp_data.pending_racp_response_operand[0] = opcode;
- p_cgms->racp_data.pending_racp_response_operand[1] = value;
- racp_send(p_cgms, &p_cgms->racp_data.pending_racp_response);
- }
- /**@brief Function for responding to the ALL operation.
- *
- * @param[in] p_cgms Service instance.
- *
- * @return NRF_SUCCESS on success, otherwise an error code.
- */
- static uint32_t racp_report_records_all(nrf_ble_cgms_t * p_cgms)
- {
- uint16_t total_records = cgms_db_num_records_get();
- uint16_t cur_nb_rec;
- uint8_t i;
- uint8_t nb_rec_to_send;
- if (p_cgms->racp_data.racp_proc_record_ndx >= total_records)
- {
- p_cgms->racp_data.racp_procesing_active = false;
- }
- else
- {
- uint32_t err_code;
- ble_cgms_rec_t rec[NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX];
- cur_nb_rec = total_records - p_cgms->racp_data.racp_proc_record_ndx;
- if (cur_nb_rec > NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX)
- {
- cur_nb_rec = NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX;
- }
- nb_rec_to_send = (uint8_t)cur_nb_rec;
- for (i = 0; i < cur_nb_rec; i++)
- {
- err_code = cgms_db_record_get(p_cgms->racp_data.racp_proc_record_ndx + i, &(rec[i]));
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- }
- err_code = cgms_meas_send(p_cgms, rec, &nb_rec_to_send);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- p_cgms->racp_data.racp_proc_record_ndx += nb_rec_to_send;
- }
- return NRF_SUCCESS;
- }
- /**@brief Function for responding to the FIRST or the LAST operation.
- *
- * @param[in] p_cgms Service instance.
- *
- * @return NRF_SUCCESS on success, otherwise an error code.
- */
- static uint32_t racp_report_records_first_last(nrf_ble_cgms_t * p_cgms)
- {
- uint32_t err_code;
- ble_cgms_rec_t rec;
- uint16_t total_records;
- uint8_t nb_rec_to_send = 1;
- total_records = cgms_db_num_records_get();
- if ((p_cgms->racp_data.racp_proc_records_reported != 0) || (total_records == 0))
- {
- p_cgms->racp_data.racp_procesing_active = false;
- }
- else
- {
- if (p_cgms->racp_data.racp_proc_operator == RACP_OPERATOR_FIRST)
- {
- err_code = cgms_db_record_get(0, &rec);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- }
- else if (p_cgms->racp_data.racp_proc_operator == RACP_OPERATOR_LAST)
- {
- err_code = cgms_db_record_get(total_records - 1, &rec);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- }
- err_code = cgms_meas_send(p_cgms, &rec, &nb_rec_to_send);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- p_cgms->racp_data.racp_proc_record_ndx++;
- }
- return NRF_SUCCESS;
- }
- /**@brief Function for responding to the LESS OR EQUAL operation.
- *
- * @param[in] p_cgms Service instance.
- *
- * @return NRF_SUCCESS on success, otherwise an error code.
- */
- static ret_code_t racp_report_records_less_equal(nrf_ble_cgms_t * p_cgms)
- {
- uint16_t total_rec_nb_to_send;
- uint16_t rec_nb_left_to_send;
- uint8_t nb_rec_to_send;
- uint16_t i;
- total_rec_nb_to_send = p_cgms->racp_data.racp_proc_records_ndx_last_to_send +1;
- if (p_cgms->racp_data.racp_proc_record_ndx >= total_rec_nb_to_send)
- {
- p_cgms->racp_data.racp_procesing_active = false;
- }
- else
- {
- ret_code_t err_code;
- ble_cgms_rec_t rec[NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX];
- rec_nb_left_to_send = total_rec_nb_to_send - p_cgms->racp_data.racp_proc_records_reported;
- if (rec_nb_left_to_send > NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX)
- {
- nb_rec_to_send = NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX;
- }
- else
- {
- nb_rec_to_send = (uint8_t)rec_nb_left_to_send;
- }
- for (i = 0; i < nb_rec_to_send; i++)
- {
- err_code = cgms_db_record_get(p_cgms->racp_data.racp_proc_record_ndx + i, &(rec[i]));
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- }
- err_code = cgms_meas_send(p_cgms, rec, &nb_rec_to_send);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- p_cgms->racp_data.racp_proc_record_ndx += nb_rec_to_send;
- }
- return NRF_SUCCESS;
- }
- /**@brief Function for responding to the GREATER OR EQUAL operation.
- *
- * @param[in] p_cgms Service instance.
- *
- * @return NRF_SUCCESS on success, otherwise an error code.
- */
- static ret_code_t racp_report_records_greater_equal(nrf_ble_cgms_t * p_cgms)
- {
- ret_code_t err_code;
- uint16_t total_rec_nb = cgms_db_num_records_get();
- uint16_t rec_nb_left_to_send;
- uint8_t nb_rec_to_send;
- uint16_t i;
- total_rec_nb = cgms_db_num_records_get();
- if (p_cgms->racp_data.racp_proc_record_ndx >= total_rec_nb)
- {
- p_cgms->racp_data.racp_procesing_active = false;
- return NRF_SUCCESS;
- }
- ble_cgms_rec_t rec[NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX];
- rec_nb_left_to_send = total_rec_nb - p_cgms->racp_data.racp_proc_record_ndx;
- if (rec_nb_left_to_send > NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX)
- {
- nb_rec_to_send = NRF_BLE_CGMS_MEAS_REC_PER_NOTIF_MAX;
- }
- else
- {
- nb_rec_to_send = (uint8_t)rec_nb_left_to_send;
- }
- for (i = 0; i < nb_rec_to_send; i++)
- {
- err_code = cgms_db_record_get(p_cgms->racp_data.racp_proc_record_ndx + i, &(rec[i]));
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- }
- err_code = cgms_meas_send(p_cgms, rec, &nb_rec_to_send);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- p_cgms->racp_data.racp_proc_record_ndx += nb_rec_to_send;
- return NRF_SUCCESS;
- }
- /**@brief Function for informing that the REPORT RECORDS procedure is completed.
- *
- * @param[in] p_cgms Service instance.
- */
- static void racp_report_records_completed(nrf_ble_cgms_t * p_cgms)
- {
- uint8_t resp_code_value;
- if (p_cgms->racp_data.racp_proc_records_reported > 0)
- {
- resp_code_value = RACP_RESPONSE_SUCCESS;
- }
- else
- {
- resp_code_value = RACP_RESPONSE_NO_RECORDS_FOUND;
- }
- racp_response_code_send(p_cgms, RACP_OPCODE_REPORT_RECS, resp_code_value);
- }
- /**@brief Function for the RACP report records procedure.
- *
- * @param[in] p_cgms Service instance.
- */
- static void racp_report_records_procedure(nrf_ble_cgms_t * p_cgms)
- {
- ret_code_t err_code = NRF_SUCCESS;
- while (p_cgms->racp_data.racp_procesing_active)
- {
- // Execute requested procedure
- switch (p_cgms->racp_data.racp_proc_operator)
- {
- case RACP_OPERATOR_ALL:
- err_code = racp_report_records_all(p_cgms);
- break;
- case RACP_OPERATOR_FIRST:
- // Fall through.
- case RACP_OPERATOR_LAST:
- err_code = racp_report_records_first_last(p_cgms);
- break;
- case RACP_OPERATOR_GREATER_OR_EQUAL:
- err_code = racp_report_records_greater_equal(p_cgms);
- break;
- case RACP_OPERATOR_LESS_OR_EQUAL:
- err_code = racp_report_records_less_equal(p_cgms);
- break;
- default:
- // Report error to application
- if (p_cgms->error_handler != NULL)
- {
- p_cgms->error_handler(NRF_ERROR_INTERNAL);
- }
- p_cgms->racp_data.racp_procesing_active = false;
- return;
- }
- // Error handling
- switch (err_code)
- {
- case NRF_SUCCESS:
- if (!p_cgms->racp_data.racp_procesing_active)
- {
- racp_report_records_completed(p_cgms);
- }
- break;
- case NRF_ERROR_RESOURCES:
- // Wait for TX_COMPLETE event to resume transmission.
- return;
- case NRF_ERROR_INVALID_STATE:
- // Notification is probably not enabled. Ignore request.
- p_cgms->racp_data.racp_procesing_active = false;;
- return;
- default:
- // Report error to application.
- if (p_cgms->error_handler != NULL)
- {
- p_cgms->error_handler(err_code);
- }
- // Make sure state machine returns to the default state.
- p_cgms->racp_data.racp_procesing_active = false;
- return;
- }
- }
- }
- /**@brief Function for testing if the received request is to be executed.
- *
- * @param[in] p_racp_request Request to be checked.
- * @param[out] p_response_code Response code to be sent in case the request is rejected.
- * RACP_RESPONSE_RESERVED is returned if the received message is
- * to be rejected without sending a respone.
- *
- * @return TRUE if the request is to be executed, FALSE if it is to be rejected.
- * If it is to be rejected, p_response_code will contain the response code to be
- * returned to the central.
- */
- static bool is_request_to_be_executed(nrf_ble_cgms_t * p_cgms,
- const ble_racp_value_t * p_racp_request,
- uint8_t * p_response_code)
- {
- *p_response_code = RACP_RESPONSE_RESERVED;
- if (p_racp_request->opcode == RACP_OPCODE_ABORT_OPERATION)
- {
- if (p_cgms->racp_data.racp_procesing_active)
- {
- if (p_racp_request->operator != RACP_OPERATOR_NULL)
- {
- *p_response_code = RACP_RESPONSE_INVALID_OPERATOR;
- }
- else if (p_racp_request->operand_len != 0)
- {
- *p_response_code = RACP_RESPONSE_INVALID_OPERAND;
- }
- else
- {
- *p_response_code = RACP_RESPONSE_SUCCESS;
- }
- }
- else
- {
- *p_response_code = RACP_RESPONSE_ABORT_FAILED;
- }
- }
- else if (p_cgms->racp_data.racp_procesing_active)
- {
- return false;
- }
- // Supported opcodes
- else if ((p_racp_request->opcode == RACP_OPCODE_REPORT_RECS) ||
- (p_racp_request->opcode == RACP_OPCODE_REPORT_NUM_RECS))
- {
- switch (p_racp_request->operator)
- {
- // Operators without a filter.
- case RACP_OPERATOR_ALL:
- // Fall through.
- case RACP_OPERATOR_FIRST:
- // Fall through.
- case RACP_OPERATOR_LAST:
- if (p_racp_request->operand_len != 0)
- {
- *p_response_code = RACP_RESPONSE_INVALID_OPERAND;
- }
- break;
- // Operators with a filter as part of the operand.
- case RACP_OPERATOR_LESS_OR_EQUAL:
- // Fall Through.
- case RACP_OPERATOR_GREATER_OR_EQUAL:
- if (*(p_racp_request->p_operand) == RACP_OPERAND_FILTER_TYPE_FACING_TIME)
- {
- *p_response_code = RACP_RESPONSE_PROCEDURE_NOT_DONE;
- }
- if (p_racp_request->operand_len != OPERAND_LESS_GREATER_SIZE)
- {
- *p_response_code = RACP_RESPONSE_INVALID_OPERAND;
- }
- break;
- case RACP_OPERATOR_RANGE:
- *p_response_code = RACP_RESPONSE_OPERATOR_UNSUPPORTED;
- break;
- // Invalid operators.
- case RACP_OPERATOR_NULL:
- // Fall through.
- default:
- *p_response_code = RACP_RESPONSE_INVALID_OPERATOR;
- break;
- }
- }
- // Unsupported opcodes.
- else if (p_racp_request->opcode == RACP_OPCODE_DELETE_RECS)
- {
- *p_response_code = RACP_RESPONSE_OPCODE_UNSUPPORTED;
- }
- // Unknown opcodes.
- else
- {
- *p_response_code = RACP_RESPONSE_OPCODE_UNSUPPORTED;
- }
- return (*p_response_code == RACP_RESPONSE_RESERVED);
- }
- /**@brief Function for getting a record with time offset less or equal to the input param.
- *
- * @param[in] offset The record that this function returns must have an time offset less or greater to this.
- * @param[out] record_num Pointer to the record index of the record that has the desired time offset.
- *
- * @retval NRF_SUCCESS If the record was successfully retrieved.
- * @retval NRF_ERROR_NOT_FOUND A record with the desired offset does not exist in the database.
- * @return If functions from other modules return errors to this function,
- * the @ref nrf_error are propagated.
- */
- static ret_code_t record_index_offset_less_or_equal_get(uint16_t offset, uint16_t * record_num)
- {
- ret_code_t err_code;
- ble_cgms_rec_t rec;
- uint16_t upper_bound = cgms_db_num_records_get();
- for((*record_num) = upper_bound; (*record_num)-- >0;)
- {
- err_code = cgms_db_record_get(*record_num, &rec);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- if (rec.meas.time_offset <= offset)
- {
- return NRF_SUCCESS;
- }
- }
- return NRF_ERROR_NOT_FOUND;
- }
- /**@brief Function for getting a record with time offset greater or equal to the input param.
- *
- * @param[in] offset The record that this function returns must have an time offset equal or
- * greater to this.
- * @param[out] record_num Pointer to the record index of the record that has the desired time offset.
- *
- * @retval NRF_SUCCESS If the record was successfully retrieved.
- * @retval NRF_ERROR_NOT_FOUND A record with the desired offset does not exist in the database.
- * @return If functions from other modules return errors to this function,
- * the @ref nrf_error are propagated.
- */
- static ret_code_t record_index_offset_greater_or_equal_get(uint16_t offset, uint16_t * record_num)
- {
- ret_code_t err_code;
- ble_cgms_rec_t rec;
- uint16_t upper_bound = cgms_db_num_records_get();
- for(*record_num = 0; *record_num < upper_bound; (*record_num)++)
- {
- err_code = cgms_db_record_get(*record_num, &rec);
- if (err_code != NRF_SUCCESS)
- {
- return err_code;
- }
- if (rec.meas.time_offset >= offset)
- {
- return NRF_SUCCESS;
- }
- }
- return NRF_ERROR_NOT_FOUND;
- }
- /**@brief Function for processing a REPORT RECORDS request.
- *
- * @details Set initial values before entering the state machine of racp_report_records_procedure().
- *
- * @param[in] p_cgms Service instance.
- * @param[in] p_racp_request Request to be executed.
- */
- static void report_records_request_execute(nrf_ble_cgms_t * p_cgms,
- ble_racp_value_t * p_racp_request)
- {
- p_cgms->racp_data.racp_procesing_active = true;
- p_cgms->racp_data.racp_proc_record_ndx = 0;
- p_cgms->racp_data.racp_proc_operator = p_racp_request->operator;
- p_cgms->racp_data.racp_proc_records_reported = 0;
- p_cgms->racp_data.racp_proc_records_ndx_last_to_send = 0;
- if (p_cgms->racp_data.racp_proc_operator == RACP_OPERATOR_GREATER_OR_EQUAL)
- {
- uint16_t offset_requested = uint16_decode(&p_cgms->racp_data.racp_request.p_operand[OPERAND_LESS_GREATER_FILTER_TYPE_SIZE]);
- ret_code_t err_code = record_index_offset_greater_or_equal_get(offset_requested, &p_cgms->racp_data.racp_proc_record_ndx);
- if (err_code != NRF_SUCCESS)
- {
- racp_report_records_completed(p_cgms);
- }
- }
- if (p_cgms->racp_data.racp_proc_operator == RACP_OPERATOR_LESS_OR_EQUAL)
- {
- uint16_t offset_requested = uint16_decode(&p_cgms->racp_data.racp_request.p_operand[OPERAND_LESS_GREATER_FILTER_TYPE_SIZE]);
- ret_code_t err_code = record_index_offset_less_or_equal_get(offset_requested,
- &p_cgms->racp_data.racp_proc_records_ndx_last_to_send);
- if (err_code != NRF_SUCCESS)
- {
- racp_report_records_completed(p_cgms);
- }
- }
- racp_report_records_procedure(p_cgms);
- }
- /**@brief Function for processing a REPORT NUM RECORDS request.
- *
- * @param[in] p_cgms Service instance.
- * @param[in] p_racp_request Request to be executed.
- */
- static void report_num_records_request_execute(nrf_ble_cgms_t * p_cgms,
- ble_racp_value_t * p_racp_request)
- {
- uint16_t total_records;
- uint16_t num_records;
- total_records = cgms_db_num_records_get();
- num_records = 0;
- if (p_racp_request->operator == RACP_OPERATOR_ALL)
- {
- num_records = total_records;
- }
- else if ((p_racp_request->operator == RACP_OPERATOR_FIRST) ||
- (p_racp_request->operator == RACP_OPERATOR_LAST))
- {
- if (total_records > 0)
- {
- num_records = 1;
- }
- }
- else if (p_racp_request->operator == RACP_OPERATOR_GREATER_OR_EQUAL)
- {
- uint16_t index_of_offset;
- uint16_t offset_requested = uint16_decode(&p_cgms->racp_data.racp_request.p_operand[OPERAND_LESS_GREATER_FILTER_TYPE_SIZE]);
- ret_code_t err_code = record_index_offset_greater_or_equal_get(offset_requested, &index_of_offset);
- if (err_code != NRF_SUCCESS)
- {
- num_records = 0;
- }
- else
- {
- num_records = total_records - index_of_offset;
- }
- }
- p_cgms->racp_data.pending_racp_response.opcode = RACP_OPCODE_NUM_RECS_RESPONSE;
- p_cgms->racp_data.pending_racp_response.operator = RACP_OPERATOR_NULL;
- p_cgms->racp_data.pending_racp_response.operand_len = sizeof(uint16_t);
- p_cgms->racp_data.pending_racp_response.p_operand =
- p_cgms->racp_data.pending_racp_response_operand;
- p_cgms->racp_data.pending_racp_response_operand[0] = num_records & 0xFF;
- p_cgms->racp_data.pending_racp_response_operand[1] = num_records >> 8;
- racp_send(p_cgms, &p_cgms->racp_data.pending_racp_response);
- }
- /**@brief Function for handling a write event to the Record Access Control Point.
- *
- * @param[in] p_cgms Service instance.
- * @param[in] p_evt_write WRITE event to be handled.
- */
- static void on_racp_value_write(nrf_ble_cgms_t * p_cgms, ble_gatts_evt_write_t const * p_evt_write)
- {
- uint8_t response_code;
- // set up reply to authorized write.
- ble_gatts_rw_authorize_reply_params_t auth_reply;
- uint32_t err_code;
- auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
- auth_reply.params.write.offset = 0;
- auth_reply.params.write.len = 0;
- auth_reply.params.write.p_data = NULL;
- // Decode request.
- ble_racp_decode(p_evt_write->len, p_evt_write->data, &p_cgms->racp_data.racp_request);
- // Check if request is to be executed
- if (is_request_to_be_executed(p_cgms, &p_cgms->racp_data.racp_request, &response_code))
- {
- auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
- auth_reply.params.write.update = 1;
- err_code = sd_ble_gatts_rw_authorize_reply(p_cgms->conn_handle,
- &auth_reply);
- if (err_code != NRF_SUCCESS)
- {
- if (p_cgms->error_handler != NULL)
- {
- p_cgms->error_handler(err_code);
- }
- return;
- }
- // Execute request
- if (p_cgms->racp_data.racp_request.opcode == RACP_OPCODE_REPORT_RECS)
- {
- report_records_request_execute(p_cgms, &p_cgms->racp_data.racp_request);
- }
- else if (p_cgms->racp_data.racp_request.opcode == RACP_OPCODE_REPORT_NUM_RECS)
- {
- report_num_records_request_execute(p_cgms, &p_cgms->racp_data.racp_request);
- }
- }
- else if (response_code != RACP_RESPONSE_RESERVED)
- {
- auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
- auth_reply.params.write.update = 1;
- err_code = sd_ble_gatts_rw_authorize_reply(p_cgms->conn_handle,
- &auth_reply);
- if (err_code != NRF_SUCCESS)
- {
- if (p_cgms->error_handler != NULL)
- {
- p_cgms->error_handler(err_code);
- }
- return;
- }
- // Abort any running procedure
- p_cgms->racp_data.racp_procesing_active = false;
- // Respond with error code
- racp_response_code_send(p_cgms, p_cgms->racp_data.racp_request.opcode, response_code);
- }
- else
- {
- // ignore request
- auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
- auth_reply.params.write.update = 1;
- err_code = sd_ble_gatts_rw_authorize_reply(p_cgms->conn_handle,
- &auth_reply);
- if (err_code != NRF_SUCCESS)
- {
- if (p_cgms->error_handler != NULL)
- {
- p_cgms->error_handler(err_code);
- }
- return;
- }
- }
- }
- void cgms_racp_on_rw_auth_req(nrf_ble_cgms_t * p_cgms,
- ble_gatts_evt_rw_authorize_request_t const * p_auth_req)
- {
- if (p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
- {
- if (p_auth_req->request.write.handle == p_cgms->char_handles.racp.value_handle)
- {
- on_racp_value_write(p_cgms, &p_auth_req->request.write);
- }
- }
- }
- /**@brief Function for handling BLE_GATTS_EVT_HVN_TX_COMPLETE events.
- *
- * @param[in] p_cgms Glucose Service structure.
- */
- void cgms_racp_on_tx_complete(nrf_ble_cgms_t * p_cgms)
- {
- if (p_cgms->racp_data.racp_procesing_active)
- {
- racp_report_records_procedure(p_cgms);
- }
- }
|