--- hw/object.c | 14 ++++++++++---- hw/object.h | 16 +++++++++++++--- hw/qdev.c | 30 ++++++++++++++++++++++++++++-- 3 files changed, 51 insertions(+), 9 deletions(-)
diff --git a/hw/object.c b/hw/object.c index be61677..520591a 100644 --- a/hw/object.c +++ b/hw/object.c @@ -17,7 +17,7 @@ typedef struct InterfaceImpl { const char *parent; - void (*interface_initfn)(ObjectClass *class); + void (*interface_initfn)(ObjectClass *class, void *data); Type type; } InterfaceImpl; @@ -33,8 +33,10 @@ typedef struct TypeImpl void (*base_init)(ObjectClass *klass); void (*base_finalize)(ObjectClass *klass); - void (*class_init)(ObjectClass *klass); - void (*class_finalize)(ObjectClass *klass); + void (*class_init)(ObjectClass *klass, void *data); + void (*class_finalize)(ObjectClass *klass, void *data); + + void *class_data; void (*instance_init)(Object *obj); void (*instance_finalize)(Object *obj); @@ -61,6 +63,8 @@ Type type_register_static(const TypeInfo *info) assert(info->name != NULL); + printf("Added type %s -> %s\n", info->name, info->parent); + ti->name = info->name; ti->parent = info->parent; ti->type = type; @@ -73,6 +77,7 @@ Type type_register_static(const TypeInfo *info) ti->class_init = info->class_init; ti->class_finalize = info->class_finalize; + ti->class_data = info->class_data; ti->instance_init = info->instance_init; ti->instance_finalize = info->instance_finalize; @@ -114,6 +119,7 @@ static Type type_register_anonymous(const TypeInfo *info) ti->class_init = info->class_init; ti->class_finalize = info->class_finalize; + ti->class_data = info->class_data; ti->instance_init = info->instance_init; ti->instance_finalize = info->instance_finalize; @@ -237,7 +243,7 @@ static void type_class_init(TypeImpl *ti) } if (ti->class_init) { - ti->class_init(ti->class); + ti->class_init(ti->class, ti->class_data); } } diff --git a/hw/object.h b/hw/object.h index 834e89e..b02709e 100644 --- a/hw/object.h +++ b/hw/object.h @@ -27,6 +27,8 @@ typedef struct InterfaceClass InterfaceClass; typedef struct Interface Interface; typedef struct InterfaceInfo InterfaceInfo; +#define TYPE_OBJECT NULL + /** * @ObjectClass: * @@ -183,7 +185,7 @@ struct TypeInfo * to allow a class to set its default virtual method pointers. This is * also the function to use to override virtual methods from a parent class. */ - void (*class_init)(ObjectClass *klass); + void (*class_init)(ObjectClass *klass, void *data); /** * @class_finalize @@ -191,7 +193,15 @@ struct TypeInfo * This function is called during class destruction and is meant to release * and dynamic parameters allocated by @class_init. */ - void (*class_finalize)(ObjectClass *klass); + void (*class_finalize)(ObjectClass *klass, void *data); + + /** + * @class_data + * + * Data to pass to the @class_init and @class_finalize functions. This can + * be useful when building dynamic classes. + */ + void *class_data; /** * Interfaces @@ -306,7 +316,7 @@ struct InterfaceInfo * initialize any default virtual functions for a class and/or override * virtual functions in a parent class. */ - void (*interface_initfn)(ObjectClass *class); + void (*interface_initfn)(ObjectClass *class, void *data); }; #define TYPE_INTERFACE "interface" diff --git a/hw/qdev.c b/hw/qdev.c index 83913c7..7a5aa9f 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -44,12 +44,23 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name, const BusInfo *info); static BusState *qbus_find(const char *path); +#define TYPE_DEVICE "device" +#define DEVICE(obj) OBJECT_CHECK(DeviceState, (obj), TYPE_DEVICE) + /* Register a new device type. */ void qdev_register(DeviceInfo *info) { + TypeInfo type_info = {}; + assert(info->size >= sizeof(DeviceState)); assert(!info->next); + type_info.name = info->name; + type_info.parent = TYPE_DEVICE; + type_info.instance_size = info->size; + + type_register_static(&type_info); + info->next = device_info_list; device_info_list = info; } @@ -86,7 +97,7 @@ static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info) Property *prop; assert(bus->info == info->bus_info); - dev = g_malloc0(info->size); + dev = DEVICE(object_new(info->name)); dev->info = info; dev->parent_bus = bus; qdev_prop_set_defaults(dev, dev->info->props); @@ -484,7 +495,7 @@ void qdev_free(DeviceState *dev) prop->info->free(dev, prop); } } - g_free(dev); + object_delete(OBJECT(dev)); } void qdev_machine_creation_done(void) @@ -1515,3 +1526,18 @@ void qdev_property_add_str(DeviceState *dev, const char *name, qdev_property_release_str, prop, errp); } + +static TypeInfo device_type_info = { + .name = TYPE_DEVICE, + .parent = TYPE_OBJECT, + .instance_size = sizeof(DeviceState), + .abstract = true, + .class_size = sizeof(DeviceClass), +}; + +static void init_qdev(void) +{ + type_register_static(&device_type_info); +} + +device_init(init_qdev); -- 1.7.4.1