CONFIG_DFU_NAND
This enables support for exposing NAND devices via DFU.
+ CONFIG_SYS_DFU_DATA_BUF_SIZE
+ Dfu transfer uses a buffer before writing data to the
+ raw storage device. Make the size (in bytes) of this buffer
+ configurable. The size of this buffer is also configurable
+ through the "dfu_bufsiz" environment variable.
+
CONFIG_SYS_DFU_MAX_FILE_SIZE
When updating files rather than the raw storage device,
we use a static buffer to copy the file into and then write
*/
#include <common.h>
+#include <errno.h>
#include <malloc.h>
#include <mmc.h>
#include <fat.h>
return ++i;
}
-static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
- dfu_buf[DFU_DATA_BUF_SIZE];
+static unsigned char *dfu_buf;
+static unsigned long dfu_buf_size = CONFIG_SYS_DFU_DATA_BUF_SIZE;
+
+static unsigned char *dfu_free_buf(void)
+{
+ free(dfu_buf);
+ dfu_buf = NULL;
+ return dfu_buf;
+}
+
+static unsigned char *dfu_get_buf(void)
+{
+ char *s;
+
+ if (dfu_buf != NULL)
+ return dfu_buf;
+
+ s = getenv("dfu_bufsiz");
+ dfu_buf_size = s ? (unsigned long)simple_strtol(s, NULL, 16) :
+ CONFIG_SYS_DFU_DATA_BUF_SIZE;
+
+ dfu_buf = memalign(CONFIG_SYS_CACHELINE_SIZE, dfu_buf_size);
+ if (dfu_buf == NULL)
+ printf("%s: Could not memalign 0x%lx bytes\n",
+ __func__, dfu_buf_size);
+
+ return dfu_buf;
+}
static int dfu_write_buffer_drain(struct dfu_entity *dfu)
{
dfu->offset = 0;
dfu->bad_skip = 0;
dfu->i_blk_seq_num = 0;
- dfu->i_buf_start = dfu_buf;
- dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
+ dfu->i_buf_start = dfu_get_buf();
+ if (dfu->i_buf_start == NULL)
+ return -ENOMEM;
+ dfu->i_buf_end = dfu_get_buf() + dfu_buf_size;
dfu->i_buf = dfu->i_buf_start;
dfu->inited = 1;
printf("\nDFU complete CRC32: 0x%08x\n", dfu->crc);
/* clear everything */
+ dfu_free_buf();
dfu->crc = 0;
dfu->offset = 0;
dfu->i_blk_seq_num = 0;
dfu->i_buf_start = dfu_buf;
- dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
+ dfu->i_buf_end = dfu_buf;
dfu->i_buf = dfu->i_buf_start;
dfu->inited = 0;
dfu->i_blk_seq_num = 0;
dfu->crc = 0;
dfu->offset = 0;
- dfu->i_buf_start = dfu_buf;
- dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
+ dfu->i_buf_start = dfu_get_buf();
+ if (dfu->i_buf_start == NULL)
+ return -ENOMEM;
+ dfu->i_buf_end = dfu_get_buf() + dfu_buf_size;
dfu->i_buf = dfu->i_buf_start;
dfu->b_left = 0;
debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name, dfu->crc);
puts("\nUPLOAD ... done\nCtrl+C to exit ...\n");
+ dfu_free_buf();
dfu->i_blk_seq_num = 0;
dfu->crc = 0;
dfu->offset = 0;
dfu->i_buf_start = dfu_buf;
- dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
+ dfu->i_buf_end = dfu_buf;
dfu->i_buf = dfu->i_buf_start;
dfu->b_left = 0;
static const struct asix_dongle const asix_dongles[] = {
{ 0x05ac, 0x1402, FLAG_TYPE_AX88772 }, /* Apple USB Ethernet Adapter */
{ 0x07d1, 0x3c05, FLAG_TYPE_AX88772 }, /* D-Link DUB-E100 H/W Ver B1 */
+ { 0x2001, 0x1a02, FLAG_TYPE_AX88772 }, /* D-Link DUB-E100 H/W Ver C1 */
/* Cables-to-Go USB Ethernet Adapter */
{ 0x0b95, 0x772a, FLAG_TYPE_AX88772 },
{ 0x0b95, 0x7720, FLAG_TYPE_AX88772 }, /* Trendnet TU2-ET100 V3.0R */
if (status < 0)
goto fail;
- cdev->desc = *composite->dev;
+ memcpy(&cdev->desc, composite->dev,
+ sizeof(struct usb_device_descriptor));
cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
debug("%s: ready\n", composite->name);
{
f_dfu->usb_function.strings = dfu_strings;
f_dfu->usb_function.hs_descriptors = f_dfu->function;
+ f_dfu->dfu_state = DFU_STATE_dfuIDLE;
}
static inline void to_runtime_mode(struct f_dfu *f_dfu)
case USB_REQ_DFU_DETACH:
f_dfu->dfu_state = DFU_STATE_appDETACH;
to_dfu_mode(f_dfu);
- f_dfu->dfu_state = DFU_STATE_dfuIDLE;
value = RET_ZLP;
break;
default:
struct usb_interface_descriptor *d;
int i = 0;
- f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n);
+ f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n + 1);
if (!f_dfu->function)
goto enomem;
->iInterface = id;
}
+ to_dfu_mode(f_dfu);
+
stringtab_dfu.strings = f_dfu->strings;
cdev->req->context = f_dfu;
{
struct fsg_dev *fsg = fsg_from_func(f);
struct usb_request *req = fsg->common->ep0req;
- u16 w_index = le16_to_cpu(ctrl->wIndex);
- u16 w_value = le16_to_cpu(ctrl->wValue);
- u16 w_length = le16_to_cpu(ctrl->wLength);
+ u16 w_index = get_unaligned_le16(&ctrl->wIndex);
+ u16 w_value = get_unaligned_le16(&ctrl->wValue);
+ u16 w_length = get_unaligned_le16(&ctrl->wLength);
if (!fsg_is_set(fsg->common))
return -EOPNOTSUPP;
"unknown class-specific control req "
"%02x.%02x v%04x i%04x l%u\n",
ctrl->bRequestType, ctrl->bRequest,
- le16_to_cpu(ctrl->wValue), w_index, w_length);
+ get_unaligned_le16(&ctrl->wValue), w_index, w_length);
return -EOPNOTSUPP;
}
return usb_add_config(cdev, &config);
}
+__weak
+int g_dnl_bind_fixup(struct usb_device_descriptor *dev)
+{
+ return 0;
+}
+
static int g_dnl_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
g_dnl_string_defs[1].id = id;
device_desc.iProduct = id;
+ g_dnl_bind_fixup(&device_desc);
ret = g_dnl_config_register(cdev);
if (ret)
goto error;
#include <common.h>
+#include <watchdog.h>
#include <asm/errno.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
int usb_gadget_handle_interrupts(void)
{
+ WATCHDOG_RESET();
if (!gadget || !gadget->isr)
return -EINVAL;
#define DFU_NAME_SIZE 32
#define DFU_CMD_BUF_SIZE 128
-#define DFU_DATA_BUF_SIZE (1024*1024*8) /* 8 MiB */
+#ifndef CONFIG_SYS_DFU_DATA_BUF_SIZE
+#define CONFIG_SYS_DFU_DATA_BUF_SIZE (1024*1024*8) /* 8 MiB */
+#endif
#ifndef CONFIG_SYS_DFU_MAX_FILE_SIZE
#define CONFIG_SYS_DFU_MAX_FILE_SIZE (4 << 20) /* 4 MiB */
#endif
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
-
+int g_dnl_bind_fixup(struct usb_device_descriptor *);
int g_dnl_register(const char *s);
void g_dnl_unregister(void);
/* private: */
/* internals */
unsigned int suspended:1;
- struct usb_device_descriptor desc;
+ struct usb_device_descriptor __aligned(CONFIG_SYS_CACHELINE_SIZE) desc;
struct list_head configs;
struct usb_composite_driver *driver;
u8 next_string_id;