This commit adds support for virDomainSendKey. It also serves as an example of how to use the new method invocation APIs with a single "simple" type parameter. --- src/hyperv/hyperv_driver.c | 123 ++++++++++++++++++++++++++++++++++ src/hyperv/hyperv_wmi.c | 7 ++ src/hyperv/hyperv_wmi.h | 3 +- src/hyperv/hyperv_wmi_generator.input | 86 ++++++++++++++++++++++++ 4 files changed, 218 insertions(+), 1 deletion(-) diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c index 0ca5971..7ee3d9a 100644 --- a/src/hyperv/hyperv_driver.c +++ b/src/hyperv/hyperv_driver.c @@ -35,6 +35,8 @@ #include "hyperv_wmi.h" #include "openwsman.h" #include "virstring.h" +#include "virkeycode.h" +#include "intprops.h" #define VIR_FROM_THIS VIR_FROM_HYPERV @@ -1373,6 +1375,126 @@ hypervConnectListAllDomains(virConnectPtr conn, #undef MATCH +static int +hypervDomainSendKey(virDomainPtr domain, unsigned int codeset, + unsigned int holdtime, unsigned int *keycodes, int nkeycodes, + unsigned int flags) +{ + int result = -1; + size_t i = 0; + int keycode = 0; + int *translatedKeycodes = NULL; + hypervPrivate *priv = domain->conn->privateData; + char uuid_string[VIR_UUID_STRING_BUFLEN]; + char *selector = NULL; + Msvm_ComputerSystem *computerSystem = NULL; + Msvm_Keyboard *keyboard = NULL; + virBuffer query = VIR_BUFFER_INITIALIZER; + hypervInvokeParamsListPtr params = NULL; + char keycodeStr[INT_BUFSIZE_BOUND(int)]; + + virCheckFlags(0, -1); + + virUUIDFormat(domain->uuid, uuid_string); + + if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) + goto cleanup; + + virBufferAsprintf(&query, + "associators of " + "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\"," + "Name=\"%s\"} " + "where ResultClass = Msvm_Keyboard", + uuid_string); + + if (hypervGetMsvmKeyboardList(priv, &query, &keyboard) < 0) + goto cleanup; + + if (VIR_ALLOC_N(translatedKeycodes, nkeycodes) < 0) + goto cleanup; + + /* translate keycodes to win32 and generate keyup scancodes. */ + for (i = 0; i < nkeycodes; i++) { + if (codeset != VIR_KEYCODE_SET_WIN32) { + keycode = virKeycodeValueTranslate(codeset, VIR_KEYCODE_SET_WIN32, + keycodes[i]); + + if (keycode < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Could not translate keycode")); + goto cleanup; + } + translatedKeycodes[i] = keycode; + } + } + + if (virAsprintf(&selector, + "CreationClassName=Msvm_Keyboard&DeviceID=%s&" + "SystemCreationClassName=Msvm_ComputerSystem&" + "SystemName=%s", keyboard->data.common->DeviceID, uuid_string) < 0) + goto cleanup; + + /* press the keys */ + for (i = 0; i < nkeycodes; i++) { + snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]); + + params = hypervCreateInvokeParamsList(priv, "PressKey", selector, + Msvm_Keyboard_WmiInfo); + + if (!params) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create param")); + goto cleanup; + } + + if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0) { + hypervFreeInvokeParams(params); + goto cleanup; + } + + if (hypervInvokeMethod(priv, params, NULL) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not press key %d"), + translatedKeycodes[i]); + goto cleanup; + } + } + + /* simulate holdtime by sleeping */ + if (holdtime > 0) + usleep(holdtime * 1000); + + /* release the keys */ + for (i = 0; i < nkeycodes; i++) { + snprintf(keycodeStr, sizeof(keycodeStr), "%d", translatedKeycodes[i]); + params = hypervCreateInvokeParamsList(priv, "ReleaseKey", selector, + Msvm_Keyboard_WmiInfo); + + if (!params) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Could not create param")); + goto cleanup; + } + + if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0) { + hypervFreeInvokeParams(params); + goto cleanup; + } + + if (hypervInvokeMethod(priv, params, NULL) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not release key %s"), + keycodeStr); + goto cleanup; + } + } + + result = 0; + + cleanup: + VIR_FREE(translatedKeycodes); + VIR_FREE(selector); + hypervFreeObject(priv, (hypervObject *) keyboard); + hypervFreeObject(priv, (hypervObject *) computerSystem); + virBufferFreeAndReset(&query); + return result; +} static virHypervisorDriver hypervHypervisorDriver = { @@ -1408,6 +1530,7 @@ static virHypervisorDriver hypervHypervisorDriver = { .domainManagedSave = hypervDomainManagedSave, /* 0.9.5 */ .domainHasManagedSaveImage = hypervDomainHasManagedSaveImage, /* 0.9.5 */ .domainManagedSaveRemove = hypervDomainManagedSaveRemove, /* 0.9.5 */ + .domainSendKey = hypervDomainSendKey, /* TODO: version */ .connectIsAlive = hypervConnectIsAlive, /* 0.9.8 */ }; diff --git a/src/hyperv/hyperv_wmi.c b/src/hyperv/hyperv_wmi.c index f944b14..36d3c2e 100644 --- a/src/hyperv/hyperv_wmi.c +++ b/src/hyperv/hyperv_wmi.c @@ -1342,6 +1342,13 @@ hypervGetMsvmMemorySettingDataList(hypervPrivate *priv, virBufferPtr query, (hypervObject **) list); } +int hypervGetMsvmKeyboardList(hypervPrivate *priv, virBufferPtr query, + Msvm_Keyboard **list) +{ + return hypervGetWmiClassList(priv, Msvm_Keyboard_WmiInfo, query, + (hypervObject **) list); +} + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * diff --git a/src/hyperv/hyperv_wmi.h b/src/hyperv/hyperv_wmi.h index 25cc470..5c9da04 100644 --- a/src/hyperv/hyperv_wmi.h +++ b/src/hyperv/hyperv_wmi.h @@ -219,7 +219,8 @@ int hypervGetMsvmProcessorSettingDataList(hypervPrivate *priv, int hypervGetMsvmMemorySettingDataList(hypervPrivate *priv, virBufferPtr query, Msvm_MemorySettingData **list); - +int hypervGetMsvmKeyboardList(hypervPrivate *priv, virBufferPtr query, + Msvm_Keyboard **list); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Msvm_ComputerSystem diff --git a/src/hyperv/hyperv_wmi_generator.input b/src/hyperv/hyperv_wmi_generator.input index d7f819e..4ccda04 100644 --- a/src/hyperv/hyperv_wmi_generator.input +++ b/src/hyperv/hyperv_wmi_generator.input @@ -956,3 +956,89 @@ class Msvm_VirtualHardDiskSettingData uint32 PhysicalSectorSize string VirtualDiskId end + +class Msvm_Keyboard + string Caption + string Description + string ElementName + datetime InstallDate + string Name + uint16 OperationalStatus[] + string StatusDescriptions[] + string Status + uint16 HealthState + uint16 EnabledState + string OtherEnabledState + uint16 RequestedState + uint16 EnabledDefault + datetime TimeOfLastStateChange + string SystemCreationClassName + string SystemName + string CreationClassName + string DeviceID + boolean PowerManagementSupported + uint16 PowerManagementCapabilities[] + uint16 Availability + uint16 StatusInfo + uint32 LastErrorCode + string ErrorDescription + boolean ErrorCleared + string OtherIdentifyingInfo[] + uint64 PowerOnHours + uint64 TotalPowerOnHours + string IdentifyingDescriptions[] + uint16 AdditionalAvailability[] + uint64 MaxQuiesceTime + uint16 LocationIndicator + boolean IsLocked + string Layout + uint16 NumberOfFunctionKeys + uint16 Password +end + + +class v2/Msvm_Keyboard + string InstanceID + string Caption + string Description + string ElementName + datetime InstallDate + string Name + uint16 OperationalStatus[] + string StatusDescriptions[] + string Status + uint16 HealthState + uint16 CommunicationStatus + uint16 DetailedStatus + uint16 OperatingStatus + uint16 PrimaryStatus + uint16 EnabledState + string OtherEnabledState + uint16 RequestedState + uint16 EnabledDefault + datetime TimeOfLastStateChange + uint16 AvailableRequestedStates[] + uint16 TransitioningToState + string SystemCreationClassName + string SystemName + string CreationClassName + string DeviceID + boolean PowerManagementSupported + uint16 PowerManagementCapabilities[] + uint16 Availability + uint16 StatusInfo + uint32 LastErrorCode + string ErrorDescription + boolean ErrorCleared + string OtherIdentifyingInfo[] + uint64 PowerOnHours + uint64 TotalPowerOnHours + string IdentifyingDescriptions[] + uint16 AdditionalAvailability[] + uint64 MaxQuiesceTime + boolean IsLocked + string Layout + uint16 NumberOfFunctionKeys + uint16 Password + boolean UnicodeSupported +end -- 2.9.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list