slavio_intctl: avoid structure holes spotted by pahole
[qemu/mdroth.git] / usb-redir.c
blob3fbbcfff97a5a9d9510a01d7f60919e29801f9f0
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 return qemu_chr_write(dev->cs, data, count);
232 * Async and buffered packets helpers
235 static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p)
237 AsyncURB *aurb = (AsyncURB *) g_malloc0(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++;
244 return aurb;
247 static void async_free(USBRedirDevice *dev, AsyncURB *aurb)
249 QTAILQ_REMOVE(&dev->asyncq, aurb, next);
250 g_free(aurb);
253 static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id)
255 AsyncURB *aurb;
257 QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
258 if (aurb->packet_id == packet_id) {
259 return aurb;
262 ERROR("could not find async urb for packet_id %u\n", packet_id);
263 return NULL;
266 static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
268 USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
269 AsyncURB *aurb;
271 QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
272 if (p != aurb->packet) {
273 continue;
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);
280 /* Mark it as dead */
281 aurb->packet = NULL;
282 break;
286 static struct buf_packet *bufp_alloc(USBRedirDevice *dev,
287 uint8_t *data, int len, int status, uint8_t ep)
289 struct buf_packet *bufp = g_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;
297 static void bufp_free(USBRedirDevice *dev, struct buf_packet *bufp,
298 uint8_t ep)
300 QTAILQ_REMOVE(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
301 free(bufp->data);
302 g_free(bufp);
305 static void usbredir_free_bufpq(USBRedirDevice *dev, uint8_t ep)
307 struct buf_packet *buf, *buf_next;
309 QTAILQ_FOREACH_SAFE(buf, &dev->endpoint[EP2I(ep)].bufpq, next, buf_next) {
310 bufp_free(dev, buf, ep);
315 * USBDevice callbacks
318 static void usbredir_handle_reset(USBDevice *udev)
320 USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
322 DPRINTF("reset device\n");
323 usbredirparser_send_reset(dev->parser);
324 usbredirparser_do_write(dev->parser);
327 static int usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
328 uint8_t ep)
330 int status, len;
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,
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;
347 if (ep & USB_DIR_IN) {
348 struct buf_packet *isop;
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);
358 DPRINTF2("iso-token-in ep %02X status %d len %d\n", ep, isop->status,
359 isop->len);
361 status = isop->status;
362 if (status != usb_redir_success) {
363 bufp_free(dev, isop, ep);
364 return usbredir_handle_status(dev, status, 0);
367 len = isop->len;
368 if (len > p->iov.size) {
369 ERROR("received iso data is larger then packet ep %02X\n", ep);
370 bufp_free(dev, isop, ep);
371 return USB_RET_NAK;
373 usb_packet_copy(p, 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->iov.size
384 uint8_t buf[p->iov.size];
385 /* No id, we look at the ep when receiving a status back */
386 usb_packet_copy(p, buf, p->iov.size);
387 usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet,
388 buf, p->iov.size);
389 usbredirparser_do_write(dev->parser);
391 status = dev->endpoint[EP2I(ep)].iso_error;
392 dev->endpoint[EP2I(ep)].iso_error = 0;
393 DPRINTF2("iso-token-out ep %02X status %d len %zd\n", ep, status,
394 p->iov.size);
395 return usbredir_handle_status(dev, status, p->iov.size);
399 static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep)
401 struct usb_redir_stop_iso_stream_header stop_iso_stream = {
402 .endpoint = ep
404 if (dev->endpoint[EP2I(ep)].iso_started) {
405 usbredirparser_send_stop_iso_stream(dev->parser, 0, &stop_iso_stream);
406 DPRINTF("iso stream stopped ep %02X\n", ep);
407 dev->endpoint[EP2I(ep)].iso_started = 0;
409 usbredir_free_bufpq(dev, ep);
412 static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
413 uint8_t ep)
415 AsyncURB *aurb = async_alloc(dev, p);
416 struct usb_redir_bulk_packet_header bulk_packet;
418 DPRINTF("bulk-out ep %02X len %zd id %u\n", ep,
419 p->iov.size, aurb->packet_id);
421 bulk_packet.endpoint = ep;
422 bulk_packet.length = p->iov.size;
423 bulk_packet.stream_id = 0;
424 aurb->bulk_packet = bulk_packet;
426 if (ep & USB_DIR_IN) {
427 usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
428 &bulk_packet, NULL, 0);
429 } else {
430 uint8_t buf[p->iov.size];
431 usb_packet_copy(p, buf, p->iov.size);
432 usbredir_log_data(dev, "bulk data out:", buf, p->iov.size);
433 usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
434 &bulk_packet, buf, p->iov.size);
436 usbredirparser_do_write(dev->parser);
437 return USB_RET_ASYNC;
440 static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
441 USBPacket *p, uint8_t ep)
443 if (ep & USB_DIR_IN) {
444 /* Input interrupt endpoint, buffered packet input */
445 struct buf_packet *intp;
446 int status, len;
448 if (!dev->endpoint[EP2I(ep)].interrupt_started &&
449 !dev->endpoint[EP2I(ep)].interrupt_error) {
450 struct usb_redir_start_interrupt_receiving_header start_int = {
451 .endpoint = ep,
453 /* No id, we look at the ep when receiving a status back */
454 usbredirparser_send_start_interrupt_receiving(dev->parser, 0,
455 &start_int);
456 usbredirparser_do_write(dev->parser);
457 DPRINTF("interrupt recv started ep %02X\n", ep);
458 dev->endpoint[EP2I(ep)].interrupt_started = 1;
461 intp = QTAILQ_FIRST(&dev->endpoint[EP2I(ep)].bufpq);
462 if (intp == NULL) {
463 DPRINTF2("interrupt-token-in ep %02X, no intp\n", ep);
464 /* Check interrupt_error for stream errors */
465 status = dev->endpoint[EP2I(ep)].interrupt_error;
466 dev->endpoint[EP2I(ep)].interrupt_error = 0;
467 return usbredir_handle_status(dev, status, 0);
469 DPRINTF("interrupt-token-in ep %02X status %d len %d\n", ep,
470 intp->status, intp->len);
472 status = intp->status;
473 if (status != usb_redir_success) {
474 bufp_free(dev, intp, ep);
475 return usbredir_handle_status(dev, status, 0);
478 len = intp->len;
479 if (len > p->iov.size) {
480 ERROR("received int data is larger then packet ep %02X\n", ep);
481 bufp_free(dev, intp, ep);
482 return USB_RET_NAK;
484 usb_packet_copy(p, intp->data, len);
485 bufp_free(dev, intp, ep);
486 return len;
487 } else {
488 /* Output interrupt endpoint, normal async operation */
489 AsyncURB *aurb = async_alloc(dev, p);
490 struct usb_redir_interrupt_packet_header interrupt_packet;
491 uint8_t buf[p->iov.size];
493 DPRINTF("interrupt-out ep %02X len %zd id %u\n", ep, p->iov.size,
494 aurb->packet_id);
496 interrupt_packet.endpoint = ep;
497 interrupt_packet.length = p->iov.size;
498 aurb->interrupt_packet = interrupt_packet;
500 usb_packet_copy(p, buf, p->iov.size);
501 usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size);
502 usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id,
503 &interrupt_packet, buf, p->iov.size);
504 usbredirparser_do_write(dev->parser);
505 return USB_RET_ASYNC;
509 static void usbredir_stop_interrupt_receiving(USBRedirDevice *dev,
510 uint8_t ep)
512 struct usb_redir_stop_interrupt_receiving_header stop_interrupt_recv = {
513 .endpoint = ep
515 if (dev->endpoint[EP2I(ep)].interrupt_started) {
516 usbredirparser_send_stop_interrupt_receiving(dev->parser, 0,
517 &stop_interrupt_recv);
518 DPRINTF("interrupt recv stopped ep %02X\n", ep);
519 dev->endpoint[EP2I(ep)].interrupt_started = 0;
521 usbredir_free_bufpq(dev, ep);
524 static int usbredir_handle_data(USBDevice *udev, USBPacket *p)
526 USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
527 uint8_t ep;
529 ep = p->devep;
530 if (p->pid == USB_TOKEN_IN) {
531 ep |= USB_DIR_IN;
534 switch (dev->endpoint[EP2I(ep)].type) {
535 case USB_ENDPOINT_XFER_CONTROL:
536 ERROR("handle_data called for control transfer on ep %02X\n", ep);
537 return USB_RET_NAK;
538 case USB_ENDPOINT_XFER_ISOC:
539 return usbredir_handle_iso_data(dev, p, ep);
540 case USB_ENDPOINT_XFER_BULK:
541 return usbredir_handle_bulk_data(dev, p, ep);;
542 case USB_ENDPOINT_XFER_INT:
543 return usbredir_handle_interrupt_data(dev, p, ep);;
544 default:
545 ERROR("handle_data ep %02X has unknown type %d\n", ep,
546 dev->endpoint[EP2I(ep)].type);
547 return USB_RET_NAK;
551 static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
552 int config)
554 struct usb_redir_set_configuration_header set_config;
555 AsyncURB *aurb = async_alloc(dev, p);
556 int i;
558 DPRINTF("set config %d id %u\n", config, aurb->packet_id);
560 for (i = 0; i < MAX_ENDPOINTS; i++) {
561 switch (dev->endpoint[i].type) {
562 case USB_ENDPOINT_XFER_ISOC:
563 usbredir_stop_iso_stream(dev, I2EP(i));
564 break;
565 case USB_ENDPOINT_XFER_INT:
566 if (i & 0x10) {
567 usbredir_stop_interrupt_receiving(dev, I2EP(i));
569 break;
571 usbredir_free_bufpq(dev, I2EP(i));
574 set_config.configuration = config;
575 usbredirparser_send_set_configuration(dev->parser, aurb->packet_id,
576 &set_config);
577 usbredirparser_do_write(dev->parser);
578 return USB_RET_ASYNC;
581 static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
583 AsyncURB *aurb = async_alloc(dev, p);
585 DPRINTF("get config id %u\n", aurb->packet_id);
587 aurb->get = 1;
588 usbredirparser_send_get_configuration(dev->parser, aurb->packet_id);
589 usbredirparser_do_write(dev->parser);
590 return USB_RET_ASYNC;
593 static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
594 int interface, int alt)
596 struct usb_redir_set_alt_setting_header set_alt;
597 AsyncURB *aurb = async_alloc(dev, p);
598 int i;
600 DPRINTF("set interface %d alt %d id %u\n", interface, alt,
601 aurb->packet_id);
603 for (i = 0; i < MAX_ENDPOINTS; i++) {
604 if (dev->endpoint[i].interface == interface) {
605 switch (dev->endpoint[i].type) {
606 case USB_ENDPOINT_XFER_ISOC:
607 usbredir_stop_iso_stream(dev, I2EP(i));
608 break;
609 case USB_ENDPOINT_XFER_INT:
610 if (i & 0x10) {
611 usbredir_stop_interrupt_receiving(dev, I2EP(i));
613 break;
615 usbredir_free_bufpq(dev, I2EP(i));
619 set_alt.interface = interface;
620 set_alt.alt = alt;
621 usbredirparser_send_set_alt_setting(dev->parser, aurb->packet_id,
622 &set_alt);
623 usbredirparser_do_write(dev->parser);
624 return USB_RET_ASYNC;
627 static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
628 int interface)
630 struct usb_redir_get_alt_setting_header get_alt;
631 AsyncURB *aurb = async_alloc(dev, p);
633 DPRINTF("get interface %d id %u\n", interface, aurb->packet_id);
635 get_alt.interface = interface;
636 aurb->get = 1;
637 usbredirparser_send_get_alt_setting(dev->parser, aurb->packet_id,
638 &get_alt);
639 usbredirparser_do_write(dev->parser);
640 return USB_RET_ASYNC;
643 static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
644 int request, int value, int index, int length, uint8_t *data)
646 USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
647 struct usb_redir_control_packet_header control_packet;
648 AsyncURB *aurb;
650 /* Special cases for certain standard device requests */
651 switch (request) {
652 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
653 DPRINTF("set address %d\n", value);
654 dev->dev.addr = value;
655 return 0;
656 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
657 return usbredir_set_config(dev, p, value & 0xff);
658 case DeviceRequest | USB_REQ_GET_CONFIGURATION:
659 return usbredir_get_config(dev, p);
660 case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
661 return usbredir_set_interface(dev, p, index, value);
662 case InterfaceRequest | USB_REQ_GET_INTERFACE:
663 return usbredir_get_interface(dev, p, index);
666 /* "Normal" ctrl requests */
667 aurb = async_alloc(dev, p);
669 /* Note request is (bRequestType << 8) | bRequest */
670 DPRINTF("ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %u\n",
671 request >> 8, request & 0xff, value, index, length,
672 aurb->packet_id);
674 control_packet.request = request & 0xFF;
675 control_packet.requesttype = request >> 8;
676 control_packet.endpoint = control_packet.requesttype & USB_DIR_IN;
677 control_packet.value = value;
678 control_packet.index = index;
679 control_packet.length = length;
680 aurb->control_packet = control_packet;
682 if (control_packet.requesttype & USB_DIR_IN) {
683 usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
684 &control_packet, NULL, 0);
685 } else {
686 usbredir_log_data(dev, "ctrl data out:", data, length);
687 usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
688 &control_packet, data, length);
690 usbredirparser_do_write(dev->parser);
691 return USB_RET_ASYNC;
695 * Close events can be triggered by usbredirparser_do_write which gets called
696 * from within the USBDevice data / control packet callbacks and doing a
697 * usb_detach from within these callbacks is not a good idea.
699 * So we use a bh handler to take care of close events. We also handle
700 * open events from this callback to make sure that a close directly followed
701 * by an open gets handled in the right order.
703 static void usbredir_open_close_bh(void *opaque)
705 USBRedirDevice *dev = opaque;
707 usbredir_device_disconnect(dev);
709 if (dev->parser) {
710 usbredirparser_destroy(dev->parser);
711 dev->parser = NULL;
714 if (dev->cs->opened) {
715 dev->parser = qemu_oom_check(usbredirparser_create());
716 dev->parser->priv = dev;
717 dev->parser->log_func = usbredir_log;
718 dev->parser->read_func = usbredir_read;
719 dev->parser->write_func = usbredir_write;
720 dev->parser->device_connect_func = usbredir_device_connect;
721 dev->parser->device_disconnect_func = usbredir_device_disconnect;
722 dev->parser->interface_info_func = usbredir_interface_info;
723 dev->parser->ep_info_func = usbredir_ep_info;
724 dev->parser->configuration_status_func = usbredir_configuration_status;
725 dev->parser->alt_setting_status_func = usbredir_alt_setting_status;
726 dev->parser->iso_stream_status_func = usbredir_iso_stream_status;
727 dev->parser->interrupt_receiving_status_func =
728 usbredir_interrupt_receiving_status;
729 dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status;
730 dev->parser->control_packet_func = usbredir_control_packet;
731 dev->parser->bulk_packet_func = usbredir_bulk_packet;
732 dev->parser->iso_packet_func = usbredir_iso_packet;
733 dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
734 dev->read_buf = NULL;
735 dev->read_buf_size = 0;
736 usbredirparser_init(dev->parser, VERSION, NULL, 0, 0);
737 usbredirparser_do_write(dev->parser);
741 static void usbredir_do_attach(void *opaque)
743 USBRedirDevice *dev = opaque;
745 usb_device_attach(&dev->dev);
749 * chardev callbacks
752 static int usbredir_chardev_can_read(void *opaque)
754 USBRedirDevice *dev = opaque;
756 if (dev->parser) {
757 /* usbredir_parser_do_read will consume *all* data we give it */
758 return 1024 * 1024;
759 } else {
760 /* usbredir_open_close_bh hasn't handled the open event yet */
761 return 0;
765 static void usbredir_chardev_read(void *opaque, const uint8_t *buf, int size)
767 USBRedirDevice *dev = opaque;
769 /* No recursion allowed! */
770 assert(dev->read_buf == NULL);
772 dev->read_buf = buf;
773 dev->read_buf_size = size;
775 usbredirparser_do_read(dev->parser);
776 /* Send any acks, etc. which may be queued now */
777 usbredirparser_do_write(dev->parser);
780 static void usbredir_chardev_event(void *opaque, int event)
782 USBRedirDevice *dev = opaque;
784 switch (event) {
785 case CHR_EVENT_OPENED:
786 case CHR_EVENT_CLOSED:
787 qemu_bh_schedule(dev->open_close_bh);
788 break;
793 * init + destroy
796 static int usbredir_initfn(USBDevice *udev)
798 USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
799 int i;
801 if (dev->cs == NULL) {
802 qerror_report(QERR_MISSING_PARAMETER, "chardev");
803 return -1;
806 dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
807 dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
809 QTAILQ_INIT(&dev->asyncq);
810 for (i = 0; i < MAX_ENDPOINTS; i++) {
811 QTAILQ_INIT(&dev->endpoint[i].bufpq);
814 /* We'll do the attach once we receive the speed from the usb-host */
815 udev->auto_attach = 0;
817 qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
818 usbredir_chardev_read, usbredir_chardev_event, dev);
820 return 0;
823 static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
825 AsyncURB *aurb, *next_aurb;
826 int i;
828 QTAILQ_FOREACH_SAFE(aurb, &dev->asyncq, next, next_aurb) {
829 async_free(dev, aurb);
831 for (i = 0; i < MAX_ENDPOINTS; i++) {
832 usbredir_free_bufpq(dev, I2EP(i));
836 static void usbredir_handle_destroy(USBDevice *udev)
838 USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
840 qemu_chr_close(dev->cs);
841 /* Note must be done after qemu_chr_close, as that causes a close event */
842 qemu_bh_delete(dev->open_close_bh);
844 qemu_del_timer(dev->attach_timer);
845 qemu_free_timer(dev->attach_timer);
847 usbredir_cleanup_device_queues(dev);
849 if (dev->parser) {
850 usbredirparser_destroy(dev->parser);
855 * usbredirparser packet complete callbacks
858 static int usbredir_handle_status(USBRedirDevice *dev,
859 int status, int actual_len)
861 switch (status) {
862 case usb_redir_success:
863 return actual_len;
864 case usb_redir_stall:
865 return USB_RET_STALL;
866 case usb_redir_cancelled:
867 WARNING("returning cancelled packet to HC?\n");
868 case usb_redir_inval:
869 case usb_redir_ioerror:
870 case usb_redir_timeout:
871 default:
872 return USB_RET_NAK;
876 static void usbredir_device_connect(void *priv,
877 struct usb_redir_device_connect_header *device_connect)
879 USBRedirDevice *dev = priv;
881 switch (device_connect->speed) {
882 case usb_redir_speed_low:
883 DPRINTF("attaching low speed device\n");
884 dev->dev.speed = USB_SPEED_LOW;
885 break;
886 case usb_redir_speed_full:
887 DPRINTF("attaching full speed device\n");
888 dev->dev.speed = USB_SPEED_FULL;
889 break;
890 case usb_redir_speed_high:
891 DPRINTF("attaching high speed device\n");
892 dev->dev.speed = USB_SPEED_HIGH;
893 break;
894 case usb_redir_speed_super:
895 DPRINTF("attaching super speed device\n");
896 dev->dev.speed = USB_SPEED_SUPER;
897 break;
898 default:
899 DPRINTF("attaching unknown speed device, assuming full speed\n");
900 dev->dev.speed = USB_SPEED_FULL;
902 dev->dev.speedmask = (1 << dev->dev.speed);
903 qemu_mod_timer(dev->attach_timer, dev->next_attach_time);
906 static void usbredir_device_disconnect(void *priv)
908 USBRedirDevice *dev = priv;
910 /* Stop any pending attaches */
911 qemu_del_timer(dev->attach_timer);
913 if (dev->dev.attached) {
914 usb_device_detach(&dev->dev);
915 usbredir_cleanup_device_queues(dev);
917 * Delay next usb device attach to give the guest a chance to see
918 * see the detach / attach in case of quick close / open succession
920 dev->next_attach_time = qemu_get_clock_ms(vm_clock) + 200;
924 static void usbredir_interface_info(void *priv,
925 struct usb_redir_interface_info_header *interface_info)
927 /* The intention is to allow specifying acceptable interface classes
928 for redirection on the cmdline and in the future verify this here,
929 and disconnect (or never connect) the device if a not accepted
930 interface class is detected */
933 static void usbredir_ep_info(void *priv,
934 struct usb_redir_ep_info_header *ep_info)
936 USBRedirDevice *dev = priv;
937 int i;
939 for (i = 0; i < MAX_ENDPOINTS; i++) {
940 dev->endpoint[i].type = ep_info->type[i];
941 dev->endpoint[i].interval = ep_info->interval[i];
942 dev->endpoint[i].interface = ep_info->interface[i];
943 if (dev->endpoint[i].type != usb_redir_type_invalid) {
944 DPRINTF("ep: %02X type: %d interface: %d\n", I2EP(i),
945 dev->endpoint[i].type, dev->endpoint[i].interface);
950 static void usbredir_configuration_status(void *priv, uint32_t id,
951 struct usb_redir_configuration_status_header *config_status)
953 USBRedirDevice *dev = priv;
954 AsyncURB *aurb;
955 int len = 0;
957 DPRINTF("set config status %d config %d id %u\n", config_status->status,
958 config_status->configuration, id);
960 aurb = async_find(dev, id);
961 if (!aurb) {
962 return;
964 if (aurb->packet) {
965 if (aurb->get) {
966 dev->dev.data_buf[0] = config_status->configuration;
967 len = 1;
969 aurb->packet->result =
970 usbredir_handle_status(dev, config_status->status, len);
971 usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
973 async_free(dev, aurb);
976 static void usbredir_alt_setting_status(void *priv, uint32_t id,
977 struct usb_redir_alt_setting_status_header *alt_setting_status)
979 USBRedirDevice *dev = priv;
980 AsyncURB *aurb;
981 int len = 0;
983 DPRINTF("alt status %d intf %d alt %d id: %u\n",
984 alt_setting_status->status,
985 alt_setting_status->interface,
986 alt_setting_status->alt, id);
988 aurb = async_find(dev, id);
989 if (!aurb) {
990 return;
992 if (aurb->packet) {
993 if (aurb->get) {
994 dev->dev.data_buf[0] = alt_setting_status->alt;
995 len = 1;
997 aurb->packet->result =
998 usbredir_handle_status(dev, alt_setting_status->status, len);
999 usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
1001 async_free(dev, aurb);
1004 static void usbredir_iso_stream_status(void *priv, uint32_t id,
1005 struct usb_redir_iso_stream_status_header *iso_stream_status)
1007 USBRedirDevice *dev = priv;
1008 uint8_t ep = iso_stream_status->endpoint;
1010 DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status,
1011 ep, id);
1013 dev->endpoint[EP2I(ep)].iso_error = iso_stream_status->status;
1014 if (iso_stream_status->status == usb_redir_stall) {
1015 DPRINTF("iso stream stopped by peer ep %02X\n", ep);
1016 dev->endpoint[EP2I(ep)].iso_started = 0;
1020 static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
1021 struct usb_redir_interrupt_receiving_status_header
1022 *interrupt_receiving_status)
1024 USBRedirDevice *dev = priv;
1025 uint8_t ep = interrupt_receiving_status->endpoint;
1027 DPRINTF("interrupt recv status %d ep %02X id %u\n",
1028 interrupt_receiving_status->status, ep, id);
1030 dev->endpoint[EP2I(ep)].interrupt_error =
1031 interrupt_receiving_status->status;
1032 if (interrupt_receiving_status->status == usb_redir_stall) {
1033 DPRINTF("interrupt receiving stopped by peer ep %02X\n", ep);
1034 dev->endpoint[EP2I(ep)].interrupt_started = 0;
1038 static void usbredir_bulk_streams_status(void *priv, uint32_t id,
1039 struct usb_redir_bulk_streams_status_header *bulk_streams_status)
1043 static void usbredir_control_packet(void *priv, uint32_t id,
1044 struct usb_redir_control_packet_header *control_packet,
1045 uint8_t *data, int data_len)
1047 USBRedirDevice *dev = priv;
1048 int len = control_packet->length;
1049 AsyncURB *aurb;
1051 DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status,
1052 len, id);
1054 aurb = async_find(dev, id);
1055 if (!aurb) {
1056 free(data);
1057 return;
1060 aurb->control_packet.status = control_packet->status;
1061 aurb->control_packet.length = control_packet->length;
1062 if (memcmp(&aurb->control_packet, control_packet,
1063 sizeof(*control_packet))) {
1064 ERROR("return control packet mismatch, please report this!\n");
1065 len = USB_RET_NAK;
1068 if (aurb->packet) {
1069 len = usbredir_handle_status(dev, control_packet->status, len);
1070 if (len > 0) {
1071 usbredir_log_data(dev, "ctrl data in:", data, data_len);
1072 if (data_len <= sizeof(dev->dev.data_buf)) {
1073 memcpy(dev->dev.data_buf, data, data_len);
1074 } else {
1075 ERROR("ctrl buffer too small (%d > %zu)\n",
1076 data_len, sizeof(dev->dev.data_buf));
1077 len = USB_RET_STALL;
1080 aurb->packet->result = len;
1081 usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
1083 async_free(dev, aurb);
1084 free(data);
1087 static void usbredir_bulk_packet(void *priv, uint32_t id,
1088 struct usb_redir_bulk_packet_header *bulk_packet,
1089 uint8_t *data, int data_len)
1091 USBRedirDevice *dev = priv;
1092 uint8_t ep = bulk_packet->endpoint;
1093 int len = bulk_packet->length;
1094 AsyncURB *aurb;
1096 DPRINTF("bulk-in status %d ep %02X len %d id %u\n", bulk_packet->status,
1097 ep, len, id);
1099 aurb = async_find(dev, id);
1100 if (!aurb) {
1101 free(data);
1102 return;
1105 if (aurb->bulk_packet.endpoint != bulk_packet->endpoint ||
1106 aurb->bulk_packet.stream_id != bulk_packet->stream_id) {
1107 ERROR("return bulk packet mismatch, please report this!\n");
1108 len = USB_RET_NAK;
1111 if (aurb->packet) {
1112 len = usbredir_handle_status(dev, bulk_packet->status, len);
1113 if (len > 0) {
1114 usbredir_log_data(dev, "bulk data in:", data, data_len);
1115 if (data_len <= aurb->packet->iov.size) {
1116 usb_packet_copy(aurb->packet, data, data_len);
1117 } else {
1118 ERROR("bulk buffer too small (%d > %zd)\n", data_len,
1119 aurb->packet->iov.size);
1120 len = USB_RET_STALL;
1123 aurb->packet->result = len;
1124 usb_packet_complete(&dev->dev, aurb->packet);
1126 async_free(dev, aurb);
1127 free(data);
1130 static void usbredir_iso_packet(void *priv, uint32_t id,
1131 struct usb_redir_iso_packet_header *iso_packet,
1132 uint8_t *data, int data_len)
1134 USBRedirDevice *dev = priv;
1135 uint8_t ep = iso_packet->endpoint;
1137 DPRINTF2("iso-in status %d ep %02X len %d id %u\n", iso_packet->status, ep,
1138 data_len, id);
1140 if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_ISOC) {
1141 ERROR("received iso packet for non iso endpoint %02X\n", ep);
1142 free(data);
1143 return;
1146 if (dev->endpoint[EP2I(ep)].iso_started == 0) {
1147 DPRINTF("received iso packet for non started stream ep %02X\n", ep);
1148 free(data);
1149 return;
1152 /* bufp_alloc also adds the packet to the ep queue */
1153 bufp_alloc(dev, data, data_len, iso_packet->status, ep);
1156 static void usbredir_interrupt_packet(void *priv, uint32_t id,
1157 struct usb_redir_interrupt_packet_header *interrupt_packet,
1158 uint8_t *data, int data_len)
1160 USBRedirDevice *dev = priv;
1161 uint8_t ep = interrupt_packet->endpoint;
1163 DPRINTF("interrupt-in status %d ep %02X len %d id %u\n",
1164 interrupt_packet->status, ep, data_len, id);
1166 if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_INT) {
1167 ERROR("received int packet for non interrupt endpoint %02X\n", ep);
1168 free(data);
1169 return;
1172 if (ep & USB_DIR_IN) {
1173 if (dev->endpoint[EP2I(ep)].interrupt_started == 0) {
1174 DPRINTF("received int packet while not started 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, interrupt_packet->status, ep);
1181 } else {
1182 int len = interrupt_packet->length;
1184 AsyncURB *aurb = async_find(dev, id);
1185 if (!aurb) {
1186 return;
1189 if (aurb->interrupt_packet.endpoint != interrupt_packet->endpoint) {
1190 ERROR("return int packet mismatch, please report this!\n");
1191 len = USB_RET_NAK;
1194 if (aurb->packet) {
1195 aurb->packet->result = usbredir_handle_status(dev,
1196 interrupt_packet->status, len);
1197 usb_packet_complete(&dev->dev, aurb->packet);
1199 async_free(dev, aurb);
1203 static struct USBDeviceInfo usbredir_dev_info = {
1204 .product_desc = "USB Redirection Device",
1205 .qdev.name = "usb-redir",
1206 .qdev.size = sizeof(USBRedirDevice),
1207 .init = usbredir_initfn,
1208 .handle_destroy = usbredir_handle_destroy,
1209 .handle_packet = usb_generic_handle_packet,
1210 .cancel_packet = usbredir_cancel_packet,
1211 .handle_reset = usbredir_handle_reset,
1212 .handle_data = usbredir_handle_data,
1213 .handle_control = usbredir_handle_control,
1214 .qdev.props = (Property[]) {
1215 DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
1216 DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
1217 DEFINE_PROP_END_OF_LIST(),
1221 static void usbredir_register_devices(void)
1223 usb_qdev_register(&usbredir_dev_info);
1225 device_init(usbredir_register_devices);