[libvirt] [PATCH v4 4/5] hyperv: support virDomainSendKey

Sri Ramanujam posted 5 patches 7 years, 12 months ago
[libvirt] [PATCH v4 4/5] hyperv: support virDomainSendKey
Posted by Sri Ramanujam 7 years, 12 months ago
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            | 107 ++++++++++++++++++++++++++++++++++
 src/hyperv/hyperv_wmi.c               |   7 +++
 src/hyperv/hyperv_wmi.h               |   3 +-
 src/hyperv/hyperv_wmi_generator.input |  86 +++++++++++++++++++++++++++
 4 files changed, 202 insertions(+), 1 deletion(-)

diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
index 0ca5971..a01515a 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,110 @@ 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 (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0)
+            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 (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0)
+            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 +1514,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 b847d17..2165838 100644
--- a/src/hyperv/hyperv_wmi.c
+++ b/src/hyperv/hyperv_wmi.c
@@ -1326,6 +1326,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 f39f79f..eb6f43d 100644
--- a/src/hyperv/hyperv_wmi.h
+++ b/src/hyperv/hyperv_wmi.h
@@ -217,7 +217,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@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH v4 4/5] hyperv: support virDomainSendKey
Posted by Matthias Bolte 7 years, 11 months ago
2017-05-19 22:58 GMT+02:00 Sri Ramanujam <sramanujam@datto.com>:
> 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            | 107 ++++++++++++++++++++++++++++++++++
>  src/hyperv/hyperv_wmi.c               |   7 +++
>  src/hyperv/hyperv_wmi.h               |   3 +-
>  src/hyperv/hyperv_wmi_generator.input |  86 +++++++++++++++++++++++++++
>  4 files changed, 202 insertions(+), 1 deletion(-)
>
> diff --git a/src/hyperv/hyperv_driver.c b/src/hyperv/hyperv_driver.c
> index 0ca5971..a01515a 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,110 @@ 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);

Shouldn't you check for params == NULL here?

> +        if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0)
> +            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);

Shouldn't you check for params == NULL here?

> +        if (hypervAddSimpleParam(params, "keyCode", keycodeStr) < 0)
> +            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 +1514,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 b847d17..2165838 100644
> --- a/src/hyperv/hyperv_wmi.c
> +++ b/src/hyperv/hyperv_wmi.c
> @@ -1326,6 +1326,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 f39f79f..eb6f43d 100644
> --- a/src/hyperv/hyperv_wmi.h
> +++ b/src/hyperv/hyperv_wmi.h
> @@ -217,7 +217,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@redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list



-- 
Matthias Bolte
http://photron.blogspot.com

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list