1019808f9SSimon Glass /* 2019808f9SSimon Glass * (C) Copyright 2015 Google, Inc 3019808f9SSimon Glass * Written by Simon Glass <sjg@chromium.org> 4019808f9SSimon Glass * 5019808f9SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 6019808f9SSimon Glass */ 7019808f9SSimon Glass 8019808f9SSimon Glass #include <common.h> 9019808f9SSimon Glass #include <dm.h> 10019808f9SSimon Glass #include <usb.h> 11019808f9SSimon Glass #include <dm/root.h> 12019808f9SSimon Glass #include <dm/device-internal.h> 13019808f9SSimon Glass 14019808f9SSimon Glass DECLARE_GLOBAL_DATA_PTR; 15019808f9SSimon Glass 16019808f9SSimon Glass static int copy_to_unicode(char *buff, int length, const char *str) 17019808f9SSimon Glass { 18019808f9SSimon Glass int ptr; 19019808f9SSimon Glass int i; 20019808f9SSimon Glass 21019808f9SSimon Glass if (length < 2) 22019808f9SSimon Glass return 0; 23019808f9SSimon Glass buff[1] = USB_DT_STRING; 24019808f9SSimon Glass for (ptr = 2, i = 0; ptr + 1 < length && *str; i++, ptr += 2) { 25019808f9SSimon Glass buff[ptr] = str[i]; 26019808f9SSimon Glass buff[ptr + 1] = 0; 27019808f9SSimon Glass } 28019808f9SSimon Glass buff[0] = ptr; 29019808f9SSimon Glass 30019808f9SSimon Glass return ptr; 31019808f9SSimon Glass } 32019808f9SSimon Glass 33019808f9SSimon Glass static int usb_emul_get_string(struct usb_string *strings, int index, 34019808f9SSimon Glass char *buff, int length) 35019808f9SSimon Glass { 36019808f9SSimon Glass if (index == 0) { 37019808f9SSimon Glass char *desc = buff; 38019808f9SSimon Glass 39019808f9SSimon Glass desc[0] = 4; 40019808f9SSimon Glass desc[1] = USB_DT_STRING; 41019808f9SSimon Glass desc[2] = 0x09; 42019808f9SSimon Glass desc[3] = 0x14; 43019808f9SSimon Glass return 4; 44019808f9SSimon Glass } else if (strings) { 45019808f9SSimon Glass struct usb_string *ptr; 46019808f9SSimon Glass 47019808f9SSimon Glass for (ptr = strings; ptr->s; ptr++) { 48019808f9SSimon Glass if (ptr->id == index) 49019808f9SSimon Glass return copy_to_unicode(buff, length, ptr->s); 50019808f9SSimon Glass } 51019808f9SSimon Glass } 52019808f9SSimon Glass 53019808f9SSimon Glass return -EINVAL; 54019808f9SSimon Glass } 55019808f9SSimon Glass 56019808f9SSimon Glass static struct usb_generic_descriptor **find_descriptor( 57019808f9SSimon Glass struct usb_generic_descriptor **ptr, int type, int index) 58019808f9SSimon Glass { 59019808f9SSimon Glass debug("%s: type=%x, index=%d\n", __func__, type, index); 60019808f9SSimon Glass for (; *ptr; ptr++) { 61019808f9SSimon Glass if ((*ptr)->bDescriptorType != type) 62019808f9SSimon Glass continue; 63019808f9SSimon Glass switch (type) { 64019808f9SSimon Glass case USB_DT_CONFIG: { 65019808f9SSimon Glass struct usb_config_descriptor *cdesc; 66019808f9SSimon Glass 67019808f9SSimon Glass cdesc = (struct usb_config_descriptor *)*ptr; 68019808f9SSimon Glass if (cdesc && cdesc->bConfigurationValue == index) 69019808f9SSimon Glass return ptr; 70019808f9SSimon Glass break; 71019808f9SSimon Glass } 72019808f9SSimon Glass default: 73019808f9SSimon Glass return ptr; 74019808f9SSimon Glass } 75019808f9SSimon Glass } 76019808f9SSimon Glass debug("%s: config ptr=%p\n", __func__, *ptr); 77019808f9SSimon Glass 78019808f9SSimon Glass return ptr; 79019808f9SSimon Glass } 80019808f9SSimon Glass 81019808f9SSimon Glass static int usb_emul_get_descriptor(struct usb_dev_platdata *plat, int value, 82019808f9SSimon Glass void *buffer, int length) 83019808f9SSimon Glass { 84019808f9SSimon Glass struct usb_generic_descriptor **ptr; 85019808f9SSimon Glass int type = value >> 8; 86019808f9SSimon Glass int index = value & 0xff; 87019808f9SSimon Glass int upto, todo; 88019808f9SSimon Glass 89019808f9SSimon Glass debug("%s: type=%d, index=%d, plat=%p\n", __func__, type, index, plat); 90019808f9SSimon Glass if (type == USB_DT_STRING) { 91019808f9SSimon Glass return usb_emul_get_string(plat->strings, index, buffer, 92019808f9SSimon Glass length); 93019808f9SSimon Glass } 94019808f9SSimon Glass 95019808f9SSimon Glass ptr = find_descriptor((struct usb_generic_descriptor **)plat->desc_list, 96019808f9SSimon Glass type, index); 97019808f9SSimon Glass if (!ptr) { 98019808f9SSimon Glass debug("%s: Could not find descriptor type %d, index %d\n", 99019808f9SSimon Glass __func__, type, index); 100019808f9SSimon Glass return -ENOENT; 101019808f9SSimon Glass } 102019808f9SSimon Glass for (upto = 0; *ptr && upto < length; ptr++, upto += todo) { 103019808f9SSimon Glass todo = min(length - upto, (int)(*ptr)->bLength); 104019808f9SSimon Glass 105019808f9SSimon Glass memcpy(buffer + upto, *ptr, todo); 106019808f9SSimon Glass } 107019808f9SSimon Glass 108019808f9SSimon Glass return upto ? upto : length ? -EIO : 0; 109019808f9SSimon Glass } 110019808f9SSimon Glass 111*af9c7c11SSimon Glass static int usb_emul_find_devnum(int devnum, struct udevice **emulp) 112019808f9SSimon Glass { 113019808f9SSimon Glass struct udevice *dev; 114019808f9SSimon Glass struct uclass *uc; 115019808f9SSimon Glass int ret; 116019808f9SSimon Glass 117019808f9SSimon Glass *emulp = NULL; 118019808f9SSimon Glass ret = uclass_get(UCLASS_USB_EMUL, &uc); 119019808f9SSimon Glass if (ret) 120019808f9SSimon Glass return ret; 121019808f9SSimon Glass uclass_foreach_dev(dev, uc) { 122019808f9SSimon Glass struct usb_dev_platdata *udev = dev_get_parent_platdata(dev); 123019808f9SSimon Glass 124019808f9SSimon Glass if (udev->devnum == devnum) { 125019808f9SSimon Glass debug("%s: Found emulator '%s', addr %d\n", __func__, 126019808f9SSimon Glass dev->name, udev->devnum); 127019808f9SSimon Glass *emulp = dev; 128019808f9SSimon Glass return 0; 129019808f9SSimon Glass } 130019808f9SSimon Glass } 131019808f9SSimon Glass 132019808f9SSimon Glass debug("%s: No emulator found, addr %d\n", __func__, devnum); 133019808f9SSimon Glass return -ENOENT; 134019808f9SSimon Glass } 135019808f9SSimon Glass 136*af9c7c11SSimon Glass int usb_emul_find(struct udevice *bus, ulong pipe, struct udevice **emulp) 137*af9c7c11SSimon Glass { 138*af9c7c11SSimon Glass int devnum = usb_pipedevice(pipe); 139*af9c7c11SSimon Glass 140*af9c7c11SSimon Glass return usb_emul_find_devnum(devnum, emulp); 141*af9c7c11SSimon Glass } 142*af9c7c11SSimon Glass 143*af9c7c11SSimon Glass int usb_emul_find_for_dev(struct udevice *dev, struct udevice **emulp) 144*af9c7c11SSimon Glass { 145*af9c7c11SSimon Glass struct usb_dev_platdata *udev = dev_get_parent_platdata(dev); 146*af9c7c11SSimon Glass 147*af9c7c11SSimon Glass return usb_emul_find_devnum(udev->devnum, emulp); 148*af9c7c11SSimon Glass } 149*af9c7c11SSimon Glass 150019808f9SSimon Glass int usb_emul_control(struct udevice *emul, struct usb_device *udev, 151019808f9SSimon Glass unsigned long pipe, void *buffer, int length, 152019808f9SSimon Glass struct devrequest *setup) 153019808f9SSimon Glass { 154019808f9SSimon Glass struct dm_usb_ops *ops = usb_get_emul_ops(emul); 155019808f9SSimon Glass struct usb_dev_platdata *plat; 156019808f9SSimon Glass int ret; 157019808f9SSimon Glass 158019808f9SSimon Glass /* We permit getting the descriptor before we are probed */ 159019808f9SSimon Glass plat = dev_get_parent_platdata(emul); 160019808f9SSimon Glass if (!ops->control) 161019808f9SSimon Glass return -ENOSYS; 162019808f9SSimon Glass debug("%s: dev=%s\n", __func__, emul->name); 163019808f9SSimon Glass if (pipe == usb_rcvctrlpipe(udev, 0)) { 164019808f9SSimon Glass switch (setup->request) { 165019808f9SSimon Glass case USB_REQ_GET_DESCRIPTOR: { 166019808f9SSimon Glass return usb_emul_get_descriptor(plat, setup->value, 167019808f9SSimon Glass buffer, length); 168019808f9SSimon Glass } 169019808f9SSimon Glass default: 170019808f9SSimon Glass ret = device_probe(emul); 171019808f9SSimon Glass if (ret) 172019808f9SSimon Glass return ret; 173019808f9SSimon Glass return ops->control(emul, udev, pipe, buffer, length, 174019808f9SSimon Glass setup); 175019808f9SSimon Glass } 176019808f9SSimon Glass } else if (pipe == usb_snddefctrl(udev)) { 177019808f9SSimon Glass switch (setup->request) { 178019808f9SSimon Glass case USB_REQ_SET_ADDRESS: 179019808f9SSimon Glass debug(" ** set address %s %d\n", emul->name, 180019808f9SSimon Glass setup->value); 181019808f9SSimon Glass plat->devnum = setup->value; 182019808f9SSimon Glass return 0; 183019808f9SSimon Glass default: 184019808f9SSimon Glass debug("requestsend =%x\n", setup->request); 185019808f9SSimon Glass break; 186019808f9SSimon Glass } 187019808f9SSimon Glass } else if (pipe == usb_sndctrlpipe(udev, 0)) { 188019808f9SSimon Glass switch (setup->request) { 189019808f9SSimon Glass case USB_REQ_SET_CONFIGURATION: 190019808f9SSimon Glass plat->configno = setup->value; 191019808f9SSimon Glass return 0; 192019808f9SSimon Glass default: 193019808f9SSimon Glass ret = device_probe(emul); 194019808f9SSimon Glass if (ret) 195019808f9SSimon Glass return ret; 196019808f9SSimon Glass return ops->control(emul, udev, pipe, buffer, length, 197019808f9SSimon Glass setup); 198019808f9SSimon Glass } 199019808f9SSimon Glass } 200019808f9SSimon Glass debug("pipe=%lx\n", pipe); 201019808f9SSimon Glass 202019808f9SSimon Glass return -EIO; 203019808f9SSimon Glass } 204019808f9SSimon Glass 205019808f9SSimon Glass int usb_emul_bulk(struct udevice *emul, struct usb_device *udev, 206019808f9SSimon Glass unsigned long pipe, void *buffer, int length) 207019808f9SSimon Glass { 208019808f9SSimon Glass struct dm_usb_ops *ops = usb_get_emul_ops(emul); 209019808f9SSimon Glass int ret; 210019808f9SSimon Glass 211019808f9SSimon Glass /* We permit getting the descriptor before we are probed */ 212019808f9SSimon Glass if (!ops->bulk) 213019808f9SSimon Glass return -ENOSYS; 214019808f9SSimon Glass debug("%s: dev=%s\n", __func__, emul->name); 215019808f9SSimon Glass ret = device_probe(emul); 216019808f9SSimon Glass if (ret) 217019808f9SSimon Glass return ret; 218019808f9SSimon Glass return ops->bulk(emul, udev, pipe, buffer, length); 219019808f9SSimon Glass } 220019808f9SSimon Glass 221019808f9SSimon Glass int usb_emul_setup_device(struct udevice *dev, int maxpacketsize, 222019808f9SSimon Glass struct usb_string *strings, void **desc_list) 223019808f9SSimon Glass { 224019808f9SSimon Glass struct usb_dev_platdata *plat = dev_get_parent_platdata(dev); 225019808f9SSimon Glass struct usb_generic_descriptor **ptr; 226019808f9SSimon Glass struct usb_config_descriptor *cdesc; 227019808f9SSimon Glass int upto; 228019808f9SSimon Glass 229019808f9SSimon Glass plat->strings = strings; 230019808f9SSimon Glass plat->desc_list = (struct usb_generic_descriptor **)desc_list; 231019808f9SSimon Glass 232019808f9SSimon Glass /* Fill in wTotalLength for each configuration descriptor */ 233019808f9SSimon Glass ptr = plat->desc_list; 234019808f9SSimon Glass for (cdesc = NULL, upto = 0; *ptr; upto += (*ptr)->bLength, ptr++) { 235019808f9SSimon Glass debug(" - upto=%d, type=%d\n", upto, (*ptr)->bDescriptorType); 236019808f9SSimon Glass if ((*ptr)->bDescriptorType == USB_DT_CONFIG) { 237019808f9SSimon Glass if (cdesc) { 238019808f9SSimon Glass cdesc->wTotalLength = upto; 239019808f9SSimon Glass debug("%s: config %d length %d\n", __func__, 240019808f9SSimon Glass cdesc->bConfigurationValue, 241019808f9SSimon Glass cdesc->bLength); 242019808f9SSimon Glass } 243019808f9SSimon Glass cdesc = (struct usb_config_descriptor *)*ptr; 244019808f9SSimon Glass upto = 0; 245019808f9SSimon Glass } 246019808f9SSimon Glass } 247019808f9SSimon Glass if (cdesc) { 248019808f9SSimon Glass cdesc->wTotalLength = upto; 249019808f9SSimon Glass debug("%s: config %d length %d\n", __func__, 250019808f9SSimon Glass cdesc->bConfigurationValue, cdesc->wTotalLength); 251019808f9SSimon Glass } 252019808f9SSimon Glass 253019808f9SSimon Glass return 0; 254019808f9SSimon Glass } 255019808f9SSimon Glass 256019808f9SSimon Glass int usb_emul_post_bind(struct udevice *dev) 257019808f9SSimon Glass { 258019808f9SSimon Glass /* Scan the bus for devices */ 259019808f9SSimon Glass return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); 260019808f9SSimon Glass } 261019808f9SSimon Glass 262019808f9SSimon Glass void usb_emul_reset(struct udevice *dev) 263019808f9SSimon Glass { 264019808f9SSimon Glass struct usb_dev_platdata *plat = dev_get_parent_platdata(dev); 265019808f9SSimon Glass 266019808f9SSimon Glass plat->devnum = 0; 267019808f9SSimon Glass plat->configno = 0; 268019808f9SSimon Glass } 269019808f9SSimon Glass 270019808f9SSimon Glass UCLASS_DRIVER(usb_emul) = { 271019808f9SSimon Glass .id = UCLASS_USB_EMUL, 272019808f9SSimon Glass .name = "usb_emul", 273019808f9SSimon Glass .post_bind = usb_emul_post_bind, 274019808f9SSimon Glass .per_child_auto_alloc_size = sizeof(struct usb_device), 275019808f9SSimon Glass .per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata), 276019808f9SSimon Glass }; 277