/**@brief Function for handling the @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event from the * SoftDevice. * * @param[in] p_dfu DFU Service Structure. * @param[in] p_ble_evt Pointer to the event received from BLE stack. */ static bool on_rw_authorize_req(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt) { uint32_t err_code; ble_gatts_rw_authorize_reply_params_t auth_reply = {0}; ble_gatts_evt_rw_authorize_request_t * p_authorize_request; ble_gatts_evt_write_t * p_ble_write_evt; p_authorize_request = &(p_ble_evt->evt.gatts_evt.params.authorize_request); p_ble_write_evt = &(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write); if ((p_authorize_request->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) && (p_authorize_request->request.write.handle == p_dfu->dfu_ctrl_pt_handles.value_handle) && (p_authorize_request->request.write.op != BLE_GATTS_OP_PREP_WRITE_REQ) && (p_authorize_request->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) && (p_authorize_request->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL) ) { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; auth_reply.params.write.update = 1; auth_reply.params.write.offset = p_ble_write_evt->offset; auth_reply.params.write.len = p_ble_write_evt->len; auth_reply.params.write.p_data = p_ble_write_evt->data; if (!is_cccd_configured(p_dfu)) { // Send an error response to the peer indicating that the CCCD is improperly configured. auth_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR; // Ignore response of auth reply (void)sd_ble_gatts_rw_authorize_reply(m_conn_handle, &auth_reply); return false; } auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; err_code = sd_ble_gatts_rw_authorize_reply(m_conn_handle, &auth_reply); return err_code == NRF_SUCCESS ? true: false; } else { return false; } }
/**@brief Function for handling a Write event on the Control Point characteristic. * * @param[in] p_dfu DFU Service Structure. * @param[in] p_ble_write_evt Pointer to the write event received from BLE stack. * * @return NRF_SUCCESS on successful processing of control point write. Otherwise an error code. */ static uint32_t on_ctrl_pt_write(ble_dfu_t * p_dfu, ble_gatts_evt_write_t * p_ble_write_evt) { ble_gatts_rw_authorize_reply_params_t write_authorize_reply; write_authorize_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; if (!is_cccd_configured(p_dfu)) { // Send an error response to the peer indicating that the CCCD is improperly configured. write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR; return (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &write_authorize_reply)); } else { uint32_t err_code; write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; err_code = (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &write_authorize_reply)); if (err_code != NRF_SUCCESS) { return err_code; } } ble_dfu_evt_t ble_dfu_evt; switch (p_ble_write_evt->data[0]) { case OP_CODE_START_DFU: ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_START; if (p_ble_write_evt->len < PKT_START_DFU_PARAM_LEN) { return ble_dfu_response_send(p_dfu, (ble_dfu_procedure_t) p_ble_write_evt->data[0], BLE_DFU_RESP_VAL_OPER_FAILED); } ble_dfu_evt.evt.ble_dfu_pkt_write.len = 1; ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]); p_dfu->evt_handler(p_dfu, &ble_dfu_evt); break; case OP_CODE_RECEIVE_INIT: ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_INIT_DATA; if (p_ble_write_evt->len < PKT_INIT_DFU_PARAM_LEN) { return ble_dfu_response_send(p_dfu, (ble_dfu_procedure_t) p_ble_write_evt->data[0], BLE_DFU_RESP_VAL_OPER_FAILED); } ble_dfu_evt.evt.ble_dfu_pkt_write.len = 1; ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]); p_dfu->evt_handler(p_dfu, &ble_dfu_evt); break; case OP_CODE_RECEIVE_FW: ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_APP_DATA; p_dfu->evt_handler(p_dfu, &ble_dfu_evt); break; case OP_CODE_VALIDATE: ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_VALIDATE; p_dfu->evt_handler(p_dfu, &ble_dfu_evt); break; case OP_CODE_ACTIVATE_N_RESET: ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_ACTIVATE_N_RESET; p_dfu->evt_handler(p_dfu, &ble_dfu_evt); break; case OP_CODE_SYS_RESET: ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_SYS_RESET; p_dfu->evt_handler(p_dfu, &ble_dfu_evt); break; case OP_CODE_PKT_RCPT_NOTIF_REQ: if (p_ble_write_evt->len < PKT_RCPT_NOTIF_REQ_LEN) { return (ble_dfu_response_send(p_dfu, BLE_DFU_PKT_RCPT_REQ_PROCEDURE, BLE_DFU_RESP_VAL_NOT_SUPPORTED)); } ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts = uint16_decode(&(p_ble_write_evt->data[1])); if (ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts == 0) { ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_DISABLED; } else { ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_ENABLED; } p_dfu->evt_handler(p_dfu, &ble_dfu_evt); break; case OP_CODE_IMAGE_SIZE_REQ: ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_BYTES_RECEIVED_SEND; p_dfu->evt_handler(p_dfu, &ble_dfu_evt); break; default: // Unsupported op code. return ble_dfu_response_send(p_dfu, (ble_dfu_procedure_t) p_ble_write_evt->data[0], BLE_DFU_RESP_VAL_NOT_SUPPORTED); } return NRF_SUCCESS; }
/**@brief Handle a write event to the Speed and Cadence Control Point. * * @param[in] p_sc_ctrlpt SC Ctrlpt structure. * @param[in] p_evt_write WRITE event to be handled. */ static void on_ctrlpt_write(ble_sc_ctrlpt_t * p_sc_ctrlpt, ble_gatts_evt_write_t const * p_evt_write) { ble_sc_ctrlpt_val_t rcvd_ctrlpt = { BLE_SCPT_RESPONSE_CODE , 0, BLE_SENSOR_LOCATION_OTHER }; ble_sc_ctrlpt_rsp_t rsp; uint32_t err_code; ble_gatts_rw_authorize_reply_params_t auth_reply; ble_sc_ctrlpt_evt_t evt; 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; auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; auth_reply.params.write.update = 1; if (is_cccd_configured(p_sc_ctrlpt)) { if (p_sc_ctrlpt->procedure_status == BLE_SCPT_NO_PROC_IN_PROGRESS) { auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; } else { auth_reply.params.write.gatt_status = SC_CTRLPT_NACK_PROC_ALREADY_IN_PROGRESS; } } else { auth_reply.params.write.gatt_status = SC_CTRLPT_NACK_CCCD_IMPROPERLY_CONFIGURED; } err_code = sd_ble_gatts_rw_authorize_reply(p_sc_ctrlpt->conn_handle, &auth_reply); if (err_code != NRF_SUCCESS) { // Report error to application. if (p_sc_ctrlpt->error_handler != NULL) { p_sc_ctrlpt->error_handler(err_code); } } if (auth_reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS) { return; } p_sc_ctrlpt->procedure_status = BLE_SCPT_INDICATION_PENDING; rsp.status = BLE_SCPT_OP_CODE_NOT_SUPPORTED; err_code = sc_ctrlpt_decode(p_evt_write->data, p_evt_write->len, &rcvd_ctrlpt); if (err_code != NRF_SUCCESS) { rsp.opcode = rcvd_ctrlpt.opcode; rsp.status = BLE_SCPT_OP_CODE_NOT_SUPPORTED; } else { rsp.opcode = rcvd_ctrlpt.opcode; switch (rcvd_ctrlpt.opcode) { case BLE_SCPT_REQUEST_SUPPORTED_SENSOR_LOCATIONS: if ((p_sc_ctrlpt->supported_functions & BLE_SRV_SC_CTRLPT_SENSOR_LOCATIONS_OP_SUPPORTED) == BLE_SRV_SC_CTRLPT_SENSOR_LOCATIONS_OP_SUPPORTED) { rsp.status = BLE_SCPT_SUCCESS; } else { rsp.status = BLE_SCPT_OP_CODE_NOT_SUPPORTED; } break; case BLE_SCPT_UPDATE_SENSOR_LOCATION: if ((p_sc_ctrlpt->supported_functions & BLE_SRV_SC_CTRLPT_SENSOR_LOCATIONS_OP_SUPPORTED) == BLE_SRV_SC_CTRLPT_SENSOR_LOCATIONS_OP_SUPPORTED) { if (is_location_supported(p_sc_ctrlpt, rcvd_ctrlpt.location)) { ble_gatts_value_t gatts_value; uint8_t rcvd_location = (uint8_t)rcvd_ctrlpt.location; rsp.status = BLE_SCPT_SUCCESS; // Initialize value struct. memset(&gatts_value, 0, sizeof(gatts_value)); gatts_value.len = sizeof(uint8_t); gatts_value.offset = 0; gatts_value.p_value = &rcvd_location; evt.evt_type = BLE_SC_CTRLPT_EVT_UPDATE_LOCATION; evt.params.update_location = rcvd_ctrlpt.location; if (p_sc_ctrlpt->evt_handler != NULL) { rsp.status = p_sc_ctrlpt->evt_handler(p_sc_ctrlpt, &evt); } if (rsp.status == BLE_SCPT_SUCCESS) { err_code = sd_ble_gatts_value_set(p_sc_ctrlpt->conn_handle, p_sc_ctrlpt->sensor_location_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); } rsp.status = BLE_SCPT_OPERATION_FAILED; } } } else { rsp.status = BLE_SCPT_INVALID_PARAMETER; } } else { rsp.status = BLE_SCPT_OP_CODE_NOT_SUPPORTED; } break; case BLE_SCPT_SET_CUMULATIVE_VALUE: if ((p_sc_ctrlpt->supported_functions & BLE_SRV_SC_CTRLPT_CUM_VAL_OP_SUPPORTED) == BLE_SRV_SC_CTRLPT_CUM_VAL_OP_SUPPORTED) { rsp.status = BLE_SCPT_SUCCESS; evt.evt_type = BLE_SC_CTRLPT_EVT_SET_CUMUL_VALUE; evt.params.cumulative_value = rcvd_ctrlpt.cumulative_value; if (p_sc_ctrlpt->evt_handler != NULL) { rsp.status = p_sc_ctrlpt->evt_handler(p_sc_ctrlpt, &evt); } } else { rsp.status = BLE_SCPT_OP_CODE_NOT_SUPPORTED; } break; case BLE_SCPT_START_AUTOMATIC_CALIBRATION: if ((p_sc_ctrlpt->supported_functions & BLE_SRV_SC_CTRLPT_START_CALIB_OP_SUPPORTED) == BLE_SRV_SC_CTRLPT_START_CALIB_OP_SUPPORTED) { p_sc_ctrlpt->procedure_status = BLE_SCPT_AUTOMATIC_CALIB_IN_PROGRESS; evt.evt_type = BLE_SC_CTRLPT_EVT_START_CALIBRATION; if (p_sc_ctrlpt->evt_handler != NULL) { rsp.status = p_sc_ctrlpt->evt_handler(p_sc_ctrlpt, &evt); if (rsp.status != BLE_SCPT_SUCCESS) { // If the application returns an error, the response is to be sent // right away and the calibration is considered as not started. p_sc_ctrlpt->procedure_status = BLE_SCPT_INDICATION_PENDING; } } } else { rsp.status = BLE_SCPT_OP_CODE_NOT_SUPPORTED; } break; default: rsp.status = BLE_SCPT_OP_CODE_NOT_SUPPORTED; break; } } p_sc_ctrlpt->response.len = ctrlpt_rsp_encode(p_sc_ctrlpt, &rsp, p_sc_ctrlpt->response.encoded_ctrl_rsp); if (p_sc_ctrlpt->procedure_status == BLE_SCPT_INDICATION_PENDING) { sc_ctrlpt_resp_send(p_sc_ctrlpt); } }
static void on_ctrlpt_write(ble_achs_t * p_achs, ble_gatts_evt_write_t * p_evt_write) { ble_gatts_rw_authorize_reply_params_t auth_reply; auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; if (is_cccd_configured()) { auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; uint32_t err_code = sd_ble_gatts_rw_authorize_reply(p_achs->conn_handle, &auth_reply); (void)err_code; } else { auth_reply.params.write.gatt_status = ACH_CTRLPT_NACK_CCCD_IMPROPERLY_CONFIGURED; uint32_t err_code = sd_ble_gatts_rw_authorize_reply(p_achs->conn_handle, &auth_reply); (void)err_code; return; } uint8_t op_code = p_evt_write->data[0]; //lint --e{415} uint8_t command = p_evt_write->data[1]; if (op_code == ACH_OP_COMMAND) { switch (command) { case ACH_CMD_REPORTING_MODE_OFF: { //Load up the last received command structure so the application //gets recent data when it asks for it m_last_received_command.command = REPORTING_MODE_OFF; m_last_received_command.master_id = EVERY_MASTER_ID; //Set the command received flag so the application will know to ask for //the most recent command. asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED); } break; case ACH_CMD_REPORTING_MODE_ON: { //Load up the last received command structure so the application //gets recent data when it asks for it m_last_received_command.command = REPORTING_MODE_ON; m_last_received_command.master_id = EVERY_MASTER_ID; //Set the command received flag so the application will know to ask for //the most recent command. asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED); } break; case ACH_CMD_REPORTING_MODE_WARNINGS: { /* this command is not currently supported by this demo //Load up the last received command structure so the application //gets recent data when it asks for it m_last_received_command.command = REPORTING_MODE_WARNINGS; m_last_received_command.master_id = EVERY_MASTER_ID; //Set the command received flag so the application will know to ask for //the most recent command. asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED); */ } break; case ACH_CMD_PERI_ON: { //Load up the last received command structure so the application //gets recent data when it asks for it m_last_received_command.command = TURN_ON; //lint --e{415} //lint --e{416} m_last_received_command.shared_address = p_evt_write->data[2]; //lint --e{415} //lint --e{416} m_last_received_command.master_id = uint16_decode(&p_evt_write->data[4]); m_last_received_command.group_number = NO_GROUPS;/**< @todo can the demo actually use groups? Double check this everywhere*/ //Set the command received flag so the application will know to ask for //the most recent command. asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED); } break; case ACH_CMD_PERI_OFF: { //Load up the last received command structure so the application //gets recent data when it asks for it m_last_received_command.command = TURN_OFF; //lint --e{416} m_last_received_command.shared_address = p_evt_write->data[2]; //lint --e{416} m_last_received_command.master_id = uint16_decode(&p_evt_write->data[4]); m_last_received_command.group_number = NO_GROUPS; //Set the command received flag so the application will know to ask for //the most recent command. asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED); } break; case ACH_CMD_GROUP_ASSIGN: { //Load up the last received command structure so the application //gets recent data when it asks for it m_last_received_command.command = ASSIGN_TO_GROUP; //lint --e{416} m_last_received_command.shared_address = p_evt_write->data[2]; //lint --e{416} m_last_received_command.master_id = uint16_decode(&p_evt_write->data[4]); m_last_received_command.group_number = p_evt_write->data[3]; //Set the command received flag so the application will know to ask for //the most recent command. asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED); } break; case ACH_CMD_GROUP_ON: { //Load up the last received command structure so the application //gets recent data when it asks for it m_last_received_command.command = TURN_ON; m_last_received_command.shared_address = EVERY_DEVICE_ADDRESS; //lint --e{416} m_last_received_command.master_id = uint16_decode(&p_evt_write->data[3]); m_last_received_command.group_number = p_evt_write->data[2]; asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED); } break; case ACH_CMD_GROUP_OFF: { //Load up the last received command structure so the application //gets recent data when it asks for it m_last_received_command.command = TURN_OFF; m_last_received_command.shared_address = EVERY_DEVICE_ADDRESS; //lint --e{416} m_last_received_command.master_id = uint16_decode(&p_evt_write->data[3]); m_last_received_command.group_number = p_evt_write->data[2]; asc_event_set(&m_event_flags, EVENT_ASC_COMMAND_RECEIVED); } break; default: break; } // end switch(command) } }