[libvirt] [PATCH 10/13] qemu:send-key: Implement the driver methods

Lai Jiangshan laijs at cn.fujitsu.com
Wed May 25 09:37:52 UTC 2011


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);
+
+    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);
 
 #endif /* QEMU_MONITOR_TEXT_H */
-- 
1.7.4.4




More information about the libvir-list mailing list