Annotation of qemu/hw/usb/host-bsd.c, revision 1.1

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"
        !            28: #include "monitor.h"
        !            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>
        !            37: #ifndef __DragonFly__
        !            38: #include <dev/usb/usb.h>
        !            39: #else
        !            40: #include <bus/usb/usb.h>
        !            41: #endif
        !            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) {
        !            74: #if defined(__FreeBSD__) || defined(__DragonFly__)
        !            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,
        !           125:                                    USBPacket *p,
        !           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->ep->nr;
        !           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)
        !           256:         ret = readv(fd, p->iov.iov, p->iov.niov);
        !           257:     else
        !           258:         ret = writev(fd, p->iov.iov, p->iov.niov);
        !           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: 
        !           293:     g_free(s);
        !           294: }
        !           295: 
        !           296: static int usb_host_initfn(USBDevice *dev)
        !           297: {
        !           298:     return 0;
        !           299: }
        !           300: 
        !           301: USBDevice *usb_host_device_open(USBBus *guest_bus, const char *devname)
        !           302: {
        !           303:     struct usb_device_info bus_info, dev_info;
        !           304:     USBDevice *d = NULL, *ret = NULL;
        !           305:     USBHostDevice *dev;
        !           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: 
        !           311:     if (usb_host_find_device(&bus, &address, devname) < 0) {
        !           312:         goto fail;
        !           313:     }
        !           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
        !           323:         goto fail;
        !           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
        !           332:         goto fail_bfd;
        !           333:     }
        !           334: 
        !           335: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
        !           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:         }
        !           350:         goto fail_dfd;
        !           351:     }
        !           352: 
        !           353:     if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) {
        !           354: #ifdef DEBUG
        !           355:         printf("usb_host_device_open: failed to grab device info - %s\n",
        !           356:                strerror(errno));
        !           357: #endif
        !           358:         goto fail_dfd;
        !           359:     }
        !           360: 
        !           361:     d = usb_create(guest_bus, "usb-host");
        !           362:     dev = DO_UPCAST(USBHostDevice, dev, d);
        !           363: 
        !           364:     if (dev_info.udi_speed == 1) {
        !           365:         dev->dev.speed = USB_SPEED_LOW - 1;
        !           366:         dev->dev.speedmask = USB_SPEED_MASK_LOW;
        !           367:     } else {
        !           368:         dev->dev.speed = USB_SPEED_FULL - 1;
        !           369:         dev->dev.speedmask = USB_SPEED_MASK_FULL;
        !           370:     }
        !           371: 
        !           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:     }
        !           379: 
        !           380:     pstrcpy(dev->devpath, sizeof(dev->devpath), "/dev/");
        !           381:     pstrcat(dev->devpath, sizeof(dev->devpath), dev_info.udi_devnames[0]);
        !           382: 
        !           383:     /* Mark the endpoints as not yet open */
        !           384:     for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
        !           385:         dev->ep_fd[i] = -1;
        !           386:     }
        !           387: 
        !           388:     ioctl(dfd, USB_SETDEBUG, &ugendebug);
        !           389: 
        !           390:     ret = (USBDevice *)dev;
        !           391: 
        !           392: fail_dfd:
        !           393:     close(dfd);
        !           394: fail_bfd:
        !           395:     close(bfd);
        !           396: fail:
        !           397:     return ret;
        !           398: }
        !           399: 
        !           400: static void usb_host_class_initfn(ObjectClass *klass, void *data)
        !           401: {
        !           402:     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
        !           403: 
        !           404:     uc->product_desc   = "USB Host Device";
        !           405:     uc->init           = usb_host_initfn;
        !           406:     uc->handle_reset   = usb_host_handle_reset;
        !           407:     uc->handle_control = usb_host_handle_control;
        !           408:     uc->handle_data    = usb_host_handle_data;
        !           409:     uc->handle_destroy = usb_host_handle_destroy;
        !           410: }
        !           411: 
        !           412: static TypeInfo usb_host_dev_info = {
        !           413:     .name          = "usb-host",
        !           414:     .parent        = TYPE_USB_DEVICE,
        !           415:     .instance_size = sizeof(USBHostDevice),
        !           416:     .class_init    = usb_host_class_initfn,
        !           417: };
        !           418: 
        !           419: static void usb_host_register_types(void)
        !           420: {
        !           421:     type_register_static(&usb_host_dev_info);
        !           422: }
        !           423: 
        !           424: type_init(usb_host_register_types)
        !           425: 
        !           426: static int usb_host_scan(void *opaque, USBScanFunc *func)
        !           427: {
        !           428:     struct usb_device_info bus_info;
        !           429:     struct usb_device_info dev_info;
        !           430:     uint16_t vendor_id, product_id, class_id, speed;
        !           431:     int bfd, dfd, bus, address;
        !           432:     char busbuf[20], devbuf[20], product_name[256];
        !           433:     int ret = 0;
        !           434: 
        !           435:     for (bus = 0; bus < 10; bus++) {
        !           436: 
        !           437:         snprintf(busbuf, sizeof(busbuf) - 1, "/dev/usb%d", bus);
        !           438:         bfd = open(busbuf, O_RDWR);
        !           439:         if (bfd < 0)
        !           440:            continue;
        !           441: 
        !           442:         for (address = 1; address < 127; address++) {
        !           443: 
        !           444:             bus_info.udi_addr = address;
        !           445:             if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0)
        !           446:                 continue;
        !           447: 
        !           448:             /* only list devices that can be used by generic layer */
        !           449:             if (strncmp(bus_info.udi_devnames[0], "ugen", 4) != 0)
        !           450:                 continue;
        !           451: 
        !           452: #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
        !           453:             snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s", bus_info.udi_devnames[0]);
        !           454: #else
        !           455:             snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s.00", bus_info.udi_devnames[0]);
        !           456: #endif
        !           457: 
        !           458:             dfd = open(devbuf, O_RDONLY);
        !           459:             if (dfd < 0) {
        !           460: #ifdef DEBUG
        !           461:                 printf("usb_host_scan: couldn't open device %s - %s\n", devbuf,
        !           462:                        strerror(errno));
        !           463: #endif
        !           464:                 continue;
        !           465:             }
        !           466: 
        !           467:             if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0)
        !           468:                 printf("usb_host_scan: couldn't get device information for %s - %s\n",
        !           469:                        devbuf, strerror(errno));
        !           470: 
        !           471:             /* XXX: might need to fixup endianness of word values before copying over */
        !           472: 
        !           473:             vendor_id = dev_info.udi_vendorNo;
        !           474:             product_id = dev_info.udi_productNo;
        !           475:             class_id = dev_info.udi_class;
        !           476:             speed = dev_info.udi_speed;
        !           477: 
        !           478:             if (strncmp(dev_info.udi_product, "product", 7) != 0)
        !           479:                 pstrcpy(product_name, sizeof(product_name),
        !           480:                         dev_info.udi_product);
        !           481:             else
        !           482:                 product_name[0] = '\0';
        !           483: 
        !           484:             ret = func(opaque, bus, address, class_id, vendor_id,
        !           485:                        product_id, product_name, speed);
        !           486: 
        !           487:             close(dfd);
        !           488: 
        !           489:             if (ret)
        !           490:                 goto the_end;
        !           491:         }
        !           492: 
        !           493:         close(bfd);
        !           494:     }
        !           495: 
        !           496: the_end:
        !           497:     return ret;
        !           498: }
        !           499: 
        !           500: typedef struct FindDeviceState {
        !           501:     int vendor_id;
        !           502:     int product_id;
        !           503:     int bus_num;
        !           504:     int addr;
        !           505: } FindDeviceState;
        !           506: 
        !           507: static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
        !           508:                                      int class_id,
        !           509:                                      int vendor_id, int product_id,
        !           510:                                      const char *product_name, int speed)
        !           511: {
        !           512:     FindDeviceState *s = opaque;
        !           513:     if (vendor_id == s->vendor_id &&
        !           514:         product_id == s->product_id) {
        !           515:         s->bus_num = bus_num;
        !           516:         s->addr = addr;
        !           517:         return 1;
        !           518:      } else {
        !           519:         return 0;
        !           520:      }
        !           521: }
        !           522: 
        !           523: 
        !           524: /* the syntax is :
        !           525:    'bus.addr' (decimal numbers) or
        !           526:    'vendor_id:product_id' (hexa numbers) */
        !           527: static int usb_host_find_device(int *pbus_num, int *paddr,
        !           528:                                 const char *devname)
        !           529: {
        !           530:     const char *p;
        !           531:     int ret;
        !           532:     FindDeviceState fs;
        !           533: 
        !           534:     p = strchr(devname, '.');
        !           535:     if (p) {
        !           536:         *pbus_num = strtoul(devname, NULL, 0);
        !           537:         *paddr = strtoul(p + 1, NULL, 0);
        !           538:         return 0;
        !           539:     }
        !           540:     p = strchr(devname, ':');
        !           541:     if (p) {
        !           542:         fs.vendor_id = strtoul(devname, NULL, 16);
        !           543:         fs.product_id = strtoul(p + 1, NULL, 16);
        !           544:         ret = usb_host_scan(&fs, usb_host_find_device_scan);
        !           545:         if (ret) {
        !           546:             *pbus_num = fs.bus_num;
        !           547:             *paddr = fs.addr;
        !           548:             return 0;
        !           549:         }
        !           550:      }
        !           551:      return -1;
        !           552: }
        !           553: 
        !           554: /**********************/
        !           555: /* USB host device info */
        !           556: 
        !           557: struct usb_class_info {
        !           558:     int class;
        !           559:     const char *class_name;
        !           560: };
        !           561: 
        !           562: static const struct usb_class_info usb_class_info[] = {
        !           563:     { USB_CLASS_AUDIO, "Audio"},
        !           564:     { USB_CLASS_COMM, "Communication"},
        !           565:     { USB_CLASS_HID, "HID"},
        !           566:     { USB_CLASS_HUB, "Hub" },
        !           567:     { USB_CLASS_PHYSICAL, "Physical" },
        !           568:     { USB_CLASS_PRINTER, "Printer" },
        !           569:     { USB_CLASS_MASS_STORAGE, "Storage" },
        !           570:     { USB_CLASS_CDC_DATA, "Data" },
        !           571:     { USB_CLASS_APP_SPEC, "Application Specific" },
        !           572:     { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
        !           573:     { USB_CLASS_STILL_IMAGE, "Still Image" },
        !           574:     { USB_CLASS_CSCID, "Smart Card" },
        !           575:     { USB_CLASS_CONTENT_SEC, "Content Security" },
        !           576:     { -1, NULL }
        !           577: };
        !           578: 
        !           579: static const char *usb_class_str(uint8_t class)
        !           580: {
        !           581:     const struct usb_class_info *p;
        !           582:     for (p = usb_class_info; p->class != -1; p++) {
        !           583:         if (p->class == class)
        !           584:             break;
        !           585:     }
        !           586:     return p->class_name;
        !           587: }
        !           588: 
        !           589: static void usb_info_device(Monitor *mon, int bus_num, int addr, int class_id,
        !           590:                             int vendor_id, int product_id,
        !           591:                             const char *product_name,
        !           592:                             int speed)
        !           593: {
        !           594:     const char *class_str, *speed_str;
        !           595: 
        !           596:     switch(speed) {
        !           597:     case USB_SPEED_LOW:
        !           598:         speed_str = "1.5";
        !           599:         break;
        !           600:     case USB_SPEED_FULL:
        !           601:         speed_str = "12";
        !           602:         break;
        !           603:     case USB_SPEED_HIGH:
        !           604:         speed_str = "480";
        !           605:         break;
        !           606:     default:
        !           607:         speed_str = "?";
        !           608:         break;
        !           609:     }
        !           610: 
        !           611:     monitor_printf(mon, "  Device %d.%d, speed %s Mb/s\n",
        !           612:                    bus_num, addr, speed_str);
        !           613:     class_str = usb_class_str(class_id);
        !           614:     if (class_str)
        !           615:         monitor_printf(mon, "    %s:", class_str);
        !           616:     else
        !           617:         monitor_printf(mon, "    Class %02x:", class_id);
        !           618:     monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
        !           619:     if (product_name[0] != '\0')
        !           620:         monitor_printf(mon, ", %s", product_name);
        !           621:     monitor_printf(mon, "\n");
        !           622: }
        !           623: 
        !           624: static int usb_host_info_device(void *opaque,
        !           625:                                 int bus_num, int addr,
        !           626:                                 int class_id,
        !           627:                                 int vendor_id, int product_id,
        !           628:                                 const char *product_name,
        !           629:                                 int speed)
        !           630: {
        !           631:     Monitor *mon = opaque;
        !           632: 
        !           633:     usb_info_device(mon, bus_num, addr, class_id, vendor_id, product_id,
        !           634:                     product_name, speed);
        !           635:     return 0;
        !           636: }
        !           637: 
        !           638: void usb_host_info(Monitor *mon)
        !           639: {
        !           640:     usb_host_scan(mon, usb_host_info_device);
        !           641: }
        !           642: 
        !           643: /* XXX add this */
        !           644: int usb_host_device_close(const char *devname)
        !           645: {
        !           646:     return 0;
        !           647: }

unix.superglobalmegacorp.com

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