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