qdev: add -device command line option.

The -device switch is the users frontend to the qdev_device_add function
added by the previous patch.

Also adds a linked list where command line options can be saved.
Use it for the new -device and for the -usbdevice and -bt switches.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/vl.c b/vl.c
index 3fff64a..cbdfff0 100644
--- a/vl.c
+++ b/vl.c
@@ -145,6 +145,7 @@
 #include "hw/watchdog.h"
 #include "hw/smbios.h"
 #include "hw/xen.h"
+#include "hw/qdev.h"
 #include "bt-host.h"
 #include "net.h"
 #include "monitor.h"
@@ -175,12 +176,6 @@
 
 #define DEFAULT_RAM_SIZE 128
 
-/* Max number of USB devices that can be specified on the commandline.  */
-#define MAX_USB_CMDLINE 8
-
-/* Max number of bluetooth switches on the commandline.  */
-#define MAX_BT_CMDLINE 10
-
 static const char *data_dir;
 const char *bios_name = NULL;
 /* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
@@ -2633,6 +2628,11 @@
     return usb_device_del_addr(bus_num, addr);
 }
 
+static int usb_parse(const char *cmdline)
+{
+    return usb_device_add(cmdline, 0);
+}
+
 void do_usb_add(Monitor *mon, const char *devname)
 {
     usb_device_add(devname, 1);
@@ -4827,6 +4827,52 @@
     return buf;
 }
 
+struct device_config {
+    enum {
+        DEV_GENERIC,   /* -device      */
+        DEV_USB,       /* -usbdevice   */
+        DEV_BT,        /* -bt          */
+    } type;
+    const char *cmdline;
+    TAILQ_ENTRY(device_config) next;
+};
+TAILQ_HEAD(, device_config) device_configs = TAILQ_HEAD_INITIALIZER(device_configs);
+
+static void add_device_config(int type, const char *cmdline)
+{
+    struct device_config *conf;
+
+    conf = qemu_mallocz(sizeof(*conf));
+    conf->type = type;
+    conf->cmdline = cmdline;
+    TAILQ_INSERT_TAIL(&device_configs, conf, next);
+}
+
+static int foreach_device_config(int type, int (*func)(const char *cmdline))
+{
+    struct device_config *conf;
+    int rc;
+
+    TAILQ_FOREACH(conf, &device_configs, next) {
+        if (conf->type != type)
+            continue;
+        rc = func(conf->cmdline);
+        if (0 != rc)
+            return rc;
+    }
+    return 0;
+}
+
+static int generic_parse(const char *cmdline)
+{
+    DeviceState *dev;
+
+    dev = qdev_device_add(cmdline);
+    if (!dev)
+        return -1;
+    return 0;
+}
+
 int main(int argc, char **argv, char **envp)
 {
     const char *gdbstub_dev = NULL;
@@ -4841,8 +4887,6 @@
     int cyls, heads, secs, translation;
     const char *net_clients[MAX_NET_CLIENTS];
     int nb_net_clients;
-    const char *bt_opts[MAX_BT_CMDLINE];
-    int nb_bt_opts;
     int hda_index;
     int optind;
     const char *r, *optarg;
@@ -4857,8 +4901,6 @@
     const char *loadvm = NULL;
     QEMUMachine *machine;
     const char *cpu_model;
-    const char *usb_devices[MAX_USB_CMDLINE];
-    int usb_devices_index;
 #ifndef _WIN32
     int fds[2];
 #endif
@@ -4938,10 +4980,7 @@
         node_cpumask[i] = 0;
     }
 
-    usb_devices_index = 0;
-
     nb_net_clients = 0;
-    nb_bt_opts = 0;
     nb_drives = 0;
     nb_drives_opt = 0;
     nb_numa_nodes = 0;
@@ -5209,11 +5248,7 @@
                 break;
 #endif
             case QEMU_OPTION_bt:
-                if (nb_bt_opts >= MAX_BT_CMDLINE) {
-                    fprintf(stderr, "qemu: too many bluetooth options\n");
-                    exit(1);
-                }
-                bt_opts[nb_bt_opts++] = optarg;
+                add_device_config(DEV_BT, optarg);
                 break;
 #ifdef HAS_AUDIO
             case QEMU_OPTION_audio_help:
@@ -5455,12 +5490,10 @@
                 break;
             case QEMU_OPTION_usbdevice:
                 usb_enabled = 1;
-                if (usb_devices_index >= MAX_USB_CMDLINE) {
-                    fprintf(stderr, "Too many USB devices\n");
-                    exit(1);
-                }
-                usb_devices[usb_devices_index] = optarg;
-                usb_devices_index++;
+                add_device_config(DEV_USB, optarg);
+                break;
+            case QEMU_OPTION_device:
+                add_device_config(DEV_GENERIC, optarg);
                 break;
             case QEMU_OPTION_smp:
                 smp_cpus = atoi(optarg);
@@ -5779,9 +5812,8 @@
     net_client_check();
 
     /* init the bluetooth world */
-    for (i = 0; i < nb_bt_opts; i++)
-        if (bt_parse(bt_opts[i]))
-            exit(1);
+    if (foreach_device_config(DEV_BT, bt_parse))
+        exit(1);
 
     /* init the memory */
     if (ram_size == 0)
@@ -5972,14 +6004,13 @@
 
     /* init USB devices */
     if (usb_enabled) {
-        for(i = 0; i < usb_devices_index; i++) {
-            if (usb_device_add(usb_devices[i], 0) < 0) {
-                fprintf(stderr, "Warning: could not add USB device %s\n",
-                        usb_devices[i]);
-            }
-        }
+        foreach_device_config(DEV_USB, usb_parse);
     }
 
+    /* init generic devices */
+    if (foreach_device_config(DEV_GENERIC, generic_parse))
+        exit(1);
+
     if (!display_state)
         dumb_display_init();
     /* just use the first displaystate for the moment */