From bcb292e8cae4e7c8ac1d6b7a380ed08c4b71a2e0 Mon Sep 17 00:00:00 2001
Message-Id: <bcb292e8cae4e7c8ac1d6b7a380ed08c4b71a2e0.1374754302.git.minovotn@redhat.com>
In-Reply-To: <5d75a8513d08b33975bdf5971871c0c977167cd1.1374754301.git.minovotn@redhat.com>
References: <5d75a8513d08b33975bdf5971871c0c977167cd1.1374754301.git.minovotn@redhat.com>
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Mon, 24 Jun 2013 07:05:58 +0200
Subject: [PATCH 47/65] chardev: add support for qapi-based chardev
 initialization

RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1372057576-26450-48-git-send-email-kraxel@redhat.com>
Patchwork-id: 52159
O-Subject: [RHEL-6.5 qemu-kvm PATCH v2 47/65] chardev: add support for qapi-based chardev initialization
Bugzilla: 676568
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Acked-by: Hans de Goede <hdegoede@redhat.com>
RH-Acked-by: Luiz Capitulino <lcapitulino@redhat.com>

This patch add support for a new way to initialize chardev devices.
Instead of calling a initialization function with a QemuOpts we will
now create a (qapi) ChardevBackend, optionally call a function to
fill ChardevBackend from QemuOpts, then go create the chardev using
the new qapi code path which is also used by chardev-add.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 2c5f488293c7d0cd095635c74157c2526e2c4947)

Conflicts:

	qemu-char.h

[ rhel6: put qapi bits into qemu-char-qapi.h due to nasty header
         dependencies. ]
[ rhel6: deal with qapi_free_ChardevBackend() limitations ]
---
 qemu-char-qapi.h |    7 +++++++
 qemu-char.c      |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+)
 create mode 100644 qemu-char-qapi.h

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 qemu-char-qapi.h |  7 +++++++
 qemu-char.c      | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+)
 create mode 100644 qemu-char-qapi.h

diff --git a/qemu-char-qapi.h b/qemu-char-qapi.h
new file mode 100644
index 0000000..405c487
--- /dev/null
+++ b/qemu-char-qapi.h
@@ -0,0 +1,7 @@
+#ifndef QEMU_CHAR_QAPI_H
+#define QEMU_CHAR_QAPI_H
+
+void register_char_driver_qapi(const char *name, int kind,
+        void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp));
+
+#endif
diff --git a/qemu-char.c b/qemu-char.c
index 722267b..56b5f1e 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -31,6 +31,7 @@
 #include "hw/usb.h"
 #include "qemu-objects.h"
 #include "qapi-visit.h"
+#include "qemu-char-qapi.h"
 #include "qmp-commands.h"
 
 #include <unistd.h>
@@ -2809,7 +2810,11 @@ static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
 
 typedef struct CharDriver {
     const char *name;
+    /* old, pre qapi */
     CharDriverState *(*open)(QemuOpts *opts);
+    /* new, qapi-based */
+    int kind;
+    void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp);
 } CharDriver;
 
 static GSList *backends;
@@ -2825,6 +2830,19 @@ void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts *)
     backends = g_slist_append(backends, s);
 }
 
+void register_char_driver_qapi(const char *name, int kind,
+        void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp))
+{
+    CharDriver *s;
+
+    s = g_malloc0(sizeof(*s));
+    s->name = g_strdup(name);
+    s->kind = kind;
+    s->parse = parse;
+
+    backends = g_slist_append(backends, s);
+}
+
 CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
                                     void (*init)(struct CharDriverState *s),
                                     Error **errp)
@@ -2856,6 +2874,38 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
         return NULL;
     }
 
+    if (!cd->open) {
+        /* using new, qapi init */
+        ChardevBackend *backend = g_new0(ChardevBackend, 1);
+        ChardevReturn *ret = NULL;
+        const char *id = qemu_opts_id(opts);
+
+        chr = NULL;
+        backend->kind = cd->kind;
+        if (cd->parse) {
+            cd->parse(opts, backend, errp);
+            if (error_is_set(errp)) {
+                goto qapi_out;
+            }
+        }
+        ret = qmp_chardev_add(qemu_opts_id(opts), backend, errp);
+        if (error_is_set(errp)) {
+            goto qapi_out;
+        }
+        chr = qemu_chr_find(id);
+
+    qapi_out:
+        if (!backend->data) {
+            /* RHEL-6 qapi_free_ChardevBackend() can't handle
+               half-initialized ChardevBackend */
+            g_free(backend);
+        } else {
+            qapi_free_ChardevBackend(backend);
+        }
+        qapi_free_ChardevReturn(ret);
+        return chr;
+    }
+
     chr = cd->open(opts);
     if (!chr) {
         error_setg(errp, "chardev: opening backend \"%s\" failed",
-- 
1.7.11.7

