On Tue, Jun 07, 2011 at 05:11:17PM +0800, Lai Jiangshan wrote: > Signed-off-by: Lai Jiangshan <laijs@xxxxxxxxxxxxxx> > --- > src/qemu/qemu_driver.c | 50 ++++++++++++++++++++++++++++++++++++++++++ > src/qemu/qemu_monitor.c | 27 ++++++++++++++++++++++ > src/qemu/qemu_monitor.h | 6 +++++ > src/qemu/qemu_monitor_json.c | 15 ++++++++++++ > src/qemu/qemu_monitor_json.h | 5 ++++ > src/qemu/qemu_monitor_text.c | 47 +++++++++++++++++++++++++++++++++++++++ > src/qemu/qemu_monitor_text.h | 5 ++++ > 7 files changed, 155 insertions(+), 0 deletions(-) > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index 2957467..1678deb 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -1764,6 +1764,55 @@ cleanup: > return ret; > } > > +static int qemuDomainSendKey(virDomainPtr domain, > + unsigned int codeset, > + unsigned int holdtime, > + unsigned int *keycodes, > + unsigned int nkeycodes, > + unsigned int flags) > +{ > + struct qemud_driver *driver = domain->conn->privateData; > + virDomainObjPtr vm = NULL; > + int ret = -1; > + qemuDomainObjPrivatePtr priv; > + > + virCheckFlags(0, -1); > + > + qemuDriverLock(driver); > + vm = virDomainFindByUUID(&driver->domains, domain->uuid); > + if (!vm) { > + char uuidstr[VIR_UUID_STRING_BUFLEN]; > + virUUIDFormat(domain->uuid, uuidstr); > + qemuReportError(VIR_ERR_NO_DOMAIN, > + _("no domain with matching uuid '%s'"), uuidstr); > + goto cleanup; > + } > + > + if (!virDomainObjIsActive(vm)) { > + qemuReportError(VIR_ERR_OPERATION_INVALID, > + "%s", _("domain is not running")); > + goto cleanup; > + } > + > + priv = vm->privateData; > + > + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0) > + goto cleanup; > + qemuDomainObjEnterMonitorWithDriver(driver, vm); > + ret = qemuMonitorSendKey(priv->mon, codeset, holdtime, nkeycodes, keycodes); > + qemuDomainObjExitMonitorWithDriver(driver, vm); > + if (qemuDomainObjEndJob(vm) == 0) { > + vm = NULL; > + goto cleanup; > + } > + > +cleanup: > + if (vm) > + virDomainObjUnlock(vm); > + qemuDriverUnlock(driver); > + return ret; > +} > + > static int qemudDomainGetInfo(virDomainPtr dom, > virDomainInfoPtr info) > { > @@ -8092,6 +8141,7 @@ static virDriver qemuDriver = { > .domainMigratePerform3 = qemuDomainMigratePerform3, /* 0.9.2 */ > .domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */ > .domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */ > + .domainSendKey = qemuDomainSendKey, /* 0.9.2 */ Needs updating to 0.9.3 > diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c > index 26bb814..faab819 100644 > --- a/src/qemu/qemu_monitor.c > +++ b/src/qemu/qemu_monitor.c > @@ -38,6 +38,8 @@ > #include "logging.h" > #include "files.h" > > +#include <libvirt/virtkeys.h> > + > #define VIR_FROM_THIS VIR_FROM_QEMU > > #define DEBUG_IO 0 > @@ -2357,6 +2359,31 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon) > return ret; > } > > +int qemuMonitorSendKey(qemuMonitorPtr mon, > + unsigned int codeset, > + unsigned int holdtime, > + unsigned int nkeycodes, > + unsigned int *keycodes) > +{ > + int ret; > + > + VIR_DEBUG("mon=%p, codeset=%u, holdtime=%u, nkeycodes=%u", > + mon, codeset, holdtime, nkeycodes); > + > + if (codeset != LIBVIRT_KEYCODE_XT) { > + qemuReportError(VIR_ERR_NO_SUPPORT, > + "qemu monitor can not support the codeset: %d", > + codeset); > + return -1; > + } > + > + if (mon->json) > + ret = qemuMonitorJSONSendKey(mon, holdtime, nkeycodes, keycodes); > + else > + ret = qemuMonitorTextSendKey(mon, holdtime, nkeycodes, keycodes); > + return ret; > +} > + > int qemuMonitorScreendump(qemuMonitorPtr mon, > const char *file) > { > diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h > index 910865b..64a6320 100644 > --- a/src/qemu/qemu_monitor.h > +++ b/src/qemu/qemu_monitor.h > @@ -441,6 +441,12 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon); > int qemuMonitorScreendump(qemuMonitorPtr mon, > const char *file); > > +int qemuMonitorSendKey(qemuMonitorPtr mon, > + unsigned int codeset, > + unsigned int holdtime, > + unsigned int nkeycodes, > + unsigned int *keycodes); > + > /** > * When running two dd process and using <> redirection, we need a > * shell that will not truncate files. These two strings serve that > diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c > index 75adf66..538e98f 100644 > --- a/src/qemu/qemu_monitor_json.c > +++ b/src/qemu/qemu_monitor_json.c > @@ -2619,6 +2619,21 @@ cleanup: > return ret; > } > > +int qemuMonitorJSONSendKey(qemuMonitorPtr mon, > + unsigned int holdtime, > + unsigned int nkeycodes, > + unsigned int *keycodes) > +{ > + /* > + * FIXME: qmp sendkey has not been implemented yet, > + * and qmp API of it can not be anticipated, so we use hmp temporary. > + */ > + if (qemuMonitorCheckHMP(mon, "sendkey")) { > + return qemuMonitorTextSendKey(mon, holdtime, nkeycodes, keycodes); > + } else > + return -1; > +} > + > int qemuMonitorJSONScreendump(qemuMonitorPtr mon, > const char *file) > { > diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h > index ec79b03..89d7515 100644 > --- a/src/qemu/qemu_monitor_json.h > +++ b/src/qemu/qemu_monitor_json.h > @@ -214,6 +214,11 @@ int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon, > > int qemuMonitorJSONInjectNMI(qemuMonitorPtr mon); > > +int qemuMonitorJSONSendKey(qemuMonitorPtr mon, > + unsigned int holdtime, > + unsigned int nkeycodes, > + unsigned int *keycodes); > + > int qemuMonitorJSONScreendump(qemuMonitorPtr mon, > const char *file); > > diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c > index 3b42e7a..1b301e4 100644 > --- a/src/qemu/qemu_monitor_text.c > +++ b/src/qemu/qemu_monitor_text.c > @@ -2718,6 +2718,53 @@ fail: > return -1; > } > > +int qemuMonitorTextSendKey(qemuMonitorPtr mon, > + unsigned int holdtime, > + unsigned int nkeycodes, > + unsigned int *keycodes) > +{ > + int i; > + virBuffer buf = VIR_BUFFER_INITIALIZER; > + char *cmd, *reply = NULL; > + > + if (nkeycodes > 16 || nkeycodes == 0) > + return -1; > + > + virBufferAddLit(&buf, "sendkey "); > + for (i = 0; i < nkeycodes; i++) { > + if (keycodes[i] > 255) { > + qemuReportError(VIR_ERR_OPERATION_FAILED, > + _("the %dth keycode is invalid: 0x%02X"), > + i, keycodes[i]); > + cmd = virBufferContentAndReset(&buf); > + VIR_FREE(cmd); You can just replace thse two lines with virBufferFreeAndReset(&buf) instead. > + return -1; > + } > + > + if (i) > + virBufferAddChar(&buf, '-'); > + virBufferAsprintf(&buf, "0x%02X", keycodes[i]); > + } > + > + if (holdtime) > + virBufferAsprintf(&buf, " %u", holdtime); You want a check here before using 'cmd': if (virBufferError(&buf)) { virReportOOMError(); return -1; } > + > + cmd = virBufferContentAndReset(&buf); > + if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0) > + goto fail; > + > + VIR_FREE(cmd); > + VIR_FREE(reply); > + return 0; > + > +fail: > + qemuReportError(VIR_ERR_OPERATION_FAILED, > + _("failed to send key using command '%s'"), > + cmd); > + VIR_FREE(cmd); > + return -1; There's only one place which ever jumps to 'fail', so I'd just move the code upto that place and eliminate the extra goto. > +} > + > /* Returns -1 on error, -2 if not supported */ > int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file) > { > diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h > index 8a69105..971de83 100644 > --- a/src/qemu/qemu_monitor_text.h > +++ b/src/qemu/qemu_monitor_text.h > @@ -208,6 +208,11 @@ int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd, > > int qemuMonitorTextInjectNMI(qemuMonitorPtr mon); > > +int qemuMonitorTextSendKey(qemuMonitorPtr mon, > + unsigned int holdtime, > + unsigned int nkeycodes, > + unsigned int *keycodes); > + > int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file); > > #endif /* QEMU_MONITOR_TEXT_H */ Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list