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