1*b7d75c0bSMarkus Armbruster /*
2*b7d75c0bSMarkus Armbruster * HMP commands related to character devices
3*b7d75c0bSMarkus Armbruster *
4*b7d75c0bSMarkus Armbruster * Copyright IBM, Corp. 2011
5*b7d75c0bSMarkus Armbruster *
6*b7d75c0bSMarkus Armbruster * Authors:
7*b7d75c0bSMarkus Armbruster * Anthony Liguori <aliguori@us.ibm.com>
8*b7d75c0bSMarkus Armbruster *
9*b7d75c0bSMarkus Armbruster * This work is licensed under the terms of the GNU GPL, version 2. See
10*b7d75c0bSMarkus Armbruster * the COPYING file in the top-level directory.
11*b7d75c0bSMarkus Armbruster *
12*b7d75c0bSMarkus Armbruster * Contributions after 2012-01-13 are licensed under the terms of the
13*b7d75c0bSMarkus Armbruster * GNU GPL, version 2 or (at your option) any later version.
14*b7d75c0bSMarkus Armbruster */
15*b7d75c0bSMarkus Armbruster
16*b7d75c0bSMarkus Armbruster #include "qemu/osdep.h"
17*b7d75c0bSMarkus Armbruster #include "chardev/char.h"
18*b7d75c0bSMarkus Armbruster #include "monitor/hmp.h"
19*b7d75c0bSMarkus Armbruster #include "monitor/monitor.h"
20*b7d75c0bSMarkus Armbruster #include "qapi/error.h"
21*b7d75c0bSMarkus Armbruster #include "qapi/qapi-commands-char.h"
22*b7d75c0bSMarkus Armbruster #include "qapi/qmp/qdict.h"
23*b7d75c0bSMarkus Armbruster #include "qemu/config-file.h"
24*b7d75c0bSMarkus Armbruster #include "qemu/option.h"
25*b7d75c0bSMarkus Armbruster
hmp_info_chardev(Monitor * mon,const QDict * qdict)26*b7d75c0bSMarkus Armbruster void hmp_info_chardev(Monitor *mon, const QDict *qdict)
27*b7d75c0bSMarkus Armbruster {
28*b7d75c0bSMarkus Armbruster ChardevInfoList *char_info, *info;
29*b7d75c0bSMarkus Armbruster
30*b7d75c0bSMarkus Armbruster char_info = qmp_query_chardev(NULL);
31*b7d75c0bSMarkus Armbruster for (info = char_info; info; info = info->next) {
32*b7d75c0bSMarkus Armbruster monitor_printf(mon, "%s: filename=%s\n", info->value->label,
33*b7d75c0bSMarkus Armbruster info->value->filename);
34*b7d75c0bSMarkus Armbruster }
35*b7d75c0bSMarkus Armbruster
36*b7d75c0bSMarkus Armbruster qapi_free_ChardevInfoList(char_info);
37*b7d75c0bSMarkus Armbruster }
38*b7d75c0bSMarkus Armbruster
hmp_ringbuf_write(Monitor * mon,const QDict * qdict)39*b7d75c0bSMarkus Armbruster void hmp_ringbuf_write(Monitor *mon, const QDict *qdict)
40*b7d75c0bSMarkus Armbruster {
41*b7d75c0bSMarkus Armbruster const char *chardev = qdict_get_str(qdict, "device");
42*b7d75c0bSMarkus Armbruster const char *data = qdict_get_str(qdict, "data");
43*b7d75c0bSMarkus Armbruster Error *err = NULL;
44*b7d75c0bSMarkus Armbruster
45*b7d75c0bSMarkus Armbruster qmp_ringbuf_write(chardev, data, false, 0, &err);
46*b7d75c0bSMarkus Armbruster
47*b7d75c0bSMarkus Armbruster hmp_handle_error(mon, err);
48*b7d75c0bSMarkus Armbruster }
49*b7d75c0bSMarkus Armbruster
hmp_ringbuf_read(Monitor * mon,const QDict * qdict)50*b7d75c0bSMarkus Armbruster void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
51*b7d75c0bSMarkus Armbruster {
52*b7d75c0bSMarkus Armbruster uint32_t size = qdict_get_int(qdict, "size");
53*b7d75c0bSMarkus Armbruster const char *chardev = qdict_get_str(qdict, "device");
54*b7d75c0bSMarkus Armbruster char *data;
55*b7d75c0bSMarkus Armbruster Error *err = NULL;
56*b7d75c0bSMarkus Armbruster int i;
57*b7d75c0bSMarkus Armbruster
58*b7d75c0bSMarkus Armbruster data = qmp_ringbuf_read(chardev, size, false, 0, &err);
59*b7d75c0bSMarkus Armbruster if (hmp_handle_error(mon, err)) {
60*b7d75c0bSMarkus Armbruster return;
61*b7d75c0bSMarkus Armbruster }
62*b7d75c0bSMarkus Armbruster
63*b7d75c0bSMarkus Armbruster for (i = 0; data[i]; i++) {
64*b7d75c0bSMarkus Armbruster unsigned char ch = data[i];
65*b7d75c0bSMarkus Armbruster
66*b7d75c0bSMarkus Armbruster if (ch == '\\') {
67*b7d75c0bSMarkus Armbruster monitor_printf(mon, "\\\\");
68*b7d75c0bSMarkus Armbruster } else if ((ch < 0x20 && ch != '\n' && ch != '\t') || ch == 0x7F) {
69*b7d75c0bSMarkus Armbruster monitor_printf(mon, "\\u%04X", ch);
70*b7d75c0bSMarkus Armbruster } else {
71*b7d75c0bSMarkus Armbruster monitor_printf(mon, "%c", ch);
72*b7d75c0bSMarkus Armbruster }
73*b7d75c0bSMarkus Armbruster
74*b7d75c0bSMarkus Armbruster }
75*b7d75c0bSMarkus Armbruster monitor_printf(mon, "\n");
76*b7d75c0bSMarkus Armbruster g_free(data);
77*b7d75c0bSMarkus Armbruster }
78*b7d75c0bSMarkus Armbruster
hmp_chardev_add(Monitor * mon,const QDict * qdict)79*b7d75c0bSMarkus Armbruster void hmp_chardev_add(Monitor *mon, const QDict *qdict)
80*b7d75c0bSMarkus Armbruster {
81*b7d75c0bSMarkus Armbruster const char *args = qdict_get_str(qdict, "args");
82*b7d75c0bSMarkus Armbruster Error *err = NULL;
83*b7d75c0bSMarkus Armbruster QemuOpts *opts;
84*b7d75c0bSMarkus Armbruster
85*b7d75c0bSMarkus Armbruster opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"), args, true);
86*b7d75c0bSMarkus Armbruster if (opts == NULL) {
87*b7d75c0bSMarkus Armbruster error_setg(&err, "Parsing chardev args failed");
88*b7d75c0bSMarkus Armbruster } else {
89*b7d75c0bSMarkus Armbruster qemu_chr_new_from_opts(opts, NULL, &err);
90*b7d75c0bSMarkus Armbruster qemu_opts_del(opts);
91*b7d75c0bSMarkus Armbruster }
92*b7d75c0bSMarkus Armbruster hmp_handle_error(mon, err);
93*b7d75c0bSMarkus Armbruster }
94*b7d75c0bSMarkus Armbruster
hmp_chardev_change(Monitor * mon,const QDict * qdict)95*b7d75c0bSMarkus Armbruster void hmp_chardev_change(Monitor *mon, const QDict *qdict)
96*b7d75c0bSMarkus Armbruster {
97*b7d75c0bSMarkus Armbruster const char *args = qdict_get_str(qdict, "args");
98*b7d75c0bSMarkus Armbruster const char *id;
99*b7d75c0bSMarkus Armbruster Error *err = NULL;
100*b7d75c0bSMarkus Armbruster ChardevBackend *backend = NULL;
101*b7d75c0bSMarkus Armbruster ChardevReturn *ret = NULL;
102*b7d75c0bSMarkus Armbruster QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"), args,
103*b7d75c0bSMarkus Armbruster true);
104*b7d75c0bSMarkus Armbruster if (!opts) {
105*b7d75c0bSMarkus Armbruster error_setg(&err, "Parsing chardev args failed");
106*b7d75c0bSMarkus Armbruster goto end;
107*b7d75c0bSMarkus Armbruster }
108*b7d75c0bSMarkus Armbruster
109*b7d75c0bSMarkus Armbruster id = qdict_get_str(qdict, "id");
110*b7d75c0bSMarkus Armbruster if (qemu_opts_id(opts)) {
111*b7d75c0bSMarkus Armbruster error_setg(&err, "Unexpected 'id' parameter");
112*b7d75c0bSMarkus Armbruster goto end;
113*b7d75c0bSMarkus Armbruster }
114*b7d75c0bSMarkus Armbruster
115*b7d75c0bSMarkus Armbruster backend = qemu_chr_parse_opts(opts, &err);
116*b7d75c0bSMarkus Armbruster if (!backend) {
117*b7d75c0bSMarkus Armbruster goto end;
118*b7d75c0bSMarkus Armbruster }
119*b7d75c0bSMarkus Armbruster
120*b7d75c0bSMarkus Armbruster ret = qmp_chardev_change(id, backend, &err);
121*b7d75c0bSMarkus Armbruster
122*b7d75c0bSMarkus Armbruster end:
123*b7d75c0bSMarkus Armbruster qapi_free_ChardevReturn(ret);
124*b7d75c0bSMarkus Armbruster qapi_free_ChardevBackend(backend);
125*b7d75c0bSMarkus Armbruster qemu_opts_del(opts);
126*b7d75c0bSMarkus Armbruster hmp_handle_error(mon, err);
127*b7d75c0bSMarkus Armbruster }
128*b7d75c0bSMarkus Armbruster
hmp_chardev_remove(Monitor * mon,const QDict * qdict)129*b7d75c0bSMarkus Armbruster void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
130*b7d75c0bSMarkus Armbruster {
131*b7d75c0bSMarkus Armbruster Error *local_err = NULL;
132*b7d75c0bSMarkus Armbruster
133*b7d75c0bSMarkus Armbruster qmp_chardev_remove(qdict_get_str(qdict, "id"), &local_err);
134*b7d75c0bSMarkus Armbruster hmp_handle_error(mon, local_err);
135*b7d75c0bSMarkus Armbruster }
136*b7d75c0bSMarkus Armbruster
hmp_chardev_send_break(Monitor * mon,const QDict * qdict)137*b7d75c0bSMarkus Armbruster void hmp_chardev_send_break(Monitor *mon, const QDict *qdict)
138*b7d75c0bSMarkus Armbruster {
139*b7d75c0bSMarkus Armbruster Error *local_err = NULL;
140*b7d75c0bSMarkus Armbruster
141*b7d75c0bSMarkus Armbruster qmp_chardev_send_break(qdict_get_str(qdict, "id"), &local_err);
142*b7d75c0bSMarkus Armbruster hmp_handle_error(mon, local_err);
143*b7d75c0bSMarkus Armbruster }
144*b7d75c0bSMarkus Armbruster
chardev_add_completion(ReadLineState * rs,int nb_args,const char * str)145*b7d75c0bSMarkus Armbruster void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str)
146*b7d75c0bSMarkus Armbruster {
147*b7d75c0bSMarkus Armbruster size_t len;
148*b7d75c0bSMarkus Armbruster ChardevBackendInfoList *list, *start;
149*b7d75c0bSMarkus Armbruster
150*b7d75c0bSMarkus Armbruster if (nb_args != 2) {
151*b7d75c0bSMarkus Armbruster return;
152*b7d75c0bSMarkus Armbruster }
153*b7d75c0bSMarkus Armbruster len = strlen(str);
154*b7d75c0bSMarkus Armbruster readline_set_completion_index(rs, len);
155*b7d75c0bSMarkus Armbruster
156*b7d75c0bSMarkus Armbruster start = list = qmp_query_chardev_backends(NULL);
157*b7d75c0bSMarkus Armbruster while (list) {
158*b7d75c0bSMarkus Armbruster const char *chr_name = list->value->name;
159*b7d75c0bSMarkus Armbruster
160*b7d75c0bSMarkus Armbruster if (!strncmp(chr_name, str, len)) {
161*b7d75c0bSMarkus Armbruster readline_add_completion(rs, chr_name);
162*b7d75c0bSMarkus Armbruster }
163*b7d75c0bSMarkus Armbruster list = list->next;
164*b7d75c0bSMarkus Armbruster }
165*b7d75c0bSMarkus Armbruster qapi_free_ChardevBackendInfoList(start);
166*b7d75c0bSMarkus Armbruster }
167*b7d75c0bSMarkus Armbruster
chardev_remove_completion(ReadLineState * rs,int nb_args,const char * str)168*b7d75c0bSMarkus Armbruster void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str)
169*b7d75c0bSMarkus Armbruster {
170*b7d75c0bSMarkus Armbruster size_t len;
171*b7d75c0bSMarkus Armbruster ChardevInfoList *list, *start;
172*b7d75c0bSMarkus Armbruster
173*b7d75c0bSMarkus Armbruster if (nb_args != 2) {
174*b7d75c0bSMarkus Armbruster return;
175*b7d75c0bSMarkus Armbruster }
176*b7d75c0bSMarkus Armbruster len = strlen(str);
177*b7d75c0bSMarkus Armbruster readline_set_completion_index(rs, len);
178*b7d75c0bSMarkus Armbruster
179*b7d75c0bSMarkus Armbruster start = list = qmp_query_chardev(NULL);
180*b7d75c0bSMarkus Armbruster while (list) {
181*b7d75c0bSMarkus Armbruster ChardevInfo *chr = list->value;
182*b7d75c0bSMarkus Armbruster
183*b7d75c0bSMarkus Armbruster if (!strncmp(chr->label, str, len)) {
184*b7d75c0bSMarkus Armbruster readline_add_completion(rs, chr->label);
185*b7d75c0bSMarkus Armbruster }
186*b7d75c0bSMarkus Armbruster list = list->next;
187*b7d75c0bSMarkus Armbruster }
188*b7d75c0bSMarkus Armbruster qapi_free_ChardevInfoList(start);
189*b7d75c0bSMarkus Armbruster }
190*b7d75c0bSMarkus Armbruster
ringbuf_completion(ReadLineState * rs,const char * str)191*b7d75c0bSMarkus Armbruster static void ringbuf_completion(ReadLineState *rs, const char *str)
192*b7d75c0bSMarkus Armbruster {
193*b7d75c0bSMarkus Armbruster size_t len;
194*b7d75c0bSMarkus Armbruster ChardevInfoList *list, *start;
195*b7d75c0bSMarkus Armbruster
196*b7d75c0bSMarkus Armbruster len = strlen(str);
197*b7d75c0bSMarkus Armbruster readline_set_completion_index(rs, len);
198*b7d75c0bSMarkus Armbruster
199*b7d75c0bSMarkus Armbruster start = list = qmp_query_chardev(NULL);
200*b7d75c0bSMarkus Armbruster while (list) {
201*b7d75c0bSMarkus Armbruster ChardevInfo *chr_info = list->value;
202*b7d75c0bSMarkus Armbruster
203*b7d75c0bSMarkus Armbruster if (!strncmp(chr_info->label, str, len)) {
204*b7d75c0bSMarkus Armbruster Chardev *chr = qemu_chr_find(chr_info->label);
205*b7d75c0bSMarkus Armbruster if (chr && CHARDEV_IS_RINGBUF(chr)) {
206*b7d75c0bSMarkus Armbruster readline_add_completion(rs, chr_info->label);
207*b7d75c0bSMarkus Armbruster }
208*b7d75c0bSMarkus Armbruster }
209*b7d75c0bSMarkus Armbruster list = list->next;
210*b7d75c0bSMarkus Armbruster }
211*b7d75c0bSMarkus Armbruster qapi_free_ChardevInfoList(start);
212*b7d75c0bSMarkus Armbruster }
213*b7d75c0bSMarkus Armbruster
ringbuf_write_completion(ReadLineState * rs,int nb_args,const char * str)214*b7d75c0bSMarkus Armbruster void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str)
215*b7d75c0bSMarkus Armbruster {
216*b7d75c0bSMarkus Armbruster if (nb_args != 2) {
217*b7d75c0bSMarkus Armbruster return;
218*b7d75c0bSMarkus Armbruster }
219*b7d75c0bSMarkus Armbruster ringbuf_completion(rs, str);
220*b7d75c0bSMarkus Armbruster }
221