mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-07 17:28:15 +00:00
qemu: send-key: Implement the driver methods
qemu driver just accept xt_kbd codeset's keycode, so the lib virtkey is used for translating keycodes from other codesets
This commit is contained in:
parent
7818b7ef85
commit
e40725779c
@ -87,6 +87,7 @@
|
|||||||
#include "configmake.h"
|
#include "configmake.h"
|
||||||
#include "threadpool.h"
|
#include "threadpool.h"
|
||||||
#include "locking/lock_manager.h"
|
#include "locking/lock_manager.h"
|
||||||
|
#include "virkeycode.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_QEMU
|
#define VIR_FROM_THIS VIR_FROM_QEMU
|
||||||
|
|
||||||
@ -1849,6 +1850,75 @@ cleanup:
|
|||||||
return ret;
|
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,
|
static int qemudDomainGetInfo(virDomainPtr dom,
|
||||||
virDomainInfoPtr info)
|
virDomainInfoPtr info)
|
||||||
{
|
{
|
||||||
@ -8653,6 +8723,7 @@ static virDriver qemuDriver = {
|
|||||||
.domainMigratePerform3 = qemuDomainMigratePerform3, /* 0.9.2 */
|
.domainMigratePerform3 = qemuDomainMigratePerform3, /* 0.9.2 */
|
||||||
.domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
|
.domainMigrateFinish3 = qemuDomainMigrateFinish3, /* 0.9.2 */
|
||||||
.domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
|
.domainMigrateConfirm3 = qemuDomainMigrateConfirm3, /* 0.9.2 */
|
||||||
|
.domainSendKey = qemuDomainSendKey, /* 0.9.4 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2408,6 +2408,23 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon)
|
|||||||
return ret;
|
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,
|
int qemuMonitorScreendump(qemuMonitorPtr mon,
|
||||||
const char *file)
|
const char *file)
|
||||||
{
|
{
|
||||||
|
@ -447,6 +447,11 @@ int qemuMonitorInjectNMI(qemuMonitorPtr mon);
|
|||||||
int qemuMonitorScreendump(qemuMonitorPtr mon,
|
int qemuMonitorScreendump(qemuMonitorPtr mon,
|
||||||
const char *file);
|
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
|
* When running two dd process and using <> redirection, we need a
|
||||||
* shell that will not truncate files. These two strings serve that
|
* shell that will not truncate files. These two strings serve that
|
||||||
|
@ -2695,6 +2695,21 @@ cleanup:
|
|||||||
return ret;
|
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,
|
int qemuMonitorJSONScreendump(qemuMonitorPtr mon,
|
||||||
const char *file)
|
const char *file)
|
||||||
{
|
{
|
||||||
|
@ -217,6 +217,11 @@ int qemuMonitorJSONArbitraryCommand(qemuMonitorPtr mon,
|
|||||||
|
|
||||||
int qemuMonitorJSONInjectNMI(qemuMonitorPtr mon);
|
int qemuMonitorJSONInjectNMI(qemuMonitorPtr mon);
|
||||||
|
|
||||||
|
int qemuMonitorJSONSendKey(qemuMonitorPtr mon,
|
||||||
|
unsigned int holdtime,
|
||||||
|
unsigned int *keycodes,
|
||||||
|
unsigned int nkeycodes);
|
||||||
|
|
||||||
int qemuMonitorJSONScreendump(qemuMonitorPtr mon,
|
int qemuMonitorJSONScreendump(qemuMonitorPtr mon,
|
||||||
const char *file);
|
const char *file);
|
||||||
|
|
||||||
|
@ -2755,6 +2755,55 @@ fail:
|
|||||||
return -1;
|
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 */
|
/* Returns -1 on error, -2 if not supported */
|
||||||
int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file)
|
int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file)
|
||||||
{
|
{
|
||||||
|
@ -211,6 +211,11 @@ int qemuMonitorTextArbitraryCommand(qemuMonitorPtr mon, const char *cmd,
|
|||||||
|
|
||||||
int qemuMonitorTextInjectNMI(qemuMonitorPtr mon);
|
int qemuMonitorTextInjectNMI(qemuMonitorPtr mon);
|
||||||
|
|
||||||
|
int qemuMonitorTextSendKey(qemuMonitorPtr mon,
|
||||||
|
unsigned int holdtime,
|
||||||
|
unsigned int *keycodes,
|
||||||
|
unsigned int nkeycodes);
|
||||||
|
|
||||||
int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file);
|
int qemuMonitorTextScreendump(qemuMonitorPtr mon, const char *file);
|
||||||
|
|
||||||
#endif /* QEMU_MONITOR_TEXT_H */
|
#endif /* QEMU_MONITOR_TEXT_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user