]> git.proxmox.com Git - qemu.git/blobdiff - hw/usb-msd.c
qdev: Replace device names containing whitespace
[qemu.git] / hw / usb-msd.c
index b1ad9ec09d4878a4d5198c0a45d9c6176f986d0b..1fb62ad13c46f7d9cc4c704529df3ee6b13f2ec3 100644 (file)
@@ -7,15 +7,22 @@
  * This code is licenced under the LGPL.
  */
 
-#include "vl.h"
+#include "qemu-common.h"
+#include "qemu-option.h"
+#include "qemu-config.h"
+#include "usb.h"
+#include "block.h"
+#include "scsi.h"
+#include "console.h"
+#include "monitor.h"
 
 //#define DEBUG_MSD
 
 #ifdef DEBUG_MSD
-#define DPRINTF(fmt, args...) \
-do { printf("usb-msd: " fmt , ##args); } while (0)
+#define DPRINTF(fmt, ...) \
+do { printf("usb-msd: " fmt , ## __VA_ARGS__); } while (0)
 #else
-#define DPRINTF(fmt, args...) do {} while(0)
+#define DPRINTF(fmt, ...) do {} while(0)
 #endif
 
 /* USB requests.  */
@@ -39,7 +46,8 @@ typedef struct {
     uint32_t data_len;
     uint32_t residue;
     uint32_t tag;
-    BlockDriverState *bs;
+    SCSIBus bus;
+    DriveInfo *dinfo;
     SCSIDevice *scsi_dev;
     int result;
     /* For async completion.  */
@@ -146,9 +154,9 @@ static void usb_msd_copy_data(MSDState *s)
     s->data_len -= len;
     if (s->scsi_len == 0) {
         if (s->mode == USB_MSDM_DATAIN) {
-            scsi_read_data(s->scsi_dev, s->tag);
+            s->scsi_dev->info->read_data(s->scsi_dev, s->tag);
         } else if (s->mode == USB_MSDM_DATAOUT) {
-            scsi_write_data(s->scsi_dev, s->tag);
+            s->scsi_dev->info->write_data(s->scsi_dev, s->tag);
         }
     }
 }
@@ -164,10 +172,10 @@ static void usb_msd_send_status(MSDState *s)
     memcpy(s->usb_buf, &csw, 13);
 }
 
-static void usb_msd_command_complete(void *opaque, int reason, uint32_t tag,
+static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
                                      uint32_t arg)
 {
-    MSDState *s = (MSDState *)opaque;
+    MSDState *s = DO_UPCAST(MSDState, dev.qdev, bus->qbus.parent);
     USBPacket *p = s->packet;
 
     if (tag != s->tag) {
@@ -201,7 +209,7 @@ static void usb_msd_command_complete(void *opaque, int reason, uint32_t tag,
         return;
     }
     s->scsi_len = arg;
-    s->scsi_buf = scsi_get_buf(s->scsi_dev, tag);
+    s->scsi_buf = s->scsi_dev->info->get_buf(s->scsi_dev, tag);
     if (p) {
         usb_msd_copy_data(s);
         if (s->usb_len == 0) {
@@ -339,7 +347,7 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
 static void usb_msd_cancel_io(USBPacket *p, void *opaque)
 {
     MSDState *s = opaque;
-    scsi_cancel_io(s->scsi_dev, s->tag);
+    s->scsi_dev->info->cancel_io(s->scsi_dev, s->tag);
     s->packet = NULL;
     s->scsi_len = 0;
 }
@@ -387,14 +395,14 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             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);
+            s->scsi_dev->info->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);
+                    s->scsi_dev->info->read_data(s->scsi_dev, s->tag);
                 } else if (s->mode == USB_MSDM_DATAOUT) {
-                    scsi_write_data(s->scsi_dev, s->tag);
+                    s->scsi_dev->info->write_data(s->scsi_dev, s->tag);
                 }
             }
             ret = len;
@@ -501,46 +509,115 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
     return ret;
 }
 
-static void usb_msd_handle_destroy(USBDevice *dev)
+static void usb_msd_password_cb(void *opaque, int err)
 {
-    MSDState *s = (MSDState *)dev;
+    MSDState *s = opaque;
 
-    scsi_disk_destroy(s->scsi_dev);
-    bdrv_delete(s->bs);
-    qemu_free(s);
+    if (!err)
+        usb_device_attach(&s->dev);
+    else
+        qdev_unplug(&s->dev.qdev);
 }
 
-USBDevice *usb_msd_init(const char *filename)
+static int usb_msd_initfn(USBDevice *dev)
 {
-    MSDState *s;
-    BlockDriverState *bdrv;
+    MSDState *s = DO_UPCAST(MSDState, dev, dev);
+
+    if (!s->dinfo || !s->dinfo->bdrv) {
+        qemu_error("usb-msd: drive property not set\n");
+        return -1;
+    }
 
-    s = qemu_mallocz(sizeof(MSDState));
-    if (!s)
+    s->dev.speed = USB_SPEED_FULL;
+    scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete);
+    s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, s->dinfo, 0);
+    s->bus.qbus.allow_hotplug = 0;
+    usb_msd_handle_reset(dev);
+
+    if (bdrv_key_required(s->dinfo->bdrv)) {
+        if (s->dev.qdev.hotplugged) {
+            monitor_read_bdrv_key_start(cur_mon, s->dinfo->bdrv,
+                                        usb_msd_password_cb, s);
+            s->dev.auto_attach = 0;
+        } else {
+            autostart = 0;
+        }
+    }
+
+    return 0;
+}
+
+static USBDevice *usb_msd_init(const char *filename)
+{
+    static int nr=0;
+    char id[8];
+    QemuOpts *opts;
+    DriveInfo *dinfo;
+    USBDevice *dev;
+    int fatal_error;
+    const char *p1;
+    char fmt[32];
+
+    /* parse -usbdevice disk: syntax into drive opts */
+    snprintf(id, sizeof(id), "usb%d", nr++);
+    opts = qemu_opts_create(&qemu_drive_opts, id, 0);
+
+    p1 = strchr(filename, ':');
+    if (p1++) {
+        const char *p2;
+
+        if (strstart(filename, "format=", &p2)) {
+            int len = MIN(p1 - p2, sizeof(fmt));
+            pstrcpy(fmt, len, p2);
+            qemu_opt_set(opts, "format", fmt);
+        } else if (*filename != ':') {
+            printf("unrecognized USB mass-storage option %s\n", filename);
+            return NULL;
+        }
+        filename = p1;
+    }
+    if (!*filename) {
+        printf("block device specification needed\n");
         return NULL;
+    }
+    qemu_opt_set(opts, "file", filename);
+    qemu_opt_set(opts, "if", "none");
 
-    bdrv = bdrv_new("usb");
-    if (bdrv_open(bdrv, filename, 0) < 0)
-        goto fail;
-    if (qemu_key_check(bdrv, filename))
-        goto fail;
-    s->bs = bdrv;
+    /* create host drive */
+    dinfo = drive_init(opts, NULL, &fatal_error);
+    if (!dinfo) {
+        qemu_opts_del(opts);
+        return NULL;
+    }
 
-    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;
+    /* create guest device */
+    dev = usb_create(NULL /* FIXME */, "usb-storage");
+    qdev_prop_set_drive(&dev->qdev, "drive", dinfo);
+    if (qdev_init(&dev->qdev) < 0)
+        return NULL;
+
+    return dev;
+}
+
+static struct USBDeviceInfo msd_info = {
+    .product_desc   = "QEMU USB MSD",
+    .qdev.name      = "usb-storage",
+    .qdev.size      = sizeof(MSDState),
+    .init           = usb_msd_initfn,
+    .handle_packet  = usb_generic_handle_packet,
+    .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_PROP_DRIVE("drive", MSDState, dinfo),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+};
+
+static void usb_msd_register_devices(void)
+{
+    usb_qdev_register(&msd_info);
 }
+device_init(usb_msd_register_devices)