blob: b31dc950e3abb6ab6c389d89ee6917e1e6230612 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass59d66d22015-03-25 12:22:37 -06002/*
3 * (C) Copyright 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
Simon Glass59d66d22015-03-25 12:22:37 -06005 */
6
Patrick Delaunay81313352021-04-27 11:02:19 +02007#define LOG_CATEGORY UCLASS_USB_EMUL
8
Simon Glass59d66d22015-03-25 12:22:37 -06009#include <common.h>
10#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060011#include <log.h>
Simon Glass59d66d22015-03-25 12:22:37 -060012#include <usb.h>
Simon Glass59d66d22015-03-25 12:22:37 -060013#include <dm/device-internal.h>
14
Simon Glass59d66d22015-03-25 12:22:37 -060015static int copy_to_unicode(char *buff, int length, const char *str)
16{
17 int ptr;
Simon Glass59d66d22015-03-25 12:22:37 -060018
19 if (length < 2)
20 return 0;
21 buff[1] = USB_DT_STRING;
Andrew Scull7152f7b2022-04-03 10:39:11 +000022 for (ptr = 2; ptr + 1 < length && *str; str++, ptr += 2) {
23 buff[ptr] = *str;
Simon Glass59d66d22015-03-25 12:22:37 -060024 buff[ptr + 1] = 0;
25 }
26 buff[0] = ptr;
27
28 return ptr;
29}
30
31static int usb_emul_get_string(struct usb_string *strings, int index,
32 char *buff, int length)
33{
34 if (index == 0) {
35 char *desc = buff;
36
37 desc[0] = 4;
38 desc[1] = USB_DT_STRING;
39 desc[2] = 0x09;
40 desc[3] = 0x14;
41 return 4;
42 } else if (strings) {
43 struct usb_string *ptr;
44
45 for (ptr = strings; ptr->s; ptr++) {
46 if (ptr->id == index)
47 return copy_to_unicode(buff, length, ptr->s);
48 }
49 }
50
51 return -EINVAL;
52}
53
Bin Meng3b363762017-10-01 06:19:40 -070054struct usb_generic_descriptor **usb_emul_find_descriptor(
Simon Glass59d66d22015-03-25 12:22:37 -060055 struct usb_generic_descriptor **ptr, int type, int index)
56{
57 debug("%s: type=%x, index=%d\n", __func__, type, index);
58 for (; *ptr; ptr++) {
59 if ((*ptr)->bDescriptorType != type)
60 continue;
61 switch (type) {
62 case USB_DT_CONFIG: {
63 struct usb_config_descriptor *cdesc;
64
65 cdesc = (struct usb_config_descriptor *)*ptr;
66 if (cdesc && cdesc->bConfigurationValue == index)
67 return ptr;
68 break;
69 }
70 default:
71 return ptr;
72 }
73 }
74 debug("%s: config ptr=%p\n", __func__, *ptr);
75
76 return ptr;
77}
78
Simon Glassb75b15b2020-12-03 16:55:23 -070079static int usb_emul_get_descriptor(struct usb_dev_plat *plat, int value,
Simon Glass59d66d22015-03-25 12:22:37 -060080 void *buffer, int length)
81{
82 struct usb_generic_descriptor **ptr;
83 int type = value >> 8;
84 int index = value & 0xff;
85 int upto, todo;
86
87 debug("%s: type=%d, index=%d, plat=%p\n", __func__, type, index, plat);
88 if (type == USB_DT_STRING) {
89 return usb_emul_get_string(plat->strings, index, buffer,
90 length);
91 }
92
Bin Meng3b363762017-10-01 06:19:40 -070093 ptr = usb_emul_find_descriptor(plat->desc_list, type, index);
Simon Glass59d66d22015-03-25 12:22:37 -060094 if (!ptr) {
95 debug("%s: Could not find descriptor type %d, index %d\n",
96 __func__, type, index);
97 return -ENOENT;
98 }
99 for (upto = 0; *ptr && upto < length; ptr++, upto += todo) {
100 todo = min(length - upto, (int)(*ptr)->bLength);
101
102 memcpy(buffer + upto, *ptr, todo);
103 }
104
105 return upto ? upto : length ? -EIO : 0;
106}
107
Bin Mengf1966442017-10-01 06:19:39 -0700108static int usb_emul_find_devnum(int devnum, int port1, struct udevice **emulp)
Simon Glass59d66d22015-03-25 12:22:37 -0600109{
Simon Glass59d66d22015-03-25 12:22:37 -0600110 struct udevice *dev;
111 struct uclass *uc;
112 int ret;
113
114 *emulp = NULL;
115 ret = uclass_get(UCLASS_USB_EMUL, &uc);
116 if (ret)
117 return ret;
118 uclass_foreach_dev(dev, uc) {
Simon Glassb75b15b2020-12-03 16:55:23 -0700119 struct usb_dev_plat *udev = dev_get_parent_plat(dev);
Simon Glass59d66d22015-03-25 12:22:37 -0600120
Bin Mengf1966442017-10-01 06:19:39 -0700121 /*
122 * devnum is initialzied to zero at the beginning of the
123 * enumeration process in usb_setup_device(). At this
124 * point, udev->devnum has not been assigned to any valid
125 * USB address either, so we can't rely on the comparison
126 * result between udev->devnum and devnum to select an
127 * emulator device.
128 */
129 if (!devnum) {
Simon Glassb75b15b2020-12-03 16:55:23 -0700130 struct usb_emul_plat *plat;
Bin Mengf1966442017-10-01 06:19:39 -0700131
132 /*
133 * If the parent is sandbox USB controller, we are
134 * the root hub. And there is only one root hub
135 * in the system.
136 */
137 if (device_get_uclass_id(dev->parent) == UCLASS_USB) {
138 debug("%s: Found emulator '%s'\n",
139 __func__, dev->name);
140 *emulp = dev;
141 return 0;
142 }
143
Simon Glass71fa5b42020-12-03 16:55:18 -0700144 plat = dev_get_uclass_plat(dev);
Bin Mengf1966442017-10-01 06:19:39 -0700145 if (plat->port1 == port1) {
146 debug("%s: Found emulator '%s', port %d\n",
147 __func__, dev->name, port1);
148 *emulp = dev;
149 return 0;
150 }
151 } else if (udev->devnum == devnum) {
Simon Glass59d66d22015-03-25 12:22:37 -0600152 debug("%s: Found emulator '%s', addr %d\n", __func__,
153 dev->name, udev->devnum);
154 *emulp = dev;
155 return 0;
156 }
157 }
158
159 debug("%s: No emulator found, addr %d\n", __func__, devnum);
160 return -ENOENT;
161}
162
Bin Mengf1966442017-10-01 06:19:39 -0700163int usb_emul_find(struct udevice *bus, ulong pipe, int port1,
164 struct udevice **emulp)
Simon Glass668ef3d2015-11-08 23:47:55 -0700165{
166 int devnum = usb_pipedevice(pipe);
167
Bin Mengf1966442017-10-01 06:19:39 -0700168 return usb_emul_find_devnum(devnum, port1, emulp);
Simon Glass668ef3d2015-11-08 23:47:55 -0700169}
170
171int usb_emul_find_for_dev(struct udevice *dev, struct udevice **emulp)
172{
Simon Glassb75b15b2020-12-03 16:55:23 -0700173 struct usb_dev_plat *udev = dev_get_parent_plat(dev);
Simon Glass668ef3d2015-11-08 23:47:55 -0700174
Bin Mengf1966442017-10-01 06:19:39 -0700175 return usb_emul_find_devnum(udev->devnum, 0, emulp);
Simon Glass668ef3d2015-11-08 23:47:55 -0700176}
177
Simon Glass59d66d22015-03-25 12:22:37 -0600178int usb_emul_control(struct udevice *emul, struct usb_device *udev,
179 unsigned long pipe, void *buffer, int length,
180 struct devrequest *setup)
181{
182 struct dm_usb_ops *ops = usb_get_emul_ops(emul);
Simon Glassb75b15b2020-12-03 16:55:23 -0700183 struct usb_dev_plat *plat;
Simon Glass59d66d22015-03-25 12:22:37 -0600184 int ret;
185
186 /* We permit getting the descriptor before we are probed */
Simon Glass71fa5b42020-12-03 16:55:18 -0700187 plat = dev_get_parent_plat(emul);
Simon Glass59d66d22015-03-25 12:22:37 -0600188 if (!ops->control)
189 return -ENOSYS;
190 debug("%s: dev=%s\n", __func__, emul->name);
191 if (pipe == usb_rcvctrlpipe(udev, 0)) {
192 switch (setup->request) {
193 case USB_REQ_GET_DESCRIPTOR: {
194 return usb_emul_get_descriptor(plat, setup->value,
195 buffer, length);
196 }
197 default:
198 ret = device_probe(emul);
199 if (ret)
200 return ret;
201 return ops->control(emul, udev, pipe, buffer, length,
202 setup);
203 }
204 } else if (pipe == usb_snddefctrl(udev)) {
205 switch (setup->request) {
206 case USB_REQ_SET_ADDRESS:
207 debug(" ** set address %s %d\n", emul->name,
208 setup->value);
209 plat->devnum = setup->value;
210 return 0;
211 default:
212 debug("requestsend =%x\n", setup->request);
213 break;
214 }
215 } else if (pipe == usb_sndctrlpipe(udev, 0)) {
216 switch (setup->request) {
217 case USB_REQ_SET_CONFIGURATION:
218 plat->configno = setup->value;
219 return 0;
220 default:
221 ret = device_probe(emul);
222 if (ret)
223 return ret;
224 return ops->control(emul, udev, pipe, buffer, length,
225 setup);
226 }
227 }
228 debug("pipe=%lx\n", pipe);
229
230 return -EIO;
231}
232
233int usb_emul_bulk(struct udevice *emul, struct usb_device *udev,
234 unsigned long pipe, void *buffer, int length)
235{
236 struct dm_usb_ops *ops = usb_get_emul_ops(emul);
237 int ret;
238
239 /* We permit getting the descriptor before we are probed */
240 if (!ops->bulk)
241 return -ENOSYS;
242 debug("%s: dev=%s\n", __func__, emul->name);
243 ret = device_probe(emul);
244 if (ret)
245 return ret;
246 return ops->bulk(emul, udev, pipe, buffer, length);
247}
248
Simon Glass90421792015-11-08 23:48:05 -0700249int usb_emul_int(struct udevice *emul, struct usb_device *udev,
Michal Suchanek1c95b9f2019-08-18 10:55:27 +0200250 unsigned long pipe, void *buffer, int length, int interval,
251 bool nonblock)
Simon Glass90421792015-11-08 23:48:05 -0700252{
253 struct dm_usb_ops *ops = usb_get_emul_ops(emul);
254
255 if (!ops->interrupt)
256 return -ENOSYS;
257 debug("%s: dev=%s\n", __func__, emul->name);
258
Michal Suchanek1c95b9f2019-08-18 10:55:27 +0200259 return ops->interrupt(emul, udev, pipe, buffer, length, interval,
260 nonblock);
Simon Glass90421792015-11-08 23:48:05 -0700261}
262
Bin Mengd502cf12017-10-01 06:19:36 -0700263int usb_emul_setup_device(struct udevice *dev, struct usb_string *strings,
264 void **desc_list)
Simon Glass59d66d22015-03-25 12:22:37 -0600265{
Simon Glassb75b15b2020-12-03 16:55:23 -0700266 struct usb_dev_plat *plat = dev_get_parent_plat(dev);
Simon Glass59d66d22015-03-25 12:22:37 -0600267 struct usb_generic_descriptor **ptr;
268 struct usb_config_descriptor *cdesc;
269 int upto;
270
271 plat->strings = strings;
272 plat->desc_list = (struct usb_generic_descriptor **)desc_list;
273
274 /* Fill in wTotalLength for each configuration descriptor */
275 ptr = plat->desc_list;
276 for (cdesc = NULL, upto = 0; *ptr; upto += (*ptr)->bLength, ptr++) {
277 debug(" - upto=%d, type=%d\n", upto, (*ptr)->bDescriptorType);
278 if ((*ptr)->bDescriptorType == USB_DT_CONFIG) {
279 if (cdesc) {
280 cdesc->wTotalLength = upto;
281 debug("%s: config %d length %d\n", __func__,
282 cdesc->bConfigurationValue,
283 cdesc->bLength);
284 }
285 cdesc = (struct usb_config_descriptor *)*ptr;
286 upto = 0;
287 }
288 }
289 if (cdesc) {
290 cdesc->wTotalLength = upto;
291 debug("%s: config %d length %d\n", __func__,
292 cdesc->bConfigurationValue, cdesc->wTotalLength);
293 }
294
295 return 0;
296}
297
Simon Glass59d66d22015-03-25 12:22:37 -0600298UCLASS_DRIVER(usb_emul) = {
299 .id = UCLASS_USB_EMUL,
300 .name = "usb_emul",
Simon Glass18230342016-07-05 17:10:10 -0600301 .post_bind = dm_scan_fdt_dev,
Simon Glassb75b15b2020-12-03 16:55:23 -0700302 .per_device_plat_auto = sizeof(struct usb_emul_plat),
Simon Glass8a2b47f2020-12-03 16:55:17 -0700303 .per_child_auto = sizeof(struct usb_device),
Simon Glassb75b15b2020-12-03 16:55:23 -0700304 .per_child_plat_auto = sizeof(struct usb_dev_plat),
Simon Glass59d66d22015-03-25 12:22:37 -0600305};