static void on_rw_authorize_request(ble_iqo_t * p_iqo, ble_evt_t * p_ble_evt) { ble_gatts_evt_rw_authorize_request_t * evt_rw_auth = &p_ble_evt->evt.gatts_evt.params.authorize_request; if (evt_rw_auth->type != BLE_GATTS_AUTHORIZE_TYPE_READ) { // Unexpected operation return; } if (evt_rw_auth->request.read.handle == p_iqo->iqo_wifi_status_handle.value_handle) { ble_gatts_rw_authorize_reply_params_t auth_params; ble_gatts_rw_authorize_reply_params_t * p_auth_params = &auth_params; uint8_t ret = 0; ret = intermcu_get_wifi_status(ip_buf); if (ret == 2) { memset((void *)p_auth_params, 0, sizeof(auth_params)); auth_params.type = BLE_GATTS_AUTHORIZE_TYPE_READ; auth_params.params.read.p_data = ip_buf; auth_params.params.read.len = 15; auth_params.params.read.update = 1; } else { memset((void *)p_auth_params, 0, sizeof(auth_params)); auth_params.type = BLE_GATTS_AUTHORIZE_TYPE_READ; auth_params.params.read.p_data = &ret; auth_params.params.read.len = 1; auth_params.params.read.update = 1; } APP_ERROR_CHECK(sd_ble_gatts_rw_authorize_reply(p_iqo->conn_handle, p_auth_params)); } else if (evt_rw_auth->request.read.handle == p_iqo->iqo_peer_status_handle.value_handle) { ble_gatts_rw_authorize_reply_params_t auth_params; ble_gatts_rw_authorize_reply_params_t * p_auth_params = &auth_params; uint8_t ret = 0; ret = ble_iqo_c_status(); memset((void *)p_auth_params, 0, sizeof(auth_params)); auth_params.type = BLE_GATTS_AUTHORIZE_TYPE_READ; auth_params.params.read.p_data = &ret; auth_params.params.read.len = 1; auth_params.params.read.update = 1; APP_ERROR_CHECK(sd_ble_gatts_rw_authorize_reply(p_iqo->conn_handle, p_auth_params)); } }
/**@brief Function for handling write events to the Buttonless Secure DFU Service Service Control Point characteristic. * * @param[in] p_evt_write Write event received from the BLE stack. */ static void on_ctrlpt_write(ble_gatts_evt_write_t const * p_evt_write) { uint32_t err_code; ble_gatts_rw_authorize_reply_params_t write_authorize_reply; memset(&write_authorize_reply, 0, sizeof(write_authorize_reply)); write_authorize_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; if (m_dfu.is_ctrlpt_indication_enabled) { write_authorize_reply.params.write.update = 1; write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; } else { write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR; } // Authorize the write request do { err_code = sd_ble_gatts_rw_authorize_reply(m_dfu.conn_handle, &write_authorize_reply); } while (err_code == NRF_ERROR_BUSY); if (write_authorize_reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS) { return; } // Forward the write event to the Buttonless DFU module. ble_dfu_buttonless_on_ctrl_pt_write(p_evt_write); }
uint32_t conn_mw_ble_gatts_rw_authorize_reply(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; uint8_t data[BLE_GATTS_VAR_ATTR_LEN_MAX]; ble_gatts_rw_authorize_reply_params_t auth_params; ble_gatts_rw_authorize_reply_params_t * p_auth_params = &auth_params; auth_params.params.read.p_data = data; auth_params.params.read.len = sizeof (data); uint32_t err_code = NRF_SUCCESS; uint32_t sd_err_code; err_code = ble_gatts_rw_authorize_reply_req_dec(p_rx_buf, rx_buf_len, &conn_handle, &p_auth_params); SER_ASSERT(err_code == NRF_SUCCESS, err_code); sd_err_code = sd_ble_gatts_rw_authorize_reply(conn_handle, p_auth_params); err_code = ble_gatts_rw_authorize_reply_rsp_enc(sd_err_code, p_tx_buf, p_tx_buf_len); SER_ASSERT(err_code == NRF_SUCCESS, err_code); return err_code; }
/**@brief Function for handling the Glucose session start time write event. * * @param[in] p_cgms Service instance. * @param[in] p_evt_write WRITE event to be handled. */ static void on_sst_value_write(nrf_ble_cgms_t * p_cgms, ble_gatts_evt_write_t const * p_evt_write) { ble_gatts_rw_authorize_reply_params_t auth_reply; uint32_t err_code; memset(&auth_reply, 0, sizeof(auth_reply)); auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; auth_reply.params.write.update = 1; auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; 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); } } err_code = cgm_update_sst(p_cgms, p_evt_write); if (err_code != NRF_SUCCESS) { if (p_cgms->error_handler != NULL) { p_cgms->error_handler(err_code); } } }
/**@brief Function for handling the Application's BLE Stack events. * * @param[in] p_ble_evt Bluetooth stack event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code = NRF_SUCCESS; ble_gatts_rw_authorize_reply_params_t auth_reply; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; break; case BLE_GAP_EVT_DISCONNECTED: m_conn_handle = BLE_CONN_HANDLE_INVALID; break; case BLE_EVT_USER_MEM_REQUEST: err_code = sd_ble_user_mem_reply(m_conn_handle, NULL); APP_ERROR_CHECK(err_code); break; case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: if(p_ble_evt->evt.gatts_evt.params.authorize_request.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID) { if ((p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ) || (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) || (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) { if (p_ble_evt->evt.gatts_evt.params.authorize_request.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; } else { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; } auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED; err_code = sd_ble_gatts_rw_authorize_reply(m_conn_handle,&auth_reply); APP_ERROR_CHECK(err_code); } } break; case BLE_GATTS_OP_EXEC_WRITE_REQ_NOW: break; default: // No implementation needed. break; } }
/**@brief Function for handling BLE Stack events involving peripheral applications. Manages the * LEDs used to report the status of the peripheral applications. * * @param[in] p_ble_evt Bluetooth stack event. */ static void on_ble_peripheral_evt(ble_evt_t * p_ble_evt) { uint32_t err_code; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: NRF_LOG_PRINTF("Peripheral connected\r\n"); LEDS_OFF(PERIPHERAL_ADVERTISING_LED); LEDS_ON(PERIPHERAL_CONNECTED_LED); break; //BLE_GAP_EVT_CONNECTED case BLE_GAP_EVT_DISCONNECTED: NRF_LOG_PRINTF("Peripheral disconnected\r\n"); LEDS_OFF(PERIPHERAL_CONNECTED_LED); break;//BLE_GAP_EVT_DISCONNECTED case BLE_EVT_USER_MEM_REQUEST: err_code = sd_ble_user_mem_reply(p_ble_evt->evt.gap_evt.conn_handle, NULL); APP_ERROR_CHECK(err_code); break;//BLE_EVT_USER_MEM_REQUEST case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: { ble_gatts_rw_authorize_reply_params_t auth_reply; if(p_ble_evt->evt.gatts_evt.params.authorize_request.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID) { if ((p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ) || (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) || (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) { if (p_ble_evt->evt.gatts_evt.params.authorize_request.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; } else { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; } auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED; err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gap_evt.conn_handle,&auth_reply); APP_ERROR_CHECK(err_code); } } }break;//BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST default: // No implementation needed. break; } }
/**@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 Handle write events to the Location and Navigation Service Control Point characteristic. * * @param[in] p_dfu DFU Service structure. * @param[in] p_evt_write Write event received from the BLE stack. */ static void on_ctrlpt_write(ble_dfu_t * p_dfu, ble_gatts_evt_write_t const * p_evt_write) { uint32_t err_code; ble_dfu_rsp_code_t rsp_code = DFU_RSP_OPERATION_FAILED; ble_gatts_rw_authorize_reply_params_t write_authorize_reply; memset(&write_authorize_reply, 0, sizeof(write_authorize_reply)); write_authorize_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; if (p_dfu->is_ctrlpt_notification_enabled) { write_authorize_reply.params.write.update = 1; write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; } else { write_authorize_reply.params.write.gatt_status = DFU_RSP_CCCD_CONFIG_IMPROPER; } // reply to the write authorization do { err_code = sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &write_authorize_reply); } while (err_code == NRF_ERROR_BUSY); if (write_authorize_reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS) { return; } // Start executing the control point write action switch (p_evt_write->data[0]) { case BLE_DFU_ENTER_BOOTLOADER: rsp_code = DFU_RSP_SUCCESS; break; // Unrecognized Op Code default: rsp_code = DFU_RSP_OP_CODE_NOT_SUPPORTED; break; } resp_send(p_dfu, (ble_dfu_buttonless_op_code_t)p_evt_write->data[0], rsp_code); if (rsp_code == BLE_DFU_ENTER_BOOTLOADER && p_evt_write->data[0] == BLE_DFU_ENTER_BOOTLOADER) { enter_bootloader(p_dfu); } }
ret_code_t es_gatts_send_reply(nrf_ble_escs_t * p_escs, ble_gatts_rw_authorize_reply_params_t * p_reply) { VERIFY_PARAM_NOT_NULL(p_escs); VERIFY_PARAM_NOT_NULL(p_reply); if (p_escs->conn_handle != BLE_CONN_HANDLE_INVALID) { return sd_ble_gatts_rw_authorize_reply(p_escs->conn_handle, p_reply); } return NRF_ERROR_INVALID_STATE; }
//Function for handling Read Authorization static void on_read(ble_lc_t * p_lc, ble_evt_t * p_ble_evt) { uint8_t update_data; ble_gatts_rw_authorize_reply_params_t reply_params; update_data = p_lc->data_handler_status(); memset(&reply_params, 0, sizeof(reply_params)); reply_params.type = BLE_GATTS_AUTHORIZE_TYPE_READ; reply_params.params.read.p_data = &update_data; reply_params.params.read.len = sizeof(update_data); reply_params.params.read.offset = 0; reply_params.params.read.update = 1; sd_ble_gatts_rw_authorize_reply(p_lc->conn_handle, &reply_params); }
/**@brief Authorize WRITE request event handler. * * @details Handles WRITE events from the BLE stack. * * @param[in] p_bms Bond Management Service structure. * @param[in] p_gatts_evt GATTS Event received from the BLE stack. * */ static void on_rw_auth_req(nrf_ble_bms_t * p_bms, ble_gatts_evt_t * p_gatts_evt) { ble_gatts_evt_rw_authorize_request_t * p_auth_req = &p_gatts_evt->params.authorize_request; ble_gatts_rw_authorize_reply_params_t auth_reply; ret_code_t err_code; memset(&auth_reply, 0, sizeof(auth_reply)); if ((p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) && (p_auth_req->request.write.op == BLE_GATTS_OP_WRITE_REQ) && (p_auth_req->request.write.handle == p_bms->ctrlpt_handles.value_handle)) { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; on_ctrlpt_write(p_bms, &p_auth_req->request.write, &auth_reply.params.write); /* Send authorization reply */ err_code = sd_ble_gatts_rw_authorize_reply(p_bms->conn_handle, &auth_reply); error_check(err_code, p_bms->error_handler); } }
static void onRWAuthReq(ble_evt_t *p_ble_evt) { ret_code_t err_code; ble_gatts_evt_rw_authorize_request_t *p_auth_req = &p_ble_evt->evt.gatts_evt.params.authorize_request; // バッファを用意 uint8_t buffer[GATT_MAX_DATA_LENGTH]; uint8_t length = 0; memset(buffer, 0, sizeof(buffer)); // 実際の読み出し処理 if(p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_READ) { if( p_auth_req->request.read.handle == context.target_datetime_char_handle.value_handle){ length = onRWAuthReq_datetime_char(buffer, GATT_MAX_DATA_LENGTH); } else if( p_auth_req->request.read.handle == context.target_abstract_char_handle.value_handle){ length = onRWAuthReq_abstract_char(buffer, GATT_MAX_DATA_LENGTH); } else { // ハンドラの一致なし、ここで終了 return; } // リプライを用意 ble_gatts_rw_authorize_reply_params_t reply_params; memset(&reply_params, 0, sizeof(reply_params)); reply_params.type = BLE_GATTS_AUTHORIZE_TYPE_READ; reply_params.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS; reply_params.params.read.update = (length != 0); reply_params.params.read.offset = 0; reply_params.params.read.len = length; reply_params.params.read.p_data = buffer; // リプライ err_code = sd_ble_gatts_rw_authorize_reply(context.connection_handle, &reply_params); APP_ERROR_CHECK(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 { } }
/**@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); } }
void service_ble_event(ble_evt_t* event) { uint32_t err_code; switch (event->header.evt_id) { case BLE_GAP_EVT_CONNECTED: service_state.connection_handle = event->evt.gap_evt.conn_handle; break; case BLE_GAP_EVT_DISCONNECTED: service_state.connection_handle = BLE_CONN_HANDLE_INVALID; break; case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: { switch (event->evt.gatts_evt.params.authorize_request.type) { case BLE_GATTS_AUTHORIZE_TYPE_WRITE: { const service_characteristic_t* characteristic = service_findCharacteristicByHandle(event->evt.gatts_evt.params.authorize_request.request.write.handle); if (characteristic) { switch (event->evt.gatts_evt.params.authorize_request.request.write.op) { case BLE_GATTS_OP_WRITE_REQ: if (characteristic->write && (characteristic->plain || session_isEncrypted())) { uint16_t blength = 0; if (SESSION_PLAIN_BUFFERLEN(event->evt.gatts_evt.params.authorize_request.request.write.len) <= sizeof(buffer_buffer) && session_writeData(event->evt.gatts_evt.params.authorize_request.request.write.data, event->evt.gatts_evt.params.authorize_request.request.write.len, buffer_buffer, &blength)) { characteristic->write(buffer_buffer, blength, characteristic->ctx); } } service_state.current_characteristic = NULL; break; case BLE_GATTS_OP_PREP_WRITE_REQ: if (!service_state.current_characteristic) { service_state.current_characteristic = characteristic; service_state.length = 0; } if (service_state.current_characteristic == characteristic) { if (event->evt.gatts_evt.params.authorize_request.request.write.offset + event->evt.gatts_evt.params.authorize_request.request.write.len <= sizeof(buffer_buffer)) { memcpy(buffer_buffer + service_state.length, event->evt.gatts_evt.params.authorize_request.request.write.data, event->evt.gatts_evt.params.authorize_request.request.write.len); service_state.length = service_state.length + event->evt.gatts_evt.params.authorize_request.request.write.len; } } else { service_state.current_characteristic = NULL; } break; default: break; } static const ble_gatts_rw_authorize_reply_params_t reply = { .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, .params.write.gatt_status = BLE_GATT_STATUS_SUCCESS }; err_code = sd_ble_gatts_rw_authorize_reply(event->evt.gatts_evt.conn_handle, &reply); APP_ERROR_CHECK(err_code); break; } else if (event->evt.gatts_evt.params.authorize_request.request.write.handle == 0 && event->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW && service_state.current_characteristic) { if (service_state.current_characteristic->write && (service_state.current_characteristic->plain || session_isEncrypted())) { uint16_t blength = 0; if (session_writeData(buffer_buffer, service_state.length, buffer_buffer, &blength)) { service_state.current_characteristic->write(buffer_buffer, blength, service_state.current_characteristic); } } service_state.current_characteristic = NULL; static const ble_gatts_rw_authorize_reply_params_t reply = { .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, .params.write.gatt_status = BLE_GATT_STATUS_SUCCESS }; err_code = sd_ble_gatts_rw_authorize_reply(event->evt.gatts_evt.conn_handle, &reply); APP_ERROR_CHECK(err_code); } break; } case BLE_GATTS_AUTHORIZE_TYPE_READ: { const service_characteristic_t* characteristic = service_findCharacteristicByHandle(event->evt.gatts_evt.params.authorize_request.request.read.handle); if (characteristic) { if (event->evt.gatts_evt.params.authorize_request.request.read.offset == 0) { uint16_t blength = 0; uint16_t length = 0; uint8_t* buffer = NULL; if (characteristic->read && (characteristic->plain || session_isEncrypted())) { characteristic->read(&buffer, &length, characteristic); if (buffer && length) { session_readData(buffer, length, buffer_buffer, &blength); } } ble_gatts_rw_authorize_reply_params_t reply = { .type = BLE_GATTS_AUTHORIZE_TYPE_READ, .params.read = { .gatt_status = BLE_GATT_STATUS_SUCCESS, .update = 1, .offset = 0, .len = blength, .p_data = buffer_buffer } }; err_code = sd_ble_gatts_rw_authorize_reply(event->evt.gatts_evt.conn_handle, &reply); APP_ERROR_CHECK(err_code); } else { static const ble_gatts_rw_authorize_reply_params_t reply = { .type = BLE_GATTS_AUTHORIZE_TYPE_READ, .params.read = { .gatt_status = BLE_GATT_STATUS_SUCCESS, } }; err_code = sd_ble_gatts_rw_authorize_reply(event->evt.gatts_evt.conn_handle, &reply); APP_ERROR_CHECK(err_code); } break; } break; } default: break; } break; } default: break; }
/**@brief Function for the application's SoftDevice event handler. * * @param[in] p_ble_evt SoftDevice event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; NRF_LOG_INFO("Connected\r\n"); break; // BLE_GAP_EVT_CONNECTED case BLE_GAP_EVT_DISCONNECTED: err_code = bsp_indication_set(BSP_INDICATE_IDLE); APP_ERROR_CHECK(err_code); m_conn_handle = BLE_CONN_HANDLE_INVALID; NRF_LOG_INFO("Disconnected\r\n"); break; // BLE_GAP_EVT_DISCONNECTED case BLE_GAP_EVT_SEC_PARAMS_REQUEST: // Pairing not supported err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); APP_ERROR_CHECK(err_code); break; // BLE_GAP_EVT_SEC_PARAMS_REQUEST case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST: { ble_gap_data_length_params_t dl_params; // Clearing the struct will effectivly set members to @ref BLE_GAP_DATA_LENGTH_AUTO memset(&dl_params, 0, sizeof(ble_gap_data_length_params_t)); err_code = sd_ble_gap_data_length_update(p_ble_evt->evt.gap_evt.conn_handle, &dl_params, NULL); APP_ERROR_CHECK(err_code); } break; case BLE_GATTS_EVT_SYS_ATTR_MISSING: // No system attributes have been stored. err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); APP_ERROR_CHECK(err_code); break; // BLE_GATTS_EVT_SYS_ATTR_MISSING case BLE_GATTC_EVT_TIMEOUT: // Disconnect on GATT Client timeout event. err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; // BLE_GATTC_EVT_TIMEOUT case BLE_GATTS_EVT_TIMEOUT: // Disconnect on GATT Server timeout event. err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; // BLE_GATTS_EVT_TIMEOUT case BLE_EVT_USER_MEM_REQUEST: err_code = sd_ble_user_mem_reply(p_ble_evt->evt.gattc_evt.conn_handle, NULL); APP_ERROR_CHECK(err_code); break; // BLE_EVT_USER_MEM_REQUEST case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: { ble_gatts_evt_rw_authorize_request_t req; ble_gatts_rw_authorize_reply_params_t auth_reply; req = p_ble_evt->evt.gatts_evt.params.authorize_request; if (req.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID) { if ((req.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ) || (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) || (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) { if (req.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; } else { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; } auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED; err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, &auth_reply); APP_ERROR_CHECK(err_code); } } } break; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST default: // No implementation needed. break; } }
/**@brief Function for handling the Application's BLE Stack events. * * @param[in] p_ble_evt Bluetooth stack event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code = NRF_SUCCESS; //lint -save -e438 // Last value assigned to variable 'err_code' not used switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_DISCONNECTED: { NRF_LOG_PRINTF("[APP]: %s: BLE_GAP_EVT_DISCONNECTED\r\n", __func__); m_conn_handle = BLE_CONN_HANDLE_INVALID; /*check if the last connected peer had not used MITM, if so, delete its bond information*/ if (peer_to_be_deleted != PM_PEER_ID_INVALID) { ret_code_t ret_val = pm_peer_delete(peer_to_be_deleted); APP_ERROR_CHECK(ret_val); APP_LOG("Collector's bond deleted\r\n"); peer_to_be_deleted = PM_PEER_ID_INVALID; } // advertising_init(); // TODO: Check if this is correct, shouldn't be needed nrf_gpio_pin_clear(LED_1); }break;//BLE_GAP_EVT_DISCONNECTED case BLE_GAP_EVT_CONNECTED: { NRF_LOG_PRINTF("[APP]: %s: BLE_GAP_EVT_CONNECTED\r\n", __func__); peer_to_be_deleted = PM_PEER_ID_INVALID; m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; // Start Security Request timer. err_code = app_timer_start(m_sec_req_timer_id, SECURITY_REQUEST_DELAY, NULL); APP_ERROR_CHECK(err_code); }break;//BLE_GAP_EVT_CONNECTED case BLE_GATTS_EVT_TIMEOUT: NRF_LOG_PRINTF("[APP]: %s: BLE_GATTS_EVT_TIMEOUT\r\n", __func__); // Disconnect on GATT Server timeout events. err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break;//BLE_GATTS_EVT_TIMEOUT case BLE_GAP_EVT_SEC_PARAMS_REQUEST: NRF_LOG_DEBUG("BLE_GAP_EVT_SEC_PARAMS_REQUEST\r\n"); break;//BLE_GAP_EVT_SEC_PARAMS_REQUEST case BLE_GAP_EVT_PASSKEY_DISPLAY: { NRF_LOG_PRINTF("[APP]: %s: BLE_GAP_EVT_PASSKEY_DISPLAY\r\n", __func__); char passkey[PASSKEY_LENGTH+1]; memcpy(passkey,p_ble_evt->evt.gap_evt.params.passkey_display.passkey,PASSKEY_LENGTH); passkey[PASSKEY_LENGTH] = 0; // Don't send delayed Security Request if security procedure is already in progress. err_code = app_timer_stop(m_sec_req_timer_id); APP_ERROR_CHECK(err_code); NRF_LOG_PRINTF("Passkey: %s\r\n",passkey); }break;//BLE_GAP_EVT_PASSKEY_DISPLAY case BLE_EVT_USER_MEM_REQUEST: NRF_LOG_PRINTF("[APP]: %s: BLE_EVT_USER_MEM_REQUEST\r\n", __func__); err_code = sd_ble_user_mem_reply(m_conn_handle, NULL); APP_ERROR_CHECK(err_code); break;//BLE_EVT_USER_MEM_REQUEST case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: { NRF_LOG_PRINTF("[APP]: %s: BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST\r\n", __func__); ble_gatts_rw_authorize_reply_params_t auth_reply; if(p_ble_evt->evt.gatts_evt.params.authorize_request.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID) { if ((p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ) || (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) || (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) { if (p_ble_evt->evt.gatts_evt.params.authorize_request.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; } else { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; } auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED; err_code = sd_ble_gatts_rw_authorize_reply(m_conn_handle,&auth_reply); APP_ERROR_CHECK(err_code); } } }break;//BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST default: // No implementation needed. break; } }
/**@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 Function for handling the Application's BLE Stack events. * * @param[in] p_ble_evt Bluetooth stack event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: NRF_LOG_INFO("Connected\r\n"); err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; /* Disable advertising, so when disconnected it does not restart. */ advertising_disable(); break; // BLE_GAP_EVT_CONNECTED case BLE_GAP_EVT_DISCONNECTED: NRF_LOG_INFO("Disonnected\r\n"); m_conn_handle = BLE_CONN_HANDLE_INVALID; m_advertising_flag = 0; if (m_is_wl_changed) { // The whitelist has been modified, update it in the Peer Manager. err_code = pm_whitelist_set(m_whitelist_peers, m_whitelist_peer_cnt); APP_ERROR_CHECK(err_code); err_code = pm_device_identities_list_set(m_whitelist_peers, m_whitelist_peer_cnt); if (err_code != NRF_ERROR_NOT_SUPPORTED) { APP_ERROR_CHECK(err_code); } m_is_wl_changed = false; } break; // BLE_GAP_EVT_DISCONNECTED case BLE_GAP_EVT_AUTH_KEY_REQUEST: err_code = sd_ble_gap_auth_key_reply(p_ble_evt->evt.gap_evt.conn_handle, BLE_GAP_AUTH_KEY_TYPE_OOB, m_oob_auth_key.tk); APP_ERROR_CHECK(err_code); break; // BLE_GAP_EVT_AUTH_KEY_REQUEST case BLE_GAP_EVT_AUTH_STATUS: { if (p_ble_evt->evt.gap_evt.params.auth_status.auth_status == BLE_GAP_SEC_STATUS_SUCCESS) { /* Configure NFC launchapp data (requires stopping NFC tag emulation) */ err_code = nfc_t2t_emulation_stop(); APP_ERROR_CHECK(err_code); nfc_launchapp_data_set(); err_code = nfc_t2t_emulation_start(); APP_ERROR_CHECK(err_code); } }break; // BLE_GAP_EVT_AUTH_STATUS case BLE_GATTC_EVT_TIMEOUT: // Disconnect on GATT Client timeout event. NRF_LOG_DEBUG("GATT Client Timeout.\r\n"); err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; // BLE_GATTC_EVT_TIMEOUT case BLE_GATTS_EVT_TIMEOUT: // Disconnect on GATT Server timeout event. NRF_LOG_DEBUG("GATT Server Timeout.\r\n"); err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; // BLE_GATTS_EVT_TIMEOUT case BLE_EVT_USER_MEM_REQUEST: err_code = sd_ble_user_mem_reply(m_conn_handle, NULL); APP_ERROR_CHECK(err_code); break; // BLE_EVT_USER_MEM_REQUEST case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: { ble_gatts_evt_rw_authorize_request_t req; ble_gatts_rw_authorize_reply_params_t auth_reply; req = p_ble_evt->evt.gatts_evt.params.authorize_request; if (req.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID) { if ((req.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ) || (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) || (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) { if (req.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; } else { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; } auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED; err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, &auth_reply); APP_ERROR_CHECK(err_code); } } } break; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST #if (NRF_SD_BLE_API_VERSION == 3) case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: err_code = sd_ble_gatts_exchange_mtu_reply(p_ble_evt->evt.gatts_evt.conn_handle, NRF_BLE_MAX_MTU_SIZE); APP_ERROR_CHECK(err_code); break; // BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST #endif default: // No implementation needed. break; } }
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) } }
/**@brief Function for handling the Application's BLE Stack events. * * @param[in] p_ble_evt Bluetooth stack event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: NRF_LOG_INFO("Connected\r\n"); err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; break; // BLE_GAP_EVT_CONNECTED case BLE_GAP_EVT_DISCONNECTED: NRF_LOG_INFO("Disconnected, reason %d\r\n", p_ble_evt->evt.gap_evt.params.disconnected.reason); m_conn_handle = BLE_CONN_HANDLE_INVALID; break; // BLE_GAP_EVT_DISCONNECTED case BLE_GATTC_EVT_TIMEOUT: // Disconnect on GATT Client timeout event. NRF_LOG_DEBUG("GATT Client Timeout.\r\n"); err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; // BLE_GATTC_EVT_TIMEOUT case BLE_GATTS_EVT_TIMEOUT: // Disconnect on GATT Server timeout event. NRF_LOG_DEBUG("GATT Server Timeout.\r\n"); err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; // BLE_GATTS_EVT_TIMEOUT case BLE_EVT_USER_MEM_REQUEST: err_code = sd_ble_user_mem_reply(m_conn_handle, NULL); APP_ERROR_CHECK(err_code); break; // BLE_EVT_USER_MEM_REQUEST case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: { ble_gatts_evt_rw_authorize_request_t req; ble_gatts_rw_authorize_reply_params_t auth_reply; req = p_ble_evt->evt.gatts_evt.params.authorize_request; if (req.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID) { if ((req.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ) || (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) || (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) { if (req.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; } else { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; } auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED; err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, &auth_reply); APP_ERROR_CHECK(err_code); } } } break; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST default: // No implementation needed. break; } }
/**@brief Function for the application's SoftDevice event handler. * * @param[in] p_ble_evt SoftDevice event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: isConnected = true; SEGGER_RTT_WriteString(0, "\nConnected to Bluetooth Device\n"); err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; break; // BLE_GAP_EVT_CONNECTED case BLE_GAP_EVT_DISCONNECTED: isConnected = false; SEGGER_RTT_WriteString(0, "\nDisconnected from Bluetooth Device\n"); err_code = bsp_indication_set(BSP_INDICATE_IDLE); APP_ERROR_CHECK(err_code); m_conn_handle = BLE_CONN_HANDLE_INVALID; break; // BLE_GAP_EVT_DISCONNECTED case BLE_GAP_EVT_SEC_PARAMS_REQUEST: // Pairing not supported err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); APP_ERROR_CHECK(err_code); break; // BLE_GAP_EVT_SEC_PARAMS_REQUEST case BLE_GATTS_EVT_SYS_ATTR_MISSING: // No system attributes have been stored. err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); APP_ERROR_CHECK(err_code); break; // BLE_GATTS_EVT_SYS_ATTR_MISSING case BLE_GATTC_EVT_TIMEOUT: // Disconnect on GATT Client timeout event. err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; // BLE_GATTC_EVT_TIMEOUT case BLE_GATTS_EVT_TIMEOUT: // Disconnect on GATT Server timeout event. err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; // BLE_GATTS_EVT_TIMEOUT case BLE_EVT_USER_MEM_REQUEST: err_code = sd_ble_user_mem_reply(p_ble_evt->evt.gattc_evt.conn_handle, NULL); APP_ERROR_CHECK(err_code); break; // BLE_EVT_USER_MEM_REQUEST case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: { ble_gatts_evt_rw_authorize_request_t req; ble_gatts_rw_authorize_reply_params_t auth_reply; req = p_ble_evt->evt.gatts_evt.params.authorize_request; if (req.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID) { if ((req.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ) || (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) || (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) { if (req.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; } else { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; } auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED; err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, &auth_reply); APP_ERROR_CHECK(err_code); } } } break; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST #if (NRF_SD_BLE_API_VERSION == 3) case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: err_code = sd_ble_gatts_exchange_mtu_reply(p_ble_evt->evt.gatts_evt.conn_handle, NRF_BLE_MAX_MTU_SIZE); APP_ERROR_CHECK(err_code); break; // BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST #endif default: // No implementation needed. break; } }
/**@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 * p_evt_write) { ble_racp_value_t racp_request; 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, &racp_request); // Check if request is to be executed if (is_request_to_be_executed(p_cgms, &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 (racp_request.opcode == RACP_OPCODE_REPORT_RECS) { report_records_request_execute(p_cgms, &racp_request); } else if (racp_request.opcode == RACP_OPCODE_REPORT_NUM_RECS) { report_num_records_request_execute(p_cgms, &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->cgms_com_state = STATE_NO_COMM; // Respond with error code racp_response_code_send(p_cgms, 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; } } }
/**@brief Function for handling the Application's BLE Stack events. * * @param[in] p_ble_evt Bluetooth stack event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code = NRF_SUCCESS; ble_gatts_rw_authorize_reply_params_t auth_reply; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; break; case BLE_GAP_EVT_DISCONNECTED: err_code = bsp_indication_set(BSP_INDICATE_IDLE); APP_ERROR_CHECK(err_code); advertising_start(); break; case BLE_GAP_EVT_TIMEOUT: if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING) { err_code = bsp_indication_set(BSP_INDICATE_IDLE); APP_ERROR_CHECK(err_code); // enable buttons to wake-up from power off err_code = bsp_buttons_enable( (1 << WAKEUP_BUTTON_ID) |(1 << BOND_DELETE_ALL_BUTTON_ID) ); APP_ERROR_CHECK(err_code); // Go to system-off mode (this function will not return; wakeup will cause a reset). err_code = sd_power_system_off(); APP_ERROR_CHECK(err_code); } break; case BLE_GAP_EVT_PASSKEY_DISPLAY: { char passkey[PASSKEY_LENGTH+1]; memcpy(passkey,p_ble_evt->evt.gap_evt.params.passkey_display.passkey,PASSKEY_LENGTH); passkey[PASSKEY_LENGTH] = 0; // Don't send delayed Security Request if security procedure is already in progress. err_code = app_timer_stop(m_sec_req_timer_id); APP_ERROR_CHECK(err_code); printf("Passkey: %s\n",passkey); break; } case BLE_EVT_USER_MEM_REQUEST: err_code = sd_ble_user_mem_reply(m_conn_handle, NULL); APP_ERROR_CHECK(err_code); break; case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: if(p_ble_evt->evt.gatts_evt.params.authorize_request.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID) { if ((p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ) || (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) || (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) { if (p_ble_evt->evt.gatts_evt.params.authorize_request.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; } else { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; } auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED; err_code = sd_ble_gatts_rw_authorize_reply(m_conn_handle,&auth_reply); APP_ERROR_CHECK(err_code); } } break; case BLE_GAP_EVT_AUTH_STATUS: case BLE_GAP_EVT_CONN_SEC_UPDATE: break; default: // No implementation needed. break; } }
void nRF5xGattServer::hwCallback(const ble_evt_t *p_ble_evt) { GattAttribute::Handle_t handle_value; GattServerEvents::gattEvent_t eventType; const ble_gatts_evt_t *gattsEventP = &p_ble_evt->evt.gatts_evt; switch (p_ble_evt->header.evt_id) { case BLE_GATTS_EVT_WRITE: { /* There are 2 use case here: Values being updated & CCCD (indicate/notify) enabled */ /* 1.) Handle CCCD changes */ handle_value = gattsEventP->params.write.handle; int characteristicIndex = resolveCCCDHandleToCharIndex(handle_value); if ((characteristicIndex != -1) && (p_characteristics[characteristicIndex]->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY))) { uint16_t cccd_value = (gattsEventP->params.write.data[1] << 8) | gattsEventP->params.write.data[0]; /* Little Endian but M0 may be mis-aligned */ if (((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION)) || ((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) && (cccd_value & BLE_GATT_HVX_NOTIFICATION))) { eventType = GattServerEvents::GATT_EVENT_UPDATES_ENABLED; } else { eventType = GattServerEvents::GATT_EVENT_UPDATES_DISABLED; } handleEvent(eventType, p_characteristics[characteristicIndex]->getValueHandle()); return; } /* 2.) Changes to the characteristic value will be handled with other events below */ eventType = GattServerEvents::GATT_EVENT_DATA_WRITTEN; } break; case BLE_GATTS_EVT_HVC: /* Indication confirmation received */ eventType = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED; handle_value = gattsEventP->params.hvc.handle; break; #if NRF_SD_BLE_API_VERSION >= 4 // This event has been renamed in API V4+ case BLE_GATTS_EVT_HVN_TX_COMPLETE: { handleDataSentEvent(p_ble_evt->evt.gatts_evt.params.hvn_tx_complete.count); return; } #else case BLE_EVT_TX_COMPLETE: { handleDataSentEvent(p_ble_evt->evt.common_evt.params.tx_complete.count); return; } #endif case BLE_GATTS_EVT_SYS_ATTR_MISSING: sd_ble_gatts_sys_attr_set(gattsEventP->conn_handle, NULL, 0, 0); return; case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: switch (gattsEventP->params.authorize_request.type) { case BLE_GATTS_AUTHORIZE_TYPE_READ: eventType = GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ; handle_value = gattsEventP->params.authorize_request.request.read.handle; break; case BLE_GATTS_AUTHORIZE_TYPE_WRITE: eventType = GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ; handle_value = gattsEventP->params.authorize_request.request.write.handle; break; default: return; } break; case BLE_EVT_USER_MEM_REQUEST: { uint16_t conn_handle = p_ble_evt->evt.common_evt.conn_handle; // allocate a new long request for this connection // NOTE: we don't care about the result at this stage, // it is not possible to cancel the operation anyway. // If the request was not allocated then it will gracefully failled // at subsequent stages. allocateLongWriteRequest(conn_handle); sd_ble_user_mem_reply(conn_handle, NULL); return; } default: return; } int characteristicIndex = resolveValueHandleToCharIndex(handle_value); if (characteristicIndex == -1) { // filter out the case were the request is a long one, // and there is no attribute handle provided uint8_t write_op = gattsEventP->params.authorize_request.request.write.op; if (eventType != GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ || (write_op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW && write_op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) { return; } } /* Find index (charHandle) in the pool */ switch (eventType) { case GattServerEvents::GATT_EVENT_DATA_WRITTEN: { GattWriteCallbackParams cbParams = { /* .connHandle = */ gattsEventP->conn_handle, /* .handle = */ handle_value, /* .writeOp = */ static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.write.op), /* .offset = */ gattsEventP->params.write.offset, /* .len = */ gattsEventP->params.write.len, /* .data = */ gattsEventP->params.write.data }; handleDataWrittenEvent(&cbParams); break; } case GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ: { uint16_t conn_handle = gattsEventP->conn_handle; const ble_gatts_evt_write_t& input_req = gattsEventP->params.authorize_request.request.write; const uint16_t max_size = getBiggestCharacteristicSize(); // this is a long write request, handle it here. switch (input_req.op) { case BLE_GATTS_OP_PREP_WRITE_REQ: { // verify that the request is not outside of the possible range if ((input_req.offset + input_req.len) > max_size) { sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_offset_reply); releaseLongWriteRequest(conn_handle); return; } // find the write request long_write_request_t* req = findLongWriteRequest(conn_handle); if (!req) { sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply); return; } // initialize the first request by setting the offset if (req->length == 0) { req->attr_handle = input_req.handle; req->offset = input_req.offset; } else { // it should be the subsequent write if ((req->offset + req->length) != input_req.offset) { sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_offset_reply); releaseLongWriteRequest(conn_handle); return; } // it is not allowed to write multiple characteristic with the same request if (input_req.handle != req->attr_handle) { sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply); releaseLongWriteRequest(conn_handle); return; } } // start the copy of what is in input memcpy(req->data + req->length, input_req.data, input_req.len); // update the lenght of the data written req->length = req->length + input_req.len; // success, signal it to the softdevice ble_gatts_rw_authorize_reply_params_t reply = { /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, /* .params = */ { /* .write = */ { /* .gatt_status = */ BLE_GATT_STATUS_SUCCESS, /* .update = */ 1, /* .offset = */ input_req.offset, /* .len = */ input_req.len, /* .p_data = */ input_req.data } } }; sd_ble_gatts_rw_authorize_reply(conn_handle, &reply); } return; case BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL: { releaseLongWriteRequest(conn_handle); sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_succes_reply); } return; case BLE_GATTS_OP_EXEC_WRITE_REQ_NOW: { long_write_request_t* req = findLongWriteRequest(conn_handle); if (!req) { sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply); return; } GattWriteAuthCallbackParams cbParams = { /* .connHandle = */ conn_handle, /* .handle = */ req->attr_handle, /* .offset = */ req->offset, /* .len = */ req->length, /* .data = */ req->data, /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; uint16_t write_authorization = p_characteristics[characteristicIndex]->authorizeWrite(&cbParams); // the user code didn't provide the write authorization, // just leave here. if (write_authorization != AUTH_CALLBACK_REPLY_SUCCESS) { // report the status of the operation in any cases sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply); releaseLongWriteRequest(conn_handle); return; } // FIXME can't use ::write here, this function doesn't take the offset into account ... ble_gatts_value_t value = { /* .len = */ req->length, /* .offset = */ req->offset, /* .p_value = */ req->data }; uint32_t update_err = sd_ble_gatts_value_set(conn_handle, req->attr_handle, &value); if (update_err) { sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply); releaseLongWriteRequest(conn_handle); return; } sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_succes_reply); GattWriteCallbackParams writeParams = { /* .connHandle = */ conn_handle, /* .handle = */ req->attr_handle, /* .writeOp = */ static_cast<GattWriteCallbackParams::WriteOp_t>(input_req.op), /* .offset = */ req->offset, /* .len = */ req->length, /* .data = */ req->data, }; handleDataWrittenEvent(&writeParams); releaseLongWriteRequest(conn_handle); } return; } GattWriteAuthCallbackParams cbParams = { /* .connHandle = */ gattsEventP->conn_handle, /* .handle = */ handle_value, /* .offset = */ gattsEventP->params.authorize_request.request.write.offset, /* .len = */ gattsEventP->params.authorize_request.request.write.len, /* .data = */ gattsEventP->params.authorize_request.request.write.data, /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; ble_gatts_rw_authorize_reply_params_t reply = { /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_WRITE, /* .params = */ { /* .write = */ { /* .gatt_status = */ p_characteristics[characteristicIndex]->authorizeWrite(&cbParams), /* .update = */ 1, /* .offset = */ cbParams.offset, /* .len = */ cbParams.len, /* .p_data = */ cbParams.data } } }; if (reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS) { reply.params.write.update = 0; } sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); /* * If write-authorization is enabled for a characteristic, * AUTHORIZATION_REQ event (if replied with true) is *not* * followed by another DATA_WRITTEN event; so we still need * to invoke handleDataWritten(), much the same as we would * have done if write-authorization had not been enabled. */ if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) { GattWriteCallbackParams cbParams = { /* .connHandle = */ gattsEventP->conn_handle, /* .handle = */ handle_value, /* .writeOp = */ static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.authorize_request.request.write.op), /* .offset = */ gattsEventP->params.authorize_request.request.write.offset, /* .len = */ gattsEventP->params.authorize_request.request.write.len, /* .data = */ gattsEventP->params.authorize_request.request.write.data, }; handleDataWrittenEvent(&cbParams); } break; } case GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ: { GattReadAuthCallbackParams cbParams = { /* .connHandle = */ gattsEventP->conn_handle, /* .handle = */ handle_value, /* .offset = */ gattsEventP->params.authorize_request.request.read.offset, /* .len = */ 0, /* .data = */ NULL, /* .authorizationReply = */ AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member * set to AUTH_CALLBACK_REPLY_SUCCESS if the client * request is to proceed. */ }; ble_gatts_rw_authorize_reply_params_t reply = { /* .type = */ BLE_GATTS_AUTHORIZE_TYPE_READ, /* .params = */ { /* .read = */ { /* .gatt_status = */ p_characteristics[characteristicIndex]->authorizeRead(&cbParams) } } }; if (cbParams.authorizationReply == BLE_GATT_STATUS_SUCCESS) { if (cbParams.data != NULL) { reply.params.read.update = 1; reply.params.read.offset = cbParams.offset; reply.params.read.len = cbParams.len; reply.params.read.p_data = cbParams.data; } } sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); break; } default: handleEvent(eventType, handle_value); break; } }
/**@brief Function for handling the Application's BLE Stack events. * * @param[in] p_ble_evt Bluetooth stack event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code = NRF_SUCCESS; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_DISCONNECTED: err_code = bsp_indication_set(BSP_INDICATE_IDLE); APP_ERROR_CHECK(err_code); break;//BLE_GAP_EVT_DISCONNECTED case BLE_GAP_EVT_CONNECTED: err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); err_code = ble_db_discovery_start(&m_ble_db_discovery, p_ble_evt->evt.gap_evt.conn_handle); APP_ERROR_CHECK(err_code); break;//BLE_GAP_EVT_CONNECTED case BLE_GATTC_EVT_TIMEOUT: /* fall through */ case BLE_GATTS_EVT_TIMEOUT: // Disconnect on GATT Server and Client timeout events. err_code = sd_ble_gap_disconnect(m_ans_c.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break;//BLE_GATTC_EVT_TIMEOUT and BLE_GATTS_EVT_TIMEOUT case BLE_EVT_USER_MEM_REQUEST: err_code = sd_ble_user_mem_reply(m_ans_c.conn_handle, NULL); APP_ERROR_CHECK(err_code); break;//BLE_EVT_USER_MEM_REQUEST case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: { ble_gatts_rw_authorize_reply_params_t auth_reply; if(p_ble_evt->evt.gatts_evt.params.authorize_request.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID) { if ((p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ) || (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) || (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) { if (p_ble_evt->evt.gatts_evt.params.authorize_request.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; } else { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; } auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED; err_code = sd_ble_gatts_rw_authorize_reply(m_ans_c.conn_handle,&auth_reply); APP_ERROR_CHECK(err_code); } } }break;//BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST default: // No implementation needed. break; } }