All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function
@ 2012-07-03  9:38 Lukasz Majewski
  2012-07-03  9:38 ` [U-Boot] [PATCH 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
                   ` (12 more replies)
  0 siblings, 13 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-03  9:38 UTC (permalink / raw)
  To: u-boot

Those patches add support for composite USB download gadget.
This gadget (at least for now) is equipped with DFU download function.

A separate DFU back-end and front-end have been added.
Back-end is placed at ./drivers/dfu directory. The front-end is implemented
as USB function.

The back-end is written in a generic manner with storage device specific 
code separated (eMMC).

DFU specification can be found at:
http://wiki.openmoko.org/wiki/USB_DFU_-_The_USB_Device_Firmware_Upgrade_standard

Example usage:

u-boot side: dfu mmc 0 
PC: dfu-util -U IMAGE.bin -a uImage (for upload)
    dfu-util -D uImage -a uImage (download)

To list the alt settings:
	dfu mmc 0 list

Test HW:
	Exynos4210 Trats board

Lukasz Majewski (7):
  dfu:usb: Support for g_dnl composite download gadget.
  dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  dfu: DFU backend implementation
  dfu: MMC specific routines for DFU operation
  dfu:cmd: Support for DFU u-boot command
  arm:trats: Support for USB UDC driver at TRATS board.
  arm:trats: Enable g_dnl composite USB gadget with embedded DFU
    function on TRATS

 Makefile                    |    1 +
 board/samsung/trats/trats.c |    9 +
 common/Makefile             |    1 +
 common/cmd_dfu.c            |   81 ++++++
 drivers/dfu/Makefile        |   44 +++
 drivers/dfu/dfu.c           |  259 +++++++++++++++++
 drivers/dfu/dfu_mmc.c       |  126 ++++++++
 drivers/usb/gadget/Makefile |    2 +
 drivers/usb/gadget/f_dfu.c  |  666 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/f_dfu.h  |  100 +++++++
 drivers/usb/gadget/g_dnl.c  |  235 +++++++++++++++
 include/configs/trats.h     |   19 ++-
 include/dfu.h               |   99 +++++++
 include/g_dnl.h             |   33 +++
 14 files changed, 1674 insertions(+), 1 deletions(-)
 create mode 100644 common/cmd_dfu.c
 create mode 100644 drivers/dfu/Makefile
 create mode 100644 drivers/dfu/dfu.c
 create mode 100644 drivers/dfu/dfu_mmc.c
 create mode 100644 drivers/usb/gadget/f_dfu.c
 create mode 100644 drivers/usb/gadget/f_dfu.h
 create mode 100644 drivers/usb/gadget/g_dnl.c
 create mode 100644 include/dfu.h
 create mode 100644 include/g_dnl.h

-- 
1.7.2.3

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 1/7] dfu:usb: Support for g_dnl composite download gadget.
  2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
@ 2012-07-03  9:38 ` Lukasz Majewski
  2012-07-03 18:41   ` Marek Vasut
  2012-07-20  4:14   ` Mike Frysinger
  2012-07-03  9:38 ` [U-Boot] [PATCH 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
                   ` (11 subsequent siblings)
  12 siblings, 2 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-03  9:38 UTC (permalink / raw)
  To: u-boot

Composite USB download gadget support (g_dnl) for download functions.
This code works on top of composite gadget.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
---
 drivers/usb/gadget/Makefile |    1 +
 drivers/usb/gadget/g_dnl.c  |  235 +++++++++++++++++++++++++++++++++++++++++++
 include/g_dnl.h             |   33 ++++++
 3 files changed, 269 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/gadget/g_dnl.c
 create mode 100644 include/g_dnl.h

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 87d1918..2c067c8 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -29,6 +29,7 @@ LIB	:= $(obj)libusb_gadget.o
 ifdef CONFIG_USB_GADGET
 COBJS-y += epautoconf.o config.o usbstring.o
 COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
+COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
 endif
 ifdef CONFIG_USB_ETHER
 COBJS-y += ether.o epautoconf.o config.o usbstring.o
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
new file mode 100644
index 0000000..7925d0e
--- /dev/null
+++ b/drivers/usb/gadget/g_dnl.c
@@ -0,0 +1,235 @@
+/*
+ * g_dnl.c -- USB Downloader Gadget
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski  <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <errno.h>
+#include <common.h>
+#include <malloc.h>
+#include <linux/usb/ch9.h>
+#include <usbdescriptors.h>
+#include <linux/usb/gadget.h>
+
+#include <mmc.h>
+#include <part.h>
+
+#include <g_dnl.h>
+#include "f_dfu.h"
+
+#include "gadget_chips.h"
+#include "composite.c"
+
+/* Samsung's IDs */
+#define DRIVER_VENDOR_NUM 0x04E8
+#define DRIVER_PRODUCT_NUM 0x6601
+
+#define STRING_MANUFACTURER 25
+#define STRING_PRODUCT 2
+#define STRING_USBDOWN 2
+#define CONFIG_USBDOWNLOADER 2
+
+#define DRIVER_VERSION		"usb_dnl 2.0"
+
+static const char shortname[] = "usb_dnl_";
+static const char product[] = "SLP USB download gadget";
+static const char manufacturer[] = "Samsung";
+
+static struct usb_device_descriptor device_desc = {
+	.bLength =		sizeof device_desc,
+	.bDescriptorType =	USB_DT_DEVICE,
+
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_COMM,
+	.bDeviceSubClass =      0x02,	/*0x02:CDC-modem , 0x00:CDC-serial*/
+
+	.idVendor =		__constant_cpu_to_le16(DRIVER_VENDOR_NUM),
+	.idProduct =		__constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
+	.iProduct =		STRING_PRODUCT,
+	.bNumConfigurations =	1,
+};
+
+static const struct usb_descriptor_header *otg_desc[] = {
+	(struct usb_descriptor_header *) &(struct usb_otg_descriptor){
+		.bLength =		sizeof(struct usb_otg_descriptor),
+		.bDescriptorType =	USB_DT_OTG,
+		.bmAttributes =		USB_OTG_SRP,
+	},
+	NULL,
+};
+
+/* static strings, in UTF-8 */
+static struct usb_string odin_string_defs[] = {
+	{ 0, manufacturer, },
+	{ 1, product, },
+};
+
+static struct usb_gadget_strings odin_string_tab = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= odin_string_defs,
+};
+
+static struct usb_gadget_strings *g_dnl_composite_strings[] = {
+	&odin_string_tab,
+	NULL,
+};
+
+static int g_dnl_unbind(struct usb_composite_dev *cdev)
+{
+	debug("%s\n", __func__);
+	return 0;
+}
+
+static int g_dnl_do_config(struct usb_configuration *c)
+{
+	int ret = -1;
+	char *s = (char *) c->cdev->driver->name;
+
+	debug("%s: c: 0x%p cdev: 0x%p\n", __func__, c, c->cdev);
+
+	if (gadget_is_otg(c->cdev->gadget)) {
+		c->descriptors = otg_desc;
+		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
+	printf("GADGET DRIVER: %s\n", s);
+
+	if (!strcmp(s, "usb_dnl_dfu"))
+		ret = dfu_add(c);
+
+	return ret;
+}
+
+static int g_dnl_config_register(struct usb_composite_dev *cdev)
+{
+	debug("%s:\n", __func__);
+	static struct usb_configuration config = {
+		.label = "usb_dnload",
+		.bmAttributes =	USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+		.bConfigurationValue =	CONFIG_USBDOWNLOADER,
+		.iConfiguration =	STRING_USBDOWN,
+
+		.bind = g_dnl_do_config,
+	};
+
+	return usb_add_config(cdev, &config);
+}
+
+static int g_dnl_bind(struct usb_composite_dev *cdev)
+{
+	int			gcnum;
+	int id, ret;
+	struct usb_gadget	*gadget = cdev->gadget;
+
+	debug("%s: gadget: 0x%p cdev: 0x%p\n", __func__, gadget, cdev);
+
+	id = usb_string_id(cdev);
+
+	if (id < 0)
+		return id;
+	odin_string_defs[0].id = id;
+	device_desc.iManufacturer = id;
+
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+
+	odin_string_defs[1].id = id;
+	device_desc.iProduct = id;
+
+	ret = g_dnl_config_register(cdev);
+	if (ret)
+		goto error;
+
+
+	gcnum = usb_gadget_controller_number(gadget);
+
+	debug("gcnum: %d\n", gcnum);
+	if (gcnum >= 0)
+		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
+	else {
+		debug("%s: controller '%s' not recognized\n",
+			shortname, gadget->name);
+		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
+	}
+
+	return 0;
+
+ error:
+	g_dnl_unbind(cdev);
+	return -ENOMEM;
+}
+
+static void g_dnl_suspend(struct usb_composite_dev *cdev)
+{
+	if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
+		return;
+
+	debug("suspend\n");
+}
+
+static void g_dnl_resume(struct usb_composite_dev *cdev)
+{
+	debug("resume\n");
+}
+
+static struct usb_composite_driver g_dnl_driver = {
+	.name		= NULL,
+	.dev		= &device_desc,
+	.strings	= g_dnl_composite_strings,
+
+	.bind		= g_dnl_bind,
+	.unbind		= g_dnl_unbind,
+
+	.suspend	= g_dnl_suspend,
+	.resume		= g_dnl_resume,
+};
+
+int g_dnl_init(char *s)
+{
+	int ret;
+	static char str[16];
+
+	memset(str, '\0', sizeof(str));
+
+	strncpy(str, shortname, sizeof(shortname));
+
+	if (!strncmp(s, "dfu", sizeof(s))) {
+		strncat(str, s, sizeof(str));
+	} else {
+		printf("%s: unknown command: %s\n", __func__, s);
+		return -EINVAL;
+	}
+
+	g_dnl_driver.name = str;
+
+	debug("%s: g_dnl_driver.name: %s\n", __func__, g_dnl_driver.name);
+	ret = usb_composite_register(&g_dnl_driver);
+
+	if (ret) {
+		printf("%s: failed!, error:%d ", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+void g_dnl_cleanup(void)
+{
+	usb_composite_unregister(&g_dnl_driver);
+}
diff --git a/include/g_dnl.h b/include/g_dnl.h
new file mode 100644
index 0000000..5d0e9a5
--- /dev/null
+++ b/include/g_dnl.h
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (C) 2012 Samsung Electronics
+ *  Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __G_DOWNLOAD_H_
+#define __G_DOWNLOAD_H_
+
+#include <linux/usb/ch9.h>
+#include <usbdescriptors.h>
+#include <linux/usb/gadget.h>
+
+int g_dnl_init(char *s);
+void g_dnl_cleanup(void);
+
+/* USB initialization declaration - board specific*/
+void board_usb_init(void);
+#endif /* __G_DOWNLOAD_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
  2012-07-03  9:38 ` [U-Boot] [PATCH 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
@ 2012-07-03  9:38 ` Lukasz Majewski
  2012-07-03 21:21   ` Marek Vasut
  2012-07-03  9:38 ` [U-Boot] [PATCH 3/7] dfu: DFU backend implementation Lukasz Majewski
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-03  9:38 UTC (permalink / raw)
  To: u-boot

Support for f_dfu USB function.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
---
 drivers/usb/gadget/Makefile |    1 +
 drivers/usb/gadget/f_dfu.c  |  666 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/f_dfu.h  |  100 +++++++
 3 files changed, 767 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/gadget/f_dfu.c
 create mode 100644 drivers/usb/gadget/f_dfu.h

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 2c067c8..5bbdd36 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -30,6 +30,7 @@ ifdef CONFIG_USB_GADGET
 COBJS-y += epautoconf.o config.o usbstring.o
 COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
 COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
+COBJS-$(CONFIG_DFU_FUNCTION) += f_dfu.o
 endif
 ifdef CONFIG_USB_ETHER
 COBJS-y += ether.o epautoconf.o config.o usbstring.o
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
new file mode 100644
index 0000000..c2bf60c
--- /dev/null
+++ b/drivers/usb/gadget/f_dfu.c
@@ -0,0 +1,666 @@
+/*
+ * f_dfu.c -- Device Firmware Update USB function
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *          Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <errno.h>
+#include <common.h>
+#include <malloc.h>
+
+#include <linux/usb/ch9.h>
+#include <usbdescriptors.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/composite.h>
+
+#include <dfu.h>
+#include "f_dfu.h"
+
+struct f_dfu {
+	struct usb_function		usb_function;
+
+	struct usb_descriptor_header	**function;
+	struct usb_string		*strings;
+
+	/* when configured, we have one config */
+	u8				config;
+	u8				altsetting;
+	enum dfu_state			dfu_state;
+	unsigned int			dfu_status;
+
+	/* Send/received block number is handy for data integrity check */
+	int                             blk_seq_num;
+};
+
+static inline struct f_dfu *func_to_dfu(struct usb_function *f)
+{
+	return container_of(f, struct f_dfu, usb_function);
+}
+
+static const struct dfu_function_descriptor dfu_func = {
+	.bLength =		sizeof dfu_func,
+	.bDescriptorType =	DFU_DT_FUNC,
+	.bmAttributes =		DFU_BIT_WILL_DETACH |
+				DFU_BIT_MANIFESTATION_TOLERANT |
+				DFU_BIT_CAN_UPLOAD |
+				DFU_BIT_CAN_DNLOAD,
+	.wDetachTimeOut =	0,
+	.wTransferSize =	DFU_USB_BUFSIZ,
+	.bcdDFUVersion =	__constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_interface_descriptor dfu_intf_runtime = {
+	.bLength =		sizeof dfu_intf_runtime,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	.bNumEndpoints =	0,
+	.bInterfaceClass =	USB_CLASS_APP_SPEC,
+	.bInterfaceSubClass =	1,
+	.bInterfaceProtocol =	1,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_descriptor_header *dfu_runtime_descs[] = {
+	(struct usb_descriptor_header *) &dfu_intf_runtime,
+	NULL,
+};
+
+static struct usb_qualifier_descriptor dev_qualifier = {
+	.bLength =		sizeof dev_qualifier,
+	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
+	.bNumConfigurations =	1,
+};
+
+static const char dfu_name[] = "Device Firmware Upgrade";
+
+/* static strings, in UTF-8 */
+/*
+ * dfu_genericiguration specific
+ */
+static struct usb_string strings_dfu_generic[] = {
+	[0].s = dfu_name,
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab_dfu_generic = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_dfu_generic,
+};
+
+static struct usb_gadget_strings *dfu_generic_strings[] = {
+	&stringtab_dfu_generic,
+	NULL,
+};
+
+/*
+ * usb_function specific
+ */
+static struct usb_gadget_strings stringtab_dfu = {
+	.language	= 0x0409,	/* en-us */
+	/*
+	 * .strings
+	 *
+	 * assigned during initialization,
+	 * depends on number of flash entities
+	 *
+	 */
+};
+
+static struct usb_gadget_strings *dfu_strings[] = {
+	&stringtab_dfu,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
+		  req->length, f_dfu->blk_seq_num);
+
+	if (req->length == 0) {
+		puts("DOWNLOAD ... OK\n");
+		puts("Ctrl+C to exit ...\n");
+	}
+}
+
+static void handle_getstatus(struct usb_request *req)
+{
+	struct dfu_status *dstat = (struct dfu_status *)req->buf;
+	struct f_dfu *f_dfu = req->context;
+
+	switch (f_dfu->dfu_state) {
+	case DFU_STATE_dfuDNLOAD_SYNC:
+	case DFU_STATE_dfuDNBUSY:
+		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
+		break;
+	case DFU_STATE_dfuMANIFEST_SYNC:
+		break;
+	default:
+		break;
+	}
+
+	/* send status response */
+	dstat->bStatus = f_dfu->dfu_status;
+	/* FIXME: set dstat->bwPollTimeout */
+	dstat->bState = f_dfu->dfu_state;
+	dstat->iString = 0;
+}
+
+static void handle_getstate(struct usb_request *req)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	((u8 *)req->buf)[0] = f_dfu->dfu_state & 0xff;
+	req->actual = sizeof(u8);
+}
+
+static inline void to_dfu_mode(struct f_dfu *f_dfu)
+{
+	f_dfu->usb_function.strings = dfu_strings;
+	f_dfu->usb_function.hs_descriptors = f_dfu->function;
+}
+
+static inline void to_runtime_mode(struct f_dfu *f_dfu)
+{
+	f_dfu->usb_function.strings = NULL;
+	f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+}
+
+static int handle_upload(struct usb_request *req, u16 len)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	return dfu_read(dfu_get_entity(f_dfu->altsetting), req->buf,
+			req->length, f_dfu->blk_seq_num);
+}
+
+static int handle_dnload(struct usb_gadget *gadget, u16 len)
+{
+	struct usb_composite_dev *cdev = get_gadget_data(gadget);
+	struct usb_request *req = cdev->req;
+	struct f_dfu *f_dfu = req->context;
+
+	if (len == 0)
+		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
+
+	req->complete = dnload_request_complete;
+
+	return len;
+}
+
+
+static int
+dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct usb_gadget *gadget = f->config->cdev->gadget;
+	struct usb_request *req = f->config->cdev->req;
+	struct f_dfu *f_dfu = f->config->cdev->req->context;
+	u16 len = le16_to_cpu(ctrl->wLength);
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	int value = 0;
+	int standard;
+
+	standard = (ctrl->bRequestType & USB_TYPE_MASK)
+						== USB_TYPE_STANDARD;
+
+	debug("w_value: 0x%x len: 0x%x\n", w_value, len);
+	debug("standard: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n",
+	       standard, ctrl->bRequest, f_dfu->dfu_state);
+
+	if (!standard) {
+		switch (f_dfu->dfu_state) {
+		case DFU_STATE_appIDLE:
+			switch (ctrl->bRequest) {
+			case USB_REQ_DFU_GETSTATUS:
+				handle_getstatus(req);
+				value = RET_STAT_LEN;
+				break;
+			case USB_REQ_DFU_GETSTATE:
+				handle_getstate(req);
+				break;
+			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:
+				value = RET_STALL;
+				break;
+			}
+			break;
+		case DFU_STATE_appDETACH:
+			switch (ctrl->bRequest) {
+			case USB_REQ_DFU_GETSTATUS:
+				handle_getstatus(req);
+				value = RET_STAT_LEN;
+				break;
+			case USB_REQ_DFU_GETSTATE:
+				handle_getstate(req);
+				break;
+			default:
+				f_dfu->dfu_state = DFU_STATE_appIDLE;
+				value = RET_STALL;
+				break;
+			}
+			/* FIXME: implement timer to return to appIDLE */
+			break;
+		case DFU_STATE_dfuIDLE:
+			switch (ctrl->bRequest) {
+			case USB_REQ_DFU_DNLOAD:
+				if (len == 0) {
+					f_dfu->dfu_state = DFU_STATE_dfuERROR;
+					value = RET_STALL;
+					break;
+				}
+				f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
+				f_dfu->blk_seq_num = w_value;
+				value = handle_dnload(gadget, len);
+				break;
+			case USB_REQ_DFU_UPLOAD:
+				f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
+				f_dfu->blk_seq_num = 0;
+				value = handle_upload(req, len);
+				break;
+			case USB_REQ_DFU_ABORT:
+				/* no zlp? */
+				value = RET_ZLP;
+				break;
+			case USB_REQ_DFU_GETSTATUS:
+				handle_getstatus(req);
+				value = RET_STAT_LEN;
+				break;
+			case USB_REQ_DFU_GETSTATE:
+				handle_getstate(req);
+				break;
+			case USB_REQ_DFU_DETACH:
+			/*
+			 * Proprietary extension: 'detach' from idle mode and
+			 * get back to runtime mode in case of USB Reset.  As
+			 * much as I dislike this, we just can't use every USB
+			 * bus reset to switch back to runtime mode, since at
+			 * least the Linux USB stack likes to send a number of
+			 * resets in a row :(
+			 */
+				f_dfu->dfu_state =
+					DFU_STATE_dfuMANIFEST_WAIT_RST;
+				to_runtime_mode(f_dfu);
+				f_dfu->dfu_state = DFU_STATE_appIDLE;
+				break;
+			default:
+				f_dfu->dfu_state = DFU_STATE_dfuERROR;
+				value = RET_STALL;
+				break;
+			}
+			break;
+		case DFU_STATE_dfuDNLOAD_SYNC:
+			switch (ctrl->bRequest) {
+			case USB_REQ_DFU_GETSTATUS:
+				handle_getstatus(req);
+				value = RET_STAT_LEN;
+				break;
+				/* FIXME: state transition depending
+				 * on block completeness */
+			case USB_REQ_DFU_GETSTATE:
+				handle_getstate(req);
+				break;
+			default:
+				f_dfu->dfu_state = DFU_STATE_dfuERROR;
+				value = RET_STALL;
+				break;
+			}
+			break;
+		case DFU_STATE_dfuDNBUSY:
+			switch (ctrl->bRequest) {
+			case USB_REQ_DFU_GETSTATUS:
+				/* FIXME: only accept getstatus if bwPollTimeout
+				 * has elapsed */
+				handle_getstatus(req);
+				value = RET_STAT_LEN;
+				break;
+			default:
+				f_dfu->dfu_state = DFU_STATE_dfuERROR;
+				value = RET_STALL;
+				break;
+			}
+			break;
+		case DFU_STATE_dfuDNLOAD_IDLE:
+			switch (ctrl->bRequest) {
+			case USB_REQ_DFU_DNLOAD:
+				f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
+				f_dfu->blk_seq_num = w_value;
+				value = handle_dnload(gadget, len);
+				break;
+			case USB_REQ_DFU_ABORT:
+				f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+				value = RET_ZLP;
+				break;
+			case USB_REQ_DFU_GETSTATUS:
+				handle_getstatus(req);
+				value = RET_STAT_LEN;
+				break;
+			case USB_REQ_DFU_GETSTATE:
+				handle_getstate(req);
+				break;
+			default:
+				f_dfu->dfu_state = DFU_STATE_dfuERROR;
+				value = RET_STALL;
+				break;
+			}
+			break;
+		case DFU_STATE_dfuMANIFEST_SYNC:
+			switch (ctrl->bRequest) {
+			case USB_REQ_DFU_GETSTATUS:
+				/* We're MainfestationTolerant */
+				f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+				handle_getstatus(req);
+				f_dfu->blk_seq_num = 0;
+				value = RET_STAT_LEN;
+				break;
+			case USB_REQ_DFU_GETSTATE:
+				handle_getstate(req);
+				break;
+			default:
+				f_dfu->dfu_state = DFU_STATE_dfuERROR;
+				value = RET_STALL;
+				break;
+			}
+			break;
+		case DFU_STATE_dfuMANIFEST:
+			/* we should never go here */
+			f_dfu->dfu_state = DFU_STATE_dfuERROR;
+			value = RET_STALL;
+			break;
+		case DFU_STATE_dfuMANIFEST_WAIT_RST:
+			/* we should never go here */
+			break;
+		case DFU_STATE_dfuUPLOAD_IDLE:
+			switch (ctrl->bRequest) {
+			case USB_REQ_DFU_UPLOAD:
+			/* state transition if less data then requested */
+				f_dfu->blk_seq_num = w_value;
+				value = handle_upload(req, len);
+				if (value >= 0 && value < len)
+					f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+
+				break;
+			case USB_REQ_DFU_ABORT:
+				f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+				/* no zlp? */
+				value = RET_ZLP;
+				break;
+			case USB_REQ_DFU_GETSTATUS:
+				handle_getstatus(req);
+				value = RET_STAT_LEN;
+				break;
+			case USB_REQ_DFU_GETSTATE:
+				handle_getstate(req);
+				break;
+			default:
+				f_dfu->dfu_state = DFU_STATE_dfuERROR;
+				value = RET_STALL;
+				break;
+			}
+			break;
+		case DFU_STATE_dfuERROR:
+			switch (ctrl->bRequest) {
+			case USB_REQ_DFU_GETSTATUS:
+				handle_getstatus(req);
+				value = RET_STAT_LEN;
+				break;
+			case USB_REQ_DFU_GETSTATE:
+				handle_getstate(req);
+				break;
+			case USB_REQ_DFU_CLRSTATUS:
+				f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+				f_dfu->dfu_status = DFU_STATUS_OK;
+				/* no zlp? */
+				value = RET_ZLP;
+				break;
+			default:
+				f_dfu->dfu_state = DFU_STATE_dfuERROR;
+				value = RET_STALL;
+				break;
+			}
+			break;
+		default:
+			value = -1;
+		}
+	} else  {/* standard */
+		if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR &&
+		    (w_value >> 8) == DFU_DT_FUNC) {
+			value = min(len, (u16) sizeof dfu_func);
+			memcpy(req->buf, &dfu_func, value);
+		}
+	}
+
+	if (value >= 0) {
+		req->length = value;
+		req->zero = value < len;
+		value = usb_ep_queue(gadget->ep0, req, 0);
+		if (value < 0) {
+			debug("ep_queue --> %d\n", value);
+			req->status = 0;
+		}
+	}
+
+	return value;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+dfu_prepare_strings(struct f_dfu *f_dfu, int n)
+{
+	struct dfu_entity *de = NULL;
+	int i = 0;
+
+	f_dfu->strings = calloc(((n + 1) * sizeof(struct usb_string)), 1);
+	if (!f_dfu->strings)
+		goto enomem;
+
+	for (i = 0; i < n; ++i) {
+		de = dfu_get_entity(i);
+		f_dfu->strings[i].s = de->name;
+	}
+
+	f_dfu->strings[i].id = 0;
+	f_dfu->strings[i].s = NULL;
+
+	return 0;
+
+enomem:
+	while (i)
+		f_dfu->strings[--i].s = NULL;
+
+	kfree(f_dfu->strings);
+
+	return -ENOMEM;
+}
+
+static int dfu_prepare_function(struct f_dfu *f_dfu, int n)
+{
+	struct usb_interface_descriptor *d;
+	int i = 0;
+
+	f_dfu->function = calloc(n * sizeof(struct usb_descriptor_header *), 1);
+	if (!f_dfu->function)
+		goto enomem;
+
+	for (i = 0; i < n; ++i) {
+		d = kzalloc(sizeof(*d), GFP_KERNEL);
+		if (!d)
+			goto enomem;
+
+		d->bLength =		sizeof(*d);
+		d->bDescriptorType =	USB_DT_INTERFACE;
+		d->bAlternateSetting =	i;
+		d->bNumEndpoints =	0;
+		d->bInterfaceClass =	USB_CLASS_APP_SPEC;
+		d->bInterfaceSubClass =	1;
+		d->bInterfaceProtocol =	2;
+
+		f_dfu->function[i] = (struct usb_descriptor_header *)d;
+	}
+	f_dfu->function[i] = NULL;
+
+	return 0;
+
+enomem:
+	while (i) {
+		kfree(f_dfu->function[--i]);
+		f_dfu->function[i] = NULL;
+	}
+	kfree(f_dfu->function);
+
+	return -ENOMEM;
+}
+
+static int dfu_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	int alt_num = dfu_get_alt_number();
+	int rv, id, i;
+
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	dfu_intf_runtime.bInterfaceNumber = id;
+
+	f_dfu->dfu_state = DFU_STATE_appIDLE;
+	f_dfu->dfu_status = DFU_STATUS_OK;
+
+	rv = dfu_prepare_function(f_dfu, alt_num);
+	if (rv)
+		goto error;
+
+	rv = dfu_prepare_strings(f_dfu, alt_num);
+	if (rv)
+		goto error;
+	for (i = 0; i < alt_num; i++) {
+		id = usb_string_id(cdev);
+		if (id < 0)
+			return id;
+		f_dfu->strings[i].id = id;
+		((struct usb_interface_descriptor *)f_dfu->function[i])
+			->iInterface = id;
+	}
+
+	stringtab_dfu.strings = f_dfu->strings;
+
+	cdev->req->context = f_dfu;
+
+	return 0;
+error:
+	return rv;
+}
+
+static void dfu_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	int alt_num = dfu_get_alt_number();
+	int i;
+
+	if (f_dfu->strings) {
+		i = alt_num;
+		while (i)
+			f_dfu->strings[--i].s = NULL;
+
+		kfree(f_dfu->strings);
+	}
+
+	if (f_dfu->function) {
+		i = alt_num;
+		while (i) {
+			kfree(f_dfu->function[--i]);
+			f_dfu->function[i] = NULL;
+		}
+		kfree(f_dfu->function);
+	}
+
+	kfree(f_dfu);
+}
+
+static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+
+	debug("%s: intf:%d alt:%d\n", __func__, intf, alt);
+
+	f_dfu->altsetting = alt;
+
+	return 0;
+}
+
+/* TODO: is this really what we need here? */
+static void dfu_disable(struct usb_function *f)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	if (f_dfu->config == 0)
+		return;
+
+	debug("%s: reset config\n", __func__);
+
+	f_dfu->config = 0;
+}
+
+static int dfu_bind_config(struct usb_configuration *c)
+{
+	struct f_dfu *f_dfu;
+	int status;
+
+	f_dfu = kzalloc(sizeof(*f_dfu), GFP_KERNEL);
+	if (!f_dfu)
+		return -ENOMEM;
+	f_dfu->usb_function.name = "dfu";
+	f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+	f_dfu->usb_function.bind = dfu_bind;
+	f_dfu->usb_function.unbind = dfu_unbind;
+	f_dfu->usb_function.set_alt = dfu_set_alt;
+	f_dfu->usb_function.disable = dfu_disable;
+	f_dfu->usb_function.strings = dfu_generic_strings,
+	f_dfu->usb_function.setup = dfu_handle,
+
+	status = usb_add_function(c, &f_dfu->usb_function);
+	if (status)
+		kfree(f_dfu);
+
+	return status;
+}
+
+int dfu_add(struct usb_configuration *c)
+{
+	int id;
+
+	id = usb_string_id(c->cdev);
+	if (id < 0)
+		return id;
+	strings_dfu_generic[0].id = id;
+	dfu_intf_runtime.iInterface = id;
+
+	debug("%s: cdev: 0x%p gadget:0x%p gadget->ep0: 0x%p\n", __func__,
+	       c->cdev, c->cdev->gadget, c->cdev->gadget->ep0);
+
+	return dfu_bind_config(c);
+}
diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h
new file mode 100644
index 0000000..023e1ad
--- /dev/null
+++ b/drivers/usb/gadget/f_dfu.h
@@ -0,0 +1,100 @@
+/*
+ * f_dfu.h -- Device Firmware Update gadget
+ *
+ * Copyright (C) 2011-2012 Samsung Electronics
+ * author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __F_DFU_H_
+#define __F_DFU_H_
+
+#include <linux/compiler.h>
+#include <linux/usb/composite.h>
+
+#define DFU_CONFIG_VAL			1
+#define DFU_DT_FUNC			0x21
+
+#define DFU_BIT_WILL_DETACH		(0x1 << 3)
+#define DFU_BIT_MANIFESTATION_TOLERANT	(0x1 << 2)
+#define DFU_BIT_CAN_UPLOAD		(0x1 << 1)
+#define DFU_BIT_CAN_DNLOAD		0x1
+
+/* big enough to hold our biggest descriptor */
+#define DFU_USB_BUFSIZ			4096
+
+#define USB_REQ_DFU_DETACH		0x00
+#define USB_REQ_DFU_DNLOAD		0x01
+#define USB_REQ_DFU_UPLOAD		0x02
+#define USB_REQ_DFU_GETSTATUS		0x03
+#define USB_REQ_DFU_CLRSTATUS		0x04
+#define USB_REQ_DFU_GETSTATE		0x05
+#define USB_REQ_DFU_ABORT		0x06
+
+#define DFU_STATUS_OK			0x00
+#define DFU_STATUS_errTARGET		0x01
+#define DFU_STATUS_errFILE		0x02
+#define DFU_STATUS_errWRITE		0x03
+#define DFU_STATUS_errERASE		0x04
+#define DFU_STATUS_errCHECK_ERASED	0x05
+#define DFU_STATUS_errPROG		0x06
+#define DFU_STATUS_errVERIFY		0x07
+#define DFU_STATUS_errADDRESS		0x08
+#define DFU_STATUS_errNOTDONE		0x09
+#define DFU_STATUS_errFIRMWARE		0x0a
+#define DFU_STATUS_errVENDOR		0x0b
+#define DFU_STATUS_errUSBR		0x0c
+#define DFU_STATUS_errPOR		0x0d
+#define DFU_STATUS_errUNKNOWN		0x0e
+#define DFU_STATUS_errSTALLEDPKT	0x0f
+
+#define RET_STALL			-1
+#define RET_ZLP				0
+#define RET_STAT_LEN			6
+
+enum dfu_state {
+	DFU_STATE_appIDLE		= 0,
+	DFU_STATE_appDETACH		= 1,
+	DFU_STATE_dfuIDLE		= 2,
+	DFU_STATE_dfuDNLOAD_SYNC	= 3,
+	DFU_STATE_dfuDNBUSY		= 4,
+	DFU_STATE_dfuDNLOAD_IDLE	= 5,
+	DFU_STATE_dfuMANIFEST_SYNC	= 6,
+	DFU_STATE_dfuMANIFEST		= 7,
+	DFU_STATE_dfuMANIFEST_WAIT_RST	= 8,
+	DFU_STATE_dfuUPLOAD_IDLE	= 9,
+	DFU_STATE_dfuERROR		= 10,
+};
+
+struct dfu_status {
+	__u8				bStatus;
+	__u8				bwPollTimeout[3];
+	__u8				bState;
+	__u8				iString;
+} __packed;
+
+struct dfu_function_descriptor {
+	__u8				bLength;
+	__u8				bDescriptorType;
+	__u8				bmAttributes;
+	__le16				wDetachTimeOut;
+	__le16				wTransferSize;
+	__le16				bcdDFUVersion;
+} __packed;
+
+/* configuration-specific linkup */
+int dfu_add(struct usb_configuration *c);
+#endif /* __F_DFU_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 3/7] dfu: DFU backend implementation
  2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
  2012-07-03  9:38 ` [U-Boot] [PATCH 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
  2012-07-03  9:38 ` [U-Boot] [PATCH 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
@ 2012-07-03  9:38 ` Lukasz Majewski
  2012-07-03 21:28   ` Marek Vasut
  2012-07-20  4:32   ` Mike Frysinger
  2012-07-03  9:38 ` [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
                   ` (9 subsequent siblings)
  12 siblings, 2 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-03  9:38 UTC (permalink / raw)
  To: u-boot

New, separate driver at ./drivers/dfu has been added. It allows platform
and storage independent operation of DFU.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
---
 Makefile             |    1 +
 drivers/dfu/Makefile |   43 ++++++++
 drivers/dfu/dfu.c    |  259 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/dfu.h        |   99 +++++++++++++++++++
 4 files changed, 402 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dfu/Makefile
 create mode 100644 drivers/dfu/dfu.c
 create mode 100644 include/dfu.h

diff --git a/Makefile b/Makefile
index 0197239..c37dcf3 100644
--- a/Makefile
+++ b/Makefile
@@ -271,6 +271,7 @@ LIBS += drivers/pci/libpci.o
 LIBS += drivers/pcmcia/libpcmcia.o
 LIBS += drivers/power/libpower.o
 LIBS += drivers/spi/libspi.o
+LIBS += drivers/dfu/libdfu.o
 ifeq ($(CPU),mpc83xx)
 LIBS += drivers/qe/libqe.o
 LIBS += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o
diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
new file mode 100644
index 0000000..7736485
--- /dev/null
+++ b/drivers/dfu/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2012 Samsung Electronics
+# Lukasz Majewski <l.majewski@samsung.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)libdfu.o
+
+COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
+
+SRCS    := $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
new file mode 100644
index 0000000..63733fb
--- /dev/null
+++ b/drivers/dfu/dfu.c
@@ -0,0 +1,259 @@
+/*
+ * dfu.c -- DFU back-end routines
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <fat.h>
+#include <dfu.h>
+#include <linux/list.h>
+#include <linux/compiler.h>
+
+static LIST_HEAD(dfu_list);
+static int dfu_alt_num;
+
+static int dfu_find_alt_num(char *s)
+{
+	int i = 0;
+
+	for (; *s; s++)
+		if (*s == ';')
+			i++;
+
+	return ++i;
+}
+
+static char *dfu_extract_entity(char** env)
+{
+	char *s = *env;
+
+	strsep(env, ";");
+	return s;
+}
+
+char *dfu_extract_token(char** e, int *n)
+{
+	char *st = *e;
+
+	debug("%s: %s\n", __func__, st);
+
+	strsep(e, " ");
+	*n = *e - st;
+
+	return st;
+}
+
+static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
+				     dfu_buf[DFU_DATA_BUF_SIZE];
+
+int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
+{
+	static unsigned char *i_buf;
+	static int i_blk_seq_num;
+	long w_size = 0;
+	int ret = 0;
+
+	debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
+	       __func__, dfu->name, buf, size, blk_seq_num, i_buf);
+
+	if (blk_seq_num == 0) {
+		memset(dfu_buf, '\0', sizeof(dfu_buf));
+		i_buf = dfu_buf;
+		i_blk_seq_num = 0;
+	}
+
+	if (i_blk_seq_num++ != blk_seq_num) {
+		printf("%s: Wrong sequence number! [%d] [%d]\n",
+		       __func__, i_blk_seq_num, blk_seq_num);
+		return -1;
+	}
+
+	memcpy(i_buf, buf, size);
+	i_buf += size;
+
+	if (size == 0) {
+		/* Integrity check (if needed) */
+		debug("%s: %s %d [B] CRC32: 0x%x\n", __func__, dfu->name,
+		       i_buf - dfu_buf, crc32(0, dfu_buf, i_buf - dfu_buf));
+
+		w_size = i_buf - dfu_buf;
+		ret = dfu->write_medium(dfu, dfu_buf, &w_size);
+		if (ret)
+			debug("%s: Write error!\n", __func__);
+
+		i_blk_seq_num = 0;
+		i_buf = NULL;
+		return ret;
+	}
+
+	return ret;
+}
+
+int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
+{
+	static unsigned char *i_buf;
+	static int i_blk_seq_num;
+	static long r_size;
+	static u32 crc;
+	int ret = 0;
+
+	debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
+	       __func__, dfu->name, buf, size, blk_seq_num, i_buf);
+
+	if (blk_seq_num == 0) {
+		i_buf = dfu_buf;
+		memset(dfu_buf, '\0', sizeof(dfu_buf));
+		ret = dfu->read_medium(dfu, i_buf, &r_size);
+		debug("%s: %s %ld [B]\n", __func__, dfu->name, r_size);
+		i_blk_seq_num = 0;
+		/* Integrity check (if needed) */
+		crc = crc32(0, dfu_buf, r_size);
+	}
+
+	if (i_blk_seq_num++ != blk_seq_num) {
+		printf("%s: Wrong sequence number! [%d] [%d]\n",
+		       __func__, i_blk_seq_num, blk_seq_num);
+		return -1;
+	}
+
+	if (r_size >= size) {
+		memcpy(buf, i_buf, size);
+		i_buf += size;
+		r_size -= size;
+		return size;
+	} else {
+		memcpy(buf, i_buf, r_size);
+		i_buf += r_size;
+		debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name, crc);
+		puts("UPLOAD ... done\n");
+		puts("Ctrl+C to exit ...\n");
+
+		i_buf = NULL;
+		i_blk_seq_num = 0;
+		crc = 0;
+		return r_size;
+	}
+	return ret;
+}
+
+static int dfu_fill_entity(struct dfu_entity *dfu, char* s, int alt,
+			    char *interface, int num)
+{
+	char *st = NULL;
+	int n = 0;
+
+	debug("%s: %s interface: %s num: %d\n", __func__, s, interface, num);
+
+	st = dfu_extract_token(&s, &n);
+	strncpy((char *) &dfu->name, st, n);
+
+	dfu->dev_num = num;
+	dfu->alt = alt;
+
+	/* Specific for mmc device */
+	if (strcmp(interface, "mmc") == 0) {
+		if (dfu_fill_entity_mmc(dfu, s))
+			return -1;
+	} else {
+		printf("dfu: Device %s not supported\n", interface);
+		return -1;
+	}
+
+	return 0;
+}
+
+int dfu_config_entities(char *env, char *interface, int num)
+{
+	struct dfu_entity *dfu;
+	int i, ret;
+	char *s;
+
+	dfu_alt_num = dfu_find_alt_num(env);
+	debug("%s: dfu_alt_num=%d\n", __func__, dfu_alt_num);
+
+	for (i = 0; i < dfu_alt_num; i++) {
+		dfu = calloc(sizeof(struct dfu_entity), 1);
+
+		s = dfu_extract_entity(&env);
+		ret = dfu_fill_entity(dfu, s, i, interface, num);
+		if (ret)
+			return -1;
+
+		list_add_tail(&dfu->list, &dfu_list);
+	}
+
+	return 0;
+}
+
+void dfu_free_entities(void)
+{
+	struct dfu_entity *dfu = NULL, *p = NULL;
+
+	list_for_each_entry_safe_reverse(dfu, p, &dfu_list, list) {
+		list_del(&dfu->list);
+		free(dfu);
+	}
+
+	INIT_LIST_HEAD(&dfu_list);
+}
+
+static char *dfu_get_dev_type(enum dfu_device_type t)
+{
+	static char *dev_t[] = {NULL, "MMC", "ONENAND", "NAND" };
+	return dev_t[t];
+}
+
+static char *dfu_get_layout(enum dfu_device_type l)
+{
+	static char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT" };
+	return dfu_layout[l];
+}
+
+void dfu_show_entities(void)
+{
+	struct dfu_entity *dfu = NULL;
+
+	puts("DFU alt settings list:\n");
+
+	list_for_each_entry(dfu, &dfu_list, list) {
+		printf("dev: %s alt: %d name: %s layout: %s\n",
+		       dfu_get_dev_type(dfu->dev_type), dfu->alt,
+		       dfu->name, dfu_get_layout(dfu->layout));
+	}
+}
+
+int dfu_get_alt_number(void)
+{
+	return dfu_alt_num;
+}
+
+struct dfu_entity *dfu_get_entity(int alt)
+{
+	struct dfu_entity *dfu = NULL;
+
+	list_for_each_entry(dfu, &dfu_list, list) {
+		if (dfu->alt == alt)
+			return dfu;
+	}
+
+	return NULL;
+}
diff --git a/include/dfu.h b/include/dfu.h
new file mode 100644
index 0000000..f7d823b
--- /dev/null
+++ b/include/dfu.h
@@ -0,0 +1,99 @@
+/*
+ * dfu.h - DFU flashable area description
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __DFU_ENTITY_H_
+#define __DFU_ENTITY_H_
+
+#include <common.h>
+#include <linux/list.h>
+#include <mmc.h>
+
+enum dfu_device_type {
+	MMC = 1,
+	ONENAND,
+	NAND
+};
+
+enum dfu_layout {
+	RAW_ADDR = 1,
+	FAT,
+	EXT,
+};
+
+struct mmc_internal_data {
+	/* RAW programming */
+	unsigned int lba_start;
+	unsigned int lba_size;
+	unsigned int lba_blk_size;
+
+	/* FAT/EXT */
+	unsigned int dev;
+	unsigned int part;
+};
+
+static inline unsigned int get_mmc_blk_size(int dev)
+{
+	return find_mmc_device(dev)->read_bl_len;
+}
+
+#define DFU_NAME_SIZE 32
+#define DFU_CMD_BUF_SIZE 128
+#define DFU_DATA_BUF_SIZE (1024*1024*4) /* 4 MiB */
+
+struct dfu_entity {
+	char			name[DFU_NAME_SIZE];
+	int                     alt;
+	void                    *dev_private;
+	int                     dev_num;
+	enum dfu_device_type    dev_type;
+	enum dfu_layout         layout;
+
+	union {
+		struct mmc_internal_data mmc;
+	} data;
+
+	int (*read_medium)(struct dfu_entity *dfu, void *buf, long *len);
+	int (*write_medium)(struct dfu_entity *dfu, void *buf, long *len);
+
+	struct list_head list;
+};
+
+int dfu_config_entities(char *s, char *interface, int num);
+void dfu_free_entities(void);
+void dfu_show_entities(void);
+int dfu_get_alt_number(void);
+struct dfu_entity *dfu_get_entity(int alt);
+char *dfu_extract_token(char** e, int *n);
+
+int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
+int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
+/* Device specific */
+#ifdef CONFIG_DFU_MMC
+extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s);
+#else
+static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s)
+{
+	puts("MMC support not available!\n");
+	return -1;
+}
+#endif
+#endif /* __DFU_ENTITY_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
                   ` (2 preceding siblings ...)
  2012-07-03  9:38 ` [U-Boot] [PATCH 3/7] dfu: DFU backend implementation Lukasz Majewski
@ 2012-07-03  9:38 ` Lukasz Majewski
  2012-07-03 21:29   ` Marek Vasut
  2012-07-03  9:38 ` [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-03  9:38 UTC (permalink / raw)
  To: u-boot

Support for MMC storage devices to work with DFU framework.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
---
 drivers/dfu/Makefile  |    1 +
 drivers/dfu/dfu_mmc.c |  126 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 127 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dfu/dfu_mmc.c

diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
index 7736485..7b717bc 100644
--- a/drivers/dfu/Makefile
+++ b/drivers/dfu/Makefile
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)libdfu.o
 
 COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
+COBJS-$(CONFIG_DFU_MMC) += dfu_mmc.o
 
 SRCS    := $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS-y))
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
new file mode 100644
index 0000000..3151fbc
--- /dev/null
+++ b/drivers/dfu/dfu_mmc.c
@@ -0,0 +1,126 @@
+/*
+ * dfu.c -- DFU back-end routines
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <dfu.h>
+
+int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf, DFU_CMD_BUF_SIZE);
+
+	memset(cmd_buf, '\0', sizeof(cmd_buf));
+
+	switch (dfu->layout) {
+	case RAW_ADDR:
+		sprintf(cmd_buf, "mmc write 0x%x %x %x", (unsigned int) buf,
+			dfu->data.mmc.lba_start, dfu->data.mmc.lba_size);
+		break;
+	case FAT:
+		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx",
+			dfu->data.mmc.dev, dfu->data.mmc.part,
+			(unsigned int) buf, dfu->name, *len);
+		break;
+	default:
+		printf("%s: Wrong layout!\n", __func__);
+	}
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+	run_command(cmd_buf, 0);
+
+	return 0;
+}
+
+int dfu_read_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf, DFU_CMD_BUF_SIZE);
+	char *str_env = NULL;
+	int ret = 0;
+
+	memset(cmd_buf, '\0', sizeof(cmd_buf));
+
+	switch (dfu->layout) {
+	case RAW_ADDR:
+		sprintf(cmd_buf, "mmc read 0x%x %x %x", (unsigned int) buf,
+			dfu->data.mmc.lba_start, dfu->data.mmc.lba_size);
+
+		*len = dfu->data.mmc.lba_blk_size * dfu->data.mmc.lba_size;
+		break;
+	case FAT:
+		sprintf(cmd_buf, "fatload mmc %d:%d 0x%x %s",
+			dfu->data.mmc.dev, dfu->data.mmc.part,
+			(unsigned int) buf, dfu->name);
+		break;
+	default:
+		printf("%s: Wrong layout!\n", __func__);
+	}
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+
+	ret = run_command(cmd_buf, 0);
+	if (ret) {
+		puts("dfu: Read error!\n");
+		return ret;
+	}
+
+	if (dfu->layout != RAW_ADDR) {
+		str_env = getenv("filesize");
+		if (str_env == NULL) {
+			puts("dfu: Wrong file size!\n");
+			return -1;
+		}
+
+		*len = simple_strtoul(str_env, NULL, 16);
+	}
+	return ret;
+}
+
+int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s)
+{
+	char *st = NULL;
+	int n = 0;
+
+	dfu->dev_type = MMC;
+	st = dfu_extract_token(&s, &n);
+
+	if (!strncmp(st, "mmc", n)) {
+		dfu->layout = RAW_ADDR;
+
+		dfu->data.mmc.lba_start = simple_strtoul(s, &s, 16);
+		dfu->data.mmc.lba_size = simple_strtoul(++s, &s, 16);
+		dfu->data.mmc.lba_blk_size = get_mmc_blk_size(dfu->dev_num);
+
+	} else if (!strncmp(st, "fat", n)) {
+		dfu->layout = FAT;
+
+		dfu->data.mmc.dev = simple_strtoul(s, &s, 10);
+		dfu->data.mmc.part = simple_strtoul(++s, &s, 10);
+
+	} else {
+		printf("%s: Wrong memory layout!\n", __func__);
+	}
+
+	dfu->read_medium = dfu_read_medium_mmc;
+	dfu->write_medium = dfu_write_medium_mmc;
+
+	return 0;
+}
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
                   ` (3 preceding siblings ...)
  2012-07-03  9:38 ` [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
@ 2012-07-03  9:38 ` Lukasz Majewski
  2012-07-03 21:32   ` Marek Vasut
  2012-07-20  4:20   ` Mike Frysinger
  2012-07-03  9:38 ` [U-Boot] [PATCH 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
                   ` (7 subsequent siblings)
  12 siblings, 2 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-03  9:38 UTC (permalink / raw)
  To: u-boot

Support for u-boot's command line command "dfu <interface> <dev> [list]".

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
---
 common/Makefile  |    1 +
 common/cmd_dfu.c |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+), 0 deletions(-)
 create mode 100644 common/cmd_dfu.c

diff --git a/common/Makefile b/common/Makefile
index 6e23baa..de43ead 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -186,6 +186,7 @@ COBJS-$(CONFIG_MENU) += menu.o
 COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o
 COBJS-$(CONFIG_UPDATE_TFTP) += update.o
 COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
+COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o
 endif
 
 ifdef CONFIG_SPL_BUILD
diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
new file mode 100644
index 0000000..ceb0f54
--- /dev/null
+++ b/common/cmd_dfu.c
@@ -0,0 +1,81 @@
+/*
+ * cmd_dfu.c -- dfu command
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <dfu.h>
+#include <asm/errno.h>
+#include <g_dnl.h>
+
+int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	char *str_env = NULL, *env_bkp = NULL;
+	static char *s = "dfu";
+	int ret = 0;
+
+	if (argc < 3)
+		return CMD_RET_USAGE;
+
+	str_env = getenv("dfu_alt_info");
+	if (str_env == NULL) {
+		printf("%s: \"dfu_alt_info\" env variable not defined!\n",
+		       __func__);
+		return CMD_RET_FAILURE;
+	}
+
+	env_bkp = strdup(str_env);
+	ret = dfu_config_entities(env_bkp, argv[1],
+			    (int)simple_strtoul(argv[2], NULL, 10));
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	if (strcmp(argv[3], "list") == 0) {
+		dfu_show_entities();
+		dfu_free_entities();
+		free(env_bkp);
+		return CMD_RET_SUCCESS;
+	}
+
+	board_usb_init();
+	g_dnl_init(s);
+	while (1) {
+		if (ctrlc())
+			goto exit;
+
+		usb_gadget_handle_interrupts();
+	}
+exit:
+	g_dnl_cleanup();
+	dfu_free_entities();
+	free(env_bkp);
+
+	return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu,
+	"Device Firmware Upgrade",
+	"<interface> <dev> [list]\n"
+	"  - device firmware upgrade on a device <dev>\n"
+	"    attached to interface <interface>\n"
+	"    [list] - list available alt settings"
+);
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 6/7] arm:trats: Support for USB UDC driver at TRATS board.
  2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
                   ` (4 preceding siblings ...)
  2012-07-03  9:38 ` [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
@ 2012-07-03  9:38 ` Lukasz Majewski
  2012-07-04  0:20   ` Minkyu Kang
  2012-07-03  9:38 ` [U-Boot] [PATCH 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-03  9:38 UTC (permalink / raw)
  To: u-boot

Support for USB UDC driver at trats board.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Minkyu Kang <mk7.kang@samsung.com>
---
 board/samsung/trats/trats.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/board/samsung/trats/trats.c b/board/samsung/trats/trats.c
index a95a516..2f3a531 100644
--- a/board/samsung/trats/trats.c
+++ b/board/samsung/trats/trats.c
@@ -59,6 +59,8 @@ static int hwrevision(int rev)
 	return (board_rev & 0xf) == rev;
 }
 
+struct s3c_plat_otg_data s5pc210_otg_data;
+
 int board_init(void)
 {
 	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
@@ -259,6 +261,13 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
 	.usb_phy_ctrl	= EXYNOS4_USBPHY_CONTROL,
 	.usb_flags	= PHY0_SLEEP,
 };
+
+void board_usb_init(void)
+{
+	puts("USB_udc_probe\n");
+	s3c_udc_probe(&s5pc210_otg_data);
+
+}
 #endif
 
 static void pmic_reset(void)
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS
  2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
                   ` (5 preceding siblings ...)
  2012-07-03  9:38 ` [U-Boot] [PATCH 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
@ 2012-07-03  9:38 ` Lukasz Majewski
  2012-07-04  0:22   ` Minkyu Kang
  2012-07-03 12:52 ` [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Otavio Salvador
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-03  9:38 UTC (permalink / raw)
  To: u-boot

Enable the g_dnl composite USB gadget driver with embedded DFU function on it.
It now uses the composite gadget framework to support download specific
USB functions (like enabled DFU or USB Mass Storage).

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Minkyu Kang <mk7.kang@samsung.com>
---
 include/configs/trats.h |   19 ++++++++++++++++++-
 1 files changed, 18 insertions(+), 1 deletions(-)

diff --git a/include/configs/trats.h b/include/configs/trats.h
index 2f96a18..dcbd198 100644
--- a/include/configs/trats.h
+++ b/include/configs/trats.h
@@ -94,6 +94,16 @@
 #undef CONFIG_CMD_ONENAND
 #undef CONFIG_CMD_MTDPARTS
 #define CONFIG_CMD_MMC
+#define CONFIG_CMD_DFU
+
+/* FAT */
+#define CONFIG_CMD_FAT
+#define CONFIG_FAT_WRITE
+
+/* USB Composite download gadget - g_dnl */
+#define CONFIG_USBDOWNLOAD_GADGET
+#define CONFIG_DFU_FUNCTION
+#define CONFIG_DFU_MMC
 
 #define CONFIG_BOOTDELAY		1
 #define CONFIG_ZERO_BOOTDELAY_CHECK
@@ -104,6 +114,11 @@
 #define CONFIG_BOOTBLOCK		"10"
 #define CONFIG_ENV_COMMON_BOOT		"${console} ${meminfo}"
 
+#define CONFIG_DFU_ALT \
+	"dfu_alt_info=" \
+	"u-boot mmc 80 400;" \
+	"uImage fat 0 2\0" \
+
 #define CONFIG_ENV_OVERWRITE
 #define CONFIG_SYS_CONSOLE_INFO_QUIET
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
@@ -146,7 +161,8 @@
 	"mmcdev=0\0" \
 	"mmcbootpart=2\0" \
 	"mmcrootpart=3\0" \
-	"opts=always_resume=1"
+	"opts=always_resume=1\0" \
+	CONFIG_DFU_ALT
 
 /* Miscellaneous configurable options */
 #define CONFIG_SYS_LONGHELP		/* undef to save memory */
@@ -213,6 +229,7 @@
 #define CONFIG_USB_GADGET
 #define CONFIG_USB_GADGET_S3C_UDC_OTG
 #define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_GADGET_VBUS_DRAW	2
 
 /* LCD */
 #define CONFIG_EXYNOS_FB
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function
  2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
                   ` (6 preceding siblings ...)
  2012-07-03  9:38 ` [U-Boot] [PATCH 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
@ 2012-07-03 12:52 ` Otavio Salvador
  2012-07-03 12:59   ` Marek Vasut
  2012-07-04 15:48 ` [U-Boot] [PATCH v2 " Lukasz Majewski
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 147+ messages in thread
From: Otavio Salvador @ 2012-07-03 12:52 UTC (permalink / raw)
  To: u-boot

On Tue, Jul 3, 2012 at 6:38 AM, Lukasz Majewski <l.majewski@samsung.com> wrote:
> Those patches add support for composite USB download gadget.
> This gadget (at least for now) is equipped with DFU download function.

Awesome! :-)

-- 
Otavio Salvador                             O.S. Systems
E-mail: otavio at ossystems.com.br  http://www.ossystems.com.br
Mobile: +55 53 9981-7854              http://projetos.ossystems.com.br

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function
  2012-07-03 12:52 ` [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Otavio Salvador
@ 2012-07-03 12:59   ` Marek Vasut
  0 siblings, 0 replies; 147+ messages in thread
From: Marek Vasut @ 2012-07-03 12:59 UTC (permalink / raw)
  To: u-boot

Dear Otavio Salvador,

> On Tue, Jul 3, 2012 at 6:38 AM, Lukasz Majewski <l.majewski@samsung.com> 
wrote:
> > Those patches add support for composite USB download gadget.
> > This gadget (at least for now) is equipped with DFU download function.
> 
> Awesome! :-)

Hey Otavio ... we can do the same with our bootrom :-p

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 1/7] dfu:usb: Support for g_dnl composite download gadget.
  2012-07-03  9:38 ` [U-Boot] [PATCH 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
@ 2012-07-03 18:41   ` Marek Vasut
  2012-07-04  7:42     ` Lukasz Majewski
  2012-07-20  4:14   ` Mike Frysinger
  1 sibling, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-03 18:41 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> Composite USB download gadget support (g_dnl) for download functions.
> This code works on top of composite gadget.
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> ---
>  drivers/usb/gadget/Makefile |    1 +
>  drivers/usb/gadget/g_dnl.c  |  235
> +++++++++++++++++++++++++++++++++++++++++++ include/g_dnl.h             | 
>  33 ++++++
>  3 files changed, 269 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/usb/gadget/g_dnl.c
>  create mode 100644 include/g_dnl.h
> 
> diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
> index 87d1918..2c067c8 100644
> --- a/drivers/usb/gadget/Makefile
> +++ b/drivers/usb/gadget/Makefile
> @@ -29,6 +29,7 @@ LIB	:= $(obj)libusb_gadget.o
>  ifdef CONFIG_USB_GADGET
>  COBJS-y += epautoconf.o config.o usbstring.o
>  COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
> +COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
>  endif
>  ifdef CONFIG_USB_ETHER
>  COBJS-y += ether.o epautoconf.o config.o usbstring.o
> diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
> new file mode 100644
> index 0000000..7925d0e
> --- /dev/null
> +++ b/drivers/usb/gadget/g_dnl.c
> @@ -0,0 +1,235 @@
> +/*
> + * g_dnl.c -- USB Downloader Gadget
> + *
> + * Copyright (C) 2012 Samsung Electronics
> + * Lukasz Majewski  <l.majewski@samsung.com>
> + *
> + * 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
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 
> USA + */
> +
> +#include <errno.h>
> +#include <common.h>
> +#include <malloc.h>
> +#include <linux/usb/ch9.h>
> +#include <usbdescriptors.h>
> +#include <linux/usb/gadget.h>
> +
> +#include <mmc.h>
> +#include <part.h>
> +
> +#include <g_dnl.h>
> +#include "f_dfu.h"
> +
> +#include "gadget_chips.h"
> +#include "composite.c"
> +
> +/* Samsung's IDs */
> +#define DRIVER_VENDOR_NUM 0x04E8
> +#define DRIVER_PRODUCT_NUM 0x6601

Is it samsung specific? Or can we use some USB IDs that are not bound to 
samsung?

> +#define STRING_MANUFACTURER 25
> +#define STRING_PRODUCT 2
> +#define STRING_USBDOWN 2
> +#define CONFIG_USBDOWNLOADER 2
> +
> +#define DRIVER_VERSION		"usb_dnl 2.0"
> +
> +static const char shortname[] = "usb_dnl_";
> +static const char product[] = "SLP USB download gadget";
> +static const char manufacturer[] = "Samsung";

DITTO?

> +
> +static struct usb_device_descriptor device_desc = {
> +	.bLength =		sizeof device_desc,
> +	.bDescriptorType =	USB_DT_DEVICE,
> +
> +	.bcdUSB =		__constant_cpu_to_le16(0x0200),
> +	.bDeviceClass =		USB_CLASS_COMM,
> +	.bDeviceSubClass =      0x02,	/*0x02:CDC-modem , 0x00:CDC-serial*/
> +
> +	.idVendor =		__constant_cpu_to_le16(DRIVER_VENDOR_NUM),
> +	.idProduct =		__constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
> +	.iProduct =		STRING_PRODUCT,
> +	.bNumConfigurations =	1,
> +};
> +
> +static const struct usb_descriptor_header *otg_desc[] = {
> +	(struct usb_descriptor_header *) &(struct usb_otg_descriptor){
> +		.bLength =		sizeof(struct usb_otg_descriptor),
> +		.bDescriptorType =	USB_DT_OTG,
> +		.bmAttributes =		USB_OTG_SRP,
> +	},
> +	NULL,
> +};
> +
> +/* static strings, in UTF-8 */
> +static struct usb_string odin_string_defs[] = {
> +	{ 0, manufacturer, },
> +	{ 1, product, },
> +};
> +
> +static struct usb_gadget_strings odin_string_tab = {
> +	.language	= 0x0409,	/* en-us */
> +	.strings	= odin_string_defs,
> +};
> +
> +static struct usb_gadget_strings *g_dnl_composite_strings[] = {
> +	&odin_string_tab,
> +	NULL,
> +};
> +
> +static int g_dnl_unbind(struct usb_composite_dev *cdev)
> +{
> +	debug("%s\n", __func__);
> +	return 0;
> +}
> +
> +static int g_dnl_do_config(struct usb_configuration *c)
> +{
> +	int ret = -1;
> +	char *s = (char *) c->cdev->driver->name;
> +
> +	debug("%s: c: 0x%p cdev: 0x%p\n", __func__, c, c->cdev);

Can you elaborate in that debug message more? It's not really useful ;-)

> +	if (gadget_is_otg(c->cdev->gadget)) {
> +		c->descriptors = otg_desc;
> +		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
> +	}
> +
> +	printf("GADGET DRIVER: %s\n", s);
> +
> +	if (!strcmp(s, "usb_dnl_dfu"))
> +		ret = dfu_add(c);

And if this fails, we should set ret= as well, no?

> +
> +	return ret;
> +}
> +
> +static int g_dnl_config_register(struct usb_composite_dev *cdev)
> +{
> +	debug("%s:\n", __func__);
> +	static struct usb_configuration config = {
> +		.label = "usb_dnload",
> +		.bmAttributes =	USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
> +		.bConfigurationValue =	CONFIG_USBDOWNLOADER,
> +		.iConfiguration =	STRING_USBDOWN,
> +
> +		.bind = g_dnl_do_config,
> +	};
> +
> +	return usb_add_config(cdev, &config);
> +}
> +
> +static int g_dnl_bind(struct usb_composite_dev *cdev)
> +{
> +	int			gcnum;
> +	int id, ret;
> +	struct usb_gadget	*gadget = cdev->gadget;
> +
> +	debug("%s: gadget: 0x%p cdev: 0x%p\n", __func__, gadget, cdev);
> +
> +	id = usb_string_id(cdev);
> +
> +	if (id < 0)
> +		return id;
> +	odin_string_defs[0].id = id;
> +	device_desc.iManufacturer = id;
> +
> +	id = usb_string_id(cdev);
> +	if (id < 0)
> +		return id;
> +
> +	odin_string_defs[1].id = id;
> +	device_desc.iProduct = id;
> +
> +	ret = g_dnl_config_register(cdev);
> +	if (ret)
> +		goto error;
> +
> +

Two newlines

> +	gcnum = usb_gadget_controller_number(gadget);
> +
> +	debug("gcnum: %d\n", gcnum);
> +	if (gcnum >= 0)
> +		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
> +	else {
> +		debug("%s: controller '%s' not recognized\n",
> +			shortname, gadget->name);
> +		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
> +	}
> +
> +	return 0;
> +
> + error:
> +	g_dnl_unbind(cdev);
> +	return -ENOMEM;
> +}
> +
> +static void g_dnl_suspend(struct usb_composite_dev *cdev)
> +{
> +	if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
> +		return;
> +
> +	debug("suspend\n");
> +}
> +
> +static void g_dnl_resume(struct usb_composite_dev *cdev)
> +{
> +	debug("resume\n");
> +}

Maybe you should check if suspend/resume are set at all. Then you won't need the 
above stubs.

> +static struct usb_composite_driver g_dnl_driver = {
> +	.name		= NULL,
> +	.dev		= &device_desc,
> +	.strings	= g_dnl_composite_strings,
> +
> +	.bind		= g_dnl_bind,
> +	.unbind		= g_dnl_unbind,
> +
> +	.suspend	= g_dnl_suspend,
> +	.resume		= g_dnl_resume,
> +};
> +
> +int g_dnl_init(char *s)
> +{
> +	int ret;
> +	static char str[16];
> +

Why use '\0' if you can just use 0 ?

> +	memset(str, '\0', sizeof(str));
> +
> +	strncpy(str, shortname, sizeof(shortname));
> +
> +	if (!strncmp(s, "dfu", sizeof(s))) {
> +		strncat(str, s, sizeof(str));
> +	} else {
> +		printf("%s: unknown command: %s\n", __func__, s);
> +		return -EINVAL;
> +	}
> +
> +	g_dnl_driver.name = str;
> +
> +	debug("%s: g_dnl_driver.name: %s\n", __func__, g_dnl_driver.name);
> +	ret = usb_composite_register(&g_dnl_driver);
> +
> +	if (ret) {
> +		printf("%s: failed!, error:%d ", __func__, ret);

Missing newline in printf() (...error:%d ").

> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +void g_dnl_cleanup(void)
> +{
> +	usb_composite_unregister(&g_dnl_driver);
> +}
> diff --git a/include/g_dnl.h b/include/g_dnl.h
> new file mode 100644
> index 0000000..5d0e9a5
> --- /dev/null
> +++ b/include/g_dnl.h
> @@ -0,0 +1,33 @@
> +/*
> + *  Copyright (C) 2012 Samsung Electronics
> + *  Lukasz Majewski <l.majewski@samsung.com>
> + *
> + * 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 the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#ifndef __G_DOWNLOAD_H_
> +#define __G_DOWNLOAD_H_
> +
> +#include <linux/usb/ch9.h>
> +#include <usbdescriptors.h>
> +#include <linux/usb/gadget.h>
> +
> +int g_dnl_init(char *s);
> +void g_dnl_cleanup(void);
> +
> +/* USB initialization declaration - board specific*/
> +void board_usb_init(void);
> +#endif /* __G_DOWNLOAD_H_ */

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  2012-07-03  9:38 ` [U-Boot] [PATCH 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
@ 2012-07-03 21:21   ` Marek Vasut
  2012-07-04  8:39     ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-03 21:21 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> Support for f_dfu USB function.
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> ---
[...]
> +
> +static const char dfu_name[] = "Device Firmware Upgrade";
> +
> +/* static strings, in UTF-8 */
> +/*
> + * dfu_genericiguration specific


generi....what?

> + */
> +static struct usb_string strings_dfu_generic[] = {
> +	[0].s = dfu_name,
> +	{  }			/* end of list */
> +};
> +
> +static struct usb_gadget_strings stringtab_dfu_generic = {
> +	.language	= 0x0409,	/* en-us */
> +	.strings	= strings_dfu_generic,
> +};
> +
> +static struct usb_gadget_strings *dfu_generic_strings[] = {
> +	&stringtab_dfu_generic,
> +	NULL,
> +};
> +
> +/*
> + * usb_function specific
> + */
> +static struct usb_gadget_strings stringtab_dfu = {
> +	.language	= 0x0409,	/* en-us */
> +	/*
> +	 * .strings
> +	 *
> +	 * assigned during initialization,
> +	 * depends on number of flash entities
> +	 *
> +	 */
> +};
> +
> +static struct usb_gadget_strings *dfu_strings[] = {
> +	&stringtab_dfu,
> +	NULL,
> +};
> +
> +/*------------------------------------------------------------------------
> -*/ +
> +static void dnload_request_complete(struct usb_ep *ep, struct usb_request
> *req) +{
> +	struct f_dfu *f_dfu = req->context;
> +
> +	dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
> +		  req->length, f_dfu->blk_seq_num);
> +
> +	if (req->length == 0) {
> +		puts("DOWNLOAD ... OK\n");
> +		puts("Ctrl+C to exit ...\n");
> +	}
> +}
> +
> +static void handle_getstatus(struct usb_request *req)
> +{
> +	struct dfu_status *dstat = (struct dfu_status *)req->buf;
> +	struct f_dfu *f_dfu = req->context;
> +
> +	switch (f_dfu->dfu_state) {
> +	case DFU_STATE_dfuDNLOAD_SYNC:

What's this crazy cammel case in here ? :-)

> +	case DFU_STATE_dfuDNBUSY:
> +		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
> +		break;
> +	case DFU_STATE_dfuMANIFEST_SYNC:
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	/* send status response */
> +	dstat->bStatus = f_dfu->dfu_status;
> +	/* FIXME: set dstat->bwPollTimeout */

FIXME ... so fix it ;-)

> +	dstat->bState = f_dfu->dfu_state;
> +	dstat->iString = 0;
> +}
> +
> +static void handle_getstate(struct usb_request *req)
> +{
> +	struct f_dfu *f_dfu = req->context;
> +
> +	((u8 *)req->buf)[0] = f_dfu->dfu_state & 0xff;

Now ... this is ubercrazy ... can't this be made without this typecasting 
voodoo?

> +	req->actual = sizeof(u8);
> +}
> +
[...]
> +static int handle_dnload(struct usb_gadget *gadget, u16 len)
> +{
> +	struct usb_composite_dev *cdev = get_gadget_data(gadget);
> +	struct usb_request *req = cdev->req;
> +	struct f_dfu *f_dfu = req->context;
> +
> +	if (len == 0)
> +		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
> +
> +	req->complete = dnload_request_complete;
> +
> +	return len;
> +}

One newline too much below.

> +
> +
> +static int
> +dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
> +{
> +	struct usb_gadget *gadget = f->config->cdev->gadget;
> +	struct usb_request *req = f->config->cdev->req;
> +	struct f_dfu *f_dfu = f->config->cdev->req->context;
> +	u16 len = le16_to_cpu(ctrl->wLength);
> +	u16 w_value = le16_to_cpu(ctrl->wValue);
> +	int value = 0;
> +	int standard;
> +
> +	standard = (ctrl->bRequestType & USB_TYPE_MASK)
> +						== USB_TYPE_STANDARD;
> +
> +	debug("w_value: 0x%x len: 0x%x\n", w_value, len);
> +	debug("standard: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n",
> +	       standard, ctrl->bRequest, f_dfu->dfu_state);
> +
> +	if (!standard) {

This function doesn't fit on my screen ... that means it's waaaay too long and 
shall be split into more functions ;-)

That's also remove the need for your crazy conditional assignment of standard.

> +		switch (f_dfu->dfu_state) {
> +		case DFU_STATE_appIDLE:
> +			switch (ctrl->bRequest) {
> +			case USB_REQ_DFU_GETSTATUS:
> +				handle_getstatus(req);
> +				value = RET_STAT_LEN;
> +				break;
[...]

> +
> +/*------------------------------------------------------------------------
> -*/ +
> +static int
> +dfu_prepare_strings(struct f_dfu *f_dfu, int n)
> +{
> +	struct dfu_entity *de = NULL;
> +	int i = 0;
> +
> +	f_dfu->strings = calloc(((n + 1) * sizeof(struct usb_string)), 1);

calloc(n, 1) ... that's the same as malloc(), isn't it ?

> +	if (!f_dfu->strings)
> +		goto enomem;
> +
> +	for (i = 0; i < n; ++i) {
> +		de = dfu_get_entity(i);
> +		f_dfu->strings[i].s = de->name;
> +	}
> +
> +	f_dfu->strings[i].id = 0;
> +	f_dfu->strings[i].s = NULL;
> +
> +	return 0;
> +
> +enomem:
> +	while (i)
> +		f_dfu->strings[--i].s = NULL;
> +
> +	kfree(f_dfu->strings);
> +
> +	return -ENOMEM;
> +}
> +
> +static int dfu_prepare_function(struct f_dfu *f_dfu, int n)
> +{
> +	struct usb_interface_descriptor *d;
> +	int i = 0;
> +
> +	f_dfu->function = calloc(n * sizeof(struct usb_descriptor_header *), 1);

DITTO

> +	if (!f_dfu->function)
> +		goto enomem;
> +
> +	for (i = 0; i < n; ++i) {
> +		d = kzalloc(sizeof(*d), GFP_KERNEL);

Why use the kernel alternatives ? just use malloc()/free() ?

> +		if (!d)
> +			goto enomem;
> +
> +		d->bLength =		sizeof(*d);
> +		d->bDescriptorType =	USB_DT_INTERFACE;
> +		d->bAlternateSetting =	i;
> +		d->bNumEndpoints =	0;
> +		d->bInterfaceClass =	USB_CLASS_APP_SPEC;
> +		d->bInterfaceSubClass =	1;
> +		d->bInterfaceProtocol =	2;
> +
> +		f_dfu->function[i] = (struct usb_descriptor_header *)d;
> +	}
> +	f_dfu->function[i] = NULL;
> +
> +	return 0;
> +
> +enomem:
> +	while (i) {
> +		kfree(f_dfu->function[--i]);
> +		f_dfu->function[i] = NULL;
> +	}
> +	kfree(f_dfu->function);
> +
> +	return -ENOMEM;
> +}
> +
> +static int dfu_bind(struct usb_configuration *c, struct usb_function *f)
> +{
> +	struct usb_composite_dev *cdev = c->cdev;
> +	struct f_dfu *f_dfu = func_to_dfu(f);
> +	int alt_num = dfu_get_alt_number();
> +	int rv, id, i;
> +
> +	id = usb_interface_id(c, f);
> +	if (id < 0)
> +		return id;
> +	dfu_intf_runtime.bInterfaceNumber = id;
> +
> +	f_dfu->dfu_state = DFU_STATE_appIDLE;
> +	f_dfu->dfu_status = DFU_STATUS_OK;
> +
> +	rv = dfu_prepare_function(f_dfu, alt_num);
> +	if (rv)
> +		goto error;
> +
> +	rv = dfu_prepare_strings(f_dfu, alt_num);
> +	if (rv)
> +		goto error;
> +	for (i = 0; i < alt_num; i++) {
> +		id = usb_string_id(cdev);
> +		if (id < 0)
> +			return id;
> +		f_dfu->strings[i].id = id;
> +		((struct usb_interface_descriptor *)f_dfu->function[i])
> +			->iInterface = id;
> +	}
> +
> +	stringtab_dfu.strings = f_dfu->strings;
> +
> +	cdev->req->context = f_dfu;
> +
> +	return 0;
> +error:
> +	return rv;

So just return the retval ...

> +}
> +

Every time I review patches and find multiple small issues, I feel bad :-(

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 3/7] dfu: DFU backend implementation
  2012-07-03  9:38 ` [U-Boot] [PATCH 3/7] dfu: DFU backend implementation Lukasz Majewski
@ 2012-07-03 21:28   ` Marek Vasut
  2012-07-04  8:56     ` Lukasz Majewski
  2012-07-20  4:32   ` Mike Frysinger
  1 sibling, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-03 21:28 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> New, separate driver at ./drivers/dfu has been added. It allows platform
> and storage independent operation of DFU.
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> ---

[...]

> +#include <common.h>
> +#include <malloc.h>
> +#include <mmc.h>
> +#include <fat.h>
> +#include <dfu.h>
> +#include <linux/list.h>
> +#include <linux/compiler.h>
> +
> +static LIST_HEAD(dfu_list);
> +static int dfu_alt_num;
> +
> +static int dfu_find_alt_num(char *s)
> +{
> +	int i = 0;
> +
> +	for (; *s; s++)
> +		if (*s == ';')
> +			i++;
> +
> +	return ++i;
> +}
> +
> +static char *dfu_extract_entity(char** env)
> +{
> +	char *s = *env;
> +
> +	strsep(env, ";");
> +	return s;
> +}

Shall we not make these all generic? They seem to be quite helpful components.

> +
> +char *dfu_extract_token(char** e, int *n)
> +{
> +	char *st = *e;
> +
> +	debug("%s: %s\n", __func__, st);
> +
> +	strsep(e, " ");
> +	*n = *e - st;
> +
> +	return st;
> +}
> +
> +static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
> +				     dfu_buf[DFU_DATA_BUF_SIZE];

Can we not stack-allocate it with ALLOC_CACHE_ALIGN_BUFFER()?

[...]

> diff --git a/include/dfu.h b/include/dfu.h
> new file mode 100644
> index 0000000..f7d823b
> --- /dev/null
> +++ b/include/dfu.h

[...]

> +struct dfu_entity {
> +	char			name[DFU_NAME_SIZE];
> +	int                     alt;
> +	void                    *dev_private;
> +	int                     dev_num;
> +	enum dfu_device_type    dev_type;
> +	enum dfu_layout         layout;
> +
> +	union {
> +		struct mmc_internal_data mmc;

This union seems redundant ;-)

[...]

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-03  9:38 ` [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
@ 2012-07-03 21:29   ` Marek Vasut
  2012-07-03 21:55     ` Tom Rini
  0 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-03 21:29 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> Support for MMC storage devices to work with DFU framework.
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> ---

[...]

> +
> +#include <common.h>
> +#include <malloc.h>
> +#include <dfu.h>
> +
> +int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
> +{
> +	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf, DFU_CMD_BUF_SIZE);
> +
> +	memset(cmd_buf, '\0', sizeof(cmd_buf));
> +
> +	switch (dfu->layout) {
> +	case RAW_ADDR:
> +		sprintf(cmd_buf, "mmc write 0x%x %x %x", (unsigned int) buf,
> +			dfu->data.mmc.lba_start, dfu->data.mmc.lba_size);
> +		break;
> +	case FAT:
> +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx",
> +			dfu->data.mmc.dev, dfu->data.mmc.part,
> +			(unsigned int) buf, dfu->name, *len);
> +		break;
> +	default:
> +		printf("%s: Wrong layout!\n", __func__);
> +	}
> +
> +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> +	run_command(cmd_buf, 0);

Holy Moly ... can we not make this into simple calls to those subsystems ? 
Instead invoking command is crazy ;-)

[...]

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-03  9:38 ` [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
@ 2012-07-03 21:32   ` Marek Vasut
  2012-07-04  9:28     ` Lukasz Majewski
  2012-07-20  4:22     ` Mike Frysinger
  2012-07-20  4:20   ` Mike Frysinger
  1 sibling, 2 replies; 147+ messages in thread
From: Marek Vasut @ 2012-07-03 21:32 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> Support for u-boot's command line command "dfu <interface> <dev> [list]".
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> ---

[...]

> +int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +	char *str_env = NULL, *env_bkp = NULL;
> +	static char *s = "dfu";
> +	int ret = 0;
> +
> +	if (argc < 3)
> +		return CMD_RET_USAGE;
> +
> +	str_env = getenv("dfu_alt_info");
> +	if (str_env == NULL) {
> +		printf("%s: \"dfu_alt_info\" env variable not defined!\n",
> +		       __func__);

I was always curious if it's not possible to do something like 

puts(__func__ "rest of string");

Maybe it'd help the overhead a bit? Certainly, it's beyond the scope of this 
patchset, I'm just curious :)

> +		return CMD_RET_FAILURE;
> +	}

[...]

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-03 21:29   ` Marek Vasut
@ 2012-07-03 21:55     ` Tom Rini
  2012-07-03 22:01       ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Tom Rini @ 2012-07-03 21:55 UTC (permalink / raw)
  To: u-boot

On Tue, Jul 03, 2012 at 11:29:31PM +0200, Marek Vasut wrote:
> Dear Lukasz Majewski,
> 
> > Support for MMC storage devices to work with DFU framework.
> > 
> > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > Cc: Marek Vasut <marex@denx.de>
> > ---
> 
> [...]
> 
> > +
> > +#include <common.h>
> > +#include <malloc.h>
> > +#include <dfu.h>
> > +
> > +int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
> > +{
> > +	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf, DFU_CMD_BUF_SIZE);
> > +
> > +	memset(cmd_buf, '\0', sizeof(cmd_buf));
> > +
> > +	switch (dfu->layout) {
> > +	case RAW_ADDR:
> > +		sprintf(cmd_buf, "mmc write 0x%x %x %x", (unsigned int) buf,
> > +			dfu->data.mmc.lba_start, dfu->data.mmc.lba_size);
> > +		break;
> > +	case FAT:
> > +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx",
> > +			dfu->data.mmc.dev, dfu->data.mmc.part,
> > +			(unsigned int) buf, dfu->name, *len);
> > +		break;
> > +	default:
> > +		printf("%s: Wrong layout!\n", __func__);
> > +	}
> > +
> > +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> > +	run_command(cmd_buf, 0);
> 
> Holy Moly ... can we not make this into simple calls to those subsystems ? 
> Instead invoking command is crazy ;-)

Are they really simple?  There's a few other places we do this, and so
long as it's documented that DFU depends on CONFIG_FAT_WRITE for writing
to fat and so forth.

-- 
Tom

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-03 21:55     ` Tom Rini
@ 2012-07-03 22:01       ` Marek Vasut
  2012-07-03 22:06         ` Tom Rini
  2012-07-04  9:10         ` Lukasz Majewski
  0 siblings, 2 replies; 147+ messages in thread
From: Marek Vasut @ 2012-07-03 22:01 UTC (permalink / raw)
  To: u-boot

Dear Tom Rini,

> On Tue, Jul 03, 2012 at 11:29:31PM +0200, Marek Vasut wrote:
> > Dear Lukasz Majewski,
> > 
> > > Support for MMC storage devices to work with DFU framework.
> > > 
> > > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > Cc: Marek Vasut <marex@denx.de>
> > > ---
> > 
> > [...]
> > 
> > > +
> > > +#include <common.h>
> > > +#include <malloc.h>
> > > +#include <dfu.h>
> > > +
> > > +int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
> > > +{
> > > +	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf, DFU_CMD_BUF_SIZE);
> > > +
> > > +	memset(cmd_buf, '\0', sizeof(cmd_buf));
> > > +
> > > +	switch (dfu->layout) {
> > > +	case RAW_ADDR:
> > > +		sprintf(cmd_buf, "mmc write 0x%x %x %x", (unsigned int) buf,
> > > +			dfu->data.mmc.lba_start, dfu->data.mmc.lba_size);
> > > +		break;
> > > +	case FAT:
> > > +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx",
> > > +			dfu->data.mmc.dev, dfu->data.mmc.part,
> > > +			(unsigned int) buf, dfu->name, *len);
> > > +		break;
> > > +	default:
> > > +		printf("%s: Wrong layout!\n", __func__);
> > > +	}
> > > +
> > > +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> > > +	run_command(cmd_buf, 0);
> > 
> > Holy Moly ... can we not make this into simple calls to those subsystems
> > ? Instead invoking command is crazy ;-)
> 
> Are they really simple?  There's a few other places we do this, and so
> long as it's documented that DFU depends on CONFIG_FAT_WRITE for writing
> to fat and so forth.

Well ain't it easier to call fat_write() or similar?

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-03 22:01       ` Marek Vasut
@ 2012-07-03 22:06         ` Tom Rini
  2012-07-03 22:31           ` Marek Vasut
  2012-07-04  9:10         ` Lukasz Majewski
  1 sibling, 1 reply; 147+ messages in thread
From: Tom Rini @ 2012-07-03 22:06 UTC (permalink / raw)
  To: u-boot

On Wed, Jul 04, 2012 at 12:01:27AM +0200, Marek Vasut wrote:
> Dear Tom Rini,
> 
> > On Tue, Jul 03, 2012 at 11:29:31PM +0200, Marek Vasut wrote:
> > > Dear Lukasz Majewski,
> > > 
> > > > Support for MMC storage devices to work with DFU framework.
> > > > 
> > > > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > > > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > > Cc: Marek Vasut <marex@denx.de>
> > > > ---
> > > 
> > > [...]
> > > 
> > > > +
> > > > +#include <common.h>
> > > > +#include <malloc.h>
> > > > +#include <dfu.h>
> > > > +
> > > > +int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
> > > > +{
> > > > +	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf, DFU_CMD_BUF_SIZE);
> > > > +
> > > > +	memset(cmd_buf, '\0', sizeof(cmd_buf));
> > > > +
> > > > +	switch (dfu->layout) {
> > > > +	case RAW_ADDR:
> > > > +		sprintf(cmd_buf, "mmc write 0x%x %x %x", (unsigned int) buf,
> > > > +			dfu->data.mmc.lba_start, dfu->data.mmc.lba_size);
> > > > +		break;
> > > > +	case FAT:
> > > > +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx",
> > > > +			dfu->data.mmc.dev, dfu->data.mmc.part,
> > > > +			(unsigned int) buf, dfu->name, *len);
> > > > +		break;
> > > > +	default:
> > > > +		printf("%s: Wrong layout!\n", __func__);
> > > > +	}
> > > > +
> > > > +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> > > > +	run_command(cmd_buf, 0);
> > > 
> > > Holy Moly ... can we not make this into simple calls to those subsystems
> > > ? Instead invoking command is crazy ;-)
> > 
> > Are they really simple?  There's a few other places we do this, and so
> > long as it's documented that DFU depends on CONFIG_FAT_WRITE for writing
> > to fat and so forth.
> 
> Well ain't it easier to call fat_write() or similar?

Assuming that most of the logic in do_fat_fswrite is needed, no.  And I
think a good portion of it is, at first glance at least.

-- 
Tom

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-03 22:06         ` Tom Rini
@ 2012-07-03 22:31           ` Marek Vasut
  2012-07-03 22:33             ` Tom Rini
  0 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-03 22:31 UTC (permalink / raw)
  To: u-boot

Dear Tom Rini,

[...]

> > > > > +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> > > > > +	run_command(cmd_buf, 0);
> > > > 
> > > > Holy Moly ... can we not make this into simple calls to those
> > > > subsystems ? Instead invoking command is crazy ;-)
> > > 
> > > Are they really simple?  There's a few other places we do this, and so
> > > long as it's documented that DFU depends on CONFIG_FAT_WRITE for
> > > writing to fat and so forth.
> > 
> > Well ain't it easier to call fat_write() or similar?
> 
> Assuming that most of the logic in do_fat_fswrite is needed, no.  And I
> think a good portion of it is, at first glance at least.

Abstracting it out into a function won't cut it?

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-03 22:31           ` Marek Vasut
@ 2012-07-03 22:33             ` Tom Rini
  2012-07-03 23:07               ` Stephen Warren
  2012-07-04  0:13               ` Marek Vasut
  0 siblings, 2 replies; 147+ messages in thread
From: Tom Rini @ 2012-07-03 22:33 UTC (permalink / raw)
  To: u-boot

On Wed, Jul 04, 2012 at 12:31:14AM +0200, Marek Vasut wrote:
> Dear Tom Rini,
> 
> [...]
> 
> > > > > > +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> > > > > > +	run_command(cmd_buf, 0);
> > > > > 
> > > > > Holy Moly ... can we not make this into simple calls to those
> > > > > subsystems ? Instead invoking command is crazy ;-)
> > > > 
> > > > Are they really simple?  There's a few other places we do this, and so
> > > > long as it's documented that DFU depends on CONFIG_FAT_WRITE for
> > > > writing to fat and so forth.
> > > 
> > > Well ain't it easier to call fat_write() or similar?
> > 
> > Assuming that most of the logic in do_fat_fswrite is needed, no.  And I
> > think a good portion of it is, at first glance at least.
> 
> Abstracting it out into a function won't cut it?

My inclination would be to say that seems a bit sillier than just using
run_command(...) to call the existing command.

-- 
Tom

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-03 22:33             ` Tom Rini
@ 2012-07-03 23:07               ` Stephen Warren
  2012-07-03 23:38                 ` Tom Rini
  2012-07-04  0:13               ` Marek Vasut
  1 sibling, 1 reply; 147+ messages in thread
From: Stephen Warren @ 2012-07-03 23:07 UTC (permalink / raw)
  To: u-boot

On 07/03/2012 04:33 PM, Tom Rini wrote:
> On Wed, Jul 04, 2012 at 12:31:14AM +0200, Marek Vasut wrote:
>> Dear Tom Rini,
>>
>> [...]
>>
>>>>>>> +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
>>>>>>> +	run_command(cmd_buf, 0);
>>>>>>
>>>>>> Holy Moly ... can we not make this into simple calls to those
>>>>>> subsystems ? Instead invoking command is crazy ;-)
>>>>>
>>>>> Are they really simple?  There's a few other places we do this, and so
>>>>> long as it's documented that DFU depends on CONFIG_FAT_WRITE for
>>>>> writing to fat and so forth.
>>>>
>>>> Well ain't it easier to call fat_write() or similar?
>>>
>>> Assuming that most of the logic in do_fat_fswrite is needed, no.  And I
>>> think a good portion of it is, at first glance at least.
>>
>> Abstracting it out into a function won't cut it?
> 
> My inclination would be to say that seems a bit sillier than just using
> run_command(...) to call the existing command.

Abstracting into a function definitely means the compiler will be able
to type-check all the arguments to the function. Is the same true using
run_command; I assume everything gets serialized to an array of strings
and hence any validation is deferred until run-time then?

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-03 23:07               ` Stephen Warren
@ 2012-07-03 23:38                 ` Tom Rini
  2012-07-03 23:58                   ` Stephen Warren
  0 siblings, 1 reply; 147+ messages in thread
From: Tom Rini @ 2012-07-03 23:38 UTC (permalink / raw)
  To: u-boot

On Tue, Jul 03, 2012 at 05:07:04PM -0600, Stephen Warren wrote:
> On 07/03/2012 04:33 PM, Tom Rini wrote:
> > On Wed, Jul 04, 2012 at 12:31:14AM +0200, Marek Vasut wrote:
> >> Dear Tom Rini,
> >>
> >> [...]
> >>
> >>>>>>> +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> >>>>>>> +	run_command(cmd_buf, 0);
> >>>>>>
> >>>>>> Holy Moly ... can we not make this into simple calls to those
> >>>>>> subsystems ? Instead invoking command is crazy ;-)
> >>>>>
> >>>>> Are they really simple?  There's a few other places we do this, and so
> >>>>> long as it's documented that DFU depends on CONFIG_FAT_WRITE for
> >>>>> writing to fat and so forth.
> >>>>
> >>>> Well ain't it easier to call fat_write() or similar?
> >>>
> >>> Assuming that most of the logic in do_fat_fswrite is needed, no.  And I
> >>> think a good portion of it is, at first glance at least.
> >>
> >> Abstracting it out into a function won't cut it?
> > 
> > My inclination would be to say that seems a bit sillier than just using
> > run_command(...) to call the existing command.
> 
> Abstracting into a function definitely means the compiler will be able
> to type-check all the arguments to the function. Is the same true using
> run_command; I assume everything gets serialized to an array of strings
> and hence any validation is deferred until run-time then?

string is constructed with sprintf and that gives us some type checking.
Only cast today is buf to an unsigned int.  And the information either
comes from tools that should/must have done sanity checking or from the
'dfu' command which again should (didn't verify that patch yet) have
done sanity checking to get us this far.

-- 
Tom

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-03 23:38                 ` Tom Rini
@ 2012-07-03 23:58                   ` Stephen Warren
  0 siblings, 0 replies; 147+ messages in thread
From: Stephen Warren @ 2012-07-03 23:58 UTC (permalink / raw)
  To: u-boot

On 07/03/2012 05:38 PM, Tom Rini wrote:
> On Tue, Jul 03, 2012 at 05:07:04PM -0600, Stephen Warren wrote:
>> On 07/03/2012 04:33 PM, Tom Rini wrote:
>>> On Wed, Jul 04, 2012 at 12:31:14AM +0200, Marek Vasut wrote:
>>>> Dear Tom Rini,
>>>>
>>>> [...]
>>>>
>>>>>>>>> +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
>>>>>>>>> +	run_command(cmd_buf, 0);
>>>>>>>>
>>>>>>>> Holy Moly ... can we not make this into simple calls to those
>>>>>>>> subsystems ? Instead invoking command is crazy ;-)
>>>>>>>
>>>>>>> Are they really simple?  There's a few other places we do this, and so
>>>>>>> long as it's documented that DFU depends on CONFIG_FAT_WRITE for
>>>>>>> writing to fat and so forth.
>>>>>>
>>>>>> Well ain't it easier to call fat_write() or similar?
>>>>>
>>>>> Assuming that most of the logic in do_fat_fswrite is needed, no.  And I
>>>>> think a good portion of it is, at first glance at least.
>>>>
>>>> Abstracting it out into a function won't cut it?
>>>
>>> My inclination would be to say that seems a bit sillier than just using
>>> run_command(...) to call the existing command.
>>
>> Abstracting into a function definitely means the compiler will be able
>> to type-check all the arguments to the function. Is the same true using
>> run_command; I assume everything gets serialized to an array of strings
>> and hence any validation is deferred until run-time then?
> 
> string is constructed with sprintf and that gives us some type checking.
> Only cast today is buf to an unsigned int.  And the information either
> comes from tools that should/must have done sanity checking or from the
> 'dfu' command which again should (didn't verify that patch yet) have
> done sanity checking to get us this far.

So that checks the parameters against the sprintf format string, but
what checks that you chose the right format string for the command?

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-03 22:33             ` Tom Rini
  2012-07-03 23:07               ` Stephen Warren
@ 2012-07-04  0:13               ` Marek Vasut
  2012-07-20  4:25                 ` Mike Frysinger
  1 sibling, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-04  0:13 UTC (permalink / raw)
  To: u-boot

Dear Tom Rini,

> On Wed, Jul 04, 2012 at 12:31:14AM +0200, Marek Vasut wrote:
> > Dear Tom Rini,
> > 
> > [...]
> > 
> > > > > > > +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> > > > > > > +	run_command(cmd_buf, 0);
> > > > > > 
> > > > > > Holy Moly ... can we not make this into simple calls to those
> > > > > > subsystems ? Instead invoking command is crazy ;-)
> > > > > 
> > > > > Are they really simple?  There's a few other places we do this, and
> > > > > so long as it's documented that DFU depends on CONFIG_FAT_WRITE
> > > > > for writing to fat and so forth.
> > > > 
> > > > Well ain't it easier to call fat_write() or similar?
> > > 
> > > Assuming that most of the logic in do_fat_fswrite is needed, no.  And I
> > > think a good portion of it is, at first glance at least.
> > 
> > Abstracting it out into a function won't cut it?
> 
> My inclination would be to say that seems a bit sillier than just using
> run_command(...) to call the existing command.

Whose's syntax will likely soon change, breaking all this :-(

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 6/7] arm:trats: Support for USB UDC driver at TRATS board.
  2012-07-03  9:38 ` [U-Boot] [PATCH 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
@ 2012-07-04  0:20   ` Minkyu Kang
  2012-07-04  9:33     ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Minkyu Kang @ 2012-07-04  0:20 UTC (permalink / raw)
  To: u-boot

Dear Lukasz,

On 3 July 2012 18:38, Lukasz Majewski <l.majewski@samsung.com> wrote:
> Support for USB UDC driver at trats board.
>
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> Cc: Minkyu Kang <mk7.kang@samsung.com>
> ---
>  board/samsung/trats/trats.c |    9 +++++++++
>  1 files changed, 9 insertions(+), 0 deletions(-)
>
> diff --git a/board/samsung/trats/trats.c b/board/samsung/trats/trats.c
> index a95a516..2f3a531 100644
> --- a/board/samsung/trats/trats.c
> +++ b/board/samsung/trats/trats.c
> @@ -59,6 +59,8 @@ static int hwrevision(int rev)
>         return (board_rev & 0xf) == rev;
>  }
>
> +struct s3c_plat_otg_data s5pc210_otg_data;
> +
>  int board_init(void)
>  {
>         gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
> @@ -259,6 +261,13 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
>         .usb_phy_ctrl   = EXYNOS4_USBPHY_CONTROL,
>         .usb_flags      = PHY0_SLEEP,
>  };
> +
> +void board_usb_init(void)
> +{
> +       puts("USB_udc_probe\n");

is it useful information? or debug message?

> +       s3c_udc_probe(&s5pc210_otg_data);
> +
> +}
>  #endif
>

Thanks.
Minkyu Kang.
-- 
from. prom.
www.promsoft.net

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS
  2012-07-03  9:38 ` [U-Boot] [PATCH 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
@ 2012-07-04  0:22   ` Minkyu Kang
  0 siblings, 0 replies; 147+ messages in thread
From: Minkyu Kang @ 2012-07-04  0:22 UTC (permalink / raw)
  To: u-boot

On 3 July 2012 18:38, Lukasz Majewski <l.majewski@samsung.com> wrote:
> Enable the g_dnl composite USB gadget driver with embedded DFU function on it.
> It now uses the composite gadget framework to support download specific
> USB functions (like enabled DFU or USB Mass Storage).
>
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> Cc: Minkyu Kang <mk7.kang@samsung.com>
> ---
>  include/configs/trats.h |   19 ++++++++++++++++++-
>  1 files changed, 18 insertions(+), 1 deletions(-)
>

Acked-by: Minkyu Kang <mk7.kang@samsung.com>

-- 
from. prom.
www.promsoft.net

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 1/7] dfu:usb: Support for g_dnl composite download gadget.
  2012-07-03 18:41   ` Marek Vasut
@ 2012-07-04  7:42     ` Lukasz Majewski
  0 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04  7:42 UTC (permalink / raw)
  To: u-boot

Hi Marek,

Thanks for review.

> Dear Lukasz Majewski,
> 
> > Composite USB download gadget support (g_dnl) for download
> > functions. This code works on top of composite gadget.
> > 
> > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > Cc: Marek Vasut <marex@denx.de>
> > ---
> >  drivers/usb/gadget/Makefile |    1 +
> >  drivers/usb/gadget/g_dnl.c  |  235
> > +++++++++++++++++++++++++++++++++++++++++++
> > include/g_dnl.h             | 33 ++++++
> >  3 files changed, 269 insertions(+), 0 deletions(-)
> >  create mode 100644 drivers/usb/gadget/g_dnl.c
> >  create mode 100644 include/g_dnl.h
> > 
> > diff --git a/drivers/usb/gadget/Makefile
> > b/drivers/usb/gadget/Makefile index 87d1918..2c067c8 100644
> > --- a/drivers/usb/gadget/Makefile
> > +++ b/drivers/usb/gadget/Makefile
> > @@ -29,6 +29,7 @@ LIB	:= $(obj)libusb_gadget.o
> >  ifdef CONFIG_USB_GADGET
> >  COBJS-y += epautoconf.o config.o usbstring.o
> >  COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
> > +COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
> >  endif
> >  ifdef CONFIG_USB_ETHER
> >  COBJS-y += ether.o epautoconf.o config.o usbstring.o
> > diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
> > new file mode 100644
> > index 0000000..7925d0e
> > --- /dev/null
> > +++ b/drivers/usb/gadget/g_dnl.c
> > @@ -0,0 +1,235 @@
> > +/*
> > + * g_dnl.c -- USB Downloader Gadget
> > + *
> > + * Copyright (C) 2012 Samsung Electronics
> > + * Lukasz Majewski  <l.majewski@samsung.com>
> > + *
> > + * 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
> > + * the Free Software Foundation; either version 2 of the License,
> > or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public
> > License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
> > 02111-1307 USA + */
> > +
> > +#include <errno.h>
> > +#include <common.h>
> > +#include <malloc.h>
> > +#include <linux/usb/ch9.h>
> > +#include <usbdescriptors.h>
> > +#include <linux/usb/gadget.h>
> > +
> > +#include <mmc.h>
> > +#include <part.h>
> > +
> > +#include <g_dnl.h>
> > +#include "f_dfu.h"
> > +
> > +#include "gadget_chips.h"
> > +#include "composite.c"
> > +
> > +/* Samsung's IDs */
> > +#define DRIVER_VENDOR_NUM 0x04E8
> > +#define DRIVER_PRODUCT_NUM 0x6601
> 
> Is it samsung specific? Or can we use some USB IDs that are not bound
> to samsung?

I think, that those IDs shall be defined at include/configs/<board>.h
In that way one can use any ID.

> 
> > +#define STRING_MANUFACTURER 25
> > +#define STRING_PRODUCT 2
> > +#define STRING_USBDOWN 2
> > +#define CONFIG_USBDOWNLOADER 2
> > +
> > +#define DRIVER_VERSION		"usb_dnl 2.0"
> > +
> > +static const char shortname[] = "usb_dnl_";
> > +static const char product[] = "SLP USB download gadget";
> > +static const char manufacturer[] = "Samsung";
> 
> DITTO?

Manufacturer field can be either omitted or changed to other name.

> 
> > +
> > +static struct usb_device_descriptor device_desc = {
> > +	.bLength =		sizeof device_desc,
> > +	.bDescriptorType =	USB_DT_DEVICE,
> > +
> > +	.bcdUSB =		__constant_cpu_to_le16(0x0200),
> > +	.bDeviceClass =		USB_CLASS_COMM,
> > +	.bDeviceSubClass =      0x02,	/*0x02:CDC-modem ,
> > 0x00:CDC-serial*/ +
> > +	.idVendor =
> > __constant_cpu_to_le16(DRIVER_VENDOR_NUM),
> > +	.idProduct =
> > __constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
> > +	.iProduct =		STRING_PRODUCT,
> > +	.bNumConfigurations =	1,
> > +};
> > +
> > +static const struct usb_descriptor_header *otg_desc[] = {
> > +	(struct usb_descriptor_header *) &(struct
> > usb_otg_descriptor){
> > +		.bLength =		sizeof(struct
> > usb_otg_descriptor),
> > +		.bDescriptorType =	USB_DT_OTG,
> > +		.bmAttributes =		USB_OTG_SRP,
> > +	},
> > +	NULL,
> > +};
> > +
> > +/* static strings, in UTF-8 */
> > +static struct usb_string odin_string_defs[] = {
> > +	{ 0, manufacturer, },
> > +	{ 1, product, },
> > +};
> > +
> > +static struct usb_gadget_strings odin_string_tab = {
> > +	.language	= 0x0409,	/* en-us */
> > +	.strings	= odin_string_defs,
> > +};
> > +
> > +static struct usb_gadget_strings *g_dnl_composite_strings[] = {
> > +	&odin_string_tab,
> > +	NULL,
> > +};
> > +
> > +static int g_dnl_unbind(struct usb_composite_dev *cdev)
> > +{
> > +	debug("%s\n", __func__);
> > +	return 0;
> > +}
> > +
> > +static int g_dnl_do_config(struct usb_configuration *c)
> > +{
> > +	int ret = -1;
> > +	char *s = (char *) c->cdev->driver->name;
> > +
> > +	debug("%s: c: 0x%p cdev: 0x%p\n", __func__, c, c->cdev);
> 
> Can you elaborate in that debug message more? It's not really
> useful ;-)

I will correct that.

> 
> > +	if (gadget_is_otg(c->cdev->gadget)) {
> > +		c->descriptors = otg_desc;
> > +		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
> > +	}
> > +
> > +	printf("GADGET DRIVER: %s\n", s);
> > +
> > +	if (!strcmp(s, "usb_dnl_dfu"))
> > +		ret = dfu_add(c);
> 
> And if this fails, we should set ret= as well, no?

The dynamic variable "ret" is defined with -1 value on the beginning of
the function. When comparison fails, the -1 value is returned.

> 
> > +
> > +	return ret;
> > +}
> > +
> > +static int g_dnl_config_register(struct usb_composite_dev *cdev)
> > +{
> > +	debug("%s:\n", __func__);
> > +	static struct usb_configuration config = {
> > +		.label = "usb_dnload",
> > +		.bmAttributes =	USB_CONFIG_ATT_ONE |
> > USB_CONFIG_ATT_SELFPOWER,
> > +		.bConfigurationValue =	CONFIG_USBDOWNLOADER,
> > +		.iConfiguration =	STRING_USBDOWN,
> > +
> > +		.bind = g_dnl_do_config,
> > +	};
> > +
> > +	return usb_add_config(cdev, &config);
> > +}
> > +
> > +static int g_dnl_bind(struct usb_composite_dev *cdev)
> > +{
> > +	int			gcnum;
> > +	int id, ret;
> > +	struct usb_gadget	*gadget = cdev->gadget;
> > +
> > +	debug("%s: gadget: 0x%p cdev: 0x%p\n", __func__, gadget,
> > cdev); +
> > +	id = usb_string_id(cdev);
> > +
> > +	if (id < 0)
> > +		return id;
> > +	odin_string_defs[0].id = id;
> > +	device_desc.iManufacturer = id;
> > +
> > +	id = usb_string_id(cdev);
> > +	if (id < 0)
> > +		return id;
> > +
> > +	odin_string_defs[1].id = id;
> > +	device_desc.iProduct = id;
> > +
> > +	ret = g_dnl_config_register(cdev);
> > +	if (ret)
> > +		goto error;
> > +
> > +
> 
> Two newlines

Will fix.
> 
> > +	gcnum = usb_gadget_controller_number(gadget);
> > +
> > +	debug("gcnum: %d\n", gcnum);
> > +	if (gcnum >= 0)
> > +		device_desc.bcdDevice = cpu_to_le16(0x0200 +
> > gcnum);
> > +	else {
> > +		debug("%s: controller '%s' not recognized\n",
> > +			shortname, gadget->name);
> > +		device_desc.bcdDevice =
> > __constant_cpu_to_le16(0x9999);
> > +	}
> > +
> > +	return 0;
> > +
> > + error:
> > +	g_dnl_unbind(cdev);
> > +	return -ENOMEM;
> > +}
> > +
> > +static void g_dnl_suspend(struct usb_composite_dev *cdev)
> > +{
> > +	if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
> > +		return;
> > +
> > +	debug("suspend\n");
> > +}
> > +
> > +static void g_dnl_resume(struct usb_composite_dev *cdev)
> > +{
> > +	debug("resume\n");
> > +}
> 
> Maybe you should check if suspend/resume are set at all. Then you
> won't need the above stubs.

I will remove them.
> 
> > +static struct usb_composite_driver g_dnl_driver = {
> > +	.name		= NULL,
> > +	.dev		= &device_desc,
> > +	.strings	= g_dnl_composite_strings,
> > +
> > +	.bind		= g_dnl_bind,
> > +	.unbind		= g_dnl_unbind,
> > +
> > +	.suspend	= g_dnl_suspend,
> > +	.resume		= g_dnl_resume,
> > +};
> > +
> > +int g_dnl_init(char *s)
> > +{
> > +	int ret;
> > +	static char str[16];
> > +
> 
> Why use '\0' if you can just use 0 ?

I will change.
> 
> > +	memset(str, '\0', sizeof(str));
> > +
> > +	strncpy(str, shortname, sizeof(shortname));
> > +
> > +	if (!strncmp(s, "dfu", sizeof(s))) {
> > +		strncat(str, s, sizeof(str));
> > +	} else {
> > +		printf("%s: unknown command: %s\n", __func__, s);
> > +		return -EINVAL;
> > +	}
> > +
> > +	g_dnl_driver.name = str;
> > +
> > +	debug("%s: g_dnl_driver.name: %s\n", __func__,
> > g_dnl_driver.name);
> > +	ret = usb_composite_register(&g_dnl_driver);
> > +
> > +	if (ret) {
> > +		printf("%s: failed!, error:%d ", __func__, ret);
> 
> Missing newline in printf() (...error:%d ").

I will change that.

> 
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +void g_dnl_cleanup(void)
> > +{
> > +	usb_composite_unregister(&g_dnl_driver);
> > +}
> > diff --git a/include/g_dnl.h b/include/g_dnl.h
> > new file mode 100644
> > index 0000000..5d0e9a5
> > --- /dev/null
> > +++ b/include/g_dnl.h
> > @@ -0,0 +1,33 @@
> > +/*
> > + *  Copyright (C) 2012 Samsung Electronics
> > + *  Lukasz Majewski <l.majewski@samsung.com>
> > + *
> > + * 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 the Free Software Foundation; either version 2 of
> > + * the License, or (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public
> > License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> > + * MA 02111-1307 USA
> > + */
> > +
> > +#ifndef __G_DOWNLOAD_H_
> > +#define __G_DOWNLOAD_H_
> > +
> > +#include <linux/usb/ch9.h>
> > +#include <usbdescriptors.h>
> > +#include <linux/usb/gadget.h>
> > +
> > +int g_dnl_init(char *s);
> > +void g_dnl_cleanup(void);
> > +
> > +/* USB initialization declaration - board specific*/
> > +void board_usb_init(void);
> > +#endif /* __G_DOWNLOAD_H_ */



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  2012-07-03 21:21   ` Marek Vasut
@ 2012-07-04  8:39     ` Lukasz Majewski
  2012-07-04 14:35       ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04  8:39 UTC (permalink / raw)
  To: u-boot

Hi Marek,

> Dear Lukasz Majewski,
> 
> > Support for f_dfu USB function.
> > 
> > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > Cc: Marek Vasut <marex@denx.de>
> > ---
> [...]
> > +
> > +static const char dfu_name[] = "Device Firmware Upgrade";
> > +
> > +/* static strings, in UTF-8 */
> > +/*
> > + * dfu_genericiguration specific
> 
> 
> generi....what?

Misspelled, fixed.
> 
> > + */
> > +static struct usb_string strings_dfu_generic[] = {
> > +	[0].s = dfu_name,
> > +	{  }			/* end of list */
> > +};
> > +
> > +static struct usb_gadget_strings stringtab_dfu_generic = {
> > +	.language	= 0x0409,	/* en-us */
> > +	.strings	= strings_dfu_generic,
> > +};
> > +
> > +static struct usb_gadget_strings *dfu_generic_strings[] = {
> > +	&stringtab_dfu_generic,
> > +	NULL,
> > +};
> > +
> > +/*
> > + * usb_function specific
> > + */
> > +static struct usb_gadget_strings stringtab_dfu = {
> > +	.language	= 0x0409,	/* en-us */
> > +	/*
> > +	 * .strings
> > +	 *
> > +	 * assigned during initialization,
> > +	 * depends on number of flash entities
> > +	 *
> > +	 */
> > +};
> > +
> > +static struct usb_gadget_strings *dfu_strings[] = {
> > +	&stringtab_dfu,
> > +	NULL,
> > +};
> > +
> > +/*------------------------------------------------------------------------
> > -*/ +
> > +static void dnload_request_complete(struct usb_ep *ep, struct
> > usb_request *req) +{
> > +	struct f_dfu *f_dfu = req->context;
> > +
> > +	dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
> > +		  req->length, f_dfu->blk_seq_num);
> > +
> > +	if (req->length == 0) {
> > +		puts("DOWNLOAD ... OK\n");
> > +		puts("Ctrl+C to exit ...\n");
> > +	}
> > +}
> > +
> > +static void handle_getstatus(struct usb_request *req)
> > +{
> > +	struct dfu_status *dstat = (struct dfu_status *)req->buf;
> > +	struct f_dfu *f_dfu = req->context;
> > +
> > +	switch (f_dfu->dfu_state) {
> > +	case DFU_STATE_dfuDNLOAD_SYNC:
> 
> What's this crazy cammel case in here ? :-)

I know, that camel case descriptions are not welcome :-),
but those are written in this way for purpose.

dfuDNLOAD_SYNC is the exact state name mentioned at DFU specification.
Other states - like dfuDNBUSY are exactly the same.

From mine experience it is more readable. Please consider for
example the Fig. A1 - Interface state transition diagram from page 28
at DFU_1.1.pdf spec (link below).

http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf

> 
> > +	case DFU_STATE_dfuDNBUSY:
> > +		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
> > +		break;
> > +	case DFU_STATE_dfuMANIFEST_SYNC:
> > +		break;
> > +	default:
> > +		break;
> > +	}
> > +
> > +	/* send status response */
> > +	dstat->bStatus = f_dfu->dfu_status;
> > +	/* FIXME: set dstat->bwPollTimeout */
> 
> FIXME ... so fix it ;-)
This is not u-boot related - will be removed 

> 
> > +	dstat->bState = f_dfu->dfu_state;
> > +	dstat->iString = 0;
> > +}
> > +
> > +static void handle_getstate(struct usb_request *req)
> > +{
> > +	struct f_dfu *f_dfu = req->context;
> > +
> > +	((u8 *)req->buf)[0] = f_dfu->dfu_state & 0xff;
> 
> Now ... this is ubercrazy ... can't this be made without this
> typecasting voodoo?

The problem is that req->buf is a void pointer. And the goal is to
store dfu state at 8 bits.

> 
> > +	req->actual = sizeof(u8);
> > +}
> > +
> [...]
> > +static int handle_dnload(struct usb_gadget *gadget, u16 len)
> > +{
> > +	struct usb_composite_dev *cdev = get_gadget_data(gadget);
> > +	struct usb_request *req = cdev->req;
> > +	struct f_dfu *f_dfu = req->context;
> > +
> > +	if (len == 0)
> > +		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
> > +
> > +	req->complete = dnload_request_complete;
> > +
> > +	return len;
> > +}
> 
> One newline too much below.
Fixed.
> 
> > +
> > +
> > +static int
> > +dfu_handle(struct usb_function *f, const struct usb_ctrlrequest
> > *ctrl) +{
> > +	struct usb_gadget *gadget = f->config->cdev->gadget;
> > +	struct usb_request *req = f->config->cdev->req;
> > +	struct f_dfu *f_dfu = f->config->cdev->req->context;
> > +	u16 len = le16_to_cpu(ctrl->wLength);
> > +	u16 w_value = le16_to_cpu(ctrl->wValue);
> > +	int value = 0;
> > +	int standard;
> > +
> > +	standard = (ctrl->bRequestType & USB_TYPE_MASK)
> > +						==
> > USB_TYPE_STANDARD; +
> > +	debug("w_value: 0x%x len: 0x%x\n", w_value, len);
> > +	debug("standard: 0x%x ctrl->bRequest: 0x%x
> > f_dfu->dfu_state: 0x%x\n",
> > +	       standard, ctrl->bRequest, f_dfu->dfu_state);
> > +
> > +	if (!standard) {
> 
> This function doesn't fit on my screen ... that means it's waaaay too
> long and shall be split into more functions ;-)
> 
> That's also remove the need for your crazy conditional assignment of
> standard.

You are correct :-). I will split the if(!standard) clause to two
separate. It shall improve readability.

> 
> > +		switch (f_dfu->dfu_state) {
> > +		case DFU_STATE_appIDLE:
> > +			switch (ctrl->bRequest) {
> > +			case USB_REQ_DFU_GETSTATUS:
> > +				handle_getstatus(req);
> > +				value = RET_STAT_LEN;
> > +				break;
> [...]
> 
> > +
> > +/*------------------------------------------------------------------------
> > -*/ +
> > +static int
> > +dfu_prepare_strings(struct f_dfu *f_dfu, int n)
> > +{
> > +	struct dfu_entity *de = NULL;
> > +	int i = 0;
> > +
> > +	f_dfu->strings = calloc(((n + 1) * sizeof(struct
> > usb_string)), 1);
> 
> calloc(n, 1) ... that's the same as malloc(), isn't it ?

I now wonder how mine mind produced this :-)

Correct version:

f_dfu->strings = calloc(sizeof(struct usb_string), n + 1);

I prefer calloc, since it delivers zeroed memory.

> 
> > +	if (!f_dfu->strings)
> > +		goto enomem;
> > +
> > +	for (i = 0; i < n; ++i) {
> > +		de = dfu_get_entity(i);
> > +		f_dfu->strings[i].s = de->name;
> > +	}
> > +
> > +	f_dfu->strings[i].id = 0;
> > +	f_dfu->strings[i].s = NULL;
> > +
> > +	return 0;
> > +
> > +enomem:
> > +	while (i)
> > +		f_dfu->strings[--i].s = NULL;
> > +
> > +	kfree(f_dfu->strings);
> > +
> > +	return -ENOMEM;
> > +}
> > +
> > +static int dfu_prepare_function(struct f_dfu *f_dfu, int n)
> > +{
> > +	struct usb_interface_descriptor *d;
> > +	int i = 0;
> > +
> > +	f_dfu->function = calloc(n * sizeof(struct
> > usb_descriptor_header *), 1);
> 
> DITTO

As above.
> 
> > +	if (!f_dfu->function)
> > +		goto enomem;
> > +
> > +	for (i = 0; i < n; ++i) {
> > +		d = kzalloc(sizeof(*d), GFP_KERNEL);
> 
> Why use the kernel alternatives ? just use malloc()/free() ?

I will use calloc(sizeof(*d), 1) to receive cleared memory.
> 
> > +		if (!d)
> > +			goto enomem;
> > +
> > +		d->bLength =		sizeof(*d);
> > +		d->bDescriptorType =	USB_DT_INTERFACE;
> > +		d->bAlternateSetting =	i;
> > +		d->bNumEndpoints =	0;
> > +		d->bInterfaceClass =	USB_CLASS_APP_SPEC;
> > +		d->bInterfaceSubClass =	1;
> > +		d->bInterfaceProtocol =	2;
> > +
> > +		f_dfu->function[i] = (struct usb_descriptor_header
> > *)d;
> > +	}
> > +	f_dfu->function[i] = NULL;
> > +
> > +	return 0;
> > +
> > +enomem:
> > +	while (i) {
> > +		kfree(f_dfu->function[--i]);
> > +		f_dfu->function[i] = NULL;
> > +	}
> > +	kfree(f_dfu->function);
> > +
> > +	return -ENOMEM;
> > +}
> > +
> > +static int dfu_bind(struct usb_configuration *c, struct
> > usb_function *f) +{
> > +	struct usb_composite_dev *cdev = c->cdev;
> > +	struct f_dfu *f_dfu = func_to_dfu(f);
> > +	int alt_num = dfu_get_alt_number();
> > +	int rv, id, i;
> > +
> > +	id = usb_interface_id(c, f);
> > +	if (id < 0)
> > +		return id;
> > +	dfu_intf_runtime.bInterfaceNumber = id;
> > +
> > +	f_dfu->dfu_state = DFU_STATE_appIDLE;
> > +	f_dfu->dfu_status = DFU_STATUS_OK;
> > +
> > +	rv = dfu_prepare_function(f_dfu, alt_num);
> > +	if (rv)
> > +		goto error;
> > +
> > +	rv = dfu_prepare_strings(f_dfu, alt_num);
> > +	if (rv)
> > +		goto error;
> > +	for (i = 0; i < alt_num; i++) {
> > +		id = usb_string_id(cdev);
> > +		if (id < 0)
> > +			return id;
> > +		f_dfu->strings[i].id = id;
> > +		((struct usb_interface_descriptor
> > *)f_dfu->function[i])
> > +			->iInterface = id;
> > +	}
> > +
> > +	stringtab_dfu.strings = f_dfu->strings;
> > +
> > +	cdev->req->context = f_dfu;
> > +
> > +	return 0;
> > +error:
> > +	return rv;
> 
> So just return the retval ...

Fixed.
> 
> > +}
> > +
> 
> Every time I review patches and find multiple small issues, I feel
> bad :-(

All will be OK :-)



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 3/7] dfu: DFU backend implementation
  2012-07-03 21:28   ` Marek Vasut
@ 2012-07-04  8:56     ` Lukasz Majewski
  2012-07-04 14:36       ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04  8:56 UTC (permalink / raw)
  To: u-boot

Hi Marek,

> Dear Lukasz Majewski,
> 
> > New, separate driver at ./drivers/dfu has been added. It allows
> > platform and storage independent operation of DFU.
> > 
> > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > Cc: Marek Vasut <marex@denx.de>
> > ---
> 
> [...]
> 
> > +#include <common.h>
> > +#include <malloc.h>
> > +#include <mmc.h>
> > +#include <fat.h>
> > +#include <dfu.h>
> > +#include <linux/list.h>
> > +#include <linux/compiler.h>
> > +
> > +static LIST_HEAD(dfu_list);
> > +static int dfu_alt_num;
> > +
> > +static int dfu_find_alt_num(char *s)
> > +{
> > +	int i = 0;
> > +
> > +	for (; *s; s++)
> > +		if (*s == ';')
> > +			i++;
> > +
> > +	return ++i;
> > +}
> > +
> > +static char *dfu_extract_entity(char** env)
> > +{
> > +	char *s = *env;
> > +
> > +	strsep(env, ";");
> > +	return s;
> > +}
> 
> Shall we not make these all generic? They seem to be quite helpful
> components.

It is a good topic for a discussion if those functions shall be moved
to ./lib/string.c. 
I regarded them as a "little" helper functions for parsing DFU alt
setting env variable. Those are very short and build with methods
exported from string.c

> 
> > +
> > +char *dfu_extract_token(char** e, int *n)
> > +{
> > +	char *st = *e;
> > +
> > +	debug("%s: %s\n", __func__, st);
> > +
> > +	strsep(e, " ");
> > +	*n = *e - st;
> > +
> > +	return st;
> > +}
> > +
> > +static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
> > +				     dfu_buf[DFU_DATA_BUF_SIZE];
> 
> Can we not stack-allocate it with ALLOC_CACHE_ALIGN_BUFFER()?

The dfu_buf is 4 MiB (this is the size of DFU_DATA_BUF_SIZE). I don't
think, that allocating it on the stack (for stack allocation the
ALLOC_CACHE_ALIGN_BUFFER() is designed) is a good idea.

> 
> [...]
> 
> > diff --git a/include/dfu.h b/include/dfu.h
> > new file mode 100644
> > index 0000000..f7d823b
> > --- /dev/null
> > +++ b/include/dfu.h
> 
> [...]
> 
> > +struct dfu_entity {
> > +	char			name[DFU_NAME_SIZE];
> > +	int                     alt;
> > +	void                    *dev_private;
> > +	int                     dev_num;
> > +	enum dfu_device_type    dev_type;
> > +	enum dfu_layout         layout;
> > +
> > +	union {
> > +		struct mmc_internal_data mmc;
> 
> This union seems redundant ;-)

Good point :-), but I predict, that DFU will be used to program other
memory types (OneNAND, or NAND). To support those, one needs to extend
the union with e.g struct onenand_internal_data onenand.

Since we don't have so many memory types, I think that union usage is
acceptable. 

> 
> [...]



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-03 22:01       ` Marek Vasut
  2012-07-03 22:06         ` Tom Rini
@ 2012-07-04  9:10         ` Lukasz Majewski
  2012-07-04 14:38           ` Marek Vasut
  1 sibling, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04  9:10 UTC (permalink / raw)
  To: u-boot

Hi Marek,

> Dear Tom Rini,
> 
> > On Tue, Jul 03, 2012 at 11:29:31PM +0200, Marek Vasut wrote:
> > > Dear Lukasz Majewski,
> > > 
> > > > Support for MMC storage devices to work with DFU framework.
> > > > 
> > > > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > > > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > > Cc: Marek Vasut <marex@denx.de>
> > > > ---
> > > 
> > > [...]
> > > 
> > > > +
> > > > +#include <common.h>
> > > > +#include <malloc.h>
> > > > +#include <dfu.h>
> > > > +
> > > > +int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf,
> > > > long *len) +{
> > > > +	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf,
> > > > DFU_CMD_BUF_SIZE); +
> > > > +	memset(cmd_buf, '\0', sizeof(cmd_buf));
> > > > +
> > > > +	switch (dfu->layout) {
> > > > +	case RAW_ADDR:
> > > > +		sprintf(cmd_buf, "mmc write 0x%x %x %x",
> > > > (unsigned int) buf,
> > > > +			dfu->data.mmc.lba_start,
> > > > dfu->data.mmc.lba_size);
> > > > +		break;
> > > > +	case FAT:
> > > > +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s
> > > > %lx",
> > > > +			dfu->data.mmc.dev, dfu->data.mmc.part,
> > > > +			(unsigned int) buf, dfu->name, *len);
> > > > +		break;
> > > > +	default:
> > > > +		printf("%s: Wrong layout!\n", __func__);
> > > > +	}
> > > > +
> > > > +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> > > > +	run_command(cmd_buf, 0);
> > > 
> > > Holy Moly ... can we not make this into simple calls to those
> > > subsystems ? Instead invoking command is crazy ;-)
> > 
> > Are they really simple?  There's a few other places we do this, and
> > so long as it's documented that DFU depends on CONFIG_FAT_WRITE for
> > writing to fat and so forth.
> 
> Well ain't it easier to call fat_write() or similar?
> 
I've decided to use run_command on a purpose.

This call provides clean and reliable API. It is very unlikely that the
mmc write <dev> <addr> <start> <size> command will change (or any
other). 
On the other hand the fields of struct mmc are changed from time to
time.

Moreover, mmc drivers are also a subject to change (like adding dw_mmc
recently).
Using run_command also takes the burden of mmc_init() related calls. 

Of course the run_command's downside is the speed of execution. But is
it so important when one considers, the firmware update? 

Side note: DFU uses only EP0 (for transfer and configuration), so this
is rather slow communication link. 

I'm open for discussion.


-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-03 21:32   ` Marek Vasut
@ 2012-07-04  9:28     ` Lukasz Majewski
  2012-07-04 14:39       ` Marek Vasut
  2012-07-20  4:22     ` Mike Frysinger
  1 sibling, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04  9:28 UTC (permalink / raw)
  To: u-boot

Hi Marek,

> Dear Lukasz Majewski,
> 
> > Support for u-boot's command line command "dfu <interface> <dev>
> > [list]".
> > 
> > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > Cc: Marek Vasut <marex@denx.de>
> > ---
> 
> [...]
> 
> > +int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const
> > argv[]) +{
> > +	char *str_env = NULL, *env_bkp = NULL;
> > +	static char *s = "dfu";
> > +	int ret = 0;
> > +
> > +	if (argc < 3)
> > +		return CMD_RET_USAGE;
> > +
> > +	str_env = getenv("dfu_alt_info");
> > +	if (str_env == NULL) {
> > +		printf("%s: \"dfu_alt_info\" env variable not
> > defined!\n",
> > +		       __func__);
> 
> I was always curious if it's not possible to do something like 
> 
> puts(__func__ "rest of string");
> 
> Maybe it'd help the overhead a bit? Certainly, it's beyond the scope
> of this patchset, I'm just curious :)

It is a good idea, since many error/info messages are supposed to
produce following output:

"dfu_write: Not enough space!"

Putting there the __func__ name would improve structure and speed up
finding right place.

> 
> > +		return CMD_RET_FAILURE;
> > +	}
> 
> [...]
> 
> Best regards,
> Marek Vasut



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 6/7] arm:trats: Support for USB UDC driver at TRATS board.
  2012-07-04  0:20   ` Minkyu Kang
@ 2012-07-04  9:33     ` Lukasz Majewski
  0 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04  9:33 UTC (permalink / raw)
  To: u-boot

Hi Minkyu,

> Dear Lukasz,
> 
> On 3 July 2012 18:38, Lukasz Majewski <l.majewski@samsung.com> wrote:
> > Support for USB UDC driver at trats board.
> >
> > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > Cc: Marek Vasut <marex@denx.de>
> > Cc: Minkyu Kang <mk7.kang@samsung.com>
> > ---
> >  board/samsung/trats/trats.c |    9 +++++++++
> >  1 files changed, 9 insertions(+), 0 deletions(-)
> >
> > diff --git a/board/samsung/trats/trats.c
> > b/board/samsung/trats/trats.c index a95a516..2f3a531 100644
> > --- a/board/samsung/trats/trats.c
> > +++ b/board/samsung/trats/trats.c
> > @@ -59,6 +59,8 @@ static int hwrevision(int rev)
> >         return (board_rev & 0xf) == rev;
> >  }
> >
> > +struct s3c_plat_otg_data s5pc210_otg_data;
> > +
> >  int board_init(void)
> >  {
> >         gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
> > @@ -259,6 +261,13 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
> >         .usb_phy_ctrl   = EXYNOS4_USBPHY_CONTROL,
> >         .usb_flags      = PHY0_SLEEP,
> >  };
> > +
> > +void board_usb_init(void)
> > +{
> > +       puts("USB_udc_probe\n");
> 
> is it useful information? or debug message?

Good point. I will change it to debug.
> 
> > +       s3c_udc_probe(&s5pc210_otg_data);
> > +
> > +}
> >  #endif
> >
> 
> Thanks.
> Minkyu Kang.



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  2012-07-04  8:39     ` Lukasz Majewski
@ 2012-07-04 14:35       ` Marek Vasut
  2012-07-04 15:04         ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-04 14:35 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

[...]

> > > +static void handle_getstatus(struct usb_request *req)
> > > +{
> > > +	struct dfu_status *dstat = (struct dfu_status *)req->buf;
> > > +	struct f_dfu *f_dfu = req->context;
> > > +
> > > +	switch (f_dfu->dfu_state) {
> > 
> > > +	case DFU_STATE_dfuDNLOAD_SYNC:
> > What's this crazy cammel case in here ? :-)
> 
> I know, that camel case descriptions are not welcome :-),
> but those are written in this way for purpose.
> 
> dfuDNLOAD_SYNC is the exact state name mentioned at DFU specification.
> Other states - like dfuDNBUSY are exactly the same.
> 
> From mine experience it is more readable. Please consider for
> example the Fig. A1 - Interface state transition diagram from page 28
> at DFU_1.1.pdf spec (link below).
> 
> http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf

OK, good.

> > > +	case DFU_STATE_dfuDNBUSY:
> > > +		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
> > > +		break;
> > > +	case DFU_STATE_dfuMANIFEST_SYNC:
> > > +		break;
> > > +	default:
> > > +		break;
> > > +	}
> > > +
> > > +	/* send status response */
> > > +	dstat->bStatus = f_dfu->dfu_status;
> > > +	/* FIXME: set dstat->bwPollTimeout */
> > 
> > FIXME ... so fix it ;-)
> 
> This is not u-boot related - will be removed
> 
> > > +	dstat->bState = f_dfu->dfu_state;
> > > +	dstat->iString = 0;
> > > +}
> > > +
> > > +static void handle_getstate(struct usb_request *req)
> > > +{
> > > +	struct f_dfu *f_dfu = req->context;
> > > +
> > > +	((u8 *)req->buf)[0] = f_dfu->dfu_state & 0xff;
> > 
> > Now ... this is ubercrazy ... can't this be made without this
> > typecasting voodoo?
> 
> The problem is that req->buf is a void pointer. And the goal is to
> store dfu state at 8 bits.

Sure, but why not make the buffer u8 ?

> > > +	req->actual = sizeof(u8);
> > > +}
> > > +

[...]

> > > +static int
> > > +dfu_prepare_strings(struct f_dfu *f_dfu, int n)
> > > +{
> > > +	struct dfu_entity *de = NULL;
> > > +	int i = 0;
> > > +
> > > +	f_dfu->strings = calloc(((n + 1) * sizeof(struct
> > > usb_string)), 1);
> > 
> > calloc(n, 1) ... that's the same as malloc(), isn't it ?
> 
> I now wonder how mine mind produced this :-)
> 
> Correct version:
> 
> f_dfu->strings = calloc(sizeof(struct usb_string), n + 1);
> 
> I prefer calloc, since it delivers zeroed memory.

ok, that's better :)

[...]

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 3/7] dfu: DFU backend implementation
  2012-07-04  8:56     ` Lukasz Majewski
@ 2012-07-04 14:36       ` Marek Vasut
  2012-07-04 15:07         ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-04 14:36 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> Hi Marek,
> 
> > Dear Lukasz Majewski,
> > 
> > > New, separate driver at ./drivers/dfu has been added. It allows
> > > platform and storage independent operation of DFU.
> > > 
> > > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > Cc: Marek Vasut <marex@denx.de>
> > > ---
> > 
> > [...]
> > 
> > > +#include <common.h>
> > > +#include <malloc.h>
> > > +#include <mmc.h>
> > > +#include <fat.h>
> > > +#include <dfu.h>
> > > +#include <linux/list.h>
> > > +#include <linux/compiler.h>
> > > +
> > > +static LIST_HEAD(dfu_list);
> > > +static int dfu_alt_num;
> > > +
> > > +static int dfu_find_alt_num(char *s)
> > > +{
> > > +	int i = 0;
> > > +
> > > +	for (; *s; s++)
> > > +		if (*s == ';')
> > > +			i++;
> > > +
> > > +	return ++i;
> > > +}
> > > +
> > > +static char *dfu_extract_entity(char** env)
> > > +{
> > > +	char *s = *env;
> > > +
> > > +	strsep(env, ";");
> > > +	return s;
> > > +}
> > 
> > Shall we not make these all generic? They seem to be quite helpful
> > components.
> 
> It is a good topic for a discussion if those functions shall be moved
> to ./lib/string.c.
> I regarded them as a "little" helper functions for parsing DFU alt
> setting env variable. Those are very short and build with methods
> exported from string.c

Good point

> > > +
> > > +char *dfu_extract_token(char** e, int *n)
> > > +{
> > > +	char *st = *e;
> > > +
> > > +	debug("%s: %s\n", __func__, st);
> > > +
> > > +	strsep(e, " ");
> > > +	*n = *e - st;
> > > +
> > > +	return st;
> > > +}
> > > +
> > > +static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
> > > +				     dfu_buf[DFU_DATA_BUF_SIZE];
> > 
> > Can we not stack-allocate it with ALLOC_CACHE_ALIGN_BUFFER()?
> 
> The dfu_buf is 4 MiB (this is the size of DFU_DATA_BUF_SIZE). I don't
> think, that allocating it on the stack (for stack allocation the
> ALLOC_CACHE_ALIGN_BUFFER() is designed) is a good idea.

Heh, agreed :-)

> > [...]
> > 
> > > diff --git a/include/dfu.h b/include/dfu.h
> > > new file mode 100644
> > > index 0000000..f7d823b
> > > --- /dev/null
> > > +++ b/include/dfu.h
> > 
> > [...]
> > 
> > > +struct dfu_entity {
> > > +	char			name[DFU_NAME_SIZE];
> > > +	int                     alt;
> > > +	void                    *dev_private;
> > > +	int                     dev_num;
> > > +	enum dfu_device_type    dev_type;
> > > +	enum dfu_layout         layout;
> > > +
> > > +	union {
> > > +		struct mmc_internal_data mmc;
> > 
> > This union seems redundant ;-)
> 
> Good point :-), but I predict, that DFU will be used to program other
> memory types (OneNAND, or NAND). To support those, one needs to extend
> the union with e.g struct onenand_internal_data onenand.
> 
> Since we don't have so many memory types, I think that union usage is
> acceptable.

And will those pieces be implemented any soon ? :)

> > [...]

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-04  9:10         ` Lukasz Majewski
@ 2012-07-04 14:38           ` Marek Vasut
  2012-07-04 15:13             ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-04 14:38 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

[...]

> > > > Holy Moly ... can we not make this into simple calls to those
> > > > subsystems ? Instead invoking command is crazy ;-)
> > > 
> > > Are they really simple?  There's a few other places we do this, and
> > > so long as it's documented that DFU depends on CONFIG_FAT_WRITE for
> > > writing to fat and so forth.
> > 
> > Well ain't it easier to call fat_write() or similar?
> 
> I've decided to use run_command on a purpose.
> 
> This call provides clean and reliable API. It is very unlikely that the
> mmc write <dev> <addr> <start> <size> command will change (or any
> other).
> On the other hand the fields of struct mmc are changed from time to
> time.

I'm afraid it might change with the driver model soon.

> Moreover, mmc drivers are also a subject to change (like adding dw_mmc
> recently).
> Using run_command also takes the burden of mmc_init() related calls.
> 
> Of course the run_command's downside is the speed of execution. But is
> it so important when one considers, the firmware update?

But as Stephen pointed out, the type checking is much better when used as 
function.

> Side note: DFU uses only EP0 (for transfer and configuration), so this
> is rather slow communication link.

I see

> I'm open for discussion.

Yes please, I think I started some bad flamewar in here :/

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-04  9:28     ` Lukasz Majewski
@ 2012-07-04 14:39       ` Marek Vasut
  2012-07-20  4:23         ` Mike Frysinger
  0 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-04 14:39 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> Hi Marek,
> 
> > Dear Lukasz Majewski,
> > 
> > > Support for u-boot's command line command "dfu <interface> <dev>
> > > [list]".
> > > 
> > > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > Cc: Marek Vasut <marex@denx.de>
> > > ---
> > 
> > [...]
> > 
> > > +int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const
> > > argv[]) +{
> > > +	char *str_env = NULL, *env_bkp = NULL;
> > > +	static char *s = "dfu";
> > > +	int ret = 0;
> > > +
> > > +	if (argc < 3)
> > > +		return CMD_RET_USAGE;
> > > +
> > > +	str_env = getenv("dfu_alt_info");
> > > +	if (str_env == NULL) {
> > > +		printf("%s: \"dfu_alt_info\" env variable not
> > > defined!\n",
> > > +		       __func__);
> > 
> > I was always curious if it's not possible to do something like
> > 
> > puts(__func__ "rest of string");
> > 
> > Maybe it'd help the overhead a bit? Certainly, it's beyond the scope
> > of this patchset, I'm just curious :)
> 
> It is a good idea, since many error/info messages are supposed to
> produce following output:
> 
> "dfu_write: Not enough space!"
> 
> Putting there the __func__ name would improve structure and speed up
> finding right place.

And if you want to use even __LINE__, look up __stringify patch in the ML 
archives ;-)

> > > +		return CMD_RET_FAILURE;
> > > +	}
> > 
> > [...]
> > 
> > Best regards,
> > Marek Vasut

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  2012-07-04 14:35       ` Marek Vasut
@ 2012-07-04 15:04         ` Lukasz Majewski
  2012-07-04 16:21           ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04 15:04 UTC (permalink / raw)
  To: u-boot

Hi Marek,

> Dear Lukasz Majewski,
> 
> [...]
> 
> > > > +static void handle_getstatus(struct usb_request *req)
> > > > +{
> > > > +	struct dfu_status *dstat = (struct dfu_status
> > > > *)req->buf;
> > > > +	struct f_dfu *f_dfu = req->context;
> > > > +
> > > > +	switch (f_dfu->dfu_state) {
> > > 
> > > > +	case DFU_STATE_dfuDNLOAD_SYNC:
> > > What's this crazy cammel case in here ? :-)
> > 
> > I know, that camel case descriptions are not welcome :-),
> > but those are written in this way for purpose.
> > 
> > dfuDNLOAD_SYNC is the exact state name mentioned at DFU
> > specification. Other states - like dfuDNBUSY are exactly the same.
> > 
> > From mine experience it is more readable. Please consider for
> > example the Fig. A1 - Interface state transition diagram from page
> > 28 at DFU_1.1.pdf spec (link below).
> > 
> > http://www.usb.org/developers/devclass_docs/DFU_1.1.pdf
> 
> OK, good.
> 
> > > > +	case DFU_STATE_dfuDNBUSY:
> > > > +		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
> > > > +		break;
> > > > +	case DFU_STATE_dfuMANIFEST_SYNC:
> > > > +		break;
> > > > +	default:
> > > > +		break;
> > > > +	}
> > > > +
> > > > +	/* send status response */
> > > > +	dstat->bStatus = f_dfu->dfu_status;
> > > > +	/* FIXME: set dstat->bwPollTimeout */
> > > 
> > > FIXME ... so fix it ;-)
> > 
> > This is not u-boot related - will be removed
> > 
> > > > +	dstat->bState = f_dfu->dfu_state;
> > > > +	dstat->iString = 0;
> > > > +}
> > > > +
> > > > +static void handle_getstate(struct usb_request *req)
> > > > +{
> > > > +	struct f_dfu *f_dfu = req->context;
> > > > +
> > > > +	((u8 *)req->buf)[0] = f_dfu->dfu_state & 0xff;
> > > 
> > > Now ... this is ubercrazy ... can't this be made without this
> > > typecasting voodoo?
> > 
> > The problem is that req->buf is a void pointer. And the goal is to
> > store dfu state at 8 bits.
> 
> Sure, but why not make the buffer u8 ?

The req->buf is a member of usb_request defined at gadget.h.

It represents the request from USB. I cannot guarantee, that we will
always regard data pointed by buf as u8. For flexibility of gadget
usage it is safer to leave it as void pointer.

> 
> > > > +	req->actual = sizeof(u8);
> > > > +}
> > > > +
> 
> [...]
> 
> > > > +static int
> > > > +dfu_prepare_strings(struct f_dfu *f_dfu, int n)
> > > > +{
> > > > +	struct dfu_entity *de = NULL;
> > > > +	int i = 0;
> > > > +
> > > > +	f_dfu->strings = calloc(((n + 1) * sizeof(struct
> > > > usb_string)), 1);
> > > 
> > > calloc(n, 1) ... that's the same as malloc(), isn't it ?
> > 
> > I now wonder how mine mind produced this :-)
> > 
> > Correct version:
> > 
> > f_dfu->strings = calloc(sizeof(struct usb_string), n + 1);
> > 
> > I prefer calloc, since it delivers zeroed memory.
> 
> ok, that's better :)
> 
> [...]



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 3/7] dfu: DFU backend implementation
  2012-07-04 14:36       ` Marek Vasut
@ 2012-07-04 15:07         ` Lukasz Majewski
  2012-07-04 16:22           ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04 15:07 UTC (permalink / raw)
  To: u-boot

Hi Marek,

> Dear Lukasz Majewski,
> 
> > Hi Marek,
> > 
> > > Dear Lukasz Majewski,
> > > 
> > > > New, separate driver at ./drivers/dfu has been added. It allows
> > > > platform and storage independent operation of DFU.
> > > > 
> > > > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > > > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > > Cc: Marek Vasut <marex@denx.de>
> > > > ---
> > > 
> > > [...]
> > > 
> > > > +#include <common.h>
> > > > +#include <malloc.h>
> > > > +#include <mmc.h>
> > > > +#include <fat.h>
> > > > +#include <dfu.h>
> > > > +#include <linux/list.h>
> > > > +#include <linux/compiler.h>
> > > > +
> > > > +static LIST_HEAD(dfu_list);
> > > > +static int dfu_alt_num;
> > > > +
> > > > +static int dfu_find_alt_num(char *s)
> > > > +{
> > > > +	int i = 0;
> > > > +
> > > > +	for (; *s; s++)
> > > > +		if (*s == ';')
> > > > +			i++;
> > > > +
> > > > +	return ++i;
> > > > +}
> > > > +
> > > > +static char *dfu_extract_entity(char** env)
> > > > +{
> > > > +	char *s = *env;
> > > > +
> > > > +	strsep(env, ";");
> > > > +	return s;
> > > > +}
> > > 
> > > Shall we not make these all generic? They seem to be quite helpful
> > > components.
> > 
> > It is a good topic for a discussion if those functions shall be
> > moved to ./lib/string.c.
> > I regarded them as a "little" helper functions for parsing DFU alt
> > setting env variable. Those are very short and build with methods
> > exported from string.c
> 
> Good point
> 
> > > > +
> > > > +char *dfu_extract_token(char** e, int *n)
> > > > +{
> > > > +	char *st = *e;
> > > > +
> > > > +	debug("%s: %s\n", __func__, st);
> > > > +
> > > > +	strsep(e, " ");
> > > > +	*n = *e - st;
> > > > +
> > > > +	return st;
> > > > +}
> > > > +
> > > > +static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
> > > > +
> > > > dfu_buf[DFU_DATA_BUF_SIZE];
> > > 
> > > Can we not stack-allocate it with ALLOC_CACHE_ALIGN_BUFFER()?
> > 
> > The dfu_buf is 4 MiB (this is the size of DFU_DATA_BUF_SIZE). I
> > don't think, that allocating it on the stack (for stack allocation
> > the ALLOC_CACHE_ALIGN_BUFFER() is designed) is a good idea.
> 
> Heh, agreed :-)
> 
> > > [...]
> > > 
> > > > diff --git a/include/dfu.h b/include/dfu.h
> > > > new file mode 100644
> > > > index 0000000..f7d823b
> > > > --- /dev/null
> > > > +++ b/include/dfu.h
> > > 
> > > [...]
> > > 
> > > > +struct dfu_entity {
> > > > +	char			name[DFU_NAME_SIZE];
> > > > +	int                     alt;
> > > > +	void                    *dev_private;
> > > > +	int                     dev_num;
> > > > +	enum dfu_device_type    dev_type;
> > > > +	enum dfu_layout         layout;
> > > > +
> > > > +	union {
> > > > +		struct mmc_internal_data mmc;
> > > 
> > > This union seems redundant ;-)
> > 
> > Good point :-), but I predict, that DFU will be used to program
> > other memory types (OneNAND, or NAND). To support those, one needs
> > to extend the union with e.g struct onenand_internal_data onenand.
> > 
> > Since we don't have so many memory types, I think that union usage
> > is acceptable.
> 
> And will those pieces be implemented any soon ? :)

:-). Since I'm the OneNAND custodian I shall keep in the back of my
head, that support for this memory is important :-)

> 
> > > [...]
> 
> Best regards,
> Marek Vasut



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-04 14:38           ` Marek Vasut
@ 2012-07-04 15:13             ` Lukasz Majewski
  0 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04 15:13 UTC (permalink / raw)
  To: u-boot

Hi Marek,

> Dear Lukasz Majewski,
> 
> [...]
> 
> > > > > Holy Moly ... can we not make this into simple calls to those
> > > > > subsystems ? Instead invoking command is crazy ;-)
> > > > 
> > > > Are they really simple?  There's a few other places we do this,
> > > > and so long as it's documented that DFU depends on
> > > > CONFIG_FAT_WRITE for writing to fat and so forth.
> > > 
> > > Well ain't it easier to call fat_write() or similar?
> > 
> > I've decided to use run_command on a purpose.
> > 
> > This call provides clean and reliable API. It is very unlikely that
> > the mmc write <dev> <addr> <start> <size> command will change (or
> > any other).
> > On the other hand the fields of struct mmc are changed from time to
> > time.
> 
> I'm afraid it might change with the driver model soon.
You have probably more information than I about the driver model :-)

Since I know u-boot this API was stable. If it changes, I will adjust
the sprintf :-)

> 
> > Moreover, mmc drivers are also a subject to change (like adding
> > dw_mmc recently).
> > Using run_command also takes the burden of mmc_init() related calls.
> > 
> > Of course the run_command's downside is the speed of execution. But
> > is it so important when one considers, the firmware update?
> 
> But as Stephen pointed out, the type checking is much better when
> used as function.
Yes, I agree about the type check. 

Contrary, the cmd_mmc.c code is not checking the correctness of passed
data. It performs strncmp, then simple_strtoul and with this parameter
calls 
mmc->block_dev.block_read(). For this command such behavior is
acceptable.


> 
> > Side note: DFU uses only EP0 (for transfer and configuration), so
> > this is rather slow communication link.
> 
> I see
> 
> > I'm open for discussion.
> 
> Yes please, I think I started some bad flamewar in here :/

Maybe we come up with a better solution thanks to that :-).


-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 0/7] dfu:usb: Composite USB download gadget with DFU function
  2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
                   ` (7 preceding siblings ...)
  2012-07-03 12:52 ` [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Otavio Salvador
@ 2012-07-04 15:48 ` Lukasz Majewski
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
                     ` (7 more replies)
  2012-07-18 12:51 ` [U-Boot] [PATCH " Marek Vasut
                   ` (3 subsequent siblings)
  12 siblings, 8 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04 15:48 UTC (permalink / raw)
  To: u-boot

Those patches add support for composite USB download gadget.
This gadget (at least for now) is equipped with DFU download function.

A separate DFU back-end and front-end have been added.
Back-end is placed at ./drivers/dfu directory. The front-end is implemented
as USB function.

The back-end is written in a generic manner with storage device specific
code separated (eMMC).

DFU specification can be found at:
http://wiki.openmoko.org/wiki/USB_DFU_-_The_USB_Device_Firmware_Upgrade_standard

Example usage:

u-boot side: dfu mmc 0
PC: dfu-util -U IMAGE.bin -a uImage (for upload)
    dfu-util -D uImage -a uImage (download)

To list the alt settings:
        dfu mmc 0 list

Test HW:
        Exynos4210 Trats board


Lukasz Majewski (7):
  dfu:usb: Support for g_dnl composite download gadget.
  dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  dfu: DFU backend implementation
  dfu: MMC specific routines for DFU operation
  dfu:cmd: Support for DFU u-boot command
  arm:trats: Support for USB UDC driver at TRATS board.
  arm:trats: Enable g_dnl composite USB gadget with embedded DFU
    function on TRATS

 Makefile                    |    1 +
 board/samsung/trats/trats.c |    8 +
 common/Makefile             |    1 +
 common/cmd_dfu.c            |   81 +++++
 drivers/dfu/Makefile        |   44 +++
 drivers/dfu/dfu.c           |  259 +++++++++++++++
 drivers/dfu/dfu_mmc.c       |  126 +++++++
 drivers/usb/gadget/Makefile |    2 +
 drivers/usb/gadget/f_dfu.c  |  753 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/f_dfu.h  |  100 ++++++
 drivers/usb/gadget/g_dnl.c  |  223 +++++++++++++
 include/configs/trats.h     |   24 ++-
 include/dfu.h               |   99 ++++++
 include/g_dnl.h             |   33 ++
 14 files changed, 1753 insertions(+), 1 deletions(-)
 create mode 100644 common/cmd_dfu.c
 create mode 100644 drivers/dfu/Makefile
 create mode 100644 drivers/dfu/dfu.c
 create mode 100644 drivers/dfu/dfu_mmc.c
 create mode 100644 drivers/usb/gadget/f_dfu.c
 create mode 100644 drivers/usb/gadget/f_dfu.h
 create mode 100644 drivers/usb/gadget/g_dnl.c
 create mode 100644 include/dfu.h
 create mode 100644 include/g_dnl.h

-- 
1.7.2.3

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 1/7] dfu:usb: Support for g_dnl composite download gadget.
  2012-07-04 15:48 ` [U-Boot] [PATCH v2 " Lukasz Majewski
@ 2012-07-04 15:48   ` Lukasz Majewski
  2012-07-09 16:30     ` Marek Vasut
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
                     ` (6 subsequent siblings)
  7 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04 15:48 UTC (permalink / raw)
  To: u-boot

Composite USB download gadget support (g_dnl) for download functions.
This code works on top of composite gadget.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:

- G_DNL_{VENDOR_NUM, PRODUCT_NUM and MANUFACTURER} defined at
./include/configs/<board>.h
- Suspend and resume stub methods removed
- '\0' repleaced with plain 0
---
 drivers/usb/gadget/Makefile |    1 +
 drivers/usb/gadget/g_dnl.c  |  223 +++++++++++++++++++++++++++++++++++++++++++
 include/g_dnl.h             |   33 +++++++
 3 files changed, 257 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/gadget/g_dnl.c
 create mode 100644 include/g_dnl.h

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 87d1918..2c067c8 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -29,6 +29,7 @@ LIB	:= $(obj)libusb_gadget.o
 ifdef CONFIG_USB_GADGET
 COBJS-y += epautoconf.o config.o usbstring.o
 COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
+COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
 endif
 ifdef CONFIG_USB_ETHER
 COBJS-y += ether.o epautoconf.o config.o usbstring.o
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
new file mode 100644
index 0000000..fe996b4
--- /dev/null
+++ b/drivers/usb/gadget/g_dnl.c
@@ -0,0 +1,223 @@
+/*
+ * g_dnl.c -- USB Downloader Gadget
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski  <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <errno.h>
+#include <common.h>
+#include <malloc.h>
+#include <linux/usb/ch9.h>
+#include <usbdescriptors.h>
+#include <linux/usb/gadget.h>
+
+#include <mmc.h>
+#include <part.h>
+
+#include <g_dnl.h>
+#include "f_dfu.h"
+
+#include "gadget_chips.h"
+#include "composite.c"
+
+/*
+ * One needs to define the following:
+ * G_DNL_VENDOR_NUM
+ * G_DNL_PRODUCT_NUM
+ * G_DNL_MANUFACTURER
+ * at e.g. ./include/configs/<board>.h
+ */
+
+#define STRING_MANUFACTURER 25
+#define STRING_PRODUCT 2
+#define STRING_USBDOWN 2
+#define CONFIG_USBDOWNLOADER 2
+
+#define DRIVER_VERSION		"usb_dnl 2.0"
+
+static const char shortname[] = "usb_dnl_";
+static const char product[] = "USB download gadget";
+static const char manufacturer[] = G_DNL_MANUFACTURER;
+
+static struct usb_device_descriptor device_desc = {
+	.bLength =		sizeof device_desc,
+	.bDescriptorType =	USB_DT_DEVICE,
+
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_COMM,
+	.bDeviceSubClass =      0x02,	/*0x02:CDC-modem , 0x00:CDC-serial*/
+
+	.idVendor =		__constant_cpu_to_le16(G_DNL_VENDOR_NUM),
+	.idProduct =		__constant_cpu_to_le16(G_DNL_PRODUCT_NUM),
+	.iProduct =		STRING_PRODUCT,
+	.bNumConfigurations =	1,
+};
+
+static const struct usb_descriptor_header *otg_desc[] = {
+	(struct usb_descriptor_header *) &(struct usb_otg_descriptor){
+		.bLength =		sizeof(struct usb_otg_descriptor),
+		.bDescriptorType =	USB_DT_OTG,
+		.bmAttributes =		USB_OTG_SRP,
+	},
+	NULL,
+};
+
+/* static strings, in UTF-8 */
+static struct usb_string odin_string_defs[] = {
+	{ 0, manufacturer, },
+	{ 1, product, },
+};
+
+static struct usb_gadget_strings odin_string_tab = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= odin_string_defs,
+};
+
+static struct usb_gadget_strings *g_dnl_composite_strings[] = {
+	&odin_string_tab,
+	NULL,
+};
+
+static int g_dnl_unbind(struct usb_composite_dev *cdev)
+{
+	debug("%s\n", __func__);
+	return 0;
+}
+
+static int g_dnl_do_config(struct usb_configuration *c)
+{
+	int ret = -1;
+	char *s = (char *) c->cdev->driver->name;
+
+	debug("%s: configuration: 0x%p composite dev: 0x%p\n",
+	      __func__, c, c->cdev);
+
+	if (gadget_is_otg(c->cdev->gadget)) {
+		c->descriptors = otg_desc;
+		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
+	printf("GADGET DRIVER: %s\n", s);
+
+	if (!strcmp(s, "usb_dnl_dfu"))
+		ret = dfu_add(c);
+
+	return ret;
+}
+
+static int g_dnl_config_register(struct usb_composite_dev *cdev)
+{
+	debug("%s:\n", __func__);
+	static struct usb_configuration config = {
+		.label = "usb_dnload",
+		.bmAttributes =	USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+		.bConfigurationValue =	CONFIG_USBDOWNLOADER,
+		.iConfiguration =	STRING_USBDOWN,
+
+		.bind = g_dnl_do_config,
+	};
+
+	return usb_add_config(cdev, &config);
+}
+
+static int g_dnl_bind(struct usb_composite_dev *cdev)
+{
+	int			gcnum;
+	int id, ret;
+	struct usb_gadget	*gadget = cdev->gadget;
+
+	debug("%s: gadget: 0x%p cdev: 0x%p\n", __func__, gadget, cdev);
+
+	id = usb_string_id(cdev);
+
+	if (id < 0)
+		return id;
+	odin_string_defs[0].id = id;
+	device_desc.iManufacturer = id;
+
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+
+	odin_string_defs[1].id = id;
+	device_desc.iProduct = id;
+
+	ret = g_dnl_config_register(cdev);
+	if (ret)
+		goto error;
+
+	gcnum = usb_gadget_controller_number(gadget);
+
+	debug("gcnum: %d\n", gcnum);
+	if (gcnum >= 0)
+		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
+	else {
+		debug("%s: controller '%s' not recognized\n",
+			shortname, gadget->name);
+		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
+	}
+
+	return 0;
+
+ error:
+	g_dnl_unbind(cdev);
+	return -ENOMEM;
+}
+
+static struct usb_composite_driver g_dnl_driver = {
+	.name		= NULL,
+	.dev		= &device_desc,
+	.strings	= g_dnl_composite_strings,
+
+	.bind		= g_dnl_bind,
+	.unbind		= g_dnl_unbind,
+};
+
+int g_dnl_init(char *s)
+{
+	int ret;
+	static char str[16];
+
+	memset(str, 0, sizeof(str));
+
+	strncpy(str, shortname, sizeof(shortname));
+
+	if (!strncmp(s, "dfu", sizeof(s))) {
+		strncat(str, s, sizeof(str));
+	} else {
+		printf("%s: unknown command: %s\n", __func__, s);
+		return -EINVAL;
+	}
+
+	g_dnl_driver.name = str;
+
+	debug("%s: g_dnl_driver.name: %s\n", __func__, g_dnl_driver.name);
+	ret = usb_composite_register(&g_dnl_driver);
+
+	if (ret) {
+		printf("%s: failed!, error:%d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+void g_dnl_cleanup(void)
+{
+	usb_composite_unregister(&g_dnl_driver);
+}
diff --git a/include/g_dnl.h b/include/g_dnl.h
new file mode 100644
index 0000000..5d0e9a5
--- /dev/null
+++ b/include/g_dnl.h
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (C) 2012 Samsung Electronics
+ *  Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __G_DOWNLOAD_H_
+#define __G_DOWNLOAD_H_
+
+#include <linux/usb/ch9.h>
+#include <usbdescriptors.h>
+#include <linux/usb/gadget.h>
+
+int g_dnl_init(char *s);
+void g_dnl_cleanup(void);
+
+/* USB initialization declaration - board specific*/
+void board_usb_init(void);
+#endif /* __G_DOWNLOAD_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  2012-07-04 15:48 ` [U-Boot] [PATCH v2 " Lukasz Majewski
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
@ 2012-07-04 15:48   ` Lukasz Majewski
  2012-07-09 16:34     ` Marek Vasut
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 3/7] dfu: DFU backend implementation Lukasz Majewski
                     ` (5 subsequent siblings)
  7 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04 15:48 UTC (permalink / raw)
  To: u-boot

Support for f_dfu USB function.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:

- Replace kzalloc and kfree with free and calloc
- Reorganization of calloc calls
- Misspelling corrected
- Redesign of DFU state machine from "switch case" to function pointers
- Split the dfu_handle method to separate functions for each DFU state
---
 drivers/usb/gadget/Makefile |    1 +
 drivers/usb/gadget/f_dfu.c  |  753 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/f_dfu.h  |  100 ++++++
 3 files changed, 854 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/gadget/f_dfu.c
 create mode 100644 drivers/usb/gadget/f_dfu.h

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 2c067c8..5bbdd36 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -30,6 +30,7 @@ ifdef CONFIG_USB_GADGET
 COBJS-y += epautoconf.o config.o usbstring.o
 COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
 COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
+COBJS-$(CONFIG_DFU_FUNCTION) += f_dfu.o
 endif
 ifdef CONFIG_USB_ETHER
 COBJS-y += ether.o epautoconf.o config.o usbstring.o
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
new file mode 100644
index 0000000..c1ef70c
--- /dev/null
+++ b/drivers/usb/gadget/f_dfu.c
@@ -0,0 +1,753 @@
+/*
+ * f_dfu.c -- Device Firmware Update USB function
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *          Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <errno.h>
+#include <common.h>
+#include <malloc.h>
+
+#include <linux/usb/ch9.h>
+#include <usbdescriptors.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/composite.h>
+
+#include <dfu.h>
+#include "f_dfu.h"
+
+struct f_dfu {
+	struct usb_function		usb_function;
+
+	struct usb_descriptor_header	**function;
+	struct usb_string		*strings;
+
+	/* when configured, we have one config */
+	u8				config;
+	u8				altsetting;
+	enum dfu_state			dfu_state;
+	unsigned int			dfu_status;
+
+	/* Send/received block number is handy for data integrity check */
+	int                             blk_seq_num;
+};
+
+typedef int (*dfu_state_fn) (struct f_dfu *,
+			     const struct usb_ctrlrequest *,
+			     struct usb_gadget *,
+			     struct usb_request *);
+
+static inline struct f_dfu *func_to_dfu(struct usb_function *f)
+{
+	return container_of(f, struct f_dfu, usb_function);
+}
+
+static const struct dfu_function_descriptor dfu_func = {
+	.bLength =		sizeof dfu_func,
+	.bDescriptorType =	DFU_DT_FUNC,
+	.bmAttributes =		DFU_BIT_WILL_DETACH |
+				DFU_BIT_MANIFESTATION_TOLERANT |
+				DFU_BIT_CAN_UPLOAD |
+				DFU_BIT_CAN_DNLOAD,
+	.wDetachTimeOut =	0,
+	.wTransferSize =	DFU_USB_BUFSIZ,
+	.bcdDFUVersion =	__constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_interface_descriptor dfu_intf_runtime = {
+	.bLength =		sizeof dfu_intf_runtime,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	.bNumEndpoints =	0,
+	.bInterfaceClass =	USB_CLASS_APP_SPEC,
+	.bInterfaceSubClass =	1,
+	.bInterfaceProtocol =	1,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_descriptor_header *dfu_runtime_descs[] = {
+	(struct usb_descriptor_header *) &dfu_intf_runtime,
+	NULL,
+};
+
+static struct usb_qualifier_descriptor dev_qualifier = {
+	.bLength =		sizeof dev_qualifier,
+	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
+	.bNumConfigurations =	1,
+};
+
+static const char dfu_name[] = "Device Firmware Upgrade";
+
+/*
+ * static strings, in UTF-8
+ *
+ * dfu_generic configuration
+ */
+static struct usb_string strings_dfu_generic[] = {
+	[0].s = dfu_name,
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab_dfu_generic = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_dfu_generic,
+};
+
+static struct usb_gadget_strings *dfu_generic_strings[] = {
+	&stringtab_dfu_generic,
+	NULL,
+};
+
+/*
+ * usb_function specific
+ */
+static struct usb_gadget_strings stringtab_dfu = {
+	.language	= 0x0409,	/* en-us */
+	/*
+	 * .strings
+	 *
+	 * assigned during initialization,
+	 * depends on number of flash entities
+	 *
+	 */
+};
+
+static struct usb_gadget_strings *dfu_strings[] = {
+	&stringtab_dfu,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
+		  req->length, f_dfu->blk_seq_num);
+
+	if (req->length == 0) {
+		puts("DOWNLOAD ... OK\n");
+		puts("Ctrl+C to exit ...\n");
+	}
+}
+
+static void handle_getstatus(struct usb_request *req)
+{
+	struct dfu_status *dstat = (struct dfu_status *)req->buf;
+	struct f_dfu *f_dfu = req->context;
+
+	switch (f_dfu->dfu_state) {
+	case DFU_STATE_dfuDNLOAD_SYNC:
+	case DFU_STATE_dfuDNBUSY:
+		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
+		break;
+	case DFU_STATE_dfuMANIFEST_SYNC:
+		break;
+	default:
+		break;
+	}
+
+	/* send status response */
+	dstat->bStatus = f_dfu->dfu_status;
+	/* FIXME: set dstat->bwPollTimeout */
+	dstat->bState = f_dfu->dfu_state;
+	dstat->iString = 0;
+}
+
+static void handle_getstate(struct usb_request *req)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	((u8 *)req->buf)[0] = f_dfu->dfu_state & 0xff;
+	req->actual = sizeof(u8);
+}
+
+static inline void to_dfu_mode(struct f_dfu *f_dfu)
+{
+	f_dfu->usb_function.strings = dfu_strings;
+	f_dfu->usb_function.hs_descriptors = f_dfu->function;
+}
+
+static inline void to_runtime_mode(struct f_dfu *f_dfu)
+{
+	f_dfu->usb_function.strings = NULL;
+	f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+}
+
+static int handle_upload(struct usb_request *req, u16 len)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	return dfu_read(dfu_get_entity(f_dfu->altsetting), req->buf,
+			req->length, f_dfu->blk_seq_num);
+}
+
+static int handle_dnload(struct usb_gadget *gadget, u16 len)
+{
+	struct usb_composite_dev *cdev = get_gadget_data(gadget);
+	struct usb_request *req = cdev->req;
+	struct f_dfu *f_dfu = req->context;
+
+	if (len == 0)
+		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
+
+	req->complete = dnload_request_complete;
+
+	return len;
+}
+
+/*-------------------------------------------------------------------------*/
+/* DFU state machine  */
+static int state_app_idle(struct f_dfu *f_dfu,
+			  const struct usb_ctrlrequest *ctrl,
+			  struct usb_gadget *gadget,
+			  struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	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:
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_app_detach(struct f_dfu *f_dfu,
+			    const struct usb_ctrlrequest *ctrl,
+			    struct usb_gadget *gadget,
+			    struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_appIDLE;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_idle(struct f_dfu *f_dfu,
+			  const struct usb_ctrlrequest *ctrl,
+			  struct usb_gadget *gadget,
+			  struct usb_request *req)
+{
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 len = le16_to_cpu(ctrl->wLength);
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_DNLOAD:
+		if (len == 0) {
+			f_dfu->dfu_state = DFU_STATE_dfuERROR;
+			value = RET_STALL;
+			break;
+		}
+		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
+		f_dfu->blk_seq_num = w_value;
+		value = handle_dnload(gadget, len);
+		break;
+	case USB_REQ_DFU_UPLOAD:
+		f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
+		f_dfu->blk_seq_num = 0;
+		value = handle_upload(req, len);
+		break;
+	case USB_REQ_DFU_ABORT:
+		/* no zlp? */
+		value = RET_ZLP;
+		break;
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	case USB_REQ_DFU_DETACH:
+		/*
+		 * Proprietary extension: 'detach' from idle mode and
+		 * get back to runtime mode in case of USB Reset.  As
+		 * much as I dislike this, we just can't use every USB
+		 * bus reset to switch back to runtime mode, since at
+		 * least the Linux USB stack likes to send a number of
+		 * resets in a row :(
+		 */
+		f_dfu->dfu_state =
+			DFU_STATE_dfuMANIFEST_WAIT_RST;
+		to_runtime_mode(f_dfu);
+		f_dfu->dfu_state = DFU_STATE_appIDLE;
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_dnload_sync(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_dnbusy(struct f_dfu *f_dfu,
+			    const struct usb_ctrlrequest *ctrl,
+			    struct usb_gadget *gadget,
+			    struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_dnload_idle(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 len = le16_to_cpu(ctrl->wLength);
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_DNLOAD:
+		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
+		f_dfu->blk_seq_num = w_value;
+		value = handle_dnload(gadget, len);
+		break;
+	case USB_REQ_DFU_ABORT:
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		value = RET_ZLP;
+		break;
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_manifest_sync(struct f_dfu *f_dfu,
+				   const struct usb_ctrlrequest *ctrl,
+				   struct usb_gadget *gadget,
+				   struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		/* We're MainfestationTolerant */
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		handle_getstatus(req);
+		f_dfu->blk_seq_num = 0;
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_upload_idle(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 len = le16_to_cpu(ctrl->wLength);
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_UPLOAD:
+		/* state transition if less data then requested */
+		f_dfu->blk_seq_num = w_value;
+		value = handle_upload(req, len);
+		if (value >= 0 && value < len)
+			f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		break;
+	case USB_REQ_DFU_ABORT:
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		/* no zlp? */
+		value = RET_ZLP;
+		break;
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_error(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	case USB_REQ_DFU_CLRSTATUS:
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		f_dfu->dfu_status = DFU_STATUS_OK;
+		/* no zlp? */
+		value = RET_ZLP;
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static dfu_state_fn dfu_state[] = {
+	state_app_idle,          /* DFU_STATE_appIDLE */
+	state_app_detach,        /* DFU_STATE_appDETACH */
+	state_dfu_idle,          /* DFU_STATE_dfuIDLE */
+	state_dfu_dnload_sync,   /* DFU_STATE_dfuDNLOAD_SYNC */
+	state_dfu_dnbusy,        /* DFU_STATE_dfuDNBUSY */
+	state_dfu_dnload_idle,   /* DFU_STATE_dfuDNLOAD_IDLE */
+	state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */
+	NULL,                    /* DFU_STATE_dfuMANIFEST */
+	NULL,                    /* DFU_STATE_dfuMANIFEST_WAIT_RST */
+	state_dfu_upload_idle,   /* DFU_STATE_dfuUPLOAD_IDLE */
+	state_dfu_error          /* DFU_STATE_dfuERROR */
+};
+
+static int
+dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct usb_gadget *gadget = f->config->cdev->gadget;
+	struct usb_request *req = f->config->cdev->req;
+	struct f_dfu *f_dfu = f->config->cdev->req->context;
+	u16 len = le16_to_cpu(ctrl->wLength);
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	int value = 0;
+	u8 req_type = ctrl->bRequestType & USB_TYPE_MASK;
+
+	debug("w_value: 0x%x len: 0x%x\n", w_value, len);
+	debug("req_type: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n",
+	       req_type, ctrl->bRequest, f_dfu->dfu_state);
+
+
+	if (req_type == USB_TYPE_STANDARD) {
+		if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR &&
+		    (w_value >> 8) == DFU_DT_FUNC) {
+			value = min(len, (u16) sizeof dfu_func);
+			memcpy(req->buf, &dfu_func, value);
+		}
+	} else /* DFU specific request */
+		value = dfu_state[f_dfu->dfu_state] (f_dfu, ctrl, gadget, req);
+
+	if (value >= 0) {
+		req->length = value;
+		req->zero = value < len;
+		value = usb_ep_queue(gadget->ep0, req, 0);
+		if (value < 0) {
+			debug("ep_queue --> %d\n", value);
+			req->status = 0;
+		}
+	}
+
+	return value;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+dfu_prepare_strings(struct f_dfu *f_dfu, int n)
+{
+	struct dfu_entity *de = NULL;
+	int i = 0;
+
+	f_dfu->strings = calloc(sizeof(struct usb_string), n + 1);
+	if (!f_dfu->strings)
+		goto enomem;
+
+	for (i = 0; i < n; ++i) {
+		de = dfu_get_entity(i);
+		f_dfu->strings[i].s = de->name;
+	}
+
+	f_dfu->strings[i].id = 0;
+	f_dfu->strings[i].s = NULL;
+
+	return 0;
+
+enomem:
+	while (i)
+		f_dfu->strings[--i].s = NULL;
+
+	free(f_dfu->strings);
+
+	return -ENOMEM;
+}
+
+static int dfu_prepare_function(struct f_dfu *f_dfu, int n)
+{
+	struct usb_interface_descriptor *d;
+	int i = 0;
+
+	f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n);
+	if (!f_dfu->function)
+		goto enomem;
+
+	for (i = 0; i < n; ++i) {
+		d = calloc(sizeof(*d), 1);
+		if (!d)
+			goto enomem;
+
+		d->bLength =		sizeof(*d);
+		d->bDescriptorType =	USB_DT_INTERFACE;
+		d->bAlternateSetting =	i;
+		d->bNumEndpoints =	0;
+		d->bInterfaceClass =	USB_CLASS_APP_SPEC;
+		d->bInterfaceSubClass =	1;
+		d->bInterfaceProtocol =	2;
+
+		f_dfu->function[i] = (struct usb_descriptor_header *)d;
+	}
+	f_dfu->function[i] = NULL;
+
+	return 0;
+
+enomem:
+	while (i) {
+		free(f_dfu->function[--i]);
+		f_dfu->function[i] = NULL;
+	}
+	free(f_dfu->function);
+
+	return -ENOMEM;
+}
+
+static int dfu_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	int alt_num = dfu_get_alt_number();
+	int rv, id, i;
+
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	dfu_intf_runtime.bInterfaceNumber = id;
+
+	f_dfu->dfu_state = DFU_STATE_appIDLE;
+	f_dfu->dfu_status = DFU_STATUS_OK;
+
+	rv = dfu_prepare_function(f_dfu, alt_num);
+	if (rv)
+		goto error;
+
+	rv = dfu_prepare_strings(f_dfu, alt_num);
+	if (rv)
+		goto error;
+	for (i = 0; i < alt_num; i++) {
+		id = usb_string_id(cdev);
+		if (id < 0)
+			return id;
+		f_dfu->strings[i].id = id;
+		((struct usb_interface_descriptor *)f_dfu->function[i])
+			->iInterface = id;
+	}
+
+	stringtab_dfu.strings = f_dfu->strings;
+
+	cdev->req->context = f_dfu;
+
+error:
+	return rv;
+}
+
+static void dfu_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	int alt_num = dfu_get_alt_number();
+	int i;
+
+	if (f_dfu->strings) {
+		i = alt_num;
+		while (i)
+			f_dfu->strings[--i].s = NULL;
+
+		free(f_dfu->strings);
+	}
+
+	if (f_dfu->function) {
+		i = alt_num;
+		while (i) {
+			free(f_dfu->function[--i]);
+			f_dfu->function[i] = NULL;
+		}
+		free(f_dfu->function);
+	}
+
+	free(f_dfu);
+}
+
+static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+
+	debug("%s: intf:%d alt:%d\n", __func__, intf, alt);
+
+	f_dfu->altsetting = alt;
+
+	return 0;
+}
+
+/* TODO: is this really what we need here? */
+static void dfu_disable(struct usb_function *f)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	if (f_dfu->config == 0)
+		return;
+
+	debug("%s: reset config\n", __func__);
+
+	f_dfu->config = 0;
+}
+
+static int dfu_bind_config(struct usb_configuration *c)
+{
+	struct f_dfu *f_dfu;
+	int status;
+
+	f_dfu = calloc(sizeof(*f_dfu), 1);
+	if (!f_dfu)
+		return -ENOMEM;
+	f_dfu->usb_function.name = "dfu";
+	f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+	f_dfu->usb_function.bind = dfu_bind;
+	f_dfu->usb_function.unbind = dfu_unbind;
+	f_dfu->usb_function.set_alt = dfu_set_alt;
+	f_dfu->usb_function.disable = dfu_disable;
+	f_dfu->usb_function.strings = dfu_generic_strings,
+	f_dfu->usb_function.setup = dfu_handle,
+
+	status = usb_add_function(c, &f_dfu->usb_function);
+	if (status)
+		free(f_dfu);
+
+	return status;
+}
+
+int dfu_add(struct usb_configuration *c)
+{
+	int id;
+
+	id = usb_string_id(c->cdev);
+	if (id < 0)
+		return id;
+	strings_dfu_generic[0].id = id;
+	dfu_intf_runtime.iInterface = id;
+
+	debug("%s: cdev: 0x%p gadget:0x%p gadget->ep0: 0x%p\n", __func__,
+	       c->cdev, c->cdev->gadget, c->cdev->gadget->ep0);
+
+	return dfu_bind_config(c);
+}
diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h
new file mode 100644
index 0000000..023e1ad
--- /dev/null
+++ b/drivers/usb/gadget/f_dfu.h
@@ -0,0 +1,100 @@
+/*
+ * f_dfu.h -- Device Firmware Update gadget
+ *
+ * Copyright (C) 2011-2012 Samsung Electronics
+ * author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __F_DFU_H_
+#define __F_DFU_H_
+
+#include <linux/compiler.h>
+#include <linux/usb/composite.h>
+
+#define DFU_CONFIG_VAL			1
+#define DFU_DT_FUNC			0x21
+
+#define DFU_BIT_WILL_DETACH		(0x1 << 3)
+#define DFU_BIT_MANIFESTATION_TOLERANT	(0x1 << 2)
+#define DFU_BIT_CAN_UPLOAD		(0x1 << 1)
+#define DFU_BIT_CAN_DNLOAD		0x1
+
+/* big enough to hold our biggest descriptor */
+#define DFU_USB_BUFSIZ			4096
+
+#define USB_REQ_DFU_DETACH		0x00
+#define USB_REQ_DFU_DNLOAD		0x01
+#define USB_REQ_DFU_UPLOAD		0x02
+#define USB_REQ_DFU_GETSTATUS		0x03
+#define USB_REQ_DFU_CLRSTATUS		0x04
+#define USB_REQ_DFU_GETSTATE		0x05
+#define USB_REQ_DFU_ABORT		0x06
+
+#define DFU_STATUS_OK			0x00
+#define DFU_STATUS_errTARGET		0x01
+#define DFU_STATUS_errFILE		0x02
+#define DFU_STATUS_errWRITE		0x03
+#define DFU_STATUS_errERASE		0x04
+#define DFU_STATUS_errCHECK_ERASED	0x05
+#define DFU_STATUS_errPROG		0x06
+#define DFU_STATUS_errVERIFY		0x07
+#define DFU_STATUS_errADDRESS		0x08
+#define DFU_STATUS_errNOTDONE		0x09
+#define DFU_STATUS_errFIRMWARE		0x0a
+#define DFU_STATUS_errVENDOR		0x0b
+#define DFU_STATUS_errUSBR		0x0c
+#define DFU_STATUS_errPOR		0x0d
+#define DFU_STATUS_errUNKNOWN		0x0e
+#define DFU_STATUS_errSTALLEDPKT	0x0f
+
+#define RET_STALL			-1
+#define RET_ZLP				0
+#define RET_STAT_LEN			6
+
+enum dfu_state {
+	DFU_STATE_appIDLE		= 0,
+	DFU_STATE_appDETACH		= 1,
+	DFU_STATE_dfuIDLE		= 2,
+	DFU_STATE_dfuDNLOAD_SYNC	= 3,
+	DFU_STATE_dfuDNBUSY		= 4,
+	DFU_STATE_dfuDNLOAD_IDLE	= 5,
+	DFU_STATE_dfuMANIFEST_SYNC	= 6,
+	DFU_STATE_dfuMANIFEST		= 7,
+	DFU_STATE_dfuMANIFEST_WAIT_RST	= 8,
+	DFU_STATE_dfuUPLOAD_IDLE	= 9,
+	DFU_STATE_dfuERROR		= 10,
+};
+
+struct dfu_status {
+	__u8				bStatus;
+	__u8				bwPollTimeout[3];
+	__u8				bState;
+	__u8				iString;
+} __packed;
+
+struct dfu_function_descriptor {
+	__u8				bLength;
+	__u8				bDescriptorType;
+	__u8				bmAttributes;
+	__le16				wDetachTimeOut;
+	__le16				wTransferSize;
+	__le16				bcdDFUVersion;
+} __packed;
+
+/* configuration-specific linkup */
+int dfu_add(struct usb_configuration *c);
+#endif /* __F_DFU_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 3/7] dfu: DFU backend implementation
  2012-07-04 15:48 ` [U-Boot] [PATCH v2 " Lukasz Majewski
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
@ 2012-07-04 15:48   ` Lukasz Majewski
  2012-07-09 16:35     ` Marek Vasut
  2012-07-27 11:58     ` Wolfgang Denk
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
                     ` (4 subsequent siblings)
  7 siblings, 2 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04 15:48 UTC (permalink / raw)
  To: u-boot

New, separate driver at ./drivers/dfu has been added. It allows platform
and storage independent operation of DFU.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:
- None
---
 Makefile             |    1 +
 drivers/dfu/Makefile |   43 ++++++++
 drivers/dfu/dfu.c    |  259 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/dfu.h        |   99 +++++++++++++++++++
 4 files changed, 402 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dfu/Makefile
 create mode 100644 drivers/dfu/dfu.c
 create mode 100644 include/dfu.h

diff --git a/Makefile b/Makefile
index 0197239..c37dcf3 100644
--- a/Makefile
+++ b/Makefile
@@ -271,6 +271,7 @@ LIBS += drivers/pci/libpci.o
 LIBS += drivers/pcmcia/libpcmcia.o
 LIBS += drivers/power/libpower.o
 LIBS += drivers/spi/libspi.o
+LIBS += drivers/dfu/libdfu.o
 ifeq ($(CPU),mpc83xx)
 LIBS += drivers/qe/libqe.o
 LIBS += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o
diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
new file mode 100644
index 0000000..7736485
--- /dev/null
+++ b/drivers/dfu/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2012 Samsung Electronics
+# Lukasz Majewski <l.majewski@samsung.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)libdfu.o
+
+COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
+
+SRCS    := $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
new file mode 100644
index 0000000..63733fb
--- /dev/null
+++ b/drivers/dfu/dfu.c
@@ -0,0 +1,259 @@
+/*
+ * dfu.c -- DFU back-end routines
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <fat.h>
+#include <dfu.h>
+#include <linux/list.h>
+#include <linux/compiler.h>
+
+static LIST_HEAD(dfu_list);
+static int dfu_alt_num;
+
+static int dfu_find_alt_num(char *s)
+{
+	int i = 0;
+
+	for (; *s; s++)
+		if (*s == ';')
+			i++;
+
+	return ++i;
+}
+
+static char *dfu_extract_entity(char** env)
+{
+	char *s = *env;
+
+	strsep(env, ";");
+	return s;
+}
+
+char *dfu_extract_token(char** e, int *n)
+{
+	char *st = *e;
+
+	debug("%s: %s\n", __func__, st);
+
+	strsep(e, " ");
+	*n = *e - st;
+
+	return st;
+}
+
+static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
+				     dfu_buf[DFU_DATA_BUF_SIZE];
+
+int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
+{
+	static unsigned char *i_buf;
+	static int i_blk_seq_num;
+	long w_size = 0;
+	int ret = 0;
+
+	debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
+	       __func__, dfu->name, buf, size, blk_seq_num, i_buf);
+
+	if (blk_seq_num == 0) {
+		memset(dfu_buf, '\0', sizeof(dfu_buf));
+		i_buf = dfu_buf;
+		i_blk_seq_num = 0;
+	}
+
+	if (i_blk_seq_num++ != blk_seq_num) {
+		printf("%s: Wrong sequence number! [%d] [%d]\n",
+		       __func__, i_blk_seq_num, blk_seq_num);
+		return -1;
+	}
+
+	memcpy(i_buf, buf, size);
+	i_buf += size;
+
+	if (size == 0) {
+		/* Integrity check (if needed) */
+		debug("%s: %s %d [B] CRC32: 0x%x\n", __func__, dfu->name,
+		       i_buf - dfu_buf, crc32(0, dfu_buf, i_buf - dfu_buf));
+
+		w_size = i_buf - dfu_buf;
+		ret = dfu->write_medium(dfu, dfu_buf, &w_size);
+		if (ret)
+			debug("%s: Write error!\n", __func__);
+
+		i_blk_seq_num = 0;
+		i_buf = NULL;
+		return ret;
+	}
+
+	return ret;
+}
+
+int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
+{
+	static unsigned char *i_buf;
+	static int i_blk_seq_num;
+	static long r_size;
+	static u32 crc;
+	int ret = 0;
+
+	debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
+	       __func__, dfu->name, buf, size, blk_seq_num, i_buf);
+
+	if (blk_seq_num == 0) {
+		i_buf = dfu_buf;
+		memset(dfu_buf, '\0', sizeof(dfu_buf));
+		ret = dfu->read_medium(dfu, i_buf, &r_size);
+		debug("%s: %s %ld [B]\n", __func__, dfu->name, r_size);
+		i_blk_seq_num = 0;
+		/* Integrity check (if needed) */
+		crc = crc32(0, dfu_buf, r_size);
+	}
+
+	if (i_blk_seq_num++ != blk_seq_num) {
+		printf("%s: Wrong sequence number! [%d] [%d]\n",
+		       __func__, i_blk_seq_num, blk_seq_num);
+		return -1;
+	}
+
+	if (r_size >= size) {
+		memcpy(buf, i_buf, size);
+		i_buf += size;
+		r_size -= size;
+		return size;
+	} else {
+		memcpy(buf, i_buf, r_size);
+		i_buf += r_size;
+		debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name, crc);
+		puts("UPLOAD ... done\n");
+		puts("Ctrl+C to exit ...\n");
+
+		i_buf = NULL;
+		i_blk_seq_num = 0;
+		crc = 0;
+		return r_size;
+	}
+	return ret;
+}
+
+static int dfu_fill_entity(struct dfu_entity *dfu, char* s, int alt,
+			    char *interface, int num)
+{
+	char *st = NULL;
+	int n = 0;
+
+	debug("%s: %s interface: %s num: %d\n", __func__, s, interface, num);
+
+	st = dfu_extract_token(&s, &n);
+	strncpy((char *) &dfu->name, st, n);
+
+	dfu->dev_num = num;
+	dfu->alt = alt;
+
+	/* Specific for mmc device */
+	if (strcmp(interface, "mmc") == 0) {
+		if (dfu_fill_entity_mmc(dfu, s))
+			return -1;
+	} else {
+		printf("dfu: Device %s not supported\n", interface);
+		return -1;
+	}
+
+	return 0;
+}
+
+int dfu_config_entities(char *env, char *interface, int num)
+{
+	struct dfu_entity *dfu;
+	int i, ret;
+	char *s;
+
+	dfu_alt_num = dfu_find_alt_num(env);
+	debug("%s: dfu_alt_num=%d\n", __func__, dfu_alt_num);
+
+	for (i = 0; i < dfu_alt_num; i++) {
+		dfu = calloc(sizeof(struct dfu_entity), 1);
+
+		s = dfu_extract_entity(&env);
+		ret = dfu_fill_entity(dfu, s, i, interface, num);
+		if (ret)
+			return -1;
+
+		list_add_tail(&dfu->list, &dfu_list);
+	}
+
+	return 0;
+}
+
+void dfu_free_entities(void)
+{
+	struct dfu_entity *dfu = NULL, *p = NULL;
+
+	list_for_each_entry_safe_reverse(dfu, p, &dfu_list, list) {
+		list_del(&dfu->list);
+		free(dfu);
+	}
+
+	INIT_LIST_HEAD(&dfu_list);
+}
+
+static char *dfu_get_dev_type(enum dfu_device_type t)
+{
+	static char *dev_t[] = {NULL, "MMC", "ONENAND", "NAND" };
+	return dev_t[t];
+}
+
+static char *dfu_get_layout(enum dfu_device_type l)
+{
+	static char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT" };
+	return dfu_layout[l];
+}
+
+void dfu_show_entities(void)
+{
+	struct dfu_entity *dfu = NULL;
+
+	puts("DFU alt settings list:\n");
+
+	list_for_each_entry(dfu, &dfu_list, list) {
+		printf("dev: %s alt: %d name: %s layout: %s\n",
+		       dfu_get_dev_type(dfu->dev_type), dfu->alt,
+		       dfu->name, dfu_get_layout(dfu->layout));
+	}
+}
+
+int dfu_get_alt_number(void)
+{
+	return dfu_alt_num;
+}
+
+struct dfu_entity *dfu_get_entity(int alt)
+{
+	struct dfu_entity *dfu = NULL;
+
+	list_for_each_entry(dfu, &dfu_list, list) {
+		if (dfu->alt == alt)
+			return dfu;
+	}
+
+	return NULL;
+}
diff --git a/include/dfu.h b/include/dfu.h
new file mode 100644
index 0000000..f7d823b
--- /dev/null
+++ b/include/dfu.h
@@ -0,0 +1,99 @@
+/*
+ * dfu.h - DFU flashable area description
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __DFU_ENTITY_H_
+#define __DFU_ENTITY_H_
+
+#include <common.h>
+#include <linux/list.h>
+#include <mmc.h>
+
+enum dfu_device_type {
+	MMC = 1,
+	ONENAND,
+	NAND
+};
+
+enum dfu_layout {
+	RAW_ADDR = 1,
+	FAT,
+	EXT,
+};
+
+struct mmc_internal_data {
+	/* RAW programming */
+	unsigned int lba_start;
+	unsigned int lba_size;
+	unsigned int lba_blk_size;
+
+	/* FAT/EXT */
+	unsigned int dev;
+	unsigned int part;
+};
+
+static inline unsigned int get_mmc_blk_size(int dev)
+{
+	return find_mmc_device(dev)->read_bl_len;
+}
+
+#define DFU_NAME_SIZE 32
+#define DFU_CMD_BUF_SIZE 128
+#define DFU_DATA_BUF_SIZE (1024*1024*4) /* 4 MiB */
+
+struct dfu_entity {
+	char			name[DFU_NAME_SIZE];
+	int                     alt;
+	void                    *dev_private;
+	int                     dev_num;
+	enum dfu_device_type    dev_type;
+	enum dfu_layout         layout;
+
+	union {
+		struct mmc_internal_data mmc;
+	} data;
+
+	int (*read_medium)(struct dfu_entity *dfu, void *buf, long *len);
+	int (*write_medium)(struct dfu_entity *dfu, void *buf, long *len);
+
+	struct list_head list;
+};
+
+int dfu_config_entities(char *s, char *interface, int num);
+void dfu_free_entities(void);
+void dfu_show_entities(void);
+int dfu_get_alt_number(void);
+struct dfu_entity *dfu_get_entity(int alt);
+char *dfu_extract_token(char** e, int *n);
+
+int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
+int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
+/* Device specific */
+#ifdef CONFIG_DFU_MMC
+extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s);
+#else
+static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s)
+{
+	puts("MMC support not available!\n");
+	return -1;
+}
+#endif
+#endif /* __DFU_ENTITY_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-04 15:48 ` [U-Boot] [PATCH v2 " Lukasz Majewski
                     ` (2 preceding siblings ...)
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 3/7] dfu: DFU backend implementation Lukasz Majewski
@ 2012-07-04 15:48   ` Lukasz Majewski
  2012-07-09 16:36     ` Marek Vasut
                       ` (2 more replies)
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
                     ` (3 subsequent siblings)
  7 siblings, 3 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04 15:48 UTC (permalink / raw)
  To: u-boot

Support for MMC storage devices to work with DFU framework.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:
- None
---
 drivers/dfu/Makefile  |    1 +
 drivers/dfu/dfu_mmc.c |  126 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 127 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dfu/dfu_mmc.c

diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
index 7736485..7b717bc 100644
--- a/drivers/dfu/Makefile
+++ b/drivers/dfu/Makefile
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)libdfu.o
 
 COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
+COBJS-$(CONFIG_DFU_MMC) += dfu_mmc.o
 
 SRCS    := $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS-y))
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
new file mode 100644
index 0000000..3151fbc
--- /dev/null
+++ b/drivers/dfu/dfu_mmc.c
@@ -0,0 +1,126 @@
+/*
+ * dfu.c -- DFU back-end routines
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <dfu.h>
+
+int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf, DFU_CMD_BUF_SIZE);
+
+	memset(cmd_buf, '\0', sizeof(cmd_buf));
+
+	switch (dfu->layout) {
+	case RAW_ADDR:
+		sprintf(cmd_buf, "mmc write 0x%x %x %x", (unsigned int) buf,
+			dfu->data.mmc.lba_start, dfu->data.mmc.lba_size);
+		break;
+	case FAT:
+		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx",
+			dfu->data.mmc.dev, dfu->data.mmc.part,
+			(unsigned int) buf, dfu->name, *len);
+		break;
+	default:
+		printf("%s: Wrong layout!\n", __func__);
+	}
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+	run_command(cmd_buf, 0);
+
+	return 0;
+}
+
+int dfu_read_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf, DFU_CMD_BUF_SIZE);
+	char *str_env = NULL;
+	int ret = 0;
+
+	memset(cmd_buf, '\0', sizeof(cmd_buf));
+
+	switch (dfu->layout) {
+	case RAW_ADDR:
+		sprintf(cmd_buf, "mmc read 0x%x %x %x", (unsigned int) buf,
+			dfu->data.mmc.lba_start, dfu->data.mmc.lba_size);
+
+		*len = dfu->data.mmc.lba_blk_size * dfu->data.mmc.lba_size;
+		break;
+	case FAT:
+		sprintf(cmd_buf, "fatload mmc %d:%d 0x%x %s",
+			dfu->data.mmc.dev, dfu->data.mmc.part,
+			(unsigned int) buf, dfu->name);
+		break;
+	default:
+		printf("%s: Wrong layout!\n", __func__);
+	}
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+
+	ret = run_command(cmd_buf, 0);
+	if (ret) {
+		puts("dfu: Read error!\n");
+		return ret;
+	}
+
+	if (dfu->layout != RAW_ADDR) {
+		str_env = getenv("filesize");
+		if (str_env == NULL) {
+			puts("dfu: Wrong file size!\n");
+			return -1;
+		}
+
+		*len = simple_strtoul(str_env, NULL, 16);
+	}
+	return ret;
+}
+
+int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s)
+{
+	char *st = NULL;
+	int n = 0;
+
+	dfu->dev_type = MMC;
+	st = dfu_extract_token(&s, &n);
+
+	if (!strncmp(st, "mmc", n)) {
+		dfu->layout = RAW_ADDR;
+
+		dfu->data.mmc.lba_start = simple_strtoul(s, &s, 16);
+		dfu->data.mmc.lba_size = simple_strtoul(++s, &s, 16);
+		dfu->data.mmc.lba_blk_size = get_mmc_blk_size(dfu->dev_num);
+
+	} else if (!strncmp(st, "fat", n)) {
+		dfu->layout = FAT;
+
+		dfu->data.mmc.dev = simple_strtoul(s, &s, 10);
+		dfu->data.mmc.part = simple_strtoul(++s, &s, 10);
+
+	} else {
+		printf("%s: Wrong memory layout!\n", __func__);
+	}
+
+	dfu->read_medium = dfu_read_medium_mmc;
+	dfu->write_medium = dfu_write_medium_mmc;
+
+	return 0;
+}
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-04 15:48 ` [U-Boot] [PATCH v2 " Lukasz Majewski
                     ` (3 preceding siblings ...)
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
@ 2012-07-04 15:48   ` Lukasz Majewski
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04 15:48 UTC (permalink / raw)
  To: u-boot

Support for u-boot's command line command "dfu <interface> <dev> [list]".

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:
- None
---
 common/Makefile  |    1 +
 common/cmd_dfu.c |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+), 0 deletions(-)
 create mode 100644 common/cmd_dfu.c

diff --git a/common/Makefile b/common/Makefile
index 31175e3..9d60fe1 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -184,6 +184,7 @@ COBJS-$(CONFIG_MENU) += menu.o
 COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o
 COBJS-$(CONFIG_UPDATE_TFTP) += update.o
 COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
+COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o
 endif
 
 ifdef CONFIG_SPL_BUILD
diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
new file mode 100644
index 0000000..ceb0f54
--- /dev/null
+++ b/common/cmd_dfu.c
@@ -0,0 +1,81 @@
+/*
+ * cmd_dfu.c -- dfu command
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <dfu.h>
+#include <asm/errno.h>
+#include <g_dnl.h>
+
+int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	char *str_env = NULL, *env_bkp = NULL;
+	static char *s = "dfu";
+	int ret = 0;
+
+	if (argc < 3)
+		return CMD_RET_USAGE;
+
+	str_env = getenv("dfu_alt_info");
+	if (str_env == NULL) {
+		printf("%s: \"dfu_alt_info\" env variable not defined!\n",
+		       __func__);
+		return CMD_RET_FAILURE;
+	}
+
+	env_bkp = strdup(str_env);
+	ret = dfu_config_entities(env_bkp, argv[1],
+			    (int)simple_strtoul(argv[2], NULL, 10));
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	if (strcmp(argv[3], "list") == 0) {
+		dfu_show_entities();
+		dfu_free_entities();
+		free(env_bkp);
+		return CMD_RET_SUCCESS;
+	}
+
+	board_usb_init();
+	g_dnl_init(s);
+	while (1) {
+		if (ctrlc())
+			goto exit;
+
+		usb_gadget_handle_interrupts();
+	}
+exit:
+	g_dnl_cleanup();
+	dfu_free_entities();
+	free(env_bkp);
+
+	return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu,
+	"Device Firmware Upgrade",
+	"<interface> <dev> [list]\n"
+	"  - device firmware upgrade on a device <dev>\n"
+	"    attached to interface <interface>\n"
+	"    [list] - list available alt settings"
+);
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 6/7] arm:trats: Support for USB UDC driver at TRATS board.
  2012-07-04 15:48 ` [U-Boot] [PATCH v2 " Lukasz Majewski
                     ` (4 preceding siblings ...)
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
@ 2012-07-04 15:48   ` Lukasz Majewski
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
  2012-07-09 11:28   ` [U-Boot] [PATCH v2 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
  7 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04 15:48 UTC (permalink / raw)
  To: u-boot

Support for USB UDC driver at trats board.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Minkyu Kang <mk7.kang@samsung.com>

---
Changes for v2:
- replace puts to debug
---
 board/samsung/trats/trats.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/board/samsung/trats/trats.c b/board/samsung/trats/trats.c
index a95a516..a557e5c 100644
--- a/board/samsung/trats/trats.c
+++ b/board/samsung/trats/trats.c
@@ -59,6 +59,8 @@ static int hwrevision(int rev)
 	return (board_rev & 0xf) == rev;
 }
 
+struct s3c_plat_otg_data s5pc210_otg_data;
+
 int board_init(void)
 {
 	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
@@ -259,6 +261,12 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
 	.usb_phy_ctrl	= EXYNOS4_USBPHY_CONTROL,
 	.usb_flags	= PHY0_SLEEP,
 };
+
+void board_usb_init(void)
+{
+	debug("USB_udc_probe\n");
+	s3c_udc_probe(&s5pc210_otg_data);
+}
 #endif
 
 static void pmic_reset(void)
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS
  2012-07-04 15:48 ` [U-Boot] [PATCH v2 " Lukasz Majewski
                     ` (5 preceding siblings ...)
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
@ 2012-07-04 15:48   ` Lukasz Majewski
  2012-07-09 11:28   ` [U-Boot] [PATCH v2 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
  7 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-04 15:48 UTC (permalink / raw)
  To: u-boot

Enable the g_dnl composite USB gadget driver with embedded DFU function on it.
It now uses the composite gadget framework to support download specific
USB functions (like enabled DFU or USB Mass Storage).

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Minkyu Kang <mk7.kang@samsung.com>

---
Change for v2:
- Move the G_DNL_{VENDOR_NUM, PRODUCT_NUM and MANUFACTURER} definitions to
  ./include/configs/<board>.h
---
 include/configs/trats.h |   24 +++++++++++++++++++++++-
 1 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/include/configs/trats.h b/include/configs/trats.h
index eb269b2..a24e73d 100644
--- a/include/configs/trats.h
+++ b/include/configs/trats.h
@@ -94,6 +94,21 @@
 #undef CONFIG_CMD_ONENAND
 #undef CONFIG_CMD_MTDPARTS
 #define CONFIG_CMD_MMC
+#define CONFIG_CMD_DFU
+
+/* FAT */
+#define CONFIG_CMD_FAT
+#define CONFIG_FAT_WRITE
+
+/* USB Composite download gadget - g_dnl */
+#define CONFIG_USBDOWNLOAD_GADGET
+#define CONFIG_DFU_FUNCTION
+#define CONFIG_DFU_MMC
+
+/* USB Samsung's IDs */
+#define G_DNL_VENDOR_NUM 0x04E8
+#define G_DNL_PRODUCT_NUM 0x6601
+#define G_DNL_MANUFACTURER "Samsung"
 
 #define CONFIG_BOOTDELAY		1
 #define CONFIG_ZERO_BOOTDELAY_CHECK
@@ -104,6 +119,11 @@
 #define CONFIG_BOOTBLOCK		"10"
 #define CONFIG_ENV_COMMON_BOOT		"${console} ${meminfo}"
 
+#define CONFIG_DFU_ALT \
+	"dfu_alt_info=" \
+	"u-boot mmc 80 400;" \
+	"uImage fat 0 2\0" \
+
 #define CONFIG_ENV_OVERWRITE
 #define CONFIG_SYS_CONSOLE_INFO_QUIET
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
@@ -146,7 +166,8 @@
 	"mmcdev=0\0" \
 	"mmcbootpart=2\0" \
 	"mmcrootpart=3\0" \
-	"opts=always_resume=1"
+	"opts=always_resume=1\0" \
+	CONFIG_DFU_ALT
 
 /* Miscellaneous configurable options */
 #define CONFIG_SYS_LONGHELP		/* undef to save memory */
@@ -209,6 +230,7 @@
 #define CONFIG_USB_GADGET
 #define CONFIG_USB_GADGET_S3C_UDC_OTG
 #define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_GADGET_VBUS_DRAW	2
 
 /* LCD */
 #define CONFIG_EXYNOS_FB
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  2012-07-04 15:04         ` Lukasz Majewski
@ 2012-07-04 16:21           ` Marek Vasut
  0 siblings, 0 replies; 147+ messages in thread
From: Marek Vasut @ 2012-07-04 16:21 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

[...]

> > > > Now ... this is ubercrazy ... can't this be made without this
> > > > typecasting voodoo?
> > > 
> > > The problem is that req->buf is a void pointer. And the goal is to
> > > store dfu state at 8 bits.
> > 
> > Sure, but why not make the buffer u8 ?
> 
> The req->buf is a member of usb_request defined at gadget.h.
> 
> It represents the request from USB. I cannot guarantee, that we will
> always regard data pointed by buf as u8. For flexibility of gadget
> usage it is safer to leave it as void pointer.

OK, then it's good :)

[...]

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 3/7] dfu: DFU backend implementation
  2012-07-04 15:07         ` Lukasz Majewski
@ 2012-07-04 16:22           ` Marek Vasut
  0 siblings, 0 replies; 147+ messages in thread
From: Marek Vasut @ 2012-07-04 16:22 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

[...]

> > 
> > And will those pieces be implemented any soon ? :)
> :
> :-). Since I'm the OneNAND custodian I shall keep in the back of my
> 
> head, that support for this memory is important :-)

Good, will look forward to it :)


Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 0/7] dfu:usb: Composite USB download gadget with DFU function
  2012-07-04 15:48 ` [U-Boot] [PATCH v2 " Lukasz Majewski
                     ` (6 preceding siblings ...)
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
@ 2012-07-09 11:28   ` Lukasz Majewski
  2012-07-09 11:46     ` Tom Rini
  7 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-09 11:28 UTC (permalink / raw)
  To: u-boot

Hi Marek,


> Those patches add support for composite USB download gadget.
> This gadget (at least for now) is equipped with DFU download function.
> 
> A separate DFU back-end and front-end have been added.
> Back-end is placed at ./drivers/dfu directory. The front-end is
> implemented as USB function.
> 
> The back-end is written in a generic manner with storage device
> specific code separated (eMMC).
> 
> DFU specification can be found at:
> http://wiki.openmoko.org/wiki/USB_DFU_-_The_USB_Device_Firmware_Upgrade_standard
> 
> Example usage:
> 
> u-boot side: dfu mmc 0
> PC: dfu-util -U IMAGE.bin -a uImage (for upload)
>     dfu-util -D uImage -a uImage (download)
> 
> To list the alt settings:
>         dfu mmc 0 list
> 
> Test HW:
>         Exynos4210 Trats board
> 
> 
> Lukasz Majewski (7):
>   dfu:usb: Support for g_dnl composite download gadget.
>   dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
>   dfu: DFU backend implementation
>   dfu: MMC specific routines for DFU operation
>   dfu:cmd: Support for DFU u-boot command
>   arm:trats: Support for USB UDC driver at TRATS board.
>   arm:trats: Enable g_dnl composite USB gadget with embedded DFU
>     function on TRATS

Do you have more comments about those patches? 


-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 0/7] dfu:usb: Composite USB download gadget with DFU function
  2012-07-09 11:28   ` [U-Boot] [PATCH v2 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
@ 2012-07-09 11:46     ` Tom Rini
  2012-07-09 16:25       ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Tom Rini @ 2012-07-09 11:46 UTC (permalink / raw)
  To: u-boot

On Mon, Jul 09, 2012 at 01:28:27PM +0200, Lukasz Majewski wrote:
> Hi Marek,
> 
> 
> > Those patches add support for composite USB download gadget.
> > This gadget (at least for now) is equipped with DFU download function.
> > 
> > A separate DFU back-end and front-end have been added.
> > Back-end is placed at ./drivers/dfu directory. The front-end is
> > implemented as USB function.
> > 
> > The back-end is written in a generic manner with storage device
> > specific code separated (eMMC).
> > 
> > DFU specification can be found at:
> > http://wiki.openmoko.org/wiki/USB_DFU_-_The_USB_Device_Firmware_Upgrade_standard
> > 
> > Example usage:
> > 
> > u-boot side: dfu mmc 0
> > PC: dfu-util -U IMAGE.bin -a uImage (for upload)
> >     dfu-util -D uImage -a uImage (download)
> > 
> > To list the alt settings:
> >         dfu mmc 0 list
> > 
> > Test HW:
> >         Exynos4210 Trats board
> > 
> > 
> > Lukasz Majewski (7):
> >   dfu:usb: Support for g_dnl composite download gadget.
> >   dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
> >   dfu: DFU backend implementation
> >   dfu: MMC specific routines for DFU operation
> >   dfu:cmd: Support for DFU u-boot command
> >   arm:trats: Support for USB UDC driver at TRATS board.
> >   arm:trats: Enable g_dnl composite USB gadget with embedded DFU
> >     function on TRATS
> 
> Do you have more comments about those patches? 

I _think_ he's been busy with exams and preparing for the U-Boot BoF
this week.  I'll make sure this gets brought up then however.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120709/db7e1ef4/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 0/7] dfu:usb: Composite USB download gadget with DFU function
  2012-07-09 11:46     ` Tom Rini
@ 2012-07-09 16:25       ` Marek Vasut
  2012-07-10  8:27         ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-09 16:25 UTC (permalink / raw)
  To: u-boot

Dear Tom Rini,

> On Mon, Jul 09, 2012 at 01:28:27PM +0200, Lukasz Majewski wrote:
> > Hi Marek,
> > 
> > > Those patches add support for composite USB download gadget.
> > > This gadget (at least for now) is equipped with DFU download function.
> > > 
> > > A separate DFU back-end and front-end have been added.
> > > Back-end is placed at ./drivers/dfu directory. The front-end is
> > > implemented as USB function.
> > > 
> > > The back-end is written in a generic manner with storage device
> > > specific code separated (eMMC).
> > > 
> > > DFU specification can be found at:
> > > http://wiki.openmoko.org/wiki/USB_DFU_-_The_USB_Device_Firmware_Upgrade
> > > _standard
> > > 
> > > Example usage:
> > > 
> > > u-boot side: dfu mmc 0
> > > PC: dfu-util -U IMAGE.bin -a uImage (for upload)
> > > 
> > >     dfu-util -D uImage -a uImage (download)
> > > 
> > > To list the alt settings:
> > >         dfu mmc 0 list
> > > 
> > > Test HW:
> > >         Exynos4210 Trats board
> > > 
> > > Lukasz Majewski (7):
> > >   dfu:usb: Support for g_dnl composite download gadget.
> > >   dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
> > >   dfu: DFU backend implementation
> > >   dfu: MMC specific routines for DFU operation
> > >   dfu:cmd: Support for DFU u-boot command
> > >   arm:trats: Support for USB UDC driver at TRATS board.
> > >   arm:trats: Enable g_dnl composite USB gadget with embedded DFU
> > >   
> > >     function on TRATS
> > 
> > Do you have more comments about those patches?
> 
> I _think_ he's been busy with exams and preparing for the U-Boot BoF
> this week.  I'll make sure this gets brought up then however.

Exams are long past, but there's a lot of other stuff -- the driver model, the 
denx work, the LSM this week -- I wish I could cut myself in four or so.

But weren't there some open questions, especially about the function vs. command 
stuff? The rest were really minor things and I believe you closed them with 
ease. There are just the few big questions, but it doesn't seem people are too 
interested to discuss them.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 1/7] dfu:usb: Support for g_dnl composite download gadget.
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
@ 2012-07-09 16:30     ` Marek Vasut
  0 siblings, 0 replies; 147+ messages in thread
From: Marek Vasut @ 2012-07-09 16:30 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> Composite USB download gadget support (g_dnl) for download functions.
> This code works on top of composite gadget.
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> 
> ---
> Changes for v2:
> 
> - G_DNL_{VENDOR_NUM, PRODUCT_NUM and MANUFACTURER} defined at

make this CONFIG_G_....

The rest seems ok.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
@ 2012-07-09 16:34     ` Marek Vasut
  0 siblings, 0 replies; 147+ messages in thread
From: Marek Vasut @ 2012-07-09 16:34 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> Support for f_dfu USB function.
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> 
[...]

> +static void handle_getstatus(struct usb_request *req)
> +{
> +	struct dfu_status *dstat = (struct dfu_status *)req->buf;
> +	struct f_dfu *f_dfu = req->context;
> +
> +	switch (f_dfu->dfu_state) {
> +	case DFU_STATE_dfuDNLOAD_SYNC:
> +	case DFU_STATE_dfuDNBUSY:
> +		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
> +		break;
> +	case DFU_STATE_dfuMANIFEST_SYNC:
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	/* send status response */
> +	dstat->bStatus = f_dfu->dfu_status;
> +	/* FIXME: set dstat->bwPollTimeout */

FIXME? :)

> +	dstat->bState = f_dfu->dfu_state;
> +	dstat->iString = 0;
> +}

[...]

> +static int
> +dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
> +{
> +	struct usb_gadget *gadget = f->config->cdev->gadget;
> +	struct usb_request *req = f->config->cdev->req;
> +	struct f_dfu *f_dfu = f->config->cdev->req->context;
> +	u16 len = le16_to_cpu(ctrl->wLength);
> +	u16 w_value = le16_to_cpu(ctrl->wValue);
> +	int value = 0;
> +	u8 req_type = ctrl->bRequestType & USB_TYPE_MASK;
> +
> +	debug("w_value: 0x%x len: 0x%x\n", w_value, len);
> +	debug("req_type: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n",
> +	       req_type, ctrl->bRequest, f_dfu->dfu_state);
> +
> +
> +	if (req_type == USB_TYPE_STANDARD) {
> +		if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR &&
> +		    (w_value >> 8) == DFU_DT_FUNC) {
> +			value = min(len, (u16) sizeof dfu_func);

Does the sizeof really miss braces up here ?

[...]

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 3/7] dfu: DFU backend implementation
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 3/7] dfu: DFU backend implementation Lukasz Majewski
@ 2012-07-09 16:35     ` Marek Vasut
  2012-07-27 11:58     ` Wolfgang Denk
  1 sibling, 0 replies; 147+ messages in thread
From: Marek Vasut @ 2012-07-09 16:35 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> New, separate driver at ./drivers/dfu has been added. It allows platform
> and storage independent operation of DFU.
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> 

[...]

> +char *dfu_extract_token(char** e, int *n)
> +{
> +	char *st = *e;
> +
> +	debug("%s: %s\n", __func__, st);
> +
> +	strsep(e, " ");
> +	*n = *e - st;
> +
> +	return st;
> +}

Sigh, what about these? btw don't we have strtok?
[...]


Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
@ 2012-07-09 16:36     ` Marek Vasut
  2012-07-10  8:45     ` Tom Rini
  2012-07-27 12:36     ` Wolfgang Denk
  2 siblings, 0 replies; 147+ messages in thread
From: Marek Vasut @ 2012-07-09 16:36 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> Support for MMC storage devices to work with DFU framework.
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> 

This one opens some questions.

[...]

> +int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s)
> +{
> +	char *st = NULL;
> +	int n = 0;
> +
> +	dfu->dev_type = MMC;
> +	st = dfu_extract_token(&s, &n);
> +
> +	if (!strncmp(st, "mmc", n)) {
> +		dfu->layout = RAW_ADDR;
> +
> +		dfu->data.mmc.lba_start = simple_strtoul(s, &s, 16);
> +		dfu->data.mmc.lba_size = simple_strtoul(++s, &s, 16);
> +		dfu->data.mmc.lba_blk_size = get_mmc_blk_size(dfu->dev_num);
> +

^ one line too much.

> +	} else if (!strncmp(st, "fat", n)) {
> +		dfu->layout = FAT;
> +
> +		dfu->data.mmc.dev = simple_strtoul(s, &s, 10);
> +		dfu->data.mmc.part = simple_strtoul(++s, &s, 10);
> +
> +	} else {
> +		printf("%s: Wrong memory layout!\n", __func__);
> +	}
> +
> +	dfu->read_medium = dfu_read_medium_mmc;
> +	dfu->write_medium = dfu_write_medium_mmc;
> +
> +	return 0;
> +}

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 0/7] dfu:usb: Composite USB download gadget with DFU function
  2012-07-09 16:25       ` Marek Vasut
@ 2012-07-10  8:27         ` Lukasz Majewski
  2012-07-10  9:28           ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-10  8:27 UTC (permalink / raw)
  To: u-boot

Hi Marek,

> Dear Tom Rini,
> 
> > On Mon, Jul 09, 2012 at 01:28:27PM +0200, Lukasz Majewski wrote:
> > > Hi Marek,
> > > 
> > > > Those patches add support for composite USB download gadget.
> > > > This gadget (at least for now) is equipped with DFU download
> > > > function.
> > > > 
> > > > A separate DFU back-end and front-end have been added.
> > > > Back-end is placed at ./drivers/dfu directory. The front-end is
> > > > implemented as USB function.
> > > > 
> > > > The back-end is written in a generic manner with storage device
> > > > specific code separated (eMMC).
> > > > 
> > > > DFU specification can be found at:
> > > > http://wiki.openmoko.org/wiki/USB_DFU_-_The_USB_Device_Firmware_Upgrade
> > > > _standard
> > > > 
> > > > Example usage:
> > > > 
> > > > u-boot side: dfu mmc 0
> > > > PC: dfu-util -U IMAGE.bin -a uImage (for upload)
> > > > 
> > > >     dfu-util -D uImage -a uImage (download)
> > > > 
> > > > To list the alt settings:
> > > >         dfu mmc 0 list
> > > > 
> > > > Test HW:
> > > >         Exynos4210 Trats board
> > > > 
> > > > Lukasz Majewski (7):
> > > >   dfu:usb: Support for g_dnl composite download gadget.
> > > >   dfu:usb: DFU USB function (f_dfu) support for g_dnl composite
> > > > gadget dfu: DFU backend implementation
> > > >   dfu: MMC specific routines for DFU operation
> > > >   dfu:cmd: Support for DFU u-boot command
> > > >   arm:trats: Support for USB UDC driver at TRATS board.
> > > >   arm:trats: Enable g_dnl composite USB gadget with embedded DFU
> > > >   
> > > >     function on TRATS
> > > 
> > > Do you have more comments about those patches?
> > 
> > I _think_ he's been busy with exams and preparing for the U-Boot BoF
> > this week.  I'll make sure this gets brought up then however.
> 
> Exams are long past, but there's a lot of other stuff -- the driver
> model, the denx work, the LSM this week -- I wish I could cut myself
> in four or so.

As a side note - I'm looking forward to see your keynote video about
the new driver model :-).

> 
> But weren't there some open questions, especially about the function
> vs. command stuff? The rest were really minor things and I believe
> you closed them with ease. There are just the few big questions, but
> it doesn't seem people are too interested to discuss them.

I'm open for a discussion :-) 

I will post the v3, after the LSM and discussion about the command
vs. function issue.

-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
  2012-07-09 16:36     ` Marek Vasut
@ 2012-07-10  8:45     ` Tom Rini
  2012-07-10 10:38       ` Lukasz Majewski
  2012-07-27 12:36     ` Wolfgang Denk
  2 siblings, 1 reply; 147+ messages in thread
From: Tom Rini @ 2012-07-10  8:45 UTC (permalink / raw)
  To: u-boot

On Wed, Jul 04, 2012 at 05:48:39PM +0200, Lukasz Majewski wrote:
> Support for MMC storage devices to work with DFU framework.
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
[snip]
> +	case RAW_ADDR:
> +		sprintf(cmd_buf, "mmc write 0x%x %x %x", (unsigned int) buf,
> +			dfu->data.mmc.lba_start, dfu->data.mmc.lba_size);
> +		break;
> +	case FAT:
> +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx",
> +			dfu->data.mmc.dev, dfu->data.mmc.part,
> +			(unsigned int) buf, dfu->name, *len);
> +		break;
> +	default:
> +		printf("%s: Wrong layout!\n", __func__);
> +	}
> +
> +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> +	run_command(cmd_buf, 0);

If we try and take the long-view here, that fatwrite/mmc write don't
perform a lot of sanity checking on input isn't good.  Lots of commands
I believe don't, but we can start somewhere.  So, lets do what Marek was
suggesting of making common/cmd_mmc.c and common/cmd_fat.c call a
sub-function that takes compile-time typecheckable inputs, and call that
here.  That opens things up for later making the user commands perform
better checking and so forth.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120710/641ed618/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 0/7] dfu:usb: Composite USB download gadget with DFU function
  2012-07-10  8:27         ` Lukasz Majewski
@ 2012-07-10  9:28           ` Marek Vasut
  0 siblings, 0 replies; 147+ messages in thread
From: Marek Vasut @ 2012-07-10  9:28 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

[...]

> > > > Do you have more comments about those patches?
> > > 
> > > I _think_ he's been busy with exams and preparing for the U-Boot BoF
> > > this week.  I'll make sure this gets brought up then however.
> > 
> > Exams are long past, but there's a lot of other stuff -- the driver
> > model, the denx work, the LSM this week -- I wish I could cut myself
> > in four or so.
> 
> As a side note - I'm looking forward to see your keynote video about
> the new driver model :-).

Oh, just rub it in even more. I'm just starting to get seriously nervous about 
the talk. Just a while ago, it fell on me ;-) I hope you'll like it though.

> > But weren't there some open questions, especially about the function
> > vs. command stuff? The rest were really minor things and I believe
> > you closed them with ease. There are just the few big questions, but
> > it doesn't seem people are too interested to discuss them.
> 
> I'm open for a discussion :-)

I'm glad for that, really.

> I will post the v3, after the LSM and discussion about the command
> vs. function issue.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-10  8:45     ` Tom Rini
@ 2012-07-10 10:38       ` Lukasz Majewski
  2012-07-11 11:54         ` Tom Rini
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-10 10:38 UTC (permalink / raw)
  To: u-boot

Hi Tom,

> On Wed, Jul 04, 2012 at 05:48:39PM +0200, Lukasz Majewski wrote:
> > Support for MMC storage devices to work with DFU framework.
> > 
> > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > Cc: Marek Vasut <marex@denx.de>
> [snip]
> > +	case RAW_ADDR:
> > +		sprintf(cmd_buf, "mmc write 0x%x %x %x", (unsigned
> > int) buf,
> > +			dfu->data.mmc.lba_start,
> > dfu->data.mmc.lba_size);
> > +		break;
> > +	case FAT:
> > +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx",
> > +			dfu->data.mmc.dev, dfu->data.mmc.part,
> > +			(unsigned int) buf, dfu->name, *len);
> > +		break;
> > +	default:
> > +		printf("%s: Wrong layout!\n", __func__);
> > +	}
> > +
> > +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> > +	run_command(cmd_buf, 0);
> 
> If we try and take the long-view here, that fatwrite/mmc write don't
> perform a lot of sanity checking on input isn't good.  Lots of
> commands I believe don't, but we can start somewhere. 
Yes, indeed they don't. But I think, that it is a deeper problem.

When one looks into the cmd_mmc.c, the code is not checking the
correctness of passed data. It performs strncmp, then simple_strtoul
and with this parameter calls mmc->block_dev.block_read(). 

But I'm a bit concern if adding function:

do_mmcops_check(unsigned int lba_start, unsigned int lba_end, ...) to

do_mmcops(argc, argv) {
	int i = simple_strtol(argv[]);
	return do_mmcops_check(i);
}

will help with preventing errors.

As I've written previously, data from prompt is passed in a form of
text, which is converted to the well defined type anyway (with e.g.
simple_strtoul - returns unsigned long, strict_strtoul - returns int,
simple_strtol - returns long, simple_strtoull - returns unsigned long
long). Using those functions correctly would ensure correct types
passed to e.g. mmc->block_dev.block_read().

When one create the do_mmcops_check() function, the compiler would
check if its arguments are correct (i.e. the i in the above example is
int). What is the difference between checking at compile time the
output of simple_strtoul? 

The real problem in my opinion is the lack of checking if arguments
passed as text to the do_mmcops are correct or not. This is not done
for MMC and I doubt, if adding compile time type checking (in a form of
a separate function) would solve/alleviate the problem.



> So, lets do
> what Marek was suggesting of making common/cmd_mmc.c and
> common/cmd_fat.c call a sub-function that takes compile-time
> typecheckable inputs, and call that here.  That opens things up for
> later making the user commands perform better checking and so forth.

I'd like to point to the problem with passing and then parsing
parameters as text. 

User typed parameters aren't checked.

Please correct me if I misunderstood the problem or the proposed
solution.

-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-10 10:38       ` Lukasz Majewski
@ 2012-07-11 11:54         ` Tom Rini
  2012-07-12 12:39           ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Tom Rini @ 2012-07-11 11:54 UTC (permalink / raw)
  To: u-boot

On Tue, Jul 10, 2012 at 12:38:54PM +0200, Lukasz Majewski wrote:
> Hi Tom,
> 
> > On Wed, Jul 04, 2012 at 05:48:39PM +0200, Lukasz Majewski wrote:
> > > Support for MMC storage devices to work with DFU framework.
> > > 
> > > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > Cc: Marek Vasut <marex@denx.de>
> > [snip]
> > > +	case RAW_ADDR:
> > > +		sprintf(cmd_buf, "mmc write 0x%x %x %x", (unsigned
> > > int) buf,
> > > +			dfu->data.mmc.lba_start,
> > > dfu->data.mmc.lba_size);
> > > +		break;
> > > +	case FAT:
> > > +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx",
> > > +			dfu->data.mmc.dev, dfu->data.mmc.part,
> > > +			(unsigned int) buf, dfu->name, *len);
> > > +		break;
> > > +	default:
> > > +		printf("%s: Wrong layout!\n", __func__);
> > > +	}
> > > +
> > > +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> > > +	run_command(cmd_buf, 0);
> > 
> > If we try and take the long-view here, that fatwrite/mmc write don't
> > perform a lot of sanity checking on input isn't good.  Lots of
> > commands I believe don't, but we can start somewhere. 
> Yes, indeed they don't. But I think, that it is a deeper problem.
> 
> When one looks into the cmd_mmc.c, the code is not checking the
> correctness of passed data. It performs strncmp, then simple_strtoul
> and with this parameter calls mmc->block_dev.block_read(). 
> 
> But I'm a bit concern if adding function:
> 
> do_mmcops_check(unsigned int lba_start, unsigned int lba_end, ...) to
> 
> do_mmcops(argc, argv) {
> 	int i = simple_strtol(argv[]);
> 	return do_mmcops_check(i);
> }

Well, what I was suggesting would be:

do_mmcops_real(uint lba_start, ...) { .. most of do_mmcops today .. }
do_mmcops_from_cmd(argc, argv) {
 ... convert user input today, maybe try and sanity check input tomorrow
 ..
}

And then dfu calls do_mmcops_real(lba_start, ...).  A further clean-up
would be to make the interface the command uses to perform checking of
the arguments passed.  Does this make sense?

-- 
Tom

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-11 11:54         ` Tom Rini
@ 2012-07-12 12:39           ` Lukasz Majewski
  2012-07-12 12:46             ` Tom Rini
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-12 12:39 UTC (permalink / raw)
  To: u-boot

On Wed, 11 Jul 2012 04:54:31 -0700
Tom Rini <trini@ti.com> wrote:

> On Tue, Jul 10, 2012 at 12:38:54PM +0200, Lukasz Majewski wrote:
> > Hi Tom,
> > 
> > > On Wed, Jul 04, 2012 at 05:48:39PM +0200, Lukasz Majewski wrote:
> > > > Support for MMC storage devices to work with DFU framework.
> > > > 
> > > > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > > > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > > Cc: Marek Vasut <marex@denx.de>
> > > [snip]
> > > > +	case RAW_ADDR:
> > > > +		sprintf(cmd_buf, "mmc write 0x%x %x %x",
> > > > (unsigned int) buf,
> > > > +			dfu->data.mmc.lba_start,
> > > > dfu->data.mmc.lba_size);
> > > > +		break;
> > > > +	case FAT:
> > > > +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s
> > > > %lx",
> > > > +			dfu->data.mmc.dev, dfu->data.mmc.part,
> > > > +			(unsigned int) buf, dfu->name, *len);
> > > > +		break;
> > > > +	default:
> > > > +		printf("%s: Wrong layout!\n", __func__);
> > > > +	}
> > > > +
> > > > +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> > > > +	run_command(cmd_buf, 0);
> > > 
> > > If we try and take the long-view here, that fatwrite/mmc write
> > > don't perform a lot of sanity checking on input isn't good.  Lots
> > > of commands I believe don't, but we can start somewhere. 
> > Yes, indeed they don't. But I think, that it is a deeper problem.
> > 
> > When one looks into the cmd_mmc.c, the code is not checking the
> > correctness of passed data. It performs strncmp, then simple_strtoul
> > and with this parameter calls mmc->block_dev.block_read(). 
> > 
> > But I'm a bit concern if adding function:
> > 
> > do_mmcops_check(unsigned int lba_start, unsigned int lba_end, ...)
> > to
> > 
> > do_mmcops(argc, argv) {
> > 	int i = simple_strtol(argv[]);
> > 	return do_mmcops_check(i);
> > }
> 
> Well, what I was suggesting would be:
> 
> do_mmcops_real(uint lba_start, ...) { .. most of do_mmcops today .. }
> do_mmcops_from_cmd(argc, argv) {
>  ... convert user input today, maybe try and sanity check input
> tomorrow ..
> }
> 
> And then dfu calls do_mmcops_real(lba_start, ...).  A further clean-up
> would be to make the interface the command uses to perform checking of
> the arguments passed.  Does this make sense?
> 

Generally it is in my opinion a good way to go.

However, why we aren't first writing sanity checks for passed arguments?

We are adding one more level of abstraction, but don't think of the main
problem (checking values of passed arguments)?

Anyway we shall wait for Marek's opinion.

-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-12 12:39           ` Lukasz Majewski
@ 2012-07-12 12:46             ` Tom Rini
  2012-07-13 10:29               ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Tom Rini @ 2012-07-12 12:46 UTC (permalink / raw)
  To: u-boot

On Thu, Jul 12, 2012 at 02:39:27PM +0200, Lukasz Majewski wrote:
> On Wed, 11 Jul 2012 04:54:31 -0700
> Tom Rini <trini@ti.com> wrote:
> 
> > On Tue, Jul 10, 2012 at 12:38:54PM +0200, Lukasz Majewski wrote:
> > > Hi Tom,
> > > 
> > > > On Wed, Jul 04, 2012 at 05:48:39PM +0200, Lukasz Majewski wrote:
> > > > > Support for MMC storage devices to work with DFU framework.
> > > > > 
> > > > > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > > > > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > > > Cc: Marek Vasut <marex@denx.de>
> > > > [snip]
> > > > > +	case RAW_ADDR:
> > > > > +		sprintf(cmd_buf, "mmc write 0x%x %x %x",
> > > > > (unsigned int) buf,
> > > > > +			dfu->data.mmc.lba_start,
> > > > > dfu->data.mmc.lba_size);
> > > > > +		break;
> > > > > +	case FAT:
> > > > > +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s
> > > > > %lx",
> > > > > +			dfu->data.mmc.dev, dfu->data.mmc.part,
> > > > > +			(unsigned int) buf, dfu->name, *len);
> > > > > +		break;
> > > > > +	default:
> > > > > +		printf("%s: Wrong layout!\n", __func__);
> > > > > +	}
> > > > > +
> > > > > +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> > > > > +	run_command(cmd_buf, 0);
> > > > 
> > > > If we try and take the long-view here, that fatwrite/mmc write
> > > > don't perform a lot of sanity checking on input isn't good.  Lots
> > > > of commands I believe don't, but we can start somewhere. 
> > > Yes, indeed they don't. But I think, that it is a deeper problem.
> > > 
> > > When one looks into the cmd_mmc.c, the code is not checking the
> > > correctness of passed data. It performs strncmp, then simple_strtoul
> > > and with this parameter calls mmc->block_dev.block_read(). 
> > > 
> > > But I'm a bit concern if adding function:
> > > 
> > > do_mmcops_check(unsigned int lba_start, unsigned int lba_end, ...)
> > > to
> > > 
> > > do_mmcops(argc, argv) {
> > > 	int i = simple_strtol(argv[]);
> > > 	return do_mmcops_check(i);
> > > }
> > 
> > Well, what I was suggesting would be:
> > 
> > do_mmcops_real(uint lba_start, ...) { .. most of do_mmcops today .. }
> > do_mmcops_from_cmd(argc, argv) {
> >  ... convert user input today, maybe try and sanity check input
> > tomorrow ..
> > }
> > 
> > And then dfu calls do_mmcops_real(lba_start, ...).  A further clean-up
> > would be to make the interface the command uses to perform checking of
> > the arguments passed.  Does this make sense?
> > 
> 
> Generally it is in my opinion a good way to go.
> 
> However, why we aren't first writing sanity checks for passed arguments?

Simply because I didn't want to ask you to do a lot more unrelated work
:)  If you want to split and check the mmc (and fatwrite) argueuments
and then make the DFU series depend on that, by all means please do so!

> We are adding one more level of abstraction, but don't think of the main
> problem (checking values of passed arguments)?
> 
> Anyway we shall wait for Marek's opinion.

Yes, a good idea as well.

-- 
Tom

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-12 12:46             ` Tom Rini
@ 2012-07-13 10:29               ` Marek Vasut
  2012-07-13 21:27                 ` Andy Fleming
  0 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-13 10:29 UTC (permalink / raw)
  To: u-boot

Dear Tom Rini,

> On Thu, Jul 12, 2012 at 02:39:27PM +0200, Lukasz Majewski wrote:
> > On Wed, 11 Jul 2012 04:54:31 -0700
> > 
> > Tom Rini <trini@ti.com> wrote:
> > > On Tue, Jul 10, 2012 at 12:38:54PM +0200, Lukasz Majewski wrote:
> > > > Hi Tom,
> > > > 
> > > > > On Wed, Jul 04, 2012 at 05:48:39PM +0200, Lukasz Majewski wrote:
> > > > > > Support for MMC storage devices to work with DFU framework.
> > > > > > 
> > > > > > Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> > > > > > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > > > > > Cc: Marek Vasut <marex@denx.de>
> > > > > 
> > > > > [snip]
> > > > > 
> > > > > > +	case RAW_ADDR:
> > > > > > +		sprintf(cmd_buf, "mmc write 0x%x %x %x",
> > > > > > (unsigned int) buf,
> > > > > > +			dfu->data.mmc.lba_start,
> > > > > > dfu->data.mmc.lba_size);
> > > > > > +		break;
> > > > > > +	case FAT:
> > > > > > +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s
> > > > > > %lx",
> > > > > > +			dfu->data.mmc.dev, dfu->data.mmc.part,
> > > > > > +			(unsigned int) buf, dfu->name, *len);
> > > > > > +		break;
> > > > > > +	default:
> > > > > > +		printf("%s: Wrong layout!\n", __func__);
> > > > > > +	}
> > > > > > +
> > > > > > +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> > > > > > +	run_command(cmd_buf, 0);
> > > > > 
> > > > > If we try and take the long-view here, that fatwrite/mmc write
> > > > > don't perform a lot of sanity checking on input isn't good.  Lots
> > > > > of commands I believe don't, but we can start somewhere.
> > > > 
> > > > Yes, indeed they don't. But I think, that it is a deeper problem.
> > > > 
> > > > When one looks into the cmd_mmc.c, the code is not checking the
> > > > correctness of passed data. It performs strncmp, then simple_strtoul
> > > > and with this parameter calls mmc->block_dev.block_read().
> > > > 
> > > > But I'm a bit concern if adding function:
> > > > 
> > > > do_mmcops_check(unsigned int lba_start, unsigned int lba_end, ...)
> > > > to
> > > > 
> > > > do_mmcops(argc, argv) {
> > > > 
> > > > 	int i = simple_strtol(argv[]);
> > > > 	return do_mmcops_check(i);
> > > > 
> > > > }
> > > 
> > > Well, what I was suggesting would be:
> > > 
> > > do_mmcops_real(uint lba_start, ...) { .. most of do_mmcops today .. }
> > > do_mmcops_from_cmd(argc, argv) {
> > > 
> > >  ... convert user input today, maybe try and sanity check input
> > > 
> > > tomorrow ..
> > > }
> > > 
> > > And then dfu calls do_mmcops_real(lba_start, ...).  A further clean-up
> > > would be to make the interface the command uses to perform checking of
> > > the arguments passed.  Does this make sense?
> > 
> > Generally it is in my opinion a good way to go.
> > 
> > However, why we aren't first writing sanity checks for passed arguments?
> 
> Simply because I didn't want to ask you to do a lot more unrelated work
> 
> :)  If you want to split and check the mmc (and fatwrite) argueuments
> 
> and then make the DFU series depend on that, by all means please do so!

Would be cool indeed.

> > We are adding one more level of abstraction, but don't think of the main
> > problem (checking values of passed arguments)?
> > 
> > Anyway we shall wait for Marek's opinion.
> 
> Yes, a good idea as well.

My opinion is that if you'll do the sanity checks, that'd be good. We're right 
before .07 release anyway, so the patches will hit the next merge window. Are 
you up for doing a lot of unrelated work to make this proper?

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-13 10:29               ` Marek Vasut
@ 2012-07-13 21:27                 ` Andy Fleming
  0 siblings, 0 replies; 147+ messages in thread
From: Andy Fleming @ 2012-07-13 21:27 UTC (permalink / raw)
  To: u-boot

>> > Generally it is in my opinion a good way to go.
>> >
>> > However, why we aren't first writing sanity checks for passed arguments?
>>
>> Simply because I didn't want to ask you to do a lot more unrelated work
>>
>> :)  If you want to split and check the mmc (and fatwrite) argueuments
>>
>> and then make the DFU series depend on that, by all means please do so!
>
> Would be cool indeed.
>
>> > We are adding one more level of abstraction, but don't think of the main
>> > problem (checking values of passed arguments)?
>> >
>> > Anyway we shall wait for Marek's opinion.
>>
>> Yes, a good idea as well.
>
> My opinion is that if you'll do the sanity checks, that'd be good. We're right
> before .07 release anyway, so the patches will hit the next merge window. Are
> you up for doing a lot of unrelated work to make this proper?


I agree with the general sense that adding sanity checking would be
good. Just because I was too lazy to add them, doesn't mean I was
right. ;)

Andy

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function
  2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
                   ` (8 preceding siblings ...)
  2012-07-04 15:48 ` [U-Boot] [PATCH v2 " Lukasz Majewski
@ 2012-07-18 12:51 ` Marek Vasut
  2012-07-23  7:57   ` Lukasz Majewski
  2012-07-31  6:36 ` [U-Boot] [PATCH v3 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-18 12:51 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> Those patches add support for composite USB download gadget.
> This gadget (at least for now) is equipped with DFU download function.
> 
> A separate DFU back-end and front-end have been added.
> Back-end is placed at ./drivers/dfu directory. The front-end is implemented
> as USB function.
> 
> The back-end is written in a generic manner with storage device specific
> code separated (eMMC).
> 
> DFU specification can be found at:
> http://wiki.openmoko.org/wiki/USB_DFU_-_The_USB_Device_Firmware_Upgrade_sta
> ndard

[...]

will we see a next version of this series please? Or where did the discussion 
get?

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 1/7] dfu:usb: Support for g_dnl composite download gadget.
  2012-07-03  9:38 ` [U-Boot] [PATCH 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
  2012-07-03 18:41   ` Marek Vasut
@ 2012-07-20  4:14   ` Mike Frysinger
  2012-07-23 15:25     ` Lukasz Majewski
  1 sibling, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-07-20  4:14 UTC (permalink / raw)
  To: u-boot

On Tuesday 03 July 2012 05:38:05 Lukasz Majewski wrote:
> --- /dev/null
> +++ b/drivers/usb/gadget/g_dnl.c
>
> +static const char shortname[] = "usb_dnl_";

shortname -> gadget_name_prefix

> +static void g_dnl_suspend(struct usb_composite_dev *cdev)
> +{
> +	if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
> +		return;
> +
> +	debug("suspend\n");
> +}
> +
> +static void g_dnl_resume(struct usb_composite_dev *cdev)
> +{
> +	debug("resume\n");
> +}

do suspend/resume funcs make any sense in u-boot ?

> +int g_dnl_init(char *s)

const char

> +{
> +	int ret;
> +	static char str[16];
> +
> +	memset(str, '\0', sizeof(str));
> +
> +	strncpy(str, shortname, sizeof(shortname));

no need for the memset.  this strncpy looks broken -- the 3rd arg is for how 
many bytes are available in the *dest* buffer, not how long the source is.

> +	if (!strncmp(s, "dfu", sizeof(s))) {

sizeof() here is wrong -- that gives you back 4 (the size of a pointer) on 
32bit systems

> +		strncat(str, s, sizeof(str));

this is also incorrect.  the length given to strncat is how many bytes are 
left, not the total length.

since this string parsing logic is all just completely broken, i'd suggest 
replacing it all with:

{
	int ret;
	/* We only allow "dfu" atm, so 3 should be enough */
	static char name[sizeof(shortname) + 3];

	if (strcmp(s, "dfu")) {
		printf("%s: unknown command: %s\n", __func__, s);
		return -EINVAL;
	}

	strcpy(name, shortname);
	strcat(name, s);

> +	if (ret) {
> +		printf("%s: failed!, error:%d ", __func__, ret);

needs a space between "error:" and "%d"

> --- /dev/null
> +++ b/include/g_dnl.h
>
> +#include <linux/usb/ch9.h>
> +#include <usbdescriptors.h>
> +#include <linux/usb/gadget.h>

unused -> delete

> +int g_dnl_init(char *s);

int g_dnl_register(const char *type);

this also needs documentation in the header explaining how to use this func

> +void g_dnl_cleanup(void);

void g_dnl_unregister(void);

> +/* USB initialization declaration - board specific*/
> +void board_usb_init(void);

not used in these files -> delete
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120720/587193d8/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-03  9:38 ` [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
  2012-07-03 21:32   ` Marek Vasut
@ 2012-07-20  4:20   ` Mike Frysinger
  2012-07-23 16:01     ` Lukasz Majewski
  1 sibling, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-07-20  4:20 UTC (permalink / raw)
  To: u-boot

On Tuesday 03 July 2012 05:38:09 Lukasz Majewski wrote:
> --- /dev/null
> +++ b/common/cmd_dfu.c
>
> +int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

static

> +{
> +	char *str_env = NULL, *env_bkp = NULL;

no need to assign NULL here.  str_env should be const.

> +	static char *s = "dfu";

no need to declare this static

> +	int ret = 0;

no need to init to 0

> +	env_bkp = strdup(str_env);
> +	ret = dfu_config_entities(env_bkp, argv[1],
> +			    (int)simple_strtoul(argv[2], NULL, 10));
> +	if (ret)
> +		return CMD_RET_FAILURE;
> +
> +	if (strcmp(argv[3], "list") == 0) {
> +		dfu_show_entities();
> +		dfu_free_entities();
> +		free(env_bkp);
> +		return CMD_RET_SUCCESS;

for these last three statements, you could just do "goto done" and put a done 
label below ...

> +exit:
> +	g_dnl_cleanup();

done:

> +	dfu_free_entities();
> +	free(env_bkp);
> +
> +	return CMD_RET_SUCCESS;

-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120720/7b1add72/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-03 21:32   ` Marek Vasut
  2012-07-04  9:28     ` Lukasz Majewski
@ 2012-07-20  4:22     ` Mike Frysinger
  2012-07-20 11:35       ` Marek Vasut
  1 sibling, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-07-20  4:22 UTC (permalink / raw)
  To: u-boot

On Tuesday 03 July 2012 17:32:54 Marek Vasut wrote:
> > +int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> > +{
> > +	char *str_env = NULL, *env_bkp = NULL;
> > +	static char *s = "dfu";
> > +	int ret = 0;
> > +
> > +	if (argc < 3)
> > +		return CMD_RET_USAGE;
> > +
> > +	str_env = getenv("dfu_alt_info");
> > +	if (str_env == NULL) {
> > +		printf("%s: \"dfu_alt_info\" env variable not defined!\n",
> > +		       __func__);
> 
> I was always curious if it's not possible to do something like
> 
> puts(__func__ "rest of string");
> 
> Maybe it'd help the overhead a bit? Certainly, it's beyond the scope of
> this patchset, I'm just curious :)

not anymore -- gcc disabled support for that sometime ago.  and it's good they 
did as it causes more bloat than good.  as soon as you do more than one 
statement, you get duplication.  the string table will have:
	"some_func: rest of string"
	"some_func: boo"
	"some_func: another message"
which takes up more space than:
	"some_func"
	"%s: rest of string"
	"%s: boo"
	"%s: another message"
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120720/19f853eb/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-04 14:39       ` Marek Vasut
@ 2012-07-20  4:23         ` Mike Frysinger
  2012-07-20 11:33           ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-07-20  4:23 UTC (permalink / raw)
  To: u-boot

On Wednesday 04 July 2012 10:39:20 Marek Vasut wrote:
> > Putting there the __func__ name would improve structure and speed up
> > finding right place.
> 
> And if you want to use even __LINE__, look up __stringify patch in the ML
> archives ;-)

ugh, no, let's not use __LINE__ anywhere other than debug().  it has no 
business in code we ship as it is pointless bloated noise.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120720/4cdf7149/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation
  2012-07-04  0:13               ` Marek Vasut
@ 2012-07-20  4:25                 ` Mike Frysinger
  0 siblings, 0 replies; 147+ messages in thread
From: Mike Frysinger @ 2012-07-20  4:25 UTC (permalink / raw)
  To: u-boot

On Tuesday 03 July 2012 20:13:37 Marek Vasut wrote:
> Dear Tom Rini,
> > On Wed, Jul 04, 2012 at 12:31:14AM +0200, Marek Vasut wrote:
> > > Dear Tom Rini,
> > > > > > > > +	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
> > > > > > > > +	run_command(cmd_buf, 0);
> > > > > > > 
> > > > > > > Holy Moly ... can we not make this into simple calls to those
> > > > > > > subsystems ? Instead invoking command is crazy ;-)
> > > > > > 
> > > > > > Are they really simple?  There's a few other places we do this,
> > > > > > and so long as it's documented that DFU depends on
> > > > > > CONFIG_FAT_WRITE for writing to fat and so forth.
> > > > > 
> > > > > Well ain't it easier to call fat_write() or similar?
> > > > 
> > > > Assuming that most of the logic in do_fat_fswrite is needed, no.  And
> > > > I think a good portion of it is, at first glance at least.
> > > 
> > > Abstracting it out into a function won't cut it?
> > 
> > My inclination would be to say that seems a bit sillier than just using
> > run_command(...) to call the existing command.
> 
> Whose's syntax will likely soon change, breaking all this :-(

and would be pretty much impossible to detect at compile time.  extending the 
API for code to call is the right answer ... abusing the shell at runtime from 
other code should be an absolute last resort.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120720/d37ea667/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 3/7] dfu: DFU backend implementation
  2012-07-03  9:38 ` [U-Boot] [PATCH 3/7] dfu: DFU backend implementation Lukasz Majewski
  2012-07-03 21:28   ` Marek Vasut
@ 2012-07-20  4:32   ` Mike Frysinger
  2012-07-23 16:11     ` Lukasz Majewski
  1 sibling, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-07-20  4:32 UTC (permalink / raw)
  To: u-boot

On Tuesday 03 July 2012 05:38:07 Lukasz Majewski wrote:
> +		puts("UPLOAD ... done\n");
> +		puts("Ctrl+C to exit ...\n");

combine into a single puts() ?

> +static int dfu_fill_entity(struct dfu_entity *dfu, char* s, int alt,
> +			    char *interface, int num)
> +{
> +	char *st = NULL;
> +	int n = 0;
> +
> +	debug("%s: %s interface: %s num: %d\n", __func__, s, interface, num);
> +
> +	st = dfu_extract_token(&s, &n);
> +	strncpy((char *) &dfu->name, st, n);

what's with the pointless cast ?  just do:
	strncpy(dfu->name, st, n);

also, "n" here is wrong.  it should be sizeof(dfu->name), not (presumably) the 
length of st.  considering this is the 2nd time i noticed this bug in the dfu 
patchset, you might want to do a grep on your patches to see if your other 
string related usage is wrong.

> +void dfu_free_entities(void)
> +{
> +	struct dfu_entity *dfu = NULL, *p = NULL;

no point in assigning to NULL here

> +static char *dfu_get_dev_type(enum dfu_device_type t)

static const char *...

> +{
> +	static char *dev_t[] = {NULL, "MMC", "ONENAND", "NAND" };

static const char * const dev_t[] = {...}

> +static char *dfu_get_layout(enum dfu_device_type l)

static const char *...

> +{
> +	static char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT" };

static const char * const dfu_layout[] = {...}

> +void dfu_show_entities(void)
> +{
> +	struct dfu_entity *dfu = NULL;

no point in assigning to NULL

> +struct dfu_entity *dfu_get_entity(int alt)
> +{
> +	struct dfu_entity *dfu = NULL;

no point in assigning to NULL
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120720/97ce9d54/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-20  4:23         ` Mike Frysinger
@ 2012-07-20 11:33           ` Marek Vasut
  2012-07-20 14:43             ` Mike Frysinger
  0 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-20 11:33 UTC (permalink / raw)
  To: u-boot

Dear Mike Frysinger,

> On Wednesday 04 July 2012 10:39:20 Marek Vasut wrote:
> > > Putting there the __func__ name would improve structure and speed up
> > > finding right place.
> > 
> > And if you want to use even __LINE__, look up __stringify patch in the ML
> > archives ;-)
> 
> ugh, no, let's not use __LINE__ anywhere other than debug().  it has no
> business in code we ship as it is pointless bloated noise.

Helps find out the problematic place in code ... 

> -mike

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-20  4:22     ` Mike Frysinger
@ 2012-07-20 11:35       ` Marek Vasut
  0 siblings, 0 replies; 147+ messages in thread
From: Marek Vasut @ 2012-07-20 11:35 UTC (permalink / raw)
  To: u-boot

Dear Mike Frysinger,

> On Tuesday 03 July 2012 17:32:54 Marek Vasut wrote:
> > > +int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> > > +{
> > > +	char *str_env = NULL, *env_bkp = NULL;
> > > +	static char *s = "dfu";
> > > +	int ret = 0;
> > > +
> > > +	if (argc < 3)
> > > +		return CMD_RET_USAGE;
> > > +
> > > +	str_env = getenv("dfu_alt_info");
> > > +	if (str_env == NULL) {
> > > +		printf("%s: \"dfu_alt_info\" env variable not defined!\n",
> > > +		       __func__);
> > 
> > I was always curious if it's not possible to do something like
> > 
> > puts(__func__ "rest of string");
> > 
> > Maybe it'd help the overhead a bit? Certainly, it's beyond the scope of
> > this patchset, I'm just curious :)
> 
> not anymore -- gcc disabled support for that sometime ago.  and it's good
> they did as it causes more bloat than good.  as soon as you do more than
> one statement, you get duplication.  the string table will have:
> 	"some_func: rest of string"
> 	"some_func: boo"
> 	"some_func: another message"
> which takes up more space than:
> 	"some_func"
> 	"%s: rest of string"
> 	"%s: boo"
> 	"%s: another message"

Good knowing this. I'd expect gcc would build some trie in there to optimize the 
size.

> -mike

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-20 11:33           ` Marek Vasut
@ 2012-07-20 14:43             ` Mike Frysinger
  2012-07-20 21:11               ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-07-20 14:43 UTC (permalink / raw)
  To: u-boot

On Friday 20 July 2012 07:33:49 Marek Vasut wrote:
> Dear Mike Frysinger,
> > On Wednesday 04 July 2012 10:39:20 Marek Vasut wrote:
> > > > Putting there the __func__ name would improve structure and speed up
> > > > finding right place.
> > > 
> > > And if you want to use even __LINE__, look up __stringify patch in the
> > > ML archives ;-)
> > 
> > ugh, no, let's not use __LINE__ anywhere other than debug().  it has no
> > business in code we ship as it is pointless bloated noise.
> 
> Helps find out the problematic place in code ...

except the code changes thus invalidating the line numbers, and how often are 
you putting the same string in multiple places that you can't easily 
coordinate where it came from ?  if people are using the same exact string in 
multiple places, that sounds like a different problem.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120720/e9bf6f8a/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-20 14:43             ` Mike Frysinger
@ 2012-07-20 21:11               ` Marek Vasut
  2012-07-21 17:20                 ` Mike Frysinger
  0 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-20 21:11 UTC (permalink / raw)
  To: u-boot

Dear Mike Frysinger,

> On Friday 20 July 2012 07:33:49 Marek Vasut wrote:
> > Dear Mike Frysinger,
> > 
> > > On Wednesday 04 July 2012 10:39:20 Marek Vasut wrote:
> > > > > Putting there the __func__ name would improve structure and speed
> > > > > up finding right place.
> > > > 
> > > > And if you want to use even __LINE__, look up __stringify patch in
> > > > the ML archives ;-)
> > > 
> > > ugh, no, let's not use __LINE__ anywhere other than debug().  it has no
> > > business in code we ship as it is pointless bloated noise.
> > 
> > Helps find out the problematic place in code ...
> 
> except the code changes thus invalidating the line numbers, and how often
> are you putting the same string in multiple places that you can't easily
> coordinate where it came from ?  if people are using the same exact string
> in multiple places, that sounds like a different problem.

You can always replace the function names with macros, which expand in place. 
And then simply add __func__ __LINE__ __FILE__ etc.

> -mike

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-20 21:11               ` Marek Vasut
@ 2012-07-21 17:20                 ` Mike Frysinger
  2012-07-21 17:21                   ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-07-21 17:20 UTC (permalink / raw)
  To: u-boot

On Friday 20 July 2012 17:11:33 Marek Vasut wrote:
> Dear Mike Frysinger,
> > On Friday 20 July 2012 07:33:49 Marek Vasut wrote:
> > > Dear Mike Frysinger,
> > > > On Wednesday 04 July 2012 10:39:20 Marek Vasut wrote:
> > > > > > Putting there the __func__ name would improve structure and speed
> > > > > > up finding right place.
> > > > > 
> > > > > And if you want to use even __LINE__, look up __stringify patch in
> > > > > the ML archives ;-)
> > > > 
> > > > ugh, no, let's not use __LINE__ anywhere other than debug().  it has
> > > > no business in code we ship as it is pointless bloated noise.
> > > 
> > > Helps find out the problematic place in code ...
> > 
> > except the code changes thus invalidating the line numbers, and how often
> > are you putting the same string in multiple places that you can't easily
> > coordinate where it came from ?  if people are using the same exact
> > string in multiple places, that sounds like a different problem.
> 
> You can always replace the function names with macros, which expand in
> place. And then simply add __func__ __LINE__ __FILE__ etc.

if you wanted to add it while debugging, that's fine, but the point is that 
this doesn't belong in normal runtime images.  it's even trivial to define such 
a macro:
#ifdef DEBUG
# define printf(fmt, args...) printf("%s:%s:%i: " fmt, __FILE__, __LINE__, 
__func__, ## args)
#endif
(will obviously need a little more work to handle non-const fmt strings, but 
you get the idea).
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120721/832382c4/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-21 17:20                 ` Mike Frysinger
@ 2012-07-21 17:21                   ` Marek Vasut
  0 siblings, 0 replies; 147+ messages in thread
From: Marek Vasut @ 2012-07-21 17:21 UTC (permalink / raw)
  To: u-boot

Dear Mike Frysinger,

> On Friday 20 July 2012 17:11:33 Marek Vasut wrote:
> > Dear Mike Frysinger,
> > 
> > > On Friday 20 July 2012 07:33:49 Marek Vasut wrote:
> > > > Dear Mike Frysinger,
> > > > 
> > > > > On Wednesday 04 July 2012 10:39:20 Marek Vasut wrote:
> > > > > > > Putting there the __func__ name would improve structure and
> > > > > > > speed up finding right place.
> > > > > > 
> > > > > > And if you want to use even __LINE__, look up __stringify patch
> > > > > > in the ML archives ;-)
> > > > > 
> > > > > ugh, no, let's not use __LINE__ anywhere other than debug().  it
> > > > > has no business in code we ship as it is pointless bloated noise.
> > > > 
> > > > Helps find out the problematic place in code ...
> > > 
> > > except the code changes thus invalidating the line numbers, and how
> > > often are you putting the same string in multiple places that you
> > > can't easily coordinate where it came from ?  if people are using the
> > > same exact string in multiple places, that sounds like a different
> > > problem.
> > 
> > You can always replace the function names with macros, which expand in
> > place. And then simply add __func__ __LINE__ __FILE__ etc.
> 
> if you wanted to add it while debugging, that's fine, but the point is that
> this doesn't belong in normal runtime images.

Well doh ...

> it's even trivial to define
> such a macro:
> #ifdef DEBUG
> # define printf(fmt, args...) printf("%s:%s:%i: " fmt, __FILE__, __LINE__,
> __func__, ## args)
> #endif

Uh, now I'm not sure what you mean by this stuff above.

> (will obviously need a little more work to handle non-const fmt strings,
> but you get the idea).
> -mike

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function
  2012-07-18 12:51 ` [U-Boot] [PATCH " Marek Vasut
@ 2012-07-23  7:57   ` Lukasz Majewski
  2012-07-23 10:57     ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-23  7:57 UTC (permalink / raw)
  To: u-boot

Hi Marek,

> Dear Lukasz Majewski,
> 
> > Those patches add support for composite USB download gadget.
> > This gadget (at least for now) is equipped with DFU download
> > function.
> > 
> > A separate DFU back-end and front-end have been added.
> > Back-end is placed at ./drivers/dfu directory. The front-end is
> > implemented as USB function.
> > 
> > The back-end is written in a generic manner with storage device
> > specific code separated (eMMC).
> > 
> > DFU specification can be found at:
> > http://wiki.openmoko.org/wiki/USB_DFU_-_The_USB_Device_Firmware_Upgrade_sta
> > ndard
> 
> [...]
> 
> will we see a next version of this series please? 

I've just come back from my holiday. I will continue work on this.

> Or where did the
> discussion get?

As fair as I remember, the discussion ended up with a conclusion, that
new layer of abstraction (in a form of function call) is needed.

I will rehack the cmd_mmc.c to include new functions in it. It will be
a prepatch for the DFU.


-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function
  2012-07-23  7:57   ` Lukasz Majewski
@ 2012-07-23 10:57     ` Marek Vasut
  0 siblings, 0 replies; 147+ messages in thread
From: Marek Vasut @ 2012-07-23 10:57 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> Hi Marek,
> 
> > Dear Lukasz Majewski,
> > 
> > > Those patches add support for composite USB download gadget.
> > > This gadget (at least for now) is equipped with DFU download
> > > function.
> > > 
> > > A separate DFU back-end and front-end have been added.
> > > Back-end is placed at ./drivers/dfu directory. The front-end is
> > > implemented as USB function.
> > > 
> > > The back-end is written in a generic manner with storage device
> > > specific code separated (eMMC).
> > > 
> > > DFU specification can be found at:
> > > http://wiki.openmoko.org/wiki/USB_DFU_-_The_USB_Device_Firmware_Upgrade
> > > _sta ndard
> > 
> > [...]
> > 
> > will we see a next version of this series please?
> 
> I've just come back from my holiday. I will continue work on this.
> 
> > Or where did the
> > discussion get?
> 
> As fair as I remember, the discussion ended up with a conclusion, that
> new layer of abstraction (in a form of function call) is needed.
> 
> I will rehack the cmd_mmc.c to include new functions in it. It will be
> a prepatch for the DFU.

Thanks a lot! I didn't intend to torture you, really ... I just wanted this to 
be done properly.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 1/7] dfu:usb: Support for g_dnl composite download gadget.
  2012-07-20  4:14   ` Mike Frysinger
@ 2012-07-23 15:25     ` Lukasz Majewski
  2012-07-24 17:50       ` Mike Frysinger
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-23 15:25 UTC (permalink / raw)
  To: u-boot

Dear Mike Frysinger,

Thank you for thorough review.

> On Tuesday 03 July 2012 05:38:05 Lukasz Majewski wrote:
> > --- /dev/null
> > +++ b/drivers/usb/gadget/g_dnl.c
> >
> > +static const char shortname[] = "usb_dnl_";
> 
> shortname -> gadget_name_prefix

This might be only matter of taste, but in my opinion this name is more
readable.

> 
> > +static void g_dnl_suspend(struct usb_composite_dev *cdev)
> > +{
> > +	if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
> > +		return;
> > +
> > +	debug("suspend\n");
> > +}
> > +
> > +static void g_dnl_resume(struct usb_composite_dev *cdev)
> > +{
> > +	debug("resume\n");
> > +}
> 
> do suspend/resume funcs make any sense in u-boot ?

You have reviewed the v1 of this patch series. Marek Vasut has already
pointed out this problem and it has been resoled with v2.

> 
> > +int g_dnl_init(char *s)
> 
> const char

Ok.
> 
> > +{
> > +	int ret;
> > +	static char str[16];
> > +
> > +	memset(str, '\0', sizeof(str));
> > +
> > +	strncpy(str, shortname, sizeof(shortname));
> 
> no need for the memset. 
The gadget can be called from many separate commands (e.g. command
"dfu" and command "ums") and those commands can be executed without
power cycle. Thereof I need to be sure, that str is not polluted by
previous name. 

> this strncpy looks broken -- the 3rd arg is
> for how many bytes are available in the *dest* buffer, not how long
> the source is.
After looking deeply into the source I admit that providing the
upper bound on the dest is more safe. 

> 
> > +	if (!strncmp(s, "dfu", sizeof(s))) {
> 
> sizeof() here is wrong -- that gives you back 4 (the size of a
> pointer) on 32bit systems

... and it works only because the "dfu\0" and "ums\0" is 4 lenght. :/

> 
> > +		strncat(str, s, sizeof(str));
> 
> this is also incorrect.  the length given to strncat is how many
> bytes are left, not the total length.
I cannot agree. sizeof(str) return 16, which is the destination buffer
size.
> 
> since this string parsing logic is all just completely broken, i'd
> suggest replacing it all with:
> 
> {
> 	int ret;
> 	/* We only allow "dfu" atm, so 3 should be enough */
> 	static char name[sizeof(shortname) + 3];
> 
> 	if (strcmp(s, "dfu")) {
> 		printf("%s: unknown command: %s\n", __func__, s);
> 		return -EINVAL;
> 	}
> 
> 	strcpy(name, shortname);
> 	strcat(name, s);
> 

This is a very neat design, but it assumes that there will be only one
function ("dfu" in this case). For this particular function +3
applies, but what if another function (like "usb_storage") will be
defined? 
I'm now working on another function - the USB Mass Storage (named
"ums" ;-) ).

Another issue is omitting the strncmp/strncpy functions and depending on
the: static char name[sizeof(shortname) + 3]; definition to prevent
buffer overflow.

The +3 magic number worries me a bit...

> > +	if (ret) {
> > +		printf("%s: failed!, error:%d ", __func__, ret);
> 
> needs a space between "error:" and "%d"
Will be fixed
> 
> > --- /dev/null
> > +++ b/include/g_dnl.h
> >
> > +#include <linux/usb/ch9.h>
> > +#include <usbdescriptors.h>
> > +#include <linux/usb/gadget.h>
> 
> unused -> delete
I will remove those includes from g_dnl.c file
> 
> > +int g_dnl_init(char *s);
> 
> int g_dnl_register(const char *type);
> 
> this also needs documentation in the header explaining how to use
> this func

I will provide the working example of this gadget. I will not insist on
the function name. It can be g_dnl_register().

> 
> > +void g_dnl_cleanup(void);
> 
> void g_dnl_unregister(void);
Can be g_dnl_unregister() as well.
> 
> > +/* USB initialization declaration - board specific*/
> > +void board_usb_init(void);
> 
> not used in these files -> delete

But it is used at e.g. samsung/trats/trats.c I think that g_dnl.h is a
good place for this.

> -mike


-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-20  4:20   ` Mike Frysinger
@ 2012-07-23 16:01     ` Lukasz Majewski
  2012-07-24 18:00       ` Mike Frysinger
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-23 16:01 UTC (permalink / raw)
  To: u-boot

Dear Mike,

> On Tuesday 03 July 2012 05:38:09 Lukasz Majewski wrote:
> > --- /dev/null
> > +++ b/common/cmd_dfu.c
> >
> > +int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const
> > argv[])
> 
> static

It can be static (static int do_dfu). On the other hand the U_BOOT_CMD
macro defines:

int	(*cmd)(struct cmd_tbl_s *, int, int, char * const []); at
struct cmd_tbl_s, which is int.

> 
> > +{
> > +	char *str_env = NULL, *env_bkp = NULL;
> 
> no need to assign NULL here.  str_env should be const.
Yes, correct.
> 
> > +	static char *s = "dfu";
> 
> no need to declare this static
Why not? The s ptr is further passed to g_dnl_init(s), so my intend was
to declare string in the data segment of this translation unit. In this
way the data under this ptr will not vanish. 
> 
> > +	int ret = 0;
> 
> no need to init to 0

Ok.
> 
> > +	env_bkp = strdup(str_env);
> > +	ret = dfu_config_entities(env_bkp, argv[1],
> > +			    (int)simple_strtoul(argv[2], NULL,
> > 10));
> > +	if (ret)
> > +		return CMD_RET_FAILURE;
> > +
> > +	if (strcmp(argv[3], "list") == 0) {
> > +		dfu_show_entities();
> > +		dfu_free_entities();
> > +		free(env_bkp);
> > +		return CMD_RET_SUCCESS;
> 
> for these last three statements, you could just do "goto done" and
> put a done label below ...

Yes, you are correct. Thanks for tip.

> 
> > +exit:
> > +	g_dnl_cleanup();
> 
> done:
> 
> > +	dfu_free_entities();
> > +	free(env_bkp);
> > +
> > +	return CMD_RET_SUCCESS;
> 
> -mike



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 3/7] dfu: DFU backend implementation
  2012-07-20  4:32   ` Mike Frysinger
@ 2012-07-23 16:11     ` Lukasz Majewski
  0 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-23 16:11 UTC (permalink / raw)
  To: u-boot

Dear Mike Frysinger,

> On Tuesday 03 July 2012 05:38:07 Lukasz Majewski wrote:
> > +		puts("UPLOAD ... done\n");
> > +		puts("Ctrl+C to exit ...\n");
> 
> combine into a single puts() ?
Ok, will be done
> 
> > +static int dfu_fill_entity(struct dfu_entity *dfu, char* s, int
> > alt,
> > +			    char *interface, int num)
> > +{
> > +	char *st = NULL;
> > +	int n = 0;
> > +
> > +	debug("%s: %s interface: %s num: %d\n", __func__, s,
> > interface, num); +
> > +	st = dfu_extract_token(&s, &n);
> > +	strncpy((char *) &dfu->name, st, n);
> 
> what's with the pointless cast ?  just do:
> 	strncpy(dfu->name, st, n);
Yes, you are right.

> 
> also, "n" here is wrong.  it should be sizeof(dfu->name), not
> (presumably) the length of st.  considering this is the 2nd time i
> noticed this bug in the dfu patchset, you might want to do a grep on
> your patches to see if your other string related usage is wrong.

I will double-check the string operations.

> 
> > +void dfu_free_entities(void)
> > +{
> > +	struct dfu_entity *dfu = NULL, *p = NULL;
> 
> no point in assigning to NULL here

Will remove.
> 
> > +static char *dfu_get_dev_type(enum dfu_device_type t)
> 
> static const char *...
Will correct.
> 
> > +{
> > +	static char *dev_t[] = {NULL, "MMC", "ONENAND", "NAND" };
> 
> static const char * const dev_t[] = {...}
Ok
> 
> > +static char *dfu_get_layout(enum dfu_device_type l)
> 
> static const char *...
> 
Ok
> > +{
> > +	static char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT",
> > "EXT" };
> 
> static const char * const dfu_layout[] = {...}
> 
OK
> > +void dfu_show_entities(void)
> > +{
> > +	struct dfu_entity *dfu = NULL;
> 
> no point in assigning to NULL
OK
> 
> > +struct dfu_entity *dfu_get_entity(int alt)
> > +{
> > +	struct dfu_entity *dfu = NULL;
> 
> no point in assigning to NULL
OK
> -mike



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 1/7] dfu:usb: Support for g_dnl composite download gadget.
  2012-07-23 15:25     ` Lukasz Majewski
@ 2012-07-24 17:50       ` Mike Frysinger
  0 siblings, 0 replies; 147+ messages in thread
From: Mike Frysinger @ 2012-07-24 17:50 UTC (permalink / raw)
  To: u-boot

On Monday 23 July 2012 11:25:25 Lukasz Majewski wrote:
> Dear Mike Frysinger,
> > On Tuesday 03 July 2012 05:38:05 Lukasz Majewski wrote:
> > > +{
> > > +	int ret;
> > > +	static char str[16];
> > > +
> > > +	memset(str, '\0', sizeof(str));
> > > +
> > > +	strncpy(str, shortname, sizeof(shortname));
> > 
> > no need for the memset.
> 
> The gadget can be called from many separate commands (e.g. command
> "dfu" and command "ums") and those commands can be executed without
> power cycle. Thereof I need to be sure, that str is not polluted by
> previous name.

that makes no sense.  please read the documentation of the str*cpy functions 
-- they do no analysis of the target string and merely copy the source to the 
destination.  thus this code is basically:

	str[0] = '\0';
	str[1] = '\0';
	str[...] = '\0';
	str[0] = shortname[0];
	str[1] = shortname[1];
	str[...] = shortname[...];

it should be fairly obvious now why that memset is pointless.

> > this strncpy looks broken -- the 3rd arg is
> > for how many bytes are available in the *dest* buffer, not how long
> > the source is.
> 
> After looking deeply into the source I admit that providing the
> upper bound on the dest is more safe.

it isn't a matter of being safe, it's a matter of correctness

> > > +		strncat(str, s, sizeof(str));
> > 
> > this is also incorrect.  the length given to strncat is how many
> > bytes are left, not the total length.
> 
> I cannot agree. sizeof(str) return 16, which is the destination buffer
> size.

which is wrong.  please read the strncat specification.

> > since this string parsing logic is all just completely broken, i'd
> > suggest replacing it all with:
> > 
> > {
> > 	int ret;
> > 	/* We only allow "dfu" atm, so 3 should be enough */
> > 	static char name[sizeof(shortname) + 3];
> > 	
> > 	if (strcmp(s, "dfu")) {
> > 		printf("%s: unknown command: %s\n", __func__, s);
> > 		return -EINVAL;
> > 	}
> > 	
> > 	strcpy(name, shortname);
> > 	strcat(name, s);
> 
> This is a very neat design, but it assumes that there will be only one
> function ("dfu" in this case). For this particular function +3
> applies, but what if another function (like "usb_storage") will be
> defined?

why does that matter ?  the snippet i posted above is trivial to extend to 
support any number of functions.  increase the "3" to the max you care about, 
and then add more strcmp() to the if statement.

> I'm now working on another function - the USB Mass Storage (named
> "ums" ;-) ).
> 
> Another issue is omitting the strncmp/strncpy functions and depending on
> the: static char name[sizeof(shortname) + 3]; definition to prevent
> buffer overflow.

your existing code is already full of bugs that don't prevent overflow, and 
having the "3" right next to the "dfu" with a comment makes it pretty clear 
what is going on.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120724/a538543b/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-23 16:01     ` Lukasz Majewski
@ 2012-07-24 18:00       ` Mike Frysinger
  2012-07-24 20:48         ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-07-24 18:00 UTC (permalink / raw)
  To: u-boot

On Monday 23 July 2012 12:01:04 Lukasz Majewski wrote:
> Dear Mike,
> > On Tuesday 03 July 2012 05:38:09 Lukasz Majewski wrote:
> > > --- /dev/null
> > > +++ b/common/cmd_dfu.c
> > > 
> > > +int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const
> > > argv[])
> > 
> > static
> 
> It can be static (static int do_dfu). On the other hand the U_BOOT_CMD
> macro defines:
> 
> int	(*cmd)(struct cmd_tbl_s *, int, int, char * const []); at
> struct cmd_tbl_s, which is int.

i don't understand what you're trying to say

> > > +	static char *s = "dfu";
> > 
> > no need to declare this static
> 
> Why not? The s ptr is further passed to g_dnl_init(s), so my intend was
> to declare string in the data segment of this translation unit. In this
> way the data under this ptr will not vanish.

except your g_dnl_init already copies the incoming string to local storage, so 
where it is stored doesn't matter.  further, the "dfu" is going to be in 
.rodata (thus never going away), it is only the "s" pointer which will be 
stored in .data, not the thing it points to.

had you done:
	char s[] = { 'd', 'f', 'u', '\0', };
then you'd get 4 bytes on the stack
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120724/7bdd3c07/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-24 18:00       ` Mike Frysinger
@ 2012-07-24 20:48         ` Lukasz Majewski
  0 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-24 20:48 UTC (permalink / raw)
  To: u-boot

Hi Mike,

> On Monday 23 July 2012 12:01:04 Lukasz Majewski wrote:
> > Dear Mike,
> > > On Tuesday 03 July 2012 05:38:09 Lukasz Majewski wrote:
> > > > --- /dev/null
> > > > +++ b/common/cmd_dfu.c
> > > > 
> > > > +int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const
> > > > argv[])
> > > 
> > > static
> > 
> > It can be static (static int do_dfu). On the other hand the
> > U_BOOT_CMD macro defines:
> > 
> > int	(*cmd)(struct cmd_tbl_s *, int, int, char * const []); at
> > struct cmd_tbl_s, which is int.
> 
> i don't understand what you're trying to say
> 
> > > > +	static char *s = "dfu";
> > > 
> > > no need to declare this static
> > 
> > Why not? The s ptr is further passed to g_dnl_init(s), so my intend
> > was to declare string in the data segment of this translation unit.
> > In this way the data under this ptr will not vanish.
> 
> except your g_dnl_init already copies the incoming string to local
> storage, so where it is stored doesn't matter.  further, the "dfu" is
> going to be in .rodata (thus never going away), it is only the "s"
> pointer which will be stored in .data, not the thing it points to.
> 
> had you done:
> 	char s[] = { 'd', 'f', 'u', '\0', };
> then you'd get 4 bytes on the stack

Thanks for clarification

Regards,
Lukasz Majewski

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 3/7] dfu: DFU backend implementation
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 3/7] dfu: DFU backend implementation Lukasz Majewski
  2012-07-09 16:35     ` Marek Vasut
@ 2012-07-27 11:58     ` Wolfgang Denk
  2012-07-27 13:15       ` Lukasz Majewski
  1 sibling, 1 reply; 147+ messages in thread
From: Wolfgang Denk @ 2012-07-27 11:58 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

In message <1341416922-13792-4-git-send-email-l.majewski@samsung.com> you wrote:
> New, separate driver at ./drivers/dfu has been added. It allows platform
> and storage independent operation of DFU.

Sorry for a probably stupid question, but I know basicly zero about
DFU.   We are talking about "storage independent" here.  Does this
also mean file system independent?

> +static char *dfu_get_dev_type(enum dfu_device_type t)
> +{
> +	static char *dev_t[] = {NULL, "MMC", "ONENAND", "NAND" };
> +	return dev_t[t];
> +}

So this currently supports MMC, OneNAND and NAND as storage devices?

> +static char *dfu_get_layout(enum dfu_device_type l)
> +{
> +	static char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT" };
> +	return dfu_layout[l];
> +}

And FAT (or VFAT?) and EXT (as in EXT2? or EXT3? or ... ?) as file
systems?

> +enum dfu_device_type {
> +	MMC = 1,
> +	ONENAND,
> +	NAND
> +};
> +
> +enum dfu_layout {
> +	RAW_ADDR = 1,
> +	FAT,
> +	EXT,
> +};

MMC, NAND, FAT and EXT are very generic names that heavily pollute on
the global name space.  Please chose more specific names, probaly also
indicating the meaning (EXT could be some "extension" or "external" or
whatever - the name does not indicate that this is a file system type
here.


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
It is your destiny.                                     - Darth Vader

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-04 15:48   ` [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
  2012-07-09 16:36     ` Marek Vasut
  2012-07-10  8:45     ` Tom Rini
@ 2012-07-27 12:36     ` Wolfgang Denk
  2012-07-27 12:43       ` Marek Vasut
  2012-07-27 13:33       ` Lukasz Majewski
  2 siblings, 2 replies; 147+ messages in thread
From: Wolfgang Denk @ 2012-07-27 12:36 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

In message <1341416922-13792-5-git-send-email-l.majewski@samsung.com> you wrote:
> Support for MMC storage devices to work with DFU framework.

Sorry for jumping in late.


> +	switch (dfu->layout) {
> +	case RAW_ADDR:
> +		sprintf(cmd_buf, "mmc write 0x%x %x %x", (unsigned int) buf,
> +			dfu->data.mmc.lba_start, dfu->data.mmc.lba_size);
> +		break;
> +	case FAT:
> +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx",
> +			dfu->data.mmc.dev, dfu->data.mmc.part,
> +			(unsigned int) buf, dfu->name, *len);
> +		break;
> +	default:
> +		printf("%s: Wrong layout!\n", __func__);
> +	}

In case of error, you should always print what the unexpected data
was.  The end user who receives an "Wrong layout!" error is probably
pretty much surpised and doesn't know what he did wrong.   If you
print instead: "EXT2 layout not supported (yet)" he would know exactly
what to change to make it work.


There has been some dicussion already if using this sprintf() /
run_command() approach is good or not, or how it should be fixed.

It appears, all this discussion forgot to take into account that
patch 3/7 dfu: DFU backend implementation promised to add "platform
and storage independent operation of DFU."  Here we are breaking this
promise.

And by adding special functions to the FAT file system code thing sget
just worse, as now not only the DFU code needs to be extended when we
want to use this with any other file system type, but suddenly this
also bleeds into all supported file system code.


I am aware that the current implementation suffers from the fact that
we don't have a unified access to file systems - each comes with it's
own set of commands and more or less (in)compatible command line and
function call interfaces.  This will hopefully improve in the context
of the device model rework, but we don't want to block you until then.
But considering that this is going to change in a foreseeable future,
it also makes littel sense to invest big efforts into generic code
that covers all potential future uses.

Here is my poposal:

Let's introduce a thin shim layer to abstract the file system
interface from the accesses you need here.  As far as I can see here,
you need exactly 4 functions:

- block_read()
- block_write()
- file_read()
- file_write()

These names could be function pointers to implement the device I/O in
a both device and file system agnostic way; you can implement
specific versions of the functions like mmc_block_read(),
usb_block_read(), ... etc. and use the settings of dfu_device_type
and dfu_layout to set the pointers to these functions.

For this shim layer I would actually prefer the original approach
(shown above) to use sprintf() to build commands based on the existing
command interface - this is the minimal intrusive way to implement
this for now.  With this approach, no modifications to file system
and/or device driver code are needed, and we still maintain full
flexibility here in the DFU code.  Yes, error checking may not be
perfect, and we my not win a price for elegance of design either, but
we should get mostly clean, working code quickly.


The advantage I see for this code is that we have separated all
this device interface stuff from both the generic DFU code and from
the device and file system code as well.  As soon as we have a better
implementation below, all we need to adjust (or potentially even
remove) is this shim layer.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
To the systems programmer,  users  and  applications  serve  only  to
provide a test load.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-27 12:36     ` Wolfgang Denk
@ 2012-07-27 12:43       ` Marek Vasut
  2012-07-27 12:57         ` Wolfgang Denk
  2012-07-27 13:33       ` Lukasz Majewski
  1 sibling, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-27 12:43 UTC (permalink / raw)
  To: u-boot

Dear Wolfgang Denk,

> Dear Lukasz Majewski,
> 
> In message <1341416922-13792-5-git-send-email-l.majewski@samsung.com> you 
wrote:
> > Support for MMC storage devices to work with DFU framework.
> 
> Sorry for jumping in late.
> 
> > +	switch (dfu->layout) {
> > +	case RAW_ADDR:
> > +		sprintf(cmd_buf, "mmc write 0x%x %x %x", (unsigned int) buf,
> > +			dfu->data.mmc.lba_start, dfu->data.mmc.lba_size);
> > +		break;
> > +	case FAT:
> > +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx",
> > +			dfu->data.mmc.dev, dfu->data.mmc.part,
> > +			(unsigned int) buf, dfu->name, *len);
> > +		break;
> > +	default:
> > +		printf("%s: Wrong layout!\n", __func__);
> > +	}
> 
> In case of error, you should always print what the unexpected data
> was.  The end user who receives an "Wrong layout!" error is probably
> pretty much surpised and doesn't know what he did wrong.   If you
> print instead: "EXT2 layout not supported (yet)" he would know exactly
> what to change to make it work.
> 
> 
> There has been some dicussion already if using this sprintf() /
> run_command() approach is good or not, or how it should be fixed.
> 
> It appears, all this discussion forgot to take into account that
> patch 3/7 dfu: DFU backend implementation promised to add "platform
> and storage independent operation of DFU."  Here we are breaking this
> promise.
> 
> And by adding special functions to the FAT file system code thing sget
> just worse, as now not only the DFU code needs to be extended when we
> want to use this with any other file system type, but suddenly this
> also bleeds into all supported file system code.
> 
> 
> I am aware that the current implementation suffers from the fact that
> we don't have a unified access to file systems - each comes with it's
> own set of commands and more or less (in)compatible command line and
> function call interfaces.  This will hopefully improve in the context
> of the device model rework, but we don't want to block you until then.
> But considering that this is going to change in a foreseeable future,
> it also makes littel sense to invest big efforts into generic code
> that covers all potential future uses.
> 
> Here is my poposal:
> 
> Let's introduce a thin shim layer to abstract the file system
> interface from the accesses you need here.  As far as I can see here,
> you need exactly 4 functions:
> 
> - block_read()
> - block_write()
> - file_read()
> - file_write()
> 
> These names could be function pointers to implement the device I/O in
> a both device and file system agnostic way; you can implement
> specific versions of the functions like mmc_block_read(),
> usb_block_read(), ... etc. and use the settings of dfu_device_type
> and dfu_layout to set the pointers to these functions.
> 
> For this shim layer I would actually prefer the original approach
> (shown above) to use sprintf() to build commands based on the existing
> command interface

We discussed it for a while ... figure out the missing typechecking and abuse of 
the command line interface is not a way to go.

> this is the minimal intrusive way to implement
> this for now.  With this approach, no modifications to file system
> and/or device driver code are needed, and we still maintain full
> flexibility here in the DFU code.  Yes, error checking may not be
> perfect, and we my not win a price for elegance of design either, but
> we should get mostly clean, working code quickly.

But now that we started going in the typechecking way, I'd prefer to go all the 
way. And once DFU extends properly towards other supported filesystems/devices, 
the rest of the interface can get cleaned along the way.

> The advantage I see for this code is that we have separated all
> this device interface stuff from both the generic DFU code and from
> the device and file system code as well.  As soon as we have a better
> implementation below, all we need to adjust (or potentially even
> remove) is this shim layer.

Shim layer is cool -- abusing command line is not cool ;-)

> Best regards,
> 
> Wolfgang Denk

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-27 12:43       ` Marek Vasut
@ 2012-07-27 12:57         ` Wolfgang Denk
  2012-07-27 13:15           ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Wolfgang Denk @ 2012-07-27 12:57 UTC (permalink / raw)
  To: u-boot

Dear Marek Vasut,

In message <201207271443.45189.marex@denx.de> you wrote:
>
> > For this shim layer I would actually prefer the original approach
> > (shown above) to use sprintf() to build commands based on the existing
> > command interface
> 
> We discussed it for a while ... figure out the missing typechecking and abuse of 
> the command line interface is not a way to go.

I agree that this is not the preferred way for a permanent solution,
but for now I cxonsider it acceptable, as it allows to easily deal
with the inconsistent API of the misc file system handlers.  For
example instead of

	sprintf(cmd_buf, "fatread mmc %d:%d 0x%x %s %lx", ...

we can even do something like

	sprintf(cmd_buf, "%s %s  %d:%d 0x%x %s %lx", 
		command, device, ...

and set command as needed to "fatread" or "ext2load" or whatever, and
device can be set to "mmc" or "usb" or ...

> > this is the minimal intrusive way to implement
> > this for now.  With this approach, no modifications to file system
> > and/or device driver code are needed, and we still maintain full
> > flexibility here in the DFU code.  Yes, error checking may not be
> > perfect, and we my not win a price for elegance of design either, but
> > we should get mostly clean, working code quickly.
> 
> But now that we started going in the typechecking way, I'd prefer to go all the 
> way. And once DFU extends properly towards other supported filesystems/devices, 
> the rest of the interface can get cleaned along the way.

You can implement the type checking code when you hav ea stable, well
define API for storage devices and file systems.  For now we don't
have that, and it makes ZERO sense to add special code just for that
just to throw it away in a few weeks.

> Shim layer is cool -- abusing command line is not cool ;-)

Whether this is abuse or clever use remains to be defined, and this
is probably largely a matter of taste.  In any case, this will be a
small piece of code that is of clearly transient nature, to be
replaced or removed as soon as we can do better.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
The nice thing about  standards  is that there are  so many to choose
from.                                           - Andrew S. Tanenbaum

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 3/7] dfu: DFU backend implementation
  2012-07-27 11:58     ` Wolfgang Denk
@ 2012-07-27 13:15       ` Lukasz Majewski
  2012-07-27 13:35         ` Wolfgang Denk
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-27 13:15 UTC (permalink / raw)
  To: u-boot

Dear Wolfgang Denk,

> Dear Lukasz Majewski,
> 
> In message <1341416922-13792-4-git-send-email-l.majewski@samsung.com>
> you wrote:
> > New, separate driver at ./drivers/dfu has been added. It allows
> > platform and storage independent operation of DFU.
> 
> Sorry for a probably stupid question, but I know basicly zero about
> DFU.   We are talking about "storage independent" here.  Does this
> also mean file system independent?

Some clarification is needed. I've divided DFU support (PATCH v2) to
three separate parts:
1. DFU transmission handling (via USB)
with ./drivers/usb/gadget/g_dnl.c|f_dfu.c

2. Generic DFU functions ./drivers/dfu/dfu.c - which try to abstract
DFU operation to be platform independent.
	Generic dfu_{write|read} functions have been defined and are
	accessible from USB code. On the other hand dfu_{write|read}
	calls function pointers dfu->{read|write}_medium(), which points
	to medium specific functions.

3. Code for MMC write/read - dfu_mmc.c. 
It is possible to read/write raw data to MMC (with passing LBA address)
or to file systems (like FAT). For now MMC is only supported. It uses
(in my opinion) "generic" sprintf+run_command() calls, which can be
easily extended. 
To support OneNAND one needs to define dfu_onenand.c file with OneNAND
specific functions.


Considering above, there are already defined "generic" access functions
- dfu_{write|read}.



> 
> > +static char *dfu_get_dev_type(enum dfu_device_type t)
> > +{
> > +	static char *dev_t[] = {NULL, "MMC", "ONENAND", "NAND" };
> > +	return dev_t[t];
> > +}
> 
> So this currently supports MMC, OneNAND and NAND as storage devices?

It currently only supports MMC devices. Others (ONENAND/NAND) have been
added as place holders for future usage.

> 
> > +static char *dfu_get_layout(enum dfu_device_type l)
> > +{
> > +	static char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT",
> > "EXT" };
> > +	return dfu_layout[l];
> > +}
> 
> And FAT (or VFAT?) and EXT (as in EXT2? or EXT3? or ... ?) as file
> systems?
> 
> > +enum dfu_device_type {
> > +	MMC = 1,
> > +	ONENAND,
> > +	NAND
> > +};
> > +
> > +enum dfu_layout {
> > +	RAW_ADDR = 1,
> > +	FAT,
> > +	EXT,
> > +};
> 
> MMC, NAND, FAT and EXT are very generic names that heavily pollute on
> the global name space.  Please chose more specific names, probaly also
> indicating the meaning (EXT could be some "extension" or "external" or
> whatever - the name does not indicate that this is a file system type
> here.

Ok, no problem with this.

> 
> 
> Best regards,
> 
> Wolfgang Denk
> 



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-27 12:57         ` Wolfgang Denk
@ 2012-07-27 13:15           ` Marek Vasut
  2012-07-27 13:38             ` Wolfgang Denk
  0 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-07-27 13:15 UTC (permalink / raw)
  To: u-boot

Dear Wolfgang Denk,

> Dear Marek Vasut,
> 
> In message <201207271443.45189.marex@denx.de> you wrote:
> > > For this shim layer I would actually prefer the original approach
> > > (shown above) to use sprintf() to build commands based on the existing
> > > command interface
> > 
> > We discussed it for a while ... figure out the missing typechecking and
> > abuse of the command line interface is not a way to go.
> 
> I agree that this is not the preferred way for a permanent solution,
> but for now I cxonsider it acceptable, as it allows to easily deal
> with the inconsistent API of the misc file system handlers.  For
> example instead of
> 
> 	sprintf(cmd_buf, "fatread mmc %d:%d 0x%x %s %lx", ...
> 
> we can even do something like
> 
> 	sprintf(cmd_buf, "%s %s  %d:%d 0x%x %s %lx",
> 		command, device, ...
> 
> and set command as needed to "fatread" or "ext2load" or whatever, and
> device can be set to "mmc" or "usb" or ...

Given that they have slightly different syntax, this is crazy too.

> > > this is the minimal intrusive way to implement
> > > this for now.  With this approach, no modifications to file system
> > > and/or device driver code are needed, and we still maintain full
> > > flexibility here in the DFU code.  Yes, error checking may not be
> > > perfect, and we my not win a price for elegance of design either, but
> > > we should get mostly clean, working code quickly.
> > 
> > But now that we started going in the typechecking way, I'd prefer to go
> > all the way. And once DFU extends properly towards other supported
> > filesystems/devices, the rest of the interface can get cleaned along the
> > way.
> 
> You can implement the type checking code when you hav ea stable, well
> define API for storage devices and file systems.  For now we don't
> have that, and it makes ZERO sense to add special code just for that
> just to throw it away in a few weeks.

Ad API -- adding Pavel to CC. Hope his GMail works better than mine (mine 
doesn't, crashed again, damned google stuff). Pavel, can you provide us with how 
the API will look maybe?

> > Shim layer is cool -- abusing command line is not cool ;-)
> 
> Whether this is abuse or clever use remains to be defined, and this
> is probably largely a matter of taste.  In any case, this will be a
> small piece of code that is of clearly transient nature, to be
> replaced or removed as soon as we can do better.
> 
> Best regards,
> 
> Wolfgang Denk

Well ... after this discussion, I feel like I'll just go dig me a grave again.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-27 12:36     ` Wolfgang Denk
  2012-07-27 12:43       ` Marek Vasut
@ 2012-07-27 13:33       ` Lukasz Majewski
  2012-07-27 13:47         ` Wolfgang Denk
  1 sibling, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-27 13:33 UTC (permalink / raw)
  To: u-boot

Dear Wolfgang Denk,

> Dear Lukasz Majewski,
> 
> In message <1341416922-13792-5-git-send-email-l.majewski@samsung.com>
> you wrote:
> > Support for MMC storage devices to work with DFU framework.
> 
> Sorry for jumping in late.
> 
> 
> > +	switch (dfu->layout) {
> > +	case RAW_ADDR:
> > +		sprintf(cmd_buf, "mmc write 0x%x %x %x", (unsigned
> > int) buf,
> > +			dfu->data.mmc.lba_start,
> > dfu->data.mmc.lba_size);
> > +		break;
> > +	case FAT:
> > +		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx",
> > +			dfu->data.mmc.dev, dfu->data.mmc.part,
> > +			(unsigned int) buf, dfu->name, *len);
> > +		break;
> > +	default:
> > +		printf("%s: Wrong layout!\n", __func__);
> > +	}
> 
> In case of error, you should always print what the unexpected data
> was.  The end user who receives an "Wrong layout!" error is probably
> pretty much surpised and doesn't know what he did wrong.   If you
> print instead: "EXT2 layout not supported (yet)" he would know exactly
> what to change to make it work.

Ok, this can be easily corrected.
> 
> 
> There has been some dicussion already if using this sprintf() /
> run_command() approach is good or not, or how it should be fixed.
> 
> It appears, all this discussion forgot to take into account that
> patch 3/7 dfu: DFU backend implementation promised to add "platform
> and storage independent operation of DFU."  Here we are breaking this
> promise.
>
> And by adding special functions to the FAT file system code thing sget
> just worse, as now not only the DFU code needs to be extended when we
> want to use this with any other file system type, but suddenly this
> also bleeds into all supported file system code.
> 
> 
> I am aware that the current implementation suffers from the fact that
> we don't have a unified access to file systems - each comes with it's
> own set of commands and more or less (in)compatible command line and
> function call interfaces.  This will hopefully improve in the context
> of the device model rework, but we don't want to block you until then.
> But considering that this is going to change in a foreseeable future,
> it also makes littel sense to invest big efforts into generic code
> that covers all potential future uses.
> 
> Here is my poposal:
> 
> Let's introduce a thin shim layer to abstract the file system
> interface from the accesses you need here.  As far as I can see here,
> you need exactly 4 functions:
> 
> - block_read()
> - block_write()
> - file_read()
> - file_write()
> 
> These names could be function pointers to implement the device I/O in
> a both device and file system agnostic way; you can implement
> specific versions of the functions like mmc_block_read(),
> usb_block_read(), ... etc. and use the settings of dfu_device_type
> and dfu_layout to set the pointers to these functions.
> 
> For this shim layer I would actually prefer the original approach
> (shown above) to use sprintf() to build commands based on the existing
> command interface - this is the minimal intrusive way to implement
> this for now.  With this approach, no modifications to file system
> and/or device driver code are needed, and we still maintain full
> flexibility here in the DFU code.  Yes, error checking may not be
> perfect, and we my not win a price for elegance of design either, but
> we should get mostly clean, working code quickly.
> 

So I suppose, that you are proposing something like this (pseudo code):

int mmc_block_write() {
	sprintf(cmd_buf, "mmc write 0x%x %x %x")
	run_command(cmd_buf, 0);
}

int mmc_file_write(enum fs_type) {
	switch (fs_type)
	case FAT:
		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx")
	break;
	case EXT4:
		sprintf(cmd_buf, "ext4write mmc %d:%d 0x%x %s %lx")
	break;
	run_command(cmd_buf);
}

int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
{
	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf, DFU_CMD_BUF_SIZE);

	memset(cmd_buf, '\0', sizeof(cmd_buf));

	switch (dfu->layout) {
	case RAW_ADDR:
		mmc_block_write()
		break;
	case FAT:
	case EXT3:
	case EXT4:
		mmc_file_write(dfu->layout);
		break;
	default:
		printf("%s: Wrong layout %s!\n", __func__,
		layout_table[dfu->layout]); }	

	return 0;
}


> 
> The advantage I see for this code is that we have separated all
> this device interface stuff from both the generic DFU code and from
> the device and file system code as well.  As soon as we have a better
> implementation below, all we need to adjust (or potentially even
> remove) is this shim layer.
> 


-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 3/7] dfu: DFU backend implementation
  2012-07-27 13:15       ` Lukasz Majewski
@ 2012-07-27 13:35         ` Wolfgang Denk
  2012-07-27 13:47           ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Wolfgang Denk @ 2012-07-27 13:35 UTC (permalink / raw)
  To: u-boot

Dear Lukasz,

In message <20120727151523.41406989@amdc308.digital.local> you wrote:
> 
> Some clarification is needed. I've divided DFU support (PATCH v2) to
> three separate parts:
> 1. DFU transmission handling (via USB)
...
> 2. Generic DFU functions ./drivers/dfu/dfu.c - which try to abstract
> DFU operation to be platform independent.
...
> 3. Code for MMC write/read - dfu_mmc.c. 

OK, than my understanding was mostly correct.

> It is possible to read/write raw data to MMC (with passing LBA address)
> or to file systems (like FAT). For now MMC is only supported. It uses
> (in my opinion) "generic" sprintf+run_command() calls, which can be
> easily extended. 
> To support OneNAND one needs to define dfu_onenand.c file with OneNAND
> specific functions.

Correct.  And adaption for other devices (say, NAND or USB mass
storage) should be trivial as well.

> Considering above, there are already defined "generic" access functions
> - dfu_{write|read}.

OK - but the device specific stuff is only used in the sprintf()
command then.  That's why I recommend to move just this very small
function into a separate file, which can be replaced or removed later.

> > So this currently supports MMC, OneNAND and NAND as storage devices?
> 
> It currently only supports MMC devices. Others (ONENAND/NAND) have been
> added as place holders for future usage.

Yes, I understand.  But then, adding such support looks pretty
straightforward, and even trivial to me.  You provided a pretty clear
infrastructure for this, thanks.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
I thought my people would grow tired of killing. But you were  right,
they  see it is easier than trading. And it has its pleasures. I feel
it myself. Like the hunt, but with richer rewards.
	-- Apella, "A Private Little War", stardate 4211.8

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-27 13:15           ` Marek Vasut
@ 2012-07-27 13:38             ` Wolfgang Denk
  0 siblings, 0 replies; 147+ messages in thread
From: Wolfgang Denk @ 2012-07-27 13:38 UTC (permalink / raw)
  To: u-boot

Dear Marek Vasut,

In message <201207271515.36085.marex@denx.de> you wrote:
> 
> > 	sprintf(cmd_buf, "%s %s  %d:%d 0x%x %s %lx",
> > 		command, device, ...
> > 
> > and set command as needed to "fatread" or "ext2load" or whatever, and
> > device can be set to "mmc" or "usb" or ...
> 
> Given that they have slightly different syntax, this is crazy too.

Draw the line between clever and crazy, genius and idiot :-)


> Well ... after this discussion, I feel like I'll just go dig me a grave again.

Why?  I think the discussion has been beneficial - we isolated a poor
piece of code, discussed how it should be improved, and now ry to find
an intermediate solution that adds not too much work for Lukasz while
still keeing the existing code clean and allowing for easy adaption to
the new DM interfaces - three worthwile goals at once.

Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Sorry, but my karma just ran over your dogma.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 3/7] dfu: DFU backend implementation
  2012-07-27 13:35         ` Wolfgang Denk
@ 2012-07-27 13:47           ` Lukasz Majewski
  0 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-27 13:47 UTC (permalink / raw)
  To: u-boot

Dear Wolfgang Denk,

> Correct.  And adaption for other devices (say, NAND or USB mass
> storage) should be trivial as well.


USB Mass Storage is also under development. It is supposed to be a
function (f_ums.c) for g_dnl.c composite gadget.

I will postpone posting it to ML until we agree for the DFU shape (and
thereof the g_dnl composite gadget driver).

-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation
  2012-07-27 13:33       ` Lukasz Majewski
@ 2012-07-27 13:47         ` Wolfgang Denk
  0 siblings, 0 replies; 147+ messages in thread
From: Wolfgang Denk @ 2012-07-27 13:47 UTC (permalink / raw)
  To: u-boot

Dear Lukasz,

In message <20120727153345.008fde41@amdc308.digital.local> you wrote:
> 
> So I suppose, that you are proposing something like this (pseudo code):

Yes, very close.

> int mmc_block_write() {
> 	sprintf(cmd_buf, "mmc write 0x%x %x %x")
> 	run_command(cmd_buf, 0);
> }
> 
> int mmc_file_write(enum fs_type) {
> 	switch (fs_type)
> 	case FAT:
> 		sprintf(cmd_buf, "fatwrite mmc %d:%d 0x%x %s %lx")
> 	break;
> 	case EXT4:
> 		sprintf(cmd_buf, "ext4write mmc %d:%d 0x%x %s %lx")
> 	break;
> 	run_command(cmd_buf);
> }


> int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
> {

I suggest just use 

	int dfu_write_medium(struct dfu_entity *dfu, void *buf, long *len)

here; you can then so something like

	switch (dfu->dev_type) {
	case MMC:	block_write = mmc_block_write;
			file_write  = mmc_file_write;
			break;
#ifdef NAND_SUPPORT_AVAILABLE
	case NAND:	block_write = nand_block_write;
			file_write  = nand_block_write;
			break;
#endif
	...

and use block_write() resp. file_write() in the rest.  So the code is
really trivial to extend for other storage devices and file systems.

I feel we are very close, thanks!

Let's see if Pavel adds some comments about the best API to chose to
be as compatible with possible with the upcoming block device layer,
and then we can go for it.


Best regards,

Wolfgang Denk

-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
Houston, Tranquillity Base here.  The Eagle has landed.
                                                    -- Neil Armstrong

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 0/7] dfu:usb: DFU support via USB Download gadget
  2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
                   ` (9 preceding siblings ...)
  2012-07-18 12:51 ` [U-Boot] [PATCH " Marek Vasut
@ 2012-07-31  6:36 ` Lukasz Majewski
  2012-07-31  6:36   ` [U-Boot] [PATCH v3 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
                     ` (6 more replies)
  2012-08-03  7:45 ` [U-Boot] [PATCH v4 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
  2012-08-06 12:41 ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
  12 siblings, 7 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-31  6:36 UTC (permalink / raw)
  To: u-boot

Those patches add support for composite USB download gadget.
This gadget (at least for now) is equipped with DFU download function.

A separate DFU back-end and front-end have been added.
Back-end is placed at ./drivers/dfu directory. The front-end is implemented
as USB function.

The back-end is written in a generic manner with storage device specific
code separated (eMMC).

DFU specification can be found at:
http://wiki.openmoko.org/wiki/USB_DFU_-_The_USB_Device_Firmware_Upgrade_standard

Example usage:

u-boot side: dfu mmc 0
PC: dfu-util -U IMAGE.bin -a uImage (for upload)
    dfu-util -D uImage -a uImage (download)

To list the alt settings:
        dfu mmc 0 list

Test HW:
        Exynos4210 Trats board


Lukasz Majewski (7):
  dfu:usb: Support for g_dnl composite download gadget.
  dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  dfu: DFU backend implementation
  dfu: MMC specific routines for DFU operation
  dfu:cmd: Support for DFU u-boot command
  arm:trats: Support for USB UDC driver at TRATS board.
  arm:trats: Enable g_dnl composite USB gadget with embedded DFU
    function on TRATS

 Makefile                    |    1 +
 board/samsung/trats/trats.c |    8 +
 common/Makefile             |    1 +
 common/cmd_dfu.c            |   81 +++++
 drivers/dfu/Makefile        |   44 +++
 drivers/dfu/dfu.c           |  237 ++++++++++++++
 drivers/dfu/dfu_mmc.c       |  165 ++++++++++
 drivers/usb/gadget/Makefile |    2 +
 drivers/usb/gadget/f_dfu.c  |  751 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/f_dfu.h  |  100 ++++++
 drivers/usb/gadget/g_dnl.c  |  218 +++++++++++++
 include/configs/trats.h     |   24 ++-
 include/dfu.h               |  103 ++++++
 include/g_dnl.h             |   33 ++
 14 files changed, 1767 insertions(+), 1 deletions(-)
 create mode 100644 common/cmd_dfu.c
 create mode 100644 drivers/dfu/Makefile
 create mode 100644 drivers/dfu/dfu.c
 create mode 100644 drivers/dfu/dfu_mmc.c
 create mode 100644 drivers/usb/gadget/f_dfu.c
 create mode 100644 drivers/usb/gadget/f_dfu.h
 create mode 100644 drivers/usb/gadget/g_dnl.c
 create mode 100644 include/dfu.h
 create mode 100644 include/g_dnl.h

-- 
1.7.2.3

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 1/7] dfu:usb: Support for g_dnl composite download gadget.
  2012-07-31  6:36 ` [U-Boot] [PATCH v3 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
@ 2012-07-31  6:36   ` Lukasz Majewski
  2012-08-01 22:40     ` Mike Frysinger
  2012-07-31  6:36   ` [U-Boot] [PATCH v3 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
                     ` (5 subsequent siblings)
  6 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-31  6:36 UTC (permalink / raw)
  To: u-boot

Composite USB download gadget support (g_dnl) for download functions.
This code works on top of composite gadget.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:

- G_DNL_{VENDOR_NUM, PRODUCT_NUM and MANUFACTURER} defined at
./include/configs/<board>.h
- Suspend and resume stub methods removed
- '\0' repleaced with plain 0

Changes for v3:
- Remove unused #includes
- Replace strncpy and strncat with strcpy and strcat. It was possible
  due to new approach to g_dnl name generation (at g_dnl_register function)
- Rename the g_dnl_{init|cleanup} to g_dnl_{register|unregister}
- Replace the G_DNL_* CONFIG_G_DNL_*
---
 drivers/usb/gadget/Makefile |    1 +
 drivers/usb/gadget/g_dnl.c  |  218 +++++++++++++++++++++++++++++++++++++++++++
 include/g_dnl.h             |   33 +++++++
 3 files changed, 252 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/gadget/g_dnl.c
 create mode 100644 include/g_dnl.h

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 87d1918..2c067c8 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -29,6 +29,7 @@ LIB	:= $(obj)libusb_gadget.o
 ifdef CONFIG_USB_GADGET
 COBJS-y += epautoconf.o config.o usbstring.o
 COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
+COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
 endif
 ifdef CONFIG_USB_ETHER
 COBJS-y += ether.o epautoconf.o config.o usbstring.o
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
new file mode 100644
index 0000000..a77da30
--- /dev/null
+++ b/drivers/usb/gadget/g_dnl.c
@@ -0,0 +1,218 @@
+/*
+ * g_dnl.c -- USB Downloader Gadget
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski  <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <errno.h>
+#include <common.h>
+#include <malloc.h>
+
+#include <mmc.h>
+#include <part.h>
+
+#include <g_dnl.h>
+#include "f_dfu.h"
+
+#include "gadget_chips.h"
+#include "composite.c"
+
+/*
+ * One needs to define the following:
+ * CONFIG_G_DNL_VENDOR_NUM
+ * CONFIG_G_DNL_PRODUCT_NUM
+ * CONFIG_G_DNL_MANUFACTURER
+ * at e.g. ./include/configs/<board>.h
+ */
+
+#define STRING_MANUFACTURER 25
+#define STRING_PRODUCT 2
+#define STRING_USBDOWN 2
+#define CONFIG_USBDOWNLOADER 2
+
+#define DRIVER_VERSION		"usb_dnl 2.0"
+
+static const char shortname[] = "usb_dnl_";
+static const char product[] = "USB download gadget";
+static const char manufacturer[] = CONFIG_G_DNL_MANUFACTURER;
+
+static struct usb_device_descriptor device_desc = {
+	.bLength =		sizeof device_desc,
+	.bDescriptorType =	USB_DT_DEVICE,
+
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_COMM,
+	.bDeviceSubClass =      0x02,	/*0x02:CDC-modem , 0x00:CDC-serial*/
+
+	.idVendor =	__constant_cpu_to_le16(CONFIG_G_DNL_VENDOR_NUM),
+	.idProduct =	__constant_cpu_to_le16(CONFIG_G_DNL_PRODUCT_NUM),
+	.iProduct =	STRING_PRODUCT,
+	.bNumConfigurations =	1,
+};
+
+static const struct usb_descriptor_header *otg_desc[] = {
+	(struct usb_descriptor_header *) &(struct usb_otg_descriptor){
+		.bLength =		sizeof(struct usb_otg_descriptor),
+		.bDescriptorType =	USB_DT_OTG,
+		.bmAttributes =		USB_OTG_SRP,
+	},
+	NULL,
+};
+
+/* static strings, in UTF-8 */
+static struct usb_string odin_string_defs[] = {
+	{ 0, manufacturer, },
+	{ 1, product, },
+};
+
+static struct usb_gadget_strings odin_string_tab = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= odin_string_defs,
+};
+
+static struct usb_gadget_strings *g_dnl_composite_strings[] = {
+	&odin_string_tab,
+	NULL,
+};
+
+static int g_dnl_unbind(struct usb_composite_dev *cdev)
+{
+	debug("%s\n", __func__);
+	return 0;
+}
+
+static int g_dnl_do_config(struct usb_configuration *c)
+{
+	int ret = -1;
+	char *s = (char *) c->cdev->driver->name;
+
+	debug("%s: configuration: 0x%p composite dev: 0x%p\n",
+	      __func__, c, c->cdev);
+
+	if (gadget_is_otg(c->cdev->gadget)) {
+		c->descriptors = otg_desc;
+		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
+	printf("GADGET DRIVER: %s\n", s);
+
+	if (!strcmp(s, "usb_dnl_dfu"))
+		ret = dfu_add(c);
+
+	return ret;
+}
+
+static int g_dnl_config_register(struct usb_composite_dev *cdev)
+{
+	debug("%s:\n", __func__);
+	static struct usb_configuration config = {
+		.label = "usb_dnload",
+		.bmAttributes =	USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+		.bConfigurationValue =	CONFIG_USBDOWNLOADER,
+		.iConfiguration =	STRING_USBDOWN,
+
+		.bind = g_dnl_do_config,
+	};
+
+	return usb_add_config(cdev, &config);
+}
+
+static int g_dnl_bind(struct usb_composite_dev *cdev)
+{
+	int			gcnum;
+	int id, ret;
+	struct usb_gadget	*gadget = cdev->gadget;
+
+	debug("%s: gadget: 0x%p cdev: 0x%p\n", __func__, gadget, cdev);
+
+	id = usb_string_id(cdev);
+
+	if (id < 0)
+		return id;
+	odin_string_defs[0].id = id;
+	device_desc.iManufacturer = id;
+
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+
+	odin_string_defs[1].id = id;
+	device_desc.iProduct = id;
+
+	ret = g_dnl_config_register(cdev);
+	if (ret)
+		goto error;
+
+	gcnum = usb_gadget_controller_number(gadget);
+
+	debug("gcnum: %d\n", gcnum);
+	if (gcnum >= 0)
+		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
+	else {
+		debug("%s: controller '%s' not recognized\n",
+			shortname, gadget->name);
+		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
+	}
+
+	return 0;
+
+ error:
+	g_dnl_unbind(cdev);
+	return -ENOMEM;
+}
+
+static struct usb_composite_driver g_dnl_driver = {
+	.name		= NULL,
+	.dev		= &device_desc,
+	.strings	= g_dnl_composite_strings,
+
+	.bind		= g_dnl_bind,
+	.unbind		= g_dnl_unbind,
+};
+
+int g_dnl_register(const char *type)
+{
+	int ret;
+	/* We only allow "dfu" atm, so 3 should be enough */
+	static char name[sizeof(shortname) + 3];
+
+	if (!strcmp(type, "dfu")) {
+		strcpy(name, shortname);
+		strcat(name, type);
+	} else {
+		printf("%s: unknown command: %s\n", __func__, type);
+		return -EINVAL;
+	}
+
+	g_dnl_driver.name = name;
+
+	debug("%s: g_dnl_driver.name: %s\n", __func__, g_dnl_driver.name);
+	ret = usb_composite_register(&g_dnl_driver);
+
+	if (ret) {
+		printf("%s: failed!, error: %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+void g_dnl_unregister(void)
+{
+	usb_composite_unregister(&g_dnl_driver);
+}
diff --git a/include/g_dnl.h b/include/g_dnl.h
new file mode 100644
index 0000000..d65214f
--- /dev/null
+++ b/include/g_dnl.h
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (C) 2012 Samsung Electronics
+ *  Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __G_DOWNLOAD_H_
+#define __G_DOWNLOAD_H_
+
+#include <linux/usb/ch9.h>
+#include <usbdescriptors.h>
+#include <linux/usb/gadget.h>
+
+int g_dnl_register(const char *s);
+void g_dnl_unregister(void);
+
+/* USB initialization declaration - board specific*/
+void board_usb_init(void);
+#endif /* __G_DOWNLOAD_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  2012-07-31  6:36 ` [U-Boot] [PATCH v3 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
  2012-07-31  6:36   ` [U-Boot] [PATCH v3 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
@ 2012-07-31  6:36   ` Lukasz Majewski
  2012-08-01 22:45     ` Mike Frysinger
  2012-07-31  6:36   ` [U-Boot] [PATCH v3 3/7] dfu: DFU backend implementation Lukasz Majewski
                     ` (4 subsequent siblings)
  6 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-31  6:36 UTC (permalink / raw)
  To: u-boot

Support for f_dfu USB function.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:

- Replace kzalloc and kfree with free and calloc
- Reorganization of calloc calls
- Misspelling corrected
- Redesign of DFU state machine from "switch case" to function pointers
- Split the dfu_handle method to separate functions for each DFU state

Changes for v3:
- Missing parenthesis added to sizeof call
---
 drivers/usb/gadget/Makefile |    1 +
 drivers/usb/gadget/f_dfu.c  |  751 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/f_dfu.h  |  100 ++++++
 3 files changed, 852 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/gadget/f_dfu.c
 create mode 100644 drivers/usb/gadget/f_dfu.h

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 2c067c8..5bbdd36 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -30,6 +30,7 @@ ifdef CONFIG_USB_GADGET
 COBJS-y += epautoconf.o config.o usbstring.o
 COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
 COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
+COBJS-$(CONFIG_DFU_FUNCTION) += f_dfu.o
 endif
 ifdef CONFIG_USB_ETHER
 COBJS-y += ether.o epautoconf.o config.o usbstring.o
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
new file mode 100644
index 0000000..17b656c
--- /dev/null
+++ b/drivers/usb/gadget/f_dfu.c
@@ -0,0 +1,751 @@
+/*
+ * f_dfu.c -- Device Firmware Update USB function
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *          Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <errno.h>
+#include <common.h>
+#include <malloc.h>
+
+#include <linux/usb/ch9.h>
+#include <usbdescriptors.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/composite.h>
+
+#include <dfu.h>
+#include "f_dfu.h"
+
+struct f_dfu {
+	struct usb_function		usb_function;
+
+	struct usb_descriptor_header	**function;
+	struct usb_string		*strings;
+
+	/* when configured, we have one config */
+	u8				config;
+	u8				altsetting;
+	enum dfu_state			dfu_state;
+	unsigned int			dfu_status;
+
+	/* Send/received block number is handy for data integrity check */
+	int                             blk_seq_num;
+};
+
+typedef int (*dfu_state_fn) (struct f_dfu *,
+			     const struct usb_ctrlrequest *,
+			     struct usb_gadget *,
+			     struct usb_request *);
+
+static inline struct f_dfu *func_to_dfu(struct usb_function *f)
+{
+	return container_of(f, struct f_dfu, usb_function);
+}
+
+static const struct dfu_function_descriptor dfu_func = {
+	.bLength =		sizeof dfu_func,
+	.bDescriptorType =	DFU_DT_FUNC,
+	.bmAttributes =		DFU_BIT_WILL_DETACH |
+				DFU_BIT_MANIFESTATION_TOLERANT |
+				DFU_BIT_CAN_UPLOAD |
+				DFU_BIT_CAN_DNLOAD,
+	.wDetachTimeOut =	0,
+	.wTransferSize =	DFU_USB_BUFSIZ,
+	.bcdDFUVersion =	__constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_interface_descriptor dfu_intf_runtime = {
+	.bLength =		sizeof dfu_intf_runtime,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	.bNumEndpoints =	0,
+	.bInterfaceClass =	USB_CLASS_APP_SPEC,
+	.bInterfaceSubClass =	1,
+	.bInterfaceProtocol =	1,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_descriptor_header *dfu_runtime_descs[] = {
+	(struct usb_descriptor_header *) &dfu_intf_runtime,
+	NULL,
+};
+
+static struct usb_qualifier_descriptor dev_qualifier = {
+	.bLength =		sizeof dev_qualifier,
+	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
+	.bNumConfigurations =	1,
+};
+
+static const char dfu_name[] = "Device Firmware Upgrade";
+
+/*
+ * static strings, in UTF-8
+ *
+ * dfu_generic configuration
+ */
+static struct usb_string strings_dfu_generic[] = {
+	[0].s = dfu_name,
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab_dfu_generic = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_dfu_generic,
+};
+
+static struct usb_gadget_strings *dfu_generic_strings[] = {
+	&stringtab_dfu_generic,
+	NULL,
+};
+
+/*
+ * usb_function specific
+ */
+static struct usb_gadget_strings stringtab_dfu = {
+	.language	= 0x0409,	/* en-us */
+	/*
+	 * .strings
+	 *
+	 * assigned during initialization,
+	 * depends on number of flash entities
+	 *
+	 */
+};
+
+static struct usb_gadget_strings *dfu_strings[] = {
+	&stringtab_dfu,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
+		  req->length, f_dfu->blk_seq_num);
+
+	if (req->length == 0) {
+		puts("DOWNLOAD ... OK\n");
+		puts("Ctrl+C to exit ...\n");
+	}
+}
+
+static void handle_getstatus(struct usb_request *req)
+{
+	struct dfu_status *dstat = (struct dfu_status *)req->buf;
+	struct f_dfu *f_dfu = req->context;
+
+	switch (f_dfu->dfu_state) {
+	case DFU_STATE_dfuDNLOAD_SYNC:
+	case DFU_STATE_dfuDNBUSY:
+		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
+		break;
+	case DFU_STATE_dfuMANIFEST_SYNC:
+		break;
+	default:
+		break;
+	}
+
+	/* send status response */
+	dstat->bStatus = f_dfu->dfu_status;
+	dstat->bState = f_dfu->dfu_state;
+	dstat->iString = 0;
+}
+
+static void handle_getstate(struct usb_request *req)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	((u8 *)req->buf)[0] = f_dfu->dfu_state & 0xff;
+	req->actual = sizeof(u8);
+}
+
+static inline void to_dfu_mode(struct f_dfu *f_dfu)
+{
+	f_dfu->usb_function.strings = dfu_strings;
+	f_dfu->usb_function.hs_descriptors = f_dfu->function;
+}
+
+static inline void to_runtime_mode(struct f_dfu *f_dfu)
+{
+	f_dfu->usb_function.strings = NULL;
+	f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+}
+
+static int handle_upload(struct usb_request *req, u16 len)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	return dfu_read(dfu_get_entity(f_dfu->altsetting), req->buf,
+			req->length, f_dfu->blk_seq_num);
+}
+
+static int handle_dnload(struct usb_gadget *gadget, u16 len)
+{
+	struct usb_composite_dev *cdev = get_gadget_data(gadget);
+	struct usb_request *req = cdev->req;
+	struct f_dfu *f_dfu = req->context;
+
+	if (len == 0)
+		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
+
+	req->complete = dnload_request_complete;
+
+	return len;
+}
+
+/*-------------------------------------------------------------------------*/
+/* DFU state machine  */
+static int state_app_idle(struct f_dfu *f_dfu,
+			  const struct usb_ctrlrequest *ctrl,
+			  struct usb_gadget *gadget,
+			  struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	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:
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_app_detach(struct f_dfu *f_dfu,
+			    const struct usb_ctrlrequest *ctrl,
+			    struct usb_gadget *gadget,
+			    struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_appIDLE;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_idle(struct f_dfu *f_dfu,
+			  const struct usb_ctrlrequest *ctrl,
+			  struct usb_gadget *gadget,
+			  struct usb_request *req)
+{
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 len = le16_to_cpu(ctrl->wLength);
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_DNLOAD:
+		if (len == 0) {
+			f_dfu->dfu_state = DFU_STATE_dfuERROR;
+			value = RET_STALL;
+			break;
+		}
+		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
+		f_dfu->blk_seq_num = w_value;
+		value = handle_dnload(gadget, len);
+		break;
+	case USB_REQ_DFU_UPLOAD:
+		f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
+		f_dfu->blk_seq_num = 0;
+		value = handle_upload(req, len);
+		break;
+	case USB_REQ_DFU_ABORT:
+		/* no zlp? */
+		value = RET_ZLP;
+		break;
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	case USB_REQ_DFU_DETACH:
+		/*
+		 * Proprietary extension: 'detach' from idle mode and
+		 * get back to runtime mode in case of USB Reset.  As
+		 * much as I dislike this, we just can't use every USB
+		 * bus reset to switch back to runtime mode, since at
+		 * least the Linux USB stack likes to send a number of
+		 * resets in a row :(
+		 */
+		f_dfu->dfu_state =
+			DFU_STATE_dfuMANIFEST_WAIT_RST;
+		to_runtime_mode(f_dfu);
+		f_dfu->dfu_state = DFU_STATE_appIDLE;
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_dnload_sync(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_dnbusy(struct f_dfu *f_dfu,
+			    const struct usb_ctrlrequest *ctrl,
+			    struct usb_gadget *gadget,
+			    struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_dnload_idle(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 len = le16_to_cpu(ctrl->wLength);
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_DNLOAD:
+		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
+		f_dfu->blk_seq_num = w_value;
+		value = handle_dnload(gadget, len);
+		break;
+	case USB_REQ_DFU_ABORT:
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		value = RET_ZLP;
+		break;
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_manifest_sync(struct f_dfu *f_dfu,
+				   const struct usb_ctrlrequest *ctrl,
+				   struct usb_gadget *gadget,
+				   struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		/* We're MainfestationTolerant */
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		handle_getstatus(req);
+		f_dfu->blk_seq_num = 0;
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_upload_idle(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 len = le16_to_cpu(ctrl->wLength);
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_UPLOAD:
+		/* state transition if less data then requested */
+		f_dfu->blk_seq_num = w_value;
+		value = handle_upload(req, len);
+		if (value >= 0 && value < len)
+			f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		break;
+	case USB_REQ_DFU_ABORT:
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		/* no zlp? */
+		value = RET_ZLP;
+		break;
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_error(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	case USB_REQ_DFU_CLRSTATUS:
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		f_dfu->dfu_status = DFU_STATUS_OK;
+		/* no zlp? */
+		value = RET_ZLP;
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static dfu_state_fn dfu_state[] = {
+	state_app_idle,          /* DFU_STATE_appIDLE */
+	state_app_detach,        /* DFU_STATE_appDETACH */
+	state_dfu_idle,          /* DFU_STATE_dfuIDLE */
+	state_dfu_dnload_sync,   /* DFU_STATE_dfuDNLOAD_SYNC */
+	state_dfu_dnbusy,        /* DFU_STATE_dfuDNBUSY */
+	state_dfu_dnload_idle,   /* DFU_STATE_dfuDNLOAD_IDLE */
+	state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */
+	NULL,                    /* DFU_STATE_dfuMANIFEST */
+	NULL,                    /* DFU_STATE_dfuMANIFEST_WAIT_RST */
+	state_dfu_upload_idle,   /* DFU_STATE_dfuUPLOAD_IDLE */
+	state_dfu_error          /* DFU_STATE_dfuERROR */
+};
+
+static int
+dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct usb_gadget *gadget = f->config->cdev->gadget;
+	struct usb_request *req = f->config->cdev->req;
+	struct f_dfu *f_dfu = f->config->cdev->req->context;
+	u16 len = le16_to_cpu(ctrl->wLength);
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	int value = 0;
+	u8 req_type = ctrl->bRequestType & USB_TYPE_MASK;
+
+	debug("w_value: 0x%x len: 0x%x\n", w_value, len);
+	debug("req_type: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n",
+	       req_type, ctrl->bRequest, f_dfu->dfu_state);
+
+	if (req_type == USB_TYPE_STANDARD) {
+		if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR &&
+		    (w_value >> 8) == DFU_DT_FUNC) {
+			value = min(len, (u16) sizeof(dfu_func));
+			memcpy(req->buf, &dfu_func, value);
+		}
+	} else /* DFU specific request */
+		value = dfu_state[f_dfu->dfu_state] (f_dfu, ctrl, gadget, req);
+
+	if (value >= 0) {
+		req->length = value;
+		req->zero = value < len;
+		value = usb_ep_queue(gadget->ep0, req, 0);
+		if (value < 0) {
+			debug("ep_queue --> %d\n", value);
+			req->status = 0;
+		}
+	}
+
+	return value;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+dfu_prepare_strings(struct f_dfu *f_dfu, int n)
+{
+	struct dfu_entity *de = NULL;
+	int i = 0;
+
+	f_dfu->strings = calloc(sizeof(struct usb_string), n + 1);
+	if (!f_dfu->strings)
+		goto enomem;
+
+	for (i = 0; i < n; ++i) {
+		de = dfu_get_entity(i);
+		f_dfu->strings[i].s = de->name;
+	}
+
+	f_dfu->strings[i].id = 0;
+	f_dfu->strings[i].s = NULL;
+
+	return 0;
+
+enomem:
+	while (i)
+		f_dfu->strings[--i].s = NULL;
+
+	free(f_dfu->strings);
+
+	return -ENOMEM;
+}
+
+static int dfu_prepare_function(struct f_dfu *f_dfu, int n)
+{
+	struct usb_interface_descriptor *d;
+	int i = 0;
+
+	f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n);
+	if (!f_dfu->function)
+		goto enomem;
+
+	for (i = 0; i < n; ++i) {
+		d = calloc(sizeof(*d), 1);
+		if (!d)
+			goto enomem;
+
+		d->bLength =		sizeof(*d);
+		d->bDescriptorType =	USB_DT_INTERFACE;
+		d->bAlternateSetting =	i;
+		d->bNumEndpoints =	0;
+		d->bInterfaceClass =	USB_CLASS_APP_SPEC;
+		d->bInterfaceSubClass =	1;
+		d->bInterfaceProtocol =	2;
+
+		f_dfu->function[i] = (struct usb_descriptor_header *)d;
+	}
+	f_dfu->function[i] = NULL;
+
+	return 0;
+
+enomem:
+	while (i) {
+		free(f_dfu->function[--i]);
+		f_dfu->function[i] = NULL;
+	}
+	free(f_dfu->function);
+
+	return -ENOMEM;
+}
+
+static int dfu_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	int alt_num = dfu_get_alt_number();
+	int rv, id, i;
+
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	dfu_intf_runtime.bInterfaceNumber = id;
+
+	f_dfu->dfu_state = DFU_STATE_appIDLE;
+	f_dfu->dfu_status = DFU_STATUS_OK;
+
+	rv = dfu_prepare_function(f_dfu, alt_num);
+	if (rv)
+		goto error;
+
+	rv = dfu_prepare_strings(f_dfu, alt_num);
+	if (rv)
+		goto error;
+	for (i = 0; i < alt_num; i++) {
+		id = usb_string_id(cdev);
+		if (id < 0)
+			return id;
+		f_dfu->strings[i].id = id;
+		((struct usb_interface_descriptor *)f_dfu->function[i])
+			->iInterface = id;
+	}
+
+	stringtab_dfu.strings = f_dfu->strings;
+
+	cdev->req->context = f_dfu;
+
+error:
+	return rv;
+}
+
+static void dfu_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	int alt_num = dfu_get_alt_number();
+	int i;
+
+	if (f_dfu->strings) {
+		i = alt_num;
+		while (i)
+			f_dfu->strings[--i].s = NULL;
+
+		free(f_dfu->strings);
+	}
+
+	if (f_dfu->function) {
+		i = alt_num;
+		while (i) {
+			free(f_dfu->function[--i]);
+			f_dfu->function[i] = NULL;
+		}
+		free(f_dfu->function);
+	}
+
+	free(f_dfu);
+}
+
+static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+
+	debug("%s: intf:%d alt:%d\n", __func__, intf, alt);
+
+	f_dfu->altsetting = alt;
+
+	return 0;
+}
+
+/* TODO: is this really what we need here? */
+static void dfu_disable(struct usb_function *f)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	if (f_dfu->config == 0)
+		return;
+
+	debug("%s: reset config\n", __func__);
+
+	f_dfu->config = 0;
+}
+
+static int dfu_bind_config(struct usb_configuration *c)
+{
+	struct f_dfu *f_dfu;
+	int status;
+
+	f_dfu = calloc(sizeof(*f_dfu), 1);
+	if (!f_dfu)
+		return -ENOMEM;
+	f_dfu->usb_function.name = "dfu";
+	f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+	f_dfu->usb_function.bind = dfu_bind;
+	f_dfu->usb_function.unbind = dfu_unbind;
+	f_dfu->usb_function.set_alt = dfu_set_alt;
+	f_dfu->usb_function.disable = dfu_disable;
+	f_dfu->usb_function.strings = dfu_generic_strings,
+	f_dfu->usb_function.setup = dfu_handle,
+
+	status = usb_add_function(c, &f_dfu->usb_function);
+	if (status)
+		free(f_dfu);
+
+	return status;
+}
+
+int dfu_add(struct usb_configuration *c)
+{
+	int id;
+
+	id = usb_string_id(c->cdev);
+	if (id < 0)
+		return id;
+	strings_dfu_generic[0].id = id;
+	dfu_intf_runtime.iInterface = id;
+
+	debug("%s: cdev: 0x%p gadget:0x%p gadget->ep0: 0x%p\n", __func__,
+	       c->cdev, c->cdev->gadget, c->cdev->gadget->ep0);
+
+	return dfu_bind_config(c);
+}
diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h
new file mode 100644
index 0000000..023e1ad
--- /dev/null
+++ b/drivers/usb/gadget/f_dfu.h
@@ -0,0 +1,100 @@
+/*
+ * f_dfu.h -- Device Firmware Update gadget
+ *
+ * Copyright (C) 2011-2012 Samsung Electronics
+ * author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __F_DFU_H_
+#define __F_DFU_H_
+
+#include <linux/compiler.h>
+#include <linux/usb/composite.h>
+
+#define DFU_CONFIG_VAL			1
+#define DFU_DT_FUNC			0x21
+
+#define DFU_BIT_WILL_DETACH		(0x1 << 3)
+#define DFU_BIT_MANIFESTATION_TOLERANT	(0x1 << 2)
+#define DFU_BIT_CAN_UPLOAD		(0x1 << 1)
+#define DFU_BIT_CAN_DNLOAD		0x1
+
+/* big enough to hold our biggest descriptor */
+#define DFU_USB_BUFSIZ			4096
+
+#define USB_REQ_DFU_DETACH		0x00
+#define USB_REQ_DFU_DNLOAD		0x01
+#define USB_REQ_DFU_UPLOAD		0x02
+#define USB_REQ_DFU_GETSTATUS		0x03
+#define USB_REQ_DFU_CLRSTATUS		0x04
+#define USB_REQ_DFU_GETSTATE		0x05
+#define USB_REQ_DFU_ABORT		0x06
+
+#define DFU_STATUS_OK			0x00
+#define DFU_STATUS_errTARGET		0x01
+#define DFU_STATUS_errFILE		0x02
+#define DFU_STATUS_errWRITE		0x03
+#define DFU_STATUS_errERASE		0x04
+#define DFU_STATUS_errCHECK_ERASED	0x05
+#define DFU_STATUS_errPROG		0x06
+#define DFU_STATUS_errVERIFY		0x07
+#define DFU_STATUS_errADDRESS		0x08
+#define DFU_STATUS_errNOTDONE		0x09
+#define DFU_STATUS_errFIRMWARE		0x0a
+#define DFU_STATUS_errVENDOR		0x0b
+#define DFU_STATUS_errUSBR		0x0c
+#define DFU_STATUS_errPOR		0x0d
+#define DFU_STATUS_errUNKNOWN		0x0e
+#define DFU_STATUS_errSTALLEDPKT	0x0f
+
+#define RET_STALL			-1
+#define RET_ZLP				0
+#define RET_STAT_LEN			6
+
+enum dfu_state {
+	DFU_STATE_appIDLE		= 0,
+	DFU_STATE_appDETACH		= 1,
+	DFU_STATE_dfuIDLE		= 2,
+	DFU_STATE_dfuDNLOAD_SYNC	= 3,
+	DFU_STATE_dfuDNBUSY		= 4,
+	DFU_STATE_dfuDNLOAD_IDLE	= 5,
+	DFU_STATE_dfuMANIFEST_SYNC	= 6,
+	DFU_STATE_dfuMANIFEST		= 7,
+	DFU_STATE_dfuMANIFEST_WAIT_RST	= 8,
+	DFU_STATE_dfuUPLOAD_IDLE	= 9,
+	DFU_STATE_dfuERROR		= 10,
+};
+
+struct dfu_status {
+	__u8				bStatus;
+	__u8				bwPollTimeout[3];
+	__u8				bState;
+	__u8				iString;
+} __packed;
+
+struct dfu_function_descriptor {
+	__u8				bLength;
+	__u8				bDescriptorType;
+	__u8				bmAttributes;
+	__le16				wDetachTimeOut;
+	__le16				wTransferSize;
+	__le16				bcdDFUVersion;
+} __packed;
+
+/* configuration-specific linkup */
+int dfu_add(struct usb_configuration *c);
+#endif /* __F_DFU_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 3/7] dfu: DFU backend implementation
  2012-07-31  6:36 ` [U-Boot] [PATCH v3 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
  2012-07-31  6:36   ` [U-Boot] [PATCH v3 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
  2012-07-31  6:36   ` [U-Boot] [PATCH v3 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
@ 2012-07-31  6:36   ` Lukasz Majewski
  2012-08-01 22:57     ` Mike Frysinger
  2012-07-31  6:37   ` [U-Boot] [PATCH v3 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
                     ` (3 subsequent siblings)
  6 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-31  6:36 UTC (permalink / raw)
  To: u-boot

New, separate driver at ./drivers/dfu has been added. It allows platform
and storage independent operation of DFU.
It has been extended to use new MMC level of command abstraction.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:
- None

Changes for v3:
- Remove unnecessary NULL and 0 initialization of dynamic variables
- Combine two puts to one
- Adding const qualifier to device and layout definitions
- Remove unnecessary casting at dfu->name passing
- Provide more meaningful names for dfu layouts and device types
- Removal of dfu_extract_{token|entity} functions and replace them
  with strsep calls
---
 Makefile             |    1 +
 drivers/dfu/Makefile |   43 +++++++++
 drivers/dfu/dfu.c    |  237 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/dfu.h        |  103 ++++++++++++++++++++++
 4 files changed, 384 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dfu/Makefile
 create mode 100644 drivers/dfu/dfu.c
 create mode 100644 include/dfu.h

diff --git a/Makefile b/Makefile
index d57c15e..bd469f4 100644
--- a/Makefile
+++ b/Makefile
@@ -271,6 +271,7 @@ LIBS += drivers/pci/libpci.o
 LIBS += drivers/pcmcia/libpcmcia.o
 LIBS += drivers/power/libpower.o
 LIBS += drivers/spi/libspi.o
+LIBS += drivers/dfu/libdfu.o
 ifeq ($(CPU),mpc83xx)
 LIBS += drivers/qe/libqe.o
 LIBS += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o
diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
new file mode 100644
index 0000000..7736485
--- /dev/null
+++ b/drivers/dfu/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2012 Samsung Electronics
+# Lukasz Majewski <l.majewski@samsung.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)libdfu.o
+
+COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
+
+SRCS    := $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
new file mode 100644
index 0000000..8f48b49
--- /dev/null
+++ b/drivers/dfu/dfu.c
@@ -0,0 +1,237 @@
+/*
+ * dfu.c -- DFU back-end routines
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * author: Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <fat.h>
+#include <dfu.h>
+#include <linux/list.h>
+#include <linux/compiler.h>
+
+static LIST_HEAD(dfu_list);
+static int dfu_alt_num;
+
+static int dfu_find_alt_num(char *s)
+{
+	int i = 0;
+
+	for (; *s; s++)
+		if (*s == ';')
+			i++;
+
+	return ++i;
+}
+
+static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
+				     dfu_buf[DFU_DATA_BUF_SIZE];
+
+int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
+{
+	static unsigned char *i_buf;
+	static int i_blk_seq_num;
+	long w_size = 0;
+	int ret = 0;
+
+	debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
+	       __func__, dfu->name, buf, size, blk_seq_num, i_buf);
+
+	if (blk_seq_num == 0) {
+		memset(dfu_buf, '\0', sizeof(dfu_buf));
+		i_buf = dfu_buf;
+		i_blk_seq_num = 0;
+	}
+
+	if (i_blk_seq_num++ != blk_seq_num) {
+		printf("%s: Wrong sequence number! [%d] [%d]\n",
+		       __func__, i_blk_seq_num, blk_seq_num);
+		return -1;
+	}
+
+	memcpy(i_buf, buf, size);
+	i_buf += size;
+
+	if (size == 0) {
+		/* Integrity check (if needed) */
+		debug("%s: %s %d [B] CRC32: 0x%x\n", __func__, dfu->name,
+		       i_buf - dfu_buf, crc32(0, dfu_buf, i_buf - dfu_buf));
+
+		w_size = i_buf - dfu_buf;
+		ret = dfu->write_medium(dfu, dfu_buf, &w_size);
+		if (ret)
+			debug("%s: Write error!\n", __func__);
+
+		i_blk_seq_num = 0;
+		i_buf = NULL;
+		return ret;
+	}
+
+	return ret;
+}
+
+int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
+{
+	static unsigned char *i_buf;
+	static int i_blk_seq_num;
+	static long r_size;
+	static u32 crc;
+	int ret = 0;
+
+	debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
+	       __func__, dfu->name, buf, size, blk_seq_num, i_buf);
+
+	if (blk_seq_num == 0) {
+		i_buf = dfu_buf;
+		memset(dfu_buf, '\0', sizeof(dfu_buf));
+		ret = dfu->read_medium(dfu, i_buf, &r_size);
+		debug("%s: %s %ld [B]\n", __func__, dfu->name, r_size);
+		i_blk_seq_num = 0;
+		/* Integrity check (if needed) */
+		crc = crc32(0, dfu_buf, r_size);
+	}
+
+	if (i_blk_seq_num++ != blk_seq_num) {
+		printf("%s: Wrong sequence number! [%d] [%d]\n",
+		       __func__, i_blk_seq_num, blk_seq_num);
+		return -1;
+	}
+
+	if (r_size >= size) {
+		memcpy(buf, i_buf, size);
+		i_buf += size;
+		r_size -= size;
+		return size;
+	} else {
+		memcpy(buf, i_buf, r_size);
+		i_buf += r_size;
+		debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name, crc);
+		puts("UPLOAD ... done\nCtrl+C to exit ...\n");
+
+		i_buf = NULL;
+		i_blk_seq_num = 0;
+		crc = 0;
+		return r_size;
+	}
+	return ret;
+}
+
+static int dfu_fill_entity(struct dfu_entity *dfu, char* s, int alt,
+			    char *interface, int num)
+{
+	char *st;
+
+	debug("%s: %s interface: %s num: %d\n", __func__, s, interface, num);
+	st = strsep(&s, " ");
+	strcpy(dfu->name, st);
+
+	dfu->dev_num = num;
+	dfu->alt = alt;
+
+	/* Specific for mmc device */
+	if (strcmp(interface, "mmc") == 0) {
+		if (dfu_fill_entity_mmc(dfu, s))
+			return -1;
+	} else {
+		printf("%s: Device %s not (yet) supported!\n",
+		       __func__,  interface);
+		return -1;
+	}
+
+	return 0;
+}
+
+int dfu_config_entities(char *env, char *interface, int num)
+{
+	struct dfu_entity *dfu;
+	int i, ret;
+	char *s;
+
+	dfu_alt_num = dfu_find_alt_num(env);
+	debug("%s: dfu_alt_num=%d\n", __func__, dfu_alt_num);
+
+	for (i = 0; i < dfu_alt_num; i++) {
+		dfu = calloc(sizeof(struct dfu_entity), 1);
+
+		s = strsep(&env, ";");
+		ret = dfu_fill_entity(dfu, s, i, interface, num);
+		if (ret)
+			return -1;
+
+		list_add_tail(&dfu->list, &dfu_list);
+	}
+
+	return 0;
+}
+
+void dfu_free_entities(void)
+{
+	struct dfu_entity *dfu, *p;
+
+	list_for_each_entry_safe_reverse(dfu, p, &dfu_list, list) {
+		list_del(&dfu->list);
+		free(dfu);
+	}
+
+	INIT_LIST_HEAD(&dfu_list);
+}
+
+const char *dfu_get_dev_type(enum dfu_device_type t)
+{
+	const char *dev_t[] = {NULL, "eMMC", "OneNAND", "NAND" };
+	return dev_t[t];
+}
+
+const char *dfu_get_layout(enum dfu_layout l)
+{
+	const char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2",
+					   "EXT3", "EXT4" };
+	return dfu_layout[l];
+}
+
+void dfu_show_entities(void)
+{
+	struct dfu_entity *dfu;
+
+	puts("DFU alt settings list:\n");
+
+	list_for_each_entry(dfu, &dfu_list, list) {
+		printf("dev: %s alt: %d name: %s layout: %s\n",
+		       dfu_get_dev_type(dfu->dev_type), dfu->alt,
+		       dfu->name, dfu_get_layout(dfu->layout));
+	}
+}
+
+int dfu_get_alt_number(void)
+{
+	return dfu_alt_num;
+}
+
+struct dfu_entity *dfu_get_entity(int alt)
+{
+	struct dfu_entity *dfu;
+
+	list_for_each_entry(dfu, &dfu_list, list) {
+		if (dfu->alt == alt)
+			return dfu;
+	}
+
+	return NULL;
+}
diff --git a/include/dfu.h b/include/dfu.h
new file mode 100644
index 0000000..d908f18
--- /dev/null
+++ b/include/dfu.h
@@ -0,0 +1,103 @@
+/*
+ * dfu.h - DFU flashable area description
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __DFU_ENTITY_H_
+#define __DFU_ENTITY_H_
+
+#include <common.h>
+#include <linux/list.h>
+#include <mmc.h>
+
+enum dfu_device_type {
+	DFU_DEV_MMC = 1,
+	DFU_DEV_ONENAND,
+	DFU_DEV_NAND,
+};
+
+enum dfu_layout {
+	DFU_RAW_ADDR = 1,
+	DFU_FS_FAT,
+	DFU_FS_EXT2,
+	DFU_FS_EXT3,
+	DFU_FS_EXT4,
+};
+
+struct mmc_internal_data {
+	/* RAW programming */
+	unsigned int lba_start;
+	unsigned int lba_size;
+	unsigned int lba_blk_size;
+
+	/* FAT/EXT */
+	unsigned int dev;
+	unsigned int part;
+};
+
+static inline unsigned int get_mmc_blk_size(int dev)
+{
+	return find_mmc_device(dev)->read_bl_len;
+}
+
+#define DFU_NAME_SIZE 32
+#define DFU_CMD_BUF_SIZE 128
+#define DFU_DATA_BUF_SIZE (1024*1024*4) /* 4 MiB */
+
+struct dfu_entity {
+	char			name[DFU_NAME_SIZE];
+	int                     alt;
+	void                    *dev_private;
+	int                     dev_num;
+	enum dfu_device_type    dev_type;
+	enum dfu_layout         layout;
+
+	union {
+		struct mmc_internal_data mmc;
+	} data;
+
+	int (*read_medium)(struct dfu_entity *dfu, void *buf, long *len);
+	int (*write_medium)(struct dfu_entity *dfu, void *buf, long *len);
+
+	struct list_head list;
+};
+
+int dfu_config_entities(char *s, char *interface, int num);
+void dfu_free_entities(void);
+void dfu_show_entities(void);
+int dfu_get_alt_number(void);
+const char *dfu_get_dev_type(enum dfu_device_type t);
+const char *dfu_get_layout(enum dfu_layout l);
+struct dfu_entity *dfu_get_entity(int alt);
+char *dfu_extract_token(char** e, int *n);
+
+int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
+int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
+/* Device specific */
+#ifdef CONFIG_DFU_MMC
+extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s);
+#else
+static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s)
+{
+	puts("MMC support not available!\n");
+	return -1;
+}
+#endif
+#endif /* __DFU_ENTITY_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 4/7] dfu: MMC specific routines for DFU operation
  2012-07-31  6:36 ` [U-Boot] [PATCH v3 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                     ` (2 preceding siblings ...)
  2012-07-31  6:36   ` [U-Boot] [PATCH v3 3/7] dfu: DFU backend implementation Lukasz Majewski
@ 2012-07-31  6:37   ` Lukasz Majewski
  2012-08-01 23:00     ` Mike Frysinger
  2012-07-31  6:37   ` [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
                     ` (2 subsequent siblings)
  6 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-31  6:37 UTC (permalink / raw)
  To: u-boot

Support for MMC storage devices to work with DFU framework.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:
- None

Changes for v3:
- Provide special abstraction layer (mmc_{block|file}_{read|write})
  to alleviate switch to new device model (DM)
- More verbose messages when not supported layout encountered
- Calls to strncmp() replaced with strcmp()
---
 drivers/dfu/Makefile  |    1 +
 drivers/dfu/dfu_mmc.c |  165 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 166 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dfu/dfu_mmc.c

diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
index 7736485..7b717bc 100644
--- a/drivers/dfu/Makefile
+++ b/drivers/dfu/Makefile
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)libdfu.o
 
 COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
+COBJS-$(CONFIG_DFU_MMC) += dfu_mmc.o
 
 SRCS    := $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS-y))
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
new file mode 100644
index 0000000..3909910
--- /dev/null
+++ b/drivers/dfu/dfu_mmc.c
@@ -0,0 +1,165 @@
+/*
+ * dfu.c -- DFU back-end routines
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * author: Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <dfu.h>
+
+enum dfu_mmc_op {
+	DFU_OP_READ = 1,
+	DFU_OP_WRITE,
+};
+
+static int mmc_block_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
+			void *buf, long *len)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf, DFU_CMD_BUF_SIZE);
+	memset(cmd_buf, '\0', sizeof(cmd_buf));
+
+	sprintf(cmd_buf, "mmc %s 0x%x %x %x",
+		op == DFU_OP_READ ? "read" : "write",
+		(unsigned int) buf,
+		dfu->data.mmc.lba_start,
+		dfu->data.mmc.lba_size);
+
+	if (op == DFU_OP_READ)
+		*len = dfu->data.mmc.lba_blk_size * dfu->data.mmc.lba_size;
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+	return run_command(cmd_buf, 0);
+}
+
+static inline int mmc_block_write(struct dfu_entity *dfu, void *buf, long *len)
+{
+	return mmc_block_op(DFU_OP_WRITE, dfu, buf, len);
+}
+
+static inline int mmc_block_read(struct dfu_entity *dfu, void *buf, long *len)
+{
+	return mmc_block_op(DFU_OP_READ, dfu, buf, len);
+}
+
+static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
+			void *buf, long *len)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf, DFU_CMD_BUF_SIZE);
+	char *str_env;
+	int ret;
+
+	memset(cmd_buf, '\0', sizeof(cmd_buf));
+
+	sprintf(cmd_buf, "fat%s mmc %d:%d 0x%x %s %lx",
+		op == DFU_OP_READ ? "load" : "write",
+		dfu->data.mmc.dev, dfu->data.mmc.part,
+		(unsigned int) buf, dfu->name, *len);
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+
+	ret = run_command(cmd_buf, 0);
+	if (ret) {
+		puts("dfu: Read error!\n");
+		return ret;
+	}
+
+	if (dfu->layout != DFU_RAW_ADDR) {
+		str_env = getenv("filesize");
+		if (str_env == NULL) {
+			puts("dfu: Wrong file size!\n");
+			return -1;
+		}
+		*len = simple_strtoul(str_env, NULL, 16);
+	}
+
+	return ret;
+}
+
+static inline int mmc_file_write(struct dfu_entity *dfu, void *buf, long *len)
+{
+	return mmc_file_op(DFU_OP_WRITE, dfu, buf, len);
+}
+
+static inline int mmc_file_read(struct dfu_entity *dfu, void *buf, long *len)
+{
+	return mmc_file_op(DFU_OP_READ, dfu, buf, len);
+}
+
+int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
+{
+	int ret = -1;
+
+	switch (dfu->layout) {
+	case DFU_RAW_ADDR:
+		ret = mmc_block_write(dfu, buf, len);
+		break;
+	case DFU_FS_FAT:
+		ret = mmc_file_write(dfu, buf, len);
+		break;
+	default:
+		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
+		       dfu_get_layout(dfu->layout));
+	}
+
+	return ret;
+}
+
+int dfu_read_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
+{
+	int ret = -1;
+
+	switch (dfu->layout) {
+	case DFU_RAW_ADDR:
+		ret = mmc_block_read(dfu, buf, len);
+		break;
+	case DFU_FS_FAT:
+		ret = mmc_file_read(dfu, buf, len);
+		break;
+	default:
+		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
+		       dfu_get_layout(dfu->layout));
+	}
+
+	return ret;
+}
+
+int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s)
+{
+	char *st;
+
+	dfu->dev_type = DFU_DEV_MMC;
+	st = strsep(&s, " ");
+	if (!strcmp(st, "mmc")) {
+		dfu->layout = DFU_RAW_ADDR;
+		dfu->data.mmc.lba_start = simple_strtoul(s, &s, 16);
+		dfu->data.mmc.lba_size = simple_strtoul(++s, &s, 16);
+		dfu->data.mmc.lba_blk_size = get_mmc_blk_size(dfu->dev_num);
+	} else if (!strcmp(st, "fat")) {
+		dfu->layout = DFU_FS_FAT;
+		dfu->data.mmc.dev = simple_strtoul(s, &s, 10);
+		dfu->data.mmc.part = simple_strtoul(++s, &s, 10);
+	} else {
+		printf("%s: Memory layout (%s) not supported!\n", __func__, st);
+	}
+
+	dfu->read_medium = dfu_read_medium_mmc;
+	dfu->write_medium = dfu_write_medium_mmc;
+
+	return 0;
+}
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-31  6:36 ` [U-Boot] [PATCH v3 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                     ` (3 preceding siblings ...)
  2012-07-31  6:37   ` [U-Boot] [PATCH v3 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
@ 2012-07-31  6:37   ` Lukasz Majewski
  2012-07-31 17:14     ` Stephen Warren
  2012-08-01 18:04     ` Mike Frysinger
  2012-07-31  6:37   ` [U-Boot] [PATCH v3 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
  2012-07-31  6:37   ` [U-Boot] [PATCH v3 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
  6 siblings, 2 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-31  6:37 UTC (permalink / raw)
  To: u-boot

Support for u-boot's "dfu <interface> <dev> [list]" command.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:
- None

Changes for v3:
- Remove unnecessary initialization to NULL of dynamic variables
- goto done added to reduce code duplication
- static definition of do_dfu()
---
 common/Makefile  |    1 +
 common/cmd_dfu.c |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+), 0 deletions(-)
 create mode 100644 common/cmd_dfu.c

diff --git a/common/Makefile b/common/Makefile
index 483eb4d..32d44e5 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -183,6 +183,7 @@ COBJS-$(CONFIG_MENU) += menu.o
 COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o
 COBJS-$(CONFIG_UPDATE_TFTP) += update.o
 COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
+COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o
 endif
 
 ifdef CONFIG_SPL_BUILD
diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
new file mode 100644
index 0000000..72efb60
--- /dev/null
+++ b/common/cmd_dfu.c
@@ -0,0 +1,81 @@
+/*
+ * cmd_dfu.c -- dfu command
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <dfu.h>
+#include <asm/errno.h>
+#include <g_dnl.h>
+
+static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	static char *s = "dfu";
+	const char *str_env;
+	char *env_bkp;
+	int ret;
+
+	if (argc < 3)
+		return CMD_RET_USAGE;
+
+	str_env = getenv("dfu_alt_info");
+	if (str_env == NULL) {
+		printf("%s: \"dfu_alt_info\" env variable not defined!\n",
+		       __func__);
+		return CMD_RET_FAILURE;
+	}
+
+	env_bkp = strdup(str_env);
+	ret = dfu_config_entities(env_bkp, argv[1],
+			    (int)simple_strtoul(argv[2], NULL, 10));
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	if (strcmp(argv[3], "list") == 0) {
+		dfu_show_entities();
+		goto done;
+	}
+
+	board_usb_init();
+	g_dnl_register(s);
+	while (1) {
+		if (ctrlc())
+			goto exit;
+
+		usb_gadget_handle_interrupts();
+	}
+exit:
+	g_dnl_unregister();
+done:
+	dfu_free_entities();
+	free(env_bkp);
+
+	return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu,
+	"Device Firmware Upgrade",
+	"<interface> <dev> [list]\n"
+	"  - device firmware upgrade on a device <dev>\n"
+	"    attached to interface <interface>\n"
+	"    [list] - list available alt settings"
+);
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 6/7] arm:trats: Support for USB UDC driver at TRATS board.
  2012-07-31  6:36 ` [U-Boot] [PATCH v3 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                     ` (4 preceding siblings ...)
  2012-07-31  6:37   ` [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
@ 2012-07-31  6:37   ` Lukasz Majewski
  2012-07-31  8:31     ` Minkyu Kang
  2012-07-31  6:37   ` [U-Boot] [PATCH v3 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
  6 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-31  6:37 UTC (permalink / raw)
  To: u-boot

Support for USB UDC driver at trats board.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Minkyu Kang <mk7.kang@samsung.com>

---
Changes for v2:
- replace puts to debug
---
 board/samsung/trats/trats.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/board/samsung/trats/trats.c b/board/samsung/trats/trats.c
index a8b2b11..4f9cb5a 100644
--- a/board/samsung/trats/trats.c
+++ b/board/samsung/trats/trats.c
@@ -59,6 +59,8 @@ static int hwrevision(int rev)
 	return (board_rev & 0xf) == rev;
 }
 
+struct s3c_plat_otg_data s5pc210_otg_data;
+
 int board_init(void)
 {
 	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
@@ -259,6 +261,12 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
 	.usb_phy_ctrl	= EXYNOS4_USBPHY_CONTROL,
 	.usb_flags	= PHY0_SLEEP,
 };
+
+void board_usb_init(void)
+{
+	debug("USB_udc_probe\n");
+	s3c_udc_probe(&s5pc210_otg_data);
+}
 #endif
 
 static void pmic_reset(void)
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS
  2012-07-31  6:36 ` [U-Boot] [PATCH v3 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                     ` (5 preceding siblings ...)
  2012-07-31  6:37   ` [U-Boot] [PATCH v3 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
@ 2012-07-31  6:37   ` Lukasz Majewski
  2012-07-31  8:32     ` Minkyu Kang
  6 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-07-31  6:37 UTC (permalink / raw)
  To: u-boot

Enable the g_dnl composite USB gadget driver with embedded DFU function on it.
It now uses the composite gadget framework to support download specific
USB functions (like enabled DFU or USB Mass Storage).

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Minkyu Kang <mk7.kang@samsung.com>

---
Change for v2:
- Move the G_DNL_{VENDOR_NUM, PRODUCT_NUM and MANUFACTURER} definitions to
  ./include/configs/<board>.h

Changes for v3:
- None
---
 include/configs/trats.h |   24 +++++++++++++++++++++++-
 1 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/include/configs/trats.h b/include/configs/trats.h
index eb269b2..75a23b0 100644
--- a/include/configs/trats.h
+++ b/include/configs/trats.h
@@ -94,6 +94,21 @@
 #undef CONFIG_CMD_ONENAND
 #undef CONFIG_CMD_MTDPARTS
 #define CONFIG_CMD_MMC
+#define CONFIG_CMD_DFU
+
+/* FAT */
+#define CONFIG_CMD_FAT
+#define CONFIG_FAT_WRITE
+
+/* USB Composite download gadget - g_dnl */
+#define CONFIG_USBDOWNLOAD_GADGET
+#define CONFIG_DFU_FUNCTION
+#define CONFIG_DFU_MMC
+
+/* USB Samsung's IDs */
+#define CONFIG_G_DNL_VENDOR_NUM 0x04E8
+#define CONFIG_G_DNL_PRODUCT_NUM 0x6601
+#define CONFIG_G_DNL_MANUFACTURER "Samsung"
 
 #define CONFIG_BOOTDELAY		1
 #define CONFIG_ZERO_BOOTDELAY_CHECK
@@ -104,6 +119,11 @@
 #define CONFIG_BOOTBLOCK		"10"
 #define CONFIG_ENV_COMMON_BOOT		"${console} ${meminfo}"
 
+#define CONFIG_DFU_ALT \
+	"dfu_alt_info=" \
+	"u-boot mmc 80 400;" \
+	"uImage fat 0 2\0" \
+
 #define CONFIG_ENV_OVERWRITE
 #define CONFIG_SYS_CONSOLE_INFO_QUIET
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
@@ -146,7 +166,8 @@
 	"mmcdev=0\0" \
 	"mmcbootpart=2\0" \
 	"mmcrootpart=3\0" \
-	"opts=always_resume=1"
+	"opts=always_resume=1\0" \
+	CONFIG_DFU_ALT
 
 /* Miscellaneous configurable options */
 #define CONFIG_SYS_LONGHELP		/* undef to save memory */
@@ -209,6 +230,7 @@
 #define CONFIG_USB_GADGET
 #define CONFIG_USB_GADGET_S3C_UDC_OTG
 #define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_GADGET_VBUS_DRAW	2
 
 /* LCD */
 #define CONFIG_EXYNOS_FB
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 6/7] arm:trats: Support for USB UDC driver at TRATS board.
  2012-07-31  6:37   ` [U-Boot] [PATCH v3 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
@ 2012-07-31  8:31     ` Minkyu Kang
  0 siblings, 0 replies; 147+ messages in thread
From: Minkyu Kang @ 2012-07-31  8:31 UTC (permalink / raw)
  To: u-boot

On 31 July 2012 15:37, Lukasz Majewski <l.majewski@samsung.com> wrote:
> Support for USB UDC driver at trats board.
>
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> Cc: Minkyu Kang <mk7.kang@samsung.com>
>
> ---
> Changes for v2:
> - replace puts to debug
> ---
>  board/samsung/trats/trats.c |    8 ++++++++
>  1 files changed, 8 insertions(+), 0 deletions(-)
>

Acked-by: Minkyu Kang <mk7.kang@samsung.com>

Thanks.
Minkyu Kang.
-- 
from. prom.
www.promsoft.net

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS
  2012-07-31  6:37   ` [U-Boot] [PATCH v3 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
@ 2012-07-31  8:32     ` Minkyu Kang
  0 siblings, 0 replies; 147+ messages in thread
From: Minkyu Kang @ 2012-07-31  8:32 UTC (permalink / raw)
  To: u-boot

On 31 July 2012 15:37, Lukasz Majewski <l.majewski@samsung.com> wrote:
> Enable the g_dnl composite USB gadget driver with embedded DFU function on it.
> It now uses the composite gadget framework to support download specific
> USB functions (like enabled DFU or USB Mass Storage).
>
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> Cc: Minkyu Kang <mk7.kang@samsung.com>
>
> ---
> Change for v2:
> - Move the G_DNL_{VENDOR_NUM, PRODUCT_NUM and MANUFACTURER} definitions to
>   ./include/configs/<board>.h
>
> Changes for v3:
> - None
> ---
>  include/configs/trats.h |   24 +++++++++++++++++++++++-
>  1 files changed, 23 insertions(+), 1 deletions(-)
>

Acked-by: Minkyu Kang <mk7.kang@samsung.com>

Thanks.
Minkyu Kang.
-- 
from. prom.
www.promsoft.net

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-31  6:37   ` [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
@ 2012-07-31 17:14     ` Stephen Warren
  2012-08-01  7:16       ` Lukasz Majewski
  2012-08-01 18:04     ` Mike Frysinger
  1 sibling, 1 reply; 147+ messages in thread
From: Stephen Warren @ 2012-07-31 17:14 UTC (permalink / raw)
  To: u-boot

On 07/31/2012 12:37 AM, Lukasz Majewski wrote:
> Support for u-boot's "dfu <interface> <dev> [list]" command.

> +U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu,
> +	"Device Firmware Upgrade",
> +	"<interface> <dev> [list]\n"
> +	"  - device firmware upgrade on a device <dev>\n"
> +	"    attached to interface <interface>\n"
> +	"    [list] - list available alt settings"
> +);

Hmm. Is there any way to make this work without specifying "interface
dev", or to allow specifying multiple "interface dev" entries? On a
system with all of eMMC, NAND, and SPI, I'd like to just run "dfu" as
the U-Boot command, and have the host specify which of those "devices"
it wants to download to using the DFU protocol. So, if flashing a bunch
of devices, there is no need to interact with U-Boot over both serial
and USB in order to invoke the dfu command multiple times.

Somewhat related to this, it looks like the eMMC support doesn't allow
the HW partition to be specified; it would be nice to expose alt
settings for all of:

a) Each individual HW partition (boot0/1 if present, general0/1/2/3 if
present, the user area, maybe the replay block)

b) Perhaps also a linearized view of the raw eMMC (LBAs 0..boot_size-1
write to boot 0, LBAs boot_size..(2*boot_size)-1 write to boot1, LBAs
2*boot_size..end_of_device write to user area for example).

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-31 17:14     ` Stephen Warren
@ 2012-08-01  7:16       ` Lukasz Majewski
  2012-08-01 17:13         ` Stephen Warren
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-01  7:16 UTC (permalink / raw)
  To: u-boot

Hi Stephen Warren,

> On 07/31/2012 12:37 AM, Lukasz Majewski wrote:
> > Support for u-boot's "dfu <interface> <dev> [list]" command.
> 
> > +U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu,
> > +	"Device Firmware Upgrade",
> > +	"<interface> <dev> [list]\n"
> > +	"  - device firmware upgrade on a device <dev>\n"
> > +	"    attached to interface <interface>\n"
> > +	"    [list] - list available alt settings"
> > +);
> 
> Hmm. Is there any way to make this work without specifying "interface
> dev", or to allow specifying multiple "interface dev" entries? On a
> system with all of eMMC, NAND, and SPI, I'd like to just run "dfu" as
> the U-Boot command, and have the host specify which of those "devices"
> it wants to download to using the DFU protocol. So, if flashing a
> bunch of devices, there is no need to interact with U-Boot over both
> serial and USB in order to invoke the dfu command multiple times.

It would be possible by specifying proper altsettings e.g.:
a1 mmc-boot
a2 mmc-uImage
a3 nand-part0
a4 nand-part1
etc.

However, I think that for the start, the approach proposed here (as dfu
mmc 0 command call) is sufficient.

This approach is used with several file systems calls (e.g. fatload
mmc ... , fatwrite mmc ... etc.) and in my opinion it is consistent.

> 
> Somewhat related to this, it looks like the eMMC support doesn't allow
> the HW partition to be specified; it would be nice to expose alt
> settings for all of:
> 
> a) Each individual HW partition (boot0/1 if present, general0/1/2/3 if
> present, the user area, maybe the replay block)

I'm fully aware of this problem.
In the eMMC case, the access to boot partitions will be served by
defining special alt settings for DFU.

Those altsettings will be defined as follows:
-a[N] boot0
-a[N+1] boot1

Prerequisite for this functionality is support of "boot"
command, which will allow switching of the MMC available address spaces
(e.g. between boot0/boot1 and user accessible space).

> 
> b) Perhaps also a linearized view of the raw eMMC (LBAs 0..boot_size-1
> write to boot 0, LBAs boot_size..(2*boot_size)-1 write to boot1, LBAs
> 2*boot_size..end_of_device write to user area for example).

Access to partitions will be done differently. I assume that each eMMC
memory (the user accessible part) will be equipped with MBR or GPT
definition.

For this reason I'm now developing the USB Mass Storage (UMS) gadget to
export eMMC to host PC.
This solves the problem with accessing separate partitions. 

Please also be aware, that DFU shall be used only for relatively small
files (due to small EP0 bandwidth).

Large files shall be copied with UMS.

-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command
  2012-08-01  7:16       ` Lukasz Majewski
@ 2012-08-01 17:13         ` Stephen Warren
  2012-08-02  8:31           ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Stephen Warren @ 2012-08-01 17:13 UTC (permalink / raw)
  To: u-boot

On 08/01/2012 01:16 AM, Lukasz Majewski wrote:
> Hi Stephen Warren,
> 
>> On 07/31/2012 12:37 AM, Lukasz Majewski wrote:
>>> Support for u-boot's "dfu <interface> <dev> [list]" command.
>>
>>> +U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu,
>>> +	"Device Firmware Upgrade",
>>> +	"<interface> <dev> [list]\n"
>>> +	"  - device firmware upgrade on a device <dev>\n"
>>> +	"    attached to interface <interface>\n"
>>> +	"    [list] - list available alt settings"
>>> +);
...
>> Somewhat related to this, it looks like the eMMC support doesn't allow
>> the HW partition to be specified; it would be nice to expose alt
>> settings for all of:
>>
>> a) Each individual HW partition (boot0/1 if present, general0/1/2/3 if
>> present, the user area, maybe the replay block)
> 
> I'm fully aware of this problem.
> In the eMMC case, the access to boot partitions will be served by
> defining special alt settings for DFU.
> 
> Those altsettings will be defined as follows:
> -a[N] boot0
> -a[N+1] boot1
> 
> Prerequisite for this functionality is support of "boot"
> command, which will allow switching of the MMC available address spaces
> (e.g. between boot0/boot1 and user accessible space).

Is this "boot" command a DFU protocol command, or a U-Boot command-line
command? I note that the U-Boot command-line already allows HW partition
selection using an additional parameter to "mmc" - "mmc dev
$mmc_device_id $partition_id".

>> b) Perhaps also a linearized view of the raw eMMC (LBAs 0..boot_size-1
>> write to boot 0, LBAs boot_size..(2*boot_size)-1 write to boot1, LBAs
>> 2*boot_size..end_of_device write to user area for example).
> 
> Access to partitions will be done differently. I assume that each eMMC
> memory (the user accessible part) will be equipped with MBR or GPT
> definition.

That's a different kind of partition though.

In general, there's no need for the eMMC device to contain any kind of
standardized SW-level partition table. On Tegra, the boot ROM can boot
directly from an eMMC device, and that requires raw data in the
partitions, not a standardized SW partition table.

> For this reason I'm now developing the USB Mass Storage (UMS) gadget to
> export eMMC to host PC.
> This solves the problem with accessing separate partitions. 

OK, if the raw eMMC device is exposed using USB storage, we should be
able to dd directly to it and the presence-or-lack-thereof of any
MBR/GPT wouldn't even be relevant.

It'd still be useful to have a linearized view of the flash that
concatenated all the HW partitions into a single raw device, but I guess
an alt setting for that probably could be added later.

> Please also be aware, that DFU shall be used only for relatively small
> files (due to small EP0 bandwidth).
> 
> Large files shall be copied with UMS.

Oh, didn't know that. Just out of curiosity, are you thinking of
implementing that too?

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command
  2012-07-31  6:37   ` [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
  2012-07-31 17:14     ` Stephen Warren
@ 2012-08-01 18:04     ` Mike Frysinger
  2012-08-02  7:16       ` Marek Vasut
  1 sibling, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-08-01 18:04 UTC (permalink / raw)
  To: u-boot

On Tuesday 31 July 2012 02:37:01 Lukasz Majewski wrote:
> --- /dev/null
> +++ b/common/cmd_dfu.c
>
> +	static char *s = "dfu";

no need for this to be static
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120801/a3fe945f/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 1/7] dfu:usb: Support for g_dnl composite download gadget.
  2012-07-31  6:36   ` [U-Boot] [PATCH v3 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
@ 2012-08-01 22:40     ` Mike Frysinger
  2012-08-02  9:55       ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-08-01 22:40 UTC (permalink / raw)
  To: u-boot

On Tuesday 31 July 2012 02:36:57 Lukasz Majewski wrote:
> --- /dev/null
> +++ b/drivers/usb/gadget/g_dnl.c
>
> +static const struct usb_descriptor_header *otg_desc[] = {
> +	(struct usb_descriptor_header *) &(struct usb_otg_descriptor){

since you're just casting away things, you could just use (void*) to make it a 
bit more compact

also, can this be:
static const struct usb_descriptor_header * const otg_desc[]
(notice the 2nd const)

> +static struct usb_gadget_strings *g_dnl_composite_strings[] = {

here too:
static struct usb_gadget_strings * const g_dnl_composite_strings[] = {

> +static int g_dnl_do_config(struct usb_configuration *c)
> +{
> +	int ret = -1;
> +	char *s = (char *) c->cdev->driver->name;

pretty sure this should be:
	const char *s = c->cdev->driver->name;

> +static int g_dnl_bind(struct usb_composite_dev *cdev)
> +{
> +	int			gcnum;
> +	int id, ret;
> +	struct usb_gadget	*gadget = cdev->gadget;

can we stick to a single space for indentation between the type and the 
variable name please ?

> +int g_dnl_register(const char *type)
> +{
> +	int ret;
> +	/* We only allow "dfu" atm, so 3 should be enough */
> +	static char name[sizeof(shortname) + 3];
> +
> +	if (!strcmp(type, "dfu")) {
> +		strcpy(name, shortname);
> +		strcat(name, type);

if u-boot had stpcpy(), we could do:
	strcpy(stpcpy(name, shortname), type);

> --- /dev/null
> +++ b/include/g_dnl.h
>
> +/* USB initialization declaration - board specific*/

needs a space before that "*/"
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120801/8b19b384/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  2012-07-31  6:36   ` [U-Boot] [PATCH v3 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
@ 2012-08-01 22:45     ` Mike Frysinger
  2012-08-02 10:54       ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-08-01 22:45 UTC (permalink / raw)
  To: u-boot

On Tuesday 31 July 2012 02:36:58 Lukasz Majewski wrote:
> --- /dev/null
> +++ b/drivers/usb/gadget/f_dfu.c
>
> +static struct usb_interface_descriptor dfu_intf_runtime = {

can this be made const ?

> +static struct usb_descriptor_header *dfu_runtime_descs[] = {
> +	(struct usb_descriptor_header *) &dfu_intf_runtime,

can you change the descs array to be const ?
static const struct usb_descriptor_header * const dfu_runtime_descs[] = {

then i think you can drop the cast there ...

> +static struct usb_qualifier_descriptor dev_qualifier = {
> +static struct usb_gadget_strings stringtab_dfu_generic = {
> +static struct usb_gadget_strings *dfu_generic_strings[] = {
> +static struct usb_gadget_strings stringtab_dfu = {
> +static struct usb_gadget_strings *dfu_strings[] = {

can these be made const ?

> +static void handle_getstate(struct usb_request *req)
> +{
> +	struct f_dfu *f_dfu = req->context;
> +
> +	((u8 *)req->buf)[0] = f_dfu->dfu_state & 0xff;

pretty sure you don't need that "& 0xff"

> +static int state_app_idle(struct f_dfu *f_dfu,
> +			  const struct usb_ctrlrequest *ctrl,
> +			  struct usb_gadget *gadget,
> +			  struct usb_request *req)
> +{
> +	int value = 0;

might be good to push this down into the 1 case statement 
(USB_REQ_DFU_GETSTATE) that uses it rather than init it up top

same goes for all the other funcs below that follow this style
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120801/72139cae/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 3/7] dfu: DFU backend implementation
  2012-07-31  6:36   ` [U-Boot] [PATCH v3 3/7] dfu: DFU backend implementation Lukasz Majewski
@ 2012-08-01 22:57     ` Mike Frysinger
  2012-08-02 13:55       ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-08-01 22:57 UTC (permalink / raw)
  To: u-boot

On Tuesday 31 July 2012 02:36:59 Lukasz Majewski wrote:
> --- /dev/null
> +++ b/drivers/dfu/dfu.c
>
> +static int dfu_find_alt_num(char *s)

const char *s

> +{
> +	int i = 0;
> +
> +	for (; *s; s++)
> +		if (*s == ';')
> +			i++;
> +
> +	return ++i;
> +}

looks kind of like:
	return (strrchr(s, ';') - s) + 1;

> +int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
> +{
> +	static unsigned char *i_buf;
> +	static int i_blk_seq_num;
> +	long w_size = 0;
> +	int ret = 0;
> +
> +	if (blk_seq_num == 0) {
> +		memset(dfu_buf, '\0', sizeof(dfu_buf));
> ...
> +	memcpy(i_buf, buf, size);
> +	i_buf += size;

why bother clearing it ?  since right below we memcpy() in the data we care 
about from buf, i'd skip the memset() completely.

> +int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
> +{
> +	static unsigned char *i_buf;
> +	static int i_blk_seq_num;
> +	static long r_size;
> +	static u32 crc;
> +	int ret = 0;
> +
> +	if (blk_seq_num == 0) {
> +		i_buf = dfu_buf;
> +		memset(dfu_buf, '\0', sizeof(dfu_buf));
> +		ret = dfu->read_medium(dfu, i_buf, &r_size);
> +		debug("%s: %s %ld [B]\n", __func__, dfu->name, r_size);
> +		i_blk_seq_num = 0;
> +		/* Integrity check (if needed) */
> +		crc = crc32(0, dfu_buf, r_size);
> +	}

same here -- punt the memset()

> +static int dfu_fill_entity(struct dfu_entity *dfu, char* s, int alt,

"char *s", not "char* s"

> +int dfu_config_entities(char *env, char *interface, int num)
> +{
> +	struct dfu_entity *dfu;
> +	int i, ret;
> +	char *s;
> +
> +	dfu_alt_num = dfu_find_alt_num(env);
> +	debug("%s: dfu_alt_num=%d\n", __func__, dfu_alt_num);
> +
> +	for (i = 0; i < dfu_alt_num; i++) {
> +		dfu = calloc(sizeof(struct dfu_entity), 1);

seems like you can do this in a single call outside of the for loop:
	dfu = calloc(sizeof(*dfu), dfu_alt_num);
	if (!dfu)
		return -1;
	for (i = 0; i < dfu_alt_num; i++) {
		s = strsep(&env, ";");
		ret = dfu_fill_entity(&dfu[i], s, i, interface, num);
		if (ret)
			return -1;
		list_add_tail(&dfu[i].list, &dfu_list);
	}

> --- /dev/null
> +++ b/include/dfu.h
>
> +char *dfu_extract_token(char** e, int *n);
> +extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s);
> +static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s)

"char *s", not "char* s"
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120801/c7c6b43f/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 4/7] dfu: MMC specific routines for DFU operation
  2012-07-31  6:37   ` [U-Boot] [PATCH v3 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
@ 2012-08-01 23:00     ` Mike Frysinger
  2012-08-02 14:47       ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-08-01 23:00 UTC (permalink / raw)
  To: u-boot

On Tuesday 31 July 2012 02:37:00 Lukasz Majewski wrote:
> --- /dev/null
> +++ b/drivers/dfu/dfu_mmc.c
>
> +static int mmc_block_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
> +			void *buf, long *len)
> +{
> +	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf, DFU_CMD_BUF_SIZE);

ugh, what ?  you're passing this string to run_command so there is no point in 
aligning it (not to mention the topic of u-boot code internally calling 
run_command() is seriously wrong.

> +	memset(cmd_buf, '\0', sizeof(cmd_buf));
> +
> +	sprintf(cmd_buf, "mmc %s 0x%x %x %x",

that memset is pointless.  delete it.

> +static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
> +			void *buf, long *len)
> +{

came comments for this func as above

> +int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s)

"char *s", not "char* s".  please search all your patches for this mistake as 
it seems to have come up a lot.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120801/e8f04431/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command
  2012-08-01 18:04     ` Mike Frysinger
@ 2012-08-02  7:16       ` Marek Vasut
  2012-08-02 15:28         ` Lukasz Majewski
  2012-08-02 17:47         ` Mike Frysinger
  0 siblings, 2 replies; 147+ messages in thread
From: Marek Vasut @ 2012-08-02  7:16 UTC (permalink / raw)
  To: u-boot

Dear Mike Frysinger,

> On Tuesday 31 July 2012 02:37:01 Lukasz Majewski wrote:
> > --- /dev/null
> > +++ b/common/cmd_dfu.c
> > 
> > +	static char *s = "dfu";
> 
> no need for this to be static

It can be pulled out of the function and be made into const static

> -mike

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command
  2012-08-01 17:13         ` Stephen Warren
@ 2012-08-02  8:31           ` Lukasz Majewski
  2012-08-02 15:52             ` Stephen Warren
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-02  8:31 UTC (permalink / raw)
  To: u-boot

On Wed, 01 Aug 2012 11:13:14 -0600
Stephen Warren <swarren@wwwdotorg.org> wrote:

> On 08/01/2012 01:16 AM, Lukasz Majewski wrote:
> > Hi Stephen Warren,
> > 
> >> On 07/31/2012 12:37 AM, Lukasz Majewski wrote:
> >>> Support for u-boot's "dfu <interface> <dev> [list]" command.
> >>
> >>> +U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu,
> >>> +	"Device Firmware Upgrade",
> >>> +	"<interface> <dev> [list]\n"
> >>> +	"  - device firmware upgrade on a device <dev>\n"
> >>> +	"    attached to interface <interface>\n"
> >>> +	"    [list] - list available alt settings"
> >>> +);
> ...
> >> Somewhat related to this, it looks like the eMMC support doesn't
> >> allow the HW partition to be specified; it would be nice to expose
> >> alt settings for all of:
> >>
> >> a) Each individual HW partition (boot0/1 if present,
> >> general0/1/2/3 if present, the user area, maybe the replay block)
> > 
> > I'm fully aware of this problem.
> > In the eMMC case, the access to boot partitions will be served by
> > defining special alt settings for DFU.
> > 
> > Those altsettings will be defined as follows:
> > -a[N] boot0
> > -a[N+1] boot1
> > 
> > Prerequisite for this functionality is support of "boot"
> > command, which will allow switching of the MMC available address
> > spaces (e.g. between boot0/boot1 and user accessible space).
> 
> Is this "boot" command a DFU protocol command, or a U-Boot
> command-line command? I note that the U-Boot command-line already
> allows HW partition selection using an additional parameter to "mmc"
> - "mmc dev $mmc_device_id $partition_id".

I'm rather thinking of a U-boot command (as it is easier to integrate).
The command would be "mmc boot <dev> <params .. boot partition>"

Although it is not yet implemented, it is on the top of mine "TO DO"
list :-).

> 
> >> b) Perhaps also a linearized view of the raw eMMC (LBAs
> >> 0..boot_size-1 write to boot 0, LBAs boot_size..(2*boot_size)-1
> >> write to boot1, LBAs 2*boot_size..end_of_device write to user area
> >> for example).
> > 
> > Access to partitions will be done differently. I assume that each
> > eMMC memory (the user accessible part) will be equipped with MBR or
> > GPT definition.
> 
> That's a different kind of partition though.
> 
> In general, there's no need for the eMMC device to contain any kind of
> standardized SW-level partition table. On Tegra, the boot ROM can boot
> directly from an eMMC device, and that requires raw data in the
> partitions, not a standardized SW partition table.
> 
> > For this reason I'm now developing the USB Mass Storage (UMS)
> > gadget to export eMMC to host PC.
> > This solves the problem with accessing separate partitions. 
> 
> OK, if the raw eMMC device is exposed using USB storage, we should be
> able to dd directly to it and the presence-or-lack-thereof of any
> MBR/GPT wouldn't even be relevant.

With the UMS you would see the whole mmc address space as one
partition. Then you can use dd with several parameters to "dump" data
to a specific LBA address. 

When correct MBR or GPT is present, then we can specify partitions to
be accessed.

> 
> It'd still be useful to have a linearized view of the flash that
> concatenated all the HW partitions into a single raw device, but I
> guess an alt setting for that probably could be added later.

I think that UMS solves this issue. However, correct me if I'm wrong.

Let's assume, that UMS causes host to see following partitions:
sde: sde1 sde2 sde3 sde4 < sde5 .. sdeN >

Is the "mount -t vfat /dev/sde /mnt" not allowing access to the whole
eMMC device (despite of the partitions)?

> 
> > Please also be aware, that DFU shall be used only for relatively
> > small files (due to small EP0 bandwidth).
> > 
> > Large files shall be copied with UMS.
> 
> Oh, didn't know that. Just out of curiosity, are you thinking of
> implementing that too?

The USB Mass Storage gadget is now working with the g_dnl composite
gadget as a f_ums function.

Unfortunately it is not polished enough to be posted to ML.

I'd prefer that DFU related patches would be pulled to ML first.
Afterwards I would post the UMS function.

-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 1/7] dfu:usb: Support for g_dnl composite download gadget.
  2012-08-01 22:40     ` Mike Frysinger
@ 2012-08-02  9:55       ` Lukasz Majewski
  0 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-02  9:55 UTC (permalink / raw)
  To: u-boot

Hi Mike,

> On Tuesday 31 July 2012 02:36:57 Lukasz Majewski wrote:
> > --- /dev/null
> > +++ b/drivers/usb/gadget/g_dnl.c
> >
> > +static const struct usb_descriptor_header *otg_desc[] = {
> > +	(struct usb_descriptor_header *) &(struct
> > usb_otg_descriptor){
> 
> since you're just casting away things, you could just use (void*) to
> make it a bit more compact
> 
> also, can this be:
> static const struct usb_descriptor_header * const otg_desc[]
> (notice the 2nd const)
> 

After looking into the code I can say that otg_support is not needed
(at least for this gadget) in u-boot. Will be removed.

> > +static struct usb_gadget_strings *g_dnl_composite_strings[] = {
> 
> here too:
> static struct usb_gadget_strings * const g_dnl_composite_strings[] = {

This const is anyway discarded by compiler (GCC 4.6.1) when .string
field of struct usb_composite_driver is initialized. 

> 
> > +static int g_dnl_do_config(struct usb_configuration *c)
> > +{
> > +	int ret = -1;
> > +	char *s = (char *) c->cdev->driver->name;
> 
> pretty sure this should be:
> 	const char *s = c->cdev->driver->name;

Yes, you are right. Corrected.
> 
> > +static int g_dnl_bind(struct usb_composite_dev *cdev)
> > +{
> > +	int			gcnum;
> > +	int id, ret;
> > +	struct usb_gadget	*gadget = cdev->gadget;
> 
> can we stick to a single space for indentation between the type and
> the variable name please ?

Corrected.
> 
> > +int g_dnl_register(const char *type)
> > +{
> > +	int ret;
> > +	/* We only allow "dfu" atm, so 3 should be enough */
> > +	static char name[sizeof(shortname) + 3];
> > +
> > +	if (!strcmp(type, "dfu")) {
> > +		strcpy(name, shortname);
> > +		strcat(name, type);
> 
> if u-boot had stpcpy(), we could do:
> 	strcpy(stpcpy(name, shortname), type);
> 
> > --- /dev/null
> > +++ b/include/g_dnl.h
> >
> > +/* USB initialization declaration - board specific*/
> 
> needs a space before that "*/"

Corrected.

> -mike



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  2012-08-01 22:45     ` Mike Frysinger
@ 2012-08-02 10:54       ` Lukasz Majewski
  0 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-02 10:54 UTC (permalink / raw)
  To: u-boot

Dear Mike,

> On Tuesday 31 July 2012 02:36:58 Lukasz Majewski wrote:
> > --- /dev/null
> > +++ b/drivers/usb/gadget/f_dfu.c
> >
> > +static struct usb_interface_descriptor dfu_intf_runtime = {
> 
> can this be made const ?

Unfortunately those structs cannot be const, since some of their fields
are filled during running DFU code(when switching between "normal" and
"dfu" mode).
> 
> > +static struct usb_descriptor_header *dfu_runtime_descs[] = {
> > +	(struct usb_descriptor_header *) &dfu_intf_runtime,
> 
> can you change the descs array to be const ?
> static const struct usb_descriptor_header * const dfu_runtime_descs[]
> = {
> 

The same as above. Moreover the DFU implementation passes the
information about available alt settings as descriptors filled at
runtime.

> then i think you can drop the cast there ...
> 
> > +static struct usb_qualifier_descriptor dev_qualifier = {
Struct above can only be defined as const.
> > +static struct usb_gadget_strings stringtab_dfu_generic = {
> > +static struct usb_gadget_strings *dfu_generic_strings[] = {
> > +static struct usb_gadget_strings stringtab_dfu = {
> > +static struct usb_gadget_strings *dfu_strings[] = {
> 
> can these be made const ?
> 
> > +static void handle_getstate(struct usb_request *req)
> > +{
> > +	struct f_dfu *f_dfu = req->context;
> > +
> > +	((u8 *)req->buf)[0] = f_dfu->dfu_state & 0xff;
> 
> pretty sure you don't need that "& 0xff"
OK.
> 
> > +static int state_app_idle(struct f_dfu *f_dfu,
> > +			  const struct usb_ctrlrequest *ctrl,
> > +			  struct usb_gadget *gadget,
> > +			  struct usb_request *req)
> > +{
> > +	int value = 0;
> 
> might be good to push this down into the 1 case statement 
> (USB_REQ_DFU_GETSTATE) that uses it rather than init it up top
> 

I haven't understood this comment. 

Do you suggest to combine all those functions (like state_app_* or
state_dfu_*) in one big switch - case clause?
The state machine was initially implemented in this way, but for sake
of clearness Marek Vasut asked to split it down do separate functions
as defined at dfu_state[]. I also think that this approach is better
than one bit switch - case.

> same goes for all the other funcs below that follow this style
> -mike



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 3/7] dfu: DFU backend implementation
  2012-08-01 22:57     ` Mike Frysinger
@ 2012-08-02 13:55       ` Lukasz Majewski
  2012-08-03 23:19         ` Mike Frysinger
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-02 13:55 UTC (permalink / raw)
  To: u-boot

Dear Mike Frysinger,

> On Tuesday 31 July 2012 02:36:59 Lukasz Majewski wrote:
> > --- /dev/null
> > +++ b/drivers/dfu/dfu.c
> >
> > +static int dfu_find_alt_num(char *s)
> 
> const char *s
Good point.
> 
> > +{
> > +	int i = 0;
> > +
> > +	for (; *s; s++)
> > +		if (*s == ';')
> > +			i++;
> > +
> > +	return ++i;
> > +}

In this function I count how many times the ';' separator appears.
I didn't found proper function at ./lib/string.c.

> 
> looks kind of like:
> 	return (strrchr(s, ';') - s) + 1;

The above code returns position of the last occurrence of the ';'
separator.

> 
> > +int dfu_write(struct dfu_entity *dfu, void *buf, int size, int
> > blk_seq_num) +{
> > +	static unsigned char *i_buf;
> > +	static int i_blk_seq_num;
> > +	long w_size = 0;
> > +	int ret = 0;
> > +
> > +	if (blk_seq_num == 0) {
> > +		memset(dfu_buf, '\0', sizeof(dfu_buf));
> > ...
> > +	memcpy(i_buf, buf, size);
> > +	i_buf += size;
> 
> why bother clearing it ?  since right below we memcpy() in the data
> we care about from buf, i'd skip the memset() completely.
You are right, removed.
> 
> > +int dfu_read(struct dfu_entity *dfu, void *buf, int size, int
> > blk_seq_num) +{
> > +	static unsigned char *i_buf;
> > +	static int i_blk_seq_num;
> > +	static long r_size;
> > +	static u32 crc;
> > +	int ret = 0;
> > +
> > +	if (blk_seq_num == 0) {
> > +		i_buf = dfu_buf;
> > +		memset(dfu_buf, '\0', sizeof(dfu_buf));
> > +		ret = dfu->read_medium(dfu, i_buf, &r_size);
> > +		debug("%s: %s %ld [B]\n", __func__, dfu->name,
> > r_size);
> > +		i_blk_seq_num = 0;
> > +		/* Integrity check (if needed) */
> > +		crc = crc32(0, dfu_buf, r_size);
> > +	}
> 
> same here -- punt the memset()
OK,
> 
> > +static int dfu_fill_entity(struct dfu_entity *dfu, char* s, int
> > alt,
> 
> "char *s", not "char* s"
OK,
> 
> > +int dfu_config_entities(char *env, char *interface, int num)
> > +{
> > +	struct dfu_entity *dfu;
> > +	int i, ret;
> > +	char *s;
> > +
> > +	dfu_alt_num = dfu_find_alt_num(env);
> > +	debug("%s: dfu_alt_num=%d\n", __func__, dfu_alt_num);
> > +
> > +	for (i = 0; i < dfu_alt_num; i++) {
> > +		dfu = calloc(sizeof(struct dfu_entity), 1);
> 
> seems like you can do this in a single call outside of the for loop:
> 	dfu = calloc(sizeof(*dfu), dfu_alt_num);
> 	if (!dfu)
> 		return -1;
> 	for (i = 0; i < dfu_alt_num; i++) {
> 		s = strsep(&env, ";");
> 		ret = dfu_fill_entity(&dfu[i], s, i, interface, num);
> 		if (ret)
> 			return -1;
> 		list_add_tail(&dfu[i].list, &dfu_list);
> 	}
> 

I'd prefer to leave it as it is (since IMHO is more readable) with the
addition of following code:

for (i = 0; i < dfu_alt_num; i++) {
	dfu = calloc(sizeof(struct dfu_entity), 1);
	if (!dfu) {
		dfu_free_entities();
		return -1;
	}
}

> > --- /dev/null
> > +++ b/include/dfu.h
> >
> > +char *dfu_extract_token(char** e, int *n);
> > +extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s);
> > +static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu,
> > char* s)
> 
> "char *s", not "char* s"
OK
> -mike



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 4/7] dfu: MMC specific routines for DFU operation
  2012-08-01 23:00     ` Mike Frysinger
@ 2012-08-02 14:47       ` Lukasz Majewski
  0 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-02 14:47 UTC (permalink / raw)
  To: u-boot

Dear Mike Frysinger,

> On Tuesday 31 July 2012 02:37:00 Lukasz Majewski wrote:
> > --- /dev/null
> > +++ b/drivers/dfu/dfu_mmc.c
> >
> > +static int mmc_block_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
> > +			void *buf, long *len)
> > +{
> > +	ALLOC_CACHE_ALIGN_BUFFER(char, cmd_buf, DFU_CMD_BUF_SIZE);
> 
> ugh, what ?  you're passing this string to run_command so there is no
> point in aligning it
Ok, I will change this.

> (not to mention the topic of u-boot code
> internally calling run_command() is seriously wrong.
We are all aware that this approach is a compromise. And this code
will be rewritten when new DM appears.

> 
> > +	memset(cmd_buf, '\0', sizeof(cmd_buf));
> > +
> > +	sprintf(cmd_buf, "mmc %s 0x%x %x %x",
> 
> that memset is pointless.  delete it.

Done.
> 
> > +static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
> > +			void *buf, long *len)
> > +{
> 
> came comments for this func as above
> 
> > +int dfu_fill_entity_mmc(struct dfu_entity *dfu, char* s)
> 
> "char *s", not "char* s".  please search all your patches for this
> mistake as it seems to have come up a lot.
Hmm, ./tools/checkpatch wasn't complaining about this... 

> -mike



-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command
  2012-08-02  7:16       ` Marek Vasut
@ 2012-08-02 15:28         ` Lukasz Majewski
  2012-08-02 17:47         ` Mike Frysinger
  1 sibling, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-02 15:28 UTC (permalink / raw)
  To: u-boot

Dear Marek Vasut,

> Dear Mike Frysinger,
> 
> > On Tuesday 31 July 2012 02:37:01 Lukasz Majewski wrote:
> > > --- /dev/null
> > > +++ b/common/cmd_dfu.c
> > > 
> > > +	static char *s = "dfu";
> > 
> > no need for this to be static
> 
> It can be pulled out of the function and be made into const static

Ok.
> 
> > -mike
> 
> Best regards,
> Marek Vasut


-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command
  2012-08-02  8:31           ` Lukasz Majewski
@ 2012-08-02 15:52             ` Stephen Warren
  2012-08-03  6:13               ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Stephen Warren @ 2012-08-02 15:52 UTC (permalink / raw)
  To: u-boot

On 08/02/2012 02:31 AM, Lukasz Majewski wrote:
> On Wed, 01 Aug 2012 11:13:14 -0600
> Stephen Warren <swarren@wwwdotorg.org> wrote:
> 
>> On 08/01/2012 01:16 AM, Lukasz Majewski wrote:
>>> Hi Stephen Warren,
>>>
>>>> On 07/31/2012 12:37 AM, Lukasz Majewski wrote:
>>>>> Support for u-boot's "dfu <interface> <dev> [list]" command.
>>>>
>>>>> +U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu,
>>>>> +	"Device Firmware Upgrade",
>>>>> +	"<interface> <dev> [list]\n"
>>>>> +	"  - device firmware upgrade on a device <dev>\n"
>>>>> +	"    attached to interface <interface>\n"
>>>>> +	"    [list] - list available alt settings"
>>>>> +);
>> ...
>>>> Somewhat related to this, it looks like the eMMC support doesn't
>>>> allow the HW partition to be specified; it would be nice to expose
>>>> alt settings for all of:
>>>>
>>>> a) Each individual HW partition (boot0/1 if present,
>>>> general0/1/2/3 if present, the user area, maybe the replay block)
>>>
>>> I'm fully aware of this problem.
>>> In the eMMC case, the access to boot partitions will be served by
>>> defining special alt settings for DFU.
>>>
>>> Those altsettings will be defined as follows:
>>> -a[N] boot0
>>> -a[N+1] boot1
>>>
>>> Prerequisite for this functionality is support of "boot"
>>> command, which will allow switching of the MMC available address
>>> spaces (e.g. between boot0/boot1 and user accessible space).
>>
>> Is this "boot" command a DFU protocol command, or a U-Boot
>> command-line command? I note that the U-Boot command-line already
>> allows HW partition selection using an additional parameter to "mmc"
>> - "mmc dev $mmc_device_id $partition_id".
> 
> I'm rather thinking of a U-boot command (as it is easier to integrate).
> The command would be "mmc boot <dev> <params .. boot partition>"
> 
> Although it is not yet implemented, it is on the top of mine "TO DO"
> list :-).

I guess I'm confused what that "boot" command would actually do then...
The only thing I can think that it might do is already covered by the
"mmc" command's partition parameter.

>>>> b) Perhaps also a linearized view of the raw eMMC (LBAs
>>>> 0..boot_size-1 write to boot 0, LBAs boot_size..(2*boot_size)-1
>>>> write to boot1, LBAs 2*boot_size..end_of_device write to user area
>>>> for example).
>>>
>>> Access to partitions will be done differently. I assume that each
>>> eMMC memory (the user accessible part) will be equipped with MBR or
>>> GPT definition.
>>
>> That's a different kind of partition though.
>>
>> In general, there's no need for the eMMC device to contain any kind of
>> standardized SW-level partition table. On Tegra, the boot ROM can boot
>> directly from an eMMC device, and that requires raw data in the
>> partitions, not a standardized SW partition table.
>>
>>> For this reason I'm now developing the USB Mass Storage (UMS)
>>> gadget to export eMMC to host PC.
>>> This solves the problem with accessing separate partitions. 
>>
>> OK, if the raw eMMC device is exposed using USB storage, we should be
>> able to dd directly to it and the presence-or-lack-thereof of any
>> MBR/GPT wouldn't even be relevant.
> 
> With the UMS you would see the whole mmc address space as one
> partition. Then you can use dd with several parameters to "dump" data
> to a specific LBA address. 
> 
> When correct MBR or GPT is present, then we can specify partitions to
> be accessed.
> 
>> It'd still be useful to have a linearized view of the flash that
>> concatenated all the HW partitions into a single raw device, but I
>> guess an alt setting for that probably could be added later.
> 
> I think that UMS solves this issue. However, correct me if I'm wrong.
> 
> Let's assume, that UMS causes host to see following partitions:
> sde: sde1 sde2 sde3 sde4 < sde5 .. sdeN >
> 
> Is the "mount -t vfat /dev/sde /mnt" not allowing access to the whole
> eMMC device (despite of the partitions)?

Again, this is confusing two different kinds of partitions.

There are HW-level partitions/regions/areas within the eMMC HW itself.
You need to send commands to the eMMC device to select whether
read/write commands act on the boot0/boot1/general*/user HW partition.

There are (or can be) SW-level partitions within any/all of those HW
partitions. This is the level at which an MBR/GPT partition would exist.

With DFU, I'd expect an alt setting for each of the HW partitions at least.

With UMS, I'd expect a device to appear for each of the HW partitions.
(these may show up as say /dev/sdb for boot0, /dev/sdc for boot1,
/dev/sdd for the user area). If an MBR/GPT is present within any of
those, Linux may then create a device for each SW partition, so e.g.
/dev/sdd1, /dev/sdd2, etc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command
  2012-08-02  7:16       ` Marek Vasut
  2012-08-02 15:28         ` Lukasz Majewski
@ 2012-08-02 17:47         ` Mike Frysinger
  1 sibling, 0 replies; 147+ messages in thread
From: Mike Frysinger @ 2012-08-02 17:47 UTC (permalink / raw)
  To: u-boot

On Thursday 02 August 2012 03:16:18 Marek Vasut wrote:
> Dear Mike Frysinger,
> 
> > On Tuesday 31 July 2012 02:37:01 Lukasz Majewski wrote:
> > > --- /dev/null
> > > +++ b/common/cmd_dfu.c
> > > 
> > > +	static char *s = "dfu";
> > 
> > no need for this to be static
> 
> It can be pulled out of the function and be made into const static

err, there's no point.  the static markings here are for the pointer "s", not 
the stuff it's pointing to "dfu".

use:
	char s[] = "dfu";
and it'll probably all optimize away correctly
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120802/e8c413ea/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command
  2012-08-02 15:52             ` Stephen Warren
@ 2012-08-03  6:13               ` Lukasz Majewski
  2012-08-03 15:32                 ` Stephen Warren
  0 siblings, 1 reply; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-03  6:13 UTC (permalink / raw)
  To: u-boot

Dear Stephen Warren,

> Again, this is confusing two different kinds of partitions.
> 
> There are HW-level partitions/regions/areas within the eMMC HW itself.
> You need to send commands to the eMMC device to select whether
> read/write commands act on the boot0/boot1/general*/user HW partition.

This will be done via "mmc boot [dev] [HW partition (boot0/1/user]"
command (from u-boot prompt).
This command is not yet implemented at u-boot (at least for Trats
development board).
After its implementation it will be used as a helper function for dfu.

As a result the access to those partition will be done via proper DFU's
alt settings:
mmc-boot0
mmc-boot1
etc.


> 
> There are (or can be) SW-level partitions within any/all of those HW
> partitions. This is the level at which an MBR/GPT partition would
> exist.
> 
> With DFU, I'd expect an alt setting for each of the HW partitions at
> least.

And this is my goal. Now only the "user" HW partition is supported.
After "mmc boot ..." command implementation support for other
partitions will be added for DFU as well.

> 
> With UMS, I'd expect a device to appear for each of the HW partitions.
> (these may show up as say /dev/sdb for boot0, /dev/sdc for boot1,
> /dev/sdd for the user area). 

Frankly speaking I've thought of providing access only to user
HW partition for initial UMS implementation (the UMS v1 implementation).
However access to all HW partitions from UMS is worth consideration.

> If an MBR/GPT is present within any of
> those, Linux may then create a device for each SW partition, so e.g.
> /dev/sdd1, /dev/sdd2, etc.

This is the functionality which now UMS (v1) provides. 


-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v4 0/7] dfu:usb: DFU support via USB Download gadget
  2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
                   ` (10 preceding siblings ...)
  2012-07-31  6:36 ` [U-Boot] [PATCH v3 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
@ 2012-08-03  7:45 ` Lukasz Majewski
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
                     ` (6 more replies)
  2012-08-06 12:41 ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
  12 siblings, 7 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-03  7:45 UTC (permalink / raw)
  To: u-boot

Those patches add support for composite USB download gadget.
This gadget (at least for now) is equipped with DFU download function.

A separate DFU back-end and front-end have been added.
Back-end is placed at ./drivers/dfu directory. The front-end is implemented
as USB function.

The back-end is written in a generic manner with storage device specific
code separated (eMMC).

DFU specification can be found at:
http://wiki.openmoko.org/wiki/USB_DFU_-_The_USB_Device_Firmware_Upgrade_standard

Example usage:

u-boot side: dfu mmc 0
PC: dfu-util -U IMAGE.bin -a uImage (for upload)
    dfu-util -D uImage -a uImage (download)

To list the alt settings:
        dfu mmc 0 list

Test HW:
        Exynos4210 Trats board

Lukasz Majewski (7):
  dfu:usb: Support for g_dnl composite download gadget.
  dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  dfu: DFU backend implementation
  dfu: MMC specific routines for DFU operation
  dfu:cmd: Support for DFU u-boot command
  arm:trats: Support for USB UDC driver at TRATS board.
  arm:trats: Enable g_dnl composite USB gadget with embedded DFU
    function on TRATS

 Makefile                    |    1 +
 board/samsung/trats/trats.c |    8 +
 common/Makefile             |    1 +
 common/cmd_dfu.c            |   81 +++++
 drivers/dfu/Makefile        |   44 +++
 drivers/dfu/dfu.c           |  239 ++++++++++++++
 drivers/dfu/dfu_mmc.c       |  162 ++++++++++
 drivers/usb/gadget/Makefile |    2 +
 drivers/usb/gadget/f_dfu.c  |  749 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/f_dfu.h  |  100 ++++++
 drivers/usb/gadget/g_dnl.c  |  202 ++++++++++++
 include/configs/trats.h     |   24 ++-
 include/dfu.h               |  103 ++++++
 include/g_dnl.h             |   33 ++
 14 files changed, 1748 insertions(+), 1 deletions(-)
 create mode 100644 common/cmd_dfu.c
 create mode 100644 drivers/dfu/Makefile
 create mode 100644 drivers/dfu/dfu.c
 create mode 100644 drivers/dfu/dfu_mmc.c
 create mode 100644 drivers/usb/gadget/f_dfu.c
 create mode 100644 drivers/usb/gadget/f_dfu.h
 create mode 100644 drivers/usb/gadget/g_dnl.c
 create mode 100644 include/dfu.h
 create mode 100644 include/g_dnl.h

-- 
1.7.2.3

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v4 1/7] dfu:usb: Support for g_dnl composite download gadget.
  2012-08-03  7:45 ` [U-Boot] [PATCH v4 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
@ 2012-08-03  7:45   ` Lukasz Majewski
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-03  7:45 UTC (permalink / raw)
  To: u-boot

Composite USB download gadget support (g_dnl) for download functions.
This code works on top of composite gadget.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:

- G_DNL_{VENDOR_NUM, PRODUCT_NUM and MANUFACTURER} defined at
./include/configs/<board>.h
- Suspend and resume stub methods removed
- '\0' repleaced with plain 0

Changes for v3:
- Remove unused #includes
- Replace strncpy and strncat with strcpy and strcat. It was possible
  due to new approach to g_dnl name generation (at g_dnl_register function)
- Rename the g_dnl_{init|cleanup} to g_dnl_{register|unregister}
- Replace the G_DNL_* CONFIG_G_DNL_*

Changes for v4:
- Remove unnecessary otg calls
- odin prefix replaced with g_dnl
- Single space indentation between type and variable name
---
 drivers/usb/gadget/Makefile |    1 +
 drivers/usb/gadget/g_dnl.c  |  202 +++++++++++++++++++++++++++++++++++++++++++
 include/g_dnl.h             |   33 +++++++
 3 files changed, 236 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/gadget/g_dnl.c
 create mode 100644 include/g_dnl.h

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 87d1918..2c067c8 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -29,6 +29,7 @@ LIB	:= $(obj)libusb_gadget.o
 ifdef CONFIG_USB_GADGET
 COBJS-y += epautoconf.o config.o usbstring.o
 COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
+COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
 endif
 ifdef CONFIG_USB_ETHER
 COBJS-y += ether.o epautoconf.o config.o usbstring.o
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
new file mode 100644
index 0000000..7d87050
--- /dev/null
+++ b/drivers/usb/gadget/g_dnl.c
@@ -0,0 +1,202 @@
+/*
+ * g_dnl.c -- USB Downloader Gadget
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski  <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <errno.h>
+#include <common.h>
+#include <malloc.h>
+
+#include <mmc.h>
+#include <part.h>
+
+#include <g_dnl.h>
+#include "f_dfu.h"
+
+#include "gadget_chips.h"
+#include "composite.c"
+
+/*
+ * One needs to define the following:
+ * CONFIG_G_DNL_VENDOR_NUM
+ * CONFIG_G_DNL_PRODUCT_NUM
+ * CONFIG_G_DNL_MANUFACTURER
+ * at e.g. ./include/configs/<board>.h
+ */
+
+#define STRING_MANUFACTURER 25
+#define STRING_PRODUCT 2
+#define STRING_USBDOWN 2
+#define CONFIG_USBDOWNLOADER 2
+
+#define DRIVER_VERSION		"usb_dnl 2.0"
+
+static const char shortname[] = "usb_dnl_";
+static const char product[] = "USB download gadget";
+static const char manufacturer[] = CONFIG_G_DNL_MANUFACTURER;
+
+static struct usb_device_descriptor device_desc = {
+	.bLength = sizeof device_desc,
+	.bDescriptorType = USB_DT_DEVICE,
+
+	.bcdUSB = __constant_cpu_to_le16(0x0200),
+	.bDeviceClass = USB_CLASS_COMM,
+	.bDeviceSubClass = 0x02, /*0x02:CDC-modem , 0x00:CDC-serial*/
+
+	.idVendor = __constant_cpu_to_le16(CONFIG_G_DNL_VENDOR_NUM),
+	.idProduct = __constant_cpu_to_le16(CONFIG_G_DNL_PRODUCT_NUM),
+	.iProduct = STRING_PRODUCT,
+	.bNumConfigurations = 1,
+};
+
+/* static strings, in UTF-8 */
+static struct usb_string g_dnl_string_defs[] = {
+	{ 0, manufacturer, },
+	{ 1, product, },
+};
+
+static struct usb_gadget_strings g_dnl_string_tab = {
+	.language = 0x0409, /* en-us */
+	.strings = g_dnl_string_defs,
+};
+
+static struct usb_gadget_strings *g_dnl_composite_strings[] = {
+	&g_dnl_string_tab,
+	NULL,
+};
+
+static int g_dnl_unbind(struct usb_composite_dev *cdev)
+{
+	debug("%s\n", __func__);
+	return 0;
+}
+
+static int g_dnl_do_config(struct usb_configuration *c)
+{
+	const char *s = c->cdev->driver->name;
+	int ret = -1;
+
+	debug("%s: configuration: 0x%p composite dev: 0x%p\n",
+	      __func__, c, c->cdev);
+
+	printf("GADGET DRIVER: %s\n", s);
+	if (!strcmp(s, "usb_dnl_dfu"))
+		ret = dfu_add(c);
+
+	return ret;
+}
+
+static int g_dnl_config_register(struct usb_composite_dev *cdev)
+{
+	static struct usb_configuration config = {
+		.label = "usb_dnload",
+		.bmAttributes =	USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+		.bConfigurationValue =	CONFIG_USBDOWNLOADER,
+		.iConfiguration =	STRING_USBDOWN,
+
+		.bind = g_dnl_do_config,
+	};
+
+	return usb_add_config(cdev, &config);
+}
+
+static int g_dnl_bind(struct usb_composite_dev *cdev)
+{
+	struct usb_gadget *gadget = cdev->gadget;
+	int id, ret;
+	int gcnum;
+
+	debug("%s: gadget: 0x%p cdev: 0x%p\n", __func__, gadget, cdev);
+
+	id = usb_string_id(cdev);
+
+	if (id < 0)
+		return id;
+	g_dnl_string_defs[0].id = id;
+	device_desc.iManufacturer = id;
+
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+
+	g_dnl_string_defs[1].id = id;
+	device_desc.iProduct = id;
+
+	ret = g_dnl_config_register(cdev);
+	if (ret)
+		goto error;
+
+	gcnum = usb_gadget_controller_number(gadget);
+
+	debug("gcnum: %d\n", gcnum);
+	if (gcnum >= 0)
+		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
+	else {
+		debug("%s: controller '%s' not recognized\n",
+			shortname, gadget->name);
+		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
+	}
+
+	return 0;
+
+ error:
+	g_dnl_unbind(cdev);
+	return -ENOMEM;
+}
+
+static struct usb_composite_driver g_dnl_driver = {
+	.name = NULL,
+	.dev = &device_desc,
+	.strings = g_dnl_composite_strings,
+
+	.bind = g_dnl_bind,
+	.unbind = g_dnl_unbind,
+};
+
+int g_dnl_register(const char *type)
+{
+	/* We only allow "dfu" atm, so 3 should be enough */
+	static char name[sizeof(shortname) + 3];
+	int ret;
+
+	if (!strcmp(type, "dfu")) {
+		strcpy(name, shortname);
+		strcat(name, type);
+	} else {
+		printf("%s: unknown command: %s\n", __func__, type);
+		return -EINVAL;
+	}
+
+	g_dnl_driver.name = name;
+
+	debug("%s: g_dnl_driver.name: %s\n", __func__, g_dnl_driver.name);
+	ret = usb_composite_register(&g_dnl_driver);
+
+	if (ret) {
+		printf("%s: failed!, error: %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+void g_dnl_unregister(void)
+{
+	usb_composite_unregister(&g_dnl_driver);
+}
diff --git a/include/g_dnl.h b/include/g_dnl.h
new file mode 100644
index 0000000..0ec7440
--- /dev/null
+++ b/include/g_dnl.h
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (C) 2012 Samsung Electronics
+ *  Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __G_DOWNLOAD_H_
+#define __G_DOWNLOAD_H_
+
+#include <linux/usb/ch9.h>
+#include <usbdescriptors.h>
+#include <linux/usb/gadget.h>
+
+int g_dnl_register(const char *s);
+void g_dnl_unregister(void);
+
+/* USB initialization declaration - board specific */
+void board_usb_init(void);
+#endif /* __G_DOWNLOAD_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v4 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  2012-08-03  7:45 ` [U-Boot] [PATCH v4 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
@ 2012-08-03  7:45   ` Lukasz Majewski
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 3/7] dfu: DFU backend implementation Lukasz Majewski
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-03  7:45 UTC (permalink / raw)
  To: u-boot

Support for f_dfu USB function.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:

- Replace kzalloc and kfree with free and calloc
- Reorganization of calloc calls
- Misspelling corrected
- Redesign of DFU state machine from "switch case" to function pointers
- Split the dfu_handle method to separate functions for each DFU state

Changes for v3:
- Missing parenthesis added to sizeof call

Changes for v4:
- Replace two puts with one
- Remove the 0xff at handle_getstate function
- Add const qualifier to struct definitions when possible
---
 drivers/usb/gadget/Makefile |    1 +
 drivers/usb/gadget/f_dfu.c  |  749 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/f_dfu.h  |  100 ++++++
 3 files changed, 850 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/gadget/f_dfu.c
 create mode 100644 drivers/usb/gadget/f_dfu.h

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 2c067c8..5bbdd36 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -30,6 +30,7 @@ ifdef CONFIG_USB_GADGET
 COBJS-y += epautoconf.o config.o usbstring.o
 COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
 COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
+COBJS-$(CONFIG_DFU_FUNCTION) += f_dfu.o
 endif
 ifdef CONFIG_USB_ETHER
 COBJS-y += ether.o epautoconf.o config.o usbstring.o
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
new file mode 100644
index 0000000..3ec4c65
--- /dev/null
+++ b/drivers/usb/gadget/f_dfu.c
@@ -0,0 +1,749 @@
+/*
+ * f_dfu.c -- Device Firmware Update USB function
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *          Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <errno.h>
+#include <common.h>
+#include <malloc.h>
+
+#include <linux/usb/ch9.h>
+#include <usbdescriptors.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/composite.h>
+
+#include <dfu.h>
+#include "f_dfu.h"
+
+struct f_dfu {
+	struct usb_function		usb_function;
+
+	struct usb_descriptor_header	**function;
+	struct usb_string		*strings;
+
+	/* when configured, we have one config */
+	u8				config;
+	u8				altsetting;
+	enum dfu_state			dfu_state;
+	unsigned int			dfu_status;
+
+	/* Send/received block number is handy for data integrity check */
+	int                             blk_seq_num;
+};
+
+typedef int (*dfu_state_fn) (struct f_dfu *,
+			     const struct usb_ctrlrequest *,
+			     struct usb_gadget *,
+			     struct usb_request *);
+
+static inline struct f_dfu *func_to_dfu(struct usb_function *f)
+{
+	return container_of(f, struct f_dfu, usb_function);
+}
+
+static const struct dfu_function_descriptor dfu_func = {
+	.bLength =		sizeof dfu_func,
+	.bDescriptorType =	DFU_DT_FUNC,
+	.bmAttributes =		DFU_BIT_WILL_DETACH |
+				DFU_BIT_MANIFESTATION_TOLERANT |
+				DFU_BIT_CAN_UPLOAD |
+				DFU_BIT_CAN_DNLOAD,
+	.wDetachTimeOut =	0,
+	.wTransferSize =	DFU_USB_BUFSIZ,
+	.bcdDFUVersion =	__constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_interface_descriptor dfu_intf_runtime = {
+	.bLength =		sizeof dfu_intf_runtime,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	.bNumEndpoints =	0,
+	.bInterfaceClass =	USB_CLASS_APP_SPEC,
+	.bInterfaceSubClass =	1,
+	.bInterfaceProtocol =	1,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_descriptor_header *dfu_runtime_descs[] = {
+	(struct usb_descriptor_header *) &dfu_intf_runtime,
+	NULL,
+};
+
+static const struct usb_qualifier_descriptor dev_qualifier = {
+	.bLength =		sizeof dev_qualifier,
+	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
+	.bNumConfigurations =	1,
+};
+
+static const char dfu_name[] = "Device Firmware Upgrade";
+
+/*
+ * static strings, in UTF-8
+ *
+ * dfu_generic configuration
+ */
+static struct usb_string strings_dfu_generic[] = {
+	[0].s = dfu_name,
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab_dfu_generic = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_dfu_generic,
+};
+
+static struct usb_gadget_strings *dfu_generic_strings[] = {
+	&stringtab_dfu_generic,
+	NULL,
+};
+
+/*
+ * usb_function specific
+ */
+static struct usb_gadget_strings stringtab_dfu = {
+	.language	= 0x0409,	/* en-us */
+	/*
+	 * .strings
+	 *
+	 * assigned during initialization,
+	 * depends on number of flash entities
+	 *
+	 */
+};
+
+static struct usb_gadget_strings *dfu_strings[] = {
+	&stringtab_dfu,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
+		  req->length, f_dfu->blk_seq_num);
+
+	if (req->length == 0)
+		puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n");
+}
+
+static void handle_getstatus(struct usb_request *req)
+{
+	struct dfu_status *dstat = (struct dfu_status *)req->buf;
+	struct f_dfu *f_dfu = req->context;
+
+	switch (f_dfu->dfu_state) {
+	case DFU_STATE_dfuDNLOAD_SYNC:
+	case DFU_STATE_dfuDNBUSY:
+		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
+		break;
+	case DFU_STATE_dfuMANIFEST_SYNC:
+		break;
+	default:
+		break;
+	}
+
+	/* send status response */
+	dstat->bStatus = f_dfu->dfu_status;
+	dstat->bState = f_dfu->dfu_state;
+	dstat->iString = 0;
+}
+
+static void handle_getstate(struct usb_request *req)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	((u8 *)req->buf)[0] = f_dfu->dfu_state;
+	req->actual = sizeof(u8);
+}
+
+static inline void to_dfu_mode(struct f_dfu *f_dfu)
+{
+	f_dfu->usb_function.strings = dfu_strings;
+	f_dfu->usb_function.hs_descriptors = f_dfu->function;
+}
+
+static inline void to_runtime_mode(struct f_dfu *f_dfu)
+{
+	f_dfu->usb_function.strings = NULL;
+	f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+}
+
+static int handle_upload(struct usb_request *req, u16 len)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	return dfu_read(dfu_get_entity(f_dfu->altsetting), req->buf,
+			req->length, f_dfu->blk_seq_num);
+}
+
+static int handle_dnload(struct usb_gadget *gadget, u16 len)
+{
+	struct usb_composite_dev *cdev = get_gadget_data(gadget);
+	struct usb_request *req = cdev->req;
+	struct f_dfu *f_dfu = req->context;
+
+	if (len == 0)
+		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
+
+	req->complete = dnload_request_complete;
+
+	return len;
+}
+
+/*-------------------------------------------------------------------------*/
+/* DFU state machine  */
+static int state_app_idle(struct f_dfu *f_dfu,
+			  const struct usb_ctrlrequest *ctrl,
+			  struct usb_gadget *gadget,
+			  struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	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:
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_app_detach(struct f_dfu *f_dfu,
+			    const struct usb_ctrlrequest *ctrl,
+			    struct usb_gadget *gadget,
+			    struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_appIDLE;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_idle(struct f_dfu *f_dfu,
+			  const struct usb_ctrlrequest *ctrl,
+			  struct usb_gadget *gadget,
+			  struct usb_request *req)
+{
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 len = le16_to_cpu(ctrl->wLength);
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_DNLOAD:
+		if (len == 0) {
+			f_dfu->dfu_state = DFU_STATE_dfuERROR;
+			value = RET_STALL;
+			break;
+		}
+		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
+		f_dfu->blk_seq_num = w_value;
+		value = handle_dnload(gadget, len);
+		break;
+	case USB_REQ_DFU_UPLOAD:
+		f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
+		f_dfu->blk_seq_num = 0;
+		value = handle_upload(req, len);
+		break;
+	case USB_REQ_DFU_ABORT:
+		/* no zlp? */
+		value = RET_ZLP;
+		break;
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	case USB_REQ_DFU_DETACH:
+		/*
+		 * Proprietary extension: 'detach' from idle mode and
+		 * get back to runtime mode in case of USB Reset.  As
+		 * much as I dislike this, we just can't use every USB
+		 * bus reset to switch back to runtime mode, since at
+		 * least the Linux USB stack likes to send a number of
+		 * resets in a row :(
+		 */
+		f_dfu->dfu_state =
+			DFU_STATE_dfuMANIFEST_WAIT_RST;
+		to_runtime_mode(f_dfu);
+		f_dfu->dfu_state = DFU_STATE_appIDLE;
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_dnload_sync(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_dnbusy(struct f_dfu *f_dfu,
+			    const struct usb_ctrlrequest *ctrl,
+			    struct usb_gadget *gadget,
+			    struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_dnload_idle(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 len = le16_to_cpu(ctrl->wLength);
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_DNLOAD:
+		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
+		f_dfu->blk_seq_num = w_value;
+		value = handle_dnload(gadget, len);
+		break;
+	case USB_REQ_DFU_ABORT:
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		value = RET_ZLP;
+		break;
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_manifest_sync(struct f_dfu *f_dfu,
+				   const struct usb_ctrlrequest *ctrl,
+				   struct usb_gadget *gadget,
+				   struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		/* We're MainfestationTolerant */
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		handle_getstatus(req);
+		f_dfu->blk_seq_num = 0;
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_upload_idle(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 len = le16_to_cpu(ctrl->wLength);
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_UPLOAD:
+		/* state transition if less data then requested */
+		f_dfu->blk_seq_num = w_value;
+		value = handle_upload(req, len);
+		if (value >= 0 && value < len)
+			f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		break;
+	case USB_REQ_DFU_ABORT:
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		/* no zlp? */
+		value = RET_ZLP;
+		break;
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_error(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	case USB_REQ_DFU_CLRSTATUS:
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		f_dfu->dfu_status = DFU_STATUS_OK;
+		/* no zlp? */
+		value = RET_ZLP;
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static dfu_state_fn dfu_state[] = {
+	state_app_idle,          /* DFU_STATE_appIDLE */
+	state_app_detach,        /* DFU_STATE_appDETACH */
+	state_dfu_idle,          /* DFU_STATE_dfuIDLE */
+	state_dfu_dnload_sync,   /* DFU_STATE_dfuDNLOAD_SYNC */
+	state_dfu_dnbusy,        /* DFU_STATE_dfuDNBUSY */
+	state_dfu_dnload_idle,   /* DFU_STATE_dfuDNLOAD_IDLE */
+	state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */
+	NULL,                    /* DFU_STATE_dfuMANIFEST */
+	NULL,                    /* DFU_STATE_dfuMANIFEST_WAIT_RST */
+	state_dfu_upload_idle,   /* DFU_STATE_dfuUPLOAD_IDLE */
+	state_dfu_error          /* DFU_STATE_dfuERROR */
+};
+
+static int
+dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct usb_gadget *gadget = f->config->cdev->gadget;
+	struct usb_request *req = f->config->cdev->req;
+	struct f_dfu *f_dfu = f->config->cdev->req->context;
+	u16 len = le16_to_cpu(ctrl->wLength);
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	int value = 0;
+	u8 req_type = ctrl->bRequestType & USB_TYPE_MASK;
+
+	debug("w_value: 0x%x len: 0x%x\n", w_value, len);
+	debug("req_type: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n",
+	       req_type, ctrl->bRequest, f_dfu->dfu_state);
+
+	if (req_type == USB_TYPE_STANDARD) {
+		if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR &&
+		    (w_value >> 8) == DFU_DT_FUNC) {
+			value = min(len, (u16) sizeof(dfu_func));
+			memcpy(req->buf, &dfu_func, value);
+		}
+	} else /* DFU specific request */
+		value = dfu_state[f_dfu->dfu_state] (f_dfu, ctrl, gadget, req);
+
+	if (value >= 0) {
+		req->length = value;
+		req->zero = value < len;
+		value = usb_ep_queue(gadget->ep0, req, 0);
+		if (value < 0) {
+			debug("ep_queue --> %d\n", value);
+			req->status = 0;
+		}
+	}
+
+	return value;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+dfu_prepare_strings(struct f_dfu *f_dfu, int n)
+{
+	struct dfu_entity *de = NULL;
+	int i = 0;
+
+	f_dfu->strings = calloc(sizeof(struct usb_string), n + 1);
+	if (!f_dfu->strings)
+		goto enomem;
+
+	for (i = 0; i < n; ++i) {
+		de = dfu_get_entity(i);
+		f_dfu->strings[i].s = de->name;
+	}
+
+	f_dfu->strings[i].id = 0;
+	f_dfu->strings[i].s = NULL;
+
+	return 0;
+
+enomem:
+	while (i)
+		f_dfu->strings[--i].s = NULL;
+
+	free(f_dfu->strings);
+
+	return -ENOMEM;
+}
+
+static int dfu_prepare_function(struct f_dfu *f_dfu, int n)
+{
+	struct usb_interface_descriptor *d;
+	int i = 0;
+
+	f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n);
+	if (!f_dfu->function)
+		goto enomem;
+
+	for (i = 0; i < n; ++i) {
+		d = calloc(sizeof(*d), 1);
+		if (!d)
+			goto enomem;
+
+		d->bLength =		sizeof(*d);
+		d->bDescriptorType =	USB_DT_INTERFACE;
+		d->bAlternateSetting =	i;
+		d->bNumEndpoints =	0;
+		d->bInterfaceClass =	USB_CLASS_APP_SPEC;
+		d->bInterfaceSubClass =	1;
+		d->bInterfaceProtocol =	2;
+
+		f_dfu->function[i] = (struct usb_descriptor_header *)d;
+	}
+	f_dfu->function[i] = NULL;
+
+	return 0;
+
+enomem:
+	while (i) {
+		free(f_dfu->function[--i]);
+		f_dfu->function[i] = NULL;
+	}
+	free(f_dfu->function);
+
+	return -ENOMEM;
+}
+
+static int dfu_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	int alt_num = dfu_get_alt_number();
+	int rv, id, i;
+
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	dfu_intf_runtime.bInterfaceNumber = id;
+
+	f_dfu->dfu_state = DFU_STATE_appIDLE;
+	f_dfu->dfu_status = DFU_STATUS_OK;
+
+	rv = dfu_prepare_function(f_dfu, alt_num);
+	if (rv)
+		goto error;
+
+	rv = dfu_prepare_strings(f_dfu, alt_num);
+	if (rv)
+		goto error;
+	for (i = 0; i < alt_num; i++) {
+		id = usb_string_id(cdev);
+		if (id < 0)
+			return id;
+		f_dfu->strings[i].id = id;
+		((struct usb_interface_descriptor *)f_dfu->function[i])
+			->iInterface = id;
+	}
+
+	stringtab_dfu.strings = f_dfu->strings;
+
+	cdev->req->context = f_dfu;
+
+error:
+	return rv;
+}
+
+static void dfu_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	int alt_num = dfu_get_alt_number();
+	int i;
+
+	if (f_dfu->strings) {
+		i = alt_num;
+		while (i)
+			f_dfu->strings[--i].s = NULL;
+
+		free(f_dfu->strings);
+	}
+
+	if (f_dfu->function) {
+		i = alt_num;
+		while (i) {
+			free(f_dfu->function[--i]);
+			f_dfu->function[i] = NULL;
+		}
+		free(f_dfu->function);
+	}
+
+	free(f_dfu);
+}
+
+static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+
+	debug("%s: intf:%d alt:%d\n", __func__, intf, alt);
+
+	f_dfu->altsetting = alt;
+
+	return 0;
+}
+
+/* TODO: is this really what we need here? */
+static void dfu_disable(struct usb_function *f)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	if (f_dfu->config == 0)
+		return;
+
+	debug("%s: reset config\n", __func__);
+
+	f_dfu->config = 0;
+}
+
+static int dfu_bind_config(struct usb_configuration *c)
+{
+	struct f_dfu *f_dfu;
+	int status;
+
+	f_dfu = calloc(sizeof(*f_dfu), 1);
+	if (!f_dfu)
+		return -ENOMEM;
+	f_dfu->usb_function.name = "dfu";
+	f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+	f_dfu->usb_function.bind = dfu_bind;
+	f_dfu->usb_function.unbind = dfu_unbind;
+	f_dfu->usb_function.set_alt = dfu_set_alt;
+	f_dfu->usb_function.disable = dfu_disable;
+	f_dfu->usb_function.strings = dfu_generic_strings,
+	f_dfu->usb_function.setup = dfu_handle,
+
+	status = usb_add_function(c, &f_dfu->usb_function);
+	if (status)
+		free(f_dfu);
+
+	return status;
+}
+
+int dfu_add(struct usb_configuration *c)
+{
+	int id;
+
+	id = usb_string_id(c->cdev);
+	if (id < 0)
+		return id;
+	strings_dfu_generic[0].id = id;
+	dfu_intf_runtime.iInterface = id;
+
+	debug("%s: cdev: 0x%p gadget:0x%p gadget->ep0: 0x%p\n", __func__,
+	       c->cdev, c->cdev->gadget, c->cdev->gadget->ep0);
+
+	return dfu_bind_config(c);
+}
diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h
new file mode 100644
index 0000000..023e1ad
--- /dev/null
+++ b/drivers/usb/gadget/f_dfu.h
@@ -0,0 +1,100 @@
+/*
+ * f_dfu.h -- Device Firmware Update gadget
+ *
+ * Copyright (C) 2011-2012 Samsung Electronics
+ * author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __F_DFU_H_
+#define __F_DFU_H_
+
+#include <linux/compiler.h>
+#include <linux/usb/composite.h>
+
+#define DFU_CONFIG_VAL			1
+#define DFU_DT_FUNC			0x21
+
+#define DFU_BIT_WILL_DETACH		(0x1 << 3)
+#define DFU_BIT_MANIFESTATION_TOLERANT	(0x1 << 2)
+#define DFU_BIT_CAN_UPLOAD		(0x1 << 1)
+#define DFU_BIT_CAN_DNLOAD		0x1
+
+/* big enough to hold our biggest descriptor */
+#define DFU_USB_BUFSIZ			4096
+
+#define USB_REQ_DFU_DETACH		0x00
+#define USB_REQ_DFU_DNLOAD		0x01
+#define USB_REQ_DFU_UPLOAD		0x02
+#define USB_REQ_DFU_GETSTATUS		0x03
+#define USB_REQ_DFU_CLRSTATUS		0x04
+#define USB_REQ_DFU_GETSTATE		0x05
+#define USB_REQ_DFU_ABORT		0x06
+
+#define DFU_STATUS_OK			0x00
+#define DFU_STATUS_errTARGET		0x01
+#define DFU_STATUS_errFILE		0x02
+#define DFU_STATUS_errWRITE		0x03
+#define DFU_STATUS_errERASE		0x04
+#define DFU_STATUS_errCHECK_ERASED	0x05
+#define DFU_STATUS_errPROG		0x06
+#define DFU_STATUS_errVERIFY		0x07
+#define DFU_STATUS_errADDRESS		0x08
+#define DFU_STATUS_errNOTDONE		0x09
+#define DFU_STATUS_errFIRMWARE		0x0a
+#define DFU_STATUS_errVENDOR		0x0b
+#define DFU_STATUS_errUSBR		0x0c
+#define DFU_STATUS_errPOR		0x0d
+#define DFU_STATUS_errUNKNOWN		0x0e
+#define DFU_STATUS_errSTALLEDPKT	0x0f
+
+#define RET_STALL			-1
+#define RET_ZLP				0
+#define RET_STAT_LEN			6
+
+enum dfu_state {
+	DFU_STATE_appIDLE		= 0,
+	DFU_STATE_appDETACH		= 1,
+	DFU_STATE_dfuIDLE		= 2,
+	DFU_STATE_dfuDNLOAD_SYNC	= 3,
+	DFU_STATE_dfuDNBUSY		= 4,
+	DFU_STATE_dfuDNLOAD_IDLE	= 5,
+	DFU_STATE_dfuMANIFEST_SYNC	= 6,
+	DFU_STATE_dfuMANIFEST		= 7,
+	DFU_STATE_dfuMANIFEST_WAIT_RST	= 8,
+	DFU_STATE_dfuUPLOAD_IDLE	= 9,
+	DFU_STATE_dfuERROR		= 10,
+};
+
+struct dfu_status {
+	__u8				bStatus;
+	__u8				bwPollTimeout[3];
+	__u8				bState;
+	__u8				iString;
+} __packed;
+
+struct dfu_function_descriptor {
+	__u8				bLength;
+	__u8				bDescriptorType;
+	__u8				bmAttributes;
+	__le16				wDetachTimeOut;
+	__le16				wTransferSize;
+	__le16				bcdDFUVersion;
+} __packed;
+
+/* configuration-specific linkup */
+int dfu_add(struct usb_configuration *c);
+#endif /* __F_DFU_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v4 3/7] dfu: DFU backend implementation
  2012-08-03  7:45 ` [U-Boot] [PATCH v4 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
@ 2012-08-03  7:45   ` Lukasz Majewski
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-03  7:45 UTC (permalink / raw)
  To: u-boot

New, separate driver at ./drivers/dfu has been added. It allows platform
and storage independent operation of DFU.
It has been extended to use new MMC level of command abstraction.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:
- None

Changes for v3:
- Remove unnecessary NULL and 0 initialization of dynamic variables
- Combine two puts to one
- Adding const qualifier to device and layout definitions
- Remove unnecessary casting at dfu->name passing
- Provide more meaningful names for dfu layouts and device types
- Removal of dfu_extract_{token|entity} functions and replace them
  with strsep calls

Changes for v4:
- Remove unnecessary memset
- const added where applicable
- Handling calloc failure in dfu_config_entries()
---
 Makefile             |    1 +
 drivers/dfu/Makefile |   43 +++++++++
 drivers/dfu/dfu.c    |  239 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/dfu.h        |  103 ++++++++++++++++++++++
 4 files changed, 386 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dfu/Makefile
 create mode 100644 drivers/dfu/dfu.c
 create mode 100644 include/dfu.h

diff --git a/Makefile b/Makefile
index eb37ea1..67c627d 100644
--- a/Makefile
+++ b/Makefile
@@ -271,6 +271,7 @@ LIBS += drivers/pci/libpci.o
 LIBS += drivers/pcmcia/libpcmcia.o
 LIBS += drivers/power/libpower.o
 LIBS += drivers/spi/libspi.o
+LIBS += drivers/dfu/libdfu.o
 ifeq ($(CPU),mpc83xx)
 LIBS += drivers/qe/libqe.o
 LIBS += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o
diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
new file mode 100644
index 0000000..7736485
--- /dev/null
+++ b/drivers/dfu/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2012 Samsung Electronics
+# Lukasz Majewski <l.majewski@samsung.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)libdfu.o
+
+COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
+
+SRCS    := $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
new file mode 100644
index 0000000..36d7bee
--- /dev/null
+++ b/drivers/dfu/dfu.c
@@ -0,0 +1,239 @@
+/*
+ * dfu.c -- DFU back-end routines
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * author: Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <fat.h>
+#include <dfu.h>
+#include <linux/list.h>
+#include <linux/compiler.h>
+
+static LIST_HEAD(dfu_list);
+static int dfu_alt_num;
+
+static int dfu_find_alt_num(const char *s)
+{
+	int i = 0;
+
+	for (; *s; s++)
+		if (*s == ';')
+			i++;
+
+	return ++i;
+}
+
+static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
+				     dfu_buf[DFU_DATA_BUF_SIZE];
+
+int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
+{
+	static unsigned char *i_buf;
+	static int i_blk_seq_num;
+	long w_size = 0;
+	int ret = 0;
+
+	debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
+	       __func__, dfu->name, buf, size, blk_seq_num, i_buf);
+
+	if (blk_seq_num == 0) {
+		i_buf = dfu_buf;
+		i_blk_seq_num = 0;
+	}
+
+	if (i_blk_seq_num++ != blk_seq_num) {
+		printf("%s: Wrong sequence number! [%d] [%d]\n",
+		       __func__, i_blk_seq_num, blk_seq_num);
+		return -1;
+	}
+
+	memcpy(i_buf, buf, size);
+	i_buf += size;
+
+	if (size == 0) {
+		/* Integrity check (if needed) */
+		debug("%s: %s %d [B] CRC32: 0x%x\n", __func__, dfu->name,
+		       i_buf - dfu_buf, crc32(0, dfu_buf, i_buf - dfu_buf));
+
+		w_size = i_buf - dfu_buf;
+		ret = dfu->write_medium(dfu, dfu_buf, &w_size);
+		if (ret)
+			debug("%s: Write error!\n", __func__);
+
+		i_blk_seq_num = 0;
+		i_buf = NULL;
+		return ret;
+	}
+
+	return ret;
+}
+
+int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
+{
+	static unsigned char *i_buf;
+	static int i_blk_seq_num;
+	static long r_size;
+	static u32 crc;
+	int ret = 0;
+
+	debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
+	       __func__, dfu->name, buf, size, blk_seq_num, i_buf);
+
+	if (blk_seq_num == 0) {
+		i_buf = dfu_buf;
+		ret = dfu->read_medium(dfu, i_buf, &r_size);
+		debug("%s: %s %ld [B]\n", __func__, dfu->name, r_size);
+		i_blk_seq_num = 0;
+		/* Integrity check (if needed) */
+		crc = crc32(0, dfu_buf, r_size);
+	}
+
+	if (i_blk_seq_num++ != blk_seq_num) {
+		printf("%s: Wrong sequence number! [%d] [%d]\n",
+		       __func__, i_blk_seq_num, blk_seq_num);
+		return -1;
+	}
+
+	if (r_size >= size) {
+		memcpy(buf, i_buf, size);
+		i_buf += size;
+		r_size -= size;
+		return size;
+	} else {
+		memcpy(buf, i_buf, r_size);
+		i_buf += r_size;
+		debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name, crc);
+		puts("UPLOAD ... done\nCtrl+C to exit ...\n");
+
+		i_buf = NULL;
+		i_blk_seq_num = 0;
+		crc = 0;
+		return r_size;
+	}
+	return ret;
+}
+
+static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt,
+			    char *interface, int num)
+{
+	char *st;
+
+	debug("%s: %s interface: %s num: %d\n", __func__, s, interface, num);
+	st = strsep(&s, " ");
+	strcpy(dfu->name, st);
+
+	dfu->dev_num = num;
+	dfu->alt = alt;
+
+	/* Specific for mmc device */
+	if (strcmp(interface, "mmc") == 0) {
+		if (dfu_fill_entity_mmc(dfu, s))
+			return -1;
+	} else {
+		printf("%s: Device %s not (yet) supported!\n",
+		       __func__,  interface);
+		return -1;
+	}
+
+	return 0;
+}
+
+void dfu_free_entities(void)
+{
+	struct dfu_entity *dfu, *p;
+
+	list_for_each_entry_safe_reverse(dfu, p, &dfu_list, list) {
+		list_del(&dfu->list);
+		free(dfu);
+	}
+
+	INIT_LIST_HEAD(&dfu_list);
+}
+
+int dfu_config_entities(char *env, char *interface, int num)
+{
+	struct dfu_entity *dfu;
+	int i, ret;
+	char *s;
+
+	dfu_alt_num = dfu_find_alt_num(env);
+	debug("%s: dfu_alt_num=%d\n", __func__, dfu_alt_num);
+
+	for (i = 0; i < dfu_alt_num; i++) {
+		dfu = calloc(sizeof(struct dfu_entity), 1);
+		if (!dfu) {
+			dfu_free_entities();
+			return -1;
+		}
+
+		s = strsep(&env, ";");
+		ret = dfu_fill_entity(dfu, s, i, interface, num);
+		if (ret)
+			return -1;
+
+		list_add_tail(&dfu->list, &dfu_list);
+	}
+
+	return 0;
+}
+
+const char *dfu_get_dev_type(enum dfu_device_type t)
+{
+	const char *dev_t[] = {NULL, "eMMC", "OneNAND", "NAND" };
+	return dev_t[t];
+}
+
+const char *dfu_get_layout(enum dfu_layout l)
+{
+	const char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2",
+					   "EXT3", "EXT4" };
+	return dfu_layout[l];
+}
+
+void dfu_show_entities(void)
+{
+	struct dfu_entity *dfu;
+
+	puts("DFU alt settings list:\n");
+
+	list_for_each_entry(dfu, &dfu_list, list) {
+		printf("dev: %s alt: %d name: %s layout: %s\n",
+		       dfu_get_dev_type(dfu->dev_type), dfu->alt,
+		       dfu->name, dfu_get_layout(dfu->layout));
+	}
+}
+
+int dfu_get_alt_number(void)
+{
+	return dfu_alt_num;
+}
+
+struct dfu_entity *dfu_get_entity(int alt)
+{
+	struct dfu_entity *dfu;
+
+	list_for_each_entry(dfu, &dfu_list, list) {
+		if (dfu->alt == alt)
+			return dfu;
+	}
+
+	return NULL;
+}
diff --git a/include/dfu.h b/include/dfu.h
new file mode 100644
index 0000000..5350d79
--- /dev/null
+++ b/include/dfu.h
@@ -0,0 +1,103 @@
+/*
+ * dfu.h - DFU flashable area description
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __DFU_ENTITY_H_
+#define __DFU_ENTITY_H_
+
+#include <common.h>
+#include <linux/list.h>
+#include <mmc.h>
+
+enum dfu_device_type {
+	DFU_DEV_MMC = 1,
+	DFU_DEV_ONENAND,
+	DFU_DEV_NAND,
+};
+
+enum dfu_layout {
+	DFU_RAW_ADDR = 1,
+	DFU_FS_FAT,
+	DFU_FS_EXT2,
+	DFU_FS_EXT3,
+	DFU_FS_EXT4,
+};
+
+struct mmc_internal_data {
+	/* RAW programming */
+	unsigned int lba_start;
+	unsigned int lba_size;
+	unsigned int lba_blk_size;
+
+	/* FAT/EXT */
+	unsigned int dev;
+	unsigned int part;
+};
+
+static inline unsigned int get_mmc_blk_size(int dev)
+{
+	return find_mmc_device(dev)->read_bl_len;
+}
+
+#define DFU_NAME_SIZE 32
+#define DFU_CMD_BUF_SIZE 128
+#define DFU_DATA_BUF_SIZE (1024*1024*4) /* 4 MiB */
+
+struct dfu_entity {
+	char			name[DFU_NAME_SIZE];
+	int                     alt;
+	void                    *dev_private;
+	int                     dev_num;
+	enum dfu_device_type    dev_type;
+	enum dfu_layout         layout;
+
+	union {
+		struct mmc_internal_data mmc;
+	} data;
+
+	int (*read_medium)(struct dfu_entity *dfu, void *buf, long *len);
+	int (*write_medium)(struct dfu_entity *dfu, void *buf, long *len);
+
+	struct list_head list;
+};
+
+int dfu_config_entities(char *s, char *interface, int num);
+void dfu_free_entities(void);
+void dfu_show_entities(void);
+int dfu_get_alt_number(void);
+const char *dfu_get_dev_type(enum dfu_device_type t);
+const char *dfu_get_layout(enum dfu_layout l);
+struct dfu_entity *dfu_get_entity(int alt);
+char *dfu_extract_token(char** e, int *n);
+
+int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
+int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
+/* Device specific */
+#ifdef CONFIG_DFU_MMC
+extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s);
+#else
+static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
+{
+	puts("MMC support not available!\n");
+	return -1;
+}
+#endif
+#endif /* __DFU_ENTITY_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v4 4/7] dfu: MMC specific routines for DFU operation
  2012-08-03  7:45 ` [U-Boot] [PATCH v4 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                     ` (2 preceding siblings ...)
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 3/7] dfu: DFU backend implementation Lukasz Majewski
@ 2012-08-03  7:45   ` Lukasz Majewski
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-03  7:45 UTC (permalink / raw)
  To: u-boot

Support for MMC storage devices to work with DFU framework.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:
- None

Changes for v3:
- Provide special abstraction layer (mmc_{block|file}_{read|write})
  to alleviate switch to new device model (DM)
- More verbose messages when not supported layout encountered
- Calls to strncmp() replaced with strcmp()

Changes for v4:
- Remove superfluous memset() calls
- Replace ALLOC_CACHE_ALIGN_BUFFER with plain table definition
- Cosmetic changes with pointers definition
---
 drivers/dfu/Makefile  |    1 +
 drivers/dfu/dfu_mmc.c |  162 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 163 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dfu/dfu_mmc.c

diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
index 7736485..7b717bc 100644
--- a/drivers/dfu/Makefile
+++ b/drivers/dfu/Makefile
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)libdfu.o
 
 COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
+COBJS-$(CONFIG_DFU_MMC) += dfu_mmc.o
 
 SRCS    := $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS-y))
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
new file mode 100644
index 0000000..060145b
--- /dev/null
+++ b/drivers/dfu/dfu_mmc.c
@@ -0,0 +1,162 @@
+/*
+ * dfu.c -- DFU back-end routines
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * author: Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <dfu.h>
+
+enum dfu_mmc_op {
+	DFU_OP_READ = 1,
+	DFU_OP_WRITE,
+};
+
+static int mmc_block_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
+			void *buf, long *len)
+{
+	char cmd_buf[DFU_CMD_BUF_SIZE];
+
+	sprintf(cmd_buf, "mmc %s 0x%x %x %x",
+		op == DFU_OP_READ ? "read" : "write",
+		(unsigned int) buf,
+		dfu->data.mmc.lba_start,
+		dfu->data.mmc.lba_size);
+
+	if (op == DFU_OP_READ)
+		*len = dfu->data.mmc.lba_blk_size * dfu->data.mmc.lba_size;
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+	return run_command(cmd_buf, 0);
+}
+
+static inline int mmc_block_write(struct dfu_entity *dfu, void *buf, long *len)
+{
+	return mmc_block_op(DFU_OP_WRITE, dfu, buf, len);
+}
+
+static inline int mmc_block_read(struct dfu_entity *dfu, void *buf, long *len)
+{
+	return mmc_block_op(DFU_OP_READ, dfu, buf, len);
+}
+
+static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
+			void *buf, long *len)
+{
+	char cmd_buf[DFU_CMD_BUF_SIZE];
+	char *str_env;
+	int ret;
+
+	sprintf(cmd_buf, "fat%s mmc %d:%d 0x%x %s %lx",
+		op == DFU_OP_READ ? "load" : "write",
+		dfu->data.mmc.dev, dfu->data.mmc.part,
+		(unsigned int) buf, dfu->name, *len);
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+
+	ret = run_command(cmd_buf, 0);
+	if (ret) {
+		puts("dfu: Read error!\n");
+		return ret;
+	}
+
+	if (dfu->layout != DFU_RAW_ADDR) {
+		str_env = getenv("filesize");
+		if (str_env == NULL) {
+			puts("dfu: Wrong file size!\n");
+			return -1;
+		}
+		*len = simple_strtoul(str_env, NULL, 16);
+	}
+
+	return ret;
+}
+
+static inline int mmc_file_write(struct dfu_entity *dfu, void *buf, long *len)
+{
+	return mmc_file_op(DFU_OP_WRITE, dfu, buf, len);
+}
+
+static inline int mmc_file_read(struct dfu_entity *dfu, void *buf, long *len)
+{
+	return mmc_file_op(DFU_OP_READ, dfu, buf, len);
+}
+
+int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
+{
+	int ret = -1;
+
+	switch (dfu->layout) {
+	case DFU_RAW_ADDR:
+		ret = mmc_block_write(dfu, buf, len);
+		break;
+	case DFU_FS_FAT:
+		ret = mmc_file_write(dfu, buf, len);
+		break;
+	default:
+		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
+		       dfu_get_layout(dfu->layout));
+	}
+
+	return ret;
+}
+
+int dfu_read_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
+{
+	int ret = -1;
+
+	switch (dfu->layout) {
+	case DFU_RAW_ADDR:
+		ret = mmc_block_read(dfu, buf, len);
+		break;
+	case DFU_FS_FAT:
+		ret = mmc_file_read(dfu, buf, len);
+		break;
+	default:
+		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
+		       dfu_get_layout(dfu->layout));
+	}
+
+	return ret;
+}
+
+int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
+{
+	char *st;
+
+	dfu->dev_type = DFU_DEV_MMC;
+	st = strsep(&s, " ");
+	if (!strcmp(st, "mmc")) {
+		dfu->layout = DFU_RAW_ADDR;
+		dfu->data.mmc.lba_start = simple_strtoul(s, &s, 16);
+		dfu->data.mmc.lba_size = simple_strtoul(++s, &s, 16);
+		dfu->data.mmc.lba_blk_size = get_mmc_blk_size(dfu->dev_num);
+	} else if (!strcmp(st, "fat")) {
+		dfu->layout = DFU_FS_FAT;
+		dfu->data.mmc.dev = simple_strtoul(s, &s, 10);
+		dfu->data.mmc.part = simple_strtoul(++s, &s, 10);
+	} else {
+		printf("%s: Memory layout (%s) not supported!\n", __func__, st);
+	}
+
+	dfu->read_medium = dfu_read_medium_mmc;
+	dfu->write_medium = dfu_write_medium_mmc;
+
+	return 0;
+}
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v4 5/7] dfu:cmd: Support for DFU u-boot command
  2012-08-03  7:45 ` [U-Boot] [PATCH v4 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                     ` (3 preceding siblings ...)
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
@ 2012-08-03  7:45   ` Lukasz Majewski
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
  6 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-03  7:45 UTC (permalink / raw)
  To: u-boot

Support for u-boot's command line command "dfu <interface> <dev> [list]".

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:
- None

Changes for v3:
- Remove unnecessary initialization to NULL of dynamic variables
- goto done added to reduce code duplication
- static definition of do_dfu()

Changes for v4:
- Define "dfu" string as an array
---
 common/Makefile  |    1 +
 common/cmd_dfu.c |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+), 0 deletions(-)
 create mode 100644 common/cmd_dfu.c

diff --git a/common/Makefile b/common/Makefile
index 483eb4d..32d44e5 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -183,6 +183,7 @@ COBJS-$(CONFIG_MENU) += menu.o
 COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o
 COBJS-$(CONFIG_UPDATE_TFTP) += update.o
 COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
+COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o
 endif
 
 ifdef CONFIG_SPL_BUILD
diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
new file mode 100644
index 0000000..62fb890
--- /dev/null
+++ b/common/cmd_dfu.c
@@ -0,0 +1,81 @@
+/*
+ * cmd_dfu.c -- dfu command
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <dfu.h>
+#include <asm/errno.h>
+#include <g_dnl.h>
+
+static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	const char *str_env;
+	char s[] = "dfu";
+	char *env_bkp;
+	int ret;
+
+	if (argc < 3)
+		return CMD_RET_USAGE;
+
+	str_env = getenv("dfu_alt_info");
+	if (str_env == NULL) {
+		printf("%s: \"dfu_alt_info\" env variable not defined!\n",
+		       __func__);
+		return CMD_RET_FAILURE;
+	}
+
+	env_bkp = strdup(str_env);
+	ret = dfu_config_entities(env_bkp, argv[1],
+			    (int)simple_strtoul(argv[2], NULL, 10));
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	if (strcmp(argv[3], "list") == 0) {
+		dfu_show_entities();
+		goto done;
+	}
+
+	board_usb_init();
+	g_dnl_register(s);
+	while (1) {
+		if (ctrlc())
+			goto exit;
+
+		usb_gadget_handle_interrupts();
+	}
+exit:
+	g_dnl_unregister();
+done:
+	dfu_free_entities();
+	free(env_bkp);
+
+	return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu,
+	"Device Firmware Upgrade",
+	"<interface> <dev> [list]\n"
+	"  - device firmware upgrade on a device <dev>\n"
+	"    attached to interface <interface>\n"
+	"    [list] - list available alt settings"
+);
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v4 6/7] arm:trats: Support for USB UDC driver at TRATS board.
  2012-08-03  7:45 ` [U-Boot] [PATCH v4 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                     ` (4 preceding siblings ...)
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
@ 2012-08-03  7:45   ` Lukasz Majewski
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
  6 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-03  7:45 UTC (permalink / raw)
  To: u-boot

Support for USB UDC driver at trats board.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Minkyu Kang <mk7.kang@samsung.com>

---
Changes for v2:
- replace puts to debug
---
 board/samsung/trats/trats.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/board/samsung/trats/trats.c b/board/samsung/trats/trats.c
index a8b2b11..4f9cb5a 100644
--- a/board/samsung/trats/trats.c
+++ b/board/samsung/trats/trats.c
@@ -59,6 +59,8 @@ static int hwrevision(int rev)
 	return (board_rev & 0xf) == rev;
 }
 
+struct s3c_plat_otg_data s5pc210_otg_data;
+
 int board_init(void)
 {
 	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
@@ -259,6 +261,12 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
 	.usb_phy_ctrl	= EXYNOS4_USBPHY_CONTROL,
 	.usb_flags	= PHY0_SLEEP,
 };
+
+void board_usb_init(void)
+{
+	debug("USB_udc_probe\n");
+	s3c_udc_probe(&s5pc210_otg_data);
+}
 #endif
 
 static void pmic_reset(void)
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v4 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS
  2012-08-03  7:45 ` [U-Boot] [PATCH v4 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                     ` (5 preceding siblings ...)
  2012-08-03  7:45   ` [U-Boot] [PATCH v4 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
@ 2012-08-03  7:45   ` Lukasz Majewski
  6 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-03  7:45 UTC (permalink / raw)
  To: u-boot

Enable the g_dnl composite USB gadget driver with embedded DFU function on it.
It now uses the composite gadget framework to support download specific
USB functions (like enabled DFU or USB Mass Storage).

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Minkyu Kang <mk7.kang@samsung.com>

---
Change for v2:
- Move the G_DNL_{VENDOR_NUM, PRODUCT_NUM and MANUFACTURER} definitions to
  ./include/configs/<board>.h

Changes for v3:
- None
---
 include/configs/trats.h |   24 +++++++++++++++++++++++-
 1 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/include/configs/trats.h b/include/configs/trats.h
index eb269b2..75a23b0 100644
--- a/include/configs/trats.h
+++ b/include/configs/trats.h
@@ -94,6 +94,21 @@
 #undef CONFIG_CMD_ONENAND
 #undef CONFIG_CMD_MTDPARTS
 #define CONFIG_CMD_MMC
+#define CONFIG_CMD_DFU
+
+/* FAT */
+#define CONFIG_CMD_FAT
+#define CONFIG_FAT_WRITE
+
+/* USB Composite download gadget - g_dnl */
+#define CONFIG_USBDOWNLOAD_GADGET
+#define CONFIG_DFU_FUNCTION
+#define CONFIG_DFU_MMC
+
+/* USB Samsung's IDs */
+#define CONFIG_G_DNL_VENDOR_NUM 0x04E8
+#define CONFIG_G_DNL_PRODUCT_NUM 0x6601
+#define CONFIG_G_DNL_MANUFACTURER "Samsung"
 
 #define CONFIG_BOOTDELAY		1
 #define CONFIG_ZERO_BOOTDELAY_CHECK
@@ -104,6 +119,11 @@
 #define CONFIG_BOOTBLOCK		"10"
 #define CONFIG_ENV_COMMON_BOOT		"${console} ${meminfo}"
 
+#define CONFIG_DFU_ALT \
+	"dfu_alt_info=" \
+	"u-boot mmc 80 400;" \
+	"uImage fat 0 2\0" \
+
 #define CONFIG_ENV_OVERWRITE
 #define CONFIG_SYS_CONSOLE_INFO_QUIET
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
@@ -146,7 +166,8 @@
 	"mmcdev=0\0" \
 	"mmcbootpart=2\0" \
 	"mmcrootpart=3\0" \
-	"opts=always_resume=1"
+	"opts=always_resume=1\0" \
+	CONFIG_DFU_ALT
 
 /* Miscellaneous configurable options */
 #define CONFIG_SYS_LONGHELP		/* undef to save memory */
@@ -209,6 +230,7 @@
 #define CONFIG_USB_GADGET
 #define CONFIG_USB_GADGET_S3C_UDC_OTG
 #define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_GADGET_VBUS_DRAW	2
 
 /* LCD */
 #define CONFIG_EXYNOS_FB
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command
  2012-08-03  6:13               ` Lukasz Majewski
@ 2012-08-03 15:32                 ` Stephen Warren
  2012-08-06  7:13                   ` Lukasz Majewski
  0 siblings, 1 reply; 147+ messages in thread
From: Stephen Warren @ 2012-08-03 15:32 UTC (permalink / raw)
  To: u-boot

On 08/03/2012 12:13 AM, Lukasz Majewski wrote:
> Dear Stephen Warren,
> 
>> Again, this is confusing two different kinds of partitions.
>>
>> There are HW-level partitions/regions/areas within the eMMC HW itself.
>> You need to send commands to the eMMC device to select whether
>> read/write commands act on the boot0/boot1/general*/user HW partition.
> 
> This will be done via "mmc boot [dev] [HW partition (boot0/1/user]"
> command (from u-boot prompt).

Hmm. I still fail to see how this is any different to the existing "mmc
dev" command. Are the following two commands not exactly identical:

mmc dev $dev $part      # already exists today
mmc boot $dev $part     # new command you're proposing

?

> This command is not yet implemented at u-boot (at least for Trats
> development board).
> After its implementation it will be used as a helper function for dfu.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 3/7] dfu: DFU backend implementation
  2012-08-02 13:55       ` Lukasz Majewski
@ 2012-08-03 23:19         ` Mike Frysinger
  2012-08-04  7:47           ` Marek Vasut
  0 siblings, 1 reply; 147+ messages in thread
From: Mike Frysinger @ 2012-08-03 23:19 UTC (permalink / raw)
  To: u-boot

On Thursday 02 August 2012 09:55:24 Lukasz Majewski wrote:
> Dear Mike Frysinger,
> > On Tuesday 31 July 2012 02:36:59 Lukasz Majewski wrote:
> > > +{
> > > +	int i = 0;
> > > +
> > > +	for (; *s; s++)
> > > +		if (*s == ';')
> > > +			i++;
> > > +
> > > +	return ++i;
> > > +}
> 
> In this function I count how many times the ';' separator appears.

well, to be more specific, i think it's counting the number of elements if you 
were to split on ';'.  so if there was one ';', this would return 2.  but 
you're correct of course that my suggested replacement is not equivalent.

> > > +int dfu_config_entities(char *env, char *interface, int num)
> > > +{
> > > +	struct dfu_entity *dfu;
> > > +	int i, ret;
> > > +	char *s;
> > > +
> > > +	dfu_alt_num = dfu_find_alt_num(env);
> > > +	debug("%s: dfu_alt_num=%d\n", __func__, dfu_alt_num);
> > > +
> > > +	for (i = 0; i < dfu_alt_num; i++) {
> > > +		dfu = calloc(sizeof(struct dfu_entity), 1);
> > 
> > seems like you can do this in a single call outside of the for loop:
> > 	dfu = calloc(sizeof(*dfu), dfu_alt_num);
> > 	if (!dfu)
> > 	
> > 		return -1;
> > 	
> > 	for (i = 0; i < dfu_alt_num; i++) {
> > 	
> > 		s = strsep(&env, ";");
> > 		ret = dfu_fill_entity(&dfu[i], s, i, interface, num);
> > 		if (ret)
> > 		
> > 			return -1;
> > 		
> > 		list_add_tail(&dfu[i].list, &dfu_list);
> > 	
> > 	}
> 
> I'd prefer to leave it as it is (since IMHO is more readable) with the
> addition of following code:

it might be more slightly more readable, but doing a single function call 
results in better runtime performance
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120803/55145bc3/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 3/7] dfu: DFU backend implementation
  2012-08-03 23:19         ` Mike Frysinger
@ 2012-08-04  7:47           ` Marek Vasut
  2012-08-04 16:28             ` Mike Frysinger
  0 siblings, 1 reply; 147+ messages in thread
From: Marek Vasut @ 2012-08-04  7:47 UTC (permalink / raw)
  To: u-boot

Dear Mike Frysinger,

> On Thursday 02 August 2012 09:55:24 Lukasz Majewski wrote:
> > Dear Mike Frysinger,
> > 
> > > On Tuesday 31 July 2012 02:36:59 Lukasz Majewski wrote:
> > > > +{
> > > > +	int i = 0;
> > > > +
> > > > +	for (; *s; s++)
> > > > +		if (*s == ';')
> > > > +			i++;
> > > > +
> > > > +	return ++i;
> > > > +}
> > 
> > In this function I count how many times the ';' separator appears.
> 
> well, to be more specific, i think it's counting the number of elements if
> you were to split on ';'.  so if there was one ';', this would return 2. 
> but you're correct of course that my suggested replacement is not
> equivalent.
> 
> > > > +int dfu_config_entities(char *env, char *interface, int num)
> > > > +{
> > > > +	struct dfu_entity *dfu;
> > > > +	int i, ret;
> > > > +	char *s;
> > > > +
> > > > +	dfu_alt_num = dfu_find_alt_num(env);
> > > > +	debug("%s: dfu_alt_num=%d\n", __func__, dfu_alt_num);
> > > > +
> > > > +	for (i = 0; i < dfu_alt_num; i++) {
> > > > +		dfu = calloc(sizeof(struct dfu_entity), 1);
> > > 
> > > seems like you can do this in a single call outside of the for loop:
> > > 	dfu = calloc(sizeof(*dfu), dfu_alt_num);
> > > 	if (!dfu)
> > > 	
> > > 		return -1;
> > > 	
> > > 	for (i = 0; i < dfu_alt_num; i++) {
> > > 	
> > > 		s = strsep(&env, ";");
> > > 		ret = dfu_fill_entity(&dfu[i], s, i, interface, num);
> > > 		if (ret)
> > > 		
> > > 			return -1;
> > > 		
> > > 		list_add_tail(&dfu[i].list, &dfu_list);
> > > 	
> > > 	}
> > 
> > I'd prefer to leave it as it is (since IMHO is more readable) with the
> 
> > addition of following code:
> it might be more slightly more readable, but doing a single function call
> results in better runtime performance

Doesn't the compiler optimize it as it sees fit?

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 3/7] dfu: DFU backend implementation
  2012-08-04  7:47           ` Marek Vasut
@ 2012-08-04 16:28             ` Mike Frysinger
  0 siblings, 0 replies; 147+ messages in thread
From: Mike Frysinger @ 2012-08-04 16:28 UTC (permalink / raw)
  To: u-boot

On Saturday 04 August 2012 03:47:34 Marek Vasut wrote:
> Dear Mike Frysinger,
> > On Thursday 02 August 2012 09:55:24 Lukasz Majewski wrote:
> > > Dear Mike Frysinger,
> > > > On Tuesday 31 July 2012 02:36:59 Lukasz Majewski wrote:
> > > > > +int dfu_config_entities(char *env, char *interface, int num)
> > > > > +{
> > > > > +	struct dfu_entity *dfu;
> > > > > +	int i, ret;
> > > > > +	char *s;
> > > > > +
> > > > > +	dfu_alt_num = dfu_find_alt_num(env);
> > > > > +	debug("%s: dfu_alt_num=%d\n", __func__, dfu_alt_num);
> > > > > +
> > > > > +	for (i = 0; i < dfu_alt_num; i++) {
> > > > > +		dfu = calloc(sizeof(struct dfu_entity), 1);
> > > > 
> > > > seems like you can do this in a single call outside of the for loop:
> > > > 	dfu = calloc(sizeof(*dfu), dfu_alt_num);
> > > > 	if (!dfu)
> > > > 	
> > > > 		return -1;
> > > > 	
> > > > 	for (i = 0; i < dfu_alt_num; i++) {
> > > > 	
> > > > 		s = strsep(&env, ";");
> > > > 		ret = dfu_fill_entity(&dfu[i], s, i, interface, num);
> > > > 		if (ret)
> > > > 		
> > > > 			return -1;
> > > > 		
> > > > 		list_add_tail(&dfu[i].list, &dfu_list);
> > > > 	
> > > > 	}
> > > 
> > > I'd prefer to leave it as it is (since IMHO is more readable) with the
> > 
> > > addition of following code:
> > it might be more slightly more readable, but doing a single function call
> > results in better runtime performance
> 
> Doesn't the compiler optimize it as it sees fit?

gcc can't know to optimize malloc calls like this
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20120804/bc42c593/attachment.pgp>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command
  2012-08-03 15:32                 ` Stephen Warren
@ 2012-08-06  7:13                   ` Lukasz Majewski
  0 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-06  7:13 UTC (permalink / raw)
  To: u-boot

Dear Stephen Warren,

> On 08/03/2012 12:13 AM, Lukasz Majewski wrote:
> > Dear Stephen Warren,
> > 
> >> Again, this is confusing two different kinds of partitions.
> >>
> >> There are HW-level partitions/regions/areas within the eMMC HW
> >> itself. You need to send commands to the eMMC device to select
> >> whether read/write commands act on the boot0/boot1/general*/user
> >> HW partition.
> > 
> > This will be done via "mmc boot [dev] [HW partition (boot0/1/user]"
> > command (from u-boot prompt).
> 
> Hmm. I still fail to see how this is any different to the existing
> "mmc dev" command. Are the following two commands not exactly
> identical:
> 
> mmc dev $dev $part      # already exists today
> mmc boot $dev $part     # new command you're proposing
> 
> ?

You are totally right the $part part is the thing I'm looking for.
I had in mind a previous version of "mmc dev" command with only the
$dev part.

As I can see in the code - the mmc_switch() call does exactly the
things that I need :-)
> 
> > This command is not yet implemented at u-boot (at least for Trats
> > development board).
> > After its implementation it will be used as a helper function for
> > dfu.
> 


-- 
Best regards,

Lukasz Majewski

Samsung Poland R&D Center | Linux Platform Group

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget
  2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
                   ` (11 preceding siblings ...)
  2012-08-03  7:45 ` [U-Boot] [PATCH v4 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
@ 2012-08-06 12:41 ` Lukasz Majewski
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
                     ` (7 more replies)
  12 siblings, 8 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-06 12:41 UTC (permalink / raw)
  To: u-boot

Those patches add support for composite USB download gadget.
This gadget (at least for now) is equipped with DFU download function.

A separate DFU back-end and front-end have been added.
Back-end is placed at ./drivers/dfu directory. The front-end is implemented
as USB function.

The back-end is written in a generic manner with storage device specific
code separated (eMMC).

DFU specification can be found at:
http://wiki.openmoko.org/wiki/USB_DFU_-_The_USB_Device_Firmware_Upgrade_standard

Example usage:

u-boot side: dfu mmc 0
PC: dfu-util -U IMAGE.bin -a uImage (for upload)
    dfu-util -D uImage -a uImage (download)

To list the alt settings:
        dfu mmc 0 list

Test HW:
        Exynos4210 Trats board

Lukasz Majewski (7):
  dfu:usb: Support for g_dnl composite download gadget.
  dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  dfu: DFU backend implementation
  dfu: MMC specific routines for DFU operation
  dfu:cmd: Support for DFU u-boot command
  arm:trats: Support for USB UDC driver at TRATS board.
  arm:trats: Enable g_dnl composite USB gadget with embedded DFU
    function on TRATS

 Makefile                    |    1 +
 board/samsung/trats/trats.c |    8 +
 common/Makefile             |    1 +
 common/cmd_dfu.c            |   81 +++++
 drivers/dfu/Makefile        |   44 +++
 drivers/dfu/dfu.c           |  238 ++++++++++++++
 drivers/dfu/dfu_mmc.c       |  162 ++++++++++
 drivers/usb/gadget/Makefile |    2 +
 drivers/usb/gadget/f_dfu.c  |  749 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/f_dfu.h  |  100 ++++++
 drivers/usb/gadget/g_dnl.c  |  202 ++++++++++++
 include/configs/trats.h     |   24 ++-
 include/dfu.h               |  103 ++++++
 include/g_dnl.h             |   33 ++
 14 files changed, 1747 insertions(+), 1 deletions(-)
 create mode 100644 common/cmd_dfu.c
 create mode 100644 drivers/dfu/Makefile
 create mode 100644 drivers/dfu/dfu.c
 create mode 100644 drivers/dfu/dfu_mmc.c
 create mode 100644 drivers/usb/gadget/f_dfu.c
 create mode 100644 drivers/usb/gadget/f_dfu.h
 create mode 100644 drivers/usb/gadget/g_dnl.c
 create mode 100644 include/dfu.h
 create mode 100644 include/g_dnl.h

-- 
1.7.2.3

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v5 1/7] dfu:usb: Support for g_dnl composite download gadget.
  2012-08-06 12:41 ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
@ 2012-08-06 12:41   ` Lukasz Majewski
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
                     ` (6 subsequent siblings)
  7 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-06 12:41 UTC (permalink / raw)
  To: u-boot

Composite USB download gadget support (g_dnl) for download functions.
This code works on top of composite gadget.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:

- G_DNL_{VENDOR_NUM, PRODUCT_NUM and MANUFACTURER} defined at
./include/configs/<board>.h
- Suspend and resume stub methods removed
- '\0' repleaced with plain 0

Changes for v3:
- Remove unused #includes
- Replace strncpy and strncat with strcpy and strcat. It was possible
  due to new approach to g_dnl name generation (at g_dnl_register function)
- Rename the g_dnl_{init|cleanup} to g_dnl_{register|unregister}
- Replace the G_DNL_* CONFIG_G_DNL_*

Changes for v4:
- Remove unnecessary otg calls
- odin prefix replaced with g_dnl
- Single space indentation between type and variable name

Changes for v5:
- None
---
 drivers/usb/gadget/Makefile |    1 +
 drivers/usb/gadget/g_dnl.c  |  202 +++++++++++++++++++++++++++++++++++++++++++
 include/g_dnl.h             |   33 +++++++
 3 files changed, 236 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/gadget/g_dnl.c
 create mode 100644 include/g_dnl.h

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 87d1918..2c067c8 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -29,6 +29,7 @@ LIB	:= $(obj)libusb_gadget.o
 ifdef CONFIG_USB_GADGET
 COBJS-y += epautoconf.o config.o usbstring.o
 COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
+COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
 endif
 ifdef CONFIG_USB_ETHER
 COBJS-y += ether.o epautoconf.o config.o usbstring.o
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
new file mode 100644
index 0000000..7d87050
--- /dev/null
+++ b/drivers/usb/gadget/g_dnl.c
@@ -0,0 +1,202 @@
+/*
+ * g_dnl.c -- USB Downloader Gadget
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski  <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <errno.h>
+#include <common.h>
+#include <malloc.h>
+
+#include <mmc.h>
+#include <part.h>
+
+#include <g_dnl.h>
+#include "f_dfu.h"
+
+#include "gadget_chips.h"
+#include "composite.c"
+
+/*
+ * One needs to define the following:
+ * CONFIG_G_DNL_VENDOR_NUM
+ * CONFIG_G_DNL_PRODUCT_NUM
+ * CONFIG_G_DNL_MANUFACTURER
+ * at e.g. ./include/configs/<board>.h
+ */
+
+#define STRING_MANUFACTURER 25
+#define STRING_PRODUCT 2
+#define STRING_USBDOWN 2
+#define CONFIG_USBDOWNLOADER 2
+
+#define DRIVER_VERSION		"usb_dnl 2.0"
+
+static const char shortname[] = "usb_dnl_";
+static const char product[] = "USB download gadget";
+static const char manufacturer[] = CONFIG_G_DNL_MANUFACTURER;
+
+static struct usb_device_descriptor device_desc = {
+	.bLength = sizeof device_desc,
+	.bDescriptorType = USB_DT_DEVICE,
+
+	.bcdUSB = __constant_cpu_to_le16(0x0200),
+	.bDeviceClass = USB_CLASS_COMM,
+	.bDeviceSubClass = 0x02, /*0x02:CDC-modem , 0x00:CDC-serial*/
+
+	.idVendor = __constant_cpu_to_le16(CONFIG_G_DNL_VENDOR_NUM),
+	.idProduct = __constant_cpu_to_le16(CONFIG_G_DNL_PRODUCT_NUM),
+	.iProduct = STRING_PRODUCT,
+	.bNumConfigurations = 1,
+};
+
+/* static strings, in UTF-8 */
+static struct usb_string g_dnl_string_defs[] = {
+	{ 0, manufacturer, },
+	{ 1, product, },
+};
+
+static struct usb_gadget_strings g_dnl_string_tab = {
+	.language = 0x0409, /* en-us */
+	.strings = g_dnl_string_defs,
+};
+
+static struct usb_gadget_strings *g_dnl_composite_strings[] = {
+	&g_dnl_string_tab,
+	NULL,
+};
+
+static int g_dnl_unbind(struct usb_composite_dev *cdev)
+{
+	debug("%s\n", __func__);
+	return 0;
+}
+
+static int g_dnl_do_config(struct usb_configuration *c)
+{
+	const char *s = c->cdev->driver->name;
+	int ret = -1;
+
+	debug("%s: configuration: 0x%p composite dev: 0x%p\n",
+	      __func__, c, c->cdev);
+
+	printf("GADGET DRIVER: %s\n", s);
+	if (!strcmp(s, "usb_dnl_dfu"))
+		ret = dfu_add(c);
+
+	return ret;
+}
+
+static int g_dnl_config_register(struct usb_composite_dev *cdev)
+{
+	static struct usb_configuration config = {
+		.label = "usb_dnload",
+		.bmAttributes =	USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+		.bConfigurationValue =	CONFIG_USBDOWNLOADER,
+		.iConfiguration =	STRING_USBDOWN,
+
+		.bind = g_dnl_do_config,
+	};
+
+	return usb_add_config(cdev, &config);
+}
+
+static int g_dnl_bind(struct usb_composite_dev *cdev)
+{
+	struct usb_gadget *gadget = cdev->gadget;
+	int id, ret;
+	int gcnum;
+
+	debug("%s: gadget: 0x%p cdev: 0x%p\n", __func__, gadget, cdev);
+
+	id = usb_string_id(cdev);
+
+	if (id < 0)
+		return id;
+	g_dnl_string_defs[0].id = id;
+	device_desc.iManufacturer = id;
+
+	id = usb_string_id(cdev);
+	if (id < 0)
+		return id;
+
+	g_dnl_string_defs[1].id = id;
+	device_desc.iProduct = id;
+
+	ret = g_dnl_config_register(cdev);
+	if (ret)
+		goto error;
+
+	gcnum = usb_gadget_controller_number(gadget);
+
+	debug("gcnum: %d\n", gcnum);
+	if (gcnum >= 0)
+		device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
+	else {
+		debug("%s: controller '%s' not recognized\n",
+			shortname, gadget->name);
+		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
+	}
+
+	return 0;
+
+ error:
+	g_dnl_unbind(cdev);
+	return -ENOMEM;
+}
+
+static struct usb_composite_driver g_dnl_driver = {
+	.name = NULL,
+	.dev = &device_desc,
+	.strings = g_dnl_composite_strings,
+
+	.bind = g_dnl_bind,
+	.unbind = g_dnl_unbind,
+};
+
+int g_dnl_register(const char *type)
+{
+	/* We only allow "dfu" atm, so 3 should be enough */
+	static char name[sizeof(shortname) + 3];
+	int ret;
+
+	if (!strcmp(type, "dfu")) {
+		strcpy(name, shortname);
+		strcat(name, type);
+	} else {
+		printf("%s: unknown command: %s\n", __func__, type);
+		return -EINVAL;
+	}
+
+	g_dnl_driver.name = name;
+
+	debug("%s: g_dnl_driver.name: %s\n", __func__, g_dnl_driver.name);
+	ret = usb_composite_register(&g_dnl_driver);
+
+	if (ret) {
+		printf("%s: failed!, error: %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+void g_dnl_unregister(void)
+{
+	usb_composite_unregister(&g_dnl_driver);
+}
diff --git a/include/g_dnl.h b/include/g_dnl.h
new file mode 100644
index 0000000..0ec7440
--- /dev/null
+++ b/include/g_dnl.h
@@ -0,0 +1,33 @@
+/*
+ *  Copyright (C) 2012 Samsung Electronics
+ *  Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __G_DOWNLOAD_H_
+#define __G_DOWNLOAD_H_
+
+#include <linux/usb/ch9.h>
+#include <usbdescriptors.h>
+#include <linux/usb/gadget.h>
+
+int g_dnl_register(const char *s);
+void g_dnl_unregister(void);
+
+/* USB initialization declaration - board specific */
+void board_usb_init(void);
+#endif /* __G_DOWNLOAD_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v5 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget
  2012-08-06 12:41 ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
@ 2012-08-06 12:41   ` Lukasz Majewski
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 3/7] dfu: DFU backend implementation Lukasz Majewski
                     ` (5 subsequent siblings)
  7 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-06 12:41 UTC (permalink / raw)
  To: u-boot

Support for f_dfu USB function.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:

- Replace kzalloc and kfree with free and calloc
- Reorganization of calloc calls
- Misspelling corrected
- Redesign of DFU state machine from "switch case" to function pointers
- Split the dfu_handle method to separate functions for each DFU state

Changes for v3:
- Missing parenthesis added to sizeof call

Changes for v4:
- Replace two puts with one
- Remove the 0xff at handle_getstate function
- Add const qualifier to struct definitions when possible

Changes for v5:
- None
---
 drivers/usb/gadget/Makefile |    1 +
 drivers/usb/gadget/f_dfu.c  |  749 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/f_dfu.h  |  100 ++++++
 3 files changed, 850 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/gadget/f_dfu.c
 create mode 100644 drivers/usb/gadget/f_dfu.h

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 2c067c8..5bbdd36 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -30,6 +30,7 @@ ifdef CONFIG_USB_GADGET
 COBJS-y += epautoconf.o config.o usbstring.o
 COBJS-$(CONFIG_USB_GADGET_S3C_UDC_OTG) += s3c_udc_otg.o
 COBJS-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
+COBJS-$(CONFIG_DFU_FUNCTION) += f_dfu.o
 endif
 ifdef CONFIG_USB_ETHER
 COBJS-y += ether.o epautoconf.o config.o usbstring.o
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
new file mode 100644
index 0000000..3ec4c65
--- /dev/null
+++ b/drivers/usb/gadget/f_dfu.c
@@ -0,0 +1,749 @@
+/*
+ * f_dfu.c -- Device Firmware Update USB function
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *          Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <errno.h>
+#include <common.h>
+#include <malloc.h>
+
+#include <linux/usb/ch9.h>
+#include <usbdescriptors.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/composite.h>
+
+#include <dfu.h>
+#include "f_dfu.h"
+
+struct f_dfu {
+	struct usb_function		usb_function;
+
+	struct usb_descriptor_header	**function;
+	struct usb_string		*strings;
+
+	/* when configured, we have one config */
+	u8				config;
+	u8				altsetting;
+	enum dfu_state			dfu_state;
+	unsigned int			dfu_status;
+
+	/* Send/received block number is handy for data integrity check */
+	int                             blk_seq_num;
+};
+
+typedef int (*dfu_state_fn) (struct f_dfu *,
+			     const struct usb_ctrlrequest *,
+			     struct usb_gadget *,
+			     struct usb_request *);
+
+static inline struct f_dfu *func_to_dfu(struct usb_function *f)
+{
+	return container_of(f, struct f_dfu, usb_function);
+}
+
+static const struct dfu_function_descriptor dfu_func = {
+	.bLength =		sizeof dfu_func,
+	.bDescriptorType =	DFU_DT_FUNC,
+	.bmAttributes =		DFU_BIT_WILL_DETACH |
+				DFU_BIT_MANIFESTATION_TOLERANT |
+				DFU_BIT_CAN_UPLOAD |
+				DFU_BIT_CAN_DNLOAD,
+	.wDetachTimeOut =	0,
+	.wTransferSize =	DFU_USB_BUFSIZ,
+	.bcdDFUVersion =	__constant_cpu_to_le16(0x0110),
+};
+
+static struct usb_interface_descriptor dfu_intf_runtime = {
+	.bLength =		sizeof dfu_intf_runtime,
+	.bDescriptorType =	USB_DT_INTERFACE,
+	.bNumEndpoints =	0,
+	.bInterfaceClass =	USB_CLASS_APP_SPEC,
+	.bInterfaceSubClass =	1,
+	.bInterfaceProtocol =	1,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_descriptor_header *dfu_runtime_descs[] = {
+	(struct usb_descriptor_header *) &dfu_intf_runtime,
+	NULL,
+};
+
+static const struct usb_qualifier_descriptor dev_qualifier = {
+	.bLength =		sizeof dev_qualifier,
+	.bDescriptorType =	USB_DT_DEVICE_QUALIFIER,
+	.bcdUSB =		__constant_cpu_to_le16(0x0200),
+	.bDeviceClass =		USB_CLASS_VENDOR_SPEC,
+	.bNumConfigurations =	1,
+};
+
+static const char dfu_name[] = "Device Firmware Upgrade";
+
+/*
+ * static strings, in UTF-8
+ *
+ * dfu_generic configuration
+ */
+static struct usb_string strings_dfu_generic[] = {
+	[0].s = dfu_name,
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab_dfu_generic = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_dfu_generic,
+};
+
+static struct usb_gadget_strings *dfu_generic_strings[] = {
+	&stringtab_dfu_generic,
+	NULL,
+};
+
+/*
+ * usb_function specific
+ */
+static struct usb_gadget_strings stringtab_dfu = {
+	.language	= 0x0409,	/* en-us */
+	/*
+	 * .strings
+	 *
+	 * assigned during initialization,
+	 * depends on number of flash entities
+	 *
+	 */
+};
+
+static struct usb_gadget_strings *dfu_strings[] = {
+	&stringtab_dfu,
+	NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static void dnload_request_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	dfu_write(dfu_get_entity(f_dfu->altsetting), req->buf,
+		  req->length, f_dfu->blk_seq_num);
+
+	if (req->length == 0)
+		puts("DOWNLOAD ... OK\nCtrl+C to exit ...\n");
+}
+
+static void handle_getstatus(struct usb_request *req)
+{
+	struct dfu_status *dstat = (struct dfu_status *)req->buf;
+	struct f_dfu *f_dfu = req->context;
+
+	switch (f_dfu->dfu_state) {
+	case DFU_STATE_dfuDNLOAD_SYNC:
+	case DFU_STATE_dfuDNBUSY:
+		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
+		break;
+	case DFU_STATE_dfuMANIFEST_SYNC:
+		break;
+	default:
+		break;
+	}
+
+	/* send status response */
+	dstat->bStatus = f_dfu->dfu_status;
+	dstat->bState = f_dfu->dfu_state;
+	dstat->iString = 0;
+}
+
+static void handle_getstate(struct usb_request *req)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	((u8 *)req->buf)[0] = f_dfu->dfu_state;
+	req->actual = sizeof(u8);
+}
+
+static inline void to_dfu_mode(struct f_dfu *f_dfu)
+{
+	f_dfu->usb_function.strings = dfu_strings;
+	f_dfu->usb_function.hs_descriptors = f_dfu->function;
+}
+
+static inline void to_runtime_mode(struct f_dfu *f_dfu)
+{
+	f_dfu->usb_function.strings = NULL;
+	f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+}
+
+static int handle_upload(struct usb_request *req, u16 len)
+{
+	struct f_dfu *f_dfu = req->context;
+
+	return dfu_read(dfu_get_entity(f_dfu->altsetting), req->buf,
+			req->length, f_dfu->blk_seq_num);
+}
+
+static int handle_dnload(struct usb_gadget *gadget, u16 len)
+{
+	struct usb_composite_dev *cdev = get_gadget_data(gadget);
+	struct usb_request *req = cdev->req;
+	struct f_dfu *f_dfu = req->context;
+
+	if (len == 0)
+		f_dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
+
+	req->complete = dnload_request_complete;
+
+	return len;
+}
+
+/*-------------------------------------------------------------------------*/
+/* DFU state machine  */
+static int state_app_idle(struct f_dfu *f_dfu,
+			  const struct usb_ctrlrequest *ctrl,
+			  struct usb_gadget *gadget,
+			  struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	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:
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_app_detach(struct f_dfu *f_dfu,
+			    const struct usb_ctrlrequest *ctrl,
+			    struct usb_gadget *gadget,
+			    struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_appIDLE;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_idle(struct f_dfu *f_dfu,
+			  const struct usb_ctrlrequest *ctrl,
+			  struct usb_gadget *gadget,
+			  struct usb_request *req)
+{
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 len = le16_to_cpu(ctrl->wLength);
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_DNLOAD:
+		if (len == 0) {
+			f_dfu->dfu_state = DFU_STATE_dfuERROR;
+			value = RET_STALL;
+			break;
+		}
+		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
+		f_dfu->blk_seq_num = w_value;
+		value = handle_dnload(gadget, len);
+		break;
+	case USB_REQ_DFU_UPLOAD:
+		f_dfu->dfu_state = DFU_STATE_dfuUPLOAD_IDLE;
+		f_dfu->blk_seq_num = 0;
+		value = handle_upload(req, len);
+		break;
+	case USB_REQ_DFU_ABORT:
+		/* no zlp? */
+		value = RET_ZLP;
+		break;
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	case USB_REQ_DFU_DETACH:
+		/*
+		 * Proprietary extension: 'detach' from idle mode and
+		 * get back to runtime mode in case of USB Reset.  As
+		 * much as I dislike this, we just can't use every USB
+		 * bus reset to switch back to runtime mode, since at
+		 * least the Linux USB stack likes to send a number of
+		 * resets in a row :(
+		 */
+		f_dfu->dfu_state =
+			DFU_STATE_dfuMANIFEST_WAIT_RST;
+		to_runtime_mode(f_dfu);
+		f_dfu->dfu_state = DFU_STATE_appIDLE;
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_dnload_sync(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_dnbusy(struct f_dfu *f_dfu,
+			    const struct usb_ctrlrequest *ctrl,
+			    struct usb_gadget *gadget,
+			    struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_dnload_idle(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 len = le16_to_cpu(ctrl->wLength);
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_DNLOAD:
+		f_dfu->dfu_state = DFU_STATE_dfuDNLOAD_SYNC;
+		f_dfu->blk_seq_num = w_value;
+		value = handle_dnload(gadget, len);
+		break;
+	case USB_REQ_DFU_ABORT:
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		value = RET_ZLP;
+		break;
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_manifest_sync(struct f_dfu *f_dfu,
+				   const struct usb_ctrlrequest *ctrl,
+				   struct usb_gadget *gadget,
+				   struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		/* We're MainfestationTolerant */
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		handle_getstatus(req);
+		f_dfu->blk_seq_num = 0;
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_upload_idle(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	u16 len = le16_to_cpu(ctrl->wLength);
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_UPLOAD:
+		/* state transition if less data then requested */
+		f_dfu->blk_seq_num = w_value;
+		value = handle_upload(req, len);
+		if (value >= 0 && value < len)
+			f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		break;
+	case USB_REQ_DFU_ABORT:
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		/* no zlp? */
+		value = RET_ZLP;
+		break;
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static int state_dfu_error(struct f_dfu *f_dfu,
+				 const struct usb_ctrlrequest *ctrl,
+				 struct usb_gadget *gadget,
+				 struct usb_request *req)
+{
+	int value = 0;
+
+	switch (ctrl->bRequest) {
+	case USB_REQ_DFU_GETSTATUS:
+		handle_getstatus(req);
+		value = RET_STAT_LEN;
+		break;
+	case USB_REQ_DFU_GETSTATE:
+		handle_getstate(req);
+		break;
+	case USB_REQ_DFU_CLRSTATUS:
+		f_dfu->dfu_state = DFU_STATE_dfuIDLE;
+		f_dfu->dfu_status = DFU_STATUS_OK;
+		/* no zlp? */
+		value = RET_ZLP;
+		break;
+	default:
+		f_dfu->dfu_state = DFU_STATE_dfuERROR;
+		value = RET_STALL;
+		break;
+	}
+
+	return value;
+}
+
+static dfu_state_fn dfu_state[] = {
+	state_app_idle,          /* DFU_STATE_appIDLE */
+	state_app_detach,        /* DFU_STATE_appDETACH */
+	state_dfu_idle,          /* DFU_STATE_dfuIDLE */
+	state_dfu_dnload_sync,   /* DFU_STATE_dfuDNLOAD_SYNC */
+	state_dfu_dnbusy,        /* DFU_STATE_dfuDNBUSY */
+	state_dfu_dnload_idle,   /* DFU_STATE_dfuDNLOAD_IDLE */
+	state_dfu_manifest_sync, /* DFU_STATE_dfuMANIFEST_SYNC */
+	NULL,                    /* DFU_STATE_dfuMANIFEST */
+	NULL,                    /* DFU_STATE_dfuMANIFEST_WAIT_RST */
+	state_dfu_upload_idle,   /* DFU_STATE_dfuUPLOAD_IDLE */
+	state_dfu_error          /* DFU_STATE_dfuERROR */
+};
+
+static int
+dfu_handle(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct usb_gadget *gadget = f->config->cdev->gadget;
+	struct usb_request *req = f->config->cdev->req;
+	struct f_dfu *f_dfu = f->config->cdev->req->context;
+	u16 len = le16_to_cpu(ctrl->wLength);
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	int value = 0;
+	u8 req_type = ctrl->bRequestType & USB_TYPE_MASK;
+
+	debug("w_value: 0x%x len: 0x%x\n", w_value, len);
+	debug("req_type: 0x%x ctrl->bRequest: 0x%x f_dfu->dfu_state: 0x%x\n",
+	       req_type, ctrl->bRequest, f_dfu->dfu_state);
+
+	if (req_type == USB_TYPE_STANDARD) {
+		if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR &&
+		    (w_value >> 8) == DFU_DT_FUNC) {
+			value = min(len, (u16) sizeof(dfu_func));
+			memcpy(req->buf, &dfu_func, value);
+		}
+	} else /* DFU specific request */
+		value = dfu_state[f_dfu->dfu_state] (f_dfu, ctrl, gadget, req);
+
+	if (value >= 0) {
+		req->length = value;
+		req->zero = value < len;
+		value = usb_ep_queue(gadget->ep0, req, 0);
+		if (value < 0) {
+			debug("ep_queue --> %d\n", value);
+			req->status = 0;
+		}
+	}
+
+	return value;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int
+dfu_prepare_strings(struct f_dfu *f_dfu, int n)
+{
+	struct dfu_entity *de = NULL;
+	int i = 0;
+
+	f_dfu->strings = calloc(sizeof(struct usb_string), n + 1);
+	if (!f_dfu->strings)
+		goto enomem;
+
+	for (i = 0; i < n; ++i) {
+		de = dfu_get_entity(i);
+		f_dfu->strings[i].s = de->name;
+	}
+
+	f_dfu->strings[i].id = 0;
+	f_dfu->strings[i].s = NULL;
+
+	return 0;
+
+enomem:
+	while (i)
+		f_dfu->strings[--i].s = NULL;
+
+	free(f_dfu->strings);
+
+	return -ENOMEM;
+}
+
+static int dfu_prepare_function(struct f_dfu *f_dfu, int n)
+{
+	struct usb_interface_descriptor *d;
+	int i = 0;
+
+	f_dfu->function = calloc(sizeof(struct usb_descriptor_header *), n);
+	if (!f_dfu->function)
+		goto enomem;
+
+	for (i = 0; i < n; ++i) {
+		d = calloc(sizeof(*d), 1);
+		if (!d)
+			goto enomem;
+
+		d->bLength =		sizeof(*d);
+		d->bDescriptorType =	USB_DT_INTERFACE;
+		d->bAlternateSetting =	i;
+		d->bNumEndpoints =	0;
+		d->bInterfaceClass =	USB_CLASS_APP_SPEC;
+		d->bInterfaceSubClass =	1;
+		d->bInterfaceProtocol =	2;
+
+		f_dfu->function[i] = (struct usb_descriptor_header *)d;
+	}
+	f_dfu->function[i] = NULL;
+
+	return 0;
+
+enomem:
+	while (i) {
+		free(f_dfu->function[--i]);
+		f_dfu->function[i] = NULL;
+	}
+	free(f_dfu->function);
+
+	return -ENOMEM;
+}
+
+static int dfu_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	int alt_num = dfu_get_alt_number();
+	int rv, id, i;
+
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	dfu_intf_runtime.bInterfaceNumber = id;
+
+	f_dfu->dfu_state = DFU_STATE_appIDLE;
+	f_dfu->dfu_status = DFU_STATUS_OK;
+
+	rv = dfu_prepare_function(f_dfu, alt_num);
+	if (rv)
+		goto error;
+
+	rv = dfu_prepare_strings(f_dfu, alt_num);
+	if (rv)
+		goto error;
+	for (i = 0; i < alt_num; i++) {
+		id = usb_string_id(cdev);
+		if (id < 0)
+			return id;
+		f_dfu->strings[i].id = id;
+		((struct usb_interface_descriptor *)f_dfu->function[i])
+			->iInterface = id;
+	}
+
+	stringtab_dfu.strings = f_dfu->strings;
+
+	cdev->req->context = f_dfu;
+
+error:
+	return rv;
+}
+
+static void dfu_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	int alt_num = dfu_get_alt_number();
+	int i;
+
+	if (f_dfu->strings) {
+		i = alt_num;
+		while (i)
+			f_dfu->strings[--i].s = NULL;
+
+		free(f_dfu->strings);
+	}
+
+	if (f_dfu->function) {
+		i = alt_num;
+		while (i) {
+			free(f_dfu->function[--i]);
+			f_dfu->function[i] = NULL;
+		}
+		free(f_dfu->function);
+	}
+
+	free(f_dfu);
+}
+
+static int dfu_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+
+	debug("%s: intf:%d alt:%d\n", __func__, intf, alt);
+
+	f_dfu->altsetting = alt;
+
+	return 0;
+}
+
+/* TODO: is this really what we need here? */
+static void dfu_disable(struct usb_function *f)
+{
+	struct f_dfu *f_dfu = func_to_dfu(f);
+	if (f_dfu->config == 0)
+		return;
+
+	debug("%s: reset config\n", __func__);
+
+	f_dfu->config = 0;
+}
+
+static int dfu_bind_config(struct usb_configuration *c)
+{
+	struct f_dfu *f_dfu;
+	int status;
+
+	f_dfu = calloc(sizeof(*f_dfu), 1);
+	if (!f_dfu)
+		return -ENOMEM;
+	f_dfu->usb_function.name = "dfu";
+	f_dfu->usb_function.hs_descriptors = dfu_runtime_descs;
+	f_dfu->usb_function.bind = dfu_bind;
+	f_dfu->usb_function.unbind = dfu_unbind;
+	f_dfu->usb_function.set_alt = dfu_set_alt;
+	f_dfu->usb_function.disable = dfu_disable;
+	f_dfu->usb_function.strings = dfu_generic_strings,
+	f_dfu->usb_function.setup = dfu_handle,
+
+	status = usb_add_function(c, &f_dfu->usb_function);
+	if (status)
+		free(f_dfu);
+
+	return status;
+}
+
+int dfu_add(struct usb_configuration *c)
+{
+	int id;
+
+	id = usb_string_id(c->cdev);
+	if (id < 0)
+		return id;
+	strings_dfu_generic[0].id = id;
+	dfu_intf_runtime.iInterface = id;
+
+	debug("%s: cdev: 0x%p gadget:0x%p gadget->ep0: 0x%p\n", __func__,
+	       c->cdev, c->cdev->gadget, c->cdev->gadget->ep0);
+
+	return dfu_bind_config(c);
+}
diff --git a/drivers/usb/gadget/f_dfu.h b/drivers/usb/gadget/f_dfu.h
new file mode 100644
index 0000000..023e1ad
--- /dev/null
+++ b/drivers/usb/gadget/f_dfu.h
@@ -0,0 +1,100 @@
+/*
+ * f_dfu.h -- Device Firmware Update gadget
+ *
+ * Copyright (C) 2011-2012 Samsung Electronics
+ * author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __F_DFU_H_
+#define __F_DFU_H_
+
+#include <linux/compiler.h>
+#include <linux/usb/composite.h>
+
+#define DFU_CONFIG_VAL			1
+#define DFU_DT_FUNC			0x21
+
+#define DFU_BIT_WILL_DETACH		(0x1 << 3)
+#define DFU_BIT_MANIFESTATION_TOLERANT	(0x1 << 2)
+#define DFU_BIT_CAN_UPLOAD		(0x1 << 1)
+#define DFU_BIT_CAN_DNLOAD		0x1
+
+/* big enough to hold our biggest descriptor */
+#define DFU_USB_BUFSIZ			4096
+
+#define USB_REQ_DFU_DETACH		0x00
+#define USB_REQ_DFU_DNLOAD		0x01
+#define USB_REQ_DFU_UPLOAD		0x02
+#define USB_REQ_DFU_GETSTATUS		0x03
+#define USB_REQ_DFU_CLRSTATUS		0x04
+#define USB_REQ_DFU_GETSTATE		0x05
+#define USB_REQ_DFU_ABORT		0x06
+
+#define DFU_STATUS_OK			0x00
+#define DFU_STATUS_errTARGET		0x01
+#define DFU_STATUS_errFILE		0x02
+#define DFU_STATUS_errWRITE		0x03
+#define DFU_STATUS_errERASE		0x04
+#define DFU_STATUS_errCHECK_ERASED	0x05
+#define DFU_STATUS_errPROG		0x06
+#define DFU_STATUS_errVERIFY		0x07
+#define DFU_STATUS_errADDRESS		0x08
+#define DFU_STATUS_errNOTDONE		0x09
+#define DFU_STATUS_errFIRMWARE		0x0a
+#define DFU_STATUS_errVENDOR		0x0b
+#define DFU_STATUS_errUSBR		0x0c
+#define DFU_STATUS_errPOR		0x0d
+#define DFU_STATUS_errUNKNOWN		0x0e
+#define DFU_STATUS_errSTALLEDPKT	0x0f
+
+#define RET_STALL			-1
+#define RET_ZLP				0
+#define RET_STAT_LEN			6
+
+enum dfu_state {
+	DFU_STATE_appIDLE		= 0,
+	DFU_STATE_appDETACH		= 1,
+	DFU_STATE_dfuIDLE		= 2,
+	DFU_STATE_dfuDNLOAD_SYNC	= 3,
+	DFU_STATE_dfuDNBUSY		= 4,
+	DFU_STATE_dfuDNLOAD_IDLE	= 5,
+	DFU_STATE_dfuMANIFEST_SYNC	= 6,
+	DFU_STATE_dfuMANIFEST		= 7,
+	DFU_STATE_dfuMANIFEST_WAIT_RST	= 8,
+	DFU_STATE_dfuUPLOAD_IDLE	= 9,
+	DFU_STATE_dfuERROR		= 10,
+};
+
+struct dfu_status {
+	__u8				bStatus;
+	__u8				bwPollTimeout[3];
+	__u8				bState;
+	__u8				iString;
+} __packed;
+
+struct dfu_function_descriptor {
+	__u8				bLength;
+	__u8				bDescriptorType;
+	__u8				bmAttributes;
+	__le16				wDetachTimeOut;
+	__le16				wTransferSize;
+	__le16				bcdDFUVersion;
+} __packed;
+
+/* configuration-specific linkup */
+int dfu_add(struct usb_configuration *c);
+#endif /* __F_DFU_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v5 3/7] dfu: DFU backend implementation
  2012-08-06 12:41 ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
@ 2012-08-06 12:41   ` Lukasz Majewski
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
                     ` (4 subsequent siblings)
  7 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-06 12:41 UTC (permalink / raw)
  To: u-boot

New, separate driver at ./drivers/dfu has been added. It allows platform
and storage independent operation of DFU.
It has been extended to use new MMC level of command abstraction.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:
- None

Changes for v3:
- Remove unnecessary NULL and 0 initialization of dynamic variables
- Combine two puts to one
- Adding const qualifier to device and layout definitions
- Remove unnecessary casting at dfu->name passing
- Provide more meaningful names for dfu layouts and device types
- Removal of dfu_extract_{token|entity} functions and replace them
  with strsep calls

Changes for v4:
- Remove unnecessary memset
- const added where applicable
- Handling calloc failure in dfu_config_entries()

Changes for v5:
- Replace several calls to calloc(sizeof(struct dfu_entity), 1);
  with only one, done outside the for loop
---
 Makefile             |    1 +
 drivers/dfu/Makefile |   43 +++++++++
 drivers/dfu/dfu.c    |  238 ++++++++++++++++++++++++++++++++++++++++++++++++++
 include/dfu.h        |  103 ++++++++++++++++++++++
 4 files changed, 385 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dfu/Makefile
 create mode 100644 drivers/dfu/dfu.c
 create mode 100644 include/dfu.h

diff --git a/Makefile b/Makefile
index eb37ea1..67c627d 100644
--- a/Makefile
+++ b/Makefile
@@ -271,6 +271,7 @@ LIBS += drivers/pci/libpci.o
 LIBS += drivers/pcmcia/libpcmcia.o
 LIBS += drivers/power/libpower.o
 LIBS += drivers/spi/libspi.o
+LIBS += drivers/dfu/libdfu.o
 ifeq ($(CPU),mpc83xx)
 LIBS += drivers/qe/libqe.o
 LIBS += arch/powerpc/cpu/mpc8xxx/ddr/libddr.o
diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
new file mode 100644
index 0000000..7736485
--- /dev/null
+++ b/drivers/dfu/Makefile
@@ -0,0 +1,43 @@
+#
+# Copyright (C) 2012 Samsung Electronics
+# Lukasz Majewski <l.majewski@samsung.com>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# 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 the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)libdfu.o
+
+COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
+
+SRCS    := $(COBJS-y:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS-y))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c
new file mode 100644
index 0000000..e8477fb
--- /dev/null
+++ b/drivers/dfu/dfu.c
@@ -0,0 +1,238 @@
+/*
+ * dfu.c -- DFU back-end routines
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * author: Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <fat.h>
+#include <dfu.h>
+#include <linux/list.h>
+#include <linux/compiler.h>
+
+static LIST_HEAD(dfu_list);
+static int dfu_alt_num;
+
+static int dfu_find_alt_num(const char *s)
+{
+	int i = 0;
+
+	for (; *s; s++)
+		if (*s == ';')
+			i++;
+
+	return ++i;
+}
+
+static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
+				     dfu_buf[DFU_DATA_BUF_SIZE];
+
+int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
+{
+	static unsigned char *i_buf;
+	static int i_blk_seq_num;
+	long w_size = 0;
+	int ret = 0;
+
+	debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
+	       __func__, dfu->name, buf, size, blk_seq_num, i_buf);
+
+	if (blk_seq_num == 0) {
+		i_buf = dfu_buf;
+		i_blk_seq_num = 0;
+	}
+
+	if (i_blk_seq_num++ != blk_seq_num) {
+		printf("%s: Wrong sequence number! [%d] [%d]\n",
+		       __func__, i_blk_seq_num, blk_seq_num);
+		return -1;
+	}
+
+	memcpy(i_buf, buf, size);
+	i_buf += size;
+
+	if (size == 0) {
+		/* Integrity check (if needed) */
+		debug("%s: %s %d [B] CRC32: 0x%x\n", __func__, dfu->name,
+		       i_buf - dfu_buf, crc32(0, dfu_buf, i_buf - dfu_buf));
+
+		w_size = i_buf - dfu_buf;
+		ret = dfu->write_medium(dfu, dfu_buf, &w_size);
+		if (ret)
+			debug("%s: Write error!\n", __func__);
+
+		i_blk_seq_num = 0;
+		i_buf = NULL;
+		return ret;
+	}
+
+	return ret;
+}
+
+int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
+{
+	static unsigned char *i_buf;
+	static int i_blk_seq_num;
+	static long r_size;
+	static u32 crc;
+	int ret = 0;
+
+	debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
+	       __func__, dfu->name, buf, size, blk_seq_num, i_buf);
+
+	if (blk_seq_num == 0) {
+		i_buf = dfu_buf;
+		ret = dfu->read_medium(dfu, i_buf, &r_size);
+		debug("%s: %s %ld [B]\n", __func__, dfu->name, r_size);
+		i_blk_seq_num = 0;
+		/* Integrity check (if needed) */
+		crc = crc32(0, dfu_buf, r_size);
+	}
+
+	if (i_blk_seq_num++ != blk_seq_num) {
+		printf("%s: Wrong sequence number! [%d] [%d]\n",
+		       __func__, i_blk_seq_num, blk_seq_num);
+		return -1;
+	}
+
+	if (r_size >= size) {
+		memcpy(buf, i_buf, size);
+		i_buf += size;
+		r_size -= size;
+		return size;
+	} else {
+		memcpy(buf, i_buf, r_size);
+		i_buf += r_size;
+		debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name, crc);
+		puts("UPLOAD ... done\nCtrl+C to exit ...\n");
+
+		i_buf = NULL;
+		i_blk_seq_num = 0;
+		crc = 0;
+		return r_size;
+	}
+	return ret;
+}
+
+static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt,
+			    char *interface, int num)
+{
+	char *st;
+
+	debug("%s: %s interface: %s num: %d\n", __func__, s, interface, num);
+	st = strsep(&s, " ");
+	strcpy(dfu->name, st);
+
+	dfu->dev_num = num;
+	dfu->alt = alt;
+
+	/* Specific for mmc device */
+	if (strcmp(interface, "mmc") == 0) {
+		if (dfu_fill_entity_mmc(dfu, s))
+			return -1;
+	} else {
+		printf("%s: Device %s not (yet) supported!\n",
+		       __func__,  interface);
+		return -1;
+	}
+
+	return 0;
+}
+
+void dfu_free_entities(void)
+{
+	struct dfu_entity *dfu, *p, *t = NULL;
+
+	list_for_each_entry_safe_reverse(dfu, p, &dfu_list, list) {
+		list_del(&dfu->list);
+		t = dfu;
+	}
+	if (t)
+		free(t);
+	INIT_LIST_HEAD(&dfu_list);
+}
+
+int dfu_config_entities(char *env, char *interface, int num)
+{
+	struct dfu_entity *dfu;
+	int i, ret;
+	char *s;
+
+	dfu_alt_num = dfu_find_alt_num(env);
+	debug("%s: dfu_alt_num=%d\n", __func__, dfu_alt_num);
+
+	dfu = calloc(sizeof(*dfu), dfu_alt_num);
+	if (!dfu)
+		return -1;
+	for (i = 0; i < dfu_alt_num; i++) {
+
+		s = strsep(&env, ";");
+		ret = dfu_fill_entity(&dfu[i], s, i, interface, num);
+		if (ret)
+			return -1;
+
+		list_add_tail(&dfu[i].list, &dfu_list);
+	}
+
+	return 0;
+}
+
+const char *dfu_get_dev_type(enum dfu_device_type t)
+{
+	const char *dev_t[] = {NULL, "eMMC", "OneNAND", "NAND" };
+	return dev_t[t];
+}
+
+const char *dfu_get_layout(enum dfu_layout l)
+{
+	const char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2",
+					   "EXT3", "EXT4" };
+	return dfu_layout[l];
+}
+
+void dfu_show_entities(void)
+{
+	struct dfu_entity *dfu;
+
+	puts("DFU alt settings list:\n");
+
+	list_for_each_entry(dfu, &dfu_list, list) {
+		printf("dev: %s alt: %d name: %s layout: %s\n",
+		       dfu_get_dev_type(dfu->dev_type), dfu->alt,
+		       dfu->name, dfu_get_layout(dfu->layout));
+	}
+}
+
+int dfu_get_alt_number(void)
+{
+	return dfu_alt_num;
+}
+
+struct dfu_entity *dfu_get_entity(int alt)
+{
+	struct dfu_entity *dfu;
+
+	list_for_each_entry(dfu, &dfu_list, list) {
+		if (dfu->alt == alt)
+			return dfu;
+	}
+
+	return NULL;
+}
diff --git a/include/dfu.h b/include/dfu.h
new file mode 100644
index 0000000..5350d79
--- /dev/null
+++ b/include/dfu.h
@@ -0,0 +1,103 @@
+/*
+ * dfu.h - DFU flashable area description
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __DFU_ENTITY_H_
+#define __DFU_ENTITY_H_
+
+#include <common.h>
+#include <linux/list.h>
+#include <mmc.h>
+
+enum dfu_device_type {
+	DFU_DEV_MMC = 1,
+	DFU_DEV_ONENAND,
+	DFU_DEV_NAND,
+};
+
+enum dfu_layout {
+	DFU_RAW_ADDR = 1,
+	DFU_FS_FAT,
+	DFU_FS_EXT2,
+	DFU_FS_EXT3,
+	DFU_FS_EXT4,
+};
+
+struct mmc_internal_data {
+	/* RAW programming */
+	unsigned int lba_start;
+	unsigned int lba_size;
+	unsigned int lba_blk_size;
+
+	/* FAT/EXT */
+	unsigned int dev;
+	unsigned int part;
+};
+
+static inline unsigned int get_mmc_blk_size(int dev)
+{
+	return find_mmc_device(dev)->read_bl_len;
+}
+
+#define DFU_NAME_SIZE 32
+#define DFU_CMD_BUF_SIZE 128
+#define DFU_DATA_BUF_SIZE (1024*1024*4) /* 4 MiB */
+
+struct dfu_entity {
+	char			name[DFU_NAME_SIZE];
+	int                     alt;
+	void                    *dev_private;
+	int                     dev_num;
+	enum dfu_device_type    dev_type;
+	enum dfu_layout         layout;
+
+	union {
+		struct mmc_internal_data mmc;
+	} data;
+
+	int (*read_medium)(struct dfu_entity *dfu, void *buf, long *len);
+	int (*write_medium)(struct dfu_entity *dfu, void *buf, long *len);
+
+	struct list_head list;
+};
+
+int dfu_config_entities(char *s, char *interface, int num);
+void dfu_free_entities(void);
+void dfu_show_entities(void);
+int dfu_get_alt_number(void);
+const char *dfu_get_dev_type(enum dfu_device_type t);
+const char *dfu_get_layout(enum dfu_layout l);
+struct dfu_entity *dfu_get_entity(int alt);
+char *dfu_extract_token(char** e, int *n);
+
+int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
+int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
+/* Device specific */
+#ifdef CONFIG_DFU_MMC
+extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s);
+#else
+static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
+{
+	puts("MMC support not available!\n");
+	return -1;
+}
+#endif
+#endif /* __DFU_ENTITY_H_ */
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v5 4/7] dfu: MMC specific routines for DFU operation
  2012-08-06 12:41 ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                     ` (2 preceding siblings ...)
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 3/7] dfu: DFU backend implementation Lukasz Majewski
@ 2012-08-06 12:41   ` Lukasz Majewski
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-06 12:41 UTC (permalink / raw)
  To: u-boot

Support for MMC storage devices to work with DFU framework.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:
- None

Changes for v3:
- Provide special abstraction layer (mmc_{block|file}_{read|write})
  to alleviate switch to new device model (DM)
- More verbose messages when not supported layout encountered
- Calls to strncmp() replaced with strcmp()

Changes for v4:
- Remove superfluous memset() calls
- Replace ALLOC_CACHE_ALIGN_BUFFER with plain table definition
- Cosmetic changes with pointers definition

Changes for v5:
- None
---
 drivers/dfu/Makefile  |    1 +
 drivers/dfu/dfu_mmc.c |  162 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 163 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dfu/dfu_mmc.c

diff --git a/drivers/dfu/Makefile b/drivers/dfu/Makefile
index 7736485..7b717bc 100644
--- a/drivers/dfu/Makefile
+++ b/drivers/dfu/Makefile
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk
 LIB	= $(obj)libdfu.o
 
 COBJS-$(CONFIG_DFU_FUNCTION) += dfu.o
+COBJS-$(CONFIG_DFU_MMC) += dfu_mmc.o
 
 SRCS    := $(COBJS-y:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS-y))
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
new file mode 100644
index 0000000..060145b
--- /dev/null
+++ b/drivers/dfu/dfu_mmc.c
@@ -0,0 +1,162 @@
+/*
+ * dfu.c -- DFU back-end routines
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * author: Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <dfu.h>
+
+enum dfu_mmc_op {
+	DFU_OP_READ = 1,
+	DFU_OP_WRITE,
+};
+
+static int mmc_block_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
+			void *buf, long *len)
+{
+	char cmd_buf[DFU_CMD_BUF_SIZE];
+
+	sprintf(cmd_buf, "mmc %s 0x%x %x %x",
+		op == DFU_OP_READ ? "read" : "write",
+		(unsigned int) buf,
+		dfu->data.mmc.lba_start,
+		dfu->data.mmc.lba_size);
+
+	if (op == DFU_OP_READ)
+		*len = dfu->data.mmc.lba_blk_size * dfu->data.mmc.lba_size;
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+	return run_command(cmd_buf, 0);
+}
+
+static inline int mmc_block_write(struct dfu_entity *dfu, void *buf, long *len)
+{
+	return mmc_block_op(DFU_OP_WRITE, dfu, buf, len);
+}
+
+static inline int mmc_block_read(struct dfu_entity *dfu, void *buf, long *len)
+{
+	return mmc_block_op(DFU_OP_READ, dfu, buf, len);
+}
+
+static int mmc_file_op(enum dfu_mmc_op op, struct dfu_entity *dfu,
+			void *buf, long *len)
+{
+	char cmd_buf[DFU_CMD_BUF_SIZE];
+	char *str_env;
+	int ret;
+
+	sprintf(cmd_buf, "fat%s mmc %d:%d 0x%x %s %lx",
+		op == DFU_OP_READ ? "load" : "write",
+		dfu->data.mmc.dev, dfu->data.mmc.part,
+		(unsigned int) buf, dfu->name, *len);
+
+	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
+
+	ret = run_command(cmd_buf, 0);
+	if (ret) {
+		puts("dfu: Read error!\n");
+		return ret;
+	}
+
+	if (dfu->layout != DFU_RAW_ADDR) {
+		str_env = getenv("filesize");
+		if (str_env == NULL) {
+			puts("dfu: Wrong file size!\n");
+			return -1;
+		}
+		*len = simple_strtoul(str_env, NULL, 16);
+	}
+
+	return ret;
+}
+
+static inline int mmc_file_write(struct dfu_entity *dfu, void *buf, long *len)
+{
+	return mmc_file_op(DFU_OP_WRITE, dfu, buf, len);
+}
+
+static inline int mmc_file_read(struct dfu_entity *dfu, void *buf, long *len)
+{
+	return mmc_file_op(DFU_OP_READ, dfu, buf, len);
+}
+
+int dfu_write_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
+{
+	int ret = -1;
+
+	switch (dfu->layout) {
+	case DFU_RAW_ADDR:
+		ret = mmc_block_write(dfu, buf, len);
+		break;
+	case DFU_FS_FAT:
+		ret = mmc_file_write(dfu, buf, len);
+		break;
+	default:
+		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
+		       dfu_get_layout(dfu->layout));
+	}
+
+	return ret;
+}
+
+int dfu_read_medium_mmc(struct dfu_entity *dfu, void *buf, long *len)
+{
+	int ret = -1;
+
+	switch (dfu->layout) {
+	case DFU_RAW_ADDR:
+		ret = mmc_block_read(dfu, buf, len);
+		break;
+	case DFU_FS_FAT:
+		ret = mmc_file_read(dfu, buf, len);
+		break;
+	default:
+		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
+		       dfu_get_layout(dfu->layout));
+	}
+
+	return ret;
+}
+
+int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *s)
+{
+	char *st;
+
+	dfu->dev_type = DFU_DEV_MMC;
+	st = strsep(&s, " ");
+	if (!strcmp(st, "mmc")) {
+		dfu->layout = DFU_RAW_ADDR;
+		dfu->data.mmc.lba_start = simple_strtoul(s, &s, 16);
+		dfu->data.mmc.lba_size = simple_strtoul(++s, &s, 16);
+		dfu->data.mmc.lba_blk_size = get_mmc_blk_size(dfu->dev_num);
+	} else if (!strcmp(st, "fat")) {
+		dfu->layout = DFU_FS_FAT;
+		dfu->data.mmc.dev = simple_strtoul(s, &s, 10);
+		dfu->data.mmc.part = simple_strtoul(++s, &s, 10);
+	} else {
+		printf("%s: Memory layout (%s) not supported!\n", __func__, st);
+	}
+
+	dfu->read_medium = dfu_read_medium_mmc;
+	dfu->write_medium = dfu_write_medium_mmc;
+
+	return 0;
+}
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v5 5/7] dfu:cmd: Support for DFU u-boot command
  2012-08-06 12:41 ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                     ` (3 preceding siblings ...)
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
@ 2012-08-06 12:41   ` Lukasz Majewski
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-06 12:41 UTC (permalink / raw)
  To: u-boot

Support for u-boot's command line command "dfu <interface> <dev> [list]".

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>

---
Changes for v2:
- None

Changes for v3:
- Remove unnecessary initialization to NULL of dynamic variables
- goto done added to reduce code duplication
- static definition of do_dfu()

Changes for v4:
- Define "dfu" string as an array

Changes for v5:
- None
---
 common/Makefile  |    1 +
 common/cmd_dfu.c |   81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+), 0 deletions(-)
 create mode 100644 common/cmd_dfu.c

diff --git a/common/Makefile b/common/Makefile
index 483eb4d..32d44e5 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -183,6 +183,7 @@ COBJS-$(CONFIG_MENU) += menu.o
 COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o
 COBJS-$(CONFIG_UPDATE_TFTP) += update.o
 COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
+COBJS-$(CONFIG_CMD_DFU) += cmd_dfu.o
 endif
 
 ifdef CONFIG_SPL_BUILD
diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
new file mode 100644
index 0000000..62fb890
--- /dev/null
+++ b/common/cmd_dfu.c
@@ -0,0 +1,81 @@
+/*
+ * cmd_dfu.c -- dfu command
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *	    Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <dfu.h>
+#include <asm/errno.h>
+#include <g_dnl.h>
+
+static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	const char *str_env;
+	char s[] = "dfu";
+	char *env_bkp;
+	int ret;
+
+	if (argc < 3)
+		return CMD_RET_USAGE;
+
+	str_env = getenv("dfu_alt_info");
+	if (str_env == NULL) {
+		printf("%s: \"dfu_alt_info\" env variable not defined!\n",
+		       __func__);
+		return CMD_RET_FAILURE;
+	}
+
+	env_bkp = strdup(str_env);
+	ret = dfu_config_entities(env_bkp, argv[1],
+			    (int)simple_strtoul(argv[2], NULL, 10));
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	if (strcmp(argv[3], "list") == 0) {
+		dfu_show_entities();
+		goto done;
+	}
+
+	board_usb_init();
+	g_dnl_register(s);
+	while (1) {
+		if (ctrlc())
+			goto exit;
+
+		usb_gadget_handle_interrupts();
+	}
+exit:
+	g_dnl_unregister();
+done:
+	dfu_free_entities();
+	free(env_bkp);
+
+	return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu,
+	"Device Firmware Upgrade",
+	"<interface> <dev> [list]\n"
+	"  - device firmware upgrade on a device <dev>\n"
+	"    attached to interface <interface>\n"
+	"    [list] - list available alt settings"
+);
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v5 6/7] arm:trats: Support for USB UDC driver at TRATS board.
  2012-08-06 12:41 ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                     ` (4 preceding siblings ...)
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
@ 2012-08-06 12:41   ` Lukasz Majewski
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
  2012-08-06 20:31   ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Marek Vasut
  7 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-06 12:41 UTC (permalink / raw)
  To: u-boot

Support for USB UDC driver at trats board.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Minkyu Kang <mk7.kang@samsung.com>

---
Changes for v2:
- replace puts to debug

Changes for v3:
- None

Changes for v4:
- None

Changes for v5:
- None
---
 board/samsung/trats/trats.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/board/samsung/trats/trats.c b/board/samsung/trats/trats.c
index a8b2b11..4f9cb5a 100644
--- a/board/samsung/trats/trats.c
+++ b/board/samsung/trats/trats.c
@@ -59,6 +59,8 @@ static int hwrevision(int rev)
 	return (board_rev & 0xf) == rev;
 }
 
+struct s3c_plat_otg_data s5pc210_otg_data;
+
 int board_init(void)
 {
 	gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
@@ -259,6 +261,12 @@ struct s3c_plat_otg_data s5pc210_otg_data = {
 	.usb_phy_ctrl	= EXYNOS4_USBPHY_CONTROL,
 	.usb_flags	= PHY0_SLEEP,
 };
+
+void board_usb_init(void)
+{
+	debug("USB_udc_probe\n");
+	s3c_udc_probe(&s5pc210_otg_data);
+}
 #endif
 
 static void pmic_reset(void)
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v5 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS
  2012-08-06 12:41 ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                     ` (5 preceding siblings ...)
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
@ 2012-08-06 12:41   ` Lukasz Majewski
  2012-08-06 20:31   ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Marek Vasut
  7 siblings, 0 replies; 147+ messages in thread
From: Lukasz Majewski @ 2012-08-06 12:41 UTC (permalink / raw)
  To: u-boot

Enable the g_dnl composite USB gadget driver with embedded DFU function on it.
It now uses the composite gadget framework to support download specific
USB functions (like enabled DFU or USB Mass Storage).

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
Cc: Minkyu Kang <mk7.kang@samsung.com>

---
Change for v2:
- Move the G_DNL_{VENDOR_NUM, PRODUCT_NUM and MANUFACTURER} definitions to
  ./include/configs/<board>.h

Changes for v3:
- None

Changes for v4:
- None

Changes for v5:
- None
---
 include/configs/trats.h |   24 +++++++++++++++++++++++-
 1 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/include/configs/trats.h b/include/configs/trats.h
index eb269b2..75a23b0 100644
--- a/include/configs/trats.h
+++ b/include/configs/trats.h
@@ -94,6 +94,21 @@
 #undef CONFIG_CMD_ONENAND
 #undef CONFIG_CMD_MTDPARTS
 #define CONFIG_CMD_MMC
+#define CONFIG_CMD_DFU
+
+/* FAT */
+#define CONFIG_CMD_FAT
+#define CONFIG_FAT_WRITE
+
+/* USB Composite download gadget - g_dnl */
+#define CONFIG_USBDOWNLOAD_GADGET
+#define CONFIG_DFU_FUNCTION
+#define CONFIG_DFU_MMC
+
+/* USB Samsung's IDs */
+#define CONFIG_G_DNL_VENDOR_NUM 0x04E8
+#define CONFIG_G_DNL_PRODUCT_NUM 0x6601
+#define CONFIG_G_DNL_MANUFACTURER "Samsung"
 
 #define CONFIG_BOOTDELAY		1
 #define CONFIG_ZERO_BOOTDELAY_CHECK
@@ -104,6 +119,11 @@
 #define CONFIG_BOOTBLOCK		"10"
 #define CONFIG_ENV_COMMON_BOOT		"${console} ${meminfo}"
 
+#define CONFIG_DFU_ALT \
+	"dfu_alt_info=" \
+	"u-boot mmc 80 400;" \
+	"uImage fat 0 2\0" \
+
 #define CONFIG_ENV_OVERWRITE
 #define CONFIG_SYS_CONSOLE_INFO_QUIET
 #define CONFIG_SYS_CONSOLE_IS_IN_ENV
@@ -146,7 +166,8 @@
 	"mmcdev=0\0" \
 	"mmcbootpart=2\0" \
 	"mmcrootpart=3\0" \
-	"opts=always_resume=1"
+	"opts=always_resume=1\0" \
+	CONFIG_DFU_ALT
 
 /* Miscellaneous configurable options */
 #define CONFIG_SYS_LONGHELP		/* undef to save memory */
@@ -209,6 +230,7 @@
 #define CONFIG_USB_GADGET
 #define CONFIG_USB_GADGET_S3C_UDC_OTG
 #define CONFIG_USB_GADGET_DUALSPEED
+#define CONFIG_USB_GADGET_VBUS_DRAW	2
 
 /* LCD */
 #define CONFIG_EXYNOS_FB
-- 
1.7.2.3

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget
  2012-08-06 12:41 ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
                     ` (6 preceding siblings ...)
  2012-08-06 12:41   ` [U-Boot] [PATCH v5 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
@ 2012-08-06 20:31   ` Marek Vasut
  7 siblings, 0 replies; 147+ messages in thread
From: Marek Vasut @ 2012-08-06 20:31 UTC (permalink / raw)
  To: u-boot

Dear Lukasz Majewski,

> Those patches add support for composite USB download gadget.
> This gadget (at least for now) is equipped with DFU download function.
> 
> A separate DFU back-end and front-end have been added.
> Back-end is placed at ./drivers/dfu directory. The front-end is implemented
> as USB function.
> 
> The back-end is written in a generic manner with storage device specific
> code separated (eMMC).
> 
> DFU specification can be found at:
> http://wiki.openmoko.org/wiki/USB_DFU_-_The_USB_Device_Firmware_Upgrade_sta
> ndard
[...]

Applied the series and pushed to u-boot-usb ... now guys, please do final rounds 
of tests etc. so I can submit pullRQ.

Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 147+ messages in thread

end of thread, other threads:[~2012-08-06 20:31 UTC | newest]

Thread overview: 147+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-03  9:38 [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
2012-07-03  9:38 ` [U-Boot] [PATCH 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
2012-07-03 18:41   ` Marek Vasut
2012-07-04  7:42     ` Lukasz Majewski
2012-07-20  4:14   ` Mike Frysinger
2012-07-23 15:25     ` Lukasz Majewski
2012-07-24 17:50       ` Mike Frysinger
2012-07-03  9:38 ` [U-Boot] [PATCH 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
2012-07-03 21:21   ` Marek Vasut
2012-07-04  8:39     ` Lukasz Majewski
2012-07-04 14:35       ` Marek Vasut
2012-07-04 15:04         ` Lukasz Majewski
2012-07-04 16:21           ` Marek Vasut
2012-07-03  9:38 ` [U-Boot] [PATCH 3/7] dfu: DFU backend implementation Lukasz Majewski
2012-07-03 21:28   ` Marek Vasut
2012-07-04  8:56     ` Lukasz Majewski
2012-07-04 14:36       ` Marek Vasut
2012-07-04 15:07         ` Lukasz Majewski
2012-07-04 16:22           ` Marek Vasut
2012-07-20  4:32   ` Mike Frysinger
2012-07-23 16:11     ` Lukasz Majewski
2012-07-03  9:38 ` [U-Boot] [PATCH 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
2012-07-03 21:29   ` Marek Vasut
2012-07-03 21:55     ` Tom Rini
2012-07-03 22:01       ` Marek Vasut
2012-07-03 22:06         ` Tom Rini
2012-07-03 22:31           ` Marek Vasut
2012-07-03 22:33             ` Tom Rini
2012-07-03 23:07               ` Stephen Warren
2012-07-03 23:38                 ` Tom Rini
2012-07-03 23:58                   ` Stephen Warren
2012-07-04  0:13               ` Marek Vasut
2012-07-20  4:25                 ` Mike Frysinger
2012-07-04  9:10         ` Lukasz Majewski
2012-07-04 14:38           ` Marek Vasut
2012-07-04 15:13             ` Lukasz Majewski
2012-07-03  9:38 ` [U-Boot] [PATCH 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
2012-07-03 21:32   ` Marek Vasut
2012-07-04  9:28     ` Lukasz Majewski
2012-07-04 14:39       ` Marek Vasut
2012-07-20  4:23         ` Mike Frysinger
2012-07-20 11:33           ` Marek Vasut
2012-07-20 14:43             ` Mike Frysinger
2012-07-20 21:11               ` Marek Vasut
2012-07-21 17:20                 ` Mike Frysinger
2012-07-21 17:21                   ` Marek Vasut
2012-07-20  4:22     ` Mike Frysinger
2012-07-20 11:35       ` Marek Vasut
2012-07-20  4:20   ` Mike Frysinger
2012-07-23 16:01     ` Lukasz Majewski
2012-07-24 18:00       ` Mike Frysinger
2012-07-24 20:48         ` Lukasz Majewski
2012-07-03  9:38 ` [U-Boot] [PATCH 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
2012-07-04  0:20   ` Minkyu Kang
2012-07-04  9:33     ` Lukasz Majewski
2012-07-03  9:38 ` [U-Boot] [PATCH 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
2012-07-04  0:22   ` Minkyu Kang
2012-07-03 12:52 ` [U-Boot] [PATCH 0/7] dfu:usb: Composite USB download gadget with DFU function Otavio Salvador
2012-07-03 12:59   ` Marek Vasut
2012-07-04 15:48 ` [U-Boot] [PATCH v2 " Lukasz Majewski
2012-07-04 15:48   ` [U-Boot] [PATCH v2 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
2012-07-09 16:30     ` Marek Vasut
2012-07-04 15:48   ` [U-Boot] [PATCH v2 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
2012-07-09 16:34     ` Marek Vasut
2012-07-04 15:48   ` [U-Boot] [PATCH v2 3/7] dfu: DFU backend implementation Lukasz Majewski
2012-07-09 16:35     ` Marek Vasut
2012-07-27 11:58     ` Wolfgang Denk
2012-07-27 13:15       ` Lukasz Majewski
2012-07-27 13:35         ` Wolfgang Denk
2012-07-27 13:47           ` Lukasz Majewski
2012-07-04 15:48   ` [U-Boot] [PATCH v2 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
2012-07-09 16:36     ` Marek Vasut
2012-07-10  8:45     ` Tom Rini
2012-07-10 10:38       ` Lukasz Majewski
2012-07-11 11:54         ` Tom Rini
2012-07-12 12:39           ` Lukasz Majewski
2012-07-12 12:46             ` Tom Rini
2012-07-13 10:29               ` Marek Vasut
2012-07-13 21:27                 ` Andy Fleming
2012-07-27 12:36     ` Wolfgang Denk
2012-07-27 12:43       ` Marek Vasut
2012-07-27 12:57         ` Wolfgang Denk
2012-07-27 13:15           ` Marek Vasut
2012-07-27 13:38             ` Wolfgang Denk
2012-07-27 13:33       ` Lukasz Majewski
2012-07-27 13:47         ` Wolfgang Denk
2012-07-04 15:48   ` [U-Boot] [PATCH v2 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
2012-07-04 15:48   ` [U-Boot] [PATCH v2 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
2012-07-04 15:48   ` [U-Boot] [PATCH v2 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
2012-07-09 11:28   ` [U-Boot] [PATCH v2 0/7] dfu:usb: Composite USB download gadget with DFU function Lukasz Majewski
2012-07-09 11:46     ` Tom Rini
2012-07-09 16:25       ` Marek Vasut
2012-07-10  8:27         ` Lukasz Majewski
2012-07-10  9:28           ` Marek Vasut
2012-07-18 12:51 ` [U-Boot] [PATCH " Marek Vasut
2012-07-23  7:57   ` Lukasz Majewski
2012-07-23 10:57     ` Marek Vasut
2012-07-31  6:36 ` [U-Boot] [PATCH v3 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
2012-07-31  6:36   ` [U-Boot] [PATCH v3 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
2012-08-01 22:40     ` Mike Frysinger
2012-08-02  9:55       ` Lukasz Majewski
2012-07-31  6:36   ` [U-Boot] [PATCH v3 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
2012-08-01 22:45     ` Mike Frysinger
2012-08-02 10:54       ` Lukasz Majewski
2012-07-31  6:36   ` [U-Boot] [PATCH v3 3/7] dfu: DFU backend implementation Lukasz Majewski
2012-08-01 22:57     ` Mike Frysinger
2012-08-02 13:55       ` Lukasz Majewski
2012-08-03 23:19         ` Mike Frysinger
2012-08-04  7:47           ` Marek Vasut
2012-08-04 16:28             ` Mike Frysinger
2012-07-31  6:37   ` [U-Boot] [PATCH v3 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
2012-08-01 23:00     ` Mike Frysinger
2012-08-02 14:47       ` Lukasz Majewski
2012-07-31  6:37   ` [U-Boot] [PATCH v3 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
2012-07-31 17:14     ` Stephen Warren
2012-08-01  7:16       ` Lukasz Majewski
2012-08-01 17:13         ` Stephen Warren
2012-08-02  8:31           ` Lukasz Majewski
2012-08-02 15:52             ` Stephen Warren
2012-08-03  6:13               ` Lukasz Majewski
2012-08-03 15:32                 ` Stephen Warren
2012-08-06  7:13                   ` Lukasz Majewski
2012-08-01 18:04     ` Mike Frysinger
2012-08-02  7:16       ` Marek Vasut
2012-08-02 15:28         ` Lukasz Majewski
2012-08-02 17:47         ` Mike Frysinger
2012-07-31  6:37   ` [U-Boot] [PATCH v3 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
2012-07-31  8:31     ` Minkyu Kang
2012-07-31  6:37   ` [U-Boot] [PATCH v3 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
2012-07-31  8:32     ` Minkyu Kang
2012-08-03  7:45 ` [U-Boot] [PATCH v4 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
2012-08-03  7:45   ` [U-Boot] [PATCH v4 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
2012-08-03  7:45   ` [U-Boot] [PATCH v4 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
2012-08-03  7:45   ` [U-Boot] [PATCH v4 3/7] dfu: DFU backend implementation Lukasz Majewski
2012-08-03  7:45   ` [U-Boot] [PATCH v4 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
2012-08-03  7:45   ` [U-Boot] [PATCH v4 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
2012-08-03  7:45   ` [U-Boot] [PATCH v4 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
2012-08-03  7:45   ` [U-Boot] [PATCH v4 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
2012-08-06 12:41 ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Lukasz Majewski
2012-08-06 12:41   ` [U-Boot] [PATCH v5 1/7] dfu:usb: Support for g_dnl composite download gadget Lukasz Majewski
2012-08-06 12:41   ` [U-Boot] [PATCH v5 2/7] dfu:usb: DFU USB function (f_dfu) support for g_dnl composite gadget Lukasz Majewski
2012-08-06 12:41   ` [U-Boot] [PATCH v5 3/7] dfu: DFU backend implementation Lukasz Majewski
2012-08-06 12:41   ` [U-Boot] [PATCH v5 4/7] dfu: MMC specific routines for DFU operation Lukasz Majewski
2012-08-06 12:41   ` [U-Boot] [PATCH v5 5/7] dfu:cmd: Support for DFU u-boot command Lukasz Majewski
2012-08-06 12:41   ` [U-Boot] [PATCH v5 6/7] arm:trats: Support for USB UDC driver at TRATS board Lukasz Majewski
2012-08-06 12:41   ` [U-Boot] [PATCH v5 7/7] arm:trats: Enable g_dnl composite USB gadget with embedded DFU function on TRATS Lukasz Majewski
2012-08-06 20:31   ` [U-Boot] [PATCH v5 0/7] dfu:usb: DFU support via USB Download gadget Marek Vasut

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.