]> git.proxmox.com Git - mirror_qemu.git/blame - hw/usb.c
USB user interface
[mirror_qemu.git] / hw / usb.c
CommitLineData
bb36d470
FB
1/*
2 * QEMU USB emulation
3 *
4 * Copyright (c) 2005 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#include "vl.h"
25
26void usb_attach(USBPort *port, USBDevice *dev)
27{
28 port->attach(port, dev);
29}
30
31/**********************/
32/* generic USB device helpers (you are not forced to use them when
33 writing your USB device driver, but they help handling the
34 protocol)
35*/
36
37#define SETUP_STATE_IDLE 0
38#define SETUP_STATE_DATA 1
39#define SETUP_STATE_ACK 2
40
41int usb_generic_handle_packet(USBDevice *s, int pid,
42 uint8_t devaddr, uint8_t devep,
43 uint8_t *data, int len)
44{
45 int l, ret = 0;
46
47 switch(pid) {
48 case USB_MSG_ATTACH:
49 s->state = USB_STATE_ATTACHED;
50 break;
51 case USB_MSG_DETACH:
52 s->state = USB_STATE_NOTATTACHED;
53 break;
54 case USB_MSG_RESET:
55 s->remote_wakeup = 0;
56 s->addr = 0;
57 s->state = USB_STATE_DEFAULT;
58 s->handle_reset(s);
59 break;
60 case USB_TOKEN_SETUP:
61 if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
62 return USB_RET_NODEV;
63 if (len != 8)
64 goto fail;
65 memcpy(s->setup_buf, data, 8);
66 s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
67 s->setup_index = 0;
68 if (s->setup_buf[0] & USB_DIR_IN) {
69 ret = s->handle_control(s,
70 (s->setup_buf[0] << 8) | s->setup_buf[1],
71 (s->setup_buf[3] << 8) | s->setup_buf[2],
72 (s->setup_buf[5] << 8) | s->setup_buf[4],
73 s->setup_len,
74 s->data_buf);
75 if (ret < 0)
76 return ret;
77 if (ret < s->setup_len)
78 s->setup_len = ret;
79 s->setup_state = SETUP_STATE_DATA;
80 } else {
81 if (s->setup_len == 0)
82 s->setup_state = SETUP_STATE_ACK;
83 else
84 s->setup_state = SETUP_STATE_DATA;
85 }
86 break;
87 case USB_TOKEN_IN:
88 if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
89 return USB_RET_NODEV;
90 switch(devep) {
91 case 0:
92 switch(s->setup_state) {
93 case SETUP_STATE_ACK:
94 s->setup_state = SETUP_STATE_IDLE;
95 if (!(s->setup_buf[0] & USB_DIR_IN)) {
96 ret = s->handle_control(s,
97 (s->setup_buf[0] << 8) | s->setup_buf[1],
98 (s->setup_buf[3] << 8) | s->setup_buf[2],
99 (s->setup_buf[5] << 8) | s->setup_buf[4],
100 s->setup_len,
101 s->data_buf);
102 if (ret > 0)
103 ret = 0;
104 } else {
105 goto fail;
106 }
107 break;
108 case SETUP_STATE_DATA:
109 if (s->setup_buf[0] & USB_DIR_IN) {
110 l = s->setup_len - s->setup_index;
111 if (l > len)
112 l = len;
113 memcpy(data, s->data_buf + s->setup_index, l);
114 s->setup_index += l;
115 if (s->setup_index >= s->setup_len)
116 s->setup_state = SETUP_STATE_ACK;
117 ret = l;
118 } else {
119 s->setup_state = SETUP_STATE_IDLE;
120 goto fail;
121 }
122 break;
123 default:
124 goto fail;
125 }
126 break;
127 default:
128 ret = s->handle_data(s, pid, devep, data, len);
129 break;
130 }
131 break;
132 case USB_TOKEN_OUT:
133 if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
134 return USB_RET_NODEV;
135 switch(devep) {
136 case 0:
137 switch(s->setup_state) {
138 case SETUP_STATE_ACK:
139 s->setup_state = SETUP_STATE_IDLE;
140 if (s->setup_buf[0] & USB_DIR_IN) {
141 /* transfer OK */
142 } else {
143 goto fail;
144 }
145 break;
146 case SETUP_STATE_DATA:
147 if (!(s->setup_buf[0] & USB_DIR_IN)) {
148 l = s->setup_len - s->setup_index;
149 if (l > len)
150 l = len;
151 memcpy(s->data_buf + s->setup_index, data, l);
152 s->setup_index += l;
153 if (s->setup_index >= s->setup_len)
154 s->setup_state = SETUP_STATE_ACK;
155 ret = l;
156 } else {
157 s->setup_state = SETUP_STATE_IDLE;
158 goto fail;
159 }
160 break;
161 default:
162 goto fail;
163 }
164 break;
165 default:
166 ret = s->handle_data(s, pid, devep, data, len);
167 break;
168 }
169 break;
170 default:
171 fail:
172 ret = USB_RET_STALL;
173 break;
174 }
175 return ret;
176}
177
178/* XXX: fix overflow */
179int set_usb_string(uint8_t *buf, const char *str)
180{
181 int len, i;
182 uint8_t *q;
183
184 q = buf;
185 len = strlen(str);
186 *q++ = 2 * len + 1;
187 *q++ = 3;
188 for(i = 0; i < len; i++) {
189 *q++ = str[i];
190 *q++ = 0;
191 }
192 return q - buf;
193}
194
195/**********************/
196/* USB hub emulation */
197
198//#define DEBUG
199
200#define MAX_PORTS 8
201
bb36d470
FB
202typedef struct USBHubPort {
203 USBPort port;
bb36d470
FB
204 uint16_t wPortStatus;
205 uint16_t wPortChange;
206} USBHubPort;
207
208typedef struct USBHubState {
209 USBDevice dev;
210 int nb_ports;
211 USBHubPort ports[MAX_PORTS];
212} USBHubState;
213
214#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE)
215#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE)
216#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR)
217#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS)
218#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS)
219#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE)
220#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE)
221
222#define PORT_STAT_CONNECTION 0x0001
223#define PORT_STAT_ENABLE 0x0002
224#define PORT_STAT_SUSPEND 0x0004
225#define PORT_STAT_OVERCURRENT 0x0008
226#define PORT_STAT_RESET 0x0010
227#define PORT_STAT_POWER 0x0100
228#define PORT_STAT_LOW_SPEED 0x0200
229#define PORT_STAT_HIGH_SPEED 0x0400
230#define PORT_STAT_TEST 0x0800
231#define PORT_STAT_INDICATOR 0x1000
232
233#define PORT_STAT_C_CONNECTION 0x0001
234#define PORT_STAT_C_ENABLE 0x0002
235#define PORT_STAT_C_SUSPEND 0x0004
236#define PORT_STAT_C_OVERCURRENT 0x0008
237#define PORT_STAT_C_RESET 0x0010
238
239#define PORT_CONNECTION 0
240#define PORT_ENABLE 1
241#define PORT_SUSPEND 2
242#define PORT_OVERCURRENT 3
243#define PORT_RESET 4
244#define PORT_POWER 8
245#define PORT_LOWSPEED 9
246#define PORT_HIGHSPEED 10
247#define PORT_C_CONNECTION 16
248#define PORT_C_ENABLE 17
249#define PORT_C_SUSPEND 18
250#define PORT_C_OVERCURRENT 19
251#define PORT_C_RESET 20
252#define PORT_TEST 21
253#define PORT_INDICATOR 22
254
255/* same as Linux kernel root hubs */
256
257static const uint8_t qemu_hub_dev_descriptor[] = {
92414fdc
FB
258 0x12, /* u8 bLength; */
259 0x01, /* u8 bDescriptorType; Device */
260 0x10, 0x01, /* u16 bcdUSB; v1.1 */
261
262 0x09, /* u8 bDeviceClass; HUB_CLASSCODE */
263 0x00, /* u8 bDeviceSubClass; */
264 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
265 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
266
267 0x00, 0x00, /* u16 idVendor; */
268 0x00, 0x00, /* u16 idProduct; */
269 0x01, 0x01, /* u16 bcdDevice */
270
271 0x03, /* u8 iManufacturer; */
272 0x02, /* u8 iProduct; */
273 0x01, /* u8 iSerialNumber; */
274 0x01 /* u8 bNumConfigurations; */
bb36d470
FB
275};
276
277/* XXX: patch interrupt size */
278static const uint8_t qemu_hub_config_descriptor[] = {
279
280 /* one configuration */
92414fdc
FB
281 0x09, /* u8 bLength; */
282 0x02, /* u8 bDescriptorType; Configuration */
283 0x19, 0x00, /* u16 wTotalLength; */
284 0x01, /* u8 bNumInterfaces; (1) */
285 0x01, /* u8 bConfigurationValue; */
286 0x00, /* u8 iConfiguration; */
287 0xc0, /* u8 bmAttributes;
bb36d470
FB
288 Bit 7: must be set,
289 6: Self-powered,
290 5: Remote wakeup,
291 4..0: resvd */
92414fdc 292 0x00, /* u8 MaxPower; */
bb36d470
FB
293
294 /* USB 1.1:
295 * USB 2.0, single TT organization (mandatory):
296 * one interface, protocol 0
297 *
298 * USB 2.0, multiple TT organization (optional):
299 * two interfaces, protocols 1 (like single TT)
300 * and 2 (multiple TT mode) ... config is
301 * sometimes settable
302 * NOT IMPLEMENTED
303 */
304
305 /* one interface */
92414fdc
FB
306 0x09, /* u8 if_bLength; */
307 0x04, /* u8 if_bDescriptorType; Interface */
308 0x00, /* u8 if_bInterfaceNumber; */
309 0x00, /* u8 if_bAlternateSetting; */
310 0x01, /* u8 if_bNumEndpoints; */
311 0x09, /* u8 if_bInterfaceClass; HUB_CLASSCODE */
312 0x00, /* u8 if_bInterfaceSubClass; */
313 0x00, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
314 0x00, /* u8 if_iInterface; */
bb36d470
FB
315
316 /* one endpoint (status change endpoint) */
92414fdc
FB
317 0x07, /* u8 ep_bLength; */
318 0x05, /* u8 ep_bDescriptorType; Endpoint */
319 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
320 0x03, /* u8 ep_bmAttributes; Interrupt */
321 0x02, 0x00, /* u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
322 0xff /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
bb36d470
FB
323};
324
325static const uint8_t qemu_hub_hub_descriptor[] =
326{
92414fdc
FB
327 0x09, /* u8 bLength; */
328 0x29, /* u8 bDescriptorType; Hub-descriptor */
329 0x00, /* u8 bNbrPorts; (patched later) */
330 0x0a, /* u16 wHubCharacteristics; */
bb36d470 331 0x00, /* (per-port OC, no power switching) */
92414fdc
FB
332 0x01, /* u8 bPwrOn2pwrGood; 2ms */
333 0x00, /* u8 bHubContrCurrent; 0 mA */
334 0x00, /* u8 DeviceRemovable; *** 7 Ports max *** */
335 0xff /* u8 PortPwrCtrlMask; *** 7 ports max *** */
bb36d470
FB
336};
337
338static void usb_hub_attach(USBPort *port1, USBDevice *dev)
339{
340 USBHubState *s = port1->opaque;
341 USBHubPort *port = &s->ports[port1->index];
342
343 if (dev) {
a594cfbf 344 if (port->port.dev)
bb36d470
FB
345 usb_attach(port1, NULL);
346
347 port->wPortStatus |= PORT_STAT_CONNECTION;
348 port->wPortChange |= PORT_STAT_C_CONNECTION;
349 if (dev->speed == USB_SPEED_LOW)
350 port->wPortStatus |= PORT_STAT_LOW_SPEED;
351 else
352 port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
a594cfbf 353 port->port.dev = dev;
bb36d470 354 } else {
a594cfbf 355 dev = port->port.dev;
bb36d470
FB
356 if (dev) {
357 port->wPortStatus &= ~PORT_STAT_CONNECTION;
358 port->wPortChange |= PORT_STAT_C_CONNECTION;
359 if (port->wPortStatus & PORT_STAT_ENABLE) {
360 port->wPortStatus &= ~PORT_STAT_ENABLE;
361 port->wPortChange |= PORT_STAT_C_ENABLE;
362 }
a594cfbf 363 port->port.dev = NULL;
bb36d470
FB
364 }
365 }
366}
367
368static void usb_hub_handle_reset(USBDevice *dev)
369{
370 /* XXX: do it */
371}
372
373static int usb_hub_handle_control(USBDevice *dev, int request, int value,
374 int index, int length, uint8_t *data)
375{
376 USBHubState *s = (USBHubState *)dev;
377 int ret;
378
379 switch(request) {
380 case DeviceRequest | USB_REQ_GET_STATUS:
381 data[0] = (1 << USB_DEVICE_SELF_POWERED) |
382 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
383 data[1] = 0x00;
384 ret = 2;
385 break;
386 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
387 if (value == USB_DEVICE_REMOTE_WAKEUP) {
388 dev->remote_wakeup = 0;
389 } else {
390 goto fail;
391 }
392 ret = 0;
393 break;
394 case DeviceOutRequest | USB_REQ_SET_FEATURE:
395 if (value == USB_DEVICE_REMOTE_WAKEUP) {
396 dev->remote_wakeup = 1;
397 } else {
398 goto fail;
399 }
400 ret = 0;
401 break;
402 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
403 dev->addr = value;
404 ret = 0;
405 break;
406 case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
407 switch(value >> 8) {
408 case USB_DT_DEVICE:
409 memcpy(data, qemu_hub_dev_descriptor,
410 sizeof(qemu_hub_dev_descriptor));
411 ret = sizeof(qemu_hub_dev_descriptor);
412 break;
413 case USB_DT_CONFIG:
414 memcpy(data, qemu_hub_config_descriptor,
415 sizeof(qemu_hub_config_descriptor));
416 ret = sizeof(qemu_hub_config_descriptor);
417 break;
418 case USB_DT_STRING:
419 switch(value & 0xff) {
420 case 0:
421 /* language ids */
422 data[0] = 4;
423 data[1] = 3;
424 data[2] = 0x09;
425 data[3] = 0x04;
426 ret = 4;
427 break;
428 case 1:
429 /* serial number */
430 ret = set_usb_string(data, "314159");
431 break;
432 case 2:
433 /* product description */
434 ret = set_usb_string(data, "QEMU USB Hub");
435 break;
436 case 3:
437 /* vendor description */
438 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
439 break;
440 default:
441 goto fail;
442 }
443 break;
444 default:
445 goto fail;
446 }
447 break;
448 case DeviceRequest | USB_REQ_GET_CONFIGURATION:
449 data[0] = 1;
450 ret = 1;
451 break;
452 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
453 ret = 0;
454 break;
455 case DeviceRequest | USB_REQ_GET_INTERFACE:
456 data[0] = 0;
457 ret = 1;
458 break;
459 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
460 ret = 0;
461 break;
462 /* usb specific requests */
463 case GetHubStatus:
464 data[0] = 0;
465 data[1] = 0;
466 data[2] = 0;
467 data[3] = 0;
468 ret = 4;
469 break;
470 case GetPortStatus:
471 {
472 unsigned int n = index - 1;
473 USBHubPort *port;
474 if (n >= s->nb_ports)
475 goto fail;
476 port = &s->ports[n];
477 data[0] = port->wPortStatus;
478 data[1] = port->wPortStatus >> 8;
479 data[2] = port->wPortChange;
480 data[3] = port->wPortChange >> 8;
481 ret = 4;
482 }
483 break;
484 case SetHubFeature:
485 case ClearHubFeature:
486 if (value == 0 || value == 1) {
487 } else {
488 goto fail;
489 }
490 ret = 0;
491 break;
492 case SetPortFeature:
493 {
494 unsigned int n = index - 1;
495 USBHubPort *port;
496 USBDevice *dev;
497 if (n >= s->nb_ports)
498 goto fail;
499 port = &s->ports[n];
a594cfbf 500 dev = port->port.dev;
bb36d470
FB
501 switch(value) {
502 case PORT_SUSPEND:
503 port->wPortStatus |= PORT_STAT_SUSPEND;
504 break;
505 case PORT_RESET:
506 if (dev) {
507 dev->handle_packet(dev,
508 USB_MSG_RESET, 0, 0, NULL, 0);
509 port->wPortChange |= PORT_STAT_C_RESET;
510 /* set enable bit */
511 port->wPortChange |= PORT_STAT_C_ENABLE;
512 port->wPortStatus |= PORT_STAT_ENABLE;
513 }
514 break;
515 case PORT_POWER:
516 break;
517 default:
518 goto fail;
519 }
520 ret = 0;
521 }
522 break;
523 case ClearPortFeature:
524 {
525 unsigned int n = index - 1;
526 USBHubPort *port;
527 USBDevice *dev;
528 if (n >= s->nb_ports)
529 goto fail;
530 port = &s->ports[n];
a594cfbf 531 dev = port->port.dev;
bb36d470
FB
532 switch(value) {
533 case PORT_ENABLE:
534 port->wPortStatus &= ~PORT_STAT_ENABLE;
535 break;
536 case PORT_C_ENABLE:
537 port->wPortChange &= ~PORT_STAT_C_ENABLE;
538 break;
539 case PORT_SUSPEND:
540 port->wPortStatus &= ~PORT_STAT_SUSPEND;
541 break;
542 case PORT_C_SUSPEND:
543 port->wPortChange &= ~PORT_STAT_C_SUSPEND;
544 break;
545 case PORT_C_CONNECTION:
546 port->wPortChange &= ~PORT_STAT_C_CONNECTION;
547 break;
548 case PORT_C_OVERCURRENT:
549 port->wPortChange &= ~PORT_STAT_C_OVERCURRENT;
550 break;
551 case PORT_C_RESET:
552 port->wPortChange &= ~PORT_STAT_C_RESET;
553 break;
554 default:
555 goto fail;
556 }
557 ret = 0;
558 }
559 break;
560 case GetHubDescriptor:
561 memcpy(data, qemu_hub_hub_descriptor,
562 sizeof(qemu_hub_hub_descriptor));
563 data[2] = s->nb_ports;
564 ret = sizeof(qemu_hub_hub_descriptor);
565 break;
566 default:
567 fail:
568 ret = USB_RET_STALL;
92414fdc 569 break;
bb36d470
FB
570 }
571 return ret;
572}
573
574static int usb_hub_handle_data(USBDevice *dev, int pid,
575 uint8_t devep, uint8_t *data, int len)
576{
577 USBHubState *s = (USBHubState *)dev;
578 int ret;
579
580 switch(pid) {
581 case USB_TOKEN_IN:
582 if (devep == 1) {
583 USBHubPort *port;
584 unsigned int status;
585 int i, n;
586 n = (s->nb_ports + 1 + 7) / 8;
587 if (n > len)
588 return USB_RET_BABBLE;
589 status = 0;
590 for(i = 0; i < s->nb_ports; i++) {
591 port = &s->ports[i];
592 if (port->wPortChange)
593 status |= (1 << (i + 1));
594 }
595 if (status != 0) {
596 for(i = 0; i < n; i++) {
597 data[i] = status >> (8 * i);
598 }
599 ret = n;
600 } else {
601 ret = 0;
602 }
603 } else {
604 goto fail;
605 }
606 break;
607 case USB_TOKEN_OUT:
608 default:
609 fail:
610 ret = USB_RET_STALL;
611 break;
612 }
613 return ret;
614}
615
616static int usb_hub_broadcast_packet(USBHubState *s, int pid,
617 uint8_t devaddr, uint8_t devep,
618 uint8_t *data, int len)
619{
620 USBHubPort *port;
621 USBDevice *dev;
622 int i, ret;
623
624 for(i = 0; i < s->nb_ports; i++) {
625 port = &s->ports[i];
a594cfbf 626 dev = port->port.dev;
bb36d470
FB
627 if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
628 ret = dev->handle_packet(dev, pid,
629 devaddr, devep,
630 data, len);
631 if (ret != USB_RET_NODEV) {
632 return ret;
633 }
634 }
635 }
636 return USB_RET_NODEV;
637}
638
639static int usb_hub_handle_packet(USBDevice *dev, int pid,
640 uint8_t devaddr, uint8_t devep,
641 uint8_t *data, int len)
642{
643 USBHubState *s = (USBHubState *)dev;
644
645#if defined(DEBUG) && 0
646 printf("usb_hub: pid=0x%x\n", pid);
647#endif
648 if (dev->state == USB_STATE_DEFAULT &&
649 dev->addr != 0 &&
650 devaddr != dev->addr &&
651 (pid == USB_TOKEN_SETUP ||
652 pid == USB_TOKEN_OUT ||
653 pid == USB_TOKEN_IN)) {
654 /* broadcast the packet to the devices */
655 return usb_hub_broadcast_packet(s, pid, devaddr, devep, data, len);
656 }
657 return usb_generic_handle_packet(dev, pid, devaddr, devep, data, len);
658}
659
660USBDevice *usb_hub_init(USBPort **usb_ports, int nb_ports)
661{
662 USBHubState *s;
663 USBHubPort *port;
664 int i;
665
666 if (nb_ports > MAX_PORTS)
667 return NULL;
668 s = qemu_mallocz(sizeof(USBHubState));
669 if (!s)
670 return NULL;
671 s->dev.speed = USB_SPEED_FULL;
672 s->dev.handle_packet = usb_hub_handle_packet;
673
674 /* generic USB device init */
675 s->dev.handle_reset = usb_hub_handle_reset;
676 s->dev.handle_control = usb_hub_handle_control;
677 s->dev.handle_data = usb_hub_handle_data;
678
679 s->nb_ports = nb_ports;
680 for(i = 0; i < s->nb_ports; i++) {
681 port = &s->ports[i];
682 port->wPortStatus = PORT_STAT_POWER;
683 port->wPortChange = 0;
684 port->port.attach = usb_hub_attach;
685 port->port.opaque = s;
686 port->port.index = i;
687 usb_ports[i] = &port->port;
688 }
689 return (USBDevice *)s;
690}