mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-30 09:53:10 +00:00
qemu: add usb-serial support
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 chosen 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
This commit is contained in:
parent
f8d478b6df
commit
e3a04455fa
@ -3688,7 +3688,14 @@ qemu-kvm -net nic,model=? /dev/null
|
|||||||
<p>
|
<p>
|
||||||
<code>target</code> can have a <code>port</code> attribute, which
|
<code>target</code> can have a <code>port</code> attribute, which
|
||||||
specifies the port number. Ports are numbered starting from 0. There are
|
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> can tie the device to a particular controller,
|
||||||
|
<a href="#elementsAddress">documented above</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h6><a name="elementCharConsole">Console</a></h6>
|
<h6><a name="elementCharConsole">Console</a></h6>
|
||||||
|
@ -2473,12 +2473,26 @@
|
|||||||
</attribute>
|
</attribute>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
|
<define name='qemucdevSerialTgtType'>
|
||||||
|
<attribute name='type'>
|
||||||
|
<choice>
|
||||||
|
<value>isa-serial</value>
|
||||||
|
<value>usb-serial</value>
|
||||||
|
</choice>
|
||||||
|
</attribute>
|
||||||
|
</define>
|
||||||
|
|
||||||
<define name="qemucdevTgtDef">
|
<define name="qemucdevTgtDef">
|
||||||
<element name="target">
|
<element name="target">
|
||||||
<interleave>
|
<interleave>
|
||||||
|
<choice>
|
||||||
<optional>
|
<optional>
|
||||||
<ref name="qemucdevConsoleTgtType"/>
|
<ref name="qemucdevConsoleTgtType"/>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="qemucdevSerialTgtType"/>
|
||||||
|
</optional>
|
||||||
|
</choice>
|
||||||
<optional>
|
<optional>
|
||||||
<attribute name="port"/>
|
<attribute name="port"/>
|
||||||
</optional>
|
</optional>
|
||||||
|
@ -342,6 +342,11 @@ VIR_ENUM_IMPL(virDomainNetInterfaceLinkState, VIR_DOMAIN_NET_INTERFACE_LINK_STAT
|
|||||||
"up",
|
"up",
|
||||||
"down")
|
"down")
|
||||||
|
|
||||||
|
VIR_ENUM_IMPL(virDomainChrSerialTarget,
|
||||||
|
VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_LAST,
|
||||||
|
"isa-serial",
|
||||||
|
"usb-serial")
|
||||||
|
|
||||||
VIR_ENUM_IMPL(virDomainChrChannelTarget,
|
VIR_ENUM_IMPL(virDomainChrChannelTarget,
|
||||||
VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST,
|
VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST,
|
||||||
"none",
|
"none",
|
||||||
@ -5466,6 +5471,9 @@ virDomainChrDefaultTargetType(virCapsPtr caps,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
|
case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
|
||||||
|
target = VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_ISA;
|
||||||
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
|
case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
|
||||||
default:
|
default:
|
||||||
/* No target type yet*/
|
/* No target type yet*/
|
||||||
@ -5478,7 +5486,8 @@ virDomainChrDefaultTargetType(virCapsPtr caps,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
virDomainChrTargetTypeFromString(virCapsPtr caps,
|
virDomainChrTargetTypeFromString(virCapsPtr caps,
|
||||||
virDomainDefPtr def,
|
virDomainDefPtr vmdef,
|
||||||
|
virDomainChrDefPtr def,
|
||||||
int devtype,
|
int devtype,
|
||||||
const char *targetType)
|
const char *targetType)
|
||||||
{
|
{
|
||||||
@ -5486,7 +5495,7 @@ virDomainChrTargetTypeFromString(virCapsPtr caps,
|
|||||||
int target = 0;
|
int target = 0;
|
||||||
|
|
||||||
if (!targetType) {
|
if (!targetType) {
|
||||||
target = virDomainChrDefaultTargetType(caps, def, devtype);
|
target = virDomainChrDefaultTargetType(caps, vmdef, devtype);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5500,12 +5509,17 @@ virDomainChrTargetTypeFromString(virCapsPtr caps,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
|
case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
|
||||||
|
target = virDomainChrSerialTargetTypeFromString(targetType);
|
||||||
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
|
case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
|
||||||
default:
|
default:
|
||||||
/* No target type yet*/
|
/* No target type yet*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def->targetTypeAttr = true;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
ret = target;
|
ret = target;
|
||||||
return ret;
|
return ret;
|
||||||
@ -5524,7 +5538,7 @@ virDomainChrDefParseTargetXML(virCapsPtr caps,
|
|||||||
const char *portStr = NULL;
|
const char *portStr = NULL;
|
||||||
|
|
||||||
if ((def->targetType =
|
if ((def->targetType =
|
||||||
virDomainChrTargetTypeFromString(caps, vmdef,
|
virDomainChrTargetTypeFromString(caps, vmdef, def,
|
||||||
def->deviceType, targetType)) < 0) {
|
def->deviceType, targetType)) < 0) {
|
||||||
virReportError(VIR_ERR_XML_ERROR,
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
_("unknown target type '%s' specified for character device"),
|
_("unknown target type '%s' specified for character device"),
|
||||||
@ -5957,6 +5971,15 @@ virDomainChrDefParseXML(virCapsPtr caps,
|
|||||||
if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
|
if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
|
||||||
goto error;
|
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:
|
cleanup:
|
||||||
VIR_FREE(type);
|
VIR_FREE(type);
|
||||||
|
|
||||||
@ -7960,6 +7983,9 @@ virDomainChrTargetTypeToString(int deviceType,
|
|||||||
case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
|
case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
|
||||||
type = virDomainChrConsoleTargetTypeToString(targetType);
|
type = virDomainChrConsoleTargetTypeToString(targetType);
|
||||||
break;
|
break;
|
||||||
|
case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
|
||||||
|
type = virDomainChrSerialTargetTypeToString(targetType);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -13119,6 +13145,15 @@ virDomainChrDefFormat(virBufferPtr buf,
|
|||||||
def->target.port);
|
def->target.port);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
|
||||||
|
if (def->targetTypeAttr) {
|
||||||
|
virBufferAsprintf(buf,
|
||||||
|
" <target type='%s' port='%d'/>\n",
|
||||||
|
virDomainChrTargetTypeToString(def->deviceType,
|
||||||
|
def->targetType),
|
||||||
|
def->target.port);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
virBufferAsprintf(buf, " <target port='%d'/>\n",
|
virBufferAsprintf(buf, " <target port='%d'/>\n",
|
||||||
def->target.port);
|
def->target.port);
|
||||||
@ -14446,6 +14481,7 @@ virDomainDefFormatInternal(virDomainDefPtr def,
|
|||||||
(n < def->nserials)) {
|
(n < def->nserials)) {
|
||||||
memcpy(&console, def->serials[n], sizeof(console));
|
memcpy(&console, def->serials[n], sizeof(console));
|
||||||
console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
|
console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
|
||||||
|
console.targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL;
|
||||||
} else {
|
} else {
|
||||||
memcpy(&console, def->consoles[n], sizeof(console));
|
memcpy(&console, def->consoles[n], sizeof(console));
|
||||||
}
|
}
|
||||||
|
@ -918,6 +918,13 @@ enum virDomainChrDeviceType {
|
|||||||
VIR_DOMAIN_CHR_DEVICE_TYPE_LAST
|
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 {
|
enum virDomainChrChannelTargetType {
|
||||||
VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_NONE = 0,
|
VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_NONE = 0,
|
||||||
VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD,
|
VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD,
|
||||||
@ -1005,6 +1012,8 @@ struct _virDomainChrSourceDef {
|
|||||||
/* A complete character device, both host and domain views. */
|
/* A complete character device, both host and domain views. */
|
||||||
struct _virDomainChrDef {
|
struct _virDomainChrDef {
|
||||||
int deviceType;
|
int deviceType;
|
||||||
|
|
||||||
|
bool targetTypeAttr;
|
||||||
int targetType;
|
int targetType;
|
||||||
union {
|
union {
|
||||||
int port; /* parallel, serial, console */
|
int port; /* parallel, serial, console */
|
||||||
@ -2262,6 +2271,7 @@ VIR_ENUM_DECL(virDomainNetInterfaceLinkState)
|
|||||||
VIR_ENUM_DECL(virDomainChrDevice)
|
VIR_ENUM_DECL(virDomainChrDevice)
|
||||||
VIR_ENUM_DECL(virDomainChrChannelTarget)
|
VIR_ENUM_DECL(virDomainChrChannelTarget)
|
||||||
VIR_ENUM_DECL(virDomainChrConsoleTarget)
|
VIR_ENUM_DECL(virDomainChrConsoleTarget)
|
||||||
|
VIR_ENUM_DECL(virDomainChrSerialTarget)
|
||||||
VIR_ENUM_DECL(virDomainSmartcard)
|
VIR_ENUM_DECL(virDomainSmartcard)
|
||||||
VIR_ENUM_DECL(virDomainChr)
|
VIR_ENUM_DECL(virDomainChr)
|
||||||
VIR_ENUM_DECL(virDomainChrTcpProtocol)
|
VIR_ENUM_DECL(virDomainChrTcpProtocol)
|
||||||
|
@ -293,6 +293,8 @@ virDomainChrConsoleTargetTypeToString;
|
|||||||
virDomainChrDefForeach;
|
virDomainChrDefForeach;
|
||||||
virDomainChrDefFree;
|
virDomainChrDefFree;
|
||||||
virDomainChrDefNew;
|
virDomainChrDefNew;
|
||||||
|
virDomainChrSerialTargetTypeFromString;
|
||||||
|
virDomainChrSerialTargetTypeToString;
|
||||||
virDomainChrSourceDefCopy;
|
virDomainChrSourceDefCopy;
|
||||||
virDomainChrSourceDefFree;
|
virDomainChrSourceDefFree;
|
||||||
virDomainChrSpicevmcTypeFromString;
|
virDomainChrSpicevmcTypeFromString;
|
||||||
|
@ -7035,10 +7035,30 @@ qemuBuildChrDeviceStr(virDomainChrDefPtr serial,
|
|||||||
if (qemuBuildDeviceAddressStr(&cmd, &serial->info, caps) < 0)
|
if (qemuBuildDeviceAddressStr(&cmd, &serial->info, caps) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
virBufferAsprintf(&cmd, "isa-serial,chardev=char%s,id=%s",
|
virBufferAsprintf(&cmd, "%s,chardev=char%s,id=%s",
|
||||||
|
virDomainChrSerialTargetTypeToString(serial->targetType),
|
||||||
serial->info.alias, serial->info.alias);
|
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)) {
|
if (virBufferError(&cmd)) {
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
goto error;
|
goto error;
|
||||||
|
Loading…
Reference in New Issue
Block a user