summaryrefslogtreecommitdiff
path: root/hw/qdev.c
diff options
context:
space:
mode:
authorAnthony Liguori <aliguori@us.ibm.com>2011-12-12 14:29:32 -0600
committerAnthony Liguori <aliguori@us.ibm.com>2011-12-15 09:20:48 -0600
commit83e94fb8d5167d08d19eb1a84d058d9cd350bae9 (patch)
tree7a45a0dbf146639a37cbebf220aea7068b85c9b4 /hw/qdev.c
parent3de1c3e82d06ac7fe789d912feb8876c0a8b270e (diff)
downloadqemu-83e94fb8d5167d08d19eb1a84d058d9cd350bae9.tar.gz
qom: add link properties (v2)
Links represent an ephemeral relationship between devices. They are meant to replace the qdev concept of busses by allowing more informal relationships between devices. Links are fairly limited in their usefulness without implementing QOM-style subclassing and interfaces. Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/qdev.c')
-rw-r--r--hw/qdev.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/hw/qdev.c b/hw/qdev.c
index 167f459996..d4482754b0 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -1200,6 +1200,80 @@ void qdev_property_add_child(DeviceState *dev, const char *name,
g_free(type);
}
+static void qdev_get_link_property(DeviceState *dev, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ DeviceState **child = opaque;
+ gchar *path;
+
+ if (*child) {
+ path = qdev_get_canonical_path(*child);
+ visit_type_str(v, &path, name, errp);
+ g_free(path);
+ } else {
+ path = (gchar *)"";
+ visit_type_str(v, &path, name, errp);
+ }
+}
+
+static void qdev_set_link_property(DeviceState *dev, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ DeviceState **child = opaque;
+ bool ambiguous = false;
+ const char *type;
+ char *path;
+
+ type = qdev_property_get_type(dev, name, NULL);
+
+ visit_type_str(v, &path, name, errp);
+
+ if (*child) {
+ qdev_unref(*child);
+ }
+
+ if (strcmp(path, "") != 0) {
+ DeviceState *target;
+
+ target = qdev_resolve_path(path, &ambiguous);
+ if (target) {
+ gchar *target_type;
+
+ target_type = g_strdup_printf("link<%s>", target->info->name);
+ if (strcmp(target_type, type) == 0) {
+ *child = target;
+ qdev_ref(target);
+ } else {
+ error_set(errp, QERR_INVALID_PARAMETER_TYPE, name, type);
+ }
+
+ g_free(target_type);
+ } else {
+ error_set(errp, QERR_DEVICE_NOT_FOUND, path);
+ }
+ } else {
+ *child = NULL;
+ }
+
+ g_free(path);
+}
+
+void qdev_property_add_link(DeviceState *dev, const char *name,
+ const char *type, DeviceState **child,
+ Error **errp)
+{
+ gchar *full_type;
+
+ full_type = g_strdup_printf("link<%s>", type);
+
+ qdev_property_add(dev, name, full_type,
+ qdev_get_link_property,
+ qdev_set_link_property,
+ NULL, child, errp);
+
+ g_free(full_type);
+}
+
static gchar *qdev_get_path_in(DeviceState *parent, DeviceState *dev)
{
DeviceProperty *prop;