diff --git a/include/char/char.h b/include/char/char.h index 2e24270895..afe002498e 100644 --- a/include/char/char.h +++ b/include/char/char.h @@ -245,6 +245,8 @@ CharDriverState *qemu_chr_find(const char *name); QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename); void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts *)); +void register_char_driver_qapi(const char *name, int kind, + void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp)); /* add an eventfd to the qemu devices that are polled */ CharDriverState *qemu_chr_open_eventfd(int eventfd); diff --git a/qemu-char.c b/qemu-char.c index 83787c74c4..c2e198e858 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -3204,7 +3204,11 @@ static CharDriverState *qemu_chr_open_pp(QemuOpts *opts) typedef struct CharDriver { const char *name; + /* old, pre qapi */ CharDriverState *(*open)(QemuOpts *opts); + /* new, qapi-based */ + int kind; + void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp); } CharDriver; static GSList *backends; @@ -3220,6 +3224,19 @@ void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts *) backends = g_slist_append(backends, s); } +void register_char_driver_qapi(const char *name, int kind, + void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp)) +{ + CharDriver *s; + + s = g_malloc0(sizeof(*s)); + s->name = g_strdup(name); + s->kind = kind; + s->parse = parse; + + backends = g_slist_append(backends, s); +} + CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts, void (*init)(struct CharDriverState *s), Error **errp) @@ -3251,6 +3268,32 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts, return NULL; } + if (!cd->open) { + /* using new, qapi init */ + ChardevBackend *backend = g_new0(ChardevBackend, 1); + ChardevReturn *ret = NULL; + const char *id = qemu_opts_id(opts); + + chr = NULL; + backend->kind = cd->kind; + if (cd->parse) { + cd->parse(opts, backend, errp); + if (error_is_set(errp)) { + goto qapi_out; + } + } + ret = qmp_chardev_add(qemu_opts_id(opts), backend, errp); + if (error_is_set(errp)) { + goto qapi_out; + } + chr = qemu_chr_find(id); + + qapi_out: + qapi_free_ChardevBackend(backend); + qapi_free_ChardevReturn(ret); + return chr; + } + chr = cd->open(opts); if (!chr) { error_setg(errp, "chardev: opening backend \"%s\" failed",