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 <pkrempa(a)redhat.com>
---
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:
</devices>
...
+:since:`Since 9.4.0` the ``usb`` sound device can be optionally switched into
+multi-channel mode by using the ``multichannel`` attribute::
+
+ <sound model='usb' multichannel='yes'/>
+
Each ``sound`` element has an optional sub-element ``<address>`` 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 @@
<value>usb</value>
</choice>
</attribute>
+ <optional>
+ <attribute name="multichannel">
+ <ref name="virYesNo"/>
+ </attribute>
+ </optional>
<interleave>
<optional>
<ref name="alias"/>
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 @@
<codec type='duplex'/>
<codec type='output'/>
</sound>
- <sound model='usb'/>
+ <sound model='usb' multichannel='yes'/>
<memballoon model='virtio'/>
</devices>
</domain>
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 @@
<codec type='output'/>
<address type='pci' domain='0x0000' bus='0x00'
slot='0x07' function='0x0'/>
</sound>
- <sound model='usb'/>
+ <sound model='usb' multichannel='yes'/>
<audio id='1' type='none'/>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00'
slot='0x08' function='0x0'/>
--
2.40.0