ui: Move HMP commands from monitor to new ui/ui-hmp-cmds.c
This moves these commands from MAINTAINERS section "Human Monitor (HMP)" to "Graphics". Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20230109190321.1056914-12-armbru@redhat.com>
This commit is contained in:
parent
3125af295e
commit
5011d262f0
@ -81,6 +81,8 @@ 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_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);
|
||||
|
@ -51,7 +51,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 +58,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 +173,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,168 +491,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;
|
||||
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_info_balloon(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
BalloonInfo *info;
|
||||
@ -1262,69 +1075,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)
|
||||
@ -1521,94 +1271,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)) {
|
||||
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 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");
|
||||
|
@ -34,7 +34,6 @@
|
||||
#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 +824,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 +1656,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;
|
||||
|
@ -14,6 +14,7 @@ softmmu_ss.add(files(
|
||||
'kbd-state.c',
|
||||
'keymaps.c',
|
||||
'qemu-pixman.c',
|
||||
'ui-hmp-cmds.c',
|
||||
'ui-qmp-cmds.c',
|
||||
'util.c',
|
||||
))
|
||||
|
422
ui/ui-hmp-cmds.c
Normal file
422
ui/ui-hmp-cmds.c
Normal file
@ -0,0 +1,422 @@
|
||||
/*
|
||||
* 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.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_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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user