mirror of
git://projects.qi-hardware.com/ben-wpan.git
synced 2024-11-22 07:25:19 +02:00
atusb/fw/: DFU: support multiple sets of flash operations; support multiple alt settings
This commit is contained in:
parent
8b0859486e
commit
8f2f13c30a
@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* fw/descr.c - USB descriptors
|
* fw/descr.c - USB descriptors
|
||||||
*
|
*
|
||||||
* Written 2008-2011 by Werner Almesberger
|
* Written 2008-2011, 2014 by Werner Almesberger
|
||||||
* Copyright 2008-2011 Werner Almesberger
|
* Copyright 2008-2011, 2014 Werner Almesberger
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -100,5 +100,5 @@ const uint8_t config_descriptor[] = {
|
|||||||
|
|
||||||
/* Interface #1 */
|
/* Interface #1 */
|
||||||
|
|
||||||
DFU_ITF_DESCR(1, dfu_proto_runtime)
|
DFU_ITF_DESCR(1, 0, dfu_proto_runtime)
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* fw/flash.c - Board-specific flash functions
|
* fw/flash.c - Board-specific flash functions
|
||||||
*
|
*
|
||||||
* Written 2011, 2013 by Werner Almesberger
|
* Written 2011, 2013, 2014 by Werner Almesberger
|
||||||
* Copyright 2011, 2013 Werner Almesberger
|
* Copyright 2011, 2013, 2014 Werner Almesberger
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -24,19 +24,19 @@
|
|||||||
static uint32_t payload;
|
static uint32_t payload;
|
||||||
|
|
||||||
|
|
||||||
void flash_start(void)
|
static void flash_start(void)
|
||||||
{
|
{
|
||||||
payload = 0;
|
payload = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool flash_can_write(uint16_t size)
|
static bool flash_can_write(uint16_t size)
|
||||||
{
|
{
|
||||||
return payload+size <= BOOT_ADDR;
|
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;
|
static uint8_t last;
|
||||||
const uint8_t *p;
|
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)) {
|
if (payload & (SPM_PAGESIZE-1)) {
|
||||||
boot_page_write(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;
|
uint16_t got = 0;
|
||||||
|
|
||||||
@ -83,3 +83,15 @@ uint16_t flash_read(uint8_t *buf, uint16_t size)
|
|||||||
}
|
}
|
||||||
return got;
|
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;
|
||||||
|
@ -42,6 +42,11 @@
|
|||||||
#define error(...)
|
#define error(...)
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DFU_ALT_SETTINGS
|
||||||
|
#define DFU_ALT_SETTINGS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
const uint8_t device_descriptor[] = {
|
const uint8_t device_descriptor[] = {
|
||||||
18, /* bLength */
|
18, /* bLength */
|
||||||
USB_DT_DEVICE, /* bDescriptorType */
|
USB_DT_DEVICE, /* bDescriptorType */
|
||||||
@ -67,7 +72,7 @@ const uint8_t device_descriptor[] = {
|
|||||||
const uint8_t config_descriptor[] = {
|
const uint8_t config_descriptor[] = {
|
||||||
9, /* bLength */
|
9, /* bLength */
|
||||||
USB_DT_CONFIG, /* bDescriptorType */
|
USB_DT_CONFIG, /* bDescriptorType */
|
||||||
LE(9+9), /* wTotalLength */
|
LE(9+9*DFU_ALT_SETTINGS), /* wTotalLength */
|
||||||
1, /* bNumInterfaces */
|
1, /* bNumInterfaces */
|
||||||
1, /* bConfigurationValue (> 0 !) */
|
1, /* bConfigurationValue (> 0 !) */
|
||||||
0, /* iConfiguration */
|
0, /* iConfiguration */
|
||||||
@ -77,7 +82,13 @@ const uint8_t config_descriptor[] = {
|
|||||||
|
|
||||||
/* Interface #0 */
|
/* 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;
|
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;
|
static uint16_t size;
|
||||||
|
|
||||||
if (!flash_can_write(length)) {
|
if (!dfu_flash_ops->can_write(length)) {
|
||||||
dfu.state = dfuERROR;
|
dfu.state = dfuERROR;
|
||||||
dfu.status = errADDRESS;
|
dfu.status = errADDRESS;
|
||||||
return 0;
|
return 0;
|
||||||
@ -125,7 +136,7 @@ static bool block_transmit(uint16_t length)
|
|||||||
dfu.status = errUNKNOWN;
|
dfu.status = errUNKNOWN;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
got = flash_read(buf, length);
|
got = dfu_flash_ops->read(buf, length);
|
||||||
if (got < length) {
|
if (got < length) {
|
||||||
length = got;
|
length = got;
|
||||||
dfu.state = dfuIDLE;
|
dfu.state = dfuIDLE;
|
||||||
@ -152,7 +163,7 @@ static bool my_setup(const struct setup_request *setup)
|
|||||||
debug("DFU_DNLOAD\n");
|
debug("DFU_DNLOAD\n");
|
||||||
if (dfu.state == dfuIDLE) {
|
if (dfu.state == dfuIDLE) {
|
||||||
next_block = setup->wValue;
|
next_block = setup->wValue;
|
||||||
flash_start();
|
dfu_flash_ops->start();
|
||||||
}
|
}
|
||||||
else if (dfu.state != dfuDNLOAD_IDLE) {
|
else if (dfu.state != dfuDNLOAD_IDLE) {
|
||||||
error("bad state\n");
|
error("bad state\n");
|
||||||
@ -171,7 +182,7 @@ static bool my_setup(const struct setup_request *setup)
|
|||||||
}
|
}
|
||||||
if (!setup->wLength) {
|
if (!setup->wLength) {
|
||||||
debug("DONE\n");
|
debug("DONE\n");
|
||||||
flash_end_write();
|
dfu_flash_ops->end_write();
|
||||||
dfu.state = dfuIDLE;
|
dfu.state = dfuIDLE;
|
||||||
did_download = 1;
|
did_download = 1;
|
||||||
return 1;
|
return 1;
|
||||||
@ -184,7 +195,7 @@ static bool my_setup(const struct setup_request *setup)
|
|||||||
debug("DFU_UPLOAD\n");
|
debug("DFU_UPLOAD\n");
|
||||||
if (dfu.state == dfuIDLE) {
|
if (dfu.state == dfuIDLE) {
|
||||||
next_block = setup->wValue;
|
next_block = setup->wValue;
|
||||||
flash_start();
|
dfu_flash_ops->start();
|
||||||
}
|
}
|
||||||
else if (dfu.state != dfuUPLOAD_IDLE)
|
else if (dfu.state != dfuUPLOAD_IDLE)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* boot/dfu.h - DFU protocol constants and data structures
|
* boot/dfu.h - DFU protocol constants and data structures
|
||||||
*
|
*
|
||||||
* Written 2008, 2011, 2013 by Werner Almesberger
|
* Written 2008, 2011, 2013, 2014 by Werner Almesberger
|
||||||
* Copyright 2008, 2011, 2013 Werner Almesberger
|
* Copyright 2008, 2011, 2013, 2014 Werner Almesberger
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* 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 */ \
|
9, /* bLength */ \
|
||||||
USB_DT_INTERFACE, /* bDescriptorType */ \
|
USB_DT_INTERFACE, /* bDescriptorType */ \
|
||||||
(itf), /* bInterfaceNumber */ \
|
(itf), /* bInterfaceNumber */ \
|
||||||
0, /* bAlternateSetting */ \
|
(alt), /* bAlternateSetting */ \
|
||||||
0, /* bNumEndpoints */ \
|
0, /* bNumEndpoints */ \
|
||||||
0xfe, /* bInterfaceClass (application specific) */ \
|
0xfe, /* bInterfaceClass (application specific) */ \
|
||||||
0x01, /* bInterfaceSubClass (device fw upgrade) */ \
|
0x01, /* bInterfaceSubClass (device fw upgrade) */ \
|
||||||
@ -98,15 +98,18 @@ struct dfu {
|
|||||||
0, /* iInterface */
|
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 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_setup_common(const struct setup_request *setup);
|
||||||
bool dfu_my_descr(uint8_t type, uint8_t index, const uint8_t **reply,
|
bool dfu_my_descr(uint8_t type, uint8_t index, const uint8_t **reply,
|
||||||
uint8_t *size);
|
uint8_t *size);
|
||||||
|
Loading…
Reference in New Issue
Block a user