Walk through all the usb controllers in the domain definition
and create the corresponding structures in the virDomainUSBAddressSet.
---
src/conf/domain_addr.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_addr.h | 4 ++
src/libvirt_private.syms | 1 +
3 files changed, 126 insertions(+)
diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
index 658aad5..ea37a42 100644
--- a/src/conf/domain_addr.c
+++ b/src/conf/domain_addr.c
@@ -1326,3 +1326,124 @@ virDomainUSBAddressSetFree(virDomainUSBAddressSetPtr addrs)
VIR_FREE(addrs->buses);
VIR_FREE(addrs);
}
+
+
+static size_t
+virDomainUSBAddressControllerModelToPorts(virDomainControllerDefPtr cont)
+{
+ int model = cont->model;
+
+ if (model == -1)
+ model = VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI;
+
+ switch ((virDomainControllerModelUSB) model) {
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX3_UHCI:
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_PIIX4_UHCI:
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_VT82C686B_UHCI:
+ return 2;
+
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_EHCI:
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_EHCI1:
+ return 6;
+
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI1:
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI2:
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_ICH9_UHCI3:
+ /* These have two ports each and are used to provide USB1.1
+ * ports while ICH9_EHCI1 provides 6 USB2.0 ports.
+ * Ignore these since we will add the EHCI1 too. */
+ return 0;
+
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_PCI_OHCI:
+ return 3;
+
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_NEC_XHCI:
+ if (cont->opts.usbopts.ports != -1)
+ return cont->opts.usbopts.ports;
+ return 4;
+
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE:
+ case VIR_DOMAIN_CONTROLLER_MODEL_USB_LAST:
+ break;
+ }
+ return 0;
+}
+
+
+static virDomainUSBAddressHubPtr
+virDomainUSBAddressHubNew(size_t nports)
+{
+ virDomainUSBAddressHubPtr hub = NULL, ret = NULL;
+
+ if (VIR_ALLOC(hub) < 0)
+ goto cleanup;
+
+ if (!(hub->portmap = virBitmapNew(nports)))
+ goto cleanup;
+
+ if (VIR_ALLOC_N(hub->ports, nports) < 0)
+ goto cleanup;
+ hub->nports = nports;
+
+ ret = hub;
+ hub = NULL;
+ cleanup:
+ virDomainUSBAddressHubFree(hub);
+ return ret;
+}
+
+
+static int
+virDomainUSBAddressSetAddController(virDomainUSBAddressSetPtr addrs,
+ virDomainControllerDefPtr cont)
+{
+ size_t nports = virDomainUSBAddressControllerModelToPorts(cont);
+ virDomainUSBAddressHubPtr hub = NULL;
+ int ret = -1;
+
+ VIR_DEBUG("Adding a USB controller model=%s with %zu ports",
+ virDomainControllerModelUSBTypeToString(cont->model),
+ nports);
+
+ /* Skip UHCI{1,2,3} companions; only add the EHCI1 */
+ if (nports == 0)
+ return 0;
+
+ if (addrs->nbuses <= cont->idx) {
+ if (VIR_EXPAND_N(addrs->buses, addrs->nbuses, cont->idx -
addrs->nbuses + 1) < 0)
+ goto cleanup;
+ } else if (addrs->buses[cont->idx]) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Duplicate USB controllers with index %u"),
+ cont->idx);
+ goto cleanup;
+ }
+
+ if (!(hub = virDomainUSBAddressHubNew(nports)))
+ goto cleanup;
+
+ addrs->buses[cont->idx] = hub;
+ hub = NULL;
+
+ ret = 0;
+ cleanup:
+ virDomainUSBAddressHubFree(hub);
+ return ret;
+}
+
+
+int
+virDomainUSBAddressSetAddControllers(virDomainUSBAddressSetPtr addrs,
+ virDomainDefPtr def)
+{
+ size_t i;
+
+ for (i = 0; i < def->ncontrollers; i++) {
+ virDomainControllerDefPtr cont = def->controllers[i];
+ if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_USB) {
+ if (virDomainUSBAddressSetAddController(addrs, cont) < 0)
+ return -1;
+ }
+ }
+ return 0;
+}
diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
index 168d3ed..2bd4a0d 100644
--- a/src/conf/domain_addr.h
+++ b/src/conf/domain_addr.h
@@ -269,6 +269,10 @@ typedef struct _virDomainUSBAddressSet virDomainUSBAddressSet;
typedef virDomainUSBAddressSet *virDomainUSBAddressSetPtr;
virDomainUSBAddressSetPtr virDomainUSBAddressSetCreate(void);
+
+int virDomainUSBAddressSetAddControllers(virDomainUSBAddressSetPtr addrs,
+ virDomainDefPtr def)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
void virDomainUSBAddressSetFree(virDomainUSBAddressSetPtr addrs);
#endif /* __DOMAIN_ADDR_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 089b66b..62d63f4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -110,6 +110,7 @@ virDomainPCIControllerModelToConnectType;
virDomainUSBAddressPortFormat;
virDomainUSBAddressPortFormatBuf;
virDomainUSBAddressPortIsValid;
+virDomainUSBAddressSetAddControllers;
virDomainUSBAddressSetCreate;
virDomainUSBAddressSetFree;
virDomainVirtioSerialAddrAssign;
--
2.7.3