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
= 0x6001;
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
;