? tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.sexpr ? tests/sexpr2xmldata/sexpr2xml-fv-usbmouse.xml ? tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.sexpr ? tests/sexpr2xmldata/sexpr2xml-fv-usbtablet.xml ? tests/xmconfigdata/test-fullvirt-usbmouse.cfg ? tests/xmconfigdata/test-fullvirt-usbmouse.xml ? tests/xmconfigdata/test-fullvirt-usbtablet-no-bus.xml ? tests/xmconfigdata/test-fullvirt-usbtablet.cfg ? tests/xmconfigdata/test-fullvirt-usbtablet.xml ? tests/xml2sexprdata/xml2sexpr-fv-usbmouse.sexpr ? tests/xml2sexprdata/xml2sexpr-fv-usbmouse.xml ? tests/xml2sexprdata/xml2sexpr-fv-usbtablet.sexpr ? tests/xml2sexprdata/xml2sexpr-fv-usbtablet.xml Index: src/qemu_conf.c =================================================================== RCS file: /data/cvs/libvirt/src/qemu_conf.c,v retrieving revision 1.3 diff -u -p -u -p -r1.3 qemu_conf.c --- src/qemu_conf.c 16 Jul 2007 21:30:30 -0000 1.3 +++ src/qemu_conf.c 17 Jul 2007 00:49:13 -0000 @@ -806,6 +806,74 @@ static struct qemud_vm_net_def *qemudPar } +/* Parse the XML definition for a network interface */ +static struct qemud_vm_input_def *qemudParseInputXML(virConnectPtr conn, + struct qemud_driver *driver ATTRIBUTE_UNUSED, + xmlNodePtr node) { + struct qemud_vm_input_def *input = calloc(1, sizeof(struct qemud_vm_input_def)); + xmlChar *type = NULL; + xmlChar *bus = NULL; + + if (!input) { + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "input"); + return NULL; + } + + type = xmlGetProp(node, BAD_CAST "type"); + bus = xmlGetProp(node, BAD_CAST "bus"); + + if (!type) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "no type provide for input device"); + goto error; + } + + if (!strcmp((const char *)type, "mouse")) { + input->type = QEMU_INPUT_TYPE_MOUSE; + } else if (!strcmp((const char *)type, "tablet")) { + input->type = QEMU_INPUT_TYPE_TABLET; + } else { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "unsupported input device type %s", (const char*)type); + goto error; + } + + if (bus) { + if (!strcmp((const char*)bus, "ps2")) { /* Only allow mouse */ + if (input->type == QEMU_INPUT_TYPE_TABLET) { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "ps2 bus does not support %s input device", (const char*)type); + goto error; + } + input->bus = QEMU_INPUT_BUS_PS2; + } else if (!strcmp((const char *)type, "usb")) { /* Allow mouse & keyboard */ + input->bus = QEMU_INPUT_BUS_USB; + } else { + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "unsupported input bus %s", (const char*)bus); + goto error; + } + } else { + if (input->type == QEMU_INPUT_TYPE_MOUSE) + input->bus = QEMU_INPUT_BUS_PS2; + else + input->bus = QEMU_INPUT_BUS_USB; + } + + if (type) + xmlFree(type); + if (bus) + xmlFree(bus); + + return input; + + error: + if (type) + xmlFree(type); + if (bus) + xmlFree(bus); + + free(input); + return NULL; +} + + /* * Parses a libvirt XML definition of a guest, and populates the * the qemud_vm struct with matching data about the guests config @@ -1193,6 +1261,55 @@ static struct qemud_vm_def *qemudParseXM } } xmlXPathFreeObject(obj); + + /* analysis of the input devices */ + obj = xmlXPathEval(BAD_CAST "/domain/devices/input", ctxt); + if ((obj != NULL) && (obj->type == XPATH_NODESET) && + (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) { + struct qemud_vm_input_def *prev = NULL; + for (i = 0; i < obj->nodesetval->nodeNr; i++) { + struct qemud_vm_input_def *input; + if (!(input = qemudParseInputXML(conn, driver, obj->nodesetval->nodeTab[i]))) { + goto error; + } + def->ninputs++; + input->next = NULL; + if (i == 0) { + def->inputs = input; + } else { + prev->next = input; + } + prev = input; + } + } + xmlXPathFreeObject(obj); + obj = NULL; + + /* If graphics are enabled, there's an implicit PS2 mouse */ + if (def->graphicsType != QEMUD_GRAPHICS_NONE) { + int hasPS2mouse = 0; + struct qemud_vm_input_def *input = def->inputs; + while (input) { + if (input->type == QEMU_INPUT_TYPE_MOUSE && + input->bus == QEMU_INPUT_BUS_PS2) + hasPS2mouse = 1; + input = input->next; + } + + if (!hasPS2mouse) { + input = calloc(1, sizeof(struct qemud_vm_input_def)); + if (!input) { + qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY, "input"); + goto error; + } + input->type = QEMU_INPUT_TYPE_MOUSE; + input->bus = QEMU_INPUT_BUS_PS2; + input->next = def->inputs; + def->inputs = input; + def->ninputs++; + } + } + xmlXPathFreeContext(ctxt); return def; @@ -2541,6 +2658,7 @@ char *qemudGenerateXML(virConnectPtr con unsigned char *uuid; struct qemud_vm_disk_def *disk; struct qemud_vm_net_def *net; + struct qemud_vm_input_def *input; const char *type = NULL; int n; @@ -2769,6 +2887,14 @@ char *qemudGenerateXML(virConnectPtr con net = net->next; } + input = def->inputs; + while (input) { + virBufferVSprintf(buf, " \n", + input->type == QEMU_INPUT_TYPE_MOUSE ? "mouse" : "tablet", + input->bus == QEMU_INPUT_BUS_PS2 ? "ps2" : "usb"); + input = input->next; + } + switch (def->graphicsType) { case QEMUD_GRAPHICS_VNC: if (virBufferAdd(buf, " \n", hvm ? "ps2": "xen"); virBufferAdd(&buf, " \n", 27); } else if (tmp && !strcmp(tmp, "vnc")) { int port = xenStoreDomainGetVNCPort(conn, domid); const char *listenAddr = sexpr_node(node, "device/vfb/vnclisten"); const char *keymap = sexpr_node(node, "device/vfb/keymap"); + virBufferVSprintf(&buf, " \n", hvm ? "ps2": "xen"); virBufferVSprintf(&buf, " kind == SEXPR_CONS; cur = cur->cdr) { + node = cur->car; + if (sexpr_lookup(node, "usbdevice")) { + tmp = sexpr_node(node, "usbdevice"); + if (tmp && *tmp) { + if (!strcmp(tmp, "usbtablet")) + virBufferAdd(&buf, " \n", 37); + else if (!strcmp(tmp, "usbmouse")) + virBufferAdd(&buf, " \n", 36); + } + } + } + } + /* Graphics device (HVM <= 3.0.4, or PV <= 3.0.3) vnc config */ if ((hvm && xendConfigVersion < 4) || (!hvm && xendConfigVersion < 3)) { @@ -1713,6 +1731,7 @@ xend_parse_sexp_desc(virConnectPtr conn, */ if (port == -1 && xendConfigVersion < 2) port = 5900 + domid; + virBufferVSprintf(&buf, " \n", hvm ? "ps2" : "xen"); virBufferVSprintf(&buf, " \n", hvm ? "ps2" : "xen"); virBufferAdd(&buf, " \n", 27 ); + } } } Index: src/xm_internal.c =================================================================== RCS file: /data/cvs/libvirt/src/xm_internal.c,v retrieving revision 1.37 diff -u -p -u -p -r1.37 xm_internal.c --- src/xm_internal.c 16 Jul 2007 21:30:30 -0000 1.37 +++ src/xm_internal.c 17 Jul 2007 00:49:14 -0000 @@ -913,6 +913,17 @@ char *xenXMDomainFormatXML(virConnectPtr } } + if (hvm) { + if (xenXMConfigGetString(conf, "usbdevice", &str) == 0 && str) { + if (!strcmp(str, "tablet")) + virBufferAdd(buf, " \n", 37); + else if (!strcmp(str, "mouse")) + virBufferAdd(buf, " \n", 36); + /* Ignore else branch - probably some other non-input device we don't + support in libvirt yet */ + } + } + /* HVM guests, or old PV guests use this config format */ if (hvm || priv->xendConfigVersion < 3) { if (xenXMConfigGetInt(conf, "vnc", &val) == 0 && val) { @@ -980,6 +991,9 @@ char *xenXMDomainFormatXML(virConnectPtr } } + if (vnc || sdl) { + virBufferVSprintf(buf, " \n", hvm ? "ps2":"xen"); + } if (vnc) { virBufferVSprintf(buf, " xendConfigVersion < 3) { Index: src/xml.c =================================================================== RCS file: /data/cvs/libvirt/src/xml.c,v retrieving revision 1.84 diff -u -p -u -p -r1.84 xml.c --- src/xml.c 16 Jul 2007 21:30:30 -0000 1.84 +++ src/xml.c 17 Jul 2007 00:49:14 -0000 @@ -416,11 +416,12 @@ static int virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int vcpus, int xendConfigVersion) { xmlNodePtr cur, txt; + xmlNodePtr *nodes = NULL; xmlChar *type = NULL; xmlChar *loader = NULL; char bootorder[5]; int nbootorder = 0; - int res; + int res, nb_nodes; char *str; cur = node->children; @@ -540,6 +541,57 @@ virDomainParseXMLOSDescHVM(virConnectPtr if (virXPathNode("/domain/features/pae", ctxt) != NULL) virBufferAdd(buf, "(pae 1)", 7); + virBufferAdd(buf, "(usb 1)", 7); + nb_nodes = virXPathNodeSet("/domain/devices/input", ctxt, &nodes); + if (nb_nodes > 0) { + int i; + for (i = 0; i < nb_nodes; i++) { + xmlChar *itype = NULL, *bus = NULL; + int isMouse = 1; + + itype = xmlGetProp(nodes[i], (xmlChar *)"type"); + + if (!itype) { + goto error; + } + if (!strcmp((const char *)itype, "tablet")) + isMouse = 0; + else if (strcmp((const char*)itype, "mouse")) { + xmlFree(itype); + virXMLError(conn, VIR_ERR_XML_ERROR, "input", 0); + goto error; + } + xmlFree(itype); + + bus = xmlGetProp(nodes[i], (xmlChar *)"bus"); + if (!bus) { + if (!isMouse) { + /* Nothing - implicit ps2 */ + } else { + virBufferAdd(buf, "(usbdevice tablet)", 13); + } + } else { + if (!strcmp((const char*)bus, "ps2")) { + if (!isMouse) { + xmlFree(bus); + virXMLError(conn, VIR_ERR_XML_ERROR, "input", 0); + goto error; + } + /* Nothing - implicit ps2 */ + } else if (!strcmp((const char*)bus, "usb")) { + if (isMouse) + virBufferAdd(buf, "(usbdevice mouse)", 17); + else + virBufferAdd(buf, "(usbdevice tablet)", 18); + } + } + xmlFree(bus); + } + free(nodes); + nodes = NULL; + } + + res = virXPathBoolean("count(domain/devices/console) > 0", ctxt); if (res < 0) { virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0); @@ -572,6 +624,8 @@ virDomainParseXMLOSDescHVM(virConnectPtr return (0); error: + if (nodes) + free(nodes); return(-1); } Index: tests/sexpr2xmltest.c =================================================================== RCS file: /data/cvs/libvirt/tests/sexpr2xmltest.c,v retrieving revision 1.14 diff -u -p -u -p -r1.14 sexpr2xmltest.c --- tests/sexpr2xmltest.c 16 Jul 2007 21:30:30 -0000 1.14 +++ tests/sexpr2xmltest.c 17 Jul 2007 00:49:14 -0000 @@ -137,6 +137,18 @@ static int testCompareNoSourceCDRom(void 1); } +static int testCompareFVInputUSBMouse(void *data ATTRIBUTE_UNUSED) { + return testCompareFiles("sexpr2xmldata/sexpr2xml-fv-usbmouse.xml", + "sexpr2xmldata/sexpr2xml-fv-usbmouse.sexpr", + 1); +} + +static int testCompareFVInputUSBTablet(void *data ATTRIBUTE_UNUSED) { + return testCompareFiles("sexpr2xmldata/sexpr2xml-fv-usbtablet.xml", + "sexpr2xmldata/sexpr2xml-fv-usbtablet.sexpr", + 1); +} + static int testCompareFVclockUTC(void *data ATTRIBUTE_UNUSED) { return testCompareFiles("sexpr2xmldata/sexpr2xml-fv-utc.xml", "sexpr2xmldata/sexpr2xml-fv-utc.sexpr", @@ -150,7 +162,6 @@ static int testCompareFVclockLocaltime(v } - int main(int argc, char **argv) { @@ -223,6 +234,13 @@ main(int argc, char **argv) 1, testCompareNoSourceCDRom, NULL) != 0) ret = -1; + if (virtTestRun("SEXPR-2-XML USB Mouse", + 1, testCompareFVInputUSBMouse, NULL) != 0) + ret = -1; + if (virtTestRun("SEXPR-2-XML USB Tablet", + 1, testCompareFVInputUSBTablet, NULL) != 0) + ret = -1; + if (virtTestRun("SEXPR-2-XML clock UTC", 1, testCompareFVclockUTC, NULL) != 0) ret = -1; Index: tests/xmconfigtest.c =================================================================== RCS file: /data/cvs/libvirt/tests/xmconfigtest.c,v retrieving revision 1.5 diff -u -p -u -p -r1.5 xmconfigtest.c --- tests/xmconfigtest.c 16 Jul 2007 21:30:30 -0000 1.5 +++ tests/xmconfigtest.c 17 Jul 2007 00:49:14 -0000 @@ -209,12 +209,43 @@ static int testCompareFullvirtClockLocal "xmconfigdata/test-fullvirt-localtime.xml", 2); } + static int testCompareFullvirtClockLocaltimeParse(void *data ATTRIBUTE_UNUSED) { return testCompareParseXML("xmconfigdata/test-fullvirt-localtime.cfg", "xmconfigdata/test-fullvirt-localtime.xml", 2); } +static int testCompareFullvirtInputUSBTabletFormat(void *data ATTRIBUTE_UNUSED) { + return testCompareFormatXML("xmconfigdata/test-fullvirt-usbtablet.cfg", + "xmconfigdata/test-fullvirt-usbtablet.xml", + 2); +} + +static int testCompareFullvirtInputUSBTabletParse(void *data ATTRIBUTE_UNUSED) { + return testCompareParseXML("xmconfigdata/test-fullvirt-usbtablet.cfg", + "xmconfigdata/test-fullvirt-usbtablet.xml", + 2); +} + +static int testCompareFullvirtInputUSBTabletNoBusParse(void *data ATTRIBUTE_UNUSED) { + return testCompareParseXML("xmconfigdata/test-fullvirt-usbtablet.cfg", + "xmconfigdata/test-fullvirt-usbtablet-no-bus.xml", + 2); +} + +static int testCompareFullvirtInputUSBMouseFormat(void *data ATTRIBUTE_UNUSED) { + return testCompareParseXML("xmconfigdata/test-fullvirt-usbmouse.cfg", + "xmconfigdata/test-fullvirt-usbmouse.xml", + 2); +} + +static int testCompareFullvirtInputUSBMouseParse(void *data ATTRIBUTE_UNUSED) { + return testCompareParseXML("xmconfigdata/test-fullvirt-usbmouse.cfg", + "xmconfigdata/test-fullvirt-usbmouse.xml", + 2); +} + int main(int argc, char **argv) @@ -247,6 +278,12 @@ main(int argc, char **argv) if (virtTestRun("Fullvirt clock UTC (Format)", 1, testCompareFullvirtClockUTCFormat, NULL) != 0) ret = -1; + if (virtTestRun("Fullvirt USB mouse (Format)", + 1, testCompareFullvirtInputUSBMouseFormat, NULL) != 0) + ret = -1; + if (virtTestRun("Fullvirt USB tablet (Format)", + 1, testCompareFullvirtInputUSBTabletFormat, NULL) != 0) + ret = -1; /* XML -> Config */ if (virtTestRun("Paravirt old PVFB (Parse)", @@ -267,6 +304,16 @@ main(int argc, char **argv) if (virtTestRun("Fullvirt clock UTC (Parse)", 1, testCompareFullvirtClockUTCParse, NULL) != 0) ret = -1; + if (virtTestRun("Fullvirt USB mouse (Parse)", + 1, testCompareFullvirtInputUSBMouseParse, NULL) != 0) + ret = -1; + if (virtTestRun("Fullvirt USB tablet (Parse)", + 1, testCompareFullvirtInputUSBTabletParse, NULL) != 0) + ret = -1; + if (virtTestRun("Fullvirt USB tablet no bus (Parse)", + 1, testCompareFullvirtInputUSBTabletNoBusParse, NULL) != 0) + ret = -1; + exit(ret==0 ? EXIT_SUCCESS : EXIT_FAILURE); } Index: tests/xml2sexprtest.c =================================================================== RCS file: /data/cvs/libvirt/tests/xml2sexprtest.c,v retrieving revision 1.13 diff -u -p -u -p -r1.13 xml2sexprtest.c --- tests/xml2sexprtest.c 16 Jul 2007 21:30:30 -0000 1.13 +++ tests/xml2sexprtest.c 17 Jul 2007 00:49:14 -0000 @@ -30,11 +30,11 @@ static int testCompareFiles(const char * if (!(gotsexpr = virDomainParseXMLDesc(NULL, xmlData, &gotname, xendConfigVersion))) goto fail; - if (getenv("DEBUG_TESTS")) { - printf("Expect %d '%s'\n", (int)strlen(sexprData), sexprData); - printf("Actual %d '%s'\n", (int)strlen(gotsexpr), gotsexpr); - } if (strcmp(sexprData, gotsexpr)) { + if (getenv("DEBUG_TESTS")) { + printf("Expect %d '%s'\n", (int)strlen(sexprData), sexprData); + printf("Actual %d '%s'\n", (int)strlen(gotsexpr), gotsexpr); + } goto fail; } @@ -202,6 +202,22 @@ static int testCompareFVclockLocaltime(v } +static int testCompareFVInputUSBMouse(void *data ATTRIBUTE_UNUSED) { + return testCompareFiles("xml2sexprdata/xml2sexpr-fv-usbmouse.xml", + "xml2sexprdata/xml2sexpr-fv-usbmouse.sexpr", + "fvtest", + 1); +} + +static int testCompareFVInputUSBTablet(void *data ATTRIBUTE_UNUSED) { + return testCompareFiles("xml2sexprdata/xml2sexpr-fv-usbtablet.xml", + "xml2sexprdata/xml2sexpr-fv-usbtablet.sexpr", + "fvtest", + 1); +} + + + int main(int argc, char **argv) { @@ -290,6 +306,13 @@ main(int argc, char **argv) 1, testCompareNoSourceCDRom, NULL) != 0) ret = -1; + if (virtTestRun("XML-2-SEXPR FV usb mouse)", + 1, testCompareFVInputUSBMouse, NULL) != 0) + ret = -1; + if (virtTestRun("XML-2-SEXPR FV usb tablet)", + 1, testCompareFVInputUSBTablet, NULL) != 0) + ret = -1; + if (virtTestRun("XML-2-SEXPR clock UTC", 1, testCompareFVclockUTC, NULL) != 0) ret = -1; Index: tests/sexpr2xmldata/sexpr2xml-curmem.xml =================================================================== RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-curmem.xml,v retrieving revision 1.1 diff -u -p -u -p -r1.1 sexpr2xml-curmem.xml --- tests/sexpr2xmldata/sexpr2xml-curmem.xml 10 Nov 2006 11:13:01 -0000 1.1 +++ tests/sexpr2xmldata/sexpr2xml-curmem.xml 17 Jul 2007 00:49:14 -0000 @@ -25,6 +25,7 @@ + Index: tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml =================================================================== RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml,v retrieving revision 1.1 diff -u -p -u -p -r1.1 sexpr2xml-fv-localtime.xml --- tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml 16 Jul 2007 21:30:30 -0000 1.1 +++ tests/sexpr2xmldata/sexpr2xml-fv-localtime.xml 17 Jul 2007 00:49:14 -0000 @@ -33,6 +33,7 @@ + Index: tests/sexpr2xmldata/sexpr2xml-fv-utc.xml =================================================================== RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-utc.xml,v retrieving revision 1.1 diff -u -p -u -p -r1.1 sexpr2xml-fv-utc.xml --- tests/sexpr2xmldata/sexpr2xml-fv-utc.xml 16 Jul 2007 21:30:30 -0000 1.1 +++ tests/sexpr2xmldata/sexpr2xml-fv-utc.xml 17 Jul 2007 00:49:14 -0000 @@ -33,6 +33,7 @@ + Index: tests/sexpr2xmldata/sexpr2xml-fv-v2.xml =================================================================== RCS file: /data/cvs/libvirt/tests/sexpr2xmldata/sexpr2xml-fv-v2.xml,v retrieving revision 1.4 diff -u -p -u -p -r1.4 sexpr2xml-fv-v2.xml --- tests/sexpr2xmldata/sexpr2xml-fv-v2.xml 16 Jul 2007 21:30:30 -0000 1.4 +++ tests/sexpr2xmldata/sexpr2xml-fv-v2.xml 17 Jul 2007 00:49:14 -0000 @@ -33,6 +33,7 @@