e1000: bounds packet size against buffer size
[qemu.git] / usb-redir.c
blobfb91c926a9e53d475b9b54edb19bcca0da19b57d
1 /*
2 * USB redirector usb-guest
4 * Copyright (c) 2011 Red Hat, Inc.
6 * Red Hat Authors:
7 * Hans de Goede <hdegoede@redhat.com>
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:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
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.
28 #include "qemu-common.h"
29 #include "qemu-timer.h"
30 #include "monitor.h"
31 #include "sysemu.h"
33 #include <dirent.h>
34 #include <sys/ioctl.h>
35 #include <signal.h>
36 #include <usbredirparser.h>
38 #include "hw/usb.h"
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))
44 typedef struct AsyncURB AsyncURB;
45 typedef struct USBRedirDevice USBRedirDevice;
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;
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;
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;
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;
95 QTAILQ_ENTRY(AsyncURB)next;
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);
129 static int usbredir_handle_status(USBRedirDevice *dev,
130 int status, int actual_len);
132 #define VERSION "qemu usb-redir guest " QEMU_VERSION
135 * Logging stuff
138 #define ERROR(...) \
139 do { \
140 if (dev->debug >= usbredirparser_error) { \
141 error_report("usb-redir error: " __VA_ARGS__); \
143 } while (0)
144 #define WARNING(...) \
145 do { \
146 if (dev->debug >= usbredirparser_warning) { \
147 error_report("usb-redir warning: " __VA_ARGS__); \
149 } while (0)
150 #define INFO(...) \
151 do { \
152 if (dev->debug >= usbredirparser_info) { \
153 error_report("usb-redir: " __VA_ARGS__); \
155 } while (0)
156 #define DPRINTF(...) \
157 do { \
158 if (dev->debug >= usbredirparser_debug) { \
159 error_report("usb-redir: " __VA_ARGS__); \
161 } while (0)
162 #define DPRINTF2(...) \
163 do { \
164 if (dev->debug >= usbredirparser_debug_data) { \
165 error_report("usb-redir: " __VA_ARGS__); \
167 } while (0)
169 static void usbredir_log(void *priv, int level, const char *msg)
171 USBRedirDevice *dev = priv;
173 if (dev->debug < level) {
174 return;
177 error_report("%s\n", msg);
180 static void usbredir_log_data(USBRedirDevice *dev, const char *desc,
181 const uint8_t *data, int len)
183 int i, j, n;
185 if (dev->debug < usbredirparser_debug_data) {
186 return;
189 for (i = 0; i < len; i += j) {
190 char buf[128];
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]);
196 error_report("%s\n", buf);
201 * usbredirparser io functions
204 static int usbredir_read(void *priv, uint8_t *data, int count)
206 USBRedirDevice *dev = priv;
208 if (dev->read_buf_size < count) {
209 count = dev->read_buf_size;
212 memcpy(data, dev->read_buf, count);
214 dev->read_buf_size -= count;
215 if (dev->read_buf_size) {
216 dev->read_buf += count;
217 } else {
218 dev->read_buf = NULL;
221 return count;
224 static int usbredir_write(void *priv, uint8_t *data, int count)
226 USBRedirDevice *dev = priv;
228 if (!dev->cs->opened) {
229 return 0;
232 return qemu_chr_fe_write(dev->cs, data, count);
236 * Async and buffered packets helpers
239 static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p)
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++;
248 return aurb;
251 static void async_free(USBRedirDevice *dev, AsyncURB *aurb)
253 QTAILQ_REMOVE(&dev->asyncq, aurb, next);
254 g_free(aurb);
257 static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id)
259 AsyncURB *aurb;
261 QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
262 if (aurb->packet_id == packet_id) {
263 return aurb;
266 ERROR("could not find async urb for packet_id %u\n", packet_id);
267 return NULL;
270 static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
272 USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
273 AsyncURB *aurb;
275 QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
276 if (p != aurb->packet) {
277 continue;
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);
284 /* Mark it as dead */
285 aurb->packet = NULL;
286 break;
290 static struct buf_packet *bufp_alloc(USBRedirDevice *dev,
291 uint8_t *data, int len, int status, uint8_t ep)
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;
301 static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp,
302 uint8_t ep)
304 QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
305 free(bufp->data);
306 g_free(bufp);
309 static void usbredir_free_bufpq(USBRedirDevice *dev, uint8_t ep)
311 struct buf_packet *buf, *buf_next;
313 QTAILQ_FOREACH_SAFE(buf, &dev->endpoint[EP2I(ep)].bufpq, next, buf_next) {
314 bufp_free(dev, buf, ep);
319 * USBDevice callbacks
322 static void usbredir_handle_reset(USBDevice *udev)
324 USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
326 DPRINTF("reset device\n");
327 usbredirparser_send_reset(dev->parser);
328 usbredirparser_do_write(dev->parser);
331 static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
332 uint8_t ep)
334 int status, len;
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,
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;
351 if (ep & USB_DIR_IN) {
352 struct buf_packet *isop;
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);
362 DPRINTF2("iso-token-in ep %02X status %d len %d\n", ep, isop->status,
363 isop->len);
365 status = isop->status;
366 if (status != usb_redir_success) {
367 bufp_free(dev, isop, ep);
368 return usbredir_handle_status(dev, status, 0);
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;
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
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);
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);
403 static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep)
405 struct usb_redir_stop_iso_stream_header stop_iso_stream = {
406 .endpoint = ep
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;
413 usbredir_free_bufpq(dev, ep);
416 static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
417 uint8_t ep)
419 AsyncURB *aurb = async_alloc(dev, p);
420 struct usb_redir_bulk_packet_header bulk_packet;
422 DPRINTF("bulk-out ep %02X len %zd id %u\n", ep,
423 p->iov.size, aurb->packet_id);
425 bulk_packet.endpoint = ep;
426 bulk_packet.length = p->iov.size;
427 bulk_packet.stream_id = 0;
428 aurb->bulk_packet = bulk_packet;
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);
440 usbredirparser_do_write(dev->parser);
441 return USB_RET_ASYNC;
444 static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
445 USBPacket *p, uint8_t ep)
447 if (ep & USB_DIR_IN) {
448 /* Input interrupt endpoint, buffered packet input */
449 struct buf_packet *intp;
450 int status, len;
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,
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;
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);
473 DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
474 intp->status, intp->len);
476 status = intp->status;
477 if (status != usb_redir_success) {
478 bufp_free(dev, intp, ep);
479 return usbredir_handle_status(dev, status, 0);
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;
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];
497 DPRINTF("interrupt-out ep %02X len %zd id %u\n", ep, p->iov.size,
498 aurb->packet_id);
500 interrupt_packet.endpoint = ep;
501 interrupt_packet.length = p->iov.size;
502 aurb->interrupt_packet = interrupt_packet;
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;
513 static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev,
514 uint8_t ep)
516 struct usb_redir_stop_interrupt_receiving_header stop_interrupt_recv = {
517 .endpoint = ep
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;
525 usbredir_free_bufpq(dev, ep);
528 static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
530 USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
531 uint8_t ep;
533 ep = p->devep;
534 if (p->pid == USB_TOKEN_IN) {
535 ep |= USB_DIR_IN;
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;
555 static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
556 int config)
558 struct usb_redir_set_configuration_header set_config;
559 AsyncURB *aurb = async_alloc(dev, p);
560 int i;
562 DPRINTF("set config %d id %u\n", config, aurb->packet_id);
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));
573 break;
575 usbredir_free_bufpq(dev, I2EP(i));
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;
585 static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
587 AsyncURB *aurb = async_alloc(dev, p);
589 DPRINTF("get config id %u\n", aurb->packet_id);
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;
597 static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
598 int interface, int alt)
600 struct usb_redir_set_alt_setting_header set_alt;
601 AsyncURB *aurb = async_alloc(dev, p);
602 int i;
604 DPRINTF("set interface %d alt %d id %u\n", interface, alt,
605 aurb->packet_id);
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));
617 break;
619 usbredir_free_bufpq(dev, I2EP(i));
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;
631 static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
632 int interface)
634 struct usb_redir_get_alt_setting_header get_alt;
635 AsyncURB *aurb = async_alloc(dev, p);
637 DPRINTF("get interface %d id %u\n", interface, aurb->packet_id);
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;
647 static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
648 int request, int value, int index, int length, uint8_t *data)
650 USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
651 struct usb_redir_control_packet_header control_packet;
652 AsyncURB *aurb;
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);
670 /* "Normal" ctrl requests */
671 aurb = async_alloc(dev, p);
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);
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;
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);
694 usbredirparser_do_write(dev->parser);
695 return USB_RET_ASYNC;
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.
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.
707 static void usbredir_open_close_bh(void *opaque)
709 USBRedirDevice *dev = opaque;
711 usbredir_device_disconnect(dev);
713 if (dev->parser) {
714 usbredirparser_destroy(dev->parser);
715 dev->parser = NULL;
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);
745 static void usbredir_do_attach(void *opaque)
747 USBRedirDevice *dev = opaque;
749 usb_device_attach(&dev->dev);
753 * chardev callbacks
756 static int usbredir_chardev_can_read(void *opaque)
758 USBRedirDevice *dev = opaque;
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;
769 static void usbredir_chardev_read(void *opaque, const uint8_t *buf, int size)
771 USBRedirDevice *dev = opaque;
773 /* No recursion allowed! */
774 assert(dev->read_buf == NULL);
776 dev->read_buf = buf;
777 dev->read_buf_size = size;
779 usbredirparser_do_read(dev->parser);
780 /* Send any acks, etc. which may be queued now */
781 usbredirparser_do_write(dev->parser);
784 static void usbredir_chardev_event(void *opaque, int event)
786 USBRedirDevice *dev = opaque;
788 switch (event) {
789 case CHR_EVENT_OPENED:
790 case CHR_EVENT_CLOSED:
791 qemu_bh_schedule(dev->open_close_bh);
792 break;
797 * init + destroy
800 static int usbredir_initfn(USBDevice *udev)
802 USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
803 int i;
805 if (dev->cs == NULL) {
806 qerror_report(QERR_MISSING_PARAMETER, "chardev");
807 return -1;
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);
813 QTAILQ_INIT(&dev->asyncq);
814 for (i = 0; i < MAX_ENDPOINTS; i++) {
815 QTAILQ_INIT(&dev->endpoint[i].bufpq);
818 /* We'll do the attach once we receive the speed from the usb-host */
819 udev->auto_attach = 0;
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);
826 return 0;
829 static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
831 AsyncURB *aurb, *next_aurb;
832 int i;
834 QTAILQ_FOREACH_SAFE(aurb, &dev->asyncq, next, next_aurb) {
835 async_free(dev, aurb);
837 for (i = 0; i < MAX_ENDPOINTS; i++) {
838 usbredir_free_bufpq(dev, I2EP(i));
842 static void usbredir_handle_destroy(USBDevice *udev)
844 USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
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);
851 qemu_del_timer(dev->attach_timer);
852 qemu_free_timer(dev->attach_timer);
854 usbredir_cleanup_device_queues(dev);
856 if (dev->parser) {
857 usbredirparser_destroy(dev->parser);
862 * usbredirparser packet complete callbacks
865 static int usbredir_handle_status(USBRedirDevice *dev,
866 int status, int actual_len)
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;
883 static void usbredir_device_connect(void *priv,
884 struct usb_redir_device_connect_header *device_connect)
886 USBRedirDevice *dev = priv;
888 if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
889 ERROR("Received device connect while already connected\n");
890 return;
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;
914 dev->dev.speedmask = (1 << dev->dev.speed);
915 qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
918 static void usbredir_device_disconnect(void *priv)
920 USBRedirDevice *dev = priv;
921 int i;
923 /* Stop any pending attaches */
924 qemu_del_timer(dev->attach_timer);
926 if (dev->dev.attached) {
927 usb_device_detach(&dev->dev);
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
932 dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200;
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);
943 static void usbredir_interface_info(void *priv,
944 struct usb_redir_interface_info_header *interface_info)
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 */
952 static void usbredir_ep_info(void *priv,
953 struct usb_redir_ep_info_header *ep_info)
955 USBRedirDevice *dev = priv;
956 int i;
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);
969 static void usbredir_configuration_status(void *priv, uint32_t id,
970 struct usb_redir_configuration_status_header *config_status)
972 USBRedirDevice *dev = priv;
973 AsyncURB *aurb;
974 int len = 0;
976 DPRINTF("set config status %d config %d id %u\n", config_status->status,
977 config_status->configuration, id);
979 aurb = async_find(dev, id);
980 if (!aurb) {
981 return;
983 if (aurb->packet) {
984 if (aurb->get) {
985 dev->dev.data_buf[0] = config_status->configuration;
986 len = 1;
988 aurb->packet->result =
989 usbredir_handle_status(dev, config_status->status, len);
990 usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
992 async_free(dev, aurb);
995 static void usbredir_alt_setting_status(void *priv, uint32_t id,
996 struct usb_redir_alt_setting_status_header *alt_setting_status)
998 USBRedirDevice *dev = priv;
999 AsyncURB *aurb;
1000 int len = 0;
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);
1007 aurb = async_find(dev, id);
1008 if (!aurb) {
1009 return;
1011 if (aurb->packet) {
1012 if (aurb->get) {
1013 dev->dev.data_buf[0] = alt_setting_status->alt;
1014 len = 1;
1016 aurb->packet->result =
1017 usbredir_handle_status(dev, alt_setting_status->status, len);
1018 usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
1020 async_free(dev, aurb);
1023 static void usbredir_iso_stream_status(void *priv, uint32_t id,
1024 struct usb_redir_iso_stream_status_header *iso_stream_status)
1026 USBRedirDevice *dev = priv;
1027 uint8_t ep = iso_stream_status->endpoint;
1029 DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status,
1030 ep, id);
1032 if (!dev->dev.attached) {
1033 return;
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;
1043 static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
1044 struct usb_redir_interrupt_receiving_status_header
1045 *interrupt_receiving_status)
1047 USBRedirDevice *dev = priv;
1048 uint8_t ep = interrupt_receiving_status->endpoint;
1050 DPRINTF("interrupt recv status %d ep %02X id %u\n",
1051 interrupt_receiving_status->status, ep, id);
1053 if (!dev->dev.attached) {
1054 return;
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;
1065 static void usbredir_bulk_streams_status(void *priv, uint32_t id,
1066 struct usb_redir_bulk_streams_status_header *bulk_streams_status)
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)
1074 USBRedirDevice *dev = priv;
1075 int len = control_packet->length;
1076 AsyncURB *aurb;
1078 DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status,
1079 len, id);
1081 aurb = async_find(dev, id);
1082 if (!aurb) {
1083 free(data);
1084 return;
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;
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;
1107 aurb->packet->result = len;
1108 usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
1110 async_free(dev, aurb);
1111 free(data);
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)
1118 USBRedirDevice *dev = priv;
1119 uint8_t ep = bulk_packet->endpoint;
1120 int len = bulk_packet->length;
1121 AsyncURB *aurb;
1123 DPRINTF("bulk-in status %d ep %02X len %d id %u\n", bulk_packet->status,
1124 ep, len, id);
1126 aurb = async_find(dev, id);
1127 if (!aurb) {
1128 free(data);
1129 return;
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;
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;
1150 aurb->packet->result = len;
1151 usb_packet_complete(&dev->dev, aurb->packet);
1153 async_free(dev, aurb);
1154 free(data);
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)
1161 USBRedirDevice *dev = priv;
1162 uint8_t ep = iso_packet->endpoint;
1164 DPRINTF2("iso-in status %d ep %02X len %d id %u\n", iso_packet->status, ep,
1165 data_len, id);
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;
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;
1179 /* bufp_alloc also adds the packet to the ep queue */
1180 bufp_alloc(dev, data, data_len, iso_packet->status, ep);
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)
1187 USBRedirDevice *dev = priv;
1188 uint8_t ep = interrupt_packet->endpoint;
1190 DPRINTF("interrupt-in status %d ep %02X len %d id %u\n",
1191 interrupt_packet->status, ep, data_len, id);
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;
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;
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;
1211 AsyncURB *aurb = async_find(dev, id);
1212 if (!aurb) {
1213 return;
1216 if (aurb->interrupt_packet.endpoint != interrupt_packet->endpoint) {
1217 ERROR("return int packet mismatch, please report this!\n");
1218 len = USB_RET_NAK;
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);
1226 async_free(dev, aurb);
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(),
1248 static void usbredir_register_devices(void)
1250 usb_qdev_register(&usbredir_dev_info);
1252 device_init(usbredir_register_devices);