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