mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-11-03 20:01:16 +00:00
Add USB companion controllers support
Companion controllers take an extra 'master' attribute to associate them. Also add tests for this
This commit is contained in:
parent
22c0d433ab
commit
f3ce59621f
@ -1245,6 +1245,28 @@
|
|||||||
sub-element.
|
sub-element.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
USB companion controllers have an optional
|
||||||
|
sub-element <code><master></code> to specify the exact
|
||||||
|
relationship of the companion to its master controller.
|
||||||
|
A companion controller is on the same bus as its master, so
|
||||||
|
the companion <code>index</code> value should be equal.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
...
|
||||||
|
<devices>
|
||||||
|
<controller type='usb' index='0' model='ich9-ehci1'>
|
||||||
|
<address type='pci' domain='0' bus='0' slot='4' function='7'/>
|
||||||
|
</controller>
|
||||||
|
<controller type='usb' index='0' model='ich9-uhci1'>
|
||||||
|
<master startport='0'/>
|
||||||
|
<address type='pci' domain='0' bus='0' slot='4' function='0'/>
|
||||||
|
</controller>
|
||||||
|
...
|
||||||
|
</devices>
|
||||||
|
...</pre>
|
||||||
|
|
||||||
<h4><a name="elementsLease">Device leases</a></h4>
|
<h4><a name="elementsLease">Device leases</a></h4>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -923,6 +923,9 @@
|
|||||||
</choice>
|
</choice>
|
||||||
</attribute>
|
</attribute>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="usbmaster"/>
|
||||||
|
</optional>
|
||||||
<optional>
|
<optional>
|
||||||
<ref name="address"/>
|
<ref name="address"/>
|
||||||
</optional>
|
</optional>
|
||||||
@ -2379,6 +2382,15 @@
|
|||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
|
<define name="usbmaster">
|
||||||
|
<element name="master">
|
||||||
|
<attribute name="startport">
|
||||||
|
<ref name="usbAddr"/>
|
||||||
|
</attribute>
|
||||||
|
<empty/>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
<define name="filterref-node-attributes">
|
<define name="filterref-node-attributes">
|
||||||
<attribute name="filter">
|
<attribute name="filter">
|
||||||
<data type="NCName"/>
|
<data type="NCName"/>
|
||||||
|
@ -1556,6 +1556,11 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
|
|||||||
virBufferAsprintf(buf, " <alias name='%s'/>\n", info->alias);
|
virBufferAsprintf(buf, " <alias name='%s'/>\n", info->alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info->mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB) {
|
||||||
|
virBufferAsprintf(buf, " <master startport='%d'/>\n",
|
||||||
|
info->master.usb.startport);
|
||||||
|
}
|
||||||
|
|
||||||
if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
|
if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1833,6 +1838,31 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainDeviceUSBMasterParseXML(xmlNodePtr node,
|
||||||
|
virDomainDeviceUSBMasterPtr master)
|
||||||
|
{
|
||||||
|
char *startport;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
memset(master, 0, sizeof(*master));
|
||||||
|
|
||||||
|
startport = virXMLPropString(node, "startport");
|
||||||
|
|
||||||
|
if (startport &&
|
||||||
|
virStrToLong_ui(startport, NULL, 10, &master->startport) < 0) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Cannot parse <master> 'startport' attribute"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(startport);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse the XML definition for a device address
|
/* Parse the XML definition for a device address
|
||||||
* @param node XML nodeset to parse for device address definition
|
* @param node XML nodeset to parse for device address definition
|
||||||
*/
|
*/
|
||||||
@ -1843,6 +1873,7 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
|
|||||||
{
|
{
|
||||||
xmlNodePtr cur;
|
xmlNodePtr cur;
|
||||||
xmlNodePtr address = NULL;
|
xmlNodePtr address = NULL;
|
||||||
|
xmlNodePtr master = NULL;
|
||||||
xmlNodePtr alias = NULL;
|
xmlNodePtr alias = NULL;
|
||||||
char *type = NULL;
|
char *type = NULL;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@ -1859,6 +1890,9 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
|
|||||||
} else if (address == NULL &&
|
} else if (address == NULL &&
|
||||||
xmlStrEqual(cur->name, BAD_CAST "address")) {
|
xmlStrEqual(cur->name, BAD_CAST "address")) {
|
||||||
address = cur;
|
address = cur;
|
||||||
|
} else if (master == NULL &&
|
||||||
|
xmlStrEqual(cur->name, BAD_CAST "master")) {
|
||||||
|
master = cur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
@ -1867,6 +1901,12 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
|
|||||||
if (alias)
|
if (alias)
|
||||||
info->alias = virXMLPropString(alias, "name");
|
info->alias = virXMLPropString(alias, "name");
|
||||||
|
|
||||||
|
if (master) {
|
||||||
|
info->mastertype = VIR_DOMAIN_CONTROLLER_MASTER_USB;
|
||||||
|
if (virDomainDeviceUSBMasterParseXML(master, &info->master.usb) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if (!address)
|
if (!address)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -113,6 +113,19 @@ struct _virDomainDeviceUSBAddress {
|
|||||||
unsigned int port;
|
unsigned int port;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum virDomainControllerMaster {
|
||||||
|
VIR_DOMAIN_CONTROLLER_MASTER_NONE,
|
||||||
|
VIR_DOMAIN_CONTROLLER_MASTER_USB,
|
||||||
|
|
||||||
|
VIR_DOMAIN_CONTROLLER_MASTER_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _virDomainDeviceUSBMaster virDomainDeviceUSBMaster;
|
||||||
|
typedef virDomainDeviceUSBMaster *virDomainDeviceUSBMasterPtr;
|
||||||
|
struct _virDomainDeviceUSBMaster {
|
||||||
|
unsigned int startport;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct _virDomainDeviceInfo virDomainDeviceInfo;
|
typedef struct _virDomainDeviceInfo virDomainDeviceInfo;
|
||||||
typedef virDomainDeviceInfo *virDomainDeviceInfoPtr;
|
typedef virDomainDeviceInfo *virDomainDeviceInfoPtr;
|
||||||
struct _virDomainDeviceInfo {
|
struct _virDomainDeviceInfo {
|
||||||
@ -125,6 +138,10 @@ struct _virDomainDeviceInfo {
|
|||||||
virDomainDeviceCcidAddress ccid;
|
virDomainDeviceCcidAddress ccid;
|
||||||
virDomainDeviceUSBAddress usb;
|
virDomainDeviceUSBAddress usb;
|
||||||
} addr;
|
} addr;
|
||||||
|
int mastertype;
|
||||||
|
union {
|
||||||
|
virDomainDeviceUSBMaster usb;
|
||||||
|
} master;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _virDomainLeaseDef virDomainLeaseDef;
|
typedef struct _virDomainLeaseDef virDomainLeaseDef;
|
||||||
|
@ -1767,7 +1767,16 @@ qemuBuildUSBControllerDevStr(virDomainControllerDefPtr def,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
virBufferAsprintf(buf, "%s,id=usb%d", smodel, def->idx);
|
virBufferAsprintf(buf, "%s", smodel);
|
||||||
|
|
||||||
|
if (def->info.mastertype == VIR_DOMAIN_CONTROLLER_MASTER_USB) {
|
||||||
|
virBufferAsprintf(buf, ",masterbus=usb%d.0", def->idx);
|
||||||
|
virBufferAsprintf(buf, ",firstport=%d", def->info.master.usb.startport);
|
||||||
|
} else {
|
||||||
|
virBufferAsprintf(buf, ",id=usb%d", def->idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c \
|
||||||
|
-device ich9-usb-ehci1,id=usb0,bus=pci.0,multifunction=on,addr=0x4.0x7 \
|
||||||
|
-device ich9-usb-uhci1,masterbus=usb0.0,firstport=0,bus=pci.0,multifunction=on,addr=0x4.0x0 \
|
||||||
|
-device ich9-usb-uhci2,masterbus=usb0.0,firstport=2,bus=pci.0,multifunction=on,addr=0x4.0x1 \
|
||||||
|
-device ich9-usb-uhci3,masterbus=usb0.0,firstport=4,bus=pci.0,multifunction=on,addr=0x4.0x2 \
|
||||||
|
-device virtio-balloon-pci,id=balloon0,bus=pci.0,multifunction=on,addr=0x3.0x0
|
30
tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml
Normal file
30
tests/qemuxml2argvdata/qemuxml2argv-usb-ich9-companion.xml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<domain type='qemu'>
|
||||||
|
<name>QEMUGuest1</name>
|
||||||
|
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||||
|
<memory>219136</memory>
|
||||||
|
<currentMemory>219200</currentMemory>
|
||||||
|
<vcpu>1</vcpu>
|
||||||
|
<os>
|
||||||
|
<type arch='i686' machine='pc'>hvm</type>
|
||||||
|
<boot dev='hd'/>
|
||||||
|
</os>
|
||||||
|
<devices>
|
||||||
|
<emulator>/usr/bin/qemu</emulator>
|
||||||
|
<controller type='usb' index='0' model='ich9-ehci1'>
|
||||||
|
<address type='pci' domain='0' bus='0' slot='4' function='7'/>
|
||||||
|
</controller>
|
||||||
|
<controller type='usb' index='0' model='ich9-uhci1'>
|
||||||
|
<master startport='0'/>
|
||||||
|
<address type='pci' domain='0' bus='0' slot='4' function='0'/>
|
||||||
|
</controller>
|
||||||
|
<controller type='usb' index='0' model='ich9-uhci2'>
|
||||||
|
<master startport='2'/>
|
||||||
|
<address type='pci' domain='0' bus='0' slot='4' function='1'/>
|
||||||
|
</controller>
|
||||||
|
<controller type='usb' index='0' model='ich9-uhci3'>
|
||||||
|
<master startport='4'/>
|
||||||
|
<address type='pci' domain='0' bus='0' slot='4' function='2'/>
|
||||||
|
</controller>
|
||||||
|
<memballoon model='virtio'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
@ -498,6 +498,9 @@ mymain(void)
|
|||||||
QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1);
|
QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1);
|
||||||
DO_TEST("input-usbmouse-addr", false,
|
DO_TEST("input-usbmouse-addr", false,
|
||||||
QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
|
QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
|
||||||
|
DO_TEST("usb-ich9-companion", false,
|
||||||
|
QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
|
||||||
|
QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1);
|
||||||
|
|
||||||
DO_TEST("smbios", false, QEMU_CAPS_SMBIOS_TYPE);
|
DO_TEST("smbios", false, QEMU_CAPS_SMBIOS_TYPE);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user