示例#1
0
/* 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 */
}
示例#2
0
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;
    }
}
示例#4
0
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;
    }
}
示例#5
0
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;