[libvirt] [PATCH 2/2] qemu: add usb-serial support

Guannan Ren gren at redhat.com
Thu Jan 3 06:57:26 UTC 2013


Add an optional 'type' attribute to <target> element of serial port
device. There are two choices for its value, 'isa-serial' and
'usb-serial'. For backward compatibility, when attribute 'type' is
missing the 'isa-serial' will be chose as before.

Libvirt XML sample

    <serial type='pty'>
      <target type='usb-serial' port='0'/>
      <address type='usb' bus='0' port='1'/>
    </serial>

qemu commandline:

qemu ${other_vm_args}              \
    -chardev pty,id=charserial0    \
    -device usb-serial,chardev=charserial0,id=serial0,bus=usb.0,port=1
---
 docs/formatdomain.html.in     |  9 ++++++++-
 docs/schemas/domaincommon.rng | 20 +++++++++++++++++---
 src/conf/domain_conf.c        | 42 +++++++++++++++++++++++++++++++++++++++---
 src/conf/domain_conf.h        | 10 ++++++++++
 src/libvirt_private.syms      |  2 ++
 src/qemu/qemu_command.c       | 24 ++++++++++++++++++++++--
 6 files changed, 98 insertions(+), 9 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 94df6f8..7241bb9 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -3677,7 +3677,14 @@ qemu-kvm -net nic,model=? /dev/null
     <p>
       <code>target</code> can have a <code>port</code> attribute, which
       specifies the port number. Ports are numbered starting from 0. There are
-      usually 0, 1 or 2 serial ports.
+      usually 0, 1 or 2 serial ports. There is also an optional
+      <code>type</code> attribute <span class="since">Since 1.0.2</span>
+      which has two choices for its value, one is< code>isa-serial</code>,
+      the other is <code>usb-serial</code>. If <code>type</code> is missing,
+      <code>isa-serial</code> will be used by default. For <code>usb-serial</code>
+      an optional sub-element <code><address></code> with
+      <code>type='usb'</code>which can tie the device to a particular controller,
+      <a href="#elementsAddress">documentedabove</a>.
     </p>
 
     <h6><a name="elementCharConsole">Console</a></h6>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 0529d62..7b7a2f9 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2453,12 +2453,26 @@
     </attribute>
   </define>
 
+  <define name='qemucdevSerialTgtType'>
+    <attribute name='type'>
+      <choice>
+        <value>isa-serial</value>
+        <value>usb-serial</value>
+      </choice>
+    </attribute>
+  </define>
+
   <define  name="qemucdevTgtDef">
     <element name="target">
       <interleave>
-        <optional>
-          <ref name="qemucdevConsoleTgtType"/>
-        </optional>
+        <choice>
+          <optional>
+            <ref name="qemucdevConsoleTgtType"/>
+          </optional>
+          <optional>
+            <ref name="qemucdevSerialTgtType"/>
+          </optional>
+        </choice>
         <optional>
           <attribute name="port"/>
         </optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 79af087..9ece160 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -336,6 +336,11 @@ VIR_ENUM_IMPL(virDomainNetInterfaceLinkState, VIR_DOMAIN_NET_INTERFACE_LINK_STAT
               "up",
               "down")
 
+VIR_ENUM_IMPL(virDomainChrSerialTarget,
+              VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_LAST,
+              "isa-serial",
+              "usb-serial")
+
 VIR_ENUM_IMPL(virDomainChrChannelTarget,
               VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST,
               "none",
@@ -5445,6 +5450,9 @@ virDomainChrDefaultTargetType(virCapsPtr caps,
         break;
 
     case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
+        target = VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_ISA;
+        break;
+
     case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
     default:
         /* No target type yet*/
@@ -5457,7 +5465,8 @@ virDomainChrDefaultTargetType(virCapsPtr caps,
 
 static int
 virDomainChrTargetTypeFromString(virCapsPtr caps,
-                                 virDomainDefPtr def,
+                                 virDomainDefPtr vmdef,
+                                 virDomainChrDefPtr def,
                                  int devtype,
                                  const char *targetType)
 {
@@ -5465,7 +5474,7 @@ virDomainChrTargetTypeFromString(virCapsPtr caps,
     int target = 0;
 
     if (!targetType) {
-        target = virDomainChrDefaultTargetType(caps, def, devtype);
+        target = virDomainChrDefaultTargetType(caps, vmdef, devtype);
         goto out;
     }
 
@@ -5479,12 +5488,17 @@ virDomainChrTargetTypeFromString(virCapsPtr caps,
         break;
 
     case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
+        target = virDomainChrSerialTargetTypeFromString(targetType);
+        break;
+
     case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
     default:
         /* No target type yet*/
         break;
     }
 
+    def->targetType_attr = true;
+
 out:
     ret = target;
     return ret;
@@ -5503,7 +5517,7 @@ virDomainChrDefParseTargetXML(virCapsPtr caps,
     const char *portStr = NULL;
 
     if ((def->targetType =
-         virDomainChrTargetTypeFromString(caps, vmdef,
+         virDomainChrTargetTypeFromString(caps, vmdef, def,
                                           def->deviceType, targetType)) < 0) {
         virReportError(VIR_ERR_XML_ERROR,
                        _("unknown target type '%s' specified for character device"),
@@ -5936,6 +5950,15 @@ virDomainChrDefParseXML(virCapsPtr caps,
     if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
         goto error;
 
+    if (def->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
+        def->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB &&
+        def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+        def->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("usb-serial requires address of usb type"));
+        goto error;
+    }
+
 cleanup:
     VIR_FREE(type);
 
@@ -7939,6 +7962,9 @@ virDomainChrTargetTypeToString(int deviceType,
     case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
         type = virDomainChrConsoleTargetTypeToString(targetType);
         break;
+    case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
+        type = virDomainChrSerialTargetTypeToString(targetType);
+        break;
     default:
         break;
     }
@@ -13088,6 +13114,15 @@ virDomainChrDefFormat(virBufferPtr buf,
                           def->target.port);
         break;
 
+    case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
+        if (def->targetType_attr) {
+            virBufferAsprintf(buf,
+                              "      <target type='%s' port='%d'/>\n",
+                              virDomainChrTargetTypeToString(def->deviceType,
+                                                             def->targetType),
+                              def->target.port);
+            break;
+        }
     default:
         virBufferAsprintf(buf, "      <target port='%d'/>\n",
                           def->target.port);
@@ -14415,6 +14450,7 @@ virDomainDefFormatInternal(virDomainDefPtr def,
             (n < def->nserials)) {
             memcpy(&console, def->serials[n], sizeof(console));
             console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
+            console.targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
         } else {
             memcpy(&console, def->consoles[n], sizeof(console));
         }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a975a63..0e2746b 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -909,6 +909,13 @@ enum virDomainChrDeviceType {
     VIR_DOMAIN_CHR_DEVICE_TYPE_LAST
 };
 
+enum virDomainChrSerialTargetType {
+    VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_ISA = 0,
+    VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB,
+
+    VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_LAST
+};
+
 enum virDomainChrChannelTargetType {
     VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_NONE = 0,
     VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD,
@@ -994,6 +1001,8 @@ struct _virDomainChrSourceDef {
 /* A complete character device, both host and domain views.  */
 struct _virDomainChrDef {
     int deviceType;
+
+    bool targetType_attr;
     int targetType;
     union {
         int port; /* parallel, serial, console */
@@ -2250,6 +2259,7 @@ VIR_ENUM_DECL(virDomainNetInterfaceLinkState)
 VIR_ENUM_DECL(virDomainChrDevice)
 VIR_ENUM_DECL(virDomainChrChannelTarget)
 VIR_ENUM_DECL(virDomainChrConsoleTarget)
+VIR_ENUM_DECL(virDomainChrSerialTarget)
 VIR_ENUM_DECL(virDomainSmartcard)
 VIR_ENUM_DECL(virDomainChr)
 VIR_ENUM_DECL(virDomainChrTcpProtocol)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 497d5d3..aefdf9c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -293,6 +293,8 @@ virDomainChrConsoleTargetTypeToString;
 virDomainChrDefForeach;
 virDomainChrDefFree;
 virDomainChrDefNew;
+virDomainChrSerialTargetTypeFromString;
+virDomainChrSerialTargetTypeToString;
 virDomainChrSourceDefCopy;
 virDomainChrSourceDefFree;
 virDomainChrSpicevmcTypeFromString;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 8a3de09..879b943 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6975,10 +6975,30 @@ qemuBuildChrDeviceStr(virDomainChrDefPtr serial,
             if (qemuBuildDeviceAddressStr(&cmd, &serial->info, caps) < 0)
                 goto error;
         }
-    } else
-        virBufferAsprintf(&cmd, "isa-serial,chardev=char%s,id=%s",
+    } else {
+        virBufferAsprintf(&cmd, "%s,chardev=char%s,id=%s",
+                          virDomainChrSerialTargetTypeToString(serial->targetType),
                           serial->info.alias, serial->info.alias);
 
+        if (serial->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_USB) {
+            if (!qemuCapsGet(caps, QEMU_CAPS_DEVICE_USB_SERIAL)) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("usb-serial is not supported in this QEMU binary"));
+                goto error;
+            }
+
+            if (serial->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+                serial->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("usb-serial requires address of usb type"));
+                goto error;
+            }
+
+            if (qemuBuildDeviceAddressStr(&cmd, &serial->info, caps) < 0)
+               goto error;
+        }
+    }
+
     if (virBufferError(&cmd)) {
         virReportOOMError();
         goto error;
-- 
1.7.11.4




More information about the libvir-list mailing list