Annotation of qemu/hw/usb/dev-hub.c, revision 1.1.1.1

1.1       root        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 "qemu-common.h"
                     25: #include "trace.h"
                     26: #include "hw/usb.h"
                     27: #include "hw/usb/desc.h"
                     28: 
                     29: #define NUM_PORTS 8
                     30: 
                     31: typedef struct USBHubPort {
                     32:     USBPort port;
                     33:     uint16_t wPortStatus;
                     34:     uint16_t wPortChange;
                     35: } USBHubPort;
                     36: 
                     37: typedef struct USBHubState {
                     38:     USBDevice dev;
                     39:     USBEndpoint *intr;
                     40:     USBHubPort ports[NUM_PORTS];
                     41: } USBHubState;
                     42: 
                     43: #define ClearHubFeature                (0x2000 | USB_REQ_CLEAR_FEATURE)
                     44: #define ClearPortFeature       (0x2300 | USB_REQ_CLEAR_FEATURE)
                     45: #define GetHubDescriptor       (0xa000 | USB_REQ_GET_DESCRIPTOR)
                     46: #define GetHubStatus           (0xa000 | USB_REQ_GET_STATUS)
                     47: #define GetPortStatus          (0xa300 | USB_REQ_GET_STATUS)
                     48: #define SetHubFeature          (0x2000 | USB_REQ_SET_FEATURE)
                     49: #define SetPortFeature         (0x2300 | USB_REQ_SET_FEATURE)
                     50: 
                     51: #define PORT_STAT_CONNECTION   0x0001
                     52: #define PORT_STAT_ENABLE       0x0002
                     53: #define PORT_STAT_SUSPEND      0x0004
                     54: #define PORT_STAT_OVERCURRENT  0x0008
                     55: #define PORT_STAT_RESET                0x0010
                     56: #define PORT_STAT_POWER                0x0100
                     57: #define PORT_STAT_LOW_SPEED    0x0200
                     58: #define PORT_STAT_HIGH_SPEED    0x0400
                     59: #define PORT_STAT_TEST          0x0800
                     60: #define PORT_STAT_INDICATOR     0x1000
                     61: 
                     62: #define PORT_STAT_C_CONNECTION 0x0001
                     63: #define PORT_STAT_C_ENABLE     0x0002
                     64: #define PORT_STAT_C_SUSPEND    0x0004
                     65: #define PORT_STAT_C_OVERCURRENT        0x0008
                     66: #define PORT_STAT_C_RESET      0x0010
                     67: 
                     68: #define PORT_CONNECTION                0
                     69: #define PORT_ENABLE            1
                     70: #define PORT_SUSPEND           2
                     71: #define PORT_OVERCURRENT       3
                     72: #define PORT_RESET             4
                     73: #define PORT_POWER             8
                     74: #define PORT_LOWSPEED          9
                     75: #define PORT_HIGHSPEED         10
                     76: #define PORT_C_CONNECTION      16
                     77: #define PORT_C_ENABLE          17
                     78: #define PORT_C_SUSPEND         18
                     79: #define PORT_C_OVERCURRENT     19
                     80: #define PORT_C_RESET           20
                     81: #define PORT_TEST               21
                     82: #define PORT_INDICATOR          22
                     83: 
                     84: /* same as Linux kernel root hubs */
                     85: 
                     86: enum {
                     87:     STR_MANUFACTURER = 1,
                     88:     STR_PRODUCT,
                     89:     STR_SERIALNUMBER,
                     90: };
                     91: 
                     92: static const USBDescStrings desc_strings = {
                     93:     [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
                     94:     [STR_PRODUCT]      = "QEMU USB Hub",
                     95:     [STR_SERIALNUMBER] = "314159",
                     96: };
                     97: 
                     98: static const USBDescIface desc_iface_hub = {
                     99:     .bInterfaceNumber              = 0,
                    100:     .bNumEndpoints                 = 1,
                    101:     .bInterfaceClass               = USB_CLASS_HUB,
                    102:     .eps = (USBDescEndpoint[]) {
                    103:         {
                    104:             .bEndpointAddress      = USB_DIR_IN | 0x01,
                    105:             .bmAttributes          = USB_ENDPOINT_XFER_INT,
                    106:             .wMaxPacketSize        = 1 + (NUM_PORTS + 7) / 8,
                    107:             .bInterval             = 0xff,
                    108:         },
                    109:     }
                    110: };
                    111: 
                    112: static const USBDescDevice desc_device_hub = {
                    113:     .bcdUSB                        = 0x0110,
                    114:     .bDeviceClass                  = USB_CLASS_HUB,
                    115:     .bMaxPacketSize0               = 8,
                    116:     .bNumConfigurations            = 1,
                    117:     .confs = (USBDescConfig[]) {
                    118:         {
                    119:             .bNumInterfaces        = 1,
                    120:             .bConfigurationValue   = 1,
                    121:             .bmAttributes          = 0xe0,
                    122:             .nif = 1,
                    123:             .ifs = &desc_iface_hub,
                    124:         },
                    125:     },
                    126: };
                    127: 
                    128: static const USBDesc desc_hub = {
                    129:     .id = {
                    130:         .idVendor          = 0x0409,
                    131:         .idProduct         = 0x55aa,
                    132:         .bcdDevice         = 0x0101,
                    133:         .iManufacturer     = STR_MANUFACTURER,
                    134:         .iProduct          = STR_PRODUCT,
                    135:         .iSerialNumber     = STR_SERIALNUMBER,
                    136:     },
                    137:     .full = &desc_device_hub,
                    138:     .str  = desc_strings,
                    139: };
                    140: 
                    141: static const uint8_t qemu_hub_hub_descriptor[] =
                    142: {
                    143:        0x00,                   /*  u8  bLength; patched in later */
                    144:        0x29,                   /*  u8  bDescriptorType; Hub-descriptor */
                    145:        0x00,                   /*  u8  bNbrPorts; (patched later) */
                    146:        0x0a,                   /* u16  wHubCharacteristics; */
                    147:        0x00,                   /*   (per-port OC, no power switching) */
                    148:        0x01,                   /*  u8  bPwrOn2pwrGood; 2ms */
                    149:        0x00                    /*  u8  bHubContrCurrent; 0 mA */
                    150: 
                    151:         /* DeviceRemovable and PortPwrCtrlMask patched in later */
                    152: };
                    153: 
                    154: static void usb_hub_attach(USBPort *port1)
                    155: {
                    156:     USBHubState *s = port1->opaque;
                    157:     USBHubPort *port = &s->ports[port1->index];
                    158: 
                    159:     trace_usb_hub_attach(s->dev.addr, port1->index + 1);
                    160:     port->wPortStatus |= PORT_STAT_CONNECTION;
                    161:     port->wPortChange |= PORT_STAT_C_CONNECTION;
                    162:     if (port->port.dev->speed == USB_SPEED_LOW) {
                    163:         port->wPortStatus |= PORT_STAT_LOW_SPEED;
                    164:     } else {
                    165:         port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
                    166:     }
                    167:     usb_wakeup(s->intr);
                    168: }
                    169: 
                    170: static void usb_hub_detach(USBPort *port1)
                    171: {
                    172:     USBHubState *s = port1->opaque;
                    173:     USBHubPort *port = &s->ports[port1->index];
                    174: 
                    175:     trace_usb_hub_detach(s->dev.addr, port1->index + 1);
                    176:     usb_wakeup(s->intr);
                    177: 
                    178:     /* Let upstream know the device on this port is gone */
                    179:     s->dev.port->ops->child_detach(s->dev.port, port1->dev);
                    180: 
                    181:     port->wPortStatus &= ~PORT_STAT_CONNECTION;
                    182:     port->wPortChange |= PORT_STAT_C_CONNECTION;
                    183:     if (port->wPortStatus & PORT_STAT_ENABLE) {
                    184:         port->wPortStatus &= ~PORT_STAT_ENABLE;
                    185:         port->wPortChange |= PORT_STAT_C_ENABLE;
                    186:     }
                    187: }
                    188: 
                    189: static void usb_hub_child_detach(USBPort *port1, USBDevice *child)
                    190: {
                    191:     USBHubState *s = port1->opaque;
                    192: 
                    193:     /* Pass along upstream */
                    194:     s->dev.port->ops->child_detach(s->dev.port, child);
                    195: }
                    196: 
                    197: static void usb_hub_wakeup(USBPort *port1)
                    198: {
                    199:     USBHubState *s = port1->opaque;
                    200:     USBHubPort *port = &s->ports[port1->index];
                    201: 
                    202:     if (port->wPortStatus & PORT_STAT_SUSPEND) {
                    203:         port->wPortChange |= PORT_STAT_C_SUSPEND;
                    204:         usb_wakeup(s->intr);
                    205:     }
                    206: }
                    207: 
                    208: static void usb_hub_complete(USBPort *port, USBPacket *packet)
                    209: {
                    210:     USBHubState *s = port->opaque;
                    211: 
                    212:     /*
                    213:      * Just pass it along upstream for now.
                    214:      *
                    215:      * If we ever implement usb 2.0 split transactions this will
                    216:      * become a little more complicated ...
                    217:      *
                    218:      * Can't use usb_packet_complete() here because packet->owner is
                    219:      * cleared already, go call the ->complete() callback directly
                    220:      * instead.
                    221:      */
                    222:     s->dev.port->ops->complete(s->dev.port, packet);
                    223: }
                    224: 
                    225: static USBDevice *usb_hub_find_device(USBDevice *dev, uint8_t addr)
                    226: {
                    227:     USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
                    228:     USBHubPort *port;
                    229:     USBDevice *downstream;
                    230:     int i;
                    231: 
                    232:     for (i = 0; i < NUM_PORTS; i++) {
                    233:         port = &s->ports[i];
                    234:         if (!(port->wPortStatus & PORT_STAT_ENABLE)) {
                    235:             continue;
                    236:         }
                    237:         downstream = usb_find_device(&port->port, addr);
                    238:         if (downstream != NULL) {
                    239:             return downstream;
                    240:         }
                    241:     }
                    242:     return NULL;
                    243: }
                    244: 
                    245: static void usb_hub_handle_reset(USBDevice *dev)
                    246: {
                    247:     USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
                    248:     USBHubPort *port;
                    249:     int i;
                    250: 
                    251:     trace_usb_hub_reset(s->dev.addr);
                    252:     for (i = 0; i < NUM_PORTS; i++) {
                    253:         port = s->ports + i;
                    254:         port->wPortStatus = PORT_STAT_POWER;
                    255:         port->wPortChange = 0;
                    256:         if (port->port.dev && port->port.dev->attached) {
                    257:             port->wPortStatus |= PORT_STAT_CONNECTION;
                    258:             port->wPortChange |= PORT_STAT_C_CONNECTION;
                    259:             if (port->port.dev->speed == USB_SPEED_LOW) {
                    260:                 port->wPortStatus |= PORT_STAT_LOW_SPEED;
                    261:             }
                    262:         }
                    263:     }
                    264: }
                    265: 
                    266: static const char *feature_name(int feature)
                    267: {
                    268:     static const char *name[] = {
                    269:         [PORT_CONNECTION]    = "connection",
                    270:         [PORT_ENABLE]        = "enable",
                    271:         [PORT_SUSPEND]       = "suspend",
                    272:         [PORT_OVERCURRENT]   = "overcurrent",
                    273:         [PORT_RESET]         = "reset",
                    274:         [PORT_POWER]         = "power",
                    275:         [PORT_LOWSPEED]      = "lowspeed",
                    276:         [PORT_HIGHSPEED]     = "highspeed",
                    277:         [PORT_C_CONNECTION]  = "change connection",
                    278:         [PORT_C_ENABLE]      = "change enable",
                    279:         [PORT_C_SUSPEND]     = "change suspend",
                    280:         [PORT_C_OVERCURRENT] = "change overcurrent",
                    281:         [PORT_C_RESET]       = "change reset",
                    282:         [PORT_TEST]          = "test",
                    283:         [PORT_INDICATOR]     = "indicator",
                    284:     };
                    285:     if (feature < 0 || feature >= ARRAY_SIZE(name)) {
                    286:         return "?";
                    287:     }
                    288:     return name[feature] ?: "?";
                    289: }
                    290: 
                    291: static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
                    292:                int request, int value, int index, int length, uint8_t *data)
                    293: {
                    294:     USBHubState *s = (USBHubState *)dev;
                    295:     int ret;
                    296: 
                    297:     trace_usb_hub_control(s->dev.addr, request, value, index, length);
                    298: 
                    299:     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
                    300:     if (ret >= 0) {
                    301:         return ret;
                    302:     }
                    303: 
                    304:     switch(request) {
                    305:     case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
                    306:         if (value == 0 && index != 0x81) { /* clear ep halt */
                    307:             goto fail;
                    308:         }
                    309:         ret = 0;
                    310:         break;
                    311:         /* usb specific requests */
                    312:     case GetHubStatus:
                    313:         data[0] = 0;
                    314:         data[1] = 0;
                    315:         data[2] = 0;
                    316:         data[3] = 0;
                    317:         ret = 4;
                    318:         break;
                    319:     case GetPortStatus:
                    320:         {
                    321:             unsigned int n = index - 1;
                    322:             USBHubPort *port;
                    323:             if (n >= NUM_PORTS) {
                    324:                 goto fail;
                    325:             }
                    326:             port = &s->ports[n];
                    327:             trace_usb_hub_get_port_status(s->dev.addr, index,
                    328:                                           port->wPortStatus,
                    329:                                           port->wPortChange);
                    330:             data[0] = port->wPortStatus;
                    331:             data[1] = port->wPortStatus >> 8;
                    332:             data[2] = port->wPortChange;
                    333:             data[3] = port->wPortChange >> 8;
                    334:             ret = 4;
                    335:         }
                    336:         break;
                    337:     case SetHubFeature:
                    338:     case ClearHubFeature:
                    339:         if (value == 0 || value == 1) {
                    340:         } else {
                    341:             goto fail;
                    342:         }
                    343:         ret = 0;
                    344:         break;
                    345:     case SetPortFeature:
                    346:         {
                    347:             unsigned int n = index - 1;
                    348:             USBHubPort *port;
                    349:             USBDevice *dev;
                    350: 
                    351:             trace_usb_hub_set_port_feature(s->dev.addr, index,
                    352:                                            feature_name(value));
                    353: 
                    354:             if (n >= NUM_PORTS) {
                    355:                 goto fail;
                    356:             }
                    357:             port = &s->ports[n];
                    358:             dev = port->port.dev;
                    359:             switch(value) {
                    360:             case PORT_SUSPEND:
                    361:                 port->wPortStatus |= PORT_STAT_SUSPEND;
                    362:                 break;
                    363:             case PORT_RESET:
                    364:                 if (dev && dev->attached) {
                    365:                     usb_device_reset(dev);
                    366:                     port->wPortChange |= PORT_STAT_C_RESET;
                    367:                     /* set enable bit */
                    368:                     port->wPortStatus |= PORT_STAT_ENABLE;
                    369:                 }
                    370:                 break;
                    371:             case PORT_POWER:
                    372:                 break;
                    373:             default:
                    374:                 goto fail;
                    375:             }
                    376:             ret = 0;
                    377:         }
                    378:         break;
                    379:     case ClearPortFeature:
                    380:         {
                    381:             unsigned int n = index - 1;
                    382:             USBHubPort *port;
                    383: 
                    384:             trace_usb_hub_clear_port_feature(s->dev.addr, index,
                    385:                                              feature_name(value));
                    386: 
                    387:             if (n >= NUM_PORTS) {
                    388:                 goto fail;
                    389:             }
                    390:             port = &s->ports[n];
                    391:             switch(value) {
                    392:             case PORT_ENABLE:
                    393:                 port->wPortStatus &= ~PORT_STAT_ENABLE;
                    394:                 break;
                    395:             case PORT_C_ENABLE:
                    396:                 port->wPortChange &= ~PORT_STAT_C_ENABLE;
                    397:                 break;
                    398:             case PORT_SUSPEND:
                    399:                 port->wPortStatus &= ~PORT_STAT_SUSPEND;
                    400:                 break;
                    401:             case PORT_C_SUSPEND:
                    402:                 port->wPortChange &= ~PORT_STAT_C_SUSPEND;
                    403:                 break;
                    404:             case PORT_C_CONNECTION:
                    405:                 port->wPortChange &= ~PORT_STAT_C_CONNECTION;
                    406:                 break;
                    407:             case PORT_C_OVERCURRENT:
                    408:                 port->wPortChange &= ~PORT_STAT_C_OVERCURRENT;
                    409:                 break;
                    410:             case PORT_C_RESET:
                    411:                 port->wPortChange &= ~PORT_STAT_C_RESET;
                    412:                 break;
                    413:             default:
                    414:                 goto fail;
                    415:             }
                    416:             ret = 0;
                    417:         }
                    418:         break;
                    419:     case GetHubDescriptor:
                    420:         {
                    421:             unsigned int n, limit, var_hub_size = 0;
                    422:             memcpy(data, qemu_hub_hub_descriptor,
                    423:                    sizeof(qemu_hub_hub_descriptor));
                    424:             data[2] = NUM_PORTS;
                    425: 
                    426:             /* fill DeviceRemovable bits */
                    427:             limit = ((NUM_PORTS + 1 + 7) / 8) + 7;
                    428:             for (n = 7; n < limit; n++) {
                    429:                 data[n] = 0x00;
                    430:                 var_hub_size++;
                    431:             }
                    432: 
                    433:             /* fill PortPwrCtrlMask bits */
                    434:             limit = limit + ((NUM_PORTS + 7) / 8);
                    435:             for (;n < limit; n++) {
                    436:                 data[n] = 0xff;
                    437:                 var_hub_size++;
                    438:             }
                    439: 
                    440:             ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size;
                    441:             data[0] = ret;
                    442:             break;
                    443:         }
                    444:     default:
                    445:     fail:
                    446:         ret = USB_RET_STALL;
                    447:         break;
                    448:     }
                    449:     return ret;
                    450: }
                    451: 
                    452: static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
                    453: {
                    454:     USBHubState *s = (USBHubState *)dev;
                    455:     int ret;
                    456: 
                    457:     switch(p->pid) {
                    458:     case USB_TOKEN_IN:
                    459:         if (p->ep->nr == 1) {
                    460:             USBHubPort *port;
                    461:             unsigned int status;
                    462:             uint8_t buf[4];
                    463:             int i, n;
                    464:             n = (NUM_PORTS + 1 + 7) / 8;
                    465:             if (p->iov.size == 1) { /* FreeBSD workaround */
                    466:                 n = 1;
                    467:             } else if (n > p->iov.size) {
                    468:                 return USB_RET_BABBLE;
                    469:             }
                    470:             status = 0;
                    471:             for(i = 0; i < NUM_PORTS; i++) {
                    472:                 port = &s->ports[i];
                    473:                 if (port->wPortChange)
                    474:                     status |= (1 << (i + 1));
                    475:             }
                    476:             if (status != 0) {
                    477:                 for(i = 0; i < n; i++) {
                    478:                     buf[i] = status >> (8 * i);
                    479:                 }
                    480:                 usb_packet_copy(p, buf, n);
                    481:                 ret = n;
                    482:             } else {
                    483:                 ret = USB_RET_NAK; /* usb11 11.13.1 */
                    484:             }
                    485:         } else {
                    486:             goto fail;
                    487:         }
                    488:         break;
                    489:     case USB_TOKEN_OUT:
                    490:     default:
                    491:     fail:
                    492:         ret = USB_RET_STALL;
                    493:         break;
                    494:     }
                    495:     return ret;
                    496: }
                    497: 
                    498: static void usb_hub_handle_destroy(USBDevice *dev)
                    499: {
                    500:     USBHubState *s = (USBHubState *)dev;
                    501:     int i;
                    502: 
                    503:     for (i = 0; i < NUM_PORTS; i++) {
                    504:         usb_unregister_port(usb_bus_from_device(dev),
                    505:                             &s->ports[i].port);
                    506:     }
                    507: }
                    508: 
                    509: static USBPortOps usb_hub_port_ops = {
                    510:     .attach = usb_hub_attach,
                    511:     .detach = usb_hub_detach,
                    512:     .child_detach = usb_hub_child_detach,
                    513:     .wakeup = usb_hub_wakeup,
                    514:     .complete = usb_hub_complete,
                    515: };
                    516: 
                    517: static int usb_hub_initfn(USBDevice *dev)
                    518: {
                    519:     USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
                    520:     USBHubPort *port;
                    521:     int i;
                    522: 
                    523:     usb_desc_create_serial(dev);
                    524:     usb_desc_init(dev);
                    525:     s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
                    526:     for (i = 0; i < NUM_PORTS; i++) {
                    527:         port = &s->ports[i];
                    528:         usb_register_port(usb_bus_from_device(dev),
                    529:                           &port->port, s, i, &usb_hub_port_ops,
                    530:                           USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
                    531:         usb_port_location(&port->port, dev->port, i+1);
                    532:     }
                    533:     usb_hub_handle_reset(dev);
                    534:     return 0;
                    535: }
                    536: 
                    537: static const VMStateDescription vmstate_usb_hub_port = {
                    538:     .name = "usb-hub-port",
                    539:     .version_id = 1,
                    540:     .minimum_version_id = 1,
                    541:     .fields = (VMStateField []) {
                    542:         VMSTATE_UINT16(wPortStatus, USBHubPort),
                    543:         VMSTATE_UINT16(wPortChange, USBHubPort),
                    544:         VMSTATE_END_OF_LIST()
                    545:     }
                    546: };
                    547: 
                    548: static const VMStateDescription vmstate_usb_hub = {
                    549:     .name = "usb-hub",
                    550:     .version_id = 1,
                    551:     .minimum_version_id = 1,
                    552:     .fields = (VMStateField []) {
                    553:         VMSTATE_USB_DEVICE(dev, USBHubState),
                    554:         VMSTATE_STRUCT_ARRAY(ports, USBHubState, NUM_PORTS, 0,
                    555:                              vmstate_usb_hub_port, USBHubPort),
                    556:         VMSTATE_END_OF_LIST()
                    557:     }
                    558: };
                    559: 
                    560: static void usb_hub_class_initfn(ObjectClass *klass, void *data)
                    561: {
                    562:     DeviceClass *dc = DEVICE_CLASS(klass);
                    563:     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
                    564: 
                    565:     uc->init           = usb_hub_initfn;
                    566:     uc->product_desc   = "QEMU USB Hub";
                    567:     uc->usb_desc       = &desc_hub;
                    568:     uc->find_device    = usb_hub_find_device;
                    569:     uc->handle_reset   = usb_hub_handle_reset;
                    570:     uc->handle_control = usb_hub_handle_control;
                    571:     uc->handle_data    = usb_hub_handle_data;
                    572:     uc->handle_destroy = usb_hub_handle_destroy;
                    573:     dc->fw_name = "hub";
                    574:     dc->vmsd = &vmstate_usb_hub;
                    575: }
                    576: 
                    577: static TypeInfo hub_info = {
                    578:     .name          = "usb-hub",
                    579:     .parent        = TYPE_USB_DEVICE,
                    580:     .instance_size = sizeof(USBHubState),
                    581:     .class_init    = usb_hub_class_initfn,
                    582: };
                    583: 
                    584: static void usb_hub_register_types(void)
                    585: {
                    586:     type_register_static(&hub_info);
                    587: }
                    588: 
                    589: type_init(usb_hub_register_types)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.