usb.c 38.9 KB
Newer Older
W
wdenk 已提交
1 2 3
/*
 *
 * Most of this source has been derived from the Linux USB
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
W
wdenk 已提交
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 *
 */

/*
 * 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>
#include <asm/processor.h>
50
#include <linux/ctype.h>
51
#include <asm/byteorder.h>
52
#include <asm/unaligned.h>
W
wdenk 已提交
53 54 55

#include <usb.h>
#ifdef CONFIG_4xx
56
#include <asm/4xx_pci.h>
W
wdenk 已提交
57 58
#endif

59
#ifdef DEBUG
60 61
#define USB_DEBUG	1
#define USB_HUB_DEBUG	1
W
wdenk 已提交
62
#else
63 64
#define USB_DEBUG	0
#define USB_HUB_DEBUG	0
W
wdenk 已提交
65 66
#endif

67 68 69
#define USB_PRINTF(fmt, args...)	debug_cond(USB_DEBUG, fmt, ##args)
#define USB_HUB_PRINTF(fmt, args...)	debug_cond(USB_HUB_DEBUG, fmt, ##args)

W
wdenk 已提交
70 71
#define USB_BUFSIZ	512

W
wdenk 已提交
72 73 74 75 76 77
static struct usb_device usb_dev[USB_MAX_DEVICE];
static int dev_index;
static int running;
static int asynch_allowed;
static struct devrequest setup_packet;

78 79
char usb_started; /* flag for the started/stopped USB status */

W
wdenk 已提交
80 81 82 83 84 85 86
/**********************************************************************
 * some forward declerations...
 */
void usb_scan_devices(void);

int usb_hub_probe(struct usb_device *dev, int ifnum);
void usb_hub_reset(void);
87 88
static int hub_port_reset(struct usb_device *dev, int port,
			  unsigned short *portstat);
89

W
wdenk 已提交
90 91 92 93
/***********************************************************************
 * wait_ms
 */

94
inline void wait_ms(unsigned long ms)
W
wdenk 已提交
95
{
96
	while (ms-- > 0)
W
wdenk 已提交
97 98
		udelay(1000);
}
99

W
wdenk 已提交
100 101 102 103 104 105 106 107
/***************************************************************************
 * Init USB Device
 */

int usb_init(void)
{
	int result;

108 109 110
	running = 0;
	dev_index = 0;
	asynch_allowed = 1;
W
wdenk 已提交
111 112 113 114
	usb_hub_reset();
	/* init low_level USB */
	printf("USB:   ");
	result = usb_lowlevel_init();
115 116 117
	/* if lowlevel init is OK, scan the bus for devices
	 * i.e. search HUBs and configure them */
	if (result == 0) {
W
wdenk 已提交
118
		printf("scanning bus for devices... ");
119
		running = 1;
W
wdenk 已提交
120
		usb_scan_devices();
121
		usb_started = 1;
W
wdenk 已提交
122
		return 0;
123
	} else {
W
wdenk 已提交
124
		printf("Error, couldn't init Lowlevel part\n");
125
		usb_started = 0;
W
wdenk 已提交
126 127 128 129 130 131 132 133 134
		return -1;
	}
}

/******************************************************************************
 * Stop USB this stops the LowLevel Part and deregisters USB devices.
 */
int usb_stop(void)
{
135 136 137 138 139 140 141 142 143
	int res = 0;

	if (usb_started) {
		asynch_allowed = 1;
		usb_started = 0;
		usb_hub_reset();
		res = usb_lowlevel_stop();
	}
	return res;
W
wdenk 已提交
144 145 146 147 148
}

/*
 * 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.
149
 * Returns the old value so it can be restored later.
W
wdenk 已提交
150
 */
151
int usb_disable_asynch(int disable)
W
wdenk 已提交
152
{
153 154
	int old_value = asynch_allowed;

155
	asynch_allowed = !disable;
156
	return old_value;
W
wdenk 已提交
157 158 159 160 161 162 163 164 165 166 167 168
}


/*-------------------------------------------------------------------
 * Message wrappers.
 *
 */

/*
 * submits an Interrupt Message
 */
int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
169
			void *buffer, int transfer_len, int interval)
W
wdenk 已提交
170
{
171
	return submit_int_msg(dev, pipe, buffer, transfer_len, interval);
W
wdenk 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
}

/*
 * 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)).
 * returns the transfered length if OK or -1 if error. The transfered length
 * 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)
{
188 189
	if ((timeout == 0) && (!asynch_allowed)) {
		/* request for a asynch control pipe is not allowed */
W
wdenk 已提交
190
		return -1;
191
	}
192

W
wdenk 已提交
193 194 195
	/* set setup command */
	setup_packet.requesttype = requesttype;
	setup_packet.request = request;
196 197 198
	setup_packet.value = cpu_to_le16(value);
	setup_packet.index = cpu_to_le16(index);
	setup_packet.length = cpu_to_le16(size);
199 200 201 202
	USB_PRINTF("usb_control_msg: request: 0x%X, requesttype: 0x%X, " \
		   "value 0x%X index 0x%X length 0x%X\n",
		   request, requesttype, value, index, size);
	dev->status = USB_ST_NOT_PROC; /*not yet processed */
W
wdenk 已提交
203

204 205
	submit_control_msg(dev, pipe, data, size, &setup_packet);
	if (timeout == 0)
W
wdenk 已提交
206
		return (int)size;
207

208 209 210 211 212 213 214 215 216
	/*
	 * 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;
		wait_ms(1);
R
Remy Bohmer 已提交
217
	}
218 219
	if (dev->status)
		return -1;
R
Remy Bohmer 已提交
220 221

	return dev->act_len;
222

W
wdenk 已提交
223 224 225 226 227 228 229 230 231 232 233 234
}

/*-------------------------------------------------------------------
 * submits bulk message, and waits for completion. returns 0 if Ok or
 * -1 if Error.
 * 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)
		return -1;
235 236 237 238
	dev->status = USB_ST_NOT_PROC; /*not yet processed */
	submit_bulk_msg(dev, pipe, data, len);
	while (timeout--) {
		if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
W
wdenk 已提交
239 240 241
			break;
		wait_ms(1);
	}
242 243
	*actual_length = dev->act_len;
	if (dev->status == 0)
W
wdenk 已提交
244 245 246 247 248 249 250 251 252 253 254 255 256 257
		return 0;
	else
		return -1;
}


/*-------------------------------------------------------------------
 * Max Packet stuff
 */

/*
 * returns the max packet size, depending on the pipe direction and
 * the configurations values
 */
258
int usb_maxpacket(struct usb_device *dev, unsigned long pipe)
W
wdenk 已提交
259
{
260 261
	/* direction is out -> use emaxpacket out */
	if ((pipe & USB_DIR_IN) == 0)
262
		return dev->epmaxpacketout[((pipe>>15) & 0xf)];
W
wdenk 已提交
263
	else
264
		return dev->epmaxpacketin[((pipe>>15) & 0xf)];
W
wdenk 已提交
265 266
}

M
Marek Vasut 已提交
267 268
/*
 * The routine usb_set_maxpacket_ep() is extracted from the loop of routine
269 270 271 272 273 274
 * 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)
M
Marek Vasut 已提交
275 276
 *
 * NOTE: Similar behaviour was observed with GCC4.6 on ARMv5.
277 278
 */
static void  __attribute__((noinline))
M
Marek Vasut 已提交
279
usb_set_maxpacket_ep(struct usb_device *dev, int if_idx, int ep_idx)
280 281
{
	int b;
M
Marek Vasut 已提交
282
	struct usb_endpoint_descriptor *ep;
283
	u16 ep_wMaxPacketSize;
M
Marek Vasut 已提交
284 285

	ep = &dev->config.if_desc[if_idx].ep_desc[ep_idx];
286 287

	b = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
288
	ep_wMaxPacketSize = get_unaligned(&ep->wMaxPacketSize);
289 290 291 292

	if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
						USB_ENDPOINT_XFER_CONTROL) {
		/* Control => bidirectional */
293 294
		dev->epmaxpacketout[b] = ep_wMaxPacketSize;
		dev->epmaxpacketin[b] = ep_wMaxPacketSize;
295 296 297 298 299
		USB_PRINTF("##Control EP epmaxpacketout/in[%d] = %d\n",
			   b, dev->epmaxpacketin[b]);
	} else {
		if ((ep->bEndpointAddress & 0x80) == 0) {
			/* OUT Endpoint */
300 301
			if (ep_wMaxPacketSize > dev->epmaxpacketout[b]) {
				dev->epmaxpacketout[b] = ep_wMaxPacketSize;
302 303 304 305 306
				USB_PRINTF("##EP epmaxpacketout[%d] = %d\n",
					   b, dev->epmaxpacketout[b]);
			}
		} else {
			/* IN Endpoint */
307 308
			if (ep_wMaxPacketSize > dev->epmaxpacketin[b]) {
				dev->epmaxpacketin[b] = ep_wMaxPacketSize;
309 310 311 312 313 314 315
				USB_PRINTF("##EP epmaxpacketin[%d] = %d\n",
					   b, dev->epmaxpacketin[b]);
			}
		} /* if out */
	} /* if control */
}

W
wdenk 已提交
316 317 318 319 320
/*
 * set the max packed value of all endpoints in the given configuration
 */
int usb_set_maxpacket(struct usb_device *dev)
{
321
	int i, ii;
W
wdenk 已提交
322

T
Tom Rix 已提交
323 324
	for (i = 0; i < dev->config.desc.bNumInterfaces; i++)
		for (ii = 0; ii < dev->config.if_desc[i].desc.bNumEndpoints; ii++)
M
Marek Vasut 已提交
325
			usb_set_maxpacket_ep(dev, i, ii);
W
wdenk 已提交
326 327 328 329 330 331 332 333 334 335 336

	return 0;
}

/*******************************************************************************
 * Parse the config, located in buffer, and fills the dev->config structure.
 * Note that all little/big endian swapping are done automatically.
 */
int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
{
	struct usb_descriptor_header *head;
337 338
	int index, ifno, epno, curr_if_num;
	int i;
339
	u16 ep_wMaxPacketSize;
340 341 342 343 344 345 346

	ifno = -1;
	epno = -1;
	curr_if_num = -1;

	dev->configno = cfgno;
	head = (struct usb_descriptor_header *) &buffer[0];
347 348 349
	if (head->bDescriptorType != USB_DT_CONFIG) {
		printf(" ERROR: NOT USB_CONFIG_DESC %x\n",
			head->bDescriptorType);
W
wdenk 已提交
350 351
		return -1;
	}
352
	memcpy(&dev->config, buffer, buffer[0]);
T
Tom Rix 已提交
353
	le16_to_cpus(&(dev->config.desc.wTotalLength));
354
	dev->config.no_of_if = 0;
W
wdenk 已提交
355

T
Tom Rix 已提交
356
	index = dev->config.desc.bLength;
357 358
	/* Ok the first entry must be a configuration entry,
	 * now process the others */
359
	head = (struct usb_descriptor_header *) &buffer[index];
T
Tom Rix 已提交
360
	while (index + 1 < dev->config.desc.wTotalLength) {
361 362 363 364 365 366 367 368
		switch (head->bDescriptorType) {
		case USB_DT_INTERFACE:
			if (((struct usb_interface_descriptor *) \
			     &buffer[index])->bInterfaceNumber != curr_if_num) {
				/* this is a new interface, copy new desc */
				ifno = dev->config.no_of_if;
				dev->config.no_of_if++;
				memcpy(&dev->config.if_desc[ifno],
369
					&buffer[index], buffer[index]);
370 371 372
				dev->config.if_desc[ifno].no_of_ep = 0;
				dev->config.if_desc[ifno].num_altsetting = 1;
				curr_if_num =
T
Tom Rix 已提交
373
				     dev->config.if_desc[ifno].desc.bInterfaceNumber;
374 375 376 377 378 379 380 381 382 383 384
			} else {
				/* found alternate setting for the interface */
				dev->config.if_desc[ifno].num_altsetting++;
			}
			break;
		case USB_DT_ENDPOINT:
			epno = dev->config.if_desc[ifno].no_of_ep;
			/* found an endpoint */
			dev->config.if_desc[ifno].no_of_ep++;
			memcpy(&dev->config.if_desc[ifno].ep_desc[epno],
				&buffer[index], buffer[index]);
385 386 387 388 389 390 391 392 393
			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);
394 395 396 397 398 399 400 401 402 403
			USB_PRINTF("if %d, ep %d\n", ifno, epno);
			break;
		default:
			if (head->bLength == 0)
				return 1;

			USB_PRINTF("unknown Description Type : %x\n",
				   head->bDescriptorType);

			{
404 405 406
#ifdef USB_DEBUG
				unsigned char *ch = (unsigned char *)head;
#endif
407 408 409 410 411
				for (i = 0; i < head->bLength; i++)
					USB_PRINTF("%02X ", *ch++);
				USB_PRINTF("\n\n\n");
			}
			break;
W
wdenk 已提交
412
		}
413 414
		index += head->bLength;
		head = (struct usb_descriptor_header *)&buffer[index];
W
wdenk 已提交
415 416 417 418 419 420 421 422 423 424 425 426
	}
	return 1;
}

/***********************************************************************
 * 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;
427
	int endp = usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
W
wdenk 已提交
428 429

	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
430 431
				 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
				 endp, NULL, 0, USB_CNTL_TIMEOUT * 3);
W
wdenk 已提交
432 433 434 435

	/* don't clear if failed */
	if (result < 0)
		return result;
436

W
Wolfgang Denk 已提交
437
	/*
438 439 440 441
	 * NOTE: we do not get status and verify reset was successful
	 * as some devices are reported to lock up upon this check..
	 */

W
wdenk 已提交
442
	usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
443

W
wdenk 已提交
444 445 446 447 448 449 450 451 452
	/* toggle is reset on clear */
	usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
	return 0;
}


/**********************************************************************
 * get_descriptor type
 */
453 454
int usb_get_descriptor(struct usb_device *dev, unsigned char type,
			unsigned char index, void *buf, int size)
W
wdenk 已提交
455 456
{
	int res;
W
Wolfgang Denk 已提交
457
	res = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
W
wdenk 已提交
458 459 460 461 462 463 464 465 466
			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
			(type << 8) + index, 0,
			buf, size, USB_CNTL_TIMEOUT);
	return res;
}

/**********************************************************************
 * gets configuration cfgno and store it in the buffer
 */
467 468
int usb_get_configuration_no(struct usb_device *dev,
			     unsigned char *buffer, int cfgno)
W
wdenk 已提交
469
{
W
Wolfgang Denk 已提交
470
	int result;
W
wdenk 已提交
471
	unsigned int tmp;
T
Tom Rix 已提交
472
	struct usb_configuration_descriptor *config;
W
wdenk 已提交
473

T
Tom Rix 已提交
474
	config = (struct usb_configuration_descriptor *)&buffer[0];
R
Remy Bohmer 已提交
475 476
	result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 9);
	if (result < 9) {
W
wdenk 已提交
477
		if (result < 0)
478 479
			printf("unable to get descriptor, error %lX\n",
				dev->status);
W
wdenk 已提交
480
		else
481
			printf("config descriptor too short " \
R
Remy Bohmer 已提交
482
				"(expected %i, got %i)\n", 9, result);
W
wdenk 已提交
483 484
		return -1;
	}
485
	tmp = le16_to_cpu(config->wTotalLength);
W
wdenk 已提交
486

W
wdenk 已提交
487
	if (tmp > USB_BUFSIZ) {
488 489
		USB_PRINTF("usb_get_configuration_no: failed to get " \
			   "descriptor - too long: %d\n", tmp);
W
wdenk 已提交
490 491 492
		return -1;
	}

W
wdenk 已提交
493
	result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, tmp);
494 495
	USB_PRINTF("get_conf_no %d Result %d, wLength %d\n",
		   cfgno, result, tmp);
W
wdenk 已提交
496 497 498 499 500 501 502 503 504 505 506
	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)
 */
int usb_set_address(struct usb_device *dev)
{
	int res;

507 508 509 510 511
	USB_PRINTF("set address %d\n", dev->devnum);
	res = usb_control_msg(dev, usb_snddefctrl(dev),
				USB_REQ_SET_ADDRESS, 0,
				(dev->devnum), 0,
				NULL, 0, USB_CNTL_TIMEOUT);
W
wdenk 已提交
512 513 514 515 516 517 518 519
	return res;
}

/********************************************************************
 * set interface number to interface
 */
int usb_set_interface(struct usb_device *dev, int interface, int alternate)
{
T
Tom Rix 已提交
520
	struct usb_interface *if_face = NULL;
W
wdenk 已提交
521 522
	int ret, i;

T
Tom Rix 已提交
523 524
	for (i = 0; i < dev->config.desc.bNumInterfaces; i++) {
		if (dev->config.if_desc[i].desc.bInterfaceNumber == interface) {
W
wdenk 已提交
525 526 527 528 529 530 531 532
			if_face = &dev->config.if_desc[i];
			break;
		}
	}
	if (!if_face) {
		printf("selecting invalid interface %d", interface);
		return -1;
	}
533 534
	/*
	 * We should return now for devices with only one alternate setting.
535 536 537 538
	 * 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.
539 540 541
	 */
	if (if_face->num_altsetting == 1)
		return 0;
W
wdenk 已提交
542

543 544 545 546 547
	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)
W
wdenk 已提交
548 549 550 551 552 553 554 555 556 557 558
		return ret;

	return 0;
}

/********************************************************************
 * set configuration number to configuration
 */
int usb_set_configuration(struct usb_device *dev, int configuration)
{
	int res;
559
	USB_PRINTF("set configuration %d\n", configuration);
W
wdenk 已提交
560
	/* set setup command */
561 562 563 564 565
	res = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
				USB_REQ_SET_CONFIGURATION, 0,
				configuration, 0,
				NULL, 0, USB_CNTL_TIMEOUT);
	if (res == 0) {
W
wdenk 已提交
566 567 568
		dev->toggle[0] = 0;
		dev->toggle[1] = 0;
		return 0;
569
	} else
W
wdenk 已提交
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
		return -1;
}

/********************************************************************
 * 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
 */
596 597
int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
		   unsigned char id, void *buf, int size)
W
wdenk 已提交
598 599
{
	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
600 601 602
			USB_REQ_GET_REPORT,
			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
			(type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT);
W
wdenk 已提交
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
}

/********************************************************************
 * 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
 */
619 620
int usb_get_string(struct usb_device *dev, unsigned short langid,
		   unsigned char index, void *buf, int size)
W
wdenk 已提交
621
{
622 623 624 625 626 627 628
	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,
W
Wolfgang Denk 已提交
629
			(USB_DT_STRING << 8) + index, langid, buf, size,
630 631 632 633
			USB_CNTL_TIMEOUT);

		if (result > 0)
			break;
W
Wolfgang Denk 已提交
634 635
	}

636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
	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;
	}
W
wdenk 已提交
652 653
}

654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683

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)
W
Wolfgang Denk 已提交
684
		rc = -1;
685 686 687 688 689

	return rc;
}


W
wdenk 已提交
690 691 692 693 694 695 696
/********************************************************************
 * 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)
{
W
wdenk 已提交
697
	unsigned char mybuf[USB_BUFSIZ];
W
wdenk 已提交
698 699 700 701 702 703 704
	unsigned char *tbuf;
	int err;
	unsigned int u, idx;

	if (size <= 0 || !buf || !index)
		return -1;
	buf[0] = 0;
705
	tbuf = &mybuf[0];
W
wdenk 已提交
706 707 708

	/* get langid for strings if it's not yet known */
	if (!dev->have_langid) {
709
		err = usb_string_sub(dev, 0, 0, tbuf);
W
wdenk 已提交
710
		if (err < 0) {
711
			USB_PRINTF("error getting string descriptor 0 " \
712
				   "(error=%lx)\n", dev->status);
W
wdenk 已提交
713 714 715 716 717 718
			return -1;
		} else if (tbuf[0] < 4) {
			USB_PRINTF("string descriptor 0 too short\n");
			return -1;
		} else {
			dev->have_langid = -1;
719
			dev->string_langid = tbuf[2] | (tbuf[3] << 8);
W
wdenk 已提交
720
				/* always use the first langid listed */
721 722 723
			USB_PRINTF("USB device number %d default " \
				   "language ID 0x%x\n",
				   dev->devnum, dev->string_langid);
W
wdenk 已提交
724 725
		}
	}
W
wdenk 已提交
726

727
	err = usb_string_sub(dev, dev->string_langid, index, tbuf);
W
wdenk 已提交
728 729
	if (err < 0)
		return err;
730

W
wdenk 已提交
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754
	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].
 */


/* returns a pointer to the device with the index [index].
 * if the device is not assigned (dev->devnum==-1) returns NULL
 */
755
struct usb_device *usb_get_dev_index(int index)
W
wdenk 已提交
756
{
757
	if (usb_dev[index].devnum == -1)
W
wdenk 已提交
758 759 760 761 762 763 764 765 766
		return NULL;
	else
		return &usb_dev[index];
}


/* returns a pointer of a new device structure or NULL, if
 * no device struct is available
 */
767
struct usb_device *usb_alloc_new_device(void)
W
wdenk 已提交
768 769
{
	int i;
770 771 772
	USB_PRINTF("New Device %d\n", dev_index);
	if (dev_index == USB_MAX_DEVICE) {
		printf("ERROR, too many USB Devices, max=%d\n", USB_MAX_DEVICE);
W
wdenk 已提交
773 774
		return NULL;
	}
775 776 777 778 779 780
	/* 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;
W
wdenk 已提交
781
	dev_index++;
782
	return &usb_dev[dev_index - 1];
W
wdenk 已提交
783 784 785 786 787 788 789 790 791 792 793 794 795 796
}


/*
 * 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)
{
	int addr, err;
	int tmp;
W
wdenk 已提交
797
	unsigned char tmpbuf[USB_BUFSIZ];
W
wdenk 已提交
798 799 800 801

	/* We still haven't set the Address yet */
	addr = dev->devnum;
	dev->devnum = 0;
802

803 804 805 806 807 808 809
#ifdef CONFIG_LEGACY_USB_INIT_SEQ
	/* this is the old and known way of initializing devices, it is
	 * different than what Windows and Linux are doing. Windows and Linux
	 * both retrieve 64 bytes while reading the device descriptor
	 * Several USB stick devices report ERR: CTL_TIMEOUT, caused by an
	 * invalid header while reading 8 bytes as device descriptor. */
	dev->descriptor.bMaxPacketSize0 = 8;	    /* Start off at 8 bytes  */
R
Remy Bohmer 已提交
810
	dev->maxpacketsize = PACKET_SIZE_8;
811
	dev->epmaxpacketin[0] = 8;
812 813 814 815 816
	dev->epmaxpacketout[0] = 8;

	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
	if (err < 8) {
		printf("\n      USB device not responding, " \
817
		       "giving up (status=%lX)\n", dev->status);
818 819 820
		return 1;
	}
#else
R
Remy Bohmer 已提交
821 822
	/* This is a Windows scheme of initialization sequence, with double
	 * reset of the device (Linux uses the same sequence)
823 824
	 * Some equipment is said to work only with such init sequence; this
	 * patch is based on the work by Alan Stern:
825 826
	 * http://sourceforge.net/mailarchive/forum.php?
	 * thread_id=5729457&forum_id=5398
827 828 829 830 831 832 833 834 835
	 */
	struct usb_device_descriptor *desc;
	int port = -1;
	struct usb_device *parent = dev->parent;
	unsigned short portstatus;

	/* send 64-byte GET-DEVICE-DESCRIPTOR request.  Since the descriptor is
	 * 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
836
	 * some more, or keeps on retransmitting the 8 byte header. */
837 838

	desc = (struct usb_device_descriptor *)tmpbuf;
839
	dev->descriptor.bMaxPacketSize0 = 64;	    /* Start off at 64 bytes  */
R
Remy Bohmer 已提交
840 841
	/* Default to 64 byte max packet size */
	dev->maxpacketsize = PACKET_SIZE_64;
842
	dev->epmaxpacketin[0] = 64;
843
	dev->epmaxpacketout[0] = 64;
R
Remy Bohmer 已提交
844 845 846 847 848

	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64);
	if (err < 0) {
		USB_PRINTF("usb_new_device: usb_get_descriptor() failed\n");
		return 1;
849
	}
R
Remy Bohmer 已提交
850

851
	dev->descriptor.bMaxPacketSize0 = desc->bMaxPacketSize0;
W
Wolfgang Denk 已提交
852

853 854
	/* find the port number we're at */
	if (parent) {
R
Remy Bohmer 已提交
855
		int j;
W
Wolfgang Denk 已提交
856

857 858 859 860 861 862 863
		for (j = 0; j < parent->maxchild; j++) {
			if (parent->children[j] == dev) {
				port = j;
				break;
			}
		}
		if (port < 0) {
864
			printf("usb_new_device:cannot locate device's port.\n");
865 866 867 868 869 870 871 872 873 874 875 876
			return 1;
		}

		/* reset the port for the second time */
		err = hub_port_reset(dev->parent, port, &portstatus);
		if (err < 0) {
			printf("\n     Couldn't reset port %i\n", port);
			return 1;
		}
	}
#endif

877
	dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0;
W
wdenk 已提交
878 879
	dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
	switch (dev->descriptor.bMaxPacketSize0) {
880 881 882 883 884 885 886 887 888 889 890 891
	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;
W
wdenk 已提交
892 893 894 895 896 897
	}
	dev->devnum = addr;

	err = usb_set_address(dev); /* set address */

	if (err < 0) {
898 899
		printf("\n      USB device not accepting new address " \
			"(error=%lX)\n", dev->status);
W
wdenk 已提交
900 901 902 903 904 905 906
		return 1;
	}

	wait_ms(10);	/* Let the SET_ADDRESS settle */

	tmp = sizeof(dev->descriptor);

907 908
	err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
				 &dev->descriptor, sizeof(dev->descriptor));
W
wdenk 已提交
909 910
	if (err < tmp) {
		if (err < 0)
911 912
			printf("unable to get device descriptor (error=%d)\n",
			       err);
W
wdenk 已提交
913
		else
914 915
			printf("USB device descriptor short read " \
				"(expected %i, got %i)\n", tmp, err);
W
wdenk 已提交
916 917 918
		return 1;
	}
	/* correct le values */
919 920 921 922
	le16_to_cpus(&dev->descriptor.bcdUSB);
	le16_to_cpus(&dev->descriptor.idVendor);
	le16_to_cpus(&dev->descriptor.idProduct);
	le16_to_cpus(&dev->descriptor.bcdDevice);
W
wdenk 已提交
923
	/* only support for one config for now */
924 925
	usb_get_configuration_no(dev, &tmpbuf[0], 0);
	usb_parse_config(dev, &tmpbuf[0], 0);
W
wdenk 已提交
926 927
	usb_set_maxpacket(dev);
	/* we set the default configuration here */
T
Tom Rix 已提交
928
	if (usb_set_configuration(dev, dev->config.desc.bConfigurationValue)) {
929 930
		printf("failed to set default configuration " \
			"len %d, status %lX\n", dev->act_len, dev->status);
W
wdenk 已提交
931 932 933
		return -1;
	}
	USB_PRINTF("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
934 935
		   dev->descriptor.iManufacturer, dev->descriptor.iProduct,
		   dev->descriptor.iSerialNumber);
W
wdenk 已提交
936 937 938 939
	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)
940 941
		usb_string(dev, dev->descriptor.iManufacturer,
			   dev->mf, sizeof(dev->mf));
W
wdenk 已提交
942
	if (dev->descriptor.iProduct)
943 944
		usb_string(dev, dev->descriptor.iProduct,
			   dev->prod, sizeof(dev->prod));
W
wdenk 已提交
945
	if (dev->descriptor.iSerialNumber)
946 947
		usb_string(dev, dev->descriptor.iSerialNumber,
			   dev->serial, sizeof(dev->serial));
W
wdenk 已提交
948 949 950 951
	USB_PRINTF("Manufacturer %s\n", dev->mf);
	USB_PRINTF("Product      %s\n", dev->prod);
	USB_PRINTF("SerialNumber %s\n", dev->serial);
	/* now prode if the device is a hub */
952
	usb_hub_probe(dev, 0);
W
wdenk 已提交
953 954 955 956 957 958 959 960 961 962
	return 0;
}

/* build device Tree  */
void usb_scan_devices(void)
{
	int i;
	struct usb_device *dev;

	/* first make all devices unknown */
963 964
	for (i = 0; i < USB_MAX_DEVICE; i++) {
		memset(&usb_dev[i], 0, sizeof(struct usb_device));
965
		usb_dev[i].devnum = -1;
W
wdenk 已提交
966
	}
967
	dev_index = 0;
W
wdenk 已提交
968
	/* device 0 is always present (root hub, so let it analyze) */
969
	dev = usb_alloc_new_device();
970 971 972 973
	if (usb_new_device(dev))
		printf("No USB Device found\n");
	else
		printf("%d USB Device(s) found\n", dev_index);
W
wdenk 已提交
974 975 976 977
	/* insert "driver" if possible */
#ifdef CONFIG_USB_KEYBOARD
	drv_usb_kbd_init();
#endif
978
	USB_PRINTF("scan end\n");
W
wdenk 已提交
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
}


/****************************************************************************
 * HUB "Driver"
 * Probes device for being a hub and configurate it
 */

static struct usb_hub_device hub_dev[USB_MAX_HUB];
static int usb_hub_index;


int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
{
	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
		USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
		USB_DT_HUB << 8, 0, data, size, USB_CNTL_TIMEOUT);
}

int usb_clear_hub_feature(struct usb_device *dev, int feature)
{
	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1001 1002
				USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature,
				0, NULL, 0, USB_CNTL_TIMEOUT);
W
wdenk 已提交
1003 1004 1005 1006 1007
}

int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
{
	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1008 1009
				USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature,
				port, NULL, 0, USB_CNTL_TIMEOUT);
W
wdenk 已提交
1010 1011 1012 1013 1014
}

int usb_set_port_feature(struct usb_device *dev, int port, int feature)
{
	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
1015 1016
				USB_REQ_SET_FEATURE, USB_RT_PORT, feature,
				port, NULL, 0, USB_CNTL_TIMEOUT);
W
wdenk 已提交
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
}

int usb_get_hub_status(struct usb_device *dev, void *data)
{
	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
			USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
			data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT);
}

int usb_get_port_status(struct usb_device *dev, int port, void *data)
{
	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
			USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
			data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT);
}


static void usb_hub_power_on(struct usb_hub_device *hub)
{
	int i;
	struct usb_device *dev;

1039
	dev = hub->pusb_dev;
W
wdenk 已提交
1040 1041 1042 1043
	/* Enable power to the ports */
	USB_HUB_PRINTF("enabling power on all ports\n");
	for (i = 0; i < dev->maxchild; i++) {
		usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
1044
		USB_HUB_PRINTF("port %d returns %lX\n", i + 1, dev->status);
W
wdenk 已提交
1045 1046 1047 1048 1049 1050
		wait_ms(hub->desc.bPwrOn2PwrGood * 2);
	}
}

void usb_hub_reset(void)
{
1051
	usb_hub_index = 0;
W
wdenk 已提交
1052 1053 1054 1055
}

struct usb_hub_device *usb_hub_allocate(void)
{
1056
	if (usb_hub_index < USB_MAX_HUB)
W
wdenk 已提交
1057
		return &hub_dev[usb_hub_index++];
1058 1059

	printf("ERROR: USB_MAX_HUB (%d) reached\n", USB_MAX_HUB);
W
wdenk 已提交
1060 1061 1062 1063 1064
	return NULL;
}

#define MAX_TRIES 5

1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
static inline char *portspeed(int portstatus)
{
	if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED))
		return "480 Mb/s";
	else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED))
		return "1.5 Mb/s";
	else
		return "12 Mb/s";
}

1075 1076
static int hub_port_reset(struct usb_device *dev, int port,
			unsigned short *portstat)
W
wdenk 已提交
1077
{
1078
	int tries;
W
wdenk 已提交
1079 1080 1081
	struct usb_port_status portsts;
	unsigned short portstatus, portchange;

1082
	USB_HUB_PRINTF("hub_port_reset: resetting port %d...\n", port);
1083
	for (tries = 0; tries < MAX_TRIES; tries++) {
W
wdenk 已提交
1084 1085 1086 1087

		usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET);
		wait_ms(200);

1088 1089 1090
		if (usb_get_port_status(dev, port + 1, &portsts) < 0) {
			USB_HUB_PRINTF("get_port_status failed status %lX\n",
					dev->status);
1091
			return -1;
W
wdenk 已提交
1092
		}
1093 1094
		portstatus = le16_to_cpu(portsts.wPortStatus);
		portchange = le16_to_cpu(portsts.wPortChange);
M
Michael Trimarchi 已提交
1095

1096 1097
		USB_HUB_PRINTF("portstatus %x, change %x, %s\n",
				portstatus, portchange,
1098
				portspeed(portstatus));
M
Michael Trimarchi 已提交
1099

1100 1101
		USB_HUB_PRINTF("STAT_C_CONNECTION = %d STAT_CONNECTION = %d" \
			       "  USB_PORT_STAT_ENABLE %d\n",
W
wdenk 已提交
1102 1103 1104
			(portchange & USB_PORT_STAT_C_CONNECTION) ? 1 : 0,
			(portstatus & USB_PORT_STAT_CONNECTION) ? 1 : 0,
			(portstatus & USB_PORT_STAT_ENABLE) ? 1 : 0);
1105

W
wdenk 已提交
1106 1107
		if ((portchange & USB_PORT_STAT_C_CONNECTION) ||
		    !(portstatus & USB_PORT_STAT_CONNECTION))
1108
			return -1;
W
wdenk 已提交
1109

1110
		if (portstatus & USB_PORT_STAT_ENABLE)
W
wdenk 已提交
1111 1112 1113 1114 1115
			break;

		wait_ms(200);
	}

1116 1117 1118
	if (tries == MAX_TRIES) {
		USB_HUB_PRINTF("Cannot enable port %i after %i retries, " \
				"disabling port.\n", port + 1, MAX_TRIES);
W
wdenk 已提交
1119
		USB_HUB_PRINTF("Maybe the USB cable is bad?\n");
1120
		return -1;
W
wdenk 已提交
1121 1122 1123
	}

	usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_RESET);
1124 1125 1126 1127 1128 1129 1130 1131 1132
	*portstat = portstatus;
	return 0;
}


void usb_hub_port_connect_change(struct usb_device *dev, int port)
{
	struct usb_device *usb;
	struct usb_port_status portsts;
1133
	unsigned short portstatus;
1134 1135

	/* Check status */
1136
	if (usb_get_port_status(dev, port + 1, &portsts) < 0) {
1137 1138 1139 1140
		USB_HUB_PRINTF("get_port_status failed\n");
		return;
	}

1141
	portstatus = le16_to_cpu(portsts.wPortStatus);
1142
	USB_HUB_PRINTF("portstatus %x, change %x, %s\n",
1143 1144 1145
			portstatus,
			le16_to_cpu(portsts.wPortChange),
			portspeed(portstatus));
1146 1147 1148 1149 1150 1151

	/* Clear the connection change status */
	usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION);

	/* Disconnect any existing devices under this port */
	if (((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
1152
	     (!(portstatus & USB_PORT_STAT_ENABLE))) || (dev->children[port])) {
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
		USB_HUB_PRINTF("usb_disconnect(&hub->children[port]);\n");
		/* Return now if nothing is connected */
		if (!(portstatus & USB_PORT_STAT_CONNECTION))
			return;
	}
	wait_ms(200);

	/* Reset the port */
	if (hub_port_reset(dev, port, &portstatus) < 0) {
		printf("cannot reset port %i!?\n", port + 1);
		return;
	}

W
wdenk 已提交
1166 1167 1168
	wait_ms(200);

	/* Allocate a new device struct for it */
1169
	usb = usb_alloc_new_device();
M
Michael Trimarchi 已提交
1170 1171 1172 1173 1174 1175 1176

	if (portstatus & USB_PORT_STAT_HIGH_SPEED)
		usb->speed = USB_SPEED_HIGH;
	else if (portstatus & USB_PORT_STAT_LOW_SPEED)
		usb->speed = USB_SPEED_LOW;
	else
		usb->speed = USB_SPEED_FULL;
W
wdenk 已提交
1177 1178

	dev->children[port] = usb;
1179
	usb->parent = dev;
1180
	usb->portnr = port + 1;
W
wdenk 已提交
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191
	/* Run it through the hoops (find a driver, etc) */
	if (usb_new_device(usb)) {
		/* Woops, disable the port */
		USB_HUB_PRINTF("hub: disabling port %d\n", port + 1);
		usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE);
	}
}


int usb_hub_configure(struct usb_device *dev)
{
1192
	int i;
W
wdenk 已提交
1193
	unsigned char buffer[USB_BUFSIZ], *bitmap;
W
wdenk 已提交
1194 1195
	struct usb_hub_descriptor *descriptor;
	struct usb_hub_device *hub;
1196 1197 1198
#ifdef USB_HUB_DEBUG
	struct usb_hub_status *hubsts;
#endif
W
wdenk 已提交
1199 1200

	/* "allocate" Hub device */
1201 1202
	hub = usb_hub_allocate();
	if (hub == NULL)
W
wdenk 已提交
1203
		return -1;
1204
	hub->pusb_dev = dev;
W
wdenk 已提交
1205 1206
	/* Get the the hub descriptor */
	if (usb_get_hub_descriptor(dev, buffer, 4) < 0) {
1207 1208
		USB_HUB_PRINTF("usb_hub_configure: failed to get hub " \
				   "descriptor, giving up %lX\n", dev->status);
W
wdenk 已提交
1209 1210 1211
		return -1;
	}
	descriptor = (struct usb_hub_descriptor *)buffer;
W
wdenk 已提交
1212

W
wdenk 已提交
1213 1214 1215
	/* silence compiler warning if USB_BUFSIZ is > 256 [= sizeof(char)] */
	i = descriptor->bLength;
	if (i > USB_BUFSIZ) {
1216 1217 1218
		USB_HUB_PRINTF("usb_hub_configure: failed to get hub " \
				"descriptor - too long: %d\n",
				descriptor->bLength);
W
wdenk 已提交
1219 1220 1221
		return -1;
	}

W
wdenk 已提交
1222
	if (usb_get_hub_descriptor(dev, buffer, descriptor->bLength) < 0) {
1223 1224
		USB_HUB_PRINTF("usb_hub_configure: failed to get hub " \
				"descriptor 2nd giving up %lX\n", dev->status);
W
wdenk 已提交
1225 1226
		return -1;
	}
1227
	memcpy((unsigned char *)&hub->desc, buffer, descriptor->bLength);
W
wdenk 已提交
1228
	/* adjust 16bit values */
1229 1230
	hub->desc.wHubCharacteristics =
				le16_to_cpu(descriptor->wHubCharacteristics);
W
wdenk 已提交
1231
	/* set the bitmap */
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
	bitmap = (unsigned char *)&hub->desc.DeviceRemovable[0];
	/* devices not removable by default */
	memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8);
	bitmap = (unsigned char *)&hub->desc.PortPowerCtrlMask[0];
	memset(bitmap, 0xff, (USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */

	for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++)
		hub->desc.DeviceRemovable[i] = descriptor->DeviceRemovable[i];

	for (i = 0; i < ((hub->desc.bNbrPorts + 1 + 7)/8); i++)
1242
		hub->desc.PortPowerCtrlMask[i] = descriptor->PortPowerCtrlMask[i];
1243

W
wdenk 已提交
1244 1245 1246 1247
	dev->maxchild = descriptor->bNbrPorts;
	USB_HUB_PRINTF("%d ports detected\n", dev->maxchild);

	switch (hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) {
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
	case 0x00:
		USB_HUB_PRINTF("ganged power switching\n");
		break;
	case 0x01:
		USB_HUB_PRINTF("individual port power switching\n");
		break;
	case 0x02:
	case 0x03:
		USB_HUB_PRINTF("unknown reserved power switching mode\n");
		break;
W
wdenk 已提交
1258 1259 1260 1261 1262 1263 1264 1265
	}

	if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND)
		USB_HUB_PRINTF("part of a compound device\n");
	else
		USB_HUB_PRINTF("standalone hub\n");

	switch (hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) {
1266 1267 1268 1269 1270 1271 1272 1273 1274 1275
	case 0x00:
		USB_HUB_PRINTF("global over-current protection\n");
		break;
	case 0x08:
		USB_HUB_PRINTF("individual port over-current protection\n");
		break;
	case 0x10:
	case 0x18:
		USB_HUB_PRINTF("no over-current protection\n");
		break;
W
wdenk 已提交
1276
	}
1277 1278 1279 1280 1281 1282

	USB_HUB_PRINTF("power on to power good time: %dms\n",
			descriptor->bPwrOn2PwrGood * 2);
	USB_HUB_PRINTF("hub controller current requirement: %dmA\n",
			descriptor->bHubContrCurrent);

W
wdenk 已提交
1283 1284
	for (i = 0; i < dev->maxchild; i++)
		USB_HUB_PRINTF("port %d is%s removable\n", i + 1,
1285 1286 1287
			hub->desc.DeviceRemovable[(i + 1) / 8] & \
					   (1 << ((i + 1) % 8)) ? " not" : "");

W
wdenk 已提交
1288
	if (sizeof(struct usb_hub_status) > USB_BUFSIZ) {
1289 1290
		USB_HUB_PRINTF("usb_hub_configure: failed to get Status - " \
				"too long: %d\n", descriptor->bLength);
W
wdenk 已提交
1291 1292 1293
		return -1;
	}

W
wdenk 已提交
1294
	if (usb_get_hub_status(dev, buffer) < 0) {
1295 1296
		USB_HUB_PRINTF("usb_hub_configure: failed to get Status %lX\n",
				dev->status);
W
wdenk 已提交
1297 1298
		return -1;
	}
1299

1300
#ifdef USB_HUB_DEBUG
W
wdenk 已提交
1301
	hubsts = (struct usb_hub_status *)buffer;
1302
#endif
W
wdenk 已提交
1303
	USB_HUB_PRINTF("get_hub_status returned status %X, change %X\n",
1304 1305
			le16_to_cpu(hubsts->wHubStatus),
			le16_to_cpu(hubsts->wHubChange));
W
wdenk 已提交
1306
	USB_HUB_PRINTF("local power source is %s\n",
1307 1308
		(le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? \
		"lost (inactive)" : "good");
W
wdenk 已提交
1309
	USB_HUB_PRINTF("%sover-current condition exists\n",
1310 1311
		(le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? \
		"" : "no ");
W
wdenk 已提交
1312
	usb_hub_power_on(hub);
1313

W
wdenk 已提交
1314 1315 1316 1317 1318 1319 1320 1321
	for (i = 0; i < dev->maxchild; i++) {
		struct usb_port_status portsts;
		unsigned short portstatus, portchange;

		if (usb_get_port_status(dev, i + 1, &portsts) < 0) {
			USB_HUB_PRINTF("get_port_status failed\n");
			continue;
		}
1322

1323 1324
		portstatus = le16_to_cpu(portsts.wPortStatus);
		portchange = le16_to_cpu(portsts.wPortChange);
1325 1326 1327
		USB_HUB_PRINTF("Port %d Status %X Change %X\n",
				i + 1, portstatus, portchange);

W
wdenk 已提交
1328 1329 1330 1331 1332
		if (portchange & USB_PORT_STAT_C_CONNECTION) {
			USB_HUB_PRINTF("port %d connection change\n", i + 1);
			usb_hub_port_connect_change(dev, i);
		}
		if (portchange & USB_PORT_STAT_C_ENABLE) {
1333 1334 1335 1336 1337 1338 1339 1340
			USB_HUB_PRINTF("port %d enable change, status %x\n",
					i + 1, portstatus);
			usb_clear_port_feature(dev, i + 1,
						USB_PORT_FEAT_C_ENABLE);

			/* EM interference sometimes causes bad shielded USB
			 * devices to be shutdown by the hub, this hack enables
			 * them again. Works at least with mouse driver */
W
wdenk 已提交
1341
			if (!(portstatus & USB_PORT_STAT_ENABLE) &&
1342 1343 1344 1345 1346
			     (portstatus & USB_PORT_STAT_CONNECTION) &&
			     ((dev->children[i]))) {
				USB_HUB_PRINTF("already running port %i "  \
						"disabled by hub (EMI?), " \
						"re-enabling...\n", i + 1);
W
wdenk 已提交
1347 1348 1349 1350 1351
					usb_hub_port_connect_change(dev, i);
			}
		}
		if (portstatus & USB_PORT_STAT_SUSPEND) {
			USB_HUB_PRINTF("port %d suspend change\n", i + 1);
1352 1353
			usb_clear_port_feature(dev, i + 1,
						USB_PORT_FEAT_SUSPEND);
W
wdenk 已提交
1354 1355 1356 1357
		}

		if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
			USB_HUB_PRINTF("port %d over-current change\n", i + 1);
1358 1359
			usb_clear_port_feature(dev, i + 1,
						USB_PORT_FEAT_C_OVER_CURRENT);
W
wdenk 已提交
1360 1361 1362 1363 1364
			usb_hub_power_on(hub);
		}

		if (portchange & USB_PORT_STAT_C_RESET) {
			USB_HUB_PRINTF("port %d reset change\n", i + 1);
1365 1366
			usb_clear_port_feature(dev, i + 1,
						USB_PORT_FEAT_C_RESET);
W
wdenk 已提交
1367 1368 1369 1370 1371 1372 1373 1374
		}
	} /* end for i all ports */

	return 0;
}

int usb_hub_probe(struct usb_device *dev, int ifnum)
{
T
Tom Rix 已提交
1375
	struct usb_interface *iface;
W
wdenk 已提交
1376 1377 1378 1379 1380
	struct usb_endpoint_descriptor *ep;
	int ret;

	iface = &dev->config.if_desc[ifnum];
	/* Is it a hub? */
T
Tom Rix 已提交
1381
	if (iface->desc.bInterfaceClass != USB_CLASS_HUB)
W
wdenk 已提交
1382 1383 1384
		return 0;
	/* Some hubs have a subclass of 1, which AFAICT according to the */
	/*  specs is not defined, but it works */
T
Tom Rix 已提交
1385 1386
	if ((iface->desc.bInterfaceSubClass != 0) &&
	    (iface->desc.bInterfaceSubClass != 1))
W
wdenk 已提交
1387 1388
		return 0;
	/* Multiple endpoints? What kind of mutant ninja-hub is this? */
T
Tom Rix 已提交
1389
	if (iface->desc.bNumEndpoints != 1)
W
wdenk 已提交
1390 1391 1392 1393 1394 1395 1396 1397 1398 1399
		return 0;
	ep = &iface->ep_desc[0];
	/* Output endpoint? Curiousier and curiousier.. */
	if (!(ep->bEndpointAddress & USB_DIR_IN))
		return 0;
	/* If it's not an interrupt endpoint, we'd better punt! */
	if ((ep->bmAttributes & 3) != 3)
		return 0;
	/* We found a hub */
	USB_HUB_PRINTF("USB hub found\n");
1400
	ret = usb_hub_configure(dev);
W
wdenk 已提交
1401 1402 1403 1404
	return ret;
}

/* EOF */