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