Blame view

common/usb.c 34.4 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
affae2bff   wdenk   Initial revision
2
  /*
affae2bff   wdenk   Initial revision
3
   * Most of this source has been derived from the Linux USB
460c322f1   Wolfgang Denk   (re)enabled scsi ...
4
5
6
7
8
9
10
11
12
13
14
15
16
   * 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
17
   */
affae2bff   wdenk   Initial revision
18
19
20
21
22
23
24
25
26
27
28
  /*
   * 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 ...
29
  #include <dm.h>
336d4615f   Simon Glass   dm: core: Create ...
30
  #include <malloc.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
  #include <usb.h>
affae2bff   wdenk   Initial revision
39

cd0a9de68   wdenk   * Patch by Lauren...
40
  #define USB_BUFSIZ	512
affae2bff   wdenk   Initial revision
41
  static int asynch_allowed;
e51aae382   Bartlomiej Sieka   Prevent USB comma...
42
  char usb_started; /* flag for the started/stopped USB status */
fd09c205f   Sven Schwermer   usb: s/CONFIG_DM_...
43
  #if !CONFIG_IS_ENABLED(DM_USB)
95fbfe429   Simon Glass   dm: usb: Convert ...
44
45
  static struct usb_device usb_dev[USB_MAX_DEVICE];
  static int dev_index;
93c2582fe   Lucas Stach   usb: add support ...
46
47
48
  #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
  #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
  #endif
affae2bff   wdenk   Initial revision
49

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

6f5794a6f   Remy Bohmer   Refactoring parts...
61
62
  	dev_index = 0;
  	asynch_allowed = 1;
affae2bff   wdenk   Initial revision
63
  	usb_hub_reset();
93c2582fe   Lucas Stach   usb: add support ...
64
65
66
67
68
69
  
  	/* 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
70
  	/* init low_level USB */
93c2582fe   Lucas Stach   usb: add support ...
71
72
73
  	for (i = 0; i < CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
  		/* init low_level USB */
  		printf("USB%d:   ", i);
97b9eb9e6   Marek Vasut   usb: Handle -ENOD...
74
75
76
77
  		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...
78
  			controllers_initialized++;
97b9eb9e6   Marek Vasut   usb: Handle -ENOD...
79
80
81
82
  			continue;
  		}
  
  		if (ret) {		/* Other error. */
93c2582fe   Lucas Stach   usb: add support ...
83
84
85
86
87
88
89
90
  			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...
91
  		controllers_initialized++;
93c2582fe   Lucas Stach   usb: add support ...
92
93
  		start_index = dev_index;
  		printf("scanning bus %d for devices... ", i);
79b588872   Simon Glass   dm: usb: Adjust u...
94
95
  		ret = usb_alloc_new_device(ctrl, &dev);
  		if (ret)
8879be885   Paul Kocialkowski   usb: Check usb_ne...
96
  			break;
93c2582fe   Lucas Stach   usb: add support ...
97
98
99
100
  		/*
  		 * device 0 is always present
  		 * (root hub, so let it analyze)
  		 */
8879be885   Paul Kocialkowski   usb: Check usb_ne...
101
102
  		ret = usb_new_device(dev);
  		if (ret)
79b588872   Simon Glass   dm: usb: Adjust u...
103
  			usb_free_device(dev->controller);
93c2582fe   Lucas Stach   usb: add support ...
104

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

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

5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
124
  	return usb_started ? 0 : -ENODEV;
affae2bff   wdenk   Initial revision
125
126
127
128
129
130
131
  }
  
  /******************************************************************************
   * Stop USB this stops the LowLevel Part and deregisters USB devices.
   */
  int usb_stop(void)
  {
93c2582fe   Lucas Stach   usb: add support ...
132
  	int i;
eba1f2fc7   Remy Bohmer   Make usb-stop() s...
133
134
135
136
137
  
  	if (usb_started) {
  		asynch_allowed = 1;
  		usb_started = 0;
  		usb_hub_reset();
93c2582fe   Lucas Stach   usb: add support ...
138
139
140
141
142
143
  
  		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...
144
  	}
93c2582fe   Lucas Stach   usb: add support ...
145
146
  
  	return 0;
affae2bff   wdenk   Initial revision
147
  }
08f3bb0bc   Vincent Palatin   usb: add device c...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
  /******************************************************************************
   * 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;
  }
31232de07   Marek Vasut   usb: Keep async s...
173
174
175
176
177
  /* Lock or unlock async schedule on the controller */
  __weak int usb_lock_async(struct usb_device *dev, int lock)
  {
  	return 0;
  }
affae2bff   wdenk   Initial revision
178
179
180
  /*
   * 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...
181
   * Returns the old value so it can be restored later.
affae2bff   wdenk   Initial revision
182
   */
89d48367e   Simon Glass   Add USB host ethe...
183
  int usb_disable_asynch(int disable)
affae2bff   wdenk   Initial revision
184
  {
89d48367e   Simon Glass   Add USB host ethe...
185
  	int old_value = asynch_allowed;
6f5794a6f   Remy Bohmer   Refactoring parts...
186
  	asynch_allowed = !disable;
89d48367e   Simon Glass   Add USB host ethe...
187
  	return old_value;
affae2bff   wdenk   Initial revision
188
  }
fd09c205f   Sven Schwermer   usb: s/CONFIG_DM_...
189
  #endif /* !CONFIG_IS_ENABLED(DM_USB) */
affae2bff   wdenk   Initial revision
190
191
192
193
194
195
196
197
  
  
  /*-------------------------------------------------------------------
   * Message wrappers.
   *
   */
  
  /*
3437121c0   Michal Suchanek   usb: Add nonblock...
198
199
200
   * submits an Interrupt Message. Some drivers may implement non-blocking
   * polling: when non-block is true and the device is not responding return
   * -EAGAIN instead of waiting for device to respond.
affae2bff   wdenk   Initial revision
201
   */
fdd135bf8   Michal Suchanek   usb: usb_submit_i...
202
  int usb_int_msg(struct usb_device *dev, unsigned long pipe,
3437121c0   Michal Suchanek   usb: Add nonblock...
203
  		void *buffer, int transfer_len, int interval, bool nonblock)
affae2bff   wdenk   Initial revision
204
  {
3437121c0   Michal Suchanek   usb: Add nonblock...
205
206
  	return submit_int_msg(dev, pipe, buffer, transfer_len, interval,
  			      nonblock);
affae2bff   wdenk   Initial revision
207
208
209
210
211
212
213
214
  }
  
  /*
   * 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 "...
215
   * returns the transferred length if OK or -1 if error. The transferred length
affae2bff   wdenk   Initial revision
216
217
218
219
220
221
222
   * 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...
223
  	ALLOC_CACHE_ALIGN_BUFFER(struct devrequest, setup_packet, 1);
651d95c8e   Hans de Goede   usb: usb_control_...
224
  	int err;
e159e4868   Marek Vasut   USB: Make struct ...
225

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

affae2bff   wdenk   Initial revision
231
  	/* set setup command */
f57661394   Puneet Saxena   USB: Align buffer...
232
233
234
235
236
  	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...
237
238
239
240
  	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...
241
  	dev->status = USB_ST_NOT_PROC; /*not yet processed */
affae2bff   wdenk   Initial revision
242

651d95c8e   Hans de Goede   usb: usb_control_...
243
244
245
  	err = submit_control_msg(dev, pipe, data, size, setup_packet);
  	if (err < 0)
  		return err;
6f5794a6f   Remy Bohmer   Refactoring parts...
246
  	if (timeout == 0)
affae2bff   wdenk   Initial revision
247
  		return (int)size;
6f5794a6f   Remy Bohmer   Refactoring parts...
248

84d36b301   Remy Bohmer   USB: usb_control_...
249
250
251
252
253
254
255
256
  	/*
  	 * 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...
257
  		mdelay(1);
488672084   Remy Bohmer   fix USB initialis...
258
  	}
84d36b301   Remy Bohmer   USB: usb_control_...
259
260
  	if (dev->status)
  		return -1;
488672084   Remy Bohmer   fix USB initialis...
261
262
  
  	return dev->act_len;
84d36b301   Remy Bohmer   USB: usb_control_...
263

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

8f8bd565f   Tom Rix   USB Consolidate d...
366
367
  	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...
368
  			usb_set_maxpacket_ep(dev, i, ii);
affae2bff   wdenk   Initial revision
369

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

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

ceb4972a8   Vivek Gautam   usb: common: Weed...
520
521
522
  			debug("unknown Description Type : %x
  ",
  			      head->bDescriptorType);
6f5794a6f   Remy Bohmer   Refactoring parts...
523

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

095b8a379   Wolfgang Denk   Coding style cleanup
562
  	/*
9c998aa83   Wolfgang Denk   Fix low-level OHC...
563
564
565
  	 * 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
566
  	usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
9c998aa83   Wolfgang Denk   Fix low-level OHC...
567

affae2bff   wdenk   Initial revision
568
569
570
571
572
573
574
575
576
  	/* 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...
577
  static int usb_get_descriptor(struct usb_device *dev, unsigned char type,
6f5794a6f   Remy Bohmer   Refactoring parts...
578
  			unsigned char index, void *buf, int size)
affae2bff   wdenk   Initial revision
579
  {
8319aeb1d   Masahiro Yamada   usb: squash lines...
580
581
582
583
  	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
584
585
586
  }
  
  /**********************************************************************
c75f57fba   Stefan Brüns   usb: Alloc buffer...
587
   * gets len of configuration cfgno
affae2bff   wdenk   Initial revision
588
   */
c75f57fba   Stefan Brüns   usb: Alloc buffer...
589
  int usb_get_configuration_len(struct usb_device *dev, int cfgno)
affae2bff   wdenk   Initial revision
590
  {
53677ef18   Wolfgang Denk   Big white-space c...
591
  	int result;
c75f57fba   Stefan Brüns   usb: Alloc buffer...
592
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, 9);
c60795f41   Ilya Yanok   usb: use linux/us...
593
  	struct usb_config_descriptor *config;
affae2bff   wdenk   Initial revision
594

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

c75f57fba   Stefan Brüns   usb: Alloc buffer...
611
612
613
614
615
616
617
618
  /**********************************************************************
   * 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...
619

c75f57fba   Stefan Brüns   usb: Alloc buffer...
620
  	config = (struct usb_config_descriptor *)&buffer[0];
eaf3e613e   Julius Werner   usb: Use well-kno...
621
  	result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, length);
c75f57fba   Stefan Brüns   usb: Alloc buffer...
622
623
624
625
  	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...
626

affae2bff   wdenk   Initial revision
627
628
629
630
631
632
633
  	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...
634
  static int usb_set_address(struct usb_device *dev)
affae2bff   wdenk   Initial revision
635
  {
ceb4972a8   Vivek Gautam   usb: common: Weed...
636
637
  	debug("set address %d
  ", dev->devnum);
8319aeb1d   Masahiro Yamada   usb: squash lines...
638
639
640
  
  	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
641
642
643
644
645
646
647
  }
  
  /********************************************************************
   * set interface number to interface
   */
  int usb_set_interface(struct usb_device *dev, int interface, int alternate)
  {
8f8bd565f   Tom Rix   USB Consolidate d...
648
  	struct usb_interface *if_face = NULL;
affae2bff   wdenk   Initial revision
649
  	int ret, i;
8f8bd565f   Tom Rix   USB Consolidate d...
650
651
  	for (i = 0; i < dev->config.desc.bNumInterfaces; i++) {
  		if (dev->config.if_desc[i].desc.bInterfaceNumber == interface) {
affae2bff   wdenk   Initial revision
652
653
654
655
656
657
  			if_face = &dev->config.if_desc[i];
  			break;
  		}
  	}
  	if (!if_face) {
  		printf("selecting invalid interface %d", interface);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
658
  		return -EINVAL;
affae2bff   wdenk   Initial revision
659
  	}
7455af41d   Bartlomiej Sieka   Add rudimentary h...
660
661
  	/*
  	 * We should return now for devices with only one alternate setting.
6f5794a6f   Remy Bohmer   Refactoring parts...
662
663
664
665
  	 * 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...
666
667
668
  	 */
  	if (if_face->num_altsetting == 1)
  		return 0;
affae2bff   wdenk   Initial revision
669

6f5794a6f   Remy Bohmer   Refactoring parts...
670
671
672
673
674
  	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
675
  		return ret;
affae2bff   wdenk   Initial revision
676
677
678
679
680
681
  	return 0;
  }
  
  /********************************************************************
   * set configuration number to configuration
   */
c08b1b264   Marek Vasut   USB: Staticize in...
682
  static int usb_set_configuration(struct usb_device *dev, int configuration)
affae2bff   wdenk   Initial revision
683
684
  {
  	int res;
ceb4972a8   Vivek Gautam   usb: common: Weed...
685
686
  	debug("set configuration %d
  ", configuration);
affae2bff   wdenk   Initial revision
687
  	/* set setup command */
6f5794a6f   Remy Bohmer   Refactoring parts...
688
689
690
691
692
  	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
693
694
695
  		dev->toggle[0] = 0;
  		dev->toggle[1] = 0;
  		return 0;
6f5794a6f   Remy Bohmer   Refactoring parts...
696
  	} else
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
697
  		return -EIO;
affae2bff   wdenk   Initial revision
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
  }
  
  /********************************************************************
   * 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...
723
724
  int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
  		   unsigned char id, void *buf, int size)
affae2bff   wdenk   Initial revision
725
726
  {
  	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
6f5794a6f   Remy Bohmer   Refactoring parts...
727
728
729
  			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
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
  }
  
  /********************************************************************
   * 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...
746
  static int usb_get_string(struct usb_device *dev, unsigned short langid,
6f5794a6f   Remy Bohmer   Refactoring parts...
747
  		   unsigned char index, void *buf, int size)
affae2bff   wdenk   Initial revision
748
  {
9c998aa83   Wolfgang Denk   Fix low-level OHC...
749
750
751
752
753
754
755
  	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
756
  			(USB_DT_STRING << 8) + index, langid, buf, size,
9c998aa83   Wolfgang Denk   Fix low-level OHC...
757
758
759
760
  			USB_CNTL_TIMEOUT);
  
  		if (result > 0)
  			break;
095b8a379   Wolfgang Denk   Coding style cleanup
761
  	}
9c998aa83   Wolfgang Denk   Fix low-level OHC...
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
  	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
778
  }
9c998aa83   Wolfgang Denk   Fix low-level OHC...
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
  
  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...
809
  		rc = -EINVAL;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
810
811
812
  
  	return rc;
  }
affae2bff   wdenk   Initial revision
813
814
815
816
817
818
819
  /********************************************************************
   * 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...
820
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, mybuf, USB_BUFSIZ);
affae2bff   wdenk   Initial revision
821
822
823
824
825
  	unsigned char *tbuf;
  	int err;
  	unsigned int u, idx;
  
  	if (size <= 0 || !buf || !index)
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
826
  		return -EINVAL;
affae2bff   wdenk   Initial revision
827
  	buf[0] = 0;
d0ff51ba5   Wolfgang Denk   Code cleanup: fix...
828
  	tbuf = &mybuf[0];
affae2bff   wdenk   Initial revision
829
830
831
  
  	/* get langid for strings if it's not yet known */
  	if (!dev->have_langid) {
9c998aa83   Wolfgang Denk   Fix low-level OHC...
832
  		err = usb_string_sub(dev, 0, 0, tbuf);
affae2bff   wdenk   Initial revision
833
  		if (err < 0) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
834
835
836
  			debug("error getting string descriptor 0 " \
  			      "(error=%lx)
  ", dev->status);
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
837
  			return -EIO;
affae2bff   wdenk   Initial revision
838
  		} else if (tbuf[0] < 4) {
ceb4972a8   Vivek Gautam   usb: common: Weed...
839
840
  			debug("string descriptor 0 too short
  ");
5a80b3449   Paul Kocialkowski   usb: usb_new_devi...
841
  			return -EIO;
affae2bff   wdenk   Initial revision
842
843
  		} else {
  			dev->have_langid = -1;
6f5794a6f   Remy Bohmer   Refactoring parts...
844
  			dev->string_langid = tbuf[2] | (tbuf[3] << 8);
affae2bff   wdenk   Initial revision
845
  				/* always use the first langid listed */
ceb4972a8   Vivek Gautam   usb: common: Weed...
846
847
848
849
  			debug("USB device number %d default " \
  			      "language ID 0x%x
  ",
  			      dev->devnum, dev->string_langid);
affae2bff   wdenk   Initial revision
850
851
  		}
  	}
cd0a9de68   wdenk   * Patch by Lauren...
852

9c998aa83   Wolfgang Denk   Fix low-level OHC...
853
  	err = usb_string_sub(dev, dev->string_langid, index, tbuf);
affae2bff   wdenk   Initial revision
854
855
  	if (err < 0)
  		return err;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
856

affae2bff   wdenk   Initial revision
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
  	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].
   */
fd09c205f   Sven Schwermer   usb: s/CONFIG_DM_...
876
  #if !CONFIG_IS_ENABLED(DM_USB)
affae2bff   wdenk   Initial revision
877
878
879
880
  
  /* 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...
881
  struct usb_device *usb_get_dev_index(int index)
affae2bff   wdenk   Initial revision
882
  {
6f5794a6f   Remy Bohmer   Refactoring parts...
883
  	if (usb_dev[index].devnum == -1)
affae2bff   wdenk   Initial revision
884
885
886
887
  		return NULL;
  	else
  		return &usb_dev[index];
  }
79b588872   Simon Glass   dm: usb: Adjust u...
888
  int usb_alloc_new_device(struct udevice *controller, struct usb_device **devp)
affae2bff   wdenk   Initial revision
889
890
  {
  	int i;
ceb4972a8   Vivek Gautam   usb: common: Weed...
891
892
  	debug("New Device %d
  ", dev_index);
6f5794a6f   Remy Bohmer   Refactoring parts...
893
894
895
  	if (dev_index == USB_MAX_DEVICE) {
  		printf("ERROR, too many USB Devices, max=%d
  ", USB_MAX_DEVICE);
79b588872   Simon Glass   dm: usb: Adjust u...
896
  		return -ENOSPC;
affae2bff   wdenk   Initial revision
897
  	}
6f5794a6f   Remy Bohmer   Refactoring parts...
898
899
900
901
902
903
  	/* 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...
904
  	usb_dev[dev_index].controller = controller;
affae2bff   wdenk   Initial revision
905
  	dev_index++;
79b588872   Simon Glass   dm: usb: Adjust u...
906
907
908
  	*devp = &usb_dev[dev_index - 1];
  
  	return 0;
affae2bff   wdenk   Initial revision
909
  }
359439d28   Milind Choudhary   usb: Clean up new...
910
911
912
913
914
  /*
   * 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...
915
  void usb_free_device(struct udevice *controller)
359439d28   Milind Choudhary   usb: Clean up new...
916
917
  {
  	dev_index--;
ceb4972a8   Vivek Gautam   usb: common: Weed...
918
919
  	debug("Freeing device node: %d
  ", dev_index);
359439d28   Milind Choudhary   usb: Clean up new...
920
921
922
  	memset(&usb_dev[dev_index], 0, sizeof(struct usb_device));
  	usb_dev[dev_index].devnum = -1;
  }
affae2bff   wdenk   Initial revision
923
924
  
  /*
5853e1335   Vivek Gautam   USB: xHCI: Add st...
925
926
927
928
929
930
931
932
933
   * 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;
  }
fd09c205f   Sven Schwermer   usb: s/CONFIG_DM_...
934
  #endif /* !CONFIG_IS_ENABLED(DM_USB) */
862e75c0d   Simon Glass   dm: usb: Refactor...
935

682c9f8df   Hans de Goede   usb: Pass device ...
936
  static int usb_hub_port_reset(struct usb_device *dev, struct usb_device *hub)
862e75c0d   Simon Glass   dm: usb: Refactor...
937
  {
3ed9eb93c   Stefan Roese   usb: Don't reset ...
938
  	if (!hub)
8802f5634   Hans de Goede   usb: Add an usb_d...
939
  		usb_reset_root_port(dev);
862e75c0d   Simon Glass   dm: usb: Refactor...
940
941
942
  
  	return 0;
  }
0ed27905c   Simon Glass   dm: usb: Complete...
943
  static int get_descriptor_len(struct usb_device *dev, int len, int expect_len)
affae2bff   wdenk   Initial revision
944
  {
128fcac08   Simon Glass   dm: usb: Move des...
945
  	__maybe_unused struct usb_device_descriptor *desc;
f57661394   Puneet Saxena   USB: Align buffer...
946
  	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ);
0ed27905c   Simon Glass   dm: usb: Complete...
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
  	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...
972
  	/*
53d8aa0f6   Simon Glass   dm: usb: Drop the...
973
  	 * This is a Windows scheme of initialization sequence, with double
488672084   Remy Bohmer   fix USB initialis...
974
  	 * reset of the device (Linux uses the same sequence)
c9e8436b1   Remy Bohmer   USB layer of U-Bo...
975
976
  	 * 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, ...
977
978
  	 * http://sourceforge.net/mailarchive/forum.php?
  	 * thread_id=5729457&forum_id=5398
9c998aa83   Wolfgang Denk   Fix low-level OHC...
979
  	 */
9c998aa83   Wolfgang Denk   Fix low-level OHC...
980

53d8aa0f6   Simon Glass   dm: usb: Drop the...
981
982
  	/*
  	 * send 64-byte GET-DEVICE-DESCRIPTOR request.  Since the descriptor is
9c998aa83   Wolfgang Denk   Fix low-level OHC...
983
984
  	 * 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...
985
986
  	 * some more, or keeps on retransmitting the 8 byte header.
  	 */
9c998aa83   Wolfgang Denk   Fix low-level OHC...
987

2b338ef41   Hans de Goede   usb: Fix maxpacke...
988
989
990
991
992
993
994
995
996
  	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...
997

c008faa77   Bin Meng   usb: Only get 64 ...
998
  	if (do_read && dev->speed == USB_SPEED_FULL) {
128fcac08   Simon Glass   dm: usb: Move des...
999
  		int err;
862e75c0d   Simon Glass   dm: usb: Refactor...
1000

128fcac08   Simon Glass   dm: usb: Move des...
1001
  		/*
c008faa77   Bin Meng   usb: Only get 64 ...
1002
1003
1004
1005
1006
1007
1008
1009
1010
  		 * 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.
128fcac08   Simon Glass   dm: usb: Move des...
1011
  		 *
c008faa77   Bin Meng   usb: Only get 64 ...
1012
1013
1014
1015
  		 * 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.
128fcac08   Simon Glass   dm: usb: Move des...
1016
  		 */
0ed27905c   Simon Glass   dm: usb: Complete...
1017
1018
1019
  		err = get_descriptor_len(dev, 64, 8);
  		if (err)
  			return err;
9c998aa83   Wolfgang Denk   Fix low-level OHC...
1020
  	}
488672084   Remy Bohmer   fix USB initialis...
1021

de39f8c19   Michael Trimarchi   USB style patch, ...
1022
  	dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0;
affae2bff   wdenk   Initial revision
1023
1024
  	dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
  	switch (dev->descriptor.bMaxPacketSize0) {
de39f8c19   Michael Trimarchi   USB style patch, ...
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
  	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...
1037
  	default:
c008faa77   Bin Meng   usb: Only get 64 ...
1038
1039
  		printf("%s: invalid max packet size
  ", __func__);
04ee6ee2c   Paul Kocialkowski   usb: Early failur...
1040
  		return -EIO;
affae2bff   wdenk   Initial revision
1041
  	}
128fcac08   Simon Glass   dm: usb: Move des...
1042
1043
1044
  
  	return 0;
  }
91398f985   Simon Glass   dm: usb: Split ou...
1045
  static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read,
9eb72dd1f   Hans de Goede   usb: usb_setup_de...
1046
  			      struct usb_device *parent)
128fcac08   Simon Glass   dm: usb: Move des...
1047
  {
91398f985   Simon Glass   dm: usb: Split ou...
1048
  	int err;
128fcac08   Simon Glass   dm: usb: Move des...
1049
1050
1051
1052
1053
1054
1055
  
  	/*
  	 * 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...
1056
1057
  	err = usb_alloc_device(dev);
  	if (err) {
128fcac08   Simon Glass   dm: usb: Move des...
1058
1059
  		printf("Cannot allocate device context to get SLOT_ID
  ");
91398f985   Simon Glass   dm: usb: Split ou...
1060
  		return err;
128fcac08   Simon Glass   dm: usb: Move des...
1061
  	}
128fcac08   Simon Glass   dm: usb: Move des...
1062
1063
1064
  	err = usb_setup_descriptor(dev, do_read);
  	if (err)
  		return err;
682c9f8df   Hans de Goede   usb: Pass device ...
1065
  	err = usb_hub_port_reset(dev, parent);
128fcac08   Simon Glass   dm: usb: Move des...
1066
1067
  	if (err)
  		return err;
affae2bff   wdenk   Initial revision
1068
1069
1070
1071
1072
  	dev->devnum = addr;
  
  	err = usb_set_address(dev); /* set address */
  
  	if (err < 0) {
6f5794a6f   Remy Bohmer   Refactoring parts...
1073
1074
1075
1076
  		printf("
        USB device not accepting new address " \
  			"(error=%lX)
  ", dev->status);
91398f985   Simon Glass   dm: usb: Split ou...
1077
  		return err;
affae2bff   wdenk   Initial revision
1078
  	}
5b84dd67c   Mike Frysinger   usb: replace wait...
1079
  	mdelay(10);	/* Let the SET_ADDRESS settle */
affae2bff   wdenk   Initial revision
1080

932bb668b   Bin Meng   usb: Read device ...
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
  	/*
  	 * If we haven't read device descriptor before, read it here
  	 * after device is assigned an address. This is only applicable
  	 * to xHCI so far.
  	 */
  	if (!do_read) {
  		err = usb_setup_descriptor(dev, true);
  		if (err)
  			return err;
  	}
91398f985   Simon Glass   dm: usb: Split ou...
1091
1092
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1093
  int usb_select_config(struct usb_device *dev)
91398f985   Simon Glass   dm: usb: Split ou...
1094
  {
2f1b4302e   Marek Vasut   usb: Don't init p...
1095
  	unsigned char *tmpbuf = NULL;
0ed27905c   Simon Glass   dm: usb: Complete...
1096
  	int err;
91398f985   Simon Glass   dm: usb: Split ou...
1097

0ed27905c   Simon Glass   dm: usb: Complete...
1098
1099
1100
  	err = get_descriptor_len(dev, USB_DT_DEVICE_SIZE, USB_DT_DEVICE_SIZE);
  	if (err)
  		return err;
affae2bff   wdenk   Initial revision
1101

affae2bff   wdenk   Initial revision
1102
  	/* correct le values */
c918261c6   Christian Eggers   USB: replace old ...
1103
1104
1105
1106
  	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...
1107

ef71290be   Marek Vasut   usb: Assure Get D...
1108
1109
1110
1111
1112
1113
1114
  	/*
  	 * 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
1115
  	/* only support for one config for now */
c75f57fba   Stefan Brüns   usb: Alloc buffer...
1116
1117
1118
1119
1120
1121
1122
1123
  	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...
1124
1125
1126
1127
1128
  	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...
1129
  		free(tmpbuf);
0ed27905c   Simon Glass   dm: usb: Complete...
1130
  		return err;
8b8d779da   Vincent Palatin   usb: fallback saf...
1131
  	}
f57661394   Puneet Saxena   USB: Align buffer...
1132
  	usb_parse_config(dev, tmpbuf, 0);
c75f57fba   Stefan Brüns   usb: Alloc buffer...
1133
  	free(tmpbuf);
affae2bff   wdenk   Initial revision
1134
  	usb_set_maxpacket(dev);
0ed27905c   Simon Glass   dm: usb: Complete...
1135
1136
1137
1138
1139
1140
1141
  	/*
  	 * 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...
1142
1143
1144
  		printf("failed to set default configuration " \
  			"len %d, status %lX
  ", dev->act_len, dev->status);
0ed27905c   Simon Glass   dm: usb: Complete...
1145
  		return err;
affae2bff   wdenk   Initial revision
1146
  	}
f647bf0ba   Marek Vasut   usb: Wait after s...
1147
1148
1149
1150
1151
1152
1153
  
  	/*
  	 * 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...
1154
1155
1156
1157
  	debug("new device strings: Mfr=%d, Product=%d, SerialNumber=%d
  ",
  	      dev->descriptor.iManufacturer, dev->descriptor.iProduct,
  	      dev->descriptor.iSerialNumber);
affae2bff   wdenk   Initial revision
1158
1159
1160
1161
  	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...
1162
1163
  		usb_string(dev, dev->descriptor.iManufacturer,
  			   dev->mf, sizeof(dev->mf));
affae2bff   wdenk   Initial revision
1164
  	if (dev->descriptor.iProduct)
6f5794a6f   Remy Bohmer   Refactoring parts...
1165
1166
  		usb_string(dev, dev->descriptor.iProduct,
  			   dev->prod, sizeof(dev->prod));
affae2bff   wdenk   Initial revision
1167
  	if (dev->descriptor.iSerialNumber)
6f5794a6f   Remy Bohmer   Refactoring parts...
1168
1169
  		usb_string(dev, dev->descriptor.iSerialNumber,
  			   dev->serial, sizeof(dev->serial));
ceb4972a8   Vivek Gautam   usb: common: Weed...
1170
1171
1172
1173
1174
1175
  	debug("Manufacturer %s
  ", dev->mf);
  	debug("Product      %s
  ", dev->prod);
  	debug("SerialNumber %s
  ", dev->serial);
0ed27905c   Simon Glass   dm: usb: Complete...
1176
1177
1178
  
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1179
  int usb_setup_device(struct usb_device *dev, bool do_read,
9eb72dd1f   Hans de Goede   usb: usb_setup_de...
1180
  		     struct usb_device *parent)
0ed27905c   Simon Glass   dm: usb: Complete...
1181
1182
1183
1184
1185
1186
1187
  {
  	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...
1188
  	ret = usb_prepare_device(dev, addr, do_read, parent);
0ed27905c   Simon Glass   dm: usb: Complete...
1189
1190
1191
1192
1193
1194
  	if (ret)
  		return ret;
  	ret = usb_select_config(dev);
  
  	return ret;
  }
fd09c205f   Sven Schwermer   usb: s/CONFIG_DM_...
1195
  #if !CONFIG_IS_ENABLED(DM_USB)
0ed27905c   Simon Glass   dm: usb: Complete...
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
  /*
   * 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_...
1214
  #ifdef CONFIG_USB_XHCI_HCD
0ed27905c   Simon Glass   dm: usb: Complete...
1215
1216
  	do_read = false;
  #endif
9eb72dd1f   Hans de Goede   usb: usb_setup_de...
1217
  	err = usb_setup_device(dev, do_read, dev->parent);
0ed27905c   Simon Glass   dm: usb: Complete...
1218
1219
1220
1221
1222
1223
1224
  	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
1225
1226
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1227
  #endif
affae2bff   wdenk   Initial revision
1228

16297cfb2   Mateusz Zalega   usb: new board-sp...
1229
  __weak
bba679144   Troy Kisky   usb: rename board...
1230
  int board_usb_init(int index, enum usb_init_type init)
16297cfb2   Mateusz Zalega   usb: new board-sp...
1231
1232
1233
  {
  	return 0;
  }
db378d786   Kishon Vijay Abraham I   common: cmd_dfu: ...
1234
1235
1236
1237
1238
1239
  
  __weak
  int board_usb_cleanup(int index, enum usb_init_type init)
  {
  	return 0;
  }
95fbfe429   Simon Glass   dm: usb: Convert ...
1240
1241
1242
  
  bool usb_device_has_child_on_port(struct usb_device *parent, int port)
  {
fd09c205f   Sven Schwermer   usb: s/CONFIG_DM_...
1243
  #if CONFIG_IS_ENABLED(DM_USB)
95fbfe429   Simon Glass   dm: usb: Convert ...
1244
1245
1246
1247
1248
  	return false;
  #else
  	return parent->children[port] != NULL;
  #endif
  }
fd09c205f   Sven Schwermer   usb: s/CONFIG_DM_...
1249
  #if CONFIG_IS_ENABLED(DM_USB)
faa7db24a   Stefan Brüns   usb: Move determi...
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
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
  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
1305
  /* EOF */