diff --git a/examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c b/examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c index 1b089c12..97b2f4d8 100644 --- a/examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c +++ b/examples/stm32/f1/lisa-m-1/usb_dfu/usbdfu.c @@ -63,7 +63,7 @@ const struct usb_device_descriptor dev = { const struct usb_dfu_descriptor dfu_function = { .bLength = sizeof(struct usb_dfu_descriptor), .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, .wDetachTimeout = 255, .wTransferSize = 1024, .bcdDFUVersion = 0x011A, @@ -79,8 +79,7 @@ const struct usb_interface_descriptor iface = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 2, - /* The ST Microelectronics DfuSe application needs this string. - * The format isn't documented... */ + /* The ST Microelectronics DfuSe application needs this string. */ .iInterface = 4, .extra = &dfu_function, @@ -109,8 +108,30 @@ static const char *usb_strings[] = { "Black Sphere Technologies", "DFU Demo", "DEMO", - /* This string is used by ST Microelectronics' DfuSe utility. */ + // DfuSe descriptor string, used by ST DfuSe utility and also + // supported by dfu-util, see UM0424 section 10.3.2: + // + // |----------[zone]----------| + // [segment] + // \-----/ "@Internal Flash /0x08000000/8*001Ka,56*001Kg", + // start address of [zone]-^ | |--/| \-------/ + // | | | [segment] + // | | | + // | | ` [flags], "a"=readable + // [flags]: | ` 1K bytes per erase-block + // (a) readable `8 erase-blocks + // (b) earaseable + // (c) readable and earaseable + // (e) readable and writable + // (f) earaseable and writable + // (g) readable, earaseable and writable + // + // [zone]: a number of segments starting at given address, allowed + // to be non-contigous + // + // [segment]: a number of contigous erase blocks, or "sectors" in + // ST docs }; static uint8_t usbdfu_getstatus(uint32_t *bwPollTimeout) @@ -204,8 +225,12 @@ static enum usbd_request_return_codes usbdfu_control_request(usbd_device *usbd_d usbdfu_state = STATE_DFU_IDLE; return USBD_REQ_HANDLED; case DFU_UPLOAD: - /* Upload not supported for now. */ - return USBD_REQ_NOTSUPP; + usbdfu_state = STATE_DFU_UPLOAD_IDLE; + uint32_t addr = prog.addr + + ((req->wValue - 2) * dfu_function.wTransferSize); + memcpy(*buf, (void*)addr, dfu_function.wTransferSize); + *len = dfu_function.wTransferSize; + return USBD_REQ_HANDLED; case DFU_GETSTATUS: { uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ (*buf)[0] = usbdfu_getstatus(&bwPollTimeout); diff --git a/examples/stm32/f1/other/usb_dfu/usbdfu.c b/examples/stm32/f1/other/usb_dfu/usbdfu.c index 3a310040..c0344b41 100644 --- a/examples/stm32/f1/other/usb_dfu/usbdfu.c +++ b/examples/stm32/f1/other/usb_dfu/usbdfu.c @@ -63,7 +63,7 @@ const struct usb_device_descriptor dev = { const struct usb_dfu_descriptor dfu_function = { .bLength = sizeof(struct usb_dfu_descriptor), .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, .wDetachTimeout = 255, .wTransferSize = 1024, .bcdDFUVersion = 0x011A, @@ -79,8 +79,7 @@ const struct usb_interface_descriptor iface = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 2, - /* The ST Microelectronics DfuSe application needs this string. - * The format isn't documented... */ + /* The ST Microelectronics DfuSe application needs this string. */ .iInterface = 4, .extra = &dfu_function, @@ -109,8 +108,31 @@ static const char *usb_strings[] = { "Black Sphere Technologies", "DFU Demo", "DEMO", - /* This string is used by ST Microelectronics' DfuSe utility. */ + + // DfuSe descriptor string, used by ST DfuSe utility and also + // supported by dfu-util, see UM0424 section 10.3.2: + // + // |----------[zone]----------| + // [segment] + // \-----/ "@Internal Flash /0x08000000/8*001Ka,56*001Kg", + // start address of [zone]-^ | |--/| \-------/ + // | | | [segment] + // | | | + // | | ` [flags], "a"=readable + // [flags]: | ` 1K bytes per erase-block + // (a) readable `8 erase-blocks + // (b) earaseable + // (c) readable and earaseable + // (e) readable and writable + // (f) earaseable and writable + // (g) readable, earaseable and writable + // + // [zone]: a number of segments starting at given address, allowed + // to be non-contigous + // + // [segment]: a number of contigous erase blocks, or "sectors" in + // ST docs }; static uint8_t usbdfu_getstatus(uint32_t *bwPollTimeout) @@ -204,7 +226,12 @@ static enum usbd_request_return_codes usbdfu_control_request(usbd_device *usbd_d usbdfu_state = STATE_DFU_IDLE; return USBD_REQ_HANDLED; case DFU_UPLOAD: - /* Upload not supported for now. */ + usbdfu_state = STATE_DFU_UPLOAD_IDLE; + uint32_t addr = prog.addr + + ((req->wValue - 2) * dfu_function.wTransferSize); + memcpy(*buf, (void*)addr, dfu_function.wTransferSize); + *len = dfu_function.wTransferSize; + return USBD_REQ_HANDLED; return USBD_REQ_NOTSUPP; case DFU_GETSTATUS: { uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ diff --git a/examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c b/examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c index 1ac4fbaf..8aa5c1df 100644 --- a/examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c +++ b/examples/stm32/f1/stm32-h103/usb_dfu/usbdfu.c @@ -63,7 +63,7 @@ const struct usb_device_descriptor dev = { const struct usb_dfu_descriptor dfu_function = { .bLength = sizeof(struct usb_dfu_descriptor), .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, .wDetachTimeout = 255, .wTransferSize = 1024, .bcdDFUVersion = 0x011A, @@ -79,8 +79,7 @@ const struct usb_interface_descriptor iface = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 2, - /* The ST Microelectronics DfuSe application needs this string. - * The format isn't documented... */ + /* The ST Microelectronics DfuSe application needs this string. */ .iInterface = 4, .extra = &dfu_function, @@ -109,8 +108,31 @@ static const char *usb_strings[] = { "Black Sphere Technologies", "DFU Demo", "DEMO", - /* This string is used by ST Microelectronics' DfuSe utility. */ + + // DfuSe descriptor string, used by ST DfuSe utility and also + // supported by dfu-util, see UM0424 section 10.3.2: + // + // |----------[zone]----------| + // [segment] + // \-----/ "@Internal Flash /0x08000000/8*001Ka,56*001Kg", + // start address of [zone]-^ | |--/| \-------/ + // | | | [segment] + // | | | + // | | ` [flags], "a"=readable + // [flags]: | ` 1K bytes per erase-block + // (a) readable `8 erase-blocks + // (b) earaseable + // (c) readable and earaseable + // (e) readable and writable + // (f) earaseable and writable + // (g) readable, earaseable and writable + // + // [zone]: a number of segments starting at given address, allowed + // to be non-contigous + // + // [segment]: a number of contigous erase blocks, or "sectors" in + // ST docs }; static uint8_t usbdfu_getstatus(usbd_device *usbd_dev, uint32_t *bwPollTimeout) @@ -204,8 +226,12 @@ static enum usbd_request_return_codes usbdfu_control_request(usbd_device *usbd_d usbdfu_state = STATE_DFU_IDLE; return USBD_REQ_HANDLED; case DFU_UPLOAD: - /* Upload not supported for now. */ - return USBD_REQ_NOTSUPP; + usbdfu_state = STATE_DFU_UPLOAD_IDLE; + uint32_t addr = prog.addr + + ((req->wValue - 2) * dfu_function.wTransferSize); + memcpy(*buf, (void*)addr, dfu_function.wTransferSize); + *len = dfu_function.wTransferSize; + return USBD_REQ_HANDLED; case DFU_GETSTATUS: { uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ (*buf)[0] = usbdfu_getstatus(usbd_dev, &bwPollTimeout); diff --git a/examples/stm32/f1/stm32-h103/usb_iap/usbiap.c b/examples/stm32/f1/stm32-h103/usb_iap/usbiap.c index f385e050..b29641fa 100644 --- a/examples/stm32/f1/stm32-h103/usb_iap/usbiap.c +++ b/examples/stm32/f1/stm32-h103/usb_iap/usbiap.c @@ -63,7 +63,7 @@ const struct usb_device_descriptor dev = { const struct usb_dfu_descriptor dfu_function = { .bLength = sizeof(struct usb_dfu_descriptor), .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .bmAttributes = USB_DFU_CAN_UPLOAD | USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, .wDetachTimeout = 255, .wTransferSize = 1024, .bcdDFUVersion = 0x011A, @@ -79,8 +79,7 @@ const struct usb_interface_descriptor iface = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 2, - /* The ST Microelectronics DfuSe application needs this string. - * The format isn't documented... */ + /* The ST Microelectronics DfuSe application needs this string. */ .iInterface = 4, .extra = &dfu_function, @@ -109,8 +108,31 @@ static const char *usb_strings[] = { "Black Sphere Technologies", "DFU Demo", "DEMO", - /* This string is used by ST Microelectronics' DfuSe utility. */ + + // DfuSe descriptor string, used by ST DfuSe utility and also + // supported by dfu-util, see UM0424 section 10.3.2: + // + // |----------[zone]----------| + // [segment] + // \-----/ "@Internal Flash /0x08000000/8*001Ka,56*001Kg", + // start address of [zone]-^ | |--/| \-------/ + // | | | [segment] + // | | | + // | | ` [flags], "a"=readable + // [flags]: | ` 1K bytes per erase-block + // (a) readable `8 erase-blocks + // (b) earaseable + // (c) readable and earaseable + // (e) readable and writable + // (f) earaseable and writable + // (g) readable, earaseable and writable + // + // [zone]: a number of segments starting at given address, allowed + // to be non-contigous + // + // [segment]: a number of contigous erase blocks, or "sectors" in + // ST docs }; static uint8_t usbdfu_getstatus(usbd_device *usbd_dev, uint32_t *bwPollTimeout) @@ -204,8 +226,12 @@ static enum usbd_request_return_codes usbdfu_control_request(usbd_device *usbd_d usbdfu_state = STATE_DFU_IDLE; return USBD_REQ_HANDLED; case DFU_UPLOAD: - /* Upload not supported for now. */ - return USBD_REQ_NOTSUPP; + usbdfu_state = STATE_DFU_UPLOAD_IDLE; + uint32_t addr = prog.addr + + ((req->wValue - 2) * dfu_function.wTransferSize); + memcpy(*buf, (void*)addr, dfu_function.wTransferSize); + *len = dfu_function.wTransferSize; + return USBD_REQ_HANDLED; case DFU_GETSTATUS: { uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ (*buf)[0] = usbdfu_getstatus(usbd_dev, &bwPollTimeout);