]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: send-key: Implement the driver methods
authorLai Jiangshan <laijs@cn.fujitsu.com>
Thu, 21 Jul 2011 07:55:56 +0000 (15:55 +0800)
committerDaniel Veillard <veillard@redhat.com>
Thu, 21 Jul 2011 07:58:31 +0000 (15:58 +0800)
qemu driver just accept xt_kbd codeset's keycode, so the lib virtkey
is used for translating keycodes from other codesets

src/qemu/qemu_driver.c
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_monitor_json.h
src/qemu/qemu_monitor_text.c
src/qemu/qemu_monitor_text.h

index cd65bcea86a66fc244794b1966622c3e1ece1c6b..e13b63b35c7d4a63b790a7368634b62f478caf8b 100644 (file)
@@ -87,6 +87,7 @@
 #include "configmake.h"
 #include "threadpool.h"
 #include "locking/lock_manager.h"
+#include "virkeycode.h"
 
 #define VIR_FROM_THIS VIR_FROM_QEMU
 
@@ -1849,6 +1850,75 @@ cleanup:
     return ret;
 }
 
+static int qemuDomainSendKey(virDomainPtr domain,
+                             unsigned int codeset,
+                             unsigned int holdtime,
+                             unsigned int *keycodes,
+                             int nkeycodes,
+                             unsigned int flags)
+{
+    struct qemud_driver *driver = domain->conn->privateData;
+    virDomainObjPtr vm = NULL;
+    int ret = -1;
+    qemuDomainObjPrivatePtr priv;
+
+    virCheckFlags(0, -1);
+
+    /* translate the keycode to XT_KBD for qemu driver */
+    if (codeset != VIR_KEYCODE_SET_XT_KBD) {
+        int i;
+        int keycode;
+
+        for (i = 0; i < nkeycodes; i++) {
+            keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_XT_KBD,
+                                               keycodes[i]);
+            if (keycode < 0) {
+                qemuReportError(VIR_ERR_INTERNAL_ERROR,
+             _("cannot translate keycode %u of %s codeset to xt_kbd keycode"),
+                                keycodes[i],
+                                virKeycodeSetTypeToString(codeset));
+                return -1;
+            }
+            keycodes[i] = keycode;
+        }
+    }
+
+    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;
+    }
+
+    priv = vm->privateData;
+
+    if (qemuDomainObjBeginJobWithDriver(driver, vm, QEMU_JOB_MODIFY) < 0)
+        goto cleanup;
+
+    if (!virDomainObjIsActive(vm)) {
+        qemuReportError(VIR_ERR_OPERATION_INVALID,
+                        "%s", _("domain is not running"));
+        goto cleanup;
+    }
+
+    ignore_value(qemuDomainObjEnterMonitorWithDriver(driver, vm));
+    ret = qemuMonitorSendKey(priv->mon, holdtime, keycodes, nkeycodes);
+    qemuDomainObjExitMonitorWithDriver(driver, vm);
+    if (qemuDomainObjEndJob(driver, vm) == 0) {
+        vm = NULL;
+        goto cleanup;
+    }
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    qemuDriverUnlock(driver);
+    return ret;
+}
+
 static int qemudDomainGetInfo(virDomainPtr dom,
                               virDomainInfoPtr info)
 {
@@ -8653,6 +8723,7 @@ static virDriver qemuDriver = {
     .domainMigratePerform3 = qemuDomainMigratePerform3, /* 0.9.2 */
     .domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
     .domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
+    .domainSendKey = qemuDomainSendKey, /* 0.9.4 */
 };
 
 
index 3a30a157b3a0204b651b75882aee90677d2772d4..016f8f0324519c3e817f315cc8ff92cfc0bf13e5 100644 (file)
@@ -2408,6 +2408,23 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon)
     return ret;
 }
 
+int qemuMonitorSendKey(qemuMonitorPtr mon,
+                       unsigned int holdtime,
+                       unsigned int *keycodes,
+                       unsigned int nkeycodes)
+{
+    int ret;
+
+    VIR_DEBUG("mon=%p, holdtime=%u, nkeycodes=%u",
+              mon, holdtime, nkeycodes);
+
+    if (mon->json)
+        ret = qemuMonitorJSONSendKey(mon, holdtime, keycodes, nkeycodes);
+    else
+        ret = qemuMonitorTextSendKey(mon, holdtime, keycodes, nkeycodes);
+    return ret;
+}
+
 int qemuMonitorScreendump(qemuMonitorPtr mon,
                           const char *file)
 {
index f246d21a085505a7b48ac732247902e519fd5fed..0419147bf35b098824bca483be098bb70e6527e5 100644 (file)
@@ -447,6 +447,11 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon);
 int qemuMonitorScreendump(qemuMonitorPtr mon,
                           const char *file);
 
+int qemuMonitorSendKey(qemuMonitorPtr mon,
+                       unsigned int holdtime,
+                       unsigned int *keycodes,
+                       unsigned int nkeycodes);
+
 /**
  * When running two dd process and using <> redirection, we need a
  * shell that will not truncate files.  These two strings serve that
index 4db2b78ebc91e7de62f85ca0299916abbb53e9a6..74863e978e01fe7b2d644ef007c786bfa6629401 100644 (file)
@@ -2695,6 +2695,21 @@ cleanup:
     return ret;
 }
 
+int qemuMonitorJSONSendKey(qemuMonitorPtr mon,
+                           unsigned int holdtime,
+                           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.
+     */
+    if (qemuMonitorCheckHMP(mon, "sendkey")) {
+        return qemuMonitorTextSendKey(mon, holdtime, keycodes, nkeycodes);
+    } else
+        return -1;
+}
+
 int qemuMonitorJSONScreendump(qemuMonitorPtr mon,
                               const char *file)
 {
index 380e26afa0edac6d95488211f1c29d87f5a1ce27..ddd121ee638868c302eadfb0436585db1c4b9569 100644 (file)
@@ -217,6 +217,11 @@ int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
 
 int qemuMonitorJSONInjectNMI(qemuMonitorPtr mon);
 
+int qemuMonitorJSONSendKey(qemuMonitorPtr mon,
+                           unsigned int holdtime,
+                           unsigned int *keycodes,
+                           unsigned int nkeycodes);
+
 int qemuMonitorJSONScreendump(qemuMonitorPtr mon,
                               const char *file);
 
index 0965a0886abb533f2d0d853a686304bfccc513a2..52b9a34e3ba6dc6d54f63f804453bb3f64e5e0ee 100644 (file)
@@ -2755,6 +2755,55 @@ fail:
     return -1;
 }
 
+int qemuMonitorTextSendKey(qemuMonitorPtr mon,
+                           unsigned int holdtime,
+                           unsigned int *keycodes,
+                           unsigned int nkeycodes)
+{
+    int i;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    char *cmd, *reply = NULL;
+
+    if (nkeycodes > VIR_DOMAIN_SEND_KEY_MAX_KEYS || nkeycodes == 0)
+        return -1;
+
+    virBufferAddLit(&buf, "sendkey ");
+    for (i = 0; i < nkeycodes; i++) {
+        if (keycodes[i] > 0xffff) {
+            qemuReportError(VIR_ERR_OPERATION_FAILED,
+                            _("keycode %d is invalid: 0x%X"),
+                            i, keycodes[i]);
+            virBufferFreeAndReset(&buf);
+            return -1;
+        }
+
+        if (i)
+            virBufferAddChar(&buf, '-');
+        virBufferAsprintf(&buf, "0x%02X", keycodes[i]);
+    }
+
+    if (holdtime)
+        virBufferAsprintf(&buf, " %u", holdtime);
+
+    if (virBufferError(&buf)) {
+        virReportOOMError();
+        return -1;
+    }
+
+    cmd = virBufferContentAndReset(&buf);
+    if (qemuMonitorHMPCommand(mon, cmd, &reply) < 0) {
+        qemuReportError(VIR_ERR_OPERATION_FAILED,
+                         _("failed to send key using command '%s'"),
+                         cmd);
+        VIR_FREE(cmd);
+        return -1;
+    }
+
+    VIR_FREE(cmd);
+    VIR_FREE(reply);
+    return 0;
+}
+
 /* Returns -1 on error, -2 if not supported */
 int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file)
 {
index e53f69352b2b17ae16284ee335676d5353b9723d..042e581440da14153280b49b17e4a41fd8c3804f 100644 (file)
@@ -211,6 +211,11 @@ int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
 
 int qemuMonitorTextInjectNMI(qemuMonitorPtr mon);
 
+int qemuMonitorTextSendKey(qemuMonitorPtr mon,
+                           unsigned int holdtime,
+                           unsigned int *keycodes,
+                           unsigned int nkeycodes);
+
 int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file);
 
 #endif /* QEMU_MONITOR_TEXT_H */