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/device-internal.h> 12019808f9SSimon Glass 13019808f9SSimon Glass DECLARE_GLOBAL_DATA_PTR; 14019808f9SSimon Glass 15019808f9SSimon Glass static int copy_to_unicode(char *buff, int length, const char *str) 16019808f9SSimon Glass { 17019808f9SSimon Glass int ptr; 18019808f9SSimon Glass int i; 19019808f9SSimon Glass 20019808f9SSimon Glass if (length < 2) 21019808f9SSimon Glass return 0; 22019808f9SSimon Glass buff[1] = USB_DT_STRING; 23019808f9SSimon Glass for (ptr = 2, i = 0; ptr + 1 < length && *str; i++, ptr += 2) { 24019808f9SSimon Glass buff[ptr] = str[i]; 25019808f9SSimon Glass buff[ptr + 1] = 0; 26019808f9SSimon Glass } 27019808f9SSimon Glass buff[0] = ptr; 28019808f9SSimon Glass 29019808f9SSimon Glass return ptr; 30019808f9SSimon Glass } 31019808f9SSimon Glass 32019808f9SSimon Glass static int usb_emul_get_string(struct usb_string *strings, int index, 33019808f9SSimon Glass char *buff, int length) 34019808f9SSimon Glass { 35019808f9SSimon Glass if (index == 0) { 36019808f9SSimon Glass char *desc = buff; 37019808f9SSimon Glass 38019808f9SSimon Glass desc[0] = 4; 39019808f9SSimon Glass desc[1] = USB_DT_STRING; 40019808f9SSimon Glass desc[2] = 0x09; 41019808f9SSimon Glass desc[3] = 0x14; 42019808f9SSimon Glass return 4; 43019808f9SSimon Glass } else if (strings) { 44019808f9SSimon Glass struct usb_string *ptr; 45019808f9SSimon Glass 46019808f9SSimon Glass for (ptr = strings; ptr->s; ptr++) { 47019808f9SSimon Glass if (ptr->id == index) 48019808f9SSimon Glass return copy_to_unicode(buff, length, ptr->s); 49019808f9SSimon Glass } 50019808f9SSimon Glass } 51019808f9SSimon Glass 52019808f9SSimon Glass return -EINVAL; 53019808f9SSimon Glass } 54019808f9SSimon Glass 55*8e288127SBin Meng struct usb_generic_descriptor **usb_emul_find_descriptor( 56019808f9SSimon Glass struct usb_generic_descriptor **ptr, int type, int index) 57019808f9SSimon Glass { 58019808f9SSimon Glass debug("%s: type=%x, index=%d\n", __func__, type, index); 59019808f9SSimon Glass for (; *ptr; ptr++) { 60019808f9SSimon Glass if ((*ptr)->bDescriptorType != type) 61019808f9SSimon Glass continue; 62019808f9SSimon Glass switch (type) { 63019808f9SSimon Glass case USB_DT_CONFIG: { 64019808f9SSimon Glass struct usb_config_descriptor *cdesc; 65019808f9SSimon Glass 66019808f9SSimon Glass cdesc = (struct usb_config_descriptor *)*ptr; 67019808f9SSimon Glass if (cdesc && cdesc->bConfigurationValue == index) 68019808f9SSimon Glass return ptr; 69019808f9SSimon Glass break; 70019808f9SSimon Glass } 71019808f9SSimon Glass default: 72019808f9SSimon Glass return ptr; 73019808f9SSimon Glass } 74019808f9SSimon Glass } 75019808f9SSimon Glass debug("%s: config ptr=%p\n", __func__, *ptr); 76019808f9SSimon Glass 77019808f9SSimon Glass return ptr; 78019808f9SSimon Glass } 79019808f9SSimon Glass 80019808f9SSimon Glass static int usb_emul_get_descriptor(struct usb_dev_platdata *plat, int value, 81019808f9SSimon Glass void *buffer, int length) 82019808f9SSimon Glass { 83019808f9SSimon Glass struct usb_generic_descriptor **ptr; 84019808f9SSimon Glass int type = value >> 8; 85019808f9SSimon Glass int index = value & 0xff; 86019808f9SSimon Glass int upto, todo; 87019808f9SSimon Glass 88019808f9SSimon Glass debug("%s: type=%d, index=%d, plat=%p\n", __func__, type, index, plat); 89019808f9SSimon Glass if (type == USB_DT_STRING) { 90019808f9SSimon Glass return usb_emul_get_string(plat->strings, index, buffer, 91019808f9SSimon Glass length); 92019808f9SSimon Glass } 93019808f9SSimon Glass 94*8e288127SBin Meng ptr = usb_emul_find_descriptor(plat->desc_list, type, index); 95019808f9SSimon Glass if (!ptr) { 96019808f9SSimon Glass debug("%s: Could not find descriptor type %d, index %d\n", 97019808f9SSimon Glass __func__, type, index); 98019808f9SSimon Glass return -ENOENT; 99019808f9SSimon Glass } 100019808f9SSimon Glass for (upto = 0; *ptr && upto < length; ptr++, upto += todo) { 101019808f9SSimon Glass todo = min(length - upto, (int)(*ptr)->bLength); 102019808f9SSimon Glass 103019808f9SSimon Glass memcpy(buffer + upto, *ptr, todo); 104019808f9SSimon Glass } 105019808f9SSimon Glass 106019808f9SSimon Glass return upto ? upto : length ? -EIO : 0; 107019808f9SSimon Glass } 108019808f9SSimon Glass 109af9c7c11SSimon Glass static int usb_emul_find_devnum(int devnum, struct udevice **emulp) 110019808f9SSimon Glass { 111019808f9SSimon Glass struct udevice *dev; 112019808f9SSimon Glass struct uclass *uc; 113019808f9SSimon Glass int ret; 114019808f9SSimon Glass 115019808f9SSimon Glass *emulp = NULL; 116019808f9SSimon Glass ret = uclass_get(UCLASS_USB_EMUL, &uc); 117019808f9SSimon Glass if (ret) 118019808f9SSimon Glass return ret; 119019808f9SSimon Glass uclass_foreach_dev(dev, uc) { 120019808f9SSimon Glass struct usb_dev_platdata *udev = dev_get_parent_platdata(dev); 121019808f9SSimon Glass 122019808f9SSimon Glass if (udev->devnum == devnum) { 123019808f9SSimon Glass debug("%s: Found emulator '%s', addr %d\n", __func__, 124019808f9SSimon Glass dev->name, udev->devnum); 125019808f9SSimon Glass *emulp = dev; 126019808f9SSimon Glass return 0; 127019808f9SSimon Glass } 128019808f9SSimon Glass } 129019808f9SSimon Glass 130019808f9SSimon Glass debug("%s: No emulator found, addr %d\n", __func__, devnum); 131019808f9SSimon Glass return -ENOENT; 132019808f9SSimon Glass } 133019808f9SSimon Glass 134af9c7c11SSimon Glass int usb_emul_find(struct udevice *bus, ulong pipe, struct udevice **emulp) 135af9c7c11SSimon Glass { 136af9c7c11SSimon Glass int devnum = usb_pipedevice(pipe); 137af9c7c11SSimon Glass 138af9c7c11SSimon Glass return usb_emul_find_devnum(devnum, emulp); 139af9c7c11SSimon Glass } 140af9c7c11SSimon Glass 141af9c7c11SSimon Glass int usb_emul_find_for_dev(struct udevice *dev, struct udevice **emulp) 142af9c7c11SSimon Glass { 143af9c7c11SSimon Glass struct usb_dev_platdata *udev = dev_get_parent_platdata(dev); 144af9c7c11SSimon Glass 145af9c7c11SSimon Glass return usb_emul_find_devnum(udev->devnum, emulp); 146af9c7c11SSimon Glass } 147af9c7c11SSimon Glass 148019808f9SSimon Glass int usb_emul_control(struct udevice *emul, struct usb_device *udev, 149019808f9SSimon Glass unsigned long pipe, void *buffer, int length, 150019808f9SSimon Glass struct devrequest *setup) 151019808f9SSimon Glass { 152019808f9SSimon Glass struct dm_usb_ops *ops = usb_get_emul_ops(emul); 153019808f9SSimon Glass struct usb_dev_platdata *plat; 154019808f9SSimon Glass int ret; 155019808f9SSimon Glass 156019808f9SSimon Glass /* We permit getting the descriptor before we are probed */ 157019808f9SSimon Glass plat = dev_get_parent_platdata(emul); 158019808f9SSimon Glass if (!ops->control) 159019808f9SSimon Glass return -ENOSYS; 160019808f9SSimon Glass debug("%s: dev=%s\n", __func__, emul->name); 161019808f9SSimon Glass if (pipe == usb_rcvctrlpipe(udev, 0)) { 162019808f9SSimon Glass switch (setup->request) { 163019808f9SSimon Glass case USB_REQ_GET_DESCRIPTOR: { 164019808f9SSimon Glass return usb_emul_get_descriptor(plat, setup->value, 165019808f9SSimon Glass buffer, length); 166019808f9SSimon Glass } 167019808f9SSimon Glass default: 168019808f9SSimon Glass ret = device_probe(emul); 169019808f9SSimon Glass if (ret) 170019808f9SSimon Glass return ret; 171019808f9SSimon Glass return ops->control(emul, udev, pipe, buffer, length, 172019808f9SSimon Glass setup); 173019808f9SSimon Glass } 174019808f9SSimon Glass } else if (pipe == usb_snddefctrl(udev)) { 175019808f9SSimon Glass switch (setup->request) { 176019808f9SSimon Glass case USB_REQ_SET_ADDRESS: 177019808f9SSimon Glass debug(" ** set address %s %d\n", emul->name, 178019808f9SSimon Glass setup->value); 179019808f9SSimon Glass plat->devnum = setup->value; 180019808f9SSimon Glass return 0; 181019808f9SSimon Glass default: 182019808f9SSimon Glass debug("requestsend =%x\n", setup->request); 183019808f9SSimon Glass break; 184019808f9SSimon Glass } 185019808f9SSimon Glass } else if (pipe == usb_sndctrlpipe(udev, 0)) { 186019808f9SSimon Glass switch (setup->request) { 187019808f9SSimon Glass case USB_REQ_SET_CONFIGURATION: 188019808f9SSimon Glass plat->configno = setup->value; 189019808f9SSimon Glass return 0; 190019808f9SSimon Glass default: 191019808f9SSimon Glass ret = device_probe(emul); 192019808f9SSimon Glass if (ret) 193019808f9SSimon Glass return ret; 194019808f9SSimon Glass return ops->control(emul, udev, pipe, buffer, length, 195019808f9SSimon Glass setup); 196019808f9SSimon Glass } 197019808f9SSimon Glass } 198019808f9SSimon Glass debug("pipe=%lx\n", pipe); 199019808f9SSimon Glass 200019808f9SSimon Glass return -EIO; 201019808f9SSimon Glass } 202019808f9SSimon Glass 203019808f9SSimon Glass int usb_emul_bulk(struct udevice *emul, struct usb_device *udev, 204019808f9SSimon Glass unsigned long pipe, void *buffer, int length) 205019808f9SSimon Glass { 206019808f9SSimon Glass struct dm_usb_ops *ops = usb_get_emul_ops(emul); 207019808f9SSimon Glass int ret; 208019808f9SSimon Glass 209019808f9SSimon Glass /* We permit getting the descriptor before we are probed */ 210019808f9SSimon Glass if (!ops->bulk) 211019808f9SSimon Glass return -ENOSYS; 212019808f9SSimon Glass debug("%s: dev=%s\n", __func__, emul->name); 213019808f9SSimon Glass ret = device_probe(emul); 214019808f9SSimon Glass if (ret) 215019808f9SSimon Glass return ret; 216019808f9SSimon Glass return ops->bulk(emul, udev, pipe, buffer, length); 217019808f9SSimon Glass } 218019808f9SSimon Glass 219b70a3feaSSimon Glass int usb_emul_int(struct udevice *emul, struct usb_device *udev, 220b70a3feaSSimon Glass unsigned long pipe, void *buffer, int length, int interval) 221b70a3feaSSimon Glass { 222b70a3feaSSimon Glass struct dm_usb_ops *ops = usb_get_emul_ops(emul); 223b70a3feaSSimon Glass 224b70a3feaSSimon Glass if (!ops->interrupt) 225b70a3feaSSimon Glass return -ENOSYS; 226b70a3feaSSimon Glass debug("%s: dev=%s\n", __func__, emul->name); 227b70a3feaSSimon Glass 228b70a3feaSSimon Glass return ops->interrupt(emul, udev, pipe, buffer, length, interval); 229b70a3feaSSimon Glass } 230b70a3feaSSimon Glass 231879f76fcSBin Meng int usb_emul_setup_device(struct udevice *dev, struct usb_string *strings, 232879f76fcSBin Meng void **desc_list) 233019808f9SSimon Glass { 234019808f9SSimon Glass struct usb_dev_platdata *plat = dev_get_parent_platdata(dev); 235019808f9SSimon Glass struct usb_generic_descriptor **ptr; 236019808f9SSimon Glass struct usb_config_descriptor *cdesc; 237019808f9SSimon Glass int upto; 238019808f9SSimon Glass 239019808f9SSimon Glass plat->strings = strings; 240019808f9SSimon Glass plat->desc_list = (struct usb_generic_descriptor **)desc_list; 241019808f9SSimon Glass 242019808f9SSimon Glass /* Fill in wTotalLength for each configuration descriptor */ 243019808f9SSimon Glass ptr = plat->desc_list; 244019808f9SSimon Glass for (cdesc = NULL, upto = 0; *ptr; upto += (*ptr)->bLength, ptr++) { 245019808f9SSimon Glass debug(" - upto=%d, type=%d\n", upto, (*ptr)->bDescriptorType); 246019808f9SSimon Glass if ((*ptr)->bDescriptorType == USB_DT_CONFIG) { 247019808f9SSimon Glass if (cdesc) { 248019808f9SSimon Glass cdesc->wTotalLength = upto; 249019808f9SSimon Glass debug("%s: config %d length %d\n", __func__, 250019808f9SSimon Glass cdesc->bConfigurationValue, 251019808f9SSimon Glass cdesc->bLength); 252019808f9SSimon Glass } 253019808f9SSimon Glass cdesc = (struct usb_config_descriptor *)*ptr; 254019808f9SSimon Glass upto = 0; 255019808f9SSimon Glass } 256019808f9SSimon Glass } 257019808f9SSimon Glass if (cdesc) { 258019808f9SSimon Glass cdesc->wTotalLength = upto; 259019808f9SSimon Glass debug("%s: config %d length %d\n", __func__, 260019808f9SSimon Glass cdesc->bConfigurationValue, cdesc->wTotalLength); 261019808f9SSimon Glass } 262019808f9SSimon Glass 263019808f9SSimon Glass return 0; 264019808f9SSimon Glass } 265019808f9SSimon Glass 266019808f9SSimon Glass void usb_emul_reset(struct udevice *dev) 267019808f9SSimon Glass { 268019808f9SSimon Glass struct usb_dev_platdata *plat = dev_get_parent_platdata(dev); 269019808f9SSimon Glass 270019808f9SSimon Glass plat->devnum = 0; 271019808f9SSimon Glass plat->configno = 0; 272019808f9SSimon Glass } 273019808f9SSimon Glass 274019808f9SSimon Glass UCLASS_DRIVER(usb_emul) = { 275019808f9SSimon Glass .id = UCLASS_USB_EMUL, 276019808f9SSimon Glass .name = "usb_emul", 27791195485SSimon Glass .post_bind = dm_scan_fdt_dev, 278019808f9SSimon Glass .per_child_auto_alloc_size = sizeof(struct usb_device), 279019808f9SSimon Glass .per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata), 280019808f9SSimon Glass }; 281