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