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

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

unix.superglobalmegacorp.com