File:  [Qemu by Fabrice Bellard] / qemu / usb-redir.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:55:44 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu1000, qemu0151, HEAD
qemu 0.15.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:     return qemu_chr_write(dev->cs, data, count);
  229: }
  230: 
  231: /*
  232:  * Async and buffered packets helpers
  233:  */
  234: 
  235: static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p)
  236: {
  237:     AsyncURB *aurb = (AsyncURB *) qemu_mallocz(sizeof(AsyncURB));
  238:     aurb->dev = dev;
  239:     aurb->packet = p;
  240:     aurb->packet_id = dev->packet_id;
  241:     QTAILQ_INSERT_TAIL(&dev->asyncq, aurb, next);
  242:     dev->packet_id++;
  243: 
  244:     return aurb;
  245: }
  246: 
  247: static void async_free(USBRedirDevice *dev, AsyncURB *aurb)
  248: {
  249:     QTAILQ_REMOVE(&dev->asyncq, aurb, next);
  250:     qemu_free(aurb);
  251: }
  252: 
  253: static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id)
  254: {
  255:     AsyncURB *aurb;
  256: 
  257:     QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
  258:         if (aurb->packet_id == packet_id) {
  259:             return aurb;
  260:         }
  261:     }
  262:     ERROR("could not find async urb for packet_id %u\n", packet_id);
  263:     return NULL;
  264: }
  265: 
  266: static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
  267: {
  268:     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
  269:     AsyncURB *aurb;
  270: 
  271:     QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
  272:         if (p != aurb->packet) {
  273:             continue;
  274:         }
  275: 
  276:         DPRINTF("async cancel id %u\n", aurb->packet_id);
  277:         usbredirparser_send_cancel_data_packet(dev->parser, aurb->packet_id);
  278:         usbredirparser_do_write(dev->parser);
  279: 
  280:         /* Mark it as dead */
  281:         aurb->packet = NULL;
  282:         break;
  283:     }
  284: }
  285: 
  286: static struct buf_packet *bufp_alloc(USBRedirDevice *dev,
  287:     uint8_t *data, int len, int status, uint8_t ep)
  288: {
  289:     struct buf_packet *bufp = qemu_malloc(sizeof(struct buf_packet));
  290:     bufp->data   = data;
  291:     bufp->len    = len;
  292:     bufp->status = status;
  293:     QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
  294:     return bufp;
  295: }
  296: 
  297: static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp,
  298:     uint8_t ep)
  299: {
  300:     QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
  301:     free(bufp->data);
  302:     qemu_free(bufp);
  303: }
  304: 
  305: static void usbredir_free_bufpq(USBRedirDevice *dev, uint8_t ep)
  306: {
  307:     struct buf_packet *buf, *buf_next;
  308: 
  309:     QTAILQ_FOREACH_SAFE(buf, &dev->endpoint[EP2I(ep)].bufpq, next, buf_next) {
  310:         bufp_free(dev, buf, ep);
  311:     }
  312: }
  313: 
  314: /*
  315:  * USBDevice callbacks
  316:  */
  317: 
  318: static void usbredir_handle_reset(USBDevice *udev)
  319: {
  320:     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
  321: 
  322:     DPRINTF("reset device\n");
  323:     usbredirparser_send_reset(dev->parser);
  324:     usbredirparser_do_write(dev->parser);
  325: }
  326: 
  327: static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
  328:                                      uint8_t ep)
  329: {
  330:     int status, len;
  331: 
  332:     if (!dev->endpoint[EP2I(ep)].iso_started &&
  333:             !dev->endpoint[EP2I(ep)].iso_error) {
  334:         struct usb_redir_start_iso_stream_header start_iso = {
  335:             .endpoint = ep,
  336:             /* TODO maybe do something with these depending on ep interval? */
  337:             .pkts_per_urb = 32,
  338:             .no_urbs = 3,
  339:         };
  340:         /* No id, we look at the ep when receiving a status back */
  341:         usbredirparser_send_start_iso_stream(dev->parser, 0, &start_iso);
  342:         usbredirparser_do_write(dev->parser);
  343:         DPRINTF("iso stream started ep %02X\n", ep);
  344:         dev->endpoint[EP2I(ep)].iso_started = 1;
  345:     }
  346: 
  347:     if (ep & USB_DIR_IN) {
  348:         struct buf_packet *isop;
  349: 
  350:         isop = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
  351:         if (isop == NULL) {
  352:             DPRINTF2("iso-token-in ep %02X, no isop\n", ep);
  353:             /* Check iso_error for stream errors, otherwise its an underrun */
  354:             status = dev->endpoint[EP2I(ep)].iso_error;
  355:             dev->endpoint[EP2I(ep)].iso_error = 0;
  356:             return usbredir_handle_status(dev, status, 0);
  357:         }
  358:         DPRINTF2("iso-token-in ep %02X status %d len %d\n", ep, isop->status,
  359:                  isop->len);
  360: 
  361:         status = isop->status;
  362:         if (status != usb_redir_success) {
  363:             bufp_free(dev, isop, ep);
  364:             return usbredir_handle_status(dev, status, 0);
  365:         }
  366: 
  367:         len = isop->len;
  368:         if (len > p->len) {
  369:             ERROR("received iso data is larger then packet ep %02X\n", ep);
  370:             bufp_free(dev, isop, ep);
  371:             return USB_RET_NAK;
  372:         }
  373:         memcpy(p->data, isop->data, len);
  374:         bufp_free(dev, isop, ep);
  375:         return len;
  376:     } else {
  377:         /* If the stream was not started because of a pending error don't
  378:            send the packet to the usb-host */
  379:         if (dev->endpoint[EP2I(ep)].iso_started) {
  380:             struct usb_redir_iso_packet_header iso_packet = {
  381:                 .endpoint = ep,
  382:                 .length = p->len
  383:             };
  384:             /* No id, we look at the ep when receiving a status back */
  385:             usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet,
  386:                                            p->data, p->len);
  387:             usbredirparser_do_write(dev->parser);
  388:         }
  389:         status = dev->endpoint[EP2I(ep)].iso_error;
  390:         dev->endpoint[EP2I(ep)].iso_error = 0;
  391:         DPRINTF2("iso-token-out ep %02X status %d len %d\n", ep, status,
  392:                  p->len);
  393:         return usbredir_handle_status(dev, status, p->len);
  394:     }
  395: }
  396: 
  397: static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep)
  398: {
  399:     struct usb_redir_stop_iso_stream_header stop_iso_stream = {
  400:         .endpoint = ep
  401:     };
  402:     if (dev->endpoint[EP2I(ep)].iso_started) {
  403:         usbredirparser_send_stop_iso_stream(dev->parser, 0, &stop_iso_stream);
  404:         DPRINTF("iso stream stopped ep %02X\n", ep);
  405:         dev->endpoint[EP2I(ep)].iso_started = 0;
  406:     }
  407:     usbredir_free_bufpq(dev, ep);
  408: }
  409: 
  410: static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
  411:                                       uint8_t ep)
  412: {
  413:     AsyncURB *aurb = async_alloc(dev, p);
  414:     struct usb_redir_bulk_packet_header bulk_packet;
  415: 
  416:     DPRINTF("bulk-out ep %02X len %d id %u\n", ep, p->len, aurb->packet_id);
  417: 
  418:     bulk_packet.endpoint  = ep;
  419:     bulk_packet.length    = p->len;
  420:     bulk_packet.stream_id = 0;
  421:     aurb->bulk_packet = bulk_packet;
  422: 
  423:     if (ep & USB_DIR_IN) {
  424:         usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
  425:                                         &bulk_packet, NULL, 0);
  426:     } else {
  427:         usbredir_log_data(dev, "bulk data out:", p->data, p->len);
  428:         usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
  429:                                         &bulk_packet, p->data, p->len);
  430:     }
  431:     usbredirparser_do_write(dev->parser);
  432:     return USB_RET_ASYNC;
  433: }
  434: 
  435: static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
  436:                                            USBPacket *p, uint8_t ep)
  437: {
  438:     if (ep & USB_DIR_IN) {
  439:         /* Input interrupt endpoint, buffered packet input */
  440:         struct buf_packet *intp;
  441:         int status, len;
  442: 
  443:         if (!dev->endpoint[EP2I(ep)].interrupt_started &&
  444:                 !dev->endpoint[EP2I(ep)].interrupt_error) {
  445:             struct usb_redir_start_interrupt_receiving_header start_int = {
  446:                 .endpoint = ep,
  447:             };
  448:             /* No id, we look at the ep when receiving a status back */
  449:             usbredirparser_send_start_interrupt_receiving(dev->parser, 0,
  450:                                                           &start_int);
  451:             usbredirparser_do_write(dev->parser);
  452:             DPRINTF("interrupt recv started ep %02X\n", ep);
  453:             dev->endpoint[EP2I(ep)].interrupt_started = 1;
  454:         }
  455: 
  456:         intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
  457:         if (intp == NULL) {
  458:             DPRINTF2("interrupt-token-in ep %02X, no intp\n", ep);
  459:             /* Check interrupt_error for stream errors */
  460:             status = dev->endpoint[EP2I(ep)].interrupt_error;
  461:             dev->endpoint[EP2I(ep)].interrupt_error = 0;
  462:             return usbredir_handle_status(dev, status, 0);
  463:         }
  464:         DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
  465:                 intp->status, intp->len);
  466: 
  467:         status = intp->status;
  468:         if (status != usb_redir_success) {
  469:             bufp_free(dev, intp, ep);
  470:             return usbredir_handle_status(dev, status, 0);
  471:         }
  472: 
  473:         len = intp->len;
  474:         if (len > p->len) {
  475:             ERROR("received int data is larger then packet ep %02X\n", ep);
  476:             bufp_free(dev, intp, ep);
  477:             return USB_RET_NAK;
  478:         }
  479:         memcpy(p->data, intp->data, len);
  480:         bufp_free(dev, intp, ep);
  481:         return len;
  482:     } else {
  483:         /* Output interrupt endpoint, normal async operation */
  484:         AsyncURB *aurb = async_alloc(dev, p);
  485:         struct usb_redir_interrupt_packet_header interrupt_packet;
  486: 
  487:         DPRINTF("interrupt-out ep %02X len %d id %u\n", ep, p->len,
  488:                 aurb->packet_id);
  489: 
  490:         interrupt_packet.endpoint  = ep;
  491:         interrupt_packet.length    = p->len;
  492:         aurb->interrupt_packet     = interrupt_packet;
  493: 
  494:         usbredir_log_data(dev, "interrupt data out:", p->data, p->len);
  495:         usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id,
  496:                                         &interrupt_packet, p->data, p->len);
  497:         usbredirparser_do_write(dev->parser);
  498:         return USB_RET_ASYNC;
  499:     }
  500: }
  501: 
  502: static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev,
  503:     uint8_t ep)
  504: {
  505:     struct usb_redir_stop_interrupt_receiving_header stop_interrupt_recv = {
  506:         .endpoint = ep
  507:     };
  508:     if (dev->endpoint[EP2I(ep)].interrupt_started) {
  509:         usbredirparser_send_stop_interrupt_receiving(dev->parser, 0,
  510:                                                      &stop_interrupt_recv);
  511:         DPRINTF("interrupt recv stopped ep %02X\n", ep);
  512:         dev->endpoint[EP2I(ep)].interrupt_started = 0;
  513:     }
  514:     usbredir_free_bufpq(dev, ep);
  515: }
  516: 
  517: static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
  518: {
  519:     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
  520:     uint8_t ep;
  521: 
  522:     ep = p->devep;
  523:     if (p->pid == USB_TOKEN_IN) {
  524:         ep |= USB_DIR_IN;
  525:     }
  526: 
  527:     switch (dev->endpoint[EP2I(ep)].type) {
  528:     case USB_ENDPOINT_XFER_CONTROL:
  529:         ERROR("handle_data called for control transfer on ep %02X\n", ep);
  530:         return USB_RET_NAK;
  531:     case USB_ENDPOINT_XFER_ISOC:
  532:         return usbredir_handle_iso_data(dev, p, ep);
  533:     case USB_ENDPOINT_XFER_BULK:
  534:         return usbredir_handle_bulk_data(dev, p, ep);;
  535:     case USB_ENDPOINT_XFER_INT:
  536:         return usbredir_handle_interrupt_data(dev, p, ep);;
  537:     default:
  538:         ERROR("handle_data ep %02X has unknown type %d\n", ep,
  539:               dev->endpoint[EP2I(ep)].type);
  540:         return USB_RET_NAK;
  541:     }
  542: }
  543: 
  544: static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
  545:                                 int config)
  546: {
  547:     struct usb_redir_set_configuration_header set_config;
  548:     AsyncURB *aurb = async_alloc(dev, p);
  549:     int i;
  550: 
  551:     DPRINTF("set config %d id %u\n", config, aurb->packet_id);
  552: 
  553:     for (i = 0; i < MAX_ENDPOINTS; i++) {
  554:         switch (dev->endpoint[i].type) {
  555:         case USB_ENDPOINT_XFER_ISOC:
  556:             usbredir_stop_iso_stream(dev, I2EP(i));
  557:             break;
  558:         case USB_ENDPOINT_XFER_INT:
  559:             if (i & 0x10) {
  560:                 usbredir_stop_interrupt_receiving(dev, I2EP(i));
  561:             }
  562:             break;
  563:         }
  564:         usbredir_free_bufpq(dev, I2EP(i));
  565:     }
  566: 
  567:     set_config.configuration = config;
  568:     usbredirparser_send_set_configuration(dev->parser, aurb->packet_id,
  569:                                           &set_config);
  570:     usbredirparser_do_write(dev->parser);
  571:     return USB_RET_ASYNC;
  572: }
  573: 
  574: static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
  575: {
  576:     AsyncURB *aurb = async_alloc(dev, p);
  577: 
  578:     DPRINTF("get config id %u\n", aurb->packet_id);
  579: 
  580:     aurb->get = 1;
  581:     usbredirparser_send_get_configuration(dev->parser, aurb->packet_id);
  582:     usbredirparser_do_write(dev->parser);
  583:     return USB_RET_ASYNC;
  584: }
  585: 
  586: static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
  587:                                    int interface, int alt)
  588: {
  589:     struct usb_redir_set_alt_setting_header set_alt;
  590:     AsyncURB *aurb = async_alloc(dev, p);
  591:     int i;
  592: 
  593:     DPRINTF("set interface %d alt %d id %u\n", interface, alt,
  594:             aurb->packet_id);
  595: 
  596:     for (i = 0; i < MAX_ENDPOINTS; i++) {
  597:         if (dev->endpoint[i].interface == interface) {
  598:             switch (dev->endpoint[i].type) {
  599:             case USB_ENDPOINT_XFER_ISOC:
  600:                 usbredir_stop_iso_stream(dev, I2EP(i));
  601:                 break;
  602:             case USB_ENDPOINT_XFER_INT:
  603:                 if (i & 0x10) {
  604:                     usbredir_stop_interrupt_receiving(dev, I2EP(i));
  605:                 }
  606:                 break;
  607:             }
  608:             usbredir_free_bufpq(dev, I2EP(i));
  609:         }
  610:     }
  611: 
  612:     set_alt.interface = interface;
  613:     set_alt.alt = alt;
  614:     usbredirparser_send_set_alt_setting(dev->parser, aurb->packet_id,
  615:                                         &set_alt);
  616:     usbredirparser_do_write(dev->parser);
  617:     return USB_RET_ASYNC;
  618: }
  619: 
  620: static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
  621:                                    int interface)
  622: {
  623:     struct usb_redir_get_alt_setting_header get_alt;
  624:     AsyncURB *aurb = async_alloc(dev, p);
  625: 
  626:     DPRINTF("get interface %d id %u\n", interface, aurb->packet_id);
  627: 
  628:     get_alt.interface = interface;
  629:     aurb->get = 1;
  630:     usbredirparser_send_get_alt_setting(dev->parser, aurb->packet_id,
  631:                                         &get_alt);
  632:     usbredirparser_do_write(dev->parser);
  633:     return USB_RET_ASYNC;
  634: }
  635: 
  636: static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
  637:         int request, int value, int index, int length, uint8_t *data)
  638: {
  639:     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
  640:     struct usb_redir_control_packet_header control_packet;
  641:     AsyncURB *aurb;
  642: 
  643:     /* Special cases for certain standard device requests */
  644:     switch (request) {
  645:     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
  646:         DPRINTF("set address %d\n", value);
  647:         dev->dev.addr = value;
  648:         return 0;
  649:     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
  650:         return usbredir_set_config(dev, p, value & 0xff);
  651:     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
  652:         return usbredir_get_config(dev, p);
  653:     case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
  654:         return usbredir_set_interface(dev, p, index, value);
  655:     case InterfaceRequest | USB_REQ_GET_INTERFACE:
  656:         return usbredir_get_interface(dev, p, index);
  657:     }
  658: 
  659:     /* "Normal" ctrl requests */
  660:     aurb = async_alloc(dev, p);
  661: 
  662:     /* Note request is (bRequestType << 8) | bRequest */
  663:     DPRINTF("ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %u\n",
  664:             request >> 8, request & 0xff, value, index, length,
  665:             aurb->packet_id);
  666: 
  667:     control_packet.request     = request & 0xFF;
  668:     control_packet.requesttype = request >> 8;
  669:     control_packet.endpoint    = control_packet.requesttype & USB_DIR_IN;
  670:     control_packet.value       = value;
  671:     control_packet.index       = index;
  672:     control_packet.length      = length;
  673:     aurb->control_packet       = control_packet;
  674: 
  675:     if (control_packet.requesttype & USB_DIR_IN) {
  676:         usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
  677:                                            &control_packet, NULL, 0);
  678:     } else {
  679:         usbredir_log_data(dev, "ctrl data out:", data, length);
  680:         usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
  681:                                            &control_packet, data, length);
  682:     }
  683:     usbredirparser_do_write(dev->parser);
  684:     return USB_RET_ASYNC;
  685: }
  686: 
  687: /*
  688:  * Close events can be triggered by usbredirparser_do_write which gets called
  689:  * from within the USBDevice data / control packet callbacks and doing a
  690:  * usb_detach from within these callbacks is not a good idea.
  691:  *
  692:  * So we use a bh handler to take care of close events. We also handle
  693:  * open events from this callback to make sure that a close directly followed
  694:  * by an open gets handled in the right order.
  695:  */
  696: static void usbredir_open_close_bh(void *opaque)
  697: {
  698:     USBRedirDevice *dev = opaque;
  699: 
  700:     usbredir_device_disconnect(dev);
  701: 
  702:     if (dev->parser) {
  703:         usbredirparser_destroy(dev->parser);
  704:         dev->parser = NULL;
  705:     }
  706: 
  707:     if (dev->cs->opened) {
  708:         dev->parser = qemu_oom_check(usbredirparser_create());
  709:         dev->parser->priv = dev;
  710:         dev->parser->log_func = usbredir_log;
  711:         dev->parser->read_func = usbredir_read;
  712:         dev->parser->write_func = usbredir_write;
  713:         dev->parser->device_connect_func = usbredir_device_connect;
  714:         dev->parser->device_disconnect_func = usbredir_device_disconnect;
  715:         dev->parser->interface_info_func = usbredir_interface_info;
  716:         dev->parser->ep_info_func = usbredir_ep_info;
  717:         dev->parser->configuration_status_func = usbredir_configuration_status;
  718:         dev->parser->alt_setting_status_func = usbredir_alt_setting_status;
  719:         dev->parser->iso_stream_status_func = usbredir_iso_stream_status;
  720:         dev->parser->interrupt_receiving_status_func =
  721:             usbredir_interrupt_receiving_status;
  722:         dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status;
  723:         dev->parser->control_packet_func = usbredir_control_packet;
  724:         dev->parser->bulk_packet_func = usbredir_bulk_packet;
  725:         dev->parser->iso_packet_func = usbredir_iso_packet;
  726:         dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
  727:         dev->read_buf = NULL;
  728:         dev->read_buf_size = 0;
  729:         usbredirparser_init(dev->parser, VERSION, NULL, 0, 0);
  730:         usbredirparser_do_write(dev->parser);
  731:     }
  732: }
  733: 
  734: static void usbredir_do_attach(void *opaque)
  735: {
  736:     USBRedirDevice *dev = opaque;
  737: 
  738:     usb_device_attach(&dev->dev);
  739: }
  740: 
  741: /*
  742:  * chardev callbacks
  743:  */
  744: 
  745: static int usbredir_chardev_can_read(void *opaque)
  746: {
  747:     USBRedirDevice *dev = opaque;
  748: 
  749:     if (dev->parser) {
  750:         /* usbredir_parser_do_read will consume *all* data we give it */
  751:         return 1024 * 1024;
  752:     } else {
  753:         /* usbredir_open_close_bh hasn't handled the open event yet */
  754:         return 0;
  755:     }
  756: }
  757: 
  758: static void usbredir_chardev_read(void *opaque, const uint8_t *buf, int size)
  759: {
  760:     USBRedirDevice *dev = opaque;
  761: 
  762:     /* No recursion allowed! */
  763:     assert(dev->read_buf == NULL);
  764: 
  765:     dev->read_buf = buf;
  766:     dev->read_buf_size = size;
  767: 
  768:     usbredirparser_do_read(dev->parser);
  769:     /* Send any acks, etc. which may be queued now */
  770:     usbredirparser_do_write(dev->parser);
  771: }
  772: 
  773: static void usbredir_chardev_event(void *opaque, int event)
  774: {
  775:     USBRedirDevice *dev = opaque;
  776: 
  777:     switch (event) {
  778:     case CHR_EVENT_OPENED:
  779:     case CHR_EVENT_CLOSED:
  780:         qemu_bh_schedule(dev->open_close_bh);
  781:         break;
  782:     }
  783: }
  784: 
  785: /*
  786:  * init + destroy
  787:  */
  788: 
  789: static int usbredir_initfn(USBDevice *udev)
  790: {
  791:     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
  792:     int i;
  793: 
  794:     if (dev->cs == NULL) {
  795:         qerror_report(QERR_MISSING_PARAMETER, "chardev");
  796:         return -1;
  797:     }
  798: 
  799:     dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
  800:     dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
  801: 
  802:     QTAILQ_INIT(&dev->asyncq);
  803:     for (i = 0; i < MAX_ENDPOINTS; i++) {
  804:         QTAILQ_INIT(&dev->endpoint[i].bufpq);
  805:     }
  806: 
  807:     /* We'll do the attach once we receive the speed from the usb-host */
  808:     udev->auto_attach = 0;
  809: 
  810:     qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
  811:                           usbredir_chardev_read, usbredir_chardev_event, dev);
  812: 
  813:     return 0;
  814: }
  815: 
  816: static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
  817: {
  818:     AsyncURB *aurb, *next_aurb;
  819:     int i;
  820: 
  821:     QTAILQ_FOREACH_SAFE(aurb, &dev->asyncq, next, next_aurb) {
  822:         async_free(dev, aurb);
  823:     }
  824:     for (i = 0; i < MAX_ENDPOINTS; i++) {
  825:         usbredir_free_bufpq(dev, I2EP(i));
  826:     }
  827: }
  828: 
  829: static void usbredir_handle_destroy(USBDevice *udev)
  830: {
  831:     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
  832: 
  833:     qemu_chr_close(dev->cs);
  834:     /* Note must be done after qemu_chr_close, as that causes a close event */
  835:     qemu_bh_delete(dev->open_close_bh);
  836: 
  837:     qemu_del_timer(dev->attach_timer);
  838:     qemu_free_timer(dev->attach_timer);
  839: 
  840:     usbredir_cleanup_device_queues(dev);
  841: 
  842:     if (dev->parser) {
  843:         usbredirparser_destroy(dev->parser);
  844:     }
  845: }
  846: 
  847: /*
  848:  * usbredirparser packet complete callbacks
  849:  */
  850: 
  851: static int usbredir_handle_status(USBRedirDevice *dev,
  852:                                        int status, int actual_len)
  853: {
  854:     switch (status) {
  855:     case usb_redir_success:
  856:         return actual_len;
  857:     case usb_redir_stall:
  858:         return USB_RET_STALL;
  859:     case usb_redir_cancelled:
  860:         WARNING("returning cancelled packet to HC?\n");
  861:     case usb_redir_inval:
  862:     case usb_redir_ioerror:
  863:     case usb_redir_timeout:
  864:     default:
  865:         return USB_RET_NAK;
  866:     }
  867: }
  868: 
  869: static void usbredir_device_connect(void *priv,
  870:     struct usb_redir_device_connect_header *device_connect)
  871: {
  872:     USBRedirDevice *dev = priv;
  873: 
  874:     switch (device_connect->speed) {
  875:     case usb_redir_speed_low:
  876:         DPRINTF("attaching low speed device\n");
  877:         dev->dev.speed = USB_SPEED_LOW;
  878:         break;
  879:     case usb_redir_speed_full:
  880:         DPRINTF("attaching full speed device\n");
  881:         dev->dev.speed = USB_SPEED_FULL;
  882:         break;
  883:     case usb_redir_speed_high:
  884:         DPRINTF("attaching high speed device\n");
  885:         dev->dev.speed = USB_SPEED_HIGH;
  886:         break;
  887:     case usb_redir_speed_super:
  888:         DPRINTF("attaching super speed device\n");
  889:         dev->dev.speed = USB_SPEED_SUPER;
  890:         break;
  891:     default:
  892:         DPRINTF("attaching unknown speed device, assuming full speed\n");
  893:         dev->dev.speed = USB_SPEED_FULL;
  894:     }
  895:     dev->dev.speedmask = (1 << dev->dev.speed);
  896:     qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
  897: }
  898: 
  899: static void usbredir_device_disconnect(void *priv)
  900: {
  901:     USBRedirDevice *dev = priv;
  902: 
  903:     /* Stop any pending attaches */
  904:     qemu_del_timer(dev->attach_timer);
  905: 
  906:     if (dev->dev.attached) {
  907:         usb_device_detach(&dev->dev);
  908:         usbredir_cleanup_device_queues(dev);
  909:         /*
  910:          * Delay next usb device attach to give the guest a chance to see
  911:          * see the detach / attach in case of quick close / open succession
  912:          */
  913:         dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200;
  914:     }
  915: }
  916: 
  917: static void usbredir_interface_info(void *priv,
  918:     struct usb_redir_interface_info_header *interface_info)
  919: {
  920:     /* The intention is to allow specifying acceptable interface classes
  921:        for redirection on the cmdline and in the future verify this here,
  922:        and disconnect (or never connect) the device if a not accepted
  923:        interface class is detected */
  924: }
  925: 
  926: static void usbredir_ep_info(void *priv,
  927:     struct usb_redir_ep_info_header *ep_info)
  928: {
  929:     USBRedirDevice *dev = priv;
  930:     int i;
  931: 
  932:     for (i = 0; i < MAX_ENDPOINTS; i++) {
  933:         dev->endpoint[i].type = ep_info->type[i];
  934:         dev->endpoint[i].interval = ep_info->interval[i];
  935:         dev->endpoint[i].interface = ep_info->interface[i];
  936:         if (dev->endpoint[i].type != usb_redir_type_invalid) {
  937:             DPRINTF("ep: %02X type: %d interface: %d\n", I2EP(i),
  938:                     dev->endpoint[i].type, dev->endpoint[i].interface);
  939:         }
  940:     }
  941: }
  942: 
  943: static void usbredir_configuration_status(void *priv, uint32_t id,
  944:     struct usb_redir_configuration_status_header *config_status)
  945: {
  946:     USBRedirDevice *dev = priv;
  947:     AsyncURB *aurb;
  948:     int len = 0;
  949: 
  950:     DPRINTF("set config status %d config %d id %u\n", config_status->status,
  951:             config_status->configuration, id);
  952: 
  953:     aurb = async_find(dev, id);
  954:     if (!aurb) {
  955:         return;
  956:     }
  957:     if (aurb->packet) {
  958:         if (aurb->get) {
  959:             dev->dev.data_buf[0] = config_status->configuration;
  960:             len = 1;
  961:         }
  962:         aurb->packet->len =
  963:             usbredir_handle_status(dev, config_status->status, len);
  964:         usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
  965:     }
  966:     async_free(dev, aurb);
  967: }
  968: 
  969: static void usbredir_alt_setting_status(void *priv, uint32_t id,
  970:     struct usb_redir_alt_setting_status_header *alt_setting_status)
  971: {
  972:     USBRedirDevice *dev = priv;
  973:     AsyncURB *aurb;
  974:     int len = 0;
  975: 
  976:     DPRINTF("alt status %d intf %d alt %d id: %u\n",
  977:             alt_setting_status->status,
  978:             alt_setting_status->interface,
  979:             alt_setting_status->alt, id);
  980: 
  981:     aurb = async_find(dev, id);
  982:     if (!aurb) {
  983:         return;
  984:     }
  985:     if (aurb->packet) {
  986:         if (aurb->get) {
  987:             dev->dev.data_buf[0] = alt_setting_status->alt;
  988:             len = 1;
  989:         }
  990:         aurb->packet->len =
  991:             usbredir_handle_status(dev, alt_setting_status->status, len);
  992:         usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
  993:     }
  994:     async_free(dev, aurb);
  995: }
  996: 
  997: static void usbredir_iso_stream_status(void *priv, uint32_t id,
  998:     struct usb_redir_iso_stream_status_header *iso_stream_status)
  999: {
 1000:     USBRedirDevice *dev = priv;
 1001:     uint8_t ep = iso_stream_status->endpoint;
 1002: 
 1003:     DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status,
 1004:             ep, id);
 1005: 
 1006:     dev->endpoint[EP2I(ep)].iso_error = iso_stream_status->status;
 1007:     if (iso_stream_status->status == usb_redir_stall) {
 1008:         DPRINTF("iso stream stopped by peer ep %02X\n", ep);
 1009:         dev->endpoint[EP2I(ep)].iso_started = 0;
 1010:     }
 1011: }
 1012: 
 1013: static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
 1014:     struct usb_redir_interrupt_receiving_status_header
 1015:     *interrupt_receiving_status)
 1016: {
 1017:     USBRedirDevice *dev = priv;
 1018:     uint8_t ep = interrupt_receiving_status->endpoint;
 1019: 
 1020:     DPRINTF("interrupt recv status %d ep %02X id %u\n",
 1021:             interrupt_receiving_status->status, ep, id);
 1022: 
 1023:     dev->endpoint[EP2I(ep)].interrupt_error =
 1024:         interrupt_receiving_status->status;
 1025:     if (interrupt_receiving_status->status == usb_redir_stall) {
 1026:         DPRINTF("interrupt receiving stopped by peer ep %02X\n", ep);
 1027:         dev->endpoint[EP2I(ep)].interrupt_started = 0;
 1028:     }
 1029: }
 1030: 
 1031: static void usbredir_bulk_streams_status(void *priv, uint32_t id,
 1032:     struct usb_redir_bulk_streams_status_header *bulk_streams_status)
 1033: {
 1034: }
 1035: 
 1036: static void usbredir_control_packet(void *priv, uint32_t id,
 1037:     struct usb_redir_control_packet_header *control_packet,
 1038:     uint8_t *data, int data_len)
 1039: {
 1040:     USBRedirDevice *dev = priv;
 1041:     int len = control_packet->length;
 1042:     AsyncURB *aurb;
 1043: 
 1044:     DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status,
 1045:             len, id);
 1046: 
 1047:     aurb = async_find(dev, id);
 1048:     if (!aurb) {
 1049:         free(data);
 1050:         return;
 1051:     }
 1052: 
 1053:     aurb->control_packet.status = control_packet->status;
 1054:     aurb->control_packet.length = control_packet->length;
 1055:     if (memcmp(&aurb->control_packet, control_packet,
 1056:                sizeof(*control_packet))) {
 1057:         ERROR("return control packet mismatch, please report this!\n");
 1058:         len = USB_RET_NAK;
 1059:     }
 1060: 
 1061:     if (aurb->packet) {
 1062:         len = usbredir_handle_status(dev, control_packet->status, len);
 1063:         if (len > 0) {
 1064:             usbredir_log_data(dev, "ctrl data in:", data, data_len);
 1065:             if (data_len <= sizeof(dev->dev.data_buf)) {
 1066:                 memcpy(dev->dev.data_buf, data, data_len);
 1067:             } else {
 1068:                 ERROR("ctrl buffer too small (%d > %zu)\n",
 1069:                       data_len, sizeof(dev->dev.data_buf));
 1070:                 len = USB_RET_STALL;
 1071:             }
 1072:         }
 1073:         aurb->packet->len = len;
 1074:         usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
 1075:     }
 1076:     async_free(dev, aurb);
 1077:     free(data);
 1078: }
 1079: 
 1080: static void usbredir_bulk_packet(void *priv, uint32_t id,
 1081:     struct usb_redir_bulk_packet_header *bulk_packet,
 1082:     uint8_t *data, int data_len)
 1083: {
 1084:     USBRedirDevice *dev = priv;
 1085:     uint8_t ep = bulk_packet->endpoint;
 1086:     int len = bulk_packet->length;
 1087:     AsyncURB *aurb;
 1088: 
 1089:     DPRINTF("bulk-in status %d ep %02X len %d id %u\n", bulk_packet->status,
 1090:             ep, len, id);
 1091: 
 1092:     aurb = async_find(dev, id);
 1093:     if (!aurb) {
 1094:         free(data);
 1095:         return;
 1096:     }
 1097: 
 1098:     if (aurb->bulk_packet.endpoint != bulk_packet->endpoint ||
 1099:             aurb->bulk_packet.stream_id != bulk_packet->stream_id) {
 1100:         ERROR("return bulk packet mismatch, please report this!\n");
 1101:         len = USB_RET_NAK;
 1102:     }
 1103: 
 1104:     if (aurb->packet) {
 1105:         len = usbredir_handle_status(dev, bulk_packet->status, len);
 1106:         if (len > 0) {
 1107:             usbredir_log_data(dev, "bulk data in:", data, data_len);
 1108:             if (data_len <= aurb->packet->len) {
 1109:                 memcpy(aurb->packet->data, data, data_len);
 1110:             } else {
 1111:                 ERROR("bulk buffer too small (%d > %d)\n", data_len,
 1112:                       aurb->packet->len);
 1113:                 len = USB_RET_STALL;
 1114:             }
 1115:         }
 1116:         aurb->packet->len = len;
 1117:         usb_packet_complete(&dev->dev, aurb->packet);
 1118:     }
 1119:     async_free(dev, aurb);
 1120:     free(data);
 1121: }
 1122: 
 1123: static void usbredir_iso_packet(void *priv, uint32_t id,
 1124:     struct usb_redir_iso_packet_header *iso_packet,
 1125:     uint8_t *data, int data_len)
 1126: {
 1127:     USBRedirDevice *dev = priv;
 1128:     uint8_t ep = iso_packet->endpoint;
 1129: 
 1130:     DPRINTF2("iso-in status %d ep %02X len %d id %u\n", iso_packet->status, ep,
 1131:              data_len, id);
 1132: 
 1133:     if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_ISOC) {
 1134:         ERROR("received iso packet for non iso endpoint %02X\n", ep);
 1135:         free(data);
 1136:         return;
 1137:     }
 1138: 
 1139:     if (dev->endpoint[EP2I(ep)].iso_started == 0) {
 1140:         DPRINTF("received iso packet for non started stream ep %02X\n", ep);
 1141:         free(data);
 1142:         return;
 1143:     }
 1144: 
 1145:     /* bufp_alloc also adds the packet to the ep queue */
 1146:     bufp_alloc(dev, data, data_len, iso_packet->status, ep);
 1147: }
 1148: 
 1149: static void usbredir_interrupt_packet(void *priv, uint32_t id,
 1150:     struct usb_redir_interrupt_packet_header *interrupt_packet,
 1151:     uint8_t *data, int data_len)
 1152: {
 1153:     USBRedirDevice *dev = priv;
 1154:     uint8_t ep = interrupt_packet->endpoint;
 1155: 
 1156:     DPRINTF("interrupt-in status %d ep %02X len %d id %u\n",
 1157:             interrupt_packet->status, ep, data_len, id);
 1158: 
 1159:     if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_INT) {
 1160:         ERROR("received int packet for non interrupt endpoint %02X\n", ep);
 1161:         free(data);
 1162:         return;
 1163:     }
 1164: 
 1165:     if (ep & USB_DIR_IN) {
 1166:         if (dev->endpoint[EP2I(ep)].interrupt_started == 0) {
 1167:             DPRINTF("received int packet while not started ep %02X\n", ep);
 1168:             free(data);
 1169:             return;
 1170:         }
 1171: 
 1172:         /* bufp_alloc also adds the packet to the ep queue */
 1173:         bufp_alloc(dev, data, data_len, interrupt_packet->status, ep);
 1174:     } else {
 1175:         int len = interrupt_packet->length;
 1176: 
 1177:         AsyncURB *aurb = async_find(dev, id);
 1178:         if (!aurb) {
 1179:             return;
 1180:         }
 1181: 
 1182:         if (aurb->interrupt_packet.endpoint != interrupt_packet->endpoint) {
 1183:             ERROR("return int packet mismatch, please report this!\n");
 1184:             len = USB_RET_NAK;
 1185:         }
 1186: 
 1187:         if (aurb->packet) {
 1188:             aurb->packet->len = usbredir_handle_status(dev,
 1189:                                                interrupt_packet->status, len);
 1190:             usb_packet_complete(&dev->dev, aurb->packet);
 1191:         }
 1192:         async_free(dev, aurb);
 1193:     }
 1194: }
 1195: 
 1196: static struct USBDeviceInfo usbredir_dev_info = {
 1197:     .product_desc   = "USB Redirection Device",
 1198:     .qdev.name      = "usb-redir",
 1199:     .qdev.size      = sizeof(USBRedirDevice),
 1200:     .init           = usbredir_initfn,
 1201:     .handle_destroy = usbredir_handle_destroy,
 1202:     .handle_packet  = usb_generic_handle_packet,
 1203:     .cancel_packet  = usbredir_cancel_packet,
 1204:     .handle_reset   = usbredir_handle_reset,
 1205:     .handle_data    = usbredir_handle_data,
 1206:     .handle_control = usbredir_handle_control,
 1207:     .qdev.props     = (Property[]) {
 1208:         DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
 1209:         DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
 1210:         DEFINE_PROP_END_OF_LIST(),
 1211:     },
 1212: };
 1213: 
 1214: static void usbredir_register_devices(void)
 1215: {
 1216:     usb_qdev_register(&usbredir_dev_info);
 1217: }
 1218: device_init(usbredir_register_devices);

unix.superglobalmegacorp.com