/**@brief Function for processing start data written by the peer to the DFU Packet * Characteristic. * * @param[in] p_dfu DFU Service Structure. * @param[in] p_evt Pointer to the event received from the BLE stack. */ static void start_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; // Verify that the data is exactly four bytes (one word) long. if (p_evt->evt.ble_dfu_pkt_write.len != sizeof(uint32_t)) { err_code = ble_dfu_response_send(p_dfu, BLE_DFU_START_PROCEDURE, BLE_DFU_RESP_VAL_NOT_SUPPORTED); APP_ERROR_CHECK(err_code); } else { // Extract the size of from the DFU Packet Characteristic. uint32_t image_size = uint32_decode(p_evt->evt.ble_dfu_pkt_write.p_data); err_code = dfu_image_size_set(image_size); // Translate the err_code returned by the above function to DFU Response Value. ble_dfu_resp_val_t resp_val; resp_val = nrf_error_to_dfu_resp_val(err_code, BLE_DFU_START_PROCEDURE); err_code = ble_dfu_response_send(p_dfu, BLE_DFU_START_PROCEDURE, resp_val); APP_ERROR_CHECK(err_code); } }
/**@brief Function for handling the callback events from the dfu module. * Callbacks are expected when \ref dfu_data_pkt_handle has been executed. * * @param[in] packet Packet type for which this callback is related. * @param[in] result Operation result code. NRF_SUCCESS when a queued operation was successful. * @param[in] p_data Pointer to the data to which the operation is related. */ static void dfu_cb_handler(uint32_t packet, uint32_t result, uint8_t * p_data) { switch (packet) { ble_dfu_resp_val_t resp_val; uint32_t err_code; case DATA_PACKET: if (result != NRF_SUCCESS) { // Disconnect from peer. if (IS_CONNECTED()) { err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); } } else { err_code = hci_mem_pool_rx_consume(p_data); APP_ERROR_CHECK(err_code); // If the callback matches final data packet received then the peer is notified. if (mp_final_packet == p_data) { // Notify the DFU Controller about the success of the procedure. err_code = ble_dfu_response_send(&m_dfu, BLE_DFU_RECEIVE_APP_PROCEDURE, BLE_DFU_RESP_VAL_SUCCESS); APP_ERROR_CHECK(err_code); } } break; case START_PACKET: // Translate the err_code returned by the above function to DFU Response Value. resp_val = nrf_err_code_translate(result, BLE_DFU_START_PROCEDURE); err_code = ble_dfu_response_send(&m_dfu, BLE_DFU_START_PROCEDURE, resp_val); APP_ERROR_CHECK(err_code); break; default: // ignore. break; } }
void dfu_app_on_dfu_evt(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { switch (p_evt->ble_dfu_evt_type) { case BLE_DFU_START: // Starting the bootloader - will cause reset. bootloader_start(); break; case BLE_DFU_VALIDATE: case BLE_DFU_ACTIVATE_N_RESET: case BLE_DFU_SYS_RESET: case BLE_DFU_RECEIVE_INIT_DATA: case BLE_DFU_RECEIVE_APP_DATA: case BLE_DFU_PACKET_WRITE: case BLE_DFU_PKT_RCPT_NOTIF_ENABLED: case BLE_DFU_PKT_RCPT_NOTIF_DISABLED: case BLE_DFU_BYTES_RECEIVED_SEND: default: { // Unsupported event received from DFU Service. // Send back BLE_DFU_RESP_VAL_NOT_SUPPORTED message to peer. uint32_t err_code = ble_dfu_response_send(p_dfu, BLE_DFU_START_PROCEDURE, BLE_DFU_RESP_VAL_NOT_SUPPORTED); APP_ERROR_CHECK(err_code); } break; } }
/**@brief Function for notifying a DFU Controller about error conditions in the DFU module. * This function also ensures that an error is translated from nrf_errors to DFU Response * Value. * * @param[in] p_dfu DFU Service Structure. * @param[in] err_code Nrf error code that should be translated and send to the DFU Controller. */ static void dfu_error_notify(ble_dfu_t * p_dfu, uint32_t err_code) { // An error has occurred. Notify the DFU Controller about this error condition. // Translate the err_code returned to DFU Response Value. ble_dfu_resp_val_t resp_val; resp_val = nrf_err_code_translate(err_code, BLE_DFU_RECEIVE_APP_PROCEDURE); err_code = ble_dfu_response_send(p_dfu, BLE_DFU_RECEIVE_APP_PROCEDURE, resp_val); APP_ERROR_CHECK(err_code); }
/**@brief Function for processing initialization data written by the peer to the DFU Packet * Characteristic. * * @param[in] p_dfu DFU Service Structure. * @param[in] p_evt Pointer to the event received from the BLE stack. */ static void init_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; uint8_t num_of_padding_bytes = 0; dfu_update_packet_t dfu_pkt; dfu_pkt.packet_type = INIT_PACKET; dfu_pkt.p_data_packet = (uint32_t *) p_evt->evt.ble_dfu_pkt_write.p_data; // The DFU module accepts the dfu_pkt.packet_length to be in 'number of words'. And so if the // received data does not have a size which is a multiple of four, it should be padded with // zeros and the packet_length should be incremented accordingly before calling // dfu_init_pkt_handle. if ((p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1)) != 0) { // Find out the number of bytes to be padded. num_of_padding_bytes = sizeof(uint32_t) - (p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1)); uint8_t i; for (i = 0; i < num_of_padding_bytes; i++) { dfu_pkt.p_data_packet[p_evt->evt.ble_dfu_pkt_write.len + i] = 0; } } dfu_pkt.packet_length = (p_evt->evt.ble_dfu_pkt_write.len + num_of_padding_bytes) / sizeof(uint32_t); err_code = dfu_init_pkt_handle(&dfu_pkt); // Translate the err_code returned by the above function to DFU Response Value. ble_dfu_resp_val_t resp_val; resp_val = nrf_error_to_dfu_resp_val(err_code, BLE_DFU_INIT_PROCEDURE); err_code = ble_dfu_response_send(p_dfu, BLE_DFU_INIT_PROCEDURE, resp_val); APP_ERROR_CHECK(err_code); }
void dfu_app_on_dfu_evt(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { switch (p_evt->ble_dfu_evt_type) { case BLE_DFU_START: // Starting the bootloader - will cause reset. bootloader_start(p_dfu->conn_handle); break; default: { // Unsupported event received from DFU Service. // Send back BLE_DFU_RESP_VAL_NOT_SUPPORTED message to peer. uint32_t err_code = ble_dfu_response_send(p_dfu, BLE_DFU_START_PROCEDURE, BLE_DFU_RESP_VAL_NOT_SUPPORTED); APP_ERROR_CHECK(err_code); } break; } }
/**@brief Function for handling the callback events from the dfu module. * Callbacks are expected when \ref dfu_data_pkt_handle has been executed. * * @param[in] packet Packet type for which this callback is related. * @param[in] result Operation result code. NRF_SUCCESS when a queued operation was successful. * @param[in] p_data Pointer to the data to which the operation is related. */ static void dfu_cb_handler(uint32_t packet, uint32_t result, uint8_t * p_data) { switch (packet) { ble_dfu_resp_val_t resp_val; uint32_t err_code; case DATA_PACKET: if (result != NRF_SUCCESS) { // Disconnect from peer. if (IS_CONNECTED()) { err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); } } else { err_code = hci_mem_pool_rx_consume(p_data); APP_ERROR_CHECK(err_code); } break; case START_PACKET: // Translate the err_code returned by the above function to DFU Response Value. resp_val = nrf_err_code_translate(result, BLE_DFU_START_PROCEDURE); err_code = ble_dfu_response_send(&m_dfu, BLE_DFU_START_PROCEDURE, resp_val); APP_ERROR_CHECK(err_code); break; default: // ignore. break; } }
/**@brief Function for the Device Firmware Update Service event handler. * * @details This function will be called for all Device Firmware Update Service events which * are passed to the application. * * @param[in] p_dfu Device Firmware Update Service structure. * @param[in] p_evt Event received from the Device Firmware Update Service. */ static void on_dfu_evt(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; switch (p_evt->ble_dfu_evt_type) { case BLE_DFU_VALIDATE: err_code = dfu_image_validate(); // Translate the err_code returned by the above function to DFU Response Value. ble_dfu_resp_val_t resp_val; resp_val = nrf_err_code_translate(err_code, BLE_DFU_VALIDATE_PROCEDURE); err_code = ble_dfu_response_send(p_dfu, BLE_DFU_VALIDATE_PROCEDURE, resp_val); APP_ERROR_CHECK(err_code); break; case BLE_DFU_ACTIVATE_N_RESET: err_code = dfu_transport_close(); APP_ERROR_CHECK(err_code); // With the S110 Flash API it is safe to initiate the activate before connection is // fully closed. err_code = dfu_image_activate(); if (err_code != NRF_SUCCESS) { dfu_reset(); } break; case BLE_DFU_SYS_RESET: err_code = dfu_transport_close(); APP_ERROR_CHECK(err_code); dfu_reset(); break; case BLE_DFU_START: m_pkt_type = PKT_TYPE_START; if (p_evt->evt.ble_dfu_pkt_write.len == 0) { m_update_mode = DFU_UPDATE_APP; } else { m_update_mode = (uint8_t)p_evt->evt.ble_dfu_pkt_write.p_data[0]; } break; case BLE_DFU_RECEIVE_INIT_DATA: m_pkt_type = PKT_TYPE_INIT; break; case BLE_DFU_RECEIVE_APP_DATA: m_pkt_type = PKT_TYPE_FIRMWARE_DATA; break; case BLE_DFU_PACKET_WRITE: on_dfu_pkt_write(p_dfu, p_evt); break; case BLE_DFU_PKT_RCPT_NOTIF_ENABLED: m_pkt_rcpt_notif_enabled = true; m_pkt_notif_target = p_evt->evt.pkt_rcpt_notif_req.num_of_pkts; m_pkt_notif_target_cnt = p_evt->evt.pkt_rcpt_notif_req.num_of_pkts; break; case BLE_DFU_PKT_RCPT_NOTIF_DISABLED: m_pkt_rcpt_notif_enabled = false; m_pkt_notif_target = 0; break; case BLE_DFU_BYTES_RECEIVED_SEND: err_code = ble_dfu_bytes_rcvd_report(p_dfu, m_num_of_firmware_bytes_rcvd); APP_ERROR_CHECK(err_code); break; default: // Unsupported event received from DFU Service. Ignore. break; } }
/**@brief Function for processing application data written by the peer to the DFU Packet * Characteristic. * * @param[in] p_dfu DFU Service Structure. * @param[in] p_evt Pointer to the event received from the S110 SoftDevice. */ static void app_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; if ((p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1)) != 0) { // Data length is not a multiple of 4 (word size). err_code = ble_dfu_response_send(p_dfu, BLE_DFU_RECEIVE_APP_PROCEDURE, BLE_DFU_RESP_VAL_NOT_SUPPORTED); APP_ERROR_CHECK(err_code); return; } uint32_t length = p_evt->evt.ble_dfu_pkt_write.len; err_code = hci_mem_pool_rx_produce(length, (void**) &mp_rx_buffer); if (err_code != NRF_SUCCESS) { dfu_error_notify(p_dfu, err_code); return; } uint8_t * p_data_packet = p_evt->evt.ble_dfu_pkt_write.p_data; memcpy(mp_rx_buffer, p_data_packet, length); err_code = hci_mem_pool_rx_data_size_set(length); if (err_code != NRF_SUCCESS) { dfu_error_notify(p_dfu, err_code); return; } err_code = hci_mem_pool_rx_extract(&mp_rx_buffer, &length); if (err_code != NRF_SUCCESS) { dfu_error_notify(p_dfu, err_code); return; } dfu_update_packet_t dfu_pkt; dfu_pkt.packet_type = DATA_PACKET; dfu_pkt.params.data_packet.packet_length = length / sizeof(uint32_t); dfu_pkt.params.data_packet.p_data_packet = (uint32_t*)mp_rx_buffer; err_code = dfu_data_pkt_handle(&dfu_pkt); if (err_code == NRF_SUCCESS) { // All the expected firmware data has been received and processed successfully. m_num_of_firmware_bytes_rcvd += p_evt->evt.ble_dfu_pkt_write.len; // Notify the DFU Controller about the success about the procedure. err_code = ble_dfu_response_send(p_dfu, BLE_DFU_RECEIVE_APP_PROCEDURE, BLE_DFU_RESP_VAL_SUCCESS); APP_ERROR_CHECK(err_code); } else if (err_code == NRF_ERROR_INVALID_LENGTH) { // Firmware data packet was handled successfully. And more firmware data is expected. m_num_of_firmware_bytes_rcvd += p_evt->evt.ble_dfu_pkt_write.len; // Check if a packet receipt notification is needed to be sent. if (m_pkt_rcpt_notif_enabled) { // Decrement the counter for the number firmware packets needed for sending the // next packet receipt notification. m_pkt_notif_target_cnt--; if (m_pkt_notif_target_cnt == 0) { err_code = ble_dfu_pkts_rcpt_notify(p_dfu, m_num_of_firmware_bytes_rcvd); APP_ERROR_CHECK(err_code); // Reset the counter for the number of firmware packets. m_pkt_notif_target_cnt = m_pkt_notif_target; } } } else { uint32_t hci_error = hci_mem_pool_rx_consume(mp_rx_buffer); if (hci_error != NRF_SUCCESS) { dfu_error_notify(p_dfu, hci_error); } dfu_error_notify(p_dfu, err_code); } }
/**@brief Function for processing start data written by the peer to the DFU Packet * Characteristic. * * @param[in] p_dfu DFU Service Structure. * @param[in] p_evt Pointer to the event received from the S110 SoftDevice. */ static void start_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; dfu_start_packet_t start_packet = {.dfu_update_mode = m_update_mode}; dfu_update_packet_t update_packet = { .packet_type = START_PACKET, .params.start_packet = &start_packet }; uint32_t length = p_evt->evt.ble_dfu_pkt_write.len; // Verify that the data is exactly three * four bytes (three words) long. // Or a single word to support backwards compatibility of application image transfer. if ((length != (3 * sizeof(uint32_t))) && (length != sizeof(uint32_t))) { err_code = ble_dfu_response_send(p_dfu, BLE_DFU_START_PROCEDURE, BLE_DFU_RESP_VAL_NOT_SUPPORTED); APP_ERROR_CHECK(err_code); } else { // Extract the size of from the DFU Packet Characteristic. uint8_t * length_data = p_evt->evt.ble_dfu_pkt_write.p_data; if (length == sizeof(uint32_t)) { // Legacy update. start_packet.sd_image_size = 0; start_packet.bl_image_size = 0; start_packet.app_image_size = uint32_decode(length_data); } else { start_packet.sd_image_size = uint32_decode(length_data); start_packet.bl_image_size = uint32_decode(length_data + 4); start_packet.app_image_size = uint32_decode(length_data + 8); } err_code = dfu_start_pkt_handle(&update_packet); if (err_code != NRF_SUCCESS) { // Translate the err_code returned by the above function to DFU Response Value. ble_dfu_resp_val_t resp_val; resp_val = nrf_err_code_translate(err_code, BLE_DFU_START_PROCEDURE); err_code = ble_dfu_response_send(p_dfu, BLE_DFU_START_PROCEDURE, resp_val); } APP_ERROR_CHECK(err_code); } } /**@brief Function for processing initialization data written by the peer to the DFU Packet * Characteristic. * * @param[in] p_dfu DFU Service Structure. * @param[in] p_evt Pointer to the event received from the S110 SoftDevice. */ static void init_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; dfu_update_packet_t dfu_pkt; uint8_t num_of_padding_bytes = 0; dfu_pkt.packet_type = INIT_PACKET; dfu_pkt.params.data_packet.p_data_packet = (uint32_t *)p_evt->evt.ble_dfu_pkt_write.p_data; // The DFU module accepts the dfu_pkt.packet_length to be in 'number of words'. And so if the // received data does not have a size which is a multiple of four, it should be padded with // zeros and the packet_length should be incremented accordingly before calling // dfu_init_pkt_handle. if ((p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1)) != 0) { // Find out the number of bytes to be padded. num_of_padding_bytes = sizeof(uint32_t) - (p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1)); uint32_t i; for (i = 0; i < num_of_padding_bytes; i++) { dfu_pkt.params.data_packet.p_data_packet[p_evt->evt.ble_dfu_pkt_write.len + i] = 0; } } dfu_pkt.params.data_packet.packet_length = (p_evt->evt.ble_dfu_pkt_write.len + num_of_padding_bytes) / sizeof(uint32_t); err_code = dfu_init_pkt_handle(&dfu_pkt); // Translate the err_code returned by the above function to DFU Response Value. ble_dfu_resp_val_t resp_val; resp_val = nrf_err_code_translate(err_code, BLE_DFU_INIT_PROCEDURE); err_code = ble_dfu_response_send(p_dfu, BLE_DFU_INIT_PROCEDURE, resp_val); APP_ERROR_CHECK(err_code); }
/**@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 the Device Firmware Update Service event handler. * * @details This function will be called for all Device Firmware Update Service events which * are passed to the application. * * @param[in] p_dfu Device Firmware Update Service structure. * @param[in] p_evt Event received from the Device Firmware Update Service. */ static void on_dfu_evt(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; switch (p_evt->ble_dfu_evt_type) { case BLE_DFU_VALIDATE: err_code = dfu_image_validate(); // Translate the err_code returned by the above function to DFU Response Value. ble_dfu_resp_val_t resp_val; resp_val = nrf_error_to_dfu_resp_val(err_code, BLE_DFU_VALIDATE_PROCEDURE); err_code = ble_dfu_response_send(p_dfu, BLE_DFU_VALIDATE_PROCEDURE, resp_val); APP_ERROR_CHECK(err_code); break; case BLE_DFU_ACTIVATE_N_RESET: // Final state of DFU is reached. m_activate_img_after_tear_down = true; err_code = dfu_transport_close(); APP_ERROR_CHECK(err_code); break; case BLE_DFU_SYS_RESET: err_code = dfu_transport_close(); APP_ERROR_CHECK(err_code); break; case BLE_DFU_START: m_pkt_type = PKT_TYPE_START; break; case BLE_DFU_RECEIVE_INIT_DATA: m_pkt_type = PKT_TYPE_INIT; break; case BLE_DFU_RECEIVE_APP_DATA: m_pkt_type = PKT_TYPE_FIRMWARE_DATA; break; case BLE_DFU_PACKET_WRITE: on_dfu_pkt_write(p_dfu, p_evt); break; case BLE_DFU_PKT_RCPT_NOTIF_ENABLED: m_pkt_rcpt_notif_enabled = true; m_pkt_notif_target = p_evt->evt.pkt_rcpt_notif_req.num_of_pkts; m_pkt_notif_target_cnt = p_evt->evt.pkt_rcpt_notif_req.num_of_pkts; break; case BLE_DFU_PKT_RCPT_NOTIF_DISABLED: m_pkt_rcpt_notif_enabled = false; m_pkt_notif_target = 0; break; case BLE_DFU_BYTES_RECEIVED_SEND: err_code = ble_dfu_bytes_rcvd_report(p_dfu, m_num_of_firmware_bytes_rcvd); APP_ERROR_CHECK(err_code); break; default: // Unsupported event received from DFU Service. Ignore. break; } }
/**@brief Function for processing application data written by the peer to the DFU Packet * Characteristic. * * @param[in] p_dfu DFU Service Structure. * @param[in] p_evt Pointer to the event received from the BLE stack. */ static void app_data_process(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; if ((p_evt->evt.ble_dfu_pkt_write.len & (sizeof(uint32_t) - 1)) != 0) { // Data length is not a multiple of 4 (word size). err_code = ble_dfu_response_send(p_dfu, BLE_DFU_RECEIVE_APP_PROCEDURE, BLE_DFU_RESP_VAL_NOT_SUPPORTED); APP_ERROR_CHECK(err_code); return; } dfu_update_packet_t dfu_pkt; dfu_pkt.packet_type = DATA_PACKET; dfu_pkt.packet_length = p_evt->evt.ble_dfu_pkt_write.len / sizeof(uint32_t); dfu_pkt.p_data_packet = (uint32_t *)p_evt->evt.ble_dfu_pkt_write.p_data; err_code = dfu_data_pkt_handle(&dfu_pkt); if (err_code == NRF_SUCCESS) { // All the expected firmware data has been received and processed successfully. m_num_of_firmware_bytes_rcvd += p_evt->evt.ble_dfu_pkt_write.len; // Notify the DFU Controller about the success about the procedure. err_code = ble_dfu_response_send(p_dfu, BLE_DFU_RECEIVE_APP_PROCEDURE, BLE_DFU_RESP_VAL_SUCCESS); APP_ERROR_CHECK(err_code); } else if (err_code == NRF_ERROR_INVALID_LENGTH) { // Firmware data packet was handled successfully. And more firmware data is expected. m_num_of_firmware_bytes_rcvd += p_evt->evt.ble_dfu_pkt_write.len; // Check if a packet receipt notification is needed to be sent. if (m_pkt_rcpt_notif_enabled) { // Decrement the counter for the number firmware packets needed for sending the // next packet receipt notification. m_pkt_notif_target_cnt--; if (m_pkt_notif_target_cnt == 0) { err_code = ble_dfu_pkts_rcpt_notify(p_dfu, m_num_of_firmware_bytes_rcvd); APP_ERROR_CHECK(err_code); // Reset the counter for the number of firmware packets. m_pkt_notif_target_cnt = m_pkt_notif_target; } } } else { // An error has occurred. Notify the DFU Controller about this error condition. // Translate the err_code returned to DFU Response Value. ble_dfu_resp_val_t resp_val; resp_val = nrf_error_to_dfu_resp_val(err_code, BLE_DFU_RECEIVE_APP_PROCEDURE); err_code = ble_dfu_response_send(p_dfu, BLE_DFU_RECEIVE_APP_PROCEDURE, resp_val); APP_ERROR_CHECK(err_code); } }