uboot/drivers/usb/host/usb-sandbox.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2015 Google, Inc
   4 * Written by Simon Glass <sjg@chromium.org>
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <log.h>
  10#include <usb.h>
  11#include <dm/root.h>
  12#include <linux/usb/gadget.h>
  13
  14struct sandbox_udc {
  15        struct usb_gadget gadget;
  16};
  17
  18struct sandbox_udc *this_controller;
  19
  20struct sandbox_usb_ctrl {
  21        int rootdev;
  22};
  23
  24static void usbmon_trace(struct udevice *bus, ulong pipe,
  25                         struct devrequest *setup, struct udevice *emul)
  26{
  27        static const char types[] = "ZICB";
  28        int type;
  29
  30        type = (pipe & USB_PIPE_TYPE_MASK) >> USB_PIPE_TYPE_SHIFT;
  31        debug("0 0 S %c%c:%d:%03ld:%ld", types[type],
  32              pipe & USB_DIR_IN ? 'i' : 'o',
  33              dev_seq(bus),
  34              (pipe & USB_PIPE_DEV_MASK) >> USB_PIPE_DEV_SHIFT,
  35              (pipe & USB_PIPE_EP_MASK) >> USB_PIPE_EP_SHIFT);
  36        if (setup) {
  37                debug(" s %02x %02x %04x %04x %04x", setup->requesttype,
  38                      setup->request, setup->value, setup->index,
  39                      setup->length);
  40        }
  41        debug(" %s", emul ? emul->name : "(no emul found)");
  42
  43        debug("\n");
  44}
  45
  46static int sandbox_submit_control(struct udevice *bus,
  47                                      struct usb_device *udev,
  48                                      unsigned long pipe,
  49                                      void *buffer, int length,
  50                                      struct devrequest *setup)
  51{
  52        struct sandbox_usb_ctrl *ctrl = dev_get_priv(bus);
  53        struct udevice *emul;
  54        int ret;
  55
  56        /* Just use child of dev as emulator? */
  57        debug("%s: bus=%s\n", __func__, bus->name);
  58        ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
  59        usbmon_trace(bus, pipe, setup, emul);
  60        if (ret)
  61                return ret;
  62
  63        if (usb_pipedevice(pipe) == ctrl->rootdev) {
  64                if (setup->request == USB_REQ_SET_ADDRESS) {
  65                        debug("%s: Set root hub's USB address\n", __func__);
  66                        ctrl->rootdev = le16_to_cpu(setup->value);
  67                }
  68        }
  69
  70        ret = usb_emul_control(emul, udev, pipe, buffer, length, setup);
  71        if (ret < 0) {
  72                debug("ret=%d\n", ret);
  73                udev->status = ret;
  74                udev->act_len = 0;
  75        } else {
  76                udev->status = 0;
  77                udev->act_len = ret;
  78        }
  79
  80        return ret;
  81}
  82
  83static int sandbox_submit_bulk(struct udevice *bus, struct usb_device *udev,
  84                               unsigned long pipe, void *buffer, int length)
  85{
  86        struct udevice *emul;
  87        int ret;
  88
  89        /* Just use child of dev as emulator? */
  90        debug("%s: bus=%s\n", __func__, bus->name);
  91        ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
  92        usbmon_trace(bus, pipe, NULL, emul);
  93        if (ret)
  94                return ret;
  95        ret = usb_emul_bulk(emul, udev, pipe, buffer, length);
  96        if (ret < 0) {
  97                debug("ret=%d\n", ret);
  98                udev->status = ret;
  99                udev->act_len = 0;
 100        } else {
 101                udev->status = 0;
 102                udev->act_len = ret;
 103        }
 104
 105        return ret;
 106}
 107
 108static int sandbox_submit_int(struct udevice *bus, struct usb_device *udev,
 109                              unsigned long pipe, void *buffer, int length,
 110                              int interval, bool nonblock)
 111{
 112        struct udevice *emul;
 113        int ret;
 114
 115        /* Just use child of dev as emulator? */
 116        debug("%s: bus=%s\n", __func__, bus->name);
 117        ret = usb_emul_find(bus, pipe, udev->portnr, &emul);
 118        usbmon_trace(bus, pipe, NULL, emul);
 119        if (ret)
 120                return ret;
 121        ret = usb_emul_int(emul, udev, pipe, buffer, length, interval,
 122                           nonblock);
 123
 124        return ret;
 125}
 126
 127int usb_gadget_handle_interrupts(int index)
 128{
 129        return 0;
 130}
 131
 132int usb_gadget_register_driver(struct usb_gadget_driver *driver)
 133{
 134        struct sandbox_udc *dev = this_controller;
 135
 136        return driver->bind(&dev->gadget);
 137}
 138
 139int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 140{
 141        struct sandbox_udc *dev = this_controller;
 142
 143        driver->unbind(&dev->gadget);
 144
 145        return 0;
 146}
 147
 148static int sandbox_alloc_device(struct udevice *dev, struct usb_device *udev)
 149{
 150        struct sandbox_usb_ctrl *ctrl = dev_get_priv(dev);
 151
 152        /*
 153         * Root hub will be the first device to be initailized.
 154         * If this device is a root hub, initialize its device speed
 155         * to high speed as we are a USB 2.0 controller.
 156         */
 157        if (ctrl->rootdev == 0)
 158                udev->speed = USB_SPEED_HIGH;
 159
 160        return 0;
 161}
 162
 163static int sandbox_usb_probe(struct udevice *dev)
 164{
 165        return 0;
 166}
 167
 168static const struct dm_usb_ops sandbox_usb_ops = {
 169        .control        = sandbox_submit_control,
 170        .bulk           = sandbox_submit_bulk,
 171        .interrupt      = sandbox_submit_int,
 172        .alloc_device   = sandbox_alloc_device,
 173};
 174
 175static const struct udevice_id sandbox_usb_ids[] = {
 176        { .compatible = "sandbox,usb" },
 177        { }
 178};
 179
 180U_BOOT_DRIVER(usb_sandbox) = {
 181        .name   = "usb_sandbox",
 182        .id     = UCLASS_USB,
 183        .of_match = sandbox_usb_ids,
 184        .probe = sandbox_usb_probe,
 185        .ops    = &sandbox_usb_ops,
 186        .priv_auto      = sizeof(struct sandbox_usb_ctrl),
 187};
 188