xref: /OK3568_Linux_fs/u-boot/drivers/usb/emul/usb-emul-uclass.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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