⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb-serial.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 2 页
字号:
        ret = 1;        break;    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:        ret = 0;        break;    case DeviceRequest | USB_REQ_GET_INTERFACE:        data[0] = 0;        ret = 1;        break;    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:        ret = 0;        break;    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:        ret = 0;        break;        /* Class specific requests.  */    case DeviceOutVendor | FTDI_RESET:        switch (value) {        case FTDI_RESET_SIO:            usb_serial_reset(s);            break;        case FTDI_RESET_RX:            s->recv_ptr = 0;            s->recv_used = 0;            /* TODO: purge from char device */            break;        case FTDI_RESET_TX:            /* TODO: purge from char device */            break;        }        break;    case DeviceOutVendor | FTDI_SET_MDM_CTRL:        s->lines = value & FTDI_MDM_CTRL;        break;    case DeviceOutVendor | FTDI_SET_FLOW_CTRL:        /* TODO: ioctl */        break;    case DeviceOutVendor | FTDI_SET_BAUD: {        static const int subdivisors8[8] = { 0, 4, 2, 1, 3, 5, 6, 7 };        int subdivisor8 = subdivisors8[((value & 0xc000) >> 14)                                     | ((index & 1) << 2)];        int divisor = value & 0x3fff;        /* chip special cases */        if (divisor == 1 && subdivisor8 == 0)            subdivisor8 = 4;        if (divisor == 0 && subdivisor8 == 0)            divisor = 1;        s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8);        qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);        break;    }    case DeviceOutVendor | FTDI_SET_DATA:        switch (value & FTDI_PARITY) {            case 0:                s->params.parity = 'N';                break;            case FTDI_ODD:                s->params.parity = 'O';                break;            case FTDI_EVEN:                s->params.parity = 'E';                break;            default:                DPRINTF("unsupported parity %d\n", value & FTDI_PARITY);                goto fail;        }        switch (value & FTDI_STOP) {            case FTDI_STOP1:                s->params.stop_bits = 1;                break;            case FTDI_STOP2:                s->params.stop_bits = 2;                break;            default:                DPRINTF("unsupported stop bits %d\n", value & FTDI_STOP);                goto fail;        }        qemu_chr_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);        /* TODO: TX ON/OFF */        break;    case DeviceInVendor | FTDI_GET_MDM_ST:        /* TODO: return modem status */        data[0] = 0;        ret = 1;        break;    case DeviceOutVendor | FTDI_SET_EVENT_CHR:        /* TODO: handle it */        s->event_chr = value;        break;    case DeviceOutVendor | FTDI_SET_ERROR_CHR:        /* TODO: handle it */        s->error_chr = value;        break;    case DeviceOutVendor | FTDI_SET_LATENCY:        s->latency = value;        break;    case DeviceInVendor | FTDI_GET_LATENCY:        data[0] = s->latency;        ret = 1;        break;    default:    fail:        DPRINTF("got unsupported/bogus control %x, value %x\n", request, value);        ret = USB_RET_STALL;        break;    }    return ret;}static int usb_serial_handle_data(USBDevice *dev, USBPacket *p){    USBSerialState *s = (USBSerialState *)dev;    int ret = 0;    uint8_t devep = p->devep;    uint8_t *data = p->data;    int len = p->len;    int first_len;    switch (p->pid) {    case USB_TOKEN_OUT:        if (devep != 2)            goto fail;        qemu_chr_write(s->cs, data, len);        break;    case USB_TOKEN_IN:        if (devep != 1)            goto fail;        first_len = RECV_BUF - s->recv_ptr;        if (len <= 2) {            ret = USB_RET_NAK;            break;        }        /* TODO: Report serial line status */        *data++ = 0;        *data++ = 0;        len -= 2;        if (len > s->recv_used)            len = s->recv_used;        if (!len) {            ret = USB_RET_NAK;            break;        }        if (first_len > len)            first_len = len;        memcpy(data, s->recv_buf + s->recv_ptr, first_len);        if (len > first_len)            memcpy(data + first_len, s->recv_buf, len - first_len);        s->recv_used -= len;        s->recv_ptr = (s->recv_ptr + len) % RECV_BUF;        ret = len + 2;        break;    default:        DPRINTF("Bad token\n");    fail:        ret = USB_RET_STALL;        break;    }    return ret;}static void usb_serial_handle_destroy(USBDevice *dev){    USBSerialState *s = (USBSerialState *)dev;    qemu_chr_close(s->cs);    qemu_free(s);}int usb_serial_can_read(void *opaque){    USBSerialState *s = opaque;    return RECV_BUF - s->recv_used;}void usb_serial_read(void *opaque, const uint8_t *buf, int size){    USBSerialState *s = opaque;    int first_size = RECV_BUF - s->recv_ptr;    if (first_size > size)        first_size = size;    memcpy(s->recv_buf + s->recv_ptr + s->recv_used, buf, first_size);    if (size > first_size)        memcpy(s->recv_buf, buf + first_size, size - first_size);    s->recv_used += size;}void usb_serial_event(void *opaque, int event){    USBSerialState *s = opaque;    switch (event) {        case CHR_EVENT_BREAK:            /* TODO: Send Break to USB */            break;        case CHR_EVENT_FOCUS:            break;        case CHR_EVENT_RESET:            usb_serial_reset(s);            /* TODO: Reset USB port */            break;    }}USBDevice *usb_serial_init(const char *filename){    USBSerialState *s;    CharDriverState *cdrv;    unsigned short vendorid = 0x0403, productid = 0x6001;    while (*filename && *filename != ':') {        const char *p;        char *e;        if (strstart(filename, "vendorid=", &p)) {            vendorid = strtol(p, &e, 16);            if (e == p || (*e && *e != ',' && *e != ':')) {                printf("bogus vendor ID %s\n", p);                return NULL;            }            filename = e;        } else if (strstart(filename, "productid=", &p)) {            productid = strtol(p, &e, 16);            if (e == p || (*e && *e != ',' && *e != ':')) {                printf("bogus product ID %s\n", p);                return NULL;            }            filename = e;        } else {            printf("unrecognized serial USB option %s\n", filename);            return NULL;        }        while(*filename == ',')            filename++;    }    if (!*filename) {        printf("character device specification needed\n");        return NULL;    }    filename++;    s = qemu_mallocz(sizeof(USBSerialState));    if (!s)        return NULL;    cdrv = qemu_chr_open(filename);    if (!cdrv)        goto fail;    s->cs = cdrv;    qemu_chr_add_handlers(cdrv, usb_serial_can_read, usb_serial_read, usb_serial_event, s);    s->dev.speed = USB_SPEED_FULL;    s->dev.handle_packet = usb_generic_handle_packet;    s->dev.handle_reset = usb_serial_handle_reset;    s->dev.handle_control = usb_serial_handle_control;    s->dev.handle_data = usb_serial_handle_data;    s->dev.handle_destroy = usb_serial_handle_destroy;    s->vendorid = vendorid;    s->productid = productid;    snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Serial(%.16s)",             filename);    usb_serial_handle_reset((USBDevice *)s);    return (USBDevice *)s; fail:    qemu_free(s);    return NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -