Annotation of qemu/hw/usb/dev-hub.c, revision 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.