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 "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 */
|
||||
};
|
||||
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user