Annotation of qemu/usb-bsd.c, revision 1.1.1.6

1.1       root        1: /*
                      2:  * BSD host USB redirector
                      3:  *
                      4:  * Copyright (c) 2006 Lonnie Mendez
                      5:  * Portions of code and concepts borrowed from
                      6:  * usb-linux.c and libusb's bsd.c and are copyright their respective owners.
                      7:  *
                      8:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      9:  * of this software and associated documentation files (the "Software"), to deal
                     10:  * in the Software without restriction, including without limitation the rights
                     11:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     12:  * copies of the Software, and to permit persons to whom the Software is
                     13:  * furnished to do so, subject to the following conditions:
                     14:  *
                     15:  * The above copyright notice and this permission notice shall be included in
                     16:  * all copies or substantial portions of the Software.
                     17:  *
                     18:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     19:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     20:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     21:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     22:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     23:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     24:  * THE SOFTWARE.
                     25:  */
                     26: 
                     27: #include "qemu-common.h"
1.1.1.2   root       28: #include "monitor.h"
1.1       root       29: #include "hw/usb.h"
                     30: 
                     31: /* usb.h declares these */
                     32: #undef USB_SPEED_HIGH
                     33: #undef USB_SPEED_FULL
                     34: #undef USB_SPEED_LOW
                     35: 
                     36: #include <sys/ioctl.h>
1.1.1.2   root       37: #ifndef __DragonFly__
1.1       root       38: #include <dev/usb/usb.h>
1.1.1.2   root       39: #else
                     40: #include <bus/usb/usb.h>
                     41: #endif
1.1       root       42: 
                     43: /* This value has maximum potential at 16.
                     44:  * You should also set hw.usb.debug to gain
                     45:  * more detailed view.
                     46:  */
                     47: //#define DEBUG
                     48: #define UGEN_DEBUG_LEVEL 0
                     49: 
                     50: 
                     51: typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
                     52:                         int vendor_id, int product_id,
                     53:                         const char *product_name, int speed);
                     54: static int usb_host_find_device(int *pbus_num, int *paddr,
                     55:                                 const char *devname);
                     56: 
                     57: typedef struct USBHostDevice {
                     58:     USBDevice dev;
                     59:     int ep_fd[USB_MAX_ENDPOINTS];
                     60:     int devfd;
                     61:     char devpath[32];
                     62: } USBHostDevice;
                     63: 
                     64: 
                     65: static int ensure_ep_open(USBHostDevice *dev, int ep, int mode)
                     66: {
                     67:     char buf[32];
                     68:     int fd;
                     69: 
                     70:     /* Get the address for this endpoint */
                     71:     ep = UE_GET_ADDR(ep);
                     72: 
                     73:     if (dev->ep_fd[ep] < 0) {
1.1.1.2   root       74: #if defined(__FreeBSD__) || defined(__DragonFly__)
1.1       root       75:         snprintf(buf, sizeof(buf) - 1, "%s.%d", dev->devpath, ep);
                     76: #else
                     77:         snprintf(buf, sizeof(buf) - 1, "%s.%02d", dev->devpath, ep);
                     78: #endif
                     79:         /* Try to open it O_RDWR first for those devices which have in and out
                     80:          * endpoints with the same address (eg 0x02 and 0x82)
                     81:          */
                     82:         fd = open(buf, O_RDWR);
                     83:         if (fd < 0 && errno == ENXIO)
                     84:             fd = open(buf, mode);
                     85:         if (fd < 0) {
                     86: #ifdef DEBUG
                     87:             printf("ensure_ep_open: failed to open device endpoint %s: %s\n",
                     88:                    buf, strerror(errno));
                     89: #endif
                     90:         }
                     91:         dev->ep_fd[ep] = fd;
                     92:     }
                     93: 
                     94:     return dev->ep_fd[ep];
                     95: }
                     96: 
                     97: static void ensure_eps_closed(USBHostDevice *dev)
                     98: {
                     99:     int epnum = 1;
                    100: 
                    101:     if (!dev)
                    102:         return;
                    103: 
                    104:     while (epnum < USB_MAX_ENDPOINTS) {
                    105:         if (dev->ep_fd[epnum] >= 0) {
                    106:             close(dev->ep_fd[epnum]);
                    107:             dev->ep_fd[epnum] = -1;
                    108:         }
                    109:         epnum++;
                    110:     }
                    111: }
                    112: 
                    113: static void usb_host_handle_reset(USBDevice *dev)
                    114: {
                    115: #if 0
                    116:     USBHostDevice *s = (USBHostDevice *)dev;
                    117: #endif
                    118: }
                    119: 
                    120: /* XXX:
                    121:  * -check device states against transfer requests
                    122:  *  and return appropriate response
                    123:  */
                    124: static int usb_host_handle_control(USBDevice *dev,
1.1.1.5   root      125:                                    USBPacket *p,
1.1       root      126:                                    int request,
                    127:                                    int value,
                    128:                                    int index,
                    129:                                    int length,
                    130:                                    uint8_t *data)
                    131: {
                    132:     USBHostDevice *s = (USBHostDevice *)dev;
                    133:     struct usb_ctl_request req;
                    134:     struct usb_alt_interface aiface;
                    135:     int ret, timeout = 50;
                    136: 
                    137:     if ((request >> 8) == UT_WRITE_DEVICE &&
                    138:         (request & 0xff) == UR_SET_ADDRESS) {
                    139: 
                    140:         /* specific SET_ADDRESS support */
                    141:         dev->addr = value;
                    142:         return 0;
                    143:     } else if ((request >> 8) == UT_WRITE_DEVICE &&
                    144:                (request & 0xff) == UR_SET_CONFIG) {
                    145: 
                    146:         ensure_eps_closed(s); /* can't do this without all eps closed */
                    147: 
                    148:         ret = ioctl(s->devfd, USB_SET_CONFIG, &value);
                    149:         if (ret < 0) {
                    150: #ifdef DEBUG
                    151:             printf("handle_control: failed to set configuration - %s\n",
                    152:                    strerror(errno));
                    153: #endif
                    154:             return USB_RET_STALL;
                    155:         }
                    156: 
                    157:         return 0;
                    158:     } else if ((request >> 8) == UT_WRITE_INTERFACE &&
                    159:                (request & 0xff) == UR_SET_INTERFACE) {
                    160: 
                    161:         aiface.uai_interface_index = index;
                    162:         aiface.uai_alt_no = value;
                    163: 
                    164:         ensure_eps_closed(s); /* can't do this without all eps closed */
                    165:         ret = ioctl(s->devfd, USB_SET_ALTINTERFACE, &aiface);
                    166:         if (ret < 0) {
                    167: #ifdef DEBUG
                    168:             printf("handle_control: failed to set alternate interface - %s\n",
                    169:                    strerror(errno));
                    170: #endif
                    171:             return USB_RET_STALL;
                    172:         }
                    173: 
                    174:         return 0;
                    175:     } else {
                    176:         req.ucr_request.bmRequestType = request >> 8;
                    177:         req.ucr_request.bRequest = request & 0xff;
                    178:         USETW(req.ucr_request.wValue, value);
                    179:         USETW(req.ucr_request.wIndex, index);
                    180:         USETW(req.ucr_request.wLength, length);
                    181:         req.ucr_data = data;
                    182:         req.ucr_flags = USBD_SHORT_XFER_OK;
                    183: 
                    184:         ret = ioctl(s->devfd, USB_SET_TIMEOUT, &timeout);
                    185: #if defined(__NetBSD__) || defined(__OpenBSD__)
                    186:         if (ret < 0 && errno != EINVAL) {
                    187: #else
                    188:         if (ret < 0) {
                    189: #endif
                    190: #ifdef DEBUG
                    191:             printf("handle_control: setting timeout failed - %s\n",
                    192:                    strerror(errno));
                    193: #endif
                    194:         }
                    195: 
                    196:         ret = ioctl(s->devfd, USB_DO_REQUEST, &req);
                    197:         /* ugen returns EIO for usbd_do_request_ no matter what
                    198:          * happens with the transfer */
                    199:         if (ret < 0) {
                    200: #ifdef DEBUG
                    201:             printf("handle_control: error after request - %s\n",
                    202:                    strerror(errno));
                    203: #endif
                    204:             return USB_RET_NAK; // STALL
                    205:         } else {
                    206:             return req.ucr_actlen;
                    207:         }
                    208:     }
                    209: }
                    210: 
                    211: static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
                    212: {
                    213:     USBHostDevice *s = (USBHostDevice *)dev;
                    214:     int ret, fd, mode;
                    215:     int one = 1, shortpacket = 0, timeout = 50;
                    216:     sigset_t new_mask, old_mask;
                    217:     uint8_t devep = p->devep;
                    218: 
                    219:     /* protect data transfers from SIGALRM signal */
                    220:     sigemptyset(&new_mask);
                    221:     sigaddset(&new_mask, SIGALRM);
                    222:     sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
                    223: 
                    224:     if (p->pid == USB_TOKEN_IN) {
                    225:         devep |= 0x80;
                    226:         mode = O_RDONLY;
                    227:         shortpacket = 1;
                    228:     } else {
                    229:         mode = O_WRONLY;
                    230:     }
                    231: 
                    232:     fd = ensure_ep_open(s, devep, mode);
                    233:     if (fd < 0) {
                    234:         sigprocmask(SIG_SETMASK, &old_mask, NULL);
                    235:         return USB_RET_NODEV;
                    236:     }
                    237: 
                    238:     if (ioctl(fd, USB_SET_TIMEOUT, &timeout) < 0) {
                    239: #ifdef DEBUG
                    240:         printf("handle_data: failed to set timeout - %s\n",
                    241:                strerror(errno));
                    242: #endif
                    243:     }
                    244: 
                    245:     if (shortpacket) {
                    246:         if (ioctl(fd, USB_SET_SHORT_XFER, &one) < 0) {
                    247: #ifdef DEBUG
                    248:             printf("handle_data: failed to set short xfer mode - %s\n",
                    249:                    strerror(errno));
                    250: #endif
                    251:             sigprocmask(SIG_SETMASK, &old_mask, NULL);
                    252:         }
                    253:     }
                    254: 
                    255:     if (p->pid == USB_TOKEN_IN)
1.1.1.6 ! root      256:         ret = readv(fd, p->iov.iov, p->iov.niov);
1.1       root      257:     else
1.1.1.6 ! root      258:         ret = writev(fd, p->iov.iov, p->iov.niov);
1.1       root      259: 
                    260:     sigprocmask(SIG_SETMASK, &old_mask, NULL);
                    261: 
                    262:     if (ret < 0) {
                    263: #ifdef DEBUG
                    264:         printf("handle_data: error after %s data - %s\n",
                    265:                pid == USB_TOKEN_IN ? "reading" : "writing", strerror(errno));
                    266: #endif
                    267:         switch(errno) {
                    268:         case ETIMEDOUT:
                    269:         case EINTR:
                    270:             return USB_RET_NAK;
                    271:         default:
                    272:             return USB_RET_STALL;
                    273:         }
                    274:     } else {
                    275:         return ret;
                    276:     }
                    277: }
                    278: 
                    279: static void usb_host_handle_destroy(USBDevice *opaque)
                    280: {
                    281:     USBHostDevice *s = (USBHostDevice *)opaque;
                    282:     int i;
                    283: 
                    284:     for (i = 0; i < USB_MAX_ENDPOINTS; i++)
                    285:         if (s->ep_fd[i] >= 0)
                    286:             close(s->ep_fd[i]);
                    287: 
                    288:     if (s->devfd < 0)
                    289:         return;
                    290: 
                    291:     close(s->devfd);
                    292: 
1.1.1.6 ! root      293:     g_free(s);
1.1       root      294: }
                    295: 
1.1.1.3   root      296: static int usb_host_initfn(USBDevice *dev)
                    297: {
                    298:     return 0;
                    299: }
                    300: 
1.1       root      301: USBDevice *usb_host_device_open(const char *devname)
                    302: {
                    303:     struct usb_device_info bus_info, dev_info;
1.1.1.6 ! root      304:     USBDevice *d = NULL, *ret = NULL;
        !           305:     USBHostDevice *dev;
1.1       root      306:     char ctlpath[PATH_MAX + 1];
                    307:     char buspath[PATH_MAX + 1];
                    308:     int bfd, dfd, bus, address, i;
                    309:     int ugendebug = UGEN_DEBUG_LEVEL;
                    310: 
1.1.1.4   root      311:     if (usb_host_find_device(&bus, &address, devname) < 0) {
                    312:         goto fail;
                    313:     }
1.1       root      314: 
                    315:     snprintf(buspath, PATH_MAX, "/dev/usb%d", bus);
                    316: 
                    317:     bfd = open(buspath, O_RDWR);
                    318:     if (bfd < 0) {
                    319: #ifdef DEBUG
                    320:         printf("usb_host_device_open: failed to open usb bus - %s\n",
                    321:                strerror(errno));
                    322: #endif
1.1.1.4   root      323:         goto fail;
1.1       root      324:     }
                    325: 
                    326:     bus_info.udi_addr = address;
                    327:     if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) {
                    328: #ifdef DEBUG
                    329:         printf("usb_host_device_open: failed to grab bus information - %s\n",
                    330:                strerror(errno));
                    331: #endif
1.1.1.4   root      332:         goto fail_bfd;
1.1       root      333:     }
                    334: 
1.1.1.3   root      335: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
1.1       root      336:     snprintf(ctlpath, PATH_MAX, "/dev/%s", bus_info.udi_devnames[0]);
                    337: #else
                    338:     snprintf(ctlpath, PATH_MAX, "/dev/%s.00", bus_info.udi_devnames[0]);
                    339: #endif
                    340: 
                    341:     dfd  = open(ctlpath, O_RDWR);
                    342:     if (dfd < 0) {
                    343:         dfd = open(ctlpath, O_RDONLY);
                    344:         if (dfd < 0) {
                    345: #ifdef DEBUG
                    346:             printf("usb_host_device_open: failed to open usb device %s - %s\n",
                    347:                    ctlpath, strerror(errno));
                    348: #endif
                    349:         }
1.1.1.4   root      350:         goto fail_dfd;
1.1       root      351:     }
                    352: 
1.1.1.4   root      353:     if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) {
1.1       root      354: #ifdef DEBUG
1.1.1.4   root      355:         printf("usb_host_device_open: failed to grab device info - %s\n",
                    356:                strerror(errno));
1.1       root      357: #endif
1.1.1.4   root      358:         goto fail_dfd;
                    359:     }
                    360: 
                    361:     d = usb_create(NULL /* FIXME */, "usb-host");
                    362:     dev = DO_UPCAST(USBHostDevice, dev, d);
1.1       root      363: 
1.1.1.4   root      364:     if (dev_info.udi_speed == 1) {
                    365:         dev->dev.speed = USB_SPEED_LOW - 1;
1.1.1.5   root      366:         dev->dev.speedmask = USB_SPEED_MASK_LOW;
1.1.1.4   root      367:     } else {
                    368:         dev->dev.speed = USB_SPEED_FULL - 1;
1.1.1.5   root      369:         dev->dev.speedmask = USB_SPEED_MASK_FULL;
1.1.1.4   root      370:     }
1.1.1.3   root      371: 
1.1.1.4   root      372:     if (strncmp(dev_info.udi_product, "product", 7) != 0) {
                    373:         pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
                    374:                 dev_info.udi_product);
                    375:     } else {
                    376:         snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
                    377:                  "host:%s", devname);
                    378:     }
1.1       root      379: 
1.1.1.4   root      380:     pstrcpy(dev->devpath, sizeof(dev->devpath), "/dev/");
                    381:     pstrcat(dev->devpath, sizeof(dev->devpath), dev_info.udi_devnames[0]);
1.1       root      382: 
1.1.1.4   root      383:     /* Mark the endpoints as not yet open */
                    384:     for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
                    385:         dev->ep_fd[i] = -1;
1.1       root      386:     }
                    387: 
1.1.1.4   root      388:     ioctl(dfd, USB_SETDEBUG, &ugendebug);
                    389: 
                    390:     ret = (USBDevice *)dev;
                    391: 
                    392: fail_dfd:
                    393:     close(dfd);
                    394: fail_bfd:
                    395:     close(bfd);
1.1       root      396: fail:
1.1.1.4   root      397:     return ret;
1.1       root      398: }
                    399: 
1.1.1.3   root      400: static struct USBDeviceInfo usb_host_dev_info = {
                    401:     .product_desc   = "USB Host Device",
                    402:     .qdev.name      = "usb-host",
                    403:     .qdev.size      = sizeof(USBHostDevice),
                    404:     .init           = usb_host_initfn,
                    405:     .handle_packet  = usb_generic_handle_packet,
                    406:     .handle_reset   = usb_host_handle_reset,
                    407:     .handle_control = usb_host_handle_control,
                    408:     .handle_data    = usb_host_handle_data,
                    409:     .handle_destroy = usb_host_handle_destroy,
                    410: };
                    411: 
                    412: static void usb_host_register_devices(void)
                    413: {
                    414:     usb_qdev_register(&usb_host_dev_info);
                    415: }
                    416: device_init(usb_host_register_devices)
                    417: 
1.1       root      418: static int usb_host_scan(void *opaque, USBScanFunc *func)
                    419: {
                    420:     struct usb_device_info bus_info;
                    421:     struct usb_device_info dev_info;
                    422:     uint16_t vendor_id, product_id, class_id, speed;
                    423:     int bfd, dfd, bus, address;
                    424:     char busbuf[20], devbuf[20], product_name[256];
                    425:     int ret = 0;
                    426: 
                    427:     for (bus = 0; bus < 10; bus++) {
                    428: 
                    429:         snprintf(busbuf, sizeof(busbuf) - 1, "/dev/usb%d", bus);
                    430:         bfd = open(busbuf, O_RDWR);
                    431:         if (bfd < 0)
                    432:            continue;
                    433: 
                    434:         for (address = 1; address < 127; address++) {
                    435: 
                    436:             bus_info.udi_addr = address;
                    437:             if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0)
                    438:                 continue;
                    439: 
                    440:             /* only list devices that can be used by generic layer */
                    441:             if (strncmp(bus_info.udi_devnames[0], "ugen", 4) != 0)
                    442:                 continue;
                    443: 
1.1.1.3   root      444: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
1.1       root      445:             snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s", bus_info.udi_devnames[0]);
                    446: #else
                    447:             snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s.00", bus_info.udi_devnames[0]);
                    448: #endif
                    449: 
                    450:             dfd = open(devbuf, O_RDONLY);
                    451:             if (dfd < 0) {
                    452: #ifdef DEBUG
                    453:                 printf("usb_host_scan: couldn't open device %s - %s\n", devbuf,
                    454:                        strerror(errno));
                    455: #endif
                    456:                 continue;
                    457:             }
                    458: 
                    459:             if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0)
                    460:                 printf("usb_host_scan: couldn't get device information for %s - %s\n",
                    461:                        devbuf, strerror(errno));
                    462: 
1.1.1.5   root      463:             /* XXX: might need to fixup endianness of word values before copying over */
1.1       root      464: 
                    465:             vendor_id = dev_info.udi_vendorNo;
                    466:             product_id = dev_info.udi_productNo;
                    467:             class_id = dev_info.udi_class;
                    468:             speed = dev_info.udi_speed;
                    469: 
                    470:             if (strncmp(dev_info.udi_product, "product", 7) != 0)
                    471:                 pstrcpy(product_name, sizeof(product_name),
                    472:                         dev_info.udi_product);
                    473:             else
                    474:                 product_name[0] = '\0';
                    475: 
                    476:             ret = func(opaque, bus, address, class_id, vendor_id,
                    477:                        product_id, product_name, speed);
                    478: 
                    479:             close(dfd);
                    480: 
                    481:             if (ret)
                    482:                 goto the_end;
                    483:         }
                    484: 
                    485:         close(bfd);
                    486:     }
                    487: 
                    488: the_end:
                    489:     return ret;
                    490: }
                    491: 
                    492: typedef struct FindDeviceState {
                    493:     int vendor_id;
                    494:     int product_id;
                    495:     int bus_num;
                    496:     int addr;
                    497: } FindDeviceState;
                    498: 
                    499: static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
                    500:                                      int class_id,
                    501:                                      int vendor_id, int product_id,
                    502:                                      const char *product_name, int speed)
                    503: {
                    504:     FindDeviceState *s = opaque;
                    505:     if (vendor_id == s->vendor_id &&
                    506:         product_id == s->product_id) {
                    507:         s->bus_num = bus_num;
                    508:         s->addr = addr;
                    509:         return 1;
                    510:      } else {
                    511:         return 0;
                    512:      }
                    513: }
                    514: 
                    515: 
                    516: /* the syntax is :
                    517:    'bus.addr' (decimal numbers) or
                    518:    'vendor_id:product_id' (hexa numbers) */
                    519: static int usb_host_find_device(int *pbus_num, int *paddr,
                    520:                                 const char *devname)
                    521: {
                    522:     const char *p;
                    523:     int ret;
                    524:     FindDeviceState fs;
                    525: 
                    526:     p = strchr(devname, '.');
                    527:     if (p) {
                    528:         *pbus_num = strtoul(devname, NULL, 0);
                    529:         *paddr = strtoul(p + 1, NULL, 0);
                    530:         return 0;
                    531:     }
                    532:     p = strchr(devname, ':');
                    533:     if (p) {
                    534:         fs.vendor_id = strtoul(devname, NULL, 16);
                    535:         fs.product_id = strtoul(p + 1, NULL, 16);
                    536:         ret = usb_host_scan(&fs, usb_host_find_device_scan);
                    537:         if (ret) {
                    538:             *pbus_num = fs.bus_num;
                    539:             *paddr = fs.addr;
                    540:             return 0;
                    541:         }
                    542:      }
                    543:      return -1;
                    544: }
                    545: 
                    546: /**********************/
                    547: /* USB host device info */
                    548: 
                    549: struct usb_class_info {
                    550:     int class;
                    551:     const char *class_name;
                    552: };
                    553: 
                    554: static const struct usb_class_info usb_class_info[] = {
                    555:     { USB_CLASS_AUDIO, "Audio"},
                    556:     { USB_CLASS_COMM, "Communication"},
                    557:     { USB_CLASS_HID, "HID"},
                    558:     { USB_CLASS_HUB, "Hub" },
                    559:     { USB_CLASS_PHYSICAL, "Physical" },
                    560:     { USB_CLASS_PRINTER, "Printer" },
                    561:     { USB_CLASS_MASS_STORAGE, "Storage" },
                    562:     { USB_CLASS_CDC_DATA, "Data" },
                    563:     { USB_CLASS_APP_SPEC, "Application Specific" },
                    564:     { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
                    565:     { USB_CLASS_STILL_IMAGE, "Still Image" },
                    566:     { USB_CLASS_CSCID, "Smart Card" },
                    567:     { USB_CLASS_CONTENT_SEC, "Content Security" },
                    568:     { -1, NULL }
                    569: };
                    570: 
                    571: static const char *usb_class_str(uint8_t class)
                    572: {
                    573:     const struct usb_class_info *p;
                    574:     for (p = usb_class_info; p->class != -1; p++) {
                    575:         if (p->class == class)
                    576:             break;
                    577:     }
                    578:     return p->class_name;
                    579: }
                    580: 
1.1.1.3   root      581: static void usb_info_device(Monitor *mon, int bus_num, int addr, int class_id,
1.1       root      582:                             int vendor_id, int product_id,
                    583:                             const char *product_name,
                    584:                             int speed)
                    585: {
                    586:     const char *class_str, *speed_str;
                    587: 
                    588:     switch(speed) {
                    589:     case USB_SPEED_LOW:
                    590:         speed_str = "1.5";
                    591:         break;
                    592:     case USB_SPEED_FULL:
                    593:         speed_str = "12";
                    594:         break;
                    595:     case USB_SPEED_HIGH:
                    596:         speed_str = "480";
                    597:         break;
                    598:     default:
                    599:         speed_str = "?";
                    600:         break;
                    601:     }
                    602: 
1.1.1.2   root      603:     monitor_printf(mon, "  Device %d.%d, speed %s Mb/s\n",
                    604:                    bus_num, addr, speed_str);
1.1       root      605:     class_str = usb_class_str(class_id);
                    606:     if (class_str)
1.1.1.2   root      607:         monitor_printf(mon, "    %s:", class_str);
1.1       root      608:     else
1.1.1.2   root      609:         monitor_printf(mon, "    Class %02x:", class_id);
                    610:     monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
1.1       root      611:     if (product_name[0] != '\0')
1.1.1.2   root      612:         monitor_printf(mon, ", %s", product_name);
                    613:     monitor_printf(mon, "\n");
1.1       root      614: }
                    615: 
1.1.1.2   root      616: static int usb_host_info_device(void *opaque,
                    617:                                 int bus_num, int addr,
1.1       root      618:                                 int class_id,
                    619:                                 int vendor_id, int product_id,
                    620:                                 const char *product_name,
                    621:                                 int speed)
                    622: {
1.1.1.3   root      623:     Monitor *mon = opaque;
                    624: 
                    625:     usb_info_device(mon, bus_num, addr, class_id, vendor_id, product_id,
1.1       root      626:                     product_name, speed);
                    627:     return 0;
                    628: }
                    629: 
1.1.1.2   root      630: void usb_host_info(Monitor *mon)
1.1       root      631: {
1.1.1.3   root      632:     usb_host_scan(mon, usb_host_info_device);
1.1       root      633: }
                    634: 
                    635: /* XXX add this */
                    636: int usb_host_device_close(const char *devname)
                    637: {
                    638:     return 0;
                    639: }

unix.superglobalmegacorp.com