]>
Commit | Line | Data |
---|---|---|
b7d75c0b MA |
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | } |