This shows the basic approach with a new directory containing sandbox
emulations of USB devices for testing. So far hubs are not supported.

Signed-off-by: Simon Glass <s...@chromium.org>
---

 Makefile                             |   1 +
 arch/sandbox/dts/sandbox.dts         |  20 +++++
 arch/sandbox/include/asm/processor.h |   0
 drivers/usb/dev/Makefile             |  10 +++
 drivers/usb/dev/sandbox-flash.c      |  95 ++++++++++++++++++++++
 drivers/usb/dev/sandbox-hub.c        | 116 +++++++++++++++++++++++++++
 drivers/usb/dev/usb-emul-uclass.c    |  16 ++++
 drivers/usb/host/Makefile            |   3 +
 drivers/usb/host/usb-sandbox.c       | 151 +++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h            |   3 +
 include/dm/uclass-id.h               |   1 +
 include/usb_defs.h                   |  14 ++--
 12 files changed, 424 insertions(+), 6 deletions(-)
 create mode 100644 arch/sandbox/include/asm/processor.h
 create mode 100644 drivers/usb/dev/Makefile
 create mode 100644 drivers/usb/dev/sandbox-flash.c
 create mode 100644 drivers/usb/dev/sandbox-hub.c
 create mode 100644 drivers/usb/dev/usb-emul-uclass.c
 create mode 100644 drivers/usb/host/usb-sandbox.c

diff --git a/Makefile b/Makefile
index 9b406c8..836d93b 100644
--- a/Makefile
+++ b/Makefile
@@ -632,6 +632,7 @@ libs-y += drivers/spi/
 libs-$(CONFIG_FMAN_ENET) += drivers/net/fm/
 libs-$(CONFIG_SYS_FSL_DDR) += drivers/ddr/fsl/
 libs-y += drivers/serial/
+libs-y += drivers/usb/dev/
 libs-y += drivers/usb/eth/
 libs-y += drivers/usb/gadget/
 libs-y += drivers/usb/host/
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 9ce31bf..7d22920 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -181,4 +181,24 @@
                };
        };
 
+       usb@0 {
+               compatible = "sandbox,usb";
+               status = "disabled";
+               flash-stick {
+                       compatible = "sandbox,usb-flash";
+               };
+       };
+
+       usb@1 {
+               compatible = "sandbox,usb";
+               flash-stick {
+                       compatible = "sandbox,usb-hub";
+               };
+       };
+
+       usb@2 {
+               compatible = "sandbox,usb";
+               status = "disabled";
+       };
+
 };
diff --git a/arch/sandbox/include/asm/processor.h 
b/arch/sandbox/include/asm/processor.h
new file mode 100644
index 0000000..e69de29
diff --git a/drivers/usb/dev/Makefile b/drivers/usb/dev/Makefile
new file mode 100644
index 0000000..a741f45
--- /dev/null
+++ b/drivers/usb/dev/Makefile
@@ -0,0 +1,10 @@
+#
+# (C) Copyright 2015 Google, Inc
+# Written by Simon Glass <s...@chromium.org>
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-$(CONFIG_SANDBOX) += sandbox-flash.o
+obj-$(CONFIG_SANDBOX) += sandbox-hub.o
+obj-$(CONFIG_SANDBOX) += usb-emul-uclass.o
diff --git a/drivers/usb/dev/sandbox-flash.c b/drivers/usb/dev/sandbox-flash.c
new file mode 100644
index 0000000..51aec69
--- /dev/null
+++ b/drivers/usb/dev/sandbox-flash.c
@@ -0,0 +1,95 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <s...@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#define DEBUG
+#include <common.h>
+#include <dm.h>
+#include <usb.h>
+
+enum {
+       STRINGID_null,
+       STRINGID_manufacterer,
+       STRINGID_product,
+       STRINGID_serial,
+
+       STRINGID_count,
+};
+
+static char *usb_strings[] = {
+       "",
+       "sandbox",
+       "flash_emulator",
+       "1234",
+       NULL,
+};
+
+static int sandbox_flash_submit_control_msg(struct udevice *dev,
+                                           unsigned long pipe,
+                                           void *buffer, int length,
+                                           struct devrequest *setup)
+{
+       struct usb_device *udev = dev_get_uclass_priv(dev);
+
+       if (pipe == usb_rcvctrlpipe(udev, 0)) {
+               switch (setup->request) {
+               case USB_REQ_GET_DESCRIPTOR:
+                       memcpy(buffer, &udev->descriptor, length);
+                       udev->status = 0;
+                       udev->act_len = length;
+                       return 0;
+               default:
+                       debug("request=%x\n", setup->request);
+                       break;
+               }
+       }
+       debug("pipe=%lx\n", pipe);
+
+       return -EIO;
+}
+
+static int sandbox_flash_probe(struct udevice *dev)
+{
+       struct usb_device *udev = dev_get_uclass_priv(dev);
+       struct usb_device_descriptor *desc;
+       struct usb_config_descriptor *cdesc;
+
+       udev->strings = usb_strings;
+       desc = &udev->descriptor;
+       desc->iManufacturer = STRINGID_manufacterer;
+       desc->iProduct = STRINGID_product;
+       desc->iSerialNumber = STRINGID_serial;
+
+       udev->maxpacketsize = PACKET_SIZE_64;
+
+       cdesc = &udev->config.desc;
+       cdesc->bLength = sizeof(*cdesc);
+       cdesc->bDescriptorType = USB_DT_CONFIG;
+       cdesc->wTotalLength = 100;
+       cdesc->bNumInterfaces = 1;
+       cdesc->bConfigurationValue = 1;
+       cdesc->iConfiguration = 0;
+       cdesc->bmAttributes = 1 << 7;
+       cdesc->bMaxPower = 50;
+
+       return 0;
+}
+
+static const struct dm_usb_ops sandbox_usb_flash_ops = {
+       .submit_control_msg     = sandbox_flash_submit_control_msg,
+};
+
+static const struct udevice_id sandbox_usb_flash_ids[] = {
+       { .compatible = "sandbox,usb-flash" },
+       { }
+};
+
+U_BOOT_DRIVER(usb_sandbox_flash) = {
+       .name   = "usb_sandbox_flash",
+       .id     = UCLASS_USB_EMUL,
+       .of_match = sandbox_usb_flash_ids,
+       .probe = sandbox_flash_probe,
+       .ops    = &sandbox_usb_flash_ops,
+};
diff --git a/drivers/usb/dev/sandbox-hub.c b/drivers/usb/dev/sandbox-hub.c
new file mode 100644
index 0000000..60ef64a
--- /dev/null
+++ b/drivers/usb/dev/sandbox-hub.c
@@ -0,0 +1,116 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <s...@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#define DEBUG
+#include <common.h>
+#include <dm.h>
+#include <usb.h>
+
+enum {
+       STRING_null,
+       STRING_MANUFACTURER,
+       STRING_PRODUCT,
+       STRING_SERIAL,
+
+       STRING_count,
+};
+
+static char *usb_strings[] = {
+       "",
+       "sandbox",
+       "hub",
+       "2345",
+       NULL,
+};
+
+static struct usb_device_descriptor device_desc = {
+       .bLength =              sizeof(device_desc),
+       .bDescriptorType =      USB_DT_DEVICE,
+
+       .bcdUSB =               __constant_cpu_to_le16(0x0200),
+
+       .bDeviceClass =         USB_CLASS_HUB,
+       .bDeviceSubClass =      0,
+       .bDeviceProtocol =      0,
+
+       .idVendor =             __constant_cpu_to_le16(0x1234),
+       .idProduct =            __constant_cpu_to_le16(0x5678),
+       .iManufacturer =        STRING_MANUFACTURER,
+       .iProduct =             STRING_PRODUCT,
+       .iSerialNumber =        STRING_SERIAL,
+       .bNumConfigurations =   1,
+};
+
+static const struct usb_descriptor_header hub_desc[] = {
+};
+
+static int sandbox_hub_submit_control_msg(struct udevice *dev,
+                                         unsigned long pipe,
+                                         void *buffer, int length,
+                                         struct devrequest *setup)
+{
+       struct usb_device *udev = dev_get_uclass_priv(dev);
+
+       if (pipe == usb_rcvctrlpipe(udev, 0)) {
+               switch (setup->request) {
+               case USB_REQ_GET_DESCRIPTOR:
+                       memcpy(buffer, &udev->descriptor, length);
+                       udev->status = 0;
+                       udev->act_len = length;
+                       return 0;
+               default:
+                       debug("request=%x\n", setup->request);
+                       break;
+               }
+       }
+       debug("pipe=%lx\n", pipe);
+
+       return -EIO;
+}
+
+static int sandbox_hub_probe(struct udevice *dev)
+{
+       struct usb_device *udev = dev_get_uclass_priv(dev);
+       struct usb_device_descriptor *desc;
+       struct usb_config_descriptor *cdesc;
+
+       udev->strings = usb_strings;
+       desc = &udev->descriptor;
+       desc->iManufacturer = STRING_MANUFACTURER;
+       desc->iProduct = STRING_PRODUCT;
+       desc->iSerialNumber = STRING_SERIAL;
+
+       udev->maxpacketsize = PACKET_SIZE_64;
+
+       cdesc = &udev->config.desc;
+       cdesc->bLength = sizeof(*cdesc);
+       cdesc->bDescriptorType = USB_DT_CONFIG;
+       cdesc->wTotalLength = 100;
+       cdesc->bNumInterfaces = 1;
+       cdesc->bConfigurationValue = 1;
+       cdesc->iConfiguration = 0;
+       cdesc->bmAttributes = 1 << 7;
+       cdesc->bMaxPower = 50;
+
+       return 0;
+}
+
+static const struct dm_usb_ops sandbox_usb_hub_ops = {
+       .submit_control_msg     = sandbox_hub_submit_control_msg,
+};
+
+static const struct udevice_id sandbox_usb_hub_ids[] = {
+       { .compatible = "sandbox,usb-hub" },
+       { }
+};
+
+U_BOOT_DRIVER(usb_sandbox_hub) = {
+       .name   = "usb_sandbox_hub",
+       .id     = UCLASS_USB_EMUL,
+       .of_match = sandbox_usb_hub_ids,
+       .probe = sandbox_hub_probe,
+       .ops    = &sandbox_usb_hub_ops,
+};
diff --git a/drivers/usb/dev/usb-emul-uclass.c 
b/drivers/usb/dev/usb-emul-uclass.c
new file mode 100644
index 0000000..4114df0
--- /dev/null
+++ b/drivers/usb/dev/usb-emul-uclass.c
@@ -0,0 +1,16 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <s...@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <usb.h>
+
+UCLASS_DRIVER(usb_emul) = {
+       .id             = UCLASS_USB_EMUL,
+       .name           = "usb_emul",
+       .per_device_auto_alloc_size = sizeof(struct usb_device),
+};
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index d0b890a..de8354a 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -6,6 +6,9 @@
 #
 
 obj-$(CONFIG_DM_USB) += usb-uclass.o
+ifdef CONFIG_DM_USB
+obj-$(CONFIG_SANDBOX) += usb-sandbox.o
+endif
 
 # ohci
 obj-$(CONFIG_USB_OHCI_NEW) += ohci-hcd.o
diff --git a/drivers/usb/host/usb-sandbox.c b/drivers/usb/host/usb-sandbox.c
new file mode 100644
index 0000000..34bf06d
--- /dev/null
+++ b/drivers/usb/host/usb-sandbox.c
@@ -0,0 +1,151 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <s...@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+#define DEBUG
+#include <common.h>
+#include <dm.h>
+#include <usb.h>
+#include <dm/root.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int copy_to_unicode(char *buff, int length, const char *str)
+{
+       int ptr;
+       int i;
+
+       if (length < 2)
+               return 0;
+       buff[1] = USB_DT_STRING;
+       for (ptr = 2, i = 0; ptr + 1 < length && *str; i++, ptr += 2) {
+               buff[ptr] = str[i];
+               buff[ptr + 1] = 0;
+       }
+       buff[0] = ptr;
+
+       return ptr;
+}
+
+static int sandbox_submit_control_msg(struct udevice *dev, unsigned long pipe,
+                                     void *buffer, int length,
+                                     struct devrequest *setup)
+{
+       struct usb_device *udev = dev_get_uclass_priv(dev);
+       struct usb_device *emul_udev;
+       struct udevice *emul;
+       int ret;
+
+       debug("ctrl %s: pipe=%lx, buffer=%p, length=%x, setup=%p\n",
+             dev->name, pipe, buffer, length, setup);
+       ret = device_get_child(dev, 0, &emul);
+       if (ret)
+               return ret;
+       emul_udev = dev_get_uclass_priv(emul);
+       if (pipe == usb_rcvctrlpipe(udev, 0)) {
+               switch (setup->request) {
+               case USB_REQ_GET_DESCRIPTOR: {
+                       int type = setup->value >> 8;
+                       int index = setup->value & 0xff;
+
+                       if (type == USB_DT_DEVICE && index == 0) {
+                               memcpy(buffer, &emul_udev->descriptor, length);
+                               udev->status = 0;
+                               udev->act_len = length;
+                               return 0;
+                       } else if (type == USB_DT_CONFIG && index == 0) {
+                               memcpy(buffer, &emul_udev->config.desc, length);
+                               udev->status = 0;
+                               udev->act_len = length;
+                               return 0;
+                       } else if (type == USB_DT_STRING) {
+                               if (index == 0) {
+                                       char *desc = buffer;
+
+                                       desc[0] = 4;
+                                       desc[1] = USB_DT_STRING;
+                                       desc[2] = 0x09;
+                                       desc[3] = 0x14;
+                                       udev->status = 0;
+                                       udev->act_len = 4;
+                                       return 0;
+                               } else {
+                                       char **ptr = emul_udev->strings;
+                                       int i;
+
+                                       for (i = 0; i < index; i++) {
+                                               if (!ptr[i])
+                                                       break;
+                                       }
+                                       if (ptr[i]) {
+                                               udev->act_len = copy_to_unicode(
+                                                       buffer, length, ptr[i]);
+                                               udev->status = 0;
+                                               return 0;
+                                       }
+                               }
+                       }
+                       break;
+               }
+               default:
+                       debug("requestrcv =%x\n", setup->request);
+                       break;
+               }
+       } else if (pipe == usb_snddefctrl(udev)) {
+               switch (setup->request) {
+               case USB_REQ_SET_ADDRESS:
+                       emul_udev->devnum = setup->value;
+                       udev->status = 0;
+                       udev->act_len = 0;
+                       return 0;
+               default:
+                       debug("requestsend =%x\n", setup->request);
+                       break;
+               }
+       } else if (pipe == usb_sndctrlpipe(udev, 0)) {
+               switch (setup->request) {
+               case USB_REQ_SET_CONFIGURATION:
+                       emul_udev->configno = setup->value;
+                       udev->status = 0;
+                       udev->act_len = 0;
+                       return 0;
+               default:
+                       debug("sndctrlpipe req=%x\n", setup->request);
+                       break;
+               }
+       }
+       debug("pipe=%lx\n", pipe);
+
+       return -EIO;
+}
+
+static int sandbox_usb_probe(struct udevice *dev)
+{
+       return 0;
+}
+
+static int sandbox_usb_bind(struct udevice *dev)
+{
+       /* Scan the bus for devices */
+       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
+}
+
+static const struct dm_usb_ops sandbox_usb_ops = {
+       .submit_control_msg     = sandbox_submit_control_msg,
+};
+
+static const struct udevice_id sandbox_usb_ids[] = {
+       { .compatible = "sandbox,usb" },
+       { }
+};
+
+U_BOOT_DRIVER(usb_sandbox) = {
+       .name   = "usb_sandbox",
+       .id     = UCLASS_USB,
+       .of_match = sandbox_usb_ids,
+       .probe = sandbox_usb_probe,
+       .bind = sandbox_usb_bind,
+       .ops    = &sandbox_usb_ops,
+};
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index e9d3f32..392a40f 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -201,4 +201,7 @@
 
 #define CONFIG_CMD_LZMADEC
 
+#define CONFIG_CMD_USB
+#define CONFIG_DM_USB
+
 #endif
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index baab810..1c33fa6 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -20,6 +20,7 @@ enum uclass_id {
        UCLASS_TEST_BUS,
        UCLASS_SPI_EMUL,        /* sandbox SPI device emulator */
        UCLASS_I2C_EMUL,        /* sandbox I2C device emulator */
+       UCLASS_USB_EMUL,        /* sandbox USB bus device emulator */
        UCLASS_SIMPLE_BUS,
 
        /* U-Boot uclasses start here */
diff --git a/include/usb_defs.h b/include/usb_defs.h
index 236a5ec..b580bf0 100644
--- a/include/usb_defs.h
+++ b/include/usb_defs.h
@@ -165,12 +165,14 @@
 #define USB_TEST_MODE_FORCE_ENABLE  0x05
 
 
-/* "pipe" definitions */
-
-#define PIPE_ISOCHRONOUS    0
-#define PIPE_INTERRUPT      1
-#define PIPE_CONTROL        2
-#define PIPE_BULK           3
+/*
+ * "pipe" definitions, use unsigned so we can compare reliably, since this
+ * value is shifted up to bits 30/31.
+ */
+#define PIPE_ISOCHRONOUS    0U
+#define PIPE_INTERRUPT      1U
+#define PIPE_CONTROL        2U
+#define PIPE_BULK           3U
 #define PIPE_DEVEP_MASK     0x0007ff00
 
 #define USB_ISOCHRONOUS    0
-- 
2.2.0.rc0.207.ga3a616c

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to