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    CharDriverState *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, CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP)
 213        return FTDI_CTS|FTDI_DSR|FTDI_RLSD;
 214
 215    ret = 0;
 216    if (flags & CHR_TIOCM_CTS)
 217        ret |= FTDI_CTS;
 218    if (flags & CHR_TIOCM_DSR)
 219        ret |= FTDI_DSR;
 220    if (flags & CHR_TIOCM_RI)
 221        ret |= FTDI_RI;
 222    if (flags & CHR_TIOCM_CAR)
 223        ret |= FTDI_RLSD;
 224
 225    return ret;
 226}
 227
 228static void usb_serial_handle_control(USBDevice *dev, USBPacket *p,
 229               int request, int value, int index, int length, uint8_t *data)
 230{
 231    USBSerialState *s = (USBSerialState *)dev;
 232    int ret;
 233
 234    DPRINTF("got control %x, value %x\n",request, value);
 235    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
 236    if (ret >= 0) {
 237        return;
 238    }
 239
 240    switch (request) {
 241    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
 242        break;
 243
 244        /* Class specific requests.  */
 245    case DeviceOutVendor | FTDI_RESET:
 246        switch (value) {
 247        case FTDI_RESET_SIO:
 248            usb_serial_reset(s);
 249            break;
 250        case FTDI_RESET_RX:
 251            s->recv_ptr = 0;
 252            s->recv_used = 0;
 253            /* TODO: purge from char device */
 254            break;
 255        case FTDI_RESET_TX:
 256            /* TODO: purge from char device */
 257            break;
 258        }
 259        break;
 260    case DeviceOutVendor | FTDI_SET_MDM_CTRL:
 261    {
 262        static int flags;
 263        qemu_chr_fe_ioctl(s->cs,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
 264        if (value & FTDI_SET_RTS) {
 265            if (value & FTDI_RTS)
 266                flags |= CHR_TIOCM_RTS;
 267            else
 268                flags &= ~CHR_TIOCM_RTS;
 269        }
 270        if (value & FTDI_SET_DTR) {
 271            if (value & FTDI_DTR)
 272                flags |= CHR_TIOCM_DTR;
 273            else
 274                flags &= ~CHR_TIOCM_DTR;
 275        }
 276        qemu_chr_fe_ioctl(s->cs,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
 277        break;
 278    }
 279    case DeviceOutVendor | FTDI_SET_FLOW_CTRL:
 280        /* TODO: ioctl */
 281        break;
 282    case DeviceOutVendor | FTDI_SET_BAUD: {
 283        static const int subdivisors8[8] = { 0, 4, 2, 1, 3, 5, 6, 7 };
 284        int subdivisor8 = subdivisors8[((value & 0xc000) >> 14)
 285                                     | ((index & 1) << 2)];
 286        int divisor = value & 0x3fff;
 287
 288        /* chip special cases */
 289        if (divisor == 1 && subdivisor8 == 0)
 290            subdivisor8 = 4;
 291        if (divisor == 0 && subdivisor8 == 0)
 292            divisor = 1;
 293
 294        s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8);
 295        qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
 296        break;
 297    }
 298    case DeviceOutVendor | FTDI_SET_DATA:
 299        switch (value & FTDI_PARITY) {
 300            case 0:
 301                s->params.parity = 'N';
 302                break;
 303            case FTDI_ODD:
 304                s->params.parity = 'O';
 305                break;
 306            case FTDI_EVEN:
 307                s->params.parity = 'E';
 308                break;
 309            default:
 310                DPRINTF("unsupported parity %d\n", value & FTDI_PARITY);
 311                goto fail;
 312        }
 313        switch (value & FTDI_STOP) {
 314            case FTDI_STOP1:
 315                s->params.stop_bits = 1;
 316                break;
 317            case FTDI_STOP2:
 318                s->params.stop_bits = 2;
 319                break;
 320            default:
 321                DPRINTF("unsupported stop bits %d\n", value & FTDI_STOP);
 322                goto fail;
 323        }
 324        qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
 325        /* TODO: TX ON/OFF */
 326        break;
 327    case DeviceInVendor | FTDI_GET_MDM_ST:
 328        data[0] = usb_get_modem_lines(s) | 1;
 329        data[1] = 0;
 330        p->actual_length = 2;
 331        break;
 332    case DeviceOutVendor | FTDI_SET_EVENT_CHR:
 333        /* TODO: handle it */
 334        s->event_chr = value;
 335        break;
 336    case DeviceOutVendor | FTDI_SET_ERROR_CHR:
 337        /* TODO: handle it */
 338        s->error_chr = value;
 339        break;
 340    case DeviceOutVendor | FTDI_SET_LATENCY:
 341        s->latency = value;
 342        break;
 343    case DeviceInVendor | FTDI_GET_LATENCY:
 344        data[0] = s->latency;
 345        p->actual_length = 1;
 346        break;
 347    default:
 348    fail:
 349        DPRINTF("got unsupported/bogus control %x, value %x\n", request, value);
 350        p->status = USB_RET_STALL;
 351        break;
 352    }
 353}
 354
 355static void usb_serial_handle_data(USBDevice *dev, USBPacket *p)
 356{
 357    USBSerialState *s = (USBSerialState *)dev;
 358    uint8_t devep = p->ep->nr;
 359    struct iovec *iov;
 360    uint8_t header[2];
 361    int i, first_len, len;
 362
 363    switch (p->pid) {
 364    case USB_TOKEN_OUT:
 365        if (devep != 2)
 366            goto fail;
 367        for (i = 0; i < p->iov.niov; i++) {
 368            iov = p->iov.iov + i;
 369            qemu_chr_fe_write(s->cs, iov->iov_base, iov->iov_len);
 370        }
 371        p->actual_length = p->iov.size;
 372        break;
 373
 374    case USB_TOKEN_IN:
 375        if (devep != 1)
 376            goto fail;
 377        first_len = RECV_BUF - s->recv_ptr;
 378        len = p->iov.size;
 379        if (len <= 2) {
 380            p->status = USB_RET_NAK;
 381            break;
 382        }
 383        header[0] = usb_get_modem_lines(s) | 1;
 384        /* We do not have the uart details */
 385        /* handle serial break */
 386        if (s->event_trigger && s->event_trigger & FTDI_BI) {
 387            s->event_trigger &= ~FTDI_BI;
 388            header[1] = FTDI_BI;
 389            usb_packet_copy(p, header, 2);
 390            break;
 391        } else {
 392            header[1] = 0;
 393        }
 394        len -= 2;
 395        if (len > s->recv_used)
 396            len = s->recv_used;
 397        if (!len) {
 398            p->status = USB_RET_NAK;
 399            break;
 400        }
 401        if (first_len > len)
 402            first_len = len;
 403        usb_packet_copy(p, header, 2);
 404        usb_packet_copy(p, s->recv_buf + s->recv_ptr, first_len);
 405        if (len > first_len)
 406            usb_packet_copy(p, s->recv_buf, len - first_len);
 407        s->recv_used -= len;
 408        s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;
 409        break;
 410
 411    default:
 412        DPRINTF("Bad token\n");
 413    fail:
 414        p->status = USB_RET_STALL;
 415        break;
 416    }
 417}
 418
 419static int usb_serial_can_read(void *opaque)
 420{
 421    USBSerialState *s = opaque;
 422
 423    if (!s->dev.attached) {
 424        return 0;
 425    }
 426    return RECV_BUF - s->recv_used;
 427}
 428
 429static void usb_serial_read(void *opaque, const uint8_t *buf, int size)
 430{
 431    USBSerialState *s = opaque;
 432    int first_size, start;
 433
 434    /* room in the buffer? */
 435    if (size > (RECV_BUF - s->recv_used))
 436        size = RECV_BUF - s->recv_used;
 437
 438    start = s->recv_ptr + s->recv_used;
 439    if (start < RECV_BUF) {
 440        /* copy data to end of buffer */
 441        first_size = RECV_BUF - start;
 442        if (first_size > size)
 443            first_size = size;
 444
 445        memcpy(s->recv_buf + start, buf, first_size);
 446
 447        /* wrap around to front if needed */
 448        if (size > first_size)
 449            memcpy(s->recv_buf, buf + first_size, size - first_size);
 450    } else {
 451        start -= RECV_BUF;
 452        memcpy(s->recv_buf + start, buf, size);
 453    }
 454    s->recv_used += size;
 455}
 456
 457static void usb_serial_event(void *opaque, int event)
 458{
 459    USBSerialState *s = opaque;
 460
 461    switch (event) {
 462        case CHR_EVENT_BREAK:
 463            s->event_trigger |= FTDI_BI;
 464            break;
 465        case CHR_EVENT_FOCUS:
 466            break;
 467        case CHR_EVENT_OPENED:
 468            if (!s->dev.attached) {
 469                usb_device_attach(&s->dev, &error_abort);
 470            }
 471            break;
 472        case CHR_EVENT_CLOSED:
 473            if (s->dev.attached) {
 474                usb_device_detach(&s->dev);
 475            }
 476            break;
 477    }
 478}
 479
 480static void usb_serial_realize(USBDevice *dev, Error **errp)
 481{
 482    USBSerialState *s = USB_SERIAL_DEV(dev);
 483    Error *local_err = NULL;
 484
 485    usb_desc_create_serial(dev);
 486    usb_desc_init(dev);
 487    dev->auto_attach = 0;
 488
 489    if (!s->cs) {
 490        error_setg(errp, "Property chardev is required");
 491        return;
 492    }
 493
 494    usb_check_attach(dev, &local_err);
 495    if (local_err) {
 496        error_propagate(errp, local_err);
 497        return;
 498    }
 499
 500    qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
 501                          usb_serial_event, s);
 502    usb_serial_handle_reset(dev);
 503
 504    if (s->cs->be_open && !dev->attached) {
 505        usb_device_attach(dev, &error_abort);
 506    }
 507}
 508
 509static USBDevice *usb_serial_init(USBBus *bus, const char *filename)
 510{
 511    USBDevice *dev;
 512    CharDriverState *cdrv;
 513    uint32_t vendorid = 0, productid = 0;
 514    char label[32];
 515    static int index;
 516
 517    while (*filename && *filename != ':') {
 518        const char *p;
 519        char *e;
 520        if (strstart(filename, "vendorid=", &p)) {
 521            vendorid = strtol(p, &e, 16);
 522            if (e == p || (*e && *e != ',' && *e != ':')) {
 523                error_report("bogus vendor ID %s", p);
 524                return NULL;
 525            }
 526            filename = e;
 527        } else if (strstart(filename, "productid=", &p)) {
 528            productid = strtol(p, &e, 16);
 529            if (e == p || (*e && *e != ',' && *e != ':')) {
 530                error_report("bogus product ID %s", p);
 531                return NULL;
 532            }
 533            filename = e;
 534        } else {
 535            error_report("unrecognized serial USB option %s", filename);
 536            return NULL;
 537        }
 538        while(*filename == ',')
 539            filename++;
 540    }
 541    if (!*filename) {
 542        error_report("character device specification needed");
 543        return NULL;
 544    }
 545    filename++;
 546
 547    snprintf(label, sizeof(label), "usbserial%d", index++);
 548    cdrv = qemu_chr_new(label, filename, NULL);
 549    if (!cdrv)
 550        return NULL;
 551
 552    dev = usb_create(bus, "usb-serial");
 553    qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
 554    if (vendorid)
 555        qdev_prop_set_uint16(&dev->qdev, "vendorid", vendorid);
 556    if (productid)
 557        qdev_prop_set_uint16(&dev->qdev, "productid", productid);
 558    return dev;
 559}
 560
 561static USBDevice *usb_braille_init(USBBus *bus, const char *unused)
 562{
 563    USBDevice *dev;
 564    CharDriverState *cdrv;
 565
 566    cdrv = qemu_chr_new("braille", "braille", NULL);
 567    if (!cdrv)
 568        return NULL;
 569
 570    dev = usb_create(bus, "usb-braille");
 571    qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
 572    return dev;
 573}
 574
 575static const VMStateDescription vmstate_usb_serial = {
 576    .name = "usb-serial",
 577    .unmigratable = 1,
 578};
 579
 580static Property serial_properties[] = {
 581    DEFINE_PROP_CHR("chardev", USBSerialState, cs),
 582    DEFINE_PROP_END_OF_LIST(),
 583};
 584
 585static void usb_serial_dev_class_init(ObjectClass *klass, void *data)
 586{
 587    DeviceClass *dc = DEVICE_CLASS(klass);
 588    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 589
 590    uc->realize        = usb_serial_realize;
 591    uc->handle_reset   = usb_serial_handle_reset;
 592    uc->handle_control = usb_serial_handle_control;
 593    uc->handle_data    = usb_serial_handle_data;
 594    dc->vmsd = &vmstate_usb_serial;
 595    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 596}
 597
 598static const TypeInfo usb_serial_dev_type_info = {
 599    .name = TYPE_USB_SERIAL,
 600    .parent = TYPE_USB_DEVICE,
 601    .instance_size = sizeof(USBSerialState),
 602    .abstract = true,
 603    .class_init = usb_serial_dev_class_init,
 604};
 605
 606static void usb_serial_class_initfn(ObjectClass *klass, void *data)
 607{
 608    DeviceClass *dc = DEVICE_CLASS(klass);
 609    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 610
 611    uc->product_desc   = "QEMU USB Serial";
 612    uc->usb_desc       = &desc_serial;
 613    dc->props = serial_properties;
 614}
 615
 616static const TypeInfo serial_info = {
 617    .name          = "usb-serial",
 618    .parent        = TYPE_USB_SERIAL,
 619    .class_init    = usb_serial_class_initfn,
 620};
 621
 622static Property braille_properties[] = {
 623    DEFINE_PROP_CHR("chardev", USBSerialState, cs),
 624    DEFINE_PROP_END_OF_LIST(),
 625};
 626
 627static void usb_braille_class_initfn(ObjectClass *klass, void *data)
 628{
 629    DeviceClass *dc = DEVICE_CLASS(klass);
 630    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 631
 632    uc->product_desc   = "QEMU USB Braille";
 633    uc->usb_desc       = &desc_braille;
 634    dc->props = braille_properties;
 635}
 636
 637static const TypeInfo braille_info = {
 638    .name          = "usb-braille",
 639    .parent        = TYPE_USB_SERIAL,
 640    .class_init    = usb_braille_class_initfn,
 641};
 642
 643static void usb_serial_register_types(void)
 644{
 645    type_register_static(&usb_serial_dev_type_info);
 646    type_register_static(&serial_info);
 647    usb_legacy_register("usb-serial", "serial", usb_serial_init);
 648    type_register_static(&braille_info);
 649    usb_legacy_register("usb-braille", "braille", usb_braille_init);
 650}
 651
 652type_init(usb_serial_register_types)
 653