]> git.proxmox.com Git - qemu.git/blobdiff - hw/usb-msd.c
usb: Resolve warnings about unassigned bus on usb device creation
[qemu.git] / hw / usb-msd.c
index 90e57fbf6ba64ea069c2c9e139fe4b7ac1385451..c6f08a031386af876cf549bc6d1fdbc69c2e0cd3 100644 (file)
@@ -38,6 +38,13 @@ enum USBMSDMode {
     USB_MSDM_CSW /* Command Status.  */
 };
 
+struct usb_msd_csw {
+    uint32_t sig;
+    uint32_t tag;
+    uint32_t residue;
+    uint8_t status;
+};
+
 typedef struct {
     USBDevice dev;
     enum USBMSDMode mode;
@@ -45,14 +52,13 @@ typedef struct {
     uint8_t *scsi_buf;
     uint32_t data_len;
     uint32_t residue;
-    uint32_t tag;
+    struct usb_msd_csw csw;
     SCSIRequest *req;
     SCSIBus bus;
     BlockConf conf;
     char *serial;
     SCSIDevice *scsi_dev;
     uint32_t removable;
-    int result;
     /* For async completion.  */
     USBPacket *packet;
 } MSDState;
@@ -67,13 +73,6 @@ struct usb_msd_cbw {
     uint8_t cmd[16];
 };
 
-struct usb_msd_csw {
-    uint32_t sig;
-    uint32_t tag;
-    uint32_t residue;
-    uint8_t status;
-};
-
 enum {
     STR_MANUFACTURER = 1,
     STR_PRODUCT,
@@ -162,8 +161,8 @@ static const USBDescDevice desc_device_high = {
 
 static const USBDesc desc = {
     .id = {
-        .idVendor          = 0,
-        .idProduct         = 0,
+        .idVendor          = 0x46f4, /* CRC16() of "QEMU" */
+        .idProduct         = 0x0001,
         .bcdDevice         = 0,
         .iManufacturer     = STR_MANUFACTURER,
         .iProduct          = STR_PRODUCT,
@@ -191,17 +190,15 @@ static void usb_msd_copy_data(MSDState *s, USBPacket *p)
 
 static void usb_msd_send_status(MSDState *s, USBPacket *p)
 {
-    struct usb_msd_csw csw;
     int len;
 
-    csw.sig = cpu_to_le32(0x53425355);
-    csw.tag = cpu_to_le32(s->tag);
-    csw.residue = s->residue;
-    csw.status = s->result;
+    DPRINTF("Command status %d tag 0x%x, len %zd\n",
+            s->csw.status, s->csw.tag, p->iov.size);
 
-    len = MIN(sizeof(csw), p->iov.size);
-    usb_packet_copy(p, &csw, len);
-    p->result = len;
+    assert(s->csw.sig == 0x53425355);
+    len = MIN(sizeof(s->csw), p->iov.size);
+    usb_packet_copy(p, &s->csw, len);
+    memset(&s->csw, 0, sizeof(s->csw));
 }
 
 static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
@@ -226,14 +223,19 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
     }
 }
 
-static void usb_msd_command_complete(SCSIRequest *req, uint32_t status)
+static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t resid)
 {
     MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
     USBPacket *p = s->packet;
 
-    DPRINTF("Command complete %d\n", status);
+    DPRINTF("Command complete %d tag 0x%x\n", status, req->tag);
     s->residue = s->data_len;
-    s->result = status != 0;
+
+    s->csw.sig = cpu_to_le32(0x53425355);
+    s->csw.tag = cpu_to_le32(req->tag);
+    s->csw.residue = s->residue;
+    s->csw.status = status != 0;
+
     if (s->packet) {
         if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
             /* A deferred packet with no write data remaining must be
@@ -276,6 +278,18 @@ static void usb_msd_handle_reset(USBDevice *dev)
     MSDState *s = (MSDState *)dev;
 
     DPRINTF("Reset\n");
+    if (s->req) {
+        scsi_req_cancel(s->req);
+    }
+    assert(s->req == NULL);
+
+    if (s->packet) {
+        USBPacket *p = s->packet;
+        s->packet = NULL;
+        p->result = USB_RET_STALL;
+        usb_packet_complete(dev, p);
+    }
+
     s->mode = USB_MSDM_CBW;
 }
 
@@ -292,19 +306,9 @@ static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
 
     ret = 0;
     switch (request) {
-    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:
         ret = 0;
         break;
-    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
-        ret = 0;
-        break;
         /* Class specific requests.  */
     case ClassInterfaceOutRequest | MassStorageReset:
         /* Reset state ready for the next CBW.  */
@@ -325,15 +329,19 @@ static int usb_msd_handle_control(USBDevice *dev, USBPacket *p,
 static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
 {
     MSDState *s = DO_UPCAST(MSDState, dev, dev);
-    scsi_req_cancel(s->req);
+
+    if (s->req) {
+        scsi_req_cancel(s->req);
+    }
 }
 
 static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
 {
     MSDState *s = (MSDState *)dev;
+    uint32_t tag;
     int ret = 0;
     struct usb_msd_cbw cbw;
-    uint8_t devep = p->devep;
+    uint8_t devep = p->ep->nr;
 
     switch (p->pid) {
     case USB_TOKEN_OUT:
@@ -357,7 +365,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
                 fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);
                 goto fail;
             }
-            s->tag = le32_to_cpu(cbw.tag);
+            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;
@@ -367,14 +375,12 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
                 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);
+                    tag, cbw.flags, cbw.cmd_len, s->data_len);
             s->residue = 0;
             s->scsi_len = 0;
-            s->req = scsi_req_new(s->scsi_dev, s->tag, 0, NULL);
-            scsi_req_enqueue(s->req, cbw.cmd);
-            /* ??? Should check that USB and SCSI data transfer
-               directions match.  */
-            if (s->mode != USB_MSDM_CSW && s->residue == 0) {
+            s->req = scsi_req_new(s->scsi_dev, tag, 0, cbw.cmd, NULL);
+            scsi_req_enqueue(s->req);
+            if (s->req && s->req->cmd.xfer != SCSI_XFER_NONE) {
                 scsi_req_continue(s->req);
             }
             ret = p->result;
@@ -429,15 +435,19 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             break;
 
         case USB_MSDM_CSW:
-            DPRINTF("Command status %d tag 0x%x, len %zd\n",
-                    s->result, s->tag, p->iov.size);
             if (p->iov.size < 13) {
                 goto fail;
             }
 
-            usb_msd_send_status(s, p);
-            s->mode = USB_MSDM_CBW;
-            ret = 13;
+            if (s->req) {
+                /* still in flight */
+                s->packet = p;
+                ret = USB_RET_ASYNC;
+            } else {
+                usb_msd_send_status(s, p);
+                s->mode = USB_MSDM_CBW;
+                ret = 13;
+            }
             break;
 
         case USB_MSDM_DATAIN:
@@ -492,7 +502,11 @@ static void usb_msd_password_cb(void *opaque, int err)
         qdev_unplug(&s->dev.qdev);
 }
 
-static const struct SCSIBusOps usb_msd_scsi_ops = {
+static const struct SCSIBusInfo usb_msd_scsi_info = {
+    .tcq = false,
+    .max_target = 0,
+    .max_lun = 0,
+
     .transfer_data = usb_msd_transfer_data,
     .complete = usb_msd_command_complete,
     .cancel = usb_msd_request_cancelled
@@ -505,7 +519,7 @@ static int usb_msd_initfn(USBDevice *dev)
     DriveInfo *dinfo;
 
     if (!bs) {
-        error_report("usb-msd: drive property not set");
+        error_report("drive property not set");
         return -1;
     }
 
@@ -518,7 +532,7 @@ static int usb_msd_initfn(USBDevice *dev)
      *
      * The hack is probably a bad idea.
      */
-    bdrv_detach(bs, &s->dev.qdev);
+    bdrv_detach_dev(bs, &s->dev.qdev);
     s->conf.bs = NULL;
 
     if (!s->serial) {
@@ -533,8 +547,9 @@ static int usb_msd_initfn(USBDevice *dev)
     }
 
     usb_desc_init(dev);
-    scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, &usb_msd_scsi_ops);
-    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable);
+    scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info);
+    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
+                                            s->conf.bootindex);
     if (!s->scsi_dev) {
         return -1;
     }
@@ -550,11 +565,10 @@ static int usb_msd_initfn(USBDevice *dev)
         }
     }
 
-    add_boot_device_path(s->conf.bootindex, &dev->qdev, "/disk@0,0");
     return 0;
 }
 
-static USBDevice *usb_msd_init(const char *filename)
+static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
 {
     static int nr=0;
     char id[8];
@@ -597,7 +611,7 @@ static USBDevice *usb_msd_init(const char *filename)
     }
 
     /* create guest device */
-    dev = usb_create(NULL /* FIXME */, "usb-storage");
+    dev = usb_create(bus, "usb-storage");
     if (!dev) {
         return NULL;
     }
@@ -622,32 +636,42 @@ static const VMStateDescription vmstate_usb_msd = {
     }
 };
 
-static struct USBDeviceInfo msd_info = {
-    .product_desc   = "QEMU USB MSD",
-    .qdev.name      = "usb-storage",
-    .qdev.fw_name      = "storage",
-    .qdev.size      = sizeof(MSDState),
-    .qdev.vmsd      = &vmstate_usb_msd,
-    .usb_desc       = &desc,
-    .init           = usb_msd_initfn,
-    .handle_packet  = usb_generic_handle_packet,
-    .cancel_packet  = usb_msd_cancel_io,
-    .handle_attach  = usb_desc_attach,
-    .handle_reset   = usb_msd_handle_reset,
-    .handle_control = usb_msd_handle_control,
-    .handle_data    = usb_msd_handle_data,
-    .usbdevice_name = "disk",
-    .usbdevice_init = usb_msd_init,
-    .qdev.props     = (Property[]) {
-        DEFINE_BLOCK_PROPERTIES(MSDState, conf),
-        DEFINE_PROP_STRING("serial", MSDState, serial),
-        DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
-        DEFINE_PROP_END_OF_LIST(),
-    },
+static Property msd_properties[] = {
+    DEFINE_BLOCK_PROPERTIES(MSDState, conf),
+    DEFINE_PROP_STRING("serial", MSDState, serial),
+    DEFINE_PROP_BIT("removable", MSDState, removable, 0, false),
+    DEFINE_PROP_END_OF_LIST(),
 };
 
-static void usb_msd_register_devices(void)
+static void usb_msd_class_initfn(ObjectClass *klass, void *data)
 {
-    usb_qdev_register(&msd_info);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
+
+    uc->init           = usb_msd_initfn;
+    uc->product_desc   = "QEMU USB MSD";
+    uc->usb_desc       = &desc;
+    uc->cancel_packet  = usb_msd_cancel_io;
+    uc->handle_attach  = usb_desc_attach;
+    uc->handle_reset   = usb_msd_handle_reset;
+    uc->handle_control = usb_msd_handle_control;
+    uc->handle_data    = usb_msd_handle_data;
+    dc->fw_name = "storage";
+    dc->vmsd = &vmstate_usb_msd;
+    dc->props = msd_properties;
 }
-device_init(usb_msd_register_devices)
+
+static TypeInfo msd_info = {
+    .name          = "usb-storage",
+    .parent        = TYPE_USB_DEVICE,
+    .instance_size = sizeof(MSDState),
+    .class_init    = usb_msd_class_initfn,
+};
+
+static void usb_msd_register_types(void)
+{
+    type_register_static(&msd_info);
+    usb_legacy_register("usb-storage", "disk", usb_msd_init);
+}
+
+type_init(usb_msd_register_types)