Merge remote-tracking branch 'spice/spice.v66' into staging
* spice/spice.v66: docs: add spice-port-fqdn.txt spice-qemu-char: register spicevmc ports during qemu_spice_init() spice-qemu-char: keep a list of spice chardev spice-qemu-char: add spiceport chardev spice-qemu-char: factor out CharDriverState creation spice-qemu-char: write to chardev whatever amount it can read qxl+vnc: register a vm state change handler for dummy spice_server qxl: save qemu_create_displaysurface_from result Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
commit
510981a097
19
docs/spice-port-fqdn.txt
Normal file
19
docs/spice-port-fqdn.txt
Normal file
@ -0,0 +1,19 @@
|
||||
A Spice port channel is an arbitrary communication between the Spice
|
||||
server host side and the client side.
|
||||
|
||||
Thanks to the associated reverse fully qualified domain name (fqdn),
|
||||
a Spice client can handle the various ports appropriately.
|
||||
|
||||
The following fqdn names are reserved by the QEMU project:
|
||||
|
||||
org.qemu.monitor.hmp.0
|
||||
QEMU human monitor
|
||||
|
||||
org.qemu.monitor.qmp.0:
|
||||
QEMU control monitor
|
||||
|
||||
org.qemu.console.serial.0
|
||||
QEMU virtual serial port
|
||||
|
||||
org.qemu.console.debug.0
|
||||
QEMU debug console
|
@ -113,7 +113,8 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl)
|
||||
qxl->guest_primary.bits_pp);
|
||||
if (qxl->guest_primary.qxl_stride > 0) {
|
||||
qemu_free_displaysurface(vga->ds);
|
||||
qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
|
||||
vga->ds->surface = qemu_create_displaysurface_from
|
||||
(qxl->guest_primary.surface.width,
|
||||
qxl->guest_primary.surface.height,
|
||||
qxl->guest_primary.bits_pp,
|
||||
qxl->guest_primary.abs_stride,
|
||||
|
@ -2762,6 +2762,9 @@ static const struct {
|
||||
#endif
|
||||
#ifdef CONFIG_SPICE
|
||||
{ .name = "spicevmc", .open = qemu_chr_open_spice },
|
||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
||||
{ .name = "spiceport", .open = qemu_chr_open_spice_port },
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1749,6 +1749,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
|
||||
#endif
|
||||
#if defined(CONFIG_SPICE)
|
||||
"-chardev spicevmc,id=id,name=name[,debug=debug]\n"
|
||||
"-chardev spiceport,id=id,name=name[,debug=debug]\n"
|
||||
#endif
|
||||
, QEMU_ARCH_ALL
|
||||
)
|
||||
@ -1776,6 +1777,7 @@ Backend is one of:
|
||||
@option{tty},
|
||||
@option{parport},
|
||||
@option{spicevmc}.
|
||||
@option{spiceport}.
|
||||
The specific backend will determine the applicable options.
|
||||
|
||||
All devices must have an id, which can be any string up to 127 characters long.
|
||||
@ -1961,6 +1963,17 @@ required.
|
||||
|
||||
Connect to a spice virtual machine channel, such as vdiport.
|
||||
|
||||
@item -chardev spiceport ,id=@var{id} ,debug=@var{debug}, name=@var{name}
|
||||
|
||||
@option{spiceport} is only available when spice support is built in.
|
||||
|
||||
@option{debug} debug level for spicevmc
|
||||
|
||||
@option{name} name of spice port to connect to
|
||||
|
||||
Connect to a spice port, allowing a Spice client to handle the traffic
|
||||
identified by a name (preferably a fqdn).
|
||||
|
||||
@end table
|
||||
ETEXI
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "ui/qemu-spice.h"
|
||||
#include <spice.h>
|
||||
#include <spice-experimental.h>
|
||||
#include <spice/protocol.h>
|
||||
|
||||
#include "osdep.h"
|
||||
|
||||
@ -14,8 +15,6 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VMC_MAX_HOST_WRITE 2048
|
||||
|
||||
typedef struct SpiceCharDriver {
|
||||
CharDriverState* chr;
|
||||
SpiceCharDeviceInstance sin;
|
||||
@ -25,8 +24,12 @@ typedef struct SpiceCharDriver {
|
||||
uint8_t *datapos;
|
||||
ssize_t bufsize, datalen;
|
||||
uint32_t debug;
|
||||
QLIST_ENTRY(SpiceCharDriver) next;
|
||||
} SpiceCharDriver;
|
||||
|
||||
static QLIST_HEAD(, SpiceCharDriver) spice_chars =
|
||||
QLIST_HEAD_INITIALIZER(spice_chars);
|
||||
|
||||
static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
|
||||
{
|
||||
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
|
||||
@ -35,8 +38,8 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
|
||||
uint8_t* p = (uint8_t*)buf;
|
||||
|
||||
while (len > 0) {
|
||||
last_out = MIN(len, VMC_MAX_HOST_WRITE);
|
||||
if (qemu_chr_be_can_write(scd->chr) < last_out) {
|
||||
last_out = MIN(len, qemu_chr_be_can_write(scd->chr));
|
||||
if (last_out <= 0) {
|
||||
break;
|
||||
}
|
||||
qemu_chr_be_write(scd->chr, p, last_out);
|
||||
@ -69,6 +72,27 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
|
||||
return bytes;
|
||||
}
|
||||
|
||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
||||
static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event)
|
||||
{
|
||||
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
|
||||
int chr_event;
|
||||
|
||||
switch (event) {
|
||||
case SPICE_PORT_EVENT_BREAK:
|
||||
chr_event = CHR_EVENT_BREAK;
|
||||
break;
|
||||
default:
|
||||
dprintf(scd, 2, "%s: unknown %d\n", __func__, event);
|
||||
return;
|
||||
}
|
||||
|
||||
dprintf(scd, 2, "%s: %d\n", __func__, event);
|
||||
trace_spice_vmc_event(chr_event);
|
||||
qemu_chr_be_event(scd->chr, chr_event);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void vmc_state(SpiceCharDeviceInstance *sin, int connected)
|
||||
{
|
||||
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
|
||||
@ -105,6 +129,9 @@ static SpiceCharDeviceInterface vmc_interface = {
|
||||
.state = vmc_state,
|
||||
.write = vmc_write,
|
||||
.read = vmc_read,
|
||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
||||
.event = vmc_event,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -156,6 +183,7 @@ static void spice_chr_close(struct CharDriverState *chr)
|
||||
|
||||
printf("%s\n", __func__);
|
||||
vmc_unregister_interface(s);
|
||||
QLIST_REMOVE(s, next);
|
||||
g_free(s);
|
||||
}
|
||||
|
||||
@ -188,13 +216,34 @@ static void print_allowed_subtypes(void)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
|
||||
static CharDriverState *chr_open(QemuOpts *opts, const char *subtype)
|
||||
{
|
||||
CharDriverState *chr;
|
||||
SpiceCharDriver *s;
|
||||
const char* name = qemu_opt_get(opts, "name");
|
||||
uint32_t debug = qemu_opt_get_number(opts, "debug", 0);
|
||||
const char** psubtype = spice_server_char_device_recognized_subtypes();
|
||||
|
||||
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;
|
||||
chr->chr_write = spice_chr_write;
|
||||
chr->chr_close = spice_chr_close;
|
||||
chr->chr_guest_open = spice_chr_guest_open;
|
||||
chr->chr_guest_close = spice_chr_guest_close;
|
||||
|
||||
QLIST_INSERT_HEAD(&spice_chars, s, next);
|
||||
|
||||
return chr;
|
||||
}
|
||||
|
||||
CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
|
||||
{
|
||||
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) {
|
||||
@ -214,17 +263,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
chr->chr_write = spice_chr_write;
|
||||
chr->chr_close = spice_chr_close;
|
||||
chr->chr_guest_open = spice_chr_guest_open;
|
||||
chr->chr_guest_close = spice_chr_guest_close;
|
||||
chr = chr_open(opts, subtype);
|
||||
|
||||
#if SPICE_SERVER_VERSION < 0x000901
|
||||
/* See comment in vmc_state() */
|
||||
@ -235,3 +274,35 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
|
||||
|
||||
return chr;
|
||||
}
|
||||
|
||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
||||
CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts)
|
||||
{
|
||||
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");
|
||||
s = chr->opaque;
|
||||
s->sin.portname = name;
|
||||
|
||||
return chr;
|
||||
}
|
||||
|
||||
void qemu_spice_register_ports(void)
|
||||
{
|
||||
SpiceCharDriver *s;
|
||||
|
||||
QLIST_FOREACH(s, &spice_chars, next) {
|
||||
if (s->sin.portname == NULL) {
|
||||
continue;
|
||||
}
|
||||
vmc_register_interface(s);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -535,6 +535,7 @@ spice_vmc_write(ssize_t out, int len) "spice wrottn %zd of requested %d"
|
||||
spice_vmc_read(int bytes, int len) "spice read %d of requested %d"
|
||||
spice_vmc_register_interface(void *scd) "spice vmc registered interface %p"
|
||||
spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p"
|
||||
spice_vmc_event(int event) "spice vmc event %d"
|
||||
|
||||
# hw/lm32_pic.c
|
||||
lm32_pic_raise_irq(void) "Raise CPU interrupt"
|
||||
|
@ -46,6 +46,10 @@ 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);
|
||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
||||
CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts);
|
||||
void qemu_spice_register_ports(void);
|
||||
#endif
|
||||
|
||||
#else /* CONFIG_SPICE */
|
||||
#include "monitor.h"
|
||||
|
@ -714,6 +714,10 @@ void qemu_spice_init(void)
|
||||
g_free(x509_key_file);
|
||||
g_free(x509_cert_file);
|
||||
g_free(x509_cacert_file);
|
||||
|
||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
||||
qemu_spice_register_ports();
|
||||
#endif
|
||||
}
|
||||
|
||||
int qemu_spice_add_interface(SpiceBaseInstance *sin)
|
||||
@ -732,6 +736,8 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin)
|
||||
*/
|
||||
spice_server = spice_server_new();
|
||||
spice_server_init(spice_server, &core_interface);
|
||||
qemu_add_vm_change_state_handler(vm_change_state_handler,
|
||||
&spice_server);
|
||||
}
|
||||
|
||||
return spice_server_add_interface(spice_server, sin);
|
||||
|
Loading…
Reference in New Issue
Block a user