提交 815d98ac 编写于 作者: J Ján Tomko

Auto-add one hub if there are too many USB devices

When parsing a command line with USB devices that have
no address specified, QEMU automatically adds a USB hub
if the device would fill up all the available USB ports.

To help most of the users, add one hub if there are more
USB devices than available ports. For wilder configurations,
expect the user to provide us with more hubs and/or controllers.
上级 f2a781ce
......@@ -1604,6 +1604,26 @@ virDomainUSBAddressFindFreePort(virDomainUSBAddressHubPtr hub,
}
size_t
virDomainUSBAddressCountAllPorts(virDomainDefPtr def)
{
size_t i, ret = 0;
for (i = 0; i < def->ncontrollers; i++) {
virDomainControllerDefPtr cont = def->controllers[i];
if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB)
ret += virDomainUSBAddressControllerModelToPorts(cont);
}
for (i = 0; i < def->nhubs; i++) {
virDomainHubDefPtr hub = def->hubs[i];
if (hub->type == VIR_DOMAIN_HUB_TYPE_USB)
ret += VIR_DOMAIN_USB_HUB_PORTS;
}
return ret;
}
/* Try to find a free port on bus @bus.
*
* Returns 0 on success
......
......@@ -277,6 +277,8 @@ int
virDomainUSBAddressSetAddHub(virDomainUSBAddressSetPtr addrs,
virDomainHubDefPtr hub)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
size_t
virDomainUSBAddressCountAllPorts(virDomainDefPtr def);
void virDomainUSBAddressSetFree(virDomainUSBAddressSetPtr addrs);
int
......
......@@ -108,6 +108,7 @@ virDomainPCIAddressSlotInUse;
virDomainPCIAddressValidate;
virDomainPCIControllerModelToConnectType;
virDomainUSBAddressAssign;
virDomainUSBAddressCountAllPorts;
virDomainUSBAddressEnsure;
virDomainUSBAddressPortFormat;
virDomainUSBAddressPortFormatBuf;
......
......@@ -1679,6 +1679,51 @@ qemuDomainAssignUSBPorts(virDomainUSBAddressSetPtr addrs,
}
static int
qemuDomainAssignUSBPortsCounter(virDomainDeviceInfoPtr info ATTRIBUTE_UNUSED,
void *opaque)
{
struct qemuAssignUSBIteratorInfo *data = opaque;
data->count++;
return 0;
}
static int
qemuDomainUSBAddressAddHubs(virDomainDefPtr def)
{
struct qemuAssignUSBIteratorInfo data = { .count = 0 };
virDomainHubDefPtr hub = NULL;
size_t available_ports;
int ret = -1;
available_ports = virDomainUSBAddressCountAllPorts(def);
ignore_value(virDomainUSBDeviceDefForeach(def,
qemuDomainAssignUSBPortsCounter,
&data,
false));
VIR_DEBUG("Found %zu USB devices and %zu provided USB ports",
data.count, available_ports);
/* Add one hub if there are more devices than ports
* otherwise it's up to the user to specify more hubs/controllers */
if (data.count > available_ports) {
if (VIR_ALLOC(hub) < 0)
return -1;
hub->type = VIR_DOMAIN_HUB_TYPE_USB;
if (VIR_APPEND_ELEMENT(def->hubs, def->nhubs, hub) < 0)
goto cleanup;
}
ret = 0;
cleanup:
VIR_FREE(hub);
return ret;
}
static int
qemuDomainAssignUSBAddresses(virDomainDefPtr def,
virDomainObjPtr obj)
......@@ -1690,6 +1735,9 @@ qemuDomainAssignUSBAddresses(virDomainDefPtr def,
if (!(addrs = virDomainUSBAddressSetCreate()))
goto cleanup;
if (qemuDomainUSBAddressAddHubs(def) < 0)
goto cleanup;
if (virDomainUSBAddressSetAddControllers(addrs, def) < 0)
goto cleanup;
......
LC_ALL=C \
PATH=/bin \
HOME=/home/test \
USER=test \
LOGNAME=test \
QEMU_AUDIO_DRV=none \
/usr/bin/qemu \
-name QEMUGuest1 \
-S \
-M pc \
-m 214 \
-smp 1,sockets=1,cores=1,threads=1 \
-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
-nographic \
-nodefconfig \
-nodefaults \
-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
server,nowait \
-mon chardev=charmonitor,id=monitor,mode=readline \
-no-acpi \
-boot c \
-usb \
-device usb-hub,id=hub0,bus=usb.0,port=1 \
-device usb-mouse,id=input0,bus=usb.0,port=2 \
-device usb-mouse,id=input1,bus=usb.0,port=1.1 \
-device usb-mouse,id=input2,bus=usb.0,port=1.2 \
-device usb-tablet,id=input3,bus=usb.0,port=1.3 \
-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>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'/>
<memballoon model='virtio'/>
<input type='mouse' bus='usb'>
</input>
<input type='mouse' bus='usb'>
</input>
<input type='mouse' bus='usb'>
</input>
<input type='tablet' bus='usb'/>
</devices>
</domain>
......@@ -1184,6 +1184,9 @@ mymain(void)
DO_TEST("usb-hub",
QEMU_CAPS_CHARDEV, QEMU_CAPS_USB_HUB,
QEMU_CAPS_NODEFCONFIG);
DO_TEST("usb-hub-autoadd",
QEMU_CAPS_CHARDEV, QEMU_CAPS_USB_HUB,
QEMU_CAPS_NODEFCONFIG);
DO_TEST_PARSE_ERROR("usb-hub-conflict",
QEMU_CAPS_CHARDEV, QEMU_CAPS_USB_HUB,
QEMU_CAPS_NODEFCONFIG);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册