---
hw/qdev-properties.c | 487 +++++------------------------------------------
hw/qdev.c | 47 +-----
hw/qdev.h | 87 ---------
include/qemu/object.h | 98 ++++++++++
qom/Makefile | 2 +-
qom/object-properties.c | 461 ++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 607 insertions(+), 575 deletions(-)
create mode 100644 qom/object-properties.c
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 910e07f..5187604 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -3,392 +3,27 @@
#include "qerror.h"
#include "blockdev.h"
-void *object_get_prop_ptr(Object *obj, Property *prop)
-{
- void *ptr = obj;
- ptr += prop->offset;
- return ptr;
-}
-
-static uint32_t get_prop_mask(Property *prop)
-{
- assert(prop->info ==&qdev_prop_bit);
- return 0x1<< prop->bitnr;
-}
-
-static void bit_prop_set(Object *obj, Property *props, bool val)
-{
- uint32_t *p = object_get_prop_ptr(obj, props);
- uint32_t mask = get_prop_mask(props);
- if (val)
- *p |= mask;
- else
- *p&= ~mask;
-}
-
-/* Bit */
-
-static int print_bit(Object *obj, Property *prop, char *dest, size_t len)
-{
- uint32_t *p = object_get_prop_ptr(obj, prop);
- return snprintf(dest, len, (*p& get_prop_mask(prop)) ? "on" : "off");
-}
-
-static void get_bit(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- uint32_t *p = object_get_prop_ptr(obj, prop);
- bool value = (*p& get_prop_mask(prop)) != 0;
-
- visit_type_bool(v,&value, name, errp);
-}
-
-static void set_bit(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- Error *local_err = NULL;
- bool value;
-
- if (object_is_realized(obj)) {
- error_set(errp, QERR_PERMISSION_DENIED);
- return;
- }
-
- visit_type_bool(v,&value, name,&local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- bit_prop_set(obj, prop, value);
-}
-
-PropertyInfo qdev_prop_bit = {
- .name = "boolean",
- .legacy_name = "on/off",
- .print = print_bit,
- .get = get_bit,
- .set = set_bit,
-};
-
-/* --- 8bit integer --- */
-
-static void get_uint8(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- uint8_t *ptr = object_get_prop_ptr(obj, prop);
-
- visit_type_uint8(v, ptr, name, errp);
-}
-
-static void set_uint8(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- uint8_t *ptr = object_get_prop_ptr(obj, prop);
-
- if (object_is_realized(obj)) {
- error_set(errp, QERR_PERMISSION_DENIED);
- return;
- }
-
- visit_type_uint8(v, ptr, name, errp);
-}
-
-PropertyInfo qdev_prop_uint8 = {
- .name = "uint8",
- .get = get_uint8,
- .set = set_uint8,
-};
-
-/* --- 8bit hex value --- */
-
-static int parse_hex8(Object *obj, Property *prop, const char *str)
-{
- uint8_t *ptr = object_get_prop_ptr(obj, prop);
- char *end;
-
- if (str[0] != '0' || str[1] != 'x') {
- return -EINVAL;
- }
-
- *ptr = strtoul(str,&end, 16);
- if ((*end != '\0') || (end == str)) {
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int print_hex8(Object *obj, Property *prop, char *dest, size_t len)
-{
- uint8_t *ptr = object_get_prop_ptr(obj, prop);
- return snprintf(dest, len, "0x%" PRIx8, *ptr);
-}
-
-PropertyInfo qdev_prop_hex8 = {
- .name = "uint8",
- .legacy_name = "hex8",
- .parse = parse_hex8,
- .print = print_hex8,
- .get = get_uint8,
- .set = set_uint8,
-};
-
-/* --- 16bit integer --- */
-
-static void get_uint16(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- uint16_t *ptr = object_get_prop_ptr(obj, prop);
-
- visit_type_uint16(v, ptr, name, errp);
-}
-
-static void set_uint16(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- uint16_t *ptr = object_get_prop_ptr(obj, prop);
-
- if (object_is_realized(obj)) {
- error_set(errp, QERR_PERMISSION_DENIED);
- return;
- }
-
- visit_type_uint16(v, ptr, name, errp);
-}
-
-PropertyInfo qdev_prop_uint16 = {
- .name = "uint16",
- .get = get_uint16,
- .set = set_uint16,
-};
-
-/* --- 32bit integer --- */
-
-static void get_uint32(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- uint32_t *ptr = object_get_prop_ptr(obj, prop);
-
- visit_type_uint32(v, ptr, name, errp);
-}
-
-static void set_uint32(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- uint32_t *ptr = object_get_prop_ptr(obj, prop);
-
- if (object_is_realized(obj)) {
- error_set(errp, QERR_PERMISSION_DENIED);
- return;
- }
-
- visit_type_uint32(v, ptr, name, errp);
-}
-
-static void get_int32(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- int32_t *ptr = object_get_prop_ptr(obj, prop);
-
- visit_type_int32(v, ptr, name, errp);
-}
-
-static void set_int32(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- int32_t *ptr = object_get_prop_ptr(obj, prop);
-
- if (object_is_realized(obj)) {
- error_set(errp, QERR_PERMISSION_DENIED);
- return;
- }
-
- visit_type_int32(v, ptr, name, errp);
-}
-
-PropertyInfo qdev_prop_uint32 = {
- .name = "uint32",
- .get = get_uint32,
- .set = set_uint32,
-};
-
-PropertyInfo qdev_prop_int32 = {
- .name = "int32",
- .get = get_int32,
- .set = set_int32,
-};
-
-/* --- 32bit hex value --- */
-
-static int parse_hex32(Object *obj, Property *prop, const char *str)
-{
- uint32_t *ptr = object_get_prop_ptr(obj, prop);
- char *end;
-
- if (str[0] != '0' || str[1] != 'x') {
- return -EINVAL;
- }
-
- *ptr = strtoul(str,&end, 16);
- if ((*end != '\0') || (end == str)) {
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int print_hex32(Object *obj, Property *prop, char *dest, size_t len)
-{
- uint32_t *ptr = object_get_prop_ptr(obj, prop);
- return snprintf(dest, len, "0x%" PRIx32, *ptr);
-}
-
-PropertyInfo qdev_prop_hex32 = {
- .name = "uint32",
- .legacy_name = "hex32",
- .parse = parse_hex32,
- .print = print_hex32,
- .get = get_uint32,
- .set = set_uint32,
-};
-
-/* --- 64bit integer --- */
-
-static void get_uint64(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- uint64_t *ptr = object_get_prop_ptr(obj, prop);
-
- visit_type_uint64(v, ptr, name, errp);
-}
-
-static void set_uint64(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- uint64_t *ptr = object_get_prop_ptr(obj, prop);
-
- if (object_is_realized(obj)) {
- error_set(errp, QERR_PERMISSION_DENIED);
- return;
- }
-
- visit_type_uint64(v, ptr, name, errp);
-}
-
-PropertyInfo qdev_prop_uint64 = {
- .name = "uint64",
- .get = get_uint64,
- .set = set_uint64,
-};
-
-/* --- 64bit hex value --- */
-
-static int parse_hex64(Object *obj, Property *prop, const char *str)
-{
- uint64_t *ptr = object_get_prop_ptr(obj, prop);
- char *end;
-
- if (str[0] != '0' || str[1] != 'x') {
- return -EINVAL;
- }
-
- *ptr = strtoull(str,&end, 16);
- if ((*end != '\0') || (end == str)) {
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int print_hex64(Object *obj, Property *prop, char *dest, size_t len)
-{
- uint64_t *ptr = object_get_prop_ptr(obj, prop);
- return snprintf(dest, len, "0x%" PRIx64, *ptr);
-}
-
-PropertyInfo qdev_prop_hex64 = {
- .name = "uint64",
- .legacy_name = "hex64",
- .parse = parse_hex64,
- .print = print_hex64,
- .get = get_uint64,
- .set = set_uint64,
-};
-
-/* --- string --- */
-
-static void release_string(Object *obj, const char *name, void *opaque)
-{
- Property *prop = opaque;
- g_free(*(char **)object_get_prop_ptr(obj, prop));
-}
-
-static int print_string(Object *obj, Property *prop, char *dest, size_t len)
-{
- char **ptr = object_get_prop_ptr(obj, prop);
- if (!*ptr)
- return snprintf(dest, len, "<null>");
- return snprintf(dest, len, "\"%s\"", *ptr);
-}
-
-static void get_string(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- char **ptr = object_get_prop_ptr(obj, prop);
-
- if (!*ptr) {
- char *str = (char *)"";
- visit_type_str(v,&str, name, errp);
- } else {
- visit_type_str(v, ptr, name, errp);
- }
-}
-
-static void set_string(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
+void error_set_from_prop_error(Error **errp, int ret, Object *obj,
+ Property *prop, const char *value)
{
- Property *prop = opaque;
- char **ptr = object_get_prop_ptr(obj, prop);
- Error *local_err = NULL;
- char *str;
-
- if (object_is_realized(obj)) {
- error_set(errp, QERR_PERMISSION_DENIED);
- return;
- }
-
- visit_type_str(v,&str, name,&local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- if (*ptr) {
- g_free(*ptr);
+ switch (ret) {
+ case -EEXIST:
+ error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
+ object_get_id(obj), prop->name, value);
+ break;
+ default:
+ case -EINVAL:
+ error_set(errp, QERR_PROPERTY_VALUE_BAD,
+ object_get_id(obj), prop->name, value);
+ break;
+ case -ENOENT:
+ error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
+ object_get_id(obj), prop->name, value);
+ break;
+ case 0:
+ break;
}
- *ptr = str;
}
-
-PropertyInfo qdev_prop_string = {
- .name = "string",
- .print = print_string,
- .release = release_string,
- .get = get_string,
- .set = set_string,
-};
-
/* --- drive --- */
static int parse_drive(Object *obj, const char *str, void **ptr)
@@ -636,13 +271,6 @@ PropertyInfo qdev_prop_vlan = {
.set = set_vlan,
};
-/* --- pointer --- */
-
-/* Not a proper property, just for dirty hacks. TODO Remove it! */
-PropertyInfo qdev_prop_ptr = {
- .name = "ptr",
-};
-
/* --- mac address --- */
/*
@@ -713,6 +341,12 @@ PropertyInfo qdev_prop_macaddr = {
.set = set_mac,
};
+/* --- pointer --- */
+
+/* Not a proper property, just for dirty hacks. TODO Remove it! */
+PropertyInfo qdev_prop_ptr = {
+ .name = "ptr",
+};
/* --- lost tick policy --- */
@@ -726,40 +360,24 @@ static const char
*lost_tick_policy_table[LOST_TICK_MAX+1] = {
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
-static void get_enum(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- int *ptr = object_get_prop_ptr(obj, prop);
-
- visit_type_enum(v, ptr, prop->info->enum_table,
- prop->info->name, prop->name, errp);
-}
-
-static void set_enum(Object *obj, Visitor *v, void *opaque,
- const char *name, Error **errp)
-{
- Property *prop = opaque;
- int *ptr = object_get_prop_ptr(obj, prop);
-
- if (object_is_realized(obj)) {
- error_set(errp, QERR_PERMISSION_DENIED);
- return;
- }
-
- visit_type_enum(v, ptr, prop->info->enum_table,
- prop->info->name, prop->name, errp);
-}
-
PropertyInfo qdev_prop_losttickpolicy = {
.name = "LostTickPolicy",
.enum_table = lost_tick_policy_table,
- .get = get_enum,
- .set = set_enum,
+ .get = property_get_enum,
+ .set = property_set_enum,
};
/* --- pci address --- */
+static void get_pci_devfn(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ int32_t *ptr = object_get_prop_ptr(obj, prop);
+
+ visit_type_int32(v, ptr, name, errp);
+}
+
/*
* bus-local address, i.e. "$slot" or "$slot.$fn"
*/
@@ -826,12 +444,21 @@ PropertyInfo qdev_prop_pci_devfn = {
.name = "int32",
.legacy_name = "pci-devfn",
.print = print_pci_devfn,
- .get = get_int32,
+ .get = get_pci_devfn,
.set = set_pci_devfn,
};
/* --- blocksize --- */
+static void get_blocksize(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ uint16_t *ptr = object_get_prop_ptr(obj, prop);
+
+ visit_type_uint16(v, ptr, name, errp);
+}
+
static void set_blocksize(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
@@ -869,7 +496,7 @@ static void set_blocksize(Object *obj, Visitor *v, void
*opaque,
PropertyInfo qdev_prop_blocksize = {
.name = "blocksize",
- .get = get_uint16,
+ .get = get_blocksize,
.set = set_blocksize,
};
@@ -905,28 +532,6 @@ static Property *qdev_prop_find(Object *obj, const char
*name)
return NULL;
}
-void error_set_from_prop_error(Error **errp, int ret, Object *obj,
- Property *prop, const char *value)
-{
- switch (ret) {
- case -EEXIST:
- error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
- object_get_id(obj), prop->name, value);
- break;
- default:
- case -EINVAL:
- error_set(errp, QERR_PROPERTY_VALUE_BAD,
- object_get_id(obj), prop->name, value);
- break;
- case -ENOENT:
- error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
- object_get_id(obj), prop->name, value);
- break;
- case 0:
- break;
- }
-}
-
int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
{
char *legacy_name;
diff --git a/hw/qdev.c b/hw/qdev.c
index fdafd7d..d4b8f91 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -615,51 +615,6 @@ void qdev_property_add_legacy(DeviceState *dev, Property
*prop,
g_free(name);
}
-/**
- * @qdev_property_add_static - add a @Property to a device.
- *
- * Static properties access data in a struct. The actual type of the
- * property and the field depends on the property type.
- */
-void qdev_property_add_static(DeviceState *dev, Property *prop,
- Error **errp)
-{
- Error *local_err = NULL;
- Object *obj = OBJECT(dev);
-
- /*
- * TODO qdev_prop_ptr does not have getters or setters. It must
- * go now that it can be replaced with links. The test should be
- * removed along with it: all static properties are read/write.
- */
- if (!prop->info->get&& !prop->info->set) {
- return;
- }
-
- object_property_add(obj, prop->name, prop->info->name,
- prop->info->get, prop->info->set,
- prop->info->release,
- prop,&local_err);
-
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
- if (prop->qtype == QTYPE_NONE) {
- return;
- }
-
- if (prop->qtype == QTYPE_QBOOL) {
- object_property_set_bool(obj, prop->defval, prop->name,&local_err);
- } else if (prop->info->enum_table) {
- object_property_set_str(obj, prop->info->enum_table[prop->defval],
- prop->name,&local_err);
- } else if (prop->qtype == QTYPE_QINT) {
- object_property_set_int(obj, prop->defval, prop->name,&local_err);
- }
- assert_no_error(local_err);
-}
-
static void device_initfn(Object *obj)
{
DeviceState *dev = DEVICE(obj);
@@ -677,7 +632,7 @@ static void device_initfn(Object *obj)
do {
for (prop = DEVICE_CLASS(class)->props; prop&& prop->name; prop++) {
qdev_property_add_legacy(dev, prop, NULL);
- qdev_property_add_static(dev, prop, NULL);
+ object_property_add_static(OBJECT(dev), prop, NULL);
}
class = object_class_get_parent(class);
} while (class != object_class_by_name(TYPE_DEVICE));
diff --git a/hw/qdev.h b/hw/qdev.h
index bfa8620..c810d43 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -9,10 +9,6 @@
#include "qemu/object.h"
#include "error.h"
-typedef struct Property Property;
-
-typedef struct PropertyInfo PropertyInfo;
-
typedef struct CompatProperty CompatProperty;
typedef struct BusState BusState;
@@ -117,26 +113,6 @@ struct BusState {
QLIST_ENTRY(BusState) sibling;
};
-struct Property {
- const char *name;
- PropertyInfo *info;
- int offset;
- uint8_t bitnr;
- uint8_t qtype;
- int64_t defval;
-};
-
-struct PropertyInfo {
- const char *name;
- const char *legacy_name;
- const char **enum_table;
- int (*parse)(Object *obj, Property *prop, const char *str);
- int (*print)(Object *obj, Property *prop, char *dest, size_t len);
- ObjectPropertyAccessor *get;
- ObjectPropertyAccessor *set;
- ObjectPropertyRelease *release;
-};
-
typedef struct GlobalProperty {
const char *driver;
const char *property;
@@ -212,16 +188,6 @@ int do_device_del(Monitor *mon, const QDict *qdict,
QObject **ret_data);
/*** qdev-properties.c ***/
-extern PropertyInfo qdev_prop_bit;
-extern PropertyInfo qdev_prop_uint8;
-extern PropertyInfo qdev_prop_uint16;
-extern PropertyInfo qdev_prop_uint32;
-extern PropertyInfo qdev_prop_int32;
-extern PropertyInfo qdev_prop_uint64;
-extern PropertyInfo qdev_prop_hex8;
-extern PropertyInfo qdev_prop_hex32;
-extern PropertyInfo qdev_prop_hex64;
-extern PropertyInfo qdev_prop_string;
extern PropertyInfo qdev_prop_chr;
extern PropertyInfo qdev_prop_ptr;
extern PropertyInfo qdev_prop_macaddr;
@@ -232,55 +198,12 @@ extern PropertyInfo qdev_prop_vlan;
extern PropertyInfo qdev_prop_pci_devfn;
extern PropertyInfo qdev_prop_blocksize;
-#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
- .name = (_name), \
- .info =&(_prop), \
- .offset = offsetof(_state, _field) \
- + type_check(_type,typeof_field(_state, _field)), \
- }
-#define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \
- .name = (_name), \
- .info =&(_prop), \
- .offset = offsetof(_state, _field) \
- + type_check(_type,typeof_field(_state, _field)), \
- .qtype = QTYPE_QINT, \
- .defval = (_type)_defval, \
- }
-#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) { \
- .name = (_name), \
- .info =&(qdev_prop_bit), \
- .bitnr = (_bit), \
- .offset = offsetof(_state, _field) \
- + type_check(uint32_t,typeof_field(_state, _field)), \
- .qtype = QTYPE_QBOOL, \
- .defval = (bool)_defval, \
- }
-
-#define DEFINE_PROP_UINT8(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
-#define DEFINE_PROP_UINT16(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
-#define DEFINE_PROP_UINT32(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
-#define DEFINE_PROP_INT32(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t)
-#define DEFINE_PROP_UINT64(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
-#define DEFINE_PROP_HEX8(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex8, uint8_t)
-#define DEFINE_PROP_HEX32(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t)
-#define DEFINE_PROP_HEX64(_n, _s, _f, _d) \
- DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t)
#define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \
DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t)
-
#define DEFINE_PROP_PTR(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*)
#define DEFINE_PROP_CHR(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharDriverState*)
-#define DEFINE_PROP_STRING(_n, _s, _f) \
- DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
#define DEFINE_PROP_NETDEV(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, qdev_prop_netdev, VLANClientState*)
#define DEFINE_PROP_VLAN(_n, _s, _f) \
@@ -295,11 +218,7 @@ extern PropertyInfo qdev_prop_blocksize;
#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \
DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t)
-#define DEFINE_PROP_END_OF_LIST() \
- {}
-
/* Set properties between creation and init. */
-void *object_get_prop_ptr(Object *obj, Property *prop);
int qdev_prop_parse(DeviceState *dev, const char *name, const char *value);
void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value);
void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value);
@@ -326,12 +245,6 @@ void error_set_from_prop_error(Error **errp, int ret,
Object *obj,
char *qdev_get_fw_dev_path(DeviceState *dev);
/**
- * @qdev_property_add_static - add a @Property to a device referencing a
- * field in a struct.
- */
-void qdev_property_add_static(DeviceState *dev, Property *prop, Error **errp);
-
-/**
* @qdev_machine_init
*
* Initialize platform devices before machine init. This is a hack until full
diff --git a/include/qemu/object.h b/include/qemu/object.h
index 81e0280..ea5f16e 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -983,5 +983,103 @@ int object_child_foreach(Object *obj, int (*fn)(Object
*child, void *opaque),
*/
Object *container_get(Object *root, const char *path);
+typedef struct Property Property;
+typedef struct PropertyInfo PropertyInfo;
+
+struct Property {
+ const char *name;
+ PropertyInfo *info;
+ int offset;
+ uint8_t bitnr;
+ uint8_t qtype;
+ int64_t defval;
+};
+
+struct PropertyInfo {
+ const char *name;
+ const char *legacy_name;
+ const char **enum_table;
+ int (*parse)(Object *obj, Property *prop, const char *str);
+ int (*print)(Object *obj, Property *prop, char *dest, size_t len);
+ ObjectPropertyAccessor *get;
+ ObjectPropertyAccessor *set;
+ ObjectPropertyRelease *release;
+};
+
+extern PropertyInfo qdev_prop_bit;
+extern PropertyInfo qdev_prop_uint8;
+extern PropertyInfo qdev_prop_uint16;
+extern PropertyInfo qdev_prop_uint32;
+extern PropertyInfo qdev_prop_int32;
+extern PropertyInfo qdev_prop_uint64;
+extern PropertyInfo qdev_prop_hex8;
+extern PropertyInfo qdev_prop_hex32;
+extern PropertyInfo qdev_prop_hex64;
+extern PropertyInfo qdev_prop_string;
+
+#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
+ .name = (_name), \
+ .info =&(_prop), \
+ .offset = offsetof(_state, _field) \
+ + type_check(_type,typeof_field(_state, _field)), \
+ }
+#define DEFINE_PROP_DEFAULT(_name, _state, _field, _defval, _prop, _type) { \
+ .name = (_name), \
+ .info =&(_prop), \
+ .offset = offsetof(_state, _field) \
+ + type_check(_type,typeof_field(_state, _field)), \
+ .qtype = QTYPE_QINT, \
+ .defval = (_type)_defval, \
+ }
+#define DEFINE_PROP_BIT(_name, _state, _field, _bit, _defval) { \
+ .name = (_name), \
+ .info =&(qdev_prop_bit), \
+ .bitnr = (_bit), \
+ .offset = offsetof(_state, _field) \
+ + type_check(uint32_t,typeof_field(_state, _field)), \
+ .qtype = QTYPE_QBOOL, \
+ .defval = (bool)_defval, \
+ }
+
+#define DEFINE_PROP_UINT8(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
+#define DEFINE_PROP_UINT16(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint16, uint16_t)
+#define DEFINE_PROP_UINT32(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint32, uint32_t)
+#define DEFINE_PROP_INT32(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_int32, int32_t)
+#define DEFINE_PROP_UINT64(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_uint64, uint64_t)
+#define DEFINE_PROP_HEX8(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex8, uint8_t)
+#define DEFINE_PROP_HEX32(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex32, uint32_t)
+#define DEFINE_PROP_HEX64(_n, _s, _f, _d) \
+ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_hex64, uint64_t)
+#define DEFINE_PROP_STRING(_n, _s, _f) \
+ DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
+
+#define DEFINE_PROP_END_OF_LIST() \
+ {}
+
+void property_get_enum(Object *obj, struct Visitor *v, void *opaque,
+ const char *name, struct Error **errp);
+void property_set_enum(Object *obj, struct Visitor *v, void *opaque,
+ const char *name, struct Error **errp);
+
+void *object_get_prop_ptr(Object *obj, Property *prop);
+
+/**
+ * object_property_add_static:
+ * @obj: the object to add the property to
+ * @prop: the property to be added
+ * @errp: if an error occurs, a pointer to an area to store the error
+ *
+ * Add a #Property to an object referencing a field in a struct.
+ */
+void object_property_add_static(Object *obj, Property *prop,
+ struct Error **errp);
+
#endif
diff --git a/qom/Makefile b/qom/Makefile
index 34c6de5..2aae0ba 100644
--- a/qom/Makefile
+++ b/qom/Makefile
@@ -1,2 +1,2 @@
-qom-y = object.o container.o qom-qobject.o
+qom-y = object.o object-properties.o container.o qom-qobject.o
qom-twice-y = cpu.o
diff --git a/qom/object-properties.c b/qom/object-properties.c
new file mode 100644
index 0000000..6765e90
--- /dev/null
+++ b/qom/object-properties.c
@@ -0,0 +1,461 @@
+#include "qemu/object.h"
+#include "qapi/qapi-visit-core.h"
+
+void *object_get_prop_ptr(Object *obj, Property *prop)
+{
+ void *ptr = obj;
+ ptr += prop->offset;
+ return ptr;
+}
+
+static uint32_t get_prop_mask(Property *prop)
+{
+ assert(prop->info ==&qdev_prop_bit);
+ return 0x1<< prop->bitnr;
+}
+
+static void bit_prop_set(Object *obj, Property *props, bool val)
+{
+ uint32_t *p = object_get_prop_ptr(obj, props);
+ uint32_t mask = get_prop_mask(props);
+ if (val)
+ *p |= mask;
+ else
+ *p&= ~mask;
+}
+
+/* Bit */
+
+static int print_bit(Object *obj, Property *prop, char *dest, size_t len)
+{
+ uint32_t *p = object_get_prop_ptr(obj, prop);
+ return snprintf(dest, len, (*p& get_prop_mask(prop)) ? "on" : "off");
+}
+
+static void get_bit(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ uint32_t *p = object_get_prop_ptr(obj, prop);
+ bool value = (*p& get_prop_mask(prop)) != 0;
+
+ visit_type_bool(v,&value, name, errp);
+}
+
+static void set_bit(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ Error *local_err = NULL;
+ bool value;
+
+ if (object_is_realized(obj)) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ visit_type_bool(v,&value, name,&local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ bit_prop_set(obj, prop, value);
+}
+
+PropertyInfo qdev_prop_bit = {
+ .name = "boolean",
+ .legacy_name = "on/off",
+ .print = print_bit,
+ .get = get_bit,
+ .set = set_bit,
+};
+
+/* --- 8bit integer --- */
+
+static void get_uint8(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ uint8_t *ptr = object_get_prop_ptr(obj, prop);
+
+ visit_type_uint8(v, ptr, name, errp);
+}
+
+static void set_uint8(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ uint8_t *ptr = object_get_prop_ptr(obj, prop);
+
+ if (object_is_realized(obj)) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ visit_type_uint8(v, ptr, name, errp);
+}
+
+PropertyInfo qdev_prop_uint8 = {
+ .name = "uint8",
+ .get = get_uint8,
+ .set = set_uint8,
+};
+
+/* --- 8bit hex value --- */
+
+static int parse_hex8(Object *obj, Property *prop, const char *str)
+{
+ uint8_t *ptr = object_get_prop_ptr(obj, prop);
+ char *end;
+
+ if (str[0] != '0' || str[1] != 'x') {
+ return -EINVAL;
+ }
+
+ *ptr = strtoul(str,&end, 16);
+ if ((*end != '\0') || (end == str)) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int print_hex8(Object *obj, Property *prop, char *dest, size_t len)
+{
+ uint8_t *ptr = object_get_prop_ptr(obj, prop);
+ return snprintf(dest, len, "0x%" PRIx8, *ptr);
+}
+
+PropertyInfo qdev_prop_hex8 = {
+ .name = "uint8",
+ .legacy_name = "hex8",
+ .parse = parse_hex8,
+ .print = print_hex8,
+ .get = get_uint8,
+ .set = set_uint8,
+};
+
+/* --- 16bit integer --- */
+
+static void get_uint16(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ uint16_t *ptr = object_get_prop_ptr(obj, prop);
+
+ visit_type_uint16(v, ptr, name, errp);
+}
+
+static void set_uint16(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ uint16_t *ptr = object_get_prop_ptr(obj, prop);
+
+ if (object_is_realized(obj)) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ visit_type_uint16(v, ptr, name, errp);
+}
+
+PropertyInfo qdev_prop_uint16 = {
+ .name = "uint16",
+ .get = get_uint16,
+ .set = set_uint16,
+};
+
+/* --- 32bit integer --- */
+
+static void get_uint32(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ uint32_t *ptr = object_get_prop_ptr(obj, prop);
+
+ visit_type_uint32(v, ptr, name, errp);
+}
+
+static void set_uint32(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ uint32_t *ptr = object_get_prop_ptr(obj, prop);
+
+ if (object_is_realized(obj)) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ visit_type_uint32(v, ptr, name, errp);
+}
+
+static void get_int32(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ int32_t *ptr = object_get_prop_ptr(obj, prop);
+
+ visit_type_int32(v, ptr, name, errp);
+}
+
+static void set_int32(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ int32_t *ptr = object_get_prop_ptr(obj, prop);
+
+ if (object_is_realized(obj)) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ visit_type_int32(v, ptr, name, errp);
+}
+
+PropertyInfo qdev_prop_uint32 = {
+ .name = "uint32",
+ .get = get_uint32,
+ .set = set_uint32,
+};
+
+PropertyInfo qdev_prop_int32 = {
+ .name = "int32",
+ .get = get_int32,
+ .set = set_int32,
+};
+
+/* --- 32bit hex value --- */
+
+static int parse_hex32(Object *obj, Property *prop, const char *str)
+{
+ uint32_t *ptr = object_get_prop_ptr(obj, prop);
+ char *end;
+
+ if (str[0] != '0' || str[1] != 'x') {
+ return -EINVAL;
+ }
+
+ *ptr = strtoul(str,&end, 16);
+ if ((*end != '\0') || (end == str)) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int print_hex32(Object *obj, Property *prop, char *dest, size_t len)
+{
+ uint32_t *ptr = object_get_prop_ptr(obj, prop);
+ return snprintf(dest, len, "0x%" PRIx32, *ptr);
+}
+
+PropertyInfo qdev_prop_hex32 = {
+ .name = "uint32",
+ .legacy_name = "hex32",
+ .parse = parse_hex32,
+ .print = print_hex32,
+ .get = get_uint32,
+ .set = set_uint32,
+};
+
+/* --- 64bit integer --- */
+
+static void get_uint64(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ uint64_t *ptr = object_get_prop_ptr(obj, prop);
+
+ visit_type_uint64(v, ptr, name, errp);
+}
+
+static void set_uint64(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ uint64_t *ptr = object_get_prop_ptr(obj, prop);
+
+ if (object_is_realized(obj)) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ visit_type_uint64(v, ptr, name, errp);
+}
+
+PropertyInfo qdev_prop_uint64 = {
+ .name = "uint64",
+ .get = get_uint64,
+ .set = set_uint64,
+};
+
+/* --- 64bit hex value --- */
+
+static int parse_hex64(Object *obj, Property *prop, const char *str)
+{
+ uint64_t *ptr = object_get_prop_ptr(obj, prop);
+ char *end;
+
+ if (str[0] != '0' || str[1] != 'x') {
+ return -EINVAL;
+ }
+
+ *ptr = strtoull(str,&end, 16);
+ if ((*end != '\0') || (end == str)) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int print_hex64(Object *obj, Property *prop, char *dest, size_t len)
+{
+ uint64_t *ptr = object_get_prop_ptr(obj, prop);
+ return snprintf(dest, len, "0x%" PRIx64, *ptr);
+}
+
+PropertyInfo qdev_prop_hex64 = {
+ .name = "uint64",
+ .legacy_name = "hex64",
+ .parse = parse_hex64,
+ .print = print_hex64,
+ .get = get_uint64,
+ .set = set_uint64,
+};
+
+/* --- string --- */
+
+static void release_string(Object *obj, const char *name, void *opaque)
+{
+ Property *prop = opaque;
+ g_free(*(char **)object_get_prop_ptr(obj, prop));
+}
+
+static int print_string(Object *obj, Property *prop, char *dest, size_t len)
+{
+ char **ptr = object_get_prop_ptr(obj, prop);
+ if (!*ptr)
+ return snprintf(dest, len, "<null>");
+ return snprintf(dest, len, "\"%s\"", *ptr);
+}
+
+static void get_string(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ char **ptr = object_get_prop_ptr(obj, prop);
+
+ if (!*ptr) {
+ char *str = (char *)"";
+ visit_type_str(v,&str, name, errp);
+ } else {
+ visit_type_str(v, ptr, name, errp);
+ }
+}
+
+static void set_string(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ char **ptr = object_get_prop_ptr(obj, prop);
+ Error *local_err = NULL;
+ char *str;
+
+ if (object_is_realized(obj)) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ visit_type_str(v,&str, name,&local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ if (*ptr) {
+ g_free(*ptr);
+ }
+ *ptr = str;
+}
+
+PropertyInfo qdev_prop_string = {
+ .name = "string",
+ .print = print_string,
+ .release = release_string,
+ .get = get_string,
+ .set = set_string,
+};
+
+
+/* --- enums --- */
+
+void property_get_enum(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ int *ptr = object_get_prop_ptr(obj, prop);
+
+ visit_type_enum(v, ptr, prop->info->enum_table,
+ prop->info->name, prop->name, errp);
+}
+
+void property_set_enum(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ Property *prop = opaque;
+ int *ptr = object_get_prop_ptr(obj, prop);
+
+ if (object_is_realized(obj)) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ visit_type_enum(v, ptr, prop->info->enum_table,
+ prop->info->name, prop->name, errp);
+}
+
+
+/**
+ * @object_property_add_static - add a @Property to a device.
+ *
+ * Static properties access data in a struct. The actual type of the
+ * property and the field depends on the property type.
+ */
+void object_property_add_static(Object *obj, Property *prop,
+ Error **errp)
+{
+ Error *local_err = NULL;
+
+ /*
+ * TODO qdev_prop_ptr does not have getters or setters. It must
+ * go now that it can be replaced with links. The test should be
+ * removed along with it: all static properties are read/write.
+ */
+ if (!prop->info->get&& !prop->info->set) {
+ return;
+ }
+
+ object_property_add(obj, prop->name, prop->info->name,
+ prop->info->get, prop->info->set,
+ prop->info->release,
+ prop,&local_err);
+
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ if (prop->qtype == QTYPE_NONE) {
+ return;
+ }
+
+ if (prop->qtype == QTYPE_QBOOL) {
+ object_property_set_bool(obj, prop->defval, prop->name,&local_err);
+ } else if (prop->info->enum_table) {
+ object_property_set_str(obj, prop->info->enum_table[prop->defval],
+ prop->name,&local_err);
+ } else if (prop->qtype == QTYPE_QINT) {
+ object_property_set_int(obj, prop->defval, prop->name,&local_err);
+ }
+ assert_no_error(local_err);
+}