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