Revision cbcc6336
b/Makefile.objs | ||
---|---|---|
105 | 105 |
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o |
106 | 106 |
common-obj-$(CONFIG_WIN32) += version.o |
107 | 107 |
|
108 |
common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display.o |
|
108 |
common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display.o spice-qemu-char.o
|
|
109 | 109 |
|
110 | 110 |
audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o |
111 | 111 |
audio-obj-$(CONFIG_SDL) += sdlaudio.o |
b/qemu-char.c | ||
---|---|---|
97 | 97 |
#endif |
98 | 98 |
|
99 | 99 |
#include "qemu_socket.h" |
100 |
#include "ui/qemu-spice.h" |
|
100 | 101 |
|
101 | 102 |
#define READ_BUF_LEN 4096 |
102 | 103 |
|
... | ... | |
2495 | 2496 |
|| defined(__FreeBSD_kernel__) |
2496 | 2497 |
{ .name = "parport", .open = qemu_chr_open_pp }, |
2497 | 2498 |
#endif |
2499 |
#ifdef CONFIG_SPICE |
|
2500 |
{ .name = "spicevmc", .open = qemu_chr_open_spice }, |
|
2501 |
#endif |
|
2498 | 2502 |
}; |
2499 | 2503 |
|
2500 | 2504 |
CharDriverState *qemu_chr_open_opts(QemuOpts *opts, |
b/qemu-config.c | ||
---|---|---|
146 | 146 |
},{ |
147 | 147 |
.name = "signal", |
148 | 148 |
.type = QEMU_OPT_BOOL, |
149 |
},{ |
|
150 |
.name = "name", |
|
151 |
.type = QEMU_OPT_STRING, |
|
152 |
},{ |
|
153 |
.name = "debug", |
|
154 |
.type = QEMU_OPT_NUMBER, |
|
149 | 155 |
}, |
150 | 156 |
{ /* end of list */ } |
151 | 157 |
}, |
b/qemu-options.hx | ||
---|---|---|
1368 | 1368 |
#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) |
1369 | 1369 |
"-chardev parport,id=id,path=path[,mux=on|off]\n" |
1370 | 1370 |
#endif |
1371 |
#if defined(CONFIG_SPICE) |
|
1372 |
"-chardev spicevmc,id=id,name=name[,debug=debug]\n" |
|
1373 |
#endif |
|
1371 | 1374 |
, QEMU_ARCH_ALL |
1372 | 1375 |
) |
1373 | 1376 |
|
... | ... | |
1392 | 1395 |
@option{stdio}, |
1393 | 1396 |
@option{braille}, |
1394 | 1397 |
@option{tty}, |
1395 |
@option{parport}. |
|
1398 |
@option{parport}, |
|
1399 |
@option{spicevmc}. |
|
1396 | 1400 |
The specific backend will determine the applicable options. |
1397 | 1401 |
|
1398 | 1402 |
All devices must have an id, which can be any string up to 127 characters long. |
... | ... | |
1568 | 1572 |
@option{path} specifies the path to the parallel port device. @option{path} is |
1569 | 1573 |
required. |
1570 | 1574 |
|
1575 |
#if defined(CONFIG_SPICE) |
|
1576 |
@item -chardev spicevmc ,id=@var{id} ,debug=@var{debug}, name=@var{name} |
|
1577 |
|
|
1578 |
@option{debug} debug level for spicevmc |
|
1579 |
|
|
1580 |
@option{name} name of spice channel to connect to |
|
1581 |
|
|
1582 |
Connect to a spice virtual machine channel, such as vdiport. |
|
1583 |
#endif |
|
1584 |
|
|
1571 | 1585 |
@end table |
1572 | 1586 |
ETEXI |
1573 | 1587 |
|
b/spice-qemu-char.c | ||
---|---|---|
1 |
#include "config-host.h" |
|
2 |
#include "trace.h" |
|
3 |
#include "ui/qemu-spice.h" |
|
4 |
#include <spice.h> |
|
5 |
#include <spice-experimental.h> |
|
6 |
|
|
7 |
#include "osdep.h" |
|
8 |
|
|
9 |
#define dprintf(_scd, _level, _fmt, ...) \ |
|
10 |
do { \ |
|
11 |
static unsigned __dprintf_counter = 0; \ |
|
12 |
if (_scd->debug >= _level) { \ |
|
13 |
fprintf(stderr, "scd: %3d: " _fmt, ++__dprintf_counter, ## __VA_ARGS__);\ |
|
14 |
} \ |
|
15 |
} while (0) |
|
16 |
|
|
17 |
#define VMC_MAX_HOST_WRITE 2048 |
|
18 |
|
|
19 |
typedef struct SpiceCharDriver { |
|
20 |
CharDriverState* chr; |
|
21 |
SpiceCharDeviceInstance sin; |
|
22 |
char *subtype; |
|
23 |
bool active; |
|
24 |
uint8_t *buffer; |
|
25 |
uint8_t *datapos; |
|
26 |
ssize_t bufsize, datalen; |
|
27 |
uint32_t debug; |
|
28 |
} SpiceCharDriver; |
|
29 |
|
|
30 |
static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len) |
|
31 |
{ |
|
32 |
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); |
|
33 |
ssize_t out = 0; |
|
34 |
ssize_t last_out; |
|
35 |
uint8_t* p = (uint8_t*)buf; |
|
36 |
|
|
37 |
while (len > 0) { |
|
38 |
last_out = MIN(len, VMC_MAX_HOST_WRITE); |
|
39 |
qemu_chr_read(scd->chr, p, last_out); |
|
40 |
if (last_out > 0) { |
|
41 |
out += last_out; |
|
42 |
len -= last_out; |
|
43 |
p += last_out; |
|
44 |
} else { |
|
45 |
break; |
|
46 |
} |
|
47 |
} |
|
48 |
|
|
49 |
dprintf(scd, 3, "%s: %lu/%zd\n", __func__, out, len + out); |
|
50 |
trace_spice_vmc_write(out, len + out); |
|
51 |
return out; |
|
52 |
} |
|
53 |
|
|
54 |
static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len) |
|
55 |
{ |
|
56 |
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin); |
|
57 |
int bytes = MIN(len, scd->datalen); |
|
58 |
|
|
59 |
dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen); |
|
60 |
if (bytes > 0) { |
|
61 |
memcpy(buf, scd->datapos, bytes); |
|
62 |
scd->datapos += bytes; |
|
63 |
scd->datalen -= bytes; |
|
64 |
assert(scd->datalen >= 0); |
|
65 |
if (scd->datalen == 0) { |
|
66 |
scd->datapos = 0; |
|
67 |
} |
|
68 |
} |
|
69 |
trace_spice_vmc_read(bytes, len); |
|
70 |
return bytes; |
|
71 |
} |
|
72 |
|
|
73 |
static SpiceCharDeviceInterface vmc_interface = { |
|
74 |
.base.type = SPICE_INTERFACE_CHAR_DEVICE, |
|
75 |
.base.description = "spice virtual channel char device", |
|
76 |
.base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR, |
|
77 |
.base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR, |
|
78 |
.write = vmc_write, |
|
79 |
.read = vmc_read, |
|
80 |
}; |
|
81 |
|
|
82 |
|
|
83 |
static void vmc_register_interface(SpiceCharDriver *scd) |
|
84 |
{ |
|
85 |
if (scd->active) { |
|
86 |
return; |
|
87 |
} |
|
88 |
dprintf(scd, 1, "%s\n", __func__); |
|
89 |
scd->sin.base.sif = &vmc_interface.base; |
|
90 |
qemu_spice_add_interface(&scd->sin.base); |
|
91 |
scd->active = true; |
|
92 |
trace_spice_vmc_register_interface(scd); |
|
93 |
} |
|
94 |
|
|
95 |
static void vmc_unregister_interface(SpiceCharDriver *scd) |
|
96 |
{ |
|
97 |
if (!scd->active) { |
|
98 |
return; |
|
99 |
} |
|
100 |
dprintf(scd, 1, "%s\n", __func__); |
|
101 |
spice_server_remove_interface(&scd->sin.base); |
|
102 |
scd->active = false; |
|
103 |
trace_spice_vmc_unregister_interface(scd); |
|
104 |
} |
|
105 |
|
|
106 |
|
|
107 |
static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len) |
|
108 |
{ |
|
109 |
SpiceCharDriver *s = chr->opaque; |
|
110 |
|
|
111 |
dprintf(s, 2, "%s: %d\n", __func__, len); |
|
112 |
vmc_register_interface(s); |
|
113 |
assert(s->datalen == 0); |
|
114 |
if (s->bufsize < len) { |
|
115 |
s->bufsize = len; |
|
116 |
s->buffer = qemu_realloc(s->buffer, s->bufsize); |
|
117 |
} |
|
118 |
memcpy(s->buffer, buf, len); |
|
119 |
s->datapos = s->buffer; |
|
120 |
s->datalen = len; |
|
121 |
spice_server_char_device_wakeup(&s->sin); |
|
122 |
return len; |
|
123 |
} |
|
124 |
|
|
125 |
static void spice_chr_close(struct CharDriverState *chr) |
|
126 |
{ |
|
127 |
SpiceCharDriver *s = chr->opaque; |
|
128 |
|
|
129 |
printf("%s\n", __func__); |
|
130 |
vmc_unregister_interface(s); |
|
131 |
qemu_free(s); |
|
132 |
} |
|
133 |
|
|
134 |
static void print_allowed_subtypes(void) |
|
135 |
{ |
|
136 |
const char** psubtype; |
|
137 |
int i; |
|
138 |
|
|
139 |
fprintf(stderr, "allowed names: "); |
|
140 |
for(i=0, psubtype = spice_server_char_device_recognized_subtypes(); |
|
141 |
*psubtype != NULL; ++psubtype, ++i) { |
|
142 |
if (i == 0) { |
|
143 |
fprintf(stderr, "%s", *psubtype); |
|
144 |
} else { |
|
145 |
fprintf(stderr, ", %s", *psubtype); |
|
146 |
} |
|
147 |
} |
|
148 |
fprintf(stderr, "\n"); |
|
149 |
} |
|
150 |
|
|
151 |
CharDriverState *qemu_chr_open_spice(QemuOpts *opts) |
|
152 |
{ |
|
153 |
CharDriverState *chr; |
|
154 |
SpiceCharDriver *s; |
|
155 |
const char* name = qemu_opt_get(opts, "name"); |
|
156 |
uint32_t debug = qemu_opt_get_number(opts, "debug", 0); |
|
157 |
const char** psubtype = spice_server_char_device_recognized_subtypes(); |
|
158 |
const char *subtype = NULL; |
|
159 |
|
|
160 |
if (name == NULL) { |
|
161 |
fprintf(stderr, "spice-qemu-char: missing name parameter\n"); |
|
162 |
print_allowed_subtypes(); |
|
163 |
return NULL; |
|
164 |
} |
|
165 |
for(;*psubtype != NULL; ++psubtype) { |
|
166 |
if (strcmp(name, *psubtype) == 0) { |
|
167 |
subtype = *psubtype; |
|
168 |
break; |
|
169 |
} |
|
170 |
} |
|
171 |
if (subtype == NULL) { |
|
172 |
fprintf(stderr, "spice-qemu-char: unsupported name\n"); |
|
173 |
print_allowed_subtypes(); |
|
174 |
return NULL; |
|
175 |
} |
|
176 |
|
|
177 |
chr = qemu_mallocz(sizeof(CharDriverState)); |
|
178 |
s = qemu_mallocz(sizeof(SpiceCharDriver)); |
|
179 |
s->chr = chr; |
|
180 |
s->debug = debug; |
|
181 |
s->active = false; |
|
182 |
s->sin.subtype = subtype; |
|
183 |
chr->opaque = s; |
|
184 |
chr->chr_write = spice_chr_write; |
|
185 |
chr->chr_close = spice_chr_close; |
|
186 |
|
|
187 |
qemu_chr_generic_open(chr); |
|
188 |
|
|
189 |
return chr; |
|
190 |
} |
b/trace-events | ||
---|---|---|
224 | 224 |
disable qed_aio_write_prefill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64"" |
225 | 225 |
disable qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64"" |
226 | 226 |
disable qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu" |
227 |
|
|
228 |
# spice-qemu-char.c |
|
229 |
disable spice_vmc_write(ssize_t out, int len) "spice wrottn %lu of requested %zd" |
|
230 |
disable spice_vmc_read(int bytes, int len) "spice read %lu of requested %zd" |
|
231 |
disable spice_vmc_register_interface(void *scd) "spice vmc registered interface %p" |
|
232 |
disable spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p" |
b/ui/qemu-spice.h | ||
---|---|---|
24 | 24 |
|
25 | 25 |
#include "qemu-option.h" |
26 | 26 |
#include "qemu-config.h" |
27 |
#include "qemu-char.h" |
|
27 | 28 |
|
28 | 29 |
extern int using_spice; |
29 | 30 |
|
... | ... | |
41 | 42 |
void do_info_spice_print(Monitor *mon, const QObject *data); |
42 | 43 |
void do_info_spice(Monitor *mon, QObject **ret_data); |
43 | 44 |
|
45 |
CharDriverState *qemu_chr_open_spice(QemuOpts *opts); |
|
46 |
|
|
44 | 47 |
#else /* CONFIG_SPICE */ |
45 | 48 |
|
46 | 49 |
#define using_spice 0 |
Also available in: Unified diff