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(); }
uint8_t* dfu_cb_dnload_block(uint16_t block_num, uint16_t len) { if (len > DFU_TRANSFER_SIZE) { dfu_error(DFU_STATUS_errUNKNOWN); return NULL; } if (dfu_target == TARGET_FLASH) { if (block_num * DFU_TRANSFER_SIZE > FLASH_FW_SIZE) { dfu_error(DFU_STATUS_errADDRESS); return NULL; } return DFU_DEST_BASE; } else if (dfu_target == TARGET_RAM) { if (block_num * DFU_TRANSFER_SIZE > RAM_DEST_SIZE) { dfu_error(DFU_STATUS_errADDRESS); return NULL; } return DFU_DEST_BASE + block_num * DFU_TRANSFER_SIZE; } else { return NULL; } }
dfu_error DFU::detach(int timeout) { int error = libusb_control_transfer(dev_handle, REQUEST_TYPE_TO_DEVICE, dfu_request_type::detach, timeout, 4, NULL, 0, 0); return dfu_error(error); }
dfu_error DFU::eraseChip() { unsigned char write_command[6] = { 0x04, 0x00, 0xFF, 0,0,0}; int error = libusb_control_transfer(dev_handle, REQUEST_TYPE_TO_DEVICE, dfu_request_type::dnload, 0, 4, write_command, 6, 0); return dfu_error(error); }