Blame view

common/usb.c 33.8 KB
affae2bff   wdenk   Initial revision
1
  /*
affae2bff   wdenk   Initial revision
2
   * Most of this source has been derived from the Linux USB
460c322f1   Wolfgang Denk   (re)enabled scsi ...
3
4
5
6
7
8
9
10
11
12
13
14
15
   * project:
   * (C) Copyright Linus Torvalds 1999
   * (C) Copyright Johannes Erdfelt 1999-2001
   * (C) Copyright Andreas Gal 1999
   * (C) Copyright Gregory P. Smith 1999
   * (C) Copyright Deti Fliegl 1999 (new USB architecture)
   * (C) Copyright Randy Dunlap 2000
   * (C) Copyright David Brownell 2000 (kernel hotplug, usb_device_id)
   * (C) Copyright Yggdrasil Computing, Inc. 2000
   *     (usb_device_id matching changes by Adam J. Richter)
   *
   * Adapted for U-Boot:
   * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
affae2bff   wdenk   Initial revision
16
   *
1a4596601   Wolfgang Denk   Add GPL-2.0+ SPDX...
17
   * SPDX-License-Identifier:	GPL-2.0+
affae2bff   wdenk   Initial revision
18
   */
affae2bff   wdenk   Initial revision
19
20
21
22
23
24
25
26
27
28
29
  /*
   * How it works:
   *
   * Since this is a bootloader, the devices will not be automatic
   * (re)configured on hotplug, but after a restart of the USB the
   * device should work.
   *
   * For each transfer (except "Interrupt") we wait for completion.
   */
  #include <common.h>
  #include <command.h>
95fbfe429   Simon Glass   dm: usb: Convert ...
30
  #include <dm.h>
cf92e05c0   Simon Glass   Move ALLOC_CACHE_...
31
  #include <memalign.h>
affae2bff   wdenk   Initial revision
32
  #include <asm/processor.h>
66cf64107   Mike Frysinger   usb: use noinline...
33
  #include <linux/compiler.h>
9c998aa83   Wolfgang Denk   Fix low-level OHC...
34
  #include <linux/ctype.h>
c918261c6   Christian Eggers   USB: replace old ...
35
  #include <asm/byteorder.h>
b2fb47f18   Tom Rini   USB: Use (get|put...
36
  #include <asm/unaligned.h>
97b9eb9e6   Marek Vasut   usb: Handle -ENOD...
37
  #include <errno.h>
affae2bff   wdenk   Initial revision
38
39
  #include <usb.h>
  #ifdef CONFIG_4xx
3048bcbf0   Stefan Roese   ppc4xx: Rename 40...
40
  #include <asm/4xx_pci.h>
affae2bff   wdenk   Initial revision
41
  #endif
cd0a9de68   wdenk   * Patch by Lauren...
42
  #define USB_BUFSIZ	512
affae2bff   wdenk   Initial revision
43
  static int asynch_allowed;
e51aae382   Bartlomiej Sieka   Prevent USB comma...
44
  char usb_started; /* flag for the started/stopped USB status */
95fbfe429   Simon Glass   dm: usb: Convert ...
45
46
47
  #ifndef CONFIG_DM_USB
  static struct usb_device usb_dev[USB_MAX_DEVICE];
  static int dev_index;
93c2582fe   Lucas Stach   usb: add support ...
48
49
50
  #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
  #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
  #endif
affae2bff   wdenk   Initial revision
51

affae2bff   wdenk   Initial revision
52
53
54
  /***************************************************************************
   * Init USB Device
   */
affae2bff   wdenk   Initial revision
55
56
  int usb_init(void)
  {
93c2582fe   Lucas Stach   usb: add support ...
57
58
59
  	void *ctrl;
  	struct usb_device *dev;
  	int i, start_index = 0;
d906bbc26   Hans de Goede   usb: Do not log a...
60
  	int controllers_initialized = 0;
97b9eb9e6   Marek Vasut   usb: Handle -ENOD...
61
  	int ret;
affae2bff   wdenk   Initial revision
62

6f5794a6f   Remy Bohmer   Refactoring parts...
63
64
  	dev_index = 0;
  	asynch_allowed = 1;
affae2bff   wdenk   Initial revision
65
  	usb_hub_reset();
93c2582fe   Lucas Stach   usb: add support ...
66
67
68
69
70
71
  
  	/* first make all devices unknown */
  	for (i = 0; i < USB_MAX_DEVICE; i++) {
  		memset(&usb_dev[i], 0, sizeof(struct usb_device));
  		usb_dev[i].devnum = -1;
  	}
affae2bff   wdenk   Initial revision
72
  	/* init low_level USB */
93c2582fe   Lucas Stach   usb: add support ...
73
74
75
  	for (i = 0; i < CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
  		/* init low_level USB */
  		printf("USB%d:   ", i);
97b9eb9e6   Marek Vasut   usb: Handle -ENOD...
76
77
78
79
  		ret = usb_lowlevel_init(i, USB_INIT_HOST, &ctrl);
  		if (ret == -ENODEV) {	/* No such device. */
  			puts("Port not available.
  ");
d906bbc26   Hans de Goede   usb: Do not log a...
80
  			controllers_initialized++;
97b9eb9e6   Marek Vasut   usb: Handle -ENOD...
81
82
83
84
  			continue;
  		}
  
  		if (ret) {		/* Other error. */
93c2582fe   Lucas Stach   usb: add support ...
85
86
87
88
89
90
91
92
  			puts("lowlevel init failed
  ");
  			continue;
  		}
  		/*
  		 * lowlevel init is OK, now scan the bus for devices
  		 * i.e. search HUBs and configure them
  		 */
d906bbc26   Hans de Goede   usb: Do not log a...
93
  		controllers_initialized++;
93c2582fe   Lucas Stach   usb: add support ...
94
95
  		start_index = dev_index;
  		printf("scanning bus %d for devices... ", i);
79b588872   Simon Glass   dm: usb: Adjust u...
96
97
  		ret = usb_alloc_new_device(ctrl, &dev);
  		if (ret)
8879be885   Paul Kocialkowski   usb: Check usb_ne...
98
  			break;
93c2582fe   Lucas Stach   usb: add support ...
99
100
101
102
  		/*
  		 * device 0 is always present
  		 * (root hub, so let it analyze)
  		 */
8879be885   Paul Kocialkowski   usb: Check usb_ne...
103
104
  		ret = usb_new_device(dev);
  		if (ret)
79b588872   Simon Glass   dm: usb: Adjust u...
105
  			usb_free_device(dev->controller);
93c2582fe   Lucas Stach   usb: add support ...
106

8879be885   Paul Kocialkowski   usb: Check usb_ne...
107
  		if (start_index == dev_index) {
93c2582fe   Lucas Stach   usb: add support ...
108
109
  			puts("No USB Device found
  ");
8879be885   Paul Kocialkowski   usb: Check usb_ne...
110
111
  			continue;
  		} else {
93c2582fe   Lucas Stach   usb: add support ...
112
113
114
  			printf("%d USB Device(s) found
  ",
  				dev_index - start_index);
8879be885   Paul Kocialkowski   usb: Check usb_ne...
115
  		}
93c2582fe   Lucas Stach   usb: add support ...
116

e51aae382   Bartlomiej Sieka   Prevent USB comma...
117
  		usb_started = 1;
93c2582fe   Lucas Stach   usb: add support ...
118
  	}
ceb4972a8   Vivek Gautam   usb: common: Weed...
119
120
  	debug("scan end
  ");
93c2582fe   Lucas Stach   usb: add support ...
121
  	/* if we were not able to find at least one working bus, bail out */
d906bbc26   Hans de Goede   usb: Do not log a...
122
  	if (controllers_initialized == 0)
93c2582fe   Lucas Stach   usb: add support ...
123
124
  		puts("USB error: all controllers failed lowlevel init
  ");
93c2582fe   Lucas Stach   usb: add support ...
125

5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
126
  	return usb_started ? 0 : -ENODEV;
affae2bff   wdenk   Initial revision
127
128
129
130
131
132
133
  }
  
  /******************************************************************************
   * Stop USB this stops the LowLevel Part and deregisters USB devices.
   */
  int usb_stop(void)
  {
93c2582fe   Lucas Stach   usb: add support ...
134
  	int i;
eba1f2fc7   Remy Bohmer   Make usb-stop() s...
135
136
137
138
139
  
  	if (usb_started) {
  		asynch_allowed = 1;
  		usb_started = 0;
  		usb_hub_reset();
93c2582fe   Lucas Stach   usb: add support ...
140
141
142
143
144
145
  
  		for (i = 0; i < CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
  			if (usb_lowlevel_stop(i))
  				printf("failed to stop USB controller %d
  ", i);
  		}
eba1f2fc7   Remy Bohmer   Make usb-stop() s...
146
  	}
93c2582fe   Lucas Stach   usb: add support ...
147
148
  
  	return 0;
affae2bff   wdenk   Initial revision
149
  }
08f3bb0bc   Vincent Palatin   usb: add device c...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
  /******************************************************************************
   * Detect if a USB device has been plugged or unplugged.
   */
  int usb_detect_change(void)
  {
  	int i, j;
  	int change = 0;
  
  	for (j = 0; j < USB_MAX_DEVICE; j++) {
  		for (i = 0; i < usb_dev[j].maxchild; i++) {
  			struct usb_port_status status;
  
  			if (usb_get_port_status(&usb_dev[j], i + 1,
  						&status) < 0)
  				/* USB request failed */
  				continue;
  
  			if (le16_to_cpu(status.wPortChange) &
  			    USB_PORT_STAT_C_CONNECTION)
  				change++;
  		}
  	}
  
  	return change;
  }
affae2bff   wdenk   Initial revision
175
176
177
  /*
   * disables the asynch behaviour of the control message. This is used for data
   * transfers that uses the exclusiv access to the control and bulk messages.
89d48367e   Simon Glass   Add USB host ethe...
178
   * Returns the old value so it can be restored later.
affae2bff   wdenk   Initial revision
179
   */
89d48367e   Simon Glass   Add USB host ethe...
180
  int usb_disable_asynch(int disable)
affae2bff   wdenk   Initial revision
181
  {
89d48367e   Simon Glass   Add USB host ethe...
182
  	int old_value = asynch_allowed;
6f5794a6f   Remy Bohmer   Refactoring parts...
183
  	asynch_allowed = !disable;
89d48367e   Simon Glass   Add USB host ethe...
184
  	return old_value;
affae2bff   wdenk   Initial revision
185
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
186
  #endif /* !CONFIG_DM_USB */
affae2bff   wdenk   Initial revision
187
188
189
190
191
192
193
194
195
196
197
  
  
  /*-------------------------------------------------------------------
   * Message wrappers.
   *
   */
  
  /*
   * submits an Interrupt Message
   */
  int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
6f5794a6f   Remy Bohmer   Refactoring parts...
198
  			void *buffer, int transfer_len, int interval)
affae2bff   wdenk   Initial revision
199
  {
6f5794a6f   Remy Bohmer   Refactoring parts...
200
  	return submit_int_msg(dev, pipe, buffer, transfer_len, interval);
affae2bff   wdenk   Initial revision
201
202
203
204
205
206
207
208
  }
  
  /*
   * submits a control message and waits for comletion (at least timeout * 1ms)
   * If timeout is 0, we don't wait for completion (used as example to set and
   * clear keyboards LEDs). For data transfers, (storage transfers) we don't
   * allow control messages with 0 timeout, by previousely resetting the flag
   * asynch_allowed (usb_disable_asynch(1)).
a6f70a3d1   Vagrant Cascadian   Fix spelling of "...
209
   * returns the transferred length if OK or -1 if error. The transferred length
affae2bff   wdenk   Initial revision
210
211
212
213
214
215
216
   * and the current status are stored in the dev->act_len and dev->status.
   */
  int usb_control_msg(struct usb_device *dev, unsigned int pipe,
  			unsigned char request, unsigned char requesttype,
  			unsigned short value, unsigned short index,
  			void *data, unsigned short size, int timeout)
  {
f57661394   Puneet Saxena   USB: Align buffer...
217
  	ALLOC_CACHE_ALIGN_BUFFER(struct devrequest, setup_packet, 1);
651d95c8e   Hans de Goede   usb: usb_control_...
218
  	int err;
e159e4868   Marek Vasut   USB: Make struct ...
219

6f5794a6f   Remy Bohmer   Refactoring parts...
220
221
  	if ((timeout == 0) && (!asynch_allowed)) {
  		/* request for a asynch control pipe is not allowed */
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
222
  		return -EINVAL;
6f5794a6f   Remy Bohmer   Refactoring parts...
223
  	}
9c998aa83   Wolfgang Denk   Fix low-level OHC...
224

affae2bff   wdenk   Initial revision
225
  	/* set setup command */
f57661394   Puneet Saxena   USB: Align buffer...
226
227
228
229
230
  	setup_packet->requesttype = requesttype;
  	setup_packet->request = request;
  	setup_packet->value = cpu_to_le16(value);
  	setup_packet->index = cpu_to_le16(index);
  	setup_packet->length = cpu_to_le16(size);
ceb4972a8   Vivek Gautam   usb: common: Weed...
231
232
233
234
  	debug("usb_control_msg: request: 0x%X, requesttype: 0x%X, " \
  	      "value 0x%X index 0x%X length 0x%X
  ",
  	      request, requesttype, value, index, size);
6f5794a6f   Remy Bohmer   Refactoring parts...
235
  	dev->status = USB_ST_NOT_PROC; /*not yet processed */
affae2bff   wdenk   Initial revision
236

651d95c8e   Hans de Goede   usb: usb_control_...
237
238
239
  	err = submit_control_msg(dev, pipe, data, size, setup_packet);
  	if (err < 0)
  		return err;
6f5794a6f   Remy Bohmer   Refactoring parts...
240
  	if (timeout == 0)
affae2bff   wdenk   Initial revision
241
  		return (int)size;
6f5794a6f   Remy Bohmer   Refactoring parts...
242

84d36b301   Remy Bohmer   USB: usb_control_...
243
244
245
246
247
248
249
250
  	/*
  	 * Wait for status to update until timeout expires, USB driver
  	 * interrupt handler may set the status when the USB operation has
  	 * been completed.
  	 */
  	while (timeout--) {
  		if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
  			break;
5b84dd67c   Mike Frysinger   usb: replace wait...
251
  		mdelay(1);
488672084   Remy Bohmer   fix USB initialis...
252
  	}
84d36b301   Remy Bohmer   USB: usb_control_...
253
254
  	if (dev->status)
  		return -1;
488672084   Remy Bohmer   fix USB initialis...
255
256
  
  	return dev->act_len;
84d36b301   Remy Bohmer   USB: usb_control_...
257

affae2bff   wdenk   Initial revision
258
259
260
261
  }
  
  /*-------------------------------------------------------------------
   * submits bulk message, and waits for completion. returns 0 if Ok or
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
262
   * negative if Error.
affae2bff   wdenk   Initial revision
263
264
265
266
267
268
   * synchronous behavior
   */
  int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
  			void *data, int len, int *actual_length, int timeout)
  {
  	if (len < 0)
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
269
  		return -EINVAL;
6f5794a6f   Remy Bohmer   Refactoring parts...
270
  	dev->status = USB_ST_NOT_PROC; /*not yet processed */
fd06028df   Ilya Yanok   usb: check return...
271
  	if (submit_bulk_msg(dev, pipe, data, len) < 0)
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
272
  		return -EIO;
6f5794a6f   Remy Bohmer   Refactoring parts...
273
274
  	while (timeout--) {
  		if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
affae2bff   wdenk   Initial revision
275
  			break;
5b84dd67c   Mike Frysinger   usb: replace wait...
276
  		mdelay(1);
affae2bff   wdenk   Initial revision
277
  	}
6f5794a6f   Remy Bohmer   Refactoring parts...
278
279
  	*actual_length = dev->act_len;
  	if (dev->status == 0)
affae2bff   wdenk   Initial revision
280
281
  		return 0;
  	else
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
282
  		return -EIO;
affae2bff   wdenk   Initial revision
283
284
285
286
287
288
289
290
291
292
293
  }
  
  
  /*-------------------------------------------------------------------
   * Max Packet stuff
   */
  
  /*
   * returns the max packet size, depending on the pipe direction and
   * the configurations values
   */
6f5794a6f   Remy Bohmer   Refactoring parts...
294
  int usb_maxpacket(struct usb_device *dev, unsigned long pipe)
affae2bff   wdenk   Initial revision
295
  {
6f5794a6f   Remy Bohmer   Refactoring parts...
296
297
  	/* direction is out -> use emaxpacket out */
  	if ((pipe & USB_DIR_IN) == 0)
de39f8c19   Michael Trimarchi   USB style patch, ...
298
  		return dev->epmaxpacketout[((pipe>>15) & 0xf)];
affae2bff   wdenk   Initial revision
299
  	else
de39f8c19   Michael Trimarchi   USB style patch, ...
300
  		return dev->epmaxpacketin[((pipe>>15) & 0xf)];
affae2bff   wdenk   Initial revision
301
  }
5e8baf878   Marek Vasut   GCC4.6: Fix commo...
302
303
  /*
   * The routine usb_set_maxpacket_ep() is extracted from the loop of routine
be19d324e   Remy Bohmer   Fix for USB stick...
304
305
306
307
308
309
   * usb_set_maxpacket(), because the optimizer of GCC 4.x chokes on this routine
   * when it is inlined in 1 single routine. What happens is that the register r3
   * is used as loop-count 'i', but gets overwritten later on.
   * This is clearly a compiler bug, but it is easier to workaround it here than
   * to update the compiler (Occurs with at least several GCC 4.{1,2},x
   * CodeSourcery compilers like e.g. 2007q3, 2008q1, 2008q3 lite editions on ARM)
5e8baf878   Marek Vasut   GCC4.6: Fix commo...
310
311
   *
   * NOTE: Similar behaviour was observed with GCC4.6 on ARMv5.
be19d324e   Remy Bohmer   Fix for USB stick...
312
   */
66cf64107   Mike Frysinger   usb: use noinline...
313
  static void noinline
5e8baf878   Marek Vasut   GCC4.6: Fix commo...
314
  usb_set_maxpacket_ep(struct usb_device *dev, int if_idx, int ep_idx)
be19d324e   Remy Bohmer   Fix for USB stick...
315
316
  {
  	int b;
5e8baf878   Marek Vasut   GCC4.6: Fix commo...
317
  	struct usb_endpoint_descriptor *ep;
b2fb47f18   Tom Rini   USB: Use (get|put...
318
  	u16 ep_wMaxPacketSize;
5e8baf878   Marek Vasut   GCC4.6: Fix commo...
319
320
  
  	ep = &dev->config.if_desc[if_idx].ep_desc[ep_idx];
be19d324e   Remy Bohmer   Fix for USB stick...
321
322
  
  	b = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
b2fb47f18   Tom Rini   USB: Use (get|put...
323
  	ep_wMaxPacketSize = get_unaligned(&ep->wMaxPacketSize);
be19d324e   Remy Bohmer   Fix for USB stick...
324
325
326
327
  
  	if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
  						USB_ENDPOINT_XFER_CONTROL) {
  		/* Control => bidirectional */
b2fb47f18   Tom Rini   USB: Use (get|put...
328
329
  		dev->epmaxpacketout[b] = ep_wMaxPacketSize;
  		dev->epmaxpacketin[b] = ep_wMaxPacketSize;
ceb4972a8   Vivek Gautam   usb: common: Weed...
330
331
332
  		debug("##Control EP epmaxpacketout/in[%d] = %d
  ",
  		      b, dev->epmaxpacketin[b]);
be19d324e   Remy Bohmer   Fix for USB stick...
333
334
335
  	} else {
  		if ((ep->bEndpointAddress & 0x80) == 0) {
  			/* OUT Endpoint */
b2fb47f18   Tom Rini   USB: Use (get|put...
336
337
  			if (ep_wMaxPacketSize > dev->epmaxpacketout[b]) {
  				dev->epmaxpacketout[b] = ep_wMaxPacketSize;
ceb4972a8   Vivek Gautam   usb: common: Weed...
338
339
340
  				debug("##EP epmaxpacketout[%d] = %d
  ",
  				      b, dev->epmaxpacketout[b]);
be19d324e   Remy Bohmer   Fix for USB stick...
341
342
343
  			}
  		} else {
  			/* IN Endpoint */
b2fb47f18   Tom Rini   USB: Use (get|put...
344
345
  			if (ep_wMaxPacketSize > dev->epmaxpacketin[b]) {
  				dev->epmaxpacketin[b] = ep_wMaxPacketSize;
ceb4972a8   Vivek Gautam   usb: common: Weed...
346
347
348
  				debug("##EP epmaxpacketin[%d] = %d
  ",
  				      b, dev->epmaxpacketin[b]);
be19d324e   Remy Bohmer   Fix for USB stick...
349
350
351
352
  			}
  		} /* if out */
  	} /* if control */
  }
affae2bff   wdenk   Initial revision
353
354
355
  /*
   * set the max packed value of all endpoints in the given configuration
   */
c08b1b264   Marek Vasut   USB: Staticize in...
356
  static int usb_set_maxpacket(struct usb_device *dev)
affae2bff   wdenk   Initial revision
357
  {
be19d324e   Remy Bohmer   Fix for USB stick...
358
  	int i, ii;
affae2bff   wdenk   Initial revision
359

8f8bd565f   Tom Rix   USB Consolidate d...
360
361
  	for (i = 0; i < dev->config.desc.bNumInterfaces; i++)
  		for (ii = 0; ii < dev->config.if_desc[i].desc.bNumEndpoints; ii++)
5e8baf878   Marek Vasut   GCC4.6: Fix commo...
362
  			usb_set_maxpacket_ep(dev, i, ii);
affae2bff   wdenk   Initial revision
363

affae2bff   wdenk   Initial revision
364
365
366
367
368
369
  	return 0;
  }
  
  /*******************************************************************************
   * Parse the config, located in buffer, and fills the dev->config structure.
   * Note that all little/big endian swapping are done automatically.
eaf3e613e   Julius Werner   usb: Use well-kno...
370
   * (wTotalLength has already been swapped and sanitized when it was read.)
affae2bff   wdenk   Initial revision
371
   */
c08b1b264   Marek Vasut   USB: Staticize in...
372
373
  static int usb_parse_config(struct usb_device *dev,
  			unsigned char *buffer, int cfgno)
affae2bff   wdenk   Initial revision
374
375
  {
  	struct usb_descriptor_header *head;
7455af41d   Bartlomiej Sieka   Add rudimentary h...
376
  	int index, ifno, epno, curr_if_num;
b2fb47f18   Tom Rini   USB: Use (get|put...
377
  	u16 ep_wMaxPacketSize;
605bd75af   Vivek Gautam   USB: Some cleanup...
378
  	struct usb_interface *if_desc = NULL;
7455af41d   Bartlomiej Sieka   Add rudimentary h...
379
380
381
382
383
384
385
  
  	ifno = -1;
  	epno = -1;
  	curr_if_num = -1;
  
  	dev->configno = cfgno;
  	head = (struct usb_descriptor_header *) &buffer[0];
6f5794a6f   Remy Bohmer   Refactoring parts...
386
387
388
389
  	if (head->bDescriptorType != USB_DT_CONFIG) {
  		printf(" ERROR: NOT USB_CONFIG_DESC %x
  ",
  			head->bDescriptorType);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
390
  		return -EINVAL;
affae2bff   wdenk   Initial revision
391
  	}
eaf3e613e   Julius Werner   usb: Use well-kno...
392
393
394
  	if (head->bLength != USB_DT_CONFIG_SIZE) {
  		printf("ERROR: Invalid USB CFG length (%d)
  ", head->bLength);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
395
  		return -EINVAL;
eaf3e613e   Julius Werner   usb: Use well-kno...
396
397
  	}
  	memcpy(&dev->config, head, USB_DT_CONFIG_SIZE);
7455af41d   Bartlomiej Sieka   Add rudimentary h...
398
  	dev->config.no_of_if = 0;
affae2bff   wdenk   Initial revision
399

8f8bd565f   Tom Rix   USB Consolidate d...
400
  	index = dev->config.desc.bLength;
6f5794a6f   Remy Bohmer   Refactoring parts...
401
402
  	/* Ok the first entry must be a configuration entry,
  	 * now process the others */
7455af41d   Bartlomiej Sieka   Add rudimentary h...
403
  	head = (struct usb_descriptor_header *) &buffer[index];
eaf3e613e   Julius Werner   usb: Use well-kno...
404
  	while (index + 1 < dev->config.desc.wTotalLength && head->bLength) {
6f5794a6f   Remy Bohmer   Refactoring parts...
405
406
  		switch (head->bDescriptorType) {
  		case USB_DT_INTERFACE:
eaf3e613e   Julius Werner   usb: Use well-kno...
407
408
409
410
411
412
413
414
415
416
417
418
  			if (head->bLength != USB_DT_INTERFACE_SIZE) {
  				printf("ERROR: Invalid USB IF length (%d)
  ",
  					head->bLength);
  				break;
  			}
  			if (index + USB_DT_INTERFACE_SIZE >
  			    dev->config.desc.wTotalLength) {
  				puts("USB IF descriptor overflowed buffer!
  ");
  				break;
  			}
6f5794a6f   Remy Bohmer   Refactoring parts...
419
  			if (((struct usb_interface_descriptor *) \
eaf3e613e   Julius Werner   usb: Use well-kno...
420
  			     head)->bInterfaceNumber != curr_if_num) {
6f5794a6f   Remy Bohmer   Refactoring parts...
421
422
  				/* this is a new interface, copy new desc */
  				ifno = dev->config.no_of_if;
eaf3e613e   Julius Werner   usb: Use well-kno...
423
424
425
426
  				if (ifno >= USB_MAXINTERFACES) {
  					puts("Too many USB interfaces!
  ");
  					/* try to go on with what we have */
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
427
  					return -EINVAL;
eaf3e613e   Julius Werner   usb: Use well-kno...
428
  				}
605bd75af   Vivek Gautam   USB: Some cleanup...
429
  				if_desc = &dev->config.if_desc[ifno];
6f5794a6f   Remy Bohmer   Refactoring parts...
430
  				dev->config.no_of_if++;
eaf3e613e   Julius Werner   usb: Use well-kno...
431
432
  				memcpy(if_desc, head,
  					USB_DT_INTERFACE_SIZE);
605bd75af   Vivek Gautam   USB: Some cleanup...
433
434
  				if_desc->no_of_ep = 0;
  				if_desc->num_altsetting = 1;
6f5794a6f   Remy Bohmer   Refactoring parts...
435
  				curr_if_num =
605bd75af   Vivek Gautam   USB: Some cleanup...
436
  				     if_desc->desc.bInterfaceNumber;
6f5794a6f   Remy Bohmer   Refactoring parts...
437
438
  			} else {
  				/* found alternate setting for the interface */
605bd75af   Vivek Gautam   USB: Some cleanup...
439
440
441
442
  				if (ifno >= 0) {
  					if_desc = &dev->config.if_desc[ifno];
  					if_desc->num_altsetting++;
  				}
6f5794a6f   Remy Bohmer   Refactoring parts...
443
444
445
  			}
  			break;
  		case USB_DT_ENDPOINT:
eaf3e613e   Julius Werner   usb: Use well-kno...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
  			if (head->bLength != USB_DT_ENDPOINT_SIZE) {
  				printf("ERROR: Invalid USB EP length (%d)
  ",
  					head->bLength);
  				break;
  			}
  			if (index + USB_DT_ENDPOINT_SIZE >
  			    dev->config.desc.wTotalLength) {
  				puts("USB EP descriptor overflowed buffer!
  ");
  				break;
  			}
  			if (ifno < 0) {
  				puts("Endpoint descriptor out of order!
  ");
  				break;
  			}
6f5794a6f   Remy Bohmer   Refactoring parts...
463
  			epno = dev->config.if_desc[ifno].no_of_ep;
605bd75af   Vivek Gautam   USB: Some cleanup...
464
  			if_desc = &dev->config.if_desc[ifno];
447b9cdf2   Peng Fan   common: usb: fix ...
465
  			if (epno >= USB_MAXENDPOINTS) {
eaf3e613e   Julius Werner   usb: Use well-kno...
466
467
468
  				printf("Interface %d has too many endpoints!
  ",
  					if_desc->desc.bInterfaceNumber);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
469
  				return -EINVAL;
eaf3e613e   Julius Werner   usb: Use well-kno...
470
  			}
6f5794a6f   Remy Bohmer   Refactoring parts...
471
  			/* found an endpoint */
605bd75af   Vivek Gautam   USB: Some cleanup...
472
  			if_desc->no_of_ep++;
eaf3e613e   Julius Werner   usb: Use well-kno...
473
474
  			memcpy(&if_desc->ep_desc[epno], head,
  				USB_DT_ENDPOINT_SIZE);
b2fb47f18   Tom Rini   USB: Use (get|put...
475
476
477
478
479
480
481
482
483
  			ep_wMaxPacketSize = get_unaligned(&dev->config.\
  							if_desc[ifno].\
  							ep_desc[epno].\
  							wMaxPacketSize);
  			put_unaligned(le16_to_cpu(ep_wMaxPacketSize),
  					&dev->config.\
  					if_desc[ifno].\
  					ep_desc[epno].\
  					wMaxPacketSize);
ceb4972a8   Vivek Gautam   usb: common: Weed...
484
485
  			debug("if %d, ep %d
  ", ifno, epno);
6f5794a6f   Remy Bohmer   Refactoring parts...
486
  			break;
6497c6670   Vivek Gautam   USB: SS: Add supp...
487
  		case USB_DT_SS_ENDPOINT_COMP:
eaf3e613e   Julius Werner   usb: Use well-kno...
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
  			if (head->bLength != USB_DT_SS_EP_COMP_SIZE) {
  				printf("ERROR: Invalid USB EPC length (%d)
  ",
  					head->bLength);
  				break;
  			}
  			if (index + USB_DT_SS_EP_COMP_SIZE >
  			    dev->config.desc.wTotalLength) {
  				puts("USB EPC descriptor overflowed buffer!
  ");
  				break;
  			}
  			if (ifno < 0 || epno < 0) {
  				puts("EPC descriptor out of order!
  ");
  				break;
  			}
6497c6670   Vivek Gautam   USB: SS: Add supp...
505
  			if_desc = &dev->config.if_desc[ifno];
eaf3e613e   Julius Werner   usb: Use well-kno...
506
507
  			memcpy(&if_desc->ss_ep_comp_desc[epno], head,
  				USB_DT_SS_EP_COMP_SIZE);
6497c6670   Vivek Gautam   USB: SS: Add supp...
508
  			break;
6f5794a6f   Remy Bohmer   Refactoring parts...
509
510
  		default:
  			if (head->bLength == 0)
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
511
  				return -EINVAL;
6f5794a6f   Remy Bohmer   Refactoring parts...
512

ceb4972a8   Vivek Gautam   usb: common: Weed...
513
514
515
  			debug("unknown Description Type : %x
  ",
  			      head->bDescriptorType);
6f5794a6f   Remy Bohmer   Refactoring parts...
516

ceb4972a8   Vivek Gautam   usb: common: Weed...
517
  #ifdef DEBUG
6f5794a6f   Remy Bohmer   Refactoring parts...
518
  			{
fad2e1b06   Wolfgang Denk   common/usb.c: fix...
519
  				unsigned char *ch = (unsigned char *)head;
ceb4972a8   Vivek Gautam   usb: common: Weed...
520
  				int i;
6f5794a6f   Remy Bohmer   Refactoring parts...
521
  				for (i = 0; i < head->bLength; i++)
ceb4972a8   Vivek Gautam   usb: common: Weed...
522
523
524
525
526
  					debug("%02X ", *ch++);
  				debug("
  
  
  ");
6f5794a6f   Remy Bohmer   Refactoring parts...
527
  			}
ceb4972a8   Vivek Gautam   usb: common: Weed...
528
  #endif
6f5794a6f   Remy Bohmer   Refactoring parts...
529
  			break;
affae2bff   wdenk   Initial revision
530
  		}
7455af41d   Bartlomiej Sieka   Add rudimentary h...
531
532
  		index += head->bLength;
  		head = (struct usb_descriptor_header *)&buffer[index];
affae2bff   wdenk   Initial revision
533
  	}
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
534
  	return 0;
affae2bff   wdenk   Initial revision
535
536
537
538
539
540
541
542
543
544
  }
  
  /***********************************************************************
   * Clears an endpoint
   * endp: endpoint number in bits 0-3;
   * direction flag in bit 7 (1 = IN, 0 = OUT)
   */
  int usb_clear_halt(struct usb_device *dev, int pipe)
  {
  	int result;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
545
  	int endp = usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
affae2bff   wdenk   Initial revision
546
547
  
  	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
6f5794a6f   Remy Bohmer   Refactoring parts...
548
549
  				 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
  				 endp, NULL, 0, USB_CNTL_TIMEOUT * 3);
affae2bff   wdenk   Initial revision
550
551
552
553
  
  	/* don't clear if failed */
  	if (result < 0)
  		return result;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
554

095b8a379   Wolfgang Denk   Coding style cleanup
555
  	/*
9c998aa83   Wolfgang Denk   Fix low-level OHC...
556
557
558
  	 * NOTE: we do not get status and verify reset was successful
  	 * as some devices are reported to lock up upon this check..
  	 */
affae2bff   wdenk   Initial revision
559
  	usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
9c998aa83   Wolfgang Denk   Fix low-level OHC...
560

affae2bff   wdenk   Initial revision
561
562
563
564
565
566
567
568
569
  	/* toggle is reset on clear */
  	usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
  	return 0;
  }
  
  
  /**********************************************************************
   * get_descriptor type
   */
c08b1b264   Marek Vasut   USB: Staticize in...
570
  static int usb_get_descriptor(struct usb_device *dev, unsigned char type,
6f5794a6f   Remy Bohmer   Refactoring parts...
571
  			unsigned char index, void *buf, int size)
affae2bff   wdenk   Initial revision
572
  {
8319aeb1d   Masahiro Yamada   usb: squash lines...
573
574
575
576
  	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
  			       USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
  			       (type << 8) + index, 0, buf, size,
  			       USB_CNTL_TIMEOUT);
affae2bff   wdenk   Initial revision
577
578
579
  }
  
  /**********************************************************************
c75f57fba   Stefan Brüns   usb: Alloc buffer...
580
   * gets len of configuration cfgno
affae2bff   wdenk   Initial revision
581
   */
c75f57fba   Stefan Brüns   usb: Alloc buffer...
582
  int usb_get_configuration_len(struct usb_device *dev, int cfgno)
affae2bff   wdenk   Initial revision
583
  {
53677ef18   Wolfgang Denk   Big white-space c...
584
  	int result;
c75f57fba   Stefan Brüns   usb: Alloc buffer...
585
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, 9);
c60795f41   Ilya Yanok   usb: use linux/us...
586
  	struct usb_config_descriptor *config;
affae2bff   wdenk   Initial revision
587

c60795f41   Ilya Yanok   usb: use linux/us...
588
  	config = (struct usb_config_descriptor *)&buffer[0];
488672084   Remy Bohmer   fix USB initialis...
589
590
  	result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 9);
  	if (result < 9) {
affae2bff   wdenk   Initial revision
591
  		if (result < 0)
6f5794a6f   Remy Bohmer   Refactoring parts...
592
593
594
  			printf("unable to get descriptor, error %lX
  ",
  				dev->status);
affae2bff   wdenk   Initial revision
595
  		else
6f5794a6f   Remy Bohmer   Refactoring parts...
596
  			printf("config descriptor too short " \
488672084   Remy Bohmer   fix USB initialis...
597
598
  				"(expected %i, got %i)
  ", 9, result);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
599
  		return -EIO;
affae2bff   wdenk   Initial revision
600
  	}
c75f57fba   Stefan Brüns   usb: Alloc buffer...
601
602
  	return le16_to_cpu(config->wTotalLength);
  }
affae2bff   wdenk   Initial revision
603

c75f57fba   Stefan Brüns   usb: Alloc buffer...
604
605
606
607
608
609
610
611
  /**********************************************************************
   * gets configuration cfgno and store it in the buffer
   */
  int usb_get_configuration_no(struct usb_device *dev, int cfgno,
  			     unsigned char *buffer, int length)
  {
  	int result;
  	struct usb_config_descriptor *config;
cd0a9de68   wdenk   * Patch by Lauren...
612

c75f57fba   Stefan Brüns   usb: Alloc buffer...
613
  	config = (struct usb_config_descriptor *)&buffer[0];
eaf3e613e   Julius Werner   usb: Use well-kno...
614
  	result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, length);
c75f57fba   Stefan Brüns   usb: Alloc buffer...
615
616
617
618
  	debug("get_conf_no %d Result %d, wLength %d
  ", cfgno, result,
  	      le16_to_cpu(config->wTotalLength));
  	config->wTotalLength = result; /* validated, with CPU byte order */
eaf3e613e   Julius Werner   usb: Use well-kno...
619

affae2bff   wdenk   Initial revision
620
621
622
623
624
625
626
  	return result;
  }
  
  /********************************************************************
   * set address of a device to the value in dev->devnum.
   * This can only be done by addressing the device via the default address (0)
   */
c08b1b264   Marek Vasut   USB: Staticize in...
627
  static int usb_set_address(struct usb_device *dev)
affae2bff   wdenk   Initial revision
628
  {
ceb4972a8   Vivek Gautam   usb: common: Weed...
629
630
  	debug("set address %d
  ", dev->devnum);
8319aeb1d   Masahiro Yamada   usb: squash lines...
631
632
633
  
  	return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,
  			       0, (dev->devnum), 0, NULL, 0, USB_CNTL_TIMEOUT);
affae2bff   wdenk   Initial revision
634
635
636
637
638
639
640
  }
  
  /********************************************************************
   * set interface number to interface
   */
  int usb_set_interface(struct usb_device *dev, int interface, int alternate)
  {
8f8bd565f   Tom Rix   USB Consolidate d...
641
  	struct usb_interface *if_face = NULL;
affae2bff   wdenk   Initial revision
642
  	int ret, i;
8f8bd565f   Tom Rix   USB Consolidate d...
643
644
  	for (i = 0; i < dev->config.desc.bNumInterfaces; i++) {
  		if (dev->config.if_desc[i].desc.bInterfaceNumber == interface) {
affae2bff   wdenk   Initial revision
645
646
647
648
649
650
  			if_face = &dev->config.if_desc[i];
  			break;
  		}
  	}
  	if (!if_face) {
  		printf("selecting invalid interface %d", interface);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
651
  		return -EINVAL;
affae2bff   wdenk   Initial revision
652
  	}
7455af41d   Bartlomiej Sieka   Add rudimentary h...
653
654
  	/*
  	 * We should return now for devices with only one alternate setting.
6f5794a6f   Remy Bohmer   Refactoring parts...
655
656
657
658
  	 * According to 9.4.10 of the Universal Serial Bus Specification
  	 * Revision 2.0 such devices can return with a STALL. This results in
  	 * some USB sticks timeouting during initialization and then being
  	 * unusable in U-Boot.
7455af41d   Bartlomiej Sieka   Add rudimentary h...
659
660
661
  	 */
  	if (if_face->num_altsetting == 1)
  		return 0;
affae2bff   wdenk   Initial revision
662

6f5794a6f   Remy Bohmer   Refactoring parts...
663
664
665
666
667
  	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
  				USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
  				alternate, interface, NULL, 0,
  				USB_CNTL_TIMEOUT * 5);
  	if (ret < 0)
affae2bff   wdenk   Initial revision
668
  		return ret;
affae2bff   wdenk   Initial revision
669
670
671
672
673
674
  	return 0;
  }
  
  /********************************************************************
   * set configuration number to configuration
   */
c08b1b264   Marek Vasut   USB: Staticize in...
675
  static int usb_set_configuration(struct usb_device *dev, int configuration)
affae2bff   wdenk   Initial revision
676
677
  {
  	int res;
ceb4972a8   Vivek Gautam   usb: common: Weed...
678
679
  	debug("set configuration %d
  ", configuration);
affae2bff   wdenk   Initial revision
680
  	/* set setup command */
6f5794a6f   Remy Bohmer   Refactoring parts...
681
682
683
684
685
  	res = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
  				USB_REQ_SET_CONFIGURATION, 0,
  				configuration, 0,
  				NULL, 0, USB_CNTL_TIMEOUT);
  	if (res == 0) {
affae2bff   wdenk   Initial revision
686
687
688
  		dev->toggle[0] = 0;
  		dev->toggle[1] = 0;
  		return 0;
6f5794a6f   Remy Bohmer   Refactoring parts...
689
  	} else
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
690
  		return -EIO;
affae2bff   wdenk   Initial revision
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
  }
  
  /********************************************************************
   * set protocol to protocol
   */
  int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol)
  {
  	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
  		USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
  		protocol, ifnum, NULL, 0, USB_CNTL_TIMEOUT);
  }
  
  /********************************************************************
   * set idle
   */
  int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id)
  {
  	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
  		USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
  		(duration << 8) | report_id, ifnum, NULL, 0, USB_CNTL_TIMEOUT);
  }
  
  /********************************************************************
   * get report
   */
6f5794a6f   Remy Bohmer   Refactoring parts...
716
717
  int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
  		   unsigned char id, void *buf, int size)
affae2bff   wdenk   Initial revision
718
719
  {
  	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
6f5794a6f   Remy Bohmer   Refactoring parts...
720
721
722
  			USB_REQ_GET_REPORT,
  			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
  			(type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT);
affae2bff   wdenk   Initial revision
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
  }
  
  /********************************************************************
   * get class descriptor
   */
  int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
  		unsigned char type, unsigned char id, void *buf, int size)
  {
  	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
  		USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
  		(type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT);
  }
  
  /********************************************************************
   * get string index in buffer
   */
c08b1b264   Marek Vasut   USB: Staticize in...
739
  static int usb_get_string(struct usb_device *dev, unsigned short langid,
6f5794a6f   Remy Bohmer   Refactoring parts...
740
  		   unsigned char index, void *buf, int size)
affae2bff   wdenk   Initial revision
741
  {
9c998aa83   Wolfgang Denk   Fix low-level OHC...
742
743
744
745
746
747
748
  	int i;
  	int result;
  
  	for (i = 0; i < 3; ++i) {
  		/* some devices are flaky */
  		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
  			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
095b8a379   Wolfgang Denk   Coding style cleanup
749
  			(USB_DT_STRING << 8) + index, langid, buf, size,
9c998aa83   Wolfgang Denk   Fix low-level OHC...
750
751
752
753
  			USB_CNTL_TIMEOUT);
  
  		if (result > 0)
  			break;
095b8a379   Wolfgang Denk   Coding style cleanup
754
  	}
9c998aa83   Wolfgang Denk   Fix low-level OHC...
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
  	return result;
  }
  
  
  static void usb_try_string_workarounds(unsigned char *buf, int *length)
  {
  	int newlength, oldlength = *length;
  
  	for (newlength = 2; newlength + 1 < oldlength; newlength += 2)
  		if (!isprint(buf[newlength]) || buf[newlength + 1])
  			break;
  
  	if (newlength > 2) {
  		buf[0] = newlength;
  		*length = newlength;
  	}
affae2bff   wdenk   Initial revision
771
  }
9c998aa83   Wolfgang Denk   Fix low-level OHC...
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
  
  static int usb_string_sub(struct usb_device *dev, unsigned int langid,
  		unsigned int index, unsigned char *buf)
  {
  	int rc;
  
  	/* Try to read the string descriptor by asking for the maximum
  	 * possible number of bytes */
  	rc = usb_get_string(dev, langid, index, buf, 255);
  
  	/* If that failed try to read the descriptor length, then
  	 * ask for just that many bytes */
  	if (rc < 2) {
  		rc = usb_get_string(dev, langid, index, buf, 2);
  		if (rc == 2)
  			rc = usb_get_string(dev, langid, index, buf, buf[0]);
  	}
  
  	if (rc >= 2) {
  		if (!buf[0] && !buf[1])
  			usb_try_string_workarounds(buf, &rc);
  
  		/* There might be extra junk at the end of the descriptor */
  		if (buf[0] < rc)
  			rc = buf[0];
  
  		rc = rc - (rc & 1); /* force a multiple of two */
  	}
  
  	if (rc < 2)
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
802
  		rc = -EINVAL;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
803
804
805
  
  	return rc;
  }
affae2bff   wdenk   Initial revision
806
807
808
809
810
811
812
  /********************************************************************
   * usb_string:
   * Get string index and translate it to ascii.
   * returns string length (> 0) or error (< 0)
   */
  int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
  {
f57661394   Puneet Saxena   USB: Align buffer...
813
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, mybuf, USB_BUFSIZ);
affae2bff   wdenk   Initial revision
814
815
816
817
818
  	unsigned char *tbuf;
  	int err;
  	unsigned int u, idx;
  
  	if (size <= 0 || !buf || !index)
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
819
  		return -EINVAL;
affae2bff   wdenk   Initial revision
820
  	buf[0] = 0;
d0ff51ba5   Wolfgang Denk   Code cleanup: fix...
821
  	tbuf = &mybuf[0];
affae2bff   wdenk   Initial revision
822
823
824
  
  	/* get langid for strings if it's not yet known */
  	if (!dev->have_langid) {
9c998aa83   Wolfgang Denk   Fix low-level OHC...
825
  		err = usb_string_sub(dev, 0, 0, tbuf);
affae2bff   wdenk   Initial revision
826
  		if (err < 0) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
827
828
829
  			debug("error getting string descriptor 0 " \
  			      "(error=%lx)
  ", dev->status);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
830
  			return -EIO;
affae2bff   wdenk   Initial revision
831
  		} else if (tbuf[0] < 4) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
832
833
  			debug("string descriptor 0 too short
  ");
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
834
  			return -EIO;
affae2bff   wdenk   Initial revision
835
836
  		} else {
  			dev->have_langid = -1;
6f5794a6f   Remy Bohmer   Refactoring parts...
837
  			dev->string_langid = tbuf[2] | (tbuf[3] << 8);
affae2bff   wdenk   Initial revision
838
  				/* always use the first langid listed */
ceb4972a8   Vivek Gautam   usb: common: Weed...
839
840
841
842
  			debug("USB device number %d default " \
  			      "language ID 0x%x
  ",
  			      dev->devnum, dev->string_langid);
affae2bff   wdenk   Initial revision
843
844
  		}
  	}
cd0a9de68   wdenk   * Patch by Lauren...
845

9c998aa83   Wolfgang Denk   Fix low-level OHC...
846
  	err = usb_string_sub(dev, dev->string_langid, index, tbuf);
affae2bff   wdenk   Initial revision
847
848
  	if (err < 0)
  		return err;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
849

affae2bff   wdenk   Initial revision
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
  	size--;		/* leave room for trailing NULL char in output buffer */
  	for (idx = 0, u = 2; u < err; u += 2) {
  		if (idx >= size)
  			break;
  		if (tbuf[u+1])			/* high byte */
  			buf[idx++] = '?';  /* non-ASCII character */
  		else
  			buf[idx++] = tbuf[u];
  	}
  	buf[idx] = 0;
  	err = idx;
  	return err;
  }
  
  
  /********************************************************************
   * USB device handling:
   * the USB device are static allocated [USB_MAX_DEVICE].
   */
95fbfe429   Simon Glass   dm: usb: Convert ...
869
  #ifndef CONFIG_DM_USB
affae2bff   wdenk   Initial revision
870
871
872
873
  
  /* returns a pointer to the device with the index [index].
   * if the device is not assigned (dev->devnum==-1) returns NULL
   */
6f5794a6f   Remy Bohmer   Refactoring parts...
874
  struct usb_device *usb_get_dev_index(int index)
affae2bff   wdenk   Initial revision
875
  {
6f5794a6f   Remy Bohmer   Refactoring parts...
876
  	if (usb_dev[index].devnum == -1)
affae2bff   wdenk   Initial revision
877
878
879
880
  		return NULL;
  	else
  		return &usb_dev[index];
  }
79b588872   Simon Glass   dm: usb: Adjust u...
881
  int usb_alloc_new_device(struct udevice *controller, struct usb_device **devp)
affae2bff   wdenk   Initial revision
882
883
  {
  	int i;
ceb4972a8   Vivek Gautam   usb: common: Weed...
884
885
  	debug("New Device %d
  ", dev_index);
6f5794a6f   Remy Bohmer   Refactoring parts...
886
887
888
  	if (dev_index == USB_MAX_DEVICE) {
  		printf("ERROR, too many USB Devices, max=%d
  ", USB_MAX_DEVICE);
79b588872   Simon Glass   dm: usb: Adjust u...
889
  		return -ENOSPC;
affae2bff   wdenk   Initial revision
890
  	}
6f5794a6f   Remy Bohmer   Refactoring parts...
891
892
893
894
895
896
  	/* default Address is 0, real addresses start with 1 */
  	usb_dev[dev_index].devnum = dev_index + 1;
  	usb_dev[dev_index].maxchild = 0;
  	for (i = 0; i < USB_MAXCHILDREN; i++)
  		usb_dev[dev_index].children[i] = NULL;
  	usb_dev[dev_index].parent = NULL;
c7e3b2b58   Lucas Stach   usb: lowlevel int...
897
  	usb_dev[dev_index].controller = controller;
affae2bff   wdenk   Initial revision
898
  	dev_index++;
79b588872   Simon Glass   dm: usb: Adjust u...
899
900
901
  	*devp = &usb_dev[dev_index - 1];
  
  	return 0;
affae2bff   wdenk   Initial revision
902
  }
359439d28   Milind Choudhary   usb: Clean up new...
903
904
905
906
907
  /*
   * Free the newly created device node.
   * Called in error cases where configuring a newly attached
   * device fails for some reason.
   */
79b588872   Simon Glass   dm: usb: Adjust u...
908
  void usb_free_device(struct udevice *controller)
359439d28   Milind Choudhary   usb: Clean up new...
909
910
  {
  	dev_index--;
ceb4972a8   Vivek Gautam   usb: common: Weed...
911
912
  	debug("Freeing device node: %d
  ", dev_index);
359439d28   Milind Choudhary   usb: Clean up new...
913
914
915
  	memset(&usb_dev[dev_index], 0, sizeof(struct usb_device));
  	usb_dev[dev_index].devnum = -1;
  }
affae2bff   wdenk   Initial revision
916
917
  
  /*
5853e1335   Vivek Gautam   USB: xHCI: Add st...
918
919
920
921
922
923
924
925
926
   * XHCI issues Enable Slot command and thereafter
   * allocates device contexts. Provide a weak alias
   * function for the purpose, so that XHCI overrides it
   * and EHCI/OHCI just work out of the box.
   */
  __weak int usb_alloc_device(struct usb_device *udev)
  {
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
927
  #endif /* !CONFIG_DM_USB */
862e75c0d   Simon Glass   dm: usb: Refactor...
928

682c9f8df   Hans de Goede   usb: Pass device ...
929
  static int usb_hub_port_reset(struct usb_device *dev, struct usb_device *hub)
862e75c0d   Simon Glass   dm: usb: Refactor...
930
  {
3ed9eb93c   Stefan Roese   usb: Don't reset ...
931
  	if (!hub)
8802f5634   Hans de Goede   usb: Add an usb_d...
932
  		usb_reset_root_port(dev);
862e75c0d   Simon Glass   dm: usb: Refactor...
933
934
935
  
  	return 0;
  }
0ed27905c   Simon Glass   dm: usb: Complete...
936
  static int get_descriptor_len(struct usb_device *dev, int len, int expect_len)
affae2bff   wdenk   Initial revision
937
  {
128fcac08   Simon Glass   dm: usb: Move des...
938
  	__maybe_unused struct usb_device_descriptor *desc;
f57661394   Puneet Saxena   USB: Align buffer...
939
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ);
0ed27905c   Simon Glass   dm: usb: Complete...
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
  	int err;
  
  	desc = (struct usb_device_descriptor *)tmpbuf;
  
  	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, len);
  	if (err < expect_len) {
  		if (err < 0) {
  			printf("unable to get device descriptor (error=%d)
  ",
  				err);
  			return err;
  		} else {
  			printf("USB device descriptor short read (expected %i, got %i)
  ",
  				expect_len, err);
  			return -EIO;
  		}
  	}
  	memcpy(&dev->descriptor, tmpbuf, sizeof(dev->descriptor));
  
  	return 0;
  }
  
  static int usb_setup_descriptor(struct usb_device *dev, bool do_read)
  {
5853e1335   Vivek Gautam   USB: xHCI: Add st...
965
  	/*
53d8aa0f6   Simon Glass   dm: usb: Drop the...
966
  	 * This is a Windows scheme of initialization sequence, with double
488672084   Remy Bohmer   fix USB initialis...
967
  	 * reset of the device (Linux uses the same sequence)
c9e8436b1   Remy Bohmer   USB layer of U-Bo...
968
969
  	 * Some equipment is said to work only with such init sequence; this
  	 * patch is based on the work by Alan Stern:
de39f8c19   Michael Trimarchi   USB style patch, ...
970
971
  	 * http://sourceforge.net/mailarchive/forum.php?
  	 * thread_id=5729457&forum_id=5398
9c998aa83   Wolfgang Denk   Fix low-level OHC...
972
  	 */
9c998aa83   Wolfgang Denk   Fix low-level OHC...
973

53d8aa0f6   Simon Glass   dm: usb: Drop the...
974
975
  	/*
  	 * send 64-byte GET-DEVICE-DESCRIPTOR request.  Since the descriptor is
9c998aa83   Wolfgang Denk   Fix low-level OHC...
976
977
  	 * only 18 bytes long, this will terminate with a short packet.  But if
  	 * the maxpacket size is 8 or 16 the device may be waiting to transmit
2b338ef41   Hans de Goede   usb: Fix maxpacke...
978
979
  	 * some more, or keeps on retransmitting the 8 byte header.
  	 */
9c998aa83   Wolfgang Denk   Fix low-level OHC...
980

2b338ef41   Hans de Goede   usb: Fix maxpacke...
981
982
983
984
985
986
987
988
989
  	if (dev->speed == USB_SPEED_LOW) {
  		dev->descriptor.bMaxPacketSize0 = 8;
  		dev->maxpacketsize = PACKET_SIZE_8;
  	} else {
  		dev->descriptor.bMaxPacketSize0 = 64;
  		dev->maxpacketsize = PACKET_SIZE_64;
  	}
  	dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0;
  	dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
488672084   Remy Bohmer   fix USB initialis...
990

128fcac08   Simon Glass   dm: usb: Move des...
991
992
  	if (do_read) {
  		int err;
862e75c0d   Simon Glass   dm: usb: Refactor...
993

128fcac08   Simon Glass   dm: usb: Move des...
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
  		/*
  		 * Validate we've received only at least 8 bytes, not that we've
  		 * received the entire descriptor. The reasoning is:
  		 * - The code only uses fields in the first 8 bytes, so that's all we
  		 *   need to have fetched at this stage.
  		 * - The smallest maxpacket size is 8 bytes. Before we know the actual
  		 *   maxpacket the device uses, the USB controller may only accept a
  		 *   single packet. Consequently we are only guaranteed to receive 1
  		 *   packet (at least 8 bytes) even in a non-error case.
  		 *
  		 * At least the DWC2 controller needs to be programmed with the number
  		 * of packets in addition to the number of bytes. A request for 64
  		 * bytes of data with the maxpacket guessed as 64 (above) yields a
  		 * request for 1 packet.
  		 */
0ed27905c   Simon Glass   dm: usb: Complete...
1009
1010
1011
  		err = get_descriptor_len(dev, 64, 8);
  		if (err)
  			return err;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1012
  	}
488672084   Remy Bohmer   fix USB initialis...
1013

de39f8c19   Michael Trimarchi   USB style patch, ...
1014
  	dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0;
affae2bff   wdenk   Initial revision
1015
1016
  	dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
  	switch (dev->descriptor.bMaxPacketSize0) {
de39f8c19   Michael Trimarchi   USB style patch, ...
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
  	case 8:
  		dev->maxpacketsize  = PACKET_SIZE_8;
  		break;
  	case 16:
  		dev->maxpacketsize = PACKET_SIZE_16;
  		break;
  	case 32:
  		dev->maxpacketsize = PACKET_SIZE_32;
  		break;
  	case 64:
  		dev->maxpacketsize = PACKET_SIZE_64;
  		break;
04ee6ee2c   Paul Kocialkowski   usb: Early failur...
1029
1030
1031
1032
  	default:
  		printf("usb_new_device: invalid max packet size
  ");
  		return -EIO;
affae2bff   wdenk   Initial revision
1033
  	}
128fcac08   Simon Glass   dm: usb: Move des...
1034
1035
1036
  
  	return 0;
  }
91398f985   Simon Glass   dm: usb: Split ou...
1037
  static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read,
9eb72dd1f   Hans de Goede   usb: usb_setup_de...
1038
  			      struct usb_device *parent)
128fcac08   Simon Glass   dm: usb: Move des...
1039
  {
91398f985   Simon Glass   dm: usb: Split ou...
1040
  	int err;
128fcac08   Simon Glass   dm: usb: Move des...
1041
1042
1043
1044
1045
1046
1047
  
  	/*
  	 * Allocate usb 3.0 device context.
  	 * USB 3.0 (xHCI) protocol tries to allocate device slot
  	 * and related data structures first. This call does that.
  	 * Refer to sec 4.3.2 in xHCI spec rev1.0
  	 */
91398f985   Simon Glass   dm: usb: Split ou...
1048
1049
  	err = usb_alloc_device(dev);
  	if (err) {
128fcac08   Simon Glass   dm: usb: Move des...
1050
1051
  		printf("Cannot allocate device context to get SLOT_ID
  ");
91398f985   Simon Glass   dm: usb: Split ou...
1052
  		return err;
128fcac08   Simon Glass   dm: usb: Move des...
1053
  	}
128fcac08   Simon Glass   dm: usb: Move des...
1054
1055
1056
  	err = usb_setup_descriptor(dev, do_read);
  	if (err)
  		return err;
682c9f8df   Hans de Goede   usb: Pass device ...
1057
  	err = usb_hub_port_reset(dev, parent);
128fcac08   Simon Glass   dm: usb: Move des...
1058
1059
  	if (err)
  		return err;
affae2bff   wdenk   Initial revision
1060
1061
1062
1063
1064
  	dev->devnum = addr;
  
  	err = usb_set_address(dev); /* set address */
  
  	if (err < 0) {
6f5794a6f   Remy Bohmer   Refactoring parts...
1065
1066
1067
1068
  		printf("
        USB device not accepting new address " \
  			"(error=%lX)
  ", dev->status);
91398f985   Simon Glass   dm: usb: Split ou...
1069
  		return err;
affae2bff   wdenk   Initial revision
1070
  	}
5b84dd67c   Mike Frysinger   usb: replace wait...
1071
  	mdelay(10);	/* Let the SET_ADDRESS settle */
affae2bff   wdenk   Initial revision
1072

91398f985   Simon Glass   dm: usb: Split ou...
1073
1074
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1075
  int usb_select_config(struct usb_device *dev)
91398f985   Simon Glass   dm: usb: Split ou...
1076
  {
2f1b4302e   Marek Vasut   usb: Don't init p...
1077
  	unsigned char *tmpbuf = NULL;
0ed27905c   Simon Glass   dm: usb: Complete...
1078
  	int err;
91398f985   Simon Glass   dm: usb: Split ou...
1079

0ed27905c   Simon Glass   dm: usb: Complete...
1080
1081
1082
  	err = get_descriptor_len(dev, USB_DT_DEVICE_SIZE, USB_DT_DEVICE_SIZE);
  	if (err)
  		return err;
affae2bff   wdenk   Initial revision
1083

affae2bff   wdenk   Initial revision
1084
  	/* correct le values */
c918261c6   Christian Eggers   USB: replace old ...
1085
1086
1087
1088
  	le16_to_cpus(&dev->descriptor.bcdUSB);
  	le16_to_cpus(&dev->descriptor.idVendor);
  	le16_to_cpus(&dev->descriptor.idProduct);
  	le16_to_cpus(&dev->descriptor.bcdDevice);
0ed27905c   Simon Glass   dm: usb: Complete...
1089

ef71290be   Marek Vasut   usb: Assure Get D...
1090
1091
1092
1093
1094
1095
1096
  	/*
  	 * Kingston DT Ultimate 32GB USB 3.0 seems to be extremely sensitive
  	 * about this first Get Descriptor request. If there are any other
  	 * requests in the first microframe, the stick crashes. Wait about
  	 * one microframe duration here (1mS for USB 1.x , 125uS for USB 2.0).
  	 */
  	mdelay(1);
affae2bff   wdenk   Initial revision
1097
  	/* only support for one config for now */
c75f57fba   Stefan Brüns   usb: Alloc buffer...
1098
1099
1100
1101
1102
1103
1104
1105
  	err = usb_get_configuration_len(dev, 0);
  	if (err >= 0) {
  		tmpbuf = (unsigned char *)malloc_cache_aligned(err);
  		if (!tmpbuf)
  			err = -ENOMEM;
  		else
  			err = usb_get_configuration_no(dev, 0, tmpbuf, err);
  	}
8b8d779da   Vincent Palatin   usb: fallback saf...
1106
1107
1108
1109
1110
  	if (err < 0) {
  		printf("usb_new_device: Cannot read configuration, " \
  		       "skipping device %04x:%04x
  ",
  		       dev->descriptor.idVendor, dev->descriptor.idProduct);
c75f57fba   Stefan Brüns   usb: Alloc buffer...
1111
  		free(tmpbuf);
0ed27905c   Simon Glass   dm: usb: Complete...
1112
  		return err;
8b8d779da   Vincent Palatin   usb: fallback saf...
1113
  	}
f57661394   Puneet Saxena   USB: Align buffer...
1114
  	usb_parse_config(dev, tmpbuf, 0);
c75f57fba   Stefan Brüns   usb: Alloc buffer...
1115
  	free(tmpbuf);
affae2bff   wdenk   Initial revision
1116
  	usb_set_maxpacket(dev);
0ed27905c   Simon Glass   dm: usb: Complete...
1117
1118
1119
1120
1121
1122
1123
  	/*
  	 * we set the default configuration here
  	 * This seems premature. If the driver wants a different configuration
  	 * it will need to select itself.
  	 */
  	err = usb_set_configuration(dev, dev->config.desc.bConfigurationValue);
  	if (err < 0) {
6f5794a6f   Remy Bohmer   Refactoring parts...
1124
1125
1126
  		printf("failed to set default configuration " \
  			"len %d, status %lX
  ", dev->act_len, dev->status);
0ed27905c   Simon Glass   dm: usb: Complete...
1127
  		return err;
affae2bff   wdenk   Initial revision
1128
  	}
f647bf0ba   Marek Vasut   usb: Wait after s...
1129
1130
1131
1132
1133
1134
1135
  
  	/*
  	 * Wait until the Set Configuration request gets processed by the
  	 * device. This is required by at least SanDisk Cruzer Pop USB 2.0
  	 * and Kingston DT Ultimate 32GB USB 3.0 on DWC2 OTG controller.
  	 */
  	mdelay(10);
ceb4972a8   Vivek Gautam   usb: common: Weed...
1136
1137
1138
1139
  	debug("new device strings: Mfr=%d, Product=%d, SerialNumber=%d
  ",
  	      dev->descriptor.iManufacturer, dev->descriptor.iProduct,
  	      dev->descriptor.iSerialNumber);
affae2bff   wdenk   Initial revision
1140
1141
1142
1143
  	memset(dev->mf, 0, sizeof(dev->mf));
  	memset(dev->prod, 0, sizeof(dev->prod));
  	memset(dev->serial, 0, sizeof(dev->serial));
  	if (dev->descriptor.iManufacturer)
6f5794a6f   Remy Bohmer   Refactoring parts...
1144
1145
  		usb_string(dev, dev->descriptor.iManufacturer,
  			   dev->mf, sizeof(dev->mf));
affae2bff   wdenk   Initial revision
1146
  	if (dev->descriptor.iProduct)
6f5794a6f   Remy Bohmer   Refactoring parts...
1147
1148
  		usb_string(dev, dev->descriptor.iProduct,
  			   dev->prod, sizeof(dev->prod));
affae2bff   wdenk   Initial revision
1149
  	if (dev->descriptor.iSerialNumber)
6f5794a6f   Remy Bohmer   Refactoring parts...
1150
1151
  		usb_string(dev, dev->descriptor.iSerialNumber,
  			   dev->serial, sizeof(dev->serial));
ceb4972a8   Vivek Gautam   usb: common: Weed...
1152
1153
1154
1155
1156
1157
  	debug("Manufacturer %s
  ", dev->mf);
  	debug("Product      %s
  ", dev->prod);
  	debug("SerialNumber %s
  ", dev->serial);
0ed27905c   Simon Glass   dm: usb: Complete...
1158
1159
1160
  
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1161
  int usb_setup_device(struct usb_device *dev, bool do_read,
9eb72dd1f   Hans de Goede   usb: usb_setup_de...
1162
  		     struct usb_device *parent)
0ed27905c   Simon Glass   dm: usb: Complete...
1163
1164
1165
1166
1167
1168
1169
  {
  	int addr;
  	int ret;
  
  	/* We still haven't set the Address yet */
  	addr = dev->devnum;
  	dev->devnum = 0;
9eb72dd1f   Hans de Goede   usb: usb_setup_de...
1170
  	ret = usb_prepare_device(dev, addr, do_read, parent);
0ed27905c   Simon Glass   dm: usb: Complete...
1171
1172
1173
1174
1175
1176
  	if (ret)
  		return ret;
  	ret = usb_select_config(dev);
  
  	return ret;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1177
  #ifndef CONFIG_DM_USB
0ed27905c   Simon Glass   dm: usb: Complete...
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
  /*
   * By the time we get here, the device has gotten a new device ID
   * and is in the default state. We need to identify the thing and
   * get the ball rolling..
   *
   * Returns 0 for success, != 0 for error.
   */
  int usb_new_device(struct usb_device *dev)
  {
  	bool do_read = true;
  	int err;
  
  	/*
  	 * XHCI needs to issue a Address device command to setup
  	 * proper device context structures, before it can interact
  	 * with the device. So a get_descriptor will fail before any
  	 * of that is done for XHCI unlike EHCI.
  	 */
0a8cc1a3a   Masahiro Yamada   usb: move CONFIG_...
1196
  #ifdef CONFIG_USB_XHCI_HCD
0ed27905c   Simon Glass   dm: usb: Complete...
1197
1198
  	do_read = false;
  #endif
9eb72dd1f   Hans de Goede   usb: usb_setup_de...
1199
  	err = usb_setup_device(dev, do_read, dev->parent);
0ed27905c   Simon Glass   dm: usb: Complete...
1200
1201
1202
1203
1204
1205
1206
  	if (err)
  		return err;
  
  	/* Now probe if the device is a hub */
  	err = usb_hub_probe(dev, 0);
  	if (err < 0)
  		return err;
affae2bff   wdenk   Initial revision
1207
1208
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1209
  #endif
affae2bff   wdenk   Initial revision
1210

16297cfb2   Mateusz Zalega   usb: new board-sp...
1211
  __weak
bba679144   Troy Kisky   usb: rename board...
1212
  int board_usb_init(int index, enum usb_init_type init)
16297cfb2   Mateusz Zalega   usb: new board-sp...
1213
1214
1215
  {
  	return 0;
  }
db378d786   Kishon Vijay Abraham I   common: cmd_dfu: ...
1216
1217
1218
1219
1220
1221
  
  __weak
  int board_usb_cleanup(int index, enum usb_init_type init)
  {
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1222
1223
1224
1225
1226
1227
1228
1229
1230
  
  bool usb_device_has_child_on_port(struct usb_device *parent, int port)
  {
  #ifdef CONFIG_DM_USB
  	return false;
  #else
  	return parent->children[port] != NULL;
  #endif
  }
faa7db24a   Stefan Brüns   usb: Move determi...
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
  #ifdef CONFIG_DM_USB
  void usb_find_usb2_hub_address_port(struct usb_device *udev,
  			       uint8_t *hub_address, uint8_t *hub_port)
  {
  	struct udevice *parent;
  	struct usb_device *uparent, *ttdev;
  
  	/*
  	 * When called from usb-uclass.c: usb_scan_device() udev->dev points
  	 * to the parent udevice, not the actual udevice belonging to the
  	 * udev as the device is not instantiated yet. So when searching
  	 * for the first usb-2 parent start with udev->dev not
  	 * udev->dev->parent .
  	 */
  	ttdev = udev;
  	parent = udev->dev;
  	uparent = dev_get_parent_priv(parent);
  
  	while (uparent->speed != USB_SPEED_HIGH) {
  		struct udevice *dev = parent;
  
  		if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) {
  			printf("Error: Cannot find high speed parent of usb-1 device
  ");
  			*hub_address = 0;
  			*hub_port = 0;
  			return;
  		}
  
  		ttdev = dev_get_parent_priv(dev);
  		parent = dev->parent;
  		uparent = dev_get_parent_priv(parent);
  	}
  	*hub_address = uparent->devnum;
  	*hub_port = ttdev->portnr;
  }
  #else
  void usb_find_usb2_hub_address_port(struct usb_device *udev,
  			       uint8_t *hub_address, uint8_t *hub_port)
  {
  	/* Find out the nearest parent which is high speed */
  	while (udev->parent->parent != NULL)
  		if (udev->parent->speed != USB_SPEED_HIGH) {
  			udev = udev->parent;
  		} else {
  			*hub_address = udev->parent->devnum;
  			*hub_port = udev->portnr;
  			return;
  		}
  
  	printf("Error: Cannot find high speed parent of usb-1 device
  ");
  	*hub_address = 0;
  	*hub_port = 0;
  }
  #endif
affae2bff   wdenk   Initial revision
1287
  /* EOF */