[libvirt] [PATCH 2/3] qemu: parse usb-audio audio device XML and docs

Guannan Ren gren at redhat.com
Thu Jan 3 07:39:06 UTC 2013


usb-audio XML example:
 <devices>
   <sound model='usb-audio'>
     <buffer>1536</buffer>
     <address type='usb' bus='0' port='1'/>
   </sound>
 </devices>

qemu ${other_vm_args} \
 -device usb-audio,id=sound0,buffer=1536,bus=usb.0,port=1

there is an optional sub-element <buffer> to customize
the buffer size of usb audio device, if missing,
the default size is 1536(defined in qemu code).
Special size of value 0 means no buffer will be used,
so we use bool 'customized_buffer'to differentiate
user-defined 0 from being using default buffer value 1536.
---
 docs/formatdomain.html.in     | 10 +++++++--
 docs/schemas/basictypes.rng   | 11 ++++++++++
 docs/schemas/domaincommon.rng |  9 ++++++++
 docs/schemas/nwfilter.rng     | 15 -------------
 src/conf/domain_conf.c        | 49 ++++++++++++++++++++++++++++++++++++++++++-
 src/conf/domain_conf.h        |  5 +++++
 src/qemu/qemu_command.c       | 19 ++++++++++++++++-
 7 files changed, 99 insertions(+), 19 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 94df6f8..354d4f6 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -4056,9 +4056,15 @@ qemu-kvm -net nic,model=? /dev/null
         The <code>sound</code> element has one mandatory attribute,
         <code>model</code>, which specifies what real sound device is emulated.
         Valid values are specific to the underlying hypervisor, though typical
-        choices are 'es1370', 'sb16', 'ac97', and 'ich6'
+        choices are 'es1370', 'sb16', 'ac97', 'ich6' and 'usb-audio'
         (<span class="since">
-         'ac97' only since 0.6.0, 'ich6' only since 0.8.8</span>)
+         'ac97' only since 0.6.0, 'ich6' only since 0.8.8,
+         'usb-audio' only since 1.0.2</span>)
+        For the 'usb-audio' model, there is an optional sub-element <code><buffer></code>
+        to customize the buffer size of the audio device, if missing, the default size is 1536.
+        The goal of setting a buffer size is to reduce it as much as possible without
+        hearing any clicks, pops, or other glitches. Special size of value 0 means no buffer
+        will be used, e.g. <code><buffer>3072</buffer></code>.
       </dd>
     </dl>
 
diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
index 38cab16..4e8d4b8 100644
--- a/docs/schemas/basictypes.rng
+++ b/docs/schemas/basictypes.rng
@@ -42,6 +42,17 @@
       </data>
     </choice>
   </define>
+  <define name="uint32range">
+    <choice>
+      <data type="string">
+        <param name="pattern">0x[0-9a-fA-F]{1,8}</param>
+      </data>
+      <data type="long">
+        <param name="minInclusive">0</param>
+        <param name="maxInclusive">4294967295</param>
+      </data>
+    </choice>
+  </define>
 
   <define name="UUID">
     <choice>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 0529d62..55c1219 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2599,6 +2599,11 @@
       </attribute>
     </element>
   </define>
+  <define name="audiobuffer">
+    <element name='buffer'>
+      <ref name="uint32range"/>
+    </element>
+  </define>
   <define name="sound">
     <element name="sound">
       <attribute name="model">
@@ -2608,6 +2613,7 @@
           <value>pcspk</value>
           <value>ac97</value>
           <value>ich6</value>
+          <value>usb-audio</value>
         </choice>
       </attribute>
       <interleave>
@@ -2622,6 +2628,9 @@
             <ref name="codec"/>
           </choice>
         </zeroOrMore>
+        <optional>
+          <ref name ="audiobuffer"/>
+        </optional>
       </interleave>
     </element>
   </define>
diff --git a/docs/schemas/nwfilter.rng b/docs/schemas/nwfilter.rng
index cfd9ba5..5681083 100644
--- a/docs/schemas/nwfilter.rng
+++ b/docs/schemas/nwfilter.rng
@@ -942,21 +942,6 @@
     </choice>
   </define>
 
-  <define name="uint32range">
-    <choice>
-      <ref name="variable-name-type"/>
-
-      <data type="string">
-        <param name="pattern">0x[0-9a-fA-F]{1,8}</param>
-      </data>
-
-      <data type="int">
-        <param name="minInclusive">0</param>
-        <param name="maxInclusive">4294967295</param>
-      </data>
-    </choice>
-  </define>
-
   <define name="boolean">
     <choice>
       <value>yes</value>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 79af087..955e089 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -395,7 +395,8 @@ VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST,
               "es1370",
               "pcspk",
               "ac97",
-              "ich6")
+              "ich6",
+              "usb-audio")
 
 VIR_ENUM_IMPL(virDomainMemDump, VIR_DOMAIN_MEM_DUMP_LAST,
               "default",
@@ -7009,6 +7010,38 @@ error:
     goto cleanup;
 }
 
+static int
+virDomainSoundUSBAudioBufferParseXML(const xmlNodePtr node,
+                                     xmlXPathContextPtr ctxt,
+                                     virDomainSoundDefPtr def)
+{
+    int ret;
+    unsigned long value;
+
+    if (!node || !ctxt)
+        return -1;
+
+    ret = virXPathULong("string(./buffer[1])", ctxt, &value);
+    if (ret < 0) {
+        if (ret == -2) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           "%s", _("could not parse usb-audio buffer element"));
+            return -1;
+        } else {
+            def->customized_buffer = false;
+        }
+    } else if (value > UINT32_MAX) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       "%s", _("usb-audio buffer is too big, "
+                               "no more than 4294967295"));
+        return -1;
+    } else {
+        def->buf_value = value;
+        def->customized_buffer = true;
+    }
+
+    return 0;
+}
 
 static virDomainSoundDefPtr
 virDomainSoundDefParseXML(const xmlNodePtr node,
@@ -7063,6 +7096,11 @@ virDomainSoundDefParseXML(const xmlNodePtr node,
         }
     }
 
+    if (def->model == VIR_DOMAIN_SOUND_MODEL_USB_AUDIO) {
+        if (virDomainSoundUSBAudioBufferParseXML(node, ctxt, def) < 0)
+            goto error;
+    }
+
     if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
         goto error;
 
@@ -13204,6 +13242,15 @@ virDomainSoundDefFormat(virBufferPtr buf,
         virDomainSoundCodecDefFormat(buf, def->codecs[i]);
     }
 
+    if (def->customized_buffer) {
+        if (!children) {
+            virBufferAddLit(buf, ">\n");
+            children = true;
+        }
+         virBufferAsprintf(buf, "      <buffer>%lu</buffer>\n",
+                           (unsigned long)def->buf_value);
+    }
+
     if (virDomainDeviceInfoIsSet(&def->info, flags)) {
         if (!children) {
             virBufferAddLit(buf, ">\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a975a63..6493443 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1073,6 +1073,7 @@ enum virDomainSoundModel {
     VIR_DOMAIN_SOUND_MODEL_PCSPK,
     VIR_DOMAIN_SOUND_MODEL_AC97,
     VIR_DOMAIN_SOUND_MODEL_ICH6,
+    VIR_DOMAIN_SOUND_MODEL_USB_AUDIO,
 
     VIR_DOMAIN_SOUND_MODEL_LAST
 };
@@ -1088,6 +1089,10 @@ struct _virDomainSoundDef {
 
     size_t ncodecs;
     virDomainSoundCodecDefPtr *codecs;
+
+    /* for usb-audio only */
+    bool customized_buffer;
+    uint32_t buf_value;
 };
 
 enum virDomainWatchdogModel {
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 8a3de09..31b0d89 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1571,7 +1571,8 @@ qemuAssignDevicePCISlots(virDomainDefPtr def,
             continue;
         /* Skip ISA sound card, and PCSPK */
         if (def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_SB16 ||
-            def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_PCSPK)
+            def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_PCSPK ||
+            def->sounds[i]->model == VIR_DOMAIN_SOUND_MODEL_USB_AUDIO)
             continue;
 
         if (qemuDomainPCIAddressSetNextAddr(addrs, &def->sounds[i]->info) < 0)
@@ -3462,7 +3463,23 @@ qemuBuildSoundDevStr(virDomainSoundDefPtr sound,
     else if (STREQ(model, "ich6"))
         model = "intel-hda";
 
+    if (STREQ(model, "usb-audio")) {
+        if (!qemuCapsGet(caps, QEMU_CAPS_DEVICE_USB_AUDIO)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           "%s", _("usb-audio is not supported"
+                                   " by this version of QEMU"));
+            goto error;
+        } else {
+           model = "usb-audio";
+        }
+    }
+
     virBufferAsprintf(&buf, "%s,id=%s", model, sound->info.alias);
+
+    if (sound->customized_buffer)
+        virBufferAsprintf(&buf, ",buffer=%lu",
+                          (unsigned long)sound->buf_value);
+
     if (qemuBuildDeviceAddressStr(&buf, &sound->info, caps) < 0)
         goto error;
 
-- 
1.7.11.4




More information about the libvir-list mailing list