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

📄 usb-msd.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
                /* language ids */                data[0] = 4;                data[1] = 3;                data[2] = 0x09;                data[3] = 0x04;                ret = 4;                break;            case 1:                /* vendor description */                ret = set_usb_string(data, "QEMU " QEMU_VERSION);                break;            case 2:                /* product description */                ret = set_usb_string(data, "QEMU USB HARDDRIVE");                break;            case 3:                /* serial number */                ret = set_usb_string(data, "1");                break;            default:                goto fail;            }            break;        default:            goto fail;        }        break;    case DeviceRequest | USB_REQ_GET_CONFIGURATION:        data[0] = 1;        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 DeviceOutRequest | USB_REQ_SET_INTERFACE:        ret = 0;        break;    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:        if (value == 0 && index != 0x81) { /* clear ep halt */            goto fail;        }        ret = 0;        break;        /* Class specific requests.  */    case MassStorageReset:        /* Reset state ready for the next CBW.  */        s->mode = USB_MSDM_CBW;        ret = 0;        break;    case GetMaxLun:        data[0] = 0;        ret = 1;        break;    default:    fail:        ret = USB_RET_STALL;        break;    }    return ret;}static void usb_msd_cancel_io(USBPacket *p, void *opaque){    MSDState *s = opaque;    scsi_cancel_io(s->scsi_dev, s->tag);    s->packet = NULL;    s->scsi_len = 0;}static int usb_msd_handle_data(USBDevice *dev, USBPacket *p){    MSDState *s = (MSDState *)dev;    int ret = 0;    struct usb_msd_cbw cbw;    uint8_t devep = p->devep;    uint8_t *data = p->data;    int len = p->len;    switch (p->pid) {    case USB_TOKEN_OUT:        if (devep != 2)            goto fail;        switch (s->mode) {        case USB_MSDM_CBW:            if (len != 31) {                fprintf(stderr, "usb-msd: Bad CBW size");                goto fail;            }            memcpy(&cbw, data, 31);            if (le32_to_cpu(cbw.sig) != 0x43425355) {                fprintf(stderr, "usb-msd: Bad signature %08x\n",                        le32_to_cpu(cbw.sig));                goto fail;            }            DPRINTF("Command on LUN %d\n", cbw.lun);            if (cbw.lun != 0) {                fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);                goto fail;            }            s->tag = le32_to_cpu(cbw.tag);            s->data_len = le32_to_cpu(cbw.data_len);            if (s->data_len == 0) {                s->mode = USB_MSDM_CSW;            } else if (cbw.flags & 0x80) {                s->mode = USB_MSDM_DATAIN;            } else {                s->mode = USB_MSDM_DATAOUT;            }            DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",                    s->tag, cbw.flags, cbw.cmd_len, s->data_len);            s->residue = 0;            scsi_send_command(s->scsi_dev, s->tag, cbw.cmd, 0);            /* ??? Should check that USB and SCSI data transfer               directions match.  */            if (s->residue == 0) {                if (s->mode == USB_MSDM_DATAIN) {                    scsi_read_data(s->scsi_dev, s->tag);                } else if (s->mode == USB_MSDM_DATAOUT) {                    scsi_write_data(s->scsi_dev, s->tag);                }            }            ret = len;            break;        case USB_MSDM_DATAOUT:            DPRINTF("Data out %d/%d\n", len, s->data_len);            if (len > s->data_len)                goto fail;            s->usb_buf = data;            s->usb_len = len;            if (s->scsi_len) {                usb_msd_copy_data(s);            }            if (s->residue && s->usb_len) {                s->data_len -= s->usb_len;                if (s->data_len == 0)                    s->mode = USB_MSDM_CSW;                s->usb_len = 0;            }            if (s->usb_len) {                DPRINTF("Deferring packet %p\n", p);                usb_defer_packet(p, usb_msd_cancel_io, s);                s->packet = p;                ret = USB_RET_ASYNC;            } else {                ret = len;            }            break;        default:            DPRINTF("Unexpected write (len %d)\n", len);            goto fail;        }        break;    case USB_TOKEN_IN:        if (devep != 1)            goto fail;        switch (s->mode) {        case USB_MSDM_DATAOUT:            if (s->data_len != 0 || len < 13)                goto fail;            /* Waiting for SCSI write to complete.  */            usb_defer_packet(p, usb_msd_cancel_io, s);            s->packet = p;            ret = USB_RET_ASYNC;            break;        case USB_MSDM_CSW:            DPRINTF("Command status %d tag 0x%x, len %d\n",                    s->result, s->tag, len);            if (len < 13)                goto fail;            s->usb_len = len;            s->usb_buf = data;            usb_msd_send_status(s);            s->mode = USB_MSDM_CBW;            ret = 13;            break;        case USB_MSDM_DATAIN:            DPRINTF("Data in %d/%d\n", len, s->data_len);            if (len > s->data_len)                len = s->data_len;            s->usb_buf = data;            s->usb_len = len;            if (s->scsi_len) {                usb_msd_copy_data(s);            }            if (s->residue && s->usb_len) {                s->data_len -= s->usb_len;                memset(s->usb_buf, 0, s->usb_len);                if (s->data_len == 0)                    s->mode = USB_MSDM_CSW;                s->usb_len = 0;            }            if (s->usb_len) {                DPRINTF("Deferring packet %p\n", p);                usb_defer_packet(p, usb_msd_cancel_io, s);                s->packet = p;                ret = USB_RET_ASYNC;            } else {                ret = len;            }            break;        default:            DPRINTF("Unexpected read (len %d)\n", len);            goto fail;        }        break;    default:        DPRINTF("Bad token\n");    fail:        ret = USB_RET_STALL;        break;    }    return ret;}static void usb_msd_handle_destroy(USBDevice *dev){    MSDState *s = (MSDState *)dev;    scsi_disk_destroy(s->scsi_dev);    bdrv_delete(s->bs);    qemu_free(s);}USBDevice *usb_msd_init(const char *filename, BlockDriver *drv){    MSDState *s;    BlockDriverState *bdrv;    s = qemu_mallocz(sizeof(MSDState));    if (!s)        return NULL;    bdrv = bdrv_new("usb");    if (bdrv_open2(bdrv, filename, 0, drv) < 0)        goto fail;    s->bs = bdrv;    s->dev.speed = USB_SPEED_FULL;    s->dev.handle_packet = usb_generic_handle_packet;    s->dev.handle_reset = usb_msd_handle_reset;    s->dev.handle_control = usb_msd_handle_control;    s->dev.handle_data = usb_msd_handle_data;    s->dev.handle_destroy = usb_msd_handle_destroy;    snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB MSD(%.16s)",             filename);    s->scsi_dev = scsi_disk_init(bdrv, 0, usb_msd_command_complete, s);    usb_msd_handle_reset((USBDevice *)s);    return (USBDevice *)s; fail:    qemu_free(s);    return NULL;}

⌨️ 快捷键说明

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