virDomainHostdevDefFormatSubsys(virBufferPtr buf,
                                virDomainHostdevDefPtr def,
                                unsigned int flags,
                                bool includeTypeInAddr)
{
    bool closedSource = false;
    virDomainHostdevSubsysUSBPtr usbsrc = &def->source.subsys.u.usb;
    virDomainHostdevSubsysPCIPtr pcisrc = &def->source.subsys.u.pci;
    virDomainHostdevSubsysSCSIPtr scsisrc = &def->source.subsys.u.scsi;
    virDomainHostdevSubsysSCSIVHostPtr hostsrc = &def->source.subsys.u.scsi_host;
    virDomainHostdevSubsysMediatedDevPtr mdevsrc = &def->source.subsys.u.mdev;
    virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
    virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;

    if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
        pcisrc->backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) {
        const char *backend =
            virDomainHostdevSubsysPCIBackendTypeToString(pcisrc->backend);

        if (!backend) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected pci hostdev driver name type %d"),
                           pcisrc->backend);
            return -1;
        }
        virBufferAsprintf(buf, "<driver name='%s'/>\n", backend);
    }

    virBufferAddLit(buf, "<source");
    if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
        if (def->startupPolicy) {
            const char *policy;
            policy = virDomainStartupPolicyTypeToString(def->startupPolicy);
            virBufferAsprintf(buf, " startupPolicy='%s'", policy);
        }
        if (usbsrc->autoAddress && (flags & VIR_DOMAIN_DEF_FORMAT_MIGRATABLE))
            virBufferAddLit(buf, " autoAddress='yes'");

        if (def->missing && !(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE))
            virBufferAddLit(buf, " missing='yes'");
    }

    if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
        scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
        const char *protocol =
            virDomainHostdevSubsysSCSIProtocolTypeToString(scsisrc->protocol);

        virBufferAsprintf(buf, " protocol='%s' name='%s'",
                          protocol, iscsisrc->src->path);
    }

    if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) {
        const char *protocol =
            virDomainHostdevSubsysSCSIHostProtocolTypeToString(hostsrc->protocol);
        closedSource = true;

        virBufferAsprintf(buf, " protocol='%s' wwpn='%s'/",
                          protocol, hostsrc->wwpn);
    }

    virBufferAddLit(buf, ">\n");

    virBufferAdjustIndent(buf, 2);
    switch (def->source.subsys.type) {
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
        if (usbsrc->vendor) {
            virBufferAsprintf(buf, "<vendor id='0x%.4x'/>\n", usbsrc->vendor);
            virBufferAsprintf(buf, "<product id='0x%.4x'/>\n", usbsrc->product);
        }
        if (usbsrc->bus || usbsrc->device) {
            virBufferAsprintf(buf, "<address %sbus='%d' device='%d'/>\n",
                              includeTypeInAddr ? "type='usb' " : "",
                              usbsrc->bus, usbsrc->device);
        }
        break;
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
        virPCIDeviceAddressFormat(buf, pcisrc->addr,
                                  includeTypeInAddr);

        if ((flags & VIR_DOMAIN_DEF_FORMAT_PCI_ORIG_STATES) &&
            (def->origstates.states.pci.unbind_from_stub ||
             def->origstates.states.pci.remove_slot ||
             def->origstates.states.pci.reprobe)) {
            virBufferAddLit(buf, "<origstates>\n");
            virBufferAdjustIndent(buf, 2);
            if (def->origstates.states.pci.unbind_from_stub)
                virBufferAddLit(buf, "<unbind/>\n");
            if (def->origstates.states.pci.remove_slot)
                virBufferAddLit(buf, "<removeslot/>\n");
            if (def->origstates.states.pci.reprobe)
                virBufferAddLit(buf, "<reprobe/>\n");
            virBufferAdjustIndent(buf, -2);
            virBufferAddLit(buf, "</origstates>\n");
        }
        break;
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
        if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
            virBufferAddLit(buf, "<host");
            virBufferEscapeString(buf, " name='%s'", iscsisrc->src->hosts[0].name);
            if (iscsisrc->src->hosts[0].port)
                virBufferAsprintf(buf, " port='%u'", iscsisrc->src->hosts[0].port);
            virBufferAddLit(buf, "/>\n");
        } else {
            virBufferAsprintf(buf, "<adapter name='%s'/>\n",
                              scsihostsrc->adapter);
            virBufferAsprintf(buf,
                              "<address %sbus='%u' target='%u' unit='%llu'/>\n",
                              includeTypeInAddr ? "type='scsi' " : "",
                              scsihostsrc->bus, scsihostsrc->target,
                              scsihostsrc->unit);
        }
        break;
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
        break;
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV:
        virBufferAsprintf(buf, "<address uuid='%s'/>\n",
                          mdevsrc->uuidstr);
        break;
    default:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected hostdev type %d"),
                       def->source.subsys.type);
        return -1;
    }

    if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
        scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI &&
        iscsisrc->src->auth)
        virStorageAuthDefFormat(buf, iscsisrc->src->auth);

    virBufferAdjustIndent(buf, -2);
    if (!closedSource)
        virBufferAddLit(buf, "</source>\n");

    return 0;
}