1
0
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:
Lai Jiangshan 2011-07-21 15:55:56 +08:00 committed by Daniel Veillard
parent 7818b7ef85
commit e40725779c
7 changed files with 167 additions and 0 deletions

View 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 */
};

View 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)
{

View 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

View 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)
{

View 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);

View 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)
{

View 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 */