Monitor patches for 2023-01-19
-----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEENUvIs9frKmtoZ05fOHC0AOuRhlMFAmPJO+8SHGFybWJydUBy ZWRoYXQuY29tAAoJEDhwtADrkYZTbBwP/RsZLLDCz6moSet4Hly+vPTWibyYYDkS uk6a70Ja7fsAcONumBaXdpoinPtbED662eYxidbLFr//tAjnKu57jnwAIFTTOKJc sCVtdgOlbNSZFrqyIr8ctY6yKJLLBaa02in/BczFIQphPatpUwvxrvrdgxc58NNK qaeKDnWKXvZ6EUaYPpruxqE5J/NV0ykyab9Rc8rNJqdUMnqbd662zHcA0l31misH gAfKBhReo53XUbfvoFS9kaoBQaTJPk4CcKHaT7NJXR8ezlIEQVLtFzdfAf04kSdG 8VRwwx5NDpmafATEaMXJhJ74Fyc8biDWXoQ6aA1jdUCu39B2EPl1H1qlCG9ZYp7w CkbJU6UwtOYsG11NU8Mr1u9rMlAgAVkkLsMYiiI4cpLBkI0vkoV66ms3oZgYUtbq /TgCpfjKpE87ZBLIwJjGsg+TMN2AH5lpt/49HV8QEFA8mI7h29oo2HvheXE7PPzH b9iIe9ADrKwB5DpJW2vigPj+fSHqoSGd3R/hUcMVOubKnJme97mys2hD+sfxga/H qfKLzgTqQI2dGhfow/8wzfYdfYmkii+ggDyzcxLAxx2ITO/fLWJygmTgXJmA3dl6 pnpZvhOu4dEgK4VstugXcvgCVHUVXd9wqI9wxJAc+mKanTmZIJBnxCm/QVG2/w/d 5IgmP9Se7vb0 =7OEC -----END PGP SIGNATURE----- Merge tag 'pull-monitor-2023-01-19' of https://repo.or.cz/qemu/armbru into staging Monitor patches for 2023-01-19 # -----BEGIN PGP SIGNATURE----- # # iQJGBAABCAAwFiEENUvIs9frKmtoZ05fOHC0AOuRhlMFAmPJO+8SHGFybWJydUBy # ZWRoYXQuY29tAAoJEDhwtADrkYZTbBwP/RsZLLDCz6moSet4Hly+vPTWibyYYDkS # uk6a70Ja7fsAcONumBaXdpoinPtbED662eYxidbLFr//tAjnKu57jnwAIFTTOKJc # sCVtdgOlbNSZFrqyIr8ctY6yKJLLBaa02in/BczFIQphPatpUwvxrvrdgxc58NNK # qaeKDnWKXvZ6EUaYPpruxqE5J/NV0ykyab9Rc8rNJqdUMnqbd662zHcA0l31misH # gAfKBhReo53XUbfvoFS9kaoBQaTJPk4CcKHaT7NJXR8ezlIEQVLtFzdfAf04kSdG # 8VRwwx5NDpmafATEaMXJhJ74Fyc8biDWXoQ6aA1jdUCu39B2EPl1H1qlCG9ZYp7w # CkbJU6UwtOYsG11NU8Mr1u9rMlAgAVkkLsMYiiI4cpLBkI0vkoV66ms3oZgYUtbq # /TgCpfjKpE87ZBLIwJjGsg+TMN2AH5lpt/49HV8QEFA8mI7h29oo2HvheXE7PPzH # b9iIe9ADrKwB5DpJW2vigPj+fSHqoSGd3R/hUcMVOubKnJme97mys2hD+sfxga/H # qfKLzgTqQI2dGhfow/8wzfYdfYmkii+ggDyzcxLAxx2ITO/fLWJygmTgXJmA3dl6 # pnpZvhOu4dEgK4VstugXcvgCVHUVXd9wqI9wxJAc+mKanTmZIJBnxCm/QVG2/w/d # 5IgmP9Se7vb0 # =7OEC # -----END PGP SIGNATURE----- # gpg: Signature made Thu 19 Jan 2023 12:47:43 GMT # gpg: using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653 # gpg: issuer "armbru@redhat.com" # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full] # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" [full] # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * tag 'pull-monitor-2023-01-19' of https://repo.or.cz/qemu/armbru: ui: Simplify control flow in qemu_mouse_set() ui: Split hmp_mouse_set() and move the HMP part to ui/ ui: Don't check for mode change after mouse_set error ui: Reduce nesting in hmp_change_vnc() slightly ui: Factor out hmp_change_vnc(), and move to ui/ui-hmp-cmds.c ui: Improve "change vnc" error reporting ui: Move HMP commands from monitor to new ui/ui-hmp-cmds.c ui: Factor out qmp_add_client() parts and move to ui/ui-qmp-cmds.c ui: Move QMP commands from monitor to new ui/ui-qmp-cmds.c ui: Clean up a few things checkpatch.pl would flag later on ui/spice: Give hmp_info_spice()'s channel_names[] static linkage ui/spice: QXLInterface method set_mm_time() is now dead, drop ui/spice: Require spice-server >= 0.14.0 Revert "hmp: info spice: take out webdav" ui/spice: Require spice-protocol >= 0.14.0 ui: Fix silent truncation of numeric keys in HMP sendkey ui: Check numeric part of expire_password argument @time properly Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
70d17c3eed
@ -98,9 +98,7 @@ static SpiceCharDeviceInterface vmc_interface = {
|
||||
.write = vmc_write,
|
||||
.read = vmc_read,
|
||||
.event = vmc_event,
|
||||
#if SPICE_SERVER_VERSION >= 0x000c06
|
||||
.flags = SPICE_CHAR_DEVICE_NOTIFY_WRITABLE,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -260,8 +260,7 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay)
|
||||
QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG,
|
||||
0));
|
||||
} else {
|
||||
/* >= release 0.12.6, < release 0.14.2 */
|
||||
#if SPICE_SERVER_VERSION >= 0x000c06 && SPICE_SERVER_VERSION < 0x000e02
|
||||
#if SPICE_SERVER_VERSION < 0x000e02 /* release 0.14.2 */
|
||||
if (qxl->max_outputs) {
|
||||
spice_qxl_set_max_monitors(&qxl->ssd.qxl, qxl->max_outputs);
|
||||
}
|
||||
@ -544,22 +543,6 @@ static void interface_set_compression_level(QXLInstance *sin, int level)
|
||||
qxl_rom_set_dirty(qxl);
|
||||
}
|
||||
|
||||
#if SPICE_NEEDS_SET_MM_TIME
|
||||
static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
|
||||
{
|
||||
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
|
||||
|
||||
if (!qemu_spice_display_is_running(&qxl->ssd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
trace_qxl_interface_set_mm_time(qxl->id, mm_time);
|
||||
qxl->shadow_rom.mm_clock = cpu_to_le32(mm_time);
|
||||
qxl->rom->mm_clock = cpu_to_le32(mm_time);
|
||||
qxl_rom_set_dirty(qxl);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
|
||||
{
|
||||
PCIQXLDevice *qxl = container_of(sin, PCIQXLDevice, ssd.qxl);
|
||||
@ -1089,12 +1072,10 @@ static int interface_client_monitors_config(QXLInstance *sin,
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
|
||||
/* limit number of outputs based on setting limit */
|
||||
if (qxl->max_outputs && qxl->max_outputs <= max_outputs) {
|
||||
max_outputs = qxl->max_outputs;
|
||||
}
|
||||
#endif
|
||||
|
||||
config_changed = qxl_rom_monitors_config_changed(rom,
|
||||
monitors_config,
|
||||
@ -1148,9 +1129,6 @@ static const QXLInterface qxl_interface = {
|
||||
#endif
|
||||
|
||||
.set_compression_level = interface_set_compression_level,
|
||||
#if SPICE_NEEDS_SET_MM_TIME
|
||||
.set_mm_time = interface_set_mm_time,
|
||||
#endif
|
||||
.get_init_info = interface_get_init_info,
|
||||
|
||||
/* the callbacks below are called from spice server thread context */
|
||||
@ -2487,9 +2465,7 @@ static Property qxl_properties[] = {
|
||||
DEFINE_PROP_UINT32("vram64_size_mb", PCIQXLDevice, vram_size_mb, -1),
|
||||
DEFINE_PROP_UINT32("vgamem_mb", PCIQXLDevice, vgamem_size_mb, 16),
|
||||
DEFINE_PROP_INT32("surfaces", PCIQXLDevice, ssd.num_surfaces, 1024),
|
||||
#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
|
||||
DEFINE_PROP_UINT16("max_outputs", PCIQXLDevice, max_outputs, 0),
|
||||
#endif
|
||||
DEFINE_PROP_UINT32("xres", PCIQXLDevice, xres, 0),
|
||||
DEFINE_PROP_UINT32("yres", PCIQXLDevice, yres, 0),
|
||||
DEFINE_PROP_BOOL("global-vmstate", PCIQXLDevice, vga.global_vmstate, false),
|
||||
|
@ -99,9 +99,7 @@ struct PCIQXLDevice {
|
||||
QXLModes *modes;
|
||||
uint32_t rom_size;
|
||||
MemoryRegion rom_bar;
|
||||
#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */
|
||||
uint16_t max_outputs;
|
||||
#endif
|
||||
|
||||
/* vram pci bar */
|
||||
uint64_t vram_size;
|
||||
|
@ -55,7 +55,6 @@ virtio_gpu_fence_ctrl(uint64_t fence, uint32_t type) "fence 0x%" PRIx64 ", type
|
||||
virtio_gpu_fence_resp(uint64_t fence) "fence 0x%" PRIx64
|
||||
|
||||
# qxl.c
|
||||
disable qxl_interface_set_mm_time(int qid, uint32_t mm_time) "%d %d"
|
||||
disable qxl_io_write_vga(int qid, const char *mode, uint32_t addr, uint32_t val) "%d %s addr=%u val=%u"
|
||||
qxl_create_guest_primary(int qid, uint32_t width, uint32_t height, uint64_t mem, uint32_t format, uint32_t position) "%d %ux%u mem=0x%" PRIx64 " %u,%u"
|
||||
qxl_create_guest_primary_rest(int qid, int32_t stride, uint32_t type, uint32_t flags) "%d %d,%d,%d"
|
||||
|
@ -73,6 +73,11 @@ void hmp_x_colo_lost_heartbeat(Monitor *mon, const QDict *qdict);
|
||||
void hmp_set_password(Monitor *mon, const QDict *qdict);
|
||||
void hmp_expire_password(Monitor *mon, const QDict *qdict);
|
||||
void hmp_change(Monitor *mon, const QDict *qdict);
|
||||
#ifdef CONFIG_VNC
|
||||
void hmp_change_vnc(Monitor *mon, const char *device, const char *target,
|
||||
const char *arg, const char *read_only, bool force,
|
||||
Error **errp);
|
||||
#endif
|
||||
void hmp_migrate(Monitor *mon, const QDict *qdict);
|
||||
void hmp_device_add(Monitor *mon, const QDict *qdict);
|
||||
void hmp_device_del(Monitor *mon, const QDict *qdict);
|
||||
@ -81,6 +86,9 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict);
|
||||
void hmp_netdev_del(Monitor *mon, const QDict *qdict);
|
||||
void hmp_getfd(Monitor *mon, const QDict *qdict);
|
||||
void hmp_closefd(Monitor *mon, const QDict *qdict);
|
||||
void hmp_mouse_move(Monitor *mon, const QDict *qdict);
|
||||
void hmp_mouse_button(Monitor *mon, const QDict *qdict);
|
||||
void hmp_mouse_set(Monitor *mon, const QDict *qdict);
|
||||
void hmp_sendkey(Monitor *mon, const QDict *qdict);
|
||||
void coroutine_fn hmp_screendump(Monitor *mon, const QDict *qdict);
|
||||
void hmp_chardev_add(Monitor *mon, const QDict *qdict);
|
||||
|
26
include/monitor/qmp-helpers.h
Normal file
26
include/monitor/qmp-helpers.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* QMP command helpers
|
||||
*
|
||||
* Copyright (c) 2022 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Markus Armbruster <armbru@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef MONITOR_QMP_HELPERS_H
|
||||
|
||||
bool qmp_add_client_spice(int fd, bool has_skipauth, bool skipauth,
|
||||
bool has_tls, bool tls, Error **errp);
|
||||
#ifdef CONFIG_VNC
|
||||
bool qmp_add_client_vnc(int fd, bool has_skipauth, bool skipauth,
|
||||
bool has_tls, bool tls, Error **errp);
|
||||
#endif
|
||||
#ifdef CONFIG_DBUS_DISPLAY
|
||||
bool qmp_add_client_dbus_display(int fd, bool has_skipauth, bool skipauth,
|
||||
bool has_tls, bool tls, Error **errp);
|
||||
#endif
|
||||
|
||||
#endif
|
@ -65,7 +65,7 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry);
|
||||
|
||||
void kbd_put_ledstate(int ledstate);
|
||||
|
||||
void hmp_mouse_set(Monitor *mon, const QDict *qdict);
|
||||
bool qemu_mouse_set(int index, Error **errp);
|
||||
|
||||
/* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
|
||||
constants) */
|
||||
|
@ -34,13 +34,7 @@ int qemu_spice_add_display_interface(QXLInstance *qxlin, QemuConsole *con);
|
||||
int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
|
||||
const char *subject);
|
||||
|
||||
#if !defined(SPICE_SERVER_VERSION) || (SPICE_SERVER_VERSION < 0xc06)
|
||||
#define SPICE_NEEDS_SET_MM_TIME 1
|
||||
#else
|
||||
#define SPICE_NEEDS_SET_MM_TIME 0
|
||||
#endif
|
||||
|
||||
#if defined(SPICE_SERVER_VERSION) && (SPICE_SERVER_VERSION >= 0x000f00)
|
||||
#if SPICE_SERVER_VERSION >= 0x000f00 /* release 0.15.0 */
|
||||
#define SPICE_HAS_ATTACHED_WORKER 1
|
||||
#else
|
||||
#define SPICE_HAS_ATTACHED_WORKER 0
|
||||
|
@ -28,11 +28,9 @@
|
||||
#include "ui/console.h"
|
||||
|
||||
#if defined(CONFIG_OPENGL) && defined(CONFIG_GBM)
|
||||
# if SPICE_SERVER_VERSION >= 0x000d01 /* release 0.13.1 */
|
||||
# define HAVE_SPICE_GL 1
|
||||
# include "ui/egl-helpers.h"
|
||||
# include "ui/egl-context.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define NUM_MEMSLOTS 8
|
||||
|
@ -742,13 +742,13 @@ endif
|
||||
|
||||
spice_protocol = not_found
|
||||
if not get_option('spice_protocol').auto() or have_system
|
||||
spice_protocol = dependency('spice-protocol', version: '>=0.12.3',
|
||||
spice_protocol = dependency('spice-protocol', version: '>=0.14.0',
|
||||
required: get_option('spice_protocol'),
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
endif
|
||||
spice = not_found
|
||||
if not get_option('spice').auto() or have_system
|
||||
spice = dependency('spice-server', version: '>=0.12.5',
|
||||
spice = dependency('spice-server', version: '>=0.14.0',
|
||||
required: get_option('spice'),
|
||||
method: 'pkg-config', kwargs: static_kwargs)
|
||||
endif
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/sockets.h"
|
||||
#include "qemu/help_option.h"
|
||||
#include "monitor/monitor-internal.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/clone-visitor.h"
|
||||
#include "qapi/opts-visitor.h"
|
||||
@ -41,7 +41,6 @@
|
||||
#include "qapi/qapi-commands-run-state.h"
|
||||
#include "qapi/qapi-commands-stats.h"
|
||||
#include "qapi/qapi-commands-tpm.h"
|
||||
#include "qapi/qapi-commands-ui.h"
|
||||
#include "qapi/qapi-commands-virtio.h"
|
||||
#include "qapi/qapi-visit-virtio.h"
|
||||
#include "qapi/qapi-visit-net.h"
|
||||
@ -51,7 +50,6 @@
|
||||
#include "qapi/string-input-visitor.h"
|
||||
#include "qapi/string-output-visitor.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "ui/console.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/core/cpu.h"
|
||||
@ -59,10 +57,6 @@
|
||||
#include "migration/snapshot.h"
|
||||
#include "migration/misc.h"
|
||||
|
||||
#ifdef CONFIG_SPICE
|
||||
#include <spice/enums.h>
|
||||
#endif
|
||||
|
||||
bool hmp_handle_error(Monitor *mon, Error *err)
|
||||
{
|
||||
if (err) {
|
||||
@ -178,26 +172,6 @@ void hmp_info_chardev(Monitor *mon, const QDict *qdict)
|
||||
qapi_free_ChardevInfoList(char_info);
|
||||
}
|
||||
|
||||
void hmp_info_mice(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
MouseInfoList *mice_list, *mouse;
|
||||
|
||||
mice_list = qmp_query_mice(NULL);
|
||||
if (!mice_list) {
|
||||
monitor_printf(mon, "No mouse devices connected\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (mouse = mice_list; mouse; mouse = mouse->next) {
|
||||
monitor_printf(mon, "%c Mouse #%" PRId64 ": %s%s\n",
|
||||
mouse->value->current ? '*' : ' ',
|
||||
mouse->value->index, mouse->value->name,
|
||||
mouse->value->absolute ? " (absolute)" : "");
|
||||
}
|
||||
|
||||
qapi_free_MouseInfoList(mice_list);
|
||||
}
|
||||
|
||||
void hmp_info_migrate(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
MigrationInfo *info;
|
||||
@ -516,172 +490,6 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
|
||||
qapi_free_MigrationParameters(params);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_VNC
|
||||
/* Helper for hmp_info_vnc_clients, _servers */
|
||||
static void hmp_info_VncBasicInfo(Monitor *mon, VncBasicInfo *info,
|
||||
const char *name)
|
||||
{
|
||||
monitor_printf(mon, " %s: %s:%s (%s%s)\n",
|
||||
name,
|
||||
info->host,
|
||||
info->service,
|
||||
NetworkAddressFamily_str(info->family),
|
||||
info->websocket ? " (Websocket)" : "");
|
||||
}
|
||||
|
||||
/* Helper displaying and auth and crypt info */
|
||||
static void hmp_info_vnc_authcrypt(Monitor *mon, const char *indent,
|
||||
VncPrimaryAuth auth,
|
||||
VncVencryptSubAuth *vencrypt)
|
||||
{
|
||||
monitor_printf(mon, "%sAuth: %s (Sub: %s)\n", indent,
|
||||
VncPrimaryAuth_str(auth),
|
||||
vencrypt ? VncVencryptSubAuth_str(*vencrypt) : "none");
|
||||
}
|
||||
|
||||
static void hmp_info_vnc_clients(Monitor *mon, VncClientInfoList *client)
|
||||
{
|
||||
while (client) {
|
||||
VncClientInfo *cinfo = client->value;
|
||||
|
||||
hmp_info_VncBasicInfo(mon, qapi_VncClientInfo_base(cinfo), "Client");
|
||||
monitor_printf(mon, " x509_dname: %s\n",
|
||||
cinfo->x509_dname ?: "none");
|
||||
monitor_printf(mon, " sasl_username: %s\n",
|
||||
cinfo->sasl_username ?: "none");
|
||||
|
||||
client = client->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void hmp_info_vnc_servers(Monitor *mon, VncServerInfo2List *server)
|
||||
{
|
||||
while (server) {
|
||||
VncServerInfo2 *sinfo = server->value;
|
||||
hmp_info_VncBasicInfo(mon, qapi_VncServerInfo2_base(sinfo), "Server");
|
||||
hmp_info_vnc_authcrypt(mon, " ", sinfo->auth,
|
||||
sinfo->has_vencrypt ? &sinfo->vencrypt : NULL);
|
||||
server = server->next;
|
||||
}
|
||||
}
|
||||
|
||||
void hmp_info_vnc(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
VncInfo2List *info2l, *info2l_head;
|
||||
Error *err = NULL;
|
||||
|
||||
info2l = qmp_query_vnc_servers(&err);
|
||||
info2l_head = info2l;
|
||||
if (hmp_handle_error(mon, err)) {
|
||||
return;
|
||||
}
|
||||
if (!info2l) {
|
||||
monitor_printf(mon, "None\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (info2l) {
|
||||
VncInfo2 *info = info2l->value;
|
||||
monitor_printf(mon, "%s:\n", info->id);
|
||||
hmp_info_vnc_servers(mon, info->server);
|
||||
hmp_info_vnc_clients(mon, info->clients);
|
||||
if (!info->server) {
|
||||
/* The server entry displays its auth, we only
|
||||
* need to display in the case of 'reverse' connections
|
||||
* where there's no server.
|
||||
*/
|
||||
hmp_info_vnc_authcrypt(mon, " ", info->auth,
|
||||
info->has_vencrypt ? &info->vencrypt : NULL);
|
||||
}
|
||||
if (info->display) {
|
||||
monitor_printf(mon, " Display: %s\n", info->display);
|
||||
}
|
||||
info2l = info2l->next;
|
||||
}
|
||||
|
||||
qapi_free_VncInfo2List(info2l_head);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPICE
|
||||
void hmp_info_spice(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
SpiceChannelList *chan;
|
||||
SpiceInfo *info;
|
||||
const char *channel_name;
|
||||
const char * const channel_names[] = {
|
||||
[SPICE_CHANNEL_MAIN] = "main",
|
||||
[SPICE_CHANNEL_DISPLAY] = "display",
|
||||
[SPICE_CHANNEL_INPUTS] = "inputs",
|
||||
[SPICE_CHANNEL_CURSOR] = "cursor",
|
||||
[SPICE_CHANNEL_PLAYBACK] = "playback",
|
||||
[SPICE_CHANNEL_RECORD] = "record",
|
||||
[SPICE_CHANNEL_TUNNEL] = "tunnel",
|
||||
[SPICE_CHANNEL_SMARTCARD] = "smartcard",
|
||||
[SPICE_CHANNEL_USBREDIR] = "usbredir",
|
||||
[SPICE_CHANNEL_PORT] = "port",
|
||||
#if 0
|
||||
/* minimum spice-protocol is 0.12.3, webdav was added in 0.12.7,
|
||||
* no easy way to #ifdef (SPICE_CHANNEL_* is a enum). Disable
|
||||
* as quick fix for build failures with older versions. */
|
||||
[SPICE_CHANNEL_WEBDAV] = "webdav",
|
||||
#endif
|
||||
};
|
||||
|
||||
info = qmp_query_spice(NULL);
|
||||
|
||||
if (!info->enabled) {
|
||||
monitor_printf(mon, "Server: disabled\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
monitor_printf(mon, "Server:\n");
|
||||
if (info->has_port) {
|
||||
monitor_printf(mon, " address: %s:%" PRId64 "\n",
|
||||
info->host, info->port);
|
||||
}
|
||||
if (info->has_tls_port) {
|
||||
monitor_printf(mon, " address: %s:%" PRId64 " [tls]\n",
|
||||
info->host, info->tls_port);
|
||||
}
|
||||
monitor_printf(mon, " migrated: %s\n",
|
||||
info->migrated ? "true" : "false");
|
||||
monitor_printf(mon, " auth: %s\n", info->auth);
|
||||
monitor_printf(mon, " compiled: %s\n", info->compiled_version);
|
||||
monitor_printf(mon, " mouse-mode: %s\n",
|
||||
SpiceQueryMouseMode_str(info->mouse_mode));
|
||||
|
||||
if (!info->has_channels || info->channels == NULL) {
|
||||
monitor_printf(mon, "Channels: none\n");
|
||||
} else {
|
||||
for (chan = info->channels; chan; chan = chan->next) {
|
||||
monitor_printf(mon, "Channel:\n");
|
||||
monitor_printf(mon, " address: %s:%s%s\n",
|
||||
chan->value->host, chan->value->port,
|
||||
chan->value->tls ? " [tls]" : "");
|
||||
monitor_printf(mon, " session: %" PRId64 "\n",
|
||||
chan->value->connection_id);
|
||||
monitor_printf(mon, " channel: %" PRId64 ":%" PRId64 "\n",
|
||||
chan->value->channel_type, chan->value->channel_id);
|
||||
|
||||
channel_name = "unknown";
|
||||
if (chan->value->channel_type > 0 &&
|
||||
chan->value->channel_type < ARRAY_SIZE(channel_names) &&
|
||||
channel_names[chan->value->channel_type]) {
|
||||
channel_name = channel_names[chan->value->channel_type];
|
||||
}
|
||||
|
||||
monitor_printf(mon, " channel name: %s\n", channel_name);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
qapi_free_SpiceInfo(info);
|
||||
}
|
||||
#endif
|
||||
|
||||
void hmp_info_balloon(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
BalloonInfo *info;
|
||||
@ -1266,78 +1074,6 @@ void hmp_x_colo_lost_heartbeat(Monitor *mon, const QDict *qdict)
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
||||
|
||||
void hmp_set_password(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *protocol = qdict_get_str(qdict, "protocol");
|
||||
const char *password = qdict_get_str(qdict, "password");
|
||||
const char *display = qdict_get_try_str(qdict, "display");
|
||||
const char *connected = qdict_get_try_str(qdict, "connected");
|
||||
Error *err = NULL;
|
||||
|
||||
SetPasswordOptions opts = {
|
||||
.password = (char *)password,
|
||||
.has_connected = !!connected,
|
||||
};
|
||||
|
||||
opts.connected = qapi_enum_parse(&SetPasswordAction_lookup, connected,
|
||||
SET_PASSWORD_ACTION_KEEP, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
opts.protocol = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
|
||||
DISPLAY_PROTOCOL_VNC, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (opts.protocol == DISPLAY_PROTOCOL_VNC) {
|
||||
opts.u.vnc.display = (char *)display;
|
||||
}
|
||||
|
||||
qmp_set_password(&opts, &err);
|
||||
|
||||
out:
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
||||
|
||||
void hmp_expire_password(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *protocol = qdict_get_str(qdict, "protocol");
|
||||
const char *whenstr = qdict_get_str(qdict, "time");
|
||||
const char *display = qdict_get_try_str(qdict, "display");
|
||||
Error *err = NULL;
|
||||
|
||||
ExpirePasswordOptions opts = {
|
||||
.time = (char *)whenstr,
|
||||
};
|
||||
|
||||
opts.protocol = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
|
||||
DISPLAY_PROTOCOL_VNC, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (opts.protocol == DISPLAY_PROTOCOL_VNC) {
|
||||
opts.u.vnc.display = (char *)display;
|
||||
}
|
||||
|
||||
qmp_expire_password(&opts, &err);
|
||||
|
||||
out:
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_VNC
|
||||
static void hmp_change_read_arg(void *opaque, const char *password,
|
||||
void *readline_opaque)
|
||||
{
|
||||
qmp_change_vnc_password(password, NULL);
|
||||
monitor_read_command(opaque, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void hmp_change(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *device = qdict_get_str(qdict, "device");
|
||||
@ -1350,23 +1086,7 @@ void hmp_change(Monitor *mon, const QDict *qdict)
|
||||
|
||||
#ifdef CONFIG_VNC
|
||||
if (strcmp(device, "vnc") == 0) {
|
||||
if (read_only) {
|
||||
monitor_printf(mon,
|
||||
"Parameter 'read-only-mode' is invalid for VNC\n");
|
||||
return;
|
||||
}
|
||||
if (strcmp(target, "passwd") == 0 ||
|
||||
strcmp(target, "password") == 0) {
|
||||
if (!arg) {
|
||||
MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
|
||||
monitor_read_password(hmp_mon, hmp_change_read_arg, NULL);
|
||||
return;
|
||||
} else {
|
||||
qmp_change_vnc_password(arg, &err);
|
||||
}
|
||||
} else {
|
||||
monitor_printf(mon, "Expected 'password' after 'vnc'\n");
|
||||
}
|
||||
hmp_change_vnc(mon, device, target, arg, read_only, force, &err);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@ -1525,90 +1245,6 @@ void hmp_closefd(Monitor *mon, const QDict *qdict)
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
||||
|
||||
void hmp_sendkey(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *keys = qdict_get_str(qdict, "keys");
|
||||
KeyValue *v = NULL;
|
||||
KeyValueList *head = NULL, **tail = &head;
|
||||
int has_hold_time = qdict_haskey(qdict, "hold-time");
|
||||
int hold_time = qdict_get_try_int(qdict, "hold-time", -1);
|
||||
Error *err = NULL;
|
||||
const char *separator;
|
||||
int keyname_len;
|
||||
|
||||
while (1) {
|
||||
separator = qemu_strchrnul(keys, '-');
|
||||
keyname_len = separator - keys;
|
||||
|
||||
/* Be compatible with old interface, convert user inputted "<" */
|
||||
if (keys[0] == '<' && keyname_len == 1) {
|
||||
keys = "less";
|
||||
keyname_len = 4;
|
||||
}
|
||||
|
||||
v = g_malloc0(sizeof(*v));
|
||||
|
||||
if (strstart(keys, "0x", NULL)) {
|
||||
char *endp;
|
||||
int value = strtoul(keys, &endp, 0);
|
||||
assert(endp <= keys + keyname_len);
|
||||
if (endp != keys + keyname_len) {
|
||||
goto err_out;
|
||||
}
|
||||
v->type = KEY_VALUE_KIND_NUMBER;
|
||||
v->u.number.data = value;
|
||||
} else {
|
||||
int idx = index_from_key(keys, keyname_len);
|
||||
if (idx == Q_KEY_CODE__MAX) {
|
||||
goto err_out;
|
||||
}
|
||||
v->type = KEY_VALUE_KIND_QCODE;
|
||||
v->u.qcode.data = idx;
|
||||
}
|
||||
QAPI_LIST_APPEND(tail, v);
|
||||
v = NULL;
|
||||
|
||||
if (!*separator) {
|
||||
break;
|
||||
}
|
||||
keys = separator + 1;
|
||||
}
|
||||
|
||||
qmp_send_key(head, has_hold_time, hold_time, &err);
|
||||
hmp_handle_error(mon, err);
|
||||
|
||||
out:
|
||||
qapi_free_KeyValue(v);
|
||||
qapi_free_KeyValueList(head);
|
||||
return;
|
||||
|
||||
err_out:
|
||||
monitor_printf(mon, "invalid parameter: %.*s\n", keyname_len, keys);
|
||||
goto out;
|
||||
}
|
||||
|
||||
void coroutine_fn
|
||||
hmp_screendump(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *filename = qdict_get_str(qdict, "filename");
|
||||
const char *id = qdict_get_try_str(qdict, "device");
|
||||
int64_t head = qdict_get_try_int(qdict, "head", 0);
|
||||
const char *input_format = qdict_get_try_str(qdict, "format");
|
||||
Error *err = NULL;
|
||||
ImageFormat format;
|
||||
|
||||
format = qapi_enum_parse(&ImageFormat_lookup, input_format,
|
||||
IMAGE_FORMAT_PPM, &err);
|
||||
if (err) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
qmp_screendump(filename, id, id != NULL, head,
|
||||
input_format != NULL, format, &err);
|
||||
end:
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
||||
|
||||
void hmp_chardev_add(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *args = qdict_get_str(qdict, "args");
|
||||
|
@ -33,8 +33,6 @@
|
||||
#include "ui/qemu-spice.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/ctype.h"
|
||||
#include "ui/console.h"
|
||||
#include "ui/input.h"
|
||||
#include "audio/audio.h"
|
||||
#include "disas/disas.h"
|
||||
#include "qemu/timer.h"
|
||||
@ -825,49 +823,6 @@ static void hmp_sum(Monitor *mon, const QDict *qdict)
|
||||
monitor_printf(mon, "%05d\n", sum);
|
||||
}
|
||||
|
||||
static int mouse_button_state;
|
||||
|
||||
static void hmp_mouse_move(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
int dx, dy, dz, button;
|
||||
const char *dx_str = qdict_get_str(qdict, "dx_str");
|
||||
const char *dy_str = qdict_get_str(qdict, "dy_str");
|
||||
const char *dz_str = qdict_get_try_str(qdict, "dz_str");
|
||||
|
||||
dx = strtol(dx_str, NULL, 0);
|
||||
dy = strtol(dy_str, NULL, 0);
|
||||
qemu_input_queue_rel(NULL, INPUT_AXIS_X, dx);
|
||||
qemu_input_queue_rel(NULL, INPUT_AXIS_Y, dy);
|
||||
|
||||
if (dz_str) {
|
||||
dz = strtol(dz_str, NULL, 0);
|
||||
if (dz != 0) {
|
||||
button = (dz > 0) ? INPUT_BUTTON_WHEEL_UP : INPUT_BUTTON_WHEEL_DOWN;
|
||||
qemu_input_queue_btn(NULL, button, true);
|
||||
qemu_input_event_sync();
|
||||
qemu_input_queue_btn(NULL, button, false);
|
||||
}
|
||||
}
|
||||
qemu_input_event_sync();
|
||||
}
|
||||
|
||||
static void hmp_mouse_button(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
static uint32_t bmap[INPUT_BUTTON__MAX] = {
|
||||
[INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
|
||||
[INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
|
||||
[INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
|
||||
};
|
||||
int button_state = qdict_get_int(qdict, "button_state");
|
||||
|
||||
if (mouse_button_state == button_state) {
|
||||
return;
|
||||
}
|
||||
qemu_input_update_buttons(NULL, bmap, mouse_button_state, button_state);
|
||||
qemu_input_event_sync();
|
||||
mouse_button_state = button_state;
|
||||
}
|
||||
|
||||
static void hmp_ioport_read(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
int size = qdict_get_int(qdict, "size");
|
||||
@ -1700,28 +1655,6 @@ void object_del_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
qapi_free_ObjectPropertyInfoList(start);
|
||||
}
|
||||
|
||||
void sendkey_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
{
|
||||
int i;
|
||||
char *sep;
|
||||
size_t len;
|
||||
|
||||
if (nb_args != 2) {
|
||||
return;
|
||||
}
|
||||
sep = strrchr(str, '-');
|
||||
if (sep) {
|
||||
str = sep + 1;
|
||||
}
|
||||
len = strlen(str);
|
||||
readline_set_completion_index(rs, len);
|
||||
for (i = 0; i < Q_KEY_CODE__MAX; i++) {
|
||||
if (!strncmp(str, QKeyCode_str(i), len)) {
|
||||
readline_add_completion(rs, QKeyCode_str(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_link_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
{
|
||||
size_t len;
|
||||
|
@ -17,13 +17,11 @@
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/option.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "monitor/qmp-helpers.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/uuid.h"
|
||||
#include "chardev/char.h"
|
||||
#include "ui/qemu-spice.h"
|
||||
#include "ui/console.h"
|
||||
#include "ui/dbus-display.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/runstate-action.h"
|
||||
@ -36,9 +34,7 @@
|
||||
#include "qapi/qapi-commands-machine.h"
|
||||
#include "qapi/qapi-commands-misc.h"
|
||||
#include "qapi/qapi-commands-stats.h"
|
||||
#include "qapi/qapi-commands-ui.h"
|
||||
#include "qapi/type-helpers.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "exec/ramlist.h"
|
||||
#include "hw/mem/memory-device.h"
|
||||
#include "hw/acpi/acpi_dev_interface.h"
|
||||
@ -168,130 +164,54 @@ void qmp_system_wakeup(Error **errp)
|
||||
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp);
|
||||
}
|
||||
|
||||
void qmp_set_password(SetPasswordOptions *opts, Error **errp)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (opts->protocol == DISPLAY_PROTOCOL_SPICE) {
|
||||
if (!qemu_using_spice(errp)) {
|
||||
return;
|
||||
}
|
||||
rc = qemu_spice.set_passwd(opts->password,
|
||||
opts->connected == SET_PASSWORD_ACTION_FAIL,
|
||||
opts->connected == SET_PASSWORD_ACTION_DISCONNECT);
|
||||
} else {
|
||||
assert(opts->protocol == DISPLAY_PROTOCOL_VNC);
|
||||
if (opts->connected != SET_PASSWORD_ACTION_KEEP) {
|
||||
/* vnc supports "connected=keep" only */
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, "connected");
|
||||
return;
|
||||
}
|
||||
/* Note that setting an empty password will not disable login through
|
||||
* this interface. */
|
||||
rc = vnc_display_password(opts->u.vnc.display, opts->password);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
error_setg(errp, "Could not set password");
|
||||
}
|
||||
}
|
||||
|
||||
void qmp_expire_password(ExpirePasswordOptions *opts, Error **errp)
|
||||
{
|
||||
time_t when;
|
||||
int rc;
|
||||
const char *whenstr = opts->time;
|
||||
|
||||
if (strcmp(whenstr, "now") == 0) {
|
||||
when = 0;
|
||||
} else if (strcmp(whenstr, "never") == 0) {
|
||||
when = TIME_MAX;
|
||||
} else if (whenstr[0] == '+') {
|
||||
when = time(NULL) + strtoull(whenstr+1, NULL, 10);
|
||||
} else {
|
||||
when = strtoull(whenstr, NULL, 10);
|
||||
}
|
||||
|
||||
if (opts->protocol == DISPLAY_PROTOCOL_SPICE) {
|
||||
if (!qemu_using_spice(errp)) {
|
||||
return;
|
||||
}
|
||||
rc = qemu_spice.set_pw_expire(when);
|
||||
} else {
|
||||
assert(opts->protocol == DISPLAY_PROTOCOL_VNC);
|
||||
rc = vnc_display_pw_expire(opts->u.vnc.display, when);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
error_setg(errp, "Could not set password expire time");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VNC
|
||||
void qmp_change_vnc_password(const char *password, Error **errp)
|
||||
{
|
||||
if (vnc_display_password(NULL, password) < 0) {
|
||||
error_setg(errp, "Could not set password");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void qmp_add_client(const char *protocol, const char *fdname,
|
||||
bool has_skipauth, bool skipauth, bool has_tls, bool tls,
|
||||
Error **errp)
|
||||
{
|
||||
static const struct {
|
||||
const char *name;
|
||||
bool (*add_client)(int fd, bool has_skipauth, bool skipauth,
|
||||
bool has_tls, bool tls, Error **errp);
|
||||
} protocol_table[] = {
|
||||
{ "spice", qmp_add_client_spice },
|
||||
#ifdef CONFIG_VNC
|
||||
{ "vnc", qmp_add_client_vnc },
|
||||
#endif
|
||||
#ifdef CONFIG_DBUS_DISPLAY
|
||||
{ "@dbus-display", qmp_add_client_dbus_display },
|
||||
#endif
|
||||
};
|
||||
Chardev *s;
|
||||
int fd;
|
||||
int fd, i;
|
||||
|
||||
fd = monitor_get_fd(monitor_cur(), fdname, errp);
|
||||
if (fd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(protocol, "spice") == 0) {
|
||||
if (!qemu_using_spice(errp)) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
skipauth = has_skipauth ? skipauth : false;
|
||||
tls = has_tls ? tls : false;
|
||||
if (qemu_spice.display_add_client(fd, skipauth, tls) < 0) {
|
||||
error_setg(errp, "spice failed to add client");
|
||||
for (i = 0; i < ARRAY_SIZE(protocol_table); i++) {
|
||||
if (!strcmp(protocol, protocol_table[i].name)) {
|
||||
if (!protocol_table[i].add_client(fd, has_skipauth, skipauth,
|
||||
has_tls, tls, errp)) {
|
||||
close(fd);
|
||||
}
|
||||
return;
|
||||
#ifdef CONFIG_VNC
|
||||
} else if (strcmp(protocol, "vnc") == 0) {
|
||||
skipauth = has_skipauth ? skipauth : false;
|
||||
vnc_display_add_client(NULL, fd, skipauth);
|
||||
return;
|
||||
#endif
|
||||
#ifdef CONFIG_DBUS_DISPLAY
|
||||
} else if (strcmp(protocol, "@dbus-display") == 0) {
|
||||
if (!qemu_using_dbus_display(errp)) {
|
||||
}
|
||||
}
|
||||
|
||||
s = qemu_chr_find(protocol);
|
||||
if (!s) {
|
||||
error_setg(errp, "protocol '%s' is invalid", protocol);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
if (!qemu_dbus_display.add_client(fd, errp)) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
#endif
|
||||
} else if ((s = qemu_chr_find(protocol)) != NULL) {
|
||||
if (qemu_chr_add_client(s, fd) < 0) {
|
||||
error_setg(errp, "failed to add client");
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
error_setg(errp, "protocol '%s' is invalid", protocol);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
|
||||
{
|
||||
return qmp_memory_device_list();
|
||||
@ -330,38 +250,6 @@ MemoryInfo *qmp_query_memory_size_summary(Error **errp)
|
||||
return mem_info;
|
||||
}
|
||||
|
||||
void qmp_display_reload(DisplayReloadOptions *arg, Error **errp)
|
||||
{
|
||||
switch (arg->type) {
|
||||
case DISPLAY_RELOAD_TYPE_VNC:
|
||||
#ifdef CONFIG_VNC
|
||||
if (arg->u.vnc.has_tls_certs && arg->u.vnc.tls_certs) {
|
||||
vnc_display_reload_certs(NULL, errp);
|
||||
}
|
||||
#else
|
||||
error_setg(errp, "vnc is invalid, missing 'CONFIG_VNC'");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void qmp_display_update(DisplayUpdateOptions *arg, Error **errp)
|
||||
{
|
||||
switch (arg->type) {
|
||||
case DISPLAY_UPDATE_TYPE_VNC:
|
||||
#ifdef CONFIG_VNC
|
||||
vnc_display_update(&arg->u.vnc, errp);
|
||||
#else
|
||||
error_setg(errp, "vnc is invalid, missing 'CONFIG_VNC'");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static int qmp_x_query_rdma_foreach(Object *obj, void *opaque)
|
||||
{
|
||||
RdmaProvider *rdma;
|
||||
|
34
ui/input.c
34
ui/input.c
@ -2,8 +2,6 @@
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-commands-ui.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "trace.h"
|
||||
#include "ui/input.h"
|
||||
#include "ui/console.h"
|
||||
@ -594,29 +592,29 @@ MouseInfoList *qmp_query_mice(Error **errp)
|
||||
return mice_list;
|
||||
}
|
||||
|
||||
void hmp_mouse_set(Monitor *mon, const QDict *qdict)
|
||||
bool qemu_mouse_set(int index, Error **errp)
|
||||
{
|
||||
QemuInputHandlerState *s;
|
||||
int index = qdict_get_int(qdict, "index");
|
||||
int found = 0;
|
||||
|
||||
QTAILQ_FOREACH(s, &handlers, node) {
|
||||
if (s->id != index) {
|
||||
continue;
|
||||
}
|
||||
if (!(s->handler->mask & (INPUT_EVENT_MASK_REL |
|
||||
INPUT_EVENT_MASK_ABS))) {
|
||||
error_report("Input device '%s' is not a mouse", s->handler->name);
|
||||
return;
|
||||
}
|
||||
found = 1;
|
||||
qemu_input_handler_activate(s);
|
||||
if (s->id == index) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
error_report("Mouse at index '%d' not found", index);
|
||||
}
|
||||
|
||||
if (!s) {
|
||||
error_setg(errp, "Mouse at index '%d' not found", index);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(s->handler->mask & (INPUT_EVENT_MASK_REL |
|
||||
INPUT_EVENT_MASK_ABS))) {
|
||||
error_setg(errp, "Input device '%s' is not a mouse",
|
||||
s->handler->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
qemu_input_handler_activate(s);
|
||||
qemu_input_check_mode_change();
|
||||
return true;
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ softmmu_ss.add(files(
|
||||
'kbd-state.c',
|
||||
'keymaps.c',
|
||||
'qemu-pixman.c',
|
||||
'ui-hmp-cmds.c',
|
||||
'ui-qmp-cmds.c',
|
||||
'util.c',
|
||||
))
|
||||
if dbus_display
|
||||
|
@ -517,13 +517,6 @@ static void interface_set_compression_level(QXLInstance *sin, int level)
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
#if SPICE_NEEDS_SET_MM_TIME
|
||||
static void interface_set_mm_time(QXLInstance *sin, uint32_t mm_time)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
#endif
|
||||
|
||||
static void interface_get_init_info(QXLInstance *sin, QXLDevInitInfo *info)
|
||||
{
|
||||
SimpleSpiceDisplay *ssd = container_of(sin, SimpleSpiceDisplay, qxl);
|
||||
@ -715,9 +708,6 @@ static const QXLInterface dpy_interface = {
|
||||
.attache_worker = interface_attach_worker,
|
||||
#endif
|
||||
.set_compression_level = interface_set_compression_level,
|
||||
#if SPICE_NEEDS_SET_MM_TIME
|
||||
.set_mm_time = interface_set_mm_time,
|
||||
#endif
|
||||
.get_init_info = interface_get_init_info,
|
||||
|
||||
/* the callbacks below are called from spice server thread context */
|
||||
|
460
ui/ui-hmp-cmds.c
Normal file
460
ui/ui-hmp-cmds.c
Normal file
@ -0,0 +1,460 @@
|
||||
/*
|
||||
* HMP commands related to UI
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
* Contributions after 2012-01-13 are licensed under the terms of the
|
||||
* GNU GPL, version 2 or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#ifdef CONFIG_SPICE
|
||||
#include <spice/enums.h>
|
||||
#endif
|
||||
#include "monitor/hmp.h"
|
||||
#include "monitor/monitor-internal.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-commands-ui.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "ui/console.h"
|
||||
#include "ui/input.h"
|
||||
|
||||
static int mouse_button_state;
|
||||
|
||||
void hmp_mouse_move(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
int dx, dy, dz, button;
|
||||
const char *dx_str = qdict_get_str(qdict, "dx_str");
|
||||
const char *dy_str = qdict_get_str(qdict, "dy_str");
|
||||
const char *dz_str = qdict_get_try_str(qdict, "dz_str");
|
||||
|
||||
dx = strtol(dx_str, NULL, 0);
|
||||
dy = strtol(dy_str, NULL, 0);
|
||||
qemu_input_queue_rel(NULL, INPUT_AXIS_X, dx);
|
||||
qemu_input_queue_rel(NULL, INPUT_AXIS_Y, dy);
|
||||
|
||||
if (dz_str) {
|
||||
dz = strtol(dz_str, NULL, 0);
|
||||
if (dz != 0) {
|
||||
button = (dz > 0) ? INPUT_BUTTON_WHEEL_UP : INPUT_BUTTON_WHEEL_DOWN;
|
||||
qemu_input_queue_btn(NULL, button, true);
|
||||
qemu_input_event_sync();
|
||||
qemu_input_queue_btn(NULL, button, false);
|
||||
}
|
||||
}
|
||||
qemu_input_event_sync();
|
||||
}
|
||||
|
||||
void hmp_mouse_button(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
static uint32_t bmap[INPUT_BUTTON__MAX] = {
|
||||
[INPUT_BUTTON_LEFT] = MOUSE_EVENT_LBUTTON,
|
||||
[INPUT_BUTTON_MIDDLE] = MOUSE_EVENT_MBUTTON,
|
||||
[INPUT_BUTTON_RIGHT] = MOUSE_EVENT_RBUTTON,
|
||||
};
|
||||
int button_state = qdict_get_int(qdict, "button_state");
|
||||
|
||||
if (mouse_button_state == button_state) {
|
||||
return;
|
||||
}
|
||||
qemu_input_update_buttons(NULL, bmap, mouse_button_state, button_state);
|
||||
qemu_input_event_sync();
|
||||
mouse_button_state = button_state;
|
||||
}
|
||||
|
||||
void hmp_mouse_set(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
Error *err = NULL;
|
||||
|
||||
qemu_mouse_set(qdict_get_int(qdict, "index"), &err);
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
||||
|
||||
void hmp_info_mice(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
MouseInfoList *mice_list, *mouse;
|
||||
|
||||
mice_list = qmp_query_mice(NULL);
|
||||
if (!mice_list) {
|
||||
monitor_printf(mon, "No mouse devices connected\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (mouse = mice_list; mouse; mouse = mouse->next) {
|
||||
monitor_printf(mon, "%c Mouse #%" PRId64 ": %s%s\n",
|
||||
mouse->value->current ? '*' : ' ',
|
||||
mouse->value->index, mouse->value->name,
|
||||
mouse->value->absolute ? " (absolute)" : "");
|
||||
}
|
||||
|
||||
qapi_free_MouseInfoList(mice_list);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VNC
|
||||
/* Helper for hmp_info_vnc_clients, _servers */
|
||||
static void hmp_info_VncBasicInfo(Monitor *mon, VncBasicInfo *info,
|
||||
const char *name)
|
||||
{
|
||||
monitor_printf(mon, " %s: %s:%s (%s%s)\n",
|
||||
name,
|
||||
info->host,
|
||||
info->service,
|
||||
NetworkAddressFamily_str(info->family),
|
||||
info->websocket ? " (Websocket)" : "");
|
||||
}
|
||||
|
||||
/* Helper displaying and auth and crypt info */
|
||||
static void hmp_info_vnc_authcrypt(Monitor *mon, const char *indent,
|
||||
VncPrimaryAuth auth,
|
||||
VncVencryptSubAuth *vencrypt)
|
||||
{
|
||||
monitor_printf(mon, "%sAuth: %s (Sub: %s)\n", indent,
|
||||
VncPrimaryAuth_str(auth),
|
||||
vencrypt ? VncVencryptSubAuth_str(*vencrypt) : "none");
|
||||
}
|
||||
|
||||
static void hmp_info_vnc_clients(Monitor *mon, VncClientInfoList *client)
|
||||
{
|
||||
while (client) {
|
||||
VncClientInfo *cinfo = client->value;
|
||||
|
||||
hmp_info_VncBasicInfo(mon, qapi_VncClientInfo_base(cinfo), "Client");
|
||||
monitor_printf(mon, " x509_dname: %s\n",
|
||||
cinfo->x509_dname ?: "none");
|
||||
monitor_printf(mon, " sasl_username: %s\n",
|
||||
cinfo->sasl_username ?: "none");
|
||||
|
||||
client = client->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void hmp_info_vnc_servers(Monitor *mon, VncServerInfo2List *server)
|
||||
{
|
||||
while (server) {
|
||||
VncServerInfo2 *sinfo = server->value;
|
||||
hmp_info_VncBasicInfo(mon, qapi_VncServerInfo2_base(sinfo), "Server");
|
||||
hmp_info_vnc_authcrypt(mon, " ", sinfo->auth,
|
||||
sinfo->has_vencrypt ? &sinfo->vencrypt : NULL);
|
||||
server = server->next;
|
||||
}
|
||||
}
|
||||
|
||||
void hmp_info_vnc(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
VncInfo2List *info2l, *info2l_head;
|
||||
Error *err = NULL;
|
||||
|
||||
info2l = qmp_query_vnc_servers(&err);
|
||||
info2l_head = info2l;
|
||||
if (hmp_handle_error(mon, err)) {
|
||||
return;
|
||||
}
|
||||
if (!info2l) {
|
||||
monitor_printf(mon, "None\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (info2l) {
|
||||
VncInfo2 *info = info2l->value;
|
||||
monitor_printf(mon, "%s:\n", info->id);
|
||||
hmp_info_vnc_servers(mon, info->server);
|
||||
hmp_info_vnc_clients(mon, info->clients);
|
||||
if (!info->server) {
|
||||
/*
|
||||
* The server entry displays its auth, we only need to
|
||||
* display in the case of 'reverse' connections where
|
||||
* there's no server.
|
||||
*/
|
||||
hmp_info_vnc_authcrypt(mon, " ", info->auth,
|
||||
info->has_vencrypt ? &info->vencrypt : NULL);
|
||||
}
|
||||
if (info->display) {
|
||||
monitor_printf(mon, " Display: %s\n", info->display);
|
||||
}
|
||||
info2l = info2l->next;
|
||||
}
|
||||
|
||||
qapi_free_VncInfo2List(info2l_head);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SPICE
|
||||
void hmp_info_spice(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
SpiceChannelList *chan;
|
||||
SpiceInfo *info;
|
||||
const char *channel_name;
|
||||
static const char *const channel_names[] = {
|
||||
[SPICE_CHANNEL_MAIN] = "main",
|
||||
[SPICE_CHANNEL_DISPLAY] = "display",
|
||||
[SPICE_CHANNEL_INPUTS] = "inputs",
|
||||
[SPICE_CHANNEL_CURSOR] = "cursor",
|
||||
[SPICE_CHANNEL_PLAYBACK] = "playback",
|
||||
[SPICE_CHANNEL_RECORD] = "record",
|
||||
[SPICE_CHANNEL_TUNNEL] = "tunnel",
|
||||
[SPICE_CHANNEL_SMARTCARD] = "smartcard",
|
||||
[SPICE_CHANNEL_USBREDIR] = "usbredir",
|
||||
[SPICE_CHANNEL_PORT] = "port",
|
||||
[SPICE_CHANNEL_WEBDAV] = "webdav",
|
||||
};
|
||||
|
||||
info = qmp_query_spice(NULL);
|
||||
|
||||
if (!info->enabled) {
|
||||
monitor_printf(mon, "Server: disabled\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
monitor_printf(mon, "Server:\n");
|
||||
if (info->has_port) {
|
||||
monitor_printf(mon, " address: %s:%" PRId64 "\n",
|
||||
info->host, info->port);
|
||||
}
|
||||
if (info->has_tls_port) {
|
||||
monitor_printf(mon, " address: %s:%" PRId64 " [tls]\n",
|
||||
info->host, info->tls_port);
|
||||
}
|
||||
monitor_printf(mon, " migrated: %s\n",
|
||||
info->migrated ? "true" : "false");
|
||||
monitor_printf(mon, " auth: %s\n", info->auth);
|
||||
monitor_printf(mon, " compiled: %s\n", info->compiled_version);
|
||||
monitor_printf(mon, " mouse-mode: %s\n",
|
||||
SpiceQueryMouseMode_str(info->mouse_mode));
|
||||
|
||||
if (!info->has_channels || info->channels == NULL) {
|
||||
monitor_printf(mon, "Channels: none\n");
|
||||
} else {
|
||||
for (chan = info->channels; chan; chan = chan->next) {
|
||||
monitor_printf(mon, "Channel:\n");
|
||||
monitor_printf(mon, " address: %s:%s%s\n",
|
||||
chan->value->host, chan->value->port,
|
||||
chan->value->tls ? " [tls]" : "");
|
||||
monitor_printf(mon, " session: %" PRId64 "\n",
|
||||
chan->value->connection_id);
|
||||
monitor_printf(mon, " channel: %" PRId64 ":%" PRId64 "\n",
|
||||
chan->value->channel_type, chan->value->channel_id);
|
||||
|
||||
channel_name = "unknown";
|
||||
if (chan->value->channel_type > 0 &&
|
||||
chan->value->channel_type < ARRAY_SIZE(channel_names) &&
|
||||
channel_names[chan->value->channel_type]) {
|
||||
channel_name = channel_names[chan->value->channel_type];
|
||||
}
|
||||
|
||||
monitor_printf(mon, " channel name: %s\n", channel_name);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
qapi_free_SpiceInfo(info);
|
||||
}
|
||||
#endif
|
||||
|
||||
void hmp_set_password(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *protocol = qdict_get_str(qdict, "protocol");
|
||||
const char *password = qdict_get_str(qdict, "password");
|
||||
const char *display = qdict_get_try_str(qdict, "display");
|
||||
const char *connected = qdict_get_try_str(qdict, "connected");
|
||||
Error *err = NULL;
|
||||
|
||||
SetPasswordOptions opts = {
|
||||
.password = (char *)password,
|
||||
.has_connected = !!connected,
|
||||
};
|
||||
|
||||
opts.connected = qapi_enum_parse(&SetPasswordAction_lookup, connected,
|
||||
SET_PASSWORD_ACTION_KEEP, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
opts.protocol = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
|
||||
DISPLAY_PROTOCOL_VNC, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (opts.protocol == DISPLAY_PROTOCOL_VNC) {
|
||||
opts.u.vnc.display = (char *)display;
|
||||
}
|
||||
|
||||
qmp_set_password(&opts, &err);
|
||||
|
||||
out:
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
||||
|
||||
void hmp_expire_password(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *protocol = qdict_get_str(qdict, "protocol");
|
||||
const char *whenstr = qdict_get_str(qdict, "time");
|
||||
const char *display = qdict_get_try_str(qdict, "display");
|
||||
Error *err = NULL;
|
||||
|
||||
ExpirePasswordOptions opts = {
|
||||
.time = (char *)whenstr,
|
||||
};
|
||||
|
||||
opts.protocol = qapi_enum_parse(&DisplayProtocol_lookup, protocol,
|
||||
DISPLAY_PROTOCOL_VNC, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (opts.protocol == DISPLAY_PROTOCOL_VNC) {
|
||||
opts.u.vnc.display = (char *)display;
|
||||
}
|
||||
|
||||
qmp_expire_password(&opts, &err);
|
||||
|
||||
out:
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VNC
|
||||
static void hmp_change_read_arg(void *opaque, const char *password,
|
||||
void *readline_opaque)
|
||||
{
|
||||
qmp_change_vnc_password(password, NULL);
|
||||
monitor_read_command(opaque, 1);
|
||||
}
|
||||
|
||||
void hmp_change_vnc(Monitor *mon, const char *device, const char *target,
|
||||
const char *arg, const char *read_only, bool force,
|
||||
Error **errp)
|
||||
{
|
||||
if (read_only) {
|
||||
error_setg(errp, "Parameter 'read-only-mode' is invalid for VNC");
|
||||
return;
|
||||
}
|
||||
if (strcmp(target, "passwd") && strcmp(target, "password")) {
|
||||
error_setg(errp, "Expected 'password' after 'vnc'");
|
||||
return;
|
||||
}
|
||||
if (!arg) {
|
||||
MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
|
||||
monitor_read_password(hmp_mon, hmp_change_read_arg, NULL);
|
||||
} else {
|
||||
qmp_change_vnc_password(arg, errp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void hmp_sendkey(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *keys = qdict_get_str(qdict, "keys");
|
||||
KeyValue *v = NULL;
|
||||
KeyValueList *head = NULL, **tail = &head;
|
||||
int has_hold_time = qdict_haskey(qdict, "hold-time");
|
||||
int hold_time = qdict_get_try_int(qdict, "hold-time", -1);
|
||||
Error *err = NULL;
|
||||
const char *separator;
|
||||
int keyname_len;
|
||||
|
||||
while (1) {
|
||||
separator = qemu_strchrnul(keys, '-');
|
||||
keyname_len = separator - keys;
|
||||
|
||||
/* Be compatible with old interface, convert user inputted "<" */
|
||||
if (keys[0] == '<' && keyname_len == 1) {
|
||||
keys = "less";
|
||||
keyname_len = 4;
|
||||
}
|
||||
|
||||
v = g_malloc0(sizeof(*v));
|
||||
|
||||
if (strstart(keys, "0x", NULL)) {
|
||||
const char *endp;
|
||||
int value;
|
||||
|
||||
if (qemu_strtoi(keys, &endp, 0, &value) < 0) {
|
||||
goto err_out;
|
||||
}
|
||||
assert(endp <= keys + keyname_len);
|
||||
if (endp != keys + keyname_len) {
|
||||
goto err_out;
|
||||
}
|
||||
v->type = KEY_VALUE_KIND_NUMBER;
|
||||
v->u.number.data = value;
|
||||
} else {
|
||||
int idx = index_from_key(keys, keyname_len);
|
||||
if (idx == Q_KEY_CODE__MAX) {
|
||||
goto err_out;
|
||||
}
|
||||
v->type = KEY_VALUE_KIND_QCODE;
|
||||
v->u.qcode.data = idx;
|
||||
}
|
||||
QAPI_LIST_APPEND(tail, v);
|
||||
v = NULL;
|
||||
|
||||
if (!*separator) {
|
||||
break;
|
||||
}
|
||||
keys = separator + 1;
|
||||
}
|
||||
|
||||
qmp_send_key(head, has_hold_time, hold_time, &err);
|
||||
hmp_handle_error(mon, err);
|
||||
|
||||
out:
|
||||
qapi_free_KeyValue(v);
|
||||
qapi_free_KeyValueList(head);
|
||||
return;
|
||||
|
||||
err_out:
|
||||
monitor_printf(mon, "invalid parameter: %.*s\n", keyname_len, keys);
|
||||
goto out;
|
||||
}
|
||||
|
||||
void sendkey_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||
{
|
||||
int i;
|
||||
char *sep;
|
||||
size_t len;
|
||||
|
||||
if (nb_args != 2) {
|
||||
return;
|
||||
}
|
||||
sep = strrchr(str, '-');
|
||||
if (sep) {
|
||||
str = sep + 1;
|
||||
}
|
||||
len = strlen(str);
|
||||
readline_set_completion_index(rs, len);
|
||||
for (i = 0; i < Q_KEY_CODE__MAX; i++) {
|
||||
if (!strncmp(str, QKeyCode_str(i), len)) {
|
||||
readline_add_completion(rs, QKeyCode_str(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void coroutine_fn
|
||||
hmp_screendump(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
const char *filename = qdict_get_str(qdict, "filename");
|
||||
const char *id = qdict_get_try_str(qdict, "device");
|
||||
int64_t head = qdict_get_try_int(qdict, "head", 0);
|
||||
const char *input_format = qdict_get_try_str(qdict, "format");
|
||||
Error *err = NULL;
|
||||
ImageFormat format;
|
||||
|
||||
format = qapi_enum_parse(&ImageFormat_lookup, input_format,
|
||||
IMAGE_FORMAT_PPM, &err);
|
||||
if (err) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
qmp_screendump(filename, id, id != NULL, head,
|
||||
input_format != NULL, format, &err);
|
||||
end:
|
||||
hmp_handle_error(mon, err);
|
||||
}
|
177
ui/ui-qmp-cmds.c
Normal file
177
ui/ui-qmp-cmds.c
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* QMP commands related to UI
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
* Contributions after 2012-01-13 are licensed under the terms of the
|
||||
* GNU GPL, version 2 or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "monitor/qmp-helpers.h"
|
||||
#include "qapi/qapi-commands-ui.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "ui/console.h"
|
||||
#include "ui/dbus-display.h"
|
||||
#include "ui/qemu-spice.h"
|
||||
|
||||
void qmp_set_password(SetPasswordOptions *opts, Error **errp)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (opts->protocol == DISPLAY_PROTOCOL_SPICE) {
|
||||
if (!qemu_using_spice(errp)) {
|
||||
return;
|
||||
}
|
||||
rc = qemu_spice.set_passwd(opts->password,
|
||||
opts->connected == SET_PASSWORD_ACTION_FAIL,
|
||||
opts->connected == SET_PASSWORD_ACTION_DISCONNECT);
|
||||
} else {
|
||||
assert(opts->protocol == DISPLAY_PROTOCOL_VNC);
|
||||
if (opts->connected != SET_PASSWORD_ACTION_KEEP) {
|
||||
/* vnc supports "connected=keep" only */
|
||||
error_setg(errp, QERR_INVALID_PARAMETER, "connected");
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Note that setting an empty password will not disable login
|
||||
* through this interface.
|
||||
*/
|
||||
rc = vnc_display_password(opts->u.vnc.display, opts->password);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
error_setg(errp, "Could not set password");
|
||||
}
|
||||
}
|
||||
|
||||
void qmp_expire_password(ExpirePasswordOptions *opts, Error **errp)
|
||||
{
|
||||
time_t when;
|
||||
int rc;
|
||||
const char *whenstr = opts->time;
|
||||
const char *numstr = NULL;
|
||||
uint64_t num;
|
||||
|
||||
if (strcmp(whenstr, "now") == 0) {
|
||||
when = 0;
|
||||
} else if (strcmp(whenstr, "never") == 0) {
|
||||
when = TIME_MAX;
|
||||
} else if (whenstr[0] == '+') {
|
||||
when = time(NULL);
|
||||
numstr = whenstr + 1;
|
||||
} else {
|
||||
when = 0;
|
||||
numstr = whenstr;
|
||||
}
|
||||
|
||||
if (numstr) {
|
||||
if (qemu_strtou64(numstr, NULL, 10, &num) < 0) {
|
||||
error_setg(errp, "Parameter 'time' doesn't take value '%s'",
|
||||
whenstr);
|
||||
return;
|
||||
}
|
||||
when += num;
|
||||
}
|
||||
|
||||
if (opts->protocol == DISPLAY_PROTOCOL_SPICE) {
|
||||
if (!qemu_using_spice(errp)) {
|
||||
return;
|
||||
}
|
||||
rc = qemu_spice.set_pw_expire(when);
|
||||
} else {
|
||||
assert(opts->protocol == DISPLAY_PROTOCOL_VNC);
|
||||
rc = vnc_display_pw_expire(opts->u.vnc.display, when);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
error_setg(errp, "Could not set password expire time");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VNC
|
||||
void qmp_change_vnc_password(const char *password, Error **errp)
|
||||
{
|
||||
if (vnc_display_password(NULL, password) < 0) {
|
||||
error_setg(errp, "Could not set password");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool qmp_add_client_spice(int fd, bool has_skipauth, bool skipauth,
|
||||
bool has_tls, bool tls, Error **errp)
|
||||
{
|
||||
if (!qemu_using_spice(errp)) {
|
||||
return false;
|
||||
}
|
||||
skipauth = has_skipauth ? skipauth : false;
|
||||
tls = has_tls ? tls : false;
|
||||
if (qemu_spice.display_add_client(fd, skipauth, tls) < 0) {
|
||||
error_setg(errp, "spice failed to add client");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VNC
|
||||
bool qmp_add_client_vnc(int fd, bool has_skipauth, bool skipauth,
|
||||
bool has_tls, bool tls, Error **errp)
|
||||
{
|
||||
skipauth = has_skipauth ? skipauth : false;
|
||||
vnc_display_add_client(NULL, fd, skipauth);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DBUS_DISPLAY
|
||||
bool qmp_add_client_dbus_display(int fd, bool has_skipauth, bool skipauth,
|
||||
bool has_tls, bool tls, Error **errp)
|
||||
{
|
||||
if (!qemu_using_dbus_display(errp)) {
|
||||
return false;
|
||||
}
|
||||
if (!qemu_dbus_display.add_client(fd, errp)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void qmp_display_reload(DisplayReloadOptions *arg, Error **errp)
|
||||
{
|
||||
switch (arg->type) {
|
||||
case DISPLAY_RELOAD_TYPE_VNC:
|
||||
#ifdef CONFIG_VNC
|
||||
if (arg->u.vnc.has_tls_certs && arg->u.vnc.tls_certs) {
|
||||
vnc_display_reload_certs(NULL, errp);
|
||||
}
|
||||
#else
|
||||
error_setg(errp, "vnc is invalid, missing 'CONFIG_VNC'");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void qmp_display_update(DisplayUpdateOptions *arg, Error **errp)
|
||||
{
|
||||
switch (arg->type) {
|
||||
case DISPLAY_UPDATE_TYPE_VNC:
|
||||
#ifdef CONFIG_VNC
|
||||
vnc_display_update(&arg->u.vnc, errp);
|
||||
#else
|
||||
error_setg(errp, "vnc is invalid, missing 'CONFIG_VNC'");
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
@ -87,9 +87,7 @@ static const char *cap_name[] = {
|
||||
[VD_AGENT_CAP_MONITORS_CONFIG_POSITION] = "monitors-config-position",
|
||||
[VD_AGENT_CAP_FILE_XFER_DISABLED] = "file-xfer-disabled",
|
||||
[VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS] = "file-xfer-detailed-errors",
|
||||
#if CHECK_SPICE_PROTOCOL_VERSION(0, 14, 0)
|
||||
[VD_AGENT_CAP_GRAPHICS_DEVICE_INFO] = "graphics-device-info",
|
||||
#endif
|
||||
#if CHECK_SPICE_PROTOCOL_VERSION(0, 14, 1)
|
||||
[VD_AGENT_CAP_CLIPBOARD_NO_RELEASE_ON_REGRAB] = "clipboard-no-release-on-regrab",
|
||||
[VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL] = "clipboard-grab-serial",
|
||||
@ -112,9 +110,7 @@ static const char *msg_name[] = {
|
||||
[VD_AGENT_CLIENT_DISCONNECTED] = "client-disconnected",
|
||||
[VD_AGENT_MAX_CLIPBOARD] = "max-clipboard",
|
||||
[VD_AGENT_AUDIO_VOLUME_SYNC] = "audio-volume-sync",
|
||||
#if CHECK_SPICE_PROTOCOL_VERSION(0, 14, 0)
|
||||
[VD_AGENT_GRAPHICS_DEVICE_INFO] = "graphics-device-info",
|
||||
#endif
|
||||
};
|
||||
|
||||
static const char *sel_name[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user