uboot/drivers/usb/emul/usb-emul-uclass.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 <usb.h>
  10#include <dm/device-internal.h>
  11
  12static int copy_to_unicode(char *buff, int length, const char *str)
  13{
  14        int ptr;
  15        int i;
  16
  17        if (length < 2)
  18                return 0;
  19        buff[1] = USB_DT_STRING;
  20        for (ptr = 2, i = 0; ptr + 1 < length && *str; i++, ptr += 2) {
  21                buff[ptr] = str[i];
  22                buff[ptr + 1] = 0;
  23        }
  24        buff[0] = ptr;
  25
  26        return ptr;
  27}
  28
  29static int usb_emul_get_string(struct usb_string *strings, int index,
  30                               char *buff, int length)
  31{
  32        if (index == 0) {
  33                char *desc = buff;
  34
  35                desc[0] = 4;
  36                desc[1] = USB_DT_STRING;
  37                desc[2] = 0x09;
  38                desc[3] = 0x14;
  39                return 4;
  40        } else if (strings) {
  41                struct usb_string *ptr;
  42
  43                for (ptr = strings; ptr->s; ptr++) {
  44                        if (ptr->id == index)
  45                                return copy_to_unicode(buff, length, ptr->s);
  46                }
  47        }
  48
  49        return -EINVAL;
  50}
  51
  52struct usb_generic_descriptor **usb_emul_find_descriptor(
  53                struct usb_generic_descriptor **ptr, int type, int index)
  54{
  55        debug("%s: type=%x, index=%d\n", __func__, type, index);
  56        for (; *ptr; ptr++) {
  57                if ((*ptr)->bDescriptorType != type)
  58                        continue;
  59                switch (type) {
  60                case USB_DT_CONFIG: {
  61                        struct usb_config_descriptor *cdesc;
  62
  63                        cdesc = (struct usb_config_descriptor *)*ptr;
  64                        if (cdesc && cdesc->bConfigurationValue == index)
  65                                return ptr;
  66                        break;
  67                }
  68                default:
  69                        return ptr;
  70                }
  71        }
  72        debug("%s: config ptr=%p\n", __func__, *ptr);
  73
  74        return ptr;
  75}
  76
  77static int usb_emul_get_descriptor(struct usb_dev_platdata *plat, int value,
  78                                   void *buffer, int length)
  79{
  80        struct usb_generic_descriptor **ptr;
  81        int type = value >> 8;
  82        int index = value & 0xff;
  83        int upto, todo;
  84
  85        debug("%s: type=%d, index=%d, plat=%p\n", __func__, type, index, plat);
  86        if (type == USB_DT_STRING) {
  87                return usb_emul_get_string(plat->strings, index, buffer,
  88                                           length);
  89        }
  90
  91        ptr = usb_emul_find_descriptor(plat->desc_list, type, index);
  92        if (!ptr) {
  93                debug("%s: Could not find descriptor type %d, index %d\n",
  94                      __func__, type, index);
  95                return -ENOENT;
  96        }
  97        for (upto = 0; *ptr && upto < length; ptr++, upto += todo) {
  98                todo = min(length - upto, (int)(*ptr)->bLength);
  99
 100                memcpy(buffer + upto, *ptr, todo);
 101        }
 102
 103        return upto ? upto : length ? -EIO : 0;
 104}
 105
 106static int usb_emul_find_devnum(int devnum, int port1, struct udevice **emulp)
 107{
 108        struct udevice *dev;
 109        struct uclass *uc;
 110        int ret;
 111
 112        *emulp = NULL;
 113        ret = uclass_get(UCLASS_USB_EMUL, &uc);
 114        if (ret)
 115                return ret;
 116        uclass_foreach_dev(dev, uc) {
 117                struct usb_dev_platdata *udev = dev_get_parent_platdata(dev);
 118
 119                /*
 120                 * devnum is initialzied to zero at the beginning of the
 121                 * enumeration process in usb_setup_device(). At this
 122                 * point, udev->devnum has not been assigned to any valid
 123                 * USB address either, so we can't rely on the comparison
 124                 * result between udev->devnum and devnum to select an
 125                 * emulator device.
 126                 */
 127                if (!devnum) {
 128                        struct usb_emul_platdata *plat;
 129
 130                        /*
 131                         * If the parent is sandbox USB controller, we are
 132                         * the root hub. And there is only one root hub
 133                         * in the system.
 134                         */
 135                        if (device_get_uclass_id(dev->parent) == UCLASS_USB) {
 136                                debug("%s: Found emulator '%s'\n",
 137                                      __func__, dev->name);
 138                                *emulp = dev;
 139                                return 0;
 140                        }
 141
 142                        plat = dev_get_uclass_platdata(dev);
 143                        if (plat->port1 == port1) {
 144                                debug("%s: Found emulator '%s', port %d\n",
 145                                      __func__, dev->name, port1);
 146                                *emulp = dev;
 147                                return 0;
 148                        }
 149                } else if (udev->devnum == devnum) {
 150                        debug("%s: Found emulator '%s', addr %d\n", __func__,
 151                              dev->name, udev->devnum);
 152                        *emulp = dev;
 153                        return 0;
 154                }
 155        }
 156
 157        debug("%s: No emulator found, addr %d\n", __func__, devnum);
 158        return -ENOENT;
 159}
 160
 161int usb_emul_find(struct udevice *bus, ulong pipe, int port1,
 162                  struct udevice **emulp)
 163{
 164        int devnum = usb_pipedevice(pipe);
 165
 166        return usb_emul_find_devnum(devnum, port1, emulp);
 167}
 168
 169int usb_emul_find_for_dev(struct udevice *dev, struct udevice **emulp)
 170{
 171        struct usb_dev_platdata *udev = dev_get_parent_platdata(dev);
 172
 173        return usb_emul_find_devnum(udev->devnum, 0, emulp);
 174}
 175
 176int usb_emul_control(struct udevice *emul, struct usb_device *udev,
 177                     unsigned long pipe, void *buffer, int length,
 178                     struct devrequest *setup)
 179{
 180        struct dm_usb_ops *ops = usb_get_emul_ops(emul);
 181        struct usb_dev_platdata *plat;
 182        int ret;
 183
 184        /* We permit getting the descriptor before we are probed */
 185        plat = dev_get_parent_platdata(emul);
 186        if (!ops->control)
 187                return -ENOSYS;
 188        debug("%s: dev=%s\n", __func__, emul->name);
 189        if (pipe == usb_rcvctrlpipe(udev, 0)) {
 190                switch (setup->request) {
 191                case USB_REQ_GET_DESCRIPTOR: {
 192                        return usb_emul_get_descriptor(plat, setup->value,
 193                                                       buffer, length);
 194                }
 195                default:
 196                        ret = device_probe(emul);
 197                        if (ret)
 198                                return ret;
 199                        return ops->control(emul, udev, pipe, buffer, length,
 200                                            setup);
 201                }
 202        } else if (pipe == usb_snddefctrl(udev)) {
 203                switch (setup->request) {
 204                case USB_REQ_SET_ADDRESS:
 205                        debug("   ** set address %s %d\n", emul->name,
 206                              setup->value);
 207                        plat->devnum = setup->value;
 208                        return 0;
 209                default:
 210                        debug("requestsend =%x\n", setup->request);
 211                        break;
 212                }
 213        } else if (pipe == usb_sndctrlpipe(udev, 0)) {
 214                switch (setup->request) {
 215                case USB_REQ_SET_CONFIGURATION:
 216                        plat->configno = setup->value;
 217                        return 0;
 218                default:
 219                        ret = device_probe(emul);
 220                        if (ret)
 221                                return ret;
 222                        return ops->control(emul, udev, pipe, buffer, length,
 223                                            setup);
 224                }
 225        }
 226        debug("pipe=%lx\n", pipe);
 227
 228        return -EIO;
 229}
 230
 231int usb_emul_bulk(struct udevice *emul, struct usb_device *udev,
 232                  unsigned long pipe, void *buffer, int length)
 233{
 234        struct dm_usb_ops *ops = usb_get_emul_ops(emul);
 235        int ret;
 236
 237        /* We permit getting the descriptor before we are probed */
 238        if (!ops->bulk)
 239                return -ENOSYS;
 240        debug("%s: dev=%s\n", __func__, emul->name);
 241        ret = device_probe(emul);
 242        if (ret)
 243                return ret;
 244        return ops->bulk(emul, udev, pipe, buffer, length);
 245}
 246
 247int usb_emul_int(struct udevice *emul, struct usb_device *udev,
 248                  unsigned long pipe, void *buffer, int length, int interval)
 249{
 250        struct dm_usb_ops *ops = usb_get_emul_ops(emul);
 251
 252        if (!ops->interrupt)
 253                return -ENOSYS;
 254        debug("%s: dev=%s\n", __func__, emul->name);
 255
 256        return ops->interrupt(emul, udev, pipe, buffer, length, interval);
 257}
 258
 259int usb_emul_setup_device(struct udevice *dev, struct usb_string *strings,
 260                          void **desc_list)
 261{
 262        struct usb_dev_platdata *plat = dev_get_parent_platdata(dev);
 263        struct usb_generic_descriptor **ptr;
 264        struct usb_config_descriptor *cdesc;
 265        int upto;
 266
 267        plat->strings = strings;
 268        plat->desc_list = (struct usb_generic_descriptor **)desc_list;
 269
 270        /* Fill in wTotalLength for each configuration descriptor */
 271        ptr = plat->desc_list;
 272        for (cdesc = NULL, upto = 0; *ptr; upto += (*ptr)->bLength, ptr++) {
 273                debug("   - upto=%d, type=%d\n", upto, (*ptr)->bDescriptorType);
 274                if ((*ptr)->bDescriptorType == USB_DT_CONFIG) {
 275                        if (cdesc) {
 276                                cdesc->wTotalLength = upto;
 277                                debug("%s: config %d length %d\n", __func__,
 278                                      cdesc->bConfigurationValue,
 279                                      cdesc->bLength);
 280                        }
 281                        cdesc = (struct usb_config_descriptor *)*ptr;
 282                        upto = 0;
 283                }
 284        }
 285        if (cdesc) {
 286                cdesc->wTotalLength = upto;
 287                debug("%s: config %d length %d\n", __func__,
 288                      cdesc->bConfigurationValue, cdesc->wTotalLength);
 289        }
 290
 291        return 0;
 292}
 293
 294UCLASS_DRIVER(usb_emul) = {
 295        .id             = UCLASS_USB_EMUL,
 296        .name           = "usb_emul",
 297        .post_bind      = dm_scan_fdt_dev,
 298        .per_device_platdata_auto_alloc_size = sizeof(struct usb_emul_platdata),
 299        .per_child_auto_alloc_size = sizeof(struct usb_device),
 300        .per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata),
 301};
 302