Sparc32: fix SDL zooming with TCX
[qemu-kvm/fedora.git] / hw / usb-serial.c
blob19870a53cc4b2b1057c68a1dae25d8ae516d42c3
1 /*
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.
9 */
11 #include "qemu-common.h"
12 #include "usb.h"
13 #include "qemu-char.h"
15 //#define DEBUG_Serial
17 #ifdef DEBUG_Serial
18 #define DPRINTF(fmt, ...) \
19 do { printf("usb-serial: " fmt , ## __VA_ARGS__); } while (0)
20 #else
21 #define DPRINTF(fmt, ...) do {} while(0)
22 #endif
24 #define RECV_BUF 384
26 /* Commands */
27 #define FTDI_RESET 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)
41 /* RESET */
43 #define FTDI_RESET_SIO 0
44 #define FTDI_RESET_RX 1
45 #define FTDI_RESET_TX 2
47 /* SET_MDM_CTRL */
49 #define FTDI_DTR 1
50 #define FTDI_SET_DTR (FTDI_DTR << 8)
51 #define FTDI_RTS 2
52 #define FTDI_SET_RTS (FTDI_RTS << 8)
54 /* SET_FLOW_CTRL */
56 #define FTDI_RTS_CTS_HS 1
57 #define FTDI_DTR_DSR_HS 2
58 #define FTDI_XON_XOFF_HS 4
60 /* SET_DATA */
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)
73 /* GET_MDM_ST */
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
80 /* Status */
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
91 typedef struct {
92 USBDevice dev;
93 uint16_t vendorid;
94 uint16_t productid;
95 uint8_t recv_buf[RECV_BUF];
96 uint16_t recv_ptr;
97 uint16_t recv_used;
98 uint8_t event_chr;
99 uint8_t error_chr;
100 uint8_t event_trigger;
101 QEMUSerialSetParams params;
102 int latency; /* ms */
103 CharDriverState *cs;
104 } USBSerialState;
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;
137 Bit 7: must be set,
138 6: Self-powered,
139 5: Remote wakeup,
140 4..0: resvd */
141 100/2, /* u8 MaxPower; */
143 /* one interface */
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 */
174 s->event_chr = 0x0d;
175 s->event_trigger = 0;
176 s->recv_ptr = 0;
177 s->recv_used = 0;
178 /* TODO: purge in char driver */
181 static void usb_serial_handle_reset(USBDevice *dev)
183 USBSerialState *s = (USBSerialState *)dev;
185 DPRINTF("Reset\n");
187 usb_serial_reset(s);
188 /* TODO: Reset char device, send BREAK? */
191 static uint8_t usb_get_modem_lines(USBSerialState *s)
193 int flags;
194 uint8_t ret;
196 if (qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP)
197 return FTDI_CTS|FTDI_DSR|FTDI_RLSD;
199 ret = 0;
200 if (flags & CHR_TIOCM_CTS)
201 ret |= FTDI_CTS;
202 if (flags & CHR_TIOCM_DSR)
203 ret |= FTDI_DSR;
204 if (flags & CHR_TIOCM_RI)
205 ret |= FTDI_RI;
206 if (flags & CHR_TIOCM_CAR)
207 ret |= FTDI_RLSD;
209 return ret;
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;
216 int ret = 0;
218 //DPRINTF("got control %x, value %x\n",request, value);
219 switch (request) {
220 case DeviceRequest | USB_REQ_GET_STATUS:
221 data[0] = (0 << USB_DEVICE_SELF_POWERED) |
222 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
223 data[1] = 0x00;
224 ret = 2;
225 break;
226 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
227 if (value == USB_DEVICE_REMOTE_WAKEUP) {
228 dev->remote_wakeup = 0;
229 } else {
230 goto fail;
232 ret = 0;
233 break;
234 case DeviceOutRequest | USB_REQ_SET_FEATURE:
235 if (value == USB_DEVICE_REMOTE_WAKEUP) {
236 dev->remote_wakeup = 1;
237 } else {
238 goto fail;
240 ret = 0;
241 break;
242 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
243 dev->addr = value;
244 ret = 0;
245 break;
246 case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
247 switch(value >> 8) {
248 case USB_DT_DEVICE:
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);
256 break;
257 case USB_DT_CONFIG:
258 memcpy(data, qemu_serial_config_descriptor,
259 sizeof(qemu_serial_config_descriptor));
260 ret = sizeof(qemu_serial_config_descriptor);
261 break;
262 case USB_DT_STRING:
263 switch(value & 0xff) {
264 case 0:
265 /* language ids */
266 data[0] = 4;
267 data[1] = 3;
268 data[2] = 0x09;
269 data[3] = 0x04;
270 ret = 4;
271 break;
272 case 1:
273 /* vendor description */
274 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
275 break;
276 case 2:
277 /* product description */
278 ret = set_usb_string(data, "QEMU USB SERIAL");
279 break;
280 case 3:
281 /* serial number */
282 ret = set_usb_string(data, "1");
283 break;
284 default:
285 goto fail;
287 break;
288 default:
289 goto fail;
291 break;
292 case DeviceRequest | USB_REQ_GET_CONFIGURATION:
293 data[0] = 1;
294 ret = 1;
295 break;
296 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
297 ret = 0;
298 break;
299 case DeviceRequest | USB_REQ_GET_INTERFACE:
300 data[0] = 0;
301 ret = 1;
302 break;
303 case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
304 ret = 0;
305 break;
306 case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
307 ret = 0;
308 break;
310 /* Class specific requests. */
311 case DeviceOutVendor | FTDI_RESET:
312 switch (value) {
313 case FTDI_RESET_SIO:
314 usb_serial_reset(s);
315 break;
316 case FTDI_RESET_RX:
317 s->recv_ptr = 0;
318 s->recv_used = 0;
319 /* TODO: purge from char device */
320 break;
321 case FTDI_RESET_TX:
322 /* TODO: purge from char device */
323 break;
325 break;
326 case DeviceOutVendor | FTDI_SET_MDM_CTRL:
328 static int flags;
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;
333 else
334 flags &= ~CHR_TIOCM_RTS;
336 if (value & FTDI_SET_DTR) {
337 if (value & FTDI_DTR)
338 flags |= CHR_TIOCM_DTR;
339 else
340 flags &= ~CHR_TIOCM_DTR;
342 qemu_chr_ioctl(s->cs,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
343 break;
345 case DeviceOutVendor | FTDI_SET_FLOW_CTRL:
346 /* TODO: ioctl */
347 break;
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)
356 subdivisor8 = 4;
357 if (divisor == 0 && subdivisor8 == 0)
358 divisor = 1;
360 s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8);
361 qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
362 break;
364 case DeviceOutVendor | FTDI_SET_DATA:
365 switch (value & FTDI_PARITY) {
366 case 0:
367 s->params.parity = 'N';
368 break;
369 case FTDI_ODD:
370 s->params.parity = 'O';
371 break;
372 case FTDI_EVEN:
373 s->params.parity = 'E';
374 break;
375 default:
376 DPRINTF("unsupported parity %d\n", value & FTDI_PARITY);
377 goto fail;
379 switch (value & FTDI_STOP) {
380 case FTDI_STOP1:
381 s->params.stop_bits = 1;
382 break;
383 case FTDI_STOP2:
384 s->params.stop_bits = 2;
385 break;
386 default:
387 DPRINTF("unsupported stop bits %d\n", value & FTDI_STOP);
388 goto fail;
390 qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
391 /* TODO: TX ON/OFF */
392 break;
393 case DeviceInVendor | FTDI_GET_MDM_ST:
394 data[0] = usb_get_modem_lines(s) | 1;
395 data[1] = 0;
396 ret = 2;
397 break;
398 case DeviceOutVendor | FTDI_SET_EVENT_CHR:
399 /* TODO: handle it */
400 s->event_chr = value;
401 break;
402 case DeviceOutVendor | FTDI_SET_ERROR_CHR:
403 /* TODO: handle it */
404 s->error_chr = value;
405 break;
406 case DeviceOutVendor | FTDI_SET_LATENCY:
407 s->latency = value;
408 break;
409 case DeviceInVendor | FTDI_GET_LATENCY:
410 data[0] = s->latency;
411 ret = 1;
412 break;
413 default:
414 fail:
415 DPRINTF("got unsupported/bogus control %x, value %x\n", request, value);
416 ret = USB_RET_STALL;
417 break;
419 return ret;
422 static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
424 USBSerialState *s = (USBSerialState *)dev;
425 int ret = 0;
426 uint8_t devep = p->devep;
427 uint8_t *data = p->data;
428 int len = p->len;
429 int first_len;
431 switch (p->pid) {
432 case USB_TOKEN_OUT:
433 if (devep != 2)
434 goto fail;
435 qemu_chr_write(s->cs, data, len);
436 break;
438 case USB_TOKEN_IN:
439 if (devep != 1)
440 goto fail;
441 first_len = RECV_BUF - s->recv_ptr;
442 if (len <= 2) {
443 ret = USB_RET_NAK;
444 break;
446 *data++ = usb_get_modem_lines(s) | 1;
447 /* We do not have the uart details */
448 /* handle serial break */
449 if (s->event_trigger && s->event_trigger & FTDI_BI) {
450 s->event_trigger &= ~FTDI_BI;
451 *data++ = FTDI_BI;
452 ret = 2;
453 break;
454 } else {
455 *data++ = 0;
457 len -= 2;
458 if (len > s->recv_used)
459 len = s->recv_used;
460 if (!len) {
461 ret = USB_RET_NAK;
462 break;
464 if (first_len > len)
465 first_len = len;
466 memcpy(data, s->recv_buf + s->recv_ptr, first_len);
467 if (len > first_len)
468 memcpy(data + first_len, s->recv_buf, len - first_len);
469 s->recv_used -= len;
470 s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
471 ret = len + 2;
472 break;
474 default:
475 DPRINTF("Bad token\n");
476 fail:
477 ret = USB_RET_STALL;
478 break;
481 return ret;
484 static void usb_serial_handle_destroy(USBDevice *dev)
486 USBSerialState *s = (USBSerialState *)dev;
488 qemu_chr_close(s->cs);
489 qemu_free(s);
492 static int usb_serial_can_read(void *opaque)
494 USBSerialState *s = opaque;
495 return RECV_BUF - s->recv_used;
498 static void usb_serial_read(void *opaque, const uint8_t *buf, int size)
500 USBSerialState *s = opaque;
501 int first_size = RECV_BUF - s->recv_ptr;
502 if (first_size > size)
503 first_size = size;
504 memcpy(s->recv_buf + s->recv_ptr + s->recv_used, buf, first_size);
505 if (size > first_size)
506 memcpy(s->recv_buf, buf + first_size, size - first_size);
507 s->recv_used += size;
510 static void usb_serial_event(void *opaque, int event)
512 USBSerialState *s = opaque;
514 switch (event) {
515 case CHR_EVENT_BREAK:
516 s->event_trigger |= FTDI_BI;
517 break;
518 case CHR_EVENT_FOCUS:
519 break;
520 case CHR_EVENT_RESET:
521 usb_serial_reset(s);
522 /* TODO: Reset USB port */
523 break;
527 USBDevice *usb_serial_init(const char *filename)
529 USBSerialState *s;
530 CharDriverState *cdrv;
531 unsigned short vendorid = 0x0403, productid = 0x6001;
532 char label[32];
533 static int index;
535 while (*filename && *filename != ':') {
536 const char *p;
537 char *e;
538 if (strstart(filename, "vendorid=", &p)) {
539 vendorid = strtol(p, &e, 16);
540 if (e == p || (*e && *e != ',' && *e != ':')) {
541 printf("bogus vendor ID %s\n", p);
542 return NULL;
544 filename = e;
545 } else if (strstart(filename, "productid=", &p)) {
546 productid = strtol(p, &e, 16);
547 if (e == p || (*e && *e != ',' && *e != ':')) {
548 printf("bogus product ID %s\n", p);
549 return NULL;
551 filename = e;
552 } else {
553 printf("unrecognized serial USB option %s\n", filename);
554 return NULL;
556 while(*filename == ',')
557 filename++;
559 if (!*filename) {
560 printf("character device specification needed\n");
561 return NULL;
563 filename++;
564 s = qemu_mallocz(sizeof(USBSerialState));
566 snprintf(label, sizeof(label), "usbserial%d", index++);
567 cdrv = qemu_chr_open(label, filename, NULL);
568 if (!cdrv)
569 goto fail;
570 s->cs = cdrv;
571 qemu_chr_add_handlers(cdrv, usb_serial_can_read, usb_serial_read, usb_serial_event, s);
573 s->dev.speed = USB_SPEED_FULL;
574 s->dev.handle_packet = usb_generic_handle_packet;
576 s->dev.handle_reset = usb_serial_handle_reset;
577 s->dev.handle_control = usb_serial_handle_control;
578 s->dev.handle_data = usb_serial_handle_data;
579 s->dev.handle_destroy = usb_serial_handle_destroy;
581 s->vendorid = vendorid;
582 s->productid = productid;
584 snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Serial(%.16s)",
585 filename);
587 usb_serial_handle_reset((USBDevice *)s);
588 return (USBDevice *)s;
589 fail:
590 qemu_free(s);
591 return NULL;