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