|
|
|
@ -98,6 +98,7 @@ |
|
|
|
#include "ui/qemu-spice.h" |
|
|
|
|
|
|
|
#define READ_BUF_LEN 4096 |
|
|
|
#define CBUFF_SIZE 65536 |
|
|
|
|
|
|
|
/***********************************************************/ |
|
|
|
/* character device */ |
|
|
|
@ -2643,6 +2644,110 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr) |
|
|
|
return d->outbuf_size; |
|
|
|
} |
|
|
|
|
|
|
|
/*********************************************************/ |
|
|
|
/*CircularMemory chardev*/ |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
size_t size; |
|
|
|
size_t prod; |
|
|
|
size_t cons; |
|
|
|
uint8_t *cbuf; |
|
|
|
} CirMemCharDriver; |
|
|
|
|
|
|
|
static bool cirmem_chr_is_empty(const CharDriverState *chr) |
|
|
|
{ |
|
|
|
const CirMemCharDriver *d = chr->opaque; |
|
|
|
|
|
|
|
return d->cons == d->prod; |
|
|
|
} |
|
|
|
|
|
|
|
static size_t qemu_chr_cirmem_count(const CharDriverState *chr) |
|
|
|
{ |
|
|
|
const CirMemCharDriver *d = chr->opaque; |
|
|
|
|
|
|
|
return (d->prod - d->cons); |
|
|
|
} |
|
|
|
|
|
|
|
static int cirmem_chr_write(CharDriverState *chr, const uint8_t *buf, int len) |
|
|
|
{ |
|
|
|
CirMemCharDriver *d = chr->opaque; |
|
|
|
int i; |
|
|
|
|
|
|
|
if (!buf || (len < 0)) { |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
for (i = 0; i < len; i++ ) { |
|
|
|
/* Avoid writing the IAC information to the queue. */ |
|
|
|
if ((unsigned char)buf[i] == IAC) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
d->cbuf[d->prod++ % d->size] = buf[i]; |
|
|
|
if ((d->prod - d->cons) > d->size) { |
|
|
|
d->cons = d->prod - d->size; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int cirmem_chr_read(CharDriverState *chr, uint8_t *buf, int len) |
|
|
|
{ |
|
|
|
CirMemCharDriver *d = chr->opaque; |
|
|
|
int i; |
|
|
|
|
|
|
|
for (i = 0; i < len && !cirmem_chr_is_empty(chr); i++) { |
|
|
|
buf[i] = d->cbuf[d->cons++ % d->size]; |
|
|
|
} |
|
|
|
|
|
|
|
return i; |
|
|
|
} |
|
|
|
|
|
|
|
static void cirmem_chr_close(struct CharDriverState *chr) |
|
|
|
{ |
|
|
|
CirMemCharDriver *d = chr->opaque; |
|
|
|
|
|
|
|
g_free(d->cbuf); |
|
|
|
g_free(d); |
|
|
|
chr->opaque = NULL; |
|
|
|
} |
|
|
|
|
|
|
|
static CharDriverState *qemu_chr_open_cirmemchr(QemuOpts *opts) |
|
|
|
{ |
|
|
|
CharDriverState *chr; |
|
|
|
CirMemCharDriver *d; |
|
|
|
|
|
|
|
chr = g_malloc0(sizeof(CharDriverState)); |
|
|
|
d = g_malloc(sizeof(*d)); |
|
|
|
|
|
|
|
d->size = qemu_opt_get_number(opts, "maxcapacity", 0); |
|
|
|
if (d->size == 0) { |
|
|
|
d->size = CBUFF_SIZE; |
|
|
|
} |
|
|
|
|
|
|
|
/* The size must be power of 2 */ |
|
|
|
if (d->size & (d->size - 1)) { |
|
|
|
fprintf(stderr, "chardev: size of memory device must be power of 2\n"); |
|
|
|
goto fail; |
|
|
|
} |
|
|
|
|
|
|
|
d->prod = 0; |
|
|
|
d->cons = 0; |
|
|
|
d->cbuf = g_malloc0(d->size); |
|
|
|
|
|
|
|
chr->opaque = d; |
|
|
|
chr->chr_write = cirmem_chr_write; |
|
|
|
chr->chr_close = cirmem_chr_close; |
|
|
|
|
|
|
|
return chr; |
|
|
|
|
|
|
|
fail: |
|
|
|
g_free(d); |
|
|
|
g_free(chr); |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
|
|
|
|
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) |
|
|
|
{ |
|
|
|
char host[65], port[33], width[8], height[8]; |
|
|
|
@ -2697,6 +2802,11 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) |
|
|
|
qemu_opt_set(opts, "path", filename); |
|
|
|
return opts; |
|
|
|
} |
|
|
|
if (strstart(filename, "memory", &p)) { |
|
|
|
qemu_opt_set(opts, "backend", "memory"); |
|
|
|
qemu_opt_set(opts, "maxcapacity", p); |
|
|
|
return opts; |
|
|
|
} |
|
|
|
if (strstart(filename, "file:", &p)) { |
|
|
|
qemu_opt_set(opts, "backend", "file"); |
|
|
|
qemu_opt_set(opts, "path", p); |
|
|
|
@ -2796,6 +2906,7 @@ static const struct { |
|
|
|
{ .name = "udp", .open = qemu_chr_open_udp }, |
|
|
|
{ .name = "msmouse", .open = qemu_chr_open_msmouse }, |
|
|
|
{ .name = "vc", .open = text_console_init }, |
|
|
|
{ .name = "memory", .open = qemu_chr_open_cirmemchr }, |
|
|
|
#ifdef _WIN32 |
|
|
|
{ .name = "file", .open = qemu_chr_open_win_file_out }, |
|
|
|
{ .name = "pipe", .open = qemu_chr_open_win_pipe }, |
|
|
|
@ -3055,6 +3166,9 @@ QemuOptsList qemu_chardev_opts = { |
|
|
|
},{ |
|
|
|
.name = "debug", |
|
|
|
.type = QEMU_OPT_NUMBER, |
|
|
|
},{ |
|
|
|
.name = "maxcapacity", |
|
|
|
.type = QEMU_OPT_NUMBER, |
|
|
|
}, |
|
|
|
{ /* end of list */ } |
|
|
|
}, |
|
|
|
|