/* radio callback, executed in STACK_LOW */ static void tx_cb(uint8_t* data) { rbc_mesh_event_t tx_event; mesh_adv_data_t* p_adv_data = mesh_packet_adv_data_get((mesh_packet_t*) data); bool doing_tx_event = false; if (p_adv_data != NULL && vh_tx_event_flag_get(p_adv_data->handle, &doing_tx_event) == NRF_SUCCESS && doing_tx_event ) { tx_event.event_type = RBC_MESH_EVENT_TYPE_TX; tx_event.value_handle = p_adv_data->handle; tx_event.data = p_adv_data->data; tx_event.data_len = p_adv_data->adv_data_length - MESH_PACKET_ADV_OVERHEAD; tx_event.version_delta = 0; APP_ERROR_CHECK(rbc_mesh_event_push(&tx_event)); #if RBC_MESH_SERIAL mesh_aci_rbc_event_handler(&tx_event); #endif } mesh_packet_ref_count_dec((mesh_packet_t*) data); /* radio ref removed (pushed in tc_tx) */ vh_order_update(timer_get_timestamp()); /* tell the vh, so that it can push more updates */ }
void mesh_gatt_sd_ble_event_handle(ble_evt_t* p_ble_evt) { switch (p_ble_evt->header.evt_id) { case BLE_GATTS_EVT_WRITE: { if (p_ble_evt->evt.gatts_evt.params.write.handle == m_mesh_service.ble_val_char_handles.value_handle) { mesh_gatt_evt_t* p_gatt_evt = (mesh_gatt_evt_t*) p_ble_evt->evt.gatts_evt.params.write.data; switch ((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode) { case MESH_GATT_EVT_OPCODE_DATA: { if (p_gatt_evt->param.data_update.handle == RBC_MESH_INVALID_HANDLE) { mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE); break; } vh_data_status_t vh_data_status = vh_local_update( p_gatt_evt->param.data_update.handle, p_gatt_evt->param.data_update.data, p_gatt_evt->param.data_update.data_len); rbc_mesh_event_t mesh_evt; mesh_evt.data = p_gatt_evt->param.data_update.data; mesh_evt.data_len = p_gatt_evt->param.data_update.data_len; mesh_evt.value_handle = p_gatt_evt->param.data_update.handle; mesh_evt.version_delta = 1; bool send_event = true; switch (vh_data_status) { case VH_DATA_STATUS_CONFLICTING: mesh_evt.event_type = RBC_MESH_EVENT_TYPE_CONFLICTING_VAL; break; case VH_DATA_STATUS_NEW: mesh_evt.event_type = RBC_MESH_EVENT_TYPE_NEW_VAL; break; case VH_DATA_STATUS_UPDATED: mesh_evt.event_type = RBC_MESH_EVENT_TYPE_UPDATE_VAL; break; default: mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_BUSY); send_event = false; } if (send_event) { APP_ERROR_CHECK(rbc_mesh_event_push(&mesh_evt)); mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_SUCCESS); } } break; case MESH_GATT_EVT_OPCODE_FLAG_SET: switch ((mesh_gatt_evt_flag_t) p_gatt_evt->param.flag_update.flag) { case MESH_GATT_EVT_FLAG_PERSISTENT: if (vh_value_persistence_set( p_gatt_evt->param.flag_update.handle, !!(p_gatt_evt->param.flag_update.value)) != NRF_SUCCESS) { mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE); break; } mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_SUCCESS); break; case MESH_GATT_EVT_FLAG_DO_TX: if (p_gatt_evt->param.flag_update.value) { if (vh_value_enable( p_gatt_evt->param.flag_update.handle) != NRF_SUCCESS) { mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE); break; } mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_SUCCESS); } else { if (vh_value_disable( p_gatt_evt->param.flag_update.handle) != NRF_SUCCESS) { mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE); break; } mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_SUCCESS); } break; default: mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_UNKNOWN_FLAG); } break; case MESH_GATT_EVT_OPCODE_FLAG_REQ: switch ((mesh_gatt_evt_flag_t) p_gatt_evt->param.flag_update.flag) { case MESH_GATT_EVT_FLAG_PERSISTENT: { if (p_gatt_evt->param.flag_update.handle == RBC_MESH_INVALID_HANDLE) { mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE); break; } bool is_persistent = false; if (vh_value_persistence_get( p_gatt_evt->param.flag_update.handle, &is_persistent) != NRF_SUCCESS) { mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_NOT_FOUND); break; } mesh_gatt_evt_t rsp_evt; rsp_evt.opcode = MESH_GATT_EVT_OPCODE_FLAG_RSP; rsp_evt.param.flag_update.handle = p_gatt_evt->param.flag_update.handle; rsp_evt.param.flag_update.flag = p_gatt_evt->param.flag_update.flag; rsp_evt.param.flag_update.value = (uint8_t) is_persistent; mesh_gatt_evt_push(&rsp_evt); } break; case MESH_GATT_EVT_FLAG_DO_TX: { bool is_enabled; if (vh_value_is_enabled( p_gatt_evt->param.flag_update.handle, &is_enabled) != NRF_SUCCESS) { mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE); break; } mesh_gatt_evt_t rsp_evt; rsp_evt.opcode = MESH_GATT_EVT_OPCODE_FLAG_RSP; rsp_evt.param.flag_update.handle = p_gatt_evt->param.flag_update.handle; rsp_evt.param.flag_update.flag = p_gatt_evt->param.flag_update.flag; rsp_evt.param.flag_update.value = (uint8_t) is_enabled; mesh_gatt_evt_push(&rsp_evt); } break; default: mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_UNKNOWN_FLAG); } break; default: mesh_gatt_cmd_rsp_push( (mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_OPCODE); } } else if (p_ble_evt->evt.gatts_evt.params.write.handle == m_mesh_service.ble_md_char_handles.value_handle) { mesh_metadata_char_t* p_md = (mesh_metadata_char_t*) p_ble_evt->evt.gatts_evt.params.write.data; tc_radio_params_set(p_md->mesh_access_addr, p_md->mesh_channel); vh_min_interval_set(p_md->mesh_interval_min_ms); } else if (p_ble_evt->evt.gatts_evt.params.write.handle == m_mesh_service.ble_val_char_handles.cccd_handle) { m_mesh_service.notification_enabled = (p_ble_evt->evt.gatts_evt.params.write.data[0] != 0); } break; } case BLE_GAP_EVT_CONNECTED: { m_active_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; break; } case BLE_GAP_EVT_DISCONNECTED: { m_active_conn_handle = CONN_HANDLE_INVALID; // clear notification buffer on disconnect notifactionsPending = false; nb_clear(); break; } case BLE_EVT_TX_COMPLETE: { if (notifactionsPending) { resume_notifications(); } break; } } }
void mesh_gatt_sd_ble_event_handle(ble_evt_t* p_ble_evt) { if (p_ble_evt->header.evt_id == BLE_GATTS_EVT_WRITE) { if (p_ble_evt->evt.gatts_evt.params.write.handle == m_mesh_service.ble_val_char_handles.value_handle) { mesh_gatt_evt_t* p_gatt_evt = (mesh_gatt_evt_t*) p_ble_evt->evt.gatts_evt.params.write.data; switch ((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode) { case MESH_GATT_EVT_OPCODE_DATA: { if (p_gatt_evt->param.data_update.handle == RBC_MESH_INVALID_HANDLE) { mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE); break; } uint32_t error_code = vh_local_update( p_gatt_evt->param.data_update.handle, p_gatt_evt->param.data_update.data, p_gatt_evt->param.data_update.data_len); if (error_code == NRF_SUCCESS) { rbc_mesh_event_t mesh_evt; mesh_evt.type = RBC_MESH_EVENT_TYPE_UPDATE_VAL; mesh_evt.params.rx.p_data = p_gatt_evt->param.data_update.data; mesh_evt.params.rx.data_len = p_gatt_evt->param.data_update.data_len; mesh_evt.params.rx.value_handle = p_gatt_evt->param.data_update.handle; mesh_evt.params.rx.version_delta = 1; mesh_evt.params.rx.timestamp_us = timer_now(); if (rbc_mesh_event_push(&mesh_evt) != NRF_SUCCESS) { mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_BUSY); } else { mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_SUCCESS); } } else { mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_BUSY); } } break; case MESH_GATT_EVT_OPCODE_FLAG_SET: switch ((mesh_gatt_evt_flag_t) p_gatt_evt->param.flag_update.flag) { case MESH_GATT_EVT_FLAG_PERSISTENT: if (vh_value_persistence_set(p_gatt_evt->param.flag_update.handle, !!(p_gatt_evt->param.flag_update.value)) != NRF_SUCCESS) { mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE); break; } mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_SUCCESS); break; case MESH_GATT_EVT_FLAG_DO_TX: if (p_gatt_evt->param.flag_update.value) { if (vh_value_enable(p_gatt_evt->param.flag_update.handle) != NRF_SUCCESS) { mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE); break; } mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_SUCCESS); } else { if (vh_value_disable(p_gatt_evt->param.flag_update.handle) != NRF_SUCCESS) { mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE); break; } mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_SUCCESS); } break; default: mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_UNKNOWN_FLAG); } break; case MESH_GATT_EVT_OPCODE_FLAG_REQ: switch ((mesh_gatt_evt_flag_t) p_gatt_evt->param.flag_update.flag) { case MESH_GATT_EVT_FLAG_PERSISTENT: { if (p_gatt_evt->param.flag_update.handle == RBC_MESH_INVALID_HANDLE) { mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE); break; } bool is_persistent = false; if (vh_value_persistence_get(p_gatt_evt->param.flag_update.handle, &is_persistent) != NRF_SUCCESS) { mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_NOT_FOUND); break; } mesh_gatt_evt_t rsp_evt; rsp_evt.opcode = MESH_GATT_EVT_OPCODE_FLAG_RSP; rsp_evt.param.flag_update.handle = p_gatt_evt->param.flag_update.handle; rsp_evt.param.flag_update.flag = p_gatt_evt->param.flag_update.flag; rsp_evt.param.flag_update.value = (uint8_t) is_persistent; mesh_gatt_evt_push(&rsp_evt); } break; case MESH_GATT_EVT_FLAG_DO_TX: { bool is_enabled; if (vh_value_is_enabled(p_gatt_evt->param.flag_update.handle, &is_enabled) != NRF_SUCCESS) { mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_HANDLE); break; } mesh_gatt_evt_t rsp_evt; rsp_evt.opcode = MESH_GATT_EVT_OPCODE_FLAG_RSP; rsp_evt.param.flag_update.handle = p_gatt_evt->param.flag_update.handle; rsp_evt.param.flag_update.flag = p_gatt_evt->param.flag_update.flag; rsp_evt.param.flag_update.value = (uint8_t) is_enabled; mesh_gatt_evt_push(&rsp_evt); } break; default: mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_UNKNOWN_FLAG); } break; default: mesh_gatt_cmd_rsp_push((mesh_gatt_evt_opcode_t) p_gatt_evt->opcode, MESH_GATT_RESULT_ERROR_INVALID_OPCODE); } } else if (p_ble_evt->evt.gatts_evt.params.write.handle == m_mesh_service.ble_md_char_handles.value_handle) { mesh_metadata_char_t* p_md = (mesh_metadata_char_t*) p_ble_evt->evt.gatts_evt.params.write.data; tc_radio_params_set(p_md->mesh_access_addr, p_md->mesh_channel); vh_min_interval_set(p_md->mesh_interval_min_ms); } else if (p_ble_evt->evt.gatts_evt.params.write.handle == m_mesh_service.ble_val_char_handles.cccd_handle) { m_mesh_service.notification_enabled = (p_ble_evt->evt.gatts_evt.params.write.data[0] != 0); } } else if (p_ble_evt->header.evt_id == BLE_GAP_EVT_CONNECTED) { m_active_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; } else if (p_ble_evt->header.evt_id == BLE_GAP_EVT_DISCONNECTED) { m_active_conn_handle = CONN_HANDLE_INVALID; } }
static void mesh_app_packet_handle(mesh_adv_data_t* p_mesh_adv_data, uint64_t timestamp) { // LOGi("_1"); int16_t delta = vh_get_version_delta(p_mesh_adv_data->handle, p_mesh_adv_data->version); vh_data_status_t data_status = vh_rx_register(p_mesh_adv_data, timestamp); /* prepare app event */ rbc_mesh_event_t evt; evt.version_delta = delta; switch (data_status) { case VH_DATA_STATUS_NEW: /* notify application */ prepare_event(&evt, p_mesh_adv_data); evt.event_type = RBC_MESH_EVENT_TYPE_NEW_VAL; if (rbc_mesh_event_push(&evt) == NRF_SUCCESS) { mesh_gatt_value_set(p_mesh_adv_data->handle, p_mesh_adv_data->data, p_mesh_adv_data->adv_data_length - MESH_PACKET_ADV_OVERHEAD); } #ifdef RBC_MESH_SERIAL mesh_aci_rbc_event_handler(&evt); #endif break; case VH_DATA_STATUS_UPDATED: /* notify application */ prepare_event(&evt, p_mesh_adv_data); evt.event_type = RBC_MESH_EVENT_TYPE_UPDATE_VAL; if (rbc_mesh_event_push(&evt) == NRF_SUCCESS) { mesh_gatt_value_set(p_mesh_adv_data->handle, p_mesh_adv_data->data, p_mesh_adv_data->adv_data_length - MESH_PACKET_ADV_OVERHEAD); } #ifdef RBC_MESH_SERIAL mesh_aci_rbc_event_handler(&evt); #endif break; case VH_DATA_STATUS_OLD: /* do nothing */ break; case VH_DATA_STATUS_SAME: /* do nothing */ break; case VH_DATA_STATUS_CONFLICTING: prepare_event(&evt, p_mesh_adv_data); evt.event_type = RBC_MESH_EVENT_TYPE_CONFLICTING_VAL; rbc_mesh_event_push(&evt); /* ignore error - will be a normal packet drop */ #ifdef RBC_MESH_SERIAL mesh_aci_rbc_event_handler(&evt); #endif break; case VH_DATA_STATUS_UNKNOWN: break; } }
uint32_t dfu_evt_handler(bl_evt_t* p_evt) { __LOG("BL EVT (0x%x)\n", p_evt->type); switch (p_evt->type) { case BL_EVT_TYPE_ECHO: __LOG("\tEcho: %s\n", p_evt->params.echo.str); break; case BL_EVT_TYPE_DFU_ABORT: { __LOG("\tAbort event. Reason: 0x%x\n", p_evt->params.dfu.abort.reason); rbc_mesh_event_t evt; evt.type = RBC_MESH_EVENT_TYPE_DFU_END; evt.params.dfu.end.dfu_type = m_transfer_state.type; evt.params.dfu.end.role = m_transfer_state.role; evt.params.dfu.end.fwid = m_transfer_state.fwid; evt.params.dfu.end.end_reason = p_evt->params.dfu.abort.reason; memset(&m_transfer_state, 0, sizeof(dfu_transfer_state_t)); rbc_mesh_event_push(&evt); } break; case BL_EVT_TYPE_DFU_NEW_FW: { __LOG("\tNew firmware!\n"); rbc_mesh_event_t evt; evt.type = RBC_MESH_EVENT_TYPE_DFU_NEW_FW_AVAILABLE; evt.params.dfu.new_fw.dfu_type = p_evt->params.dfu.new_fw.fw_type; evt.params.dfu.new_fw.new_fwid = p_evt->params.dfu.new_fw.fwid; if (get_curr_fwid( p_evt->params.dfu.new_fw.fw_type, &evt.params.dfu.new_fw.current_fwid) == NRF_SUCCESS) { rbc_mesh_event_push(&evt); } } break; case BL_EVT_TYPE_DFU_REQ: { __LOG("\tSource/relay request!\n"); /* Forward to application */ rbc_mesh_event_t evt; switch (p_evt->params.dfu.req.role) { case DFU_ROLE_RELAY: evt.type = RBC_MESH_EVENT_TYPE_DFU_RELAY_REQ; evt.params.dfu.relay_req.dfu_type = p_evt->params.dfu.req.dfu_type; evt.params.dfu.relay_req.fwid = p_evt->params.dfu.req.fwid; evt.params.dfu.relay_req.authority = p_evt->params.dfu.req.dfu_type; break; case DFU_ROLE_SOURCE: evt.type = RBC_MESH_EVENT_TYPE_DFU_SOURCE_REQ; evt.params.dfu.source_req.dfu_type = p_evt->params.dfu.req.dfu_type; break; default: return NRF_ERROR_NOT_SUPPORTED; } rbc_mesh_event_push(&evt); } break; case BL_EVT_TYPE_DFU_START: { __LOG("\tDFU start\n"); if (p_evt->params.dfu.start.role == DFU_ROLE_TARGET) { m_transfer_state.state = DFU_STATE_TARGET; } else if (p_evt->params.dfu.start.role == DFU_ROLE_RELAY) { m_transfer_state.state = DFU_STATE_RELAY; } rbc_mesh_event_t evt; evt.type = RBC_MESH_EVENT_TYPE_DFU_START; evt.params.dfu.start.dfu_type = p_evt->params.dfu.start.dfu_type; evt.params.dfu.start.fwid = p_evt->params.dfu.start.fwid; evt.params.dfu.start.role = p_evt->params.dfu.start.role; rbc_mesh_event_push(&evt); m_timer_evt.cb = abort_timeout; return timer_sch_reschedule(&m_timer_evt, timer_now() + TIMER_START_TIMEOUT); } case BL_EVT_TYPE_DFU_DATA_SEGMENT_RX: m_transfer_state.data_progress = (uint8_t) ( ((uint32_t) p_evt->params.dfu.data_segment.received_segment * 100) / ((uint32_t) p_evt->params.dfu.data_segment.total_segments)); m_timer_evt.cb = abort_timeout; return timer_sch_reschedule(&m_timer_evt, timer_now() + TIMER_DATA_TIMEOUT); case BL_EVT_TYPE_DFU_END: { __LOG("\tDFU END!\n"); rbc_mesh_event_t evt; evt.type = RBC_MESH_EVENT_TYPE_DFU_END; evt.params.dfu.end.dfu_type = p_evt->params.dfu.end.dfu_type; evt.params.dfu.end.fwid = p_evt->params.dfu.end.fwid; evt.params.dfu.end.end_reason = DFU_END_SUCCESS; evt.params.dfu.end.role = p_evt->params.dfu.end.role; rbc_mesh_event_push(&evt); timer_sch_abort(&m_timer_evt); } break; case BL_EVT_TYPE_BANK_AVAILABLE: { __LOG("\tDFU BANK AVAILABLE\n"); rbc_mesh_event_t evt; evt.type = RBC_MESH_EVENT_TYPE_DFU_BANK_AVAILABLE; evt.params.dfu.bank.dfu_type = p_evt->params.bank_available.bank_dfu_type; evt.params.dfu.bank.fwid = p_evt->params.bank_available.bank_fwid; evt.params.dfu.bank.is_signed = p_evt->params.bank_available.is_signed; evt.params.dfu.bank.p_start_addr = p_evt->params.bank_available.p_bank_addr; rbc_mesh_event_push(&evt); } break; case BL_EVT_TYPE_FLASH_ERASE: { if (p_evt->params.flash.erase.start_addr & (NRF_FICR->CODEPAGESIZE - 1)) { return NRF_ERROR_INVALID_ADDR; } if (p_evt->params.flash.erase.length & (NRF_FICR->CODEPAGESIZE - 1)) { return NRF_ERROR_INVALID_LENGTH; } uint32_t error_code = mesh_flash_op_push(FLASH_OP_TYPE_ERASE, &p_evt->params.flash); if (error_code == NRF_SUCCESS) { __LOG("\tErase flash at: 0x%x (length %d)\n", p_evt->params.flash.erase.start_addr, p_evt->params.flash.erase.length); } return error_code; } case BL_EVT_TYPE_FLASH_WRITE: { if (!IS_WORD_ALIGNED(p_evt->params.flash.write.start_addr)) { return NRF_ERROR_INVALID_ADDR; } if (!IS_WORD_ALIGNED(p_evt->params.flash.write.length)) { return NRF_ERROR_INVALID_LENGTH; } uint32_t error_code = mesh_flash_op_push(FLASH_OP_TYPE_WRITE, &p_evt->params.flash); if (error_code == NRF_SUCCESS) { __LOG("\tWrite flash at: 0x%x (length %d)\n", p_evt->params.flash.write.start_addr, p_evt->params.flash.write.length); } return error_code; } case BL_EVT_TYPE_TX_RADIO: __LOG("\tRADIO TX! SLOT %d, count %d, interval: %s, handle: %x\n", p_evt->params.tx.radio.tx_slot, p_evt->params.tx.radio.tx_count, p_evt->params.tx.radio.interval_type == BL_RADIO_INTERVAL_TYPE_EXPONENTIAL ? "exponential" : "periodic", p_evt->params.tx.radio.p_dfu_packet->packet_type ); if (m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet) { mesh_packet_ref_count_dec(m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet); m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet = NULL; } if (mesh_packet_acquire(&m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet)) { uint32_t time_now = timer_now(); /* build packet */ mesh_packet_set_local_addr(m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet); m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->header.type = BLE_PACKET_TYPE_ADV_NONCONN_IND; m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->header.length = DFU_PACKET_OVERHEAD + p_evt->params.tx.radio.length; ((ble_ad_t*) m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->payload)->adv_data_type = MESH_ADV_DATA_TYPE; ((ble_ad_t*) m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->payload)->data[0] = (MESH_UUID & 0xFF); ((ble_ad_t*) m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->payload)->data[1] = (MESH_UUID >> 8) & 0xFF; ((ble_ad_t*) m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->payload)->adv_data_length = DFU_PACKET_ADV_OVERHEAD + p_evt->params.tx.radio.length; memcpy(&m_tx_slots[p_evt->params.tx.radio.tx_slot].p_packet->payload[4], p_evt->params.tx.radio.p_dfu_packet, p_evt->params.tx.radio.length); /* fill other fields in the TX slot. */ m_tx_slots[p_evt->params.tx.radio.tx_slot].interval_type = p_evt->params.tx.radio.interval_type; m_tx_slots[p_evt->params.tx.radio.tx_slot].repeats = p_evt->params.tx.radio.tx_count; m_tx_slots[p_evt->params.tx.radio.tx_slot].tx_count = 0; m_tx_slots[p_evt->params.tx.radio.tx_slot].order_time = time_now + DFU_TX_TIMER_MARGIN_US + (rand_prng_get(&m_prng) & (DFU_TX_START_DELAY_MASK_US)); /* Fire away */ if (!m_tx_scheduled || TIMER_DIFF(m_tx_slots[p_evt->params.tx.radio.tx_slot].order_time, time_now) < TIMER_DIFF(m_tx_timer_evt.timestamp, time_now)) { m_tx_scheduled = true; timer_sch_reschedule(&m_tx_timer_evt, m_tx_slots[p_evt->params.tx.radio.tx_slot].order_time); } } else { return NRF_ERROR_NO_MEM;