diff --git a/include/ui/qemu-spice.h b/include/ui/qemu-spice.h index 5a78fd764d7e359c27d0ac549130ed92ac8fcbb0..eba6d77d1d8d013dc4609d9ba871bde837b98cc6 100644 --- a/include/ui/qemu-spice.h +++ b/include/ui/qemu-spice.h @@ -44,10 +44,13 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port, void do_info_spice_print(Monitor *mon, const QObject *data); void do_info_spice(Monitor *mon, QObject **ret_data); -CharDriverState *qemu_chr_open_spice(QemuOpts *opts); +CharDriverState *qemu_chr_open_spice_vmc(const char *type); #if SPICE_SERVER_VERSION >= 0x000c02 -CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts); +CharDriverState *qemu_chr_open_spice_port(const char *name); void qemu_spice_register_ports(void); +#else +static inline CharDriverState *qemu_chr_open_spice_port(const char *name) +{ return NULL; } #endif #else /* CONFIG_SPICE */ diff --git a/qapi-schema.json b/qapi-schema.json index 7ea32ed415eef4730109ae180c0d54401e1ca96c..dad4d4aed1b44dfe888820d1d1fa72dac75c863e 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -3208,6 +3208,28 @@ ## { 'type': 'ChardevStdio', 'data': { '*signal' : 'bool' } } +## +# @ChardevSpiceChannel: +# +# Configuration info for spice vm channel chardevs. +# +# @type: kind of channel (for example vdagent). +# +# Since: 1.5 +## +{ 'type': 'ChardevSpiceChannel', 'data': { 'type' : 'str' } } + +## +# @ChardevSpicePort: +# +# Configuration info for spice port chardevs. +# +# @fqdn: name of the channel (see docs/spice-port-fqdn.txt) +# +# Since: 1.5 +## +{ 'type': 'ChardevSpicePort', 'data': { 'fqdn' : 'str' } } + ## # @ChardevBackend: # @@ -3228,7 +3250,9 @@ 'msmouse': 'ChardevDummy', 'braille': 'ChardevDummy', 'stdio' : 'ChardevStdio', - 'console': 'ChardevDummy' } } + 'console': 'ChardevDummy', + 'spicevmc' : 'ChardevSpiceChannel', + 'spiceport' : 'ChardevSpicePort' } } ## # @ChardevReturn: diff --git a/qemu-char.c b/qemu-char.c index 427901c0c582fd45fea49b52490f027d668907c2..f13374770a6777fed0f3bb79cb6a49020b141f73 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -3728,6 +3728,14 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend, case CHARDEV_BACKEND_KIND_CONSOLE: chr = qemu_chr_open_win_con(); break; +#endif +#ifdef CONFIG_SPICE + case CHARDEV_BACKEND_KIND_SPICEVMC: + chr = qemu_chr_open_spice_vmc(backend->spicevmc->type); + break; + case CHARDEV_BACKEND_KIND_SPICEPORT: + chr = qemu_chr_open_spice_port(backend->spiceport->fqdn); + break; #endif default: error_setg(errp, "unknown chardev backend (%d)", backend->kind); diff --git a/spice-qemu-char.c b/spice-qemu-char.c index aea3d24e7d084984d414492b84f0babff7afca35..0c92ca850b56d7632d0d04224c647d8066817d36 100644 --- a/spice-qemu-char.c +++ b/spice-qemu-char.c @@ -217,16 +217,14 @@ static void print_allowed_subtypes(void) fprintf(stderr, "\n"); } -static CharDriverState *chr_open(QemuOpts *opts, const char *subtype) +static CharDriverState *chr_open(const char *subtype) { CharDriverState *chr; SpiceCharDriver *s; - uint32_t debug = qemu_opt_get_number(opts, "debug", 0); chr = g_malloc0(sizeof(CharDriverState)); s = g_malloc0(sizeof(SpiceCharDriver)); s->chr = chr; - s->debug = debug; s->active = false; s->sin.subtype = subtype; chr->opaque = s; @@ -240,35 +238,32 @@ static CharDriverState *chr_open(QemuOpts *opts, const char *subtype) return chr; } -CharDriverState *qemu_chr_open_spice(QemuOpts *opts) +CharDriverState *qemu_chr_open_spice_vmc(const char *type) { CharDriverState *chr; - const char *name = qemu_opt_get(opts, "name"); const char **psubtype = spice_server_char_device_recognized_subtypes(); - const char *subtype = NULL; - if (name == NULL) { + if (type == NULL) { fprintf(stderr, "spice-qemu-char: missing name parameter\n"); print_allowed_subtypes(); return NULL; } - for(;*psubtype != NULL; ++psubtype) { - if (strcmp(name, *psubtype) == 0) { - subtype = *psubtype; + for (; *psubtype != NULL; ++psubtype) { + if (strcmp(type, *psubtype) == 0) { break; } } - if (subtype == NULL) { - fprintf(stderr, "spice-qemu-char: unsupported name: %s\n", name); + if (*psubtype == NULL) { + fprintf(stderr, "spice-qemu-char: unsupported type: %s\n", type); print_allowed_subtypes(); return NULL; } - chr = chr_open(opts, subtype); + chr = chr_open(type); #if SPICE_SERVER_VERSION < 0x000901 /* See comment in vmc_state() */ - if (strcmp(subtype, "vdagent") == 0) { + if (strcmp(type, "vdagent") == 0) { qemu_chr_generic_open(chr); } #endif @@ -277,18 +272,17 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts) } #if SPICE_SERVER_VERSION >= 0x000c02 -CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts) +CharDriverState *qemu_chr_open_spice_port(const char *name) { CharDriverState *chr; SpiceCharDriver *s; - const char *name = qemu_opt_get(opts, "name"); if (name == NULL) { fprintf(stderr, "spice-qemu-char: missing name parameter\n"); return NULL; } - chr = chr_open(opts, "port"); + chr = chr_open("port"); s = chr->opaque; s->sin.portname = name; @@ -308,12 +302,38 @@ void qemu_spice_register_ports(void) } #endif +static void qemu_chr_parse_spice_vmc(QemuOpts *opts, ChardevBackend *backend, + Error **errp) +{ + const char *name = qemu_opt_get(opts, "name"); + + if (name == NULL) { + error_setg(errp, "chardev: spice channel: no name given"); + return; + } + backend->spicevmc = g_new0(ChardevSpiceChannel, 1); + backend->spicevmc->type = g_strdup(name); +} + +static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend, + Error **errp) +{ + const char *name = qemu_opt_get(opts, "name"); + + if (name == NULL) { + error_setg(errp, "chardev: spice port: no name given"); + return; + } + backend->spiceport = g_new0(ChardevSpicePort, 1); + backend->spiceport->fqdn = g_strdup(name); +} + static void register_types(void) { - register_char_driver("spicevmc", qemu_chr_open_spice); -#if SPICE_SERVER_VERSION >= 0x000c02 - register_char_driver("spiceport", qemu_chr_open_spice_port); -#endif + register_char_driver_qapi("spicevmc", CHARDEV_BACKEND_KIND_SPICEVMC, + qemu_chr_parse_spice_vmc); + register_char_driver_qapi("spiceport", CHARDEV_BACKEND_KIND_SPICEPORT, + qemu_chr_parse_spice_port); } type_init(register_types);