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)
25 #define SEND_BUF 128 // Not used for now
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
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)
44 #define FTDI_RESET_SIO 0
45 #define FTDI_RESET_RX 1
46 #define FTDI_RESET_TX 2
50 #define FTDI_MDM_CTRL 3
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];
98 uint8_t send_buf[SEND_BUF];
101 uint8_t event_trigger;
103 QEMUSerialSetParams params;
104 int latency; /* ms */
108 static const uint8_t qemu_serial_dev_descriptor[] = {
109 0x12, /* u8 bLength; */
110 0x01, /* u8 bDescriptorType; Device */
111 0x00, 0x02, /* u16 bcdUSB; v2.0 */
113 0x00, /* u8 bDeviceClass; */
114 0x00, /* u8 bDeviceSubClass; */
115 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
116 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
118 /* Vendor and product id are arbitrary. */
119 0x03, 0x04, /* u16 idVendor; */
120 0x00, 0xFF, /* u16 idProduct; */
121 0x00, 0x04, /* u16 bcdDevice */
123 0x01, /* u8 iManufacturer; */
124 0x02, /* u8 iProduct; */
125 0x03, /* u8 iSerialNumber; */
126 0x01 /* u8 bNumConfigurations; */
129 static const uint8_t qemu_serial_config_descriptor[] = {
131 /* one configuration */
132 0x09, /* u8 bLength; */
133 0x02, /* u8 bDescriptorType; Configuration */
134 0x20, 0x00, /* u16 wTotalLength; */
135 0x01, /* u8 bNumInterfaces; (1) */
136 0x01, /* u8 bConfigurationValue; */
137 0x00, /* u8 iConfiguration; */
138 0x80, /* u8 bmAttributes;
143 100/2, /* u8 MaxPower; */
146 0x09, /* u8 if_bLength; */
147 0x04, /* u8 if_bDescriptorType; Interface */
148 0x00, /* u8 if_bInterfaceNumber; */
149 0x00, /* u8 if_bAlternateSetting; */
150 0x02, /* u8 if_bNumEndpoints; */
151 0xff, /* u8 if_bInterfaceClass; Vendor Specific */
152 0xff, /* u8 if_bInterfaceSubClass; Vendor Specific */
153 0xff, /* u8 if_bInterfaceProtocol; Vendor Specific */
154 0x02, /* u8 if_iInterface; */
156 /* Bulk-In endpoint */
157 0x07, /* u8 ep_bLength; */
158 0x05, /* u8 ep_bDescriptorType; Endpoint */
159 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
160 0x02, /* u8 ep_bmAttributes; Bulk */
161 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
162 0x00, /* u8 ep_bInterval; */
164 /* Bulk-Out endpoint */
165 0x07, /* u8 ep_bLength; */
166 0x05, /* u8 ep_bDescriptorType; Endpoint */
167 0x02, /* u8 ep_bEndpointAddress; OUT Endpoint 2 */
168 0x02, /* u8 ep_bmAttributes; Bulk */
169 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
170 0x00 /* u8 ep_bInterval; */
173 static void usb_serial_reset(USBSerialState *s)
175 /* TODO: Set flow control to none */
177 s->event_trigger = 0;
180 /* TODO: purge in char driver */
181 s->lines &= ~(FTDI_DTR|FTDI_RTS);
184 static void usb_serial_handle_reset(USBDevice *dev)
186 USBSerialState *s = (USBSerialState *)dev;
191 /* TODO: Reset char device, send BREAK? */
194 static int usb_serial_handle_control(USBDevice *dev, int request, int value,
195 int index, int length, uint8_t *data)
197 USBSerialState *s = (USBSerialState *)dev;
200 //DPRINTF("got control %x, value %x\n",request, value);
202 case DeviceRequest | USB_REQ_GET_STATUS:
203 data[0] = (0 << USB_DEVICE_SELF_POWERED) |
204 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
208 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
209 if (value == USB_DEVICE_REMOTE_WAKEUP) {
210 dev->remote_wakeup = 0;
216 case DeviceOutRequest | USB_REQ_SET_FEATURE:
217 if (value == USB_DEVICE_REMOTE_WAKEUP) {
218 dev->remote_wakeup = 1;
224 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
228 case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
231 memcpy(data, qemu_serial_dev_descriptor,
232 sizeof(qemu_serial_dev_descriptor));
233 data[8] = s->vendorid & 0xff;
234 data[9] = ((s->vendorid) >> 8) & 0xff;
235 data[10] = s->productid & 0xff;
236 data[11] = ((s->productid) >> 8) & 0xff;
237 ret = sizeof(qemu_serial_dev_descriptor);
240 memcpy(data, qemu_serial_config_descriptor,
241 sizeof(qemu_serial_config_descriptor));
242 ret = sizeof(qemu_serial_config_descriptor);
245 switch(value & 0xff) {
255 /* vendor description */
256 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
259 /* product description */
260 ret = set_usb_string(data, "QEMU USB SERIAL");
264 ret = set_usb_string(data, "1");
274 case DeviceRequest | USB_REQ_GET_CONFIGURATION:
278 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
281 case DeviceRequest | USB_REQ_GET_INTERFACE:
285 case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
288 case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
292 /* Class specific requests. */
293 case DeviceOutVendor | FTDI_RESET:
301 /* TODO: purge from char device */
304 /* TODO: purge from char device */
308 case DeviceOutVendor | FTDI_SET_MDM_CTRL:
309 s->lines = value & FTDI_MDM_CTRL;
311 case DeviceOutVendor | FTDI_SET_FLOW_CTRL:
314 case DeviceOutVendor | FTDI_SET_BAUD: {
315 static const int subdivisors8[8] = { 0, 4, 2, 1, 3, 5, 6, 7 };
316 int subdivisor8 = subdivisors8[((value & 0xc000) >> 14)
317 | ((index & 1) << 2)];
318 int divisor = value & 0x3fff;
320 /* chip special cases */
321 if (divisor == 1 && subdivisor8 == 0)
323 if (divisor == 0 && subdivisor8 == 0)
326 s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8);
327 qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
330 case DeviceOutVendor | FTDI_SET_DATA:
331 switch (value & FTDI_PARITY) {
333 s->params.parity = 'N';
336 s->params.parity = 'O';
339 s->params.parity = 'E';
342 DPRINTF("unsupported parity %d\n", value & FTDI_PARITY);
345 switch (value & FTDI_STOP) {
347 s->params.stop_bits = 1;
350 s->params.stop_bits = 2;
353 DPRINTF("unsupported stop bits %d\n", value & FTDI_STOP);
356 qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
357 /* TODO: TX ON/OFF */
359 case DeviceInVendor | FTDI_GET_MDM_ST:
360 /* TODO: return modem status */
364 case DeviceOutVendor | FTDI_SET_EVENT_CHR:
365 /* TODO: handle it */
366 s->event_chr = value;
368 case DeviceOutVendor | FTDI_SET_ERROR_CHR:
369 /* TODO: handle it */
370 s->error_chr = value;
372 case DeviceOutVendor | FTDI_SET_LATENCY:
375 case DeviceInVendor | FTDI_GET_LATENCY:
376 data[0] = s->latency;
381 DPRINTF("got unsupported/bogus control %x, value %x\n", request, value);
388 static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
390 USBSerialState *s = (USBSerialState *)dev;
392 uint8_t devep = p->devep;
393 uint8_t *data = p->data;
401 qemu_chr_write(s->cs, data, len);
407 first_len = RECV_BUF - s->recv_ptr;
412 /* TODO: Report serial line status */
416 if (len > s->recv_used)
424 memcpy(data, s->recv_buf + s->recv_ptr, first_len);
426 memcpy(data + first_len, s->recv_buf, len - first_len);
428 s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
433 DPRINTF("Bad token\n");
442 static void usb_serial_handle_destroy(USBDevice *dev)
444 USBSerialState *s = (USBSerialState *)dev;
446 qemu_chr_close(s->cs);
450 int usb_serial_can_read(void *opaque)
452 USBSerialState *s = opaque;
453 return RECV_BUF - s->recv_used;
456 void usb_serial_read(void *opaque, const uint8_t *buf, int size)
458 USBSerialState *s = opaque;
459 int first_size = RECV_BUF - s->recv_ptr;
460 if (first_size > size)
462 memcpy(s->recv_buf + s->recv_ptr + s->recv_used, buf, first_size);
463 if (size > first_size)
464 memcpy(s->recv_buf, buf + first_size, size - first_size);
465 s->recv_used += size;
468 void usb_serial_event(void *opaque, int event)
470 USBSerialState *s = opaque;
473 case CHR_EVENT_BREAK:
474 /* TODO: Send Break to USB */
476 case CHR_EVENT_FOCUS:
478 case CHR_EVENT_RESET:
480 /* TODO: Reset USB port */
485 USBDevice *usb_serial_init(const char *filename)
488 CharDriverState *cdrv;
489 unsigned short vendorid = 0x0403, productid = 0xFF00;
491 while (*filename && *filename != ':') {
494 if (strstart(filename, "vendorid=", &p)) {
495 vendorid = strtol(p, &e, 16);
496 if (e == p || (*e && *e != ',' && *e != ':')) {
497 printf("bogus vendor ID %s\n", p);
501 } else if (strstart(filename, "productid=", &p)) {
502 productid = strtol(p, &e, 16);
503 if (e == p || (*e && *e != ',' && *e != ':')) {
504 printf("bogus product ID %s\n", p);
509 printf("unrecognized serial USB option %s\n", filename);
512 while(*filename == ',')
516 printf("character device specification needed\n");
520 s = qemu_mallocz(sizeof(USBSerialState));
524 cdrv = qemu_chr_open(filename);
528 qemu_chr_add_handlers(cdrv, usb_serial_can_read, usb_serial_read, usb_serial_event, s);
530 s->dev.speed = USB_SPEED_FULL;
531 s->dev.handle_packet = usb_generic_handle_packet;
533 s->dev.handle_reset = usb_serial_handle_reset;
534 s->dev.handle_control = usb_serial_handle_control;
535 s->dev.handle_data = usb_serial_handle_data;
536 s->dev.handle_destroy = usb_serial_handle_destroy;
538 s->vendorid = vendorid;
539 s->productid = productid;
541 snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Serial(%.16s)",
544 usb_serial_handle_reset((USBDevice *)s);
545 return (USBDevice *)s;