2
* FTDI FT232BM Device emulation
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
8
* This code is licenced under the LGPL.
11
#include "qemu-common.h"
13
#include "qemu-char.h"
15
//#define DEBUG_Serial
18
#define DPRINTF(fmt, args...) \
19
do { printf("usb-serial: " fmt , ##args); } while (0)
21
#define DPRINTF(fmt, args...) do {} while(0)
28
#define FTDI_SET_MDM_CTRL 1
29
#define FTDI_SET_FLOW_CTRL 2
30
#define FTDI_SET_BAUD 3
31
#define FTDI_SET_DATA 4
32
#define FTDI_GET_MDM_ST 5
33
#define FTDI_SET_EVENT_CHR 6
34
#define FTDI_SET_ERROR_CHR 7
35
#define FTDI_SET_LATENCY 9
36
#define FTDI_GET_LATENCY 10
38
#define DeviceOutVendor ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
39
#define DeviceInVendor ((USB_DIR_IN |USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
43
#define FTDI_RESET_SIO 0
44
#define FTDI_RESET_RX 1
45
#define FTDI_RESET_TX 2
50
#define FTDI_SET_DTR (FTDI_DTR << 8)
52
#define FTDI_SET_RTS (FTDI_RTS << 8)
56
#define FTDI_RTS_CTS_HS 1
57
#define FTDI_DTR_DSR_HS 2
58
#define FTDI_XON_XOFF_HS 4
62
#define FTDI_PARITY (0x7 << 8)
63
#define FTDI_ODD (0x1 << 8)
64
#define FTDI_EVEN (0x2 << 8)
65
#define FTDI_MARK (0x3 << 8)
66
#define FTDI_SPACE (0x4 << 8)
68
#define FTDI_STOP (0x3 << 11)
69
#define FTDI_STOP1 (0x0 << 11)
70
#define FTDI_STOP15 (0x1 << 11)
71
#define FTDI_STOP2 (0x2 << 11)
74
/* TODO: should be sent every 40ms */
75
#define FTDI_CTS (1<<4) // CTS line status
76
#define FTDI_DSR (1<<5) // DSR line status
77
#define FTDI_RI (1<<6) // RI line status
78
#define FTDI_RLSD (1<<7) // Receive Line Signal Detect
82
#define FTDI_DR (1<<0) // Data Ready
83
#define FTDI_OE (1<<1) // Overrun Err
84
#define FTDI_PE (1<<2) // Parity Err
85
#define FTDI_FE (1<<3) // Framing Err
86
#define FTDI_BI (1<<4) // Break Interrupt
87
#define FTDI_THRE (1<<5) // Transmitter Holding Register
88
#define FTDI_TEMT (1<<6) // Transmitter Empty
89
#define FTDI_FIFO (1<<7) // Error in FIFO
95
uint8_t recv_buf[RECV_BUF];
100
uint8_t event_trigger;
101
QEMUSerialSetParams params;
102
int latency; /* ms */
106
static const uint8_t qemu_serial_dev_descriptor[] = {
107
0x12, /* u8 bLength; */
108
0x01, /* u8 bDescriptorType; Device */
109
0x00, 0x02, /* u16 bcdUSB; v2.0 */
111
0x00, /* u8 bDeviceClass; */
112
0x00, /* u8 bDeviceSubClass; */
113
0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
114
0x08, /* u8 bMaxPacketSize0; 8 Bytes */
116
/* Vendor and product id are arbitrary. */
117
0x03, 0x04, /* u16 idVendor; */
118
0x00, 0xFF, /* u16 idProduct; */
119
0x00, 0x04, /* u16 bcdDevice */
121
0x01, /* u8 iManufacturer; */
122
0x02, /* u8 iProduct; */
123
0x03, /* u8 iSerialNumber; */
124
0x01 /* u8 bNumConfigurations; */
127
static const uint8_t qemu_serial_config_descriptor[] = {
129
/* one configuration */
130
0x09, /* u8 bLength; */
131
0x02, /* u8 bDescriptorType; Configuration */
132
0x20, 0x00, /* u16 wTotalLength; */
133
0x01, /* u8 bNumInterfaces; (1) */
134
0x01, /* u8 bConfigurationValue; */
135
0x00, /* u8 iConfiguration; */
136
0x80, /* u8 bmAttributes;
141
100/2, /* u8 MaxPower; */
144
0x09, /* u8 if_bLength; */
145
0x04, /* u8 if_bDescriptorType; Interface */
146
0x00, /* u8 if_bInterfaceNumber; */
147
0x00, /* u8 if_bAlternateSetting; */
148
0x02, /* u8 if_bNumEndpoints; */
149
0xff, /* u8 if_bInterfaceClass; Vendor Specific */
150
0xff, /* u8 if_bInterfaceSubClass; Vendor Specific */
151
0xff, /* u8 if_bInterfaceProtocol; Vendor Specific */
152
0x02, /* u8 if_iInterface; */
154
/* Bulk-In endpoint */
155
0x07, /* u8 ep_bLength; */
156
0x05, /* u8 ep_bDescriptorType; Endpoint */
157
0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
158
0x02, /* u8 ep_bmAttributes; Bulk */
159
0x40, 0x00, /* u16 ep_wMaxPacketSize; */
160
0x00, /* u8 ep_bInterval; */
162
/* Bulk-Out endpoint */
163
0x07, /* u8 ep_bLength; */
164
0x05, /* u8 ep_bDescriptorType; Endpoint */
165
0x02, /* u8 ep_bEndpointAddress; OUT Endpoint 2 */
166
0x02, /* u8 ep_bmAttributes; Bulk */
167
0x40, 0x00, /* u16 ep_wMaxPacketSize; */
168
0x00 /* u8 ep_bInterval; */
171
static void usb_serial_reset(USBSerialState *s)
173
/* TODO: Set flow control to none */
175
s->event_trigger = 0;
178
/* TODO: purge in char driver */
181
static void usb_serial_handle_reset(USBDevice *dev)
183
USBSerialState *s = (USBSerialState *)dev;
188
/* TODO: Reset char device, send BREAK? */
191
static uint8_t usb_get_modem_lines(USBSerialState *s)
196
if (qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP)
197
return FTDI_CTS|FTDI_DSR|FTDI_RLSD;
200
if (flags & CHR_TIOCM_CTS)
202
if (flags & CHR_TIOCM_DSR)
204
if (flags & CHR_TIOCM_RI)
206
if (flags & CHR_TIOCM_CAR)
212
static int usb_serial_handle_control(USBDevice *dev, int request, int value,
213
int index, int length, uint8_t *data)
215
USBSerialState *s = (USBSerialState *)dev;
218
//DPRINTF("got control %x, value %x\n",request, value);
220
case DeviceRequest | USB_REQ_GET_STATUS:
221
data[0] = (0 << USB_DEVICE_SELF_POWERED) |
222
(dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
226
case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
227
if (value == USB_DEVICE_REMOTE_WAKEUP) {
228
dev->remote_wakeup = 0;
234
case DeviceOutRequest | USB_REQ_SET_FEATURE:
235
if (value == USB_DEVICE_REMOTE_WAKEUP) {
236
dev->remote_wakeup = 1;
242
case DeviceOutRequest | USB_REQ_SET_ADDRESS:
246
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
249
memcpy(data, qemu_serial_dev_descriptor,
250
sizeof(qemu_serial_dev_descriptor));
251
data[8] = s->vendorid & 0xff;
252
data[9] = ((s->vendorid) >> 8) & 0xff;
253
data[10] = s->productid & 0xff;
254
data[11] = ((s->productid) >> 8) & 0xff;
255
ret = sizeof(qemu_serial_dev_descriptor);
258
memcpy(data, qemu_serial_config_descriptor,
259
sizeof(qemu_serial_config_descriptor));
260
ret = sizeof(qemu_serial_config_descriptor);
263
switch(value & 0xff) {
273
/* vendor description */
274
ret = set_usb_string(data, "QEMU " QEMU_VERSION);
277
/* product description */
278
ret = set_usb_string(data, "QEMU USB SERIAL");
282
ret = set_usb_string(data, "1");
292
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
296
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
299
case DeviceRequest | USB_REQ_GET_INTERFACE:
303
case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
306
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
310
/* Class specific requests. */
311
case DeviceOutVendor | FTDI_RESET:
319
/* TODO: purge from char device */
322
/* TODO: purge from char device */
326
case DeviceOutVendor | FTDI_SET_MDM_CTRL:
329
qemu_chr_ioctl(s->cs,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
330
if (value & FTDI_SET_RTS) {
331
if (value & FTDI_RTS)
332
flags |= CHR_TIOCM_RTS;
334
flags &= ~CHR_TIOCM_RTS;
336
if (value & FTDI_SET_DTR) {
337
if (value & FTDI_DTR)
338
flags |= CHR_TIOCM_DTR;
340
flags &= ~CHR_TIOCM_DTR;
342
qemu_chr_ioctl(s->cs,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
345
case DeviceOutVendor | FTDI_SET_FLOW_CTRL:
348
case DeviceOutVendor | FTDI_SET_BAUD: {
349
static const int subdivisors8[8] = { 0, 4, 2, 1, 3, 5, 6, 7 };
350
int subdivisor8 = subdivisors8[((value & 0xc000) >> 14)
351
| ((index & 1) << 2)];
352
int divisor = value & 0x3fff;
354
/* chip special cases */
355
if (divisor == 1 && subdivisor8 == 0)
357
if (divisor == 0 && subdivisor8 == 0)
360
s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8);
361
qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
364
case DeviceOutVendor | FTDI_SET_DATA:
365
switch (value & FTDI_PARITY) {
367
s->params.parity = 'N';
370
s->params.parity = 'O';
373
s->params.parity = 'E';
376
DPRINTF("unsupported parity %d\n", value & FTDI_PARITY);
379
switch (value & FTDI_STOP) {
381
s->params.stop_bits = 1;
384
s->params.stop_bits = 2;
387
DPRINTF("unsupported stop bits %d\n", value & FTDI_STOP);
390
qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
391
/* TODO: TX ON/OFF */
393
case DeviceInVendor | FTDI_GET_MDM_ST:
394
data[0] = usb_get_modem_lines(s) | 1;
398
case DeviceOutVendor | FTDI_SET_EVENT_CHR:
399
/* TODO: handle it */
400
s->event_chr = value;
402
case DeviceOutVendor | FTDI_SET_ERROR_CHR:
403
/* TODO: handle it */
404
s->error_chr = value;
406
case DeviceOutVendor | FTDI_SET_LATENCY:
409
case DeviceInVendor | FTDI_GET_LATENCY:
410
data[0] = s->latency;
415
DPRINTF("got unsupported/bogus control %x, value %x\n", request, value);
422
static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
424
USBSerialState *s = (USBSerialState *)dev;
426
uint8_t devep = p->devep;
427
uint8_t *data = p->data;
435
qemu_chr_write(s->cs, data, len);
441
first_len = RECV_BUF - s->recv_ptr;
446
*data++ = usb_get_modem_lines(s) | 1;
447
/* We do not have the uart details */
450
if (len > s->recv_used)
458
memcpy(data, s->recv_buf + s->recv_ptr, first_len);
460
memcpy(data + first_len, s->recv_buf, len - first_len);
462
s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
467
DPRINTF("Bad token\n");
476
static void usb_serial_handle_destroy(USBDevice *dev)
478
USBSerialState *s = (USBSerialState *)dev;
480
qemu_chr_close(s->cs);
484
static int usb_serial_can_read(void *opaque)
486
USBSerialState *s = opaque;
487
return RECV_BUF - s->recv_used;
490
static void usb_serial_read(void *opaque, const uint8_t *buf, int size)
492
USBSerialState *s = opaque;
493
int first_size = RECV_BUF - s->recv_ptr;
494
if (first_size > size)
496
memcpy(s->recv_buf + s->recv_ptr + s->recv_used, buf, first_size);
497
if (size > first_size)
498
memcpy(s->recv_buf, buf + first_size, size - first_size);
499
s->recv_used += size;
502
static void usb_serial_event(void *opaque, int event)
504
USBSerialState *s = opaque;
507
case CHR_EVENT_BREAK:
508
/* TODO: Send Break to USB */
510
case CHR_EVENT_FOCUS:
512
case CHR_EVENT_RESET:
514
/* TODO: Reset USB port */
519
USBDevice *usb_serial_init(const char *filename)
522
CharDriverState *cdrv;
523
unsigned short vendorid = 0x0403, productid = 0x6001;
527
while (*filename && *filename != ':') {
530
if (strstart(filename, "vendorid=", &p)) {
531
vendorid = strtol(p, &e, 16);
532
if (e == p || (*e && *e != ',' && *e != ':')) {
533
printf("bogus vendor ID %s\n", p);
537
} else if (strstart(filename, "productid=", &p)) {
538
productid = strtol(p, &e, 16);
539
if (e == p || (*e && *e != ',' && *e != ':')) {
540
printf("bogus product ID %s\n", p);
545
printf("unrecognized serial USB option %s\n", filename);
548
while(*filename == ',')
552
printf("character device specification needed\n");
556
s = qemu_mallocz(sizeof(USBSerialState));
558
snprintf(label, sizeof(label), "usbserial%d", index++);
559
cdrv = qemu_chr_open(label, filename, NULL);
563
qemu_chr_add_handlers(cdrv, usb_serial_can_read, usb_serial_read, usb_serial_event, s);
565
s->dev.speed = USB_SPEED_FULL;
566
s->dev.handle_packet = usb_generic_handle_packet;
568
s->dev.handle_reset = usb_serial_handle_reset;
569
s->dev.handle_control = usb_serial_handle_control;
570
s->dev.handle_data = usb_serial_handle_data;
571
s->dev.handle_destroy = usb_serial_handle_destroy;
573
s->vendorid = vendorid;
574
s->productid = productid;
576
snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Serial(%.16s)",
579
usb_serial_handle_reset((USBDevice *)s);
580
return (USBDevice *)s;