static bool is_cccd_configured(uint16_t conn_handle) { uint32_t err_code; uint8_t cccd_value_buf[BLE_CCCD_VALUE_LEN]; ble_gatts_value_t value; bool is_ctrlpt_notif_enabled = false; value.len = BLE_CCCD_VALUE_LEN; value.offset = 0; value.p_value = cccd_value_buf; err_code = sd_ble_gatts_value_get(conn_handle, m_char_ctrlpt_handles.cccd_handle, &value); // TODO: Error codes should be sent back to application indicating that the // read of CCCD did not work. No application error handler is currently // implemented. (void)err_code; uint16_t cccd_value = uint16_decode(cccd_value_buf); is_ctrlpt_notif_enabled = ((cccd_value & BLE_GATT_HVX_NOTIFICATION) != 0); return is_ctrlpt_notif_enabled; }
/**@brief Function for checking if the CCCD of DFU Control point is configured for Notification. * * @details This function checks if the CCCD of DFU Control Point characteristic is configured * for Notification by the DFU Controller. * * @param[in] p_dfu DFU Service structure. * * @return True if the CCCD of DFU Control Point characteristic is configured for Notification. * False otherwise. */ static bool is_cccd_configured(ble_dfu_t * p_dfu) { // Check if the CCCDs are configured. uint8_t cccd_val_buf[BLE_CCCD_VALUE_LEN]; ble_gatts_value_t gatts_value; // Initialize value struct. memset(&gatts_value, 0, sizeof(gatts_value)); gatts_value.len = BLE_CCCD_VALUE_LEN; gatts_value.offset = 0; gatts_value.p_value = cccd_val_buf; // Check the CCCD Value of DFU Control Point. uint32_t err_code = sd_ble_gatts_value_get(p_dfu->conn_handle, p_dfu->dfu_ctrl_pt_handles.cccd_handle, &gatts_value); if (err_code != NRF_SUCCESS) { if (p_dfu->error_handler != NULL) { p_dfu->error_handler(err_code); } return false; } return ble_srv_is_notification_enabled(cccd_val_buf); }
uint32_t mesh_srv_char_val_get(uint8_t index, uint8_t* data, uint16_t* len, ble_gap_addr_t* origin_addr) { if (!is_initialized) { return NRF_ERROR_INVALID_STATE; } if (index > g_mesh_service.value_count || index == 0) { return NRF_ERROR_INVALID_ADDR; } *len = MAX_VALUE_LENGTH; uint32_t error_code = sd_ble_gatts_value_get( g_mesh_service.char_metadata[index - 1].char_value_handle, 0, len, data); if (error_code != NRF_SUCCESS) { return NRF_ERROR_INTERNAL; } if (origin_addr != NULL) { memcpy(origin_addr, &g_mesh_service.char_metadata[index - 1].last_sender_addr, sizeof(ble_gap_addr_t)); } return NRF_SUCCESS; }
/**@brief check if the cccd is configured * * @param[in] p_sc_ctrlpt SC Ctrlpt structure. * @return true if the sc_control point's cccd is correctly configured, false otherwise. */ static bool is_cccd_configured(ble_sc_ctrlpt_t * p_sc_ctrlpt) { uint32_t err_code; uint8_t cccd_value_buf[BLE_CCCD_VALUE_LEN]; bool is_sccp_indic_enabled = false; ble_gatts_value_t gatts_value; // Initialize value struct. memset(&gatts_value, 0, sizeof(gatts_value)); gatts_value.len = BLE_CCCD_VALUE_LEN; gatts_value.offset = 0; gatts_value.p_value = cccd_value_buf; err_code = sd_ble_gatts_value_get(p_sc_ctrlpt->conn_handle, p_sc_ctrlpt->sc_ctrlpt_handles.cccd_handle, &gatts_value); if (err_code != NRF_SUCCESS) { // Report error to application if (p_sc_ctrlpt->error_handler != NULL) { p_sc_ctrlpt->error_handler(err_code); } } is_sccp_indic_enabled = ble_srv_is_indication_enabled(cccd_value_buf); return is_sccp_indic_enabled; }
uint32_t ble_hts_is_indication_enabled(ble_hts_t * p_hts, bool * p_indication_enabled) { uint32_t err_code; uint8_t cccd_value_buf[BLE_CCCD_VALUE_LEN]; ble_gatts_value_t gatts_value; // Initialize value struct. memset(&gatts_value, 0, sizeof(gatts_value)); gatts_value.len = BLE_CCCD_VALUE_LEN; gatts_value.offset = 0; gatts_value.p_value = cccd_value_buf; err_code = sd_ble_gatts_value_get(p_hts->conn_handle, p_hts->meas_handles.cccd_handle, &gatts_value); if (err_code == NRF_SUCCESS) { *p_indication_enabled = ble_srv_is_indication_enabled(cccd_value_buf); } if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING) { *p_indication_enabled = false; return NRF_SUCCESS; } return err_code; }
ble_error_t nRF51GattServer::readValue(uint16_t charHandle, uint8_t buffer[], uint16_t *const lengthP) { ASSERT( ERROR_NONE == sd_ble_gatts_value_get(nrfCharacteristicHandles[charHandle].value_handle, 0, lengthP, buffer), BLE_ERROR_PARAM_OUT_OF_RANGE); return BLE_ERROR_NONE; }
uint32_t ble_hids_outp_rep_get(ble_hids_t * p_hids, uint8_t rep_index, uint16_t len, uint8_t offset, uint8_t * p_outp_rep) { return sd_ble_gatts_value_get(p_hids->outp_rep_array[rep_index].char_handles.value_handle, offset, &len, p_outp_rep); }
uint32_t mesh_srv_char_md_get(mesh_metadata_char_t* metadata) { if (!is_initialized) { return NRF_ERROR_INVALID_STATE; } uint8_t data_array[MESH_MD_CHAR_LEN]; uint16_t len = MESH_MD_CHAR_LEN; ble_gatts_value_t ble_gatts_value_get; ble_gatts_value_get.len = len; ble_gatts_value_get.offset = 0; ble_gatts_value_get.p_value = data_array; uint32_t error_code = sd_ble_gatts_value_get( BLE_CONN_HANDLE_INVALID, g_mesh_service.ble_md_char_handles.value_handle, &ble_gatts_value_get); len = ble_gatts_value_get.len; if (error_code != NRF_SUCCESS) { return NRF_ERROR_INTERNAL; } if (len != MESH_MD_CHAR_LEN) { return NRF_ERROR_INTERNAL; } memcpy(&metadata->mesh_access_addr, &data_array[MESH_MD_CHAR_AA_OFFSET], sizeof(metadata->mesh_access_addr)); memcpy(&metadata->mesh_adv_int_ms, &data_array[MESH_MD_CHAR_ADV_INT_OFFSET], sizeof(metadata->mesh_adv_int_ms)); memcpy(&metadata->mesh_channel, &data_array[MESH_MD_CHAR_CH_OFFSET], sizeof(metadata->mesh_channel)); memcpy(&metadata->mesh_value_count, &data_array[MESH_MD_CHAR_COUNT_OFFSET], sizeof(metadata->mesh_value_count)); return NRF_SUCCESS; }
ble_error_t nRF5xGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) { ble_gatts_value_t value = { /* .len = */ *lengthP, /* .offset = */ 0, /* .p_value = */ buffer, }; ASSERT_TRUE( ERROR_NONE == sd_ble_gatts_value_get(connectionHandle, attributeHandle, &value), BLE_ERROR_PARAM_OUT_OF_RANGE); *lengthP = value.len; return BLE_ERROR_NONE; }
uint32_t ble_ias_alert_level_get(ble_ias_t * p_ias, uint8_t * p_alert_level) { ble_gatts_value_t gatts_value; // Initialize value struct. memset(&gatts_value, 0, sizeof(gatts_value)); gatts_value.len = sizeof(uint8_t); gatts_value.offset = 0; gatts_value.p_value = p_alert_level; return sd_ble_gatts_value_get(p_ias->conn_handle, p_ias->alert_level_handles.value_handle, &gatts_value); }
static bool is_cccd_configured(ble_dfu_t * p_dfu) { uint8_t cccd_val_buf[BLE_CCCD_VALUE_LEN]; ble_gatts_value_t gatts_value = {0}; gatts_value.len = BLE_CCCD_VALUE_LEN; gatts_value.p_value = cccd_val_buf; // Check the CCCD Value of DFU Control Point. uint32_t err_code = sd_ble_gatts_value_get(m_conn_handle, p_dfu->dfu_ctrl_pt_handles.cccd_handle, &gatts_value); VERIFY_SUCCESS(err_code); return ble_srv_is_notification_enabled(cccd_val_buf); }
uint32_t ble_hts_is_indication_enabled(ble_hts_t * p_hts, bool * p_indication_enabled) { uint32_t err_code; uint8_t cccd_value_buf[BLE_CCCD_VALUE_LEN]; uint16_t len = BLE_CCCD_VALUE_LEN; err_code = sd_ble_gatts_value_get(p_hts->meas_handles.cccd_handle, 0, &len, cccd_value_buf); if (err_code == NRF_SUCCESS) { *p_indication_enabled = ble_srv_is_indication_enabled(cccd_value_buf); } return err_code; }
uint32_t ble_hids_outp_rep_get(ble_hids_t * p_hids, uint8_t rep_index, uint16_t len, uint8_t offset, uint8_t * p_outp_rep) { ble_gatts_value_t gatts_value; // Initialize value struct. memset(&gatts_value, 0, sizeof(gatts_value)); gatts_value.len = len; gatts_value.offset = offset; gatts_value.p_value = p_outp_rep; return sd_ble_gatts_value_get(p_hids->conn_handle, p_hids->outp_rep_array[rep_index].char_handles.value_handle, &gatts_value); }
/**@brief Function for checking if the CCCD of DFU Control point is configured for Notification. * * @details This function checks if the CCCD of DFU Control Point characteristic is configured * for Notification by the DFU Controller. * * @param[in] p_dfu DFU Service structure. * * @return True if the CCCD of DFU Control Point characteristic is configured for Notification. * False otherwise. */ static bool is_cccd_configured(ble_dfu_t * p_dfu) { // Check if the CCCDs are configured. uint16_t cccd_len = BLE_CCCD_VALUE_LEN; uint8_t cccd_val_buf[BLE_CCCD_VALUE_LEN]; // Check the CCCD Value of DFU Control Point. uint32_t err_code = sd_ble_gatts_value_get(p_dfu->dfu_ctrl_pt_handles.cccd_handle, 0, &cccd_len, cccd_val_buf); if (err_code != NRF_SUCCESS) { if (p_dfu->error_handler != NULL) { p_dfu->error_handler(err_code); } return false; } return ble_srv_is_notification_enabled(cccd_val_buf); }
/** * Private methods */ static void onWrite(ble_evt_t * p_ble_evt) { ret_code_t err_code; ble_gatts_evt_write_t *p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; // 値を取り出す uint8_t buf[GATT_MAX_DATA_LENGTH]; ble_gatts_value_t gatts_value; memset(&gatts_value, 0 , sizeof(gatts_value)); gatts_value.len = p_evt_write->len; gatts_value.offset = 0; gatts_value.p_value = buf; err_code = sd_ble_gatts_value_get(context.connection_handle, p_evt_write->handle, &gatts_value); APP_ERROR_CHECK(err_code); // キャラクタリスティクスごとの処理に振り分ける if(p_evt_write->handle == context.target_log_id_char_handle.value_handle && gatts_value.len == 1) { context.target_log_id = buf[0]; } }
uint32_t mesh_srv_char_val_get(uint8_t index, uint8_t* data, uint16_t* len, ble_gap_addr_t* origin_addr) { if (!is_initialized) { return NRF_ERROR_INVALID_STATE; } if (index > g_mesh_service.value_count || index == 0) { return NRF_ERROR_INVALID_ADDR; } *len = MAX_VALUE_LENGTH; ble_gatts_value_t ble_gatts_value_get; ble_gatts_value_get.len = *(uint16_t*)len; ble_gatts_value_get.offset = 0; ble_gatts_value_get.p_value = data; uint32_t error_code = sd_ble_gatts_value_get( BLE_CONN_HANDLE_INVALID, g_mesh_service.char_metadata[index - 1].char_value_handle, &ble_gatts_value_get); *len = ble_gatts_value_get.len; if (error_code != NRF_SUCCESS) { return NRF_ERROR_INTERNAL; } if (origin_addr != NULL) { memcpy(origin_addr, &g_mesh_service.char_metadata[index - 1].last_sender_addr, sizeof(ble_gap_addr_t)); } return NRF_SUCCESS; }
/**@brief check if the cccd is configured * * @param[in] p_sc_ctrlpt SC Ctrlpt structure. * @return true if the sc_control point's cccd is correctly configured, false otherwise. */ static bool is_cccd_configured(ble_sc_ctrlpt_t * p_sc_ctrlpt) { uint32_t err_code; uint8_t cccd_value_buf[BLE_CCCD_VALUE_LEN]; uint16_t len = BLE_CCCD_VALUE_LEN; bool is_sccp_indic_enabled = false; err_code = sd_ble_gatts_value_get(p_sc_ctrlpt->sc_ctrlpt_handles.cccd_handle, 0, &len, cccd_value_buf); if (err_code != NRF_SUCCESS) { // Report error to application if (p_sc_ctrlpt->error_handler != NULL) { p_sc_ctrlpt->error_handler(err_code); } } is_sccp_indic_enabled = ble_srv_is_indication_enabled(cccd_value_buf); return is_sccp_indic_enabled; }
/**@brief Handle execute write events to from the Queued Write module. * * @param[in] p_bms Bond Management Service structure. * @param[in] p_qwr Queued Write Structure. * @param[in] p_evt Event received from the Queued Writes module. * * @retval BLE_GATT_STATUS_SUCCESS If the received event is accepted. * @retval BLE_BMS_OPCODE_OPERATION_FAILED If the received event is not relevant for any of this module's attributes. * @retval BLE_BMS_OPCODE_NOT_SUPPORTED If the received opcode is not supported. */ uint16_t on_qwr_exec_write(nrf_ble_bms_t * p_bms, nrf_ble_qwr_t * p_qwr, nrf_ble_qwr_evt_t * p_evt) { ret_code_t err_code; uint16_t len = NRF_BLE_BMS_CTRLPT_MAX_LEN; uint8_t mem_buffer[NRF_BLE_BMS_CTRLPT_MAX_LEN]; nrf_ble_bms_ctrlpt_t ctrlpt; ble_gatts_value_t ctrlpt_value; ctrlpt_value.len = NRF_BLE_BMS_CTRLPT_MAX_LEN; ctrlpt_value.offset = 0; ctrlpt_value.p_value = mem_buffer; const uint16_t ctrlpt_handle = p_bms->ctrlpt_handles.value_handle; err_code = sd_ble_gatts_value_get(p_bms->conn_handle, ctrlpt_handle, &ctrlpt_value); if (err_code != NRF_SUCCESS) { NRF_LOG_ERROR("Control point write: Operation failed.\r\n"); return NRF_BLE_BMS_OPERATION_FAILED; } /* Decode operation */ err_code = ctrlpt_decode(ctrlpt_value.p_value, len, &ctrlpt); if (err_code != NRF_SUCCESS) { NRF_LOG_ERROR("Control point write: Operation failed.\r\n"); return NRF_BLE_BMS_OPERATION_FAILED; } /* Execute the requested operation. */ ctrlpt_execute(p_bms, ctrlpt.op_code); /* Reset authorization status */ p_bms->auth_status = NRF_BLE_BMS_AUTH_STATUS_DENIED; return BLE_GATT_STATUS_SUCCESS; }
uint32_t ble_ias_alert_level_get(ble_ias_t * p_ias, uint8_t * p_alert_level) { uint16_t len = sizeof(uint8_t); return sd_ble_gatts_value_get(p_ias->alert_level_handles.value_handle, 0, &len, p_alert_level); }
static void on_ble_write(ble_cch_t * p_cch_service, ble_evt_t * p_ble_evt) { // Decclare buffer variable to hold received data. The data can only be 32 bit long. uint32_t data_buffer; // Pupulate ble_gatts_value_t structure to hold received data and metadata. ble_gatts_value_t rx_data; rx_data.len = sizeof(uint32_t); rx_data.offset = 0; rx_data.p_value = (uint8_t*)&data_buffer; // Check if write event is performed on our characteristic or the CCCD if(p_ble_evt->evt.gatts_evt.params.write.handle == p_cch_service->charSTEP_handles.value_handle) { // Get stepper data sd_ble_gatts_value_get(p_cch_service->conn_handle, p_cch_service->charSTEP_handles.value_handle, &rx_data); if (rx_data.p_value[POSITION_byte] > MAX_STEPS) positionIwantToGo = MAX_STEPS; positionIwantToGo = rx_data.p_value[POSITION_byte]; speed = SPEED_LIMIT + (0xff - rx_data.p_value[SPEED_byte]) * 40; //speed = rx_data.p_value[SPEED_byte] * 40; } else if(p_ble_evt->evt.gatts_evt.params.write.handle == p_cch_service->charRGB_handles.value_handle) { // Get RGB data sd_ble_gatts_value_get(p_cch_service->conn_handle, p_cch_service->charRGB_handles.value_handle, &rx_data); if (rx_data.p_value[RED_byte] > 100) rx_data.p_value[RED_byte] = 100; if (rx_data.p_value[GREEN_byte] > 100) rx_data.p_value[GREEN_byte] = 100; if (rx_data.p_value[BLUE_byte] > 100) rx_data.p_value[BLUE_byte] = 100; setRGBled(rx_data.p_value[RED_byte], rx_data.p_value[GREEN_byte], rx_data.p_value[BLUE_byte]); } else if(p_ble_evt->evt.gatts_evt.params.write.handle == p_cch_service->charR_handles.value_handle) { // Get RED data sd_ble_gatts_value_get(p_cch_service->conn_handle, p_cch_service->charR_handles.value_handle, &rx_data); if (rx_data.p_value[MLED_byte] > 100) rx_data.p_value[MLED_byte] = 100; setMled(rx_data.p_value[MLED_byte]); } else if(p_ble_evt->evt.gatts_evt.params.write.handle == p_cch_service->charSTEP_handles.cccd_handle) { // Get stepper cccd data sd_ble_gatts_value_get(p_cch_service->conn_handle, p_cch_service->charSTEP_handles.cccd_handle, &rx_data); } else if(p_ble_evt->evt.gatts_evt.params.write.handle == p_cch_service->charRGB_handles.cccd_handle) { // Get RGB cccd data sd_ble_gatts_value_get(p_cch_service->conn_handle, p_cch_service->charRGB_handles.cccd_handle, &rx_data); } else if(p_ble_evt->evt.gatts_evt.params.write.handle == p_cch_service->charR_handles.cccd_handle) { // Get R cccd data sd_ble_gatts_value_get(p_cch_service->conn_handle, p_cch_service->charR_handles.cccd_handle, &rx_data); } }
uint32_t conn_mw_ble_gatts_value_set(uint8_t const * const p_rx_buf, uint32_t rx_buf_len, uint8_t * const p_tx_buf, uint32_t * const p_tx_buf_len) { SER_ASSERT_NOT_NULL(p_rx_buf); SER_ASSERT_NOT_NULL(p_tx_buf); SER_ASSERT_NOT_NULL(p_tx_buf_len); uint16_t conn_handle; uint16_t handle; uint8_t attr_val_table[BLE_GATTS_VAR_ATTR_LEN_MAX]; ble_gatts_value_t attr_val = { .len = sizeof (attr_val_table), .offset = 0, .p_value = attr_val_table }; ble_gatts_value_t * p_attr_val = &attr_val; uint32_t err_code = NRF_SUCCESS; uint32_t sd_err_code; err_code = ble_gatts_value_set_req_dec(p_rx_buf, rx_buf_len, &conn_handle, &handle, &p_attr_val); SER_ASSERT(err_code == NRF_SUCCESS, err_code); sd_err_code = sd_ble_gatts_value_set(conn_handle, handle, p_attr_val); err_code = ble_gatts_value_set_rsp_enc(sd_err_code, p_tx_buf, p_tx_buf_len, p_attr_val); SER_ASSERT(err_code == NRF_SUCCESS, err_code); return err_code; } uint32_t conn_mw_ble_gatts_value_get(uint8_t const * const p_rx_buf, uint32_t rx_buf_len, uint8_t * const p_tx_buf, uint32_t * const p_tx_buf_len) { SER_ASSERT_NOT_NULL(p_rx_buf); SER_ASSERT_NOT_NULL(p_tx_buf); SER_ASSERT_NOT_NULL(p_tx_buf_len); uint16_t conn_handle; uint16_t handle; uint8_t val[BLE_GATTS_VAR_ATTR_LEN_MAX]; ble_gatts_value_t attr_value; ble_gatts_value_t * p_attr_value = &attr_value; attr_value.p_value = val; uint32_t err_code = NRF_SUCCESS; uint32_t sd_err_code; err_code = ble_gatts_value_get_req_dec(p_rx_buf, rx_buf_len, &conn_handle, &handle, &p_attr_value); SER_ASSERT(err_code == NRF_SUCCESS, err_code); sd_err_code = sd_ble_gatts_value_get(conn_handle, handle, p_attr_value); err_code = ble_gatts_value_get_rsp_enc(sd_err_code, p_tx_buf, p_tx_buf_len, p_attr_value); SER_ASSERT(err_code == NRF_SUCCESS, err_code); return err_code; }
/**@brief Function for handling the @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: BLE_GATTS_AUTHORIZE_TYPE_WRITE: event from the SoftDevice. * * @param[in] p_escs Eddystone Configuration Service structure. * @param[in] p_ble_evt Pointer to the event received from BLE stack. */ static void on_long_write(nrf_ble_escs_t * p_escs, ble_evt_t * p_ble_evt) { static uint16_t write_evt_uuid; static bool write_evt_uuid_set = false; uint32_t err_code; VERIFY_PARAM_NOT_NULL_VOID(p_escs); VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt); ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.authorize_request.request.write; ble_gatts_rw_authorize_reply_params_t reply = {0}; if (p_evt_write->op == BLE_GATTS_OP_PREP_WRITE_REQ) { err_code = get_evt_type_for_handle(p_evt_write->handle, &write_evt_uuid); APP_ERROR_CHECK(err_code); write_evt_uuid_set = true; reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; reply.params.write.update = 0; reply.params.write.offset = 0; reply.params.write.len = p_evt_write->len; reply.params.write.p_data = NULL; err_code = sd_ble_gatts_rw_authorize_reply(p_escs->conn_handle, &reply); APP_ERROR_CHECK(err_code); } else if (p_evt_write->op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) { uint8_t value_buffer[ESCS_ADV_SLOT_CHAR_LENGTH_MAX] = {0}; ble_gatts_value_t value = { .len = sizeof(value_buffer), .offset = 0, .p_value = &(value_buffer[0]) }; ASSERT(write_evt_uuid_set); write_evt_uuid_set = false; reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; reply.params.write.update = 0; reply.params.write.offset = 0; reply.params.write.len = p_evt_write->len; reply.params.write.p_data = NULL; err_code = sd_ble_gatts_rw_authorize_reply(p_escs->conn_handle, &reply); APP_ERROR_CHECK(err_code); // Now that the value has been accepted using 'sd_ble_gatts_rw_authorize_reply', it can be found in the database. err_code = sd_ble_gatts_value_get( p_escs->conn_handle, p_escs->rw_adv_slot_handles.value_handle, &value); APP_ERROR_CHECK(err_code); p_escs->write_evt_handler(p_escs, write_evt_uuid, p_evt_write->handle, value.p_value, value.len); } else { } }
*/ /**************************************************************************/ ble_error_t nRF51GattServer::readValue(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) { return readValue(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, lengthP); } ble_error_t nRF51GattServer::readValue(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) { ble_gatts_value_t value = { .len = *lengthP, .offset = 0, .p_value = buffer, }; APP_ERROR_CHECK( sd_ble_gatts_value_get(connectionHandle, nrfCharacteristicHandles[attributeHandle].value_handle, &value) ); *lengthP = value.len; return BLE_ERROR_NONE; } /**************************************************************************/ /*! @brief Updates the value of a characteristic, based on the service and characteristic index fields @param[in] charHandle The handle of the GattCharacteristic to write to @param[in] buffer Data to use when updating the characteristic's value (raw byte array in LSB format)
/**************************************************************************/ ble_error_t nRF5xGattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) { return read(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, lengthP); } ble_error_t nRF5xGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) { ble_gatts_value_t value = { .len = *lengthP, .offset = 0, .p_value = buffer, }; ASSERT_TRUE( ERROR_NONE == sd_ble_gatts_value_get(connectionHandle, attributeHandle, &value), BLE_ERROR_PARAM_OUT_OF_RANGE); *lengthP = value.len; return BLE_ERROR_NONE; } /**************************************************************************/ /*! @brief Updates the value of a characteristic, based on the service and characteristic index fields @param[in] charHandle The handle of the GattCharacteristic to write to @param[in] buffer Data to use when updating the characteristic's value