func: DeviceState *qdev_device_add(QemuOpts *opts)
  
  {
  
      ObjectClass *oc;
  
      DeviceClass *dc;
  
      const char *driver, *path, *id;
  
      DeviceState *dev;
  
      BusState *bus = NULL;
  
      Error *err = NULL;
  
  
  
      driver = qemu_opt_get(opts, "driver");
  
      if (!driver) {
  
          qerror_report(QERR_MISSING_PARAMETER, "driver");
  
          return NULL;
  
      }
  
  
  
      /* find driver */
  
      oc = object_class_by_name(driver);
  
      if (!oc) {
  
          const char *typename = find_typename_by_alias(driver);
  
  
  
          if (typename) {
  
              driver = typename;
  
              oc = object_class_by_name(driver);
  
          }
  
      }
  
  
  
      if (!object_class_dynamic_cast(oc, TYPE_DEVICE)) {
  
          qerror_report(ERROR_CLASS_GENERIC_ERROR,
  
                        "'%s' is not a valid device model name", driver);
  
          return NULL;
  
      }
  
  
  
      if (object_class_is_abstract(oc)) {
  
          qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver",
  
                        "non-abstract device type");
  
          return NULL;
  
      }
  
  
  
      dc = DEVICE_CLASS(oc);
  
      if (dc->cannot_instantiate_with_device_add_yet) {
  
          qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver",
  
                        "pluggable device type");
  
          return NULL;
  
      }
  
  
  
      /* find bus */
  
      path = qemu_opt_get(opts, "bus");
  
      if (path != NULL) {
  
          bus = qbus_find(path);
  
          if (!bus) {
  
              return NULL;
  
          }
  
          if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) {
  
              qerror_report(QERR_BAD_BUS_FOR_DEVICE,
  
                            driver, object_get_typename(OBJECT(bus)));
  
              return NULL;
  
          }
  
      } else if (dc->bus_type != NULL) {
  
          bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
  
          if (!bus) {
  
              qerror_report(QERR_NO_BUS_FOR_DEVICE,
  
                            dc->bus_type, driver);
  
              return NULL;
  
          }
  
      }
  
      if (qdev_hotplug && bus && !bus->allow_hotplug) {
  
          qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
  
          return NULL;
  
      }
  
  
  
      /* create device, set properties */
  
      dev = DEVICE(object_new(driver));
  
  
  
      if (bus) {
  
          qdev_set_parent_bus(dev, bus);
  
      }
  
  
  
      id = qemu_opts_id(opts);
  
      if (id) {
  
          dev->id = id;
  
      }
  
      if (qemu_opt_foreach(opts, set_property, dev, 1) != 0) {
  
          object_unparent(OBJECT(dev));
  
          object_unref(OBJECT(dev));
  
          return NULL;
  
      }
  
      if (dev->id) {
  
          object_property_add_child(qdev_get_peripheral(), dev->id,
  
                                    OBJECT(dev), NULL);
  
      } else {
  
          static int anon_count;
  
          gchar *name = g_strdup_printf("device[%d]", anon_count++);
  
          object_property_add_child(qdev_get_peripheral_anon(), name,
  
                                    OBJECT(dev), NULL);
  
          g_free(name);
  
      }
  
  
  
      dev->opts = opts;
  
      object_property_set_bool(OBJECT(dev), true, "realized", &err);
  
      if (err != NULL) {
  
          qerror_report_err(err);
  
          error_free(err);
  
          dev->opts = NULL;
  
          object_unparent(OBJECT(dev));
  
          object_unref(OBJECT(dev));
  
          qerror_report(QERR_DEVICE_INIT_FAILED, driver);
  
          return NULL;
  
      }
  
      return dev;
  
  }
  