|
|
1.1 root 1: /*
2: * FTDI FT232BM Device emulation
3: *
4: * Copyright (c) 2006 CodeSourcery.
5: * Copyright (c) 2008 Samuel Thibault <[email protected]>
6: * Written by Paul Brook, reused for FTDI by Samuel Thibault
7: *
8: * This code is licensed under the LGPL.
9: */
10:
11: #include "qemu-common.h"
12: #include "qemu-error.h"
13: #include "hw/usb.h"
14: #include "hw/usb/desc.h"
15: #include "qemu-char.h"
16:
17: //#define DEBUG_Serial
18:
19: #ifdef DEBUG_Serial
20: #define DPRINTF(fmt, ...) \
21: do { printf("usb-serial: " fmt , ## __VA_ARGS__); } while (0)
22: #else
23: #define DPRINTF(fmt, ...) do {} while(0)
24: #endif
25:
26: #define RECV_BUF 384
27:
28: /* Commands */
29: #define FTDI_RESET 0
30: #define FTDI_SET_MDM_CTRL 1
31: #define FTDI_SET_FLOW_CTRL 2
32: #define FTDI_SET_BAUD 3
33: #define FTDI_SET_DATA 4
34: #define FTDI_GET_MDM_ST 5
35: #define FTDI_SET_EVENT_CHR 6
36: #define FTDI_SET_ERROR_CHR 7
37: #define FTDI_SET_LATENCY 9
38: #define FTDI_GET_LATENCY 10
39:
40: #define DeviceOutVendor ((USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
41: #define DeviceInVendor ((USB_DIR_IN |USB_TYPE_VENDOR|USB_RECIP_DEVICE)<<8)
42:
43: /* RESET */
44:
45: #define FTDI_RESET_SIO 0
46: #define FTDI_RESET_RX 1
47: #define FTDI_RESET_TX 2
48:
49: /* SET_MDM_CTRL */
50:
51: #define FTDI_DTR 1
52: #define FTDI_SET_DTR (FTDI_DTR << 8)
53: #define FTDI_RTS 2
54: #define FTDI_SET_RTS (FTDI_RTS << 8)
55:
56: /* SET_FLOW_CTRL */
57:
58: #define FTDI_RTS_CTS_HS 1
59: #define FTDI_DTR_DSR_HS 2
60: #define FTDI_XON_XOFF_HS 4
61:
62: /* SET_DATA */
63:
64: #define FTDI_PARITY (0x7 << 8)
65: #define FTDI_ODD (0x1 << 8)
66: #define FTDI_EVEN (0x2 << 8)
67: #define FTDI_MARK (0x3 << 8)
68: #define FTDI_SPACE (0x4 << 8)
69:
70: #define FTDI_STOP (0x3 << 11)
71: #define FTDI_STOP1 (0x0 << 11)
72: #define FTDI_STOP15 (0x1 << 11)
73: #define FTDI_STOP2 (0x2 << 11)
74:
75: /* GET_MDM_ST */
76: /* TODO: should be sent every 40ms */
77: #define FTDI_CTS (1<<4) // CTS line status
78: #define FTDI_DSR (1<<5) // DSR line status
79: #define FTDI_RI (1<<6) // RI line status
80: #define FTDI_RLSD (1<<7) // Receive Line Signal Detect
81:
82: /* Status */
83:
84: #define FTDI_DR (1<<0) // Data Ready
85: #define FTDI_OE (1<<1) // Overrun Err
86: #define FTDI_PE (1<<2) // Parity Err
87: #define FTDI_FE (1<<3) // Framing Err
88: #define FTDI_BI (1<<4) // Break Interrupt
89: #define FTDI_THRE (1<<5) // Transmitter Holding Register
90: #define FTDI_TEMT (1<<6) // Transmitter Empty
91: #define FTDI_FIFO (1<<7) // Error in FIFO
92:
93: typedef struct {
94: USBDevice dev;
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;
105:
106: enum {
107: STR_MANUFACTURER = 1,
108: STR_PRODUCT_SERIAL,
109: STR_PRODUCT_BRAILLE,
110: STR_SERIALNUMBER,
111: };
112:
113: static const USBDescStrings desc_strings = {
114: [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
115: [STR_PRODUCT_SERIAL] = "QEMU USB SERIAL",
116: [STR_PRODUCT_BRAILLE] = "QEMU USB BRAILLE",
117: [STR_SERIALNUMBER] = "1",
118: };
119:
120: static const USBDescIface desc_iface0 = {
121: .bInterfaceNumber = 0,
122: .bNumEndpoints = 2,
123: .bInterfaceClass = 0xff,
124: .bInterfaceSubClass = 0xff,
125: .bInterfaceProtocol = 0xff,
126: .eps = (USBDescEndpoint[]) {
127: {
128: .bEndpointAddress = USB_DIR_IN | 0x01,
129: .bmAttributes = USB_ENDPOINT_XFER_BULK,
130: .wMaxPacketSize = 64,
131: },{
132: .bEndpointAddress = USB_DIR_OUT | 0x02,
133: .bmAttributes = USB_ENDPOINT_XFER_BULK,
134: .wMaxPacketSize = 64,
135: },
136: }
137: };
138:
139: static const USBDescDevice desc_device = {
140: .bcdUSB = 0x0200,
141: .bMaxPacketSize0 = 8,
142: .bNumConfigurations = 1,
143: .confs = (USBDescConfig[]) {
144: {
145: .bNumInterfaces = 1,
146: .bConfigurationValue = 1,
147: .bmAttributes = 0x80,
148: .bMaxPower = 50,
149: .nif = 1,
150: .ifs = &desc_iface0,
151: },
152: },
153: };
154:
155: static const USBDesc desc_serial = {
156: .id = {
157: .idVendor = 0x0403,
158: .idProduct = 0x6001,
159: .bcdDevice = 0x0400,
160: .iManufacturer = STR_MANUFACTURER,
161: .iProduct = STR_PRODUCT_SERIAL,
162: .iSerialNumber = STR_SERIALNUMBER,
163: },
164: .full = &desc_device,
165: .str = desc_strings,
166: };
167:
168: static const USBDesc desc_braille = {
169: .id = {
170: .idVendor = 0x0403,
171: .idProduct = 0xfe72,
172: .bcdDevice = 0x0400,
173: .iManufacturer = STR_MANUFACTURER,
174: .iProduct = STR_PRODUCT_BRAILLE,
175: .iSerialNumber = STR_SERIALNUMBER,
176: },
177: .full = &desc_device,
178: .str = desc_strings,
179: };
180:
181: static void usb_serial_reset(USBSerialState *s)
182: {
183: /* TODO: Set flow control to none */
184: s->event_chr = 0x0d;
185: s->event_trigger = 0;
186: s->recv_ptr = 0;
187: s->recv_used = 0;
188: /* TODO: purge in char driver */
189: }
190:
191: static void usb_serial_handle_reset(USBDevice *dev)
192: {
193: USBSerialState *s = (USBSerialState *)dev;
194:
195: DPRINTF("Reset\n");
196:
197: usb_serial_reset(s);
198: /* TODO: Reset char device, send BREAK? */
199: }
200:
201: static uint8_t usb_get_modem_lines(USBSerialState *s)
202: {
203: int flags;
204: uint8_t ret;
205:
206: if (qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP)
207: return FTDI_CTS|FTDI_DSR|FTDI_RLSD;
208:
209: ret = 0;
210: if (flags & CHR_TIOCM_CTS)
211: ret |= FTDI_CTS;
212: if (flags & CHR_TIOCM_DSR)
213: ret |= FTDI_DSR;
214: if (flags & CHR_TIOCM_RI)
215: ret |= FTDI_RI;
216: if (flags & CHR_TIOCM_CAR)
217: ret |= FTDI_RLSD;
218:
219: return ret;
220: }
221:
222: static int usb_serial_handle_control(USBDevice *dev, USBPacket *p,
223: int request, int value, int index, int length, uint8_t *data)
224: {
225: USBSerialState *s = (USBSerialState *)dev;
226: int ret;
227:
228: DPRINTF("got control %x, value %x\n",request, value);
229: ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
230: if (ret >= 0) {
231: return ret;
232: }
233:
234: ret = 0;
235: switch (request) {
236: case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
237: ret = 0;
238: break;
239:
240: /* Class specific requests. */
241: case DeviceOutVendor | FTDI_RESET:
242: switch (value) {
243: case FTDI_RESET_SIO:
244: usb_serial_reset(s);
245: break;
246: case FTDI_RESET_RX:
247: s->recv_ptr = 0;
248: s->recv_used = 0;
249: /* TODO: purge from char device */
250: break;
251: case FTDI_RESET_TX:
252: /* TODO: purge from char device */
253: break;
254: }
255: break;
256: case DeviceOutVendor | FTDI_SET_MDM_CTRL:
257: {
258: static int flags;
259: qemu_chr_fe_ioctl(s->cs,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
260: if (value & FTDI_SET_RTS) {
261: if (value & FTDI_RTS)
262: flags |= CHR_TIOCM_RTS;
263: else
264: flags &= ~CHR_TIOCM_RTS;
265: }
266: if (value & FTDI_SET_DTR) {
267: if (value & FTDI_DTR)
268: flags |= CHR_TIOCM_DTR;
269: else
270: flags &= ~CHR_TIOCM_DTR;
271: }
272: qemu_chr_fe_ioctl(s->cs,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
273: break;
274: }
275: case DeviceOutVendor | FTDI_SET_FLOW_CTRL:
276: /* TODO: ioctl */
277: break;
278: case DeviceOutVendor | FTDI_SET_BAUD: {
279: static const int subdivisors8[8] = { 0, 4, 2, 1, 3, 5, 6, 7 };
280: int subdivisor8 = subdivisors8[((value & 0xc000) >> 14)
281: | ((index & 1) << 2)];
282: int divisor = value & 0x3fff;
283:
284: /* chip special cases */
285: if (divisor == 1 && subdivisor8 == 0)
286: subdivisor8 = 4;
287: if (divisor == 0 && subdivisor8 == 0)
288: divisor = 1;
289:
290: s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8);
291: qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
292: break;
293: }
294: case DeviceOutVendor | FTDI_SET_DATA:
295: switch (value & FTDI_PARITY) {
296: case 0:
297: s->params.parity = 'N';
298: break;
299: case FTDI_ODD:
300: s->params.parity = 'O';
301: break;
302: case FTDI_EVEN:
303: s->params.parity = 'E';
304: break;
305: default:
306: DPRINTF("unsupported parity %d\n", value & FTDI_PARITY);
307: goto fail;
308: }
309: switch (value & FTDI_STOP) {
310: case FTDI_STOP1:
311: s->params.stop_bits = 1;
312: break;
313: case FTDI_STOP2:
314: s->params.stop_bits = 2;
315: break;
316: default:
317: DPRINTF("unsupported stop bits %d\n", value & FTDI_STOP);
318: goto fail;
319: }
320: qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
321: /* TODO: TX ON/OFF */
322: break;
323: case DeviceInVendor | FTDI_GET_MDM_ST:
324: data[0] = usb_get_modem_lines(s) | 1;
325: data[1] = 0;
326: ret = 2;
327: break;
328: case DeviceOutVendor | FTDI_SET_EVENT_CHR:
329: /* TODO: handle it */
330: s->event_chr = value;
331: break;
332: case DeviceOutVendor | FTDI_SET_ERROR_CHR:
333: /* TODO: handle it */
334: s->error_chr = value;
335: break;
336: case DeviceOutVendor | FTDI_SET_LATENCY:
337: s->latency = value;
338: break;
339: case DeviceInVendor | FTDI_GET_LATENCY:
340: data[0] = s->latency;
341: ret = 1;
342: break;
343: default:
344: fail:
345: DPRINTF("got unsupported/bogus control %x, value %x\n", request, value);
346: ret = USB_RET_STALL;
347: break;
348: }
349: return ret;
350: }
351:
352: static int usb_serial_handle_data(USBDevice *dev, USBPacket *p)
353: {
354: USBSerialState *s = (USBSerialState *)dev;
355: int i, ret = 0;
356: uint8_t devep = p->ep->nr;
357: struct iovec *iov;
358: uint8_t header[2];
359: int first_len, len;
360:
361: switch (p->pid) {
362: case USB_TOKEN_OUT:
363: if (devep != 2)
364: goto fail;
365: for (i = 0; i < p->iov.niov; i++) {
366: iov = p->iov.iov + i;
367: qemu_chr_fe_write(s->cs, iov->iov_base, iov->iov_len);
368: }
369: break;
370:
371: case USB_TOKEN_IN:
372: if (devep != 1)
373: goto fail;
374: first_len = RECV_BUF - s->recv_ptr;
375: len = p->iov.size;
376: if (len <= 2) {
377: ret = USB_RET_NAK;
378: break;
379: }
380: header[0] = usb_get_modem_lines(s) | 1;
381: /* We do not have the uart details */
382: /* handle serial break */
383: if (s->event_trigger && s->event_trigger & FTDI_BI) {
384: s->event_trigger &= ~FTDI_BI;
385: header[1] = FTDI_BI;
386: usb_packet_copy(p, header, 2);
387: ret = 2;
388: break;
389: } else {
390: header[1] = 0;
391: }
392: len -= 2;
393: if (len > s->recv_used)
394: len = s->recv_used;
395: if (!len) {
396: ret = USB_RET_NAK;
397: break;
398: }
399: if (first_len > len)
400: first_len = len;
401: usb_packet_copy(p, header, 2);
402: usb_packet_copy(p, s->recv_buf + s->recv_ptr, first_len);
403: if (len > first_len)
404: usb_packet_copy(p, s->recv_buf, len - first_len);
405: s->recv_used -= len;
406: s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
407: ret = len + 2;
408: break;
409:
410: default:
411: DPRINTF("Bad token\n");
412: fail:
413: ret = USB_RET_STALL;
414: break;
415: }
416:
417: return ret;
418: }
419:
420: static void usb_serial_handle_destroy(USBDevice *dev)
421: {
422: USBSerialState *s = (USBSerialState *)dev;
423:
424: qemu_chr_delete(s->cs);
425: }
426:
427: static int usb_serial_can_read(void *opaque)
428: {
429: USBSerialState *s = opaque;
430: return RECV_BUF - s->recv_used;
431: }
432:
433: static void usb_serial_read(void *opaque, const uint8_t *buf, int size)
434: {
435: USBSerialState *s = opaque;
436: int first_size, start;
437:
438: /* room in the buffer? */
439: if (size > (RECV_BUF - s->recv_used))
440: size = RECV_BUF - s->recv_used;
441:
442: start = s->recv_ptr + s->recv_used;
443: if (start < RECV_BUF) {
444: /* copy data to end of buffer */
445: first_size = RECV_BUF - start;
446: if (first_size > size)
447: first_size = size;
448:
449: memcpy(s->recv_buf + start, buf, first_size);
450:
451: /* wrap around to front if needed */
452: if (size > first_size)
453: memcpy(s->recv_buf, buf + first_size, size - first_size);
454: } else {
455: start -= RECV_BUF;
456: memcpy(s->recv_buf + start, buf, size);
457: }
458: s->recv_used += size;
459: }
460:
461: static void usb_serial_event(void *opaque, int event)
462: {
463: USBSerialState *s = opaque;
464:
465: switch (event) {
466: case CHR_EVENT_BREAK:
467: s->event_trigger |= FTDI_BI;
468: break;
469: case CHR_EVENT_FOCUS:
470: break;
471: case CHR_EVENT_OPENED:
472: usb_serial_reset(s);
473: /* TODO: Reset USB port */
474: break;
475: }
476: }
477:
478: static int usb_serial_initfn(USBDevice *dev)
479: {
480: USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
481:
482: usb_desc_create_serial(dev);
483: usb_desc_init(dev);
484:
485: if (!s->cs) {
486: error_report("Property chardev is required");
487: return -1;
488: }
489:
490: qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
491: usb_serial_event, s);
492: usb_serial_handle_reset(dev);
493: return 0;
494: }
495:
496: static USBDevice *usb_serial_init(USBBus *bus, const char *filename)
497: {
498: USBDevice *dev;
499: CharDriverState *cdrv;
500: uint32_t vendorid = 0, productid = 0;
501: char label[32];
502: static int index;
503:
504: while (*filename && *filename != ':') {
505: const char *p;
506: char *e;
507: if (strstart(filename, "vendorid=", &p)) {
508: vendorid = strtol(p, &e, 16);
509: if (e == p || (*e && *e != ',' && *e != ':')) {
510: error_report("bogus vendor ID %s", p);
511: return NULL;
512: }
513: filename = e;
514: } else if (strstart(filename, "productid=", &p)) {
515: productid = strtol(p, &e, 16);
516: if (e == p || (*e && *e != ',' && *e != ':')) {
517: error_report("bogus product ID %s", p);
518: return NULL;
519: }
520: filename = e;
521: } else {
522: error_report("unrecognized serial USB option %s", filename);
523: return NULL;
524: }
525: while(*filename == ',')
526: filename++;
527: }
528: if (!*filename) {
529: error_report("character device specification needed");
530: return NULL;
531: }
532: filename++;
533:
534: snprintf(label, sizeof(label), "usbserial%d", index++);
535: cdrv = qemu_chr_new(label, filename, NULL);
536: if (!cdrv)
537: return NULL;
538:
539: dev = usb_create(bus, "usb-serial");
540: if (!dev) {
541: return NULL;
542: }
543: qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
544: if (vendorid)
545: qdev_prop_set_uint16(&dev->qdev, "vendorid", vendorid);
546: if (productid)
547: qdev_prop_set_uint16(&dev->qdev, "productid", productid);
548: qdev_init_nofail(&dev->qdev);
549:
550: return dev;
551: }
552:
553: static USBDevice *usb_braille_init(USBBus *bus, const char *unused)
554: {
555: USBDevice *dev;
556: CharDriverState *cdrv;
557:
558: cdrv = qemu_chr_new("braille", "braille", NULL);
559: if (!cdrv)
560: return NULL;
561:
562: dev = usb_create(bus, "usb-braille");
563: qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
564: qdev_init_nofail(&dev->qdev);
565:
566: return dev;
567: }
568:
569: static const VMStateDescription vmstate_usb_serial = {
570: .name = "usb-serial",
571: .unmigratable = 1,
572: };
573:
574: static Property serial_properties[] = {
575: DEFINE_PROP_CHR("chardev", USBSerialState, cs),
576: DEFINE_PROP_END_OF_LIST(),
577: };
578:
579: static void usb_serial_class_initfn(ObjectClass *klass, void *data)
580: {
581: DeviceClass *dc = DEVICE_CLASS(klass);
582: USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
583:
584: uc->init = usb_serial_initfn;
585: uc->product_desc = "QEMU USB Serial";
586: uc->usb_desc = &desc_serial;
587: uc->handle_reset = usb_serial_handle_reset;
588: uc->handle_control = usb_serial_handle_control;
589: uc->handle_data = usb_serial_handle_data;
590: uc->handle_destroy = usb_serial_handle_destroy;
591: dc->vmsd = &vmstate_usb_serial;
592: dc->props = serial_properties;
593: }
594:
595: static TypeInfo serial_info = {
596: .name = "usb-serial",
597: .parent = TYPE_USB_DEVICE,
598: .instance_size = sizeof(USBSerialState),
599: .class_init = usb_serial_class_initfn,
600: };
601:
602: static Property braille_properties[] = {
603: DEFINE_PROP_CHR("chardev", USBSerialState, cs),
604: DEFINE_PROP_END_OF_LIST(),
605: };
606:
607: static void usb_braille_class_initfn(ObjectClass *klass, void *data)
608: {
609: DeviceClass *dc = DEVICE_CLASS(klass);
610: USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
611:
612: uc->init = usb_serial_initfn;
613: uc->product_desc = "QEMU USB Braille";
614: uc->usb_desc = &desc_braille;
615: uc->handle_reset = usb_serial_handle_reset;
616: uc->handle_control = usb_serial_handle_control;
617: uc->handle_data = usb_serial_handle_data;
618: uc->handle_destroy = usb_serial_handle_destroy;
619: dc->vmsd = &vmstate_usb_serial;
620: dc->props = braille_properties;
621: }
622:
623: static TypeInfo braille_info = {
624: .name = "usb-braille",
625: .parent = TYPE_USB_DEVICE,
626: .instance_size = sizeof(USBSerialState),
627: .class_init = usb_braille_class_initfn,
628: };
629:
630: static void usb_serial_register_types(void)
631: {
632: type_register_static(&serial_info);
633: usb_legacy_register("usb-serial", "serial", usb_serial_init);
634: type_register_static(&braille_info);
635: usb_legacy_register("usb-braille", "braille", usb_braille_init);
636: }
637:
638: type_init(usb_serial_register_types)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.