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='ich6'> <audio id='audio0'/> </sound> <audio id='audio' 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 | 156 ++++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 24 +++++ 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, 236 insertions(+), 2 deletions(-) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index a810f569c6..b0a5e08ba0 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4366,12 +4366,47 @@ <optional> <ref name="address"/> </optional> + <optional> + <element name="audio"> + <attribute name="id"> + <data type="string"/> + </attribute> + </element> + </optional> <zeroOrMore> <ref name="codec"/> </zeroOrMore> </interleave> </element> </define> + <define name="audio"> + <element name="audio"> + <attribute name="id"> + <data type="string"/> + </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"> @@ -5286,6 +5321,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 837b004334..165a792cdf 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -692,6 +692,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 7ecd2818b9..50a5c3387d 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, @@ -728,6 +729,11 @@ VIR_ENUM_IMPL(virDomainSoundModel, "usb", ); +VIR_ENUM_IMPL(virDomainAudioType, + VIR_DOMAIN_AUDIO_TYPE_LAST, + "oss", +); + VIR_ENUM_IMPL(virDomainKeyWrapCipherName, VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_LAST, "aes", @@ -2850,6 +2856,21 @@ void virDomainSoundDefFree(virDomainSoundDefPtr def) virDomainSoundCodecDefFree(def->codecs[i]); VIR_FREE(def->codecs); + VIR_FREE(def->audioId); + + VIR_FREE(def); +} + +void virDomainAudioDefFree(virDomainAudioDefPtr def) +{ + if (!def) + return; + + VIR_FREE(def->id); + + VIR_FREE(def->inputDev); + VIR_FREE(def->outputDev); + VIR_FREE(def); } @@ -3206,6 +3227,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; @@ -3466,6 +3490,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); @@ -4054,6 +4082,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; @@ -4148,6 +4177,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; @@ -4414,6 +4446,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 @@ -5406,6 +5439,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; @@ -6795,6 +6829,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: @@ -14984,10 +15020,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"); @@ -15024,6 +15060,10 @@ virDomainSoundDefParseXML(virDomainXMLOptionPtr xmlopt, } } + audioNode = virXPathNode("./audio", ctxt); + if (audioNode) + def->audioId = virXMLPropString(audioNode, "id"); + if (virDomainDeviceInfoParseXML(xmlopt, node, &def->info, flags) < 0) goto error; @@ -15075,6 +15115,51 @@ 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 *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; + } + + def->id = virXMLPropString(node, "id"); + + 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->inputDev = virXMLPropString(inputDevNode, "dev"); + def->outputDev = virXMLPropString(outputDevNode, "dev"); + } + + return def; + + error: + virDomainAudioDefFree(def); + return NULL; +} static virDomainWatchdogDefPtr virDomainWatchdogDefParseXML(virDomainXMLOptionPtr xmlopt, xmlNodePtr node, @@ -17014,6 +17099,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))) @@ -21910,6 +21999,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; @@ -22424,7 +22529,6 @@ virDomainDefParse(const char *xmlStr, virDomainDefPtr def = NULL; int keepBlanksDefault = xmlKeepBlanksDefault(0); xmlNodePtr root; - if (!(xml = virXMLParse(filename, xmlStr, _("(domain_definition)")))) goto cleanup; @@ -24523,6 +24627,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 @@ -27284,6 +27389,9 @@ virDomainSoundDefFormat(virBufferPtr buf, for (i = 0; i < def->ncodecs; i++) virDomainSoundCodecDefFormat(&childBuf, def->codecs[i]); + if (def->audioId) + virBufferAsprintf(&childBuf, "<audio id='%s'/>\n", def->audioId); + if (virDomainDeviceInfoFormat(&childBuf, &def->info, flags) < 0) return -1; @@ -27300,6 +27408,42 @@ 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='%s' type='%s'", def->id, type); + + switch (def->type) { + case VIR_DOMAIN_AUDIO_TYPE_OSS: + if (def->inputDev) + virBufferAsprintf(&childBuf, "<input dev='%s'/>\n", def->inputDev); + if (def->outputDev) + virBufferAsprintf(&childBuf, "<output dev='%s'/>\n", def->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, @@ -29975,6 +30119,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; @@ -31147,6 +31296,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 241149af24..fefd428ccd 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; }; @@ -1415,6 +1417,23 @@ struct _virDomainSoundDef { size_t ncodecs; virDomainSoundCodecDefPtr *codecs; + + char *audioId; +}; + +typedef enum { + VIR_DOMAIN_AUDIO_TYPE_OSS, + + VIR_DOMAIN_AUDIO_TYPE_LAST +} virDomainAudioType; + +struct _virDomainAudioDef { + int type; + + char *id; + + /* OSS specific configuration */ + char *inputDev, *outputDev; }; typedef enum { @@ -2591,6 +2610,9 @@ struct _virDomainDef { size_t nsounds; virDomainSoundDefPtr *sounds; + size_t naudios; + virDomainAudioDefPtr *audios; + size_t nvideos; virDomainVideoDefPtr *videos; @@ -3021,6 +3043,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); @@ -3580,6 +3603,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 73b72c9e10..98e041bd53 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 839c93bfb4..f5c31c8a9f 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -522,6 +522,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 7530edac53..d92bf71c8b 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -5255,6 +5255,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 058cbda2a2..97d21aaf8c 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: @@ -1046,6 +1047,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 d185666ed8..4d09391062 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7953,6 +7953,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"), @@ -8087,6 +8088,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"), @@ -8306,6 +8308,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"), @@ -8508,6 +8511,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"), @@ -8615,6 +8619,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 26912334d2..008533bd8c 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 488f258d00..97c227e034 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -4144,6 +4144,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