Commit 72899afc5d2a33576094a80d1eba797e293c975a

Authored by bellard
1 parent 56bebe70

separate file for usb hub device


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1848 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
@@ -302,7 +302,7 @@ SOUND_HW += fmopl.o adlib.o @@ -302,7 +302,7 @@ SOUND_HW += fmopl.o adlib.o
302 endif 302 endif
303 303
304 # USB layer 304 # USB layer
305 -VL_OBJS+= usb.o usb-uhci.o usb-linux.o usb-hid.o 305 +VL_OBJS+= usb.o usb-hub.o usb-uhci.o usb-linux.o usb-hid.o
306 306
307 # PCI network cards 307 # PCI network cards
308 VL_OBJS+= ne2000.o rtl8139.o 308 VL_OBJS+= ne2000.o rtl8139.o
hw/usb-hub.c 0 → 100644
  1 +/*
  2 + * QEMU USB HUB 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 +
  26 +//#define DEBUG
  27 +
  28 +#define MAX_PORTS 8
  29 +
  30 +typedef struct USBHubPort {
  31 + USBPort port;
  32 + uint16_t wPortStatus;
  33 + uint16_t wPortChange;
  34 +} USBHubPort;
  35 +
  36 +typedef struct USBHubState {
  37 + USBDevice dev;
  38 + int nb_ports;
  39 + USBHubPort ports[MAX_PORTS];
  40 +} USBHubState;
  41 +
  42 +#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE)
  43 +#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE)
  44 +#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR)
  45 +#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS)
  46 +#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS)
  47 +#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE)
  48 +#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE)
  49 +
  50 +#define PORT_STAT_CONNECTION 0x0001
  51 +#define PORT_STAT_ENABLE 0x0002
  52 +#define PORT_STAT_SUSPEND 0x0004
  53 +#define PORT_STAT_OVERCURRENT 0x0008
  54 +#define PORT_STAT_RESET 0x0010
  55 +#define PORT_STAT_POWER 0x0100
  56 +#define PORT_STAT_LOW_SPEED 0x0200
  57 +#define PORT_STAT_HIGH_SPEED 0x0400
  58 +#define PORT_STAT_TEST 0x0800
  59 +#define PORT_STAT_INDICATOR 0x1000
  60 +
  61 +#define PORT_STAT_C_CONNECTION 0x0001
  62 +#define PORT_STAT_C_ENABLE 0x0002
  63 +#define PORT_STAT_C_SUSPEND 0x0004
  64 +#define PORT_STAT_C_OVERCURRENT 0x0008
  65 +#define PORT_STAT_C_RESET 0x0010
  66 +
  67 +#define PORT_CONNECTION 0
  68 +#define PORT_ENABLE 1
  69 +#define PORT_SUSPEND 2
  70 +#define PORT_OVERCURRENT 3
  71 +#define PORT_RESET 4
  72 +#define PORT_POWER 8
  73 +#define PORT_LOWSPEED 9
  74 +#define PORT_HIGHSPEED 10
  75 +#define PORT_C_CONNECTION 16
  76 +#define PORT_C_ENABLE 17
  77 +#define PORT_C_SUSPEND 18
  78 +#define PORT_C_OVERCURRENT 19
  79 +#define PORT_C_RESET 20
  80 +#define PORT_TEST 21
  81 +#define PORT_INDICATOR 22
  82 +
  83 +/* same as Linux kernel root hubs */
  84 +
  85 +static const uint8_t qemu_hub_dev_descriptor[] = {
  86 + 0x12, /* u8 bLength; */
  87 + 0x01, /* u8 bDescriptorType; Device */
  88 + 0x10, 0x01, /* u16 bcdUSB; v1.1 */
  89 +
  90 + 0x09, /* u8 bDeviceClass; HUB_CLASSCODE */
  91 + 0x00, /* u8 bDeviceSubClass; */
  92 + 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
  93 + 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
  94 +
  95 + 0x00, 0x00, /* u16 idVendor; */
  96 + 0x00, 0x00, /* u16 idProduct; */
  97 + 0x01, 0x01, /* u16 bcdDevice */
  98 +
  99 + 0x03, /* u8 iManufacturer; */
  100 + 0x02, /* u8 iProduct; */
  101 + 0x01, /* u8 iSerialNumber; */
  102 + 0x01 /* u8 bNumConfigurations; */
  103 +};
  104 +
  105 +/* XXX: patch interrupt size */
  106 +static const uint8_t qemu_hub_config_descriptor[] = {
  107 +
  108 + /* one configuration */
  109 + 0x09, /* u8 bLength; */
  110 + 0x02, /* u8 bDescriptorType; Configuration */
  111 + 0x19, 0x00, /* u16 wTotalLength; */
  112 + 0x01, /* u8 bNumInterfaces; (1) */
  113 + 0x01, /* u8 bConfigurationValue; */
  114 + 0x00, /* u8 iConfiguration; */
  115 + 0xc0, /* u8 bmAttributes;
  116 + Bit 7: must be set,
  117 + 6: Self-powered,
  118 + 5: Remote wakeup,
  119 + 4..0: resvd */
  120 + 0x00, /* u8 MaxPower; */
  121 +
  122 + /* USB 1.1:
  123 + * USB 2.0, single TT organization (mandatory):
  124 + * one interface, protocol 0
  125 + *
  126 + * USB 2.0, multiple TT organization (optional):
  127 + * two interfaces, protocols 1 (like single TT)
  128 + * and 2 (multiple TT mode) ... config is
  129 + * sometimes settable
  130 + * NOT IMPLEMENTED
  131 + */
  132 +
  133 + /* one interface */
  134 + 0x09, /* u8 if_bLength; */
  135 + 0x04, /* u8 if_bDescriptorType; Interface */
  136 + 0x00, /* u8 if_bInterfaceNumber; */
  137 + 0x00, /* u8 if_bAlternateSetting; */
  138 + 0x01, /* u8 if_bNumEndpoints; */
  139 + 0x09, /* u8 if_bInterfaceClass; HUB_CLASSCODE */
  140 + 0x00, /* u8 if_bInterfaceSubClass; */
  141 + 0x00, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
  142 + 0x00, /* u8 if_iInterface; */
  143 +
  144 + /* one endpoint (status change endpoint) */
  145 + 0x07, /* u8 ep_bLength; */
  146 + 0x05, /* u8 ep_bDescriptorType; Endpoint */
  147 + 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
  148 + 0x03, /* u8 ep_bmAttributes; Interrupt */
  149 + 0x02, 0x00, /* u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
  150 + 0xff /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
  151 +};
  152 +
  153 +static const uint8_t qemu_hub_hub_descriptor[] =
  154 +{
  155 + 0x09, /* u8 bLength; */
  156 + 0x29, /* u8 bDescriptorType; Hub-descriptor */
  157 + 0x00, /* u8 bNbrPorts; (patched later) */
  158 + 0x0a, /* u16 wHubCharacteristics; */
  159 + 0x00, /* (per-port OC, no power switching) */
  160 + 0x01, /* u8 bPwrOn2pwrGood; 2ms */
  161 + 0x00, /* u8 bHubContrCurrent; 0 mA */
  162 + 0x00, /* u8 DeviceRemovable; *** 7 Ports max *** */
  163 + 0xff /* u8 PortPwrCtrlMask; *** 7 ports max *** */
  164 +};
  165 +
  166 +static void usb_hub_attach(USBPort *port1, USBDevice *dev)
  167 +{
  168 + USBHubState *s = port1->opaque;
  169 + USBHubPort *port = &s->ports[port1->index];
  170 +
  171 + if (dev) {
  172 + if (port->port.dev)
  173 + usb_attach(port1, NULL);
  174 +
  175 + port->wPortStatus |= PORT_STAT_CONNECTION;
  176 + port->wPortChange |= PORT_STAT_C_CONNECTION;
  177 + if (dev->speed == USB_SPEED_LOW)
  178 + port->wPortStatus |= PORT_STAT_LOW_SPEED;
  179 + else
  180 + port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
  181 + port->port.dev = dev;
  182 + } else {
  183 + dev = port->port.dev;
  184 + if (dev) {
  185 + port->wPortStatus &= ~PORT_STAT_CONNECTION;
  186 + port->wPortChange |= PORT_STAT_C_CONNECTION;
  187 + if (port->wPortStatus & PORT_STAT_ENABLE) {
  188 + port->wPortStatus &= ~PORT_STAT_ENABLE;
  189 + port->wPortChange |= PORT_STAT_C_ENABLE;
  190 + }
  191 + port->port.dev = NULL;
  192 + }
  193 + }
  194 +}
  195 +
  196 +static void usb_hub_handle_reset(USBDevice *dev)
  197 +{
  198 + /* XXX: do it */
  199 +}
  200 +
  201 +static int usb_hub_handle_control(USBDevice *dev, int request, int value,
  202 + int index, int length, uint8_t *data)
  203 +{
  204 + USBHubState *s = (USBHubState *)dev;
  205 + int ret;
  206 +
  207 + switch(request) {
  208 + case DeviceRequest | USB_REQ_GET_STATUS:
  209 + data[0] = (1 << USB_DEVICE_SELF_POWERED) |
  210 + (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
  211 + data[1] = 0x00;
  212 + ret = 2;
  213 + break;
  214 + case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
  215 + if (value == USB_DEVICE_REMOTE_WAKEUP) {
  216 + dev->remote_wakeup = 0;
  217 + } else {
  218 + goto fail;
  219 + }
  220 + ret = 0;
  221 + break;
  222 + case DeviceOutRequest | USB_REQ_SET_FEATURE:
  223 + if (value == USB_DEVICE_REMOTE_WAKEUP) {
  224 + dev->remote_wakeup = 1;
  225 + } else {
  226 + goto fail;
  227 + }
  228 + ret = 0;
  229 + break;
  230 + case DeviceOutRequest | USB_REQ_SET_ADDRESS:
  231 + dev->addr = value;
  232 + ret = 0;
  233 + break;
  234 + case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
  235 + switch(value >> 8) {
  236 + case USB_DT_DEVICE:
  237 + memcpy(data, qemu_hub_dev_descriptor,
  238 + sizeof(qemu_hub_dev_descriptor));
  239 + ret = sizeof(qemu_hub_dev_descriptor);
  240 + break;
  241 + case USB_DT_CONFIG:
  242 + memcpy(data, qemu_hub_config_descriptor,
  243 + sizeof(qemu_hub_config_descriptor));
  244 + ret = sizeof(qemu_hub_config_descriptor);
  245 + break;
  246 + case USB_DT_STRING:
  247 + switch(value & 0xff) {
  248 + case 0:
  249 + /* language ids */
  250 + data[0] = 4;
  251 + data[1] = 3;
  252 + data[2] = 0x09;
  253 + data[3] = 0x04;
  254 + ret = 4;
  255 + break;
  256 + case 1:
  257 + /* serial number */
  258 + ret = set_usb_string(data, "314159");
  259 + break;
  260 + case 2:
  261 + /* product description */
  262 + ret = set_usb_string(data, "QEMU USB Hub");
  263 + break;
  264 + case 3:
  265 + /* vendor description */
  266 + ret = set_usb_string(data, "QEMU " QEMU_VERSION);
  267 + break;
  268 + default:
  269 + goto fail;
  270 + }
  271 + break;
  272 + default:
  273 + goto fail;
  274 + }
  275 + break;
  276 + case DeviceRequest | USB_REQ_GET_CONFIGURATION:
  277 + data[0] = 1;
  278 + ret = 1;
  279 + break;
  280 + case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
  281 + ret = 0;
  282 + break;
  283 + case DeviceRequest | USB_REQ_GET_INTERFACE:
  284 + data[0] = 0;
  285 + ret = 1;
  286 + break;
  287 + case DeviceOutRequest | USB_REQ_SET_INTERFACE:
  288 + ret = 0;
  289 + break;
  290 + /* usb specific requests */
  291 + case GetHubStatus:
  292 + data[0] = 0;
  293 + data[1] = 0;
  294 + data[2] = 0;
  295 + data[3] = 0;
  296 + ret = 4;
  297 + break;
  298 + case GetPortStatus:
  299 + {
  300 + unsigned int n = index - 1;
  301 + USBHubPort *port;
  302 + if (n >= s->nb_ports)
  303 + goto fail;
  304 + port = &s->ports[n];
  305 + data[0] = port->wPortStatus;
  306 + data[1] = port->wPortStatus >> 8;
  307 + data[2] = port->wPortChange;
  308 + data[3] = port->wPortChange >> 8;
  309 + ret = 4;
  310 + }
  311 + break;
  312 + case SetHubFeature:
  313 + case ClearHubFeature:
  314 + if (value == 0 || value == 1) {
  315 + } else {
  316 + goto fail;
  317 + }
  318 + ret = 0;
  319 + break;
  320 + case SetPortFeature:
  321 + {
  322 + unsigned int n = index - 1;
  323 + USBHubPort *port;
  324 + USBDevice *dev;
  325 + if (n >= s->nb_ports)
  326 + goto fail;
  327 + port = &s->ports[n];
  328 + dev = port->port.dev;
  329 + switch(value) {
  330 + case PORT_SUSPEND:
  331 + port->wPortStatus |= PORT_STAT_SUSPEND;
  332 + break;
  333 + case PORT_RESET:
  334 + if (dev) {
  335 + dev->handle_packet(dev,
  336 + USB_MSG_RESET, 0, 0, NULL, 0);
  337 + port->wPortChange |= PORT_STAT_C_RESET;
  338 + /* set enable bit */
  339 + port->wPortChange |= PORT_STAT_C_ENABLE;
  340 + port->wPortStatus |= PORT_STAT_ENABLE;
  341 + }
  342 + break;
  343 + case PORT_POWER:
  344 + break;
  345 + default:
  346 + goto fail;
  347 + }
  348 + ret = 0;
  349 + }
  350 + break;
  351 + case ClearPortFeature:
  352 + {
  353 + unsigned int n = index - 1;
  354 + USBHubPort *port;
  355 + USBDevice *dev;
  356 + if (n >= s->nb_ports)
  357 + goto fail;
  358 + port = &s->ports[n];
  359 + dev = port->port.dev;
  360 + switch(value) {
  361 + case PORT_ENABLE:
  362 + port->wPortStatus &= ~PORT_STAT_ENABLE;
  363 + break;
  364 + case PORT_C_ENABLE:
  365 + port->wPortChange &= ~PORT_STAT_C_ENABLE;
  366 + break;
  367 + case PORT_SUSPEND:
  368 + port->wPortStatus &= ~PORT_STAT_SUSPEND;
  369 + break;
  370 + case PORT_C_SUSPEND:
  371 + port->wPortChange &= ~PORT_STAT_C_SUSPEND;
  372 + break;
  373 + case PORT_C_CONNECTION:
  374 + port->wPortChange &= ~PORT_STAT_C_CONNECTION;
  375 + break;
  376 + case PORT_C_OVERCURRENT:
  377 + port->wPortChange &= ~PORT_STAT_C_OVERCURRENT;
  378 + break;
  379 + case PORT_C_RESET:
  380 + port->wPortChange &= ~PORT_STAT_C_RESET;
  381 + break;
  382 + default:
  383 + goto fail;
  384 + }
  385 + ret = 0;
  386 + }
  387 + break;
  388 + case GetHubDescriptor:
  389 + memcpy(data, qemu_hub_hub_descriptor,
  390 + sizeof(qemu_hub_hub_descriptor));
  391 + data[2] = s->nb_ports;
  392 + ret = sizeof(qemu_hub_hub_descriptor);
  393 + break;
  394 + default:
  395 + fail:
  396 + ret = USB_RET_STALL;
  397 + break;
  398 + }
  399 + return ret;
  400 +}
  401 +
  402 +static int usb_hub_handle_data(USBDevice *dev, int pid,
  403 + uint8_t devep, uint8_t *data, int len)
  404 +{
  405 + USBHubState *s = (USBHubState *)dev;
  406 + int ret;
  407 +
  408 + switch(pid) {
  409 + case USB_TOKEN_IN:
  410 + if (devep == 1) {
  411 + USBHubPort *port;
  412 + unsigned int status;
  413 + int i, n;
  414 + n = (s->nb_ports + 1 + 7) / 8;
  415 + if (n > len)
  416 + return USB_RET_BABBLE;
  417 + status = 0;
  418 + for(i = 0; i < s->nb_ports; i++) {
  419 + port = &s->ports[i];
  420 + if (port->wPortChange)
  421 + status |= (1 << (i + 1));
  422 + }
  423 + if (status != 0) {
  424 + for(i = 0; i < n; i++) {
  425 + data[i] = status >> (8 * i);
  426 + }
  427 + ret = n;
  428 + } else {
  429 + ret = 0;
  430 + }
  431 + } else {
  432 + goto fail;
  433 + }
  434 + break;
  435 + case USB_TOKEN_OUT:
  436 + default:
  437 + fail:
  438 + ret = USB_RET_STALL;
  439 + break;
  440 + }
  441 + return ret;
  442 +}
  443 +
  444 +static int usb_hub_broadcast_packet(USBHubState *s, int pid,
  445 + uint8_t devaddr, uint8_t devep,
  446 + uint8_t *data, int len)
  447 +{
  448 + USBHubPort *port;
  449 + USBDevice *dev;
  450 + int i, ret;
  451 +
  452 + for(i = 0; i < s->nb_ports; i++) {
  453 + port = &s->ports[i];
  454 + dev = port->port.dev;
  455 + if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
  456 + ret = dev->handle_packet(dev, pid,
  457 + devaddr, devep,
  458 + data, len);
  459 + if (ret != USB_RET_NODEV) {
  460 + return ret;
  461 + }
  462 + }
  463 + }
  464 + return USB_RET_NODEV;
  465 +}
  466 +
  467 +static int usb_hub_handle_packet(USBDevice *dev, int pid,
  468 + uint8_t devaddr, uint8_t devep,
  469 + uint8_t *data, int len)
  470 +{
  471 + USBHubState *s = (USBHubState *)dev;
  472 +
  473 +#if defined(DEBUG) && 0
  474 + printf("usb_hub: pid=0x%x\n", pid);
  475 +#endif
  476 + if (dev->state == USB_STATE_DEFAULT &&
  477 + dev->addr != 0 &&
  478 + devaddr != dev->addr &&
  479 + (pid == USB_TOKEN_SETUP ||
  480 + pid == USB_TOKEN_OUT ||
  481 + pid == USB_TOKEN_IN)) {
  482 + /* broadcast the packet to the devices */
  483 + return usb_hub_broadcast_packet(s, pid, devaddr, devep, data, len);
  484 + }
  485 + return usb_generic_handle_packet(dev, pid, devaddr, devep, data, len);
  486 +}
  487 +
  488 +USBDevice *usb_hub_init(USBPort **usb_ports, int nb_ports)
  489 +{
  490 + USBHubState *s;
  491 + USBHubPort *port;
  492 + int i;
  493 +
  494 + if (nb_ports > MAX_PORTS)
  495 + return NULL;
  496 + s = qemu_mallocz(sizeof(USBHubState));
  497 + if (!s)
  498 + return NULL;
  499 + s->dev.speed = USB_SPEED_FULL;
  500 + s->dev.handle_packet = usb_hub_handle_packet;
  501 +
  502 + /* generic USB device init */
  503 + s->dev.handle_reset = usb_hub_handle_reset;
  504 + s->dev.handle_control = usb_hub_handle_control;
  505 + s->dev.handle_data = usb_hub_handle_data;
  506 +
  507 + s->nb_ports = nb_ports;
  508 + for(i = 0; i < s->nb_ports; i++) {
  509 + port = &s->ports[i];
  510 + port->wPortStatus = PORT_STAT_POWER;
  511 + port->wPortChange = 0;
  512 + port->port.attach = usb_hub_attach;
  513 + port->port.opaque = s;
  514 + port->port.index = i;
  515 + usb_ports[i] = &port->port;
  516 + }
  517 + return (USBDevice *)s;
  518 +}
hw/usb.c
@@ -191,500 +191,3 @@ int set_usb_string(uint8_t *buf, const char *str) @@ -191,500 +191,3 @@ int set_usb_string(uint8_t *buf, const char *str)
191 } 191 }
192 return q - buf; 192 return q - buf;
193 } 193 }
194 -  
195 -/**********************/  
196 -/* USB hub emulation */  
197 -  
198 -//#define DEBUG  
199 -  
200 -#define MAX_PORTS 8  
201 -  
202 -typedef struct USBHubPort {  
203 - USBPort port;  
204 - uint16_t wPortStatus;  
205 - uint16_t wPortChange;  
206 -} USBHubPort;  
207 -  
208 -typedef 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 -  
257 -static const uint8_t qemu_hub_dev_descriptor[] = {  
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; */  
275 -};  
276 -  
277 -/* XXX: patch interrupt size */  
278 -static const uint8_t qemu_hub_config_descriptor[] = {  
279 -  
280 - /* one configuration */  
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;  
288 - Bit 7: must be set,  
289 - 6: Self-powered,  
290 - 5: Remote wakeup,  
291 - 4..0: resvd */  
292 - 0x00, /* u8 MaxPower; */  
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 */  
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; */  
315 -  
316 - /* one endpoint (status change endpoint) */  
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) */  
323 -};  
324 -  
325 -static const uint8_t qemu_hub_hub_descriptor[] =  
326 -{  
327 - 0x09, /* u8 bLength; */  
328 - 0x29, /* u8 bDescriptorType; Hub-descriptor */  
329 - 0x00, /* u8 bNbrPorts; (patched later) */  
330 - 0x0a, /* u16 wHubCharacteristics; */  
331 - 0x00, /* (per-port OC, no power switching) */  
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 *** */  
336 -};  
337 -  
338 -static 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) {  
344 - if (port->port.dev)  
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;  
353 - port->port.dev = dev;  
354 - } else {  
355 - dev = port->port.dev;  
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 - }  
363 - port->port.dev = NULL;  
364 - }  
365 - }  
366 -}  
367 -  
368 -static void usb_hub_handle_reset(USBDevice *dev)  
369 -{  
370 - /* XXX: do it */  
371 -}  
372 -  
373 -static 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];  
500 - dev = port->port.dev;  
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];  
531 - dev = port->port.dev;  
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;  
569 - break;  
570 - }  
571 - return ret;  
572 -}  
573 -  
574 -static 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 -  
616 -static 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];  
626 - dev = port->port.dev;  
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 -  
639 -static 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 -  
660 -USBDevice *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 -}