get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/806415/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 806415,
    "url": "http://patchwork.ozlabs.org/api/patches/806415/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/1503905040-17618-2-git-send-email-eddie.cai.linux@gmail.com/",
    "project": {
        "id": 18,
        "url": "http://patchwork.ozlabs.org/api/projects/18/?format=api",
        "name": "U-Boot",
        "link_name": "uboot",
        "list_id": "u-boot.lists.denx.de",
        "list_email": "u-boot@lists.denx.de",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<1503905040-17618-2-git-send-email-eddie.cai.linux@gmail.com>",
    "list_archive_url": null,
    "date": "2017-08-28T07:23:57",
    "name": "[U-Boot,V8,1/4] usb: rockchip: add the rockusb gadget",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": false,
    "hash": "b4a47182cad007bcc4928a6c36d9460efb4cf03b",
    "submitter": {
        "id": 70800,
        "url": "http://patchwork.ozlabs.org/api/people/70800/?format=api",
        "name": "Eddie Cai",
        "email": "eddie.cai.linux@gmail.com"
    },
    "delegate": {
        "id": 69486,
        "url": "http://patchwork.ozlabs.org/api/users/69486/?format=api",
        "username": "ptomsich",
        "first_name": "Philipp",
        "last_name": "Tomsich",
        "email": "philipp.tomsich@theobroma-systems.com"
    },
    "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/1503905040-17618-2-git-send-email-eddie.cai.linux@gmail.com/mbox/",
    "series": [
        {
            "id": 93,
            "url": "http://patchwork.ozlabs.org/api/series/93/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=93",
            "date": "2017-08-28T07:23:56",
            "name": "introduce Rockchip rockusb",
            "version": 8,
            "mbox": "http://patchwork.ozlabs.org/series/93/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/806415/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/806415/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<u-boot-bounces@lists.denx.de>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org",
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.denx.de\n\t(client-ip=81.169.180.215; helo=lists.denx.de;\n\tenvelope-from=u-boot-bounces@lists.denx.de;\n\treceiver=<UNKNOWN>)",
            "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"Mjngt81o\"; dkim-atps=neutral"
        ],
        "Received": [
            "from lists.denx.de (dione.denx.de [81.169.180.215])\n\tby ozlabs.org (Postfix) with ESMTP id 3xgjwG5LrMz9sD9\n\tfor <incoming@patchwork.ozlabs.org>;\n\tMon, 28 Aug 2017 17:25:18 +1000 (AEST)",
            "by lists.denx.de (Postfix, from userid 105)\n\tid 7105CC21C54; Mon, 28 Aug 2017 07:25:10 +0000 (UTC)",
            "from lists.denx.de (localhost [IPv6:::1])\n\tby lists.denx.de (Postfix) with ESMTP id 045A4C2244B;\n\tMon, 28 Aug 2017 07:25:00 +0000 (UTC)",
            "by lists.denx.de (Postfix, from userid 105)\n\tid DB439C22454; Mon, 28 Aug 2017 07:24:44 +0000 (UTC)",
            "from mail-pf0-f196.google.com (mail-pf0-f196.google.com\n\t[209.85.192.196])\n\tby lists.denx.de (Postfix) with ESMTPS id 33C38C22446\n\tfor <u-boot@lists.denx.de>; Mon, 28 Aug 2017 07:24:40 +0000 (UTC)",
            "by mail-pf0-f196.google.com with SMTP id p69so3632746pfk.1\n\tfor <u-boot@lists.denx.de>; Mon, 28 Aug 2017 00:24:40 -0700 (PDT)",
            "from localhost.localdomain ([103.29.142.67])\n\tby smtp.gmail.com with ESMTPSA id\n\tf16sm22860100pfd.55.2017.08.28.00.24.33\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n\tMon, 28 Aug 2017 00:24:37 -0700 (PDT)"
        ],
        "X-Spam-Checker-Version": "SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de",
        "X-Spam-Level": "",
        "X-Spam-Status": "No, score=0.0 required=5.0 tests=FREEMAIL_FROM, KHOP_BIG_TO_CC,\n\tRCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,\n\tT_DKIM_INVALID autolearn=unavailable\n\tautolearn_force=no version=3.4.0",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=s78a0+GPpfkhVJsySgcrC2SMcH4k8/FBZE07twlVEjE=;\n\tb=Mjngt81ojWTU3wMPiw/e6oC9963AkI+V9wAWhbU9uBMhO1VplvJCepRwobMuE8cd3Q\n\toDfdx+HtIyo+OoWVJnG97gMYB8b8vsLw0wM6WuvzJX5I8jLN5yGe8l51PuoSWO/wRUpd\n\tLPrYEjBvggPCKzK91VY/R328uLREjlxkIpGb1aVhveuirWjT/wh/RoDdY8flq2UI1txa\n\tGFhUeVU5olrMWYYFpUlHQXXEqPru7BdNRzywuHnvKjMFyUE0kYiS6kiAJJR1XoL6oeSO\n\tyT8Ecj46nCXAKy+fzj3Ydv8ArfjTdSyKw+tGxgDkjONO8TYjAocTJug+8Oit/M4vA0QQ\n\t2CdQ==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=s78a0+GPpfkhVJsySgcrC2SMcH4k8/FBZE07twlVEjE=;\n\tb=VYEgY9G6y20DD+UbtVoH8uiMDVwslKD1AmlSyBs8/uv8xl+WEobznG20EmI4214lCg\n\tA+5cZem3V7Q9p41ZAlI+IMGuyM26+WqmEDVvE6dASmolKLqnG90R9UlGnDMonolzrNPB\n\twU0Np2LBHkoDQU25Dr1X9RiE9/gQQiFMddEfmb9NaKfmL4D1uh2cWLTB0ZWkI7mJ/5lc\n\ti/dNnZ7q5rNj+PucPJhrBQqFXym3vJ2oED5f2qZApTO8znKjrsuVdJUomdQI0IOl89sV\n\tjYXdoIXMjGKTxk6O8qSvUvjTn9JMkPxO69dKdfVVKf2bhHDldxh3j2NYAaXuWmASS8zZ\n\t1c/w==",
        "X-Gm-Message-State": "AHYfb5hT3kVZavVRr8gMS3ppjnWR6TB/uoBmWR5gMPACc33/V4BtTVNu\n\tMf6enxtlpRRXJw==",
        "X-Received": "by 10.98.75.2 with SMTP id y2mr6352285pfa.193.1503905078684;\n\tMon, 28 Aug 2017 00:24:38 -0700 (PDT)",
        "From": "Eddie Cai <eddie.cai.linux@gmail.com>",
        "To": "lukma@denx.de, sjg@chromium.org, marex@denx.de, trini@konsulko.com,\n\twilliam.wu@rock-chips.com, yamada.masahiro@socionext.com,\n\tmaxime.ripard@free-electrons.com, agraf@suse.de, bmeng.cn@gmail.com, \n\tyanmiaobest@gmail.com, dinguyen@kernel.org,\n\tboris.brezillon@free-electrons.com, sr@denx.de,\n\turi.mashiach@compulab.co.il, michal.simek@xilinx.com",
        "Date": "Mon, 28 Aug 2017 15:23:57 +0800",
        "Message-Id": "<1503905040-17618-2-git-send-email-eddie.cai.linux@gmail.com>",
        "X-Mailer": "git-send-email 1.9.1",
        "In-Reply-To": "<1503905040-17618-1-git-send-email-eddie.cai.linux@gmail.com>",
        "References": "<1503905040-17618-1-git-send-email-eddie.cai.linux@gmail.com>",
        "Cc": "u-boot@lists.denx.de",
        "Subject": "[U-Boot] [PATCH V8 1/4] usb: rockchip: add the rockusb gadget",
        "X-BeenThere": "u-boot@lists.denx.de",
        "X-Mailman-Version": "2.1.18",
        "Precedence": "list",
        "List-Id": "U-Boot discussion <u-boot.lists.denx.de>",
        "List-Unsubscribe": "<https://lists.denx.de/options/u-boot>,\n\t<mailto:u-boot-request@lists.denx.de?subject=unsubscribe>",
        "List-Archive": "<http://lists.denx.de/pipermail/u-boot/>",
        "List-Post": "<mailto:u-boot@lists.denx.de>",
        "List-Help": "<mailto:u-boot-request@lists.denx.de?subject=help>",
        "List-Subscribe": "<https://lists.denx.de/listinfo/u-boot>,\n\t<mailto:u-boot-request@lists.denx.de?subject=subscribe>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "base64",
        "Errors-To": "u-boot-bounces@lists.denx.de",
        "Sender": "\"U-Boot\" <u-boot-bounces@lists.denx.de>"
    },
    "content": "this patch implement rockusb protocol on the device side. this is based on USB\ndownload gadget infrastructure. the rockusb function implements the rd, wl, rid\ncommands. it can work with rkdeveloptool\n\nSigned-off-by: Eddie Cai <eddie.cai.linux@gmail.com>\nReviewed-by: Simon Glass <sjg@chromium.org>\n\nChanges in v8:                                                                  \n-none\n\nChanges in v7:\n-none\n\nChanges in v6:\n-move some data to f_rockusb structure\n\nChanges in v5:\n-fix build error when build non-rockchip board\n-fix checkpatch error\n\nChanges in v4:\n-use enum instead of macro define\n-move some structure define and macro to f_rockusb.h\n-add some function comment as Simon required\n-address other comment from Simon\n-fix build error as Lukasz point out\n\n---\n arch/arm/include/asm/arch-rockchip/f_rockusb.h | 132 +++++\n drivers/usb/gadget/Kconfig                     |   8 +\n drivers/usb/gadget/Makefile                    |   1 +\n drivers/usb/gadget/f_rockusb.c                 | 691 +++++++++++++++++++++++++\n 4 files changed, 832 insertions(+)\n create mode 100644 arch/arm/include/asm/arch-rockchip/f_rockusb.h\n create mode 100644 drivers/usb/gadget/f_rockusb.c",
    "diff": "diff --git a/arch/arm/include/asm/arch-rockchip/f_rockusb.h b/arch/arm/include/asm/arch-rockchip/f_rockusb.h\nnew file mode 100644\nindex 0000000..c207a78\n--- /dev/null\n+++ b/arch/arm/include/asm/arch-rockchip/f_rockusb.h\n@@ -0,0 +1,132 @@\n+/*\n+ * (C) Copyright 2017\n+ *\n+ * Eddie Cai <eddie.cai.linux@gmail.com>\n+ *\n+ * SPDX-License-Identifier:\tGPL-2.0+\n+ */\n+\n+#ifndef _F_ROCKUSB_H_\n+#define _F_ROCKUSB_H_\n+#include <blk.h>\n+\n+#define ROCKUSB_VERSION\t\t\"0.1\"\n+\n+#define ROCKUSB_INTERFACE_CLASS\t0xff\n+#define ROCKUSB_INTERFACE_SUB_CLASS\t0x06\n+#define ROCKUSB_INTERFACE_PROTOCOL\t0x05\n+\n+#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0  (0x0200)\n+#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1  (0x0040)\n+#define TX_ENDPOINT_MAXIMUM_PACKET_SIZE      (0x0040)\n+\n+#define EP_BUFFER_SIZE\t\t\t4096\n+/*\n+ * EP_BUFFER_SIZE must always be an integral multiple of maxpacket size\n+ * (64 or 512 or 1024), else we break on certain controllers like DWC3\n+ * that expect bulk OUT requests to be divisible by maxpacket size.\n+ */\n+\n+#define CONFIG_ROCKUSB_BUF_ADDR\t\tCONFIG_SYS_LOAD_ADDR\n+#define CONFIG_ROCKUSB_BUF_SIZE\t\t0x08000000\n+\n+#define RKUSB_STATUS_IDLE\t\t\t0\n+#define RKUSB_STATUS_CMD\t\t\t1\n+#define RKUSB_STATUS_RXDATA\t\t\t2\n+#define RKUSB_STATUS_TXDATA\t\t\t3\n+#define RKUSB_STATUS_CSW\t\t\t4\n+#define RKUSB_STATUS_RXDATA_PREPARE\t\t5\n+#define RKUSB_STATUS_TXDATA_PREPARE\t\t6\n+\n+enum rkusb_command {\n+K_FW_TEST_UNIT_READY\t= 0x00,\n+K_FW_READ_FLASH_ID = 0x01,\n+K_FW_SET_DEVICE_ID = 0x02,\n+K_FW_TEST_BAD_BLOCK = 0x03,\n+K_FW_READ_10 = 0x04,\n+K_FW_WRITE_10 = 0x05,\n+K_FW_ERASE_10 = 0x06,\n+K_FW_WRITE_SPARE = 0x07,\n+K_FW_READ_SPARE = 0x08,\n+\n+K_FW_ERASE_10_FORCE = 0x0b,\n+K_FW_GET_VERSION = 0x0c,\n+\n+K_FW_LBA_READ_10 = 0x14,\n+K_FW_LBA_WRITE_10 = 0x15,\n+K_FW_ERASE_SYS_DISK = 0x16,\n+K_FW_SDRAM_READ_10 = 0x17,\n+K_FW_SDRAM_WRITE_10 = 0x18,\n+K_FW_SDRAM_EXECUTE = 0x19,\n+K_FW_READ_FLASH_INFO = 0x1A,\n+K_FW_GET_CHIP_VER = 0x1B,\n+K_FW_LOW_FORMAT = 0x1C,\n+K_FW_SET_RESET_FLAG = 0x1E,\n+K_FW_SPI_READ_10 = 0x21,\n+K_FW_SPI_WRITE_10 = 0x22,\n+\n+K_FW_SESSION = 0X30,\n+K_FW_RESET = 0xff,\n+};\n+\n+#define CBW_DIRECTION_OUT\t\t0x00\n+#define CBW_DIRECTION_IN\t\t0x80\n+\n+struct cmd_dispatch_info {\n+\tenum rkusb_command cmd;\n+\t/* call back function to handle rockusb command */\n+\tvoid (*cb)(struct usb_ep *ep, struct usb_request *req);\n+};\n+\n+/* Bulk-only data structures */\n+\n+/* Command Block Wrapper */\n+struct fsg_bulk_cb_wrap {\n+\t__le32  signature;              /* Contains 'USBC' */\n+\tu32     tag;                    /* Unique per command id */\n+\t__le32  data_transfer_length;   /* Size of the data */\n+\tu8      flags;                  /* Direction in bit 7 */\n+\tu8      lun;                    /* lun (normally 0) */\n+\tu8      length;                 /* Of the CDB, <= MAX_COMMAND_SIZE */\n+\tu8      CDB[16];                /* Command Data Block */\n+};\n+\n+#define USB_BULK_CB_WRAP_LEN    31\n+#define USB_BULK_CB_SIG         0x43425355      /* Spells out USBC */\n+#define USB_BULK_IN_FLAG        0x80\n+\n+/* Command status Wrapper */\n+struct bulk_cs_wrap {\n+\t__le32  signature;              /* Should = 'USBS' */\n+\tu32     tag;                    /* Same as original command */\n+\t__le32  residue;                /* Amount not transferred */\n+\tu8      status;                 /* See below */\n+};\n+\n+#define USB_BULK_CS_WRAP_LEN    13\n+#define USB_BULK_CS_SIG         0x53425355      /* Spells out 'USBS' */\n+#define USB_STATUS_PASS         0\n+#define USB_STATUS_FAIL         1\n+#define USB_STATUS_PHASE_ERROR  2\n+\n+#define CSW_GOOD                0x00\n+#define CSW_FAIL                0x01\n+\n+struct f_rockusb {\n+\tstruct usb_function usb_function;\n+\tstruct usb_ep *in_ep, *out_ep;\n+\tstruct usb_request *in_req, *out_req;\n+\tchar *rockusb_dev_type;\n+\tunsigned int rockusb_dev_index;\n+\tunsigned int download_tag;\n+\tunsigned int download_lba;\n+\tunsigned int download_size;\n+\tunsigned int download_bytes;\n+\tstruct blk_desc *download_desc;\n+\tint reboot_flag;\n+};\n+\n+/* init rockusb device, tell rockusb which device you want to read/write*/\n+void rockusb_dev_init(char *dev_type, int dev_index);\n+#endif /* _F_ROCKUSB_H_ */\n+\ndiff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig\nindex 261ed12..d61d9ad 100644\n--- a/drivers/usb/gadget/Kconfig\n+++ b/drivers/usb/gadget/Kconfig\n@@ -112,6 +112,14 @@ config G_DNL_VENDOR_NUM\n config G_DNL_PRODUCT_NUM\n \thex \"Product ID of USB device\"\n \n+config USB_FUNCTION_ROCKUSB\n+\tbool \"Enable USB rockusb gadget\"\n+\thelp\n+\t  Rockusb protocol is widely used by Rockchip SoC based devices. It can\n+\t  read/write info, image to/from devices. This enables the USB part of\n+\t  the rockusb gadget.for more detail about Rockusb protocol, please see\n+\t  doc/README.rockusb\n+\n config USBNET_DEVADDR\n \tstring \"USB Gadget Ethernet device mac address\"\n \tdefault \"de:ad:be:ef:00:01\"\ndiff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile\nindex 5e316a7..a3fb2c8 100644\n--- a/drivers/usb/gadget/Makefile\n+++ b/drivers/usb/gadget/Makefile\n@@ -28,6 +28,7 @@ obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o\n obj-$(CONFIG_USB_FUNCTION_DFU) += f_dfu.o\n obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o\n obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o\n+obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o\n endif\n endif\n ifdef CONFIG_USB_ETHER\ndiff --git a/drivers/usb/gadget/f_rockusb.c b/drivers/usb/gadget/f_rockusb.c\nnew file mode 100644\nindex 0000000..efd110b\n--- /dev/null\n+++ b/drivers/usb/gadget/f_rockusb.c\n@@ -0,0 +1,691 @@\n+/*\n+ * (C) Copyright 2017\n+ *\n+ * Eddie Cai <eddie.cai.linux@gmail.com>\n+ *\n+ * SPDX-License-Identifier:\tGPL-2.0+\n+ */\n+\n+#include <config.h>\n+#include <common.h>\n+#include <errno.h>\n+#include <malloc.h>\n+#include <memalign.h>\n+#include <linux/usb/ch9.h>\n+#include <linux/usb/gadget.h>\n+#include <linux/usb/composite.h>\n+#include <linux/compiler.h>\n+#include <version.h>\n+#include <g_dnl.h>\n+#include <asm/arch/f_rockusb.h>\n+\n+static inline struct f_rockusb *func_to_rockusb(struct usb_function *f)\n+{\n+\treturn container_of(f, struct f_rockusb, usb_function);\n+}\n+\n+static struct usb_endpoint_descriptor fs_ep_in = {\n+\t.bLength            = USB_DT_ENDPOINT_SIZE,\n+\t.bDescriptorType    = USB_DT_ENDPOINT,\n+\t.bEndpointAddress   = USB_DIR_IN,\n+\t.bmAttributes       = USB_ENDPOINT_XFER_BULK,\n+\t.wMaxPacketSize     = cpu_to_le16(64),\n+};\n+\n+static struct usb_endpoint_descriptor fs_ep_out = {\n+\t.bLength\t\t= USB_DT_ENDPOINT_SIZE,\n+\t.bDescriptorType\t= USB_DT_ENDPOINT,\n+\t.bEndpointAddress\t= USB_DIR_OUT,\n+\t.bmAttributes\t\t= USB_ENDPOINT_XFER_BULK,\n+\t.wMaxPacketSize\t\t= cpu_to_le16(64),\n+};\n+\n+static struct usb_endpoint_descriptor hs_ep_in = {\n+\t.bLength\t\t= USB_DT_ENDPOINT_SIZE,\n+\t.bDescriptorType\t= USB_DT_ENDPOINT,\n+\t.bEndpointAddress\t= USB_DIR_IN,\n+\t.bmAttributes\t\t= USB_ENDPOINT_XFER_BULK,\n+\t.wMaxPacketSize\t\t= cpu_to_le16(512),\n+};\n+\n+static struct usb_endpoint_descriptor hs_ep_out = {\n+\t.bLength\t\t= USB_DT_ENDPOINT_SIZE,\n+\t.bDescriptorType\t= USB_DT_ENDPOINT,\n+\t.bEndpointAddress\t= USB_DIR_OUT,\n+\t.bmAttributes\t\t= USB_ENDPOINT_XFER_BULK,\n+\t.wMaxPacketSize\t\t= cpu_to_le16(512),\n+};\n+\n+static struct usb_interface_descriptor interface_desc = {\n+\t.bLength\t\t= USB_DT_INTERFACE_SIZE,\n+\t.bDescriptorType\t= USB_DT_INTERFACE,\n+\t.bInterfaceNumber\t= 0x00,\n+\t.bAlternateSetting\t= 0x00,\n+\t.bNumEndpoints\t\t= 0x02,\n+\t.bInterfaceClass\t= ROCKUSB_INTERFACE_CLASS,\n+\t.bInterfaceSubClass\t= ROCKUSB_INTERFACE_SUB_CLASS,\n+\t.bInterfaceProtocol\t= ROCKUSB_INTERFACE_PROTOCOL,\n+};\n+\n+static struct usb_descriptor_header *rkusb_fs_function[] = {\n+\t(struct usb_descriptor_header *)&interface_desc,\n+\t(struct usb_descriptor_header *)&fs_ep_in,\n+\t(struct usb_descriptor_header *)&fs_ep_out,\n+};\n+\n+static struct usb_descriptor_header *rkusb_hs_function[] = {\n+\t(struct usb_descriptor_header *)&interface_desc,\n+\t(struct usb_descriptor_header *)&hs_ep_in,\n+\t(struct usb_descriptor_header *)&hs_ep_out,\n+\tNULL,\n+};\n+\n+static const char rkusb_name[] = \"Rockchip Rockusb\";\n+\n+static struct usb_string rkusb_string_defs[] = {\n+\t[0].s = rkusb_name,\n+\t{  }\t\t\t/* end of list */\n+};\n+\n+static struct usb_gadget_strings stringtab_rkusb = {\n+\t.language\t= 0x0409,\t/* en-us */\n+\t.strings\t= rkusb_string_defs,\n+};\n+\n+static struct usb_gadget_strings *rkusb_strings[] = {\n+\t&stringtab_rkusb,\n+\tNULL,\n+};\n+\n+static struct f_rockusb *rockusb_func;\n+static void rx_handler_command(struct usb_ep *ep, struct usb_request *req);\n+static int rockusb_tx_write_csw(u32 tag, int residue, u8 status, int size);\n+\n+struct f_rockusb *get_rkusb(void)\n+{\n+\tstruct f_rockusb *f_rkusb = rockusb_func;\n+\tif (!f_rkusb) {\n+\t\tf_rkusb = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_rkusb));\n+\t\tif (!f_rkusb)\n+\t\t\treturn 0;\n+\n+\t\trockusb_func = f_rkusb;\n+\t\tmemset(f_rkusb, 0, sizeof(*f_rkusb));\n+\t}\n+\treturn f_rkusb;\n+}\n+\n+static struct usb_endpoint_descriptor *rkusb_ep_desc(\n+struct usb_gadget *g,\n+struct usb_endpoint_descriptor *fs,\n+struct usb_endpoint_descriptor *hs)\n+{\n+\tif (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)\n+\t\treturn hs;\n+\treturn fs;\n+}\n+\n+static void rockusb_complete(struct usb_ep *ep, struct usb_request *req)\n+{\n+\tint status = req->status;\n+\tif (!status)\n+\t\treturn;\n+\tdebug(\"status: %d ep '%s' trans: %d\\n\", status, ep->name, req->actual);\n+}\n+\n+/* config the rockusb device*/\n+static int rockusb_bind(struct usb_configuration *c, struct usb_function *f)\n+{\n+\tint id;\n+\tstruct usb_gadget *gadget = c->cdev->gadget;\n+\tstruct f_rockusb *f_rkusb = func_to_rockusb(f);\n+\tconst char *s;\n+\n+\tid = usb_interface_id(c, f);\n+\tif (id < 0)\n+\t\treturn id;\n+\tinterface_desc.bInterfaceNumber = id;\n+\n+\tid = usb_string_id(c->cdev);\n+\tif (id < 0)\n+\t\treturn id;\n+\n+\trkusb_string_defs[0].id = id;\n+\tinterface_desc.iInterface = id;\n+\n+\tf_rkusb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in);\n+\tif (!f_rkusb->in_ep)\n+\t\treturn -ENODEV;\n+\tf_rkusb->in_ep->driver_data = c->cdev;\n+\n+\tf_rkusb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out);\n+\tif (!f_rkusb->out_ep)\n+\t\treturn -ENODEV;\n+\tf_rkusb->out_ep->driver_data = c->cdev;\n+\n+\tf->descriptors = rkusb_fs_function;\n+\n+\tif (gadget_is_dualspeed(gadget)) {\n+\t\ths_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress;\n+\t\ths_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress;\n+\t\tf->hs_descriptors = rkusb_hs_function;\n+\t}\n+\n+\ts = getenv(\"serial#\");\n+\tif (s)\n+\t\tg_dnl_set_serialnumber((char *)s);\n+\n+\treturn 0;\n+}\n+\n+static void rockusb_unbind(struct usb_configuration *c, struct usb_function *f)\n+{\n+\t/* clear the configuration*/\n+\tmemset(rockusb_func, 0, sizeof(*rockusb_func));\n+}\n+\n+static void rockusb_disable(struct usb_function *f)\n+{\n+\tstruct f_rockusb *f_rkusb = func_to_rockusb(f);\n+\n+\tusb_ep_disable(f_rkusb->out_ep);\n+\tusb_ep_disable(f_rkusb->in_ep);\n+\n+\tif (f_rkusb->out_req) {\n+\t\tfree(f_rkusb->out_req->buf);\n+\t\tusb_ep_free_request(f_rkusb->out_ep, f_rkusb->out_req);\n+\t\tf_rkusb->out_req = NULL;\n+\t}\n+\tif (f_rkusb->in_req) {\n+\t\tfree(f_rkusb->in_req->buf);\n+\t\tusb_ep_free_request(f_rkusb->in_ep, f_rkusb->in_req);\n+\t\tf_rkusb->in_req = NULL;\n+\t}\n+}\n+\n+static struct usb_request *rockusb_start_ep(struct usb_ep *ep)\n+{\n+\tstruct usb_request *req;\n+\n+\treq = usb_ep_alloc_request(ep, 0);\n+\tif (!req)\n+\t\treturn NULL;\n+\n+\treq->length = EP_BUFFER_SIZE;\n+\treq->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE);\n+\tif (!req->buf) {\n+\t\tusb_ep_free_request(ep, req);\n+\t\treturn NULL;\n+\t}\n+\tmemset(req->buf, 0, req->length);\n+\n+\treturn req;\n+}\n+\n+static int rockusb_set_alt(struct usb_function *f,\n+\t\t\t    unsigned interface, unsigned alt)\n+{\n+\tint ret;\n+\tstruct usb_composite_dev *cdev = f->config->cdev;\n+\tstruct usb_gadget *gadget = cdev->gadget;\n+\tstruct f_rockusb *f_rkusb = func_to_rockusb(f);\n+\tconst struct usb_endpoint_descriptor *d;\n+\n+\tdebug(\"%s: func: %s intf: %d alt: %d\\n\",\n+\t      __func__, f->name, interface, alt);\n+\n+\td = rkusb_ep_desc(gadget, &fs_ep_out, &hs_ep_out);\n+\tret = usb_ep_enable(f_rkusb->out_ep, d);\n+\tif (ret) {\n+\t\tprintf(\"failed to enable out ep\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\tf_rkusb->out_req = rockusb_start_ep(f_rkusb->out_ep);\n+\tif (!f_rkusb->out_req) {\n+\t\tprintf(\"failed to alloc out req\\n\");\n+\t\tret = -EINVAL;\n+\t\tgoto err;\n+\t}\n+\tf_rkusb->out_req->complete = rx_handler_command;\n+\n+\td = rkusb_ep_desc(gadget, &fs_ep_in, &hs_ep_in);\n+\tret = usb_ep_enable(f_rkusb->in_ep, d);\n+\tif (ret) {\n+\t\tprintf(\"failed to enable in ep\\n\");\n+\t\tgoto err;\n+\t}\n+\n+\tf_rkusb->in_req = rockusb_start_ep(f_rkusb->in_ep);\n+\tif (!f_rkusb->in_req) {\n+\t\tprintf(\"failed alloc req in\\n\");\n+\t\tret = -EINVAL;\n+\t\tgoto err;\n+\t}\n+\tf_rkusb->in_req->complete = rockusb_complete;\n+\n+\tret = usb_ep_queue(f_rkusb->out_ep, f_rkusb->out_req, 0);\n+\tif (ret)\n+\t\tgoto err;\n+\n+\treturn 0;\n+err:\n+\trockusb_disable(f);\n+\treturn ret;\n+}\n+\n+static int rockusb_add(struct usb_configuration *c)\n+{\n+\tstruct f_rockusb *f_rkusb = get_rkusb();\n+\tint status;\n+\n+\tdebug(\"%s: cdev: 0x%p\\n\", __func__, c->cdev);\n+\n+\tf_rkusb->usb_function.name = \"f_rockusb\";\n+\tf_rkusb->usb_function.bind = rockusb_bind;\n+\tf_rkusb->usb_function.unbind = rockusb_unbind;\n+\tf_rkusb->usb_function.set_alt = rockusb_set_alt;\n+\tf_rkusb->usb_function.disable = rockusb_disable;\n+\tf_rkusb->usb_function.strings = rkusb_strings;\n+\n+\tstatus = usb_add_function(c, &f_rkusb->usb_function);\n+\tif (status) {\n+\t\tfree(f_rkusb);\n+\t\trockusb_func = f_rkusb;\n+\t}\n+\treturn status;\n+}\n+\n+void rockusb_dev_init(char *dev_type, int dev_index)\n+{\n+\tstruct f_rockusb *f_rkusb = get_rkusb();\n+\tf_rkusb->rockusb_dev_type = dev_type;\n+\tf_rkusb->rockusb_dev_index = dev_index;\n+}\n+\n+DECLARE_GADGET_BIND_CALLBACK(usb_dnl_rockusb, rockusb_add);\n+\n+static int rockusb_tx_write(const char *buffer, unsigned int buffer_size)\n+{\n+\tstruct usb_request *in_req = rockusb_func->in_req;\n+\tint ret;\n+\n+\tmemcpy(in_req->buf, buffer, buffer_size);\n+\tin_req->length = buffer_size;\n+\tusb_ep_dequeue(rockusb_func->in_ep, in_req);\n+\tret = usb_ep_queue(rockusb_func->in_ep, in_req, 0);\n+\tif (ret)\n+\t\tprintf(\"Error %d on queue\\n\", ret);\n+\treturn 0;\n+}\n+\n+static int rockusb_tx_write_str(const char *buffer)\n+{\n+\treturn rockusb_tx_write(buffer, strlen(buffer));\n+}\n+\n+#ifdef DEBUG\n+static void printcbw(char *buf)\n+{\n+\tALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,\n+\t\t\t\t sizeof(struct fsg_bulk_cb_wrap));\n+\n+\tmemcpy((char *)cbw, buf, USB_BULK_CB_WRAP_LEN);\n+\n+\tdebug(\"cbw: signature:%x\\n\", cbw->signature);\n+\tdebug(\"cbw: tag=%x\\n\", cbw->tag);\n+\tdebug(\"cbw: data_transfer_length=%d\\n\", cbw->data_transfer_length);\n+\tdebug(\"cbw: flags=%x\\n\", cbw->flags);\n+\tdebug(\"cbw: lun=%d\\n\", cbw->lun);\n+\tdebug(\"cbw: length=%d\\n\", cbw->length);\n+\tdebug(\"cbw: ucOperCode=%x\\n\", cbw->CDB[0]);\n+\tdebug(\"cbw: ucReserved=%x\\n\", cbw->CDB[1]);\n+\tdebug(\"cbw: dwAddress:%x %x %x %x\\n\", cbw->CDB[5], cbw->CDB[4],\n+\t      cbw->CDB[3], cbw->CDB[2]);\n+\tdebug(\"cbw: ucReserved2=%x\\n\", cbw->CDB[6]);\n+\tdebug(\"cbw: uslength:%x %x\\n\", cbw->CDB[8], cbw->CDB[7]);\n+}\n+\n+static void printcsw(char *buf)\n+{\n+\tALLOC_CACHE_ALIGN_BUFFER(struct bulk_cs_wrap, csw,\n+\t\t\t\t sizeof(struct bulk_cs_wrap));\n+\tmemcpy((char *)csw, buf, USB_BULK_CS_WRAP_LEN);\n+\tdebug(\"csw: signature:%x\\n\", csw->signature);\n+\tdebug(\"csw: tag:%x\\n\", csw->tag);\n+\tdebug(\"csw: residue:%x\\n\", csw->residue);\n+\tdebug(\"csw: status:%x\\n\", csw->status);\n+}\n+#endif\n+\n+static int rockusb_tx_write_csw(u32 tag, int residue, u8 status, int size)\n+{\n+\tALLOC_CACHE_ALIGN_BUFFER(struct bulk_cs_wrap, csw,\n+\t\t\t\t sizeof(struct bulk_cs_wrap));\n+\tcsw->signature = cpu_to_le32(USB_BULK_CS_SIG);\n+\tcsw->tag = tag;\n+\tcsw->residue = cpu_to_be32(residue);\n+\tcsw->status = status;\n+#ifdef DEBUG\n+\tprintcsw((char *)&csw);\n+#endif\n+\treturn rockusb_tx_write((char *)csw, size);\n+}\n+\n+static unsigned int rx_bytes_expected(struct usb_ep *ep)\n+{\n+\tstruct f_rockusb *f_rkusb = get_rkusb();\n+\tint rx_remain = f_rkusb->download_size - f_rkusb->download_bytes;\n+\tunsigned int rem;\n+\tunsigned int maxpacket = ep->maxpacket;\n+\n+\tif (rx_remain <= 0)\n+\t\treturn 0;\n+\telse if (rx_remain > EP_BUFFER_SIZE)\n+\t\treturn EP_BUFFER_SIZE;\n+\n+\trem = rx_remain % maxpacket;\n+\tif (rem > 0)\n+\t\trx_remain = rx_remain + (maxpacket - rem);\n+\n+\treturn rx_remain;\n+}\n+\n+/* usb_request complete call back to handle down load image */\n+static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)\n+{\n+\tstruct f_rockusb *f_rkusb = get_rkusb();\n+\tunsigned int transfer_size = 0;\n+\tconst unsigned char *buffer = req->buf;\n+\tunsigned int buffer_size = req->actual;\n+\n+\ttransfer_size = f_rkusb->download_size - f_rkusb->download_bytes;\n+\tif (!f_rkusb->download_desc) {\n+\t\tprintf(\"rx_handler_dl_image blk_get_dev\\n\");\n+\t\tf_rkusb->download_desc = blk_get_dev(f_rkusb->rockusb_dev_type,\n+\t\t\t\tf_rkusb->rockusb_dev_index);\n+\t\tif (!f_rkusb->download_desc ||\n+\t\t    f_rkusb->download_desc->type == DEV_TYPE_UNKNOWN) {\n+\t\t\terror(\"invalid mmc device\\n\");\n+\t\t\trockusb_tx_write_csw(f_rkusb->download_tag, 0, CSW_FAIL,\n+\t\t\t\t\t     USB_BULK_CS_WRAP_LEN);\n+\t\t\treturn;\n+\t\t}\n+\t}\n+\n+\tif (req->status != 0) {\n+\t\tprintf(\"Bad status: %d\\n\", req->status);\n+\t\trockusb_tx_write_csw(f_rkusb->download_tag, 0,\n+\t\t\t\t     CSW_FAIL, USB_BULK_CS_WRAP_LEN);\n+\t\treturn;\n+\t}\n+\n+\tif (buffer_size < transfer_size)\n+\t\ttransfer_size = buffer_size;\n+\n+\tmemcpy((void *)CONFIG_ROCKUSB_BUF_ADDR + f_rkusb->download_bytes,\n+\t       buffer, transfer_size);\n+\tf_rkusb->download_bytes += transfer_size;\n+\n+\t/* Check if transfer is done */\n+\tif (f_rkusb->download_bytes >= f_rkusb->download_size) {\n+\t\tint blks = 0, blkcnt = f_rkusb->download_size/512;\n+\t\tprintf(\"download %d bytes finished, start writing to lba %x\\n\",\n+\t\t       f_rkusb->download_bytes, f_rkusb->download_lba);\n+\t\tblks = blk_dwrite(f_rkusb->download_desc,\n+\t\t\t\t  f_rkusb->download_lba, blkcnt,\n+\t\t\t\t\t(char *)CONFIG_ROCKUSB_BUF_ADDR);\n+\t\tif (blks != blkcnt) {\n+\t\t\terror(\"failed writing to device %s: %d\\n\",\n+\t\t\t      f_rkusb->rockusb_dev_type,\n+\t\t\t      f_rkusb->rockusb_dev_index);\n+\t\t\trockusb_tx_write_csw(f_rkusb->download_tag, 0,\n+\t\t\t\t\t     CSW_FAIL, USB_BULK_CS_WRAP_LEN);\n+\t\t\treturn;\n+\t\t}\n+\n+\t\treq->complete = rx_handler_command;\n+\t\treq->length = EP_BUFFER_SIZE;\n+\t\tf_rkusb->download_size = 0;\n+\t\tprintf(\"done\\n\");\n+\t\trockusb_tx_write_csw(f_rkusb->download_tag, 0, CSW_GOOD,\n+\t\t\t\t     USB_BULK_CS_WRAP_LEN);\n+\t} else {\n+\t\treq->length = rx_bytes_expected(ep);\n+\t}\n+\n+\treq->actual = 0;\n+\tusb_ep_queue(ep, req, 0);\n+}\n+\n+static void cb_test_unit_ready(struct usb_ep *ep, struct usb_request *req)\n+{\n+\tALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,\n+\t\t\t\t sizeof(struct fsg_bulk_cb_wrap));\n+\n+\tmemcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);\n+\n+\trockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length,\n+\t\t\t     CSW_GOOD, USB_BULK_CS_WRAP_LEN);\n+}\n+\n+static void cb_read_storage_id(struct usb_ep *ep, struct usb_request *req)\n+{\n+\tALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,\n+\t\t\t\t sizeof(struct fsg_bulk_cb_wrap));\n+\tchar emmc_id[] = \"EMMC \";\n+\n+\tprintf(\"cb_read_storage_id\\n\");\n+\tmemcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);\n+\trockusb_tx_write_str(emmc_id);\n+\trockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length, CSW_GOOD,\n+\t\t\t     USB_BULK_CS_WRAP_LEN);\n+}\n+\n+static void cb_write_lba(struct usb_ep *ep, struct usb_request *req)\n+{\n+\tALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,\n+\t\t\t\t sizeof(struct fsg_bulk_cb_wrap));\n+\tint sector_count;\n+\tstruct f_rockusb *f_rkusb = get_rkusb();\n+\n+\tmemcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);\n+\tsector_count = (int)get_unaligned_be16(&cbw->CDB[7]);\n+\tf_rkusb->download_lba = get_unaligned_be32(&cbw->CDB[2]);\n+\tf_rkusb->download_size = sector_count * 512;\n+\tf_rkusb->download_bytes = 0;\n+\tf_rkusb->download_tag = cbw->tag;\n+\tif ((0 == f_rkusb->download_size) ||\n+\t    (f_rkusb->download_size > CONFIG_ROCKUSB_BUF_SIZE)) {\n+\t\trockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length,\n+\t\t\t\t     CSW_FAIL, USB_BULK_CS_WRAP_LEN);\n+\t} else {\n+\t\treq->complete = rx_handler_dl_image;\n+\t\treq->length = rx_bytes_expected(ep);\n+\t}\n+}\n+\n+int __weak rkusb_set_reboot_flag(int flag)\n+{\n+\tstruct f_rockusb *f_rkusb = get_rkusb();\n+\n+\tprintf(\"rkusb_set_reboot_flag: %d\\n\", f_rkusb->reboot_flag);\n+\treturn -ENOSYS;\n+}\n+\n+static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)\n+{\n+\tstruct f_rockusb *f_rkusb = get_rkusb();\n+\n+\trkusb_set_reboot_flag(f_rkusb->reboot_flag);\n+\tdo_reset(NULL, 0, 0, NULL);\n+}\n+\n+static void cb_reboot(struct usb_ep *ep, struct usb_request *req)\n+{\n+\tALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,\n+\t\t\t\t sizeof(struct fsg_bulk_cb_wrap));\n+\tstruct f_rockusb *f_rkusb = get_rkusb();\n+\n+\tf_rkusb->reboot_flag = 0;\n+\tmemcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);\n+\tf_rkusb->reboot_flag = cbw->CDB[1];\n+\trockusb_func->in_req->complete = compl_do_reset;\n+\trockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length, CSW_GOOD,\n+\t\t\t     USB_BULK_CS_WRAP_LEN);\n+}\n+\n+static void cb_not_support(struct usb_ep *ep, struct usb_request *req)\n+{\n+\tALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,\n+\t\t\t\t sizeof(struct fsg_bulk_cb_wrap));\n+\n+\tmemcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);\n+\tprintf(\"Rockusb command %x not support yet\\n\", cbw->CDB[0]);\n+\trockusb_tx_write_csw(cbw->tag, 0, CSW_FAIL, USB_BULK_CS_WRAP_LEN);\n+}\n+\n+static const struct cmd_dispatch_info cmd_dispatch_info[] = {\n+\t{\n+\t\t.cmd = K_FW_TEST_UNIT_READY,\n+\t\t.cb = cb_test_unit_ready,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_READ_FLASH_ID,\n+\t\t.cb = cb_read_storage_id,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_SET_DEVICE_ID,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_TEST_BAD_BLOCK,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_READ_10,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_WRITE_10,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_ERASE_10,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_WRITE_SPARE,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_READ_SPARE,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_ERASE_10_FORCE,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_GET_VERSION,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_LBA_READ_10,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_LBA_WRITE_10,\n+\t\t.cb = cb_write_lba,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_ERASE_SYS_DISK,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_SDRAM_READ_10,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_SDRAM_WRITE_10,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_SDRAM_EXECUTE,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_READ_FLASH_INFO,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_GET_CHIP_VER,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_LOW_FORMAT,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_SET_RESET_FLAG,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_SPI_READ_10,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_SPI_WRITE_10,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_SESSION,\n+\t\t.cb = cb_not_support,\n+\t},\n+\t{\n+\t\t.cmd = K_FW_RESET,\n+\t\t.cb = cb_reboot,\n+\t},\n+};\n+\n+static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)\n+{\n+\tvoid (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL;\n+\tALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,\n+\t\t\t\t sizeof(struct fsg_bulk_cb_wrap));\n+\tchar *cmdbuf = req->buf;\n+\tint i;\n+\n+\tif (req->status || req->length == 0)\n+\t\treturn;\n+\n+\tmemcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);\n+#ifdef DEBUG\n+\tprintcbw(req->buf);\n+#endif\n+\n+\tfor (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) {\n+\t\tif (cmd_dispatch_info[i].cmd == cbw->CDB[0]) {\n+\t\t\tfunc_cb = cmd_dispatch_info[i].cb;\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (!func_cb) {\n+\t\terror(\"unknown command: %s\", (char *)req->buf);\n+\t\trockusb_tx_write_str(\"FAILunknown command\");\n+\t} else {\n+\t\tif (req->actual < req->length) {\n+\t\t\tu8 *buf = (u8 *)req->buf;\n+\t\t\tbuf[req->actual] = 0;\n+\t\t\tfunc_cb(ep, req);\n+\t\t} else {\n+\t\t\terror(\"buffer overflow\");\n+\t\t\trockusb_tx_write_str(\"FAILbuffer overflow\");\n+\t\t}\n+\t}\n+\n+\t*cmdbuf = '\\0';\n+\treq->actual = 0;\n+\tusb_ep_queue(ep, req, 0);\n+}\n",
    "prefixes": [
        "U-Boot",
        "V8",
        "1/4"
    ]
}