File:  [Qemu by Fabrice Bellard] / qemu / usb-bsd.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:50:35 2018 UTC (3 years, 2 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.0

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

unix.superglobalmegacorp.com