summary refs log tree commit diff stats
path: root/hw/core/qdev-properties-system.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/core/qdev-properties-system.c')
-rw-r--r--hw/core/qdev-properties-system.c84
1 files changed, 50 insertions, 34 deletions
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
index e55afe6bf2..6d45d327a5 100644
--- a/hw/core/qdev-properties-system.c
+++ b/hw/core/qdev-properties-system.c
@@ -160,55 +160,71 @@ PropertyInfo qdev_prop_drive = {
 
 /* --- character device --- */
 
-static void parse_chr(DeviceState *dev, const char *str, void **ptr,
-                      const char *propname, Error **errp)
+static void get_chr(Object *obj, Visitor *v, const char *name, void *opaque,
+                    Error **errp)
 {
-    CharDriverState *chr = qemu_chr_find(str);
-    if (chr == NULL) {
-        error_setg(errp, "Property '%s.%s' can't find value '%s'",
-                   object_get_typename(OBJECT(dev)), propname, str);
-        return;
-    }
-    if (qemu_chr_fe_claim(chr) != 0) {
-        error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
-                  object_get_typename(OBJECT(dev)), propname, str);
-        return;
-    }
-    *ptr = chr;
+    DeviceState *dev = DEVICE(obj);
+    CharBackend *be = qdev_get_prop_ptr(dev, opaque);
+    char *p;
+
+    p = g_strdup(be->chr && be->chr->label ? be->chr->label : "");
+    visit_type_str(v, name, &p, errp);
+    g_free(p);
 }
 
-static void release_chr(Object *obj, const char *name, void *opaque)
+static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque,
+                    Error **errp)
 {
     DeviceState *dev = DEVICE(obj);
+    Error *local_err = NULL;
     Property *prop = opaque;
-    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
-    CharDriverState *chr = *ptr;
+    CharBackend *be = qdev_get_prop_ptr(dev, prop);
+    CharDriverState *s;
+    char *str;
 
-    if (chr) {
-        qemu_chr_add_handlers(chr, NULL, NULL, NULL, NULL);
-        qemu_chr_fe_release(chr);
+    if (dev->realized) {
+        qdev_prop_set_after_realize(dev, name, errp);
+        return;
     }
-}
 
+    visit_type_str(v, name, &str, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
 
-static char *print_chr(void *ptr)
-{
-    CharDriverState *chr = ptr;
-    const char *val = chr->label ? chr->label : "";
+    if (!*str) {
+        g_free(str);
+        be->chr = NULL;
+        return;
+    }
 
-    return g_strdup(val);
-}
+    s = qemu_chr_find(str);
+    g_free(str);
+    if (s == NULL) {
+        error_setg(errp, "Property '%s.%s' can't find value '%s'",
+                   object_get_typename(obj), prop->name, str);
+        return;
+    }
+    if (qemu_chr_fe_claim(s) != 0) {
+        error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
+                  object_get_typename(obj), prop->name, str);
+        return;
+    }
 
-static void get_chr(Object *obj, Visitor *v, const char *name, void *opaque,
-                    Error **errp)
-{
-    get_pointer(obj, v, opaque, print_chr, name, errp);
+    qemu_chr_fe_init(be, s, errp);
 }
 
-static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque,
-                    Error **errp)
+static void release_chr(Object *obj, const char *name, void *opaque)
 {
-    set_pointer(obj, v, opaque, parse_chr, name, errp);
+    DeviceState *dev = DEVICE(obj);
+    Property *prop = opaque;
+    CharBackend *be = qdev_get_prop_ptr(dev, prop);
+
+    if (be->chr) {
+        qemu_chr_fe_set_handlers(be, NULL, NULL, NULL, NULL, NULL);
+        qemu_chr_fe_release(be->chr);
+    }
 }
 
 PropertyInfo qdev_prop_chr = {