Skip to contentSkip to conversation

introduce Rockchip rockusb

PATCH New Eddie Cai 6 participants 36 messages Mar 15, 2017 – May 14, 2017 USB

lore
Share & tools
lore

Eddie Cai

author
#0 lore raw

cover introduce Rockchip rockusb

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
Signature · 1 line
2.7.4
author
#1 lore raw

PATCH 1/3 drivers: usb: gadget: add the rockusb gadget

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

---
 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
drivers/usb/gadget/Makefile +1 -0
index 0fbbb7c..0eb27a3 100644
@@ -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
drivers/usb/gadget/f_rockusb.c new file +801 -0

801 lines not on this page · raw message

Signature · 1 line
2.7.4
#2 lore raw

PATCH 1/3 drivers: usb: gadget: add the rockusb gadget

Hi Eddie,

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

Thanks,
- Kever

Quoted 831 lines · Eddie Cai

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

---
  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

drivers/usb/gadget/Makefile +1 -0
index 0fbbb7c..0eb27a3 100644
@@ -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
drivers/usb/gadget/f_rockusb.c new file +801 -0
new file mode 100644
index 0000000..a67cb35
@@ -0,0 +1,801 @@
+/*
+ * (C) Copyright 2017
+ *
+ * Eddie Cai <[email protected]>
+ *
+ * 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);
+}
author
#3 lore raw

PATCH 1/3 drivers: usb: gadget: add the rockusb gadget

2017-03-16 15:05 GMT+08:00 Kever Yang <[email protected]>:

Quoted 5 lines

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

Quoted 874 lines

Thanks,
- Kever

Quoted 865 lines · Eddie Cai

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

---
  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

drivers/usb/gadget/Makefile +1 -0
index 0fbbb7c..0eb27a3 100644
@@ -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
drivers/usb/gadget/f_rockusb.c new file +137 -0
new file mode 100644
index 0000000..a67cb35
@@ -0,0 +1,801 @@
+/*
+ * (C) Copyright 2017
+ *
+ * Eddie Cai <[email protected]>
+ *
+ * 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);

drivers/usb/gadget/f_rockusb.c new file +7 -0
+
+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);

drivers/usb/gadget/f_rockusb.c new file +3 -0
+}
+
+static int rockusb_bind(struct usb_configuration *c, struct usb_function

*f)

drivers/usb/gadget/f_rockusb.c new file +44 -0
+{
+       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)

drivers/usb/gadget/f_rockusb.c new file +103 -0
+{
+       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));

drivers/usb/gadget/f_rockusb.c new file +62 -0
+               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 */

drivers/usb/gadget/f_rockusb.c new file +5 -0
+       u8      CDB[16];                /* Command Data Block */
+};
+
+#define USB_BULK_CB_WRAP_LEN   31
+#define USB_BULK_CB_SIG                0x43425355      /* Spells out

USBC */

drivers/usb/gadget/f_rockusb.c new file +12 -0
+#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' */

drivers/usb/gadget/f_rockusb.c new file +11 -0
+#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)));

drivers/usb/gadget/f_rockusb.c new file +21 -0
+
+       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)));

drivers/usb/gadget/f_rockusb.c new file +10 -0
+
+       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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       struct bulk_cs_wrap csw __attribute__((aligned(ARCH_DM

A_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +33 -0
+       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)

drivers/usb/gadget/f_rockusb.c new file +8 -0
+{
+       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){

drivers/usb/gadget/f_rockusb.c new file +25 -0
+                       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",

drivers/usb/gadget/f_rockusb.c new file +8 -0
+                                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);

drivers/usb/gadget/f_rockusb.c new file +18 -0
+                       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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM

A_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +9 -0
+
+       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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM

A_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +12 -0
+       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)));

drivers/usb/gadget/f_rockusb.c new file +9 -0
+       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)){

drivers/usb/gadget/f_rockusb.c new file +25 -0
+               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)));

drivers/usb/gadget/f_rockusb.c new file +11 -0
+       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)));

drivers/usb/gadget/f_rockusb.c new file +183 -0
+
+       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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       void (*func_cb)(struct usb_ep *ep, struct usb_request *req) =

NULL;
+ struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
A_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +34 -0
+       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);
+}
#4 lore raw

PATCH 1/3 drivers: usb: gadget: add the rockusb gadget

Hi Eddie,

Quoted 8 lines

2017-03-16 15:05 GMT+08:00 Kever Yang <[email protected]>:

Quoted 5 lines

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.

Quoted 893 lines
Quoted 893 lines

Thanks,
- Kever

Quoted 886 lines · Eddie Cai

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

---
  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

(quoted diff) +0 -0

b/drivers/usb/gadget/Makefile index 0fbbb7c..0eb27a3 100644

drivers/usb/gadget/Makefile +1 -0
@@ -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
drivers/usb/gadget/f_rockusb.c new file +32 -0
new file mode 100644
index 0000000..a67cb35
@@ -0,0 +1,801 @@
+/*
+ * (C) Copyright 2017
+ *
+ * Eddie Cai <[email protected]>
+ *
+ * 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.
+ */

drivers/usb/gadget/f_rockusb.c new file +10 -0
+
+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) +{

drivers/usb/gadget/f_rockusb.c new file +63 -0
+       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,

drivers/usb/gadget/f_rockusb.c new file +28 -0
+           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);

drivers/usb/gadget/f_rockusb.c new file +2 -0
+
+static void rockusb_complete(struct usb_ep *ep, struct

usb_request *req) +{

drivers/usb/gadget/f_rockusb.c new file +4 -0
+       int status = req->status;
+       if (!status)
+               return;
+       debug("status: %d ep '%s' trans: %d\n", status, ep->name,

req->actual);

drivers/usb/gadget/f_rockusb.c new file +3 -0
+}
+
+static int rockusb_bind(struct usb_configuration *c, struct

usb_function *f)

drivers/usb/gadget/f_rockusb.c new file +32 -0
+{
+       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;

drivers/usb/gadget/f_rockusb.c new file +11 -0
+               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)

drivers/usb/gadget/f_rockusb.c new file +14 -0
+{
+       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);

drivers/usb/gadget/f_rockusb.c new file +5 -0
+               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);

drivers/usb/gadget/f_rockusb.c new file +14 -0
+               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);

drivers/usb/gadget/f_rockusb.c new file +70 -0
+       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));

drivers/usb/gadget/f_rockusb.c new file +34 -0
+               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) +{

drivers/usb/gadget/f_rockusb.c new file +27 -0
+       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 */

drivers/usb/gadget/f_rockusb.c new file +5 -0
+       u8      CDB[16];                /* Command Data Block */
+};
+
+#define USB_BULK_CB_WRAP_LEN   31
+#define USB_BULK_CB_SIG                0x43425355      /* Spells

out USBC */

drivers/usb/gadget/f_rockusb.c new file +6 -0
+#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
*/

drivers/usb/gadget/f_rockusb.c new file +5 -0
+       u8      Status;                 /* See below */
+};
+
+#define USB_BULK_CS_WRAP_LEN   13
+#define USB_BULK_CS_SIG                0x53425355      /* Spells

out 'USBS' */

drivers/usb/gadget/f_rockusb.c new file +11 -0
+#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)));

drivers/usb/gadget/f_rockusb.c new file +6 -0
+
+       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);

drivers/usb/gadget/f_rockusb.c new file +6 -0
+       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]);

drivers/usb/gadget/f_rockusb.c new file +8 -0
+       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)));

drivers/usb/gadget/f_rockusb.c new file +10 -0
+
+       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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       struct bulk_cs_wrap csw __attribute__((aligned(ARCH_DM

A_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +33 -0
+       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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       unsigned int transfer_size = download_size -

download_bytes;

drivers/usb/gadget/f_rockusb.c new file +6 -0
+       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){

drivers/usb/gadget/f_rockusb.c new file +2 -0
+                       error("invalid mmc device\n");
+                       rockusb_tx_write_csw(download_tag, 0,

CSW_FAIL,
+
USB_BULK_CS_WRAP_LEN);

drivers/usb/gadget/f_rockusb.c new file +8 -0
+                       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);

drivers/usb/gadget/f_rockusb.c new file +14 -0
+               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",

drivers/usb/gadget/f_rockusb.c new file +2 -0
+                                download_bytes, download_lba);
+               blks = blk_dwrite(download_desc, download_lba,

blkcnt,
+
(char*)CONFIG_FASTBOOT_BUF_ADDR);

drivers/usb/gadget/f_rockusb.c new file +3 -0
+               if (blks != blkcnt) {
+                       error("failed writing to device %s: %d\n",
+                               rockusb_dev_type,

rockusb_dev_index);

drivers/usb/gadget/f_rockusb.c new file +2 -0
+                       rockusb_tx_write_csw(download_tag, 0,
+                                               CSW_FAIL,

USB_BULK_CS_WRAP_LEN);

drivers/usb/gadget/f_rockusb.c new file +18 -0
+                       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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM

A_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +9 -0
+
+       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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM

A_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +6 -0
+       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,

drivers/usb/gadget/f_rockusb.c new file +4 -0
+                               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)));

drivers/usb/gadget/f_rockusb.c new file +9 -0
+       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);

drivers/usb/gadget/f_rockusb.c new file +15 -0
+       } 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) +{

drivers/usb/gadget/f_rockusb.c new file +7 -0
+       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)));

drivers/usb/gadget/f_rockusb.c new file +5 -0
+       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,

drivers/usb/gadget/f_rockusb.c new file +4 -0
+                               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)));

drivers/usb/gadget/f_rockusb.c new file +4 -0
+
+       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); +}

drivers/usb/gadget/f_rockusb.c new file +178 -0
+
+#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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       void (*func_cb)(struct usb_ep *ep, struct usb_request

*req) = NULL;
+ struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
A_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +27 -0
+       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");

drivers/usb/gadget/f_rockusb.c new file +3 -0
+               }
+       }
+
Quoted 8 lines
Quoted 8 lines

drivers/usb/gadget/f_rockusb.c line 801

Quoted 5 lines
drivers/usb/gadget/f_rockusb.c new file +4 -0
+       *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

author
#5 lore raw

PATCH 1/3 drivers: usb: gadget: add the rockusb gadget

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 <[email protected]>:

Quoted 927 lines

Hi Eddie,

Quoted 8 lines

2017-03-16 15:05 GMT+08:00 Kever Yang <[email protected]>:

Quoted 5 lines

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.

Quoted 893 lines
Quoted 893 lines

Thanks,
- Kever

Quoted 886 lines · Eddie Cai

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

---
  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

(quoted diff) +0 -0

b/drivers/usb/gadget/Makefile index 0fbbb7c..0eb27a3 100644

drivers/usb/gadget/Makefile +1 -0
@@ -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
drivers/usb/gadget/f_rockusb.c new file +32 -0
new file mode 100644
index 0000000..a67cb35
@@ -0,0 +1,801 @@
+/*
+ * (C) Copyright 2017
+ *
+ * Eddie Cai <[email protected]>
+ *
+ * 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.
+ */

drivers/usb/gadget/f_rockusb.c new file +10 -0
+
+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) +{

drivers/usb/gadget/f_rockusb.c new file +63 -0
+       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,

drivers/usb/gadget/f_rockusb.c new file +28 -0
+           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);

drivers/usb/gadget/f_rockusb.c new file +2 -0
+
+static void rockusb_complete(struct usb_ep *ep, struct

usb_request *req) +{

drivers/usb/gadget/f_rockusb.c new file +4 -0
+       int status = req->status;
+       if (!status)
+               return;
+       debug("status: %d ep '%s' trans: %d\n", status, ep->name,

req->actual);

drivers/usb/gadget/f_rockusb.c new file +3 -0
+}
+
+static int rockusb_bind(struct usb_configuration *c, struct

usb_function *f)

drivers/usb/gadget/f_rockusb.c new file +32 -0
+{
+       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;

drivers/usb/gadget/f_rockusb.c new file +11 -0
+               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)

drivers/usb/gadget/f_rockusb.c new file +14 -0
+{
+       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);

drivers/usb/gadget/f_rockusb.c new file +5 -0
+               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);

drivers/usb/gadget/f_rockusb.c new file +14 -0
+               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);

drivers/usb/gadget/f_rockusb.c new file +70 -0
+       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));

drivers/usb/gadget/f_rockusb.c new file +34 -0
+               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) +{

drivers/usb/gadget/f_rockusb.c new file +27 -0
+       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 */

drivers/usb/gadget/f_rockusb.c new file +5 -0
+       u8      CDB[16];                /* Command Data Block */
+};
+
+#define USB_BULK_CB_WRAP_LEN   31
+#define USB_BULK_CB_SIG                0x43425355      /* Spells

out USBC */

drivers/usb/gadget/f_rockusb.c new file +6 -0
+#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
*/

drivers/usb/gadget/f_rockusb.c new file +5 -0
+       u8      Status;                 /* See below */
+};
+
+#define USB_BULK_CS_WRAP_LEN   13
+#define USB_BULK_CS_SIG                0x53425355      /* Spells

out 'USBS' */

drivers/usb/gadget/f_rockusb.c new file +11 -0
+#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)));

drivers/usb/gadget/f_rockusb.c new file +6 -0
+
+       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);

drivers/usb/gadget/f_rockusb.c new file +6 -0
+       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]);

drivers/usb/gadget/f_rockusb.c new file +8 -0
+       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)));

drivers/usb/gadget/f_rockusb.c new file +10 -0
+
+       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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       struct bulk_cs_wrap csw __attribute__((aligned(ARCH_DM

A_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +33 -0
+       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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       unsigned int transfer_size = download_size -

download_bytes;

drivers/usb/gadget/f_rockusb.c new file +6 -0
+       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){

drivers/usb/gadget/f_rockusb.c new file +2 -0
+                       error("invalid mmc device\n");
+                       rockusb_tx_write_csw(download_tag, 0,

CSW_FAIL,
+
USB_BULK_CS_WRAP_LEN);

drivers/usb/gadget/f_rockusb.c new file +8 -0
+                       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);

drivers/usb/gadget/f_rockusb.c new file +14 -0
+               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",

drivers/usb/gadget/f_rockusb.c new file +2 -0
+                                download_bytes, download_lba);
+               blks = blk_dwrite(download_desc, download_lba,

blkcnt,
+
(char*)CONFIG_FASTBOOT_BUF_ADDR);

drivers/usb/gadget/f_rockusb.c new file +3 -0
+               if (blks != blkcnt) {
+                       error("failed writing to device %s: %d\n",
+                               rockusb_dev_type,

rockusb_dev_index);

drivers/usb/gadget/f_rockusb.c new file +2 -0
+                       rockusb_tx_write_csw(download_tag, 0,
+                                               CSW_FAIL,

USB_BULK_CS_WRAP_LEN);

drivers/usb/gadget/f_rockusb.c new file +18 -0
+                       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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM

A_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +9 -0
+
+       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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM

A_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +6 -0
+       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,

drivers/usb/gadget/f_rockusb.c new file +4 -0
+                               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)));

drivers/usb/gadget/f_rockusb.c new file +9 -0
+       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);

drivers/usb/gadget/f_rockusb.c new file +15 -0
+       } 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) +{

drivers/usb/gadget/f_rockusb.c new file +7 -0
+       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)));

drivers/usb/gadget/f_rockusb.c new file +5 -0
+       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,

drivers/usb/gadget/f_rockusb.c new file +4 -0
+                               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)));

drivers/usb/gadget/f_rockusb.c new file +4 -0
+
+       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); +}

drivers/usb/gadget/f_rockusb.c new file +178 -0
+
+#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)

drivers/usb/gadget/f_rockusb.c new file +2 -0
+{
+       void (*func_cb)(struct usb_ep *ep, struct usb_request

*req) = NULL;
+ struct fsg_bulk_cb_wrap cbw __attribute__((aligned(ARCH_DM
A_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +27 -0
+       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");

drivers/usb/gadget/f_rockusb.c new file +3 -0
+               }
+       }
+
Quoted 8 lines
Quoted 8 lines

drivers/usb/gadget/f_rockusb.c line 801

Quoted 5 lines
drivers/usb/gadget/f_rockusb.c new file +4 -0
+       *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

#6 lore raw

PATCH 1/3 drivers: usb: gadget: add the rockusb gadget

In reply to Eddie Cai

Hi Eddie,

Quoted 62 lines

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

---
 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

drivers/usb/gadget/Makefile +1 -0
index 0fbbb7c..0eb27a3 100644
@@ -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
(quoted diff) +0 -0

b/drivers/usb/gadget/f_rockusb.c new file mode 100644 index 0000000..a67cb35

drivers/usb/gadget/f_rockusb.c new file +32 -0
@@ -0,0 +1,801 @@
+/*
+ * (C) Copyright 2017
+ *
+ * Eddie Cai <[email protected]>
+ *
+ * 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
Quoted 6 lines

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.

Quoted 386 lines
drivers/usb/gadget/f_rockusb.c new file +9 -0
+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) +{

drivers/usb/gadget/f_rockusb.c new file +63 -0
+	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,

drivers/usb/gadget/f_rockusb.c new file +28 -0
+	    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) +{

drivers/usb/gadget/f_rockusb.c new file +4 -0
+	int status = req->status;
+	if (!status)
+		return;
+	debug("status: %d ep '%s' trans: %d\n", status, ep->name,

req->actual); +}

drivers/usb/gadget/f_rockusb.c new file +2 -0
+
+static int rockusb_bind(struct usb_configuration *c, struct

usb_function *f) +{

drivers/usb/gadget/f_rockusb.c new file +31 -0
+	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;

drivers/usb/gadget/f_rockusb.c new file +1 -0
+		hs_ep_out.bEndpointAddress =

fs_ep_out.bEndpointAddress;

drivers/usb/gadget/f_rockusb.c new file +11 -0
+		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) +{

drivers/usb/gadget/f_rockusb.c new file +13 -0
+	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);

drivers/usb/gadget/f_rockusb.c new file +19 -0
+		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);

drivers/usb/gadget/f_rockusb.c new file +70 -0
+	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));

drivers/usb/gadget/f_rockusb.c new file +34 -0
+		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) +{

drivers/usb/gadget/f_rockusb.c new file +23 -0
+	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 */

drivers/usb/gadget/f_rockusb.c new file +1 -0
+	__le32	DataTransferLength;	/* Size of the data

*/

drivers/usb/gadget/f_rockusb.c new file +1 -0
+	u8	Flags;			/* Direction in bit

7 */

drivers/usb/gadget/f_rockusb.c new file +2 -0
+	u8	Lun;			/* LUN (normally 0) */
+	u8	Length;			/* Of the CDB, <=

MAX_COMMAND_SIZE */

drivers/usb/gadget/f_rockusb.c new file +5 -0
+	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

drivers/usb/gadget/f_rockusb.c new file +5 -0
+
+/* Command Status Wrapper */
+struct bulk_cs_wrap {
+	__le32	Signature;		/* Should = 'USBS' */
+	u32	Tag;			/* Same as original

command */

drivers/usb/gadget/f_rockusb.c new file +1 -0
+	__le32	Residue;		/* Amount not

transferred */

drivers/usb/gadget/f_rockusb.c new file +5 -0
+	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

drivers/usb/gadget/f_rockusb.c new file +10 -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))); +

drivers/usb/gadget/f_rockusb.c new file +5 -0
+	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);

drivers/usb/gadget/f_rockusb.c new file +6 -0
+	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],

drivers/usb/gadget/f_rockusb.c new file +1 -0
+						cbw.CDB[3],

cbw.CDB[2]);

drivers/usb/gadget/f_rockusb.c new file +8 -0
+	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))); +

drivers/usb/gadget/f_rockusb.c line 414

Quoted 7 lines
drivers/usb/gadget/f_rockusb.c new file +7 -0
+	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

Quoted 8 lines
drivers/usb/gadget/f_rockusb.c new file +2 -0
+
+static int rockusb_tx_write_csw(u32 Tag, int residue, u8 Status, int

size) +{

drivers/usb/gadget/f_rockusb.c new file +1 -0
+	struct bulk_cs_wrap csw

__attribute__((aligned(ARCH_DMA_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +3 -0
+	csw.Signature = cpu_to_le32(USB_BULK_CS_SIG);
+	csw.Tag = Tag;
+	csw.Residue = cpu_to_be32(residue);

drivers/usb/gadget/f_rockusb.c line 431

Quoted 10 lines
drivers/usb/gadget/f_rockusb.c new file +10 -0
+	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).

Quoted 45 lines
drivers/usb/gadget/f_rockusb.c new file +20 -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) +{

drivers/usb/gadget/f_rockusb.c new file +7 -0
+	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);

drivers/usb/gadget/f_rockusb.c new file +1 -0
+		if (!download_desc || download_desc->type ==

DEV_TYPE_UNKNOWN){

drivers/usb/gadget/f_rockusb.c new file +2 -0
+			error("invalid mmc device\n");
+			rockusb_tx_write_csw(download_tag, 0,

CSW_FAIL,
+
USB_BULK_CS_WRAP_LEN);

drivers/usb/gadget/f_rockusb.c new file +8 -0
+			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);

drivers/usb/gadget/f_rockusb.c line 478

Quoted 7 lines
drivers/usb/gadget/f_rockusb.c new file +7 -0
+		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).

Quoted 40 lines
drivers/usb/gadget/f_rockusb.c new file +7 -0
+	       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",

drivers/usb/gadget/f_rockusb.c new file +2 -0
+				 download_bytes, download_lba);
+		blks = blk_dwrite(download_desc, download_lba,

blkcnt,
+
(char*)CONFIG_FASTBOOT_BUF_ADDR);

drivers/usb/gadget/f_rockusb.c new file +5 -0
+		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);

drivers/usb/gadget/f_rockusb.c new file +18 -0
+			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) +{

drivers/usb/gadget/f_rockusb.c new file +1 -0
+	struct fsg_bulk_cb_wrap cbw

__attribute__((aligned(ARCH_DMA_MINALIGN))); +

drivers/usb/gadget/f_rockusb.c

Quoted 1 line
drivers/usb/gadget/f_rockusb.c new file +1 -0
+	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)

Quoted 78 lines
drivers/usb/gadget/f_rockusb.c new file +7 -0
+
+	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) +{

drivers/usb/gadget/f_rockusb.c new file +1 -0
+	struct fsg_bulk_cb_wrap cbw

__attribute__((aligned(ARCH_DMA_MINALIGN)));

drivers/usb/gadget/f_rockusb.c new file +6 -0
+	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,

drivers/usb/gadget/f_rockusb.c new file +6 -0
+				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)));

drivers/usb/gadget/f_rockusb.c new file +9 -0
+	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)){

drivers/usb/gadget/f_rockusb.c new file +1 -0
+		rockusb_tx_write_csw(cbw.Tag,

cbw.DataTransferLength,

drivers/usb/gadget/f_rockusb.c new file +1 -0
+					CSW_FAIL,

USB_BULK_CS_WRAP_LEN);

drivers/usb/gadget/f_rockusb.c new file +15 -0
+	} 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) +{

drivers/usb/gadget/f_rockusb.c new file +7 -0
+	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)));

drivers/usb/gadget/f_rockusb.c new file +5 -0
+	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,

drivers/usb/gadget/f_rockusb.c new file +4 -0
+				USB_BULK_CS_WRAP_LEN);
+}
+
+static void cb_not_support(struct usb_ep *ep, struct usb_request

*req) +{

drivers/usb/gadget/f_rockusb.c new file +1 -0
+	struct fsg_bulk_cb_wrap cbw

__attribute__((aligned(ARCH_DMA_MINALIGN))); +

drivers/usb/gadget/f_rockusb.c new file +3 -0
+	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,
Quoted 2 lines

USB_BULK_CS_WRAP_LEN); +}
+

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

Quoted 60 lines
drivers/usb/gadget/f_rockusb.c new file +60 -0
+#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
+

drivers/usb/gadget/f_rockusb.c line 657

Quoted 10 lines
drivers/usb/gadget/f_rockusb.c new file +10 -0
+#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

Quoted 112 lines
drivers/usb/gadget/f_rockusb.c new file +107 -0
+
+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) +{

drivers/usb/gadget/f_rockusb.c new file +1 -0
+	void (*func_cb)(struct usb_ep *ep, struct usb_request *req)

= NULL;

drivers/usb/gadget/f_rockusb.c new file +1 -0
+	struct fsg_bulk_cb_wrap cbw

__attribute__((aligned(ARCH_DMA_MINALIGN)));

drivers/usb/gadget/f_rockusb.c line 771

Quoted 4 lines
drivers/usb/gadget/f_rockusb.c new file +4 -0
+	int i;
+	char *cmdbuf = req->buf;
+
+	if (req->status != 0 || req->length == 0)
	    ^^^^^^^^^^^
			req->status is enough
Quoted 20 lines
drivers/usb/gadget/f_rockusb.c new file +20 -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);

drivers/usb/gadget/f_rockusb.c line 801

Quoted 10 lines
drivers/usb/gadget/f_rockusb.c new file +10 -0
+		} 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

author
#7 lore raw

PATCH 2/3 cmd: add rockusb command

In reply to Eddie Cai

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

---
 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
cmd/Kconfig +12 -0
index ef53156..dac2cc0 100644
@@ -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
cmd/Makefile +1 -0
index f13bb8c..f5f1663 100644
@@ -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
cmd/rockusb.c new file +79 -0

79 lines not on this page · raw message

include/rockusb.h new file +13 -0
new file mode 100644
index 0000000..cdea63d
@@ -0,0 +1,13 @@
+/*
+ * (C) Copyright 2017
+ *
+ * Eddie Cai <[email protected]>
+ *
+ * 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_ */
Signature · 1 line
2.7.4
#8 lore raw

PATCH 2/3 cmd: add rockusb command

Hi Eddie,

Quoted 6 lines · Eddie Cai

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

Quoted 8 lines
---
 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?

Quoted 6 lines
cmd/Kconfig +0 -0
index ef53156..dac2cc0 100644

cmd/Kconfig config CMD_DFU · line 483

Quoted 9 lines
cmd/Kconfig +6 -0
@@ -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?

Quoted 14 lines
cmd/Kconfig +6 -0
+
+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
cmd/Makefile +0 -0
index f13bb8c..f5f1663 100644

cmd/Makefile endif · line 145

Quoted 5 lines
cmd/Makefile +1 -0
@@ -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?

Quoted 10 lines
cmd/Makefile +0 -0
 obj-$(CONFIG_CMD_USB_MASS_STORAGE) += usb_mass_storage.o
cmd/rockusb.c new file +2 -0
new file mode 100644
index 0000000..f5bd86e
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 Eddie Cai <[email protected]>

cmd/rockusb.c line 12

Quoted 10 lines
cmd/rockusb.c new file +10 -0
+ *
+ * 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

cmd/rockusb.c line 13

Quoted 1 line
cmd/rockusb.c new file +1 -0
+

remove extra blank line

Quoted 14 lines
cmd/rockusb.c new file +14 -0
+
+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);

cmd/rockusb.c line 37

Quoted 10 lines
cmd/rockusb.c new file +10 -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?

cmd/rockusb.c line 48

Quoted 11 lines
cmd/rockusb.c new file +11 -0
+
+       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.

cmd/rockusb.c line 49

Quoted 1 line
cmd/rockusb.c new file +1 -0
+       printf("do_rockusb1\n");

Do you want this?

Quoted 5 lines
cmd/rockusb.c new file +5 -0
+       if (!g_dnl_board_usb_cable_connected()) {
+               puts("\rUSB cable not detected.\n" \
+                    "Command exit.\n");
+               ret = CMD_RET_FAILURE;
+               goto exit;

cmd/rockusb.c line 64

Quoted 10 lines
cmd/rockusb.c new file +10 -0
+       }
+
+       while (1) {
+               if (g_dnl_detach())
+                       break;
+               if (ctrlc())
+                       break;
+               usb_gadget_handle_interrupts(controller_index);
+       }
+       printf("do_rockusb2\n");

Do you want this?

cmd/rockusb.c line 76

Quoted 12 lines
cmd/rockusb.c new file +12 -0
+       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?

include/rockusb.h

Quoted 8 lines
cmd/rockusb.c new file +3 -0
+       "rockusb <USB_controller> [<devtype>] <devnum>  e.g. rockusb 0 mmc 0\n"
+       "    devtype defaults to mmc"
+);
include/rockusb.h new file +0 -0
new file mode 100644
index 0000000..cdea63d

Can this go in include/asm instead?

include/rockusb.h line 11

Quoted 12 lines
include/rockusb.h new file +11 -0
@@ -0,0 +1,13 @@
+/*
+ * (C) Copyright 2017
+ *
+ * Eddie Cai <[email protected]>
+ *
+ * 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.

Quoted 5 lines
include/rockusb.h new file +2 -1
+
+#endif /* _ROCKUSB_H_ */
--

2.7.4

Regards,
Simon

author
#9 lore raw

PATCH 2/3 cmd: add rockusb command

Hi Simon

2017-03-20 10:29 GMT+08:00 Simon Glass <[email protected]>:

Quoted 13 lines

Hi Eddie,

Quoted 10 lines · Eddie Cai

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

---
 cmd/Kconfig       | 12 +++++++++
 cmd/Makefile      |  1 +
 cmd/rockusb.c     | 79 ++++++++++++++++++++++++++++++
Quoted 9 lines

+++++++++++++++++++++++++

Quoted 4 lines
 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

Quoted 16 lines

cmd/Kconfig config CMD_DFU · line 475

Quoted 8 lines
cmd/Kconfig +0 -0
index ef53156..dac2cc0 100644
@@ -475,6 +475,18 @@ config CMD_DFU
          Enables the command "dfu" which is used to have U-Boot create

a DFU

cmd/Kconfig config CMD_DFU

Quoted 7 lines
cmd/Kconfig +5 -0
          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
Quoted 5 lines

create a

cmd/Kconfig config CMD_DFU · line 483

Quoted 1 line
cmd/Kconfig +1 -0
+          Rockusb class device via USB.

Does this mean Rockchip-class device?

Yes, This is vendor specific class.

Quoted 16 lines
Quoted 16 lines
cmd/Kconfig +6 -0
+
+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
cmd/Makefile +0 -0
index f13bb8c..f5f1663 100644
@@ -141,6 +141,7 @@ endif
 
Quoted 7 lines

cmd/Makefile endif · line 145

Quoted 4 lines
cmd/Makefile +1 -0
 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

Quoted 15 lines
Quoted 15 lines
cmd/Makefile +0 -0
 obj-$(CONFIG_CMD_USB_MASS_STORAGE) += usb_mass_storage.o
cmd/rockusb.c new file +6 -0
new file mode 100644
index 0000000..f5bd86e
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 Eddie Cai <[email protected]>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
Quoted 9 lines

cmd/rockusb.c line 12

Quoted 6 lines
cmd/rockusb.c new file +6 -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

Quoted 5 lines

cmd/rockusb.c line 13

Quoted 2 lines
cmd/rockusb.c new file +1 -0
+

remove extra blank line

done

Quoted 20 lines

cmd/rockusb.c line 15

Quoted 3 lines
cmd/rockusb.c new file +2 -0
+
+static int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const

argv[])

Quoted 16 lines
cmd/rockusb.c new file +16 -0
+{
+       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];
Quoted 9 lines

cmd/rockusb.c line 37

Quoted 6 lines
cmd/rockusb.c new file +6 -0
+       } 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

Quoted 15 lines

cmd/rockusb.c line 48

Quoted 12 lines
cmd/rockusb.c new file +11 -0
+
+       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.

Quoted 5 lines

cmd/rockusb.c line 49

Quoted 2 lines
cmd/rockusb.c new file +1 -0
+       printf("do_rockusb1\n");

Do you want this?

Oops, i will remove it in next version.

Quoted 17 lines
Quoted 6 lines
cmd/rockusb.c new file +5 -0
+       if (!g_dnl_board_usb_cable_connected()) {
+               puts("\rUSB cable not detected.\n" \
+                    "Command exit.\n");
+               ret = CMD_RET_FAILURE;
+               goto exit;

cmd/rockusb.c line 64

Quoted 10 lines
cmd/rockusb.c new file +10 -0
+       }
+
+       while (1) {
+               if (g_dnl_detach())
+                       break;
+               if (ctrlc())
+                       break;
+               usb_gadget_handle_interrupts(controller_index);
+       }
+       printf("do_rockusb2\n");
Quoted 2 lines

Do you want this?

i will remove it in next version.

Quoted 16 lines

cmd/rockusb.c line 76

Quoted 13 lines
cmd/rockusb.c new file +12 -0
+       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

Quoted 13 lines

cmd/rockusb.c line 77

Quoted 2 lines
cmd/rockusb.c new file +1 -0
+       "rockusb <USB_controller> [<devtype>] <devnum>  e.g. rockusb 0

mmc 0\n"

include/rockusb.h

Quoted 7 lines
cmd/rockusb.c new file +2 -0
+       "    devtype defaults to mmc"
+);
include/rockusb.h new file +0 -0
new file mode 100644
index 0000000..cdea63d

Can this go in include/asm instead?

do you mean include/asm-generic ? may i know why ?

Quoted 16 lines

include/rockusb.h line 11

Quoted 13 lines
include/rockusb.h new file +11 -0
@@ -0,0 +1,13 @@
+/*
+ * (C) Copyright 2017
+ *
+ * Eddie Cai <[email protected]>
+ *
+ * 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 .

Quoted 10 lines
Quoted 6 lines
include/rockusb.h new file +2 -1
+
+#endif /* _ROCKUSB_H_ */
--

2.7.4

Regards,
Simon

#10 lore raw

PATCH 2/3 cmd: add rockusb command

Hi Eddie,

Quoted 23 lines · Eddie Cai

Hi Simon

2017-03-20 10:29 GMT+08:00 Simon Glass <[email protected]>:

Quoted 20 lines

Hi Eddie,

Quoted 15 lines · Eddie Cai

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

---
 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

[..]

Quoted 13 lines
Quoted 12 lines

include/rockusb.h

Quoted 10 lines

+ "rockusb <USB_controller> [<devtype>] <devnum> e.g. rockusb 0
mmc 0\n"

cmd/rockusb.c new file +2 -0
+       "    devtype defaults to mmc"
+);
include/rockusb.h new file +0 -0
new file mode 100644
index 0000000..cdea63d

Can this go in include/asm instead?

Quoted 1 line

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

#11 lore raw

PATCH 2/3 cmd: add rockusb command

In reply to Eddie Cai

Hi Eddie,

Quoted 60 lines

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

---
 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
cmd/Kconfig +0 -0
index ef53156..dac2cc0 100644
@@ -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.

cmd/Kconfig +5 -0
+config CMD_ROCKUSB
+        bool "rockusb"
+        select USB_FUNCTION_ROCKUSB
+        help
+          Enables the command "rockusb" which is used to have U-Boot

create a

cmd/Kconfig +7 -0
+          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
cmd/Makefile +1 -0
index f13bb8c..f5f1663 100644
@@ -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
cmd/rockusb.c new file +4 -0
new file mode 100644
index 0000000..f5bd86e
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 Eddie Cai <[email protected]>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+

cmd/rockusb.c line 14

Quoted 10 lines
cmd/rockusb.c new file +10 -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.

Quoted 11 lines
cmd/rockusb.c new file +1 -0
+static int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char

*const argv[]) +{

cmd/rockusb.c new file +9 -0
+	int controller_index, dev_index;
+	char *usb_controller;
+	char *devtype;
+	char *devnum;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+

cmd/rockusb.c line 35

Quoted 10 lines
cmd/rockusb.c new file +10 -0
+	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.

Quoted 4 lines
cmd/rockusb.c new file +4 -0
+	dev_index = simple_strtoul(devnum, NULL, 0);
+	rockusb_dev_init(devtype, dev_index);
+
+	ret = board_usb_init(controller_index, USB_INIT_DEVICE);

cmd/rockusb.c line 49

Quoted 10 lines
cmd/rockusb.c new file +10 -0
+	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(...)".
Quoted 29 lines
cmd/rockusb.c new file +28 -0
+	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"

cmd/rockusb.c line 78

Quoted 1 line
cmd/rockusb.c new file +1 -0
+	"    devtype defaults to mmc"

[<devtype>] should be mandatory.

Quoted 10 lines
cmd/rockusb.c new file +1 -0
+);
include/rockusb.h new file +3 -0
new file mode 100644
index 0000000..cdea63d
@@ -0,0 +1,13 @@
+/*
+ * (C) Copyright 2017
+ *

include/rockusb.h line 13

Quoted 10 lines
include/rockusb.h new file +10 -0
+ * Eddie Cai <[email protected]>
+ *
+ * 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

author
#12 lore raw

PATCH 3/3 rockchip: rk3288: enable rockusb support on rk3288 based device

In reply to Eddie Cai

this patch enable rockusb support on rk3288 based device.

---
 include/configs/rk3288_common.h | 4 ++++
 1 file changed, 4 insertions(+)
include/configs/rk3288_common.h +4 -0
index b5606d4..b19a34d 100644
@@ -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
Signature · 1 line
2.7.4
#13 lore raw

PATCH 3/3 rockchip: rk3288: enable rockusb support on rk3288 based device

Hi Eddie.

Quoted 6 lines · Eddie Cai

this patch enable rockusb support on rk3288 based device.

---
 include/configs/rk3288_common.h | 4 ++++
 1 file changed, 4 insertions(+)

I think this should be done in Kconfig.

Quoted 17 lines
include/configs/rk3288_common.h +4 -1
index b5606d4..b19a34d 100644
@@ -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
--
Quoted 2 lines

2.7.4

Regards,
Simon

author
#14 lore raw

PATCH 3/3 rockchip: rk3288: enable rockusb support on rk3288 based device

Hi Simon

2017-03-20 10:30 GMT+08:00 Simon Glass <[email protected]>:

Quoted 12 lines

Hi Eddie.

Quoted 6 lines · Eddie Cai

this patch enable rockusb support on rk3288 based device.

---
 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.

Quoted 25 lines

include/configs/rk3288_

Quoted 3 lines
include/configs/rk3288_ renamed from include/configs/rk3288_common.h +0 -0

common.h

Quoted 15 lines

index b5606d4..b19a34d 100644

include/configs/rk3288_common.h +4 -1
@@ -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
--
Quoted 2 lines

2.7.4

Regards,
Simon

author
#15 lore raw

PATCH 3/3 rockchip: rk3288: enable rockusb support on rk3288 based device

In reply to Simon Glass

Hi Simon
2017-03-20 10:30 GMT+08:00 Simon Glass <[email protected]>:

Quoted 11 lines

Hi Eddie.

Quoted 6 lines · Eddie Cai

this patch enable rockusb support on rk3288 based device.

---
 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?

Quoted 23 lines
Quoted 18 lines
include/configs/rk3288_common.h +4 -1
index b5606d4..b19a34d 100644
@@ -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
--
Quoted 2 lines

2.7.4

Regards,
Simon

#16 lore raw

PATCH 3/3 rockchip: rk3288: enable rockusb support on rk3288 based device

Hi Eddie,

Quoted 12 lines · Eddie Cai

Hi Simon
2017-03-20 10:30 GMT+08:00 Simon Glass <[email protected]>:

Quoted 10 lines

Hi Eddie.

Quoted 6 lines · Eddie Cai

this patch enable rockusb support on rk3288 based device.

---
 include/configs/rk3288_common.h | 4 ++++
 1 file changed, 4 insertions(+)
Quoted 6 lines
Quoted 1 line

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.

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
include/configs/rk3288_common.h +0 -0
index b5606d4..b19a34d 100644
@@ -74,6 +74,10 @@
 #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
 #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
 
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
include/configs/rk3288_common.h +4 -1
+/* 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

author
#17 lore raw

PATCH 3/3 rockchip: rk3288: enable rockusb support on rk3288 based device

Hi Simon

2017-05-03 18:09 GMT+08:00 Simon Glass <[email protected]>:

Quoted 22 lines

Hi Eddie,

Quoted 12 lines · Eddie Cai

Hi Simon
2017-03-20 10:30 GMT+08:00 Simon Glass <[email protected]>:

Quoted 10 lines

Hi Eddie.

Quoted 6 lines · Eddie Cai

this patch enable rockusb support on rk3288 based device.

---
 include/configs/rk3288_common.h | 4 ++++
 1 file changed, 4 insertions(+)
Quoted 6 lines
Quoted 1 line

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?

Quoted 5 lines

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?

Quoted 25 lines

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

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
include/configs/rk3288_common.h +0 -0
index b5606d4..b19a34d 100644
@@ -74,6 +74,10 @@
 #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
 #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
 
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
include/configs/rk3288_common.h +4 -1
+/* 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

#18 lore raw

PATCH 3/3 rockchip: rk3288: enable rockusb support on rk3288 based device

Hi Eddie, Simon,

Quoted 29 lines

Hi Simon

2017-05-03 18:09 GMT+08:00 Simon Glass <[email protected]>:

Quoted 26 lines

Hi Eddie,

Quoted 13 lines · Eddie Cai

Hi Simon
2017-03-20 10:30 GMT+08:00 Simon Glass <[email protected]>:

Quoted 11 lines

Hi Eddie.

Quoted 6 lines · Eddie Cai

this patch enable rockusb support on rk3288 based device.

---
 include/configs/rk3288_common.h | 4 ++++
 1 file changed, 4 insertions(+)
Quoted 6 lines
Quoted 1 line

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.

Quoted 7 lines
Quoted 2 lines

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?

Quoted 13 lines
Quoted 13 lines

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

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
(quoted diff) +0 -0

b/include/configs/rk3288_common.h index b5606d4..b19a34d 100644

include/configs/rk3288_common.h +0 -0
@@ -74,6 +74,10 @@
 #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
 #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
 
Quoted 12 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
include/configs/rk3288_common.h +4 -0
+/* rockusb  */
+#define CONFIG_CMD_ROCKUSB
+#define CONFIG_USB_FUNCTION_ROCKUSB
+
Quoted 8 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
include/configs/rk3288_common.h +0 -1
 /* 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

#19 lore raw

PATCH 3/3 rockchip: rk3288: enable rockusb support on rk3288 based device

Hi,

Quoted 33 lines · Lukasz Majewski

Hi Eddie, Simon,

Quoted 31 lines

Hi Simon

2017-05-03 18:09 GMT+08:00 Simon Glass <[email protected]>:

Quoted 28 lines

Hi Eddie,

Quoted 13 lines · Eddie Cai

Hi Simon
2017-03-20 10:30 GMT+08:00 Simon Glass <[email protected]>:

Quoted 11 lines

Hi Eddie.

Quoted 6 lines · Eddie Cai

this patch enable rockusb support on rk3288 based device.

---
 include/configs/rk3288_common.h | 4 ++++
 1 file changed, 4 insertions(+)
Quoted 6 lines
Quoted 1 line

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'.

Quoted 8 lines
Quoted 5 lines

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!

Quoted 10 lines

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").

Quoted 6 lines

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.

Quoted 14 lines
Quoted 14 lines
Quoted 14 lines

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

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
(quoted diff) +0 -0

b/include/configs/rk3288_common.h index b5606d4..b19a34d 100644

include/configs/rk3288_common.h +0 -0
@@ -74,6 +74,10 @@
 #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
 #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
 
Quoted 12 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
include/configs/rk3288_common.h +4 -0
+/* rockusb  */
+#define CONFIG_CMD_ROCKUSB
+#define CONFIG_USB_FUNCTION_ROCKUSB
+
Quoted 8 lines
Quoted 8 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
include/configs/rk3288_common.h +0 -1
 /* usb mass storage */
 #define CONFIG_USB_FUNCTION_MASS_STORAGE
 #define CONFIG_CMD_USB_MASS_STORAGE
--

2.7.4

Regards,
Simon

Regards,
Simon

author
#20 lore raw

PATCH 3/3 rockchip: rk3288: enable rockusb support on rk3288 based device

2017-05-05 0:49 GMT+08:00 Simon Glass <[email protected]>:

Quoted 47 lines

Hi,

Quoted 33 lines · Lukasz Majewski

Hi Eddie, Simon,

Quoted 31 lines

Hi Simon

2017-05-03 18:09 GMT+08:00 Simon Glass <[email protected]>:

Quoted 28 lines

Hi Eddie,

Quoted 13 lines · Eddie Cai

Hi Simon
2017-03-20 10:30 GMT+08:00 Simon Glass <[email protected]>:

Quoted 11 lines

Hi Eddie.

Quoted 6 lines · Eddie Cai

this patch enable rockusb support on rk3288 based device.

---
 include/configs/rk3288_common.h | 4 ++++
 1 file changed, 4 insertions(+)
Quoted 6 lines
Quoted 1 line

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'.

Quoted 8 lines
Quoted 5 lines

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?

Quoted 8 lines

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?

Quoted 51 lines
Quoted 11 lines

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").

Quoted 6 lines

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.

Quoted 14 lines
Quoted 14 lines
Quoted 14 lines

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

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
(quoted diff) +0 -0

b/include/configs/rk3288_common.h index b5606d4..b19a34d 100644

include/configs/rk3288_common.h +0 -0
@@ -74,6 +74,10 @@
 #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
 #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
 
Quoted 12 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
include/configs/rk3288_common.h +4 -0
+/* rockusb  */
+#define CONFIG_CMD_ROCKUSB
+#define CONFIG_USB_FUNCTION_ROCKUSB
+
Quoted 8 lines
Quoted 8 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
include/configs/rk3288_common.h +0 -1
 /* usb mass storage */
 #define CONFIG_USB_FUNCTION_MASS_STORAGE
 #define CONFIG_CMD_USB_MASS_STORAGE
--

2.7.4

Regards,
Simon

Regards,
Simon

#21 lore raw

PATCH 3/3 rockchip: rk3288: enable rockusb support on rk3288 based device

Hi Eddie,

Quoted 51 lines · Eddie Cai

2017-05-05 0:49 GMT+08:00 Simon Glass <[email protected]>:

Quoted 50 lines

Hi,

Quoted 33 lines · Lukasz Majewski

Hi Eddie, Simon,

Quoted 31 lines

Hi Simon

2017-05-03 18:09 GMT+08:00 Simon Glass <[email protected]>:

Quoted 28 lines

Hi Eddie,

Quoted 13 lines · Eddie Cai

Hi Simon
2017-03-20 10:30 GMT+08:00 Simon Glass <[email protected]>:

Quoted 11 lines

Hi Eddie.

Quoted 6 lines · Eddie Cai

this patch enable rockusb support on rk3288 based device.

---
 include/configs/rk3288_common.h | 4 ++++
 1 file changed, 4 insertions(+)
Quoted 6 lines
Quoted 1 line

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'.

Quoted 8 lines
Quoted 5 lines

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

Quoted 6 lines
Quoted 5 lines

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.

Quoted 49 lines
Quoted 49 lines
Quoted 11 lines

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").

Quoted 6 lines

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.

Quoted 26 lines
Quoted 26 lines
Quoted 26 lines

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

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
(quoted diff) +0 -0

b/include/configs/rk3288_common.h index b5606d4..b19a34d 100644

include/configs/rk3288_common.h +0 -0
@@ -74,6 +74,10 @@
 #define CONFIG_FASTBOOT_BUF_ADDR       CONFIG_SYS_LOAD_ADDR
 #define CONFIG_FASTBOOT_BUF_SIZE       0x08000000
 
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
include/configs/rk3288_common.h +4 -1
+/* 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

Quoted 2 lines
Quoted 2 lines

Regards,
Simon

Regards,
Simon

#22 lore raw

PATCH 3/3 rockchip: rk3288: enable rockusb support on rk3288 based device

Dear Simon, Eddie,

Quoted 8 lines
Quoted 3 lines
Quoted 2 lines

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

#23 lore raw

PATCH 3/3 rockchip: rk3288: enable rockusb support on rk3288 based device

In reply to Eddie Cai

Hi Eddie,

Quoted 12 lines

this patch enable rockusb support on rk3288 based device.

---
 include/configs/rk3288_common.h | 4 ++++
 1 file changed, 4 insertions(+)
(quoted diff) +0 -0

b/include/configs/rk3288_common.h index b5606d4..b19a34d 100644

include/configs/rk3288_common.h line 83

Quoted 10 lines
include/configs/rk3288_common.h +4 -0
@@ -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

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

#24 lore raw

cover introduce Rockchip rockusb

In reply to Eddie Cai
Quoted 3 lines · On Wed, 15 Mar 2017 15:56:02 +0800 Eddie Cai <[email protected]> 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).

Quoted 11 lines

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
Quoted 7 lines

++++++++++++++++++++++++++++++++++++++++
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

author
#25 lore raw

cover introduce Rockchip rockusb

Hi Lukasz

2017-03-15 17:06 GMT+08:00 Lukasz Majewski <[email protected]>:

Quoted 7 lines
Quoted 3 lines · On Wed, 15 Mar 2017 15:56:02 +0800 Eddie Cai <[email protected]> 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.

Quoted 8 lines

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.

Quoted 31 lines
Quoted 12 lines

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
Quoted 7 lines

++++++++++++++++++++++++++++++++++++++++
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

#26 lore raw

cover introduce Rockchip rockusb

Quoted 13 lines · On Wed, 15 Mar 2017 17:31:27 +0800 Eddie Cai <[email protected]> wrote:

Hi Lukasz

2017-03-15 17:06 GMT+08:00 Lukasz Majewski <[email protected]>:

Quoted 9 lines
Quoted 3 lines · On Wed, 15 Mar 2017 15:56:02 +0800 Eddie Cai <[email protected]> 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.

Quoted 8 lines
Quoted 6 lines

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

Quoted 26 lines
Quoted 26 lines
Quoted 13 lines

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
Quoted 7 lines

++++++++++++++++++++++++++++++++++++++++
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

Quoted 7 lines
Quoted 7 lines

--

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

#27 lore raw

cover introduce Rockchip rockusb

In reply to Eddie Cai
Quoted 2 lines · Eddie Cai

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 ?

Quoted 17 lines

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
Signature · 2 lines
Best regards,
Marek Vasut
author
#28 lore raw

cover introduce Rockchip rockusb

2017-03-17 5:26 GMT+08:00 Marek Vasut <[email protected]>:

Quoted 8 lines · Eddie Cai
Quoted 1 line

rockusb is a protocol run between host pc and device. it help people get

device

Quoted 1 line

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.

Quoted 24 lines
Quoted 10 lines

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 ++++++++++++++++++++++++++++++

++++++++++

Quoted 7 lines
 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

#29 lore raw

cover introduce Rockchip rockusb

Quoted 5 lines · Eddie Cai

2017-03-17 5:26 GMT+08:00 Marek Vasut <[email protected]>:

Quoted 3 lines · Eddie Cai
Quoted 1 line

rockusb is a protocol run between host pc and device. it help people get

device

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

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 ?

Signature · 2 lines
Best regards,
Marek Vasut
#30 lore raw

cover introduce Rockchip rockusb

Hi Marek,

Quoted 11 lines · Marek Vasut
Quoted 10 lines · Eddie Cai

2017-03-17 5:26 GMT+08:00 Marek Vasut <[email protected]>:

Quoted 8 lines · Eddie Cai
Quoted 1 line

rockusb is a protocol run between host pc and device. it help people get

device

Quoted 1 line

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 ?

Quoted 6 lines
Quoted 3 lines

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

#31 lore raw

cover introduce Rockchip rockusb

Quoted 18 lines · Simon Glass

Hi Marek,

Quoted 15 lines · Marek Vasut
Quoted 13 lines · Eddie Cai

2017-03-17 5:26 GMT+08:00 Marek Vasut <[email protected]>:

Quoted 8 lines · Eddie Cai
Quoted 1 line

rockusb is a protocol run between host pc and device. it help people get

device

Quoted 1 line

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.

Quoted 5 lines
Quoted 2 lines

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.

Quoted 1 line

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

Yes.

Signature · 2 lines
Best regards,
Marek Vasut
#32 lore raw

cover introduce Rockchip rockusb

Hi Marek,

Quoted 17 lines · Marek Vasut
Quoted 16 lines · Simon Glass

Hi Marek,

Quoted 13 lines · Marek Vasut
Quoted 12 lines · Eddie Cai

2017-03-17 5:26 GMT+08:00 Marek Vasut <[email protected]>:

Quoted 7 lines · Eddie Cai
Quoted 1 line

rockusb is a protocol run between host pc and device. it help people get

device

Quoted 1 line

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.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

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

Quoted 4 lines
Quoted 2 lines

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

Yes.

#33 lore raw

cover introduce Rockchip rockusb

Quoted 28 lines · Kever Yang

Hi Marek,

Quoted 17 lines · Marek Vasut
Quoted 16 lines · Simon Glass

Hi Marek,

Quoted 13 lines · Marek Vasut
Quoted 12 lines · Eddie Cai

2017-03-17 5:26 GMT+08:00 Marek Vasut <[email protected]>:

Quoted 7 lines · Eddie Cai
Quoted 1 line

rockusb is a protocol run between host pc and device. it help people get

device

Quoted 1 line

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.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

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.

Quoted 10 lines

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.

Signature · 8 lines
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>
#34 lore raw

cover introduce Rockchip rockusb

In reply to Eddie Cai

HI Eddie,

Quoted 3 lines

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).

Quoted 11 lines

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
Quoted 7 lines

++++++++++++++++++++++++++++++++++++++++
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

author
#35 lore raw

cover introduce Rockchip rockusb

Hi Lukasz

2017-03-27 16:27 GMT+08:00 Lukasz Majewski <[email protected]>:

Quoted 6 lines

HI Eddie,

Quoted 3 lines

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.

Quoted 7 lines

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

Quoted 31 lines
Quoted 12 lines

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
Quoted 7 lines

++++++++++++++++++++++++++++++++++++++++
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