Introduce a new device element "<audio>" which allows to map guest sound device specified using the "<sound>" element to specific audio backend. Example: <sound model='ich7'> <audio id='1'/> </sound> <audio id='1' type='oss'> <input dev='/dev/dsp0'/> <output dev='/dev/dsp0'/> </audio> This block maps to OSS audio backend on the host using /dev/dsp0 device for both input (recording) and output (playback). OSS is the only backend supported so far. Signed-off-by: Roman Bogorodskiy <bogorodskiy@xxxxxxxxx> --- docs/schemas/domaincommon.rng | 36 +++++++ src/conf/domain_capabilities.c | 4 + src/conf/domain_conf.c | 176 ++++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 28 ++++++ src/conf/virconftypes.h | 3 + src/libvirt_private.syms | 2 + src/qemu/qemu_command.c | 1 + src/qemu/qemu_domain.c | 1 + src/qemu/qemu_domain_address.c | 2 + src/qemu/qemu_driver.c | 5 + src/qemu/qemu_hotplug.c | 3 + src/qemu/qemu_validate.c | 1 + 12 files changed, 260 insertions(+), 2 deletions(-) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index fb9638f3f6..c933c71035 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4372,12 +4372,47 @@ <optional> <ref name="address"/> </optional> + <optional> + <element name="audio"> + <attribute name="id"> + <ref name="uint8"/> + </attribute> + </element> + </optional> <zeroOrMore> <ref name="codec"/> </zeroOrMore> </interleave> </element> </define> + <define name="audio"> + <element name="audio"> + <attribute name="id"> + <ref name="uint8"/> + </attribute> + <attribute name="type"> + <choice> + <value>oss</value> + </choice> + </attribute> + <interleave> + <optional> + <element name="input"> + <attribute name="dev"> + <ref name="deviceName"/> + </attribute> + </element> + </optional> + <optional> + <element name="output"> + <attribute name="dev"> + <ref name="deviceName"/> + </attribute> + </element> + </optional> + </interleave> + </element> + </define> <define name="watchdog"> <element name="watchdog"> <attribute name="model"> @@ -5303,6 +5338,7 @@ <ref name="interface"/> <ref name="input"/> <ref name="sound"/> + <ref name="audio"/> <ref name="hostdev"/> <ref name="graphic"/> <ref name="video"/> diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index d61108e125..59ad8937a4 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -688,6 +688,10 @@ virDomainCapsDeviceDefValidate(const virDomainCaps *caps, ret = virDomainCapsDeviceVideoDefValidate(caps, dev->data.video); break; + case VIR_DOMAIN_DEVICE_AUDIO: + /* TODO: add validation */ + break; + case VIR_DOMAIN_DEVICE_DISK: case VIR_DOMAIN_DEVICE_REDIRDEV: case VIR_DOMAIN_DEVICE_NET: diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f9cdc4efa9..165d5d5f7a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -323,6 +323,7 @@ VIR_ENUM_IMPL(virDomainDevice, "memory", "iommu", "vsock", + "audio", ); VIR_ENUM_IMPL(virDomainDiskDevice, @@ -729,6 +730,11 @@ VIR_ENUM_IMPL(virDomainSoundModel, "ich7", ); +VIR_ENUM_IMPL(virDomainAudioType, + VIR_DOMAIN_AUDIO_TYPE_LAST, + "oss", +); + VIR_ENUM_IMPL(virDomainKeyWrapCipherName, VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_LAST, "aes", @@ -2872,6 +2878,24 @@ void virDomainSoundDefFree(virDomainSoundDefPtr def) VIR_FREE(def); } +void virDomainAudioDefFree(virDomainAudioDefPtr def) +{ + if (!def) + return; + + switch (def->type) { + case VIR_DOMAIN_AUDIO_TYPE_OSS: + VIR_FREE(def->backend.oss.inputDev); + VIR_FREE(def->backend.oss.outputDev); + break; + + case VIR_DOMAIN_AUDIO_TYPE_LAST: + break; + } + + VIR_FREE(def); +} + virDomainSoundDefPtr virDomainSoundDefRemove(virDomainDefPtr def, size_t idx) { @@ -3225,6 +3249,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def) case VIR_DOMAIN_DEVICE_VSOCK: virDomainVsockDefFree(def->data.vsock); break; + case VIR_DOMAIN_DEVICE_AUDIO: + virDomainAudioDefFree(def->data.audio); + break; case VIR_DOMAIN_DEVICE_LAST: case VIR_DOMAIN_DEVICE_NONE: break; @@ -3485,6 +3512,10 @@ void virDomainDefFree(virDomainDefPtr def) virDomainSoundDefFree(def->sounds[i]); VIR_FREE(def->sounds); + for (i = 0; i < def->naudios; i++) + virDomainAudioDefFree(def->audios[i]); + VIR_FREE(def->audios); + for (i = 0; i < def->nvideos; i++) virDomainVideoDefFree(def->videos[i]); VIR_FREE(def->videos); @@ -4073,6 +4104,7 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device) case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_GRAPHICS: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_LAST: case VIR_DOMAIN_DEVICE_NONE: break; @@ -4167,6 +4199,9 @@ virDomainDeviceSetData(virDomainDeviceDefPtr device, case VIR_DOMAIN_DEVICE_LEASE: device->data.lease = devicedata; break; + case VIR_DOMAIN_DEVICE_AUDIO: + device->data.audio = devicedata; + break; case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LAST: break; @@ -4433,6 +4468,7 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def, case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_VSOCK: + case VIR_DOMAIN_DEVICE_AUDIO: break; } #endif @@ -5425,6 +5461,7 @@ virDomainDeviceDefPostParseCommon(virDomainDeviceDefPtr dev, case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_AUDIO: ret = 0; break; @@ -6814,6 +6851,8 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_SHMEM: return virDomainShmemDefValidate(dev->data.shmem); + case VIR_DOMAIN_DEVICE_AUDIO: + /* TODO: validate? */ case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_FS: case VIR_DOMAIN_DEVICE_SOUND: @@ -15016,10 +15055,10 @@ virDomainSoundDefParseXML(virDomainXMLOptionPtr xmlopt, virDomainSoundDefPtr def; VIR_XPATH_NODE_AUTORESTORE(ctxt); g_autofree char *model = NULL; + xmlNodePtr audioNode; if (VIR_ALLOC(def) < 0) return NULL; - ctxt->node = node; model = virXMLPropString(node, "model"); @@ -15056,6 +15095,18 @@ virDomainSoundDefParseXML(virDomainXMLOptionPtr xmlopt, } } + audioNode = virXPathNode("./audio", ctxt); + if (audioNode) { + g_autofree char *tmp = NULL; + tmp = virXMLPropString(audioNode, "id"); + if (virStrToLong_ui(tmp, NULL, 10, &def->audioId) < 0 || + def->audioId == 0) { + virReportError(VIR_ERR_XML_ERROR, + _("Invalid audio 'id' value '%s'"), tmp); + goto error; + } + } + if (virDomainDeviceInfoParseXML(xmlopt, node, &def->info, flags) < 0) goto error; @@ -15107,6 +15158,58 @@ virDomainSoundDefFind(const virDomainDef *def, } +static virDomainAudioDefPtr +virDomainAudioDefParseXML(virDomainXMLOptionPtr xmlopt G_GNUC_UNUSED, + xmlNodePtr node G_GNUC_UNUSED, + xmlXPathContextPtr ctxt G_GNUC_UNUSED) +{ + virDomainAudioDefPtr def; + VIR_XPATH_NODE_AUTORESTORE(ctxt); + g_autofree char *tmp = NULL; + g_autofree char *type = NULL; + + if (VIR_ALLOC(def) < 0) + return NULL; + ctxt->node = node; + + type = virXMLPropString(node, "type"); + if ((def->type = virDomainAudioTypeTypeFromString(type)) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown audio type '%s'"), type); + goto error; + } + + tmp = virXMLPropString(node, "id"); + if (virStrToLong_ui(tmp, NULL, 10, &def->id) < 0 || + def->id == 0) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid audio 'id' value '%s'"), tmp); + goto error; + } + + if (def->type == VIR_DOMAIN_AUDIO_TYPE_OSS) { + xmlNodePtr inputDevNode, outputDevNode; + + inputDevNode = virXPathNode("./input", ctxt); + outputDevNode = virXPathNode("./output", ctxt); + + if (!inputDevNode || !outputDevNode) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Audio type OSS requires to have <input> " + "and <output> specified")); + goto error; + } + + def->backend.oss.inputDev = virXMLPropString(inputDevNode, "dev"); + def->backend.oss.outputDev = virXMLPropString(outputDevNode, "dev"); + } + + return def; + + error: + virDomainAudioDefFree(def); + return NULL; +} static virDomainWatchdogDefPtr virDomainWatchdogDefParseXML(virDomainXMLOptionPtr xmlopt, xmlNodePtr node, @@ -17063,6 +17166,10 @@ virDomainDeviceDefParse(const char *xmlStr, ctxt, flags))) return NULL; break; + case VIR_DOMAIN_DEVICE_AUDIO: + if (!(dev->data.audio = virDomainAudioDefParseXML(xmlopt, node, ctxt))) + return NULL; + break; case VIR_DOMAIN_DEVICE_WATCHDOG: if (!(dev->data.watchdog = virDomainWatchdogDefParseXML(xmlopt, node, flags))) @@ -21971,6 +22078,22 @@ virDomainDefParseXML(xmlDocPtr xml, } VIR_FREE(nodes); + /* analysis of the audio devices */ + if ((n = virXPathNodeSet("./devices/audio", ctxt, &nodes)) < 0) + goto error; + if (n && VIR_ALLOC_N(def->audios, n) < 0) + goto error; + for (i = 0; i < n; i++) { + virDomainAudioDefPtr audio = virDomainAudioDefParseXML(xmlopt, + nodes[i], + ctxt); + if (!audio) + goto error; + + def->audios[def->naudios++] = audio; + } + VIR_FREE(nodes); + /* analysis of the video devices */ if ((n = virXPathNodeSet("./devices/video", ctxt, &nodes)) < 0) goto error; @@ -22485,7 +22608,6 @@ virDomainDefParse(const char *xmlStr, virDomainDefPtr def = NULL; int keepBlanksDefault = xmlKeepBlanksDefault(0); xmlNodePtr root; - if (!(xml = virXMLParse(filename, xmlStr, _("(domain_definition)")))) goto cleanup; @@ -24586,6 +24708,7 @@ virDomainDefCheckABIStabilityFlags(virDomainDefPtr src, case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_VSOCK: + case VIR_DOMAIN_DEVICE_AUDIO: break; } #endif @@ -27352,6 +27475,9 @@ virDomainSoundDefFormat(virBufferPtr buf, for (i = 0; i < def->ncodecs; i++) virDomainSoundCodecDefFormat(&childBuf, def->codecs[i]); + if (def->audioId > 0) + virBufferAsprintf(&childBuf, "<audio id='%d'/>\n", def->audioId); + if (virDomainDeviceInfoFormat(&childBuf, &def->info, flags) < 0) return -1; @@ -27368,6 +27494,44 @@ virDomainSoundDefFormat(virBufferPtr buf, } +static int +virDomainAudioDefFormat(virBufferPtr buf, + virDomainAudioDefPtr def) +{ + g_auto(virBuffer) childBuf = VIR_BUFFER_INIT_CHILD(buf); + const char *type = virDomainAudioTypeTypeToString(def->type); + + if (!type) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected audio type %d"), def->type); + return -1; + } + + virBufferAsprintf(buf, "<audio id='%d' type='%s'", def->id, type); + + switch (def->type) { + case VIR_DOMAIN_AUDIO_TYPE_OSS: + if (def->backend.oss.inputDev) + virBufferAsprintf(&childBuf, "<input dev='%s'/>\n", + def->backend.oss.inputDev); + if (def->backend.oss.outputDev) + virBufferAsprintf(&childBuf, "<output dev='%s'/>\n", + def->backend.oss.outputDev); + break; + } + + if (virBufferUse(&childBuf)) { + virBufferAddLit(buf, ">\n"); + virBufferAddBuffer(buf, &childBuf); + virBufferAddLit(buf, "</audio>\n"); + } else { + virBufferAddLit(buf, "/>\n"); + } + + return 0; +} + + static int virDomainMemballoonDefFormat(virBufferPtr buf, virDomainMemballoonDefPtr def, @@ -30047,6 +30211,11 @@ virDomainDefFormatInternalSetRootName(virDomainDefPtr def, return -1; } + for (n = 0; n < def->naudios; n++) { + if (virDomainAudioDefFormat(buf, def->audios[n]) < 0) + return -1; + } + for (n = 0; n < def->nvideos; n++) { if (virDomainVideoDefFormat(buf, def->videos[n], flags) < 0) return -1; @@ -31219,6 +31388,9 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src, case VIR_DOMAIN_DEVICE_VSOCK: rc = virDomainVsockDefFormat(&buf, src->data.vsock); break; + case VIR_DOMAIN_DEVICE_AUDIO: + rc = virDomainAudioDefFormat(&buf, src->data.audio); + break; case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_SMARTCARD: diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 411b9b99e4..fdf706a7e0 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -85,6 +85,7 @@ typedef enum { VIR_DOMAIN_DEVICE_MEMORY, VIR_DOMAIN_DEVICE_IOMMU, VIR_DOMAIN_DEVICE_VSOCK, + VIR_DOMAIN_DEVICE_AUDIO, VIR_DOMAIN_DEVICE_LAST } virDomainDeviceType; @@ -116,6 +117,7 @@ struct _virDomainDeviceDef { virDomainMemoryDefPtr memory; virDomainIOMMUDefPtr iommu; virDomainVsockDefPtr vsock; + virDomainAudioDefPtr audio; } data; }; @@ -1417,6 +1419,27 @@ struct _virDomainSoundDef { size_t ncodecs; virDomainSoundCodecDefPtr *codecs; + + unsigned int audioId; +}; + +typedef enum { + VIR_DOMAIN_AUDIO_TYPE_OSS, + + VIR_DOMAIN_AUDIO_TYPE_LAST +} virDomainAudioType; + +struct _virDomainAudioDef { + int type; + + unsigned int id; + + union { + struct { + char *inputDev; + char *outputDev; + } oss; + } backend; }; typedef enum { @@ -2602,6 +2625,9 @@ struct _virDomainDef { size_t nsounds; virDomainSoundDefPtr *sounds; + size_t naudios; + virDomainAudioDefPtr *audios; + size_t nvideos; virDomainVideoDefPtr *videos; @@ -3032,6 +3058,7 @@ ssize_t virDomainSoundDefFind(const virDomainDef *def, const virDomainSoundDef *sound); void virDomainSoundDefFree(virDomainSoundDefPtr def); virDomainSoundDefPtr virDomainSoundDefRemove(virDomainDefPtr def, size_t idx); +void virDomainAudioDefFree(virDomainAudioDefPtr def); void virDomainMemballoonDefFree(virDomainMemballoonDefPtr def); void virDomainNVRAMDefFree(virDomainNVRAMDefPtr def); void virDomainWatchdogDefFree(virDomainWatchdogDefPtr def); @@ -3591,6 +3618,7 @@ VIR_ENUM_DECL(virDomainChrTcpProtocol); VIR_ENUM_DECL(virDomainChrSpicevmc); VIR_ENUM_DECL(virDomainSoundCodec); VIR_ENUM_DECL(virDomainSoundModel); +VIR_ENUM_DECL(virDomainAudioType); VIR_ENUM_DECL(virDomainKeyWrapCipherName); VIR_ENUM_DECL(virDomainMemballoonModel); VIR_ENUM_DECL(virDomainSmbiosMode); diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h index 1c62cde251..9042a2b34f 100644 --- a/src/conf/virconftypes.h +++ b/src/conf/virconftypes.h @@ -309,6 +309,9 @@ typedef virDomainSoundCodecDef *virDomainSoundCodecDefPtr; typedef struct _virDomainSoundDef virDomainSoundDef; typedef virDomainSoundDef *virDomainSoundDefPtr; +typedef struct _virDomainAudioDef virDomainAudioDef; +typedef virDomainAudioDef *virDomainAudioDefPtr; + typedef struct _virDomainTPMDef virDomainTPMDef; typedef virDomainTPMDef *virDomainTPMDefPtr; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 01c2e710cd..35bf9f08ef 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -224,6 +224,8 @@ virDiskNameToBusDeviceIndex; virDiskNameToIndex; virDomainActualNetDefFree; virDomainActualNetDefValidate; +virDomainAudioTypeTypeFromString; +virDomainAudioTypeTypeToString; virDomainBlockedReasonTypeFromString; virDomainBlockedReasonTypeToString; virDomainBlockIoTuneInfoCopy; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index ec3d4c8d99..40408fdd70 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -523,6 +523,7 @@ qemuBuildVirtioDevStr(virBufferPtr buf, case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_LAST: default: return 0; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index c440c79e1d..9c735e4776 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5265,6 +5265,7 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev, case VIR_DOMAIN_DEVICE_RNG: case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_AUDIO: ret = 0; break; diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index d25fb653d3..cbf8ffddd7 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -531,6 +531,7 @@ qemuDomainDeviceSupportZPCI(virDomainDeviceDefPtr device) case VIR_DOMAIN_DEVICE_MEMORY: case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_VSOCK: + case VIR_DOMAIN_DEVICE_AUDIO: break; case VIR_DOMAIN_DEVICE_NONE: @@ -1047,6 +1048,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDefPtr dev, case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_GRAPHICS: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_LAST: case VIR_DOMAIN_DEVICE_NONE: return 0; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0f98243fe4..43d6f6eb5b 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7960,6 +7960,7 @@ qemuDomainAttachDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("live attach of device '%s' is not supported"), @@ -8094,6 +8095,7 @@ qemuDomainUpdateDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_VSOCK: + case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("live update of device '%s' is not supported"), @@ -8313,6 +8315,7 @@ qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("persistent attach of device '%s' is not supported"), @@ -8515,6 +8518,7 @@ qemuDomainDetachDeviceConfig(virDomainDefPtr vmdef, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("persistent detach of device '%s' is not supported"), @@ -8622,6 +8626,7 @@ qemuDomainUpdateDeviceConfig(virDomainDefPtr vmdef, case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: case VIR_DOMAIN_DEVICE_VSOCK: + case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("persistent update of device '%s' is not supported"), diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 2c6c30ce03..3a780d00af 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -4944,6 +4944,7 @@ qemuDomainRemoveAuditDevice(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_LAST: /* libvirt doesn't yet support detaching these devices */ break; @@ -5042,6 +5043,7 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("don't know how to remove a %s device"), @@ -5813,6 +5815,7 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm, case VIR_DOMAIN_DEVICE_TPM: case VIR_DOMAIN_DEVICE_PANIC: case VIR_DOMAIN_DEVICE_IOMMU: + case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_LAST: virReportError(VIR_ERR_OPERATION_UNSUPPORTED, _("live detach of device '%s' is not supported"), diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 4cd377c8bc..fe8a64b933 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -4145,6 +4145,7 @@ qemuValidateDomainDeviceDef(const virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_SHMEM: case VIR_DOMAIN_DEVICE_PANIC: + case VIR_DOMAIN_DEVICE_AUDIO: case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LAST: break; -- 2.27.0