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