File:  [Qemu by Fabrice Bellard] / qemu / usb-redir.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:16:47 2018 UTC (2 years, 11 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1001, HEAD
qemu 1.0.1

    1: /*
    2:  * USB redirector usb-guest
    3:  *
    4:  * Copyright (c) 2011 Red Hat, Inc.
    5:  *
    6:  * Red Hat Authors:
    7:  * Hans de Goede <hdegoede@redhat.com>
    8:  *
    9:  * Permission is hereby granted, free of charge, to any person obtaining a copy
   10:  * of this software and associated documentation files (the "Software"), to deal
   11:  * in the Software without restriction, including without limitation the rights
   12:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   13:  * copies of the Software, and to permit persons to whom the Software is
   14:  * furnished to do so, subject to the following conditions:
   15:  *
   16:  * The above copyright notice and this permission notice shall be included in
   17:  * all copies or substantial portions of the Software.
   18:  *
   19:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   20:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   21:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   22:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   23:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   24:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   25:  * THE SOFTWARE.
   26:  */
   27: 
   28: #include "qemu-common.h"
   29: #include "qemu-timer.h"
   30: #include "monitor.h"
   31: #include "sysemu.h"
   32: 
   33: #include <dirent.h>
   34: #include <sys/ioctl.h>
   35: #include <signal.h>
   36: #include <usbredirparser.h>
   37: 
   38: #include "hw/usb.h"
   39: 
   40: #define MAX_ENDPOINTS 32
   41: #define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f))
   42: #define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f))
   43: 
   44: typedef struct AsyncURB AsyncURB;
   45: typedef struct USBRedirDevice USBRedirDevice;
   46: 
   47: /* Struct to hold buffered packets (iso or int input packets) */
   48: struct buf_packet {
   49:     uint8_t *data;
   50:     int len;
   51:     int status;
   52:     QTAILQ_ENTRY(buf_packet)next;
   53: };
   54: 
   55: struct endp_data {
   56:     uint8_t type;
   57:     uint8_t interval;
   58:     uint8_t interface; /* bInterfaceNumber this ep belongs to */
   59:     uint8_t iso_started;
   60:     uint8_t iso_error; /* For reporting iso errors to the HC */
   61:     uint8_t interrupt_started;
   62:     uint8_t interrupt_error;
   63:     QTAILQ_HEAD(, buf_packet) bufpq;
   64: };
   65: 
   66: struct USBRedirDevice {
   67:     USBDevice dev;
   68:     /* Properties */
   69:     CharDriverState *cs;
   70:     uint8_t debug;
   71:     /* Data passed from chardev the fd_read cb to the usbredirparser read cb */
   72:     const uint8_t *read_buf;
   73:     int read_buf_size;
   74:     /* For async handling of open/close */
   75:     QEMUBH *open_close_bh;
   76:     /* To delay the usb attach in case of quick chardev close + open */
   77:     QEMUTimer *attach_timer;
   78:     int64_t next_attach_time;
   79:     struct usbredirparser *parser;
   80:     struct endp_data endpoint[MAX_ENDPOINTS];
   81:     uint32_t packet_id;
   82:     QTAILQ_HEAD(, AsyncURB) asyncq;
   83: };
   84: 
   85: struct AsyncURB {
   86:     USBRedirDevice *dev;
   87:     USBPacket *packet;
   88:     uint32_t packet_id;
   89:     int get;
   90:     union {
   91:         struct usb_redir_control_packet_header control_packet;
   92:         struct usb_redir_bulk_packet_header bulk_packet;
   93:         struct usb_redir_interrupt_packet_header interrupt_packet;
   94:     };
   95:     QTAILQ_ENTRY(AsyncURB)next;
   96: };
   97: 
   98: static void usbredir_device_connect(void *priv,
   99:     struct usb_redir_device_connect_header *device_connect);
  100: static void usbredir_device_disconnect(void *priv);
  101: static void usbredir_interface_info(void *priv,
  102:     struct usb_redir_interface_info_header *interface_info);
  103: static void usbredir_ep_info(void *priv,
  104:     struct usb_redir_ep_info_header *ep_info);
  105: static void usbredir_configuration_status(void *priv, uint32_t id,
  106:     struct usb_redir_configuration_status_header *configuration_status);
  107: static void usbredir_alt_setting_status(void *priv, uint32_t id,
  108:     struct usb_redir_alt_setting_status_header *alt_setting_status);
  109: static void usbredir_iso_stream_status(void *priv, uint32_t id,
  110:     struct usb_redir_iso_stream_status_header *iso_stream_status);
  111: static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
  112:     struct usb_redir_interrupt_receiving_status_header
  113:     *interrupt_receiving_status);
  114: static void usbredir_bulk_streams_status(void *priv, uint32_t id,
  115:     struct usb_redir_bulk_streams_status_header *bulk_streams_status);
  116: static void usbredir_control_packet(void *priv, uint32_t id,
  117:     struct usb_redir_control_packet_header *control_packet,
  118:     uint8_t *data, int data_len);
  119: static void usbredir_bulk_packet(void *priv, uint32_t id,
  120:     struct usb_redir_bulk_packet_header *bulk_packet,
  121:     uint8_t *data, int data_len);
  122: static void usbredir_iso_packet(void *priv, uint32_t id,
  123:     struct usb_redir_iso_packet_header *iso_packet,
  124:     uint8_t *data, int data_len);
  125: static void usbredir_interrupt_packet(void *priv, uint32_t id,
  126:     struct usb_redir_interrupt_packet_header *interrupt_header,
  127:     uint8_t *data, int data_len);
  128: 
  129: static int usbredir_handle_status(USBRedirDevice *dev,
  130:                                        int status, int actual_len);
  131: 
  132: #define VERSION "qemu usb-redir guest " QEMU_VERSION
  133: 
  134: /*
  135:  * Logging stuff
  136:  */
  137: 
  138: #define ERROR(...) \
  139:     do { \
  140:         if (dev->debug >= usbredirparser_error) { \
  141:             error_report("usb-redir error: " __VA_ARGS__); \
  142:         } \
  143:     } while (0)
  144: #define WARNING(...) \
  145:     do { \
  146:         if (dev->debug >= usbredirparser_warning) { \
  147:             error_report("usb-redir warning: " __VA_ARGS__); \
  148:         } \
  149:     } while (0)
  150: #define INFO(...) \
  151:     do { \
  152:         if (dev->debug >= usbredirparser_info) { \
  153:             error_report("usb-redir: " __VA_ARGS__); \
  154:         } \
  155:     } while (0)
  156: #define DPRINTF(...) \
  157:     do { \
  158:         if (dev->debug >= usbredirparser_debug) { \
  159:             error_report("usb-redir: " __VA_ARGS__); \
  160:         } \
  161:     } while (0)
  162: #define DPRINTF2(...) \
  163:     do { \
  164:         if (dev->debug >= usbredirparser_debug_data) { \
  165:             error_report("usb-redir: " __VA_ARGS__); \
  166:         } \
  167:     } while (0)
  168: 
  169: static void usbredir_log(void *priv, int level, const char *msg)
  170: {
  171:     USBRedirDevice *dev = priv;
  172: 
  173:     if (dev->debug < level) {
  174:         return;
  175:     }
  176: 
  177:     error_report("%s\n", msg);
  178: }
  179: 
  180: static void usbredir_log_data(USBRedirDevice *dev, const char *desc,
  181:     const uint8_t *data, int len)
  182: {
  183:     int i, j, n;
  184: 
  185:     if (dev->debug < usbredirparser_debug_data) {
  186:         return;
  187:     }
  188: 
  189:     for (i = 0; i < len; i += j) {
  190:         char buf[128];
  191: 
  192:         n = sprintf(buf, "%s", desc);
  193:         for (j = 0; j < 8 && i + j < len; j++) {
  194:             n += sprintf(buf + n, " %02X", data[i + j]);
  195:         }
  196:         error_report("%s\n", buf);
  197:     }
  198: }
  199: 
  200: /*
  201:  * usbredirparser io functions
  202:  */
  203: 
  204: static int usbredir_read(void *priv, uint8_t *data, int count)
  205: {
  206:     USBRedirDevice *dev = priv;
  207: 
  208:     if (dev->read_buf_size < count) {
  209:         count = dev->read_buf_size;
  210:     }
  211: 
  212:     memcpy(data, dev->read_buf, count);
  213: 
  214:     dev->read_buf_size -= count;
  215:     if (dev->read_buf_size) {
  216:         dev->read_buf += count;
  217:     } else {
  218:         dev->read_buf = NULL;
  219:     }
  220: 
  221:     return count;
  222: }
  223: 
  224: static int usbredir_write(void *priv, uint8_t *data, int count)
  225: {
  226:     USBRedirDevice *dev = priv;
  227: 
  228:     if (!dev->cs->opened) {
  229:         return 0;
  230:     }
  231: 
  232:     return qemu_chr_fe_write(dev->cs, data, count);
  233: }
  234: 
  235: /*
  236:  * Async and buffered packets helpers
  237:  */
  238: 
  239: static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p)
  240: {
  241:     AsyncURB *aurb = (AsyncURB *) g_malloc0(sizeof(AsyncURB));
  242:     aurb->dev = dev;
  243:     aurb->packet = p;
  244:     aurb->packet_id = dev->packet_id;
  245:     QTAILQ_INSERT_TAIL(&dev->asyncq, aurb, next);
  246:     dev->packet_id++;
  247: 
  248:     return aurb;
  249: }
  250: 
  251: static void async_free(USBRedirDevice *dev, AsyncURB *aurb)
  252: {
  253:     QTAILQ_REMOVE(&dev->asyncq, aurb, next);
  254:     g_free(aurb);
  255: }
  256: 
  257: static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id)
  258: {
  259:     AsyncURB *aurb;
  260: 
  261:     QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
  262:         if (aurb->packet_id == packet_id) {
  263:             return aurb;
  264:         }
  265:     }
  266:     ERROR("could not find async urb for packet_id %u\n", packet_id);
  267:     return NULL;
  268: }
  269: 
  270: static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
  271: {
  272:     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
  273:     AsyncURB *aurb;
  274: 
  275:     QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
  276:         if (p != aurb->packet) {
  277:             continue;
  278:         }
  279: 
  280:         DPRINTF("async cancel id %u\n", aurb->packet_id);
  281:         usbredirparser_send_cancel_data_packet(dev->parser, aurb->packet_id);
  282:         usbredirparser_do_write(dev->parser);
  283: 
  284:         /* Mark it as dead */
  285:         aurb->packet = NULL;
  286:         break;
  287:     }
  288: }
  289: 
  290: static struct buf_packet *bufp_alloc(USBRedirDevice *dev,
  291:     uint8_t *data, int len, int status, uint8_t ep)
  292: {
  293:     struct buf_packet *bufp = g_malloc(sizeof(struct buf_packet));
  294:     bufp->data   = data;
  295:     bufp->len    = len;
  296:     bufp->status = status;
  297:     QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
  298:     return bufp;
  299: }
  300: 
  301: static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp,
  302:     uint8_t ep)
  303: {
  304:     QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
  305:     free(bufp->data);
  306:     g_free(bufp);
  307: }
  308: 
  309: static void usbredir_free_bufpq(USBRedirDevice *dev, uint8_t ep)
  310: {
  311:     struct buf_packet *buf, *buf_next;
  312: 
  313:     QTAILQ_FOREACH_SAFE(buf, &dev->endpoint[EP2I(ep)].bufpq, next, buf_next) {
  314:         bufp_free(dev, buf, ep);
  315:     }
  316: }
  317: 
  318: /*
  319:  * USBDevice callbacks
  320:  */
  321: 
  322: static void usbredir_handle_reset(USBDevice *udev)
  323: {
  324:     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
  325: 
  326:     DPRINTF("reset device\n");
  327:     usbredirparser_send_reset(dev->parser);
  328:     usbredirparser_do_write(dev->parser);
  329: }
  330: 
  331: static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
  332:                                      uint8_t ep)
  333: {
  334:     int status, len;
  335: 
  336:     if (!dev->endpoint[EP2I(ep)].iso_started &&
  337:             !dev->endpoint[EP2I(ep)].iso_error) {
  338:         struct usb_redir_start_iso_stream_header start_iso = {
  339:             .endpoint = ep,
  340:             /* TODO maybe do something with these depending on ep interval? */
  341:             .pkts_per_urb = 32,
  342:             .no_urbs = 3,
  343:         };
  344:         /* No id, we look at the ep when receiving a status back */
  345:         usbredirparser_send_start_iso_stream(dev->parser, 0, &start_iso);
  346:         usbredirparser_do_write(dev->parser);
  347:         DPRINTF("iso stream started ep %02X\n", ep);
  348:         dev->endpoint[EP2I(ep)].iso_started = 1;
  349:     }
  350: 
  351:     if (ep & USB_DIR_IN) {
  352:         struct buf_packet *isop;
  353: 
  354:         isop = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
  355:         if (isop == NULL) {
  356:             DPRINTF2("iso-token-in ep %02X, no isop\n", ep);
  357:             /* Check iso_error for stream errors, otherwise its an underrun */
  358:             status = dev->endpoint[EP2I(ep)].iso_error;
  359:             dev->endpoint[EP2I(ep)].iso_error = 0;
  360:             return usbredir_handle_status(dev, status, 0);
  361:         }
  362:         DPRINTF2("iso-token-in ep %02X status %d len %d\n", ep, isop->status,
  363:                  isop->len);
  364: 
  365:         status = isop->status;
  366:         if (status != usb_redir_success) {
  367:             bufp_free(dev, isop, ep);
  368:             return usbredir_handle_status(dev, status, 0);
  369:         }
  370: 
  371:         len = isop->len;
  372:         if (len > p->iov.size) {
  373:             ERROR("received iso data is larger then packet ep %02X\n", ep);
  374:             bufp_free(dev, isop, ep);
  375:             return USB_RET_NAK;
  376:         }
  377:         usb_packet_copy(p, isop->data, len);
  378:         bufp_free(dev, isop, ep);
  379:         return len;
  380:     } else {
  381:         /* If the stream was not started because of a pending error don't
  382:            send the packet to the usb-host */
  383:         if (dev->endpoint[EP2I(ep)].iso_started) {
  384:             struct usb_redir_iso_packet_header iso_packet = {
  385:                 .endpoint = ep,
  386:                 .length = p->iov.size
  387:             };
  388:             uint8_t buf[p->iov.size];
  389:             /* No id, we look at the ep when receiving a status back */
  390:             usb_packet_copy(p, buf, p->iov.size);
  391:             usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet,
  392:                                            buf, p->iov.size);
  393:             usbredirparser_do_write(dev->parser);
  394:         }
  395:         status = dev->endpoint[EP2I(ep)].iso_error;
  396:         dev->endpoint[EP2I(ep)].iso_error = 0;
  397:         DPRINTF2("iso-token-out ep %02X status %d len %zd\n", ep, status,
  398:                  p->iov.size);
  399:         return usbredir_handle_status(dev, status, p->iov.size);
  400:     }
  401: }
  402: 
  403: static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep)
  404: {
  405:     struct usb_redir_stop_iso_stream_header stop_iso_stream = {
  406:         .endpoint = ep
  407:     };
  408:     if (dev->endpoint[EP2I(ep)].iso_started) {
  409:         usbredirparser_send_stop_iso_stream(dev->parser, 0, &stop_iso_stream);
  410:         DPRINTF("iso stream stopped ep %02X\n", ep);
  411:         dev->endpoint[EP2I(ep)].iso_started = 0;
  412:     }
  413:     usbredir_free_bufpq(dev, ep);
  414: }
  415: 
  416: static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
  417:                                       uint8_t ep)
  418: {
  419:     AsyncURB *aurb = async_alloc(dev, p);
  420:     struct usb_redir_bulk_packet_header bulk_packet;
  421: 
  422:     DPRINTF("bulk-out ep %02X len %zd id %u\n", ep,
  423:             p->iov.size, aurb->packet_id);
  424: 
  425:     bulk_packet.endpoint  = ep;
  426:     bulk_packet.length    = p->iov.size;
  427:     bulk_packet.stream_id = 0;
  428:     aurb->bulk_packet = bulk_packet;
  429: 
  430:     if (ep & USB_DIR_IN) {
  431:         usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
  432:                                         &bulk_packet, NULL, 0);
  433:     } else {
  434:         uint8_t buf[p->iov.size];
  435:         usb_packet_copy(p, buf, p->iov.size);
  436:         usbredir_log_data(dev, "bulk data out:", buf, p->iov.size);
  437:         usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
  438:                                         &bulk_packet, buf, p->iov.size);
  439:     }
  440:     usbredirparser_do_write(dev->parser);
  441:     return USB_RET_ASYNC;
  442: }
  443: 
  444: static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
  445:                                            USBPacket *p, uint8_t ep)
  446: {
  447:     if (ep & USB_DIR_IN) {
  448:         /* Input interrupt endpoint, buffered packet input */
  449:         struct buf_packet *intp;
  450:         int status, len;
  451: 
  452:         if (!dev->endpoint[EP2I(ep)].interrupt_started &&
  453:                 !dev->endpoint[EP2I(ep)].interrupt_error) {
  454:             struct usb_redir_start_interrupt_receiving_header start_int = {
  455:                 .endpoint = ep,
  456:             };
  457:             /* No id, we look at the ep when receiving a status back */
  458:             usbredirparser_send_start_interrupt_receiving(dev->parser, 0,
  459:                                                           &start_int);
  460:             usbredirparser_do_write(dev->parser);
  461:             DPRINTF("interrupt recv started ep %02X\n", ep);
  462:             dev->endpoint[EP2I(ep)].interrupt_started = 1;
  463:         }
  464: 
  465:         intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
  466:         if (intp == NULL) {
  467:             DPRINTF2("interrupt-token-in ep %02X, no intp\n", ep);
  468:             /* Check interrupt_error for stream errors */
  469:             status = dev->endpoint[EP2I(ep)].interrupt_error;
  470:             dev->endpoint[EP2I(ep)].interrupt_error = 0;
  471:             return usbredir_handle_status(dev, status, 0);
  472:         }
  473:         DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
  474:                 intp->status, intp->len);
  475: 
  476:         status = intp->status;
  477:         if (status != usb_redir_success) {
  478:             bufp_free(dev, intp, ep);
  479:             return usbredir_handle_status(dev, status, 0);
  480:         }
  481: 
  482:         len = intp->len;
  483:         if (len > p->iov.size) {
  484:             ERROR("received int data is larger then packet ep %02X\n", ep);
  485:             bufp_free(dev, intp, ep);
  486:             return USB_RET_NAK;
  487:         }
  488:         usb_packet_copy(p, intp->data, len);
  489:         bufp_free(dev, intp, ep);
  490:         return len;
  491:     } else {
  492:         /* Output interrupt endpoint, normal async operation */
  493:         AsyncURB *aurb = async_alloc(dev, p);
  494:         struct usb_redir_interrupt_packet_header interrupt_packet;
  495:         uint8_t buf[p->iov.size];
  496: 
  497:         DPRINTF("interrupt-out ep %02X len %zd id %u\n", ep, p->iov.size,
  498:                 aurb->packet_id);
  499: 
  500:         interrupt_packet.endpoint  = ep;
  501:         interrupt_packet.length    = p->iov.size;
  502:         aurb->interrupt_packet     = interrupt_packet;
  503: 
  504:         usb_packet_copy(p, buf, p->iov.size);
  505:         usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size);
  506:         usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id,
  507:                                         &interrupt_packet, buf, p->iov.size);
  508:         usbredirparser_do_write(dev->parser);
  509:         return USB_RET_ASYNC;
  510:     }
  511: }
  512: 
  513: static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev,
  514:     uint8_t ep)
  515: {
  516:     struct usb_redir_stop_interrupt_receiving_header stop_interrupt_recv = {
  517:         .endpoint = ep
  518:     };
  519:     if (dev->endpoint[EP2I(ep)].interrupt_started) {
  520:         usbredirparser_send_stop_interrupt_receiving(dev->parser, 0,
  521:                                                      &stop_interrupt_recv);
  522:         DPRINTF("interrupt recv stopped ep %02X\n", ep);
  523:         dev->endpoint[EP2I(ep)].interrupt_started = 0;
  524:     }
  525:     usbredir_free_bufpq(dev, ep);
  526: }
  527: 
  528: static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
  529: {
  530:     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
  531:     uint8_t ep;
  532: 
  533:     ep = p->devep;
  534:     if (p->pid == USB_TOKEN_IN) {
  535:         ep |= USB_DIR_IN;
  536:     }
  537: 
  538:     switch (dev->endpoint[EP2I(ep)].type) {
  539:     case USB_ENDPOINT_XFER_CONTROL:
  540:         ERROR("handle_data called for control transfer on ep %02X\n", ep);
  541:         return USB_RET_NAK;
  542:     case USB_ENDPOINT_XFER_ISOC:
  543:         return usbredir_handle_iso_data(dev, p, ep);
  544:     case USB_ENDPOINT_XFER_BULK:
  545:         return usbredir_handle_bulk_data(dev, p, ep);;
  546:     case USB_ENDPOINT_XFER_INT:
  547:         return usbredir_handle_interrupt_data(dev, p, ep);;
  548:     default:
  549:         ERROR("handle_data ep %02X has unknown type %d\n", ep,
  550:               dev->endpoint[EP2I(ep)].type);
  551:         return USB_RET_NAK;
  552:     }
  553: }
  554: 
  555: static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
  556:                                 int config)
  557: {
  558:     struct usb_redir_set_configuration_header set_config;
  559:     AsyncURB *aurb = async_alloc(dev, p);
  560:     int i;
  561: 
  562:     DPRINTF("set config %d id %u\n", config, aurb->packet_id);
  563: 
  564:     for (i = 0; i < MAX_ENDPOINTS; i++) {
  565:         switch (dev->endpoint[i].type) {
  566:         case USB_ENDPOINT_XFER_ISOC:
  567:             usbredir_stop_iso_stream(dev, I2EP(i));
  568:             break;
  569:         case USB_ENDPOINT_XFER_INT:
  570:             if (i & 0x10) {
  571:                 usbredir_stop_interrupt_receiving(dev, I2EP(i));
  572:             }
  573:             break;
  574:         }
  575:         usbredir_free_bufpq(dev, I2EP(i));
  576:     }
  577: 
  578:     set_config.configuration = config;
  579:     usbredirparser_send_set_configuration(dev->parser, aurb->packet_id,
  580:                                           &set_config);
  581:     usbredirparser_do_write(dev->parser);
  582:     return USB_RET_ASYNC;
  583: }
  584: 
  585: static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
  586: {
  587:     AsyncURB *aurb = async_alloc(dev, p);
  588: 
  589:     DPRINTF("get config id %u\n", aurb->packet_id);
  590: 
  591:     aurb->get = 1;
  592:     usbredirparser_send_get_configuration(dev->parser, aurb->packet_id);
  593:     usbredirparser_do_write(dev->parser);
  594:     return USB_RET_ASYNC;
  595: }
  596: 
  597: static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
  598:                                    int interface, int alt)
  599: {
  600:     struct usb_redir_set_alt_setting_header set_alt;
  601:     AsyncURB *aurb = async_alloc(dev, p);
  602:     int i;
  603: 
  604:     DPRINTF("set interface %d alt %d id %u\n", interface, alt,
  605:             aurb->packet_id);
  606: 
  607:     for (i = 0; i < MAX_ENDPOINTS; i++) {
  608:         if (dev->endpoint[i].interface == interface) {
  609:             switch (dev->endpoint[i].type) {
  610:             case USB_ENDPOINT_XFER_ISOC:
  611:                 usbredir_stop_iso_stream(dev, I2EP(i));
  612:                 break;
  613:             case USB_ENDPOINT_XFER_INT:
  614:                 if (i & 0x10) {
  615:                     usbredir_stop_interrupt_receiving(dev, I2EP(i));
  616:                 }
  617:                 break;
  618:             }
  619:             usbredir_free_bufpq(dev, I2EP(i));
  620:         }
  621:     }
  622: 
  623:     set_alt.interface = interface;
  624:     set_alt.alt = alt;
  625:     usbredirparser_send_set_alt_setting(dev->parser, aurb->packet_id,
  626:                                         &set_alt);
  627:     usbredirparser_do_write(dev->parser);
  628:     return USB_RET_ASYNC;
  629: }
  630: 
  631: static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
  632:                                    int interface)
  633: {
  634:     struct usb_redir_get_alt_setting_header get_alt;
  635:     AsyncURB *aurb = async_alloc(dev, p);
  636: 
  637:     DPRINTF("get interface %d id %u\n", interface, aurb->packet_id);
  638: 
  639:     get_alt.interface = interface;
  640:     aurb->get = 1;
  641:     usbredirparser_send_get_alt_setting(dev->parser, aurb->packet_id,
  642:                                         &get_alt);
  643:     usbredirparser_do_write(dev->parser);
  644:     return USB_RET_ASYNC;
  645: }
  646: 
  647: static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
  648:         int request, int value, int index, int length, uint8_t *data)
  649: {
  650:     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
  651:     struct usb_redir_control_packet_header control_packet;
  652:     AsyncURB *aurb;
  653: 
  654:     /* Special cases for certain standard device requests */
  655:     switch (request) {
  656:     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
  657:         DPRINTF("set address %d\n", value);
  658:         dev->dev.addr = value;
  659:         return 0;
  660:     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
  661:         return usbredir_set_config(dev, p, value & 0xff);
  662:     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
  663:         return usbredir_get_config(dev, p);
  664:     case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
  665:         return usbredir_set_interface(dev, p, index, value);
  666:     case InterfaceRequest | USB_REQ_GET_INTERFACE:
  667:         return usbredir_get_interface(dev, p, index);
  668:     }
  669: 
  670:     /* "Normal" ctrl requests */
  671:     aurb = async_alloc(dev, p);
  672: 
  673:     /* Note request is (bRequestType << 8) | bRequest */
  674:     DPRINTF("ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %u\n",
  675:             request >> 8, request & 0xff, value, index, length,
  676:             aurb->packet_id);
  677: 
  678:     control_packet.request     = request & 0xFF;
  679:     control_packet.requesttype = request >> 8;
  680:     control_packet.endpoint    = control_packet.requesttype & USB_DIR_IN;
  681:     control_packet.value       = value;
  682:     control_packet.index       = index;
  683:     control_packet.length      = length;
  684:     aurb->control_packet       = control_packet;
  685: 
  686:     if (control_packet.requesttype & USB_DIR_IN) {
  687:         usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
  688:                                            &control_packet, NULL, 0);
  689:     } else {
  690:         usbredir_log_data(dev, "ctrl data out:", data, length);
  691:         usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
  692:                                            &control_packet, data, length);
  693:     }
  694:     usbredirparser_do_write(dev->parser);
  695:     return USB_RET_ASYNC;
  696: }
  697: 
  698: /*
  699:  * Close events can be triggered by usbredirparser_do_write which gets called
  700:  * from within the USBDevice data / control packet callbacks and doing a
  701:  * usb_detach from within these callbacks is not a good idea.
  702:  *
  703:  * So we use a bh handler to take care of close events. We also handle
  704:  * open events from this callback to make sure that a close directly followed
  705:  * by an open gets handled in the right order.
  706:  */
  707: static void usbredir_open_close_bh(void *opaque)
  708: {
  709:     USBRedirDevice *dev = opaque;
  710: 
  711:     usbredir_device_disconnect(dev);
  712: 
  713:     if (dev->parser) {
  714:         usbredirparser_destroy(dev->parser);
  715:         dev->parser = NULL;
  716:     }
  717: 
  718:     if (dev->cs->opened) {
  719:         dev->parser = qemu_oom_check(usbredirparser_create());
  720:         dev->parser->priv = dev;
  721:         dev->parser->log_func = usbredir_log;
  722:         dev->parser->read_func = usbredir_read;
  723:         dev->parser->write_func = usbredir_write;
  724:         dev->parser->device_connect_func = usbredir_device_connect;
  725:         dev->parser->device_disconnect_func = usbredir_device_disconnect;
  726:         dev->parser->interface_info_func = usbredir_interface_info;
  727:         dev->parser->ep_info_func = usbredir_ep_info;
  728:         dev->parser->configuration_status_func = usbredir_configuration_status;
  729:         dev->parser->alt_setting_status_func = usbredir_alt_setting_status;
  730:         dev->parser->iso_stream_status_func = usbredir_iso_stream_status;
  731:         dev->parser->interrupt_receiving_status_func =
  732:             usbredir_interrupt_receiving_status;
  733:         dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status;
  734:         dev->parser->control_packet_func = usbredir_control_packet;
  735:         dev->parser->bulk_packet_func = usbredir_bulk_packet;
  736:         dev->parser->iso_packet_func = usbredir_iso_packet;
  737:         dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
  738:         dev->read_buf = NULL;
  739:         dev->read_buf_size = 0;
  740:         usbredirparser_init(dev->parser, VERSION, NULL, 0, 0);
  741:         usbredirparser_do_write(dev->parser);
  742:     }
  743: }
  744: 
  745: static void usbredir_do_attach(void *opaque)
  746: {
  747:     USBRedirDevice *dev = opaque;
  748: 
  749:     usb_device_attach(&dev->dev);
  750: }
  751: 
  752: /*
  753:  * chardev callbacks
  754:  */
  755: 
  756: static int usbredir_chardev_can_read(void *opaque)
  757: {
  758:     USBRedirDevice *dev = opaque;
  759: 
  760:     if (dev->parser) {
  761:         /* usbredir_parser_do_read will consume *all* data we give it */
  762:         return 1024 * 1024;
  763:     } else {
  764:         /* usbredir_open_close_bh hasn't handled the open event yet */
  765:         return 0;
  766:     }
  767: }
  768: 
  769: static void usbredir_chardev_read(void *opaque, const uint8_t *buf, int size)
  770: {
  771:     USBRedirDevice *dev = opaque;
  772: 
  773:     /* No recursion allowed! */
  774:     assert(dev->read_buf == NULL);
  775: 
  776:     dev->read_buf = buf;
  777:     dev->read_buf_size = size;
  778: 
  779:     usbredirparser_do_read(dev->parser);
  780:     /* Send any acks, etc. which may be queued now */
  781:     usbredirparser_do_write(dev->parser);
  782: }
  783: 
  784: static void usbredir_chardev_event(void *opaque, int event)
  785: {
  786:     USBRedirDevice *dev = opaque;
  787: 
  788:     switch (event) {
  789:     case CHR_EVENT_OPENED:
  790:     case CHR_EVENT_CLOSED:
  791:         qemu_bh_schedule(dev->open_close_bh);
  792:         break;
  793:     }
  794: }
  795: 
  796: /*
  797:  * init + destroy
  798:  */
  799: 
  800: static int usbredir_initfn(USBDevice *udev)
  801: {
  802:     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
  803:     int i;
  804: 
  805:     if (dev->cs == NULL) {
  806:         qerror_report(QERR_MISSING_PARAMETER, "chardev");
  807:         return -1;
  808:     }
  809: 
  810:     dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
  811:     dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
  812: 
  813:     QTAILQ_INIT(&dev->asyncq);
  814:     for (i = 0; i < MAX_ENDPOINTS; i++) {
  815:         QTAILQ_INIT(&dev->endpoint[i].bufpq);
  816:     }
  817: 
  818:     /* We'll do the attach once we receive the speed from the usb-host */
  819:     udev->auto_attach = 0;
  820: 
  821:     /* Let the backend know we are ready */
  822:     qemu_chr_fe_open(dev->cs);
  823:     qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
  824:                           usbredir_chardev_read, usbredir_chardev_event, dev);
  825: 
  826:     return 0;
  827: }
  828: 
  829: static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
  830: {
  831:     AsyncURB *aurb, *next_aurb;
  832:     int i;
  833: 
  834:     QTAILQ_FOREACH_SAFE(aurb, &dev->asyncq, next, next_aurb) {
  835:         async_free(dev, aurb);
  836:     }
  837:     for (i = 0; i < MAX_ENDPOINTS; i++) {
  838:         usbredir_free_bufpq(dev, I2EP(i));
  839:     }
  840: }
  841: 
  842: static void usbredir_handle_destroy(USBDevice *udev)
  843: {
  844:     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
  845: 
  846:     qemu_chr_fe_close(dev->cs);
  847:     qemu_chr_delete(dev->cs);
  848:     /* Note must be done after qemu_chr_close, as that causes a close event */
  849:     qemu_bh_delete(dev->open_close_bh);
  850: 
  851:     qemu_del_timer(dev->attach_timer);
  852:     qemu_free_timer(dev->attach_timer);
  853: 
  854:     usbredir_cleanup_device_queues(dev);
  855: 
  856:     if (dev->parser) {
  857:         usbredirparser_destroy(dev->parser);
  858:     }
  859: }
  860: 
  861: /*
  862:  * usbredirparser packet complete callbacks
  863:  */
  864: 
  865: static int usbredir_handle_status(USBRedirDevice *dev,
  866:                                        int status, int actual_len)
  867: {
  868:     switch (status) {
  869:     case usb_redir_success:
  870:         return actual_len;
  871:     case usb_redir_stall:
  872:         return USB_RET_STALL;
  873:     case usb_redir_cancelled:
  874:         WARNING("returning cancelled packet to HC?\n");
  875:     case usb_redir_inval:
  876:     case usb_redir_ioerror:
  877:     case usb_redir_timeout:
  878:     default:
  879:         return USB_RET_NAK;
  880:     }
  881: }
  882: 
  883: static void usbredir_device_connect(void *priv,
  884:     struct usb_redir_device_connect_header *device_connect)
  885: {
  886:     USBRedirDevice *dev = priv;
  887: 
  888:     if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
  889:         ERROR("Received device connect while already connected\n");
  890:         return;
  891:     }
  892: 
  893:     switch (device_connect->speed) {
  894:     case usb_redir_speed_low:
  895:         DPRINTF("attaching low speed device\n");
  896:         dev->dev.speed = USB_SPEED_LOW;
  897:         break;
  898:     case usb_redir_speed_full:
  899:         DPRINTF("attaching full speed device\n");
  900:         dev->dev.speed = USB_SPEED_FULL;
  901:         break;
  902:     case usb_redir_speed_high:
  903:         DPRINTF("attaching high speed device\n");
  904:         dev->dev.speed = USB_SPEED_HIGH;
  905:         break;
  906:     case usb_redir_speed_super:
  907:         DPRINTF("attaching super speed device\n");
  908:         dev->dev.speed = USB_SPEED_SUPER;
  909:         break;
  910:     default:
  911:         DPRINTF("attaching unknown speed device, assuming full speed\n");
  912:         dev->dev.speed = USB_SPEED_FULL;
  913:     }
  914:     dev->dev.speedmask = (1 << dev->dev.speed);
  915:     qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
  916: }
  917: 
  918: static void usbredir_device_disconnect(void *priv)
  919: {
  920:     USBRedirDevice *dev = priv;
  921:     int i;
  922: 
  923:     /* Stop any pending attaches */
  924:     qemu_del_timer(dev->attach_timer);
  925: 
  926:     if (dev->dev.attached) {
  927:         usb_device_detach(&dev->dev);
  928:         /*
  929:          * Delay next usb device attach to give the guest a chance to see
  930:          * see the detach / attach in case of quick close / open succession
  931:          */
  932:         dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200;
  933:     }
  934: 
  935:     /* Reset state so that the next dev connected starts with a clean slate */
  936:     usbredir_cleanup_device_queues(dev);
  937:     memset(dev->endpoint, 0, sizeof(dev->endpoint));
  938:     for (i = 0; i < MAX_ENDPOINTS; i++) {
  939:         QTAILQ_INIT(&dev->endpoint[i].bufpq);
  940:     }
  941: }
  942: 
  943: static void usbredir_interface_info(void *priv,
  944:     struct usb_redir_interface_info_header *interface_info)
  945: {
  946:     /* The intention is to allow specifying acceptable interface classes
  947:        for redirection on the cmdline and in the future verify this here,
  948:        and disconnect (or never connect) the device if a not accepted
  949:        interface class is detected */
  950: }
  951: 
  952: static void usbredir_ep_info(void *priv,
  953:     struct usb_redir_ep_info_header *ep_info)
  954: {
  955:     USBRedirDevice *dev = priv;
  956:     int i;
  957: 
  958:     for (i = 0; i < MAX_ENDPOINTS; i++) {
  959:         dev->endpoint[i].type = ep_info->type[i];
  960:         dev->endpoint[i].interval = ep_info->interval[i];
  961:         dev->endpoint[i].interface = ep_info->interface[i];
  962:         if (dev->endpoint[i].type != usb_redir_type_invalid) {
  963:             DPRINTF("ep: %02X type: %d interface: %d\n", I2EP(i),
  964:                     dev->endpoint[i].type, dev->endpoint[i].interface);
  965:         }
  966:     }
  967: }
  968: 
  969: static void usbredir_configuration_status(void *priv, uint32_t id,
  970:     struct usb_redir_configuration_status_header *config_status)
  971: {
  972:     USBRedirDevice *dev = priv;
  973:     AsyncURB *aurb;
  974:     int len = 0;
  975: 
  976:     DPRINTF("set config status %d config %d id %u\n", config_status->status,
  977:             config_status->configuration, id);
  978: 
  979:     aurb = async_find(dev, id);
  980:     if (!aurb) {
  981:         return;
  982:     }
  983:     if (aurb->packet) {
  984:         if (aurb->get) {
  985:             dev->dev.data_buf[0] = config_status->configuration;
  986:             len = 1;
  987:         }
  988:         aurb->packet->result =
  989:             usbredir_handle_status(dev, config_status->status, len);
  990:         usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
  991:     }
  992:     async_free(dev, aurb);
  993: }
  994: 
  995: static void usbredir_alt_setting_status(void *priv, uint32_t id,
  996:     struct usb_redir_alt_setting_status_header *alt_setting_status)
  997: {
  998:     USBRedirDevice *dev = priv;
  999:     AsyncURB *aurb;
 1000:     int len = 0;
 1001: 
 1002:     DPRINTF("alt status %d intf %d alt %d id: %u\n",
 1003:             alt_setting_status->status,
 1004:             alt_setting_status->interface,
 1005:             alt_setting_status->alt, id);
 1006: 
 1007:     aurb = async_find(dev, id);
 1008:     if (!aurb) {
 1009:         return;
 1010:     }
 1011:     if (aurb->packet) {
 1012:         if (aurb->get) {
 1013:             dev->dev.data_buf[0] = alt_setting_status->alt;
 1014:             len = 1;
 1015:         }
 1016:         aurb->packet->result =
 1017:             usbredir_handle_status(dev, alt_setting_status->status, len);
 1018:         usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
 1019:     }
 1020:     async_free(dev, aurb);
 1021: }
 1022: 
 1023: static void usbredir_iso_stream_status(void *priv, uint32_t id,
 1024:     struct usb_redir_iso_stream_status_header *iso_stream_status)
 1025: {
 1026:     USBRedirDevice *dev = priv;
 1027:     uint8_t ep = iso_stream_status->endpoint;
 1028: 
 1029:     DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status,
 1030:             ep, id);
 1031: 
 1032:     if (!dev->dev.attached) {
 1033:         return;
 1034:     }
 1035: 
 1036:     dev->endpoint[EP2I(ep)].iso_error = iso_stream_status->status;
 1037:     if (iso_stream_status->status == usb_redir_stall) {
 1038:         DPRINTF("iso stream stopped by peer ep %02X\n", ep);
 1039:         dev->endpoint[EP2I(ep)].iso_started = 0;
 1040:     }
 1041: }
 1042: 
 1043: static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
 1044:     struct usb_redir_interrupt_receiving_status_header
 1045:     *interrupt_receiving_status)
 1046: {
 1047:     USBRedirDevice *dev = priv;
 1048:     uint8_t ep = interrupt_receiving_status->endpoint;
 1049: 
 1050:     DPRINTF("interrupt recv status %d ep %02X id %u\n",
 1051:             interrupt_receiving_status->status, ep, id);
 1052: 
 1053:     if (!dev->dev.attached) {
 1054:         return;
 1055:     }
 1056: 
 1057:     dev->endpoint[EP2I(ep)].interrupt_error =
 1058:         interrupt_receiving_status->status;
 1059:     if (interrupt_receiving_status->status == usb_redir_stall) {
 1060:         DPRINTF("interrupt receiving stopped by peer ep %02X\n", ep);
 1061:         dev->endpoint[EP2I(ep)].interrupt_started = 0;
 1062:     }
 1063: }
 1064: 
 1065: static void usbredir_bulk_streams_status(void *priv, uint32_t id,
 1066:     struct usb_redir_bulk_streams_status_header *bulk_streams_status)
 1067: {
 1068: }
 1069: 
 1070: static void usbredir_control_packet(void *priv, uint32_t id,
 1071:     struct usb_redir_control_packet_header *control_packet,
 1072:     uint8_t *data, int data_len)
 1073: {
 1074:     USBRedirDevice *dev = priv;
 1075:     int len = control_packet->length;
 1076:     AsyncURB *aurb;
 1077: 
 1078:     DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status,
 1079:             len, id);
 1080: 
 1081:     aurb = async_find(dev, id);
 1082:     if (!aurb) {
 1083:         free(data);
 1084:         return;
 1085:     }
 1086: 
 1087:     aurb->control_packet.status = control_packet->status;
 1088:     aurb->control_packet.length = control_packet->length;
 1089:     if (memcmp(&aurb->control_packet, control_packet,
 1090:                sizeof(*control_packet))) {
 1091:         ERROR("return control packet mismatch, please report this!\n");
 1092:         len = USB_RET_NAK;
 1093:     }
 1094: 
 1095:     if (aurb->packet) {
 1096:         len = usbredir_handle_status(dev, control_packet->status, len);
 1097:         if (len > 0) {
 1098:             usbredir_log_data(dev, "ctrl data in:", data, data_len);
 1099:             if (data_len <= sizeof(dev->dev.data_buf)) {
 1100:                 memcpy(dev->dev.data_buf, data, data_len);
 1101:             } else {
 1102:                 ERROR("ctrl buffer too small (%d > %zu)\n",
 1103:                       data_len, sizeof(dev->dev.data_buf));
 1104:                 len = USB_RET_STALL;
 1105:             }
 1106:         }
 1107:         aurb->packet->result = len;
 1108:         usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
 1109:     }
 1110:     async_free(dev, aurb);
 1111:     free(data);
 1112: }
 1113: 
 1114: static void usbredir_bulk_packet(void *priv, uint32_t id,
 1115:     struct usb_redir_bulk_packet_header *bulk_packet,
 1116:     uint8_t *data, int data_len)
 1117: {
 1118:     USBRedirDevice *dev = priv;
 1119:     uint8_t ep = bulk_packet->endpoint;
 1120:     int len = bulk_packet->length;
 1121:     AsyncURB *aurb;
 1122: 
 1123:     DPRINTF("bulk-in status %d ep %02X len %d id %u\n", bulk_packet->status,
 1124:             ep, len, id);
 1125: 
 1126:     aurb = async_find(dev, id);
 1127:     if (!aurb) {
 1128:         free(data);
 1129:         return;
 1130:     }
 1131: 
 1132:     if (aurb->bulk_packet.endpoint != bulk_packet->endpoint ||
 1133:             aurb->bulk_packet.stream_id != bulk_packet->stream_id) {
 1134:         ERROR("return bulk packet mismatch, please report this!\n");
 1135:         len = USB_RET_NAK;
 1136:     }
 1137: 
 1138:     if (aurb->packet) {
 1139:         len = usbredir_handle_status(dev, bulk_packet->status, len);
 1140:         if (len > 0) {
 1141:             usbredir_log_data(dev, "bulk data in:", data, data_len);
 1142:             if (data_len <= aurb->packet->iov.size) {
 1143:                 usb_packet_copy(aurb->packet, data, data_len);
 1144:             } else {
 1145:                 ERROR("bulk buffer too small (%d > %zd)\n", data_len,
 1146:                       aurb->packet->iov.size);
 1147:                 len = USB_RET_STALL;
 1148:             }
 1149:         }
 1150:         aurb->packet->result = len;
 1151:         usb_packet_complete(&dev->dev, aurb->packet);
 1152:     }
 1153:     async_free(dev, aurb);
 1154:     free(data);
 1155: }
 1156: 
 1157: static void usbredir_iso_packet(void *priv, uint32_t id,
 1158:     struct usb_redir_iso_packet_header *iso_packet,
 1159:     uint8_t *data, int data_len)
 1160: {
 1161:     USBRedirDevice *dev = priv;
 1162:     uint8_t ep = iso_packet->endpoint;
 1163: 
 1164:     DPRINTF2("iso-in status %d ep %02X len %d id %u\n", iso_packet->status, ep,
 1165:              data_len, id);
 1166: 
 1167:     if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_ISOC) {
 1168:         ERROR("received iso packet for non iso endpoint %02X\n", ep);
 1169:         free(data);
 1170:         return;
 1171:     }
 1172: 
 1173:     if (dev->endpoint[EP2I(ep)].iso_started == 0) {
 1174:         DPRINTF("received iso packet for non started stream ep %02X\n", ep);
 1175:         free(data);
 1176:         return;
 1177:     }
 1178: 
 1179:     /* bufp_alloc also adds the packet to the ep queue */
 1180:     bufp_alloc(dev, data, data_len, iso_packet->status, ep);
 1181: }
 1182: 
 1183: static void usbredir_interrupt_packet(void *priv, uint32_t id,
 1184:     struct usb_redir_interrupt_packet_header *interrupt_packet,
 1185:     uint8_t *data, int data_len)
 1186: {
 1187:     USBRedirDevice *dev = priv;
 1188:     uint8_t ep = interrupt_packet->endpoint;
 1189: 
 1190:     DPRINTF("interrupt-in status %d ep %02X len %d id %u\n",
 1191:             interrupt_packet->status, ep, data_len, id);
 1192: 
 1193:     if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_INT) {
 1194:         ERROR("received int packet for non interrupt endpoint %02X\n", ep);
 1195:         free(data);
 1196:         return;
 1197:     }
 1198: 
 1199:     if (ep & USB_DIR_IN) {
 1200:         if (dev->endpoint[EP2I(ep)].interrupt_started == 0) {
 1201:             DPRINTF("received int packet while not started ep %02X\n", ep);
 1202:             free(data);
 1203:             return;
 1204:         }
 1205: 
 1206:         /* bufp_alloc also adds the packet to the ep queue */
 1207:         bufp_alloc(dev, data, data_len, interrupt_packet->status, ep);
 1208:     } else {
 1209:         int len = interrupt_packet->length;
 1210: 
 1211:         AsyncURB *aurb = async_find(dev, id);
 1212:         if (!aurb) {
 1213:             return;
 1214:         }
 1215: 
 1216:         if (aurb->interrupt_packet.endpoint != interrupt_packet->endpoint) {
 1217:             ERROR("return int packet mismatch, please report this!\n");
 1218:             len = USB_RET_NAK;
 1219:         }
 1220: 
 1221:         if (aurb->packet) {
 1222:             aurb->packet->result = usbredir_handle_status(dev,
 1223:                                                interrupt_packet->status, len);
 1224:             usb_packet_complete(&dev->dev, aurb->packet);
 1225:         }
 1226:         async_free(dev, aurb);
 1227:     }
 1228: }
 1229: 
 1230: static struct USBDeviceInfo usbredir_dev_info = {
 1231:     .product_desc   = "USB Redirection Device",
 1232:     .qdev.name      = "usb-redir",
 1233:     .qdev.size      = sizeof(USBRedirDevice),
 1234:     .init           = usbredir_initfn,
 1235:     .handle_destroy = usbredir_handle_destroy,
 1236:     .handle_packet  = usb_generic_handle_packet,
 1237:     .cancel_packet  = usbredir_cancel_packet,
 1238:     .handle_reset   = usbredir_handle_reset,
 1239:     .handle_data    = usbredir_handle_data,
 1240:     .handle_control = usbredir_handle_control,
 1241:     .qdev.props     = (Property[]) {
 1242:         DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
 1243:         DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
 1244:         DEFINE_PROP_END_OF_LIST(),
 1245:     },
 1246: };
 1247: 
 1248: static void usbredir_register_devices(void)
 1249: {
 1250:     usb_qdev_register(&usbredir_dev_info);
 1251: }
 1252: device_init(usbredir_register_devices);

unix.superglobalmegacorp.com