Annotation of qemu/hw/usb.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QEMU USB emulation
                      3:  *
                      4:  * Copyright (c) 2005 Fabrice Bellard
                      5:  * 
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: #include "vl.h"
                     25: 
                     26: void usb_attach(USBPort *port, USBDevice *dev)
                     27: {
                     28:     port->attach(port, dev);
                     29: }
                     30: 
                     31: /**********************/
                     32: /* generic USB device helpers (you are not forced to use them when
                     33:    writing your USB device driver, but they help handling the
                     34:    protocol) 
                     35: */
                     36: 
                     37: #define SETUP_STATE_IDLE 0
                     38: #define SETUP_STATE_DATA 1
                     39: #define SETUP_STATE_ACK  2
                     40: 
                     41: int usb_generic_handle_packet(USBDevice *s, int pid, 
                     42:                               uint8_t devaddr, uint8_t devep,
                     43:                               uint8_t *data, int len)
                     44: {
                     45:     int l, ret = 0;
                     46: 
                     47:     switch(pid) {
                     48:     case USB_MSG_ATTACH:
                     49:         s->state = USB_STATE_ATTACHED;
                     50:         break;
                     51:     case USB_MSG_DETACH:
                     52:         s->state = USB_STATE_NOTATTACHED;
                     53:         break;
                     54:     case USB_MSG_RESET:
                     55:         s->remote_wakeup = 0;
                     56:         s->addr = 0;
                     57:         s->state = USB_STATE_DEFAULT;
                     58:         s->handle_reset(s);
                     59:         break;
                     60:     case USB_TOKEN_SETUP:
                     61:         if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
                     62:             return USB_RET_NODEV;
                     63:         if (len != 8)
                     64:             goto fail;
                     65:         memcpy(s->setup_buf, data, 8);
                     66:         s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
                     67:         s->setup_index = 0;
                     68:         if (s->setup_buf[0] & USB_DIR_IN) {
                     69:             ret = s->handle_control(s, 
                     70:                                     (s->setup_buf[0] << 8) | s->setup_buf[1],
                     71:                                     (s->setup_buf[3] << 8) | s->setup_buf[2],
                     72:                                     (s->setup_buf[5] << 8) | s->setup_buf[4],
                     73:                                     s->setup_len,
                     74:                                     s->data_buf);
                     75:             if (ret < 0)
                     76:                 return ret;
                     77:             if (ret < s->setup_len)
                     78:                 s->setup_len = ret;
                     79:             s->setup_state = SETUP_STATE_DATA;
                     80:         } else {
                     81:             if (s->setup_len == 0)
                     82:                 s->setup_state = SETUP_STATE_ACK;
                     83:             else
                     84:                 s->setup_state = SETUP_STATE_DATA;
                     85:         }
                     86:         break;
                     87:     case USB_TOKEN_IN:
                     88:         if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
                     89:             return USB_RET_NODEV;
                     90:         switch(devep) {
                     91:         case 0:
                     92:             switch(s->setup_state) {
                     93:             case SETUP_STATE_ACK:
                     94:                 s->setup_state = SETUP_STATE_IDLE;
                     95:                 if (!(s->setup_buf[0] & USB_DIR_IN)) {
                     96:                     ret = s->handle_control(s, 
                     97:                                       (s->setup_buf[0] << 8) | s->setup_buf[1],
                     98:                                       (s->setup_buf[3] << 8) | s->setup_buf[2],
                     99:                                       (s->setup_buf[5] << 8) | s->setup_buf[4],
                    100:                                       s->setup_len,
                    101:                                       s->data_buf);
                    102:                     if (ret > 0)
                    103:                         ret = 0;
                    104:                 } else {
                    105:                     goto fail;
                    106:                 }
                    107:                 break;
                    108:             case SETUP_STATE_DATA:
                    109:                 if (s->setup_buf[0] & USB_DIR_IN) {
                    110:                     l = s->setup_len - s->setup_index;
                    111:                     if (l > len)
                    112:                         l = len;
                    113:                     memcpy(data, s->data_buf + s->setup_index, l);
                    114:                     s->setup_index += l;
                    115:                     if (s->setup_index >= s->setup_len)
                    116:                         s->setup_state = SETUP_STATE_ACK;
                    117:                     ret = l;
                    118:                 } else {
                    119:                     s->setup_state = SETUP_STATE_IDLE;
                    120:                     goto fail;
                    121:                 }
                    122:                 break;
                    123:             default:
                    124:                 goto fail;
                    125:             }
                    126:             break;
                    127:         default:
                    128:             ret = s->handle_data(s, pid, devep, data, len);
                    129:             break;
                    130:         }
                    131:         break;
                    132:     case USB_TOKEN_OUT:
                    133:         if (s->state < USB_STATE_DEFAULT || devaddr != s->addr)
                    134:             return USB_RET_NODEV;
                    135:         switch(devep) {
                    136:         case 0:
                    137:             switch(s->setup_state) {
                    138:             case SETUP_STATE_ACK:
                    139:                 s->setup_state = SETUP_STATE_IDLE;
                    140:                 if (s->setup_buf[0] & USB_DIR_IN) {
                    141:                     /* transfer OK */
                    142:                 } else {
                    143:                     goto fail;
                    144:                 }
                    145:                 break;
                    146:             case SETUP_STATE_DATA:
                    147:                 if (!(s->setup_buf[0] & USB_DIR_IN)) {
                    148:                     l = s->setup_len - s->setup_index;
                    149:                     if (l > len)
                    150:                         l = len;
                    151:                     memcpy(s->data_buf + s->setup_index, data, l);
                    152:                     s->setup_index += l;
                    153:                     if (s->setup_index >= s->setup_len)
                    154:                         s->setup_state = SETUP_STATE_ACK;
                    155:                     ret = l;
                    156:                 } else {
                    157:                     s->setup_state = SETUP_STATE_IDLE;
                    158:                     goto fail;
                    159:                 }
                    160:                 break;
                    161:             default:
                    162:                 goto fail;
                    163:             }
                    164:             break;
                    165:         default:
                    166:             ret = s->handle_data(s, pid, devep, data, len);
                    167:             break;
                    168:         }
                    169:         break;
                    170:     default:
                    171:     fail:
                    172:         ret = USB_RET_STALL;
                    173:         break;
                    174:     }
                    175:     return ret;
                    176: }
                    177: 
                    178: /* XXX: fix overflow */
                    179: int set_usb_string(uint8_t *buf, const char *str)
                    180: {
                    181:     int len, i;
                    182:     uint8_t *q;
                    183: 
                    184:     q = buf;
                    185:     len = strlen(str);
                    186:     *q++ = 2 * len + 1;
                    187:     *q++ = 3;
                    188:     for(i = 0; i < len; i++) {
                    189:         *q++ = str[i];
                    190:         *q++ = 0;
                    191:     }
                    192:     return q - buf;
                    193: }
                    194: 
                    195: /**********************/
                    196: /* USB hub emulation */
                    197: 
                    198: //#define DEBUG
                    199: 
                    200: #define MAX_PORTS 8
                    201: 
                    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: }

unix.superglobalmegacorp.com

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