mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-08-28 11:31:16 +00:00
Add USB hub device
domain parsing and serialization code, qemu driver backend and a couple of test
This commit is contained in:
parent
f3ce59621f
commit
fdabeb3c5f
@ -2086,6 +2086,33 @@ qemu-kvm -net nic,model=? /dev/null
|
|||||||
device to a particular PCI slot.
|
device to a particular PCI slot.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h4><a name="elementsHub">Hub devices</a></h4>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A hub is a device that expands a single port into several so
|
||||||
|
that there are more ports available to connect devices to a host
|
||||||
|
system.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
...
|
||||||
|
<devices>
|
||||||
|
<hub type='usb'/>
|
||||||
|
</devices>
|
||||||
|
...</pre>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><code>hub</code></dt>
|
||||||
|
<dd>The <code>hub</code> element has one mandatory attribute,
|
||||||
|
the <code>type</code> whose value can only be 'usb'.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The <code>hub</code> element has an optional
|
||||||
|
sub-element <code><address></code> which can tie the
|
||||||
|
device to a particular controller.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h4><a name="elementsGraphics">Graphical framebuffers</a></h4>
|
<h4><a name="elementsGraphics">Graphical framebuffers</a></h4>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -1963,6 +1963,18 @@
|
|||||||
</optional>
|
</optional>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
<define name="hub">
|
||||||
|
<element name="hub">
|
||||||
|
<attribute name="type">
|
||||||
|
<choice>
|
||||||
|
<value>usb</value>
|
||||||
|
</choice>
|
||||||
|
</attribute>
|
||||||
|
<optional>
|
||||||
|
<ref name="address"/>
|
||||||
|
</optional>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
<define name="hostdev">
|
<define name="hostdev">
|
||||||
<element name="hostdev">
|
<element name="hostdev">
|
||||||
<optional>
|
<optional>
|
||||||
@ -2126,6 +2138,7 @@
|
|||||||
<ref name="serial"/>
|
<ref name="serial"/>
|
||||||
<ref name="channel"/>
|
<ref name="channel"/>
|
||||||
<ref name="smartcard"/>
|
<ref name="smartcard"/>
|
||||||
|
<ref name="hub"/>
|
||||||
</choice>
|
</choice>
|
||||||
</zeroOrMore>
|
</zeroOrMore>
|
||||||
<optional>
|
<optional>
|
||||||
|
@ -126,7 +126,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
|
|||||||
"hostdev",
|
"hostdev",
|
||||||
"watchdog",
|
"watchdog",
|
||||||
"controller",
|
"controller",
|
||||||
"graphics")
|
"graphics",
|
||||||
|
"hub")
|
||||||
|
|
||||||
VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
|
VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
|
||||||
"none",
|
"none",
|
||||||
@ -437,6 +438,9 @@ VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN_CRASHED+1,
|
|||||||
"shutoff",
|
"shutoff",
|
||||||
"crashed")
|
"crashed")
|
||||||
|
|
||||||
|
VIR_ENUM_IMPL(virDomainHub, VIR_DOMAIN_HUB_TYPE_LAST,
|
||||||
|
"usb")
|
||||||
|
|
||||||
#define VIR_DOMAIN_NOSTATE_LAST (VIR_DOMAIN_NOSTATE_UNKNOWN + 1)
|
#define VIR_DOMAIN_NOSTATE_LAST (VIR_DOMAIN_NOSTATE_UNKNOWN + 1)
|
||||||
VIR_ENUM_IMPL(virDomainNostateReason, VIR_DOMAIN_NOSTATE_LAST,
|
VIR_ENUM_IMPL(virDomainNostateReason, VIR_DOMAIN_NOSTATE_LAST,
|
||||||
"unknown")
|
"unknown")
|
||||||
@ -1000,6 +1004,15 @@ void virDomainHostdevDefFree(virDomainHostdevDefPtr def)
|
|||||||
VIR_FREE(def);
|
VIR_FREE(def);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void virDomainHubDefFree(virDomainHubDefPtr def)
|
||||||
|
{
|
||||||
|
if (!def)
|
||||||
|
return;
|
||||||
|
|
||||||
|
virDomainDeviceInfoClear(&def->info);
|
||||||
|
VIR_FREE(def);
|
||||||
|
}
|
||||||
|
|
||||||
void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
|
void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
|
||||||
{
|
{
|
||||||
if (!def)
|
if (!def)
|
||||||
@ -1036,6 +1049,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
|
|||||||
case VIR_DOMAIN_DEVICE_GRAPHICS:
|
case VIR_DOMAIN_DEVICE_GRAPHICS:
|
||||||
virDomainGraphicsDefFree(def->data.graphics);
|
virDomainGraphicsDefFree(def->data.graphics);
|
||||||
break;
|
break;
|
||||||
|
case VIR_DOMAIN_DEVICE_HUB:
|
||||||
|
virDomainHubDefFree(def->data.hub);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
VIR_FREE(def);
|
VIR_FREE(def);
|
||||||
@ -1145,6 +1161,10 @@ void virDomainDefFree(virDomainDefPtr def)
|
|||||||
virDomainHostdevDefFree(def->hostdevs[i]);
|
virDomainHostdevDefFree(def->hostdevs[i]);
|
||||||
VIR_FREE(def->hostdevs);
|
VIR_FREE(def->hostdevs);
|
||||||
|
|
||||||
|
for (i = 0 ; i < def->nhubs ; i++)
|
||||||
|
virDomainHubDefFree(def->hubs[i]);
|
||||||
|
VIR_FREE(def->hubs);
|
||||||
|
|
||||||
VIR_FREE(def->os.type);
|
VIR_FREE(def->os.type);
|
||||||
VIR_FREE(def->os.arch);
|
VIR_FREE(def->os.arch);
|
||||||
VIR_FREE(def->os.machine);
|
VIR_FREE(def->os.machine);
|
||||||
@ -1528,6 +1548,9 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def,
|
|||||||
if (def->console)
|
if (def->console)
|
||||||
if (cb(def, &def->console->info, opaque) < 0)
|
if (cb(def, &def->console->info, opaque) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
for (i = 0; i < def->nhubs ; i++)
|
||||||
|
if (cb(def, &def->hubs[i]->info, opaque) < 0)
|
||||||
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1597,6 +1620,12 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
|
|||||||
info->addr.ccid.slot);
|
info->addr.ccid.slot);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB:
|
||||||
|
virBufferAsprintf(buf, " bus='%d' port='%d'",
|
||||||
|
info->addr.usb.bus,
|
||||||
|
info->addr.usb.port);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
_("unknown address type '%d'"), info->type);
|
_("unknown address type '%d'"), info->type);
|
||||||
@ -3996,6 +4025,47 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Parse the XML definition for an hub device */
|
||||||
|
static virDomainHubDefPtr
|
||||||
|
virDomainHubDefParseXML(xmlNodePtr node, unsigned int flags)
|
||||||
|
{
|
||||||
|
virDomainHubDefPtr def;
|
||||||
|
char *type = NULL;
|
||||||
|
|
||||||
|
if (VIR_ALLOC(def) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = virXMLPropString(node, "type");
|
||||||
|
|
||||||
|
if (!type) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
"%s", _("missing hub device type"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((def->type = virDomainHubTypeFromString(type)) < 0) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("unknown hub device type '%s'"), type);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virDomainDeviceInfoParseXML(node, &def->info, flags) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(type);
|
||||||
|
|
||||||
|
return def;
|
||||||
|
|
||||||
|
error:
|
||||||
|
virDomainHubDefFree(def);
|
||||||
|
def = NULL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Parse the XML definition for a clock timer */
|
/* Parse the XML definition for a clock timer */
|
||||||
static virDomainTimerDefPtr
|
static virDomainTimerDefPtr
|
||||||
virDomainTimerDefParseXML(const xmlNodePtr node,
|
virDomainTimerDefParseXML(const xmlNodePtr node,
|
||||||
@ -5568,6 +5638,10 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps,
|
|||||||
dev->type = VIR_DOMAIN_DEVICE_GRAPHICS;
|
dev->type = VIR_DOMAIN_DEVICE_GRAPHICS;
|
||||||
if (!(dev->data.graphics = virDomainGraphicsDefParseXML(node, ctxt, flags)))
|
if (!(dev->data.graphics = virDomainGraphicsDefParseXML(node, ctxt, flags)))
|
||||||
goto error;
|
goto error;
|
||||||
|
} else if (xmlStrEqual(node->name, BAD_CAST "hub")) {
|
||||||
|
dev->type = VIR_DOMAIN_DEVICE_HUB;
|
||||||
|
if (!(dev->data.hub = virDomainHubDefParseXML(node, flags)))
|
||||||
|
goto error;
|
||||||
} else {
|
} else {
|
||||||
virDomainReportError(VIR_ERR_XML_ERROR,
|
virDomainReportError(VIR_ERR_XML_ERROR,
|
||||||
"%s", _("unknown device type"));
|
"%s", _("unknown device type"));
|
||||||
@ -6972,6 +7046,21 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* analysis of the hub devices */
|
||||||
|
if ((n = virXPathNodeSet("./devices/hub", ctxt, &nodes)) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (n && VIR_ALLOC_N(def->hubs, n) < 0)
|
||||||
|
goto no_memory;
|
||||||
|
for (i = 0 ; i < n ; i++) {
|
||||||
|
virDomainHubDefPtr hub = virDomainHubDefParseXML(nodes[i], flags);
|
||||||
|
if (!hub)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
def->hubs[def->nhubs++] = hub;
|
||||||
|
}
|
||||||
|
VIR_FREE(nodes);
|
||||||
|
|
||||||
/* analysis of security label */
|
/* analysis of security label */
|
||||||
if (virSecurityLabelDefParseXML(def, ctxt, flags) == -1)
|
if (virSecurityLabelDefParseXML(def, ctxt, flags) == -1)
|
||||||
goto error;
|
goto error;
|
||||||
@ -7882,6 +7971,29 @@ cleanup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool virDomainHubDefCheckABIStability(virDomainHubDefPtr src,
|
||||||
|
virDomainHubDefPtr dst)
|
||||||
|
{
|
||||||
|
bool identical = false;
|
||||||
|
|
||||||
|
if (src->type != dst->type) {
|
||||||
|
virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("Target hub device type %s does not match source %s"),
|
||||||
|
virDomainHubTypeToString(dst->type),
|
||||||
|
virDomainHubTypeToString(src->type));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
identical = true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
return identical;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This compares two configurations and looks for any differences
|
/* This compares two configurations and looks for any differences
|
||||||
* which will affect the guest ABI. This is primarily to allow
|
* which will affect the guest ABI. This is primarily to allow
|
||||||
* validation of custom XML config passed in during migration
|
* validation of custom XML config passed in during migration
|
||||||
@ -8115,6 +8227,17 @@ bool virDomainDefCheckABIStability(virDomainDefPtr src,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (src->nhubs != dst->nhubs) {
|
||||||
|
virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("Target domain hub device count %d does not match source %d"),
|
||||||
|
dst->nhubs, src->nhubs);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0 ; i < src->nhubs ; i++)
|
||||||
|
if (!virDomainHubDefCheckABIStability(src->hubs[i], dst->hubs[i]))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if (src->console &&
|
if (src->console &&
|
||||||
!virDomainConsoleDefCheckABIStability(src->console, dst->console))
|
!virDomainConsoleDefCheckABIStability(src->console, dst->console))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -10028,6 +10151,34 @@ virDomainHostdevDefFormat(virBufferPtr buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainHubDefFormat(virBufferPtr buf,
|
||||||
|
virDomainHubDefPtr def,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
const char *type = virDomainHubTypeToString(def->type);
|
||||||
|
|
||||||
|
if (!type) {
|
||||||
|
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("unexpected hub type %d"), def->type);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virBufferAsprintf(buf, " <hub type='%s'", type);
|
||||||
|
|
||||||
|
if (virDomainDeviceInfoIsSet(&def->info, flags)) {
|
||||||
|
virBufferAddLit(buf, ">\n");
|
||||||
|
if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0)
|
||||||
|
return -1;
|
||||||
|
virBufferAddLit(buf, " </hub>\n");
|
||||||
|
} else {
|
||||||
|
virBufferAddLit(buf, "/>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define DUMPXML_FLAGS \
|
#define DUMPXML_FLAGS \
|
||||||
(VIR_DOMAIN_XML_SECURE | \
|
(VIR_DOMAIN_XML_SECURE | \
|
||||||
VIR_DOMAIN_XML_INACTIVE | \
|
VIR_DOMAIN_XML_INACTIVE | \
|
||||||
@ -10433,6 +10584,10 @@ virDomainDefFormatInternal(virDomainDefPtr def,
|
|||||||
if (virDomainHostdevDefFormat(&buf, def->hostdevs[n], flags) < 0)
|
if (virDomainHostdevDefFormat(&buf, def->hostdevs[n], flags) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
for (n = 0 ; n < def->nhubs ; n++)
|
||||||
|
if (virDomainHubDefFormat(&buf, def->hubs[n], flags) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if (def->watchdog)
|
if (def->watchdog)
|
||||||
virDomainWatchdogDefFormat (&buf, def->watchdog, flags);
|
virDomainWatchdogDefFormat (&buf, def->watchdog, flags);
|
||||||
|
|
||||||
|
@ -616,6 +616,13 @@ struct _virDomainSmartcardDef {
|
|||||||
virDomainDeviceInfo info;
|
virDomainDeviceInfo info;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _virDomainHubDef virDomainHubDef;
|
||||||
|
typedef virDomainHubDef *virDomainHubDefPtr;
|
||||||
|
struct _virDomainHubDef {
|
||||||
|
int type;
|
||||||
|
virDomainDeviceInfo info;
|
||||||
|
};
|
||||||
|
|
||||||
enum virDomainInputType {
|
enum virDomainInputType {
|
||||||
VIR_DOMAIN_INPUT_TYPE_MOUSE,
|
VIR_DOMAIN_INPUT_TYPE_MOUSE,
|
||||||
VIR_DOMAIN_INPUT_TYPE_TABLET,
|
VIR_DOMAIN_INPUT_TYPE_TABLET,
|
||||||
@ -825,6 +832,12 @@ enum virDomainGraphicsListenType {
|
|||||||
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST,
|
VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_LAST,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum virDomainHubType {
|
||||||
|
VIR_DOMAIN_HUB_TYPE_USB,
|
||||||
|
|
||||||
|
VIR_DOMAIN_HUB_TYPE_LAST,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct _virDomainGraphicsListenDef virDomainGraphicsListenDef;
|
typedef struct _virDomainGraphicsListenDef virDomainGraphicsListenDef;
|
||||||
typedef virDomainGraphicsListenDef *virDomainGraphicsListenDefPtr;
|
typedef virDomainGraphicsListenDef *virDomainGraphicsListenDefPtr;
|
||||||
struct _virDomainGraphicsListenDef {
|
struct _virDomainGraphicsListenDef {
|
||||||
@ -965,6 +978,7 @@ enum virDomainDeviceType {
|
|||||||
VIR_DOMAIN_DEVICE_WATCHDOG,
|
VIR_DOMAIN_DEVICE_WATCHDOG,
|
||||||
VIR_DOMAIN_DEVICE_CONTROLLER,
|
VIR_DOMAIN_DEVICE_CONTROLLER,
|
||||||
VIR_DOMAIN_DEVICE_GRAPHICS,
|
VIR_DOMAIN_DEVICE_GRAPHICS,
|
||||||
|
VIR_DOMAIN_DEVICE_HUB,
|
||||||
|
|
||||||
VIR_DOMAIN_DEVICE_LAST,
|
VIR_DOMAIN_DEVICE_LAST,
|
||||||
};
|
};
|
||||||
@ -985,6 +999,7 @@ struct _virDomainDeviceDef {
|
|||||||
virDomainHostdevDefPtr hostdev;
|
virDomainHostdevDefPtr hostdev;
|
||||||
virDomainWatchdogDefPtr watchdog;
|
virDomainWatchdogDefPtr watchdog;
|
||||||
virDomainGraphicsDefPtr graphics;
|
virDomainGraphicsDefPtr graphics;
|
||||||
|
virDomainHubDefPtr hub;
|
||||||
} data;
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1312,6 +1327,9 @@ struct _virDomainDef {
|
|||||||
size_t nleases;
|
size_t nleases;
|
||||||
virDomainLeaseDefPtr *leases;
|
virDomainLeaseDefPtr *leases;
|
||||||
|
|
||||||
|
int nhubs;
|
||||||
|
virDomainHubDefPtr *hubs;
|
||||||
|
|
||||||
/* Only 1 */
|
/* Only 1 */
|
||||||
virDomainChrDefPtr console;
|
virDomainChrDefPtr console;
|
||||||
virSecurityLabelDef seclabel;
|
virSecurityLabelDef seclabel;
|
||||||
@ -1460,6 +1478,7 @@ void virDomainMemballoonDefFree(virDomainMemballoonDefPtr def);
|
|||||||
void virDomainWatchdogDefFree(virDomainWatchdogDefPtr def);
|
void virDomainWatchdogDefFree(virDomainWatchdogDefPtr def);
|
||||||
void virDomainVideoDefFree(virDomainVideoDefPtr def);
|
void virDomainVideoDefFree(virDomainVideoDefPtr def);
|
||||||
void virDomainHostdevDefFree(virDomainHostdevDefPtr def);
|
void virDomainHostdevDefFree(virDomainHostdevDefPtr def);
|
||||||
|
void virDomainHubDefFree(virDomainHubDefPtr def);
|
||||||
void virDomainDeviceDefFree(virDomainDeviceDefPtr def);
|
void virDomainDeviceDefFree(virDomainDeviceDefPtr def);
|
||||||
int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
|
int virDomainDeviceAddressIsValid(virDomainDeviceInfoPtr info,
|
||||||
int type);
|
int type);
|
||||||
@ -1740,6 +1759,7 @@ VIR_ENUM_DECL(virDomainWatchdogAction)
|
|||||||
VIR_ENUM_DECL(virDomainVideo)
|
VIR_ENUM_DECL(virDomainVideo)
|
||||||
VIR_ENUM_DECL(virDomainHostdevMode)
|
VIR_ENUM_DECL(virDomainHostdevMode)
|
||||||
VIR_ENUM_DECL(virDomainHostdevSubsys)
|
VIR_ENUM_DECL(virDomainHostdevSubsys)
|
||||||
|
VIR_ENUM_DECL(virDomainHub)
|
||||||
VIR_ENUM_DECL(virDomainInput)
|
VIR_ENUM_DECL(virDomainInput)
|
||||||
VIR_ENUM_DECL(virDomainInputBus)
|
VIR_ENUM_DECL(virDomainInputBus)
|
||||||
VIR_ENUM_DECL(virDomainGraphics)
|
VIR_ENUM_DECL(virDomainGraphics)
|
||||||
|
@ -327,6 +327,8 @@ virDomainGraphicsTypeToString;
|
|||||||
virDomainHostdevDefFree;
|
virDomainHostdevDefFree;
|
||||||
virDomainHostdevModeTypeToString;
|
virDomainHostdevModeTypeToString;
|
||||||
virDomainHostdevSubsysTypeToString;
|
virDomainHostdevSubsysTypeToString;
|
||||||
|
virDomainHubTypeFromString;
|
||||||
|
virDomainHubTypeToString;
|
||||||
virDomainInputDefFree;
|
virDomainInputDefFree;
|
||||||
virDomainIoEventFdTypeFromString;
|
virDomainIoEventFdTypeFromString;
|
||||||
virDomainIoEventFdTypeToString;
|
virDomainIoEventFdTypeToString;
|
||||||
|
@ -135,6 +135,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
|
|||||||
"vt82c686b-usb-uhci", /* 70 */
|
"vt82c686b-usb-uhci", /* 70 */
|
||||||
"pci-ohci",
|
"pci-ohci",
|
||||||
"usb-redir",
|
"usb-redir",
|
||||||
|
"usb-hub",
|
||||||
);
|
);
|
||||||
|
|
||||||
struct qemu_feature_flags {
|
struct qemu_feature_flags {
|
||||||
@ -1224,6 +1225,8 @@ qemuCapsParseDeviceStr(const char *str, virBitmapPtr flags)
|
|||||||
qemuCapsSet(flags, QEMU_CAPS_PCI_OHCI);
|
qemuCapsSet(flags, QEMU_CAPS_PCI_OHCI);
|
||||||
if (strstr(str, "name \"usb-redir\""))
|
if (strstr(str, "name \"usb-redir\""))
|
||||||
qemuCapsSet(flags, QEMU_CAPS_USB_REDIR);
|
qemuCapsSet(flags, QEMU_CAPS_USB_REDIR);
|
||||||
|
if (strstr(str, "name \"usb-hub\""))
|
||||||
|
qemuCapsSet(flags, QEMU_CAPS_USB_HUB);
|
||||||
|
|
||||||
/* Prefer -chardev spicevmc (detected earlier) over -device spicevmc */
|
/* Prefer -chardev spicevmc (detected earlier) over -device spicevmc */
|
||||||
if (!qemuCapsGet(flags, QEMU_CAPS_CHARDEV_SPICEVMC) &&
|
if (!qemuCapsGet(flags, QEMU_CAPS_CHARDEV_SPICEVMC) &&
|
||||||
|
@ -102,13 +102,14 @@ enum qemuCapsFlags {
|
|||||||
QEMU_CAPS_VIRTIO_NET_EVENT_IDX = 64, /* virtio-net-pci.event_idx */
|
QEMU_CAPS_VIRTIO_NET_EVENT_IDX = 64, /* virtio-net-pci.event_idx */
|
||||||
QEMU_CAPS_DRIVE_CACHE_DIRECTSYNC = 65, /* Is cache=directsync supported? */
|
QEMU_CAPS_DRIVE_CACHE_DIRECTSYNC = 65, /* Is cache=directsync supported? */
|
||||||
|
|
||||||
QEMU_CAPS_PIIX3_USB_UHCI = 65, /* -device piix3-usb-uhci */
|
QEMU_CAPS_PIIX3_USB_UHCI = 66, /* -device piix3-usb-uhci */
|
||||||
QEMU_CAPS_PIIX4_USB_UHCI = 66, /* -device piix4-usb-uhci */
|
QEMU_CAPS_PIIX4_USB_UHCI = 67, /* -device piix4-usb-uhci */
|
||||||
QEMU_CAPS_USB_EHCI = 67, /* -device usb-ehci */
|
QEMU_CAPS_USB_EHCI = 68, /* -device usb-ehci */
|
||||||
QEMU_CAPS_ICH9_USB_EHCI1 = 68, /* -device ich9-usb-ehci1 and companions */
|
QEMU_CAPS_ICH9_USB_EHCI1 = 69, /* -device ich9-usb-ehci1 and companions */
|
||||||
QEMU_CAPS_VT82C686B_USB_UHCI = 69, /* -device vt82c686b-usb-uhci */
|
QEMU_CAPS_VT82C686B_USB_UHCI = 70, /* -device vt82c686b-usb-uhci */
|
||||||
QEMU_CAPS_PCI_OHCI = 70, /* -device pci-ohci */
|
QEMU_CAPS_PCI_OHCI = 71, /* -device pci-ohci */
|
||||||
QEMU_CAPS_USB_REDIR = 71, /* -device usb-redir */
|
QEMU_CAPS_USB_REDIR = 72, /* -device usb-redir */
|
||||||
|
QEMU_CAPS_USB_HUB = 73, /* -device usb-hub */
|
||||||
|
|
||||||
QEMU_CAPS_LAST, /* this must always be the last item */
|
QEMU_CAPS_LAST, /* this must always be the last item */
|
||||||
};
|
};
|
||||||
|
@ -681,6 +681,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virBitmapPtr qemuCaps)
|
|||||||
if (virAsprintf(&def->smartcards[i]->info.alias, "smartcard%d", i) < 0)
|
if (virAsprintf(&def->smartcards[i]->info.alias, "smartcard%d", i) < 0)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < def->nhubs ; i++) {
|
||||||
|
if (virAsprintf(&def->hubs[i]->info.alias, "hub%d", i) < 0)
|
||||||
|
goto no_memory;
|
||||||
|
}
|
||||||
if (def->console) {
|
if (def->console) {
|
||||||
if (virAsprintf(&def->console->info.alias, "console%d", i) < 0)
|
if (virAsprintf(&def->console->info.alias, "console%d", i) < 0)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
@ -1270,6 +1274,9 @@ qemuAssignDevicePCISlots(virDomainDefPtr def, qemuDomainPCIAddressSetPtr addrs)
|
|||||||
for (i = 0; i < def->nchannels ; i++) {
|
for (i = 0; i < def->nchannels ; i++) {
|
||||||
/* Nada - none are PCI based (yet) */
|
/* Nada - none are PCI based (yet) */
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < def->nhubs ; i++) {
|
||||||
|
/* Nada - none are PCI based (yet) */
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1776,7 +1783,6 @@ qemuBuildUSBControllerDevStr(virDomainControllerDefPtr def,
|
|||||||
virBufferAsprintf(buf, ",id=usb%d", def->idx);
|
virBufferAsprintf(buf, ",id=usb%d", def->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2344,6 +2350,43 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
qemuBuildHubDevStr(virDomainHubDefPtr dev,
|
||||||
|
virBitmapPtr qemuCaps)
|
||||||
|
{
|
||||||
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
|
|
||||||
|
if (dev->type != VIR_DOMAIN_HUB_TYPE_USB) {
|
||||||
|
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("hub type %s not supported"),
|
||||||
|
virDomainHubTypeToString(dev->type));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!qemuCapsGet(qemuCaps, QEMU_CAPS_USB_HUB)) {
|
||||||
|
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("usb-hub not supported by QEMU binary"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
virBufferAddLit(&buf, "usb-hub");
|
||||||
|
virBufferAsprintf(&buf, ",id=%s", dev->info.alias);
|
||||||
|
if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (virBufferError(&buf)) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return virBufferContentAndReset(&buf);
|
||||||
|
|
||||||
|
error:
|
||||||
|
virBufferFreeAndReset(&buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
qemuBuildUSBHostdevUsbDevStr(virDomainHostdevDefPtr dev)
|
qemuBuildUSBHostdevUsbDevStr(virDomainHostdevDefPtr dev)
|
||||||
{
|
{
|
||||||
@ -4254,6 +4297,17 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|||||||
if (usbcontroller == 0)
|
if (usbcontroller == 0)
|
||||||
virCommandAddArg(cmd, "-usb");
|
virCommandAddArg(cmd, "-usb");
|
||||||
|
|
||||||
|
for (i = 0 ; i < def->nhubs ; i++) {
|
||||||
|
virDomainHubDefPtr hub = def->hubs[i];
|
||||||
|
char *optstr;
|
||||||
|
|
||||||
|
virCommandAddArg(cmd, "-device");
|
||||||
|
if (!(optstr = qemuBuildHubDevStr(hub, qemuCaps)))
|
||||||
|
goto error;
|
||||||
|
virCommandAddArg(cmd, optstr);
|
||||||
|
VIR_FREE(optstr);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0 ; i < def->ninputs ; i++) {
|
for (i = 0 ; i < def->ninputs ; i++) {
|
||||||
virDomainInputDefPtr input = def->inputs[i];
|
virDomainInputDefPtr input = def->inputs[i];
|
||||||
|
|
||||||
|
@ -119,6 +119,7 @@ char * qemuBuildUSBHostdevUsbDevStr(virDomainHostdevDefPtr dev);
|
|||||||
char * qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev,
|
char * qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev,
|
||||||
virBitmapPtr qemuCaps);
|
virBitmapPtr qemuCaps);
|
||||||
|
|
||||||
|
char * qemuBuildHubDevStr(virDomainHubDefPtr dev, virBitmapPtr qemuCaps);
|
||||||
|
|
||||||
|
|
||||||
int qemuNetworkIfaceConnect(virDomainDefPtr def,
|
int qemuNetworkIfaceConnect(virDomainDefPtr def,
|
||||||
|
@ -349,7 +349,8 @@ mymain(void)
|
|||||||
QEMU_CAPS_DRIVE_AIO,
|
QEMU_CAPS_DRIVE_AIO,
|
||||||
QEMU_CAPS_DEVICE_SPICEVMC,
|
QEMU_CAPS_DEVICE_SPICEVMC,
|
||||||
QEMU_CAPS_PIIX3_USB_UHCI,
|
QEMU_CAPS_PIIX3_USB_UHCI,
|
||||||
QEMU_CAPS_PIIX4_USB_UHCI);
|
QEMU_CAPS_PIIX4_USB_UHCI,
|
||||||
|
QEMU_CAPS_USB_HUB);
|
||||||
DO_TEST("qemu-kvm-0.12.3", 12003, 1, 0,
|
DO_TEST("qemu-kvm-0.12.3", 12003, 1, 0,
|
||||||
QEMU_CAPS_VNC_COLON,
|
QEMU_CAPS_VNC_COLON,
|
||||||
QEMU_CAPS_NO_REBOOT,
|
QEMU_CAPS_NO_REBOOT,
|
||||||
@ -437,7 +438,8 @@ mymain(void)
|
|||||||
QEMU_CAPS_PIIX3_USB_UHCI,
|
QEMU_CAPS_PIIX3_USB_UHCI,
|
||||||
QEMU_CAPS_PIIX4_USB_UHCI,
|
QEMU_CAPS_PIIX4_USB_UHCI,
|
||||||
QEMU_CAPS_VT82C686B_USB_UHCI,
|
QEMU_CAPS_VT82C686B_USB_UHCI,
|
||||||
QEMU_CAPS_PCI_OHCI);
|
QEMU_CAPS_PCI_OHCI,
|
||||||
|
QEMU_CAPS_USB_HUB);
|
||||||
DO_TEST("qemu-kvm-0.12.1.2-rhel61", 12001, 1, 0,
|
DO_TEST("qemu-kvm-0.12.1.2-rhel61", 12001, 1, 0,
|
||||||
QEMU_CAPS_VNC_COLON,
|
QEMU_CAPS_VNC_COLON,
|
||||||
QEMU_CAPS_NO_REBOOT,
|
QEMU_CAPS_NO_REBOOT,
|
||||||
@ -484,7 +486,8 @@ mymain(void)
|
|||||||
QEMU_CAPS_VIRTIO_TX_ALG,
|
QEMU_CAPS_VIRTIO_TX_ALG,
|
||||||
QEMU_CAPS_VIRTIO_IOEVENTFD,
|
QEMU_CAPS_VIRTIO_IOEVENTFD,
|
||||||
QEMU_CAPS_PIIX3_USB_UHCI,
|
QEMU_CAPS_PIIX3_USB_UHCI,
|
||||||
QEMU_CAPS_PIIX4_USB_UHCI);
|
QEMU_CAPS_PIIX4_USB_UHCI,
|
||||||
|
QEMU_CAPS_USB_HUB);
|
||||||
|
|
||||||
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
1
tests/qemuxml2argvdata/qemuxml2argv-usb-hub.args
Normal file
1
tests/qemuxml2argvdata/qemuxml2argv-usb-hub.args
Normal file
@ -0,0 +1 @@
|
|||||||
|
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 -usb -device usb-hub,id=hub0,bus=usb0.0,port=1 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
|
19
tests/qemuxml2argvdata/qemuxml2argv-usb-hub.xml
Normal file
19
tests/qemuxml2argvdata/qemuxml2argv-usb-hub.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<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'/>
|
||||||
|
<memballoon model='virtio'/>
|
||||||
|
<hub type='usb'>
|
||||||
|
<address type='usb' bus='0' port='1'/>
|
||||||
|
</hub>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
@ -501,6 +501,9 @@ mymain(void)
|
|||||||
DO_TEST("usb-ich9-companion", false,
|
DO_TEST("usb-ich9-companion", false,
|
||||||
QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
|
QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG,
|
||||||
QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1);
|
QEMU_CAPS_PCI_MULTIFUNCTION, QEMU_CAPS_ICH9_USB_EHCI1);
|
||||||
|
DO_TEST("usb-hub", false,
|
||||||
|
QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, QEMU_CAPS_USB_HUB,
|
||||||
|
QEMU_CAPS_NODEFCONFIG);
|
||||||
|
|
||||||
DO_TEST("smbios", false, QEMU_CAPS_SMBIOS_TYPE);
|
DO_TEST("smbios", false, QEMU_CAPS_SMBIOS_TYPE);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user