From ef0e1eef9780e62bfe64f9ae44fb3f7798d16916 Mon Sep 17 00:00:00 2001
From: Blue Swirl <blauwirbel@gmail.com>
Date: Sat, 29 Aug 2009 14:00:54 +0000
Subject: [PATCH] monitor: add device info infrastructure

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
---
 monitor.c       |   41 +++++++++++++++++++++++++++++++++++++++++
 monitor.h       |    5 +++++
 qemu-monitor.hx |    7 +++++++
 vl.c            |    8 ++++----
 4 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/monitor.c b/monitor.c
index 2559a62..24e817f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -78,6 +78,14 @@ struct mon_fd_t {
     LIST_ENTRY(mon_fd_t) next;
 };
 
+/* Callback for device info command */
+struct MonDevInfo {
+    DeviceInfoFunc *dev_info_cb;
+    void *dev_opaque;
+    const char *dev_name;
+    LIST_ENTRY(MonDevInfo) next;
+};
+
 struct Monitor {
     CharDriverState *chr;
     int flags;
@@ -89,6 +97,7 @@ struct Monitor {
     BlockDriverCompletionFunc *password_completion_cb;
     void *password_opaque;
     LIST_HEAD(,mon_fd_t) fds;
+    LIST_HEAD(,MonDevInfo) dev_infos;
     LIST_ENTRY(Monitor) entry;
 };
 
@@ -1755,6 +1764,18 @@ int monitor_get_fd(Monitor *mon, const char *fdname)
     return -1;
 }
 
+static void do_info_device(Monitor *mon, const char *name)
+{
+    struct MonDevInfo *dev_info;
+
+    LIST_FOREACH(dev_info, &mon->dev_infos, next) {
+        if (strcmp(dev_info->dev_name, name) != 0) {
+            continue;
+        }
+        dev_info->dev_info_cb(mon, dev_info->dev_opaque);
+    }
+}
+
 static const mon_cmd_t mon_cmds[] = {
 #include "qemu-monitor.h"
     { NULL, NULL, },
@@ -3052,6 +3073,13 @@ static void monitor_find_completion(const char *cmdline)
                 for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
                     cmd_completion(str, cmd->name);
                 }
+            } else if (!strcmp(cmd->name, "dev_info")) {
+                struct MonDevInfo *dev_info;
+
+                readline_set_completion_index(cur_mon->rs, strlen(str));
+                LIST_FOREACH(dev_info, &cur_mon->dev_infos, next) {
+                    cmd_completion(str, dev_info->dev_name);
+                }
             }
             break;
         default:
@@ -3216,6 +3244,19 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
         completion_cb(opaque, err);
 }
 
+void monitor_register_device_info(const char *dev_name,
+                                  DeviceInfoFunc *dev_info_cb,
+                                  void *dev_opaque)
+{
+    struct MonDevInfo *dev_info;
+
+    dev_info = qemu_malloc(sizeof(*dev_info));
+    dev_info->dev_name = dev_name;
+    dev_info->dev_info_cb = dev_info_cb;
+    dev_info->dev_opaque = dev_opaque;
+    LIST_INSERT_HEAD(&cur_mon->dev_infos, dev_info, next);
+}
+
 typedef struct QemuErrorSink QemuErrorSink;
 struct QemuErrorSink {
     enum {
diff --git a/monitor.h b/monitor.h
index f6a43c0..49b9066 100644
--- a/monitor.h
+++ b/monitor.h
@@ -20,6 +20,11 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
                                  BlockDriverCompletionFunc *completion_cb,
                                  void *opaque);
 
+typedef void DeviceInfoFunc(Monitor *mon, void *opaque);
+void monitor_register_device_info(const char *dev_name,
+                                  DeviceInfoFunc *dev_info_cb,
+                                  void *dev_opaque);
+
 int monitor_get_fd(Monitor *mon, const char *fdname);
 
 void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap);
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index f56354b..80d07b5 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -644,6 +644,13 @@ Close the file descriptor previously assigned to @var{fdname} using the
 used by another monitor command.
 ETEXI
 
+    { "dev_info", "s", do_info_device,
+      "", "show device information" },
+STEXI
+@item device @var{devicename}
+Show information about a device.
+ETEXI
+
 STEXI
 @end table
 ETEXI
diff --git a/vl.c b/vl.c
index a894285..447f21f 100644
--- a/vl.c
+++ b/vl.c
@@ -5887,6 +5887,10 @@ int main(int argc, char **argv, char **envp)
             exit(1);
         }
     }
+    qemu_chr_initial_reset();
+
+    if (monitor_device && monitor_hd)
+        monitor_init(monitor_hd, MONITOR_USE_READLINE | MONITOR_IS_DEFAULT);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         const char *devname = serial_devices[i];
@@ -6026,10 +6030,6 @@ int main(int argc, char **argv, char **envp)
     }
 
     text_consoles_set_display(display_state);
-    qemu_chr_initial_reset();
-
-    if (monitor_device && monitor_hd)
-        monitor_init(monitor_hd, MONITOR_USE_READLINE | MONITOR_IS_DEFAULT);
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
         const char *devname = serial_devices[i];
-- 
1.5.6.5

