Merge remote-tracking branch 'kraxel/chardev.5' into staging

* kraxel/chardev.5:
  spice-qemu-char: Remove dead debugging code
  spice-qemu-char: Fix name parameter issues after qapi-ifying
  qemu-char.c: fix waiting for telnet connection message
  Revert "hmp: Disable chardev-add and chardev-remove"
  chardev: add udp support to qapi
  chardev: add memory (ringbuf) support to qapi
  chardev: add vc support to qapi
  chardev: add spice support to qapi
  chardev: add pipe support to qapi
  chardev: add console support to qapi
  chardev: switch pty init to qapi
  chardev: switch parallel init to qapi
  chardev: switch serial/tty init to qapi
  chardev: add stdio support to qapi
  chardev: switch file init to qapi
  chardev: add braille support to qapi
  chardev: add msmouse support to qapi
  chardev: switch null init to qapi
  chardev: add mux chardev support to qapi
  chardev: add support for qapi-based chardev initialization

Conflicts:
	ui/console.c

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Anthony Liguori
2013-03-14 14:54:37 -05:00
13 changed files with 523 additions and 231 deletions
+2 -2
View File
@@ -561,7 +561,7 @@ static void baum_close(struct CharDriverState *chr)
g_free(baum);
}
static CharDriverState *chr_baum_init(QemuOpts *opts)
CharDriverState *chr_baum_init(void)
{
BaumDriverState *baum;
CharDriverState *chr;
@@ -627,7 +627,7 @@ fail_handle:
static void register_types(void)
{
register_char_driver("braille", chr_baum_init);
register_char_driver_qapi("braille", CHARDEV_BACKEND_KIND_BRAILLE, NULL);
}
type_init(register_types);
+2 -2
View File
@@ -63,7 +63,7 @@ static void msmouse_chr_close (struct CharDriverState *chr)
g_free (chr);
}
static CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
CharDriverState *qemu_chr_open_msmouse(void)
{
CharDriverState *chr;
@@ -78,7 +78,7 @@ static CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
static void register_types(void)
{
register_char_driver("msmouse", qemu_chr_open_msmouse);
register_char_driver_qapi("msmouse", CHARDEV_BACKEND_KIND_MSMOUSE, NULL);
}
type_init(register_types);
+31 -32
View File
@@ -1522,38 +1522,37 @@ passed since 1970, i.e. unix epoch.
@end table
ETEXI
HXCOMM Disabled for now, because it isn't built on top of QMP's chardev-add
HXCOMM {
HXCOMM .name = "chardev-add",
HXCOMM .args_type = "args:s",
HXCOMM .params = "args",
HXCOMM .help = "add chardev",
HXCOMM .mhandler.cmd = hmp_chardev_add,
HXCOMM },
HXCOMM
HXCOMM STEXI
HXCOMM @item chardev_add args
HXCOMM @findex chardev_add
HXCOMM
HXCOMM chardev_add accepts the same parameters as the -chardev command line switch.
HXCOMM
HXCOMM ETEXI
HXCOMM
HXCOMM {
HXCOMM .name = "chardev-remove",
HXCOMM .args_type = "id:s",
HXCOMM .params = "id",
HXCOMM .help = "remove chardev",
HXCOMM .mhandler.cmd = hmp_chardev_remove,
HXCOMM },
HXCOMM
HXCOMM STEXI
HXCOMM @item chardev_remove id
HXCOMM @findex chardev_remove
HXCOMM
HXCOMM Removes the chardev @var{id}.
HXCOMM
HXCOMM ETEXI
{
.name = "chardev-add",
.args_type = "args:s",
.params = "args",
.help = "add chardev",
.mhandler.cmd = hmp_chardev_add,
},
STEXI
@item chardev_add args
@findex chardev_add
chardev_add accepts the same parameters as the -chardev command line switch.
ETEXI
{
.name = "chardev-remove",
.args_type = "id:s",
.params = "id",
.help = "remove chardev",
.mhandler.cmd = hmp_chardev_remove,
},
STEXI
@item chardev_remove id
@findex chardev_remove
Removes the chardev @var{id}.
ETEXI
{
.name = "info",
+8
View File
@@ -245,6 +245,8 @@ CharDriverState *qemu_chr_find(const char *name);
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts *));
void register_char_driver_qapi(const char *name, int kind,
void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp));
/* add an eventfd to the qemu devices that are polled */
CharDriverState *qemu_chr_open_eventfd(int eventfd);
@@ -259,4 +261,10 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr);
CharDriverState *qemu_char_get_next_serial(void);
/* msmouse */
CharDriverState *qemu_chr_open_msmouse(void);
/* baum.c */
CharDriverState *chr_baum_init(void);
#endif
+1
View File
@@ -71,6 +71,7 @@ SocketAddress *socket_parse(const char *str, Error **errp);
int socket_connect(SocketAddress *addr, Error **errp,
NonBlockingConnectHandler *callback, void *opaque);
int socket_listen(SocketAddress *addr, Error **errp);
int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp);
/* Old, ipv4 only bits. Don't use for new code. */
int parse_host_port(struct sockaddr_in *saddr, const char *str);
+2 -2
View File
@@ -450,9 +450,9 @@ void qemu_console_resize(DisplayState *ds, int width, int height);
void qemu_console_copy(DisplayState *ds, int src_x, int src_y,
int dst_x, int dst_y, int w, int h);
typedef CharDriverState *(VcHandler)(QemuOpts *);
typedef CharDriverState *(VcHandler)(ChardevVC *vc);
CharDriverState *vc_init(QemuOpts *opts);
CharDriverState *vc_init(ChardevVC *vc);
void register_vc_handler(VcHandler *handler);
/* sdl.c */
+5 -2
View File
@@ -44,10 +44,13 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
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);
CharDriverState *qemu_chr_open_spice_vmc(const char *type);
#if SPICE_SERVER_VERSION >= 0x000c02
CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts);
CharDriverState *qemu_chr_open_spice_port(const char *name);
void qemu_spice_register_ports(void);
#else
static inline CharDriverState *qemu_chr_open_spice_port(const char *name)
{ return NULL; }
#endif
#else /* CONFIG_SPICE */
+101 -3
View File
@@ -3153,7 +3153,7 @@
##
# @ChardevHostdev:
#
# Configuration info for device chardevs.
# Configuration info for device and pipe chardevs.
#
# @device: The name of the special file for the device,
# i.e. /dev/ttyS0 on Unix or COM1: on Windows
@@ -3166,7 +3166,7 @@
##
# @ChardevSocket:
#
# Configuration info for socket chardevs.
# Configuration info for (stream) socket chardevs.
#
# @addr: socket address to listen on (server=true)
# or connect to (server=false)
@@ -3184,6 +3184,93 @@
'*nodelay' : 'bool',
'*telnet' : 'bool' } }
##
# @ChardevDgram:
#
# Configuration info for datagram socket chardevs.
#
# @remote: remote address
# @local: #optional local address
#
# Since: 1.5
##
{ 'type': 'ChardevDgram', 'data': { 'remote' : 'SocketAddress',
'*local' : 'SocketAddress' } }
##
# @ChardevMux:
#
# Configuration info for mux chardevs.
#
# @chardev: name of the base chardev.
#
# Since: 1.5
##
{ 'type': 'ChardevMux', 'data': { 'chardev' : 'str' } }
##
# @ChardevStdio:
#
# Configuration info for stdio chardevs.
#
# @signal: #optional Allow signals (such as SIGINT triggered by ^C)
# be delivered to qemu. Default: true in -nographic mode,
# false otherwise.
#
# Since: 1.5
##
{ 'type': 'ChardevStdio', 'data': { '*signal' : 'bool' } }
##
# @ChardevSpiceChannel:
#
# Configuration info for spice vm channel chardevs.
#
# @type: kind of channel (for example vdagent).
#
# Since: 1.5
##
{ 'type': 'ChardevSpiceChannel', 'data': { 'type' : 'str' } }
##
# @ChardevSpicePort:
#
# Configuration info for spice port chardevs.
#
# @fqdn: name of the channel (see docs/spice-port-fqdn.txt)
#
# Since: 1.5
##
{ 'type': 'ChardevSpicePort', 'data': { 'fqdn' : 'str' } }
##
# @ChardevVC:
#
# Configuration info for virtual console chardevs.
#
# @width: console width, in pixels
# @height: console height, in pixels
# @cols: console width, in chars
# @rows: console height, in chars
#
# Since: 1.5
##
{ 'type': 'ChardevVC', 'data': { '*width' : 'int',
'*height' : 'int',
'*cols' : 'int',
'*rows' : 'int' } }
##
# @ChardevRingbuf:
#
# Configuration info for memory chardevs
#
# @size: #optional Ringbuffer size, must be power of two, default is 65536
#
# Since: 1.5
##
{ 'type': 'ChardevRingbuf', 'data': { '*size' : 'int' } }
##
# @ChardevBackend:
#
@@ -3196,9 +3283,20 @@
{ 'union': 'ChardevBackend', 'data': { 'file' : 'ChardevFile',
'serial' : 'ChardevHostdev',
'parallel': 'ChardevHostdev',
'pipe' : 'ChardevHostdev',
'socket' : 'ChardevSocket',
'dgram' : 'ChardevDgram',
'pty' : 'ChardevDummy',
'null' : 'ChardevDummy' } }
'null' : 'ChardevDummy',
'mux' : 'ChardevMux',
'msmouse': 'ChardevDummy',
'braille': 'ChardevDummy',
'stdio' : 'ChardevStdio',
'console': 'ChardevDummy',
'spicevmc' : 'ChardevSpiceChannel',
'spiceport' : 'ChardevSpicePort',
'vc' : 'ChardevVC',
'memory' : 'ChardevRingbuf' } }
##
# @ChardevReturn:
+248 -135
View File
File diff suppressed because it is too large Load Diff
+48 -40
View File
@@ -8,14 +8,6 @@
#include "qemu/osdep.h"
#define dprintf(_scd, _level, _fmt, ...) \
do { \
static unsigned __dprintf_counter = 0; \
if (_scd->debug >= _level) { \
fprintf(stderr, "scd: %3d: " _fmt, ++__dprintf_counter, ## __VA_ARGS__);\
} \
} while (0)
typedef struct SpiceCharDriver {
CharDriverState* chr;
SpiceCharDeviceInstance sin;
@@ -24,7 +16,6 @@ typedef struct SpiceCharDriver {
uint8_t *buffer;
uint8_t *datapos;
ssize_t bufsize, datalen;
uint32_t debug;
QLIST_ENTRY(SpiceCharDriver) next;
} SpiceCharDriver;
@@ -49,7 +40,6 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
p += last_out;
}
dprintf(scd, 3, "%s: %zu/%zd\n", __func__, out, len + out);
trace_spice_vmc_write(out, len + out);
return out;
}
@@ -59,7 +49,6 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
int bytes = MIN(len, scd->datalen);
dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
if (bytes > 0) {
memcpy(buf, scd->datapos, bytes);
scd->datapos += bytes;
@@ -84,11 +73,9 @@ static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event)
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);
}
@@ -141,7 +128,6 @@ static void vmc_register_interface(SpiceCharDriver *scd)
if (scd->active) {
return;
}
dprintf(scd, 1, "%s\n", __func__);
scd->sin.base.sif = &vmc_interface.base;
qemu_spice_add_interface(&scd->sin.base);
scd->active = true;
@@ -153,7 +139,6 @@ static void vmc_unregister_interface(SpiceCharDriver *scd)
if (!scd->active) {
return;
}
dprintf(scd, 1, "%s\n", __func__);
spice_server_remove_interface(&scd->sin.base);
scd->active = false;
trace_spice_vmc_unregister_interface(scd);
@@ -164,7 +149,6 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
{
SpiceCharDriver *s = chr->opaque;
dprintf(s, 2, "%s: %d\n", __func__, len);
vmc_register_interface(s);
assert(s->datalen == 0);
if (s->bufsize < len) {
@@ -182,9 +166,13 @@ static void spice_chr_close(struct CharDriverState *chr)
{
SpiceCharDriver *s = chr->opaque;
printf("%s\n", __func__);
vmc_unregister_interface(s);
QLIST_REMOVE(s, next);
g_free((char *)s->sin.subtype);
#if SPICE_SERVER_VERSION >= 0x000c02
g_free((char *)s->sin.portname);
#endif
g_free(s);
}
@@ -217,18 +205,16 @@ static void print_allowed_subtypes(void)
fprintf(stderr, "\n");
}
static CharDriverState *chr_open(QemuOpts *opts, const char *subtype)
static CharDriverState *chr_open(const char *subtype)
{
CharDriverState *chr;
SpiceCharDriver *s;
uint32_t debug = qemu_opt_get_number(opts, "debug", 0);
chr = g_malloc0(sizeof(CharDriverState));
s = g_malloc0(sizeof(SpiceCharDriver));
s->chr = chr;
s->debug = debug;
s->active = false;
s->sin.subtype = subtype;
s->sin.subtype = g_strdup(subtype);
chr->opaque = s;
chr->chr_write = spice_chr_write;
chr->chr_close = spice_chr_close;
@@ -240,35 +226,32 @@ static CharDriverState *chr_open(QemuOpts *opts, const char *subtype)
return chr;
}
CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
CharDriverState *qemu_chr_open_spice_vmc(const char *type)
{
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) {
if (type == NULL) {
fprintf(stderr, "spice-qemu-char: missing name parameter\n");
print_allowed_subtypes();
return NULL;
}
for(;*psubtype != NULL; ++psubtype) {
if (strcmp(name, *psubtype) == 0) {
subtype = *psubtype;
for (; *psubtype != NULL; ++psubtype) {
if (strcmp(type, *psubtype) == 0) {
break;
}
}
if (subtype == NULL) {
fprintf(stderr, "spice-qemu-char: unsupported name: %s\n", name);
if (*psubtype == NULL) {
fprintf(stderr, "spice-qemu-char: unsupported type: %s\n", type);
print_allowed_subtypes();
return NULL;
}
chr = chr_open(opts, subtype);
chr = chr_open(type);
#if SPICE_SERVER_VERSION < 0x000901
/* See comment in vmc_state() */
if (strcmp(subtype, "vdagent") == 0) {
if (strcmp(type, "vdagent") == 0) {
qemu_chr_generic_open(chr);
}
#endif
@@ -277,20 +260,19 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
}
#if SPICE_SERVER_VERSION >= 0x000c02
CharDriverState *qemu_chr_open_spice_port(QemuOpts *opts)
CharDriverState *qemu_chr_open_spice_port(const char *name)
{
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");
chr = chr_open("port");
s = chr->opaque;
s->sin.portname = name;
s->sin.portname = g_strdup(name);
return chr;
}
@@ -308,12 +290,38 @@ void qemu_spice_register_ports(void)
}
#endif
static void qemu_chr_parse_spice_vmc(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
{
const char *name = qemu_opt_get(opts, "name");
if (name == NULL) {
error_setg(errp, "chardev: spice channel: no name given");
return;
}
backend->spicevmc = g_new0(ChardevSpiceChannel, 1);
backend->spicevmc->type = g_strdup(name);
}
static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
{
const char *name = qemu_opt_get(opts, "name");
if (name == NULL) {
error_setg(errp, "chardev: spice port: no name given");
return;
}
backend->spiceport = g_new0(ChardevSpicePort, 1);
backend->spiceport->fqdn = g_strdup(name);
}
static void register_types(void)
{
register_char_driver("spicevmc", qemu_chr_open_spice);
#if SPICE_SERVER_VERSION >= 0x000c02
register_char_driver("spiceport", qemu_chr_open_spice_port);
#endif
register_char_driver_qapi("spicevmc", CHARDEV_BACKEND_KIND_SPICEVMC,
qemu_chr_parse_spice_vmc);
register_char_driver_qapi("spiceport", CHARDEV_BACKEND_KIND_SPICEPORT,
qemu_chr_parse_spice_port);
}
type_init(register_types);
+49 -12
View File
@@ -1537,22 +1537,26 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
chr->init(chr);
}
static CharDriverState *text_console_init(QemuOpts *opts)
static CharDriverState *text_console_init(ChardevVC *vc)
{
CharDriverState *chr;
QemuConsole *s;
unsigned width;
unsigned height;
unsigned width = 0;
unsigned height = 0;
chr = g_malloc0(sizeof(CharDriverState));
width = qemu_opt_get_number(opts, "width", 0);
if (width == 0)
width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH;
if (vc->has_width) {
width = vc->width;
} else if (vc->has_cols) {
width = vc->cols * FONT_WIDTH;
}
height = qemu_opt_get_number(opts, "height", 0);
if (height == 0)
height = qemu_opt_get_number(opts, "rows", 0) * FONT_HEIGHT;
if (vc->has_height) {
height = vc->height;
} else if (vc->has_rows) {
height = vc->rows * FONT_HEIGHT;
}
if (width == 0 || height == 0) {
s = new_console(NULL, TEXT_CONSOLE);
@@ -1575,9 +1579,9 @@ static CharDriverState *text_console_init(QemuOpts *opts)
static VcHandler *vc_handler = text_console_init;
CharDriverState *vc_init(QemuOpts *opts)
CharDriverState *vc_init(ChardevVC *vc)
{
return vc_handler(opts);
return vc_handler(vc);
}
void register_vc_handler(VcHandler *handler)
@@ -1740,9 +1744,42 @@ PixelFormat qemu_default_pixelformat(int bpp)
return pf;
}
static void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
{
int val;
backend->vc = g_new0(ChardevVC, 1);
val = qemu_opt_get_number(opts, "width", 0);
if (val != 0) {
backend->vc->has_width = true;
backend->vc->width = val;
}
val = qemu_opt_get_number(opts, "height", 0);
if (val != 0) {
backend->vc->has_height = true;
backend->vc->height = val;
}
val = qemu_opt_get_number(opts, "cols", 0);
if (val != 0) {
backend->vc->has_cols = true;
backend->vc->cols = val;
}
val = qemu_opt_get_number(opts, "rows", 0);
if (val != 0) {
backend->vc->has_rows = true;
backend->vc->rows = val;
}
}
static void register_types(void)
{
register_char_driver("vc", vc_init);
register_char_driver_qapi("vc", CHARDEV_BACKEND_KIND_VC,
qemu_chr_parse_vc);
}
type_init(register_types);
+1 -1
View File
@@ -991,7 +991,7 @@ static int gd_vc_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
static int nb_vcs;
static CharDriverState *vcs[MAX_VCS];
static CharDriverState *gd_vc_handler(QemuOpts *opts)
static CharDriverState *gd_vc_handler(ChardevVC *unused)
{
CharDriverState *chr;
+25
View File
@@ -949,6 +949,31 @@ int socket_listen(SocketAddress *addr, Error **errp)
return fd;
}
int socket_dgram(SocketAddress *remote, SocketAddress *local, Error **errp)
{
QemuOpts *opts;
int fd;
opts = qemu_opts_create_nofail(&dummy_opts);
switch (remote->kind) {
case SOCKET_ADDRESS_KIND_INET:
qemu_opt_set(opts, "host", remote->inet->host);
qemu_opt_set(opts, "port", remote->inet->port);
if (local) {
qemu_opt_set(opts, "localaddr", local->inet->host);
qemu_opt_set(opts, "localport", local->inet->port);
}
fd = inet_dgram_opts(opts, errp);
break;
default:
error_setg(errp, "socket type unsupported for datagram");
return -1;
}
qemu_opts_del(opts);
return fd;
}
#ifdef _WIN32
static void socket_cleanup(void)
{