qemu-char: Saner naming of memchar stuff & doc fixes
New device, has never been released, so we can still improve things without worrying about compatibility. Naming is a mess. The code calls the device driver CirMemCharDriver, the public API calls it "memory", "memchardev", or "memchar", and the special commands are named like "memchar-FOO". "memory" is a particularly unfortunate choice, because there's another character device driver called MemoryDriver. Moreover, the device's distinctive property is that it's a ring buffer, not that's in memory. Therefore: * Rename CirMemCharDriver to RingBufCharDriver, and call the thing a "ringbuf" in the API. * Rename QMP and HMP commands from memchar-FOO to ringbuf-FOO. * Rename device parameter from maxcapacity to size (simple words are good for you). * Clearly mark the parameter as optional in documentation. * Fix error reporting so that chardev-add reports to current monitor, not stderr. * Replace cirmem in C identifiers by ringbuf. * Rework documentation. Document the impact of our crappy UTF-8 handling on reading. * QMP examples that even work. I could split this up into multiple commits, but they'd change the same documentation lines multiple times. Not worth it. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
5c230105cd
commit
3949e59414
@ -841,40 +841,37 @@ Inject an NMI on the given CPU (x86 only).
|
|||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
{
|
{
|
||||||
.name = "memchar_write",
|
.name = "ringbuf_write",
|
||||||
.args_type = "device:s,data:s",
|
.args_type = "device:s,data:s",
|
||||||
.params = "device data",
|
.params = "device data",
|
||||||
.help = "Provide writing interface for CirMemCharDriver. Write"
|
.help = "Write to a ring buffer character device",
|
||||||
"'data' to it.",
|
.mhandler.cmd = hmp_ringbuf_write,
|
||||||
.mhandler.cmd = hmp_memchar_write,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@item memchar_write @var{device} @var{data}
|
@item ringbuf_write @var{device} @var{data}
|
||||||
@findex memchar_write
|
@findex ringbuf_write
|
||||||
Provide writing interface for CirMemCharDriver. Write @var{data}
|
Write @var{data} to ring buffer character device @var{device}.
|
||||||
to char device 'memory'.
|
@var{data} must be a UTF-8 string.
|
||||||
|
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
{
|
{
|
||||||
.name = "memchar_read",
|
.name = "ringbuf_read",
|
||||||
.args_type = "device:s,size:i",
|
.args_type = "device:s,size:i",
|
||||||
.params = "device size",
|
.params = "device size",
|
||||||
.help = "Provide read interface for CirMemCharDriver. Read from"
|
.help = "Read from a ring buffer character device",
|
||||||
"it and return the data with size.",
|
.mhandler.cmd = hmp_ringbuf_read,
|
||||||
.mhandler.cmd = hmp_memchar_read,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
STEXI
|
STEXI
|
||||||
@item memchar_read @var{device}
|
@item ringbuf_read @var{device}
|
||||||
@findex memchar_read
|
@findex ringbuf_read
|
||||||
Provide read interface for CirMemCharDriver. Read from char device
|
Read and print up to @var{size} bytes from ring buffer character
|
||||||
'memory' and return the data.
|
device @var{device}.
|
||||||
|
Bug: can screw up when the buffer contains invalid UTF-8 sequences,
|
||||||
@var{size} is the size of data want to read from. Refer to unencoded
|
NUL characters, after the ring buffer lost data, and when reading
|
||||||
size of the raw data, would adjust to the init size of the memchar
|
stops because the size limit is reached.
|
||||||
if the requested size is larger than it.
|
|
||||||
|
|
||||||
ETEXI
|
ETEXI
|
||||||
|
|
||||||
|
8
hmp.c
8
hmp.c
@ -662,25 +662,25 @@ void hmp_pmemsave(Monitor *mon, const QDict *qdict)
|
|||||||
hmp_handle_error(mon, &errp);
|
hmp_handle_error(mon, &errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hmp_memchar_write(Monitor *mon, const QDict *qdict)
|
void hmp_ringbuf_write(Monitor *mon, const QDict *qdict)
|
||||||
{
|
{
|
||||||
const char *chardev = qdict_get_str(qdict, "device");
|
const char *chardev = qdict_get_str(qdict, "device");
|
||||||
const char *data = qdict_get_str(qdict, "data");
|
const char *data = qdict_get_str(qdict, "data");
|
||||||
Error *errp = NULL;
|
Error *errp = NULL;
|
||||||
|
|
||||||
qmp_memchar_write(chardev, data, false, 0, &errp);
|
qmp_ringbuf_write(chardev, data, false, 0, &errp);
|
||||||
|
|
||||||
hmp_handle_error(mon, &errp);
|
hmp_handle_error(mon, &errp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hmp_memchar_read(Monitor *mon, const QDict *qdict)
|
void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
|
||||||
{
|
{
|
||||||
uint32_t size = qdict_get_int(qdict, "size");
|
uint32_t size = qdict_get_int(qdict, "size");
|
||||||
const char *chardev = qdict_get_str(qdict, "device");
|
const char *chardev = qdict_get_str(qdict, "device");
|
||||||
char *data;
|
char *data;
|
||||||
Error *errp = NULL;
|
Error *errp = NULL;
|
||||||
|
|
||||||
data = qmp_memchar_read(chardev, size, false, 0, &errp);
|
data = qmp_ringbuf_read(chardev, size, false, 0, &errp);
|
||||||
if (errp) {
|
if (errp) {
|
||||||
monitor_printf(mon, "%s\n", error_get_pretty(errp));
|
monitor_printf(mon, "%s\n", error_get_pretty(errp));
|
||||||
error_free(errp);
|
error_free(errp);
|
||||||
|
4
hmp.h
4
hmp.h
@ -43,8 +43,8 @@ void hmp_system_powerdown(Monitor *mon, const QDict *qdict);
|
|||||||
void hmp_cpu(Monitor *mon, const QDict *qdict);
|
void hmp_cpu(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_memsave(Monitor *mon, const QDict *qdict);
|
void hmp_memsave(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_pmemsave(Monitor *mon, const QDict *qdict);
|
void hmp_pmemsave(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_memchar_write(Monitor *mon, const QDict *qdict);
|
void hmp_ringbuf_write(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_memchar_read(Monitor *mon, const QDict *qdict);
|
void hmp_ringbuf_read(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_cont(Monitor *mon, const QDict *qdict);
|
void hmp_cont(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_system_wakeup(Monitor *mon, const QDict *qdict);
|
void hmp_system_wakeup(Monitor *mon, const QDict *qdict);
|
||||||
void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
|
void hmp_inject_nmi(Monitor *mon, const QDict *qdict);
|
||||||
|
@ -329,9 +329,9 @@
|
|||||||
#
|
#
|
||||||
# An enumeration of data format.
|
# An enumeration of data format.
|
||||||
#
|
#
|
||||||
# @utf8: The data format is 'utf8'.
|
# @utf8: Data is a UTF-8 string (RFC 3629)
|
||||||
#
|
#
|
||||||
# @base64: The data format is 'base64'.
|
# @base64: Data is Base64 encoded binary (RFC 3548)
|
||||||
#
|
#
|
||||||
# Since: 1.4
|
# Since: 1.4
|
||||||
##
|
##
|
||||||
@ -339,44 +339,55 @@
|
|||||||
'data': [ 'utf8', 'base64' ] }
|
'data': [ 'utf8', 'base64' ] }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @memchar-write:
|
# @ringbuf-write:
|
||||||
#
|
#
|
||||||
# Provide writing interface for memchardev. Write data to char
|
# Write to a ring buffer character device.
|
||||||
# device 'memory'.
|
|
||||||
#
|
#
|
||||||
# @device: the name of the memory char device.
|
# @device: the ring buffer character device name
|
||||||
#
|
#
|
||||||
# @data: the source data write to memchar.
|
# @data: data to write
|
||||||
#
|
#
|
||||||
# @format: #optional the format of the data write to chardev 'memory',
|
# @format: #optional data encoding (default 'utf8').
|
||||||
# by default is 'utf8'.
|
# - base64: data must be base64 encoded text. Its binary
|
||||||
|
# decoding gets written.
|
||||||
|
# Bug: invalid base64 is currently not rejected.
|
||||||
|
# Whitespace *is* invalid.
|
||||||
|
# - utf8: data's UTF-8 encoding is written
|
||||||
|
# - data itself is always Unicode regardless of format, like
|
||||||
|
# any other string.
|
||||||
#
|
#
|
||||||
# Returns: Nothing on success
|
# Returns: Nothing on success
|
||||||
#
|
#
|
||||||
# Since: 1.4
|
# Since: 1.4
|
||||||
##
|
##
|
||||||
{ 'command': 'memchar-write',
|
{ 'command': 'ringbuf-write',
|
||||||
'data': {'device': 'str', 'data': 'str',
|
'data': {'device': 'str', 'data': 'str',
|
||||||
'*format': 'DataFormat'} }
|
'*format': 'DataFormat'} }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @memchar-read:
|
# @ringbuf-read:
|
||||||
#
|
#
|
||||||
# Provide read interface for memchardev. Read from the char
|
# Read from a ring buffer character device.
|
||||||
# device 'memory' and return the data.
|
|
||||||
#
|
#
|
||||||
# @device: the name of the memory char device.
|
# @device: the ring buffer character device name
|
||||||
#
|
#
|
||||||
# @size: the size to read in bytes.
|
# @size: how many bytes to read at most
|
||||||
#
|
#
|
||||||
# @format: #optional the format of the data want to read from
|
# @format: #optional data encoding (default 'utf8').
|
||||||
# memchardev, by default is 'utf8'.
|
# - base64: the data read is returned in base64 encoding.
|
||||||
|
# - utf8: the data read is interpreted as UTF-8.
|
||||||
|
# Bug: can screw up when the buffer contains invalid UTF-8
|
||||||
|
# sequences, NUL characters, after the ring buffer lost
|
||||||
|
# data, and when reading stops because the size limit is
|
||||||
|
# reached.
|
||||||
|
# - The return value is always Unicode regardless of format,
|
||||||
|
# like any other string.
|
||||||
#
|
#
|
||||||
# Returns: data read from the device
|
# Returns: data read from the device
|
||||||
#
|
#
|
||||||
# Since: 1.4
|
# Since: 1.4
|
||||||
##
|
##
|
||||||
{ 'command': 'memchar-read',
|
{ 'command': 'ringbuf-read',
|
||||||
'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'},
|
'data': {'device': 'str', 'size': 'int', '*format': 'DataFormat'},
|
||||||
'returns': 'str' }
|
'returns': 'str' }
|
||||||
|
|
||||||
|
65
qemu-char.c
65
qemu-char.c
@ -2645,25 +2645,25 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************/
|
/*********************************************************/
|
||||||
/* CircularMemory chardev */
|
/* Ring buffer chardev */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t prod;
|
size_t prod;
|
||||||
size_t cons;
|
size_t cons;
|
||||||
uint8_t *cbuf;
|
uint8_t *cbuf;
|
||||||
} CirMemCharDriver;
|
} RingBufCharDriver;
|
||||||
|
|
||||||
static size_t cirmem_count(const CharDriverState *chr)
|
static size_t ringbuf_count(const CharDriverState *chr)
|
||||||
{
|
{
|
||||||
const CirMemCharDriver *d = chr->opaque;
|
const RingBufCharDriver *d = chr->opaque;
|
||||||
|
|
||||||
return d->prod - d->cons;
|
return d->prod - d->cons;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cirmem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
static int ringbuf_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
CirMemCharDriver *d = chr->opaque;
|
RingBufCharDriver *d = chr->opaque;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!buf || (len < 0)) {
|
if (!buf || (len < 0)) {
|
||||||
@ -2680,9 +2680,9 @@ static int cirmem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cirmem_chr_read(CharDriverState *chr, uint8_t *buf, int len)
|
static int ringbuf_chr_read(CharDriverState *chr, uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
CirMemCharDriver *d = chr->opaque;
|
RingBufCharDriver *d = chr->opaque;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < len && d->cons != d->prod; i++) {
|
for (i = 0; i < len && d->cons != d->prod; i++) {
|
||||||
@ -2692,31 +2692,31 @@ static int cirmem_chr_read(CharDriverState *chr, uint8_t *buf, int len)
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cirmem_chr_close(struct CharDriverState *chr)
|
static void ringbuf_chr_close(struct CharDriverState *chr)
|
||||||
{
|
{
|
||||||
CirMemCharDriver *d = chr->opaque;
|
RingBufCharDriver *d = chr->opaque;
|
||||||
|
|
||||||
g_free(d->cbuf);
|
g_free(d->cbuf);
|
||||||
g_free(d);
|
g_free(d);
|
||||||
chr->opaque = NULL;
|
chr->opaque = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CharDriverState *qemu_chr_open_cirmemchr(QemuOpts *opts)
|
static CharDriverState *qemu_chr_open_ringbuf(QemuOpts *opts)
|
||||||
{
|
{
|
||||||
CharDriverState *chr;
|
CharDriverState *chr;
|
||||||
CirMemCharDriver *d;
|
RingBufCharDriver *d;
|
||||||
|
|
||||||
chr = g_malloc0(sizeof(CharDriverState));
|
chr = g_malloc0(sizeof(CharDriverState));
|
||||||
d = g_malloc(sizeof(*d));
|
d = g_malloc(sizeof(*d));
|
||||||
|
|
||||||
d->size = qemu_opt_get_number(opts, "maxcapacity", 0);
|
d->size = qemu_opt_get_number(opts, "size", 0);
|
||||||
if (d->size == 0) {
|
if (d->size == 0) {
|
||||||
d->size = CBUFF_SIZE;
|
d->size = CBUFF_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The size must be power of 2 */
|
/* The size must be power of 2 */
|
||||||
if (d->size & (d->size - 1)) {
|
if (d->size & (d->size - 1)) {
|
||||||
fprintf(stderr, "chardev: size of memory device must be power of 2\n");
|
error_report("size of ringbuf device must be power of two");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2725,8 +2725,8 @@ static CharDriverState *qemu_chr_open_cirmemchr(QemuOpts *opts)
|
|||||||
d->cbuf = g_malloc0(d->size);
|
d->cbuf = g_malloc0(d->size);
|
||||||
|
|
||||||
chr->opaque = d;
|
chr->opaque = d;
|
||||||
chr->chr_write = cirmem_chr_write;
|
chr->chr_write = ringbuf_chr_write;
|
||||||
chr->chr_close = cirmem_chr_close;
|
chr->chr_close = ringbuf_chr_close;
|
||||||
|
|
||||||
return chr;
|
return chr;
|
||||||
|
|
||||||
@ -2736,12 +2736,12 @@ fail:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool chr_is_cirmem(const CharDriverState *chr)
|
static bool chr_is_ringbuf(const CharDriverState *chr)
|
||||||
{
|
{
|
||||||
return chr->chr_write == cirmem_chr_write;
|
return chr->chr_write == ringbuf_chr_write;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_memchar_write(const char *device, const char *data,
|
void qmp_ringbuf_write(const char *device, const char *data,
|
||||||
bool has_format, enum DataFormat format,
|
bool has_format, enum DataFormat format,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
@ -2756,8 +2756,8 @@ void qmp_memchar_write(const char *device, const char *data,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chr_is_cirmem(chr)) {
|
if (!chr_is_ringbuf(chr)) {
|
||||||
error_setg(errp,"%s is not memory char device", device);
|
error_setg(errp,"%s is not a ringbuf device", device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2768,7 +2768,7 @@ void qmp_memchar_write(const char *device, const char *data,
|
|||||||
write_count = strlen(data);
|
write_count = strlen(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = cirmem_chr_write(chr, write_data, write_count);
|
ret = ringbuf_chr_write(chr, write_data, write_count);
|
||||||
|
|
||||||
if (write_data != (uint8_t *)data) {
|
if (write_data != (uint8_t *)data) {
|
||||||
g_free((void *)write_data);
|
g_free((void *)write_data);
|
||||||
@ -2780,7 +2780,7 @@ void qmp_memchar_write(const char *device, const char *data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *qmp_memchar_read(const char *device, int64_t size,
|
char *qmp_ringbuf_read(const char *device, int64_t size,
|
||||||
bool has_format, enum DataFormat format,
|
bool has_format, enum DataFormat format,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
@ -2795,8 +2795,8 @@ char *qmp_memchar_read(const char *device, int64_t size,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chr_is_cirmem(chr)) {
|
if (!chr_is_ringbuf(chr)) {
|
||||||
error_setg(errp,"%s is not memory char device", device);
|
error_setg(errp,"%s is not a ringbuf device", device);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2805,16 +2805,23 @@ char *qmp_memchar_read(const char *device, int64_t size,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
count = cirmem_count(chr);
|
count = ringbuf_count(chr);
|
||||||
size = size > count ? count : size;
|
size = size > count ? count : size;
|
||||||
read_data = g_malloc(size + 1);
|
read_data = g_malloc(size + 1);
|
||||||
|
|
||||||
cirmem_chr_read(chr, read_data, size);
|
ringbuf_chr_read(chr, read_data, size);
|
||||||
|
|
||||||
if (has_format && (format == DATA_FORMAT_BASE64)) {
|
if (has_format && (format == DATA_FORMAT_BASE64)) {
|
||||||
data = g_base64_encode(read_data, size);
|
data = g_base64_encode(read_data, size);
|
||||||
g_free(read_data);
|
g_free(read_data);
|
||||||
} else {
|
} else {
|
||||||
|
/*
|
||||||
|
* FIXME should read only complete, valid UTF-8 characters up
|
||||||
|
* to @size bytes. Invalid sequences should be replaced by a
|
||||||
|
* suitable replacement character. Except when (and only
|
||||||
|
* when) ring buffer lost characters since last read, initial
|
||||||
|
* continuation characters should be dropped.
|
||||||
|
*/
|
||||||
read_data[size] = 0;
|
read_data[size] = 0;
|
||||||
data = (char *)read_data;
|
data = (char *)read_data;
|
||||||
}
|
}
|
||||||
@ -2975,7 +2982,7 @@ static const struct {
|
|||||||
{ .name = "udp", .open = qemu_chr_open_udp },
|
{ .name = "udp", .open = qemu_chr_open_udp },
|
||||||
{ .name = "msmouse", .open = qemu_chr_open_msmouse },
|
{ .name = "msmouse", .open = qemu_chr_open_msmouse },
|
||||||
{ .name = "vc", .open = text_console_init },
|
{ .name = "vc", .open = text_console_init },
|
||||||
{ .name = "memory", .open = qemu_chr_open_cirmemchr },
|
{ .name = "memory", .open = qemu_chr_open_ringbuf },
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
{ .name = "file", .open = qemu_chr_open_win_file_out },
|
{ .name = "file", .open = qemu_chr_open_win_file_out },
|
||||||
{ .name = "pipe", .open = qemu_chr_open_win_pipe },
|
{ .name = "pipe", .open = qemu_chr_open_win_pipe },
|
||||||
@ -3236,7 +3243,7 @@ QemuOptsList qemu_chardev_opts = {
|
|||||||
.name = "debug",
|
.name = "debug",
|
||||||
.type = QEMU_OPT_NUMBER,
|
.type = QEMU_OPT_NUMBER,
|
||||||
},{
|
},{
|
||||||
.name = "maxcapacity",
|
.name = "size",
|
||||||
.type = QEMU_OPT_NUMBER,
|
.type = QEMU_OPT_NUMBER,
|
||||||
},
|
},
|
||||||
{ /* end of list */ }
|
{ /* end of list */ }
|
||||||
|
@ -1736,7 +1736,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
|
|||||||
"-chardev msmouse,id=id[,mux=on|off]\n"
|
"-chardev msmouse,id=id[,mux=on|off]\n"
|
||||||
"-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n"
|
"-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n"
|
||||||
" [,mux=on|off]\n"
|
" [,mux=on|off]\n"
|
||||||
"-chardev memory,id=id,maxcapacity=maxcapacity\n"
|
"-chardev ringbuf,id=id[,size=size]\n"
|
||||||
"-chardev file,id=id,path=path[,mux=on|off]\n"
|
"-chardev file,id=id,path=path[,mux=on|off]\n"
|
||||||
"-chardev pipe,id=id,path=path[,mux=on|off]\n"
|
"-chardev pipe,id=id,path=path[,mux=on|off]\n"
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -1778,7 +1778,7 @@ Backend is one of:
|
|||||||
@option{udp},
|
@option{udp},
|
||||||
@option{msmouse},
|
@option{msmouse},
|
||||||
@option{vc},
|
@option{vc},
|
||||||
@option{memory},
|
@option{ringbuf},
|
||||||
@option{file},
|
@option{file},
|
||||||
@option{pipe},
|
@option{pipe},
|
||||||
@option{console},
|
@option{console},
|
||||||
@ -1887,13 +1887,10 @@ the console, in pixels.
|
|||||||
@option{cols} and @option{rows} specify that the console be sized to fit a text
|
@option{cols} and @option{rows} specify that the console be sized to fit a text
|
||||||
console with the given dimensions.
|
console with the given dimensions.
|
||||||
|
|
||||||
@item -chardev memory ,id=@var{id} ,maxcapacity=@var{maxcapacity}
|
@item -chardev ringbuf ,id=@var{id} [,size=@var{size}]
|
||||||
|
|
||||||
Create a circular buffer with fixed size indicated by optionally @option{maxcapacity}
|
Create a ring buffer with fixed size @option{size}.
|
||||||
which will be default 64K if it is not given.
|
@var{size} must be a power of two, and defaults to @code{64K}).
|
||||||
|
|
||||||
@option{maxcapacity} specifies the max capacity of the size of circular buffer
|
|
||||||
to create. Should be power of 2.
|
|
||||||
|
|
||||||
@item -chardev file ,id=@var{id} ,path=@var{path}
|
@item -chardev file ,id=@var{id} ,path=@var{path}
|
||||||
|
|
||||||
|
@ -466,30 +466,30 @@ Note: inject-nmi fails when the guest doesn't support injecting.
|
|||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
{
|
{
|
||||||
.name = "memchar-write",
|
.name = "ringbuf-write",
|
||||||
.args_type = "device:s,data:s,format:s?",
|
.args_type = "device:s,data:s,format:s?",
|
||||||
.mhandler.cmd_new = qmp_marshal_input_memchar_write,
|
.mhandler.cmd_new = qmp_marshal_input_ringbuf_write,
|
||||||
},
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
memchar-write
|
ringbuf-write
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Provide writing interface for CirMemCharDriver. Write data to memory
|
Write to a ring buffer character device.
|
||||||
char device.
|
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
- "device": the name of the char device, must be unique (json-string)
|
- "device": ring buffer character device name (json-string)
|
||||||
- "data": the source data write to memory (json-string)
|
- "data": data to write (json-string)
|
||||||
- "format": the data format write to memory, default is
|
- "format": data format (json-string, optional)
|
||||||
utf8. (json-string, optional)
|
- Possible values: "utf8" (default), "base64"
|
||||||
- Possible values: "utf8", "base64"
|
Bug: invalid base64 is currently not rejected.
|
||||||
|
Whitespace *is* invalid.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
-> { "execute": "memchar-write",
|
-> { "execute": "ringbuf-write",
|
||||||
"arguments": { "device": foo,
|
"arguments": { "device": "foo",
|
||||||
"data": "abcdefgh",
|
"data": "abcdefgh",
|
||||||
"format": "utf8" } }
|
"format": "utf8" } }
|
||||||
<- { "return": {} }
|
<- { "return": {} }
|
||||||
@ -497,32 +497,35 @@ Example:
|
|||||||
EQMP
|
EQMP
|
||||||
|
|
||||||
{
|
{
|
||||||
.name = "memchar-read",
|
.name = "ringbuf-read",
|
||||||
.args_type = "device:s,size:i,format:s?",
|
.args_type = "device:s,size:i,format:s?",
|
||||||
.mhandler.cmd_new = qmp_marshal_input_memchar_read,
|
.mhandler.cmd_new = qmp_marshal_input_ringbuf_read,
|
||||||
},
|
},
|
||||||
|
|
||||||
SQMP
|
SQMP
|
||||||
memchar-read
|
ringbuf-read
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
Provide read interface for CirMemCharDriver. Read from the char
|
Read from a ring buffer character device.
|
||||||
device memory and return the data with size.
|
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
|
|
||||||
- "device": the name of the char device, must be unique (json-string)
|
- "device": ring buffer character device name (json-string)
|
||||||
- "size": the memory size wanted to read in bytes (refer to unencoded
|
- "size": how many bytes to read at most (json-int)
|
||||||
size of the raw data), would adjust to the init size of the
|
- Number of data bytes, not number of characters in encoded data
|
||||||
memchar if the requested size is larger than it. (json-int)
|
- "format": data format (json-string, optional)
|
||||||
- "format": the data format write to memchardev, default is
|
- Possible values: "utf8" (default), "base64"
|
||||||
utf8. (json-string, optional)
|
- Naturally, format "utf8" works only when the ring buffer
|
||||||
- Possible values: "utf8", "base64"
|
contains valid UTF-8 text. Invalid UTF-8 sequences get
|
||||||
|
replaced. Bug: replacement doesn't work. Bug: can screw
|
||||||
|
up on encountering NUL characters, after the ring buffer
|
||||||
|
lost data, and when reading stops because the size limit
|
||||||
|
is reached.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
-> { "execute": "memchar-read",
|
-> { "execute": "ringbuf-read",
|
||||||
"arguments": { "device": foo,
|
"arguments": { "device": "foo",
|
||||||
"size": 1000,
|
"size": 1000,
|
||||||
"format": "utf8" } }
|
"format": "utf8" } }
|
||||||
<- {"return": "abcdefgh"}
|
<- {"return": "abcdefgh"}
|
||||||
|
Loading…
Reference in New Issue
Block a user