[libvirt] [PATCH 10/13] qemu:send-key: Implement the driver methods
Daniel P. Berrange
berrange at redhat.com
Wed May 25 20:27:38 UTC 2011
On Wed, May 25, 2011 at 05:37:52PM +0800, Lai Jiangshan wrote:
> Signed-off-by: Lai Jiangshan <laijs at fujitsu.com>
> ---
> src/qemu/qemu_driver.c | 50 ++++++++++++++++++++++++++++++++++++++++++
> src/qemu/qemu_monitor.c | 28 +++++++++++++++++++++++
> 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 | 48 ++++++++++++++++++++++++++++++++++++++++
> src/qemu/qemu_monitor_text.h | 5 ++++
> 7 files changed, 157 insertions(+), 0 deletions(-)
>
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 691965d..f7e21bf 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -1753,6 +1753,55 @@ cleanup:
> return ret;
> }
>
> +static int qemuDomainSendKey(virDomainPtr domain,
> + unsigned int codeset,
> + unsigned int holdtime,
> + unsigned int nkeycodes,
> + unsigned int *keycodes,
> + 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)
> {
> @@ -7746,6 +7795,7 @@ static virDriver qemuDriver = {
> .domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
> .domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
> .domainSetSchedulerParametersFlags = qemuSetSchedulerParametersFlags, /* 0.9.2 */
> + .domainSendKey = qemuDomainSendKey, /* 0.9.2 */
> };
>
>
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index 5186f99..c0688fd 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
> @@ -2294,6 +2296,32 @@ 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_DRIVER_DEFAULT
> + || 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 05c3359..76a849a 100644
> --- a/src/qemu/qemu_monitor.h
> +++ b/src/qemu/qemu_monitor.h
> @@ -435,6 +435,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 2d8a390..a547f1d 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -2615,6 +2615,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 106f2d3..433cde1 100644
> --- a/src/qemu/qemu_monitor_text.c
> +++ b/src/qemu/qemu_monitor_text.c
> @@ -2717,6 +2717,54 @@ fail:
> return -1;
> }
>
> +int qemuMonitorTextSendKey(qemuMonitorPtr mon,
> + unsigned int holdtime,
> + unsigned int nkeycodes,
> + unsigned int *keycodes)
> +{
> + int i;
> + int pos = strlen("sendkey ");
> + int cmd_len = pos + nkeycodes * strlen("0xFF-") + 12 + sizeof('\0');
> + char *cmd, *reply = NULL;
> +
> + if (nkeycodes > 16 || nkeycodes == 0)
> + return -1;
> +
> + if (VIR_ALLOC_N(cmd, cmd_len) < 0)
> + return -1;
> +
> + memcpy(cmd, "sendkey ", pos);
> + 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]);
> + VIR_FREE(cmd);
> + return -1;
> + }
> +
> + pos += sprintf(cmd + pos, "0x%02X-", keycodes[i]);
> + }
> + cmd[pos - 1] = ' '; // the last '-' --> ' '
> +
> + if (holdtime)
> + sprintf(cmd + pos, "%u", holdtime);
Really don't want to use VIR_ALLOC_N/memcpy/sprintf here.
Better to use virBuffer APIs to build up the command string.
> +
> + 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;
> +}
> +
> /* 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);
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 :|
More information about the libvir-list
mailing list