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