Statistics
| Branch: | Revision:

root / hw / usb-serial.c @ 8ca209ad

History | View | Annotate | Download (19.5 kB)

1
/*
2
 * FTDI FT232BM Device emulation
3
 *
4
 * Copyright (c) 2006 CodeSourcery.
5
 * Copyright (c) 2008 Samuel Thibault <samuel.thibault@ens-lyon.org>
6
 * Written by Paul Brook, reused for FTDI by Samuel Thibault
7
 *
8
 * This code is licenced under the LGPL.
9
 */
10

    
11
#include "qemu-common.h"
12
#include "qemu-error.h"
13
#include "usb.h"
14
#include "qemu-char.h"
15

    
16
//#define DEBUG_Serial
17

    
18
#ifdef DEBUG_Serial
19
#define DPRINTF(fmt, ...) \
20
do { printf("usb-serial: " fmt , ## __VA_ARGS__); } while (0)
21
#else
22
#define DPRINTF(fmt, ...) do {} while(0)
23
#endif
24

    
25
#define RECV_BUF 384
26

    
27
/* Commands */
28
#define FTDI_RESET                0
29
#define FTDI_SET_MDM_CTRL        1
30
#define FTDI_SET_FLOW_CTRL        2
31
#define FTDI_SET_BAUD                3
32
#define FTDI_SET_DATA                4
33
#define FTDI_GET_MDM_ST                5
34
#define FTDI_SET_EVENT_CHR        6
35
#define FTDI_SET_ERROR_CHR        7
36
#define FTDI_SET_LATENCY        9
37
#define FTDI_GET_LATENCY        10
38

    
39
#define DeviceOutVendor        ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
40
#define DeviceInVendor        ((USB_DIR_IN |USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
41

    
42
/* RESET */
43

    
44
#define FTDI_RESET_SIO        0
45
#define FTDI_RESET_RX        1
46
#define FTDI_RESET_TX        2
47

    
48
/* SET_MDM_CTRL */
49

    
50
#define FTDI_DTR        1
51
#define FTDI_SET_DTR        (FTDI_DTR << 8)
52
#define FTDI_RTS        2
53
#define FTDI_SET_RTS        (FTDI_RTS << 8)
54

    
55
/* SET_FLOW_CTRL */
56

    
57
#define FTDI_RTS_CTS_HS                1
58
#define FTDI_DTR_DSR_HS                2
59
#define FTDI_XON_XOFF_HS        4
60

    
61
/* SET_DATA */
62

    
63
#define FTDI_PARITY        (0x7 << 8)
64
#define FTDI_ODD        (0x1 << 8)
65
#define FTDI_EVEN        (0x2 << 8)
66
#define FTDI_MARK        (0x3 << 8)
67
#define FTDI_SPACE        (0x4 << 8)
68

    
69
#define FTDI_STOP        (0x3 << 11)
70
#define FTDI_STOP1        (0x0 << 11)
71
#define FTDI_STOP15        (0x1 << 11)
72
#define FTDI_STOP2        (0x2 << 11)
73

    
74
/* GET_MDM_ST */
75
/* TODO: should be sent every 40ms */
76
#define FTDI_CTS  (1<<4)        // CTS line status
77
#define FTDI_DSR  (1<<5)        // DSR line status
78
#define FTDI_RI   (1<<6)        // RI line status
79
#define FTDI_RLSD (1<<7)        // Receive Line Signal Detect
80

    
81
/* Status */
82

    
83
#define FTDI_DR   (1<<0)        // Data Ready
84
#define FTDI_OE   (1<<1)        // Overrun Err
85
#define FTDI_PE   (1<<2)        // Parity Err
86
#define FTDI_FE   (1<<3)        // Framing Err
87
#define FTDI_BI   (1<<4)        // Break Interrupt
88
#define FTDI_THRE (1<<5)        // Transmitter Holding Register
89
#define FTDI_TEMT (1<<6)        // Transmitter Empty
90
#define FTDI_FIFO (1<<7)        // Error in FIFO
91

    
92
typedef struct {
93
    USBDevice dev;
94
    uint32_t vendorid;
95
    uint32_t productid;
96
    uint8_t recv_buf[RECV_BUF];
97
    uint16_t recv_ptr;
98
    uint16_t recv_used;
99
    uint8_t event_chr;
100
    uint8_t error_chr;
101
    uint8_t event_trigger;
102
    QEMUSerialSetParams params;
103
    int latency;        /* ms */
104
    CharDriverState *cs;
105
} USBSerialState;
106

    
107
static const uint8_t qemu_serial_dev_descriptor[] = {
108
        0x12,       /*  u8 bLength; */
109
        0x01,       /*  u8 bDescriptorType; Device */
110
        0x00, 0x02, /*  u16 bcdUSB; v2.0 */
111

    
112
        0x00,       /*  u8  bDeviceClass; */
113
        0x00,       /*  u8  bDeviceSubClass; */
114
        0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
115
        0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
116

    
117
        /* Vendor and product id are arbitrary.  */
118
        0x03, 0x04, /*  u16 idVendor; */
119
        0x00, 0xFF, /*  u16 idProduct; */
120
        0x00, 0x04, /*  u16 bcdDevice */
121

    
122
        0x01,       /*  u8  iManufacturer; */
123
        0x02,       /*  u8  iProduct; */
124
        0x03,       /*  u8  iSerialNumber; */
125
        0x01        /*  u8  bNumConfigurations; */
126
};
127

    
128
static const uint8_t qemu_serial_config_descriptor[] = {
129

    
130
        /* one configuration */
131
        0x09,       /*  u8  bLength; */
132
        0x02,       /*  u8  bDescriptorType; Configuration */
133
        0x20, 0x00, /*  u16 wTotalLength; */
134
        0x01,       /*  u8  bNumInterfaces; (1) */
135
        0x01,       /*  u8  bConfigurationValue; */
136
        0x00,       /*  u8  iConfiguration; */
137
        0x80,       /*  u8  bmAttributes;
138
                                 Bit 7: must be set,
139
                                     6: Self-powered,
140
                                     5: Remote wakeup,
141
                                     4..0: resvd */
142
        100/2,       /*  u8  MaxPower; */
143

    
144
        /* one interface */
145
        0x09,       /*  u8  if_bLength; */
146
        0x04,       /*  u8  if_bDescriptorType; Interface */
147
        0x00,       /*  u8  if_bInterfaceNumber; */
148
        0x00,       /*  u8  if_bAlternateSetting; */
149
        0x02,       /*  u8  if_bNumEndpoints; */
150
        0xff,       /*  u8  if_bInterfaceClass; Vendor Specific */
151
        0xff,       /*  u8  if_bInterfaceSubClass; Vendor Specific */
152
        0xff,       /*  u8  if_bInterfaceProtocol; Vendor Specific */
153
        0x02,       /*  u8  if_iInterface; */
154

    
155
        /* Bulk-In endpoint */
156
        0x07,       /*  u8  ep_bLength; */
157
        0x05,       /*  u8  ep_bDescriptorType; Endpoint */
158
        0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
159
        0x02,       /*  u8  ep_bmAttributes; Bulk */
160
        0x40, 0x00, /*  u16 ep_wMaxPacketSize; */
161
        0x00,       /*  u8  ep_bInterval; */
162

    
163
        /* Bulk-Out endpoint */
164
        0x07,       /*  u8  ep_bLength; */
165
        0x05,       /*  u8  ep_bDescriptorType; Endpoint */
166
        0x02,       /*  u8  ep_bEndpointAddress; OUT Endpoint 2 */
167
        0x02,       /*  u8  ep_bmAttributes; Bulk */
168
        0x40, 0x00, /*  u16 ep_wMaxPacketSize; */
169
        0x00        /*  u8  ep_bInterval; */
170
};
171

    
172
static void usb_serial_reset(USBSerialState *s)
173
{
174
    /* TODO: Set flow control to none */
175
    s->event_chr = 0x0d;
176
    s->event_trigger = 0;
177
    s->recv_ptr = 0;
178
    s->recv_used = 0;
179
    /* TODO: purge in char driver */
180
}
181

    
182
static void usb_serial_handle_reset(USBDevice *dev)
183
{
184
    USBSerialState *s = (USBSerialState *)dev;
185

    
186
    DPRINTF("Reset\n");
187

    
188
    usb_serial_reset(s);
189
    /* TODO: Reset char device, send BREAK? */
190
}
191

    
192
static uint8_t usb_get_modem_lines(USBSerialState *s)
193
{
194
    int flags;
195
    uint8_t ret;
196

    
197
    if (qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP)
198
        return FTDI_CTS|FTDI_DSR|FTDI_RLSD;
199

    
200
    ret = 0;
201
    if (flags & CHR_TIOCM_CTS)
202
        ret |= FTDI_CTS;
203
    if (flags & CHR_TIOCM_DSR)
204
        ret |= FTDI_DSR;
205
    if (flags & CHR_TIOCM_RI)
206
        ret |= FTDI_RI;
207
    if (flags & CHR_TIOCM_CAR)
208
        ret |= FTDI_RLSD;
209

    
210
    return ret;
211
}
212

    
213
static int usb_serial_handle_control(USBDevice *dev, int request, int value,
214
                                  int index, int length, uint8_t *data)
215
{
216
    USBSerialState *s = (USBSerialState *)dev;
217
    int ret = 0;
218

    
219
    //DPRINTF("got control %x, value %x\n",request, value);
220
    switch (request) {
221
    case DeviceRequest | USB_REQ_GET_STATUS:
222
        data[0] = (0 << USB_DEVICE_SELF_POWERED) |
223
            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
224
        data[1] = 0x00;
225
        ret = 2;
226
        break;
227
    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
228
        if (value == USB_DEVICE_REMOTE_WAKEUP) {
229
            dev->remote_wakeup = 0;
230
        } else {
231
            goto fail;
232
        }
233
        ret = 0;
234
        break;
235
    case DeviceOutRequest | USB_REQ_SET_FEATURE:
236
        if (value == USB_DEVICE_REMOTE_WAKEUP) {
237
            dev->remote_wakeup = 1;
238
        } else {
239
            goto fail;
240
        }
241
        ret = 0;
242
        break;
243
    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
244
        dev->addr = value;
245
        ret = 0;
246
        break;
247
    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
248
        switch(value >> 8) {
249
        case USB_DT_DEVICE:
250
            memcpy(data, qemu_serial_dev_descriptor,
251
                   sizeof(qemu_serial_dev_descriptor));
252
            data[8] = s->vendorid & 0xff;
253
            data[9] = ((s->vendorid) >> 8) & 0xff;
254
            data[10] = s->productid & 0xff;
255
            data[11] = ((s->productid) >> 8) & 0xff;
256
            ret = sizeof(qemu_serial_dev_descriptor);
257
            break;
258
        case USB_DT_CONFIG:
259
            memcpy(data, qemu_serial_config_descriptor,
260
                   sizeof(qemu_serial_config_descriptor));
261
            ret = sizeof(qemu_serial_config_descriptor);
262
            break;
263
        case USB_DT_STRING:
264
            switch(value & 0xff) {
265
            case 0:
266
                /* language ids */
267
                data[0] = 4;
268
                data[1] = 3;
269
                data[2] = 0x09;
270
                data[3] = 0x04;
271
                ret = 4;
272
                break;
273
            case 1:
274
                /* vendor description */
275
                ret = set_usb_string(data, "QEMU " QEMU_VERSION);
276
                break;
277
            case 2:
278
                /* product description */
279
                ret = set_usb_string(data, "QEMU USB SERIAL");
280
                break;
281
            case 3:
282
                /* serial number */
283
                ret = set_usb_string(data, "1");
284
                break;
285
            default:
286
                goto fail;
287
            }
288
            break;
289
        default:
290
            goto fail;
291
        }
292
        break;
293
    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
294
        data[0] = 1;
295
        ret = 1;
296
        break;
297
    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
298
        ret = 0;
299
        break;
300
    case DeviceRequest | USB_REQ_GET_INTERFACE:
301
        data[0] = 0;
302
        ret = 1;
303
        break;
304
    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
305
        ret = 0;
306
        break;
307
    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
308
        ret = 0;
309
        break;
310

    
311
        /* Class specific requests.  */
312
    case DeviceOutVendor | FTDI_RESET:
313
        switch (value) {
314
        case FTDI_RESET_SIO:
315
            usb_serial_reset(s);
316
            break;
317
        case FTDI_RESET_RX:
318
            s->recv_ptr = 0;
319
            s->recv_used = 0;
320
            /* TODO: purge from char device */
321
            break;
322
        case FTDI_RESET_TX:
323
            /* TODO: purge from char device */
324
            break;
325
        }
326
        break;
327
    case DeviceOutVendor | FTDI_SET_MDM_CTRL:
328
    {
329
        static int flags;
330
        qemu_chr_ioctl(s->cs,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
331
        if (value & FTDI_SET_RTS) {
332
            if (value & FTDI_RTS)
333
                flags |= CHR_TIOCM_RTS;
334
            else
335
                flags &= ~CHR_TIOCM_RTS;
336
        }
337
        if (value & FTDI_SET_DTR) {
338
            if (value & FTDI_DTR)
339
                flags |= CHR_TIOCM_DTR;
340
            else
341
                flags &= ~CHR_TIOCM_DTR;
342
        }
343
        qemu_chr_ioctl(s->cs,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
344
        break;
345
    }
346
    case DeviceOutVendor | FTDI_SET_FLOW_CTRL:
347
        /* TODO: ioctl */
348
        break;
349
    case DeviceOutVendor | FTDI_SET_BAUD: {
350
        static const int subdivisors8[8] = { 0, 4, 2, 1, 3, 5, 6, 7 };
351
        int subdivisor8 = subdivisors8[((value & 0xc000) >> 14)
352
                                     | ((index & 1) << 2)];
353
        int divisor = value & 0x3fff;
354

    
355
        /* chip special cases */
356
        if (divisor == 1 && subdivisor8 == 0)
357
            subdivisor8 = 4;
358
        if (divisor == 0 && subdivisor8 == 0)
359
            divisor = 1;
360

    
361
        s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8);
362
        qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
363
        break;
364
    }
365
    case DeviceOutVendor | FTDI_SET_DATA:
366
        switch (value & FTDI_PARITY) {
367
            case 0:
368
                s->params.parity = 'N';
369
                break;
370
            case FTDI_ODD:
371
                s->params.parity = 'O';
372
                break;
373
            case FTDI_EVEN:
374
                s->params.parity = 'E';
375
                break;
376
            default:
377
                DPRINTF("unsupported parity %d\n", value & FTDI_PARITY);
378
                goto fail;
379
        }
380
        switch (value & FTDI_STOP) {
381
            case FTDI_STOP1:
382
                s->params.stop_bits = 1;
383
                break;
384
            case FTDI_STOP2:
385
                s->params.stop_bits = 2;
386
                break;
387
            default:
388
                DPRINTF("unsupported stop bits %d\n", value & FTDI_STOP);
389
                goto fail;
390
        }
391
        qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
392
        /* TODO: TX ON/OFF */
393
        break;
394
    case DeviceInVendor | FTDI_GET_MDM_ST:
395
        data[0] = usb_get_modem_lines(s) | 1;
396
        data[1] = 0;
397
        ret = 2;
398
        break;
399
    case DeviceOutVendor | FTDI_SET_EVENT_CHR:
400
        /* TODO: handle it */
401
        s->event_chr = value;
402
        break;
403
    case DeviceOutVendor | FTDI_SET_ERROR_CHR:
404
        /* TODO: handle it */
405
        s->error_chr = value;
406
        break;
407
    case DeviceOutVendor | FTDI_SET_LATENCY:
408
        s->latency = value;
409
        break;
410
    case DeviceInVendor | FTDI_GET_LATENCY:
411
        data[0] = s->latency;
412
        ret = 1;
413
        break;
414
    default:
415
    fail:
416
        DPRINTF("got unsupported/bogus control %x, value %x\n", request, value);
417
        ret = USB_RET_STALL;
418
        break;
419
    }
420
    return ret;
421
}
422

    
423
static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
424
{
425
    USBSerialState *s = (USBSerialState *)dev;
426
    int ret = 0;
427
    uint8_t devep = p->devep;
428
    uint8_t *data = p->data;
429
    int len = p->len;
430
    int first_len;
431

    
432
    switch (p->pid) {
433
    case USB_TOKEN_OUT:
434
        if (devep != 2)
435
            goto fail;
436
        qemu_chr_write(s->cs, data, len);
437
        break;
438

    
439
    case USB_TOKEN_IN:
440
        if (devep != 1)
441
            goto fail;
442
        first_len = RECV_BUF - s->recv_ptr;
443
        if (len <= 2) {
444
            ret = USB_RET_NAK;
445
            break;
446
        }
447
        *data++ = usb_get_modem_lines(s) | 1;
448
        /* We do not have the uart details */
449
        /* handle serial break */
450
        if (s->event_trigger && s->event_trigger & FTDI_BI) {
451
            s->event_trigger &= ~FTDI_BI;
452
            *data = FTDI_BI;
453
            ret = 2;
454
            break;
455
        } else {
456
            *data++ = 0;
457
        }
458
        len -= 2;
459
        if (len > s->recv_used)
460
            len = s->recv_used;
461
        if (!len) {
462
            ret = USB_RET_NAK;
463
            break;
464
        }
465
        if (first_len > len)
466
            first_len = len;
467
        memcpy(data, s->recv_buf + s->recv_ptr, first_len);
468
        if (len > first_len)
469
            memcpy(data + first_len, s->recv_buf, len - first_len);
470
        s->recv_used -= len;
471
        s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
472
        ret = len + 2;
473
        break;
474

    
475
    default:
476
        DPRINTF("Bad token\n");
477
    fail:
478
        ret = USB_RET_STALL;
479
        break;
480
    }
481

    
482
    return ret;
483
}
484

    
485
static void usb_serial_handle_destroy(USBDevice *dev)
486
{
487
    USBSerialState *s = (USBSerialState *)dev;
488

    
489
    qemu_chr_close(s->cs);
490
}
491

    
492
static int usb_serial_can_read(void *opaque)
493
{
494
    USBSerialState *s = opaque;
495
    return RECV_BUF - s->recv_used;
496
}
497

    
498
static void usb_serial_read(void *opaque, const uint8_t *buf, int size)
499
{
500
    USBSerialState *s = opaque;
501
    int first_size, start;
502

    
503
    /* room in the buffer? */
504
    if (size > (RECV_BUF - s->recv_used))
505
        size = RECV_BUF - s->recv_used;
506

    
507
    start = s->recv_ptr + s->recv_used;
508
    if (start < RECV_BUF) {
509
        /* copy data to end of buffer */
510
        first_size = RECV_BUF - start;
511
        if (first_size > size)
512
            first_size = size;
513

    
514
        memcpy(s->recv_buf + start, buf, first_size);
515

    
516
        /* wrap around to front if needed */
517
        if (size > first_size)
518
            memcpy(s->recv_buf, buf + first_size, size - first_size);
519
    } else {
520
        start -= RECV_BUF;
521
        memcpy(s->recv_buf + start, buf, size);
522
    }
523
    s->recv_used += size;
524
}
525

    
526
static void usb_serial_event(void *opaque, int event)
527
{
528
    USBSerialState *s = opaque;
529

    
530
    switch (event) {
531
        case CHR_EVENT_BREAK:
532
            s->event_trigger |= FTDI_BI;
533
            break;
534
        case CHR_EVENT_FOCUS:
535
            break;
536
        case CHR_EVENT_OPENED:
537
            usb_serial_reset(s);
538
            /* TODO: Reset USB port */
539
            break;
540
    }
541
}
542

    
543
static int usb_serial_initfn(USBDevice *dev)
544
{
545
    USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
546
    s->dev.speed = USB_SPEED_FULL;
547

    
548
    if (!s->cs) {
549
        error_report("Property chardev is required");
550
        return -1;
551
    }
552

    
553
    qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
554
                          usb_serial_event, s);
555
    usb_serial_handle_reset(dev);
556
    return 0;
557
}
558

    
559
static USBDevice *usb_serial_init(const char *filename)
560
{
561
    USBDevice *dev;
562
    CharDriverState *cdrv;
563
    uint32_t vendorid = 0, productid = 0;
564
    char label[32];
565
    static int index;
566

    
567
    while (*filename && *filename != ':') {
568
        const char *p;
569
        char *e;
570
        if (strstart(filename, "vendorid=", &p)) {
571
            vendorid = strtol(p, &e, 16);
572
            if (e == p || (*e && *e != ',' && *e != ':')) {
573
                error_report("bogus vendor ID %s", p);
574
                return NULL;
575
            }
576
            filename = e;
577
        } else if (strstart(filename, "productid=", &p)) {
578
            productid = strtol(p, &e, 16);
579
            if (e == p || (*e && *e != ',' && *e != ':')) {
580
                error_report("bogus product ID %s", p);
581
                return NULL;
582
            }
583
            filename = e;
584
        } else {
585
            error_report("unrecognized serial USB option %s", filename);
586
            return NULL;
587
        }
588
        while(*filename == ',')
589
            filename++;
590
    }
591
    if (!*filename) {
592
        error_report("character device specification needed");
593
        return NULL;
594
    }
595
    filename++;
596

    
597
    snprintf(label, sizeof(label), "usbserial%d", index++);
598
    cdrv = qemu_chr_open(label, filename, NULL);
599
    if (!cdrv)
600
        return NULL;
601

    
602
    dev = usb_create(NULL /* FIXME */, "usb-serial");
603
    if (!dev) {
604
        return NULL;
605
    }
606
    qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
607
    if (vendorid)
608
        qdev_prop_set_uint16(&dev->qdev, "vendorid", vendorid);
609
    if (productid)
610
        qdev_prop_set_uint16(&dev->qdev, "productid", productid);
611
    qdev_init_nofail(&dev->qdev);
612

    
613
    return dev;
614
}
615

    
616
static USBDevice *usb_braille_init(const char *unused)
617
{
618
    USBDevice *dev;
619
    CharDriverState *cdrv;
620

    
621
    cdrv = qemu_chr_open("braille", "braille", NULL);
622
    if (!cdrv)
623
        return NULL;
624

    
625
    dev = usb_create(NULL /* FIXME */, "usb-braille");
626
    qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
627
    qdev_init_nofail(&dev->qdev);
628

    
629
    return dev;
630
}
631

    
632
static struct USBDeviceInfo serial_info = {
633
    .product_desc   = "QEMU USB Serial",
634
    .qdev.name      = "usb-serial",
635
    .qdev.size      = sizeof(USBSerialState),
636
    .init           = usb_serial_initfn,
637
    .handle_packet  = usb_generic_handle_packet,
638
    .handle_reset   = usb_serial_handle_reset,
639
    .handle_control = usb_serial_handle_control,
640
    .handle_data    = usb_serial_handle_data,
641
    .handle_destroy = usb_serial_handle_destroy,
642
    .usbdevice_name = "serial",
643
    .usbdevice_init = usb_serial_init,
644
    .qdev.props     = (Property[]) {
645
        DEFINE_PROP_CHR("chardev",     USBSerialState, cs),
646
        DEFINE_PROP_HEX32("vendorid",  USBSerialState, vendorid,  0x0403),
647
        DEFINE_PROP_HEX32("productid", USBSerialState, productid, 0x6001),
648
        DEFINE_PROP_END_OF_LIST(),
649
    },
650
};
651

    
652
static struct USBDeviceInfo braille_info = {
653
    .product_desc   = "QEMU USB Braille",
654
    .qdev.name      = "usb-braille",
655
    .qdev.size      = sizeof(USBSerialState),
656
    .init           = usb_serial_initfn,
657
    .handle_packet  = usb_generic_handle_packet,
658
    .handle_reset   = usb_serial_handle_reset,
659
    .handle_control = usb_serial_handle_control,
660
    .handle_data    = usb_serial_handle_data,
661
    .handle_destroy = usb_serial_handle_destroy,
662
    .usbdevice_name = "braille",
663
    .usbdevice_init = usb_braille_init,
664
    .qdev.props     = (Property[]) {
665
        DEFINE_PROP_CHR("chardev",     USBSerialState, cs),
666
        DEFINE_PROP_HEX32("vendorid",  USBSerialState, vendorid,  0x0403),
667
        DEFINE_PROP_HEX32("productid", USBSerialState, productid, 0xfe72),
668
        DEFINE_PROP_END_OF_LIST(),
669
    },
670
};
671

    
672
static void usb_serial_register_devices(void)
673
{
674
    usb_qdev_register(&serial_info);
675
    usb_qdev_register(&braille_info);
676
}
677
device_init(usb_serial_register_devices)