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 } 221