From e6503fd0d61bbcc1ff529cb2c57c2ca46ddd766c Mon Sep 17 00:00:00 2001 From: Micah Elizabeth Scott <micah@scanlime.org> Date: Mon, 7 Oct 2013 17:46:51 -0700 Subject: [PATCH] Additional DFU cleanup, usb reset callback --- bootloader/dfu.c | 7 ++- bootloader/dfu.h | 1 + bootloader/usb_desc.c | 2 +- bootloader/usb_dev.c | 104 ++++++++++++++++++++++-------------------- 4 files changed, 61 insertions(+), 53 deletions(-) diff --git a/bootloader/dfu.c b/bootloader/dfu.c index 766a9b2..90695fd 100644 --- a/bootloader/dfu.c +++ b/bootloader/dfu.c @@ -101,8 +101,6 @@ bool dfu_download(unsigned blockNum, unsigned blockLength, // Store more data... memcpy(dfu_buffer + packetOffset, data, packetLength); -debug++; - if (packetOffset + packetLength != blockLength) { // Still waiting for more data. return true; @@ -192,3 +190,8 @@ bool dfu_abort() dfu_status = OK; return true; } + +void dfu_usb_reset() +{ + debug++; +} diff --git a/bootloader/dfu.h b/bootloader/dfu.h index 105f67f..bd2bf3b 100644 --- a/bootloader/dfu.h +++ b/bootloader/dfu.h @@ -68,6 +68,7 @@ void dfu_init(); // USB entry points. Always successful. uint8_t dfu_getstate(); +void dfu_usb_reset(); // USB entry points. True on success, false for stall. bool dfu_getstatus(uint8_t *status); diff --git a/bootloader/usb_desc.c b/bootloader/usb_desc.c index d968777..b28943c 100644 --- a/bootloader/usb_desc.c +++ b/bootloader/usb_desc.c @@ -113,7 +113,7 @@ static uint8_t config_descriptor[CONFIG_DESC_SIZE] = { // DFU Functional Descriptor (DFU spec TAble 4.2) 9, // bLength 0x21, // bDescriptorType - 0x01, // bmAttributes: Download only, must be reset + 0x0D, // bmAttributes LSB(DFU_DETACH_TIMEOUT), // wDetachTimeOut MSB(DFU_DETACH_TIMEOUT), LSB(DFU_TRANSFER_SIZE), // wTransferSize diff --git a/bootloader/usb_dev.c b/bootloader/usb_dev.c index 7b17e1f..8aff8f8 100644 --- a/bootloader/usb_dev.c +++ b/bootloader/usb_dev.c @@ -38,14 +38,13 @@ #include "dfu.h" // buffer descriptor table - typedef struct { uint32_t desc; void * addr; } bdt_t; __attribute__ ((section(".usbdescriptortable"), used)) -static bdt_t table[4]; // EP0 only +static bdt_t table[64]; // BDT page (512 bytes) #define BDT_OWN 0x80 #define BDT_DATA1 0x40 @@ -74,36 +73,36 @@ static bdt_t table[4]; // EP0 only static union { - struct { - union { - struct { - uint8_t bmRequestType; - uint8_t bRequest; - }; - uint16_t wRequestAndType; - }; - uint16_t wValue; - uint16_t wIndex; - uint16_t wLength; - }; - struct { - uint32_t word1; - uint32_t word2; - }; + struct { + union { + struct { + uint8_t bmRequestType; + uint8_t bRequest; + }; + uint16_t wRequestAndType; + }; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + }; + struct { + uint32_t word1; + uint32_t word2; + }; } setup; -#define GET_STATUS 0 +#define GET_STATUS 0 #define CLEAR_FEATURE 1 -#define SET_FEATURE 3 -#define SET_ADDRESS 5 +#define SET_FEATURE 3 +#define SET_ADDRESS 5 #define GET_DESCRIPTOR 6 #define SET_DESCRIPTOR 7 #define GET_CONFIGURATION 8 #define SET_CONFIGURATION 9 #define GET_INTERFACE 10 #define SET_INTERFACE 11 -#define SYNCH_FRAME 12 +#define SYNCH_FRAME 12 // SETUP always uses a DATA0 PID for the data field of the SETUP transaction. // transactions in the data phase start with DATA1 and toggle (figure 8-12, USB1.1) @@ -135,6 +134,7 @@ static void endpoint0_transmit(const void *data, uint32_t len) ep0_tx_bdt_bank ^= 1; } + static void usb_setup(void) { const uint8_t *data = NULL; @@ -218,7 +218,12 @@ static void usb_setup(void) endpoint0_stall(); return; } - // Data comes in the OUT phase. + // Data comes in the OUT phase. But if it's a zero-length request, handle it now. + if (setup.wLength == 0) { + if (!dfu_download(setup.wValue, 0, 0, 0, NULL)) { + endpoint0_stall(); + } + } break; case 0x03a1: // DFU_GETSTATUS @@ -329,36 +334,35 @@ static void usb_control(uint32_t stat) break; case 0x01: // OUT transaction received from host - // The only control OUT request we have now, DFU_DNLOAD - if (setup.wRequestAndType == 0x0121 && setup.wIndex == 0 && - ep0_rx_offset <= setup.wLength) { - bool success; - size = setup.wLength - ep0_rx_offset; - if (size > EP0_SIZE) size = EP0_SIZE; - - success = dfu_download(setup.wValue, // blockNum - setup.wLength, // blockLength - ep0_rx_offset, // packetOffset - size, // packetLength - buf); // data - - // Give the buffer back - b->desc = BDT_DESC_RX(EP0_SIZE); + // The only control OUT request we have now, DFU_DNLOAD + if (setup.wRequestAndType == 0x0121) { - if (success) { - ep0_rx_offset += size; - if (ep0_rx_offset >= setup.wLength) { - // End of transaction, acknowledge with a zero-length IN - endpoint0_transmit(reply_buffer, 0); - } - } else { + if (setup.wIndex != 0 && ep0_rx_offset > setup.wLength) { endpoint0_stall(); + } else { + size = setup.wLength - ep0_rx_offset; + if (size > EP0_SIZE) size = EP0_SIZE; + + if (dfu_download(setup.wValue, // blockNum + setup.wLength, // blockLength + ep0_rx_offset, // packetOffset + size, // packetLength + buf)) { // data + + ep0_rx_offset += size; + if (ep0_rx_offset >= setup.wLength) { + // End of transaction, acknowledge with a zero-length IN + endpoint0_transmit(reply_buffer, 0); + } + } else { + endpoint0_stall(); + } } - } else { - // Give the buffer back - b->desc = BDT_DESC_RX(EP0_SIZE); } + + // Give the buffer back + b->desc = BDT_DESC_RX(EP0_SIZE); break; case 0x09: // IN transaction completed to host @@ -383,7 +387,6 @@ static void usb_control(uint32_t stat) } - void usb_isr(void) { uint8_t status, stat; @@ -442,6 +445,8 @@ restart: // is this necessary? USB0_CTL = USB_CTL_USBENSOFEN; + + dfu_usb_reset(); return; } @@ -462,7 +467,6 @@ restart: } - void usb_init(void) { // this basically follows the flowchart in the Kinetis -- GitLab