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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 */
 };
 
 
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);
+            return -1;
+        }
+
+        if (i)
+            virBufferAddChar(&buf, '-');
+        virBufferAsprintf(&buf, "0x%02X", keycodes[i]);
+    }
+
+    if (holdtime)
+        virBufferAsprintf(&buf, " %u", holdtime);
+
+    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;
+}
+
 /* 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

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list


[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]