All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb
@ 2017-03-15  7:56 Eddie Cai
  2017-03-15  7:56 ` [U-Boot] [U-Boot 1/3] drivers: usb: gadget: add the rockusb gadget Eddie Cai
                   ` (5 more replies)
  0 siblings, 6 replies; 36+ messages in thread
From: Eddie Cai @ 2017-03-15  7:56 UTC (permalink / raw)
  To: u-boot

rockusb is a protocol run between host pc and device. it help people get device
info, flash image to device. this patch implement rockusb on device side. 

Eddie Cai (3):
  drivers: usb: gadget: add the rockusb gadget
  cmd: add rockusb command
  rockchip: rk3288: enable rockusb support on rk3288 based device

 cmd/Kconfig                     |  12 +
 cmd/Makefile                    |   1 +
 cmd/rockusb.c                   |  79 ++++
 drivers/usb/gadget/Makefile     |   1 +
 drivers/usb/gadget/f_rockusb.c  | 801 ++++++++++++++++++++++++++++++++++++++++
 include/configs/rk3288_common.h |   4 +
 include/rockusb.h               |  13 +
 7 files changed, 911 insertions(+)
 create mode 100644 cmd/rockusb.c
 create mode 100644 drivers/usb/gadget/f_rockusb.c
 create mode 100644 include/rockusb.h

-- 
2.7.4

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

* [U-Boot] [U-Boot 1/3] drivers: usb: gadget: add the rockusb gadget
  2017-03-15  7:56 [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb Eddie Cai
@ 2017-03-15  7:56 ` Eddie Cai
  2017-03-16  7:05   ` Kever Yang
  2017-04-20 10:04   ` Lukasz Majewski
  2017-03-15  7:56 ` [U-Boot] [U-Boot 2/3] cmd: add rockusb command Eddie Cai
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 36+ messages in thread
From: Eddie Cai @ 2017-03-15  7:56 UTC (permalink / raw)
  To: u-boot

this patch implement fastboot protocol on the device side. this is based on USB
download gadget infrastructure. the rockusb function implements the rd, wl, rid
commands. it can work with rkdeveloptool;
https://github.com/rockchip-linux/rkdeveloptool

Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
---
 drivers/usb/gadget/Makefile    |   1 +
 drivers/usb/gadget/f_rockusb.c | 801 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 802 insertions(+)
 create mode 100644 drivers/usb/gadget/f_rockusb.c

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 0fbbb7c..0eb27a3 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
 obj-$(CONFIG_USB_FUNCTION_DFU) += f_dfu.o
 obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
 obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
+obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o
 endif
 endif
 ifdef CONFIG_USB_ETHER
diff --git a/drivers/usb/gadget/f_rockusb.c b/drivers/usb/gadget/f_rockusb.c
new file mode 100644
index 0000000..a67cb35
--- /dev/null
+++ b/drivers/usb/gadget/f_rockusb.c
@@ -0,0 +1,801 @@
+/*
+ * (C) Copyright 2017
+ *
+ * Eddie Cai <eddie.cai.linux@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/composite.h>
+#include <linux/compiler.h>
+#include <version.h>
+#include <g_dnl.h>
+
+#define ROCKUSB_VERSION		"0.1"
+
+#define ROCKUSB_INTERFACE_CLASS	0xff
+#define ROCKUSB_INTERFACE_SUB_CLASS	0x06
+#define ROCKUSB_INTERFACE_PROTOCOL	0x05
+
+#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0  (0x0200)
+#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1  (0x0040)
+#define TX_ENDPOINT_MAXIMUM_PACKET_SIZE      (0x0040)
+
+#define EP_BUFFER_SIZE			4096
+/*
+ * EP_BUFFER_SIZE must always be an integral multiple of maxpacket size
+ * (64 or 512 or 1024), else we break on certain controllers like DWC3
+ * that expect bulk OUT requests to be divisible by maxpacket size.
+ */
+
+struct f_rockusb {
+	struct usb_function usb_function;
+
+	/* IN/OUT EP's and corresponding requests */
+	struct usb_ep *in_ep, *out_ep;
+	struct usb_request *in_req, *out_req;
+};
+
+static inline struct f_rockusb *func_to_rockusb(struct usb_function *f)
+{
+	return container_of(f, struct f_rockusb, usb_function);
+}
+
+static struct f_rockusb *rockusb_func;
+
+static struct usb_endpoint_descriptor fs_ep_in = {
+	.bLength            = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType    = USB_DT_ENDPOINT,
+	.bEndpointAddress   = USB_DIR_IN,
+	.bmAttributes       = USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize     = cpu_to_le16(64),
+};
+
+static struct usb_endpoint_descriptor fs_ep_out = {
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
+	.bEndpointAddress	= USB_DIR_OUT,
+	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize		= cpu_to_le16(64),
+};
+
+static struct usb_endpoint_descriptor hs_ep_in = {
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
+	.bEndpointAddress	= USB_DIR_IN,
+	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize		= cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_ep_out = {
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
+	.bEndpointAddress	= USB_DIR_OUT,
+	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize		= cpu_to_le16(512),
+};
+
+static struct usb_interface_descriptor interface_desc = {
+	.bLength		= USB_DT_INTERFACE_SIZE,
+	.bDescriptorType	= USB_DT_INTERFACE,
+	.bInterfaceNumber	= 0x00,
+	.bAlternateSetting	= 0x00,
+	.bNumEndpoints		= 0x02,
+	.bInterfaceClass	= ROCKUSB_INTERFACE_CLASS,
+	.bInterfaceSubClass	= ROCKUSB_INTERFACE_SUB_CLASS,
+	.bInterfaceProtocol	= ROCKUSB_INTERFACE_PROTOCOL,
+};
+
+static struct usb_descriptor_header *rkusb_fs_function[] = {
+	(struct usb_descriptor_header *)&interface_desc,
+	(struct usb_descriptor_header *)&fs_ep_in,
+	(struct usb_descriptor_header *)&fs_ep_out,
+};
+
+static struct usb_descriptor_header *rkusb_hs_function[] = {
+	(struct usb_descriptor_header *)&interface_desc,
+	(struct usb_descriptor_header *)&hs_ep_in,
+	(struct usb_descriptor_header *)&hs_ep_out,
+	NULL,
+};
+
+static struct usb_endpoint_descriptor *
+rkusb_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
+	    struct usb_endpoint_descriptor *hs)
+{
+	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+		return hs;
+	return fs;
+}
+
+/*
+ * static strings, in UTF-8
+ */
+static const char rkusb_name[] = "Rockchip Rockusb";
+
+static struct usb_string rkusb_string_defs[] = {
+	[0].s = rkusb_name,
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab_rkusb = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= rkusb_string_defs,
+};
+
+static struct usb_gadget_strings *rkusb_strings[] = {
+	&stringtab_rkusb,
+	NULL,
+};
+
+static void rx_handler_command(struct usb_ep *ep, struct usb_request *req);
+static int rockusb_tx_write_csw(u32 Tag, int residue, u8 Status, int size);
+
+static void rockusb_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	int status = req->status;
+	if (!status)
+		return;
+	debug("status: %d ep '%s' trans: %d\n", status, ep->name, req->actual);
+}
+
+static int rockusb_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	int id;
+	struct usb_gadget *gadget = c->cdev->gadget;
+	struct f_rockusb *f_rkusb = func_to_rockusb(f);
+	const char *s;
+
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	interface_desc.bInterfaceNumber = id;
+
+	id = usb_string_id(c->cdev);
+	if (id < 0)
+		return id;
+
+	rkusb_string_defs[0].id = id;
+	interface_desc.iInterface = id;
+
+	f_rkusb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in);
+	if (!f_rkusb->in_ep)
+		return -ENODEV;
+	f_rkusb->in_ep->driver_data = c->cdev;
+
+	f_rkusb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out);
+	if (!f_rkusb->out_ep)
+		return -ENODEV;
+	f_rkusb->out_ep->driver_data = c->cdev;
+
+	f->descriptors = rkusb_fs_function;
+
+	if (gadget_is_dualspeed(gadget)) {
+		hs_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress;
+		hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress;
+		f->hs_descriptors = rkusb_hs_function;
+	}
+
+	s = getenv("serial#");
+	if (s)
+		g_dnl_set_serialnumber((char *)s);
+
+	return 0;
+}
+
+static void rockusb_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	memset(rockusb_func, 0, sizeof(*rockusb_func));
+}
+
+static void rockusb_disable(struct usb_function *f)
+{
+	struct f_rockusb *f_rkusb = func_to_rockusb(f);
+
+	usb_ep_disable(f_rkusb->out_ep);
+	usb_ep_disable(f_rkusb->in_ep);
+
+	if (f_rkusb->out_req) {
+		free(f_rkusb->out_req->buf);
+		usb_ep_free_request(f_rkusb->out_ep, f_rkusb->out_req);
+		f_rkusb->out_req = NULL;
+	}
+	if (f_rkusb->in_req) {
+		free(f_rkusb->in_req->buf);
+		usb_ep_free_request(f_rkusb->in_ep, f_rkusb->in_req);
+		f_rkusb->in_req = NULL;
+	}
+}
+
+static struct usb_request *rockusb_start_ep(struct usb_ep *ep)
+{
+	struct usb_request *req;
+
+	req = usb_ep_alloc_request(ep, 0);
+	if (!req)
+		return NULL;
+
+	req->length = EP_BUFFER_SIZE;
+	req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE);
+	if (!req->buf) {
+		usb_ep_free_request(ep, req);
+		return NULL;
+	}
+
+	memset(req->buf, 0, req->length);
+	return req;
+}
+
+static int rockusb_set_alt(struct usb_function *f,
+			    unsigned interface, unsigned alt)
+{
+	int ret;
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct usb_gadget *gadget = cdev->gadget;
+	struct f_rockusb *f_rkusb = func_to_rockusb(f);
+	const struct usb_endpoint_descriptor *d;
+
+	debug("%s: func: %s intf: %d alt: %d\n",
+	      __func__, f->name, interface, alt);
+
+	d = rkusb_ep_desc(gadget, &fs_ep_out, &hs_ep_out);
+	ret = usb_ep_enable(f_rkusb->out_ep, d);
+	if (ret) {
+		puts("failed to enable out ep\n");
+		return ret;
+	}
+
+	f_rkusb->out_req = rockusb_start_ep(f_rkusb->out_ep);
+	if (!f_rkusb->out_req) {
+		puts("failed to alloc out req\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	f_rkusb->out_req->complete = rx_handler_command;
+
+	d = rkusb_ep_desc(gadget, &fs_ep_in, &hs_ep_in);
+	ret = usb_ep_enable(f_rkusb->in_ep, d);
+	if (ret) {
+		puts("failed to enable in ep\n");
+		goto err;
+	}
+
+	f_rkusb->in_req = rockusb_start_ep(f_rkusb->in_ep);
+	if (!f_rkusb->in_req) {
+		puts("failed alloc req in\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	f_rkusb->in_req->complete = rockusb_complete;
+
+	ret = usb_ep_queue(f_rkusb->out_ep, f_rkusb->out_req, 0);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	rockusb_disable(f);
+	return ret;
+}
+
+static int rockusb_add(struct usb_configuration *c)
+{
+	struct f_rockusb *f_rkusb = rockusb_func;
+	int status;
+
+	debug("%s: cdev: 0x%p\n", __func__, c->cdev);
+
+	if (!f_rkusb) {
+		f_rkusb = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_rkusb));
+		if (!f_rkusb)
+			return -ENOMEM;
+
+		rockusb_func = f_rkusb;
+		memset(f_rkusb, 0, sizeof(*f_rkusb));
+	}
+
+	f_rkusb->usb_function.name = "f_rockusb";
+	f_rkusb->usb_function.bind = rockusb_bind;
+	f_rkusb->usb_function.unbind = rockusb_unbind;
+	f_rkusb->usb_function.set_alt = rockusb_set_alt;
+	f_rkusb->usb_function.disable = rockusb_disable;
+	f_rkusb->usb_function.strings = rkusb_strings;
+
+	status = usb_add_function(c, &f_rkusb->usb_function);
+	if (status) {
+		free(f_rkusb);
+		rockusb_func = f_rkusb;
+	}
+	return status;
+}
+
+char *rockusb_dev_type = 0;
+int rockusb_dev_index = 0;
+
+void rockusb_dev_init(char *dev_type, int dev_index)
+{
+	rockusb_dev_type = dev_type;
+	rockusb_dev_index = dev_index;
+}
+
+DECLARE_GADGET_BIND_CALLBACK(usb_dnl_rockusb, rockusb_add);
+
+static int rockusb_tx_write(const char *buffer, unsigned int buffer_size)
+{
+	struct usb_request *in_req = rockusb_func->in_req;
+	int ret;
+
+	memcpy(in_req->buf, buffer, buffer_size);
+	in_req->length = buffer_size;
+	usb_ep_dequeue(rockusb_func->in_ep, in_req);
+	ret = usb_ep_queue(rockusb_func->in_ep, in_req, 0);
+	if (ret)
+		printf("Error %d on queue\n", ret);
+	return 0;
+}
+
+static int rockusb_tx_write_str(const char *buffer)
+{
+	return rockusb_tx_write(buffer, strlen(buffer));
+}
+
+/* Bulk-only data structures */
+
+/* Command Block Wrapper */
+struct fsg_bulk_cb_wrap {
+	__le32	Signature;		/* Contains 'USBC' */
+	u32	Tag;			/* Unique per command id */
+	__le32	DataTransferLength;	/* Size of the data */
+	u8	Flags;			/* Direction in bit 7 */
+	u8	Lun;			/* LUN (normally 0) */
+	u8	Length;			/* Of the CDB, <= MAX_COMMAND_SIZE */
+	u8	CDB[16];		/* Command Data Block */
+};
+
+#define USB_BULK_CB_WRAP_LEN	31
+#define USB_BULK_CB_SIG		0x43425355	/* Spells out USBC */
+#define USB_BULK_IN_FLAG	0x80
+
+/* Command Status Wrapper */
+struct bulk_cs_wrap {
+	__le32	Signature;		/* Should = 'USBS' */
+	u32	Tag;			/* Same as original command */
+	__le32	Residue;		/* Amount not transferred */
+	u8	Status;			/* See below */
+};
+
+#define USB_BULK_CS_WRAP_LEN	13
+#define USB_BULK_CS_SIG		0x53425355	/* Spells out 'USBS' */
+#define USB_STATUS_PASS		0
+#define USB_STATUS_FAIL		1
+#define USB_STATUS_PHASE_ERROR	2
+
+
+#define	CSW_GOOD		0x00
+#define	CSW_FAIL		0x01
+
+static void printcbw(char *buf)
+{
+	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
+
+	memcpy((char*)&cbw, buf, USB_BULK_CB_WRAP_LEN);
+
+	debug("cbw: Signature:%x\n", cbw.Signature);
+	debug("cbw: Tag=%x\n", cbw.Tag);
+	debug("cbw: DataTransferLength=%d\n", cbw.DataTransferLength);
+	debug("cbw: Flags=%x\n", cbw.Flags);
+	debug("cbw: Lun=%d\n", cbw.Lun);
+	debug("cbw: Length=%d\n", cbw.Length);
+	debug("cbw: ucOperCode=%x\n", cbw.CDB[0]);
+	debug("cbw: ucReserved=%x\n", cbw.CDB[1]);
+	debug("cbw: dwAddress:%x %x %x %x\n", cbw.CDB[5], cbw.CDB[4], 
+						cbw.CDB[3], cbw.CDB[2]);
+	debug("cbw: ucReserved2=%x\n", cbw.CDB[6]);
+	debug("cbw: usLength:%x %x\n", cbw.CDB[8], cbw.CDB[7]);
+
+}
+
+static void printcsw(char *buf)
+{
+	struct bulk_cs_wrap csw __attribute__((aligned(ARCH_DMA_MINALIGN)));
+
+	memcpy((char*)&csw, buf, USB_BULK_CS_WRAP_LEN);
+	debug("csw: Signature:%x\n", csw.Signature);
+	debug("csw: Tag:%x\n", csw.Tag);
+	debug("csw: Residue:%x\n", csw.Residue);
+	debug("csw: Status:%x\n", csw.Status);
+
+}
+
+static int rockusb_tx_write_csw(u32 Tag, int residue, u8 Status, int size)
+{
+	struct bulk_cs_wrap csw __attribute__((aligned(ARCH_DMA_MINALIGN)));
+	csw.Signature = cpu_to_le32(USB_BULK_CS_SIG);
+	csw.Tag = Tag;
+	csw.Residue = cpu_to_be32(residue);
+	csw.Status = Status;
+	printcsw((char*)&csw);
+	return rockusb_tx_write((char*)&csw, size);
+}
+
+int download_tag = 0;
+int download_lba = 0;
+static unsigned int download_size;
+static unsigned int download_bytes;
+struct blk_desc *download_desc = 0;
+
+static unsigned int rx_bytes_expected(struct usb_ep *ep)
+{
+	int rx_remain = download_size - download_bytes;
+	unsigned int rem;
+	unsigned int maxpacket = ep->maxpacket;
+
+	if (rx_remain <= 0)
+		return 0;
+	else if (rx_remain > EP_BUFFER_SIZE)
+		return EP_BUFFER_SIZE;
+
+	rem = rx_remain % maxpacket;
+	if (rem > 0)
+		rx_remain = rx_remain + (maxpacket - rem);
+
+	return rx_remain;
+}
+
+static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
+{
+	unsigned int transfer_size = download_size - download_bytes;
+	const unsigned char *buffer = req->buf;
+	unsigned int buffer_size = req->actual;
+
+	if(!download_desc){
+		printf("rx_handler_dl_image blk_get_dev\n");
+		download_desc = blk_get_dev(rockusb_dev_type, rockusb_dev_index);
+		if (!download_desc || download_desc->type == DEV_TYPE_UNKNOWN){
+			error("invalid mmc device\n");
+			rockusb_tx_write_csw(download_tag, 0, CSW_FAIL,
+						USB_BULK_CS_WRAP_LEN);
+			return;
+		}
+	}
+
+	if (req->status != 0) {
+		printf("Bad status: %d\n", req->status);
+		rockusb_tx_write_csw(download_tag, 0, 
+					CSW_FAIL, USB_BULK_CS_WRAP_LEN);
+		return;
+	}
+
+	if (buffer_size < transfer_size)
+		transfer_size = buffer_size;
+
+	memcpy((void *)CONFIG_FASTBOOT_BUF_ADDR + download_bytes,
+	       buffer, transfer_size);
+	download_bytes += transfer_size;
+
+	/* Check if transfer is done */
+	if (download_bytes >= download_size) {
+		int blks = 0, blkcnt = download_size/512;
+		printf("download %d bytes finished, start writing to lba %x\n",
+				 download_bytes, download_lba);
+		blks = blk_dwrite(download_desc, download_lba, blkcnt, 
+					(char*)CONFIG_FASTBOOT_BUF_ADDR);
+		if (blks != blkcnt) {
+			error("failed writing to device %s: %d\n", 
+				rockusb_dev_type, rockusb_dev_index);
+			rockusb_tx_write_csw(download_tag, 0, 
+						CSW_FAIL, USB_BULK_CS_WRAP_LEN);
+			return;
+		}
+
+		req->complete = rx_handler_command;
+		req->length = EP_BUFFER_SIZE;
+		download_size = 0;
+		printf("done\n");
+		rockusb_tx_write_csw(download_tag, 0, CSW_GOOD, 
+					USB_BULK_CS_WRAP_LEN);
+	} else {
+		req->length = rx_bytes_expected(ep);
+	}
+
+	req->actual = 0;
+	usb_ep_queue(ep, req, 0);
+}
+
+static void cb_test_unit_ready(struct usb_ep *ep, struct usb_request *req)
+{
+	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
+
+	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
+
+	rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength, 
+				CSW_GOOD, USB_BULK_CS_WRAP_LEN);
+
+}
+
+static void cb_read_storage_id(struct usb_ep *ep, struct usb_request *req)
+{
+	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
+	char emmc_id[] = "EMMC ";
+
+	printf("cb_read_storage_id\n");
+	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
+	rockusb_tx_write_str(emmc_id);//only support emmc now
+	rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength, CSW_GOOD, 
+				USB_BULK_CS_WRAP_LEN);
+}
+
+static void cb_write_lba(struct usb_ep *ep, struct usb_request *req)
+{
+	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
+	int sector_count;
+
+	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
+	sector_count = (int)get_unaligned_be16(&cbw.CDB[7]);
+	download_lba = get_unaligned_be32(&cbw.CDB[2]);
+	download_size = sector_count * 512;
+	download_bytes = 0;
+	download_tag = cbw.Tag;
+	if ((0 == download_size) || (download_size>CONFIG_FASTBOOT_BUF_SIZE)){
+		rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength, 
+					CSW_FAIL, USB_BULK_CS_WRAP_LEN);
+	} else {
+		req->complete = rx_handler_dl_image;
+		req->length = rx_bytes_expected(ep);
+	}
+}
+
+static int reboot_flag;
+
+int __weak rkusb_set_reboot_flag(int flag)
+{
+	printf("rkusb_set_reboot_flag: %d\n", reboot_flag);
+	return -ENOSYS;
+}
+
+static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
+{
+	rkusb_set_reboot_flag(reboot_flag);
+	do_reset(NULL, 0, 0, NULL);
+}
+
+static void cb_reboot(struct usb_ep *ep, struct usb_request *req)
+{
+	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
+	reboot_flag = 0;
+	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
+	reboot_flag = cbw.CDB[1];
+	rockusb_func->in_req->complete = compl_do_reset;
+	rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength, CSW_GOOD, 
+				USB_BULK_CS_WRAP_LEN);
+}
+
+static void cb_not_support(struct usb_ep *ep, struct usb_request *req)
+{
+	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
+
+	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
+	printf("Rockusb command %x not support yet\n", cbw.CDB[0]);
+	rockusb_tx_write_csw(cbw.Tag, 0, CSW_FAIL, USB_BULK_CS_WRAP_LEN);
+}
+
+#define RKUSB_STATUS_IDLE 			0
+#define RKUSB_STATUS_CMD  			1
+#define RKUSB_STATUS_RXDATA 			2
+#define RKUSB_STATUS_TXDATA 			3
+#define RKUSB_STATUS_CSW 			4
+#define RKUSB_STATUS_RXDATA_PREPARE 		5
+#define RKUSB_STATUS_TXDATA_PREPARE 		6
+
+typedef enum {
+		TEST_UNIT_READY = 0,
+		READ_FLASH_ID = 0x01,
+		TEST_BAD_BLOCK = 0x03,
+		READ_SECTOR = 0x04,
+		WRITE_SECTOR = 0x05,
+		ERASE_NORMAL = 0x06,
+		ERASE_FORCE = 0x0B,
+		READ_LBA = 0x14,
+		WRITE_LBA = 0x15,
+		ERASE_SYSTEMDISK = 0x16,
+		READ_SDRAM = 0x17,
+		WRITE_SDRAM = 0x18,
+		EXECUTE_SDRAM = 0x19,
+		READ_FLASH_INFO = 0x1A,
+		READ_CHIP_INFO = 0x1B,
+		SET_RESET_FLAG = 0x1E,
+		WRITE_EFUSE = 0x1F,
+		READ_EFUSE = 0x20,
+		READ_SPI_FLASH = 0x21,
+		WRITE_SPI_FLASH = 0x22,
+		WRITE_NEW_EFUSE = 0x23,
+		READ_NEW_EFUSE = 0x24,
+		DEVICE_RESET = 0xFF
+} USB_OPERATION_CODE;
+
+#define	K_FW_TEST_UNIT_READY	0x00
+#define	K_FW_READ_FLASH_ID		0x01
+#define	K_FW_SET_DEVICE_ID		0x02
+#define	K_FW_TEST_BAD_BLOCK		0x03
+#define	K_FW_READ_10			0x04
+#define	K_FW_WRITE_10			0x05
+#define	K_FW_ERASE_10			0x06
+#define	K_FW_WRITE_SPARE		0x07
+#define	K_FW_READ_SPARE			0x08
+
+#define	K_FW_ERASE_10_FORCE		0x0b
+#define	K_FW_GET_VERSION		0x0c
+
+#define	K_FW_LBA_READ_10		0x14
+#define	K_FW_LBA_WRITE_10		0x15
+#define	K_FW_ERASE_SYS_DISK		0x16
+#define	K_FW_SDRAM_READ_10		0x17
+#define	K_FW_SDRAM_WRITE_10		0x18
+#define	K_FW_SDRAM_EXECUTE		0x19
+#define	K_FW_READ_FLASH_INFO		0x1A
+#define	K_FW_GET_CHIP_VER		0x1B
+#define	K_FW_LOW_FORMAT			0x1C
+#define	K_FW_SET_RESET_FLAG		0x1E
+#define	K_FW_SPI_READ_10		0x21
+#define	K_FW_SPI_WRITE_10		0x22
+
+#define	K_FW_SESSION			0X30
+#define	K_FW_RESET			0xff
+
+#define CBW_DIRECTION_OUT		0x00
+#define CBW_DIRECTION_IN		0x80
+
+struct cmd_dispatch_info {
+	int cmd;
+	void (*cb)(struct usb_ep *ep, struct usb_request *req);
+};
+
+static const struct cmd_dispatch_info cmd_dispatch_info[] = {
+	{
+		.cmd = K_FW_TEST_UNIT_READY,
+		.cb = cb_test_unit_ready,
+	},
+	{
+		.cmd = K_FW_READ_FLASH_ID,
+		.cb = cb_read_storage_id,
+	},
+	{
+		.cmd = K_FW_SET_DEVICE_ID,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_TEST_BAD_BLOCK,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_READ_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_WRITE_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_ERASE_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_WRITE_SPARE,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_READ_SPARE,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_ERASE_10_FORCE,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_GET_VERSION,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_LBA_READ_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_LBA_WRITE_10,
+		.cb = cb_write_lba,
+	},
+	{
+		.cmd = K_FW_ERASE_SYS_DISK,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SDRAM_READ_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SDRAM_WRITE_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SDRAM_EXECUTE,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_READ_FLASH_INFO,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_GET_CHIP_VER,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_LOW_FORMAT,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SET_RESET_FLAG,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SPI_READ_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SPI_WRITE_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SESSION,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_RESET,
+		.cb = cb_reboot,
+	},
+};
+
+
+
+static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
+{
+	void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL;
+	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
+	int i;
+	char *cmdbuf = req->buf;
+
+	if (req->status != 0 || req->length == 0)
+		return;
+
+	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
+	printcbw(req->buf);
+
+	for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) {
+		if (cmd_dispatch_info[i].cmd == cbw.CDB[0]) {
+			func_cb = cmd_dispatch_info[i].cb;
+			break;
+		}
+	}
+
+	if (!func_cb) {
+		error("unknown command: %s", (char*)req->buf);
+		rockusb_tx_write_str("FAILunknown command");
+	} else {
+		if (req->actual < req->length) {
+			u8 *buf = (u8 *)req->buf;
+			buf[req->actual] = 0;
+			func_cb(ep, req);
+		} else {
+			error("buffer overflow");
+			rockusb_tx_write_str("FAILbuffer overflow");
+		}
+	}
+
+	*cmdbuf = '\0';
+	req->actual = 0;
+	usb_ep_queue(ep, req, 0);
+}
-- 
2.7.4

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

* [U-Boot] [U-Boot 2/3] cmd: add rockusb command
  2017-03-15  7:56 [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb Eddie Cai
  2017-03-15  7:56 ` [U-Boot] [U-Boot 1/3] drivers: usb: gadget: add the rockusb gadget Eddie Cai
@ 2017-03-15  7:56 ` Eddie Cai
  2017-03-20  2:29   ` Simon Glass
  2017-04-20 10:11   ` Lukasz Majewski
  2017-03-15  7:56 ` [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device Eddie Cai
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 36+ messages in thread
From: Eddie Cai @ 2017-03-15  7:56 UTC (permalink / raw)
  To: u-boot

this patch add rockusb command. the usage is
	rockusb <USB_controller> [<devtype>] <devnum>
e.g. rockusb 0 mmc 0

Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
---
 cmd/Kconfig       | 12 +++++++++
 cmd/Makefile      |  1 +
 cmd/rockusb.c     | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/rockusb.h | 13 +++++++++
 4 files changed, 105 insertions(+)
 create mode 100644 cmd/rockusb.c
 create mode 100644 include/rockusb.h

diff --git a/cmd/Kconfig b/cmd/Kconfig
index ef53156..dac2cc0 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -475,6 +475,18 @@ config CMD_DFU
 	  Enables the command "dfu" which is used to have U-Boot create a DFU
 	  class device via USB.
 
+config CMD_ROCKUSB
+        bool "rockusb"
+        select USB_FUNCTION_ROCKUSB
+        help
+          Enables the command "rockusb" which is used to have U-Boot create a
+          Rockusb class device via USB.
+
+config USB_FUNCTION_ROCKUSB
+        bool "Enable USB rockusb gadget"
+        help
+          This enables the USB part of the rockusb gadget.
+
 config CMD_USB_MASS_STORAGE
 	bool "UMS usb mass storage"
 	help
diff --git a/cmd/Makefile b/cmd/Makefile
index f13bb8c..f5f1663 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -141,6 +141,7 @@ endif
 
 obj-$(CONFIG_CMD_USB) += usb.o disk.o
 obj-$(CONFIG_CMD_FASTBOOT) += fastboot.o
+obj-$(CONFIG_CMD_ROCKUSB) += rockusb.o
 obj-$(CONFIG_CMD_FS_UUID) += fs_uuid.o
 
 obj-$(CONFIG_CMD_USB_MASS_STORAGE) += usb_mass_storage.o
diff --git a/cmd/rockusb.c b/cmd/rockusb.c
new file mode 100644
index 0000000..f5bd86e
--- /dev/null
+++ b/cmd/rockusb.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 Eddie Cai <eddie.cai.linux@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <g_dnl.h>
+#include <usb.h>
+#include <rockusb.h>
+
+
+static int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	int controller_index, dev_index;
+	char *usb_controller;
+	char *devtype;
+	char *devnum;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	usb_controller = argv[1];
+	controller_index = simple_strtoul(usb_controller, NULL, 0);
+
+	if (argc >= 4) {
+		devtype = argv[2];
+		devnum  = argv[3];
+	} else {
+		devtype = "mmc";
+		devnum  = argv[2];
+	}
+	dev_index = simple_strtoul(devnum, NULL, 0);
+	rockusb_dev_init(devtype, dev_index);
+
+	ret = board_usb_init(controller_index, USB_INIT_DEVICE);
+	if (ret) {
+		error("USB init failed: %d", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	g_dnl_clear_detach();
+	ret = g_dnl_register("usb_dnl_rockusb");
+	if (ret)
+		return ret;
+	printf("do_rockusb1\n");
+	if (!g_dnl_board_usb_cable_connected()) {
+		puts("\rUSB cable not detected.\n" \
+		     "Command exit.\n");
+		ret = CMD_RET_FAILURE;
+		goto exit;
+	}
+
+	while (1) {
+		if (g_dnl_detach())
+			break;
+		if (ctrlc())
+			break;
+		usb_gadget_handle_interrupts(controller_index);
+	}
+	printf("do_rockusb2\n");
+	ret = CMD_RET_SUCCESS;
+
+exit:
+	g_dnl_unregister();
+	g_dnl_clear_detach();
+	board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+
+	return ret;
+}
+
+U_BOOT_CMD(rockusb, 4, 1, do_rockusb,
+	"Use the ROCKUSB",
+	"rockusb <USB_controller> [<devtype>] <devnum>  e.g. rockusb 0 mmc 0\n"
+	"    devtype defaults to mmc"
+);
diff --git a/include/rockusb.h b/include/rockusb.h
new file mode 100644
index 0000000..cdea63d
--- /dev/null
+++ b/include/rockusb.h
@@ -0,0 +1,13 @@
+/*
+ * (C) Copyright 2017
+ *
+ * Eddie Cai <eddie.cai.linux@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#ifndef _ROCKUSB_H_
+#define _ROCKUSB_H_
+
+void rockusb_dev_init(char *dev_type, int dev_index);
+
+#endif /* _ROCKUSB_H_ */
-- 
2.7.4

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

* [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device
  2017-03-15  7:56 [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb Eddie Cai
  2017-03-15  7:56 ` [U-Boot] [U-Boot 1/3] drivers: usb: gadget: add the rockusb gadget Eddie Cai
  2017-03-15  7:56 ` [U-Boot] [U-Boot 2/3] cmd: add rockusb command Eddie Cai
@ 2017-03-15  7:56 ` Eddie Cai
  2017-03-20  2:30   ` Simon Glass
  2017-04-20 10:12   ` Lukasz Majewski
  2017-03-15  9:06 ` [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb Lukasz Majewski
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 36+ messages in thread
From: Eddie Cai @ 2017-03-15  7:56 UTC (permalink / raw)
  To: u-boot

this patch enable rockusb support on rk3288 based device.

Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
---
 include/configs/rk3288_common.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
index b5606d4..b19a34d 100644
--- a/include/configs/rk3288_common.h
+++ b/include/configs/rk3288_common.h
@@ -74,6 +74,10 @@
 #define CONFIG_FASTBOOT_BUF_ADDR	CONFIG_SYS_LOAD_ADDR
 #define CONFIG_FASTBOOT_BUF_SIZE	0x08000000
 
+/* rockusb  */
+#define CONFIG_CMD_ROCKUSB
+#define CONFIG_USB_FUNCTION_ROCKUSB
+
 /* usb mass storage */
 #define CONFIG_USB_FUNCTION_MASS_STORAGE
 #define CONFIG_CMD_USB_MASS_STORAGE
-- 
2.7.4

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

* [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb
  2017-03-15  7:56 [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb Eddie Cai
                   ` (2 preceding siblings ...)
  2017-03-15  7:56 ` [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device Eddie Cai
@ 2017-03-15  9:06 ` Lukasz Majewski
  2017-03-15  9:31   ` Eddie Cai
  2017-03-16 21:26 ` Marek Vasut
  2017-03-27  8:27 ` Lukasz Majewski
  5 siblings, 1 reply; 36+ messages in thread
From: Lukasz Majewski @ 2017-03-15  9:06 UTC (permalink / raw)
  To: u-boot

On Wed, 15 Mar 2017 15:56:02 +0800
Eddie Cai <eddie.cai.linux@gmail.com> wrote:

> rockusb is a protocol run between host pc and device. it help people
> get device info, flash image to device. this patch implement rockusb
> on device side. 

Thank you for your patch. I will review it shortly.

If I might ask - is there any high-level documentation (pdf, webpage,
etc) describing this protocol?

If yes, please add some very short entry to ./doc repository
(e.g. ./doc/README.rockusb).

> 
> Eddie Cai (3):
>   drivers: usb: gadget: add the rockusb gadget
>   cmd: add rockusb command
>   rockchip: rk3288: enable rockusb support on rk3288 based device
> 
>  cmd/Kconfig                     |  12 +
>  cmd/Makefile                    |   1 +
>  cmd/rockusb.c                   |  79 ++++
>  drivers/usb/gadget/Makefile     |   1 +
>  drivers/usb/gadget/f_rockusb.c  | 801
> ++++++++++++++++++++++++++++++++++++++++
> include/configs/rk3288_common.h |   4 +
> include/rockusb.h               |  13 + 7 files changed, 911
> insertions(+) create mode 100644 cmd/rockusb.c
>  create mode 100644 drivers/usb/gadget/f_rockusb.c
>  create mode 100644 include/rockusb.h
> 


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
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

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

* [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb
  2017-03-15  9:06 ` [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb Lukasz Majewski
@ 2017-03-15  9:31   ` Eddie Cai
  2017-03-15  9:46     ` Lukasz Majewski
  0 siblings, 1 reply; 36+ messages in thread
From: Eddie Cai @ 2017-03-15  9:31 UTC (permalink / raw)
  To: u-boot

Hi Lukasz

2017-03-15 17:06 GMT+08:00 Lukasz Majewski <lukma@denx.de>:

> On Wed, 15 Mar 2017 15:56:02 +0800
> Eddie Cai <eddie.cai.linux@gmail.com> wrote:
>
> > rockusb is a protocol run between host pc and device. it help people
> > get device info, flash image to device. this patch implement rockusb
> > on device side.
>
> Thank you for your patch. I will review it shortly.
>
> If I might ask - is there any high-level documentation (pdf, webpage,
> etc) describing this protocol?
>
> If yes, please add some very short entry to ./doc repository
> (e.g. ./doc/README.rockusb).
>
Thanks for your quick reply. I will add README.rockusb in next version.

>
> >
> > Eddie Cai (3):
> >   drivers: usb: gadget: add the rockusb gadget
> >   cmd: add rockusb command
> >   rockchip: rk3288: enable rockusb support on rk3288 based device
> >
> >  cmd/Kconfig                     |  12 +
> >  cmd/Makefile                    |   1 +
> >  cmd/rockusb.c                   |  79 ++++
> >  drivers/usb/gadget/Makefile     |   1 +
> >  drivers/usb/gadget/f_rockusb.c  | 801
> > ++++++++++++++++++++++++++++++++++++++++
> > include/configs/rk3288_common.h |   4 +
> > include/rockusb.h               |  13 + 7 files changed, 911
> > insertions(+) create mode 100644 cmd/rockusb.c
> >  create mode 100644 drivers/usb/gadget/f_rockusb.c
> >  create mode 100644 include/rockusb.h
> >
>
>
> Best regards,
>
> Lukasz Majewski
>
> --
>
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> 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
>

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

* [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb
  2017-03-15  9:31   ` Eddie Cai
@ 2017-03-15  9:46     ` Lukasz Majewski
  0 siblings, 0 replies; 36+ messages in thread
From: Lukasz Majewski @ 2017-03-15  9:46 UTC (permalink / raw)
  To: u-boot

On Wed, 15 Mar 2017 17:31:27 +0800
Eddie Cai <eddie.cai.linux@gmail.com> wrote:

> Hi Lukasz
> 
> 2017-03-15 17:06 GMT+08:00 Lukasz Majewski <lukma@denx.de>:
> 
> > On Wed, 15 Mar 2017 15:56:02 +0800
> > Eddie Cai <eddie.cai.linux@gmail.com> wrote:
> >
> > > rockusb is a protocol run between host pc and device. it help
> > > people get device info, flash image to device. this patch
> > > implement rockusb on device side.
> >
> > Thank you for your patch. I will review it shortly.
> >
> > If I might ask - is there any high-level documentation (pdf,
> > webpage, etc) describing this protocol?
> >
> > If yes, please add some very short entry to ./doc repository
> > (e.g. ./doc/README.rockusb).
> >
> Thanks for your quick reply. I will add README.rockusb in next
> version.

Great :-)

As a reference, you can look to ./doc/README.dfutftp

> 
> >
> > >
> > > Eddie Cai (3):
> > >   drivers: usb: gadget: add the rockusb gadget
> > >   cmd: add rockusb command
> > >   rockchip: rk3288: enable rockusb support on rk3288 based device
> > >
> > >  cmd/Kconfig                     |  12 +
> > >  cmd/Makefile                    |   1 +
> > >  cmd/rockusb.c                   |  79 ++++
> > >  drivers/usb/gadget/Makefile     |   1 +
> > >  drivers/usb/gadget/f_rockusb.c  | 801
> > > ++++++++++++++++++++++++++++++++++++++++
> > > include/configs/rk3288_common.h |   4 +
> > > include/rockusb.h               |  13 + 7 files changed, 911
> > > insertions(+) create mode 100644 cmd/rockusb.c
> > >  create mode 100644 drivers/usb/gadget/f_rockusb.c
> > >  create mode 100644 include/rockusb.h
> > >
> >
> >
> > Best regards,
> >
> > Lukasz Majewski
> >
> > --
> >
> > DENX Software Engineering GmbH,      Managing Director: Wolfgang
> > Denk 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
> >




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
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

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

* [U-Boot] [U-Boot 1/3] drivers: usb: gadget: add the rockusb gadget
  2017-03-15  7:56 ` [U-Boot] [U-Boot 1/3] drivers: usb: gadget: add the rockusb gadget Eddie Cai
@ 2017-03-16  7:05   ` Kever Yang
  2017-03-20  7:24     ` Eddie Cai
  2017-04-20 10:04   ` Lukasz Majewski
  1 sibling, 1 reply; 36+ messages in thread
From: Kever Yang @ 2017-03-16  7:05 UTC (permalink / raw)
  To: u-boot

Hi Eddie,

     I recommend you to use ums framework instead of fastboot, because
ums have dual-buffer which improve performance.

Thanks,
- Kever
On 03/15/2017 03:56 PM, Eddie Cai wrote:
> this patch implement fastboot protocol on the device side. this is based on USB
> download gadget infrastructure. the rockusb function implements the rd, wl, rid
> commands. it can work with rkdeveloptool;
> https://github.com/rockchip-linux/rkdeveloptool
>
> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> ---
>   drivers/usb/gadget/Makefile    |   1 +
>   drivers/usb/gadget/f_rockusb.c | 801 +++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 802 insertions(+)
>   create mode 100644 drivers/usb/gadget/f_rockusb.c
>
> diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
> index 0fbbb7c..0eb27a3 100644
> --- a/drivers/usb/gadget/Makefile
> +++ b/drivers/usb/gadget/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
>   obj-$(CONFIG_USB_FUNCTION_DFU) += f_dfu.o
>   obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
>   obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
> +obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o
>   endif
>   endif
>   ifdef CONFIG_USB_ETHER
> diff --git a/drivers/usb/gadget/f_rockusb.c b/drivers/usb/gadget/f_rockusb.c
> new file mode 100644
> index 0000000..a67cb35
> --- /dev/null
> +++ b/drivers/usb/gadget/f_rockusb.c
> @@ -0,0 +1,801 @@
> +/*
> + * (C) Copyright 2017
> + *
> + * Eddie Cai <eddie.cai.linux@gmail.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <config.h>
> +#include <common.h>
> +#include <errno.h>
> +#include <malloc.h>
> +#include <linux/usb/ch9.h>
> +#include <linux/usb/gadget.h>
> +#include <linux/usb/composite.h>
> +#include <linux/compiler.h>
> +#include <version.h>
> +#include <g_dnl.h>
> +
> +#define ROCKUSB_VERSION		"0.1"
> +
> +#define ROCKUSB_INTERFACE_CLASS	0xff
> +#define ROCKUSB_INTERFACE_SUB_CLASS	0x06
> +#define ROCKUSB_INTERFACE_PROTOCOL	0x05
> +
> +#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0  (0x0200)
> +#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1  (0x0040)
> +#define TX_ENDPOINT_MAXIMUM_PACKET_SIZE      (0x0040)
> +
> +#define EP_BUFFER_SIZE			4096
> +/*
> + * EP_BUFFER_SIZE must always be an integral multiple of maxpacket size
> + * (64 or 512 or 1024), else we break on certain controllers like DWC3
> + * that expect bulk OUT requests to be divisible by maxpacket size.
> + */
> +
> +struct f_rockusb {
> +	struct usb_function usb_function;
> +
> +	/* IN/OUT EP's and corresponding requests */
> +	struct usb_ep *in_ep, *out_ep;
> +	struct usb_request *in_req, *out_req;
> +};
> +
> +static inline struct f_rockusb *func_to_rockusb(struct usb_function *f)
> +{
> +	return container_of(f, struct f_rockusb, usb_function);
> +}
> +
> +static struct f_rockusb *rockusb_func;
> +
> +static struct usb_endpoint_descriptor fs_ep_in = {
> +	.bLength            = USB_DT_ENDPOINT_SIZE,
> +	.bDescriptorType    = USB_DT_ENDPOINT,
> +	.bEndpointAddress   = USB_DIR_IN,
> +	.bmAttributes       = USB_ENDPOINT_XFER_BULK,
> +	.wMaxPacketSize     = cpu_to_le16(64),
> +};
> +
> +static struct usb_endpoint_descriptor fs_ep_out = {
> +	.bLength		= USB_DT_ENDPOINT_SIZE,
> +	.bDescriptorType	= USB_DT_ENDPOINT,
> +	.bEndpointAddress	= USB_DIR_OUT,
> +	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
> +	.wMaxPacketSize		= cpu_to_le16(64),
> +};
> +
> +static struct usb_endpoint_descriptor hs_ep_in = {
> +	.bLength		= USB_DT_ENDPOINT_SIZE,
> +	.bDescriptorType	= USB_DT_ENDPOINT,
> +	.bEndpointAddress	= USB_DIR_IN,
> +	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
> +	.wMaxPacketSize		= cpu_to_le16(512),
> +};
> +
> +static struct usb_endpoint_descriptor hs_ep_out = {
> +	.bLength		= USB_DT_ENDPOINT_SIZE,
> +	.bDescriptorType	= USB_DT_ENDPOINT,
> +	.bEndpointAddress	= USB_DIR_OUT,
> +	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
> +	.wMaxPacketSize		= cpu_to_le16(512),
> +};
> +
> +static struct usb_interface_descriptor interface_desc = {
> +	.bLength		= USB_DT_INTERFACE_SIZE,
> +	.bDescriptorType	= USB_DT_INTERFACE,
> +	.bInterfaceNumber	= 0x00,
> +	.bAlternateSetting	= 0x00,
> +	.bNumEndpoints		= 0x02,
> +	.bInterfaceClass	= ROCKUSB_INTERFACE_CLASS,
> +	.bInterfaceSubClass	= ROCKUSB_INTERFACE_SUB_CLASS,
> +	.bInterfaceProtocol	= ROCKUSB_INTERFACE_PROTOCOL,
> +};
> +
> +static struct usb_descriptor_header *rkusb_fs_function[] = {
> +	(struct usb_descriptor_header *)&interface_desc,
> +	(struct usb_descriptor_header *)&fs_ep_in,
> +	(struct usb_descriptor_header *)&fs_ep_out,
> +};
> +
> +static struct usb_descriptor_header *rkusb_hs_function[] = {
> +	(struct usb_descriptor_header *)&interface_desc,
> +	(struct usb_descriptor_header *)&hs_ep_in,
> +	(struct usb_descriptor_header *)&hs_ep_out,
> +	NULL,
> +};
> +
> +static struct usb_endpoint_descriptor *
> +rkusb_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
> +	    struct usb_endpoint_descriptor *hs)
> +{
> +	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
> +		return hs;
> +	return fs;
> +}
> +
> +/*
> + * static strings, in UTF-8
> + */
> +static const char rkusb_name[] = "Rockchip Rockusb";
> +
> +static struct usb_string rkusb_string_defs[] = {
> +	[0].s = rkusb_name,
> +	{  }			/* end of list */
> +};
> +
> +static struct usb_gadget_strings stringtab_rkusb = {
> +	.language	= 0x0409,	/* en-us */
> +	.strings	= rkusb_string_defs,
> +};
> +
> +static struct usb_gadget_strings *rkusb_strings[] = {
> +	&stringtab_rkusb,
> +	NULL,
> +};
> +
> +static void rx_handler_command(struct usb_ep *ep, struct usb_request *req);
> +static int rockusb_tx_write_csw(u32 Tag, int residue, u8 Status, int size);
> +
> +static void rockusb_complete(struct usb_ep *ep, struct usb_request *req)
> +{
> +	int status = req->status;
> +	if (!status)
> +		return;
> +	debug("status: %d ep '%s' trans: %d\n", status, ep->name, req->actual);
> +}
> +
> +static int rockusb_bind(struct usb_configuration *c, struct usb_function *f)
> +{
> +	int id;
> +	struct usb_gadget *gadget = c->cdev->gadget;
> +	struct f_rockusb *f_rkusb = func_to_rockusb(f);
> +	const char *s;
> +
> +	id = usb_interface_id(c, f);
> +	if (id < 0)
> +		return id;
> +	interface_desc.bInterfaceNumber = id;
> +
> +	id = usb_string_id(c->cdev);
> +	if (id < 0)
> +		return id;
> +
> +	rkusb_string_defs[0].id = id;
> +	interface_desc.iInterface = id;
> +
> +	f_rkusb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in);
> +	if (!f_rkusb->in_ep)
> +		return -ENODEV;
> +	f_rkusb->in_ep->driver_data = c->cdev;
> +
> +	f_rkusb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out);
> +	if (!f_rkusb->out_ep)
> +		return -ENODEV;
> +	f_rkusb->out_ep->driver_data = c->cdev;
> +
> +	f->descriptors = rkusb_fs_function;
> +
> +	if (gadget_is_dualspeed(gadget)) {
> +		hs_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress;
> +		hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress;
> +		f->hs_descriptors = rkusb_hs_function;
> +	}
> +
> +	s = getenv("serial#");
> +	if (s)
> +		g_dnl_set_serialnumber((char *)s);
> +
> +	return 0;
> +}
> +
> +static void rockusb_unbind(struct usb_configuration *c, struct usb_function *f)
> +{
> +	memset(rockusb_func, 0, sizeof(*rockusb_func));
> +}
> +
> +static void rockusb_disable(struct usb_function *f)
> +{
> +	struct f_rockusb *f_rkusb = func_to_rockusb(f);
> +
> +	usb_ep_disable(f_rkusb->out_ep);
> +	usb_ep_disable(f_rkusb->in_ep);
> +
> +	if (f_rkusb->out_req) {
> +		free(f_rkusb->out_req->buf);
> +		usb_ep_free_request(f_rkusb->out_ep, f_rkusb->out_req);
> +		f_rkusb->out_req = NULL;
> +	}
> +	if (f_rkusb->in_req) {
> +		free(f_rkusb->in_req->buf);
> +		usb_ep_free_request(f_rkusb->in_ep, f_rkusb->in_req);
> +		f_rkusb->in_req = NULL;
> +	}
> +}
> +
> +static struct usb_request *rockusb_start_ep(struct usb_ep *ep)
> +{
> +	struct usb_request *req;
> +
> +	req = usb_ep_alloc_request(ep, 0);
> +	if (!req)
> +		return NULL;
> +
> +	req->length = EP_BUFFER_SIZE;
> +	req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE);
> +	if (!req->buf) {
> +		usb_ep_free_request(ep, req);
> +		return NULL;
> +	}
> +
> +	memset(req->buf, 0, req->length);
> +	return req;
> +}
> +
> +static int rockusb_set_alt(struct usb_function *f,
> +			    unsigned interface, unsigned alt)
> +{
> +	int ret;
> +	struct usb_composite_dev *cdev = f->config->cdev;
> +	struct usb_gadget *gadget = cdev->gadget;
> +	struct f_rockusb *f_rkusb = func_to_rockusb(f);
> +	const struct usb_endpoint_descriptor *d;
> +
> +	debug("%s: func: %s intf: %d alt: %d\n",
> +	      __func__, f->name, interface, alt);
> +
> +	d = rkusb_ep_desc(gadget, &fs_ep_out, &hs_ep_out);
> +	ret = usb_ep_enable(f_rkusb->out_ep, d);
> +	if (ret) {
> +		puts("failed to enable out ep\n");
> +		return ret;
> +	}
> +
> +	f_rkusb->out_req = rockusb_start_ep(f_rkusb->out_ep);
> +	if (!f_rkusb->out_req) {
> +		puts("failed to alloc out req\n");
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +	f_rkusb->out_req->complete = rx_handler_command;
> +
> +	d = rkusb_ep_desc(gadget, &fs_ep_in, &hs_ep_in);
> +	ret = usb_ep_enable(f_rkusb->in_ep, d);
> +	if (ret) {
> +		puts("failed to enable in ep\n");
> +		goto err;
> +	}
> +
> +	f_rkusb->in_req = rockusb_start_ep(f_rkusb->in_ep);
> +	if (!f_rkusb->in_req) {
> +		puts("failed alloc req in\n");
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +	f_rkusb->in_req->complete = rockusb_complete;
> +
> +	ret = usb_ep_queue(f_rkusb->out_ep, f_rkusb->out_req, 0);
> +	if (ret)
> +		goto err;
> +
> +	return 0;
> +err:
> +	rockusb_disable(f);
> +	return ret;
> +}
> +
> +static int rockusb_add(struct usb_configuration *c)
> +{
> +	struct f_rockusb *f_rkusb = rockusb_func;
> +	int status;
> +
> +	debug("%s: cdev: 0x%p\n", __func__, c->cdev);
> +
> +	if (!f_rkusb) {
> +		f_rkusb = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_rkusb));
> +		if (!f_rkusb)
> +			return -ENOMEM;
> +
> +		rockusb_func = f_rkusb;
> +		memset(f_rkusb, 0, sizeof(*f_rkusb));
> +	}
> +
> +	f_rkusb->usb_function.name = "f_rockusb";
> +	f_rkusb->usb_function.bind = rockusb_bind;
> +	f_rkusb->usb_function.unbind = rockusb_unbind;
> +	f_rkusb->usb_function.set_alt = rockusb_set_alt;
> +	f_rkusb->usb_function.disable = rockusb_disable;
> +	f_rkusb->usb_function.strings = rkusb_strings;
> +
> +	status = usb_add_function(c, &f_rkusb->usb_function);
> +	if (status) {
> +		free(f_rkusb);
> +		rockusb_func = f_rkusb;
> +	}
> +	return status;
> +}
> +
> +char *rockusb_dev_type = 0;
> +int rockusb_dev_index = 0;
> +
> +void rockusb_dev_init(char *dev_type, int dev_index)
> +{
> +	rockusb_dev_type = dev_type;
> +	rockusb_dev_index = dev_index;
> +}
> +
> +DECLARE_GADGET_BIND_CALLBACK(usb_dnl_rockusb, rockusb_add);
> +
> +static int rockusb_tx_write(const char *buffer, unsigned int buffer_size)
> +{
> +	struct usb_request *in_req = rockusb_func->in_req;
> +	int ret;
> +
> +	memcpy(in_req->buf, buffer, buffer_size);
> +	in_req->length = buffer_size;
> +	usb_ep_dequeue(rockusb_func->in_ep, in_req);
> +	ret = usb_ep_queue(rockusb_func->in_ep, in_req, 0);
> +	if (ret)
> +		printf("Error %d on queue\n", ret);
> +	return 0;
> +}
> +
> +static int rockusb_tx_write_str(const char *buffer)
> +{
> +	return rockusb_tx_write(buffer, strlen(buffer));
> +}
> +
> +/* Bulk-only data structures */
> +
> +/* Command Block Wrapper */
> +struct fsg_bulk_cb_wrap {
> +	__le32	Signature;		/* Contains 'USBC' */
> +	u32	Tag;			/* Unique per command id */
> +	__le32	DataTransferLength;	/* Size of the data */
> +	u8	Flags;			/* Direction in bit 7 */
> +	u8	Lun;			/* LUN (normally 0) */
> +	u8	Length;			/* Of the CDB, <= MAX_COMMAND_SIZE */
> +	u8	CDB[16];		/* Command Data Block */
> +};
> +
> +#define USB_BULK_CB_WRAP_LEN	31
> +#define USB_BULK_CB_SIG		0x43425355	/* Spells out USBC */
> +#define USB_BULK_IN_FLAG	0x80
> +
> +/* Command Status Wrapper */
> +struct bulk_cs_wrap {
> +	__le32	Signature;		/* Should = 'USBS' */
> +	u32	Tag;			/* Same as original command */
> +	__le32	Residue;		/* Amount not transferred */
> +	u8	Status;			/* See below */
> +};
> +
> +#define USB_BULK_CS_WRAP_LEN	13
> +#define USB_BULK_CS_SIG		0x53425355	/* Spells out 'USBS' */
> +#define USB_STATUS_PASS		0
> +#define USB_STATUS_FAIL		1
> +#define USB_STATUS_PHASE_ERROR	2
> +
> +
> +#define	CSW_GOOD		0x00
> +#define	CSW_FAIL		0x01
> +
> +static void printcbw(char *buf)
> +{
> +	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +
> +	memcpy((char*)&cbw, buf, USB_BULK_CB_WRAP_LEN);
> +
> +	debug("cbw: Signature:%x\n", cbw.Signature);
> +	debug("cbw: Tag=%x\n", cbw.Tag);
> +	debug("cbw: DataTransferLength=%d\n", cbw.DataTransferLength);
> +	debug("cbw: Flags=%x\n", cbw.Flags);
> +	debug("cbw: Lun=%d\n", cbw.Lun);
> +	debug("cbw: Length=%d\n", cbw.Length);
> +	debug("cbw: ucOperCode=%x\n", cbw.CDB[0]);
> +	debug("cbw: ucReserved=%x\n", cbw.CDB[1]);
> +	debug("cbw: dwAddress:%x %x %x %x\n", cbw.CDB[5], cbw.CDB[4],
> +						cbw.CDB[3], cbw.CDB[2]);
> +	debug("cbw: ucReserved2=%x\n", cbw.CDB[6]);
> +	debug("cbw: usLength:%x %x\n", cbw.CDB[8], cbw.CDB[7]);
> +
> +}
> +
> +static void printcsw(char *buf)
> +{
> +	struct bulk_cs_wrap csw __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +
> +	memcpy((char*)&csw, buf, USB_BULK_CS_WRAP_LEN);
> +	debug("csw: Signature:%x\n", csw.Signature);
> +	debug("csw: Tag:%x\n", csw.Tag);
> +	debug("csw: Residue:%x\n", csw.Residue);
> +	debug("csw: Status:%x\n", csw.Status);
> +
> +}
> +
> +static int rockusb_tx_write_csw(u32 Tag, int residue, u8 Status, int size)
> +{
> +	struct bulk_cs_wrap csw __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +	csw.Signature = cpu_to_le32(USB_BULK_CS_SIG);
> +	csw.Tag = Tag;
> +	csw.Residue = cpu_to_be32(residue);
> +	csw.Status = Status;
> +	printcsw((char*)&csw);
> +	return rockusb_tx_write((char*)&csw, size);
> +}
> +
> +int download_tag = 0;
> +int download_lba = 0;
> +static unsigned int download_size;
> +static unsigned int download_bytes;
> +struct blk_desc *download_desc = 0;
> +
> +static unsigned int rx_bytes_expected(struct usb_ep *ep)
> +{
> +	int rx_remain = download_size - download_bytes;
> +	unsigned int rem;
> +	unsigned int maxpacket = ep->maxpacket;
> +
> +	if (rx_remain <= 0)
> +		return 0;
> +	else if (rx_remain > EP_BUFFER_SIZE)
> +		return EP_BUFFER_SIZE;
> +
> +	rem = rx_remain % maxpacket;
> +	if (rem > 0)
> +		rx_remain = rx_remain + (maxpacket - rem);
> +
> +	return rx_remain;
> +}
> +
> +static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
> +{
> +	unsigned int transfer_size = download_size - download_bytes;
> +	const unsigned char *buffer = req->buf;
> +	unsigned int buffer_size = req->actual;
> +
> +	if(!download_desc){
> +		printf("rx_handler_dl_image blk_get_dev\n");
> +		download_desc = blk_get_dev(rockusb_dev_type, rockusb_dev_index);
> +		if (!download_desc || download_desc->type == DEV_TYPE_UNKNOWN){
> +			error("invalid mmc device\n");
> +			rockusb_tx_write_csw(download_tag, 0, CSW_FAIL,
> +						USB_BULK_CS_WRAP_LEN);
> +			return;
> +		}
> +	}
> +
> +	if (req->status != 0) {
> +		printf("Bad status: %d\n", req->status);
> +		rockusb_tx_write_csw(download_tag, 0,
> +					CSW_FAIL, USB_BULK_CS_WRAP_LEN);
> +		return;
> +	}
> +
> +	if (buffer_size < transfer_size)
> +		transfer_size = buffer_size;
> +
> +	memcpy((void *)CONFIG_FASTBOOT_BUF_ADDR + download_bytes,
> +	       buffer, transfer_size);
> +	download_bytes += transfer_size;
> +
> +	/* Check if transfer is done */
> +	if (download_bytes >= download_size) {
> +		int blks = 0, blkcnt = download_size/512;
> +		printf("download %d bytes finished, start writing to lba %x\n",
> +				 download_bytes, download_lba);
> +		blks = blk_dwrite(download_desc, download_lba, blkcnt,
> +					(char*)CONFIG_FASTBOOT_BUF_ADDR);
> +		if (blks != blkcnt) {
> +			error("failed writing to device %s: %d\n",
> +				rockusb_dev_type, rockusb_dev_index);
> +			rockusb_tx_write_csw(download_tag, 0,
> +						CSW_FAIL, USB_BULK_CS_WRAP_LEN);
> +			return;
> +		}
> +
> +		req->complete = rx_handler_command;
> +		req->length = EP_BUFFER_SIZE;
> +		download_size = 0;
> +		printf("done\n");
> +		rockusb_tx_write_csw(download_tag, 0, CSW_GOOD,
> +					USB_BULK_CS_WRAP_LEN);
> +	} else {
> +		req->length = rx_bytes_expected(ep);
> +	}
> +
> +	req->actual = 0;
> +	usb_ep_queue(ep, req, 0);
> +}
> +
> +static void cb_test_unit_ready(struct usb_ep *ep, struct usb_request *req)
> +{
> +	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +
> +	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> +
> +	rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength,
> +				CSW_GOOD, USB_BULK_CS_WRAP_LEN);
> +
> +}
> +
> +static void cb_read_storage_id(struct usb_ep *ep, struct usb_request *req)
> +{
> +	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +	char emmc_id[] = "EMMC ";
> +
> +	printf("cb_read_storage_id\n");
> +	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> +	rockusb_tx_write_str(emmc_id);//only support emmc now
> +	rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength, CSW_GOOD,
> +				USB_BULK_CS_WRAP_LEN);
> +}
> +
> +static void cb_write_lba(struct usb_ep *ep, struct usb_request *req)
> +{
> +	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +	int sector_count;
> +
> +	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> +	sector_count = (int)get_unaligned_be16(&cbw.CDB[7]);
> +	download_lba = get_unaligned_be32(&cbw.CDB[2]);
> +	download_size = sector_count * 512;
> +	download_bytes = 0;
> +	download_tag = cbw.Tag;
> +	if ((0 == download_size) || (download_size>CONFIG_FASTBOOT_BUF_SIZE)){
> +		rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength,
> +					CSW_FAIL, USB_BULK_CS_WRAP_LEN);
> +	} else {
> +		req->complete = rx_handler_dl_image;
> +		req->length = rx_bytes_expected(ep);
> +	}
> +}
> +
> +static int reboot_flag;
> +
> +int __weak rkusb_set_reboot_flag(int flag)
> +{
> +	printf("rkusb_set_reboot_flag: %d\n", reboot_flag);
> +	return -ENOSYS;
> +}
> +
> +static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
> +{
> +	rkusb_set_reboot_flag(reboot_flag);
> +	do_reset(NULL, 0, 0, NULL);
> +}
> +
> +static void cb_reboot(struct usb_ep *ep, struct usb_request *req)
> +{
> +	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +	reboot_flag = 0;
> +	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> +	reboot_flag = cbw.CDB[1];
> +	rockusb_func->in_req->complete = compl_do_reset;
> +	rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength, CSW_GOOD,
> +				USB_BULK_CS_WRAP_LEN);
> +}
> +
> +static void cb_not_support(struct usb_ep *ep, struct usb_request *req)
> +{
> +	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +
> +	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> +	printf("Rockusb command %x not support yet\n", cbw.CDB[0]);
> +	rockusb_tx_write_csw(cbw.Tag, 0, CSW_FAIL, USB_BULK_CS_WRAP_LEN);
> +}
> +
> +#define RKUSB_STATUS_IDLE 			0
> +#define RKUSB_STATUS_CMD  			1
> +#define RKUSB_STATUS_RXDATA 			2
> +#define RKUSB_STATUS_TXDATA 			3
> +#define RKUSB_STATUS_CSW 			4
> +#define RKUSB_STATUS_RXDATA_PREPARE 		5
> +#define RKUSB_STATUS_TXDATA_PREPARE 		6
> +
> +typedef enum {
> +		TEST_UNIT_READY = 0,
> +		READ_FLASH_ID = 0x01,
> +		TEST_BAD_BLOCK = 0x03,
> +		READ_SECTOR = 0x04,
> +		WRITE_SECTOR = 0x05,
> +		ERASE_NORMAL = 0x06,
> +		ERASE_FORCE = 0x0B,
> +		READ_LBA = 0x14,
> +		WRITE_LBA = 0x15,
> +		ERASE_SYSTEMDISK = 0x16,
> +		READ_SDRAM = 0x17,
> +		WRITE_SDRAM = 0x18,
> +		EXECUTE_SDRAM = 0x19,
> +		READ_FLASH_INFO = 0x1A,
> +		READ_CHIP_INFO = 0x1B,
> +		SET_RESET_FLAG = 0x1E,
> +		WRITE_EFUSE = 0x1F,
> +		READ_EFUSE = 0x20,
> +		READ_SPI_FLASH = 0x21,
> +		WRITE_SPI_FLASH = 0x22,
> +		WRITE_NEW_EFUSE = 0x23,
> +		READ_NEW_EFUSE = 0x24,
> +		DEVICE_RESET = 0xFF
> +} USB_OPERATION_CODE;
> +
> +#define	K_FW_TEST_UNIT_READY	0x00
> +#define	K_FW_READ_FLASH_ID		0x01
> +#define	K_FW_SET_DEVICE_ID		0x02
> +#define	K_FW_TEST_BAD_BLOCK		0x03
> +#define	K_FW_READ_10			0x04
> +#define	K_FW_WRITE_10			0x05
> +#define	K_FW_ERASE_10			0x06
> +#define	K_FW_WRITE_SPARE		0x07
> +#define	K_FW_READ_SPARE			0x08
> +
> +#define	K_FW_ERASE_10_FORCE		0x0b
> +#define	K_FW_GET_VERSION		0x0c
> +
> +#define	K_FW_LBA_READ_10		0x14
> +#define	K_FW_LBA_WRITE_10		0x15
> +#define	K_FW_ERASE_SYS_DISK		0x16
> +#define	K_FW_SDRAM_READ_10		0x17
> +#define	K_FW_SDRAM_WRITE_10		0x18
> +#define	K_FW_SDRAM_EXECUTE		0x19
> +#define	K_FW_READ_FLASH_INFO		0x1A
> +#define	K_FW_GET_CHIP_VER		0x1B
> +#define	K_FW_LOW_FORMAT			0x1C
> +#define	K_FW_SET_RESET_FLAG		0x1E
> +#define	K_FW_SPI_READ_10		0x21
> +#define	K_FW_SPI_WRITE_10		0x22
> +
> +#define	K_FW_SESSION			0X30
> +#define	K_FW_RESET			0xff
> +
> +#define CBW_DIRECTION_OUT		0x00
> +#define CBW_DIRECTION_IN		0x80
> +
> +struct cmd_dispatch_info {
> +	int cmd;
> +	void (*cb)(struct usb_ep *ep, struct usb_request *req);
> +};
> +
> +static const struct cmd_dispatch_info cmd_dispatch_info[] = {
> +	{
> +		.cmd = K_FW_TEST_UNIT_READY,
> +		.cb = cb_test_unit_ready,
> +	},
> +	{
> +		.cmd = K_FW_READ_FLASH_ID,
> +		.cb = cb_read_storage_id,
> +	},
> +	{
> +		.cmd = K_FW_SET_DEVICE_ID,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_TEST_BAD_BLOCK,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_READ_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_WRITE_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_ERASE_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_WRITE_SPARE,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_READ_SPARE,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_ERASE_10_FORCE,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_GET_VERSION,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_LBA_READ_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_LBA_WRITE_10,
> +		.cb = cb_write_lba,
> +	},
> +	{
> +		.cmd = K_FW_ERASE_SYS_DISK,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SDRAM_READ_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SDRAM_WRITE_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SDRAM_EXECUTE,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_READ_FLASH_INFO,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_GET_CHIP_VER,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_LOW_FORMAT,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SET_RESET_FLAG,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SPI_READ_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SPI_WRITE_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SESSION,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_RESET,
> +		.cb = cb_reboot,
> +	},
> +};
> +
> +
> +
> +static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
> +{
> +	void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL;
> +	struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +	int i;
> +	char *cmdbuf = req->buf;
> +
> +	if (req->status != 0 || req->length == 0)
> +		return;
> +
> +	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> +	printcbw(req->buf);
> +
> +	for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) {
> +		if (cmd_dispatch_info[i].cmd == cbw.CDB[0]) {
> +			func_cb = cmd_dispatch_info[i].cb;
> +			break;
> +		}
> +	}
> +
> +	if (!func_cb) {
> +		error("unknown command: %s", (char*)req->buf);
> +		rockusb_tx_write_str("FAILunknown command");
> +	} else {
> +		if (req->actual < req->length) {
> +			u8 *buf = (u8 *)req->buf;
> +			buf[req->actual] = 0;
> +			func_cb(ep, req);
> +		} else {
> +			error("buffer overflow");
> +			rockusb_tx_write_str("FAILbuffer overflow");
> +		}
> +	}
> +
> +	*cmdbuf = '\0';
> +	req->actual = 0;
> +	usb_ep_queue(ep, req, 0);
> +}

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

* [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb
  2017-03-15  7:56 [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb Eddie Cai
                   ` (3 preceding siblings ...)
  2017-03-15  9:06 ` [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb Lukasz Majewski
@ 2017-03-16 21:26 ` Marek Vasut
  2017-03-20  1:53   ` Eddie Cai
  2017-03-27  8:27 ` Lukasz Majewski
  5 siblings, 1 reply; 36+ messages in thread
From: Marek Vasut @ 2017-03-16 21:26 UTC (permalink / raw)
  To: u-boot

On 03/15/2017 08:56 AM, Eddie Cai wrote:
> rockusb is a protocol run between host pc and device. it help people get device
> info, flash image to device. this patch implement rockusb on device side. 

What is the benefit of this yet-another NIH protocol compared to ie.
DFU/UMS/Thor/Fastboot ?

> Eddie Cai (3):
>   drivers: usb: gadget: add the rockusb gadget
>   cmd: add rockusb command
>   rockchip: rk3288: enable rockusb support on rk3288 based device
> 
>  cmd/Kconfig                     |  12 +
>  cmd/Makefile                    |   1 +
>  cmd/rockusb.c                   |  79 ++++
>  drivers/usb/gadget/Makefile     |   1 +
>  drivers/usb/gadget/f_rockusb.c  | 801 ++++++++++++++++++++++++++++++++++++++++
>  include/configs/rk3288_common.h |   4 +
>  include/rockusb.h               |  13 +
>  7 files changed, 911 insertions(+)
>  create mode 100644 cmd/rockusb.c
>  create mode 100644 drivers/usb/gadget/f_rockusb.c
>  create mode 100644 include/rockusb.h
> 


-- 
Best regards,
Marek Vasut

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

* [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb
  2017-03-16 21:26 ` Marek Vasut
@ 2017-03-20  1:53   ` Eddie Cai
  2017-03-20 12:24     ` Marek Vasut
  0 siblings, 1 reply; 36+ messages in thread
From: Eddie Cai @ 2017-03-20  1:53 UTC (permalink / raw)
  To: u-boot

2017-03-17 5:26 GMT+08:00 Marek Vasut <marex@denx.de>:

> On 03/15/2017 08:56 AM, Eddie Cai wrote:
> > rockusb is a protocol run between host pc and device. it help people get
> device
> > info, flash image to device. this patch implement rockusb on device side.
>
> What is the benefit of this yet-another NIH protocol compared to ie.
> DFU/UMS/Thor/Fastboot ?
>
This is mostly  used on Rockchip chipset. All the rockchip SoC boot rom and
develop tools implement this protocol.
So we want to use the same protocol which compatible with current tools.


> > Eddie Cai (3):
> >   drivers: usb: gadget: add the rockusb gadget
> >   cmd: add rockusb command
> >   rockchip: rk3288: enable rockusb support on rk3288 based device
> >
> >  cmd/Kconfig                     |  12 +
> >  cmd/Makefile                    |   1 +
> >  cmd/rockusb.c                   |  79 ++++
> >  drivers/usb/gadget/Makefile     |   1 +
> >  drivers/usb/gadget/f_rockusb.c  | 801 ++++++++++++++++++++++++++++++
> ++++++++++
> >  include/configs/rk3288_common.h |   4 +
> >  include/rockusb.h               |  13 +
> >  7 files changed, 911 insertions(+)
> >  create mode 100644 cmd/rockusb.c
> >  create mode 100644 drivers/usb/gadget/f_rockusb.c
> >  create mode 100644 include/rockusb.h
> >
>
>
> --
> Best regards,
> Marek Vasut
>

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

* [U-Boot] [U-Boot 2/3] cmd: add rockusb command
  2017-03-15  7:56 ` [U-Boot] [U-Boot 2/3] cmd: add rockusb command Eddie Cai
@ 2017-03-20  2:29   ` Simon Glass
  2017-03-20  8:14     ` Eddie Cai
  2017-04-20 10:11   ` Lukasz Majewski
  1 sibling, 1 reply; 36+ messages in thread
From: Simon Glass @ 2017-03-20  2:29 UTC (permalink / raw)
  To: u-boot

Hi Eddie,

On 15 March 2017 at 01:56, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
>
> this patch add rockusb command. the usage is
>         rockusb <USB_controller> [<devtype>] <devnum>
> e.g. rockusb 0 mmc 0
>
> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> ---
>  cmd/Kconfig       | 12 +++++++++
>  cmd/Makefile      |  1 +
>  cmd/rockusb.c     | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/rockusb.h | 13 +++++++++
>  4 files changed, 105 insertions(+)
>  create mode 100644 cmd/rockusb.c
>  create mode 100644 include/rockusb.h

Can you please add some documentation on how to use this command and
what host tools you need?

>
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index ef53156..dac2cc0 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -475,6 +475,18 @@ config CMD_DFU
>           Enables the command "dfu" which is used to have U-Boot create a DFU
>           class device via USB.
>
> +config CMD_ROCKUSB
> +        bool "rockusb"
> +        select USB_FUNCTION_ROCKUSB
> +        help
> +          Enables the command "rockusb" which is used to have U-Boot create a
> +          Rockusb class device via USB.

Does this mean Rockchip-class device?

> +
> +config USB_FUNCTION_ROCKUSB
> +        bool "Enable USB rockusb gadget"
> +        help
> +          This enables the USB part of the rockusb gadget.
> +
>  config CMD_USB_MASS_STORAGE
>         bool "UMS usb mass storage"
>         help
> diff --git a/cmd/Makefile b/cmd/Makefile
> index f13bb8c..f5f1663 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -141,6 +141,7 @@ endif
>
>  obj-$(CONFIG_CMD_USB) += usb.o disk.o
>  obj-$(CONFIG_CMD_FASTBOOT) += fastboot.o
> +obj-$(CONFIG_CMD_ROCKUSB) += rockusb.o
>  obj-$(CONFIG_CMD_FS_UUID) += fs_uuid.o

Can you put it in alphabetical order if possible?

>
>  obj-$(CONFIG_CMD_USB_MASS_STORAGE) += usb_mass_storage.o
> diff --git a/cmd/rockusb.c b/cmd/rockusb.c
> new file mode 100644
> index 0000000..f5bd86e
> --- /dev/null
> +++ b/cmd/rockusb.c
> @@ -0,0 +1,79 @@
> +/*
> + * Copyright (C) 2017 Eddie Cai <eddie.cai.linux@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <console.h>
> +#include <g_dnl.h>
> +#include <usb.h>
> +#include <rockusb.h>

Should go above usb.h

> +

remove extra blank line

> +
> +static int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
> +{
> +       int controller_index, dev_index;
> +       char *usb_controller;
> +       char *devtype;
> +       char *devnum;
> +       int ret;
> +
> +       if (argc < 2)
> +               return CMD_RET_USAGE;
> +
> +       usb_controller = argv[1];
> +       controller_index = simple_strtoul(usb_controller, NULL, 0);
> +
> +       if (argc >= 4) {
> +               devtype = argv[2];
> +               devnum  = argv[3];
> +       } else {
> +               devtype = "mmc";
> +               devnum  = argv[2];
> +       }
> +       dev_index = simple_strtoul(devnum, NULL, 0);
> +       rockusb_dev_init(devtype, dev_index);

Can this fail, e.g. if index is out of range?

> +
> +       ret = board_usb_init(controller_index, USB_INIT_DEVICE);
> +       if (ret) {
> +               error("USB init failed: %d", ret);
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       g_dnl_clear_detach();
> +       ret = g_dnl_register("usb_dnl_rockusb");
> +       if (ret)
> +               return ret;

Commands should return either 0 or CMD_RET_FAILURE.

> +       printf("do_rockusb1\n");

Do you want this?

> +       if (!g_dnl_board_usb_cable_connected()) {
> +               puts("\rUSB cable not detected.\n" \
> +                    "Command exit.\n");
> +               ret = CMD_RET_FAILURE;
> +               goto exit;
> +       }
> +
> +       while (1) {
> +               if (g_dnl_detach())
> +                       break;
> +               if (ctrlc())
> +                       break;
> +               usb_gadget_handle_interrupts(controller_index);
> +       }
> +       printf("do_rockusb2\n");

Do you want this?

> +       ret = CMD_RET_SUCCESS;
> +
> +exit:
> +       g_dnl_unregister();
> +       g_dnl_clear_detach();
> +       board_usb_cleanup(controller_index, USB_INIT_DEVICE);
> +
> +       return ret;
> +}
> +
> +U_BOOT_CMD(rockusb, 4, 1, do_rockusb,
> +       "Use the ROCKUSB",

Can you add a little more here?

> +       "rockusb <USB_controller> [<devtype>] <devnum>  e.g. rockusb 0 mmc 0\n"
> +       "    devtype defaults to mmc"
> +);
> diff --git a/include/rockusb.h b/include/rockusb.h
> new file mode 100644
> index 0000000..cdea63d
> --- /dev/null
> +++ b/include/rockusb.h

Can this go in include/asm instead?

> @@ -0,0 +1,13 @@
> +/*
> + * (C) Copyright 2017
> + *
> + * Eddie Cai <eddie.cai.linux@gmail.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +#ifndef _ROCKUSB_H_
> +#define _ROCKUSB_H_
> +
> +void rockusb_dev_init(char *dev_type, int dev_index);

Please add a function comment.

> +
> +#endif /* _ROCKUSB_H_ */
> --
> 2.7.4
>

Regards,
Simon

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

* [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device
  2017-03-15  7:56 ` [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device Eddie Cai
@ 2017-03-20  2:30   ` Simon Glass
  2017-03-20  8:16     ` Eddie Cai
  2017-05-02 10:37     ` Eddie Cai
  2017-04-20 10:12   ` Lukasz Majewski
  1 sibling, 2 replies; 36+ messages in thread
From: Simon Glass @ 2017-03-20  2:30 UTC (permalink / raw)
  To: u-boot

Hi Eddie.

On 15 March 2017 at 01:56, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
> this patch enable rockusb support on rk3288 based device.
>
> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> ---
>  include/configs/rk3288_common.h | 4 ++++
>  1 file changed, 4 insertions(+)

I think this should be done in Kconfig.

>
> diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
> index b5606d4..b19a34d 100644
> --- a/include/configs/rk3288_common.h
> +++ b/include/configs/rk3288_common.h
> @@ -74,6 +74,10 @@
>  #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
>  #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
>
> +/* rockusb  */
> +#define CONFIG_CMD_ROCKUSB
> +#define CONFIG_USB_FUNCTION_ROCKUSB
> +
>  /* usb mass storage */
>  #define CONFIG_USB_FUNCTION_MASS_STORAGE
>  #define CONFIG_CMD_USB_MASS_STORAGE
> --
> 2.7.4
>

Regards,
Simon

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

* [U-Boot] [U-Boot 1/3] drivers: usb: gadget: add the rockusb gadget
  2017-03-16  7:05   ` Kever Yang
@ 2017-03-20  7:24     ` Eddie Cai
  2017-03-20  8:37       ` Lukasz Majewski
  0 siblings, 1 reply; 36+ messages in thread
From: Eddie Cai @ 2017-03-20  7:24 UTC (permalink / raw)
  To: u-boot

2017-03-16 15:05 GMT+08:00 Kever Yang <kever.yang@rock-chips.com>:

> Hi Eddie,
>
>     I recommend you to use ums framework instead of fastboot, because
> ums have dual-buffer which improve performance.
>
I will try to add dual buffer support in next version

>
> Thanks,
> - Kever
>
> On 03/15/2017 03:56 PM, Eddie Cai wrote:
>
>> this patch implement fastboot protocol on the device side. this is based
>> on USB
>> download gadget infrastructure. the rockusb function implements the rd,
>> wl, rid
>> commands. it can work with rkdeveloptool;
>> https://github.com/rockchip-linux/rkdeveloptool
>>
>> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
>> ---
>>   drivers/usb/gadget/Makefile    |   1 +
>>   drivers/usb/gadget/f_rockusb.c | 801 ++++++++++++++++++++++++++++++
>> +++++++++++
>>   2 files changed, 802 insertions(+)
>>   create mode 100644 drivers/usb/gadget/f_rockusb.c
>>
>> diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
>> index 0fbbb7c..0eb27a3 100644
>> --- a/drivers/usb/gadget/Makefile
>> +++ b/drivers/usb/gadget/Makefile
>> @@ -28,6 +28,7 @@ obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
>>   obj-$(CONFIG_USB_FUNCTION_DFU) += f_dfu.o
>>   obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
>>   obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
>> +obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o
>>   endif
>>   endif
>>   ifdef CONFIG_USB_ETHER
>> diff --git a/drivers/usb/gadget/f_rockusb.c
>> b/drivers/usb/gadget/f_rockusb.c
>> new file mode 100644
>> index 0000000..a67cb35
>> --- /dev/null
>> +++ b/drivers/usb/gadget/f_rockusb.c
>> @@ -0,0 +1,801 @@
>> +/*
>> + * (C) Copyright 2017
>> + *
>> + * Eddie Cai <eddie.cai.linux@gmail.com>
>> + *
>> + * SPDX-License-Identifier:    GPL-2.0+
>> + */
>> +
>> +#include <config.h>
>> +#include <common.h>
>> +#include <errno.h>
>> +#include <malloc.h>
>> +#include <linux/usb/ch9.h>
>> +#include <linux/usb/gadget.h>
>> +#include <linux/usb/composite.h>
>> +#include <linux/compiler.h>
>> +#include <version.h>
>> +#include <g_dnl.h>
>> +
>> +#define ROCKUSB_VERSION                "0.1"
>> +
>> +#define ROCKUSB_INTERFACE_CLASS        0xff
>> +#define ROCKUSB_INTERFACE_SUB_CLASS    0x06
>> +#define ROCKUSB_INTERFACE_PROTOCOL     0x05
>> +
>> +#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0  (0x0200)
>> +#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1  (0x0040)
>> +#define TX_ENDPOINT_MAXIMUM_PACKET_SIZE      (0x0040)
>> +
>> +#define EP_BUFFER_SIZE                 4096
>> +/*
>> + * EP_BUFFER_SIZE must always be an integral multiple of maxpacket size
>> + * (64 or 512 or 1024), else we break on certain controllers like DWC3
>> + * that expect bulk OUT requests to be divisible by maxpacket size.
>> + */
>> +
>> +struct f_rockusb {
>> +       struct usb_function usb_function;
>> +
>> +       /* IN/OUT EP's and corresponding requests */
>> +       struct usb_ep *in_ep, *out_ep;
>> +       struct usb_request *in_req, *out_req;
>> +};
>> +
>> +static inline struct f_rockusb *func_to_rockusb(struct usb_function *f)
>> +{
>> +       return container_of(f, struct f_rockusb, usb_function);
>> +}
>> +
>> +static struct f_rockusb *rockusb_func;
>> +
>> +static struct usb_endpoint_descriptor fs_ep_in = {
>> +       .bLength            = USB_DT_ENDPOINT_SIZE,
>> +       .bDescriptorType    = USB_DT_ENDPOINT,
>> +       .bEndpointAddress   = USB_DIR_IN,
>> +       .bmAttributes       = USB_ENDPOINT_XFER_BULK,
>> +       .wMaxPacketSize     = cpu_to_le16(64),
>> +};
>> +
>> +static struct usb_endpoint_descriptor fs_ep_out = {
>> +       .bLength                = USB_DT_ENDPOINT_SIZE,
>> +       .bDescriptorType        = USB_DT_ENDPOINT,
>> +       .bEndpointAddress       = USB_DIR_OUT,
>> +       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
>> +       .wMaxPacketSize         = cpu_to_le16(64),
>> +};
>> +
>> +static struct usb_endpoint_descriptor hs_ep_in = {
>> +       .bLength                = USB_DT_ENDPOINT_SIZE,
>> +       .bDescriptorType        = USB_DT_ENDPOINT,
>> +       .bEndpointAddress       = USB_DIR_IN,
>> +       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
>> +       .wMaxPacketSize         = cpu_to_le16(512),
>> +};
>> +
>> +static struct usb_endpoint_descriptor hs_ep_out = {
>> +       .bLength                = USB_DT_ENDPOINT_SIZE,
>> +       .bDescriptorType        = USB_DT_ENDPOINT,
>> +       .bEndpointAddress       = USB_DIR_OUT,
>> +       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
>> +       .wMaxPacketSize         = cpu_to_le16(512),
>> +};
>> +
>> +static struct usb_interface_descriptor interface_desc = {
>> +       .bLength                = USB_DT_INTERFACE_SIZE,
>> +       .bDescriptorType        = USB_DT_INTERFACE,
>> +       .bInterfaceNumber       = 0x00,
>> +       .bAlternateSetting      = 0x00,
>> +       .bNumEndpoints          = 0x02,
>> +       .bInterfaceClass        = ROCKUSB_INTERFACE_CLASS,
>> +       .bInterfaceSubClass     = ROCKUSB_INTERFACE_SUB_CLASS,
>> +       .bInterfaceProtocol     = ROCKUSB_INTERFACE_PROTOCOL,
>> +};
>> +
>> +static struct usb_descriptor_header *rkusb_fs_function[] = {
>> +       (struct usb_descriptor_header *)&interface_desc,
>> +       (struct usb_descriptor_header *)&fs_ep_in,
>> +       (struct usb_descriptor_header *)&fs_ep_out,
>> +};
>> +
>> +static struct usb_descriptor_header *rkusb_hs_function[] = {
>> +       (struct usb_descriptor_header *)&interface_desc,
>> +       (struct usb_descriptor_header *)&hs_ep_in,
>> +       (struct usb_descriptor_header *)&hs_ep_out,
>> +       NULL,
>> +};
>> +
>> +static struct usb_endpoint_descriptor *
>> +rkusb_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
>> +           struct usb_endpoint_descriptor *hs)
>> +{
>> +       if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
>> +               return hs;
>> +       return fs;
>> +}
>> +
>> +/*
>> + * static strings, in UTF-8
>> + */
>> +static const char rkusb_name[] = "Rockchip Rockusb";
>> +
>> +static struct usb_string rkusb_string_defs[] = {
>> +       [0].s = rkusb_name,
>> +       {  }                    /* end of list */
>> +};
>> +
>> +static struct usb_gadget_strings stringtab_rkusb = {
>> +       .language       = 0x0409,       /* en-us */
>> +       .strings        = rkusb_string_defs,
>> +};
>> +
>> +static struct usb_gadget_strings *rkusb_strings[] = {
>> +       &stringtab_rkusb,
>> +       NULL,
>> +};
>> +
>> +static void rx_handler_command(struct usb_ep *ep, struct usb_request
>> *req);
>> +static int rockusb_tx_write_csw(u32 Tag, int residue, u8 Status, int
>> size);
>> +
>> +static void rockusb_complete(struct usb_ep *ep, struct usb_request *req)
>> +{
>> +       int status = req->status;
>> +       if (!status)
>> +               return;
>> +       debug("status: %d ep '%s' trans: %d\n", status, ep->name,
>> req->actual);
>> +}
>> +
>> +static int rockusb_bind(struct usb_configuration *c, struct usb_function
>> *f)
>> +{
>> +       int id;
>> +       struct usb_gadget *gadget = c->cdev->gadget;
>> +       struct f_rockusb *f_rkusb = func_to_rockusb(f);
>> +       const char *s;
>> +
>> +       id = usb_interface_id(c, f);
>> +       if (id < 0)
>> +               return id;
>> +       interface_desc.bInterfaceNumber = id;
>> +
>> +       id = usb_string_id(c->cdev);
>> +       if (id < 0)
>> +               return id;
>> +
>> +       rkusb_string_defs[0].id = id;
>> +       interface_desc.iInterface = id;
>> +
>> +       f_rkusb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in);
>> +       if (!f_rkusb->in_ep)
>> +               return -ENODEV;
>> +       f_rkusb->in_ep->driver_data = c->cdev;
>> +
>> +       f_rkusb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out);
>> +       if (!f_rkusb->out_ep)
>> +               return -ENODEV;
>> +       f_rkusb->out_ep->driver_data = c->cdev;
>> +
>> +       f->descriptors = rkusb_fs_function;
>> +
>> +       if (gadget_is_dualspeed(gadget)) {
>> +               hs_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress;
>> +               hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress;
>> +               f->hs_descriptors = rkusb_hs_function;
>> +       }
>> +
>> +       s = getenv("serial#");
>> +       if (s)
>> +               g_dnl_set_serialnumber((char *)s);
>> +
>> +       return 0;
>> +}
>> +
>> +static void rockusb_unbind(struct usb_configuration *c, struct
>> usb_function *f)
>> +{
>> +       memset(rockusb_func, 0, sizeof(*rockusb_func));
>> +}
>> +
>> +static void rockusb_disable(struct usb_function *f)
>> +{
>> +       struct f_rockusb *f_rkusb = func_to_rockusb(f);
>> +
>> +       usb_ep_disable(f_rkusb->out_ep);
>> +       usb_ep_disable(f_rkusb->in_ep);
>> +
>> +       if (f_rkusb->out_req) {
>> +               free(f_rkusb->out_req->buf);
>> +               usb_ep_free_request(f_rkusb->out_ep, f_rkusb->out_req);
>> +               f_rkusb->out_req = NULL;
>> +       }
>> +       if (f_rkusb->in_req) {
>> +               free(f_rkusb->in_req->buf);
>> +               usb_ep_free_request(f_rkusb->in_ep, f_rkusb->in_req);
>> +               f_rkusb->in_req = NULL;
>> +       }
>> +}
>> +
>> +static struct usb_request *rockusb_start_ep(struct usb_ep *ep)
>> +{
>> +       struct usb_request *req;
>> +
>> +       req = usb_ep_alloc_request(ep, 0);
>> +       if (!req)
>> +               return NULL;
>> +
>> +       req->length = EP_BUFFER_SIZE;
>> +       req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE);
>> +       if (!req->buf) {
>> +               usb_ep_free_request(ep, req);
>> +               return NULL;
>> +       }
>> +
>> +       memset(req->buf, 0, req->length);
>> +       return req;
>> +}
>> +
>> +static int rockusb_set_alt(struct usb_function *f,
>> +                           unsigned interface, unsigned alt)
>> +{
>> +       int ret;
>> +       struct usb_composite_dev *cdev = f->config->cdev;
>> +       struct usb_gadget *gadget = cdev->gadget;
>> +       struct f_rockusb *f_rkusb = func_to_rockusb(f);
>> +       const struct usb_endpoint_descriptor *d;
>> +
>> +       debug("%s: func: %s intf: %d alt: %d\n",
>> +             __func__, f->name, interface, alt);
>> +
>> +       d = rkusb_ep_desc(gadget, &fs_ep_out, &hs_ep_out);
>> +       ret = usb_ep_enable(f_rkusb->out_ep, d);
>> +       if (ret) {
>> +               puts("failed to enable out ep\n");
>> +               return ret;
>> +       }
>> +
>> +       f_rkusb->out_req = rockusb_start_ep(f_rkusb->out_ep);
>> +       if (!f_rkusb->out_req) {
>> +               puts("failed to alloc out req\n");
>> +               ret = -EINVAL;
>> +               goto err;
>> +       }
>> +       f_rkusb->out_req->complete = rx_handler_command;
>> +
>> +       d = rkusb_ep_desc(gadget, &fs_ep_in, &hs_ep_in);
>> +       ret = usb_ep_enable(f_rkusb->in_ep, d);
>> +       if (ret) {
>> +               puts("failed to enable in ep\n");
>> +               goto err;
>> +       }
>> +
>> +       f_rkusb->in_req = rockusb_start_ep(f_rkusb->in_ep);
>> +       if (!f_rkusb->in_req) {
>> +               puts("failed alloc req in\n");
>> +               ret = -EINVAL;
>> +               goto err;
>> +       }
>> +       f_rkusb->in_req->complete = rockusb_complete;
>> +
>> +       ret = usb_ep_queue(f_rkusb->out_ep, f_rkusb->out_req, 0);
>> +       if (ret)
>> +               goto err;
>> +
>> +       return 0;
>> +err:
>> +       rockusb_disable(f);
>> +       return ret;
>> +}
>> +
>> +static int rockusb_add(struct usb_configuration *c)
>> +{
>> +       struct f_rockusb *f_rkusb = rockusb_func;
>> +       int status;
>> +
>> +       debug("%s: cdev: 0x%p\n", __func__, c->cdev);
>> +
>> +       if (!f_rkusb) {
>> +               f_rkusb = memalign(CONFIG_SYS_CACHELINE_SIZE,
>> sizeof(*f_rkusb));
>> +               if (!f_rkusb)
>> +                       return -ENOMEM;
>> +
>> +               rockusb_func = f_rkusb;
>> +               memset(f_rkusb, 0, sizeof(*f_rkusb));
>> +       }
>> +
>> +       f_rkusb->usb_function.name = "f_rockusb";
>> +       f_rkusb->usb_function.bind = rockusb_bind;
>> +       f_rkusb->usb_function.unbind = rockusb_unbind;
>> +       f_rkusb->usb_function.set_alt = rockusb_set_alt;
>> +       f_rkusb->usb_function.disable = rockusb_disable;
>> +       f_rkusb->usb_function.strings = rkusb_strings;
>> +
>> +       status = usb_add_function(c, &f_rkusb->usb_function);
>> +       if (status) {
>> +               free(f_rkusb);
>> +               rockusb_func = f_rkusb;
>> +       }
>> +       return status;
>> +}
>> +
>> +char *rockusb_dev_type = 0;
>> +int rockusb_dev_index = 0;
>> +
>> +void rockusb_dev_init(char *dev_type, int dev_index)
>> +{
>> +       rockusb_dev_type = dev_type;
>> +       rockusb_dev_index = dev_index;
>> +}
>> +
>> +DECLARE_GADGET_BIND_CALLBACK(usb_dnl_rockusb, rockusb_add);
>> +
>> +static int rockusb_tx_write(const char *buffer, unsigned int buffer_size)
>> +{
>> +       struct usb_request *in_req = rockusb_func->in_req;
>> +       int ret;
>> +
>> +       memcpy(in_req->buf, buffer, buffer_size);
>> +       in_req->length = buffer_size;
>> +       usb_ep_dequeue(rockusb_func->in_ep, in_req);
>> +       ret = usb_ep_queue(rockusb_func->in_ep, in_req, 0);
>> +       if (ret)
>> +               printf("Error %d on queue\n", ret);
>> +       return 0;
>> +}
>> +
>> +static int rockusb_tx_write_str(const char *buffer)
>> +{
>> +       return rockusb_tx_write(buffer, strlen(buffer));
>> +}
>> +
>> +/* Bulk-only data structures */
>> +
>> +/* Command Block Wrapper */
>> +struct fsg_bulk_cb_wrap {
>> +       __le32  Signature;              /* Contains 'USBC' */
>> +       u32     Tag;                    /* Unique per command id */
>> +       __le32  DataTransferLength;     /* Size of the data */
>> +       u8      Flags;                  /* Direction in bit 7 */
>> +       u8      Lun;                    /* LUN (normally 0) */
>> +       u8      Length;                 /* Of the CDB, <=
>> MAX_COMMAND_SIZE */
>> +       u8      CDB[16];                /* Command Data Block */
>> +};
>> +
>> +#define USB_BULK_CB_WRAP_LEN   31
>> +#define USB_BULK_CB_SIG                0x43425355      /* Spells out
>> USBC */
>> +#define USB_BULK_IN_FLAG       0x80
>> +
>> +/* Command Status Wrapper */
>> +struct bulk_cs_wrap {
>> +       __le32  Signature;              /* Should = 'USBS' */
>> +       u32     Tag;                    /* Same as original command */
>> +       __le32  Residue;                /* Amount not transferred */
>> +       u8      Status;                 /* See below */
>> +};
>> +
>> +#define USB_BULK_CS_WRAP_LEN   13
>> +#define USB_BULK_CS_SIG                0x53425355      /* Spells out
>> 'USBS' */
>> +#define USB_STATUS_PASS                0
>> +#define USB_STATUS_FAIL                1
>> +#define USB_STATUS_PHASE_ERROR 2
>> +
>> +
>> +#define        CSW_GOOD                0x00
>> +#define        CSW_FAIL                0x01
>> +
>> +static void printcbw(char *buf)
>> +{
>> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> A_MINALIGN)));
>> +
>> +       memcpy((char*)&cbw, buf, USB_BULK_CB_WRAP_LEN);
>> +
>> +       debug("cbw: Signature:%x\n", cbw.Signature);
>> +       debug("cbw: Tag=%x\n", cbw.Tag);
>> +       debug("cbw: DataTransferLength=%d\n", cbw.DataTransferLength);
>> +       debug("cbw: Flags=%x\n", cbw.Flags);
>> +       debug("cbw: Lun=%d\n", cbw.Lun);
>> +       debug("cbw: Length=%d\n", cbw.Length);
>> +       debug("cbw: ucOperCode=%x\n", cbw.CDB[0]);
>> +       debug("cbw: ucReserved=%x\n", cbw.CDB[1]);
>> +       debug("cbw: dwAddress:%x %x %x %x\n", cbw.CDB[5], cbw.CDB[4],
>> +                                               cbw.CDB[3], cbw.CDB[2]);
>> +       debug("cbw: ucReserved2=%x\n", cbw.CDB[6]);
>> +       debug("cbw: usLength:%x %x\n", cbw.CDB[8], cbw.CDB[7]);
>> +
>> +}
>> +
>> +static void printcsw(char *buf)
>> +{
>> +       struct bulk_cs_wrap csw __attribute__((aligned(ARCH_DM
>> A_MINALIGN)));
>> +
>> +       memcpy((char*)&csw, buf, USB_BULK_CS_WRAP_LEN);
>> +       debug("csw: Signature:%x\n", csw.Signature);
>> +       debug("csw: Tag:%x\n", csw.Tag);
>> +       debug("csw: Residue:%x\n", csw.Residue);
>> +       debug("csw: Status:%x\n", csw.Status);
>> +
>> +}
>> +
>> +static int rockusb_tx_write_csw(u32 Tag, int residue, u8 Status, int
>> size)
>> +{
>> +       struct bulk_cs_wrap csw __attribute__((aligned(ARCH_DM
>> A_MINALIGN)));
>> +       csw.Signature = cpu_to_le32(USB_BULK_CS_SIG);
>> +       csw.Tag = Tag;
>> +       csw.Residue = cpu_to_be32(residue);
>> +       csw.Status = Status;
>> +       printcsw((char*)&csw);
>> +       return rockusb_tx_write((char*)&csw, size);
>> +}
>> +
>> +int download_tag = 0;
>> +int download_lba = 0;
>> +static unsigned int download_size;
>> +static unsigned int download_bytes;
>> +struct blk_desc *download_desc = 0;
>> +
>> +static unsigned int rx_bytes_expected(struct usb_ep *ep)
>> +{
>> +       int rx_remain = download_size - download_bytes;
>> +       unsigned int rem;
>> +       unsigned int maxpacket = ep->maxpacket;
>> +
>> +       if (rx_remain <= 0)
>> +               return 0;
>> +       else if (rx_remain > EP_BUFFER_SIZE)
>> +               return EP_BUFFER_SIZE;
>> +
>> +       rem = rx_remain % maxpacket;
>> +       if (rem > 0)
>> +               rx_remain = rx_remain + (maxpacket - rem);
>> +
>> +       return rx_remain;
>> +}
>> +
>> +static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request
>> *req)
>> +{
>> +       unsigned int transfer_size = download_size - download_bytes;
>> +       const unsigned char *buffer = req->buf;
>> +       unsigned int buffer_size = req->actual;
>> +
>> +       if(!download_desc){
>> +               printf("rx_handler_dl_image blk_get_dev\n");
>> +               download_desc = blk_get_dev(rockusb_dev_type,
>> rockusb_dev_index);
>> +               if (!download_desc || download_desc->type ==
>> DEV_TYPE_UNKNOWN){
>> +                       error("invalid mmc device\n");
>> +                       rockusb_tx_write_csw(download_tag, 0, CSW_FAIL,
>> +                                               USB_BULK_CS_WRAP_LEN);
>> +                       return;
>> +               }
>> +       }
>> +
>> +       if (req->status != 0) {
>> +               printf("Bad status: %d\n", req->status);
>> +               rockusb_tx_write_csw(download_tag, 0,
>> +                                       CSW_FAIL, USB_BULK_CS_WRAP_LEN);
>> +               return;
>> +       }
>> +
>> +       if (buffer_size < transfer_size)
>> +               transfer_size = buffer_size;
>> +
>> +       memcpy((void *)CONFIG_FASTBOOT_BUF_ADDR + download_bytes,
>> +              buffer, transfer_size);
>> +       download_bytes += transfer_size;
>> +
>> +       /* Check if transfer is done */
>> +       if (download_bytes >= download_size) {
>> +               int blks = 0, blkcnt = download_size/512;
>> +               printf("download %d bytes finished, start writing to lba
>> %x\n",
>> +                                download_bytes, download_lba);
>> +               blks = blk_dwrite(download_desc, download_lba, blkcnt,
>> +                                       (char*)CONFIG_FASTBOOT_BUF_ADDR);
>> +               if (blks != blkcnt) {
>> +                       error("failed writing to device %s: %d\n",
>> +                               rockusb_dev_type, rockusb_dev_index);
>> +                       rockusb_tx_write_csw(download_tag, 0,
>> +                                               CSW_FAIL,
>> USB_BULK_CS_WRAP_LEN);
>> +                       return;
>> +               }
>> +
>> +               req->complete = rx_handler_command;
>> +               req->length = EP_BUFFER_SIZE;
>> +               download_size = 0;
>> +               printf("done\n");
>> +               rockusb_tx_write_csw(download_tag, 0, CSW_GOOD,
>> +                                       USB_BULK_CS_WRAP_LEN);
>> +       } else {
>> +               req->length = rx_bytes_expected(ep);
>> +       }
>> +
>> +       req->actual = 0;
>> +       usb_ep_queue(ep, req, 0);
>> +}
>> +
>> +static void cb_test_unit_ready(struct usb_ep *ep, struct usb_request
>> *req)
>> +{
>> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> A_MINALIGN)));
>> +
>> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
>> +
>> +       rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength,
>> +                               CSW_GOOD, USB_BULK_CS_WRAP_LEN);
>> +
>> +}
>> +
>> +static void cb_read_storage_id(struct usb_ep *ep, struct usb_request
>> *req)
>> +{
>> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> A_MINALIGN)));
>> +       char emmc_id[] = "EMMC ";
>> +
>> +       printf("cb_read_storage_id\n");
>> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
>> +       rockusb_tx_write_str(emmc_id);//only support emmc now
>> +       rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength, CSW_GOOD,
>> +                               USB_BULK_CS_WRAP_LEN);
>> +}
>> +
>> +static void cb_write_lba(struct usb_ep *ep, struct usb_request *req)
>> +{
>> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> A_MINALIGN)));
>> +       int sector_count;
>> +
>> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
>> +       sector_count = (int)get_unaligned_be16(&cbw.CDB[7]);
>> +       download_lba = get_unaligned_be32(&cbw.CDB[2]);
>> +       download_size = sector_count * 512;
>> +       download_bytes = 0;
>> +       download_tag = cbw.Tag;
>> +       if ((0 == download_size) || (download_size>CONFIG_FASTBOOT
>> _BUF_SIZE)){
>> +               rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength,
>> +                                       CSW_FAIL, USB_BULK_CS_WRAP_LEN);
>> +       } else {
>> +               req->complete = rx_handler_dl_image;
>> +               req->length = rx_bytes_expected(ep);
>> +       }
>> +}
>> +
>> +static int reboot_flag;
>> +
>> +int __weak rkusb_set_reboot_flag(int flag)
>> +{
>> +       printf("rkusb_set_reboot_flag: %d\n", reboot_flag);
>> +       return -ENOSYS;
>> +}
>> +
>> +static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
>> +{
>> +       rkusb_set_reboot_flag(reboot_flag);
>> +       do_reset(NULL, 0, 0, NULL);
>> +}
>> +
>> +static void cb_reboot(struct usb_ep *ep, struct usb_request *req)
>> +{
>> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> A_MINALIGN)));
>> +       reboot_flag = 0;
>> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
>> +       reboot_flag = cbw.CDB[1];
>> +       rockusb_func->in_req->complete = compl_do_reset;
>> +       rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength, CSW_GOOD,
>> +                               USB_BULK_CS_WRAP_LEN);
>> +}
>> +
>> +static void cb_not_support(struct usb_ep *ep, struct usb_request *req)
>> +{
>> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> A_MINALIGN)));
>> +
>> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
>> +       printf("Rockusb command %x not support yet\n", cbw.CDB[0]);
>> +       rockusb_tx_write_csw(cbw.Tag, 0, CSW_FAIL, USB_BULK_CS_WRAP_LEN);
>> +}
>> +
>> +#define RKUSB_STATUS_IDLE                      0
>> +#define RKUSB_STATUS_CMD                       1
>> +#define RKUSB_STATUS_RXDATA                    2
>> +#define RKUSB_STATUS_TXDATA                    3
>> +#define RKUSB_STATUS_CSW                       4
>> +#define RKUSB_STATUS_RXDATA_PREPARE            5
>> +#define RKUSB_STATUS_TXDATA_PREPARE            6
>> +
>> +typedef enum {
>> +               TEST_UNIT_READY = 0,
>> +               READ_FLASH_ID = 0x01,
>> +               TEST_BAD_BLOCK = 0x03,
>> +               READ_SECTOR = 0x04,
>> +               WRITE_SECTOR = 0x05,
>> +               ERASE_NORMAL = 0x06,
>> +               ERASE_FORCE = 0x0B,
>> +               READ_LBA = 0x14,
>> +               WRITE_LBA = 0x15,
>> +               ERASE_SYSTEMDISK = 0x16,
>> +               READ_SDRAM = 0x17,
>> +               WRITE_SDRAM = 0x18,
>> +               EXECUTE_SDRAM = 0x19,
>> +               READ_FLASH_INFO = 0x1A,
>> +               READ_CHIP_INFO = 0x1B,
>> +               SET_RESET_FLAG = 0x1E,
>> +               WRITE_EFUSE = 0x1F,
>> +               READ_EFUSE = 0x20,
>> +               READ_SPI_FLASH = 0x21,
>> +               WRITE_SPI_FLASH = 0x22,
>> +               WRITE_NEW_EFUSE = 0x23,
>> +               READ_NEW_EFUSE = 0x24,
>> +               DEVICE_RESET = 0xFF
>> +} USB_OPERATION_CODE;
>> +
>> +#define        K_FW_TEST_UNIT_READY    0x00
>> +#define        K_FW_READ_FLASH_ID              0x01
>> +#define        K_FW_SET_DEVICE_ID              0x02
>> +#define        K_FW_TEST_BAD_BLOCK             0x03
>> +#define        K_FW_READ_10                    0x04
>> +#define        K_FW_WRITE_10                   0x05
>> +#define        K_FW_ERASE_10                   0x06
>> +#define        K_FW_WRITE_SPARE                0x07
>> +#define        K_FW_READ_SPARE                 0x08
>> +
>> +#define        K_FW_ERASE_10_FORCE             0x0b
>> +#define        K_FW_GET_VERSION                0x0c
>> +
>> +#define        K_FW_LBA_READ_10                0x14
>> +#define        K_FW_LBA_WRITE_10               0x15
>> +#define        K_FW_ERASE_SYS_DISK             0x16
>> +#define        K_FW_SDRAM_READ_10              0x17
>> +#define        K_FW_SDRAM_WRITE_10             0x18
>> +#define        K_FW_SDRAM_EXECUTE              0x19
>> +#define        K_FW_READ_FLASH_INFO            0x1A
>> +#define        K_FW_GET_CHIP_VER               0x1B
>> +#define        K_FW_LOW_FORMAT                 0x1C
>> +#define        K_FW_SET_RESET_FLAG             0x1E
>> +#define        K_FW_SPI_READ_10                0x21
>> +#define        K_FW_SPI_WRITE_10               0x22
>> +
>> +#define        K_FW_SESSION                    0X30
>> +#define        K_FW_RESET                      0xff
>> +
>> +#define CBW_DIRECTION_OUT              0x00
>> +#define CBW_DIRECTION_IN               0x80
>> +
>> +struct cmd_dispatch_info {
>> +       int cmd;
>> +       void (*cb)(struct usb_ep *ep, struct usb_request *req);
>> +};
>> +
>> +static const struct cmd_dispatch_info cmd_dispatch_info[] = {
>> +       {
>> +               .cmd = K_FW_TEST_UNIT_READY,
>> +               .cb = cb_test_unit_ready,
>> +       },
>> +       {
>> +               .cmd = K_FW_READ_FLASH_ID,
>> +               .cb = cb_read_storage_id,
>> +       },
>> +       {
>> +               .cmd = K_FW_SET_DEVICE_ID,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_TEST_BAD_BLOCK,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_READ_10,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_WRITE_10,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_ERASE_10,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_WRITE_SPARE,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_READ_SPARE,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_ERASE_10_FORCE,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_GET_VERSION,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_LBA_READ_10,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_LBA_WRITE_10,
>> +               .cb = cb_write_lba,
>> +       },
>> +       {
>> +               .cmd = K_FW_ERASE_SYS_DISK,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_SDRAM_READ_10,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_SDRAM_WRITE_10,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_SDRAM_EXECUTE,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_READ_FLASH_INFO,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_GET_CHIP_VER,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_LOW_FORMAT,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_SET_RESET_FLAG,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_SPI_READ_10,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_SPI_WRITE_10,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_SESSION,
>> +               .cb = cb_not_support,
>> +       },
>> +       {
>> +               .cmd = K_FW_RESET,
>> +               .cb = cb_reboot,
>> +       },
>> +};
>> +
>> +
>> +
>> +static void rx_handler_command(struct usb_ep *ep, struct usb_request
>> *req)
>> +{
>> +       void (*func_cb)(struct usb_ep *ep, struct usb_request *req) =
>> NULL;
>> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> A_MINALIGN)));
>> +       int i;
>> +       char *cmdbuf = req->buf;
>> +
>> +       if (req->status != 0 || req->length == 0)
>> +               return;
>> +
>> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
>> +       printcbw(req->buf);
>> +
>> +       for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) {
>> +               if (cmd_dispatch_info[i].cmd == cbw.CDB[0]) {
>> +                       func_cb = cmd_dispatch_info[i].cb;
>> +                       break;
>> +               }
>> +       }
>> +
>> +       if (!func_cb) {
>> +               error("unknown command: %s", (char*)req->buf);
>> +               rockusb_tx_write_str("FAILunknown command");
>> +       } else {
>> +               if (req->actual < req->length) {
>> +                       u8 *buf = (u8 *)req->buf;
>> +                       buf[req->actual] = 0;
>> +                       func_cb(ep, req);
>> +               } else {
>> +                       error("buffer overflow");
>> +                       rockusb_tx_write_str("FAILbuffer overflow");
>> +               }
>> +       }
>> +
>> +       *cmdbuf = '\0';
>> +       req->actual = 0;
>> +       usb_ep_queue(ep, req, 0);
>> +}
>>
>
>
>

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

* [U-Boot] [U-Boot 2/3] cmd: add rockusb command
  2017-03-20  2:29   ` Simon Glass
@ 2017-03-20  8:14     ` Eddie Cai
  2017-03-22 13:05       ` Simon Glass
  0 siblings, 1 reply; 36+ messages in thread
From: Eddie Cai @ 2017-03-20  8:14 UTC (permalink / raw)
  To: u-boot

Hi Simon

2017-03-20 10:29 GMT+08:00 Simon Glass <sjg@chromium.org>:

> Hi Eddie,
>
> On 15 March 2017 at 01:56, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
> >
> > this patch add rockusb command. the usage is
> >         rockusb <USB_controller> [<devtype>] <devnum>
> > e.g. rockusb 0 mmc 0
> >
> > Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> > ---
> >  cmd/Kconfig       | 12 +++++++++
> >  cmd/Makefile      |  1 +
> >  cmd/rockusb.c     | 79 ++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++
> >  include/rockusb.h | 13 +++++++++
> >  4 files changed, 105 insertions(+)
> >  create mode 100644 cmd/rockusb.c
> >  create mode 100644 include/rockusb.h
>
> Can you please add some documentation on how to use this command and
> what host tools you need?
>
Sure, I will add  README.rockusb in next version

>
> >
> > diff --git a/cmd/Kconfig b/cmd/Kconfig
> > index ef53156..dac2cc0 100644
> > --- a/cmd/Kconfig
> > +++ b/cmd/Kconfig
> > @@ -475,6 +475,18 @@ config CMD_DFU
> >           Enables the command "dfu" which is used to have U-Boot create
> a DFU
> >           class device via USB.
> >
> > +config CMD_ROCKUSB
> > +        bool "rockusb"
> > +        select USB_FUNCTION_ROCKUSB
> > +        help
> > +          Enables the command "rockusb" which is used to have U-Boot
> create a
> > +          Rockusb class device via USB.
>
> Does this mean Rockchip-class device?
>
 Yes, This is vendor specific class.

>
> > +
> > +config USB_FUNCTION_ROCKUSB
> > +        bool "Enable USB rockusb gadget"
> > +        help
> > +          This enables the USB part of the rockusb gadget.
> > +
> >  config CMD_USB_MASS_STORAGE
> >         bool "UMS usb mass storage"
> >         help
> > diff --git a/cmd/Makefile b/cmd/Makefile
> > index f13bb8c..f5f1663 100644
> > --- a/cmd/Makefile
> > +++ b/cmd/Makefile
> > @@ -141,6 +141,7 @@ endif
> >
> >  obj-$(CONFIG_CMD_USB) += usb.o disk.o
> >  obj-$(CONFIG_CMD_FASTBOOT) += fastboot.o
> > +obj-$(CONFIG_CMD_ROCKUSB) += rockusb.o
> >  obj-$(CONFIG_CMD_FS_UUID) += fs_uuid.o
>
> Can you put it in alphabetical order if possible?
>
Sure, I will try to put it in  alphabetical order in next version

>
> >
> >  obj-$(CONFIG_CMD_USB_MASS_STORAGE) += usb_mass_storage.o
> > diff --git a/cmd/rockusb.c b/cmd/rockusb.c
> > new file mode 100644
> > index 0000000..f5bd86e
> > --- /dev/null
> > +++ b/cmd/rockusb.c
> > @@ -0,0 +1,79 @@
> > +/*
> > + * Copyright (C) 2017 Eddie Cai <eddie.cai.linux@gmail.com>
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0+
> > + */
> > +
> > +#include <common.h>
> > +#include <command.h>
> > +#include <console.h>
> > +#include <g_dnl.h>
> > +#include <usb.h>
> > +#include <rockusb.h>
>
> Should go above usb.h
>
done

>
> > +
>
> remove extra blank line
>
done

>
> > +
> > +static int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const
> argv[])
> > +{
> > +       int controller_index, dev_index;
> > +       char *usb_controller;
> > +       char *devtype;
> > +       char *devnum;
> > +       int ret;
> > +
> > +       if (argc < 2)
> > +               return CMD_RET_USAGE;
> > +
> > +       usb_controller = argv[1];
> > +       controller_index = simple_strtoul(usb_controller, NULL, 0);
> > +
> > +       if (argc >= 4) {
> > +               devtype = argv[2];
> > +               devnum  = argv[3];
> > +       } else {
> > +               devtype = "mmc";
> > +               devnum  = argv[2];
> > +       }
> > +       dev_index = simple_strtoul(devnum, NULL, 0);
> > +       rockusb_dev_init(devtype, dev_index);
>
> Can this fail, e.g. if index is out of range?
>
I will add a return value in next version

>
> > +
> > +       ret = board_usb_init(controller_index, USB_INIT_DEVICE);
> > +       if (ret) {
> > +               error("USB init failed: %d", ret);
> > +               return CMD_RET_FAILURE;
> > +       }
> > +
> > +       g_dnl_clear_detach();
> > +       ret = g_dnl_register("usb_dnl_rockusb");
> > +       if (ret)
> > +               return ret;
>
> Commands should return either 0 or CMD_RET_FAILURE.
>
OK, i will fix it in next version.

>
> > +       printf("do_rockusb1\n");
>
> Do you want this?
>
Oops, i will remove it in next version.

>
> > +       if (!g_dnl_board_usb_cable_connected()) {
> > +               puts("\rUSB cable not detected.\n" \
> > +                    "Command exit.\n");
> > +               ret = CMD_RET_FAILURE;
> > +               goto exit;
> > +       }
> > +
> > +       while (1) {
> > +               if (g_dnl_detach())
> > +                       break;
> > +               if (ctrlc())
> > +                       break;
> > +               usb_gadget_handle_interrupts(controller_index);
> > +       }
> > +       printf("do_rockusb2\n");
>
> Do you want this?
>
i will remove it in next version.

>
> > +       ret = CMD_RET_SUCCESS;
> > +
> > +exit:
> > +       g_dnl_unregister();
> > +       g_dnl_clear_detach();
> > +       board_usb_cleanup(controller_index, USB_INIT_DEVICE);
> > +
> > +       return ret;
> > +}
> > +
> > +U_BOOT_CMD(rockusb, 4, 1, do_rockusb,
> > +       "Use the ROCKUSB",
>
> Can you add a little more here?
>
sure

>
> > +       "rockusb <USB_controller> [<devtype>] <devnum>  e.g. rockusb 0
> mmc 0\n"
> > +       "    devtype defaults to mmc"
> > +);
> > diff --git a/include/rockusb.h b/include/rockusb.h
> > new file mode 100644
> > index 0000000..cdea63d
> > --- /dev/null
> > +++ b/include/rockusb.h
>
> Can this go in include/asm instead?
>
do you mean include/asm-generic ? may i know why ?

>
> > @@ -0,0 +1,13 @@
> > +/*
> > + * (C) Copyright 2017
> > + *
> > + * Eddie Cai <eddie.cai.linux@gmail.com>
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0+
> > + */
> > +#ifndef _ROCKUSB_H_
> > +#define _ROCKUSB_H_
> > +
> > +void rockusb_dev_init(char *dev_type, int dev_index);
>
> Please add a function comment.
>
OK, i will add a function comment in next version .

>
> > +
> > +#endif /* _ROCKUSB_H_ */
> > --
> > 2.7.4
> >
>
> Regards,
> Simon
>

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

* [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device
  2017-03-20  2:30   ` Simon Glass
@ 2017-03-20  8:16     ` Eddie Cai
  2017-05-02 10:37     ` Eddie Cai
  1 sibling, 0 replies; 36+ messages in thread
From: Eddie Cai @ 2017-03-20  8:16 UTC (permalink / raw)
  To: u-boot

Hi Simon

2017-03-20 10:30 GMT+08:00 Simon Glass <sjg@chromium.org>:

> Hi Eddie.
>
> On 15 March 2017 at 01:56, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
> > this patch enable rockusb support on rk3288 based device.
> >
> > Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> > ---
> >  include/configs/rk3288_common.h | 4 ++++
> >  1 file changed, 4 insertions(+)
>
> I think this should be done in Kconfig.
>
OK, I will move it to Kconfig.

>
> >
> > diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_
> common.h
> > index b5606d4..b19a34d 100644
> > --- a/include/configs/rk3288_common.h
> > +++ b/include/configs/rk3288_common.h
> > @@ -74,6 +74,10 @@
> >  #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
> >  #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
> >
> > +/* rockusb  */
> > +#define CONFIG_CMD_ROCKUSB
> > +#define CONFIG_USB_FUNCTION_ROCKUSB
> > +
> >  /* usb mass storage */
> >  #define CONFIG_USB_FUNCTION_MASS_STORAGE
> >  #define CONFIG_CMD_USB_MASS_STORAGE
> > --
> > 2.7.4
> >
>
> Regards,
> Simon
>

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

* [U-Boot] [U-Boot 1/3] drivers: usb: gadget: add the rockusb gadget
  2017-03-20  7:24     ` Eddie Cai
@ 2017-03-20  8:37       ` Lukasz Majewski
  2017-04-20  0:56         ` Eddie Cai
  0 siblings, 1 reply; 36+ messages in thread
From: Lukasz Majewski @ 2017-03-20  8:37 UTC (permalink / raw)
  To: u-boot

Hi Eddie,

> 2017-03-16 15:05 GMT+08:00 Kever Yang <kever.yang@rock-chips.com>:
> 
> > Hi Eddie,
> >
> >     I recommend you to use ums framework instead of fastboot,
> > because ums have dual-buffer which improve performance.
> >
> I will try to add dual buffer support in next version

If of course possible - please reuse as much code as possible.

> 
> >
> > Thanks,
> > - Kever
> >
> > On 03/15/2017 03:56 PM, Eddie Cai wrote:
> >
> >> this patch implement fastboot protocol on the device side. this is
> >> based on USB
> >> download gadget infrastructure. the rockusb function implements
> >> the rd, wl, rid
> >> commands. it can work with rkdeveloptool;
> >> https://github.com/rockchip-linux/rkdeveloptool
> >>
> >> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> >> ---
> >>   drivers/usb/gadget/Makefile    |   1 +
> >>   drivers/usb/gadget/f_rockusb.c | 801
> >> ++++++++++++++++++++++++++++++ +++++++++++
> >>   2 files changed, 802 insertions(+)
> >>   create mode 100644 drivers/usb/gadget/f_rockusb.c
> >>
> >> diff --git a/drivers/usb/gadget/Makefile
> >> b/drivers/usb/gadget/Makefile index 0fbbb7c..0eb27a3 100644
> >> --- a/drivers/usb/gadget/Makefile
> >> +++ b/drivers/usb/gadget/Makefile
> >> @@ -28,6 +28,7 @@ obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
> >>   obj-$(CONFIG_USB_FUNCTION_DFU) += f_dfu.o
> >>   obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
> >>   obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
> >> +obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o
> >>   endif
> >>   endif
> >>   ifdef CONFIG_USB_ETHER
> >> diff --git a/drivers/usb/gadget/f_rockusb.c
> >> b/drivers/usb/gadget/f_rockusb.c
> >> new file mode 100644
> >> index 0000000..a67cb35
> >> --- /dev/null
> >> +++ b/drivers/usb/gadget/f_rockusb.c
> >> @@ -0,0 +1,801 @@
> >> +/*
> >> + * (C) Copyright 2017
> >> + *
> >> + * Eddie Cai <eddie.cai.linux@gmail.com>
> >> + *
> >> + * SPDX-License-Identifier:    GPL-2.0+
> >> + */
> >> +
> >> +#include <config.h>
> >> +#include <common.h>
> >> +#include <errno.h>
> >> +#include <malloc.h>
> >> +#include <linux/usb/ch9.h>
> >> +#include <linux/usb/gadget.h>
> >> +#include <linux/usb/composite.h>
> >> +#include <linux/compiler.h>
> >> +#include <version.h>
> >> +#include <g_dnl.h>
> >> +
> >> +#define ROCKUSB_VERSION                "0.1"
> >> +
> >> +#define ROCKUSB_INTERFACE_CLASS        0xff
> >> +#define ROCKUSB_INTERFACE_SUB_CLASS    0x06
> >> +#define ROCKUSB_INTERFACE_PROTOCOL     0x05
> >> +
> >> +#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0  (0x0200)
> >> +#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1  (0x0040)
> >> +#define TX_ENDPOINT_MAXIMUM_PACKET_SIZE      (0x0040)
> >> +
> >> +#define EP_BUFFER_SIZE                 4096
> >> +/*
> >> + * EP_BUFFER_SIZE must always be an integral multiple of
> >> maxpacket size
> >> + * (64 or 512 or 1024), else we break on certain controllers like
> >> DWC3
> >> + * that expect bulk OUT requests to be divisible by maxpacket
> >> size.
> >> + */
> >> +
> >> +struct f_rockusb {
> >> +       struct usb_function usb_function;
> >> +
> >> +       /* IN/OUT EP's and corresponding requests */
> >> +       struct usb_ep *in_ep, *out_ep;
> >> +       struct usb_request *in_req, *out_req;
> >> +};
> >> +
> >> +static inline struct f_rockusb *func_to_rockusb(struct
> >> usb_function *f) +{
> >> +       return container_of(f, struct f_rockusb, usb_function);
> >> +}
> >> +
> >> +static struct f_rockusb *rockusb_func;
> >> +
> >> +static struct usb_endpoint_descriptor fs_ep_in = {
> >> +       .bLength            = USB_DT_ENDPOINT_SIZE,
> >> +       .bDescriptorType    = USB_DT_ENDPOINT,
> >> +       .bEndpointAddress   = USB_DIR_IN,
> >> +       .bmAttributes       = USB_ENDPOINT_XFER_BULK,
> >> +       .wMaxPacketSize     = cpu_to_le16(64),
> >> +};
> >> +
> >> +static struct usb_endpoint_descriptor fs_ep_out = {
> >> +       .bLength                = USB_DT_ENDPOINT_SIZE,
> >> +       .bDescriptorType        = USB_DT_ENDPOINT,
> >> +       .bEndpointAddress       = USB_DIR_OUT,
> >> +       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
> >> +       .wMaxPacketSize         = cpu_to_le16(64),
> >> +};
> >> +
> >> +static struct usb_endpoint_descriptor hs_ep_in = {
> >> +       .bLength                = USB_DT_ENDPOINT_SIZE,
> >> +       .bDescriptorType        = USB_DT_ENDPOINT,
> >> +       .bEndpointAddress       = USB_DIR_IN,
> >> +       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
> >> +       .wMaxPacketSize         = cpu_to_le16(512),
> >> +};
> >> +
> >> +static struct usb_endpoint_descriptor hs_ep_out = {
> >> +       .bLength                = USB_DT_ENDPOINT_SIZE,
> >> +       .bDescriptorType        = USB_DT_ENDPOINT,
> >> +       .bEndpointAddress       = USB_DIR_OUT,
> >> +       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
> >> +       .wMaxPacketSize         = cpu_to_le16(512),
> >> +};
> >> +
> >> +static struct usb_interface_descriptor interface_desc = {
> >> +       .bLength                = USB_DT_INTERFACE_SIZE,
> >> +       .bDescriptorType        = USB_DT_INTERFACE,
> >> +       .bInterfaceNumber       = 0x00,
> >> +       .bAlternateSetting      = 0x00,
> >> +       .bNumEndpoints          = 0x02,
> >> +       .bInterfaceClass        = ROCKUSB_INTERFACE_CLASS,
> >> +       .bInterfaceSubClass     = ROCKUSB_INTERFACE_SUB_CLASS,
> >> +       .bInterfaceProtocol     = ROCKUSB_INTERFACE_PROTOCOL,
> >> +};
> >> +
> >> +static struct usb_descriptor_header *rkusb_fs_function[] = {
> >> +       (struct usb_descriptor_header *)&interface_desc,
> >> +       (struct usb_descriptor_header *)&fs_ep_in,
> >> +       (struct usb_descriptor_header *)&fs_ep_out,
> >> +};
> >> +
> >> +static struct usb_descriptor_header *rkusb_hs_function[] = {
> >> +       (struct usb_descriptor_header *)&interface_desc,
> >> +       (struct usb_descriptor_header *)&hs_ep_in,
> >> +       (struct usb_descriptor_header *)&hs_ep_out,
> >> +       NULL,
> >> +};
> >> +
> >> +static struct usb_endpoint_descriptor *
> >> +rkusb_ep_desc(struct usb_gadget *g, struct
> >> usb_endpoint_descriptor *fs,
> >> +           struct usb_endpoint_descriptor *hs)
> >> +{
> >> +       if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
> >> +               return hs;
> >> +       return fs;
> >> +}
> >> +
> >> +/*
> >> + * static strings, in UTF-8
> >> + */
> >> +static const char rkusb_name[] = "Rockchip Rockusb";
> >> +
> >> +static struct usb_string rkusb_string_defs[] = {
> >> +       [0].s = rkusb_name,
> >> +       {  }                    /* end of list */
> >> +};
> >> +
> >> +static struct usb_gadget_strings stringtab_rkusb = {
> >> +       .language       = 0x0409,       /* en-us */
> >> +       .strings        = rkusb_string_defs,
> >> +};
> >> +
> >> +static struct usb_gadget_strings *rkusb_strings[] = {
> >> +       &stringtab_rkusb,
> >> +       NULL,
> >> +};
> >> +
> >> +static void rx_handler_command(struct usb_ep *ep, struct
> >> usb_request *req);
> >> +static int rockusb_tx_write_csw(u32 Tag, int residue, u8 Status,
> >> int size);
> >> +
> >> +static void rockusb_complete(struct usb_ep *ep, struct
> >> usb_request *req) +{
> >> +       int status = req->status;
> >> +       if (!status)
> >> +               return;
> >> +       debug("status: %d ep '%s' trans: %d\n", status, ep->name,
> >> req->actual);
> >> +}
> >> +
> >> +static int rockusb_bind(struct usb_configuration *c, struct
> >> usb_function *f)
> >> +{
> >> +       int id;
> >> +       struct usb_gadget *gadget = c->cdev->gadget;
> >> +       struct f_rockusb *f_rkusb = func_to_rockusb(f);
> >> +       const char *s;
> >> +
> >> +       id = usb_interface_id(c, f);
> >> +       if (id < 0)
> >> +               return id;
> >> +       interface_desc.bInterfaceNumber = id;
> >> +
> >> +       id = usb_string_id(c->cdev);
> >> +       if (id < 0)
> >> +               return id;
> >> +
> >> +       rkusb_string_defs[0].id = id;
> >> +       interface_desc.iInterface = id;
> >> +
> >> +       f_rkusb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in);
> >> +       if (!f_rkusb->in_ep)
> >> +               return -ENODEV;
> >> +       f_rkusb->in_ep->driver_data = c->cdev;
> >> +
> >> +       f_rkusb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out);
> >> +       if (!f_rkusb->out_ep)
> >> +               return -ENODEV;
> >> +       f_rkusb->out_ep->driver_data = c->cdev;
> >> +
> >> +       f->descriptors = rkusb_fs_function;
> >> +
> >> +       if (gadget_is_dualspeed(gadget)) {
> >> +               hs_ep_in.bEndpointAddress =
> >> fs_ep_in.bEndpointAddress;
> >> +               hs_ep_out.bEndpointAddress =
> >> fs_ep_out.bEndpointAddress;
> >> +               f->hs_descriptors = rkusb_hs_function;
> >> +       }
> >> +
> >> +       s = getenv("serial#");
> >> +       if (s)
> >> +               g_dnl_set_serialnumber((char *)s);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static void rockusb_unbind(struct usb_configuration *c, struct
> >> usb_function *f)
> >> +{
> >> +       memset(rockusb_func, 0, sizeof(*rockusb_func));
> >> +}
> >> +
> >> +static void rockusb_disable(struct usb_function *f)
> >> +{
> >> +       struct f_rockusb *f_rkusb = func_to_rockusb(f);
> >> +
> >> +       usb_ep_disable(f_rkusb->out_ep);
> >> +       usb_ep_disable(f_rkusb->in_ep);
> >> +
> >> +       if (f_rkusb->out_req) {
> >> +               free(f_rkusb->out_req->buf);
> >> +               usb_ep_free_request(f_rkusb->out_ep,
> >> f_rkusb->out_req);
> >> +               f_rkusb->out_req = NULL;
> >> +       }
> >> +       if (f_rkusb->in_req) {
> >> +               free(f_rkusb->in_req->buf);
> >> +               usb_ep_free_request(f_rkusb->in_ep,
> >> f_rkusb->in_req);
> >> +               f_rkusb->in_req = NULL;
> >> +       }
> >> +}
> >> +
> >> +static struct usb_request *rockusb_start_ep(struct usb_ep *ep)
> >> +{
> >> +       struct usb_request *req;
> >> +
> >> +       req = usb_ep_alloc_request(ep, 0);
> >> +       if (!req)
> >> +               return NULL;
> >> +
> >> +       req->length = EP_BUFFER_SIZE;
> >> +       req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
> >> EP_BUFFER_SIZE);
> >> +       if (!req->buf) {
> >> +               usb_ep_free_request(ep, req);
> >> +               return NULL;
> >> +       }
> >> +
> >> +       memset(req->buf, 0, req->length);
> >> +       return req;
> >> +}
> >> +
> >> +static int rockusb_set_alt(struct usb_function *f,
> >> +                           unsigned interface, unsigned alt)
> >> +{
> >> +       int ret;
> >> +       struct usb_composite_dev *cdev = f->config->cdev;
> >> +       struct usb_gadget *gadget = cdev->gadget;
> >> +       struct f_rockusb *f_rkusb = func_to_rockusb(f);
> >> +       const struct usb_endpoint_descriptor *d;
> >> +
> >> +       debug("%s: func: %s intf: %d alt: %d\n",
> >> +             __func__, f->name, interface, alt);
> >> +
> >> +       d = rkusb_ep_desc(gadget, &fs_ep_out, &hs_ep_out);
> >> +       ret = usb_ep_enable(f_rkusb->out_ep, d);
> >> +       if (ret) {
> >> +               puts("failed to enable out ep\n");
> >> +               return ret;
> >> +       }
> >> +
> >> +       f_rkusb->out_req = rockusb_start_ep(f_rkusb->out_ep);
> >> +       if (!f_rkusb->out_req) {
> >> +               puts("failed to alloc out req\n");
> >> +               ret = -EINVAL;
> >> +               goto err;
> >> +       }
> >> +       f_rkusb->out_req->complete = rx_handler_command;
> >> +
> >> +       d = rkusb_ep_desc(gadget, &fs_ep_in, &hs_ep_in);
> >> +       ret = usb_ep_enable(f_rkusb->in_ep, d);
> >> +       if (ret) {
> >> +               puts("failed to enable in ep\n");
> >> +               goto err;
> >> +       }
> >> +
> >> +       f_rkusb->in_req = rockusb_start_ep(f_rkusb->in_ep);
> >> +       if (!f_rkusb->in_req) {
> >> +               puts("failed alloc req in\n");
> >> +               ret = -EINVAL;
> >> +               goto err;
> >> +       }
> >> +       f_rkusb->in_req->complete = rockusb_complete;
> >> +
> >> +       ret = usb_ep_queue(f_rkusb->out_ep, f_rkusb->out_req, 0);
> >> +       if (ret)
> >> +               goto err;
> >> +
> >> +       return 0;
> >> +err:
> >> +       rockusb_disable(f);
> >> +       return ret;
> >> +}
> >> +
> >> +static int rockusb_add(struct usb_configuration *c)
> >> +{
> >> +       struct f_rockusb *f_rkusb = rockusb_func;
> >> +       int status;
> >> +
> >> +       debug("%s: cdev: 0x%p\n", __func__, c->cdev);
> >> +
> >> +       if (!f_rkusb) {
> >> +               f_rkusb = memalign(CONFIG_SYS_CACHELINE_SIZE,
> >> sizeof(*f_rkusb));
> >> +               if (!f_rkusb)
> >> +                       return -ENOMEM;
> >> +
> >> +               rockusb_func = f_rkusb;
> >> +               memset(f_rkusb, 0, sizeof(*f_rkusb));
> >> +       }
> >> +
> >> +       f_rkusb->usb_function.name = "f_rockusb";
> >> +       f_rkusb->usb_function.bind = rockusb_bind;
> >> +       f_rkusb->usb_function.unbind = rockusb_unbind;
> >> +       f_rkusb->usb_function.set_alt = rockusb_set_alt;
> >> +       f_rkusb->usb_function.disable = rockusb_disable;
> >> +       f_rkusb->usb_function.strings = rkusb_strings;
> >> +
> >> +       status = usb_add_function(c, &f_rkusb->usb_function);
> >> +       if (status) {
> >> +               free(f_rkusb);
> >> +               rockusb_func = f_rkusb;
> >> +       }
> >> +       return status;
> >> +}
> >> +
> >> +char *rockusb_dev_type = 0;
> >> +int rockusb_dev_index = 0;
> >> +
> >> +void rockusb_dev_init(char *dev_type, int dev_index)
> >> +{
> >> +       rockusb_dev_type = dev_type;
> >> +       rockusb_dev_index = dev_index;
> >> +}
> >> +
> >> +DECLARE_GADGET_BIND_CALLBACK(usb_dnl_rockusb, rockusb_add);
> >> +
> >> +static int rockusb_tx_write(const char *buffer, unsigned int
> >> buffer_size) +{
> >> +       struct usb_request *in_req = rockusb_func->in_req;
> >> +       int ret;
> >> +
> >> +       memcpy(in_req->buf, buffer, buffer_size);
> >> +       in_req->length = buffer_size;
> >> +       usb_ep_dequeue(rockusb_func->in_ep, in_req);
> >> +       ret = usb_ep_queue(rockusb_func->in_ep, in_req, 0);
> >> +       if (ret)
> >> +               printf("Error %d on queue\n", ret);
> >> +       return 0;
> >> +}
> >> +
> >> +static int rockusb_tx_write_str(const char *buffer)
> >> +{
> >> +       return rockusb_tx_write(buffer, strlen(buffer));
> >> +}
> >> +
> >> +/* Bulk-only data structures */
> >> +
> >> +/* Command Block Wrapper */
> >> +struct fsg_bulk_cb_wrap {
> >> +       __le32  Signature;              /* Contains 'USBC' */
> >> +       u32     Tag;                    /* Unique per command id */
> >> +       __le32  DataTransferLength;     /* Size of the data */
> >> +       u8      Flags;                  /* Direction in bit 7 */
> >> +       u8      Lun;                    /* LUN (normally 0) */
> >> +       u8      Length;                 /* Of the CDB, <=
> >> MAX_COMMAND_SIZE */
> >> +       u8      CDB[16];                /* Command Data Block */
> >> +};
> >> +
> >> +#define USB_BULK_CB_WRAP_LEN   31
> >> +#define USB_BULK_CB_SIG                0x43425355      /* Spells
> >> out USBC */
> >> +#define USB_BULK_IN_FLAG       0x80
> >> +
> >> +/* Command Status Wrapper */
> >> +struct bulk_cs_wrap {
> >> +       __le32  Signature;              /* Should = 'USBS' */
> >> +       u32     Tag;                    /* Same as original
> >> command */
> >> +       __le32  Residue;                /* Amount not transferred
> >> */
> >> +       u8      Status;                 /* See below */
> >> +};
> >> +
> >> +#define USB_BULK_CS_WRAP_LEN   13
> >> +#define USB_BULK_CS_SIG                0x53425355      /* Spells
> >> out 'USBS' */
> >> +#define USB_STATUS_PASS                0
> >> +#define USB_STATUS_FAIL                1
> >> +#define USB_STATUS_PHASE_ERROR 2
> >> +
> >> +
> >> +#define        CSW_GOOD                0x00
> >> +#define        CSW_FAIL                0x01
> >> +
> >> +static void printcbw(char *buf)
> >> +{
> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
> >> A_MINALIGN)));
> >> +
> >> +       memcpy((char*)&cbw, buf, USB_BULK_CB_WRAP_LEN);
> >> +
> >> +       debug("cbw: Signature:%x\n", cbw.Signature);
> >> +       debug("cbw: Tag=%x\n", cbw.Tag);
> >> +       debug("cbw: DataTransferLength=%d\n",
> >> cbw.DataTransferLength);
> >> +       debug("cbw: Flags=%x\n", cbw.Flags);
> >> +       debug("cbw: Lun=%d\n", cbw.Lun);
> >> +       debug("cbw: Length=%d\n", cbw.Length);
> >> +       debug("cbw: ucOperCode=%x\n", cbw.CDB[0]);
> >> +       debug("cbw: ucReserved=%x\n", cbw.CDB[1]);
> >> +       debug("cbw: dwAddress:%x %x %x %x\n", cbw.CDB[5],
> >> cbw.CDB[4],
> >> +                                               cbw.CDB[3],
> >> cbw.CDB[2]);
> >> +       debug("cbw: ucReserved2=%x\n", cbw.CDB[6]);
> >> +       debug("cbw: usLength:%x %x\n", cbw.CDB[8], cbw.CDB[7]);
> >> +
> >> +}
> >> +
> >> +static void printcsw(char *buf)
> >> +{
> >> +       struct bulk_cs_wrap csw __attribute__((aligned(ARCH_DM
> >> A_MINALIGN)));
> >> +
> >> +       memcpy((char*)&csw, buf, USB_BULK_CS_WRAP_LEN);
> >> +       debug("csw: Signature:%x\n", csw.Signature);
> >> +       debug("csw: Tag:%x\n", csw.Tag);
> >> +       debug("csw: Residue:%x\n", csw.Residue);
> >> +       debug("csw: Status:%x\n", csw.Status);
> >> +
> >> +}
> >> +
> >> +static int rockusb_tx_write_csw(u32 Tag, int residue, u8 Status,
> >> int size)
> >> +{
> >> +       struct bulk_cs_wrap csw __attribute__((aligned(ARCH_DM
> >> A_MINALIGN)));
> >> +       csw.Signature = cpu_to_le32(USB_BULK_CS_SIG);
> >> +       csw.Tag = Tag;
> >> +       csw.Residue = cpu_to_be32(residue);
> >> +       csw.Status = Status;
> >> +       printcsw((char*)&csw);
> >> +       return rockusb_tx_write((char*)&csw, size);
> >> +}
> >> +
> >> +int download_tag = 0;
> >> +int download_lba = 0;
> >> +static unsigned int download_size;
> >> +static unsigned int download_bytes;
> >> +struct blk_desc *download_desc = 0;
> >> +
> >> +static unsigned int rx_bytes_expected(struct usb_ep *ep)
> >> +{
> >> +       int rx_remain = download_size - download_bytes;
> >> +       unsigned int rem;
> >> +       unsigned int maxpacket = ep->maxpacket;
> >> +
> >> +       if (rx_remain <= 0)
> >> +               return 0;
> >> +       else if (rx_remain > EP_BUFFER_SIZE)
> >> +               return EP_BUFFER_SIZE;
> >> +
> >> +       rem = rx_remain % maxpacket;
> >> +       if (rem > 0)
> >> +               rx_remain = rx_remain + (maxpacket - rem);
> >> +
> >> +       return rx_remain;
> >> +}
> >> +
> >> +static void rx_handler_dl_image(struct usb_ep *ep, struct
> >> usb_request *req)
> >> +{
> >> +       unsigned int transfer_size = download_size -
> >> download_bytes;
> >> +       const unsigned char *buffer = req->buf;
> >> +       unsigned int buffer_size = req->actual;
> >> +
> >> +       if(!download_desc){
> >> +               printf("rx_handler_dl_image blk_get_dev\n");
> >> +               download_desc = blk_get_dev(rockusb_dev_type,
> >> rockusb_dev_index);
> >> +               if (!download_desc || download_desc->type ==
> >> DEV_TYPE_UNKNOWN){
> >> +                       error("invalid mmc device\n");
> >> +                       rockusb_tx_write_csw(download_tag, 0,
> >> CSW_FAIL,
> >> +
> >> USB_BULK_CS_WRAP_LEN);
> >> +                       return;
> >> +               }
> >> +       }
> >> +
> >> +       if (req->status != 0) {
> >> +               printf("Bad status: %d\n", req->status);
> >> +               rockusb_tx_write_csw(download_tag, 0,
> >> +                                       CSW_FAIL,
> >> USB_BULK_CS_WRAP_LEN);
> >> +               return;
> >> +       }
> >> +
> >> +       if (buffer_size < transfer_size)
> >> +               transfer_size = buffer_size;
> >> +
> >> +       memcpy((void *)CONFIG_FASTBOOT_BUF_ADDR + download_bytes,
> >> +              buffer, transfer_size);
> >> +       download_bytes += transfer_size;
> >> +
> >> +       /* Check if transfer is done */
> >> +       if (download_bytes >= download_size) {
> >> +               int blks = 0, blkcnt = download_size/512;
> >> +               printf("download %d bytes finished, start writing
> >> to lba %x\n",
> >> +                                download_bytes, download_lba);
> >> +               blks = blk_dwrite(download_desc, download_lba,
> >> blkcnt,
> >> +
> >> (char*)CONFIG_FASTBOOT_BUF_ADDR);
> >> +               if (blks != blkcnt) {
> >> +                       error("failed writing to device %s: %d\n",
> >> +                               rockusb_dev_type,
> >> rockusb_dev_index);
> >> +                       rockusb_tx_write_csw(download_tag, 0,
> >> +                                               CSW_FAIL,
> >> USB_BULK_CS_WRAP_LEN);
> >> +                       return;
> >> +               }
> >> +
> >> +               req->complete = rx_handler_command;
> >> +               req->length = EP_BUFFER_SIZE;
> >> +               download_size = 0;
> >> +               printf("done\n");
> >> +               rockusb_tx_write_csw(download_tag, 0, CSW_GOOD,
> >> +                                       USB_BULK_CS_WRAP_LEN);
> >> +       } else {
> >> +               req->length = rx_bytes_expected(ep);
> >> +       }
> >> +
> >> +       req->actual = 0;
> >> +       usb_ep_queue(ep, req, 0);
> >> +}
> >> +
> >> +static void cb_test_unit_ready(struct usb_ep *ep, struct
> >> usb_request *req)
> >> +{
> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
> >> A_MINALIGN)));
> >> +
> >> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> >> +
> >> +       rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength,
> >> +                               CSW_GOOD, USB_BULK_CS_WRAP_LEN);
> >> +
> >> +}
> >> +
> >> +static void cb_read_storage_id(struct usb_ep *ep, struct
> >> usb_request *req)
> >> +{
> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
> >> A_MINALIGN)));
> >> +       char emmc_id[] = "EMMC ";
> >> +
> >> +       printf("cb_read_storage_id\n");
> >> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> >> +       rockusb_tx_write_str(emmc_id);//only support emmc now
> >> +       rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength,
> >> CSW_GOOD,
> >> +                               USB_BULK_CS_WRAP_LEN);
> >> +}
> >> +
> >> +static void cb_write_lba(struct usb_ep *ep, struct usb_request
> >> *req) +{
> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
> >> A_MINALIGN)));
> >> +       int sector_count;
> >> +
> >> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> >> +       sector_count = (int)get_unaligned_be16(&cbw.CDB[7]);
> >> +       download_lba = get_unaligned_be32(&cbw.CDB[2]);
> >> +       download_size = sector_count * 512;
> >> +       download_bytes = 0;
> >> +       download_tag = cbw.Tag;
> >> +       if ((0 == download_size) || (download_size>CONFIG_FASTBOOT
> >> _BUF_SIZE)){
> >> +               rockusb_tx_write_csw(cbw.Tag,
> >> cbw.DataTransferLength,
> >> +                                       CSW_FAIL,
> >> USB_BULK_CS_WRAP_LEN);
> >> +       } else {
> >> +               req->complete = rx_handler_dl_image;
> >> +               req->length = rx_bytes_expected(ep);
> >> +       }
> >> +}
> >> +
> >> +static int reboot_flag;
> >> +
> >> +int __weak rkusb_set_reboot_flag(int flag)
> >> +{
> >> +       printf("rkusb_set_reboot_flag: %d\n", reboot_flag);
> >> +       return -ENOSYS;
> >> +}
> >> +
> >> +static void compl_do_reset(struct usb_ep *ep, struct usb_request
> >> *req) +{
> >> +       rkusb_set_reboot_flag(reboot_flag);
> >> +       do_reset(NULL, 0, 0, NULL);
> >> +}
> >> +
> >> +static void cb_reboot(struct usb_ep *ep, struct usb_request *req)
> >> +{
> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
> >> A_MINALIGN)));
> >> +       reboot_flag = 0;
> >> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> >> +       reboot_flag = cbw.CDB[1];
> >> +       rockusb_func->in_req->complete = compl_do_reset;
> >> +       rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength,
> >> CSW_GOOD,
> >> +                               USB_BULK_CS_WRAP_LEN);
> >> +}
> >> +
> >> +static void cb_not_support(struct usb_ep *ep, struct usb_request
> >> *req) +{
> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
> >> A_MINALIGN)));
> >> +
> >> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> >> +       printf("Rockusb command %x not support yet\n", cbw.CDB[0]);
> >> +       rockusb_tx_write_csw(cbw.Tag, 0, CSW_FAIL,
> >> USB_BULK_CS_WRAP_LEN); +}
> >> +
> >> +#define RKUSB_STATUS_IDLE                      0
> >> +#define RKUSB_STATUS_CMD                       1
> >> +#define RKUSB_STATUS_RXDATA                    2
> >> +#define RKUSB_STATUS_TXDATA                    3
> >> +#define RKUSB_STATUS_CSW                       4
> >> +#define RKUSB_STATUS_RXDATA_PREPARE            5
> >> +#define RKUSB_STATUS_TXDATA_PREPARE            6
> >> +
> >> +typedef enum {
> >> +               TEST_UNIT_READY = 0,
> >> +               READ_FLASH_ID = 0x01,
> >> +               TEST_BAD_BLOCK = 0x03,
> >> +               READ_SECTOR = 0x04,
> >> +               WRITE_SECTOR = 0x05,
> >> +               ERASE_NORMAL = 0x06,
> >> +               ERASE_FORCE = 0x0B,
> >> +               READ_LBA = 0x14,
> >> +               WRITE_LBA = 0x15,
> >> +               ERASE_SYSTEMDISK = 0x16,
> >> +               READ_SDRAM = 0x17,
> >> +               WRITE_SDRAM = 0x18,
> >> +               EXECUTE_SDRAM = 0x19,
> >> +               READ_FLASH_INFO = 0x1A,
> >> +               READ_CHIP_INFO = 0x1B,
> >> +               SET_RESET_FLAG = 0x1E,
> >> +               WRITE_EFUSE = 0x1F,
> >> +               READ_EFUSE = 0x20,
> >> +               READ_SPI_FLASH = 0x21,
> >> +               WRITE_SPI_FLASH = 0x22,
> >> +               WRITE_NEW_EFUSE = 0x23,
> >> +               READ_NEW_EFUSE = 0x24,
> >> +               DEVICE_RESET = 0xFF
> >> +} USB_OPERATION_CODE;
> >> +
> >> +#define        K_FW_TEST_UNIT_READY    0x00
> >> +#define        K_FW_READ_FLASH_ID              0x01
> >> +#define        K_FW_SET_DEVICE_ID              0x02
> >> +#define        K_FW_TEST_BAD_BLOCK             0x03
> >> +#define        K_FW_READ_10                    0x04
> >> +#define        K_FW_WRITE_10                   0x05
> >> +#define        K_FW_ERASE_10                   0x06
> >> +#define        K_FW_WRITE_SPARE                0x07
> >> +#define        K_FW_READ_SPARE                 0x08
> >> +
> >> +#define        K_FW_ERASE_10_FORCE             0x0b
> >> +#define        K_FW_GET_VERSION                0x0c
> >> +
> >> +#define        K_FW_LBA_READ_10                0x14
> >> +#define        K_FW_LBA_WRITE_10               0x15
> >> +#define        K_FW_ERASE_SYS_DISK             0x16
> >> +#define        K_FW_SDRAM_READ_10              0x17
> >> +#define        K_FW_SDRAM_WRITE_10             0x18
> >> +#define        K_FW_SDRAM_EXECUTE              0x19
> >> +#define        K_FW_READ_FLASH_INFO            0x1A
> >> +#define        K_FW_GET_CHIP_VER               0x1B
> >> +#define        K_FW_LOW_FORMAT                 0x1C
> >> +#define        K_FW_SET_RESET_FLAG             0x1E
> >> +#define        K_FW_SPI_READ_10                0x21
> >> +#define        K_FW_SPI_WRITE_10               0x22
> >> +
> >> +#define        K_FW_SESSION                    0X30
> >> +#define        K_FW_RESET                      0xff
> >> +
> >> +#define CBW_DIRECTION_OUT              0x00
> >> +#define CBW_DIRECTION_IN               0x80
> >> +
> >> +struct cmd_dispatch_info {
> >> +       int cmd;
> >> +       void (*cb)(struct usb_ep *ep, struct usb_request *req);
> >> +};
> >> +
> >> +static const struct cmd_dispatch_info cmd_dispatch_info[] = {
> >> +       {
> >> +               .cmd = K_FW_TEST_UNIT_READY,
> >> +               .cb = cb_test_unit_ready,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_READ_FLASH_ID,
> >> +               .cb = cb_read_storage_id,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_SET_DEVICE_ID,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_TEST_BAD_BLOCK,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_READ_10,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_WRITE_10,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_ERASE_10,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_WRITE_SPARE,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_READ_SPARE,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_ERASE_10_FORCE,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_GET_VERSION,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_LBA_READ_10,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_LBA_WRITE_10,
> >> +               .cb = cb_write_lba,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_ERASE_SYS_DISK,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_SDRAM_READ_10,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_SDRAM_WRITE_10,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_SDRAM_EXECUTE,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_READ_FLASH_INFO,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_GET_CHIP_VER,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_LOW_FORMAT,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_SET_RESET_FLAG,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_SPI_READ_10,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_SPI_WRITE_10,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_SESSION,
> >> +               .cb = cb_not_support,
> >> +       },
> >> +       {
> >> +               .cmd = K_FW_RESET,
> >> +               .cb = cb_reboot,
> >> +       },
> >> +};
> >> +
> >> +
> >> +
> >> +static void rx_handler_command(struct usb_ep *ep, struct
> >> usb_request *req)
> >> +{
> >> +       void (*func_cb)(struct usb_ep *ep, struct usb_request
> >> *req) = NULL;
> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
> >> A_MINALIGN)));
> >> +       int i;
> >> +       char *cmdbuf = req->buf;
> >> +
> >> +       if (req->status != 0 || req->length == 0)
> >> +               return;
> >> +
> >> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> >> +       printcbw(req->buf);
> >> +
> >> +       for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) {
> >> +               if (cmd_dispatch_info[i].cmd == cbw.CDB[0]) {
> >> +                       func_cb = cmd_dispatch_info[i].cb;
> >> +                       break;
> >> +               }
> >> +       }
> >> +
> >> +       if (!func_cb) {
> >> +               error("unknown command: %s", (char*)req->buf);
> >> +               rockusb_tx_write_str("FAILunknown command");
> >> +       } else {
> >> +               if (req->actual < req->length) {
> >> +                       u8 *buf = (u8 *)req->buf;
> >> +                       buf[req->actual] = 0;
> >> +                       func_cb(ep, req);
> >> +               } else {
> >> +                       error("buffer overflow");
> >> +                       rockusb_tx_write_str("FAILbuffer
> >> overflow");
> >> +               }
> >> +       }
> >> +
> >> +       *cmdbuf = '\0';
> >> +       req->actual = 0;
> >> +       usb_ep_queue(ep, req, 0);
> >> +}
> >>
> >
> >
> >




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
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

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

* [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb
  2017-03-20  1:53   ` Eddie Cai
@ 2017-03-20 12:24     ` Marek Vasut
  2017-03-20 16:01       ` Simon Glass
  0 siblings, 1 reply; 36+ messages in thread
From: Marek Vasut @ 2017-03-20 12:24 UTC (permalink / raw)
  To: u-boot

On 03/20/2017 02:53 AM, Eddie Cai wrote:
> 2017-03-17 5:26 GMT+08:00 Marek Vasut <marex@denx.de>:
> 
>> On 03/15/2017 08:56 AM, Eddie Cai wrote:
>>> rockusb is a protocol run between host pc and device. it help people get
>> device
>>> info, flash image to device. this patch implement rockusb on device side.
>>
>> What is the benefit of this yet-another NIH protocol compared to ie.
>> DFU/UMS/Thor/Fastboot ?
>>
> This is mostly  used on Rockchip chipset. All the rockchip SoC boot rom and
> develop tools implement this protocol.
> So we want to use the same protocol which compatible with current tools.

This does not really answer my question. We have protocols which
implement exactly this functionality already, why do we need another one ?


-- 
Best regards,
Marek Vasut

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

* [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb
  2017-03-20 12:24     ` Marek Vasut
@ 2017-03-20 16:01       ` Simon Glass
  2017-03-20 16:33         ` Marek Vasut
  0 siblings, 1 reply; 36+ messages in thread
From: Simon Glass @ 2017-03-20 16:01 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On 20 March 2017 at 06:24, Marek Vasut <marex@denx.de> wrote:
> On 03/20/2017 02:53 AM, Eddie Cai wrote:
>> 2017-03-17 5:26 GMT+08:00 Marek Vasut <marex@denx.de>:
>>
>>> On 03/15/2017 08:56 AM, Eddie Cai wrote:
>>>> rockusb is a protocol run between host pc and device. it help people get
>>> device
>>>> info, flash image to device. this patch implement rockusb on device side.
>>>
>>> What is the benefit of this yet-another NIH protocol compared to ie.
>>> DFU/UMS/Thor/Fastboot ?
>>>
>> This is mostly  used on Rockchip chipset. All the rockchip SoC boot rom and
>> develop tools implement this protocol.
>> So we want to use the same protocol which compatible with current tools.
>
> This does not really answer my question. We have protocols which
> implement exactly this functionality already, why do we need another one ?

I think the point is that this is widely used with Rockchip devices,
and for mainline U-Boot to be fully useful it needs to support it.

However I do think it would be good to move to using DFU etc. if possible?

Regards,
Simon

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

* [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb
  2017-03-20 16:01       ` Simon Glass
@ 2017-03-20 16:33         ` Marek Vasut
  2017-03-21  5:17           ` Kever Yang
  0 siblings, 1 reply; 36+ messages in thread
From: Marek Vasut @ 2017-03-20 16:33 UTC (permalink / raw)
  To: u-boot

On 03/20/2017 05:01 PM, Simon Glass wrote:
> Hi Marek,
> 
> On 20 March 2017 at 06:24, Marek Vasut <marex@denx.de> wrote:
>> On 03/20/2017 02:53 AM, Eddie Cai wrote:
>>> 2017-03-17 5:26 GMT+08:00 Marek Vasut <marex@denx.de>:
>>>
>>>> On 03/15/2017 08:56 AM, Eddie Cai wrote:
>>>>> rockusb is a protocol run between host pc and device. it help people get
>>>> device
>>>>> info, flash image to device. this patch implement rockusb on device side.
>>>>
>>>> What is the benefit of this yet-another NIH protocol compared to ie.
>>>> DFU/UMS/Thor/Fastboot ?
>>>>
>>> This is mostly  used on Rockchip chipset. All the rockchip SoC boot rom and
>>> develop tools implement this protocol.
>>> So we want to use the same protocol which compatible with current tools.
>>
>> This does not really answer my question. We have protocols which
>> implement exactly this functionality already, why do we need another one ?
> 
> I think the point is that this is widely used with Rockchip devices,
> and for mainline U-Boot to be fully useful it needs to support it.

OK, I'll leave that decision to Lukasz . I'm not a big fan of adding
redundant functionality only because someone thought NIH is good before
looking at standards.

> However I do think it would be good to move to using DFU etc. if possible?

Yes.

-- 
Best regards,
Marek Vasut

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

* [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb
  2017-03-20 16:33         ` Marek Vasut
@ 2017-03-21  5:17           ` Kever Yang
  2017-03-21 14:27             ` Tom Rini
  0 siblings, 1 reply; 36+ messages in thread
From: Kever Yang @ 2017-03-21  5:17 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On 03/21/2017 12:33 AM, Marek Vasut wrote:
> On 03/20/2017 05:01 PM, Simon Glass wrote:
>> Hi Marek,
>>
>> On 20 March 2017 at 06:24, Marek Vasut <marex@denx.de> wrote:
>>> On 03/20/2017 02:53 AM, Eddie Cai wrote:
>>>> 2017-03-17 5:26 GMT+08:00 Marek Vasut <marex@denx.de>:
>>>>
>>>>> On 03/15/2017 08:56 AM, Eddie Cai wrote:
>>>>>> rockusb is a protocol run between host pc and device. it help people get
>>>>> device
>>>>>> info, flash image to device. this patch implement rockusb on device side.
>>>>> What is the benefit of this yet-another NIH protocol compared to ie.
>>>>> DFU/UMS/Thor/Fastboot ?
>>>>>
>>>> This is mostly  used on Rockchip chipset. All the rockchip SoC boot rom and
>>>> develop tools implement this protocol.
>>>> So we want to use the same protocol which compatible with current tools.
>>> This does not really answer my question. We have protocols which
>>> implement exactly this functionality already, why do we need another one ?
>> I think the point is that this is widely used with Rockchip devices,
>> and for mainline U-Boot to be fully useful it needs to support it.
> OK, I'll leave that decision to Lukasz . I'm not a big fan of adding
> redundant functionality only because someone thought NIH is good before
> looking at standards.

I don't know how you define "redundant functionality", from the gadget 
framework view,
yes, it's very similar to other storage based gadget, we may able to 
re-use the common part of the framework.
But it's definitely a different USB class driver which is used in 
Rockchip bootrom
and Rockchip loader, and some commands like RD(Reset device), 
DB(download boot)
are not able to use in ums or fastboot, but they are useful in Rockchip 
platform.

Thanks,
- Kever
>
>> However I do think it would be good to move to using DFU etc. if possible?
> Yes.
>

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

* [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb
  2017-03-21  5:17           ` Kever Yang
@ 2017-03-21 14:27             ` Tom Rini
  0 siblings, 0 replies; 36+ messages in thread
From: Tom Rini @ 2017-03-21 14:27 UTC (permalink / raw)
  To: u-boot

On Tue, Mar 21, 2017 at 01:17:18PM +0800, Kever Yang wrote:
> Hi Marek,
> 
> On 03/21/2017 12:33 AM, Marek Vasut wrote:
> >On 03/20/2017 05:01 PM, Simon Glass wrote:
> >>Hi Marek,
> >>
> >>On 20 March 2017 at 06:24, Marek Vasut <marex@denx.de> wrote:
> >>>On 03/20/2017 02:53 AM, Eddie Cai wrote:
> >>>>2017-03-17 5:26 GMT+08:00 Marek Vasut <marex@denx.de>:
> >>>>
> >>>>>On 03/15/2017 08:56 AM, Eddie Cai wrote:
> >>>>>>rockusb is a protocol run between host pc and device. it help people get
> >>>>>device
> >>>>>>info, flash image to device. this patch implement rockusb on device side.
> >>>>>What is the benefit of this yet-another NIH protocol compared to ie.
> >>>>>DFU/UMS/Thor/Fastboot ?
> >>>>>
> >>>>This is mostly  used on Rockchip chipset. All the rockchip SoC boot rom and
> >>>>develop tools implement this protocol.
> >>>>So we want to use the same protocol which compatible with current tools.
> >>>This does not really answer my question. We have protocols which
> >>>implement exactly this functionality already, why do we need another one ?
> >>I think the point is that this is widely used with Rockchip devices,
> >>and for mainline U-Boot to be fully useful it needs to support it.
> >OK, I'll leave that decision to Lukasz . I'm not a big fan of adding
> >redundant functionality only because someone thought NIH is good before
> >looking at standards.
> 
> I don't know how you define "redundant functionality", from the
> gadget framework view,
> yes, it's very similar to other storage based gadget, we may able to
> re-use the common part of the framework.
> But it's definitely a different USB class driver which is used in
> Rockchip bootrom
> and Rockchip loader, and some commands like RD(Reset device),
> DB(download boot)
> are not able to use in ums or fastboot, but they are useful in
> Rockchip platform.

So here's my two cents.  At the back end side of things, DFU, fastboot,
UMS, Thor, rockusb and whatever comes down the pipe next should all be
able to share a good bit of back end code, in a common way (and maybe we
can even address DFU using the CLI rather than API to do things) as it
all boils down to "take data via USB, write to defined location" or "do
something then reset the board" and so on.  And by that same token,
while I wish more vendors used the same protocols, we need to support
the world that exists, not the world we wish we had.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170321/16ddc6b8/attachment.sig>

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

* [U-Boot] [U-Boot 2/3] cmd: add rockusb command
  2017-03-20  8:14     ` Eddie Cai
@ 2017-03-22 13:05       ` Simon Glass
  0 siblings, 0 replies; 36+ messages in thread
From: Simon Glass @ 2017-03-22 13:05 UTC (permalink / raw)
  To: u-boot

Hi Eddie,

On 20 March 2017 at 02:14, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
> Hi Simon
>
> 2017-03-20 10:29 GMT+08:00 Simon Glass <sjg@chromium.org>:
>>
>> Hi Eddie,
>>
>> On 15 March 2017 at 01:56, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
>> >
>> > this patch add rockusb command. the usage is
>> >         rockusb <USB_controller> [<devtype>] <devnum>
>> > e.g. rockusb 0 mmc 0
>> >
>> > Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
>> > ---
>> >  cmd/Kconfig       | 12 +++++++++
>> >  cmd/Makefile      |  1 +
>> >  cmd/rockusb.c     | 79
>> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> >  include/rockusb.h | 13 +++++++++
>> >  4 files changed, 105 insertions(+)
>> >  create mode 100644 cmd/rockusb.c
>> >  create mode 100644 include/rockusb.h
>>

[..]

>>
>> > +       "rockusb <USB_controller> [<devtype>] <devnum>  e.g. rockusb 0
>> > mmc 0\n"
>> > +       "    devtype defaults to mmc"
>> > +);
>> > diff --git a/include/rockusb.h b/include/rockusb.h
>> > new file mode 100644
>> > index 0000000..cdea63d
>> > --- /dev/null
>> > +++ b/include/rockusb.h
>>
>> Can this go in include/asm instead?
>
> do you mean include/asm-generic ? may i know why ?

No I was thinking of arch/arm/include/asm/arch-rockchip. Because this
is a rockchip-specific file, isn't it?

Regards,
Simon

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

* [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb
  2017-03-15  7:56 [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb Eddie Cai
                   ` (4 preceding siblings ...)
  2017-03-16 21:26 ` Marek Vasut
@ 2017-03-27  8:27 ` Lukasz Majewski
  2017-03-28  9:13   ` Eddie Cai
  5 siblings, 1 reply; 36+ messages in thread
From: Lukasz Majewski @ 2017-03-27  8:27 UTC (permalink / raw)
  To: u-boot

HI Eddie,

> rockusb is a protocol run between host pc and device. it help people
> get device info, flash image to device. this patch implement rockusb
> on device side. 

I'm a bit confused, since I don't know if you work on v2 of those
patches (as Kever Yang pointed out that UMS approach could be
re-used here)?

(And just gentle reminder of the README.xxx file to describe
this protocol).	

> 
> Eddie Cai (3):
>   drivers: usb: gadget: add the rockusb gadget
>   cmd: add rockusb command
>   rockchip: rk3288: enable rockusb support on rk3288 based device
> 
>  cmd/Kconfig                     |  12 +
>  cmd/Makefile                    |   1 +
>  cmd/rockusb.c                   |  79 ++++
>  drivers/usb/gadget/Makefile     |   1 +
>  drivers/usb/gadget/f_rockusb.c  | 801
> ++++++++++++++++++++++++++++++++++++++++
> include/configs/rk3288_common.h |   4 +
> include/rockusb.h               |  13 + 7 files changed, 911
> insertions(+) create mode 100644 cmd/rockusb.c
>  create mode 100644 drivers/usb/gadget/f_rockusb.c
>  create mode 100644 include/rockusb.h
> 


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
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

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

* [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb
  2017-03-27  8:27 ` Lukasz Majewski
@ 2017-03-28  9:13   ` Eddie Cai
  0 siblings, 0 replies; 36+ messages in thread
From: Eddie Cai @ 2017-03-28  9:13 UTC (permalink / raw)
  To: u-boot

Hi Lukasz

2017-03-27 16:27 GMT+08:00 Lukasz Majewski <lukma@denx.de>:

> HI Eddie,
>
> > rockusb is a protocol run between host pc and device. it help people
> > get device info, flash image to device. this patch implement rockusb
> > on device side.
>
> I'm a bit confused, since I don't know if you work on v2 of those
> patches (as Kever Yang pointed out that UMS approach could be
> re-used here)?
>
> (And just gentle reminder of the README.xxx file to describe
> this protocol).
>
I am working on V2 patch. It will reused ums function as more as possible.
I won't forget README.rockusb

>
> >
> > Eddie Cai (3):
> >   drivers: usb: gadget: add the rockusb gadget
> >   cmd: add rockusb command
> >   rockchip: rk3288: enable rockusb support on rk3288 based device
> >
> >  cmd/Kconfig                     |  12 +
> >  cmd/Makefile                    |   1 +
> >  cmd/rockusb.c                   |  79 ++++
> >  drivers/usb/gadget/Makefile     |   1 +
> >  drivers/usb/gadget/f_rockusb.c  | 801
> > ++++++++++++++++++++++++++++++++++++++++
> > include/configs/rk3288_common.h |   4 +
> > include/rockusb.h               |  13 + 7 files changed, 911
> > insertions(+) create mode 100644 cmd/rockusb.c
> >  create mode 100644 drivers/usb/gadget/f_rockusb.c
> >  create mode 100644 include/rockusb.h
> >
>
>
> Best regards,
>
> Lukasz Majewski
>
> --
>
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> 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
>

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

* [U-Boot] [U-Boot 1/3] drivers: usb: gadget: add the rockusb gadget
  2017-03-20  8:37       ` Lukasz Majewski
@ 2017-04-20  0:56         ` Eddie Cai
  0 siblings, 0 replies; 36+ messages in thread
From: Eddie Cai @ 2017-04-20  0:56 UTC (permalink / raw)
  To: u-boot

Hi Lukasz

This is my V1 patch. let me know if you have some comment.

2017-03-20 16:37 GMT+08:00 Lukasz Majewski <lukma@denx.de>:
> Hi Eddie,
>
>> 2017-03-16 15:05 GMT+08:00 Kever Yang <kever.yang@rock-chips.com>:
>>
>> > Hi Eddie,
>> >
>> >     I recommend you to use ums framework instead of fastboot,
>> > because ums have dual-buffer which improve performance.
>> >
>> I will try to add dual buffer support in next version
>
> If of course possible - please reuse as much code as possible.
>
>>
>> >
>> > Thanks,
>> > - Kever
>> >
>> > On 03/15/2017 03:56 PM, Eddie Cai wrote:
>> >
>> >> this patch implement fastboot protocol on the device side. this is
>> >> based on USB
>> >> download gadget infrastructure. the rockusb function implements
>> >> the rd, wl, rid
>> >> commands. it can work with rkdeveloptool;
>> >> https://github.com/rockchip-linux/rkdeveloptool
>> >>
>> >> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
>> >> ---
>> >>   drivers/usb/gadget/Makefile    |   1 +
>> >>   drivers/usb/gadget/f_rockusb.c | 801
>> >> ++++++++++++++++++++++++++++++ +++++++++++
>> >>   2 files changed, 802 insertions(+)
>> >>   create mode 100644 drivers/usb/gadget/f_rockusb.c
>> >>
>> >> diff --git a/drivers/usb/gadget/Makefile
>> >> b/drivers/usb/gadget/Makefile index 0fbbb7c..0eb27a3 100644
>> >> --- a/drivers/usb/gadget/Makefile
>> >> +++ b/drivers/usb/gadget/Makefile
>> >> @@ -28,6 +28,7 @@ obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
>> >>   obj-$(CONFIG_USB_FUNCTION_DFU) += f_dfu.o
>> >>   obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
>> >>   obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
>> >> +obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o
>> >>   endif
>> >>   endif
>> >>   ifdef CONFIG_USB_ETHER
>> >> diff --git a/drivers/usb/gadget/f_rockusb.c
>> >> b/drivers/usb/gadget/f_rockusb.c
>> >> new file mode 100644
>> >> index 0000000..a67cb35
>> >> --- /dev/null
>> >> +++ b/drivers/usb/gadget/f_rockusb.c
>> >> @@ -0,0 +1,801 @@
>> >> +/*
>> >> + * (C) Copyright 2017
>> >> + *
>> >> + * Eddie Cai <eddie.cai.linux@gmail.com>
>> >> + *
>> >> + * SPDX-License-Identifier:    GPL-2.0+
>> >> + */
>> >> +
>> >> +#include <config.h>
>> >> +#include <common.h>
>> >> +#include <errno.h>
>> >> +#include <malloc.h>
>> >> +#include <linux/usb/ch9.h>
>> >> +#include <linux/usb/gadget.h>
>> >> +#include <linux/usb/composite.h>
>> >> +#include <linux/compiler.h>
>> >> +#include <version.h>
>> >> +#include <g_dnl.h>
>> >> +
>> >> +#define ROCKUSB_VERSION                "0.1"
>> >> +
>> >> +#define ROCKUSB_INTERFACE_CLASS        0xff
>> >> +#define ROCKUSB_INTERFACE_SUB_CLASS    0x06
>> >> +#define ROCKUSB_INTERFACE_PROTOCOL     0x05
>> >> +
>> >> +#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0  (0x0200)
>> >> +#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1  (0x0040)
>> >> +#define TX_ENDPOINT_MAXIMUM_PACKET_SIZE      (0x0040)
>> >> +
>> >> +#define EP_BUFFER_SIZE                 4096
>> >> +/*
>> >> + * EP_BUFFER_SIZE must always be an integral multiple of
>> >> maxpacket size
>> >> + * (64 or 512 or 1024), else we break on certain controllers like
>> >> DWC3
>> >> + * that expect bulk OUT requests to be divisible by maxpacket
>> >> size.
>> >> + */
>> >> +
>> >> +struct f_rockusb {
>> >> +       struct usb_function usb_function;
>> >> +
>> >> +       /* IN/OUT EP's and corresponding requests */
>> >> +       struct usb_ep *in_ep, *out_ep;
>> >> +       struct usb_request *in_req, *out_req;
>> >> +};
>> >> +
>> >> +static inline struct f_rockusb *func_to_rockusb(struct
>> >> usb_function *f) +{
>> >> +       return container_of(f, struct f_rockusb, usb_function);
>> >> +}
>> >> +
>> >> +static struct f_rockusb *rockusb_func;
>> >> +
>> >> +static struct usb_endpoint_descriptor fs_ep_in = {
>> >> +       .bLength            = USB_DT_ENDPOINT_SIZE,
>> >> +       .bDescriptorType    = USB_DT_ENDPOINT,
>> >> +       .bEndpointAddress   = USB_DIR_IN,
>> >> +       .bmAttributes       = USB_ENDPOINT_XFER_BULK,
>> >> +       .wMaxPacketSize     = cpu_to_le16(64),
>> >> +};
>> >> +
>> >> +static struct usb_endpoint_descriptor fs_ep_out = {
>> >> +       .bLength                = USB_DT_ENDPOINT_SIZE,
>> >> +       .bDescriptorType        = USB_DT_ENDPOINT,
>> >> +       .bEndpointAddress       = USB_DIR_OUT,
>> >> +       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
>> >> +       .wMaxPacketSize         = cpu_to_le16(64),
>> >> +};
>> >> +
>> >> +static struct usb_endpoint_descriptor hs_ep_in = {
>> >> +       .bLength                = USB_DT_ENDPOINT_SIZE,
>> >> +       .bDescriptorType        = USB_DT_ENDPOINT,
>> >> +       .bEndpointAddress       = USB_DIR_IN,
>> >> +       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
>> >> +       .wMaxPacketSize         = cpu_to_le16(512),
>> >> +};
>> >> +
>> >> +static struct usb_endpoint_descriptor hs_ep_out = {
>> >> +       .bLength                = USB_DT_ENDPOINT_SIZE,
>> >> +       .bDescriptorType        = USB_DT_ENDPOINT,
>> >> +       .bEndpointAddress       = USB_DIR_OUT,
>> >> +       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
>> >> +       .wMaxPacketSize         = cpu_to_le16(512),
>> >> +};
>> >> +
>> >> +static struct usb_interface_descriptor interface_desc = {
>> >> +       .bLength                = USB_DT_INTERFACE_SIZE,
>> >> +       .bDescriptorType        = USB_DT_INTERFACE,
>> >> +       .bInterfaceNumber       = 0x00,
>> >> +       .bAlternateSetting      = 0x00,
>> >> +       .bNumEndpoints          = 0x02,
>> >> +       .bInterfaceClass        = ROCKUSB_INTERFACE_CLASS,
>> >> +       .bInterfaceSubClass     = ROCKUSB_INTERFACE_SUB_CLASS,
>> >> +       .bInterfaceProtocol     = ROCKUSB_INTERFACE_PROTOCOL,
>> >> +};
>> >> +
>> >> +static struct usb_descriptor_header *rkusb_fs_function[] = {
>> >> +       (struct usb_descriptor_header *)&interface_desc,
>> >> +       (struct usb_descriptor_header *)&fs_ep_in,
>> >> +       (struct usb_descriptor_header *)&fs_ep_out,
>> >> +};
>> >> +
>> >> +static struct usb_descriptor_header *rkusb_hs_function[] = {
>> >> +       (struct usb_descriptor_header *)&interface_desc,
>> >> +       (struct usb_descriptor_header *)&hs_ep_in,
>> >> +       (struct usb_descriptor_header *)&hs_ep_out,
>> >> +       NULL,
>> >> +};
>> >> +
>> >> +static struct usb_endpoint_descriptor *
>> >> +rkusb_ep_desc(struct usb_gadget *g, struct
>> >> usb_endpoint_descriptor *fs,
>> >> +           struct usb_endpoint_descriptor *hs)
>> >> +{
>> >> +       if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
>> >> +               return hs;
>> >> +       return fs;
>> >> +}
>> >> +
>> >> +/*
>> >> + * static strings, in UTF-8
>> >> + */
>> >> +static const char rkusb_name[] = "Rockchip Rockusb";
>> >> +
>> >> +static struct usb_string rkusb_string_defs[] = {
>> >> +       [0].s = rkusb_name,
>> >> +       {  }                    /* end of list */
>> >> +};
>> >> +
>> >> +static struct usb_gadget_strings stringtab_rkusb = {
>> >> +       .language       = 0x0409,       /* en-us */
>> >> +       .strings        = rkusb_string_defs,
>> >> +};
>> >> +
>> >> +static struct usb_gadget_strings *rkusb_strings[] = {
>> >> +       &stringtab_rkusb,
>> >> +       NULL,
>> >> +};
>> >> +
>> >> +static void rx_handler_command(struct usb_ep *ep, struct
>> >> usb_request *req);
>> >> +static int rockusb_tx_write_csw(u32 Tag, int residue, u8 Status,
>> >> int size);
>> >> +
>> >> +static void rockusb_complete(struct usb_ep *ep, struct
>> >> usb_request *req) +{
>> >> +       int status = req->status;
>> >> +       if (!status)
>> >> +               return;
>> >> +       debug("status: %d ep '%s' trans: %d\n", status, ep->name,
>> >> req->actual);
>> >> +}
>> >> +
>> >> +static int rockusb_bind(struct usb_configuration *c, struct
>> >> usb_function *f)
>> >> +{
>> >> +       int id;
>> >> +       struct usb_gadget *gadget = c->cdev->gadget;
>> >> +       struct f_rockusb *f_rkusb = func_to_rockusb(f);
>> >> +       const char *s;
>> >> +
>> >> +       id = usb_interface_id(c, f);
>> >> +       if (id < 0)
>> >> +               return id;
>> >> +       interface_desc.bInterfaceNumber = id;
>> >> +
>> >> +       id = usb_string_id(c->cdev);
>> >> +       if (id < 0)
>> >> +               return id;
>> >> +
>> >> +       rkusb_string_defs[0].id = id;
>> >> +       interface_desc.iInterface = id;
>> >> +
>> >> +       f_rkusb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in);
>> >> +       if (!f_rkusb->in_ep)
>> >> +               return -ENODEV;
>> >> +       f_rkusb->in_ep->driver_data = c->cdev;
>> >> +
>> >> +       f_rkusb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out);
>> >> +       if (!f_rkusb->out_ep)
>> >> +               return -ENODEV;
>> >> +       f_rkusb->out_ep->driver_data = c->cdev;
>> >> +
>> >> +       f->descriptors = rkusb_fs_function;
>> >> +
>> >> +       if (gadget_is_dualspeed(gadget)) {
>> >> +               hs_ep_in.bEndpointAddress =
>> >> fs_ep_in.bEndpointAddress;
>> >> +               hs_ep_out.bEndpointAddress =
>> >> fs_ep_out.bEndpointAddress;
>> >> +               f->hs_descriptors = rkusb_hs_function;
>> >> +       }
>> >> +
>> >> +       s = getenv("serial#");
>> >> +       if (s)
>> >> +               g_dnl_set_serialnumber((char *)s);
>> >> +
>> >> +       return 0;
>> >> +}
>> >> +
>> >> +static void rockusb_unbind(struct usb_configuration *c, struct
>> >> usb_function *f)
>> >> +{
>> >> +       memset(rockusb_func, 0, sizeof(*rockusb_func));
>> >> +}
>> >> +
>> >> +static void rockusb_disable(struct usb_function *f)
>> >> +{
>> >> +       struct f_rockusb *f_rkusb = func_to_rockusb(f);
>> >> +
>> >> +       usb_ep_disable(f_rkusb->out_ep);
>> >> +       usb_ep_disable(f_rkusb->in_ep);
>> >> +
>> >> +       if (f_rkusb->out_req) {
>> >> +               free(f_rkusb->out_req->buf);
>> >> +               usb_ep_free_request(f_rkusb->out_ep,
>> >> f_rkusb->out_req);
>> >> +               f_rkusb->out_req = NULL;
>> >> +       }
>> >> +       if (f_rkusb->in_req) {
>> >> +               free(f_rkusb->in_req->buf);
>> >> +               usb_ep_free_request(f_rkusb->in_ep,
>> >> f_rkusb->in_req);
>> >> +               f_rkusb->in_req = NULL;
>> >> +       }
>> >> +}
>> >> +
>> >> +static struct usb_request *rockusb_start_ep(struct usb_ep *ep)
>> >> +{
>> >> +       struct usb_request *req;
>> >> +
>> >> +       req = usb_ep_alloc_request(ep, 0);
>> >> +       if (!req)
>> >> +               return NULL;
>> >> +
>> >> +       req->length = EP_BUFFER_SIZE;
>> >> +       req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
>> >> EP_BUFFER_SIZE);
>> >> +       if (!req->buf) {
>> >> +               usb_ep_free_request(ep, req);
>> >> +               return NULL;
>> >> +       }
>> >> +
>> >> +       memset(req->buf, 0, req->length);
>> >> +       return req;
>> >> +}
>> >> +
>> >> +static int rockusb_set_alt(struct usb_function *f,
>> >> +                           unsigned interface, unsigned alt)
>> >> +{
>> >> +       int ret;
>> >> +       struct usb_composite_dev *cdev = f->config->cdev;
>> >> +       struct usb_gadget *gadget = cdev->gadget;
>> >> +       struct f_rockusb *f_rkusb = func_to_rockusb(f);
>> >> +       const struct usb_endpoint_descriptor *d;
>> >> +
>> >> +       debug("%s: func: %s intf: %d alt: %d\n",
>> >> +             __func__, f->name, interface, alt);
>> >> +
>> >> +       d = rkusb_ep_desc(gadget, &fs_ep_out, &hs_ep_out);
>> >> +       ret = usb_ep_enable(f_rkusb->out_ep, d);
>> >> +       if (ret) {
>> >> +               puts("failed to enable out ep\n");
>> >> +               return ret;
>> >> +       }
>> >> +
>> >> +       f_rkusb->out_req = rockusb_start_ep(f_rkusb->out_ep);
>> >> +       if (!f_rkusb->out_req) {
>> >> +               puts("failed to alloc out req\n");
>> >> +               ret = -EINVAL;
>> >> +               goto err;
>> >> +       }
>> >> +       f_rkusb->out_req->complete = rx_handler_command;
>> >> +
>> >> +       d = rkusb_ep_desc(gadget, &fs_ep_in, &hs_ep_in);
>> >> +       ret = usb_ep_enable(f_rkusb->in_ep, d);
>> >> +       if (ret) {
>> >> +               puts("failed to enable in ep\n");
>> >> +               goto err;
>> >> +       }
>> >> +
>> >> +       f_rkusb->in_req = rockusb_start_ep(f_rkusb->in_ep);
>> >> +       if (!f_rkusb->in_req) {
>> >> +               puts("failed alloc req in\n");
>> >> +               ret = -EINVAL;
>> >> +               goto err;
>> >> +       }
>> >> +       f_rkusb->in_req->complete = rockusb_complete;
>> >> +
>> >> +       ret = usb_ep_queue(f_rkusb->out_ep, f_rkusb->out_req, 0);
>> >> +       if (ret)
>> >> +               goto err;
>> >> +
>> >> +       return 0;
>> >> +err:
>> >> +       rockusb_disable(f);
>> >> +       return ret;
>> >> +}
>> >> +
>> >> +static int rockusb_add(struct usb_configuration *c)
>> >> +{
>> >> +       struct f_rockusb *f_rkusb = rockusb_func;
>> >> +       int status;
>> >> +
>> >> +       debug("%s: cdev: 0x%p\n", __func__, c->cdev);
>> >> +
>> >> +       if (!f_rkusb) {
>> >> +               f_rkusb = memalign(CONFIG_SYS_CACHELINE_SIZE,
>> >> sizeof(*f_rkusb));
>> >> +               if (!f_rkusb)
>> >> +                       return -ENOMEM;
>> >> +
>> >> +               rockusb_func = f_rkusb;
>> >> +               memset(f_rkusb, 0, sizeof(*f_rkusb));
>> >> +       }
>> >> +
>> >> +       f_rkusb->usb_function.name = "f_rockusb";
>> >> +       f_rkusb->usb_function.bind = rockusb_bind;
>> >> +       f_rkusb->usb_function.unbind = rockusb_unbind;
>> >> +       f_rkusb->usb_function.set_alt = rockusb_set_alt;
>> >> +       f_rkusb->usb_function.disable = rockusb_disable;
>> >> +       f_rkusb->usb_function.strings = rkusb_strings;
>> >> +
>> >> +       status = usb_add_function(c, &f_rkusb->usb_function);
>> >> +       if (status) {
>> >> +               free(f_rkusb);
>> >> +               rockusb_func = f_rkusb;
>> >> +       }
>> >> +       return status;
>> >> +}
>> >> +
>> >> +char *rockusb_dev_type = 0;
>> >> +int rockusb_dev_index = 0;
>> >> +
>> >> +void rockusb_dev_init(char *dev_type, int dev_index)
>> >> +{
>> >> +       rockusb_dev_type = dev_type;
>> >> +       rockusb_dev_index = dev_index;
>> >> +}
>> >> +
>> >> +DECLARE_GADGET_BIND_CALLBACK(usb_dnl_rockusb, rockusb_add);
>> >> +
>> >> +static int rockusb_tx_write(const char *buffer, unsigned int
>> >> buffer_size) +{
>> >> +       struct usb_request *in_req = rockusb_func->in_req;
>> >> +       int ret;
>> >> +
>> >> +       memcpy(in_req->buf, buffer, buffer_size);
>> >> +       in_req->length = buffer_size;
>> >> +       usb_ep_dequeue(rockusb_func->in_ep, in_req);
>> >> +       ret = usb_ep_queue(rockusb_func->in_ep, in_req, 0);
>> >> +       if (ret)
>> >> +               printf("Error %d on queue\n", ret);
>> >> +       return 0;
>> >> +}
>> >> +
>> >> +static int rockusb_tx_write_str(const char *buffer)
>> >> +{
>> >> +       return rockusb_tx_write(buffer, strlen(buffer));
>> >> +}
>> >> +
>> >> +/* Bulk-only data structures */
>> >> +
>> >> +/* Command Block Wrapper */
>> >> +struct fsg_bulk_cb_wrap {
>> >> +       __le32  Signature;              /* Contains 'USBC' */
>> >> +       u32     Tag;                    /* Unique per command id */
>> >> +       __le32  DataTransferLength;     /* Size of the data */
>> >> +       u8      Flags;                  /* Direction in bit 7 */
>> >> +       u8      Lun;                    /* LUN (normally 0) */
>> >> +       u8      Length;                 /* Of the CDB, <=
>> >> MAX_COMMAND_SIZE */
>> >> +       u8      CDB[16];                /* Command Data Block */
>> >> +};
>> >> +
>> >> +#define USB_BULK_CB_WRAP_LEN   31
>> >> +#define USB_BULK_CB_SIG                0x43425355      /* Spells
>> >> out USBC */
>> >> +#define USB_BULK_IN_FLAG       0x80
>> >> +
>> >> +/* Command Status Wrapper */
>> >> +struct bulk_cs_wrap {
>> >> +       __le32  Signature;              /* Should = 'USBS' */
>> >> +       u32     Tag;                    /* Same as original
>> >> command */
>> >> +       __le32  Residue;                /* Amount not transferred
>> >> */
>> >> +       u8      Status;                 /* See below */
>> >> +};
>> >> +
>> >> +#define USB_BULK_CS_WRAP_LEN   13
>> >> +#define USB_BULK_CS_SIG                0x53425355      /* Spells
>> >> out 'USBS' */
>> >> +#define USB_STATUS_PASS                0
>> >> +#define USB_STATUS_FAIL                1
>> >> +#define USB_STATUS_PHASE_ERROR 2
>> >> +
>> >> +
>> >> +#define        CSW_GOOD                0x00
>> >> +#define        CSW_FAIL                0x01
>> >> +
>> >> +static void printcbw(char *buf)
>> >> +{
>> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> >> A_MINALIGN)));
>> >> +
>> >> +       memcpy((char*)&cbw, buf, USB_BULK_CB_WRAP_LEN);
>> >> +
>> >> +       debug("cbw: Signature:%x\n", cbw.Signature);
>> >> +       debug("cbw: Tag=%x\n", cbw.Tag);
>> >> +       debug("cbw: DataTransferLength=%d\n",
>> >> cbw.DataTransferLength);
>> >> +       debug("cbw: Flags=%x\n", cbw.Flags);
>> >> +       debug("cbw: Lun=%d\n", cbw.Lun);
>> >> +       debug("cbw: Length=%d\n", cbw.Length);
>> >> +       debug("cbw: ucOperCode=%x\n", cbw.CDB[0]);
>> >> +       debug("cbw: ucReserved=%x\n", cbw.CDB[1]);
>> >> +       debug("cbw: dwAddress:%x %x %x %x\n", cbw.CDB[5],
>> >> cbw.CDB[4],
>> >> +                                               cbw.CDB[3],
>> >> cbw.CDB[2]);
>> >> +       debug("cbw: ucReserved2=%x\n", cbw.CDB[6]);
>> >> +       debug("cbw: usLength:%x %x\n", cbw.CDB[8], cbw.CDB[7]);
>> >> +
>> >> +}
>> >> +
>> >> +static void printcsw(char *buf)
>> >> +{
>> >> +       struct bulk_cs_wrap csw __attribute__((aligned(ARCH_DM
>> >> A_MINALIGN)));
>> >> +
>> >> +       memcpy((char*)&csw, buf, USB_BULK_CS_WRAP_LEN);
>> >> +       debug("csw: Signature:%x\n", csw.Signature);
>> >> +       debug("csw: Tag:%x\n", csw.Tag);
>> >> +       debug("csw: Residue:%x\n", csw.Residue);
>> >> +       debug("csw: Status:%x\n", csw.Status);
>> >> +
>> >> +}
>> >> +
>> >> +static int rockusb_tx_write_csw(u32 Tag, int residue, u8 Status,
>> >> int size)
>> >> +{
>> >> +       struct bulk_cs_wrap csw __attribute__((aligned(ARCH_DM
>> >> A_MINALIGN)));
>> >> +       csw.Signature = cpu_to_le32(USB_BULK_CS_SIG);
>> >> +       csw.Tag = Tag;
>> >> +       csw.Residue = cpu_to_be32(residue);
>> >> +       csw.Status = Status;
>> >> +       printcsw((char*)&csw);
>> >> +       return rockusb_tx_write((char*)&csw, size);
>> >> +}
>> >> +
>> >> +int download_tag = 0;
>> >> +int download_lba = 0;
>> >> +static unsigned int download_size;
>> >> +static unsigned int download_bytes;
>> >> +struct blk_desc *download_desc = 0;
>> >> +
>> >> +static unsigned int rx_bytes_expected(struct usb_ep *ep)
>> >> +{
>> >> +       int rx_remain = download_size - download_bytes;
>> >> +       unsigned int rem;
>> >> +       unsigned int maxpacket = ep->maxpacket;
>> >> +
>> >> +       if (rx_remain <= 0)
>> >> +               return 0;
>> >> +       else if (rx_remain > EP_BUFFER_SIZE)
>> >> +               return EP_BUFFER_SIZE;
>> >> +
>> >> +       rem = rx_remain % maxpacket;
>> >> +       if (rem > 0)
>> >> +               rx_remain = rx_remain + (maxpacket - rem);
>> >> +
>> >> +       return rx_remain;
>> >> +}
>> >> +
>> >> +static void rx_handler_dl_image(struct usb_ep *ep, struct
>> >> usb_request *req)
>> >> +{
>> >> +       unsigned int transfer_size = download_size -
>> >> download_bytes;
>> >> +       const unsigned char *buffer = req->buf;
>> >> +       unsigned int buffer_size = req->actual;
>> >> +
>> >> +       if(!download_desc){
>> >> +               printf("rx_handler_dl_image blk_get_dev\n");
>> >> +               download_desc = blk_get_dev(rockusb_dev_type,
>> >> rockusb_dev_index);
>> >> +               if (!download_desc || download_desc->type ==
>> >> DEV_TYPE_UNKNOWN){
>> >> +                       error("invalid mmc device\n");
>> >> +                       rockusb_tx_write_csw(download_tag, 0,
>> >> CSW_FAIL,
>> >> +
>> >> USB_BULK_CS_WRAP_LEN);
>> >> +                       return;
>> >> +               }
>> >> +       }
>> >> +
>> >> +       if (req->status != 0) {
>> >> +               printf("Bad status: %d\n", req->status);
>> >> +               rockusb_tx_write_csw(download_tag, 0,
>> >> +                                       CSW_FAIL,
>> >> USB_BULK_CS_WRAP_LEN);
>> >> +               return;
>> >> +       }
>> >> +
>> >> +       if (buffer_size < transfer_size)
>> >> +               transfer_size = buffer_size;
>> >> +
>> >> +       memcpy((void *)CONFIG_FASTBOOT_BUF_ADDR + download_bytes,
>> >> +              buffer, transfer_size);
>> >> +       download_bytes += transfer_size;
>> >> +
>> >> +       /* Check if transfer is done */
>> >> +       if (download_bytes >= download_size) {
>> >> +               int blks = 0, blkcnt = download_size/512;
>> >> +               printf("download %d bytes finished, start writing
>> >> to lba %x\n",
>> >> +                                download_bytes, download_lba);
>> >> +               blks = blk_dwrite(download_desc, download_lba,
>> >> blkcnt,
>> >> +
>> >> (char*)CONFIG_FASTBOOT_BUF_ADDR);
>> >> +               if (blks != blkcnt) {
>> >> +                       error("failed writing to device %s: %d\n",
>> >> +                               rockusb_dev_type,
>> >> rockusb_dev_index);
>> >> +                       rockusb_tx_write_csw(download_tag, 0,
>> >> +                                               CSW_FAIL,
>> >> USB_BULK_CS_WRAP_LEN);
>> >> +                       return;
>> >> +               }
>> >> +
>> >> +               req->complete = rx_handler_command;
>> >> +               req->length = EP_BUFFER_SIZE;
>> >> +               download_size = 0;
>> >> +               printf("done\n");
>> >> +               rockusb_tx_write_csw(download_tag, 0, CSW_GOOD,
>> >> +                                       USB_BULK_CS_WRAP_LEN);
>> >> +       } else {
>> >> +               req->length = rx_bytes_expected(ep);
>> >> +       }
>> >> +
>> >> +       req->actual = 0;
>> >> +       usb_ep_queue(ep, req, 0);
>> >> +}
>> >> +
>> >> +static void cb_test_unit_ready(struct usb_ep *ep, struct
>> >> usb_request *req)
>> >> +{
>> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> >> A_MINALIGN)));
>> >> +
>> >> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
>> >> +
>> >> +       rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength,
>> >> +                               CSW_GOOD, USB_BULK_CS_WRAP_LEN);
>> >> +
>> >> +}
>> >> +
>> >> +static void cb_read_storage_id(struct usb_ep *ep, struct
>> >> usb_request *req)
>> >> +{
>> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> >> A_MINALIGN)));
>> >> +       char emmc_id[] = "EMMC ";
>> >> +
>> >> +       printf("cb_read_storage_id\n");
>> >> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
>> >> +       rockusb_tx_write_str(emmc_id);//only support emmc now
>> >> +       rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength,
>> >> CSW_GOOD,
>> >> +                               USB_BULK_CS_WRAP_LEN);
>> >> +}
>> >> +
>> >> +static void cb_write_lba(struct usb_ep *ep, struct usb_request
>> >> *req) +{
>> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> >> A_MINALIGN)));
>> >> +       int sector_count;
>> >> +
>> >> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
>> >> +       sector_count = (int)get_unaligned_be16(&cbw.CDB[7]);
>> >> +       download_lba = get_unaligned_be32(&cbw.CDB[2]);
>> >> +       download_size = sector_count * 512;
>> >> +       download_bytes = 0;
>> >> +       download_tag = cbw.Tag;
>> >> +       if ((0 == download_size) || (download_size>CONFIG_FASTBOOT
>> >> _BUF_SIZE)){
>> >> +               rockusb_tx_write_csw(cbw.Tag,
>> >> cbw.DataTransferLength,
>> >> +                                       CSW_FAIL,
>> >> USB_BULK_CS_WRAP_LEN);
>> >> +       } else {
>> >> +               req->complete = rx_handler_dl_image;
>> >> +               req->length = rx_bytes_expected(ep);
>> >> +       }
>> >> +}
>> >> +
>> >> +static int reboot_flag;
>> >> +
>> >> +int __weak rkusb_set_reboot_flag(int flag)
>> >> +{
>> >> +       printf("rkusb_set_reboot_flag: %d\n", reboot_flag);
>> >> +       return -ENOSYS;
>> >> +}
>> >> +
>> >> +static void compl_do_reset(struct usb_ep *ep, struct usb_request
>> >> *req) +{
>> >> +       rkusb_set_reboot_flag(reboot_flag);
>> >> +       do_reset(NULL, 0, 0, NULL);
>> >> +}
>> >> +
>> >> +static void cb_reboot(struct usb_ep *ep, struct usb_request *req)
>> >> +{
>> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> >> A_MINALIGN)));
>> >> +       reboot_flag = 0;
>> >> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
>> >> +       reboot_flag = cbw.CDB[1];
>> >> +       rockusb_func->in_req->complete = compl_do_reset;
>> >> +       rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength,
>> >> CSW_GOOD,
>> >> +                               USB_BULK_CS_WRAP_LEN);
>> >> +}
>> >> +
>> >> +static void cb_not_support(struct usb_ep *ep, struct usb_request
>> >> *req) +{
>> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> >> A_MINALIGN)));
>> >> +
>> >> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
>> >> +       printf("Rockusb command %x not support yet\n", cbw.CDB[0]);
>> >> +       rockusb_tx_write_csw(cbw.Tag, 0, CSW_FAIL,
>> >> USB_BULK_CS_WRAP_LEN); +}
>> >> +
>> >> +#define RKUSB_STATUS_IDLE                      0
>> >> +#define RKUSB_STATUS_CMD                       1
>> >> +#define RKUSB_STATUS_RXDATA                    2
>> >> +#define RKUSB_STATUS_TXDATA                    3
>> >> +#define RKUSB_STATUS_CSW                       4
>> >> +#define RKUSB_STATUS_RXDATA_PREPARE            5
>> >> +#define RKUSB_STATUS_TXDATA_PREPARE            6
>> >> +
>> >> +typedef enum {
>> >> +               TEST_UNIT_READY = 0,
>> >> +               READ_FLASH_ID = 0x01,
>> >> +               TEST_BAD_BLOCK = 0x03,
>> >> +               READ_SECTOR = 0x04,
>> >> +               WRITE_SECTOR = 0x05,
>> >> +               ERASE_NORMAL = 0x06,
>> >> +               ERASE_FORCE = 0x0B,
>> >> +               READ_LBA = 0x14,
>> >> +               WRITE_LBA = 0x15,
>> >> +               ERASE_SYSTEMDISK = 0x16,
>> >> +               READ_SDRAM = 0x17,
>> >> +               WRITE_SDRAM = 0x18,
>> >> +               EXECUTE_SDRAM = 0x19,
>> >> +               READ_FLASH_INFO = 0x1A,
>> >> +               READ_CHIP_INFO = 0x1B,
>> >> +               SET_RESET_FLAG = 0x1E,
>> >> +               WRITE_EFUSE = 0x1F,
>> >> +               READ_EFUSE = 0x20,
>> >> +               READ_SPI_FLASH = 0x21,
>> >> +               WRITE_SPI_FLASH = 0x22,
>> >> +               WRITE_NEW_EFUSE = 0x23,
>> >> +               READ_NEW_EFUSE = 0x24,
>> >> +               DEVICE_RESET = 0xFF
>> >> +} USB_OPERATION_CODE;
>> >> +
>> >> +#define        K_FW_TEST_UNIT_READY    0x00
>> >> +#define        K_FW_READ_FLASH_ID              0x01
>> >> +#define        K_FW_SET_DEVICE_ID              0x02
>> >> +#define        K_FW_TEST_BAD_BLOCK             0x03
>> >> +#define        K_FW_READ_10                    0x04
>> >> +#define        K_FW_WRITE_10                   0x05
>> >> +#define        K_FW_ERASE_10                   0x06
>> >> +#define        K_FW_WRITE_SPARE                0x07
>> >> +#define        K_FW_READ_SPARE                 0x08
>> >> +
>> >> +#define        K_FW_ERASE_10_FORCE             0x0b
>> >> +#define        K_FW_GET_VERSION                0x0c
>> >> +
>> >> +#define        K_FW_LBA_READ_10                0x14
>> >> +#define        K_FW_LBA_WRITE_10               0x15
>> >> +#define        K_FW_ERASE_SYS_DISK             0x16
>> >> +#define        K_FW_SDRAM_READ_10              0x17
>> >> +#define        K_FW_SDRAM_WRITE_10             0x18
>> >> +#define        K_FW_SDRAM_EXECUTE              0x19
>> >> +#define        K_FW_READ_FLASH_INFO            0x1A
>> >> +#define        K_FW_GET_CHIP_VER               0x1B
>> >> +#define        K_FW_LOW_FORMAT                 0x1C
>> >> +#define        K_FW_SET_RESET_FLAG             0x1E
>> >> +#define        K_FW_SPI_READ_10                0x21
>> >> +#define        K_FW_SPI_WRITE_10               0x22
>> >> +
>> >> +#define        K_FW_SESSION                    0X30
>> >> +#define        K_FW_RESET                      0xff
>> >> +
>> >> +#define CBW_DIRECTION_OUT              0x00
>> >> +#define CBW_DIRECTION_IN               0x80
>> >> +
>> >> +struct cmd_dispatch_info {
>> >> +       int cmd;
>> >> +       void (*cb)(struct usb_ep *ep, struct usb_request *req);
>> >> +};
>> >> +
>> >> +static const struct cmd_dispatch_info cmd_dispatch_info[] = {
>> >> +       {
>> >> +               .cmd = K_FW_TEST_UNIT_READY,
>> >> +               .cb = cb_test_unit_ready,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_READ_FLASH_ID,
>> >> +               .cb = cb_read_storage_id,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_SET_DEVICE_ID,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_TEST_BAD_BLOCK,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_READ_10,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_WRITE_10,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_ERASE_10,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_WRITE_SPARE,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_READ_SPARE,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_ERASE_10_FORCE,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_GET_VERSION,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_LBA_READ_10,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_LBA_WRITE_10,
>> >> +               .cb = cb_write_lba,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_ERASE_SYS_DISK,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_SDRAM_READ_10,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_SDRAM_WRITE_10,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_SDRAM_EXECUTE,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_READ_FLASH_INFO,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_GET_CHIP_VER,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_LOW_FORMAT,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_SET_RESET_FLAG,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_SPI_READ_10,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_SPI_WRITE_10,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_SESSION,
>> >> +               .cb = cb_not_support,
>> >> +       },
>> >> +       {
>> >> +               .cmd = K_FW_RESET,
>> >> +               .cb = cb_reboot,
>> >> +       },
>> >> +};
>> >> +
>> >> +
>> >> +
>> >> +static void rx_handler_command(struct usb_ep *ep, struct
>> >> usb_request *req)
>> >> +{
>> >> +       void (*func_cb)(struct usb_ep *ep, struct usb_request
>> >> *req) = NULL;
>> >> +       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
>> >> A_MINALIGN)));
>> >> +       int i;
>> >> +       char *cmdbuf = req->buf;
>> >> +
>> >> +       if (req->status != 0 || req->length == 0)
>> >> +               return;
>> >> +
>> >> +       memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
>> >> +       printcbw(req->buf);
>> >> +
>> >> +       for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) {
>> >> +               if (cmd_dispatch_info[i].cmd == cbw.CDB[0]) {
>> >> +                       func_cb = cmd_dispatch_info[i].cb;
>> >> +                       break;
>> >> +               }
>> >> +       }
>> >> +
>> >> +       if (!func_cb) {
>> >> +               error("unknown command: %s", (char*)req->buf);
>> >> +               rockusb_tx_write_str("FAILunknown command");
>> >> +       } else {
>> >> +               if (req->actual < req->length) {
>> >> +                       u8 *buf = (u8 *)req->buf;
>> >> +                       buf[req->actual] = 0;
>> >> +                       func_cb(ep, req);
>> >> +               } else {
>> >> +                       error("buffer overflow");
>> >> +                       rockusb_tx_write_str("FAILbuffer
>> >> overflow");
>> >> +               }
>> >> +       }
>> >> +
>> >> +       *cmdbuf = '\0';
>> >> +       req->actual = 0;
>> >> +       usb_ep_queue(ep, req, 0);
>> >> +}
>> >>
>> >
>> >
>> >
>
>
>
>
> Best regards,
>
> Lukasz Majewski
>
> --
>
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> 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

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

* [U-Boot] [U-Boot 1/3] drivers: usb: gadget: add the rockusb gadget
  2017-03-15  7:56 ` [U-Boot] [U-Boot 1/3] drivers: usb: gadget: add the rockusb gadget Eddie Cai
  2017-03-16  7:05   ` Kever Yang
@ 2017-04-20 10:04   ` Lukasz Majewski
  1 sibling, 0 replies; 36+ messages in thread
From: Lukasz Majewski @ 2017-04-20 10:04 UTC (permalink / raw)
  To: u-boot

Hi Eddie,

> this patch implement fastboot protocol on the device side. this is
> based on USB download gadget infrastructure. the rockusb function
> implements the rd, wl, rid commands. it can work with rkdeveloptool;
> https://github.com/rockchip-linux/rkdeveloptool
> 
> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> ---
>  drivers/usb/gadget/Makefile    |   1 +
>  drivers/usb/gadget/f_rockusb.c | 801
> +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 802
> insertions(+) create mode 100644 drivers/usb/gadget/f_rockusb.c
> 
> diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
> index 0fbbb7c..0eb27a3 100644
> --- a/drivers/usb/gadget/Makefile
> +++ b/drivers/usb/gadget/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
>  obj-$(CONFIG_USB_FUNCTION_DFU) += f_dfu.o
>  obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
>  obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
> +obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o
>  endif
>  endif
>  ifdef CONFIG_USB_ETHER
> diff --git a/drivers/usb/gadget/f_rockusb.c
> b/drivers/usb/gadget/f_rockusb.c new file mode 100644
> index 0000000..a67cb35
> --- /dev/null
> +++ b/drivers/usb/gadget/f_rockusb.c
> @@ -0,0 +1,801 @@
> +/*
> + * (C) Copyright 2017
> + *
> + * Eddie Cai <eddie.cai.linux@gmail.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <config.h>
> +#include <common.h>
> +#include <errno.h>
> +#include <malloc.h>
> +#include <linux/usb/ch9.h>
> +#include <linux/usb/gadget.h>
> +#include <linux/usb/composite.h>
> +#include <linux/compiler.h>
> +#include <version.h>
> +#include <g_dnl.h>
> +
> +#define ROCKUSB_VERSION		"0.1"
> +
> +#define ROCKUSB_INTERFACE_CLASS	0xff
> +#define ROCKUSB_INTERFACE_SUB_CLASS	0x06
> +#define ROCKUSB_INTERFACE_PROTOCOL	0x05
> +
> +#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0  (0x0200)
> +#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1  (0x0040)
> +#define TX_ENDPOINT_MAXIMUM_PACKET_SIZE      (0x0040)
> +
> +#define EP_BUFFER_SIZE			4096
> +/*
> + * EP_BUFFER_SIZE must always be an integral multiple of maxpacket
> size
> + * (64 or 512 or 1024), else we break on certain controllers like
> DWC3
> + * that expect bulk OUT requests to be divisible by maxpacket size.
> + */
> +

Maybe you could put those defines to f_rockchip.h file (which would be
local to the f_rockchip.c)?

It could store defines and structs local to the rockchip protocol.

> +struct f_rockusb {
> +	struct usb_function usb_function;
> +
> +	/* IN/OUT EP's and corresponding requests */
> +	struct usb_ep *in_ep, *out_ep;
> +	struct usb_request *in_req, *out_req;
> +};
> +
> +static inline struct f_rockusb *func_to_rockusb(struct usb_function
> *f) +{
> +	return container_of(f, struct f_rockusb, usb_function);
> +}
> +
> +static struct f_rockusb *rockusb_func;
> +
> +static struct usb_endpoint_descriptor fs_ep_in = {
> +	.bLength            = USB_DT_ENDPOINT_SIZE,
> +	.bDescriptorType    = USB_DT_ENDPOINT,
> +	.bEndpointAddress   = USB_DIR_IN,
> +	.bmAttributes       = USB_ENDPOINT_XFER_BULK,
> +	.wMaxPacketSize     = cpu_to_le16(64),
> +};
> +
> +static struct usb_endpoint_descriptor fs_ep_out = {
> +	.bLength		= USB_DT_ENDPOINT_SIZE,
> +	.bDescriptorType	= USB_DT_ENDPOINT,
> +	.bEndpointAddress	= USB_DIR_OUT,
> +	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
> +	.wMaxPacketSize		= cpu_to_le16(64),
> +};
> +
> +static struct usb_endpoint_descriptor hs_ep_in = {
> +	.bLength		= USB_DT_ENDPOINT_SIZE,
> +	.bDescriptorType	= USB_DT_ENDPOINT,
> +	.bEndpointAddress	= USB_DIR_IN,
> +	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
> +	.wMaxPacketSize		= cpu_to_le16(512),
> +};
> +
> +static struct usb_endpoint_descriptor hs_ep_out = {
> +	.bLength		= USB_DT_ENDPOINT_SIZE,
> +	.bDescriptorType	= USB_DT_ENDPOINT,
> +	.bEndpointAddress	= USB_DIR_OUT,
> +	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
> +	.wMaxPacketSize		= cpu_to_le16(512),
> +};
> +
> +static struct usb_interface_descriptor interface_desc = {
> +	.bLength		= USB_DT_INTERFACE_SIZE,
> +	.bDescriptorType	= USB_DT_INTERFACE,
> +	.bInterfaceNumber	= 0x00,
> +	.bAlternateSetting	= 0x00,
> +	.bNumEndpoints		= 0x02,
> +	.bInterfaceClass	= ROCKUSB_INTERFACE_CLASS,
> +	.bInterfaceSubClass	= ROCKUSB_INTERFACE_SUB_CLASS,
> +	.bInterfaceProtocol	= ROCKUSB_INTERFACE_PROTOCOL,
> +};
> +
> +static struct usb_descriptor_header *rkusb_fs_function[] = {
> +	(struct usb_descriptor_header *)&interface_desc,
> +	(struct usb_descriptor_header *)&fs_ep_in,
> +	(struct usb_descriptor_header *)&fs_ep_out,
> +};
> +
> +static struct usb_descriptor_header *rkusb_hs_function[] = {
> +	(struct usb_descriptor_header *)&interface_desc,
> +	(struct usb_descriptor_header *)&hs_ep_in,
> +	(struct usb_descriptor_header *)&hs_ep_out,
> +	NULL,
> +};
> +
> +static struct usb_endpoint_descriptor *
> +rkusb_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor
> *fs,
> +	    struct usb_endpoint_descriptor *hs)
> +{
> +	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
> +		return hs;
> +	return fs;
> +}
> +
> +/*
> + * static strings, in UTF-8
> + */
> +static const char rkusb_name[] = "Rockchip Rockusb";
> +
> +static struct usb_string rkusb_string_defs[] = {
> +	[0].s = rkusb_name,
> +	{  }			/* end of list */
> +};
> +
> +static struct usb_gadget_strings stringtab_rkusb = {
> +	.language	= 0x0409,	/* en-us */
> +	.strings	= rkusb_string_defs,
> +};
> +
> +static struct usb_gadget_strings *rkusb_strings[] = {
> +	&stringtab_rkusb,
> +	NULL,
> +};
> +
> +static void rx_handler_command(struct usb_ep *ep, struct usb_request
> *req); +static int rockusb_tx_write_csw(u32 Tag, int residue, u8
> Status, int size); +
> +static void rockusb_complete(struct usb_ep *ep, struct usb_request
> *req) +{
> +	int status = req->status;
> +	if (!status)
> +		return;
> +	debug("status: %d ep '%s' trans: %d\n", status, ep->name,
> req->actual); +}
> +
> +static int rockusb_bind(struct usb_configuration *c, struct
> usb_function *f) +{
> +	int id;
> +	struct usb_gadget *gadget = c->cdev->gadget;
> +	struct f_rockusb *f_rkusb = func_to_rockusb(f);
> +	const char *s;
> +
> +	id = usb_interface_id(c, f);
> +	if (id < 0)
> +		return id;
> +	interface_desc.bInterfaceNumber = id;
> +
> +	id = usb_string_id(c->cdev);
> +	if (id < 0)
> +		return id;
> +
> +	rkusb_string_defs[0].id = id;
> +	interface_desc.iInterface = id;
> +
> +	f_rkusb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in);
> +	if (!f_rkusb->in_ep)
> +		return -ENODEV;
> +	f_rkusb->in_ep->driver_data = c->cdev;
> +
> +	f_rkusb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out);
> +	if (!f_rkusb->out_ep)
> +		return -ENODEV;
> +	f_rkusb->out_ep->driver_data = c->cdev;
> +
> +	f->descriptors = rkusb_fs_function;
> +
> +	if (gadget_is_dualspeed(gadget)) {
> +		hs_ep_in.bEndpointAddress =
> fs_ep_in.bEndpointAddress;
> +		hs_ep_out.bEndpointAddress =
> fs_ep_out.bEndpointAddress;
> +		f->hs_descriptors = rkusb_hs_function;
> +	}
> +
> +	s = getenv("serial#");
> +	if (s)
> +		g_dnl_set_serialnumber((char *)s);
> +
> +	return 0;
> +}
> +
> +static void rockusb_unbind(struct usb_configuration *c, struct
> usb_function *f) +{
> +	memset(rockusb_func, 0, sizeof(*rockusb_func));
> +}
> +
> +static void rockusb_disable(struct usb_function *f)
> +{
> +	struct f_rockusb *f_rkusb = func_to_rockusb(f);
> +
> +	usb_ep_disable(f_rkusb->out_ep);
> +	usb_ep_disable(f_rkusb->in_ep);
> +
> +	if (f_rkusb->out_req) {
> +		free(f_rkusb->out_req->buf);
> +		usb_ep_free_request(f_rkusb->out_ep,
> f_rkusb->out_req);
> +		f_rkusb->out_req = NULL;
> +	}
> +	if (f_rkusb->in_req) {
> +		free(f_rkusb->in_req->buf);
> +		usb_ep_free_request(f_rkusb->in_ep, f_rkusb->in_req);
> +		f_rkusb->in_req = NULL;
> +	}
> +}
> +
> +static struct usb_request *rockusb_start_ep(struct usb_ep *ep)
> +{
> +	struct usb_request *req;
> +
> +	req = usb_ep_alloc_request(ep, 0);
> +	if (!req)
> +		return NULL;
> +
> +	req->length = EP_BUFFER_SIZE;
> +	req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
> EP_BUFFER_SIZE);
> +	if (!req->buf) {
> +		usb_ep_free_request(ep, req);
> +		return NULL;
> +	}
> +
> +	memset(req->buf, 0, req->length);
> +	return req;
> +}
> +
> +static int rockusb_set_alt(struct usb_function *f,
> +			    unsigned interface, unsigned alt)
> +{
> +	int ret;
> +	struct usb_composite_dev *cdev = f->config->cdev;
> +	struct usb_gadget *gadget = cdev->gadget;
> +	struct f_rockusb *f_rkusb = func_to_rockusb(f);
> +	const struct usb_endpoint_descriptor *d;
> +
> +	debug("%s: func: %s intf: %d alt: %d\n",
> +	      __func__, f->name, interface, alt);
> +
> +	d = rkusb_ep_desc(gadget, &fs_ep_out, &hs_ep_out);
> +	ret = usb_ep_enable(f_rkusb->out_ep, d);
> +	if (ret) {
> +		puts("failed to enable out ep\n");
> +		return ret;
> +	}
> +
> +	f_rkusb->out_req = rockusb_start_ep(f_rkusb->out_ep);
> +	if (!f_rkusb->out_req) {
> +		puts("failed to alloc out req\n");
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +	f_rkusb->out_req->complete = rx_handler_command;
> +
> +	d = rkusb_ep_desc(gadget, &fs_ep_in, &hs_ep_in);
> +	ret = usb_ep_enable(f_rkusb->in_ep, d);
> +	if (ret) {
> +		puts("failed to enable in ep\n");
> +		goto err;
> +	}
> +
> +	f_rkusb->in_req = rockusb_start_ep(f_rkusb->in_ep);
> +	if (!f_rkusb->in_req) {
> +		puts("failed alloc req in\n");
> +		ret = -EINVAL;
> +		goto err;
> +	}
> +	f_rkusb->in_req->complete = rockusb_complete;
> +
> +	ret = usb_ep_queue(f_rkusb->out_ep, f_rkusb->out_req, 0);
> +	if (ret)
> +		goto err;
> +
> +	return 0;
> +err:
> +	rockusb_disable(f);
> +	return ret;
> +}
> +
> +static int rockusb_add(struct usb_configuration *c)
> +{
> +	struct f_rockusb *f_rkusb = rockusb_func;
> +	int status;
> +
> +	debug("%s: cdev: 0x%p\n", __func__, c->cdev);
> +
> +	if (!f_rkusb) {
> +		f_rkusb = memalign(CONFIG_SYS_CACHELINE_SIZE,
> sizeof(*f_rkusb));
> +		if (!f_rkusb)
> +			return -ENOMEM;
> +
> +		rockusb_func = f_rkusb;
> +		memset(f_rkusb, 0, sizeof(*f_rkusb));
> +	}
> +
> +	f_rkusb->usb_function.name = "f_rockusb";
> +	f_rkusb->usb_function.bind = rockusb_bind;
> +	f_rkusb->usb_function.unbind = rockusb_unbind;
> +	f_rkusb->usb_function.set_alt = rockusb_set_alt;
> +	f_rkusb->usb_function.disable = rockusb_disable;
> +	f_rkusb->usb_function.strings = rkusb_strings;
> +
> +	status = usb_add_function(c, &f_rkusb->usb_function);
> +	if (status) {
> +		free(f_rkusb);
> +		rockusb_func = f_rkusb;
> +	}
> +	return status;
> +}
> +
> +char *rockusb_dev_type = 0;
> +int rockusb_dev_index = 0;
> +
> +void rockusb_dev_init(char *dev_type, int dev_index)
> +{
> +	rockusb_dev_type = dev_type;
> +	rockusb_dev_index = dev_index;
> +}
> +
> +DECLARE_GADGET_BIND_CALLBACK(usb_dnl_rockusb, rockusb_add);
> +
> +static int rockusb_tx_write(const char *buffer, unsigned int
> buffer_size) +{
> +	struct usb_request *in_req = rockusb_func->in_req;
> +	int ret;
> +
> +	memcpy(in_req->buf, buffer, buffer_size);
> +	in_req->length = buffer_size;
> +	usb_ep_dequeue(rockusb_func->in_ep, in_req);
> +	ret = usb_ep_queue(rockusb_func->in_ep, in_req, 0);
> +	if (ret)
> +		printf("Error %d on queue\n", ret);
> +	return 0;
> +}
> +
> +static int rockusb_tx_write_str(const char *buffer)
> +{
> +	return rockusb_tx_write(buffer, strlen(buffer));
> +}
> +
> +/* Bulk-only data structures */
> +
> +/* Command Block Wrapper */
> +struct fsg_bulk_cb_wrap {
> +	__le32	Signature;		/* Contains 'USBC' */
> +	u32	Tag;			/* Unique per command
> id */
> +	__le32	DataTransferLength;	/* Size of the data
> */
> +	u8	Flags;			/* Direction in bit
> 7 */
> +	u8	Lun;			/* LUN (normally 0) */
> +	u8	Length;			/* Of the CDB, <=
> MAX_COMMAND_SIZE */
> +	u8	CDB[16];		/* Command Data Block */
> +};
> +
> +#define USB_BULK_CB_WRAP_LEN	31
> +#define USB_BULK_CB_SIG		0x43425355	/* Spells
> out USBC */ +#define USB_BULK_IN_FLAG	0x80
> +
> +/* Command Status Wrapper */
> +struct bulk_cs_wrap {
> +	__le32	Signature;		/* Should = 'USBS' */
> +	u32	Tag;			/* Same as original
> command */
> +	__le32	Residue;		/* Amount not
> transferred */
> +	u8	Status;			/* See below */
> +};
> +
> +#define USB_BULK_CS_WRAP_LEN	13
> +#define USB_BULK_CS_SIG		0x53425355	/* Spells
> out 'USBS' */ +#define USB_STATUS_PASS		0
> +#define USB_STATUS_FAIL		1
> +#define USB_STATUS_PHASE_ERROR	2
> +
> +
> +#define	CSW_GOOD		0x00
> +#define	CSW_FAIL		0x01
> +
> +static void printcbw(char *buf)
> +{
> +	struct fsg_bulk_cb_wrap cbw
> __attribute__((aligned(ARCH_DMA_MINALIGN))); +
> +	memcpy((char*)&cbw, buf, USB_BULK_CB_WRAP_LEN);
> +
> +	debug("cbw: Signature:%x\n", cbw.Signature);
> +	debug("cbw: Tag=%x\n", cbw.Tag);
> +	debug("cbw: DataTransferLength=%d\n",
> cbw.DataTransferLength);
> +	debug("cbw: Flags=%x\n", cbw.Flags);
> +	debug("cbw: Lun=%d\n", cbw.Lun);
> +	debug("cbw: Length=%d\n", cbw.Length);
> +	debug("cbw: ucOperCode=%x\n", cbw.CDB[0]);
> +	debug("cbw: ucReserved=%x\n", cbw.CDB[1]);
> +	debug("cbw: dwAddress:%x %x %x %x\n", cbw.CDB[5],
> cbw.CDB[4], 
> +						cbw.CDB[3],
> cbw.CDB[2]);
> +	debug("cbw: ucReserved2=%x\n", cbw.CDB[6]);
> +	debug("cbw: usLength:%x %x\n", cbw.CDB[8], cbw.CDB[7]);
> +
> +}
> +
> +static void printcsw(char *buf)
> +{
> +	struct bulk_cs_wrap csw
> __attribute__((aligned(ARCH_DMA_MINALIGN))); +
> +	memcpy((char*)&csw, buf, USB_BULK_CS_WRAP_LEN);
> +	debug("csw: Signature:%x\n", csw.Signature);
> +	debug("csw: Tag:%x\n", csw.Tag);
> +	debug("csw: Residue:%x\n", csw.Residue);
> +	debug("csw: Status:%x\n", csw.Status);
> +
> +}

Those debug functions should go to f_rockchip.h file and should be
guarded with #ifdef DEBUG

> +
> +static int rockusb_tx_write_csw(u32 Tag, int residue, u8 Status, int
> size) +{
> +	struct bulk_cs_wrap csw
> __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +	csw.Signature = cpu_to_le32(USB_BULK_CS_SIG);
> +	csw.Tag = Tag;
> +	csw.Residue = cpu_to_be32(residue);
> +	csw.Status = Status;
> +	printcsw((char*)&csw);
> +	return rockusb_tx_write((char*)&csw, size);
> +}
> +
> +int download_tag = 0;
> +int download_lba = 0;
> +static unsigned int download_size;
> +static unsigned int download_bytes;
> +struct blk_desc *download_desc = 0;
				
			This pointer is allocated in BSS, so should
			be cleared (NULL'ed).

> +
> +static unsigned int rx_bytes_expected(struct usb_ep *ep)
> +{
> +	int rx_remain = download_size - download_bytes;
> +	unsigned int rem;
> +	unsigned int maxpacket = ep->maxpacket;
> +
> +	if (rx_remain <= 0)
> +		return 0;
> +	else if (rx_remain > EP_BUFFER_SIZE)
> +		return EP_BUFFER_SIZE;
> +
> +	rem = rx_remain % maxpacket;
> +	if (rem > 0)
> +		rx_remain = rx_remain + (maxpacket - rem);
> +
> +	return rx_remain;
> +}
> +
> +static void rx_handler_dl_image(struct usb_ep *ep, struct
> usb_request *req) +{
> +	unsigned int transfer_size = download_size - download_bytes;
> +	const unsigned char *buffer = req->buf;
> +	unsigned int buffer_size = req->actual;
> +
> +	if(!download_desc){
> +		printf("rx_handler_dl_image blk_get_dev\n");
> +		download_desc = blk_get_dev(rockusb_dev_type,
> rockusb_dev_index);
> +		if (!download_desc || download_desc->type ==
> DEV_TYPE_UNKNOWN){
> +			error("invalid mmc device\n");
> +			rockusb_tx_write_csw(download_tag, 0,
> CSW_FAIL,
> +
> USB_BULK_CS_WRAP_LEN);
> +			return;
> +		}
> +	}
> +
> +	if (req->status != 0) {
> +		printf("Bad status: %d\n", req->status);
> +		rockusb_tx_write_csw(download_tag, 0, 
> +					CSW_FAIL,
> USB_BULK_CS_WRAP_LEN);
> +		return;
> +	}
> +
> +	if (buffer_size < transfer_size)
> +		transfer_size = buffer_size;
> +
> +	memcpy((void *)CONFIG_FASTBOOT_BUF_ADDR + download_bytes,
		       
		       Here we should have different name for
		       CONFIG_*_BUF_ADDR
		       - e.g. CONFIG_ROCKCHIP_BUF_ADDR, which should be
		         defined in Kconfig as well (with some default
		         value).

> +	       buffer, transfer_size);
> +	download_bytes += transfer_size;
> +
> +	/* Check if transfer is done */
> +	if (download_bytes >= download_size) {
> +		int blks = 0, blkcnt = download_size/512;
> +		printf("download %d bytes finished, start writing to
> lba %x\n",
> +				 download_bytes, download_lba);
> +		blks = blk_dwrite(download_desc, download_lba,
> blkcnt, 
> +
> (char*)CONFIG_FASTBOOT_BUF_ADDR);
> +		if (blks != blkcnt) {
> +			error("failed writing to device %s: %d\n", 
> +				rockusb_dev_type, rockusb_dev_index);
> +			rockusb_tx_write_csw(download_tag, 0, 
> +						CSW_FAIL,
> USB_BULK_CS_WRAP_LEN);
> +			return;
> +		}
> +
> +		req->complete = rx_handler_command;
> +		req->length = EP_BUFFER_SIZE;
> +		download_size = 0;
> +		printf("done\n");
> +		rockusb_tx_write_csw(download_tag, 0, CSW_GOOD, 
> +					USB_BULK_CS_WRAP_LEN);
> +	} else {
> +		req->length = rx_bytes_expected(ep);
> +	}
> +
> +	req->actual = 0;
> +	usb_ep_queue(ep, req, 0);
> +}
> +
> +static void cb_test_unit_ready(struct usb_ep *ep, struct usb_request
> *req) +{
> +	struct fsg_bulk_cb_wrap cbw
> __attribute__((aligned(ARCH_DMA_MINALIGN))); +
> +	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);

	You can use ALLOC_CACHE_ALIGN_BUFFER() to define cache safe
	struct inside the function.
	
	Please fix it globally.

For global cache safe allocations you can use DEFINE_CACHE_ALIGN_BUFFER
(more info at ./include/memalign.h)

> +
> +	rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength, 
> +				CSW_GOOD, USB_BULK_CS_WRAP_LEN);
> +
> +}
> +
> +static void cb_read_storage_id(struct usb_ep *ep, struct usb_request
> *req) +{
> +	struct fsg_bulk_cb_wrap cbw
> __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +	char emmc_id[] = "EMMC ";
> +
> +	printf("cb_read_storage_id\n");
> +	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> +	rockusb_tx_write_str(emmc_id);//only support emmc now
> +	rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength,
> CSW_GOOD, 
> +				USB_BULK_CS_WRAP_LEN);
> +}
> +
> +static void cb_write_lba(struct usb_ep *ep, struct usb_request *req)
> +{
> +	struct fsg_bulk_cb_wrap cbw
> __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +	int sector_count;
> +
> +	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> +	sector_count = (int)get_unaligned_be16(&cbw.CDB[7]);
> +	download_lba = get_unaligned_be32(&cbw.CDB[2]);
> +	download_size = sector_count * 512;
> +	download_bytes = 0;
> +	download_tag = cbw.Tag;
> +	if ((0 == download_size) ||
> (download_size>CONFIG_FASTBOOT_BUF_SIZE)){
> +		rockusb_tx_write_csw(cbw.Tag,
> cbw.DataTransferLength, 
> +					CSW_FAIL,
> USB_BULK_CS_WRAP_LEN);
> +	} else {
> +		req->complete = rx_handler_dl_image;
> +		req->length = rx_bytes_expected(ep);
> +	}
> +}
> +
> +static int reboot_flag;
> +
> +int __weak rkusb_set_reboot_flag(int flag)
> +{
> +	printf("rkusb_set_reboot_flag: %d\n", reboot_flag);
> +	return -ENOSYS;
> +}
> +
> +static void compl_do_reset(struct usb_ep *ep, struct usb_request
> *req) +{
> +	rkusb_set_reboot_flag(reboot_flag);
> +	do_reset(NULL, 0, 0, NULL);
> +}
> +
> +static void cb_reboot(struct usb_ep *ep, struct usb_request *req)
> +{
> +	struct fsg_bulk_cb_wrap cbw
> __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +	reboot_flag = 0;
> +	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> +	reboot_flag = cbw.CDB[1];
> +	rockusb_func->in_req->complete = compl_do_reset;
> +	rockusb_tx_write_csw(cbw.Tag, cbw.DataTransferLength,
> CSW_GOOD, 
> +				USB_BULK_CS_WRAP_LEN);
> +}
> +
> +static void cb_not_support(struct usb_ep *ep, struct usb_request
> *req) +{
> +	struct fsg_bulk_cb_wrap cbw
> __attribute__((aligned(ARCH_DMA_MINALIGN))); +
> +	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> +	printf("Rockusb command %x not support yet\n", cbw.CDB[0]);
> +	rockusb_tx_write_csw(cbw.Tag, 0, CSW_FAIL,
> USB_BULK_CS_WRAP_LEN); +}
> +

------------------------>8--------------------------

> +#define RKUSB_STATUS_IDLE 			0
> +#define RKUSB_STATUS_CMD  			1
> +#define RKUSB_STATUS_RXDATA 			2
> +#define RKUSB_STATUS_TXDATA 			3
> +#define RKUSB_STATUS_CSW 			4
> +#define RKUSB_STATUS_RXDATA_PREPARE 		5
> +#define RKUSB_STATUS_TXDATA_PREPARE 		6
> +
> +typedef enum {
> +		TEST_UNIT_READY = 0,
> +		READ_FLASH_ID = 0x01,
> +		TEST_BAD_BLOCK = 0x03,
> +		READ_SECTOR = 0x04,
> +		WRITE_SECTOR = 0x05,
> +		ERASE_NORMAL = 0x06,
> +		ERASE_FORCE = 0x0B,
> +		READ_LBA = 0x14,
> +		WRITE_LBA = 0x15,
> +		ERASE_SYSTEMDISK = 0x16,
> +		READ_SDRAM = 0x17,
> +		WRITE_SDRAM = 0x18,
> +		EXECUTE_SDRAM = 0x19,
> +		READ_FLASH_INFO = 0x1A,
> +		READ_CHIP_INFO = 0x1B,
> +		SET_RESET_FLAG = 0x1E,
> +		WRITE_EFUSE = 0x1F,
> +		READ_EFUSE = 0x20,
> +		READ_SPI_FLASH = 0x21,
> +		WRITE_SPI_FLASH = 0x22,
> +		WRITE_NEW_EFUSE = 0x23,
> +		READ_NEW_EFUSE = 0x24,
> +		DEVICE_RESET = 0xFF
> +} USB_OPERATION_CODE;
> +
> +#define	K_FW_TEST_UNIT_READY	0x00
> +#define	K_FW_READ_FLASH_ID		0x01
> +#define	K_FW_SET_DEVICE_ID		0x02
> +#define	K_FW_TEST_BAD_BLOCK		0x03
> +#define	K_FW_READ_10			0x04
> +#define	K_FW_WRITE_10			0x05
> +#define	K_FW_ERASE_10			0x06
> +#define	K_FW_WRITE_SPARE		0x07
> +#define	K_FW_READ_SPARE			0x08
> +
> +#define	K_FW_ERASE_10_FORCE		0x0b
> +#define	K_FW_GET_VERSION		0x0c
> +
> +#define	K_FW_LBA_READ_10		0x14
> +#define	K_FW_LBA_WRITE_10		0x15
> +#define	K_FW_ERASE_SYS_DISK		0x16
> +#define	K_FW_SDRAM_READ_10		0x17
> +#define	K_FW_SDRAM_WRITE_10		0x18
> +#define	K_FW_SDRAM_EXECUTE		0x19
> +#define	K_FW_READ_FLASH_INFO		0x1A
> +#define	K_FW_GET_CHIP_VER		0x1B
> +#define	K_FW_LOW_FORMAT			0x1C
> +#define	K_FW_SET_RESET_FLAG		0x1E
> +#define	K_FW_SPI_READ_10		0x21
> +#define	K_FW_SPI_WRITE_10		0x22
> +
> +#define	K_FW_SESSION			0X30
> +#define	K_FW_RESET			0xff
> +
> +#define CBW_DIRECTION_OUT		0x00
> +#define CBW_DIRECTION_IN		0x80
> +
> +struct cmd_dispatch_info {
> +	int cmd;
> +	void (*cb)(struct usb_ep *ep, struct usb_request *req);
> +};

----------------------8<---------------------------------------

This should go to f_rockchip.h file

> +
> +static const struct cmd_dispatch_info cmd_dispatch_info[] = {
> +	{
> +		.cmd = K_FW_TEST_UNIT_READY,
> +		.cb = cb_test_unit_ready,
> +	},
> +	{
> +		.cmd = K_FW_READ_FLASH_ID,
> +		.cb = cb_read_storage_id,
> +	},
> +	{
> +		.cmd = K_FW_SET_DEVICE_ID,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_TEST_BAD_BLOCK,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_READ_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_WRITE_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_ERASE_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_WRITE_SPARE,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_READ_SPARE,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_ERASE_10_FORCE,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_GET_VERSION,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_LBA_READ_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_LBA_WRITE_10,
> +		.cb = cb_write_lba,
> +	},
> +	{
> +		.cmd = K_FW_ERASE_SYS_DISK,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SDRAM_READ_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SDRAM_WRITE_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SDRAM_EXECUTE,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_READ_FLASH_INFO,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_GET_CHIP_VER,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_LOW_FORMAT,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SET_RESET_FLAG,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SPI_READ_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SPI_WRITE_10,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_SESSION,
> +		.cb = cb_not_support,
> +	},
> +	{
> +		.cmd = K_FW_RESET,
> +		.cb = cb_reboot,
> +	},
> +};
> +
> +
> +
> +static void rx_handler_command(struct usb_ep *ep, struct usb_request
> *req) +{
> +	void (*func_cb)(struct usb_ep *ep, struct usb_request *req)
> = NULL;
> +	struct fsg_bulk_cb_wrap cbw
> __attribute__((aligned(ARCH_DMA_MINALIGN)));
> +	int i;
> +	char *cmdbuf = req->buf;
> +
> +	if (req->status != 0 || req->length == 0)
	    ^^^^^^^^^^^
			req->status is enough

> +		return;
> +
> +	memcpy((char*)&cbw, req->buf, USB_BULK_CB_WRAP_LEN);
> +	printcbw(req->buf);
> +
> +	for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) {
> +		if (cmd_dispatch_info[i].cmd == cbw.CDB[0]) {
> +			func_cb = cmd_dispatch_info[i].cb;
> +			break;
> +		}
> +	}
> +
> +	if (!func_cb) {
> +		error("unknown command: %s", (char*)req->buf);
> +		rockusb_tx_write_str("FAILunknown command");
> +	} else {
> +		if (req->actual < req->length) {
> +			u8 *buf = (u8 *)req->buf;
> +			buf[req->actual] = 0;
> +			func_cb(ep, req);
> +		} else {
> +			error("buffer overflow");
> +			rockusb_tx_write_str("FAILbuffer overflow");
> +		}
> +	}
> +
> +	*cmdbuf = '\0';
> +	req->actual = 0;
> +	usb_ep_queue(ep, req, 0);
> +}

Despite few minor comments - this is what I've expected. 

Please add changelog when pasting your patches.

Also using patman (./tools/patman) could facilitate posting patches.


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
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

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

* [U-Boot] [U-Boot 2/3] cmd: add rockusb command
  2017-03-15  7:56 ` [U-Boot] [U-Boot 2/3] cmd: add rockusb command Eddie Cai
  2017-03-20  2:29   ` Simon Glass
@ 2017-04-20 10:11   ` Lukasz Majewski
  1 sibling, 0 replies; 36+ messages in thread
From: Lukasz Majewski @ 2017-04-20 10:11 UTC (permalink / raw)
  To: u-boot

Hi Eddie,

> this patch add rockusb command. the usage is
> 	rockusb <USB_controller> [<devtype>] <devnum>
> e.g. rockusb 0 mmc 0
> 
> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> ---
>  cmd/Kconfig       | 12 +++++++++
>  cmd/Makefile      |  1 +
>  cmd/rockusb.c     | 79
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> include/rockusb.h | 13 +++++++++ 4 files changed, 105 insertions(+)
>  create mode 100644 cmd/rockusb.c
>  create mode 100644 include/rockusb.h
> 
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index ef53156..dac2cc0 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -475,6 +475,18 @@ config CMD_DFU
>  	  Enables the command "dfu" which is used to have U-Boot
> create a DFU class device via USB.
>  
> +config CMD_ROCKUSB
> +        bool "rockusb"
> +        select USB_FUNCTION_ROCKUSB
> +        help
> +          Enables the command "rockusb" which is used to have U-Boot
> create a
> +          Rockusb class device via USB.
> +
> +config USB_FUNCTION_ROCKUSB
> +        bool "Enable USB rockusb gadget"
> +        help
> +          This enables the USB part of the rockusb gadget.
> +
>  config CMD_USB_MASS_STORAGE
>  	bool "UMS usb mass storage"
>  	help
> diff --git a/cmd/Makefile b/cmd/Makefile
> index f13bb8c..f5f1663 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -141,6 +141,7 @@ endif
>  
>  obj-$(CONFIG_CMD_USB) += usb.o disk.o
>  obj-$(CONFIG_CMD_FASTBOOT) += fastboot.o
> +obj-$(CONFIG_CMD_ROCKUSB) += rockusb.o
>  obj-$(CONFIG_CMD_FS_UUID) += fs_uuid.o
>  
>  obj-$(CONFIG_CMD_USB_MASS_STORAGE) += usb_mass_storage.o
> diff --git a/cmd/rockusb.c b/cmd/rockusb.c
> new file mode 100644
> index 0000000..f5bd86e
> --- /dev/null
> +++ b/cmd/rockusb.c
> @@ -0,0 +1,79 @@
> +/*
> + * Copyright (C) 2017 Eddie Cai <eddie.cai.linux@gmail.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <console.h>
> +#include <g_dnl.h>
> +#include <usb.h>
> +#include <rockusb.h>
> +
> +

Please remove the extra blank here. (also run your patches
through ./scripts/checkpatch.pl before submission.

> +static int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char
> *const argv[]) +{
> +	int controller_index, dev_index;
> +	char *usb_controller;
> +	char *devtype;
> +	char *devnum;
> +	int ret;
> +
> +	if (argc < 2)
> +		return CMD_RET_USAGE;
> +
> +	usb_controller = argv[1];
> +	controller_index = simple_strtoul(usb_controller, NULL, 0);
> +
> +	if (argc >= 4) {
> +		devtype = argv[2];
> +		devnum  = argv[3];
> +	} else {
> +		devtype = "mmc";
> +		devnum  = argv[2];
> +	}

I would prefer to force the whole command syntax support:

"rockchip 0 mmc 0" to comply with other commands (like thor, dfu).

Instead of "rockchip 0 0" and imply the mmc.


> +	dev_index = simple_strtoul(devnum, NULL, 0);
> +	rockusb_dev_init(devtype, dev_index);
> +
> +	ret = board_usb_init(controller_index, USB_INIT_DEVICE);
> +	if (ret) {
> +		error("USB init failed: %d", ret);
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	g_dnl_clear_detach();
> +	ret = g_dnl_register("usb_dnl_rockusb");
> +	if (ret)
> +		return ret;
> +	printf("do_rockusb1\n");
	^^^^^^^^^^^^^^^^^^^^^^^^ this should be either removed or
	rewritten as "debug(...)".

> +	if (!g_dnl_board_usb_cable_connected()) {
> +		puts("\rUSB cable not detected.\n" \
> +		     "Command exit.\n");
> +		ret = CMD_RET_FAILURE;
> +		goto exit;
> +	}
> +
> +	while (1) {
> +		if (g_dnl_detach())
> +			break;
> +		if (ctrlc())
> +			break;
> +		usb_gadget_handle_interrupts(controller_index);
> +	}
> +	printf("do_rockusb2\n");
> +	ret = CMD_RET_SUCCESS;
> +
> +exit:
> +	g_dnl_unregister();
> +	g_dnl_clear_detach();
> +	board_usb_cleanup(controller_index, USB_INIT_DEVICE);
> +
> +	return ret;
> +}
> +
> +U_BOOT_CMD(rockusb, 4, 1, do_rockusb,
> +	"Use the ROCKUSB",
> +	"rockusb <USB_controller> [<devtype>] <devnum>  e.g. rockusb
> 0 mmc 0\n"
> +	"    devtype defaults to mmc"

	[<devtype>] should be mandatory.

> +);
> diff --git a/include/rockusb.h b/include/rockusb.h
> new file mode 100644
> index 0000000..cdea63d
> --- /dev/null
> +++ b/include/rockusb.h
> @@ -0,0 +1,13 @@
> +/*
> + * (C) Copyright 2017
> + *
> + * Eddie Cai <eddie.cai.linux@gmail.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +#ifndef _ROCKUSB_H_
> +#define _ROCKUSB_H_
> +
> +void rockusb_dev_init(char *dev_type, int dev_index);
> +
> +#endif /* _ROCKUSB_H_ */




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
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

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

* [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device
  2017-03-15  7:56 ` [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device Eddie Cai
  2017-03-20  2:30   ` Simon Glass
@ 2017-04-20 10:12   ` Lukasz Majewski
  1 sibling, 0 replies; 36+ messages in thread
From: Lukasz Majewski @ 2017-04-20 10:12 UTC (permalink / raw)
  To: u-boot

Hi Eddie,

> this patch enable rockusb support on rk3288 based device.
> 
> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> ---
>  include/configs/rk3288_common.h | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/include/configs/rk3288_common.h
> b/include/configs/rk3288_common.h index b5606d4..b19a34d 100644
> --- a/include/configs/rk3288_common.h
> +++ b/include/configs/rk3288_common.h
> @@ -74,6 +74,10 @@
>  #define CONFIG_FASTBOOT_BUF_ADDR	CONFIG_SYS_LOAD_ADDR
>  #define CONFIG_FASTBOOT_BUF_SIZE	0x08000000
>  
> +/* rockusb  */
> +#define CONFIG_CMD_ROCKUSB
> +#define CONFIG_USB_FUNCTION_ROCKUSB
> +
>  /* usb mass storage */
>  #define CONFIG_USB_FUNCTION_MASS_STORAGE
>  #define CONFIG_CMD_USB_MASS_STORAGE

Reviewed-by: Lukasz Majewski <lukma@denx.de>


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
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

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

* [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device
  2017-03-20  2:30   ` Simon Glass
  2017-03-20  8:16     ` Eddie Cai
@ 2017-05-02 10:37     ` Eddie Cai
  2017-05-03 10:09       ` Simon Glass
  1 sibling, 1 reply; 36+ messages in thread
From: Eddie Cai @ 2017-05-02 10:37 UTC (permalink / raw)
  To: u-boot

Hi Simon
2017-03-20 10:30 GMT+08:00 Simon Glass <sjg@chromium.org>:
> Hi Eddie.
>
> On 15 March 2017 at 01:56, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
>> this patch enable rockusb support on rk3288 based device.
>>
>> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
>> ---
>>  include/configs/rk3288_common.h | 4 ++++
>>  1 file changed, 4 insertions(+)
>
> I think this should be done in Kconfig.
since rockusb used so widely on rockchip soc based devices. every
rockchip soc based
device should support it. So I would like to put it in rk3288_common.h
or even rockchip-common.h.
what do you think?
>
>>
>> diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
>> index b5606d4..b19a34d 100644
>> --- a/include/configs/rk3288_common.h
>> +++ b/include/configs/rk3288_common.h
>> @@ -74,6 +74,10 @@
>>  #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
>>  #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
>>
>> +/* rockusb  */
>> +#define CONFIG_CMD_ROCKUSB
>> +#define CONFIG_USB_FUNCTION_ROCKUSB
>> +
>>  /* usb mass storage */
>>  #define CONFIG_USB_FUNCTION_MASS_STORAGE
>>  #define CONFIG_CMD_USB_MASS_STORAGE
>> --
>> 2.7.4
>>
>
> Regards,
> Simon

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

* [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device
  2017-05-02 10:37     ` Eddie Cai
@ 2017-05-03 10:09       ` Simon Glass
  2017-05-04  7:17         ` Eddie Cai
  0 siblings, 1 reply; 36+ messages in thread
From: Simon Glass @ 2017-05-03 10:09 UTC (permalink / raw)
  To: u-boot

Hi Eddie,

On 2 May 2017 at 04:37, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
> Hi Simon
> 2017-03-20 10:30 GMT+08:00 Simon Glass <sjg@chromium.org>:
>> Hi Eddie.
>>
>> On 15 March 2017 at 01:56, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
>>> this patch enable rockusb support on rk3288 based device.
>>>
>>> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
>>> ---
>>>  include/configs/rk3288_common.h | 4 ++++
>>>  1 file changed, 4 insertions(+)
>>
>> I think this should be done in Kconfig.
> since rockusb used so widely on rockchip soc based devices. every
> rockchip soc based
> device should support it. So I would like to put it in rk3288_common.h
> or even rockchip-common.h.
> what do you think?

We are moving to removing the board config headers so cannot add new
non-Kconfig CONFIG options.

You can add it to arch/arm/Kconfig - e.g. with 'imply CONFIG_....'
under 'config ARCH_ROCKCHIP'.

Please help to remove any options you can from the headers.

>>
>>>
>>> diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
>>> index b5606d4..b19a34d 100644
>>> --- a/include/configs/rk3288_common.h
>>> +++ b/include/configs/rk3288_common.h
>>> @@ -74,6 +74,10 @@
>>>  #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
>>>  #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
>>>
>>> +/* rockusb  */
>>> +#define CONFIG_CMD_ROCKUSB
>>> +#define CONFIG_USB_FUNCTION_ROCKUSB
>>> +
>>>  /* usb mass storage */
>>>  #define CONFIG_USB_FUNCTION_MASS_STORAGE
>>>  #define CONFIG_CMD_USB_MASS_STORAGE
>>> --
>>> 2.7.4

Regards,
Simon

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

* [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device
  2017-05-03 10:09       ` Simon Glass
@ 2017-05-04  7:17         ` Eddie Cai
  2017-05-04  9:19           ` Lukasz Majewski
  0 siblings, 1 reply; 36+ messages in thread
From: Eddie Cai @ 2017-05-04  7:17 UTC (permalink / raw)
  To: u-boot

Hi Simon

2017-05-03 18:09 GMT+08:00 Simon Glass <sjg@chromium.org>:
> Hi Eddie,
>
> On 2 May 2017 at 04:37, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
>> Hi Simon
>> 2017-03-20 10:30 GMT+08:00 Simon Glass <sjg@chromium.org>:
>>> Hi Eddie.
>>>
>>> On 15 March 2017 at 01:56, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
>>>> this patch enable rockusb support on rk3288 based device.
>>>>
>>>> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
>>>> ---
>>>>  include/configs/rk3288_common.h | 4 ++++
>>>>  1 file changed, 4 insertions(+)
>>>
>>> I think this should be done in Kconfig.
>> since rockusb used so widely on rockchip soc based devices. every
>> rockchip soc based
>> device should support it. So I would like to put it in rk3288_common.h
>> or even rockchip-common.h.
>> what do you think?
>
> We are moving to removing the board config headers so cannot add new
> non-Kconfig CONFIG options.
>
> You can add it to arch/arm/Kconfig - e.g. with 'imply CONFIG_....'
> under 'config ARCH_ROCKCHIP'.
USB_FUNCTION_ROCKUSB depend on USB_GADGET, USB_GADGET_DOWNLOAD,
CONFIG_G_DNL_VENDOR_NUM, CONFIG_G_DNL_PRODUCT_NUM
should i move those config to arch/arm/Kconfig? how to define
CONFIG_G_DNL_VENDOR_NUM
and CONFIG_G_DNL_PRODUCT_NUM when select it?
>
> Please help to remove any options you can from the headers.
>
>>>
>>>>
>>>> diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
>>>> index b5606d4..b19a34d 100644
>>>> --- a/include/configs/rk3288_common.h
>>>> +++ b/include/configs/rk3288_common.h
>>>> @@ -74,6 +74,10 @@
>>>>  #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
>>>>  #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
>>>>
>>>> +/* rockusb  */
>>>> +#define CONFIG_CMD_ROCKUSB
>>>> +#define CONFIG_USB_FUNCTION_ROCKUSB
>>>> +
>>>>  /* usb mass storage */
>>>>  #define CONFIG_USB_FUNCTION_MASS_STORAGE
>>>>  #define CONFIG_CMD_USB_MASS_STORAGE
>>>> --
>>>> 2.7.4
>
> Regards,
> Simon

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

* [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device
  2017-05-04  7:17         ` Eddie Cai
@ 2017-05-04  9:19           ` Lukasz Majewski
  2017-05-04 16:49             ` Simon Glass
  0 siblings, 1 reply; 36+ messages in thread
From: Lukasz Majewski @ 2017-05-04  9:19 UTC (permalink / raw)
  To: u-boot

Hi Eddie, Simon,

> Hi Simon
> 
> 2017-05-03 18:09 GMT+08:00 Simon Glass <sjg@chromium.org>:
> > Hi Eddie,
> >
> > On 2 May 2017 at 04:37, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
> >> Hi Simon
> >> 2017-03-20 10:30 GMT+08:00 Simon Glass <sjg@chromium.org>:
> >>> Hi Eddie.
> >>>
> >>> On 15 March 2017 at 01:56, Eddie Cai <eddie.cai.linux@gmail.com>
> >>> wrote:
> >>>> this patch enable rockusb support on rk3288 based device.
> >>>>
> >>>> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
> >>>> ---
> >>>>  include/configs/rk3288_common.h | 4 ++++
> >>>>  1 file changed, 4 insertions(+)
> >>>
> >>> I think this should be done in Kconfig.
> >> since rockusb used so widely on rockchip soc based devices. every
> >> rockchip soc based
> >> device should support it. So I would like to put it in
> >> rk3288_common.h or even rockchip-common.h.
> >> what do you think?
> >
> > We are moving to removing the board config headers so cannot add new
> > non-Kconfig CONFIG options.
> >
> > You can add it to arch/arm/Kconfig - e.g. with 'imply CONFIG_....'
> > under 'config ARCH_ROCKCHIP'.
> USB_FUNCTION_ROCKUSB depend on USB_GADGET, USB_GADGET_DOWNLOAD,
> CONFIG_G_DNL_VENDOR_NUM, CONFIG_G_DNL_PRODUCT_NUM
> should i move those config to arch/arm/Kconfig? how to define
> CONFIG_G_DNL_VENDOR_NUM
> and CONFIG_G_DNL_PRODUCT_NUM when select it?

I would prefer to keep those CONFIG options as they are now (and are in
sync with other gadgets).

The problem here is that the gadget infrastructure is a bit
"problematic" from the device model point of view.

It has his own "structure" borrowed from Linux kernel.

I've poked around and it seems like adding it to DM requires calling
"g_dnl_register()" with embedded name of the gadget (like
"usb_dnl_dfu").

And such call is required for each different gadget (like mass storage,
dfu, fastboot).

Or maybe we should add "stub" DM support to only indicate supported
gadgets (like dfu, ums, etc) and leave as much code untouched as
possible?

> >
> > Please help to remove any options you can from the headers.
> >
> >>>
> >>>>
> >>>> diff --git a/include/configs/rk3288_common.h
> >>>> b/include/configs/rk3288_common.h index b5606d4..b19a34d 100644
> >>>> --- a/include/configs/rk3288_common.h
> >>>> +++ b/include/configs/rk3288_common.h
> >>>> @@ -74,6 +74,10 @@
> >>>>  #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
> >>>>  #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
> >>>>
> >>>> +/* rockusb  */
> >>>> +#define CONFIG_CMD_ROCKUSB
> >>>> +#define CONFIG_USB_FUNCTION_ROCKUSB
> >>>> +
> >>>>  /* usb mass storage */
> >>>>  #define CONFIG_USB_FUNCTION_MASS_STORAGE
> >>>>  #define CONFIG_CMD_USB_MASS_STORAGE
> >>>> --
> >>>> 2.7.4
> >
> > Regards,
> > Simon




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
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

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

* [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device
  2017-05-04  9:19           ` Lukasz Majewski
@ 2017-05-04 16:49             ` Simon Glass
  2017-05-05  1:15               ` Eddie Cai
  0 siblings, 1 reply; 36+ messages in thread
From: Simon Glass @ 2017-05-04 16:49 UTC (permalink / raw)
  To: u-boot

Hi,

On 4 May 2017 at 03:19, Lukasz Majewski <lukma@denx.de> wrote:
> Hi Eddie, Simon,
>
>> Hi Simon
>>
>> 2017-05-03 18:09 GMT+08:00 Simon Glass <sjg@chromium.org>:
>> > Hi Eddie,
>> >
>> > On 2 May 2017 at 04:37, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
>> >> Hi Simon
>> >> 2017-03-20 10:30 GMT+08:00 Simon Glass <sjg@chromium.org>:
>> >>> Hi Eddie.
>> >>>
>> >>> On 15 March 2017 at 01:56, Eddie Cai <eddie.cai.linux@gmail.com>
>> >>> wrote:
>> >>>> this patch enable rockusb support on rk3288 based device.
>> >>>>
>> >>>> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
>> >>>> ---
>> >>>>  include/configs/rk3288_common.h | 4 ++++
>> >>>>  1 file changed, 4 insertions(+)
>> >>>
>> >>> I think this should be done in Kconfig.
>> >> since rockusb used so widely on rockchip soc based devices. every
>> >> rockchip soc based
>> >> device should support it. So I would like to put it in
>> >> rk3288_common.h or even rockchip-common.h.
>> >> what do you think?
>> >
>> > We are moving to removing the board config headers so cannot add new
>> > non-Kconfig CONFIG options.
>> >
>> > You can add it to arch/arm/Kconfig - e.g. with 'imply CONFIG_....'
>> > under 'config ARCH_ROCKCHIP'.
>> USB_FUNCTION_ROCKUSB depend on USB_GADGET, USB_GADGET_DOWNLOAD,
>> CONFIG_G_DNL_VENDOR_NUM, CONFIG_G_DNL_PRODUCT_NUM
>> should i move those config to arch/arm/Kconfig? how to define
>> CONFIG_G_DNL_VENDOR_NUM
>> and CONFIG_G_DNL_PRODUCT_NUM when select it?
>
> I would prefer to keep those CONFIG options as they are now (and are in
> sync with other gadgets).

These two are new though right?

CONFIG_CMD_ROCKUSB
CONFIG_USB_FUNCTION_ROCKUSB

So they should be added to Kconfig. If they 'depend' on non-Kconfig
options, that's fine IMO. We can't express that until the other
options are converted.

Let's convert them soon!

>
> The problem here is that the gadget infrastructure is a bit
> "problematic" from the device model point of view.
>
> It has his own "structure" borrowed from Linux kernel.
>
> I've poked around and it seems like adding it to DM requires calling
> "g_dnl_register()" with embedded name of the gadget (like
> "usb_dnl_dfu").
>
> And such call is required for each different gadget (like mass storage,
> dfu, fastboot).
>
> Or maybe we should add "stub" DM support to only indicate supported
> gadgets (like dfu, ums, etc) and leave as much code untouched as
> possible?

I'm sure this can be resolved in some way. I admit I have not looked
at it but was thinking of attacking usb_tty sometime, so perhaps might
see if I can figure it out.

>
>> >
>> > Please help to remove any options you can from the headers.
>> >
>> >>>
>> >>>>
>> >>>> diff --git a/include/configs/rk3288_common.h
>> >>>> b/include/configs/rk3288_common.h index b5606d4..b19a34d 100644
>> >>>> --- a/include/configs/rk3288_common.h
>> >>>> +++ b/include/configs/rk3288_common.h
>> >>>> @@ -74,6 +74,10 @@
>> >>>>  #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
>> >>>>  #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
>> >>>>
>> >>>> +/* rockusb  */
>> >>>> +#define CONFIG_CMD_ROCKUSB
>> >>>> +#define CONFIG_USB_FUNCTION_ROCKUSB
>> >>>> +
>> >>>>  /* usb mass storage */
>> >>>>  #define CONFIG_USB_FUNCTION_MASS_STORAGE
>> >>>>  #define CONFIG_CMD_USB_MASS_STORAGE
>> >>>> --
>> >>>> 2.7.4
>> >
>> > Regards,
>> > Simon

Regards,
Simon

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

* [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device
  2017-05-04 16:49             ` Simon Glass
@ 2017-05-05  1:15               ` Eddie Cai
  2017-05-14  9:32                 ` Simon Glass
  0 siblings, 1 reply; 36+ messages in thread
From: Eddie Cai @ 2017-05-05  1:15 UTC (permalink / raw)
  To: u-boot

2017-05-05 0:49 GMT+08:00 Simon Glass <sjg@chromium.org>:
> Hi,
>
> On 4 May 2017 at 03:19, Lukasz Majewski <lukma@denx.de> wrote:
>> Hi Eddie, Simon,
>>
>>> Hi Simon
>>>
>>> 2017-05-03 18:09 GMT+08:00 Simon Glass <sjg@chromium.org>:
>>> > Hi Eddie,
>>> >
>>> > On 2 May 2017 at 04:37, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
>>> >> Hi Simon
>>> >> 2017-03-20 10:30 GMT+08:00 Simon Glass <sjg@chromium.org>:
>>> >>> Hi Eddie.
>>> >>>
>>> >>> On 15 March 2017 at 01:56, Eddie Cai <eddie.cai.linux@gmail.com>
>>> >>> wrote:
>>> >>>> this patch enable rockusb support on rk3288 based device.
>>> >>>>
>>> >>>> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
>>> >>>> ---
>>> >>>>  include/configs/rk3288_common.h | 4 ++++
>>> >>>>  1 file changed, 4 insertions(+)
>>> >>>
>>> >>> I think this should be done in Kconfig.
>>> >> since rockusb used so widely on rockchip soc based devices. every
>>> >> rockchip soc based
>>> >> device should support it. So I would like to put it in
>>> >> rk3288_common.h or even rockchip-common.h.
>>> >> what do you think?
>>> >
>>> > We are moving to removing the board config headers so cannot add new
>>> > non-Kconfig CONFIG options.
>>> >
>>> > You can add it to arch/arm/Kconfig - e.g. with 'imply CONFIG_....'
>>> > under 'config ARCH_ROCKCHIP'.
>>> USB_FUNCTION_ROCKUSB depend on USB_GADGET, USB_GADGET_DOWNLOAD,
>>> CONFIG_G_DNL_VENDOR_NUM, CONFIG_G_DNL_PRODUCT_NUM
>>> should i move those config to arch/arm/Kconfig? how to define
>>> CONFIG_G_DNL_VENDOR_NUM
>>> and CONFIG_G_DNL_PRODUCT_NUM when select it?
>>
>> I would prefer to keep those CONFIG options as they are now (and are in
>> sync with other gadgets).
>
> These two are new though right?
>
> CONFIG_CMD_ROCKUSB
> CONFIG_USB_FUNCTION_ROCKUSB
>
> So they should be added to Kconfig. If they 'depend' on non-Kconfig
> options, that's fine IMO. We can't express that until the other
> options are converted.
>
> Let's convert them soon!
Does it means i can keep it in rk3288_common.h?
>
>>
>> The problem here is that the gadget infrastructure is a bit
>> "problematic" from the device model point of view.
>>
>> It has his own "structure" borrowed from Linux kernel.
>>
>> I've poked around and it seems like adding it to DM requires calling
>> "g_dnl_register()" with embedded name of the gadget (like
>> "usb_dnl_dfu").
>>
>> And such call is required for each different gadget (like mass storage,
>> dfu, fastboot).
>>
>> Or maybe we should add "stub" DM support to only indicate supported
>> gadgets (like dfu, ums, etc) and leave as much code untouched as
>> possible?
>
> I'm sure this can be resolved in some way. I admit I have not looked
> at it but was thinking of attacking usb_tty sometime, so perhaps might
> see if I can figure it out.
>
>>
>>> >
>>> > Please help to remove any options you can from the headers.
>>> >
>>> >>>
>>> >>>>
>>> >>>> diff --git a/include/configs/rk3288_common.h
>>> >>>> b/include/configs/rk3288_common.h index b5606d4..b19a34d 100644
>>> >>>> --- a/include/configs/rk3288_common.h
>>> >>>> +++ b/include/configs/rk3288_common.h
>>> >>>> @@ -74,6 +74,10 @@
>>> >>>>  #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
>>> >>>>  #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
>>> >>>>
>>> >>>> +/* rockusb  */
>>> >>>> +#define CONFIG_CMD_ROCKUSB
>>> >>>> +#define CONFIG_USB_FUNCTION_ROCKUSB
>>> >>>> +
>>> >>>>  /* usb mass storage */
>>> >>>>  #define CONFIG_USB_FUNCTION_MASS_STORAGE
>>> >>>>  #define CONFIG_CMD_USB_MASS_STORAGE
>>> >>>> --
>>> >>>> 2.7.4
>>> >
>>> > Regards,
>>> > Simon
>
> Regards,
> Simon

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

* [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device
  2017-05-05  1:15               ` Eddie Cai
@ 2017-05-14  9:32                 ` Simon Glass
  2017-05-14 21:49                   ` Lukasz Majewski
  0 siblings, 1 reply; 36+ messages in thread
From: Simon Glass @ 2017-05-14  9:32 UTC (permalink / raw)
  To: u-boot

Hi Eddie,

On 4 May 2017 at 19:15, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
> 2017-05-05 0:49 GMT+08:00 Simon Glass <sjg@chromium.org>:
>> Hi,
>>
>> On 4 May 2017 at 03:19, Lukasz Majewski <lukma@denx.de> wrote:
>>> Hi Eddie, Simon,
>>>
>>>> Hi Simon
>>>>
>>>> 2017-05-03 18:09 GMT+08:00 Simon Glass <sjg@chromium.org>:
>>>> > Hi Eddie,
>>>> >
>>>> > On 2 May 2017 at 04:37, Eddie Cai <eddie.cai.linux@gmail.com> wrote:
>>>> >> Hi Simon
>>>> >> 2017-03-20 10:30 GMT+08:00 Simon Glass <sjg@chromium.org>:
>>>> >>> Hi Eddie.
>>>> >>>
>>>> >>> On 15 March 2017 at 01:56, Eddie Cai <eddie.cai.linux@gmail.com>
>>>> >>> wrote:
>>>> >>>> this patch enable rockusb support on rk3288 based device.
>>>> >>>>
>>>> >>>> Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
>>>> >>>> ---
>>>> >>>>  include/configs/rk3288_common.h | 4 ++++
>>>> >>>>  1 file changed, 4 insertions(+)
>>>> >>>
>>>> >>> I think this should be done in Kconfig.
>>>> >> since rockusb used so widely on rockchip soc based devices. every
>>>> >> rockchip soc based
>>>> >> device should support it. So I would like to put it in
>>>> >> rk3288_common.h or even rockchip-common.h.
>>>> >> what do you think?
>>>> >
>>>> > We are moving to removing the board config headers so cannot add new
>>>> > non-Kconfig CONFIG options.
>>>> >
>>>> > You can add it to arch/arm/Kconfig - e.g. with 'imply CONFIG_....'
>>>> > under 'config ARCH_ROCKCHIP'.
>>>> USB_FUNCTION_ROCKUSB depend on USB_GADGET, USB_GADGET_DOWNLOAD,
>>>> CONFIG_G_DNL_VENDOR_NUM, CONFIG_G_DNL_PRODUCT_NUM
>>>> should i move those config to arch/arm/Kconfig? how to define
>>>> CONFIG_G_DNL_VENDOR_NUM
>>>> and CONFIG_G_DNL_PRODUCT_NUM when select it?
>>>
>>> I would prefer to keep those CONFIG options as they are now (and are in
>>> sync with other gadgets).
>>
>> These two are new though right?
>>
>> CONFIG_CMD_ROCKUSB
>> CONFIG_USB_FUNCTION_ROCKUSB
>>
>> So they should be added to Kconfig. If they 'depend' on non-Kconfig
>> options, that's fine IMO. We can't express that until the other
>> options are converted.
>>
>> Let's convert them soon!
> Does it means i can keep it in rk3288_common.h?

Anything new you add must go into defconfig. If it depends on a
non-Kconfig option, then just leave out the depend. We cannot add new
things to the config whitelist, so you should get a build error if you
try to add a new option outside Kconfig.

>>
>>>
>>> The problem here is that the gadget infrastructure is a bit
>>> "problematic" from the device model point of view.
>>>
>>> It has his own "structure" borrowed from Linux kernel.
>>>
>>> I've poked around and it seems like adding it to DM requires calling
>>> "g_dnl_register()" with embedded name of the gadget (like
>>> "usb_dnl_dfu").
>>>
>>> And such call is required for each different gadget (like mass storage,
>>> dfu, fastboot).
>>>
>>> Or maybe we should add "stub" DM support to only indicate supported
>>> gadgets (like dfu, ums, etc) and leave as much code untouched as
>>> possible?
>>
>> I'm sure this can be resolved in some way. I admit I have not looked
>> at it but was thinking of attacking usb_tty sometime, so perhaps might
>> see if I can figure it out.
>>
>>>
>>>> >
>>>> > Please help to remove any options you can from the headers.
>>>> >
>>>> >>>
>>>> >>>>
>>>> >>>> diff --git a/include/configs/rk3288_common.h
>>>> >>>> b/include/configs/rk3288_common.h index b5606d4..b19a34d 100644
>>>> >>>> --- a/include/configs/rk3288_common.h
>>>> >>>> +++ b/include/configs/rk3288_common.h
>>>> >>>> @@ -74,6 +74,10 @@
>>>> >>>>  #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
>>>> >>>>  #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
>>>> >>>>
>>>> >>>> +/* rockusb  */
>>>> >>>> +#define CONFIG_CMD_ROCKUSB
>>>> >>>> +#define CONFIG_USB_FUNCTION_ROCKUSB
>>>> >>>> +
>>>> >>>>  /* usb mass storage */
>>>> >>>>  #define CONFIG_USB_FUNCTION_MASS_STORAGE
>>>> >>>>  #define CONFIG_CMD_USB_MASS_STORAGE
>>>> >>>> --
>>>> >>>> 2.7.4
>>>> >
>>>> > Regards,
>>>> > Simon
>>
>> Regards,
>> Simon

Regards,
Simon

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

* [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device
  2017-05-14  9:32                 ` Simon Glass
@ 2017-05-14 21:49                   ` Lukasz Majewski
  0 siblings, 0 replies; 36+ messages in thread
From: Lukasz Majewski @ 2017-05-14 21:49 UTC (permalink / raw)
  To: u-boot

Dear Simon, Eddie,

> >>
> >> Let's convert them soon!  
> > Does it means i can keep it in rk3288_common.h?  
> 
> Anything new you add must go into defconfig. If it depends on a
> non-Kconfig option, then just leave out the depend. We cannot add new
> things to the config whitelist, so you should get a build error if you
> try to add a new option outside Kconfig.

Ok. Then I will wait for next iteration....


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
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

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

end of thread, other threads:[~2017-05-14 21:49 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-15  7:56 [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb Eddie Cai
2017-03-15  7:56 ` [U-Boot] [U-Boot 1/3] drivers: usb: gadget: add the rockusb gadget Eddie Cai
2017-03-16  7:05   ` Kever Yang
2017-03-20  7:24     ` Eddie Cai
2017-03-20  8:37       ` Lukasz Majewski
2017-04-20  0:56         ` Eddie Cai
2017-04-20 10:04   ` Lukasz Majewski
2017-03-15  7:56 ` [U-Boot] [U-Boot 2/3] cmd: add rockusb command Eddie Cai
2017-03-20  2:29   ` Simon Glass
2017-03-20  8:14     ` Eddie Cai
2017-03-22 13:05       ` Simon Glass
2017-04-20 10:11   ` Lukasz Majewski
2017-03-15  7:56 ` [U-Boot] [U-Boot 3/3] rockchip: rk3288: enable rockusb support on rk3288 based device Eddie Cai
2017-03-20  2:30   ` Simon Glass
2017-03-20  8:16     ` Eddie Cai
2017-05-02 10:37     ` Eddie Cai
2017-05-03 10:09       ` Simon Glass
2017-05-04  7:17         ` Eddie Cai
2017-05-04  9:19           ` Lukasz Majewski
2017-05-04 16:49             ` Simon Glass
2017-05-05  1:15               ` Eddie Cai
2017-05-14  9:32                 ` Simon Glass
2017-05-14 21:49                   ` Lukasz Majewski
2017-04-20 10:12   ` Lukasz Majewski
2017-03-15  9:06 ` [U-Boot] [U-Boot 0/3] introduce Rockchip rockusb Lukasz Majewski
2017-03-15  9:31   ` Eddie Cai
2017-03-15  9:46     ` Lukasz Majewski
2017-03-16 21:26 ` Marek Vasut
2017-03-20  1:53   ` Eddie Cai
2017-03-20 12:24     ` Marek Vasut
2017-03-20 16:01       ` Simon Glass
2017-03-20 16:33         ` Marek Vasut
2017-03-21  5:17           ` Kever Yang
2017-03-21 14:27             ` Tom Rini
2017-03-27  8:27 ` Lukasz Majewski
2017-03-28  9:13   ` Eddie Cai

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.