diff --git a/atusb/fw/descr.c b/atusb/fw/descr.c index 147e180..56447ff 100644 --- a/atusb/fw/descr.c +++ b/atusb/fw/descr.c @@ -1,8 +1,8 @@ /* * fw/descr.c - USB descriptors * - * Written 2008-2011 by Werner Almesberger - * Copyright 2008-2011 Werner Almesberger + * Written 2008-2011, 2014 by Werner Almesberger + * Copyright 2008-2011, 2014 Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -100,5 +100,5 @@ const uint8_t config_descriptor[] = { /* Interface #1 */ - DFU_ITF_DESCR(1, dfu_proto_runtime) + DFU_ITF_DESCR(1, 0, dfu_proto_runtime) }; diff --git a/atusb/fw/flash.c b/atusb/fw/flash.c index 54d9a19..75b5782 100644 --- a/atusb/fw/flash.c +++ b/atusb/fw/flash.c @@ -1,8 +1,8 @@ /* * fw/flash.c - Board-specific flash functions * - * Written 2011, 2013 by Werner Almesberger - * Copyright 2011, 2013 Werner Almesberger + * Written 2011, 2013, 2014 by Werner Almesberger + * Copyright 2011, 2013, 2014 Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,19 +24,19 @@ static uint32_t payload; -void flash_start(void) +static void flash_start(void) { payload = 0; } -bool flash_can_write(uint16_t size) +static bool flash_can_write(uint16_t size) { return payload+size <= BOOT_ADDR; } -void flash_write(const uint8_t *buf, uint16_t size) +static void flash_write(const uint8_t *buf, uint16_t size) { static uint8_t last; const uint8_t *p; @@ -61,7 +61,7 @@ void flash_write(const uint8_t *buf, uint16_t size) } -void flash_end_write(void) +static void flash_end_write(void) { if (payload & (SPM_PAGESIZE-1)) { boot_page_write(payload & ~(SPM_PAGESIZE-1)); @@ -71,7 +71,7 @@ void flash_end_write(void) } -uint16_t flash_read(uint8_t *buf, uint16_t size) +static uint16_t flash_read(uint8_t *buf, uint16_t size) { uint16_t got = 0; @@ -83,3 +83,15 @@ uint16_t flash_read(uint8_t *buf, uint16_t size) } return got; } + + +static struct dfu_flash_ops flash_ops = { + .start = flash_start, + .can_write = flash_can_write, + .write = flash_write, + .end_write = flash_end_write, + .read = flash_read, +}; + + +struct dfu_flash_ops *dfu_flash_ops = &flash_ops; diff --git a/atusb/fw/usb/dfu.c b/atusb/fw/usb/dfu.c index dc8bab3..723221c 100644 --- a/atusb/fw/usb/dfu.c +++ b/atusb/fw/usb/dfu.c @@ -42,6 +42,11 @@ #define error(...) +#ifndef DFU_ALT_SETTINGS +#define DFU_ALT_SETTINGS 1 +#endif + + const uint8_t device_descriptor[] = { 18, /* bLength */ USB_DT_DEVICE, /* bDescriptorType */ @@ -67,7 +72,7 @@ const uint8_t device_descriptor[] = { const uint8_t config_descriptor[] = { 9, /* bLength */ USB_DT_CONFIG, /* bDescriptorType */ - LE(9+9), /* wTotalLength */ + LE(9+9*DFU_ALT_SETTINGS), /* wTotalLength */ 1, /* bNumInterfaces */ 1, /* bConfigurationValue (> 0 !) */ 0, /* iConfiguration */ @@ -77,7 +82,13 @@ const uint8_t config_descriptor[] = { /* Interface #0 */ - DFU_ITF_DESCR(0, dfu_proto_dfu) + DFU_ITF_DESCR(0, 0, dfu_proto_dfu) +#if DFU_ALT_SETTINGS >= 1 + DFU_ITF_DESCR(0, 1, dfu_proto_dfu) +#endif +#if DFU_ALT_SETTINGS >= 2 + DFU_ITF_DESCR(0, 2, dfu_proto_dfu) +#endif }; @@ -92,7 +103,7 @@ static void block_write(void *user) { uint16_t *size = user; - flash_write(buf, *size); + dfu_flash_ops->write(buf, *size); } @@ -100,7 +111,7 @@ static bool block_receive(uint16_t length) { static uint16_t size; - if (!flash_can_write(length)) { + if (!dfu_flash_ops->can_write(length)) { dfu.state = dfuERROR; dfu.status = errADDRESS; return 0; @@ -125,7 +136,7 @@ static bool block_transmit(uint16_t length) dfu.status = errUNKNOWN; return 1; } - got = flash_read(buf, length); + got = dfu_flash_ops->read(buf, length); if (got < length) { length = got; dfu.state = dfuIDLE; @@ -152,7 +163,7 @@ static bool my_setup(const struct setup_request *setup) debug("DFU_DNLOAD\n"); if (dfu.state == dfuIDLE) { next_block = setup->wValue; - flash_start(); + dfu_flash_ops->start(); } else if (dfu.state != dfuDNLOAD_IDLE) { error("bad state\n"); @@ -171,7 +182,7 @@ static bool my_setup(const struct setup_request *setup) } if (!setup->wLength) { debug("DONE\n"); - flash_end_write(); + dfu_flash_ops->end_write(); dfu.state = dfuIDLE; did_download = 1; return 1; @@ -184,7 +195,7 @@ static bool my_setup(const struct setup_request *setup) debug("DFU_UPLOAD\n"); if (dfu.state == dfuIDLE) { next_block = setup->wValue; - flash_start(); + dfu_flash_ops->start(); } else if (dfu.state != dfuUPLOAD_IDLE) return 0; diff --git a/atusb/fw/usb/dfu.h b/atusb/fw/usb/dfu.h index 206a3c0..b77758f 100644 --- a/atusb/fw/usb/dfu.h +++ b/atusb/fw/usb/dfu.h @@ -1,8 +1,8 @@ /* * boot/dfu.h - DFU protocol constants and data structures * - * Written 2008, 2011, 2013 by Werner Almesberger - * Copyright 2008, 2011, 2013 Werner Almesberger + * Written 2008, 2011, 2013, 2014 by Werner Almesberger + * Copyright 2008, 2011, 2013, 2014 Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -86,11 +86,11 @@ struct dfu { }; -#define DFU_ITF_DESCR(itf, proto) \ +#define DFU_ITF_DESCR(itf, alt, proto) \ 9, /* bLength */ \ USB_DT_INTERFACE, /* bDescriptorType */ \ (itf), /* bInterfaceNumber */ \ - 0, /* bAlternateSetting */ \ + (alt), /* bAlternateSetting */ \ 0, /* bNumEndpoints */ \ 0xfe, /* bInterfaceClass (application specific) */ \ 0x01, /* bInterfaceSubClass (device fw upgrade) */ \ @@ -98,15 +98,18 @@ struct dfu { 0, /* iInterface */ +struct dfu_flash_ops { + void (*start)(void); + bool (*can_write)(uint16_t size); + void (*write)(const uint8_t *buf, uint16_t size); + void (*end_write)(void); + uint16_t (*read)(uint8_t *buf, uint16_t size); +}; + extern struct dfu dfu; +extern struct dfu_flash_ops *dfu_flash_ops; -void flash_start(void); -bool flash_can_write(uint16_t size); -void flash_write(const uint8_t *buf, uint16_t size); -void flash_end_write(void); -uint16_t flash_read(uint8_t *buf, uint16_t size); - bool dfu_setup_common(const struct setup_request *setup); bool dfu_my_descr(uint8_t type, uint8_t index, const uint8_t **reply, uint8_t *size);