From e3a04455fa4b867726157ff0a35f61a045c443a3 Mon Sep 17 00:00:00 2001 From: Guannan Ren Date: Sat, 5 Jan 2013 13:25:36 +0800 Subject: [PATCH] qemu: add usb-serial support Add an optional 'type' attribute to 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 chosen as before. Libvirt XML sample
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 c5725e5d3a..f3b35f933b 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -3688,7 +3688,14 @@ qemu-kvm -net nic,model=? /dev/null

target can have a port 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 + type attribute since 1.0.2 + which has two choices for its value, one is< code>isa-serial, + the other is usb-serial. If type is missing, + isa-serial will be used by default. For usb-serial + an optional sub-element <address> with + type='usb' can tie the device to a particular controller, + documented above.

Console
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index be121023ab..67ae864b39 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2473,12 +2473,26 @@ + + + + isa-serial + usb-serial + + + + - - - + + + + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b3a35b737c..d56c333a60 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -342,6 +342,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", @@ -5466,6 +5471,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*/ @@ -5478,7 +5486,8 @@ virDomainChrDefaultTargetType(virCapsPtr caps, static int virDomainChrTargetTypeFromString(virCapsPtr caps, - virDomainDefPtr def, + virDomainDefPtr vmdef, + virDomainChrDefPtr def, int devtype, const char *targetType) { @@ -5486,7 +5495,7 @@ virDomainChrTargetTypeFromString(virCapsPtr caps, int target = 0; if (!targetType) { - target = virDomainChrDefaultTargetType(caps, def, devtype); + target = virDomainChrDefaultTargetType(caps, vmdef, devtype); goto out; } @@ -5500,12 +5509,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->targetTypeAttr = true; + out: ret = target; return ret; @@ -5524,7 +5538,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"), @@ -5957,6 +5971,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); @@ -7960,6 +7983,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; } @@ -13119,6 +13145,15 @@ virDomainChrDefFormat(virBufferPtr buf, def->target.port); break; + case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL: + if (def->targetTypeAttr) { + virBufferAsprintf(buf, + " \n", + virDomainChrTargetTypeToString(def->deviceType, + def->targetType), + def->target.port); + break; + } default: virBufferAsprintf(buf, " \n", def->target.port); @@ -14446,6 +14481,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 4284caf6b3..2ac338c572 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -918,6 +918,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, @@ -1005,6 +1012,8 @@ struct _virDomainChrSourceDef { /* A complete character device, both host and domain views. */ struct _virDomainChrDef { int deviceType; + + bool targetTypeAttr; int targetType; union { int port; /* parallel, serial, console */ @@ -2262,6 +2271,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 d079cc9043..7be58eed9d 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 3e3b58861a..981c69205a 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -7035,10 +7035,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;