static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { if (argc < 4) return CMD_RET_USAGE; char *usb_controller = argv[1]; char *interface = argv[2]; char *devstring = argv[3]; int ret, i = 0; ret = dfu_init_env_entities(interface, simple_strtoul(devstring, NULL, 10)); if (ret) goto done; ret = CMD_RET_SUCCESS; if (argc > 4 && strcmp(argv[4], "list") == 0) { dfu_show_entities(); goto done; } int controller_index = simple_strtoul(usb_controller, NULL, 0); board_usb_init(controller_index, USB_INIT_DEVICE); g_dnl_register("usb_dnl_dfu"); while (1) { if (dfu_reset()) /* * This extra number of usb_gadget_handle_interrupts() * calls is necessary to assure correct transmission * completion with dfu-util */ if (++i == 10) goto exit; if (ctrlc()) goto exit; usb_gadget_handle_interrupts(); } exit: g_dnl_unregister(); done: dfu_free_entities(); if (dfu_reset()) run_command("reset", 0); return ret; }
void dfu_control_setup() { switch (usb_setup.bRequest) { case DFU_DNLOAD: if (dfu_state == DFU_STATE_dfuIDLE || dfu_state == DFU_STATE_dfuDNLOAD_IDLE) { if (usb_setup.wLength == 0) { dfu_state = DFU_STATE_dfuMANIFEST_SYNC; usb_ep0_out(); return usb_ep0_in(0); } else { dfu_block_offset = 0; dfu_cb_dnload_block(usb_setup.wValue, usb_setup.wLength); if (dfu_state != DFU_STATE_dfuERROR) { dfu_state = DFU_STATE_dfuDNBUSY; return usb_ep0_out(); } } } else { dfu_error(DFU_STATUS_errSTALLEDPKT); } return usb_ep0_stall(); case DFU_UPLOAD: dfu_error(DFU_STATUS_errSTALLEDPKT); return usb_ep0_stall(); case DFU_GETSTATUS: { if (dfu_state == DFU_STATE_dfuMANIFEST_SYNC) { dfu_state = DFU_STATE_dfuMANIFEST; dfu_cb_manifest(); } uint8_t len = usb_setup.wLength; if (len > sizeof(DFU_StatusResponse)) len = sizeof(DFU_StatusResponse); DFU_StatusResponse* status = (DFU_StatusResponse*) ep0_buf_in; status->bStatus = dfu_status; status->bwPollTimeout[0] = (dfu_poll_timeout >> 0) & 0xFF; status->bwPollTimeout[1] = (dfu_poll_timeout >> 8) & 0xFF; status->bwPollTimeout[2] = (dfu_poll_timeout >> 16) & 0xFF; status->bState = dfu_state; status->iString = 0; usb_ep0_in(len); return usb_ep0_out(); } case DFU_ABORT: case DFU_CLRSTATUS: dfu_reset(); usb_ep0_in(0); return usb_ep0_out(); case DFU_GETSTATE: ep0_buf_in[0] = dfu_state; usb_ep0_in(1); return usb_ep0_out(); } return usb_ep0_stall(); }
/**@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; } }