From 3d6bc5c61101aadd6fca5d558a44a1cba8120178 Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Tue, 9 May 2023 13:10:30 +0200 Subject: [PATCH] conf: qemu: Add support for multi-channel mode for 'usb' sound cards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow users controlling the multi-channel mode by adding a 'multichannel' property parsed for USB audio devices and wire up the support in the qemu driver. Closes: https://gitlab.com/libvirt/libvirt/-/issues/472 Signed-off-by: Peter Krempa Reviewed-by: Ján Tomko --- docs/formatdomain.rst | 5 ++++ src/conf/domain_conf.c | 23 +++++++++++++++++++ src/conf/domain_conf.h | 4 ++++ src/conf/schemas/domaincommon.rng | 5 ++++ src/qemu/qemu_command.c | 3 +++ .../sound-device.x86_64-4.2.0.args | 2 +- .../sound-device.x86_64-latest.args | 2 +- tests/qemuxml2argvdata/sound-device.xml | 2 +- .../sound-device.x86_64-latest.xml | 2 +- 9 files changed, 44 insertions(+), 4 deletions(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index d62bda9adb..99383e725c 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -7235,6 +7235,11 @@ Valid values are: ... +:since:`Since 9.4.0` the ``usb`` sound device can be optionally switched into +multi-channel mode by using the ``multichannel`` attribute:: + + + Each ``sound`` element has an optional sub-element ``
`` which can tie the device to a particular PCI slot. See `Device Addresses`_. diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 204b6a85e1..6a864a8db9 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -11689,6 +11689,12 @@ virDomainSoundDefParseXML(virDomainXMLOption *xmlopt, } } + if (def->model == VIR_DOMAIN_SOUND_MODEL_USB) { + if (virXMLPropTristateBool(node, "multichannel", VIR_XML_PROP_NONE, + &def->multichannel) < 0) + return NULL; + } + audioNode = virXPathNode("./audio", ctxt); if (audioNode) { if (virXMLPropUInt(audioNode, "id", 10, @@ -11721,6 +11727,9 @@ virDomainSoundDefEquals(const virDomainSoundDef *a, return false; } + if (a->multichannel != b->multichannel) + return false; + if (a->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE && !virDomainDeviceInfoAddressIsEqual(&a->info, &b->info)) return false; @@ -20010,6 +20019,14 @@ virDomainSoundDefCheckABIStability(virDomainSoundDef *src, return false; } + if (src->multichannel != dst->multichannel) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Target sound card multichannel setting '%1$s' does not match source '%2$s'"), + virTristateBoolTypeToString(dst->multichannel), + virTristateBoolTypeToString(src->multichannel)); + return false; + } + if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info)) return false; @@ -24531,6 +24548,12 @@ virDomainSoundDefFormat(virBuffer *buf, virBufferAsprintf(&attrBuf, " model='%s'", model); + if (def->model == VIR_DOMAIN_SOUND_MODEL_USB && + def->multichannel != VIR_TRISTATE_BOOL_ABSENT) { + virBufferAsprintf(&attrBuf, " multichannel='%s'", + virTristateBoolTypeToString(def->multichannel)); + } + virXMLFormatElement(buf, "sound", &attrBuf, &childBuf); return 0; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index a04f7decc6..c1cb2ed69d 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1596,6 +1596,10 @@ struct _virDomainSoundDef { size_t ncodecs; virDomainSoundCodecDef **codecs; + /* VIR_DOMAIN_SOUND_MODEL_USB can be optionally switched to + * multi-channel mode */ + virTristateBool multichannel; + unsigned int audioId; }; diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng index 57fb4a5e33..f8c7b6a648 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -4969,6 +4969,11 @@ usb + + + + + diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index dcad449413..2a6d9408f6 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4384,6 +4384,7 @@ qemuBuildSoundDevCmd(virCommand *cmd, g_autoptr(virJSONValue) props = NULL; const char *model = NULL; g_autofree char *audioid = NULL; + virTristateBool multichannel = VIR_TRISTATE_BOOL_ABSENT; switch (sound->model) { case VIR_DOMAIN_SOUND_MODEL_ES1370: @@ -4397,6 +4398,7 @@ qemuBuildSoundDevCmd(virCommand *cmd, break; case VIR_DOMAIN_SOUND_MODEL_USB: model = "usb-audio"; + multichannel = sound->multichannel; break; case VIR_DOMAIN_SOUND_MODEL_ICH9: model = "ich9-intel-hda"; @@ -4419,6 +4421,7 @@ qemuBuildSoundDevCmd(virCommand *cmd, "s:driver", model, "s:id", sound->info.alias, "S:audiodev", audioid, + "T:multi", multichannel, NULL) < 0) return -1; diff --git a/tests/qemuxml2argvdata/sound-device.x86_64-4.2.0.args b/tests/qemuxml2argvdata/sound-device.x86_64-4.2.0.args index 121b37ff99..b2a5afd8c8 100644 --- a/tests/qemuxml2argvdata/sound-device.x86_64-4.2.0.args +++ b/tests/qemuxml2argvdata/sound-device.x86_64-4.2.0.args @@ -44,7 +44,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -device hda-micro,id=sound7-codec0,bus=sound7.0,cad=0,audiodev=audio1 \ -device hda-duplex,id=sound7-codec1,bus=sound7.0,cad=1,audiodev=audio1 \ -device hda-output,id=sound7-codec2,bus=sound7.0,cad=2,audiodev=audio1 \ --device usb-audio,id=sound8,audiodev=audio1,bus=usb.0,port=1 \ +-device usb-audio,id=sound8,audiodev=audio1,multi=on,bus=usb.0,port=1 \ -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x8 \ -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ -msg timestamp=on diff --git a/tests/qemuxml2argvdata/sound-device.x86_64-latest.args b/tests/qemuxml2argvdata/sound-device.x86_64-latest.args index 3132760fe0..e0a2f21b31 100644 --- a/tests/qemuxml2argvdata/sound-device.x86_64-latest.args +++ b/tests/qemuxml2argvdata/sound-device.x86_64-latest.args @@ -44,7 +44,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \ -device '{"driver":"hda-micro","id":"sound7-codec0","bus":"sound7.0","cad":0,"audiodev":"audio1"}' \ -device '{"driver":"hda-duplex","id":"sound7-codec1","bus":"sound7.0","cad":1,"audiodev":"audio1"}' \ -device '{"driver":"hda-output","id":"sound7-codec2","bus":"sound7.0","cad":2,"audiodev":"audio1"}' \ --device '{"driver":"usb-audio","id":"sound8","audiodev":"audio1","bus":"usb.0","port":"1"}' \ +-device '{"driver":"usb-audio","id":"sound8","audiodev":"audio1","multi":true,"bus":"usb.0","port":"1"}' \ -device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x8"}' \ -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ -msg timestamp=on diff --git a/tests/qemuxml2argvdata/sound-device.xml b/tests/qemuxml2argvdata/sound-device.xml index 35a60da197..c58033235c 100644 --- a/tests/qemuxml2argvdata/sound-device.xml +++ b/tests/qemuxml2argvdata/sound-device.xml @@ -34,7 +34,7 @@ - + diff --git a/tests/qemuxml2xmloutdata/sound-device.x86_64-latest.xml b/tests/qemuxml2xmloutdata/sound-device.x86_64-latest.xml index 89f537bb01..29d700cebb 100644 --- a/tests/qemuxml2xmloutdata/sound-device.x86_64-latest.xml +++ b/tests/qemuxml2xmloutdata/sound-device.x86_64-latest.xml @@ -52,7 +52,7 @@
- +