mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-21 14:50:44 +01:00
[WIP] dfu
Change-Id: I8a30380f393a073320843ad94b7938d1f510377a
This commit is contained in:
@@ -65,6 +65,130 @@ void init() {
|
||||
m_usbDevice.init();
|
||||
}
|
||||
|
||||
#if 0
|
||||
static const struct FunctionalDescriptor functionalDescriptor = {
|
||||
.bLength = USB_DT_FUNCTIONAL_SIZE,
|
||||
.bDescriptorType = USB_DT_DFU_FUNCTIONAL,
|
||||
.bmAttributes = 0b00001011, /* TODO bitWillDetach|TODO bitManifestationTolerant|bitCanUpload|bitCanDnload */
|
||||
.wDetachTimeOut = 10, /* TODO Time, in milliseconds, that the device will wait after receipt of the DFU_DETACH request. If this time elapses without a USB reset, then the device will terminate the Reconfiguration phase and revert back to normal operation. This represents the maximum time that the device can wait (depending on its timers, etc.). The host may specify a shorter timeout in the DFU_DETACH request.*/
|
||||
.wTransferSize = 0, /* TODO Maximum number of bytes that the device can accept per control-write transaction. */
|
||||
.bcdDFUVersion = 0x0100 /* TODO Numeric expression identifying the version of the DFU Specification release. */
|
||||
};
|
||||
|
||||
DFUState sDFUState = DFUState::DFU_IDLE; // TODO We start directly in DFU Idle mode.
|
||||
static uint8_t sFlashBuffer[5*64];
|
||||
uint16_t sFlashBufferLength;
|
||||
uint32_t sDFUAddress;
|
||||
uint16_t sDFUBlockNumber;
|
||||
|
||||
|
||||
int controlDFURequest() {
|
||||
switch (sSetupData.bRequest) {
|
||||
//TODO: DFU_DETACH?
|
||||
case DFURequest::DFU_DNLOAD:
|
||||
if (sControlBufferLength > 0) {
|
||||
sDFUBlockNumber = sSetupData.wValue;
|
||||
|
||||
//TODO Why another buffer?
|
||||
sFlashBufferLength = sControlBufferLength;
|
||||
memcpy(sFlashBuffer, sControlBuffer, sControlBufferLength);
|
||||
|
||||
sDFUState = DFUState::DNLOAD_SYNC;
|
||||
return (int) RequestReturnCodes::USBD_REQ_HANDLED;
|
||||
} else {
|
||||
sDFUState = DFUState::DFU_MANIFEST_SYNC;
|
||||
return (int) RequestReturnCodes::USBD_REQ_HANDLED;
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
case DFURequest::DFU_UPLOAD:
|
||||
return 0;
|
||||
break;
|
||||
case DFURequest::DFU_GETSTATUS:
|
||||
/* bwPollTimeout is the minimum time, in milliseconds, that the host
|
||||
* should wait before sending a subsequent DFU_GETSTATUS request. 3*(8-bit)integer. */
|
||||
uint32_t bwPollTimeout = 0;
|
||||
sControlBuffer[0] = usbdfu_getstatus(&bwPollTimeout);
|
||||
// We have to send bwPollTimeout, with little-endian order.
|
||||
sControlBuffer[1] = bwPollTimeout & 0xFF;
|
||||
sControlBuffer[2] = (bwPollTimeout >> 8) & 0xFF;
|
||||
sControlBuffer[3] = (bwPollTimeout >> 16) & 0xFF;
|
||||
sControlBuffer[4] = sDFUState;
|
||||
sControlBuffer[5] = 0; // No String description
|
||||
sControlBufferLength = 6;
|
||||
|
||||
//TODO*complete = usbdfu_getstatus_complete;
|
||||
return (int) RequestReturnCodes::USBD_REQ_HANDLED;
|
||||
break;
|
||||
case DFURequest::DFU_CLRSTATUS:
|
||||
if (sDFUState == DFUState::DFU_ERROR) {
|
||||
sDFUState = DFUState::DFU_IDLE;
|
||||
}
|
||||
return (int) RequestReturnCodes::USBD_REQ_HANDLED;
|
||||
break;
|
||||
case DFURequest::DFU_GETSTATE:
|
||||
sControlBuffer[0] = sDFUState;
|
||||
sControlBufferLength = 1;
|
||||
return (int) RequestReturnCodes::USBD_REQ_HANDLED;
|
||||
break;
|
||||
case DFURequest::DFU_ABORT:
|
||||
sDFUState = DFUState::DFU_IDLE;
|
||||
return (int) RequestReturnCodes::USBD_REQ_HANDLED;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (int) RequestReturnCodes::USBD_REQ_NOTSUPP;
|
||||
}
|
||||
|
||||
int controlCustomSetup() {
|
||||
switch (sSetupData.bRequest) {
|
||||
case USB_OS_STRING_BMS_VENDOR_CODE:
|
||||
if (sSetupData.wIndex == USB_OS_FEATURE_EXTENDED_COMPAT_ID) {
|
||||
sControlBuffer = sControlBufferInit;
|
||||
sControlBufferLength = buildExtendedCompatIDDescriptor();
|
||||
return (int) RequestReturnCodes::USBD_REQ_HANDLED;
|
||||
}
|
||||
if (sSetupData.wIndex == USB_OS_FEATURE_EXTENDED_PROPERTIES) {
|
||||
sControlBuffer = sControlBufferInit;
|
||||
sControlBufferLength = buildExtendedPropertiesDescriptor();
|
||||
return (int) RequestReturnCodes::USBD_REQ_HANDLED;
|
||||
}
|
||||
break;
|
||||
case WEB_USB_BVENDOR_CODE:
|
||||
if (sSetupData.wIndex == WEB_USB_INDEX_REQUEST_GET_URL) {
|
||||
struct URLDescriptor * urlDescriptor = (struct URLDescriptor *)sControlBufferInit;
|
||||
int arrayIndex = sSetupData.wValue - 1;
|
||||
/* Check that string index is in range. */
|
||||
if (arrayIndex < 0 || arrayIndex >= sNumberOfStrings) {
|
||||
return (int) RequestReturnCodes::USBD_REQ_NOTSUPP;
|
||||
}
|
||||
/* This string is returned as UTF16, hence the multiplication */
|
||||
urlDescriptor->bLength = strlen(sStrings[arrayIndex]) * 2 +
|
||||
sizeof(urlDescriptor->bLength) +
|
||||
sizeof(urlDescriptor->bDescriptorType)+
|
||||
sizeof(urlDescriptor->bScheme);
|
||||
|
||||
sControlBufferLength = MIN(sControlBufferLength, urlDescriptor->bLength);
|
||||
|
||||
for (int i = 0; i < (sControlBufferLength / 2) - 1; i++) {
|
||||
urlDescriptor->URL[i] = sStrings[arrayIndex][i];
|
||||
}
|
||||
|
||||
urlDescriptor->bDescriptorType = USB_DT_URL;
|
||||
sControlBuffer = (uint8_t *)urlDescriptor;
|
||||
whiteScreen();
|
||||
return (int) RequestReturnCodes::USBD_REQ_HANDLED;
|
||||
}
|
||||
return (int) RequestReturnCodes::USBD_REQ_NOTSUPP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (int) RequestReturnCodes::USBD_REQ_NOTSUPP;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,70 @@ void init();
|
||||
void initGPIO();
|
||||
void shutdown();
|
||||
|
||||
#if 0
|
||||
|
||||
/* DFU */
|
||||
|
||||
enum class DFURequest {
|
||||
DFU_DETACH = 0,
|
||||
DFU_DNLOAD = 1,
|
||||
DFU_UPLOAD = 2,
|
||||
DFU_GETSTATUS = 3,
|
||||
DFU_CLRSTATUS = 4,
|
||||
DFU_GETSTATE = 5,
|
||||
DFU_ABORT = 6
|
||||
};
|
||||
|
||||
enum class DFUStatus {
|
||||
OK = 0x0,
|
||||
ERR_TARGET = 0x1,
|
||||
ERR_FILE = 0x2,
|
||||
ERR_WRITE = 0x3,
|
||||
ERR_ERASE = 0x4,
|
||||
ERR_CHECK_ERASED = 0x5,
|
||||
ERR_PROG = 0x6,
|
||||
ERR_VERIFY = 0x7,
|
||||
ERR_ADDRESS = 0x8,
|
||||
ERR_NOTDONE = 0x9,
|
||||
ERR_FIRMWARE = 0xA,
|
||||
ERR_VENDOR = 0xB,
|
||||
ERR_USBR = 0xC,
|
||||
ERR_POR = 0xD,
|
||||
ERR_UNKNOWN = 0xE,
|
||||
ERR_STALLEDPKT = 0xF
|
||||
};
|
||||
|
||||
enum class DFUState {
|
||||
APP_IDLE = 0,
|
||||
APP_DETACH = 1,
|
||||
DFU_IDLE = 2,
|
||||
DFU_DNLOAD_SYNC = 3,
|
||||
DFU_DNBUSY = 4,
|
||||
DFU_DNLOAD_IDLE = 5,
|
||||
DFU_MANIFEST_SYNC = 6,
|
||||
DFU_MANIFEST = 7,
|
||||
DFU_MANIFEST_WAIT_RESET = 8,
|
||||
DFU_UPLOAD_IDLE = 9,
|
||||
DFU_ERROR = 10
|
||||
};
|
||||
|
||||
/* USB Functional Descriptor */
|
||||
struct FunctionalDescriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bmAttributes;
|
||||
uint16_t wDetachTimeOut;
|
||||
uint16_t wTransferSize;
|
||||
uint16_t bcdDFUVersion;
|
||||
} __attribute__((packed));
|
||||
|
||||
int controlDFUSetup();
|
||||
|
||||
#define USB_DT_FUNCTIONAL_SIZE 9
|
||||
#define USB_DT_FUNCTIONAL_SIZE 9
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user