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