Instead of always using HMP use the QMP send-key command introduced in qemu 1.3. --- src/qemu/qemu_capabilities.c | 3 +++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_driver.c | 25 +++++++++++------ src/qemu/qemu_monitor.c | 5 ++-- src/qemu/qemu_monitor.h | 3 ++- src/qemu/qemu_monitor_json.c | 64 ++++++++++++++++++++++++++++++++++++++++---- 6 files changed, 85 insertions(+), 16 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 50712b0..051285c 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -216,6 +216,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "ipv6-migration", /* 135 */ "machine-opt", + "send-key", ); struct _virQEMUCaps { @@ -1954,6 +1955,8 @@ virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps, virQEMUCapsSet(qemuCaps, QEMU_CAPS_ADD_FD); else if (STREQ(name, "nbd-server-start")) virQEMUCapsSet(qemuCaps, QEMU_CAPS_NBD_SERVER); + else if (STREQ(name, "send-key")) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_SEND_KEY); VIR_FREE(name); } VIR_FREE(commands); diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index b2dc588..bcd4daf 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -176,6 +176,7 @@ enum virQEMUCapsFlags { QEMU_CAPS_SCSI_MEGASAS = 134, /* -device megasas */ QEMU_CAPS_IPV6_MIGRATION = 135, /* -incoming [::] */ QEMU_CAPS_MACHINE_OPT = 136, /* -machine xxxx*/ + QEMU_CAPS_SEND_KEY = 137, /* send-key QMP command */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 2c0d7d1..cfb6fc9 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -2227,14 +2227,16 @@ cleanup: return ret; } -static int qemuDomainSendKey(virDomainPtr domain, - unsigned int codeset, - unsigned int holdtime, - unsigned int *keycodes, - int nkeycodes, - unsigned int flags) +static int +qemuDomainSendKey(virDomainPtr domain, + unsigned int codeset, + unsigned int holdtime, + unsigned int *keycodes, + int nkeycodes, + unsigned int flags) { virQEMUDriverPtr driver = domain->conn->privateData; + virQEMUCapsPtr qemuCaps = NULL; virDomainObjPtr vm = NULL; int ret = -1; qemuDomainObjPrivatePtr priv; @@ -2251,7 +2253,8 @@ static int qemuDomainSendKey(virDomainPtr domain, keycodes[i]); if (keycode < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot translate keycode %u of %s codeset to rfb keycode"), + _("cannot translate keycode %u of %s codeset to " + "rfb keycode"), keycodes[i], virKeycodeSetTypeToString(codeset)); return -1; @@ -2263,6 +2266,10 @@ static int qemuDomainSendKey(virDomainPtr domain, if (!(vm = qemuDomObjFromDomain(domain))) goto cleanup; + if (!(qemuCaps = virQEMUCapsCacheLookup(driver->qemuCapsCache, + vm->def->emulator))) + goto cleanup; + priv = vm->privateData; if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) @@ -2275,7 +2282,8 @@ static int qemuDomainSendKey(virDomainPtr domain, } qemuDomainObjEnterMonitor(driver, vm); - ret = qemuMonitorSendKey(priv->mon, holdtime, keycodes, nkeycodes); + ret = qemuMonitorSendKey(priv->mon, holdtime, keycodes, nkeycodes, + virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEND_KEY)); qemuDomainObjExitMonitor(driver, vm); endjob: @@ -2285,6 +2293,7 @@ endjob: cleanup: if (vm) virObjectUnlock(vm); + virObjectUnref(qemuCaps); return ret; } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index d1c6690..d9b5c23 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3008,14 +3008,15 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon) int qemuMonitorSendKey(qemuMonitorPtr mon, unsigned int holdtime, unsigned int *keycodes, - unsigned int nkeycodes) + unsigned int nkeycodes, + bool useQMP) { int ret; VIR_DEBUG("mon=%p, holdtime=%u, nkeycodes=%u", mon, holdtime, nkeycodes); - if (mon->json) + if (mon->json && useQMP) ret = qemuMonitorJSONSendKey(mon, holdtime, keycodes, nkeycodes); else ret = qemuMonitorTextSendKey(mon, holdtime, keycodes, nkeycodes); diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index b3808a8..fadad08 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -601,7 +601,8 @@ int qemuMonitorScreendump(qemuMonitorPtr mon, int qemuMonitorSendKey(qemuMonitorPtr mon, unsigned int holdtime, unsigned int *keycodes, - unsigned int nkeycodes); + unsigned int nkeycodes, + bool useQMP); typedef enum { BLOCK_JOB_ABORT, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 1bf8baf..43057fb 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -3372,11 +3372,65 @@ int qemuMonitorJSONSendKey(qemuMonitorPtr mon, unsigned int *keycodes, unsigned int nkeycodes) { - /* - * FIXME: qmp sendkey has not been implemented yet, - * and qmp API of it cannot be anticipated, so we use hmp temporary. - */ - return qemuMonitorTextSendKey(mon, holdtime, keycodes, nkeycodes); + int ret = -1; + virJSONValuePtr cmd = NULL; + virJSONValuePtr reply = NULL; + virJSONValuePtr keys = NULL; + virJSONValuePtr key = NULL; + unsigned int i; + + /* create the key data array */ + if (!(keys = virJSONValueNewArray())) + goto no_memory; + + for (i = 0; i < nkeycodes; i++) { + if (keycodes[i] > 0xffff) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("keycode %d is invalid: 0x%X"), i, keycodes[i]); + goto cleanup; + } + + /* create single key object */ + if (!(key = virJSONValueNewObject())) + goto no_memory; + + /* Union KeyValue has two, types, use the generic one */ + if (virJSONValueObjectAppendString(key, "type", "number") < 0) + goto no_memory; + + /* with the keycode */ + if (virJSONValueObjectAppendNumberInt(key, "data", keycodes[i]) < 0) + goto no_memory; + + if (virJSONValueArrayAppend(keys, key) < 0) + goto no_memory; + + key = NULL; + + } + + cmd = qemuMonitorJSONMakeCommand("send-key", + "a:keys", keys, + holdtime ? "U:hold-time" : NULL, holdtime, + NULL); + if (!cmd) + goto cleanup; + + if ((ret = qemuMonitorJSONCommand(mon, cmd, &reply)) < 0) + goto cleanup; + + ret = qemuMonitorJSONCheckError(cmd, reply); + +cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + virJSONValueFree(keys); + virJSONValueFree(key); + return ret; + +no_memory: + virReportOOMError(); + goto cleanup; } int qemuMonitorJSONScreendump(qemuMonitorPtr mon, -- 1.8.1.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list