From b67f889a4098f0e6f281bbcabc8b5d6cbc60b652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9a=20Saviot?= Date: Mon, 12 Feb 2018 17:29:37 +0100 Subject: [PATCH] [WIP] dfu Change-Id: I8a30380f393a073320843ad94b7938d1f510377a --- ion/src/device/usb.cpp | 124 +++++++++++++++++++++++++++++++++++++++++ ion/src/device/usb.h | 64 +++++++++++++++++++++ 2 files changed, 188 insertions(+) diff --git a/ion/src/device/usb.cpp b/ion/src/device/usb.cpp index a1181d59e..bb159d082 100644 --- a/ion/src/device/usb.cpp +++ b/ion/src/device/usb.cpp @@ -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 + } } } diff --git a/ion/src/device/usb.h b/ion/src/device/usb.h index 324877270..575b7b80c 100644 --- a/ion/src/device/usb.h +++ b/ion/src/device/usb.h @@ -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 + + } } }