From nobody Tue Feb 10 12:39:30 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1674135270; cv=none; d=zohomail.com; s=zohoarc; b=VsBCM0ODmAwf4LsOumhZBg+uube6Cu8gzAT6HoI67MBy+vzLJlHWzQMPQxQla3ZvMshlQT1GxyEg5cjT89sbucOSP2rknG8eup6cBYuS+nXGxoNrMZ3EbsfX5ZPRBkfWnApQxPUbEmzHED8eun7Ql5iTNhTiMt91DlokfTN62b4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1674135270; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=+6RysFi4qu1hkCar9p0M3Q4S8wQkCKWITye0wzJUUNk=; b=iUS8jggZX+SDme/iqTurdc3ve+BPWqNUq6rugChr1UpRsAW13ID5RIvqm1jOUs5B8fRdnbQ2WMhDWZjCDEhprPCxJpUhtRzw5b+4RFS94iRL84BGYvPPH5kPHDQW4CVByfO4QVemqasQjf9qy57gNTEY5w1DOcWWh0o4KqYwh3I= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1674135270580125.98871350734635; Thu, 19 Jan 2023 05:34:30 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pIUxK-0005vo-4L; Thu, 19 Jan 2023 08:27:50 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pIUx9-0005s1-Kv for qemu-devel@nongnu.org; Thu, 19 Jan 2023 08:27:40 -0500 Received: from us-smtp-delivery-124.mimecast.com ([170.10.133.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pIUx1-0008CE-W5 for qemu-devel@nongnu.org; Thu, 19 Jan 2023 08:27:39 -0500 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-664-nhcSPt0UPt2lWCCUGzJxKQ-1; Thu, 19 Jan 2023 08:27:16 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 5ADB580D0EB; Thu, 19 Jan 2023 13:27:16 +0000 (UTC) Received: from blackfin.pond.sub.org (unknown [10.39.192.70]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A993E2026D2A; Thu, 19 Jan 2023 13:27:15 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 66D7221E6608; Thu, 19 Jan 2023 14:27:13 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1674134838; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+6RysFi4qu1hkCar9p0M3Q4S8wQkCKWITye0wzJUUNk=; b=b51V7gIE5UONOWfUqpsdVmZykoxg4y2jBv1GMjgPlfsXUNckuSmOCl/FjO5EU0FJM2rBoL eEfHn0dqdMzHLh3MfS0vpwM/fyFlA7o9IFTdcY8VKZeb/GntIkraOt6s9f4+9qJ/y1+thO ifCfXvygIZfSct43upHfcnDIAHSaW4U= X-MC-Unique: nhcSPt0UPt2lWCCUGzJxKQ-1 From: Markus Armbruster To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, =?UTF-8?q?Daniel=20P=20=2E=20Berrang=C3=A9?= , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PULL 11/17] ui: Move HMP commands from monitor to new ui/ui-hmp-cmds.c Date: Thu, 19 Jan 2023 14:27:07 +0100 Message-Id: <20230119132713.3493556-12-armbru@redhat.com> In-Reply-To: <20230119132713.3493556-1-armbru@redhat.com> References: <20230119132713.3493556-1-armbru@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.133.124; envelope-from=armbru@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1674135271425100001 This moves these commands from MAINTAINERS section "Human Monitor (HMP)" to "Graphics". Signed-off-by: Markus Armbruster Reviewed-by: Daniel P. Berrang=C3=A9 Reviewed-by: Philippe Mathieu-Daud=C3=A9 Message-Id: <20230109190321.1056914-12-armbru@redhat.com> --- include/monitor/hmp.h | 2 + monitor/hmp-cmds.c | 338 --------------------------------- monitor/misc.c | 66 ------- ui/ui-hmp-cmds.c | 422 ++++++++++++++++++++++++++++++++++++++++++ ui/meson.build | 1 + 5 files changed, 425 insertions(+), 404 deletions(-) create mode 100644 ui/ui-hmp-cmds.c diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h index 27f86399f7..b228a406f3 100644 --- a/include/monitor/hmp.h +++ b/include/monitor/hmp.h @@ -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); diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index c2249f77a6..c4f161a596 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -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" =20 -#ifdef CONFIG_SPICE -#include -#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); } =20 -void hmp_info_mice(Monitor *mon, const QDict *qdict) -{ - MouseInfoList *mice_list, *mouse; - - mice_list =3D qmp_query_mice(NULL); - if (!mice_list) { - monitor_printf(mon, "No mouse devices connected\n"); - return; - } - - for (mouse =3D mice_list; mouse; mouse =3D 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); } =20 - -#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 =3D 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 =3D client->next; - } -} - -static void hmp_info_vnc_servers(Monitor *mon, VncServerInfo2List *server) -{ - while (server) { - VncServerInfo2 *sinfo =3D server->value; - hmp_info_VncBasicInfo(mon, qapi_VncServerInfo2_base(sinfo), "Serve= r"); - hmp_info_vnc_authcrypt(mon, " ", sinfo->auth, - sinfo->has_vencrypt ? &sinfo->vencrypt : NU= LL); - server =3D server->next; - } -} - -void hmp_info_vnc(Monitor *mon, const QDict *qdict) -{ - VncInfo2List *info2l, *info2l_head; - Error *err =3D NULL; - - info2l =3D qmp_query_vnc_servers(&err); - info2l_head =3D info2l; - if (hmp_handle_error(mon, err)) { - return; - } - if (!info2l) { - monitor_printf(mon, "None\n"); - return; - } - - while (info2l) { - VncInfo2 *info =3D 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 =3D 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[] =3D { - [SPICE_CHANNEL_MAIN] =3D "main", - [SPICE_CHANNEL_DISPLAY] =3D "display", - [SPICE_CHANNEL_INPUTS] =3D "inputs", - [SPICE_CHANNEL_CURSOR] =3D "cursor", - [SPICE_CHANNEL_PLAYBACK] =3D "playback", - [SPICE_CHANNEL_RECORD] =3D "record", - [SPICE_CHANNEL_TUNNEL] =3D "tunnel", - [SPICE_CHANNEL_SMARTCARD] =3D "smartcard", - [SPICE_CHANNEL_USBREDIR] =3D "usbredir", - [SPICE_CHANNEL_PORT] =3D "port", - [SPICE_CHANNEL_WEBDAV] =3D "webdav", - }; - - info =3D 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 =3D=3D NULL) { - monitor_printf(mon, "Channels: none\n"); - } else { - for (chan =3D info->channels; chan; chan =3D 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 =3D "unknown"; - if (chan->value->channel_type > 0 && - chan->value->channel_type < ARRAY_SIZE(channel_names) && - channel_names[chan->value->channel_type]) { - channel_name =3D 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 Q= Dict *qdict) hmp_handle_error(mon, err); } =20 -void hmp_set_password(Monitor *mon, const QDict *qdict) -{ - const char *protocol =3D qdict_get_str(qdict, "protocol"); - const char *password =3D qdict_get_str(qdict, "password"); - const char *display =3D qdict_get_try_str(qdict, "display"); - const char *connected =3D qdict_get_try_str(qdict, "connected"); - Error *err =3D NULL; - - SetPasswordOptions opts =3D { - .password =3D (char *)password, - .has_connected =3D !!connected, - }; - - opts.connected =3D qapi_enum_parse(&SetPasswordAction_lookup, connecte= d, - SET_PASSWORD_ACTION_KEEP, &err); - if (err) { - goto out; - } - - opts.protocol =3D qapi_enum_parse(&DisplayProtocol_lookup, protocol, - DISPLAY_PROTOCOL_VNC, &err); - if (err) { - goto out; - } - - if (opts.protocol =3D=3D DISPLAY_PROTOCOL_VNC) { - opts.u.vnc.display =3D (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 =3D qdict_get_str(qdict, "protocol"); - const char *whenstr =3D qdict_get_str(qdict, "time"); - const char *display =3D qdict_get_try_str(qdict, "display"); - Error *err =3D NULL; - - ExpirePasswordOptions opts =3D { - .time =3D (char *)whenstr, - }; - - opts.protocol =3D qapi_enum_parse(&DisplayProtocol_lookup, protocol, - DISPLAY_PROTOCOL_VNC, &err); - if (err) { - goto out; - } - - if (opts.protocol =3D=3D DISPLAY_PROTOCOL_VNC) { - opts.u.vnc.display =3D (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); } =20 -void hmp_sendkey(Monitor *mon, const QDict *qdict) -{ - const char *keys =3D qdict_get_str(qdict, "keys"); - KeyValue *v =3D NULL; - KeyValueList *head =3D NULL, **tail =3D &head; - int has_hold_time =3D qdict_haskey(qdict, "hold-time"); - int hold_time =3D qdict_get_try_int(qdict, "hold-time", -1); - Error *err =3D NULL; - const char *separator; - int keyname_len; - - while (1) { - separator =3D qemu_strchrnul(keys, '-'); - keyname_len =3D separator - keys; - - /* Be compatible with old interface, convert user inputted "<" */ - if (keys[0] =3D=3D '<' && keyname_len =3D=3D 1) { - keys =3D "less"; - keyname_len =3D 4; - } - - v =3D 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 <=3D keys + keyname_len); - if (endp !=3D keys + keyname_len) { - goto err_out; - } - v->type =3D KEY_VALUE_KIND_NUMBER; - v->u.number.data =3D value; - } else { - int idx =3D index_from_key(keys, keyname_len); - if (idx =3D=3D Q_KEY_CODE__MAX) { - goto err_out; - } - v->type =3D KEY_VALUE_KIND_QCODE; - v->u.qcode.data =3D idx; - } - QAPI_LIST_APPEND(tail, v); - v =3D NULL; - - if (!*separator) { - break; - } - keys =3D 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 =3D qdict_get_str(qdict, "filename"); - const char *id =3D qdict_get_try_str(qdict, "device"); - int64_t head =3D qdict_get_try_int(qdict, "head", 0); - const char *input_format =3D qdict_get_try_str(qdict, "format"); - Error *err =3D NULL; - ImageFormat format; - - format =3D qapi_enum_parse(&ImageFormat_lookup, input_format, - IMAGE_FORMAT_PPM, &err); - if (err) { - goto end; - } - - qmp_screendump(filename, id, id !=3D NULL, head, - input_format !=3D NULL, format, &err); -end: - hmp_handle_error(mon, err); -} - void hmp_chardev_add(Monitor *mon, const QDict *qdict) { const char *args =3D qdict_get_str(qdict, "args"); diff --git a/monitor/misc.c b/monitor/misc.c index bf3f1c67ca..3d68940d28 100644 --- a/monitor/misc.c +++ b/monitor/misc.c @@ -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); } =20 -static int mouse_button_state; - -static void hmp_mouse_move(Monitor *mon, const QDict *qdict) -{ - int dx, dy, dz, button; - const char *dx_str =3D qdict_get_str(qdict, "dx_str"); - const char *dy_str =3D qdict_get_str(qdict, "dy_str"); - const char *dz_str =3D qdict_get_try_str(qdict, "dz_str"); - - dx =3D strtol(dx_str, NULL, 0); - dy =3D 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 =3D strtol(dz_str, NULL, 0); - if (dz !=3D 0) { - button =3D (dz > 0) ? INPUT_BUTTON_WHEEL_UP : INPUT_BUTTON_WHE= EL_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] =3D { - [INPUT_BUTTON_LEFT] =3D MOUSE_EVENT_LBUTTON, - [INPUT_BUTTON_MIDDLE] =3D MOUSE_EVENT_MBUTTON, - [INPUT_BUTTON_RIGHT] =3D MOUSE_EVENT_RBUTTON, - }; - int button_state =3D qdict_get_int(qdict, "button_state"); - - if (mouse_button_state =3D=3D button_state) { - return; - } - qemu_input_update_buttons(NULL, bmap, mouse_button_state, button_state= ); - qemu_input_event_sync(); - mouse_button_state =3D button_state; -} - static void hmp_ioport_read(Monitor *mon, const QDict *qdict) { int size =3D 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); } =20 -void sendkey_completion(ReadLineState *rs, int nb_args, const char *str) -{ - int i; - char *sep; - size_t len; - - if (nb_args !=3D 2) { - return; - } - sep =3D strrchr(str, '-'); - if (sep) { - str =3D sep + 1; - } - len =3D strlen(str); - readline_set_completion_index(rs, len); - for (i =3D 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; diff --git a/ui/ui-hmp-cmds.c b/ui/ui-hmp-cmds.c new file mode 100644 index 0000000000..4af92f8eaf --- /dev/null +++ b/ui/ui-hmp-cmds.c @@ -0,0 +1,422 @@ +/* + * HMP commands related to UI + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori + * + * 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 +#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 =3D qdict_get_str(qdict, "dx_str"); + const char *dy_str =3D qdict_get_str(qdict, "dy_str"); + const char *dz_str =3D qdict_get_try_str(qdict, "dz_str"); + + dx =3D strtol(dx_str, NULL, 0); + dy =3D 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 =3D strtol(dz_str, NULL, 0); + if (dz !=3D 0) { + button =3D (dz > 0) ? INPUT_BUTTON_WHEEL_UP : INPUT_BUTTON_WHE= EL_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] =3D { + [INPUT_BUTTON_LEFT] =3D MOUSE_EVENT_LBUTTON, + [INPUT_BUTTON_MIDDLE] =3D MOUSE_EVENT_MBUTTON, + [INPUT_BUTTON_RIGHT] =3D MOUSE_EVENT_RBUTTON, + }; + int button_state =3D qdict_get_int(qdict, "button_state"); + + if (mouse_button_state =3D=3D button_state) { + return; + } + qemu_input_update_buttons(NULL, bmap, mouse_button_state, button_state= ); + qemu_input_event_sync(); + mouse_button_state =3D button_state; +} + +void hmp_info_mice(Monitor *mon, const QDict *qdict) +{ + MouseInfoList *mice_list, *mouse; + + mice_list =3D qmp_query_mice(NULL); + if (!mice_list) { + monitor_printf(mon, "No mouse devices connected\n"); + return; + } + + for (mouse =3D mice_list; mouse; mouse =3D 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 =3D 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 =3D client->next; + } +} + +static void hmp_info_vnc_servers(Monitor *mon, VncServerInfo2List *server) +{ + while (server) { + VncServerInfo2 *sinfo =3D server->value; + hmp_info_VncBasicInfo(mon, qapi_VncServerInfo2_base(sinfo), "Serve= r"); + hmp_info_vnc_authcrypt(mon, " ", sinfo->auth, + sinfo->has_vencrypt ? &sinfo->vencrypt : NU= LL); + server =3D server->next; + } +} + +void hmp_info_vnc(Monitor *mon, const QDict *qdict) +{ + VncInfo2List *info2l, *info2l_head; + Error *err =3D NULL; + + info2l =3D qmp_query_vnc_servers(&err); + info2l_head =3D info2l; + if (hmp_handle_error(mon, err)) { + return; + } + if (!info2l) { + monitor_printf(mon, "None\n"); + return; + } + + while (info2l) { + VncInfo2 *info =3D 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 =3D 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[] =3D { + [SPICE_CHANNEL_MAIN] =3D "main", + [SPICE_CHANNEL_DISPLAY] =3D "display", + [SPICE_CHANNEL_INPUTS] =3D "inputs", + [SPICE_CHANNEL_CURSOR] =3D "cursor", + [SPICE_CHANNEL_PLAYBACK] =3D "playback", + [SPICE_CHANNEL_RECORD] =3D "record", + [SPICE_CHANNEL_TUNNEL] =3D "tunnel", + [SPICE_CHANNEL_SMARTCARD] =3D "smartcard", + [SPICE_CHANNEL_USBREDIR] =3D "usbredir", + [SPICE_CHANNEL_PORT] =3D "port", + [SPICE_CHANNEL_WEBDAV] =3D "webdav", + }; + + info =3D 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 =3D=3D NULL) { + monitor_printf(mon, "Channels: none\n"); + } else { + for (chan =3D info->channels; chan; chan =3D 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 =3D "unknown"; + if (chan->value->channel_type > 0 && + chan->value->channel_type < ARRAY_SIZE(channel_names) && + channel_names[chan->value->channel_type]) { + channel_name =3D 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 =3D qdict_get_str(qdict, "protocol"); + const char *password =3D qdict_get_str(qdict, "password"); + const char *display =3D qdict_get_try_str(qdict, "display"); + const char *connected =3D qdict_get_try_str(qdict, "connected"); + Error *err =3D NULL; + + SetPasswordOptions opts =3D { + .password =3D (char *)password, + .has_connected =3D !!connected, + }; + + opts.connected =3D qapi_enum_parse(&SetPasswordAction_lookup, connecte= d, + SET_PASSWORD_ACTION_KEEP, &err); + if (err) { + goto out; + } + + opts.protocol =3D qapi_enum_parse(&DisplayProtocol_lookup, protocol, + DISPLAY_PROTOCOL_VNC, &err); + if (err) { + goto out; + } + + if (opts.protocol =3D=3D DISPLAY_PROTOCOL_VNC) { + opts.u.vnc.display =3D (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 =3D qdict_get_str(qdict, "protocol"); + const char *whenstr =3D qdict_get_str(qdict, "time"); + const char *display =3D qdict_get_try_str(qdict, "display"); + Error *err =3D NULL; + + ExpirePasswordOptions opts =3D { + .time =3D (char *)whenstr, + }; + + opts.protocol =3D qapi_enum_parse(&DisplayProtocol_lookup, protocol, + DISPLAY_PROTOCOL_VNC, &err); + if (err) { + goto out; + } + + if (opts.protocol =3D=3D DISPLAY_PROTOCOL_VNC) { + opts.u.vnc.display =3D (char *)display; + } + + qmp_expire_password(&opts, &err); + +out: + hmp_handle_error(mon, err); +} + +void hmp_sendkey(Monitor *mon, const QDict *qdict) +{ + const char *keys =3D qdict_get_str(qdict, "keys"); + KeyValue *v =3D NULL; + KeyValueList *head =3D NULL, **tail =3D &head; + int has_hold_time =3D qdict_haskey(qdict, "hold-time"); + int hold_time =3D qdict_get_try_int(qdict, "hold-time", -1); + Error *err =3D NULL; + const char *separator; + int keyname_len; + + while (1) { + separator =3D qemu_strchrnul(keys, '-'); + keyname_len =3D separator - keys; + + /* Be compatible with old interface, convert user inputted "<" */ + if (keys[0] =3D=3D '<' && keyname_len =3D=3D 1) { + keys =3D "less"; + keyname_len =3D 4; + } + + v =3D 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 <=3D keys + keyname_len); + if (endp !=3D keys + keyname_len) { + goto err_out; + } + v->type =3D KEY_VALUE_KIND_NUMBER; + v->u.number.data =3D value; + } else { + int idx =3D index_from_key(keys, keyname_len); + if (idx =3D=3D Q_KEY_CODE__MAX) { + goto err_out; + } + v->type =3D KEY_VALUE_KIND_QCODE; + v->u.qcode.data =3D idx; + } + QAPI_LIST_APPEND(tail, v); + v =3D NULL; + + if (!*separator) { + break; + } + keys =3D 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 !=3D 2) { + return; + } + sep =3D strrchr(str, '-'); + if (sep) { + str =3D sep + 1; + } + len =3D strlen(str); + readline_set_completion_index(rs, len); + for (i =3D 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 =3D qdict_get_str(qdict, "filename"); + const char *id =3D qdict_get_try_str(qdict, "device"); + int64_t head =3D qdict_get_try_int(qdict, "head", 0); + const char *input_format =3D qdict_get_try_str(qdict, "format"); + Error *err =3D NULL; + ImageFormat format; + + format =3D qapi_enum_parse(&ImageFormat_lookup, input_format, + IMAGE_FORMAT_PPM, &err); + if (err) { + goto end; + } + + qmp_screendump(filename, id, id !=3D NULL, head, + input_format !=3D NULL, format, &err); +end: + hmp_handle_error(mon, err); +} diff --git a/ui/meson.build b/ui/meson.build index 9194ea335b..612ea2325b 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -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', )) --=20 2.39.0