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