~ahs3/+junk/cq-qemu

« back to all changes in this revision

Viewing changes to usb-redir.c

  • Committer: Al Stone
  • Date: 2012-02-09 01:17:20 UTC
  • Revision ID: albert.stone@canonical.com-20120209011720-tztl7ik3qayz80p4
first commit to bzr for qemu

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
44
typedef struct AsyncURB AsyncURB;
 
45
typedef struct USBRedirDevice USBRedirDevice;
 
46
 
 
47
/* Struct to hold buffered packets (iso or int input packets) */
 
48
struct buf_packet {
 
49
    uint8_t *data;
 
50
    int len;
 
51
    int status;
 
52
    QTAILQ_ENTRY(buf_packet)next;
 
53
};
 
54
 
 
55
struct endp_data {
 
56
    uint8_t type;
 
57
    uint8_t interval;
 
58
    uint8_t interface; /* bInterfaceNumber this ep belongs to */
 
59
    uint8_t iso_started;
 
60
    uint8_t iso_error; /* For reporting iso errors to the HC */
 
61
    uint8_t interrupt_started;
 
62
    uint8_t interrupt_error;
 
63
    QTAILQ_HEAD(, buf_packet) bufpq;
 
64
};
 
65
 
 
66
struct USBRedirDevice {
 
67
    USBDevice dev;
 
68
    /* Properties */
 
69
    CharDriverState *cs;
 
70
    uint8_t debug;
 
71
    /* Data passed from chardev the fd_read cb to the usbredirparser read cb */
 
72
    const uint8_t *read_buf;
 
73
    int read_buf_size;
 
74
    /* For async handling of open/close */
 
75
    QEMUBH *open_close_bh;
 
76
    /* To delay the usb attach in case of quick chardev close + open */
 
77
    QEMUTimer *attach_timer;
 
78
    int64_t next_attach_time;
 
79
    struct usbredirparser *parser;
 
80
    struct endp_data endpoint[MAX_ENDPOINTS];
 
81
    uint32_t packet_id;
 
82
    QTAILQ_HEAD(, AsyncURB) asyncq;
 
83
};
 
84
 
 
85
struct AsyncURB {
 
86
    USBRedirDevice *dev;
 
87
    USBPacket *packet;
 
88
    uint32_t packet_id;
 
89
    int get;
 
90
    union {
 
91
        struct usb_redir_control_packet_header control_packet;
 
92
        struct usb_redir_bulk_packet_header bulk_packet;
 
93
        struct usb_redir_interrupt_packet_header interrupt_packet;
 
94
    };
 
95
    QTAILQ_ENTRY(AsyncURB)next;
 
96
};
 
97
 
 
98
static void usbredir_device_connect(void *priv,
 
99
    struct usb_redir_device_connect_header *device_connect);
 
100
static void usbredir_device_disconnect(void *priv);
 
101
static void usbredir_interface_info(void *priv,
 
102
    struct usb_redir_interface_info_header *interface_info);
 
103
static void usbredir_ep_info(void *priv,
 
104
    struct usb_redir_ep_info_header *ep_info);
 
105
static void usbredir_configuration_status(void *priv, uint32_t id,
 
106
    struct usb_redir_configuration_status_header *configuration_status);
 
107
static void usbredir_alt_setting_status(void *priv, uint32_t id,
 
108
    struct usb_redir_alt_setting_status_header *alt_setting_status);
 
109
static void usbredir_iso_stream_status(void *priv, uint32_t id,
 
110
    struct usb_redir_iso_stream_status_header *iso_stream_status);
 
111
static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
 
112
    struct usb_redir_interrupt_receiving_status_header
 
113
    *interrupt_receiving_status);
 
114
static void usbredir_bulk_streams_status(void *priv, uint32_t id,
 
115
    struct usb_redir_bulk_streams_status_header *bulk_streams_status);
 
116
static void usbredir_control_packet(void *priv, uint32_t id,
 
117
    struct usb_redir_control_packet_header *control_packet,
 
118
    uint8_t *data, int data_len);
 
119
static void usbredir_bulk_packet(void *priv, uint32_t id,
 
120
    struct usb_redir_bulk_packet_header *bulk_packet,
 
121
    uint8_t *data, int data_len);
 
122
static void usbredir_iso_packet(void *priv, uint32_t id,
 
123
    struct usb_redir_iso_packet_header *iso_packet,
 
124
    uint8_t *data, int data_len);
 
125
static void usbredir_interrupt_packet(void *priv, uint32_t id,
 
126
    struct usb_redir_interrupt_packet_header *interrupt_header,
 
127
    uint8_t *data, int data_len);
 
128
 
 
129
static 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
 
 
169
static 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
 
 
180
static 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
 
 
204
static 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
 
 
224
static int usbredir_write(void *priv, uint8_t *data, int count)
 
225
{
 
226
    USBRedirDevice *dev = priv;
 
227
 
 
228
    if (!dev->cs->opened) {
 
229
        return 0;
 
230
    }
 
231
 
 
232
    return qemu_chr_fe_write(dev->cs, data, count);
 
233
}
 
234
 
 
235
/*
 
236
 * Async and buffered packets helpers
 
237
 */
 
238
 
 
239
static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p)
 
240
{
 
241
    AsyncURB *aurb = (AsyncURB *) g_malloc0(sizeof(AsyncURB));
 
242
    aurb->dev = dev;
 
243
    aurb->packet = p;
 
244
    aurb->packet_id = dev->packet_id;
 
245
    QTAILQ_INSERT_TAIL(&dev->asyncq, aurb, next);
 
246
    dev->packet_id++;
 
247
 
 
248
    return aurb;
 
249
}
 
250
 
 
251
static void async_free(USBRedirDevice *dev, AsyncURB *aurb)
 
252
{
 
253
    QTAILQ_REMOVE(&dev->asyncq, aurb, next);
 
254
    g_free(aurb);
 
255
}
 
256
 
 
257
static 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
 
 
270
static 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
 
 
290
static struct buf_packet *bufp_alloc(USBRedirDevice *dev,
 
291
    uint8_t *data, int len, int status, uint8_t ep)
 
292
{
 
293
    struct buf_packet *bufp = g_malloc(sizeof(struct buf_packet));
 
294
    bufp->data   = data;
 
295
    bufp->len    = len;
 
296
    bufp->status = status;
 
297
    QTAILQ_INSERT_TAIL(&dev->endpoint[EP2I(ep)].bufpq, bufp, next);
 
298
    return bufp;
 
299
}
 
300
 
 
301
static 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);
 
306
    g_free(bufp);
 
307
}
 
308
 
 
309
static 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
 
 
322
static 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
 
 
331
static 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;
 
372
        if (len > p->iov.size) {
 
373
            ERROR("received iso data is larger then packet ep %02X\n", ep);
 
374
            bufp_free(dev, isop, ep);
 
375
            return USB_RET_NAK;
 
376
        }
 
377
        usb_packet_copy(p, isop->data, len);
 
378
        bufp_free(dev, isop, ep);
 
379
        return len;
 
380
    } else {
 
381
        /* If the stream was not started because of a pending error don't
 
382
           send the packet to the usb-host */
 
383
        if (dev->endpoint[EP2I(ep)].iso_started) {
 
384
            struct usb_redir_iso_packet_header iso_packet = {
 
385
                .endpoint = ep,
 
386
                .length = p->iov.size
 
387
            };
 
388
            uint8_t buf[p->iov.size];
 
389
            /* No id, we look at the ep when receiving a status back */
 
390
            usb_packet_copy(p, buf, p->iov.size);
 
391
            usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet,
 
392
                                           buf, p->iov.size);
 
393
            usbredirparser_do_write(dev->parser);
 
394
        }
 
395
        status = dev->endpoint[EP2I(ep)].iso_error;
 
396
        dev->endpoint[EP2I(ep)].iso_error = 0;
 
397
        DPRINTF2("iso-token-out ep %02X status %d len %zd\n", ep, status,
 
398
                 p->iov.size);
 
399
        return usbredir_handle_status(dev, status, p->iov.size);
 
400
    }
 
401
}
 
402
 
 
403
static 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
 
 
416
static 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
 
 
422
    DPRINTF("bulk-out ep %02X len %zd id %u\n", ep,
 
423
            p->iov.size, aurb->packet_id);
 
424
 
 
425
    bulk_packet.endpoint  = ep;
 
426
    bulk_packet.length    = p->iov.size;
 
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 {
 
434
        uint8_t buf[p->iov.size];
 
435
        usb_packet_copy(p, buf, p->iov.size);
 
436
        usbredir_log_data(dev, "bulk data out:", buf, p->iov.size);
 
437
        usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
 
438
                                        &bulk_packet, buf, p->iov.size);
 
439
    }
 
440
    usbredirparser_do_write(dev->parser);
 
441
    return USB_RET_ASYNC;
 
442
}
 
443
 
 
444
static 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;
 
483
        if (len > p->iov.size) {
 
484
            ERROR("received int data is larger then packet ep %02X\n", ep);
 
485
            bufp_free(dev, intp, ep);
 
486
            return USB_RET_NAK;
 
487
        }
 
488
        usb_packet_copy(p, intp->data, len);
 
489
        bufp_free(dev, intp, ep);
 
490
        return len;
 
491
    } else {
 
492
        /* Output interrupt endpoint, normal async operation */
 
493
        AsyncURB *aurb = async_alloc(dev, p);
 
494
        struct usb_redir_interrupt_packet_header interrupt_packet;
 
495
        uint8_t buf[p->iov.size];
 
496
 
 
497
        DPRINTF("interrupt-out ep %02X len %zd id %u\n", ep, p->iov.size,
 
498
                aurb->packet_id);
 
499
 
 
500
        interrupt_packet.endpoint  = ep;
 
501
        interrupt_packet.length    = p->iov.size;
 
502
        aurb->interrupt_packet     = interrupt_packet;
 
503
 
 
504
        usb_packet_copy(p, buf, p->iov.size);
 
505
        usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size);
 
506
        usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id,
 
507
                                        &interrupt_packet, buf, p->iov.size);
 
508
        usbredirparser_do_write(dev->parser);
 
509
        return USB_RET_ASYNC;
 
510
    }
 
511
}
 
512
 
 
513
static 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
 
 
528
static 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
 
 
555
static 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
 
 
585
static 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
 
 
597
static 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
 
 
631
static 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
 
 
647
static 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
 */
 
707
static 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
 
 
745
static 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
 
 
756
static 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
 
 
769
static 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
 
 
784
static 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
 
 
800
static 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
 
 
821
    /* Let the backend know we are ready */
 
822
    qemu_chr_fe_open(dev->cs);
 
823
    qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
 
824
                          usbredir_chardev_read, usbredir_chardev_event, dev);
 
825
 
 
826
    return 0;
 
827
}
 
828
 
 
829
static 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
 
 
842
static void usbredir_handle_destroy(USBDevice *udev)
 
843
{
 
844
    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
 
845
 
 
846
    qemu_chr_fe_close(dev->cs);
 
847
    qemu_chr_delete(dev->cs);
 
848
    /* Note must be done after qemu_chr_close, as that causes a close event */
 
849
    qemu_bh_delete(dev->open_close_bh);
 
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
 
 
865
static 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
 
 
883
static void usbredir_device_connect(void *priv,
 
884
    struct usb_redir_device_connect_header *device_connect)
 
885
{
 
886
    USBRedirDevice *dev = priv;
 
887
 
 
888
    if (qemu_timer_pending(dev->attach_timer) || dev->dev.attached) {
 
889
        ERROR("Received device connect while already connected\n");
 
890
        return;
 
891
    }
 
892
 
 
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
 
 
918
static void usbredir_device_disconnect(void *priv)
 
919
{
 
920
    USBRedirDevice *dev = priv;
 
921
    int i;
 
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);
 
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
    }
 
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
    }
 
941
}
 
942
 
 
943
static 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
 
 
952
static 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
 
 
969
static 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
        }
 
988
        aurb->packet->result =
 
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
 
 
995
static 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
        }
 
1016
        aurb->packet->result =
 
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
 
 
1023
static 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
 
 
1032
    if (!dev->dev.attached) {
 
1033
        return;
 
1034
    }
 
1035
 
 
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
 
 
1043
static 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
 
 
1053
    if (!dev->dev.attached) {
 
1054
        return;
 
1055
    }
 
1056
 
 
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
 
 
1065
static void usbredir_bulk_streams_status(void *priv, uint32_t id,
 
1066
    struct usb_redir_bulk_streams_status_header *bulk_streams_status)
 
1067
{
 
1068
}
 
1069
 
 
1070
static void usbredir_control_packet(void *priv, uint32_t id,
 
1071
    struct usb_redir_control_packet_header *control_packet,
 
1072
    uint8_t *data, int data_len)
 
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
        }
 
1107
        aurb->packet->result = len;
 
1108
        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
 
1109
    }
 
1110
    async_free(dev, aurb);
 
1111
    free(data);
 
1112
}
 
1113
 
 
1114
static void usbredir_bulk_packet(void *priv, uint32_t id,
 
1115
    struct usb_redir_bulk_packet_header *bulk_packet,
 
1116
    uint8_t *data, int data_len)
 
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);
 
1142
            if (data_len <= aurb->packet->iov.size) {
 
1143
                usb_packet_copy(aurb->packet, data, data_len);
 
1144
            } else {
 
1145
                ERROR("bulk buffer too small (%d > %zd)\n", data_len,
 
1146
                      aurb->packet->iov.size);
 
1147
                len = USB_RET_STALL;
 
1148
            }
 
1149
        }
 
1150
        aurb->packet->result = len;
 
1151
        usb_packet_complete(&dev->dev, aurb->packet);
 
1152
    }
 
1153
    async_free(dev, aurb);
 
1154
    free(data);
 
1155
}
 
1156
 
 
1157
static void usbredir_iso_packet(void *priv, uint32_t id,
 
1158
    struct usb_redir_iso_packet_header *iso_packet,
 
1159
    uint8_t *data, int data_len)
 
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
 
 
1183
static void usbredir_interrupt_packet(void *priv, uint32_t id,
 
1184
    struct usb_redir_interrupt_packet_header *interrupt_packet,
 
1185
    uint8_t *data, int data_len)
 
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) {
 
1222
            aurb->packet->result = usbredir_handle_status(dev,
 
1223
                                               interrupt_packet->status, len);
 
1224
            usb_packet_complete(&dev->dev, aurb->packet);
 
1225
        }
 
1226
        async_free(dev, aurb);
 
1227
    }
 
1228
}
 
1229
 
 
1230
static struct USBDeviceInfo usbredir_dev_info = {
 
1231
    .product_desc   = "USB Redirection Device",
 
1232
    .qdev.name      = "usb-redir",
 
1233
    .qdev.size      = sizeof(USBRedirDevice),
 
1234
    .init           = usbredir_initfn,
 
1235
    .handle_destroy = usbredir_handle_destroy,
 
1236
    .handle_packet  = usb_generic_handle_packet,
 
1237
    .cancel_packet  = usbredir_cancel_packet,
 
1238
    .handle_reset   = usbredir_handle_reset,
 
1239
    .handle_data    = usbredir_handle_data,
 
1240
    .handle_control = usbredir_handle_control,
 
1241
    .qdev.props     = (Property[]) {
 
1242
        DEFINE_PROP_CHR("chardev", USBRedirDevice, cs),
 
1243
        DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, 0),
 
1244
        DEFINE_PROP_END_OF_LIST(),
 
1245
    },
 
1246
};
 
1247
 
 
1248
static void usbredir_register_devices(void)
 
1249
{
 
1250
    usb_qdev_register(&usbredir_dev_info);
 
1251
}
 
1252
device_init(usbredir_register_devices);