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