* [Qemu-devel] [PULL 01/41] MAINTAINERS: add myself to qemu-char.c
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 02/41] spice-qemu-char: convert to finalize Marc-André Lureau
` (41 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
I consider to have enough experience with qemu-char to propose myself as
maintainer. This will allow me to send pull request without waiting for
Paolo.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index e0be7bc0d4..5efd8cc671 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1194,6 +1194,7 @@ T: git git://github.com/jnsnow/qemu.git bitmaps
Character device backends
M: Paolo Bonzini <pbonzini@redhat.com>
+M: Marc-André Lureau <marcandre.lureau@redhat.com>
S: Maintained
F: qemu-char.c
F: backends/msmouse.c
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 02/41] spice-qemu-char: convert to finalize
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 01/41] MAINTAINERS: add myself to qemu-char.c Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 03/41] baum: " Marc-André Lureau
` (40 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
spice-qemu-char.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index dd97c17fca..3902202a35 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -210,9 +210,9 @@ static int spice_chr_write(Chardev *chr, const uint8_t *buf, int len)
return read_bytes;
}
-static void spice_chr_free(struct Chardev *chr)
+static void char_spice_finalize(Object *obj)
{
- SpiceChardev *s = SPICE_CHARDEV(chr);
+ SpiceChardev *s = SPICE_CHARDEV(obj);
vmc_unregister_interface(s);
QLIST_REMOVE(s, next);
@@ -365,13 +365,13 @@ static void char_spice_class_init(ObjectClass *oc, void *data)
cc->chr_write = spice_chr_write;
cc->chr_add_watch = spice_chr_add_watch;
cc->chr_accept_input = spice_chr_accept_input;
- cc->chr_free = spice_chr_free;
}
static const TypeInfo char_spice_type_info = {
.name = TYPE_CHARDEV_SPICE,
.parent = TYPE_CHARDEV,
.instance_size = sizeof(SpiceChardev),
+ .instance_finalize = char_spice_finalize,
.class_init = char_spice_class_init,
.abstract = true,
};
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 03/41] baum: convert to finalize
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 01/41] MAINTAINERS: add myself to qemu-char.c Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 02/41] spice-qemu-char: convert to finalize Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 04/41] msmouse: " Marc-André Lureau
` (39 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
backends/baum.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/backends/baum.c b/backends/baum.c
index 0f418ed358..39c9365024 100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@ -616,9 +616,9 @@ static void baum_chr_read(void *opaque)
}
}
-static void baum_chr_free(Chardev *chr)
+static void char_braille_finalize(Object *obj)
{
- BaumChardev *baum = BAUM_CHARDEV(chr);
+ BaumChardev *baum = BAUM_CHARDEV(obj);
timer_free(baum->cellCount_timer);
if (baum->brlapi) {
@@ -659,13 +659,13 @@ static void char_braille_class_init(ObjectClass *oc, void *data)
cc->open = baum_chr_open;
cc->chr_write = baum_chr_write;
cc->chr_accept_input = baum_chr_accept_input;
- cc->chr_free = baum_chr_free;
}
static const TypeInfo char_braille_type_info = {
.name = TYPE_CHARDEV_BRAILLE,
.parent = TYPE_CHARDEV,
.instance_size = sizeof(BaumChardev),
+ .instance_finalize = char_braille_finalize,
.class_init = char_braille_class_init,
};
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 04/41] msmouse: convert to finalize
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (2 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 03/41] baum: " Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 05/41] mux: " Marc-André Lureau
` (38 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
backends/msmouse.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/backends/msmouse.c b/backends/msmouse.c
index 936a5476d5..55c344f0e1 100644
--- a/backends/msmouse.c
+++ b/backends/msmouse.c
@@ -139,9 +139,9 @@ static int msmouse_chr_write(struct Chardev *s, const uint8_t *buf, int len)
return len;
}
-static void msmouse_chr_free(struct Chardev *chr)
+static void char_msmouse_finalize(Object *obj)
{
- MouseChardev *mouse = MOUSE_CHARDEV(chr);
+ MouseChardev *mouse = MOUSE_CHARDEV(obj);
qemu_input_handler_unregister(mouse->hs);
}
@@ -172,13 +172,13 @@ static void char_msmouse_class_init(ObjectClass *oc, void *data)
cc->open = msmouse_chr_open;
cc->chr_write = msmouse_chr_write;
cc->chr_accept_input = msmouse_chr_accept_input;
- cc->chr_free = msmouse_chr_free;
}
static const TypeInfo char_msmouse_type_info = {
.name = TYPE_CHARDEV_MSMOUSE,
.parent = TYPE_CHARDEV,
.instance_size = sizeof(MouseChardev),
+ .instance_finalize = char_msmouse_finalize,
.class_init = char_msmouse_class_init,
};
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 05/41] mux: convert to finalize
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (3 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 04/41] msmouse: " Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 06/41] char-udp: " Marc-André Lureau
` (37 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
qemu-char.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index 6b4a299702..91ca4cb083 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -859,9 +859,9 @@ static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond)
return cc->chr_add_watch(chr, cond);
}
-static void mux_chr_free(struct Chardev *chr)
+static void char_mux_finalize(Object *obj)
{
- MuxChardev *d = MUX_CHARDEV(chr);
+ MuxChardev *d = MUX_CHARDEV(obj);
int i;
for (i = 0; i < d->mux_cnt; i++) {
@@ -4025,7 +4025,6 @@ static void char_mux_class_init(ObjectClass *oc, void *data)
ChardevClass *cc = CHARDEV_CLASS(oc);
cc->open = qemu_chr_open_mux;
- cc->chr_free = mux_chr_free;
cc->chr_write = mux_chr_write;
cc->chr_accept_input = mux_chr_accept_input;
cc->chr_add_watch = mux_chr_add_watch;
@@ -4036,6 +4035,7 @@ static const TypeInfo char_mux_type_info = {
.parent = TYPE_CHARDEV,
.class_init = char_mux_class_init,
.instance_size = sizeof(MuxChardev),
+ .instance_finalize = char_mux_finalize,
};
static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 06/41] char-udp: convert to finalize
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (4 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 05/41] mux: " Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 07/41] char-socket: " Marc-André Lureau
` (36 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
qemu-char.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index 91ca4cb083..1c4fcf3a6e 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2779,9 +2779,10 @@ static void udp_chr_update_read_handler(Chardev *chr,
}
}
-static void udp_chr_free(Chardev *chr)
+static void char_udp_finalize(Object *obj)
{
- UdpChardev *s = UDP_CHARDEV(chr);
+ Chardev *chr = CHARDEV(obj);
+ UdpChardev *s = UDP_CHARDEV(obj);
remove_fd_in_watch(chr);
if (s->ioc) {
@@ -4975,13 +4976,13 @@ static void char_udp_class_init(ObjectClass *oc, void *data)
cc->open = qmp_chardev_open_udp;
cc->chr_write = udp_chr_write;
cc->chr_update_read_handler = udp_chr_update_read_handler;
- cc->chr_free = udp_chr_free;
}
static const TypeInfo char_udp_type_info = {
.name = TYPE_CHARDEV_UDP,
.parent = TYPE_CHARDEV,
.instance_size = sizeof(UdpChardev),
+ .instance_finalize = char_udp_finalize,
.class_init = char_udp_class_init,
};
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 07/41] char-socket: convert to finalize
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (5 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 06/41] char-udp: " Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 08/41] char-pty: " Marc-André Lureau
` (35 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Notice that finalize() will be run after a failure to open(), so cleanup
code must be adjusted.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
qemu-char.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index 1c4fcf3a6e..a00bbb0a1c 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3446,9 +3446,10 @@ int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp)
return qemu_chr_wait_connected(be->chr, errp);
}
-static void tcp_chr_free(Chardev *chr)
+static void char_socket_finalize(Object *obj)
{
- SocketChardev *s = SOCKET_CHARDEV(chr);
+ Chardev *chr = CHARDEV(obj);
+ SocketChardev *s = SOCKET_CHARDEV(obj);
tcp_chr_free_connection(chr);
@@ -4886,7 +4887,7 @@ static void qmp_chardev_open_socket(Chardev *chr,
s->listen_ioc = sioc;
if (is_waitconnect &&
qemu_chr_wait_connected(chr, errp) < 0) {
- goto error;
+ return;
}
if (!s->ioc) {
s->listen_tag = qio_channel_add_watch(
@@ -4904,9 +4905,6 @@ error:
if (sioc) {
object_unref(OBJECT(sioc));
}
- if (s->tls_creds) {
- object_unref(OBJECT(s->tls_creds));
- }
}
static const CharDriver socket_driver = {
@@ -4928,13 +4926,13 @@ static void char_socket_class_init(ObjectClass *oc, void *data)
cc->chr_add_client = tcp_chr_add_client;
cc->chr_add_watch = tcp_chr_add_watch;
cc->chr_update_read_handler = tcp_chr_update_read_handler;
- cc->chr_free = tcp_chr_free;
}
static const TypeInfo char_socket_type_info = {
.name = TYPE_CHARDEV_SOCKET,
.parent = TYPE_CHARDEV,
.instance_size = sizeof(SocketChardev),
+ .instance_finalize = char_socket_finalize,
.class_init = char_socket_class_init,
};
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 08/41] char-pty: convert to finalize
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (6 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 07/41] char-socket: " Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 09/41] char-ringbuf: " Marc-André Lureau
` (34 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
qemu-char.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index a00bbb0a1c..fecebde87a 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1659,9 +1659,10 @@ static void pty_chr_state(Chardev *chr, int connected)
}
}
-static void pty_chr_free(struct Chardev *chr)
+static void char_pty_finalize(Object *obj)
{
- PtyChardev *s = PTY_CHARDEV(chr);
+ Chardev *chr = CHARDEV(obj);
+ PtyChardev *s = PTY_CHARDEV(obj);
qemu_mutex_lock(&chr->chr_write_lock);
pty_chr_state(chr, 0);
@@ -1718,13 +1719,13 @@ static void char_pty_class_init(ObjectClass *oc, void *data)
cc->chr_write = char_pty_chr_write;
cc->chr_update_read_handler = pty_chr_update_read_handler;
cc->chr_add_watch = pty_chr_add_watch;
- cc->chr_free = pty_chr_free;
}
static const TypeInfo char_pty_type_info = {
.name = TYPE_CHARDEV_PTY,
.parent = TYPE_CHARDEV,
.instance_size = sizeof(PtyChardev),
+ .instance_finalize = char_pty_finalize,
.class_init = char_pty_class_init,
};
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 09/41] char-ringbuf: convert to finalize
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (7 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 08/41] char-pty: " Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 10/41] char-parallel: convert parallel " Marc-André Lureau
` (33 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
qemu-char.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index fecebde87a..74e78b56d1 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3550,9 +3550,9 @@ static int ringbuf_chr_read(Chardev *chr, uint8_t *buf, int len)
return i;
}
-static void ringbuf_chr_free(struct Chardev *chr)
+static void char_ringbuf_finalize(Object *obj)
{
- RingBufChardev *d = RINGBUF_CHARDEV(chr);
+ RingBufChardev *d = RINGBUF_CHARDEV(obj);
g_free(d->cbuf);
}
@@ -3982,7 +3982,6 @@ static void char_ringbuf_class_init(ObjectClass *oc, void *data)
cc->open = qemu_chr_open_ringbuf;
cc->chr_write = ringbuf_chr_write;
- cc->chr_free = ringbuf_chr_free;
}
static const TypeInfo char_ringbuf_type_info = {
@@ -3990,6 +3989,7 @@ static const TypeInfo char_ringbuf_type_info = {
.parent = TYPE_CHARDEV,
.class_init = char_ringbuf_class_init,
.instance_size = sizeof(RingBufChardev),
+ .instance_finalize = char_ringbuf_finalize,
};
/* Bug-compatibility: */
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 10/41] char-parallel: convert parallel to finalize
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (8 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 09/41] char-ringbuf: " Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 11/41] char-stdio: convert " Marc-André Lureau
` (32 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
qemu-char.c | 30 +++++++++++++++++-------------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index 74e78b56d1..1981058f45 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2025,17 +2025,6 @@ static int pp_ioctl(Chardev *chr, int cmd, void *arg)
return 0;
}
-static void pp_free(Chardev *chr)
-{
- ParallelChardev *drv = PARALLEL_CHARDEV(chr);
- int fd = drv->fd;
-
- pp_hw_mode(drv, IEEE1284_MODE_COMPAT);
- ioctl(fd, PPRELEASE);
- close(fd);
- qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
-}
-
static void qemu_chr_open_pp_fd(Chardev *chr,
int fd,
bool *be_opened,
@@ -4699,18 +4688,33 @@ static void char_parallel_class_init(ObjectClass *oc, void *data)
#if defined(__linux__)
cc->chr_write = null_chr_write;
cc->chr_ioctl = pp_ioctl;
- cc->chr_free = pp_free;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
- /* FIXME: no chr_free */
cc->chr_write = null_chr_write;
cc->chr_ioctl = pp_ioctl;
#endif
}
+static void char_parallel_finalize(Object *obj)
+{
+#if defined(__linux__)
+ Chardev *chr = CHARDEV(obj);
+ ParallelChardev *drv = PARALLEL_CHARDEV(chr);
+ int fd = drv->fd;
+
+ pp_hw_mode(drv, IEEE1284_MODE_COMPAT);
+ ioctl(fd, PPRELEASE);
+ close(fd);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+ /* FIXME: close fd? */
+#endif
+}
+
static const TypeInfo char_parallel_type_info = {
.name = TYPE_CHARDEV_PARALLEL,
.parent = TYPE_CHARDEV,
.instance_size = sizeof(ParallelChardev),
+ .instance_finalize = char_parallel_finalize,
.class_init = char_parallel_class_init,
};
#endif
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 11/41] char-stdio: convert to finalize
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (9 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 10/41] char-parallel: convert parallel " Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 12/41] char-win-stdio: " Marc-André Lureau
` (31 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
qemu-char.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index 1981058f45..390e6a99de 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1422,10 +1422,10 @@ static void qemu_chr_set_echo_stdio(Chardev *chr, bool echo)
tcsetattr (0, TCSANOW, &tty);
}
-static void qemu_chr_free_stdio(struct Chardev *chr)
+static void char_stdio_finalize(Object *obj)
{
term_exit();
- fd_chr_free(chr);
+ fd_chr_free(CHARDEV(chr));
}
static void qemu_chr_open_stdio(Chardev *chr,
@@ -3859,7 +3859,6 @@ static void char_stdio_class_init(ObjectClass *oc, void *data)
cc->chr_free = win_stdio_free;
#else
cc->chr_set_echo = qemu_chr_set_echo_stdio;
- cc->chr_free = qemu_chr_free_stdio;
#endif
}
@@ -3869,6 +3868,7 @@ static const TypeInfo char_stdio_type_info = {
.parent = TYPE_CHARDEV_WIN_STDIO,
#else
.parent = TYPE_CHARDEV_FD,
+ .instance_finalize = char_stdio_finalize,
#endif
.class_init = char_stdio_class_init,
};
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 12/41] char-win-stdio: convert to finalize
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (10 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 11/41] char-stdio: convert " Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 13/41] char-win: do not override chr_free Marc-André Lureau
` (30 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
qemu-char.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index 390e6a99de..d92642735e 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2594,9 +2594,9 @@ static void qemu_chr_set_echo_win_stdio(Chardev *chr, bool echo)
}
}
-static void win_stdio_free(Chardev *chr)
+static void char_win_stdio_finalize(Object *obj)
{
- WinStdioChardev *stdio = WIN_STDIO_CHARDEV(chr);
+ WinStdioChardev *stdio = WIN_STDIO_CHARDEV(obj);
if (stdio->hInputReadyEvent != INVALID_HANDLE_VALUE) {
CloseHandle(stdio->hInputReadyEvent);
@@ -2613,6 +2613,7 @@ static const TypeInfo char_win_stdio_type_info = {
.name = TYPE_CHARDEV_WIN_STDIO,
.parent = TYPE_CHARDEV,
.instance_size = sizeof(WinStdioChardev),
+ .instance_finalize = char_win_stdio_finalize,
.abstract = true,
};
@@ -3856,7 +3857,6 @@ static void char_stdio_class_init(ObjectClass *oc, void *data)
#ifdef _WIN32
cc->chr_write = win_stdio_write;
cc->chr_set_echo = qemu_chr_set_echo_win_stdio;
- cc->chr_free = win_stdio_free;
#else
cc->chr_set_echo = qemu_chr_set_echo_stdio;
#endif
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 13/41] char-win: do not override chr_free
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (11 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 12/41] char-win-stdio: " Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 14/41] char-win: convert to finalize Marc-André Lureau
` (29 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
For some unclear reason to me, char-file does not have chr_free on
win32. Since we want to switch to instance finalizer instead of class
chr_free, we should be able to run the base WinChardev class finalizer
in any case. Use a boolean to skip free to ease the transition to
instance finalizer.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
qemu-char.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index d92642735e..83636d76c0 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2122,6 +2122,8 @@ typedef struct {
/* Protected by the Chardev chr_write_lock. */
OVERLAPPED osend;
+ /* FIXME: file/console do not finalize */
+ bool skip_free;
} WinChardev;
#define TYPE_CHARDEV_WIN "chardev-win"
@@ -2152,6 +2154,10 @@ static void win_chr_free(Chardev *chr)
{
WinChardev *s = WIN_CHARDEV(chr);
+ if (s->skip_free) {
+ return;
+ }
+
if (s->hsend) {
CloseHandle(s->hsend);
s->hsend = NULL;
@@ -2432,6 +2438,7 @@ static void qemu_chr_open_win_file(Chardev *chr, HANDLE fd_out)
{
WinChardev *s = WIN_CHARDEV(chr);
+ s->skip_free = true;
s->hcom = fd_out;
}
@@ -2468,7 +2475,6 @@ static void char_console_class_init(ObjectClass *oc, void *data)
ChardevClass *cc = CHARDEV_CLASS(oc);
cc->open = qemu_chr_open_win_con;
- cc->chr_free = NULL;
}
static const TypeInfo char_console_type_info = {
@@ -4731,10 +4737,6 @@ static void char_file_class_init(ObjectClass *oc, void *data)
ChardevClass *cc = CHARDEV_CLASS(oc);
cc->open = qmp_chardev_open_file;
-#ifdef _WIN32
- /* FIXME: no chr_free */
- cc->chr_free = NULL;
-#endif
}
static const TypeInfo char_file_type_info = {
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 14/41] char-win: convert to finalize
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (12 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 13/41] char-win: do not override chr_free Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 15/41] char-fd: " Marc-André Lureau
` (28 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
qemu-char.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index 83636d76c0..0cece8a34f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2150,8 +2150,9 @@ typedef struct {
static int win_chr_poll(void *opaque);
static int win_chr_pipe_poll(void *opaque);
-static void win_chr_free(Chardev *chr)
+static void char_win_finalize(Object *obj)
{
+ Chardev *chr = CHARDEV(obj);
WinChardev *s = WIN_CHARDEV(chr);
if (s->skip_free) {
@@ -2160,15 +2161,12 @@ static void win_chr_free(Chardev *chr)
if (s->hsend) {
CloseHandle(s->hsend);
- s->hsend = NULL;
}
if (s->hrecv) {
CloseHandle(s->hrecv);
- s->hrecv = NULL;
}
if (s->hcom) {
CloseHandle(s->hcom);
- s->hcom = NULL;
}
if (s->fpipe)
qemu_del_polling_cb(win_chr_pipe_poll, chr);
@@ -2241,7 +2239,6 @@ static int win_chr_init(Chardev *chr, const char *filename, Error **errp)
return 0;
fail:
- win_chr_free(chr);
return -1;
}
@@ -2416,7 +2413,6 @@ static int win_chr_pipe_init(Chardev *chr, const char *filename,
return 0;
fail:
- win_chr_free(chr);
return -1;
}
@@ -2447,13 +2443,13 @@ static void char_win_class_init(ObjectClass *oc, void *data)
ChardevClass *cc = CHARDEV_CLASS(oc);
cc->chr_write = win_chr_write;
- cc->chr_free = win_chr_free;
}
static const TypeInfo char_win_type_info = {
.name = TYPE_CHARDEV_WIN,
.parent = TYPE_CHARDEV,
.instance_size = sizeof(WinChardev),
+ .instance_finalize = char_win_finalize,
.class_init = char_win_class_init,
.abstract = true,
};
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 15/41] char-fd: convert to finalize
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (13 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 14/41] char-win: convert to finalize Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 16/41] char: remove chr_free Marc-André Lureau
` (27 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
char-serial inherits from char-fd finalizer.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
qemu-char.c | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/qemu-char.c b/qemu-char.c
index 0cece8a34f..3d0d690999 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1296,9 +1296,10 @@ static void fd_chr_update_read_handler(Chardev *chr,
}
}
-static void fd_chr_free(struct Chardev *chr)
+static void char_fd_finalize(Object *obj)
{
- FDChardev *s = FD_CHARDEV(chr);
+ Chardev *chr = CHARDEV(obj);
+ FDChardev *s = FD_CHARDEV(obj);
remove_fd_in_watch(chr);
if (s->ioc_in) {
@@ -1337,13 +1338,13 @@ static void char_fd_class_init(ObjectClass *oc, void *data)
cc->chr_add_watch = fd_chr_add_watch;
cc->chr_write = fd_chr_write;
cc->chr_update_read_handler = fd_chr_update_read_handler;
- cc->chr_free = fd_chr_free;
}
static const TypeInfo char_fd_type_info = {
.name = TYPE_CHARDEV_FD,
.parent = TYPE_CHARDEV,
.instance_size = sizeof(FDChardev),
+ .instance_finalize = char_fd_finalize,
.class_init = char_fd_class_init,
.abstract = true,
};
@@ -1425,7 +1426,6 @@ static void qemu_chr_set_echo_stdio(Chardev *chr, bool echo)
static void char_stdio_finalize(Object *obj)
{
term_exit();
- fd_chr_free(CHARDEV(chr));
}
static void qemu_chr_open_stdio(Chardev *chr,
@@ -1913,11 +1913,6 @@ static int tty_serial_ioctl(Chardev *chr, int cmd, void *arg)
}
return 0;
}
-
-static void qemu_chr_free_tty(Chardev *chr)
-{
- fd_chr_free(chr);
-}
#endif /* __linux__ || __sun__ */
#if defined(__linux__)
@@ -4760,7 +4755,6 @@ static void char_serial_class_init(ObjectClass *oc, void *data)
cc->open = qmp_chardev_open_serial;
#ifndef _WIN32
cc->chr_ioctl = tty_serial_ioctl;
- cc->chr_free = qemu_chr_free_tty;
#endif
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 16/41] char: remove chr_free
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (14 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 15/41] char-fd: " Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 17/41] char: get rid of CharDriver Marc-André Lureau
` (26 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Now it uses Object instance_finalize instead.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
include/sysemu/char.h | 8 --------
qemu-char.c | 10 +---------
2 files changed, 1 insertion(+), 17 deletions(-)
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index da0e7dd494..5e5594f305 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -185,13 +185,6 @@ Chardev *qemu_chr_new_noreplay(const char *label, const char *filename);
void qemu_chr_delete(Chardev *chr);
/**
- * @qemu_chr_free:
- *
- * Destroy a character backend.
- */
-void qemu_chr_free(Chardev *chr);
-
-/**
* @qemu_chr_fe_set_echo:
*
* Ask the backend to override its normal echo setting. This only really
@@ -496,7 +489,6 @@ typedef struct ChardevClass {
int (*set_msgfds)(Chardev *s, int *fds, int num);
int (*chr_add_client)(Chardev *chr, int fd);
int (*chr_wait_connected)(Chardev *chr, Error **errp);
- void (*chr_free)(Chardev *chr);
void (*chr_disconnect)(Chardev *chr);
void (*chr_accept_input)(Chardev *chr);
void (*chr_set_echo)(Chardev *chr, bool echo);
diff --git a/qemu-char.c b/qemu-char.c
index 3d0d690999..c239418c25 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -4371,18 +4371,10 @@ void qemu_chr_fe_disconnect(CharBackend *be)
}
}
-void qemu_chr_free(Chardev *chr)
-{
- if (CHARDEV_GET_CLASS(chr)->chr_free) {
- CHARDEV_GET_CLASS(chr)->chr_free(chr);
- }
- object_unref(OBJECT(chr));
-}
-
void qemu_chr_delete(Chardev *chr)
{
QTAILQ_REMOVE(&chardevs, chr, next);
- qemu_chr_free(chr);
+ object_unref(OBJECT(chr));
}
ChardevInfoList *qmp_query_chardev(Error **errp)
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 17/41] char: get rid of CharDriver
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (15 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 16/41] char: remove chr_free Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:20 ` [Qemu-devel] [PULL 18/41] char: rename remaining CharDriver to Chardev Marc-André Lureau
` (25 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
qemu_chr_new_from_opts() is modified to not need CharDriver backend[]
array, but uses instead objectified qmp_query_chardev_backends() and
char_get_class(). The alias field is moved outside in a ChardevAlias[],
similar to QDevAlias for devices.
"kind" and "parse" are moved to ChardevClass ("kind" is to be removed
next)
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
include/sysemu/char.h | 12 +-
backends/baum.c | 6 +-
backends/msmouse.c | 6 +-
backends/testdev.c | 6 +-
qemu-char.c | 315 +++++++++++++++++++++++---------------------------
spice-qemu-char.c | 15 +--
ui/console.c | 10 +-
ui/gtk.c | 10 +-
8 files changed, 159 insertions(+), 221 deletions(-)
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 5e5594f305..2a3b887b8a 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -88,8 +88,6 @@ typedef struct CharBackend {
int fe_open;
} CharBackend;
-typedef struct CharDriver CharDriver;
-
struct Chardev {
Object parent_obj;
@@ -476,6 +474,8 @@ typedef struct ChardevClass {
ObjectClass parent_class;
bool internal; /* TODO: eventually use TYPE_USER_CREATABLE */
+ ChardevBackendKind kind;
+ void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp);
void (*open)(Chardev *chr, ChardevBackend *backend,
bool *be_opened, Error **errp);
@@ -495,17 +495,9 @@ typedef struct ChardevClass {
void (*chr_set_fe_open)(Chardev *chr, int fe_open);
} ChardevClass;
-struct CharDriver {
- ChardevBackendKind kind;
- const char *alias;
- void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp);
-};
-
Chardev *qemu_chardev_new(const char *id, const char *typename,
ChardevBackend *backend, Error **errp);
-void register_char_driver(const CharDriver *driver);
-
extern int term_escape_char;
/* console.c */
diff --git a/backends/baum.c b/backends/baum.c
index 39c9365024..5316c8da0a 100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@ -656,6 +656,7 @@ static void char_braille_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_BRAILLE;
cc->open = baum_chr_open;
cc->chr_write = baum_chr_write;
cc->chr_accept_input = baum_chr_accept_input;
@@ -671,11 +672,6 @@ static const TypeInfo char_braille_type_info = {
static void register_types(void)
{
- static const CharDriver driver = {
- .kind = CHARDEV_BACKEND_KIND_BRAILLE,
- };
-
- register_char_driver(&driver);
type_register_static(&char_braille_type_info);
}
diff --git a/backends/msmouse.c b/backends/msmouse.c
index 55c344f0e1..28689b3e29 100644
--- a/backends/msmouse.c
+++ b/backends/msmouse.c
@@ -169,6 +169,7 @@ static void char_msmouse_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_MSMOUSE;
cc->open = msmouse_chr_open;
cc->chr_write = msmouse_chr_write;
cc->chr_accept_input = msmouse_chr_accept_input;
@@ -184,11 +185,6 @@ static const TypeInfo char_msmouse_type_info = {
static void register_types(void)
{
- static const CharDriver driver = {
- .kind = CHARDEV_BACKEND_KIND_MSMOUSE,
- };
-
- register_char_driver(&driver);
type_register_static(&char_msmouse_type_info);
}
diff --git a/backends/testdev.c b/backends/testdev.c
index ea15143713..243454aaa3 100644
--- a/backends/testdev.c
+++ b/backends/testdev.c
@@ -111,6 +111,7 @@ static void char_testdev_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_TESTDEV;
cc->chr_write = testdev_chr_write;
}
@@ -123,11 +124,6 @@ static const TypeInfo char_testdev_type_info = {
static void register_types(void)
{
- static const CharDriver driver = {
- .kind = CHARDEV_BACKEND_KIND_TESTDEV,
- };
-
- register_char_driver(&driver);
type_register_static(&char_testdev_type_info);
}
diff --git a/qemu-char.c b/qemu-char.c
index c239418c25..67e577d0b5 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -560,16 +560,13 @@ static void null_chr_open(Chardev *chr,
*be_opened = false;
}
-static const CharDriver null_driver = {
- .kind = CHARDEV_BACKEND_KIND_NULL,
-};
-
static void char_null_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
cc->open = null_chr_open;
cc->chr_write = null_chr_write;
+ cc->kind = CHARDEV_BACKEND_KIND_NULL;
}
static const TypeInfo char_null_type_info = {
@@ -1707,14 +1704,11 @@ static void char_pty_open(Chardev *chr,
*be_opened = false;
}
-static const CharDriver pty_driver = {
- .kind = CHARDEV_BACKEND_KIND_PTY,
-};
-
static void char_pty_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_PTY;
cc->open = char_pty_open;
cc->chr_write = char_pty_chr_write;
cc->chr_update_read_handler = pty_chr_update_read_handler;
@@ -2457,14 +2451,11 @@ static void qemu_chr_open_win_con(Chardev *chr,
qemu_chr_open_win_file(chr, GetStdHandle(STD_OUTPUT_HANDLE));
}
-static const CharDriver console_driver = {
- .kind = CHARDEV_BACKEND_KIND_CONSOLE,
-};
-
static void char_console_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_CONSOLE;
cc->open = qemu_chr_open_win_con;
}
@@ -3841,15 +3832,12 @@ static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
stdio->signal = qemu_opt_get_bool(opts, "signal", true);
}
-static const CharDriver stdio_driver = {
- .kind = CHARDEV_BACKEND_KIND_STDIO,
- .parse = qemu_chr_parse_stdio,
-};
-
static void char_stdio_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_STDIO;
+ cc->parse = qemu_chr_parse_stdio;
cc->open = qemu_chr_open_stdio;
#ifdef _WIN32
cc->chr_write = win_stdio_write;
@@ -3919,15 +3907,12 @@ static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
dev->device = g_strdup(device);
}
-static const CharDriver pipe_driver = {
- .kind = CHARDEV_BACKEND_KIND_PIPE,
- .parse = qemu_chr_parse_pipe,
-};
-
static void char_pipe_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_PIPE;
+ cc->parse = qemu_chr_parse_pipe;
cc->open = qemu_chr_open_pipe;
}
@@ -3957,15 +3942,12 @@ static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
}
}
-static const CharDriver ringbuf_driver = {
- .kind = CHARDEV_BACKEND_KIND_RINGBUF,
- .parse = qemu_chr_parse_ringbuf,
-};
-
static void char_ringbuf_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_RINGBUF;
+ cc->parse = qemu_chr_parse_ringbuf;
cc->open = qemu_chr_open_ringbuf;
cc->chr_write = ringbuf_chr_write;
}
@@ -3979,14 +3961,17 @@ static const TypeInfo char_ringbuf_type_info = {
};
/* Bug-compatibility: */
-static const CharDriver memory_driver = {
- .kind = CHARDEV_BACKEND_KIND_MEMORY,
- .parse = qemu_chr_parse_ringbuf,
-};
+static void char_memory_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->kind = CHARDEV_BACKEND_KIND_MEMORY;
+}
static const TypeInfo char_memory_type_info = {
.name = TYPE_CHARDEV_MEMORY,
.parent = TYPE_CHARDEV_RINGBUF,
+ .class_init = char_memory_class_init,
};
static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
@@ -4004,15 +3989,12 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
mux->chardev = g_strdup(chardev);
}
-static const CharDriver mux_driver = {
- .kind = CHARDEV_BACKEND_KIND_MUX,
- .parse = qemu_chr_parse_mux,
-};
-
static void char_mux_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_MUX;
+ cc->parse = qemu_chr_parse_mux;
cc->open = qemu_chr_open_mux;
cc->chr_write = mux_chr_write;
cc->chr_accept_input = mux_chr_accept_input;
@@ -4154,18 +4136,91 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
}
}
-static const CharDriver *backends[CHARDEV_BACKEND_KIND__MAX];
+static const ChardevClass *char_get_class(const char *driver, Error **errp)
+{
+ ObjectClass *oc;
+ const ChardevClass *cc;
+ char *typename = g_strdup_printf("chardev-%s", driver);
+
+ oc = object_class_by_name(typename);
+ g_free(typename);
+
+ if (!object_class_dynamic_cast(oc, TYPE_CHARDEV)) {
+ error_setg(errp, "'%s' is not a valid char driver name", driver);
+ return NULL;
+ }
-void register_char_driver(const CharDriver *driver)
+ if (object_class_is_abstract(oc)) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
+ "abstract device type");
+ return NULL;
+ }
+
+ cc = CHARDEV_CLASS(oc);
+ if (cc->internal) {
+ error_setg(errp, "'%s' is not a valid char driver name", driver);
+ return NULL;
+ }
+
+ return cc;
+}
+
+static const struct ChardevAlias {
+ const char *typename;
+ const char *alias;
+} chardev_alias_table[] = {
+#ifdef HAVE_CHARDEV_PARPORT
+ { "parallel", "parport" },
+#endif
+#ifdef HAVE_CHARDEV_SERIAL
+ { "serial", "tty" },
+#endif
+};
+
+typedef struct ChadevClassFE {
+ void (*fn)(const char *name, void *opaque);
+ void *opaque;
+} ChadevClassFE;
+
+static void
+chardev_class_foreach(ObjectClass *klass, void *opaque)
{
- backends[driver->kind] = driver;
+ ChadevClassFE *fe = opaque;
+
+ assert(g_str_has_prefix(object_class_get_name(klass), "chardev-"));
+ if (CHARDEV_CLASS(klass)->internal) {
+ return;
+ }
+
+ fe->fn(object_class_get_name(klass) + 8, fe->opaque);
+}
+
+static void
+chardev_name_foreach(void (*fn)(const char *name, void *opaque), void *opaque)
+{
+ ChadevClassFE fe = { .fn = fn, .opaque = opaque };
+ int i;
+
+ object_class_foreach(chardev_class_foreach, TYPE_CHARDEV, false, &fe);
+
+ for (i = 0; i < ARRAY_SIZE(chardev_alias_table); i++) {
+ fn(chardev_alias_table[i].alias, opaque);
+ }
+}
+
+static void
+help_string_append(const char *name, void *opaque)
+{
+ GString *str = opaque;
+
+ g_string_append_printf(str, "\n%s", name);
}
Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
Error **errp)
{
Error *local_err = NULL;
- const CharDriver *cd = NULL;
+ const ChardevClass *cc;
Chardev *chr;
int i;
ChardevReturn *ret = NULL;
@@ -4182,15 +4237,8 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
if (is_help_option(name)) {
GString *str = g_string_new("");
- for (i = 0; i < ARRAY_SIZE(backends); i++) {
- cd = backends[i];
- if (cd) {
- g_string_append_printf(str, "\n%s", ChardevBackendKind_lookup[cd->kind]);
- if (cd->alias) {
- g_string_append_printf(str, "\n%s", cd->alias);
- }
- }
- }
+
+ chardev_name_foreach(help_string_append, str);
error_report("Available chardev backend types: %s", str->str);
g_string_free(str, true);
@@ -4202,18 +4250,15 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
goto err;
}
- for (i = 0; i < ARRAY_SIZE(backends); i++) {
- cd = backends[i];
- if (!cd) {
- continue;
- }
- if (g_strcmp0(ChardevBackendKind_lookup[cd->kind], name) == 0 ||
- g_strcmp0(cd->alias, name) == 0) {
+ for (i = 0; i < ARRAY_SIZE(chardev_alias_table); i++) {
+ if (g_strcmp0(chardev_alias_table[i].alias, name) == 0) {
+ name = chardev_alias_table[i].typename;
break;
}
}
- if (i == ARRAY_SIZE(backends)) {
- error_setg(errp, "chardev: backend \"%s\" not found", name);
+
+ cc = char_get_class(name, errp);
+ if (cc == NULL) {
goto err;
}
@@ -4224,17 +4269,17 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
}
chr = NULL;
- backend->type = cd->kind;
- if (cd->parse) {
- cd->parse(opts, backend, &local_err);
+ backend->type = cc->kind;
+ if (cc->parse) {
+ cc->parse(opts, backend, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto qapi_out;
}
} else {
- ChardevCommon *cc = g_new0(ChardevCommon, 1);
- qemu_chr_parse_common(opts, cc);
- backend->u.null.data = cc; /* Any ChardevCommon member would work */
+ ChardevCommon *ccom = g_new0(ChardevCommon, 1);
+ qemu_chr_parse_common(opts, ccom);
+ backend->u.null.data = ccom; /* Any ChardevCommon member would work */
}
ret = qmp_chardev_add(bid ? bid : id, backend, errp);
@@ -4396,34 +4441,23 @@ ChardevInfoList *qmp_query_chardev(Error **errp)
return chr_list;
}
-static ChardevBackendInfoList *
-qmp_prepend_backend(ChardevBackendInfoList *list, const char *name)
+static void
+qmp_prepend_backend(const char *name, void *opaque)
{
+ ChardevBackendInfoList **list = opaque;
ChardevBackendInfoList *info = g_malloc0(sizeof(*info));
+
info->value = g_malloc0(sizeof(*info->value));
info->value->name = g_strdup(name);
- info->next = list;
- return info;
+ info->next = *list;
+ *list = info;
}
ChardevBackendInfoList *qmp_query_chardev_backends(Error **errp)
{
ChardevBackendInfoList *backend_list = NULL;
- const CharDriver *c;
- int i;
- for (i = 0; i < ARRAY_SIZE(backends); i++) {
- c = backends[i];
- if (!c) {
- continue;
- }
-
- backend_list = qmp_prepend_backend(backend_list,
- ChardevBackendKind_lookup[c->kind]);
- if (c->alias) {
- backend_list = qmp_prepend_backend(backend_list, c->alias);
- }
- }
+ chardev_name_foreach(qmp_prepend_backend, &backend_list);
return backend_list;
}
@@ -4663,16 +4697,12 @@ static void qmp_chardev_open_parallel(Chardev *chr,
qemu_chr_open_pp_fd(chr, fd, be_opened, errp);
}
-static const CharDriver parallel_driver = {
- .kind = CHARDEV_BACKEND_KIND_PARALLEL,
- .alias = "parport",
- .parse = qemu_chr_parse_parallel,
-};
-
static void char_parallel_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_PARALLEL;
+ cc->parse = qemu_chr_parse_parallel;
cc->open = qmp_chardev_open_parallel;
#if defined(__linux__)
cc->chr_write = null_chr_write;
@@ -4710,15 +4740,12 @@ static const TypeInfo char_parallel_type_info = {
#endif /* WIN32 */
-static const CharDriver file_driver = {
- .kind = CHARDEV_BACKEND_KIND_FILE,
- .parse = qemu_chr_parse_file_out,
-};
-
static void char_file_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_FILE;
+ cc->parse = qemu_chr_parse_file_out;
cc->open = qmp_chardev_open_file;
}
@@ -4734,16 +4761,12 @@ static const TypeInfo char_file_type_info = {
#ifdef HAVE_CHARDEV_SERIAL
-static const CharDriver serial_driver = {
- .kind = CHARDEV_BACKEND_KIND_SERIAL,
- .alias = "tty",
- .parse = qemu_chr_parse_serial,
-};
-
static void char_serial_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_SERIAL;
+ cc->parse = qemu_chr_parse_serial;
cc->open = qmp_chardev_open_serial;
#ifndef _WIN32
cc->chr_ioctl = tty_serial_ioctl;
@@ -4896,15 +4919,12 @@ error:
}
}
-static const CharDriver socket_driver = {
- .kind = CHARDEV_BACKEND_KIND_SOCKET,
- .parse = qemu_chr_parse_socket,
-};
-
static void char_socket_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_SOCKET;
+ cc->parse = qemu_chr_parse_socket;
cc->open = qmp_chardev_open_socket;
cc->chr_wait_connected = tcp_chr_wait_connected;
cc->chr_write = tcp_chr_write;
@@ -4951,15 +4971,12 @@ static void qmp_chardev_open_udp(Chardev *chr,
*be_opened = false;
}
-static const CharDriver udp_driver = {
- .kind = CHARDEV_BACKEND_KIND_UDP,
- .parse = qemu_chr_parse_udp,
-};
-
static void char_udp_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_UDP;
+ cc->parse = qemu_chr_parse_udp;
cc->open = qmp_chardev_open_udp;
cc->chr_write = udp_chr_write;
cc->chr_update_read_handler = udp_chr_update_read_handler;
@@ -4985,35 +5002,6 @@ void qemu_chr_set_feature(Chardev *chr,
return set_bit(feature, chr->features);
}
-static const ChardevClass *char_get_class(const char *driver, Error **errp)
-{
- ObjectClass *oc;
- const ChardevClass *cc;
- char *typename = g_strdup_printf("chardev-%s", driver);
-
- oc = object_class_by_name(typename);
- g_free(typename);
-
- if (!object_class_dynamic_cast(oc, TYPE_CHARDEV)) {
- error_setg(errp, "'%s' is not a valid char driver name", driver);
- return NULL;
- }
-
- if (object_class_is_abstract(oc)) {
- error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
- "abstract device type");
- return NULL;
- }
-
- cc = CHARDEV_CLASS(oc);
- if (cc->internal) {
- error_setg(errp, "'%s' is not a valid char driver name", driver);
- return NULL;
- }
-
- return cc;
-}
-
Chardev *qemu_chardev_new(const char *id, const char *typename,
ChardevBackend *backend, Error **errp)
{
@@ -5109,45 +5097,34 @@ void qemu_chr_cleanup(void)
static void register_types(void)
{
- static const struct {
- const CharDriver *driver;
- const TypeInfo *type;
- } chardevs[] = {
- { &null_driver, &char_null_type_info },
- { &socket_driver, &char_socket_type_info },
- { &udp_driver, &char_udp_type_info },
- { &ringbuf_driver, &char_ringbuf_type_info },
- { &file_driver, &char_file_type_info },
- { &stdio_driver, &char_stdio_type_info },
+ type_register_static(&char_type_info);
+#ifndef _WIN32
+ type_register_static(&char_fd_type_info);
+#else
+ type_register_static(&char_win_type_info);
+ type_register_static(&char_win_stdio_type_info);
+#endif
+ type_register_static(&char_null_type_info);
+ type_register_static(&char_socket_type_info);
+ type_register_static(&char_udp_type_info);
+ type_register_static(&char_ringbuf_type_info);
+ type_register_static(&char_file_type_info);
+ type_register_static(&char_stdio_type_info);
#ifdef HAVE_CHARDEV_SERIAL
- { &serial_driver, &char_serial_type_info },
+ type_register_static(&char_serial_type_info);
#endif
#ifdef HAVE_CHARDEV_PARPORT
- { ¶llel_driver, &char_parallel_type_info },
+ type_register_static(&char_parallel_type_info);
#endif
#ifdef HAVE_CHARDEV_PTY
- { &pty_driver, &char_pty_type_info },
+ type_register_static(&char_pty_type_info);
#endif
#ifdef _WIN32
- { &console_driver, &char_console_type_info },
+ type_register_static(&char_console_type_info);
#endif
- { &pipe_driver, &char_pipe_type_info },
- { &mux_driver, &char_mux_type_info },
- { &memory_driver, &char_memory_type_info }
- };
- int i;
-
- type_register_static(&char_type_info);
-#ifndef _WIN32
- type_register_static(&char_fd_type_info);
-#else
- type_register_static(&char_win_type_info);
- type_register_static(&char_win_stdio_type_info);
-#endif
- for (i = 0; i < ARRAY_SIZE(chardevs); i++) {
- type_register_static(chardevs[i].type);
- register_char_driver(chardevs[i].driver);
- }
+ type_register_static(&char_pipe_type_info);
+ type_register_static(&char_mux_type_info);
+ type_register_static(&char_memory_type_info);
/* this must be done after machine init, since we register FEs with muxes
* as part of realize functions like serial_isa_realizefn when -nographic
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 3902202a35..17305830ab 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -380,6 +380,8 @@ static void char_spicevmc_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_SPICEVMC;
+ cc->parse = qemu_chr_parse_spice_vmc;
cc->open = qemu_chr_open_spice_vmc;
cc->chr_set_fe_open = spice_vmc_set_fe_open;
}
@@ -394,6 +396,8 @@ static void char_spiceport_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_SPICEPORT;
+ cc->parse = qemu_chr_parse_spice_port;
cc->open = qemu_chr_open_spice_port;
cc->chr_set_fe_open = spice_port_set_fe_open;
}
@@ -406,17 +410,6 @@ static const TypeInfo char_spiceport_type_info = {
static void register_types(void)
{
- static const CharDriver vmc_driver = {
- .kind = CHARDEV_BACKEND_KIND_SPICEVMC,
- .parse = qemu_chr_parse_spice_vmc,
- };
- static const CharDriver port_driver = {
- .kind = CHARDEV_BACKEND_KIND_SPICEPORT,
- .parse = qemu_chr_parse_spice_port,
- };
- register_char_driver(&vmc_driver);
- register_char_driver(&port_driver);
-
type_register_static(&char_spice_type_info);
type_register_static(&char_spicevmc_type_info);
type_register_static(&char_spiceport_type_info);
diff --git a/ui/console.c b/ui/console.c
index fe03a666f7..84fcbd86fd 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -2059,8 +2059,6 @@ static void text_console_do_init(Chardev *chr, DisplayState *ds)
qemu_chr_be_generic_open(chr);
}
-static const CharDriver vc_driver;
-
static void vc_chr_open(Chardev *chr,
ChardevBackend *backend,
bool *be_opened,
@@ -2189,6 +2187,8 @@ static void char_vc_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_VC;
+ cc->parse = qemu_chr_parse_vc;
cc->open = vc_chr_open;
cc->chr_write = vc_chr_write;
cc->chr_set_echo = vc_chr_set_echo;
@@ -2206,15 +2206,9 @@ void qemu_console_early_init(void)
/* set the default vc driver */
if (!object_class_by_name(TYPE_CHARDEV_VC)) {
type_register(&char_vc_type_info);
- register_char_driver(&vc_driver);
}
}
-static const CharDriver vc_driver = {
- .kind = CHARDEV_BACKEND_KIND_VC,
- .parse = qemu_chr_parse_vc,
-};
-
static void register_types(void)
{
type_register_static(&qemu_console_info);
diff --git a/ui/gtk.c b/ui/gtk.c
index bdd831c268..f4542e3b86 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1715,8 +1715,6 @@ static void gd_vc_chr_set_echo(Chardev *chr, bool echo)
static int nb_vcs;
static Chardev *vcs[MAX_VCS];
-static const CharDriver gd_vc_driver;
-
static void gd_vc_open(Chardev *chr,
ChardevBackend *backend,
bool *be_opened,
@@ -1739,6 +1737,8 @@ static void char_gd_vc_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
+ cc->kind = CHARDEV_BACKEND_KIND_VC;
+ cc->parse = qemu_chr_parse_vc;
cc->open = gd_vc_open;
cc->chr_write = gd_vc_chr_write;
cc->chr_set_echo = gd_vc_chr_set_echo;
@@ -1751,11 +1751,6 @@ static const TypeInfo char_gd_vc_type_info = {
.class_init = char_gd_vc_class_init,
};
-static const CharDriver gd_vc_driver = {
- .kind = CHARDEV_BACKEND_KIND_VC,
- .parse = qemu_chr_parse_vc,
-};
-
static gboolean gd_vc_in(VteTerminal *terminal, gchar *text, guint size,
gpointer user_data)
{
@@ -2353,6 +2348,5 @@ void early_gtk_display_init(int opengl)
#if defined(CONFIG_VTE)
type_register(&char_gd_vc_type_info);
- register_char_driver(&gd_vc_driver);
#endif
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 18/41] char: rename remaining CharDriver to Chardev
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (16 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 17/41] char: get rid of CharDriver Marc-André Lureau
@ 2017-01-31 16:20 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 19/41] char: remove class kind field Marc-André Lureau
` (24 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:20 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
CharDriver no longer exists, it has been replaced with Chardev.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
include/sysemu/char.h | 40 ++++++++++++++++++++--------------------
qemu-char.c | 11 +++++------
2 files changed, 25 insertions(+), 26 deletions(-)
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 2a3b887b8a..b4303e7b22 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -74,7 +74,7 @@ typedef enum {
QEMU_CHAR_FEATURE_REPLAY,
QEMU_CHAR_FEATURE_LAST,
-} CharDriverFeature;
+} ChardevFeature;
/* This is the backend as seen by frontend, the actual backend is
* Chardev */
@@ -141,7 +141,7 @@ Chardev *qemu_chr_new(const char *label, const char *filename);
* @qemu_chr_fe_disconnect:
*
* Close a fd accpeted by character backend.
- * Without associated CharDriver, do nothing.
+ * Without associated Chardev, do nothing.
*/
void qemu_chr_fe_disconnect(CharBackend *be);
@@ -156,7 +156,7 @@ void qemu_chr_cleanup(void);
* @qemu_chr_fe_wait_connected:
*
* Wait for characted backend to be connected, return < 0 on error or
- * if no assicated CharDriver.
+ * if no assicated Chardev.
*/
int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp);
@@ -188,7 +188,7 @@ void qemu_chr_delete(Chardev *chr);
* Ask the backend to override its normal echo setting. This only really
* applies to the stdio backend and is used by the QMP server such that you
* can see what you type if you try to type QMP commands.
- * Without associated CharDriver, do nothing.
+ * Without associated Chardev, do nothing.
*
* @echo true to enable echo, false to disable echo
*/
@@ -199,7 +199,7 @@ void qemu_chr_fe_set_echo(CharBackend *be, bool echo);
*
* Set character frontend open status. This is an indication that the
* front end is ready (or not) to begin doing I/O.
- * Without associated CharDriver, do nothing.
+ * Without associated Chardev, do nothing.
*/
void qemu_chr_fe_set_open(CharBackend *be, int fe_open);
@@ -208,7 +208,7 @@ void qemu_chr_fe_set_open(CharBackend *be, int fe_open);
*
* Write to a character backend using a printf style interface. This
* function is thread-safe. It does nothing without associated
- * CharDriver.
+ * Chardev.
*
* @fmt see #printf
*/
@@ -221,7 +221,7 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
* If the backend is connected, create and add a #GSource that fires
* when the given condition (typically G_IO_OUT|G_IO_HUP or G_IO_HUP)
* is active; return the #GSource's tag. If it is disconnected,
- * or without associated CharDriver, return 0.
+ * or without associated Chardev, return 0.
*
* @cond the condition to poll for
* @func the function to call when the condition happens
@@ -242,7 +242,7 @@ guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
* @buf the data
* @len the number of bytes to send
*
- * Returns: the number of bytes consumed (0 if no assicated CharDriver)
+ * Returns: the number of bytes consumed (0 if no assicated Chardev)
*/
int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len);
@@ -257,7 +257,7 @@ int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len);
* @buf the data
* @len the number of bytes to send
*
- * Returns: the number of bytes consumed (0 if no assicated CharDriver)
+ * Returns: the number of bytes consumed (0 if no assicated Chardev)
*/
int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len);
@@ -269,7 +269,7 @@ int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len);
* @buf the data buffer
* @len the number of bytes to read
*
- * Returns: the number of bytes read (0 if no assicated CharDriver)
+ * Returns: the number of bytes read (0 if no assicated Chardev)
*/
int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len);
@@ -282,7 +282,7 @@ int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len);
* @arg the data associated with @cmd
*
* Returns: if @cmd is not supported by the backend or there is no
- * associated CharDriver, -ENOTSUP, otherwise the return
+ * associated Chardev, -ENOTSUP, otherwise the return
* value depends on the semantics of @cmd
*/
int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg);
@@ -322,7 +322,7 @@ int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num);
* result in overwriting the fd array with the new value without being send.
* Upon writing the message the fd array is freed.
*
- * Returns: -1 if fd passing isn't supported or no associated CharDriver.
+ * Returns: -1 if fd passing isn't supported or no associated Chardev.
*/
int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num);
@@ -373,7 +373,7 @@ void qemu_chr_be_event(Chardev *s, int event);
* @qemu_chr_fe_init:
*
* Initializes a front end for the given CharBackend and
- * CharDriver. Call qemu_chr_fe_deinit() to remove the association and
+ * Chardev. Call qemu_chr_fe_deinit() to remove the association and
* release the driver.
*
* Returns: false on error.
@@ -384,16 +384,16 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp);
* @qemu_chr_fe_get_driver:
*
* Returns the driver associated with a CharBackend or NULL if no
- * associated CharDriver.
+ * associated Chardev.
*/
Chardev *qemu_chr_fe_get_driver(CharBackend *be);
/**
* @qemu_chr_fe_deinit:
*
- * Dissociate the CharBackend from the CharDriver.
+ * Dissociate the CharBackend from the Chardev.
*
- * Safe to call without associated CharDriver.
+ * Safe to call without associated Chardev.
*/
void qemu_chr_fe_deinit(CharBackend *b);
@@ -412,7 +412,7 @@ void qemu_chr_fe_deinit(CharBackend *b);
* Set the front end char handlers. The front end takes the focus if
* any of the handler is non-NULL.
*
- * Without associated CharDriver, nothing is changed.
+ * Without associated Chardev, nothing is changed.
*/
void qemu_chr_fe_set_handlers(CharBackend *b,
IOCanReadHandler *fd_can_read,
@@ -427,7 +427,7 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
*
* Take the focus (if the front end is muxed).
*
- * Without associated CharDriver, nothing is changed.
+ * Without associated Chardev, nothing is changed.
*/
void qemu_chr_fe_take_focus(CharBackend *b);
@@ -437,9 +437,9 @@ int qemu_chr_add_client(Chardev *s, int fd);
Chardev *qemu_chr_find(const char *name);
bool qemu_chr_has_feature(Chardev *chr,
- CharDriverFeature feature);
+ ChardevFeature feature);
void qemu_chr_set_feature(Chardev *chr,
- CharDriverFeature feature);
+ ChardevFeature feature);
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
#define TYPE_CHARDEV "chardev"
diff --git a/qemu-char.c b/qemu-char.c
index 67e577d0b5..b68d4a9059 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -3171,13 +3171,13 @@ typedef struct {
Chardev *chr;
char buf[12];
size_t buflen;
-} TCPCharDriverTelnetInit;
+} TCPChardevTelnetInit;
static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
GIOCondition cond G_GNUC_UNUSED,
gpointer user_data)
{
- TCPCharDriverTelnetInit *init = user_data;
+ TCPChardevTelnetInit *init = user_data;
ssize_t ret;
ret = qio_channel_write(ioc, init->buf, init->buflen, NULL);
@@ -3204,8 +3204,7 @@ static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
static void tcp_chr_telnet_init(Chardev *chr)
{
SocketChardev *s = SOCKET_CHARDEV(chr);
- TCPCharDriverTelnetInit *init =
- g_new0(TCPCharDriverTelnetInit, 1);
+ TCPChardevTelnetInit *init = g_new0(TCPChardevTelnetInit, 1);
size_t n = 0;
init->chr = chr;
@@ -4991,13 +4990,13 @@ static const TypeInfo char_udp_type_info = {
};
bool qemu_chr_has_feature(Chardev *chr,
- CharDriverFeature feature)
+ ChardevFeature feature)
{
return test_bit(feature, chr->features);
}
void qemu_chr_set_feature(Chardev *chr,
- CharDriverFeature feature)
+ ChardevFeature feature)
{
return set_bit(feature, chr->features);
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 19/41] char: remove class kind field
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (17 preceding siblings ...)
2017-01-31 16:20 ` [Qemu-devel] [PULL 18/41] char: rename remaining CharDriver to Chardev Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 20/41] char: move to chardev/ Marc-André Lureau
` (23 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
The class kind is necessary to lookup the chardev name in
qmp_chardev_add() after calling qemu_chr_new_from_opts() and to set
the appropriate ChardevBackend (mainly to free the right
fields).
qemu_chr_new_from_opts() can be changed to use a non-qmp function
using the chardev class typename. Introduce qemu_chardev_add() to be
called from qemu_chr_new_from_opts() and remove the class chardev kind
field. Set the backend->type in the parse callback (when non-common
fields are added).
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
include/sysemu/char.h | 1 -
backends/baum.c | 1 -
backends/msmouse.c | 1 -
backends/testdev.c | 1 -
qemu-char.c | 99 +++++++++++++++++++++++++--------------------------
spice-qemu-char.c | 4 +--
ui/console.c | 2 +-
ui/gtk.c | 1 -
8 files changed, 51 insertions(+), 59 deletions(-)
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index b4303e7b22..31229deaca 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -474,7 +474,6 @@ typedef struct ChardevClass {
ObjectClass parent_class;
bool internal; /* TODO: eventually use TYPE_USER_CREATABLE */
- ChardevBackendKind kind;
void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp);
void (*open)(Chardev *chr, ChardevBackend *backend,
diff --git a/backends/baum.c b/backends/baum.c
index 5316c8da0a..2eddcae119 100644
--- a/backends/baum.c
+++ b/backends/baum.c
@@ -656,7 +656,6 @@ static void char_braille_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_BRAILLE;
cc->open = baum_chr_open;
cc->chr_write = baum_chr_write;
cc->chr_accept_input = baum_chr_accept_input;
diff --git a/backends/msmouse.c b/backends/msmouse.c
index 28689b3e29..d2c3162f1e 100644
--- a/backends/msmouse.c
+++ b/backends/msmouse.c
@@ -169,7 +169,6 @@ static void char_msmouse_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_MSMOUSE;
cc->open = msmouse_chr_open;
cc->chr_write = msmouse_chr_write;
cc->chr_accept_input = msmouse_chr_accept_input;
diff --git a/backends/testdev.c b/backends/testdev.c
index 243454aaa3..7df9248a13 100644
--- a/backends/testdev.c
+++ b/backends/testdev.c
@@ -111,7 +111,6 @@ static void char_testdev_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_TESTDEV;
cc->chr_write = testdev_chr_write;
}
diff --git a/qemu-char.c b/qemu-char.c
index b68d4a9059..15f4a853bc 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -566,7 +566,6 @@ static void char_null_class_init(ObjectClass *oc, void *data)
cc->open = null_chr_open;
cc->chr_write = null_chr_write;
- cc->kind = CHARDEV_BACKEND_KIND_NULL;
}
static const TypeInfo char_null_type_info = {
@@ -1708,7 +1707,6 @@ static void char_pty_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_PTY;
cc->open = char_pty_open;
cc->chr_write = char_pty_chr_write;
cc->chr_update_read_handler = pty_chr_update_read_handler;
@@ -2455,7 +2453,6 @@ static void char_console_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_CONSOLE;
cc->open = qemu_chr_open_win_con;
}
@@ -3808,6 +3805,7 @@ static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
const char *path = qemu_opt_get(opts, "path");
ChardevFile *file;
+ backend->type = CHARDEV_BACKEND_KIND_FILE;
if (path == NULL) {
error_setg(errp, "chardev: file: no filename given");
return;
@@ -3825,6 +3823,7 @@ static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
{
ChardevStdio *stdio;
+ backend->type = CHARDEV_BACKEND_KIND_STDIO;
stdio = backend->u.stdio.data = g_new0(ChardevStdio, 1);
qemu_chr_parse_common(opts, qapi_ChardevStdio_base(stdio));
stdio->has_signal = true;
@@ -3835,7 +3834,6 @@ static void char_stdio_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_STDIO;
cc->parse = qemu_chr_parse_stdio;
cc->open = qemu_chr_open_stdio;
#ifdef _WIN32
@@ -3864,6 +3862,7 @@ static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
const char *device = qemu_opt_get(opts, "path");
ChardevHostdev *serial;
+ backend->type = CHARDEV_BACKEND_KIND_SERIAL;
if (device == NULL) {
error_setg(errp, "chardev: serial/tty: no device path given");
return;
@@ -3881,6 +3880,7 @@ static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
const char *device = qemu_opt_get(opts, "path");
ChardevHostdev *parallel;
+ backend->type = CHARDEV_BACKEND_KIND_PARALLEL;
if (device == NULL) {
error_setg(errp, "chardev: parallel: no device path given");
return;
@@ -3897,6 +3897,7 @@ static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
const char *device = qemu_opt_get(opts, "path");
ChardevHostdev *dev;
+ backend->type = CHARDEV_BACKEND_KIND_PIPE;
if (device == NULL) {
error_setg(errp, "chardev: pipe: no device path given");
return;
@@ -3910,7 +3911,6 @@ static void char_pipe_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_PIPE;
cc->parse = qemu_chr_parse_pipe;
cc->open = qemu_chr_open_pipe;
}
@@ -3931,6 +3931,7 @@ static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
int val;
ChardevRingbuf *ringbuf;
+ backend->type = CHARDEV_BACKEND_KIND_RINGBUF;
ringbuf = backend->u.ringbuf.data = g_new0(ChardevRingbuf, 1);
qemu_chr_parse_common(opts, qapi_ChardevRingbuf_base(ringbuf));
@@ -3945,7 +3946,6 @@ static void char_ringbuf_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_RINGBUF;
cc->parse = qemu_chr_parse_ringbuf;
cc->open = qemu_chr_open_ringbuf;
cc->chr_write = ringbuf_chr_write;
@@ -3960,17 +3960,9 @@ static const TypeInfo char_ringbuf_type_info = {
};
/* Bug-compatibility: */
-static void char_memory_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->kind = CHARDEV_BACKEND_KIND_MEMORY;
-}
-
static const TypeInfo char_memory_type_info = {
.name = TYPE_CHARDEV_MEMORY,
.parent = TYPE_CHARDEV_RINGBUF,
- .class_init = char_memory_class_init,
};
static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
@@ -3979,6 +3971,7 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
const char *chardev = qemu_opt_get(opts, "chardev");
ChardevMux *mux;
+ backend->type = CHARDEV_BACKEND_KIND_MUX;
if (chardev == NULL) {
error_setg(errp, "chardev: mux: no chardev given");
return;
@@ -3992,7 +3985,6 @@ static void char_mux_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_MUX;
cc->parse = qemu_chr_parse_mux;
cc->open = qemu_chr_open_mux;
cc->chr_write = mux_chr_write;
@@ -4023,6 +4015,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
SocketAddress *addr;
ChardevSocket *sock;
+ backend->type = CHARDEV_BACKEND_KIND_SOCKET;
if (!path) {
if (!host) {
error_setg(errp, "chardev: socket: no host given");
@@ -4088,6 +4081,7 @@ static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
SocketAddress *addr;
ChardevUdp *udp;
+ backend->type = CHARDEV_BACKEND_KIND_UDP;
if (host == NULL || strlen(host) == 0) {
host = "localhost";
}
@@ -4164,6 +4158,26 @@ static const ChardevClass *char_get_class(const char *driver, Error **errp)
return cc;
}
+static Chardev *qemu_chardev_add(const char *id, const char *typename,
+ ChardevBackend *backend, Error **errp)
+{
+ Chardev *chr;
+
+ chr = qemu_chr_find(id);
+ if (chr) {
+ error_setg(errp, "Chardev '%s' already exists", id);
+ return NULL;
+ }
+
+ chr = qemu_chardev_new(id, typename, backend, errp);
+ if (!chr) {
+ return NULL;
+ }
+
+ QTAILQ_INSERT_TAIL(&chardevs, chr, next);
+ return chr;
+}
+
static const struct ChardevAlias {
const char *typename;
const char *alias;
@@ -4222,8 +4236,7 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
const ChardevClass *cc;
Chardev *chr;
int i;
- ChardevReturn *ret = NULL;
- ChardevBackend *backend;
+ ChardevBackend *backend = NULL;
const char *name = qemu_opt_get(opts, "backend");
const char *id = qemu_opts_id(opts);
char *bid = NULL;
@@ -4231,7 +4244,7 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
if (name == NULL) {
error_setg(errp, "chardev: \"%s\" missing backend",
qemu_opts_id(opts));
- goto err;
+ return NULL;
}
if (is_help_option(name)) {
@@ -4246,7 +4259,7 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
if (id == NULL) {
error_setg(errp, "chardev: no id specified");
- goto err;
+ return NULL;
}
for (i = 0; i < ARRAY_SIZE(chardev_alias_table); i++) {
@@ -4258,22 +4271,22 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
cc = char_get_class(name, errp);
if (cc == NULL) {
- goto err;
+ return NULL;
}
backend = g_new0(ChardevBackend, 1);
+ backend->type = CHARDEV_BACKEND_KIND_NULL;
if (qemu_opt_get_bool(opts, "mux", 0)) {
bid = g_strdup_printf("%s-base", id);
}
chr = NULL;
- backend->type = cc->kind;
if (cc->parse) {
cc->parse(opts, backend, &local_err);
if (local_err) {
error_propagate(errp, local_err);
- goto qapi_out;
+ goto out;
}
} else {
ChardevCommon *ccom = g_new0(ChardevCommon, 1);
@@ -4281,37 +4294,33 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
backend->u.null.data = ccom; /* Any ChardevCommon member would work */
}
- ret = qmp_chardev_add(bid ? bid : id, backend, errp);
- if (!ret) {
- goto qapi_out;
+ chr = qemu_chardev_add(bid ? bid : id,
+ object_class_get_name(OBJECT_CLASS(cc)),
+ backend, errp);
+ if (chr == NULL) {
+ goto out;
}
if (bid) {
+ Chardev *mux;
qapi_free_ChardevBackend(backend);
- qapi_free_ChardevReturn(ret);
backend = g_new0(ChardevBackend, 1);
- backend->u.mux.data = g_new0(ChardevMux, 1);
backend->type = CHARDEV_BACKEND_KIND_MUX;
+ backend->u.mux.data = g_new0(ChardevMux, 1);
backend->u.mux.data->chardev = g_strdup(bid);
- ret = qmp_chardev_add(id, backend, errp);
- if (!ret) {
- chr = qemu_chr_find(bid);
+ mux = qemu_chardev_add(id, TYPE_CHARDEV_MUX, backend, errp);
+ if (mux == NULL) {
qemu_chr_delete(chr);
chr = NULL;
- goto qapi_out;
+ goto out;
}
+ chr = mux;
}
- chr = qemu_chr_find(id);
-
-qapi_out:
+out:
qapi_free_ChardevBackend(backend);
- qapi_free_ChardevReturn(ret);
g_free(bid);
return chr;
-
-err:
- return NULL;
}
Chardev *qemu_chr_new_noreplay(const char *label, const char *filename)
@@ -4700,7 +4709,6 @@ static void char_parallel_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_PARALLEL;
cc->parse = qemu_chr_parse_parallel;
cc->open = qmp_chardev_open_parallel;
#if defined(__linux__)
@@ -4743,7 +4751,6 @@ static void char_file_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_FILE;
cc->parse = qemu_chr_parse_file_out;
cc->open = qmp_chardev_open_file;
}
@@ -4764,7 +4771,6 @@ static void char_serial_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_SERIAL;
cc->parse = qemu_chr_parse_serial;
cc->open = qmp_chardev_open_serial;
#ifndef _WIN32
@@ -4922,7 +4928,6 @@ static void char_socket_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_SOCKET;
cc->parse = qemu_chr_parse_socket;
cc->open = qmp_chardev_open_socket;
cc->chr_wait_connected = tcp_chr_wait_connected;
@@ -4974,7 +4979,6 @@ static void char_udp_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_UDP;
cc->parse = qemu_chr_parse_udp;
cc->open = qmp_chardev_open_udp;
cc->chr_write = udp_chr_write;
@@ -5037,18 +5041,12 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
ChardevReturn *ret;
Chardev *chr;
- chr = qemu_chr_find(id);
- if (chr) {
- error_setg(errp, "Chardev '%s' already exists", id);
- return NULL;
- }
-
cc = char_get_class(ChardevBackendKind_lookup[backend->type], errp);
if (!cc) {
return NULL;
}
- chr = qemu_chardev_new(id, object_class_get_name(OBJECT_CLASS(cc)),
+ chr = qemu_chardev_add(id, object_class_get_name(OBJECT_CLASS(cc)),
backend, errp);
if (!chr) {
return NULL;
@@ -5060,7 +5058,6 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
ret->has_pty = true;
}
- QTAILQ_INSERT_TAIL(&chardevs, chr, next);
return ret;
}
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 17305830ab..adfa55b55c 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -338,6 +338,7 @@ static void qemu_chr_parse_spice_vmc(QemuOpts *opts, ChardevBackend *backend,
error_setg(errp, "chardev: spice channel: no name given");
return;
}
+ backend->type = CHARDEV_BACKEND_KIND_SPICEVMC;
spicevmc = backend->u.spicevmc.data = g_new0(ChardevSpiceChannel, 1);
qemu_chr_parse_common(opts, qapi_ChardevSpiceChannel_base(spicevmc));
spicevmc->type = g_strdup(name);
@@ -353,6 +354,7 @@ static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend,
error_setg(errp, "chardev: spice port: no name given");
return;
}
+ backend->type = CHARDEV_BACKEND_KIND_SPICEPORT;
spiceport = backend->u.spiceport.data = g_new0(ChardevSpicePort, 1);
qemu_chr_parse_common(opts, qapi_ChardevSpicePort_base(spiceport));
spiceport->fqdn = g_strdup(name);
@@ -380,7 +382,6 @@ static void char_spicevmc_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_SPICEVMC;
cc->parse = qemu_chr_parse_spice_vmc;
cc->open = qemu_chr_open_spice_vmc;
cc->chr_set_fe_open = spice_vmc_set_fe_open;
@@ -396,7 +397,6 @@ static void char_spiceport_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_SPICEPORT;
cc->parse = qemu_chr_parse_spice_port;
cc->open = qemu_chr_open_spice_port;
cc->chr_set_fe_open = spice_port_set_fe_open;
diff --git a/ui/console.c b/ui/console.c
index 84fcbd86fd..8c93f2a1e8 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -2148,6 +2148,7 @@ void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error **errp)
int val;
ChardevVC *vc;
+ backend->type = CHARDEV_BACKEND_KIND_VC;
vc = backend->u.vc.data = g_new0(ChardevVC, 1);
qemu_chr_parse_common(opts, qapi_ChardevVC_base(vc));
@@ -2187,7 +2188,6 @@ static void char_vc_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_VC;
cc->parse = qemu_chr_parse_vc;
cc->open = vc_chr_open;
cc->chr_write = vc_chr_write;
diff --git a/ui/gtk.c b/ui/gtk.c
index f4542e3b86..4984bf3bd9 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -1737,7 +1737,6 @@ static void char_gd_vc_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
- cc->kind = CHARDEV_BACKEND_KIND_VC;
cc->parse = qemu_chr_parse_vc;
cc->open = gd_vc_open;
cc->chr_write = gd_vc_chr_write;
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 20/41] char: move to chardev/
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (18 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 19/41] char: remove class kind field Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 21/41] char: create chardev-obj-y Marc-André Lureau
` (22 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
The following commits will split char.c in several files. Let's put them
in a subdirectory.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
qemu-char.c => chardev/char.c | 0
MAINTAINERS | 2 +-
Makefile.objs | 2 +-
chardev/Makefile.objs | 1 +
tests/Makefile.include | 8 +++++---
5 files changed, 8 insertions(+), 5 deletions(-)
rename qemu-char.c => chardev/char.c (100%)
create mode 100644 chardev/Makefile.objs
diff --git a/qemu-char.c b/chardev/char.c
similarity index 100%
rename from qemu-char.c
rename to chardev/char.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 5efd8cc671..497ca54627 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1196,7 +1196,7 @@ Character device backends
M: Paolo Bonzini <pbonzini@redhat.com>
M: Marc-André Lureau <marcandre.lureau@redhat.com>
S: Maintained
-F: qemu-char.c
+F: chardev/
F: backends/msmouse.c
F: backends/testdev.c
diff --git a/Makefile.objs b/Makefile.objs
index 01cef866e4..cad4c54740 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -51,7 +51,7 @@ common-obj-$(CONFIG_POSIX) += os-posix.o
common-obj-$(CONFIG_LINUX) += fsdev/
common-obj-y += migration/
-common-obj-y += qemu-char.o #aio.o
+common-obj-y += chardev/ #aio.o
common-obj-y += page_cache.o
common-obj-$(CONFIG_SPICE) += spice-qemu-char.o
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
new file mode 100644
index 0000000000..3fc5539518
--- /dev/null
+++ b/chardev/Makefile.objs
@@ -0,0 +1 @@
+common-obj-y += char.o
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 33b4f88746..2145b9877d 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -9,7 +9,7 @@ SYSEMU_TARGET_LIST := $(subst -softmmu.mak,,$(notdir \
check-unit-y = tests/check-qdict$(EXESUF)
gcov-files-check-qdict-y = qobject/qdict.c
check-unit-y += tests/test-char$(EXESUF)
-gcov-files-check-qdict-y = qemu-char.c
+gcov-files-check-qdict-y = chardev/char.c
check-unit-y += tests/check-qfloat$(EXESUF)
gcov-files-check-qfloat-y = qobject/qfloat.c
check-unit-y += tests/check-qint$(EXESUF)
@@ -510,7 +510,8 @@ tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
-tests/test-char$(EXESUF): tests/test-char.o qemu-char.o qemu-timer.o $(test-util-obj-y) $(qtest-obj-y) $(test-block-obj-y)
+tests/test-char$(EXESUF): tests/test-char.o chardev/char.o qemu-timer.o \
+ $(test-util-obj-y) $(qtest-obj-y) $(test-block-obj-y)
tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y)
tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
@@ -703,7 +704,8 @@ tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y)
tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y)
tests/pc-cpu-test$(EXESUF): tests/pc-cpu-test.o
tests/postcopy-test$(EXESUF): tests/postcopy-test.o
-tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o $(qtest-obj-y) $(test-io-obj-y) $(libqos-virtio-obj-y) $(libqos-pc-obj-y)
+tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o chardev/char.o qemu-timer.o \
+ $(qtest-obj-y) $(test-io-obj-y) $(libqos-virtio-obj-y) $(libqos-pc-obj-y)
tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y)
tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(test-block-obj-y)
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 21/41] char: create chardev-obj-y
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (19 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 20/41] char: move to chardev/ Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 22/41] char: make null_chr_write() the default method Marc-André Lureau
` (21 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
This will help to split char.c in several units without having to
reference them all everywhere. This is useful in particular for tests.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
Makefile | 4 +++-
Makefile.objs | 5 +++--
Makefile.target | 3 +++
chardev/Makefile.objs | 2 +-
tests/Makefile.include | 9 +++++----
5 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/Makefile b/Makefile
index 1e5cb1934d..aef76221f5 100644
--- a/Makefile
+++ b/Makefile
@@ -147,6 +147,7 @@ endif
dummy := $(call unnest-vars,, \
stub-obj-y \
+ chardev-obj-y \
util-obj-y \
qga-obj-y \
ivshmem-client-obj-y \
@@ -223,7 +224,8 @@ subdir-dtc:dtc/libfdt dtc/tests
dtc/%:
mkdir -p $@
-$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) $(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY))
+$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) $(chardev-obj-y) \
+ $(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY))
ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
# Only keep -O and -g cflags
diff --git a/Makefile.objs b/Makefile.objs
index cad4c54740..91a4794f28 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -51,8 +51,7 @@ common-obj-$(CONFIG_POSIX) += os-posix.o
common-obj-$(CONFIG_LINUX) += fsdev/
common-obj-y += migration/
-common-obj-y += chardev/ #aio.o
-common-obj-y += page_cache.o
+common-obj-y += page_cache.o #aio.o
common-obj-$(CONFIG_SPICE) += spice-qemu-char.o
@@ -79,6 +78,8 @@ common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
common-obj-$(CONFIG_FDT) += device_tree.o
+chardev-obj-y = chardev/
+
######################################################################
# qapi
diff --git a/Makefile.target b/Makefile.target
index fa2b151caa..5a487b5187 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -172,12 +172,14 @@ all-obj-y := $(obj-y)
target-obj-y :=
block-obj-y :=
common-obj-y :=
+chardev-obj-y :=
include $(SRC_PATH)/Makefile.objs
dummy := $(call unnest-vars,,target-obj-y)
target-obj-y-save := $(target-obj-y)
dummy := $(call unnest-vars,.., \
block-obj-y \
block-obj-m \
+ chardev-obj-y \
crypto-obj-y \
crypto-aes-obj-y \
qom-obj-y \
@@ -186,6 +188,7 @@ dummy := $(call unnest-vars,.., \
common-obj-m)
target-obj-y := $(target-obj-y-save)
all-obj-y += $(common-obj-y)
+all-obj-y += $(chardev-obj-y)
all-obj-y += $(target-obj-y)
all-obj-y += $(qom-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y)
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index 3fc5539518..8bf131b461 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -1 +1 @@
-common-obj-y += char.o
+chardev-obj-y += char.o
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 2145b9877d..ad35a6494b 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -510,8 +510,8 @@ tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
-tests/test-char$(EXESUF): tests/test-char.o chardev/char.o qemu-timer.o \
- $(test-util-obj-y) $(qtest-obj-y) $(test-block-obj-y)
+tests/test-char$(EXESUF): tests/test-char.o qemu-timer.o \
+ $(test-util-obj-y) $(qtest-obj-y) $(test-block-obj-y) $(chardev-obj-y)
tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y)
tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
tests/test-throttle$(EXESUF): tests/test-throttle.o $(test-block-obj-y)
@@ -704,8 +704,9 @@ tests/usb-hcd-ehci-test$(EXESUF): tests/usb-hcd-ehci-test.o $(libqos-usb-obj-y)
tests/usb-hcd-xhci-test$(EXESUF): tests/usb-hcd-xhci-test.o $(libqos-usb-obj-y)
tests/pc-cpu-test$(EXESUF): tests/pc-cpu-test.o
tests/postcopy-test$(EXESUF): tests/postcopy-test.o
-tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o chardev/char.o qemu-timer.o \
- $(qtest-obj-y) $(test-io-obj-y) $(libqos-virtio-obj-y) $(libqos-pc-obj-y)
+tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-timer.o \
+ $(qtest-obj-y) $(test-io-obj-y) $(libqos-virtio-obj-y) $(libqos-pc-obj-y) \
+ $(chardev-obj-y)
tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y)
tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(test-block-obj-y)
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 22/41] char: make null_chr_write() the default method
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (20 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 21/41] char: create chardev-obj-y Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 23/41] char: move null chardev to its own file Marc-André Lureau
` (20 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
All chardev must implement chr_write(), but parallel and null chardev
both use null_chr_write(). Move it to the base class, so we don't need
to export the function when splitting the chardev in respective files.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
chardev/char.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/chardev/char.c b/chardev/char.c
index 15f4a853bc..ee6ceb3471 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -522,6 +522,18 @@ static void char_init(Object *obj)
qemu_mutex_init(&chr->chr_write_lock);
}
+static int null_chr_write(Chardev *chr, const uint8_t *buf, int len)
+{
+ return len;
+}
+
+static void char_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->chr_write = null_chr_write;
+}
+
static void char_finalize(Object *obj)
{
Chardev *chr = CHARDEV(obj);
@@ -545,13 +557,9 @@ static const TypeInfo char_type_info = {
.instance_finalize = char_finalize,
.abstract = true,
.class_size = sizeof(ChardevClass),
+ .class_init = char_class_init,
};
-static int null_chr_write(Chardev *chr, const uint8_t *buf, int len)
-{
- return len;
-}
-
static void null_chr_open(Chardev *chr,
ChardevBackend *backend,
bool *be_opened,
@@ -565,7 +573,6 @@ static void char_null_class_init(ObjectClass *oc, void *data)
ChardevClass *cc = CHARDEV_CLASS(oc);
cc->open = null_chr_open;
- cc->chr_write = null_chr_write;
}
static const TypeInfo char_null_type_info = {
@@ -4712,10 +4719,8 @@ static void char_parallel_class_init(ObjectClass *oc, void *data)
cc->parse = qemu_chr_parse_parallel;
cc->open = qmp_chardev_open_parallel;
#if defined(__linux__)
- cc->chr_write = null_chr_write;
cc->chr_ioctl = pp_ioctl;
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
- cc->chr_write = null_chr_write;
cc->chr_ioctl = pp_ioctl;
#endif
}
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 23/41] char: move null chardev to its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (21 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 22/41] char: make null_chr_write() the default method Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 24/41] char: move mux " Marc-André Lureau
` (19 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
chardev/char-null.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 23 ----------------------
chardev/Makefile.objs | 1 +
3 files changed, 55 insertions(+), 23 deletions(-)
create mode 100644 chardev/char-null.c
diff --git a/chardev/char-null.c b/chardev/char-null.c
new file mode 100644
index 0000000000..dc0d68ab2d
--- /dev/null
+++ b/chardev/char-null.c
@@ -0,0 +1,54 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "sysemu/char.h"
+
+static void null_chr_open(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ *be_opened = false;
+}
+
+static void char_null_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->open = null_chr_open;
+}
+
+static const TypeInfo char_null_type_info = {
+ .name = TYPE_CHARDEV_NULL,
+ .parent = TYPE_CHARDEV,
+ .instance_size = sizeof(Chardev),
+ .class_init = char_null_class_init,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_null_type_info);
+}
+
+type_init(register_types);
diff --git a/chardev/char.c b/chardev/char.c
index ee6ceb3471..2ca6c7cf67 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -560,28 +560,6 @@ static const TypeInfo char_type_info = {
.class_init = char_class_init,
};
-static void null_chr_open(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- *be_opened = false;
-}
-
-static void char_null_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->open = null_chr_open;
-}
-
-static const TypeInfo char_null_type_info = {
- .name = TYPE_CHARDEV_NULL,
- .parent = TYPE_CHARDEV,
- .instance_size = sizeof(Chardev),
- .class_init = char_null_class_init,
-};
-
/* MUX driver for serial I/O splitting */
#define MAX_MUX 4
#define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */
@@ -5105,7 +5083,6 @@ static void register_types(void)
type_register_static(&char_win_type_info);
type_register_static(&char_win_stdio_type_info);
#endif
- type_register_static(&char_null_type_info);
type_register_static(&char_socket_type_info);
type_register_static(&char_udp_type_info);
type_register_static(&char_ringbuf_type_info);
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index 8bf131b461..be7ff800c3 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -1 +1,2 @@
chardev-obj-y += char.o
+chardev-obj-y += char-null.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 24/41] char: move mux to its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (22 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 23/41] char: move null chardev to its own file Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 25/41] char: move ringbuf/memory " Marc-André Lureau
` (18 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
A mechanical move, except that qemu_chr_write_all() needs to be declared
in char.h header to be used from chardev unit files.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
chardev/char-mux.h | 63 +++++++++
include/sysemu/char.h | 3 +-
chardev/char-mux.c | 358 ++++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 352 +------------------------------------------------
chardev/Makefile.objs | 1 +
5 files changed, 426 insertions(+), 351 deletions(-)
create mode 100644 chardev/char-mux.h
create mode 100644 chardev/char-mux.c
diff --git a/chardev/char-mux.h b/chardev/char-mux.h
new file mode 100644
index 0000000000..9a2fffce91
--- /dev/null
+++ b/chardev/char-mux.h
@@ -0,0 +1,63 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef CHAR_MUX_H
+#define CHAR_MUX_H
+
+#include "sysemu/char.h"
+
+extern bool muxes_realized;
+
+#define MAX_MUX 4
+#define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */
+#define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1)
+typedef struct MuxChardev {
+ Chardev parent;
+ CharBackend *backends[MAX_MUX];
+ CharBackend chr;
+ int focus;
+ int mux_cnt;
+ int term_got_escape;
+ int max_size;
+ /* Intermediate input buffer catches escape sequences even if the
+ currently active device is not accepting any input - but only until it
+ is full as well. */
+ unsigned char buffer[MAX_MUX][MUX_BUFFER_SIZE];
+ int prod[MAX_MUX];
+ int cons[MAX_MUX];
+ int timestamps;
+
+ /* Protected by the Chardev chr_write_lock. */
+ int linestart;
+ int64_t timestamps_start;
+} MuxChardev;
+
+#define MUX_CHARDEV(obj) OBJECT_CHECK(MuxChardev, (obj), TYPE_CHARDEV_MUX)
+#define CHARDEV_IS_MUX(chr) \
+ object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX)
+
+void mux_chr_set_handlers(Chardev *chr, GMainContext *context);
+void mux_set_focus(Chardev *chr, int focus);
+void mux_chr_send_event(MuxChardev *d, int mux_nr, int event);
+
+#endif /* CHAR_MUX_H */
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 31229deaca..1e1f5c7b2b 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -441,6 +441,7 @@ bool qemu_chr_has_feature(Chardev *chr,
void qemu_chr_set_feature(Chardev *chr,
ChardevFeature feature);
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
+int qemu_chr_write_all(Chardev *s, const uint8_t *buf, int len);
#define TYPE_CHARDEV "chardev"
#define CHARDEV(obj) OBJECT_CHECK(Chardev, (obj), TYPE_CHARDEV)
@@ -463,8 +464,6 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
#define TYPE_CHARDEV_SOCKET "chardev-socket"
#define TYPE_CHARDEV_UDP "chardev-udp"
-#define CHARDEV_IS_MUX(chr) \
- object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX)
#define CHARDEV_IS_RINGBUF(chr) \
object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_RINGBUF)
#define CHARDEV_IS_PTY(chr) \
diff --git a/chardev/char-mux.c b/chardev/char-mux.c
new file mode 100644
index 0000000000..5547a36a0a
--- /dev/null
+++ b/chardev/char-mux.c
@@ -0,0 +1,358 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "sysemu/char.h"
+#include "sysemu/block-backend.h"
+#include "char-mux.h"
+
+/* MUX driver for serial I/O splitting */
+
+/* Called with chr_write_lock held. */
+static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len)
+{
+ MuxChardev *d = MUX_CHARDEV(chr);
+ int ret;
+ if (!d->timestamps) {
+ ret = qemu_chr_fe_write(&d->chr, buf, len);
+ } else {
+ int i;
+
+ ret = 0;
+ for (i = 0; i < len; i++) {
+ if (d->linestart) {
+ char buf1[64];
+ int64_t ti;
+ int secs;
+
+ ti = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
+ if (d->timestamps_start == -1) {
+ d->timestamps_start = ti;
+ }
+ ti -= d->timestamps_start;
+ secs = ti / 1000;
+ snprintf(buf1, sizeof(buf1),
+ "[%02d:%02d:%02d.%03d] ",
+ secs / 3600,
+ (secs / 60) % 60,
+ secs % 60,
+ (int)(ti % 1000));
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_fe_write_all(&d->chr,
+ (uint8_t *)buf1, strlen(buf1));
+ d->linestart = 0;
+ }
+ ret += qemu_chr_fe_write(&d->chr, buf + i, 1);
+ if (buf[i] == '\n') {
+ d->linestart = 1;
+ }
+ }
+ }
+ return ret;
+}
+
+static const char * const mux_help[] = {
+ "% h print this help\n\r",
+ "% x exit emulator\n\r",
+ "% s save disk data back to file (if -snapshot)\n\r",
+ "% t toggle console timestamps\n\r",
+ "% b send break (magic sysrq)\n\r",
+ "% c switch between console and monitor\n\r",
+ "% % sends %\n\r",
+ NULL
+};
+
+int term_escape_char = 0x01; /* ctrl-a is used for escape */
+static void mux_print_help(Chardev *chr)
+{
+ int i, j;
+ char ebuf[15] = "Escape-Char";
+ char cbuf[50] = "\n\r";
+
+ if (term_escape_char > 0 && term_escape_char < 26) {
+ snprintf(cbuf, sizeof(cbuf), "\n\r");
+ snprintf(ebuf, sizeof(ebuf), "C-%c", term_escape_char - 1 + 'a');
+ } else {
+ snprintf(cbuf, sizeof(cbuf),
+ "\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r",
+ term_escape_char);
+ }
+ /* XXX this blocks entire thread. Rewrite to use
+ * qemu_chr_fe_write and background I/O callbacks */
+ qemu_chr_write_all(chr, (uint8_t *)cbuf, strlen(cbuf));
+ for (i = 0; mux_help[i] != NULL; i++) {
+ for (j = 0; mux_help[i][j] != '\0'; j++) {
+ if (mux_help[i][j] == '%') {
+ qemu_chr_write_all(chr, (uint8_t *)ebuf, strlen(ebuf));
+ } else {
+ qemu_chr_write_all(chr, (uint8_t *)&mux_help[i][j], 1);
+ }
+ }
+ }
+}
+
+void mux_chr_send_event(MuxChardev *d, int mux_nr, int event)
+{
+ CharBackend *be = d->backends[mux_nr];
+
+ if (be && be->chr_event) {
+ be->chr_event(be->opaque, event);
+ }
+}
+
+static int mux_proc_byte(Chardev *chr, MuxChardev *d, int ch)
+{
+ if (d->term_got_escape) {
+ d->term_got_escape = 0;
+ if (ch == term_escape_char) {
+ goto send_char;
+ }
+ switch (ch) {
+ case '?':
+ case 'h':
+ mux_print_help(chr);
+ break;
+ case 'x':
+ {
+ const char *term = "QEMU: Terminated\n\r";
+ qemu_chr_write_all(chr, (uint8_t *)term, strlen(term));
+ exit(0);
+ break;
+ }
+ case 's':
+ blk_commit_all();
+ break;
+ case 'b':
+ qemu_chr_be_event(chr, CHR_EVENT_BREAK);
+ break;
+ case 'c':
+ assert(d->mux_cnt > 0); /* handler registered with first fe */
+ /* Switch to the next registered device */
+ mux_set_focus(chr, (d->focus + 1) % d->mux_cnt);
+ break;
+ case 't':
+ d->timestamps = !d->timestamps;
+ d->timestamps_start = -1;
+ d->linestart = 0;
+ break;
+ }
+ } else if (ch == term_escape_char) {
+ d->term_got_escape = 1;
+ } else {
+ send_char:
+ return 1;
+ }
+ return 0;
+}
+
+static void mux_chr_accept_input(Chardev *chr)
+{
+ MuxChardev *d = MUX_CHARDEV(chr);
+ int m = d->focus;
+ CharBackend *be = d->backends[m];
+
+ while (be && d->prod[m] != d->cons[m] &&
+ be->chr_can_read && be->chr_can_read(be->opaque)) {
+ be->chr_read(be->opaque,
+ &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1);
+ }
+}
+
+static int mux_chr_can_read(void *opaque)
+{
+ MuxChardev *d = MUX_CHARDEV(opaque);
+ int m = d->focus;
+ CharBackend *be = d->backends[m];
+
+ if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE) {
+ return 1;
+ }
+
+ if (be && be->chr_can_read) {
+ return be->chr_can_read(be->opaque);
+ }
+
+ return 0;
+}
+
+static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
+{
+ Chardev *chr = CHARDEV(opaque);
+ MuxChardev *d = MUX_CHARDEV(opaque);
+ int m = d->focus;
+ CharBackend *be = d->backends[m];
+ int i;
+
+ mux_chr_accept_input(opaque);
+
+ for (i = 0; i < size; i++)
+ if (mux_proc_byte(chr, d, buf[i])) {
+ if (d->prod[m] == d->cons[m] &&
+ be && be->chr_can_read &&
+ be->chr_can_read(be->opaque)) {
+ be->chr_read(be->opaque, &buf[i], 1);
+ } else {
+ d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK] = buf[i];
+ }
+ }
+}
+
+bool muxes_realized;
+
+static void mux_chr_event(void *opaque, int event)
+{
+ MuxChardev *d = MUX_CHARDEV(opaque);
+ int i;
+
+ if (!muxes_realized) {
+ return;
+ }
+
+ /* Send the event to all registered listeners */
+ for (i = 0; i < d->mux_cnt; i++) {
+ mux_chr_send_event(d, i, event);
+ }
+}
+
+static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond)
+{
+ MuxChardev *d = MUX_CHARDEV(s);
+ Chardev *chr = qemu_chr_fe_get_driver(&d->chr);
+ ChardevClass *cc = CHARDEV_GET_CLASS(chr);
+
+ if (!cc->chr_add_watch) {
+ return NULL;
+ }
+
+ return cc->chr_add_watch(chr, cond);
+}
+
+static void char_mux_finalize(Object *obj)
+{
+ MuxChardev *d = MUX_CHARDEV(obj);
+ int i;
+
+ for (i = 0; i < d->mux_cnt; i++) {
+ CharBackend *be = d->backends[i];
+ if (be) {
+ be->chr = NULL;
+ }
+ }
+ qemu_chr_fe_deinit(&d->chr);
+}
+
+void mux_chr_set_handlers(Chardev *chr, GMainContext *context)
+{
+ MuxChardev *d = MUX_CHARDEV(chr);
+
+ /* Fix up the real driver with mux routines */
+ qemu_chr_fe_set_handlers(&d->chr,
+ mux_chr_can_read,
+ mux_chr_read,
+ mux_chr_event,
+ chr,
+ context, true);
+}
+
+void mux_set_focus(Chardev *chr, int focus)
+{
+ MuxChardev *d = MUX_CHARDEV(chr);
+
+ assert(focus >= 0);
+ assert(focus < d->mux_cnt);
+
+ if (d->focus != -1) {
+ mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
+ }
+
+ d->focus = focus;
+ mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
+}
+
+static void qemu_chr_open_mux(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ ChardevMux *mux = backend->u.mux.data;
+ Chardev *drv;
+ MuxChardev *d = MUX_CHARDEV(chr);
+
+ drv = qemu_chr_find(mux->chardev);
+ if (drv == NULL) {
+ error_setg(errp, "mux: base chardev %s not found", mux->chardev);
+ return;
+ }
+
+ d->focus = -1;
+ /* only default to opened state if we've realized the initial
+ * set of muxes
+ */
+ *be_opened = muxes_realized;
+ qemu_chr_fe_init(&d->chr, drv, errp);
+}
+
+static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
+{
+ const char *chardev = qemu_opt_get(opts, "chardev");
+ ChardevMux *mux;
+
+ if (chardev == NULL) {
+ error_setg(errp, "chardev: mux: no chardev given");
+ return;
+ }
+ backend->type = CHARDEV_BACKEND_KIND_MUX;
+ mux = backend->u.mux.data = g_new0(ChardevMux, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevMux_base(mux));
+ mux->chardev = g_strdup(chardev);
+}
+
+static void char_mux_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->parse = qemu_chr_parse_mux;
+ cc->open = qemu_chr_open_mux;
+ cc->chr_write = mux_chr_write;
+ cc->chr_accept_input = mux_chr_accept_input;
+ cc->chr_add_watch = mux_chr_add_watch;
+}
+
+static const TypeInfo char_mux_type_info = {
+ .name = TYPE_CHARDEV_MUX,
+ .parent = TYPE_CHARDEV,
+ .class_init = char_mux_class_init,
+ .instance_size = sizeof(MuxChardev),
+ .instance_finalize = char_mux_finalize,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_mux_type_info);
+}
+
+type_init(register_types);
diff --git a/chardev/char.c b/chardev/char.c
index 2ca6c7cf67..c8d03776b1 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -85,12 +85,12 @@
#include "qemu/sockets.h"
#include "ui/qemu-spice.h"
+#include "char-mux.h"
+
#define READ_BUF_LEN 4096
#define READ_RETRIES 10
#define TCP_MAX_FDS 16
-typedef struct MuxChardev MuxChardev;
-
/***********************************************************/
/* Socket address helpers */
@@ -284,7 +284,7 @@ int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len)
return ret;
}
-static int qemu_chr_write_all(Chardev *s, const uint8_t *buf, int len)
+int qemu_chr_write_all(Chardev *s, const uint8_t *buf, int len)
{
int offset;
int res;
@@ -482,8 +482,6 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
}
static void remove_fd_in_watch(Chardev *chr);
-static void mux_chr_set_handlers(Chardev *chr, GMainContext *context);
-static void mux_set_focus(Chardev *chr, int focus);
static void qemu_char_open(Chardev *chr, ChardevBackend *backend,
bool *be_opened, Error **errp)
@@ -560,235 +558,6 @@ static const TypeInfo char_type_info = {
.class_init = char_class_init,
};
-/* MUX driver for serial I/O splitting */
-#define MAX_MUX 4
-#define MUX_BUFFER_SIZE 32 /* Must be a power of 2. */
-#define MUX_BUFFER_MASK (MUX_BUFFER_SIZE - 1)
-struct MuxChardev {
- Chardev parent;
- CharBackend *backends[MAX_MUX];
- CharBackend chr;
- int focus;
- int mux_cnt;
- int term_got_escape;
- int max_size;
- /* Intermediate input buffer allows to catch escape sequences even if the
- currently active device is not accepting any input - but only until it
- is full as well. */
- unsigned char buffer[MAX_MUX][MUX_BUFFER_SIZE];
- int prod[MAX_MUX];
- int cons[MAX_MUX];
- int timestamps;
-
- /* Protected by the Chardev chr_write_lock. */
- int linestart;
- int64_t timestamps_start;
-};
-
-#define MUX_CHARDEV(obj) OBJECT_CHECK(MuxChardev, (obj), TYPE_CHARDEV_MUX)
-
-/* Called with chr_write_lock held. */
-static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len)
-{
- MuxChardev *d = MUX_CHARDEV(chr);
- int ret;
- if (!d->timestamps) {
- ret = qemu_chr_fe_write(&d->chr, buf, len);
- } else {
- int i;
-
- ret = 0;
- for (i = 0; i < len; i++) {
- if (d->linestart) {
- char buf1[64];
- int64_t ti;
- int secs;
-
- ti = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
- if (d->timestamps_start == -1)
- d->timestamps_start = ti;
- ti -= d->timestamps_start;
- secs = ti / 1000;
- snprintf(buf1, sizeof(buf1),
- "[%02d:%02d:%02d.%03d] ",
- secs / 3600,
- (secs / 60) % 60,
- secs % 60,
- (int)(ti % 1000));
- /* XXX this blocks entire thread. Rewrite to use
- * qemu_chr_fe_write and background I/O callbacks */
- qemu_chr_fe_write_all(&d->chr,
- (uint8_t *)buf1, strlen(buf1));
- d->linestart = 0;
- }
- ret += qemu_chr_fe_write(&d->chr, buf + i, 1);
- if (buf[i] == '\n') {
- d->linestart = 1;
- }
- }
- }
- return ret;
-}
-
-static const char * const mux_help[] = {
- "% h print this help\n\r",
- "% x exit emulator\n\r",
- "% s save disk data back to file (if -snapshot)\n\r",
- "% t toggle console timestamps\n\r",
- "% b send break (magic sysrq)\n\r",
- "% c switch between console and monitor\n\r",
- "% % sends %\n\r",
- NULL
-};
-
-int term_escape_char = 0x01; /* ctrl-a is used for escape */
-static void mux_print_help(Chardev *chr)
-{
- int i, j;
- char ebuf[15] = "Escape-Char";
- char cbuf[50] = "\n\r";
-
- if (term_escape_char > 0 && term_escape_char < 26) {
- snprintf(cbuf, sizeof(cbuf), "\n\r");
- snprintf(ebuf, sizeof(ebuf), "C-%c", term_escape_char - 1 + 'a');
- } else {
- snprintf(cbuf, sizeof(cbuf),
- "\n\rEscape-Char set to Ascii: 0x%02x\n\r\n\r",
- term_escape_char);
- }
- /* XXX this blocks entire thread. Rewrite to use
- * qemu_chr_fe_write and background I/O callbacks */
- qemu_chr_write_all(chr, (uint8_t *)cbuf, strlen(cbuf));
- for (i = 0; mux_help[i] != NULL; i++) {
- for (j=0; mux_help[i][j] != '\0'; j++) {
- if (mux_help[i][j] == '%')
- qemu_chr_write_all(chr, (uint8_t *)ebuf, strlen(ebuf));
- else
- qemu_chr_write_all(chr, (uint8_t *)&mux_help[i][j], 1);
- }
- }
-}
-
-static void mux_chr_send_event(MuxChardev *d, int mux_nr, int event)
-{
- CharBackend *be = d->backends[mux_nr];
-
- if (be && be->chr_event) {
- be->chr_event(be->opaque, event);
- }
-}
-
-static int mux_proc_byte(Chardev *chr, MuxChardev *d, int ch)
-{
- if (d->term_got_escape) {
- d->term_got_escape = 0;
- if (ch == term_escape_char)
- goto send_char;
- switch(ch) {
- case '?':
- case 'h':
- mux_print_help(chr);
- break;
- case 'x':
- {
- const char *term = "QEMU: Terminated\n\r";
- qemu_chr_write_all(chr, (uint8_t *)term, strlen(term));
- exit(0);
- break;
- }
- case 's':
- blk_commit_all();
- break;
- case 'b':
- qemu_chr_be_event(chr, CHR_EVENT_BREAK);
- break;
- case 'c':
- assert(d->mux_cnt > 0); /* handler registered with first fe */
- /* Switch to the next registered device */
- mux_set_focus(chr, (d->focus + 1) % d->mux_cnt);
- break;
- case 't':
- d->timestamps = !d->timestamps;
- d->timestamps_start = -1;
- d->linestart = 0;
- break;
- }
- } else if (ch == term_escape_char) {
- d->term_got_escape = 1;
- } else {
- send_char:
- return 1;
- }
- return 0;
-}
-
-static void mux_chr_accept_input(Chardev *chr)
-{
- MuxChardev *d = MUX_CHARDEV(chr);
- int m = d->focus;
- CharBackend *be = d->backends[m];
-
- while (be && d->prod[m] != d->cons[m] &&
- be->chr_can_read && be->chr_can_read(be->opaque)) {
- be->chr_read(be->opaque,
- &d->buffer[m][d->cons[m]++ & MUX_BUFFER_MASK], 1);
- }
-}
-
-static int mux_chr_can_read(void *opaque)
-{
- MuxChardev *d = MUX_CHARDEV(opaque);
- int m = d->focus;
- CharBackend *be = d->backends[m];
-
- if ((d->prod[m] - d->cons[m]) < MUX_BUFFER_SIZE) {
- return 1;
- }
-
- if (be && be->chr_can_read) {
- return be->chr_can_read(be->opaque);
- }
-
- return 0;
-}
-
-static void mux_chr_read(void *opaque, const uint8_t *buf, int size)
-{
- Chardev *chr = CHARDEV(opaque);
- MuxChardev *d = MUX_CHARDEV(opaque);
- int m = d->focus;
- CharBackend *be = d->backends[m];
- int i;
-
- mux_chr_accept_input(opaque);
-
- for (i = 0; i < size; i++)
- if (mux_proc_byte(chr, d, buf[i])) {
- if (d->prod[m] == d->cons[m] &&
- be && be->chr_can_read &&
- be->chr_can_read(be->opaque))
- be->chr_read(be->opaque, &buf[i], 1);
- else
- d->buffer[m][d->prod[m]++ & MUX_BUFFER_MASK] = buf[i];
- }
-}
-
-static bool muxes_realized;
-
-static void mux_chr_event(void *opaque, int event)
-{
- MuxChardev *d = MUX_CHARDEV(opaque);
- int i;
-
- if (!muxes_realized) {
- return;
- }
-
- /* Send the event to all registered listeners */
- for (i = 0; i < d->mux_cnt; i++)
- mux_chr_send_event(d, i, event);
-}
-
/**
* Called after processing of default and command-line-specified
* chardevs to deliver CHR_EVENT_OPENED events to any FEs attached
@@ -827,85 +596,6 @@ static Notifier muxes_realize_notify = {
.notify = muxes_realize_done,
};
-static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond)
-{
- MuxChardev *d = MUX_CHARDEV(s);
- Chardev *chr = qemu_chr_fe_get_driver(&d->chr);
- ChardevClass *cc = CHARDEV_GET_CLASS(chr);
-
- if (!cc->chr_add_watch) {
- return NULL;
- }
-
- return cc->chr_add_watch(chr, cond);
-}
-
-static void char_mux_finalize(Object *obj)
-{
- MuxChardev *d = MUX_CHARDEV(obj);
- int i;
-
- for (i = 0; i < d->mux_cnt; i++) {
- CharBackend *be = d->backends[i];
- if (be) {
- be->chr = NULL;
- }
- }
- qemu_chr_fe_deinit(&d->chr);
-}
-
-static void mux_chr_set_handlers(Chardev *chr, GMainContext *context)
-{
- MuxChardev *d = MUX_CHARDEV(chr);
-
- /* Fix up the real driver with mux routines */
- qemu_chr_fe_set_handlers(&d->chr,
- mux_chr_can_read,
- mux_chr_read,
- mux_chr_event,
- chr,
- context, true);
-}
-
-static void mux_set_focus(Chardev *chr, int focus)
-{
- MuxChardev *d = MUX_CHARDEV(chr);
-
- assert(focus >= 0);
- assert(focus < d->mux_cnt);
-
- if (d->focus != -1) {
- mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT);
- }
-
- d->focus = focus;
- chr->be = d->backends[focus];
- mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN);
-}
-
-static void qemu_chr_open_mux(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- ChardevMux *mux = backend->u.mux.data;
- Chardev *drv;
- MuxChardev *d = MUX_CHARDEV(chr);
-
- drv = qemu_chr_find(mux->chardev);
- if (drv == NULL) {
- error_setg(errp, "mux: base chardev %s not found", mux->chardev);
- return;
- }
-
- d->focus = -1;
- /* only default to opened state if we've realized the initial
- * set of muxes
- */
- *be_opened = muxes_realized;
- qemu_chr_fe_init(&d->chr, drv, errp);
-}
-
Chardev *qemu_chr_fe_get_driver(CharBackend *be)
{
return be->chr;
@@ -3950,41 +3640,6 @@ static const TypeInfo char_memory_type_info = {
.parent = TYPE_CHARDEV_RINGBUF,
};
-static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend,
- Error **errp)
-{
- const char *chardev = qemu_opt_get(opts, "chardev");
- ChardevMux *mux;
-
- backend->type = CHARDEV_BACKEND_KIND_MUX;
- if (chardev == NULL) {
- error_setg(errp, "chardev: mux: no chardev given");
- return;
- }
- mux = backend->u.mux.data = g_new0(ChardevMux, 1);
- qemu_chr_parse_common(opts, qapi_ChardevMux_base(mux));
- mux->chardev = g_strdup(chardev);
-}
-
-static void char_mux_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->parse = qemu_chr_parse_mux;
- cc->open = qemu_chr_open_mux;
- cc->chr_write = mux_chr_write;
- cc->chr_accept_input = mux_chr_accept_input;
- cc->chr_add_watch = mux_chr_add_watch;
-}
-
-static const TypeInfo char_mux_type_info = {
- .name = TYPE_CHARDEV_MUX,
- .parent = TYPE_CHARDEV,
- .class_init = char_mux_class_init,
- .instance_size = sizeof(MuxChardev),
- .instance_finalize = char_mux_finalize,
-};
-
static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
{
@@ -5101,7 +4756,6 @@ static void register_types(void)
type_register_static(&char_console_type_info);
#endif
type_register_static(&char_pipe_type_info);
- type_register_static(&char_mux_type_info);
type_register_static(&char_memory_type_info);
/* this must be done after machine init, since we register FEs with muxes
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index be7ff800c3..f1ccc40ae1 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -1,2 +1,3 @@
chardev-obj-y += char.o
+chardev-obj-y += char-mux.o
chardev-obj-y += char-null.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 25/41] char: move ringbuf/memory to its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (23 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 24/41] char: move mux " Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 26/41] char: rename and move to header CHR_READ_BUF_LEN Marc-André Lureau
` (17 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
chardev/char-ringbuf.c | 249 +++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 218 -------------------------------------------
chardev/Makefile.objs | 1 +
3 files changed, 250 insertions(+), 218 deletions(-)
create mode 100644 chardev/char-ringbuf.c
diff --git a/chardev/char-ringbuf.c b/chardev/char-ringbuf.c
new file mode 100644
index 0000000000..d130069e88
--- /dev/null
+++ b/chardev/char-ringbuf.c
@@ -0,0 +1,249 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "sysemu/char.h"
+#include "qmp-commands.h"
+#include "qemu/base64.h"
+
+/* Ring buffer chardev */
+
+typedef struct {
+ Chardev parent;
+ size_t size;
+ size_t prod;
+ size_t cons;
+ uint8_t *cbuf;
+} RingBufChardev;
+
+#define RINGBUF_CHARDEV(obj) \
+ OBJECT_CHECK(RingBufChardev, (obj), TYPE_CHARDEV_RINGBUF)
+
+static size_t ringbuf_count(const Chardev *chr)
+{
+ const RingBufChardev *d = RINGBUF_CHARDEV(chr);
+
+ return d->prod - d->cons;
+}
+
+static int ringbuf_chr_write(Chardev *chr, const uint8_t *buf, int len)
+{
+ RingBufChardev *d = RINGBUF_CHARDEV(chr);
+ int i;
+
+ if (!buf || (len < 0)) {
+ return -1;
+ }
+
+ for (i = 0; i < len; i++) {
+ d->cbuf[d->prod++ & (d->size - 1)] = buf[i];
+ if (d->prod - d->cons > d->size) {
+ d->cons = d->prod - d->size;
+ }
+ }
+
+ return len;
+}
+
+static int ringbuf_chr_read(Chardev *chr, uint8_t *buf, int len)
+{
+ RingBufChardev *d = RINGBUF_CHARDEV(chr);
+ int i;
+
+ qemu_mutex_lock(&chr->chr_write_lock);
+ for (i = 0; i < len && d->cons != d->prod; i++) {
+ buf[i] = d->cbuf[d->cons++ & (d->size - 1)];
+ }
+ qemu_mutex_unlock(&chr->chr_write_lock);
+
+ return i;
+}
+
+static void char_ringbuf_finalize(Object *obj)
+{
+ RingBufChardev *d = RINGBUF_CHARDEV(obj);
+
+ g_free(d->cbuf);
+}
+
+static void qemu_chr_open_ringbuf(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ ChardevRingbuf *opts = backend->u.ringbuf.data;
+ RingBufChardev *d = RINGBUF_CHARDEV(chr);
+
+ d->size = opts->has_size ? opts->size : 65536;
+
+ /* The size must be power of 2 */
+ if (d->size & (d->size - 1)) {
+ error_setg(errp, "size of ringbuf chardev must be power of two");
+ return;
+ }
+
+ d->prod = 0;
+ d->cons = 0;
+ d->cbuf = g_malloc0(d->size);
+}
+
+void qmp_ringbuf_write(const char *device, const char *data,
+ bool has_format, enum DataFormat format,
+ Error **errp)
+{
+ Chardev *chr;
+ const uint8_t *write_data;
+ int ret;
+ gsize write_count;
+
+ chr = qemu_chr_find(device);
+ if (!chr) {
+ error_setg(errp, "Device '%s' not found", device);
+ return;
+ }
+
+ if (!CHARDEV_IS_RINGBUF(chr)) {
+ error_setg(errp, "%s is not a ringbuf device", device);
+ return;
+ }
+
+ if (has_format && (format == DATA_FORMAT_BASE64)) {
+ write_data = qbase64_decode(data, -1,
+ &write_count,
+ errp);
+ if (!write_data) {
+ return;
+ }
+ } else {
+ write_data = (uint8_t *)data;
+ write_count = strlen(data);
+ }
+
+ ret = ringbuf_chr_write(chr, write_data, write_count);
+
+ if (write_data != (uint8_t *)data) {
+ g_free((void *)write_data);
+ }
+
+ if (ret < 0) {
+ error_setg(errp, "Failed to write to device %s", device);
+ return;
+ }
+}
+
+char *qmp_ringbuf_read(const char *device, int64_t size,
+ bool has_format, enum DataFormat format,
+ Error **errp)
+{
+ Chardev *chr;
+ uint8_t *read_data;
+ size_t count;
+ char *data;
+
+ chr = qemu_chr_find(device);
+ if (!chr) {
+ error_setg(errp, "Device '%s' not found", device);
+ return NULL;
+ }
+
+ if (!CHARDEV_IS_RINGBUF(chr)) {
+ error_setg(errp, "%s is not a ringbuf device", device);
+ return NULL;
+ }
+
+ if (size <= 0) {
+ error_setg(errp, "size must be greater than zero");
+ return NULL;
+ }
+
+ count = ringbuf_count(chr);
+ size = size > count ? count : size;
+ read_data = g_malloc(size + 1);
+
+ ringbuf_chr_read(chr, read_data, size);
+
+ if (has_format && (format == DATA_FORMAT_BASE64)) {
+ data = g_base64_encode(read_data, size);
+ g_free(read_data);
+ } 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;
+ data = (char *)read_data;
+ }
+
+ return data;
+}
+
+static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
+{
+ int val;
+ ChardevRingbuf *ringbuf;
+
+ backend->type = CHARDEV_BACKEND_KIND_RINGBUF;
+ ringbuf = backend->u.ringbuf.data = g_new0(ChardevRingbuf, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevRingbuf_base(ringbuf));
+
+ val = qemu_opt_get_size(opts, "size", 0);
+ if (val != 0) {
+ ringbuf->has_size = true;
+ ringbuf->size = val;
+ }
+}
+
+static void char_ringbuf_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->parse = qemu_chr_parse_ringbuf;
+ cc->open = qemu_chr_open_ringbuf;
+ cc->chr_write = ringbuf_chr_write;
+}
+
+static const TypeInfo char_ringbuf_type_info = {
+ .name = TYPE_CHARDEV_RINGBUF,
+ .parent = TYPE_CHARDEV,
+ .class_init = char_ringbuf_class_init,
+ .instance_size = sizeof(RingBufChardev),
+ .instance_finalize = char_ringbuf_finalize,
+};
+
+/* Bug-compatibility: */
+static const TypeInfo char_memory_type_info = {
+ .name = TYPE_CHARDEV_MEMORY,
+ .parent = TYPE_CHARDEV_RINGBUF,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_ringbuf_type_info);
+ type_register_static(&char_memory_type_info);
+}
+
+type_init(register_types);
diff --git a/chardev/char.c b/chardev/char.c
index c8d03776b1..6b505c6f7d 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -3144,182 +3144,6 @@ static void qemu_chr_socket_connected(QIOTask *task, void *opaque)
}
-/*********************************************************/
-/* Ring buffer chardev */
-
-typedef struct {
- Chardev parent;
- size_t size;
- size_t prod;
- size_t cons;
- uint8_t *cbuf;
-} RingBufChardev;
-
-#define RINGBUF_CHARDEV(obj) \
- OBJECT_CHECK(RingBufChardev, (obj), TYPE_CHARDEV_RINGBUF)
-
-static size_t ringbuf_count(const Chardev *chr)
-{
- const RingBufChardev *d = RINGBUF_CHARDEV(chr);
-
- return d->prod - d->cons;
-}
-
-/* Called with chr_write_lock held. */
-static int ringbuf_chr_write(Chardev *chr, const uint8_t *buf, int len)
-{
- RingBufChardev *d = RINGBUF_CHARDEV(chr);
- int i;
-
- if (!buf || (len < 0)) {
- return -1;
- }
-
- for (i = 0; i < len; i++ ) {
- d->cbuf[d->prod++ & (d->size - 1)] = buf[i];
- if (d->prod - d->cons > d->size) {
- d->cons = d->prod - d->size;
- }
- }
-
- return len;
-}
-
-static int ringbuf_chr_read(Chardev *chr, uint8_t *buf, int len)
-{
- RingBufChardev *d = RINGBUF_CHARDEV(chr);
- int i;
-
- qemu_mutex_lock(&chr->chr_write_lock);
- for (i = 0; i < len && d->cons != d->prod; i++) {
- buf[i] = d->cbuf[d->cons++ & (d->size - 1)];
- }
- qemu_mutex_unlock(&chr->chr_write_lock);
-
- return i;
-}
-
-static void char_ringbuf_finalize(Object *obj)
-{
- RingBufChardev *d = RINGBUF_CHARDEV(obj);
-
- g_free(d->cbuf);
-}
-
-static void qemu_chr_open_ringbuf(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- ChardevRingbuf *opts = backend->u.ringbuf.data;
- RingBufChardev *d = RINGBUF_CHARDEV(chr);
-
- d->size = opts->has_size ? opts->size : 65536;
-
- /* The size must be power of 2 */
- if (d->size & (d->size - 1)) {
- error_setg(errp, "size of ringbuf chardev must be power of two");
- return;
- }
-
- d->prod = 0;
- d->cons = 0;
- d->cbuf = g_malloc0(d->size);
-}
-
-void qmp_ringbuf_write(const char *device, const char *data,
- bool has_format, enum DataFormat format,
- Error **errp)
-{
- Chardev *chr;
- const uint8_t *write_data;
- int ret;
- gsize write_count;
-
- chr = qemu_chr_find(device);
- if (!chr) {
- error_setg(errp, "Device '%s' not found", device);
- return;
- }
-
- if (!CHARDEV_IS_RINGBUF(chr)) {
- error_setg(errp,"%s is not a ringbuf device", device);
- return;
- }
-
- if (has_format && (format == DATA_FORMAT_BASE64)) {
- write_data = qbase64_decode(data, -1,
- &write_count,
- errp);
- if (!write_data) {
- return;
- }
- } else {
- write_data = (uint8_t *)data;
- write_count = strlen(data);
- }
-
- ret = ringbuf_chr_write(chr, write_data, write_count);
-
- if (write_data != (uint8_t *)data) {
- g_free((void *)write_data);
- }
-
- if (ret < 0) {
- error_setg(errp, "Failed to write to device %s", device);
- return;
- }
-}
-
-char *qmp_ringbuf_read(const char *device, int64_t size,
- bool has_format, enum DataFormat format,
- Error **errp)
-{
- Chardev *chr;
- uint8_t *read_data;
- size_t count;
- char *data;
-
- chr = qemu_chr_find(device);
- if (!chr) {
- error_setg(errp, "Device '%s' not found", device);
- return NULL;
- }
-
- if (!CHARDEV_IS_RINGBUF(chr)) {
- error_setg(errp,"%s is not a ringbuf device", device);
- return NULL;
- }
-
- if (size <= 0) {
- error_setg(errp, "size must be greater than zero");
- return NULL;
- }
-
- count = ringbuf_count(chr);
- size = size > count ? count : size;
- read_data = g_malloc(size + 1);
-
- ringbuf_chr_read(chr, read_data, size);
-
- if (has_format && (format == DATA_FORMAT_BASE64)) {
- data = g_base64_encode(read_data, size);
- g_free(read_data);
- } 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;
- data = (char *)read_data;
- }
-
- return data;
-}
-
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
{
char host[65], port[33], width[8], height[8];
@@ -3600,46 +3424,6 @@ static const TypeInfo char_pipe_type_info = {
.class_init = char_pipe_class_init,
};
-static void qemu_chr_parse_ringbuf(QemuOpts *opts, ChardevBackend *backend,
- Error **errp)
-{
- int val;
- ChardevRingbuf *ringbuf;
-
- backend->type = CHARDEV_BACKEND_KIND_RINGBUF;
- ringbuf = backend->u.ringbuf.data = g_new0(ChardevRingbuf, 1);
- qemu_chr_parse_common(opts, qapi_ChardevRingbuf_base(ringbuf));
-
- val = qemu_opt_get_size(opts, "size", 0);
- if (val != 0) {
- ringbuf->has_size = true;
- ringbuf->size = val;
- }
-}
-
-static void char_ringbuf_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->parse = qemu_chr_parse_ringbuf;
- cc->open = qemu_chr_open_ringbuf;
- cc->chr_write = ringbuf_chr_write;
-}
-
-static const TypeInfo char_ringbuf_type_info = {
- .name = TYPE_CHARDEV_RINGBUF,
- .parent = TYPE_CHARDEV,
- .class_init = char_ringbuf_class_init,
- .instance_size = sizeof(RingBufChardev),
- .instance_finalize = char_ringbuf_finalize,
-};
-
-/* Bug-compatibility: */
-static const TypeInfo char_memory_type_info = {
- .name = TYPE_CHARDEV_MEMORY,
- .parent = TYPE_CHARDEV_RINGBUF,
-};
-
static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
{
@@ -4740,7 +4524,6 @@ static void register_types(void)
#endif
type_register_static(&char_socket_type_info);
type_register_static(&char_udp_type_info);
- type_register_static(&char_ringbuf_type_info);
type_register_static(&char_file_type_info);
type_register_static(&char_stdio_type_info);
#ifdef HAVE_CHARDEV_SERIAL
@@ -4756,7 +4539,6 @@ static void register_types(void)
type_register_static(&char_console_type_info);
#endif
type_register_static(&char_pipe_type_info);
- type_register_static(&char_memory_type_info);
/* this must be done after machine init, since we register FEs with muxes
* as part of realize functions like serial_isa_realizefn when -nographic
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index f1ccc40ae1..d4ffb8d70e 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -1,3 +1,4 @@
chardev-obj-y += char.o
chardev-obj-y += char-mux.o
chardev-obj-y += char-null.o
+chardev-obj-y += char-ringbuf.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 26/41] char: rename and move to header CHR_READ_BUF_LEN
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (24 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 25/41] char: move ringbuf/memory " Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 27/41] char: remove unused READ_RETRIES Marc-André Lureau
` (16 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
This define is used by several character devices, place it in char
common header.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
include/sysemu/char.h | 1 +
chardev/char.c | 13 ++++++-------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 1e1f5c7b2b..1a65798e3e 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -22,6 +22,7 @@ typedef enum {
CHR_EVENT_CLOSED /* connection closed */
} QEMUChrEvent;
+#define CHR_READ_BUF_LEN 4096
#define CHR_IOCTL_SERIAL_SET_PARAMS 1
typedef struct {
diff --git a/chardev/char.c b/chardev/char.c
index 6b505c6f7d..6d0d5e722b 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -87,7 +87,6 @@
#include "char-mux.h"
-#define READ_BUF_LEN 4096
#define READ_RETRIES 10
#define TCP_MAX_FDS 16
@@ -471,7 +470,7 @@ void qemu_chr_fe_accept_input(CharBackend *be)
void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
{
- char buf[READ_BUF_LEN];
+ char buf[CHR_READ_BUF_LEN];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
@@ -913,7 +912,7 @@ static gboolean fd_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
Chardev *chr = CHARDEV(opaque);
FDChardev *s = FD_CHARDEV(opaque);
int len;
- uint8_t buf[READ_BUF_LEN];
+ uint8_t buf[CHR_READ_BUF_LEN];
ssize_t ret;
len = sizeof(buf);
@@ -1265,7 +1264,7 @@ static gboolean pty_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
Chardev *chr = CHARDEV(opaque);
PtyChardev *s = PTY_CHARDEV(opaque);
gsize len;
- uint8_t buf[READ_BUF_LEN];
+ uint8_t buf[CHR_READ_BUF_LEN];
ssize_t ret;
len = sizeof(buf);
@@ -1952,7 +1951,7 @@ static void win_chr_readfile(Chardev *chr)
WinChardev *s = WIN_CHARDEV(chr);
int ret, err;
- uint8_t buf[READ_BUF_LEN];
+ uint8_t buf[CHR_READ_BUF_LEN];
DWORD size;
ZeroMemory(&s->orecv, sizeof(s->orecv));
@@ -2354,7 +2353,7 @@ err1:
typedef struct {
Chardev parent;
QIOChannel *ioc;
- uint8_t buf[READ_BUF_LEN];
+ uint8_t buf[CHR_READ_BUF_LEN];
int bufcnt;
int bufptr;
int max_size;
@@ -2759,7 +2758,7 @@ static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
{
Chardev *chr = CHARDEV(opaque);
SocketChardev *s = SOCKET_CHARDEV(opaque);
- uint8_t buf[READ_BUF_LEN];
+ uint8_t buf[CHR_READ_BUF_LEN];
int len, size;
if (!s->connected || s->max_size <= 0) {
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 27/41] char: remove unused READ_RETRIES
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (25 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 26/41] char: rename and move to header CHR_READ_BUF_LEN Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 28/41] char: move QIOChannel-related stuff to char-io.h Marc-André Lureau
` (15 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Curiously unused since its introduction in commit 7b0bfdf52d69.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
chardev/char.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/chardev/char.c b/chardev/char.c
index 6d0d5e722b..722c98dc33 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -87,7 +87,6 @@
#include "char-mux.h"
-#define READ_RETRIES 10
#define TCP_MAX_FDS 16
/***********************************************************/
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 28/41] char: move QIOChannel-related stuff to char-io.h
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (26 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 27/41] char: remove unused READ_RETRIES Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 29/41] char: move fd chardev in its own file Marc-André Lureau
` (14 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
chardev/char-io.h | 46 ++++++++++++
chardev/char-io.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 174 +--------------------------------------------
chardev/Makefile.objs | 1 +
4 files changed, 240 insertions(+), 173 deletions(-)
create mode 100644 chardev/char-io.h
create mode 100644 chardev/char-io.c
diff --git a/chardev/char-io.h b/chardev/char-io.h
new file mode 100644
index 0000000000..d7ae5f1585
--- /dev/null
+++ b/chardev/char-io.h
@@ -0,0 +1,46 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef CHAR_IO_H
+#define CHAR_IO_H
+
+#include "qemu-common.h"
+#include "io/channel.h"
+#include "sysemu/char.h"
+
+/* Can only be used for read */
+guint io_add_watch_poll(Chardev *chr,
+ QIOChannel *ioc,
+ IOCanReadHandler *fd_can_read,
+ QIOChannelFunc fd_read,
+ gpointer user_data,
+ GMainContext *context);
+
+void remove_fd_in_watch(Chardev *chr);
+
+int io_channel_send(QIOChannel *ioc, const void *buf, size_t len);
+
+int io_channel_send_full(QIOChannel *ioc, const void *buf, size_t len,
+ int *fds, size_t nfds);
+
+#endif /* CHAR_IO_H */
diff --git a/chardev/char-io.c b/chardev/char-io.c
new file mode 100644
index 0000000000..7dfc3f22ba
--- /dev/null
+++ b/chardev/char-io.c
@@ -0,0 +1,192 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "char-io.h"
+
+typedef struct IOWatchPoll {
+ GSource parent;
+
+ QIOChannel *ioc;
+ GSource *src;
+
+ IOCanReadHandler *fd_can_read;
+ GSourceFunc fd_read;
+ void *opaque;
+ GMainContext *context;
+} IOWatchPoll;
+
+static IOWatchPoll *io_watch_poll_from_source(GSource *source)
+{
+ return container_of(source, IOWatchPoll, parent);
+}
+
+static gboolean io_watch_poll_prepare(GSource *source,
+ gint *timeout)
+{
+ IOWatchPoll *iwp = io_watch_poll_from_source(source);
+ bool now_active = iwp->fd_can_read(iwp->opaque) > 0;
+ bool was_active = iwp->src != NULL;
+ if (was_active == now_active) {
+ return FALSE;
+ }
+
+ if (now_active) {
+ iwp->src = qio_channel_create_watch(
+ iwp->ioc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL);
+ g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL);
+ g_source_attach(iwp->src, iwp->context);
+ } else {
+ g_source_destroy(iwp->src);
+ g_source_unref(iwp->src);
+ iwp->src = NULL;
+ }
+ return FALSE;
+}
+
+static gboolean io_watch_poll_check(GSource *source)
+{
+ return FALSE;
+}
+
+static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback,
+ gpointer user_data)
+{
+ abort();
+}
+
+static void io_watch_poll_finalize(GSource *source)
+{
+ /* Due to a glib bug, removing the last reference to a source
+ * inside a finalize callback causes recursive locking (and a
+ * deadlock). This is not a problem inside other callbacks,
+ * including dispatch callbacks, so we call io_remove_watch_poll
+ * to remove this source. At this point, iwp->src must
+ * be NULL, or we would leak it.
+ *
+ * This would be solved much more elegantly by child sources,
+ * but we support older glib versions that do not have them.
+ */
+ IOWatchPoll *iwp = io_watch_poll_from_source(source);
+ assert(iwp->src == NULL);
+}
+
+static GSourceFuncs io_watch_poll_funcs = {
+ .prepare = io_watch_poll_prepare,
+ .check = io_watch_poll_check,
+ .dispatch = io_watch_poll_dispatch,
+ .finalize = io_watch_poll_finalize,
+};
+
+guint io_add_watch_poll(Chardev *chr,
+ QIOChannel *ioc,
+ IOCanReadHandler *fd_can_read,
+ QIOChannelFunc fd_read,
+ gpointer user_data,
+ GMainContext *context)
+{
+ IOWatchPoll *iwp;
+ int tag;
+ char *name;
+
+ iwp = (IOWatchPoll *) g_source_new(&io_watch_poll_funcs,
+ sizeof(IOWatchPoll));
+ iwp->fd_can_read = fd_can_read;
+ iwp->opaque = user_data;
+ iwp->ioc = ioc;
+ iwp->fd_read = (GSourceFunc) fd_read;
+ iwp->src = NULL;
+ iwp->context = context;
+
+ name = g_strdup_printf("chardev-iowatch-%s", chr->label);
+ g_source_set_name((GSource *)iwp, name);
+ g_free(name);
+
+ tag = g_source_attach(&iwp->parent, context);
+ g_source_unref(&iwp->parent);
+ return tag;
+}
+
+static void io_remove_watch_poll(guint tag)
+{
+ GSource *source;
+ IOWatchPoll *iwp;
+
+ g_return_if_fail(tag > 0);
+
+ source = g_main_context_find_source_by_id(NULL, tag);
+ g_return_if_fail(source != NULL);
+
+ iwp = io_watch_poll_from_source(source);
+ if (iwp->src) {
+ g_source_destroy(iwp->src);
+ g_source_unref(iwp->src);
+ iwp->src = NULL;
+ }
+ g_source_destroy(&iwp->parent);
+}
+
+void remove_fd_in_watch(Chardev *chr)
+{
+ if (chr->fd_in_tag) {
+ io_remove_watch_poll(chr->fd_in_tag);
+ chr->fd_in_tag = 0;
+ }
+}
+
+int io_channel_send_full(QIOChannel *ioc,
+ const void *buf, size_t len,
+ int *fds, size_t nfds)
+{
+ size_t offset = 0;
+
+ while (offset < len) {
+ ssize_t ret = 0;
+ struct iovec iov = { .iov_base = (char *)buf + offset,
+ .iov_len = len - offset };
+
+ ret = qio_channel_writev_full(
+ ioc, &iov, 1,
+ fds, nfds, NULL);
+ if (ret == QIO_CHANNEL_ERR_BLOCK) {
+ if (offset) {
+ return offset;
+ }
+
+ errno = EAGAIN;
+ return -1;
+ } else if (ret < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ offset += ret;
+ }
+
+ return offset;
+}
+
+int io_channel_send(QIOChannel *ioc, const void *buf, size_t len)
+{
+ return io_channel_send_full(ioc, buf, len, NULL, 0);
+}
diff --git a/chardev/char.c b/chardev/char.c
index 722c98dc33..3cbe42a1a8 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -86,6 +86,7 @@
#include "ui/qemu-spice.h"
#include "char-mux.h"
+#include "char-io.h"
#define TCP_MAX_FDS 16
@@ -479,8 +480,6 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
va_end(ap);
}
-static void remove_fd_in_watch(Chardev *chr);
-
static void qemu_char_open(Chardev *chr, ChardevBackend *backend,
bool *be_opened, Error **errp)
{
@@ -716,178 +715,7 @@ void qemu_chr_fe_take_focus(CharBackend *b)
}
}
-typedef struct IOWatchPoll
-{
- GSource parent;
-
- QIOChannel *ioc;
- GSource *src;
-
- IOCanReadHandler *fd_can_read;
- GSourceFunc fd_read;
- void *opaque;
- GMainContext *context;
-} IOWatchPoll;
-
-static IOWatchPoll *io_watch_poll_from_source(GSource *source)
-{
- return container_of(source, IOWatchPoll, parent);
-}
-
-static gboolean io_watch_poll_prepare(GSource *source,
- gint *timeout_)
-{
- IOWatchPoll *iwp = io_watch_poll_from_source(source);
- bool now_active = iwp->fd_can_read(iwp->opaque) > 0;
- bool was_active = iwp->src != NULL;
- if (was_active == now_active) {
- return FALSE;
- }
-
- if (now_active) {
- iwp->src = qio_channel_create_watch(
- iwp->ioc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL);
- g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL);
- g_source_attach(iwp->src, iwp->context);
- } else {
- g_source_destroy(iwp->src);
- g_source_unref(iwp->src);
- iwp->src = NULL;
- }
- return FALSE;
-}
-
-static gboolean io_watch_poll_check(GSource *source)
-{
- return FALSE;
-}
-
-static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback,
- gpointer user_data)
-{
- abort();
-}
-
-static void io_watch_poll_finalize(GSource *source)
-{
- /* Due to a glib bug, removing the last reference to a source
- * inside a finalize callback causes recursive locking (and a
- * deadlock). This is not a problem inside other callbacks,
- * including dispatch callbacks, so we call io_remove_watch_poll
- * to remove this source. At this point, iwp->src must
- * be NULL, or we would leak it.
- *
- * This would be solved much more elegantly by child sources,
- * but we support older glib versions that do not have them.
- */
- IOWatchPoll *iwp = io_watch_poll_from_source(source);
- assert(iwp->src == NULL);
-}
-
-static GSourceFuncs io_watch_poll_funcs = {
- .prepare = io_watch_poll_prepare,
- .check = io_watch_poll_check,
- .dispatch = io_watch_poll_dispatch,
- .finalize = io_watch_poll_finalize,
-};
-
-/* Can only be used for read */
-static guint io_add_watch_poll(Chardev *chr,
- QIOChannel *ioc,
- IOCanReadHandler *fd_can_read,
- QIOChannelFunc fd_read,
- gpointer user_data,
- GMainContext *context)
-{
- IOWatchPoll *iwp;
- int tag;
- char *name;
-
- iwp = (IOWatchPoll *) g_source_new(&io_watch_poll_funcs,
- sizeof(IOWatchPoll));
- iwp->fd_can_read = fd_can_read;
- iwp->opaque = user_data;
- iwp->ioc = ioc;
- iwp->fd_read = (GSourceFunc) fd_read;
- iwp->src = NULL;
- iwp->context = context;
-
- name = g_strdup_printf("chardev-iowatch-%s", chr->label);
- g_source_set_name((GSource *)iwp, name);
- g_free(name);
-
- tag = g_source_attach(&iwp->parent, context);
- g_source_unref(&iwp->parent);
- return tag;
-}
-
-static void io_remove_watch_poll(guint tag)
-{
- GSource *source;
- IOWatchPoll *iwp;
-
- g_return_if_fail (tag > 0);
-
- source = g_main_context_find_source_by_id(NULL, tag);
- g_return_if_fail (source != NULL);
-
- iwp = io_watch_poll_from_source(source);
- if (iwp->src) {
- g_source_destroy(iwp->src);
- g_source_unref(iwp->src);
- iwp->src = NULL;
- }
- g_source_destroy(&iwp->parent);
-}
-
-static void remove_fd_in_watch(Chardev *chr)
-{
- if (chr->fd_in_tag) {
- io_remove_watch_poll(chr->fd_in_tag);
- chr->fd_in_tag = 0;
- }
-}
-
-
-static int io_channel_send_full(QIOChannel *ioc,
- const void *buf, size_t len,
- int *fds, size_t nfds)
-{
- size_t offset = 0;
-
- while (offset < len) {
- ssize_t ret = 0;
- struct iovec iov = { .iov_base = (char *)buf + offset,
- .iov_len = len - offset };
-
- ret = qio_channel_writev_full(
- ioc, &iov, 1,
- fds, nfds, NULL);
- if (ret == QIO_CHANNEL_ERR_BLOCK) {
- if (offset) {
- return offset;
- }
-
- errno = EAGAIN;
- return -1;
- } else if (ret < 0) {
- errno = EINVAL;
- return -1;
- }
-
- offset += ret;
- }
-
- return offset;
-}
-
-
#ifndef _WIN32
-static int io_channel_send(QIOChannel *ioc, const void *buf, size_t len)
-{
- return io_channel_send_full(ioc, buf, len, NULL, 0);
-}
-
typedef struct FDChardev {
Chardev parent;
Chardev *chr;
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index d4ffb8d70e..5f5d3716ac 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -1,4 +1,5 @@
chardev-obj-y += char.o
+chardev-obj-y += char-io.o
chardev-obj-y += char-mux.o
chardev-obj-y += char-null.o
chardev-obj-y += char-ringbuf.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 29/41] char: move fd chardev in its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (27 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 28/41] char: move QIOChannel-related stuff to char-io.h Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 30/41] char: move win chardev base class " Marc-André Lureau
` (13 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
---
chardev/char-fd.h | 44 +++++++++++++
chardev/char-fd.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 147 +------------------------------------------
chardev/Makefile.objs | 1 +
4 files changed, 217 insertions(+), 145 deletions(-)
create mode 100644 chardev/char-fd.h
create mode 100644 chardev/char-fd.c
diff --git a/chardev/char-fd.h b/chardev/char-fd.h
new file mode 100644
index 0000000000..d8327982fb
--- /dev/null
+++ b/chardev/char-fd.h
@@ -0,0 +1,44 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef CHAR_FD_H
+#define CHAR_FD_H
+
+#include "io/channel.h"
+#include "sysemu/char.h"
+
+typedef struct FDChardev {
+ Chardev parent;
+ Chardev *chr;
+ QIOChannel *ioc_in, *ioc_out;
+ int max_size;
+} FDChardev;
+
+#define TYPE_CHARDEV_FD "chardev-fd"
+
+#define FD_CHARDEV(obj) OBJECT_CHECK(FDChardev, (obj), TYPE_CHARDEV_FD)
+
+void qemu_chr_open_fd(Chardev *chr, int fd_in, int fd_out);
+int qmp_chardev_open_file_source(char *src, int flags, Error **errp);
+
+#endif /* CHAR_FD_H */
diff --git a/chardev/char-fd.c b/chardev/char-fd.c
new file mode 100644
index 0000000000..fb51ab4234
--- /dev/null
+++ b/chardev/char-fd.c
@@ -0,0 +1,170 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qemu/sockets.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "sysemu/char.h"
+#include "io/channel-file.h"
+
+#include "char-fd.h"
+#include "char-io.h"
+
+/* Called with chr_write_lock held. */
+static int fd_chr_write(Chardev *chr, const uint8_t *buf, int len)
+{
+ FDChardev *s = FD_CHARDEV(chr);
+
+ return io_channel_send(s->ioc_out, buf, len);
+}
+
+static gboolean fd_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ FDChardev *s = FD_CHARDEV(opaque);
+ int len;
+ uint8_t buf[CHR_READ_BUF_LEN];
+ ssize_t ret;
+
+ len = sizeof(buf);
+ if (len > s->max_size) {
+ len = s->max_size;
+ }
+ if (len == 0) {
+ return TRUE;
+ }
+
+ ret = qio_channel_read(
+ chan, (gchar *)buf, len, NULL);
+ if (ret == 0) {
+ remove_fd_in_watch(chr);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+ return FALSE;
+ }
+ if (ret > 0) {
+ qemu_chr_be_write(chr, buf, ret);
+ }
+
+ return TRUE;
+}
+
+static int fd_chr_read_poll(void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ FDChardev *s = FD_CHARDEV(opaque);
+
+ s->max_size = qemu_chr_be_can_write(chr);
+ return s->max_size;
+}
+
+static GSource *fd_chr_add_watch(Chardev *chr, GIOCondition cond)
+{
+ FDChardev *s = FD_CHARDEV(chr);
+ return qio_channel_create_watch(s->ioc_out, cond);
+}
+
+static void fd_chr_update_read_handler(Chardev *chr,
+ GMainContext *context)
+{
+ FDChardev *s = FD_CHARDEV(chr);
+
+ remove_fd_in_watch(chr);
+ if (s->ioc_in) {
+ chr->fd_in_tag = io_add_watch_poll(chr, s->ioc_in,
+ fd_chr_read_poll,
+ fd_chr_read, chr,
+ context);
+ }
+}
+
+static void char_fd_finalize(Object *obj)
+{
+ Chardev *chr = CHARDEV(obj);
+ FDChardev *s = FD_CHARDEV(obj);
+
+ remove_fd_in_watch(chr);
+ if (s->ioc_in) {
+ object_unref(OBJECT(s->ioc_in));
+ }
+ if (s->ioc_out) {
+ object_unref(OBJECT(s->ioc_out));
+ }
+
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+}
+
+int qmp_chardev_open_file_source(char *src, int flags, Error **errp)
+{
+ int fd = -1;
+
+ TFR(fd = qemu_open(src, flags, 0666));
+ if (fd == -1) {
+ error_setg_file_open(errp, errno, src);
+ }
+ return fd;
+}
+
+/* open a character device to a unix fd */
+void qemu_chr_open_fd(Chardev *chr,
+ int fd_in, int fd_out)
+{
+ FDChardev *s = FD_CHARDEV(chr);
+ char *name;
+
+ s->ioc_in = QIO_CHANNEL(qio_channel_file_new_fd(fd_in));
+ name = g_strdup_printf("chardev-file-in-%s", chr->label);
+ qio_channel_set_name(QIO_CHANNEL(s->ioc_in), name);
+ g_free(name);
+ s->ioc_out = QIO_CHANNEL(qio_channel_file_new_fd(fd_out));
+ name = g_strdup_printf("chardev-file-out-%s", chr->label);
+ qio_channel_set_name(QIO_CHANNEL(s->ioc_out), name);
+ g_free(name);
+ qemu_set_nonblock(fd_out);
+ s->chr = chr;
+}
+
+static void char_fd_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->chr_add_watch = fd_chr_add_watch;
+ cc->chr_write = fd_chr_write;
+ cc->chr_update_read_handler = fd_chr_update_read_handler;
+}
+
+static const TypeInfo char_fd_type_info = {
+ .name = TYPE_CHARDEV_FD,
+ .parent = TYPE_CHARDEV,
+ .instance_size = sizeof(FDChardev),
+ .instance_finalize = char_fd_finalize,
+ .class_init = char_fd_class_init,
+ .abstract = true,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_fd_type_info);
+}
+
+type_init(register_types);
diff --git a/chardev/char.c b/chardev/char.c
index 3cbe42a1a8..aad57ac17e 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -86,6 +86,7 @@
#include "ui/qemu-spice.h"
#include "char-mux.h"
+#include "char-fd.h"
#include "char-io.h"
#define TCP_MAX_FDS 16
@@ -716,136 +717,6 @@ void qemu_chr_fe_take_focus(CharBackend *b)
}
#ifndef _WIN32
-typedef struct FDChardev {
- Chardev parent;
- Chardev *chr;
- QIOChannel *ioc_in, *ioc_out;
- int max_size;
-} FDChardev;
-
-#define TYPE_CHARDEV_FD "chardev-fd"
-#define FD_CHARDEV(obj) OBJECT_CHECK(FDChardev, (obj), TYPE_CHARDEV_FD)
-
-/* Called with chr_write_lock held. */
-static int fd_chr_write(Chardev *chr, const uint8_t *buf, int len)
-{
- FDChardev *s = FD_CHARDEV(chr);
-
- return io_channel_send(s->ioc_out, buf, len);
-}
-
-static gboolean fd_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- FDChardev *s = FD_CHARDEV(opaque);
- int len;
- uint8_t buf[CHR_READ_BUF_LEN];
- ssize_t ret;
-
- len = sizeof(buf);
- if (len > s->max_size) {
- len = s->max_size;
- }
- if (len == 0) {
- return TRUE;
- }
-
- ret = qio_channel_read(
- chan, (gchar *)buf, len, NULL);
- if (ret == 0) {
- remove_fd_in_watch(chr);
- qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
- return FALSE;
- }
- if (ret > 0) {
- qemu_chr_be_write(chr, buf, ret);
- }
-
- return TRUE;
-}
-
-static int fd_chr_read_poll(void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- FDChardev *s = FD_CHARDEV(opaque);
-
- s->max_size = qemu_chr_be_can_write(chr);
- return s->max_size;
-}
-
-static GSource *fd_chr_add_watch(Chardev *chr, GIOCondition cond)
-{
- FDChardev *s = FD_CHARDEV(chr);
- return qio_channel_create_watch(s->ioc_out, cond);
-}
-
-static void fd_chr_update_read_handler(Chardev *chr,
- GMainContext *context)
-{
- FDChardev *s = FD_CHARDEV(chr);
-
- remove_fd_in_watch(chr);
- if (s->ioc_in) {
- chr->fd_in_tag = io_add_watch_poll(chr, s->ioc_in,
- fd_chr_read_poll,
- fd_chr_read, chr,
- context);
- }
-}
-
-static void char_fd_finalize(Object *obj)
-{
- Chardev *chr = CHARDEV(obj);
- FDChardev *s = FD_CHARDEV(obj);
-
- remove_fd_in_watch(chr);
- if (s->ioc_in) {
- object_unref(OBJECT(s->ioc_in));
- }
- if (s->ioc_out) {
- object_unref(OBJECT(s->ioc_out));
- }
-
- qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
-}
-
-/* open a character device to a unix fd */
-static void qemu_chr_open_fd(Chardev *chr,
- int fd_in, int fd_out)
-{
- FDChardev *s = FD_CHARDEV(chr);
- char *name;
-
- s->ioc_in = QIO_CHANNEL(qio_channel_file_new_fd(fd_in));
- name = g_strdup_printf("chardev-file-in-%s", chr->label);
- qio_channel_set_name(QIO_CHANNEL(s->ioc_in), name);
- g_free(name);
- s->ioc_out = QIO_CHANNEL(qio_channel_file_new_fd(fd_out));
- name = g_strdup_printf("chardev-file-out-%s", chr->label);
- qio_channel_set_name(QIO_CHANNEL(s->ioc_out), name);
- g_free(name);
- qemu_set_nonblock(fd_out);
- s->chr = chr;
-}
-
-static void char_fd_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->chr_add_watch = fd_chr_add_watch;
- cc->chr_write = fd_chr_write;
- cc->chr_update_read_handler = fd_chr_update_read_handler;
-}
-
-static const TypeInfo char_fd_type_info = {
- .name = TYPE_CHARDEV_FD,
- .parent = TYPE_CHARDEV,
- .instance_size = sizeof(FDChardev),
- .instance_finalize = char_fd_finalize,
- .class_init = char_fd_class_init,
- .abstract = true,
-};
-
static void qemu_chr_open_pipe(Chardev *chr,
ChardevBackend *backend,
bool *be_opened,
@@ -3875,18 +3746,6 @@ static void qmp_chardev_open_serial(Chardev *chr,
#else /* WIN32 */
-static int qmp_chardev_open_file_source(char *src, int flags,
- Error **errp)
-{
- int fd = -1;
-
- TFR(fd = qemu_open(src, flags, 0666));
- if (fd == -1) {
- error_setg_file_open(errp, errno, src);
- }
- return fd;
-}
-
static void qmp_chardev_open_file(Chardev *chr,
ChardevBackend *backend,
bool *be_opened,
@@ -4342,9 +4201,7 @@ void qemu_chr_cleanup(void)
static void register_types(void)
{
type_register_static(&char_type_info);
-#ifndef _WIN32
- type_register_static(&char_fd_type_info);
-#else
+#ifdef _WIN32
type_register_static(&char_win_type_info);
type_register_static(&char_win_stdio_type_info);
#endif
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index 5f5d3716ac..d2f03dc5df 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -1,4 +1,5 @@
chardev-obj-y += char.o
+chardev-obj-$(CONFIG_POSIX) += char-fd.o
chardev-obj-y += char-io.o
chardev-obj-y += char-mux.o
chardev-obj-y += char-null.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 30/41] char: move win chardev base class in its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (28 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 29/41] char: move fd chardev in its own file Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 31/41] char: move win-stdio into " Marc-André Lureau
` (12 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
---
chardev/char-win.h | 53 ++++++++++
chardev/char-win.c | 265 ++++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 253 +----------------------------------------------
chardev/Makefile.objs | 1 +
4 files changed, 322 insertions(+), 250 deletions(-)
create mode 100644 chardev/char-win.h
create mode 100644 chardev/char-win.c
diff --git a/chardev/char-win.h b/chardev/char-win.h
new file mode 100644
index 0000000000..d78a7d7972
--- /dev/null
+++ b/chardev/char-win.h
@@ -0,0 +1,53 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef CHAR_WIN_H
+#define CHAR_WIN_H
+
+#include "sysemu/char.h"
+
+typedef struct {
+ Chardev parent;
+ int max_size;
+ HANDLE hcom, hrecv, hsend;
+ OVERLAPPED orecv;
+ BOOL fpipe;
+ DWORD len;
+
+ /* Protected by the Chardev chr_write_lock. */
+ OVERLAPPED osend;
+ /* FIXME: file/console do not finalize */
+ bool skip_free;
+} WinChardev;
+
+#define NSENDBUF 2048
+#define NRECVBUF 2048
+
+#define TYPE_CHARDEV_WIN "chardev-win"
+#define WIN_CHARDEV(obj) OBJECT_CHECK(WinChardev, (obj), TYPE_CHARDEV_WIN)
+
+void qemu_chr_open_win_file(Chardev *chr, HANDLE fd_out);
+int win_chr_init(Chardev *chr, const char *filename, Error **errp);
+int win_chr_pipe_poll(void *opaque);
+
+#endif /* CHAR_WIN_H */
diff --git a/chardev/char-win.c b/chardev/char-win.c
new file mode 100644
index 0000000000..e4b6957ded
--- /dev/null
+++ b/chardev/char-win.c
@@ -0,0 +1,265 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qapi/error.h"
+#include "char-win.h"
+
+static void win_chr_readfile(Chardev *chr)
+{
+ WinChardev *s = WIN_CHARDEV(chr);
+
+ int ret, err;
+ uint8_t buf[CHR_READ_BUF_LEN];
+ DWORD size;
+
+ ZeroMemory(&s->orecv, sizeof(s->orecv));
+ s->orecv.hEvent = s->hrecv;
+ ret = ReadFile(s->hcom, buf, s->len, &size, &s->orecv);
+ if (!ret) {
+ err = GetLastError();
+ if (err == ERROR_IO_PENDING) {
+ ret = GetOverlappedResult(s->hcom, &s->orecv, &size, TRUE);
+ }
+ }
+
+ if (size > 0) {
+ qemu_chr_be_write(chr, buf, size);
+ }
+}
+
+static void win_chr_read(Chardev *chr)
+{
+ WinChardev *s = WIN_CHARDEV(chr);
+
+ if (s->len > s->max_size) {
+ s->len = s->max_size;
+ }
+ if (s->len == 0) {
+ return;
+ }
+
+ win_chr_readfile(chr);
+}
+
+static int win_chr_read_poll(Chardev *chr)
+{
+ WinChardev *s = WIN_CHARDEV(chr);
+
+ s->max_size = qemu_chr_be_can_write(chr);
+ return s->max_size;
+}
+
+static int win_chr_poll(void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ WinChardev *s = WIN_CHARDEV(opaque);
+ COMSTAT status;
+ DWORD comerr;
+
+ ClearCommError(s->hcom, &comerr, &status);
+ if (status.cbInQue > 0) {
+ s->len = status.cbInQue;
+ win_chr_read_poll(chr);
+ win_chr_read(chr);
+ return 1;
+ }
+ return 0;
+}
+
+int win_chr_init(Chardev *chr, const char *filename, Error **errp)
+{
+ WinChardev *s = WIN_CHARDEV(chr);
+ COMMCONFIG comcfg;
+ COMMTIMEOUTS cto = { 0, 0, 0, 0, 0};
+ COMSTAT comstat;
+ DWORD size;
+ DWORD err;
+
+ s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (!s->hsend) {
+ error_setg(errp, "Failed CreateEvent");
+ goto fail;
+ }
+ s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (!s->hrecv) {
+ error_setg(errp, "Failed CreateEvent");
+ goto fail;
+ }
+
+ s->hcom = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
+ if (s->hcom == INVALID_HANDLE_VALUE) {
+ error_setg(errp, "Failed CreateFile (%lu)", GetLastError());
+ s->hcom = NULL;
+ goto fail;
+ }
+
+ if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) {
+ error_setg(errp, "Failed SetupComm");
+ goto fail;
+ }
+
+ ZeroMemory(&comcfg, sizeof(COMMCONFIG));
+ size = sizeof(COMMCONFIG);
+ GetDefaultCommConfig(filename, &comcfg, &size);
+ comcfg.dcb.DCBlength = sizeof(DCB);
+ CommConfigDialog(filename, NULL, &comcfg);
+
+ if (!SetCommState(s->hcom, &comcfg.dcb)) {
+ error_setg(errp, "Failed SetCommState");
+ goto fail;
+ }
+
+ if (!SetCommMask(s->hcom, EV_ERR)) {
+ error_setg(errp, "Failed SetCommMask");
+ goto fail;
+ }
+
+ cto.ReadIntervalTimeout = MAXDWORD;
+ if (!SetCommTimeouts(s->hcom, &cto)) {
+ error_setg(errp, "Failed SetCommTimeouts");
+ goto fail;
+ }
+
+ if (!ClearCommError(s->hcom, &err, &comstat)) {
+ error_setg(errp, "Failed ClearCommError");
+ goto fail;
+ }
+ qemu_add_polling_cb(win_chr_poll, chr);
+ return 0;
+
+ fail:
+ return -1;
+}
+
+int win_chr_pipe_poll(void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ WinChardev *s = WIN_CHARDEV(opaque);
+ DWORD size;
+
+ PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL);
+ if (size > 0) {
+ s->len = size;
+ win_chr_read_poll(chr);
+ win_chr_read(chr);
+ return 1;
+ }
+ return 0;
+}
+
+/* Called with chr_write_lock held. */
+static int win_chr_write(Chardev *chr, const uint8_t *buf, int len1)
+{
+ WinChardev *s = WIN_CHARDEV(chr);
+ DWORD len, ret, size, err;
+
+ len = len1;
+ ZeroMemory(&s->osend, sizeof(s->osend));
+ s->osend.hEvent = s->hsend;
+ while (len > 0) {
+ if (s->hsend) {
+ ret = WriteFile(s->hcom, buf, len, &size, &s->osend);
+ } else {
+ ret = WriteFile(s->hcom, buf, len, &size, NULL);
+ }
+ if (!ret) {
+ err = GetLastError();
+ if (err == ERROR_IO_PENDING) {
+ ret = GetOverlappedResult(s->hcom, &s->osend, &size, TRUE);
+ if (ret) {
+ buf += size;
+ len -= size;
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ } else {
+ buf += size;
+ len -= size;
+ }
+ }
+ return len1 - len;
+}
+
+static void char_win_finalize(Object *obj)
+{
+ Chardev *chr = CHARDEV(obj);
+ WinChardev *s = WIN_CHARDEV(chr);
+
+ if (s->skip_free) {
+ return;
+ }
+
+ if (s->hsend) {
+ CloseHandle(s->hsend);
+ }
+ if (s->hrecv) {
+ CloseHandle(s->hrecv);
+ }
+ if (s->hcom) {
+ CloseHandle(s->hcom);
+ }
+ if (s->fpipe) {
+ qemu_del_polling_cb(win_chr_pipe_poll, chr);
+ } else {
+ qemu_del_polling_cb(win_chr_poll, chr);
+ }
+
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+}
+
+void qemu_chr_open_win_file(Chardev *chr, HANDLE fd_out)
+{
+ WinChardev *s = WIN_CHARDEV(chr);
+
+ s->skip_free = true;
+ s->hcom = fd_out;
+}
+
+static void char_win_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->chr_write = win_chr_write;
+}
+
+static const TypeInfo char_win_type_info = {
+ .name = TYPE_CHARDEV_WIN,
+ .parent = TYPE_CHARDEV,
+ .instance_size = sizeof(WinChardev),
+ .instance_finalize = char_win_finalize,
+ .class_init = char_win_class_init,
+ .abstract = true,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_win_type_info);
+}
+
+type_init(register_types);
diff --git a/chardev/char.c b/chardev/char.c
index aad57ac17e..b80fcae028 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -88,6 +88,9 @@
#include "char-mux.h"
#include "char-fd.h"
#include "char-io.h"
+#ifdef _WIN32
+#include "char-win.h"
+#endif
#define TCP_MAX_FDS 16
@@ -1473,23 +1476,6 @@ static void qemu_chr_open_pp_fd(Chardev *chr,
typedef struct {
Chardev parent;
- int max_size;
- HANDLE hcom, hrecv, hsend;
- OVERLAPPED orecv;
- BOOL fpipe;
- DWORD len;
-
- /* Protected by the Chardev chr_write_lock. */
- OVERLAPPED osend;
- /* FIXME: file/console do not finalize */
- bool skip_free;
-} WinChardev;
-
-#define TYPE_CHARDEV_WIN "chardev-win"
-#define WIN_CHARDEV(obj) OBJECT_CHECK(WinChardev, (obj), TYPE_CHARDEV_WIN)
-
-typedef struct {
- Chardev parent;
HANDLE hStdIn;
HANDLE hInputReadyEvent;
HANDLE hInputDoneEvent;
@@ -1501,217 +1487,9 @@ typedef struct {
#define WIN_STDIO_CHARDEV(obj) \
OBJECT_CHECK(WinStdioChardev, (obj), TYPE_CHARDEV_WIN_STDIO)
-#define NSENDBUF 2048
-#define NRECVBUF 2048
#define MAXCONNECT 1
#define NTIMEOUT 5000
-static int win_chr_poll(void *opaque);
-static int win_chr_pipe_poll(void *opaque);
-
-static void char_win_finalize(Object *obj)
-{
- Chardev *chr = CHARDEV(obj);
- WinChardev *s = WIN_CHARDEV(chr);
-
- if (s->skip_free) {
- return;
- }
-
- if (s->hsend) {
- CloseHandle(s->hsend);
- }
- if (s->hrecv) {
- CloseHandle(s->hrecv);
- }
- if (s->hcom) {
- CloseHandle(s->hcom);
- }
- if (s->fpipe)
- qemu_del_polling_cb(win_chr_pipe_poll, chr);
- else
- qemu_del_polling_cb(win_chr_poll, chr);
-
- qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
-}
-
-static int win_chr_init(Chardev *chr, const char *filename, Error **errp)
-{
- WinChardev *s = WIN_CHARDEV(chr);
- COMMCONFIG comcfg;
- COMMTIMEOUTS cto = { 0, 0, 0, 0, 0};
- COMSTAT comstat;
- DWORD size;
- DWORD err;
-
- s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (!s->hsend) {
- error_setg(errp, "Failed CreateEvent");
- goto fail;
- }
- s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (!s->hrecv) {
- error_setg(errp, "Failed CreateEvent");
- goto fail;
- }
-
- s->hcom = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL,
- OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
- if (s->hcom == INVALID_HANDLE_VALUE) {
- error_setg(errp, "Failed CreateFile (%lu)", GetLastError());
- s->hcom = NULL;
- goto fail;
- }
-
- if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) {
- error_setg(errp, "Failed SetupComm");
- goto fail;
- }
-
- ZeroMemory(&comcfg, sizeof(COMMCONFIG));
- size = sizeof(COMMCONFIG);
- GetDefaultCommConfig(filename, &comcfg, &size);
- comcfg.dcb.DCBlength = sizeof(DCB);
- CommConfigDialog(filename, NULL, &comcfg);
-
- if (!SetCommState(s->hcom, &comcfg.dcb)) {
- error_setg(errp, "Failed SetCommState");
- goto fail;
- }
-
- if (!SetCommMask(s->hcom, EV_ERR)) {
- error_setg(errp, "Failed SetCommMask");
- goto fail;
- }
-
- cto.ReadIntervalTimeout = MAXDWORD;
- if (!SetCommTimeouts(s->hcom, &cto)) {
- error_setg(errp, "Failed SetCommTimeouts");
- goto fail;
- }
-
- if (!ClearCommError(s->hcom, &err, &comstat)) {
- error_setg(errp, "Failed ClearCommError");
- goto fail;
- }
- qemu_add_polling_cb(win_chr_poll, chr);
- return 0;
-
- fail:
- return -1;
-}
-
-/* Called with chr_write_lock held. */
-static int win_chr_write(Chardev *chr, const uint8_t *buf, int len1)
-{
- WinChardev *s = WIN_CHARDEV(chr);
- DWORD len, ret, size, err;
-
- len = len1;
- ZeroMemory(&s->osend, sizeof(s->osend));
- s->osend.hEvent = s->hsend;
- while (len > 0) {
- if (s->hsend)
- ret = WriteFile(s->hcom, buf, len, &size, &s->osend);
- else
- ret = WriteFile(s->hcom, buf, len, &size, NULL);
- if (!ret) {
- err = GetLastError();
- if (err == ERROR_IO_PENDING) {
- ret = GetOverlappedResult(s->hcom, &s->osend, &size, TRUE);
- if (ret) {
- buf += size;
- len -= size;
- } else {
- break;
- }
- } else {
- break;
- }
- } else {
- buf += size;
- len -= size;
- }
- }
- return len1 - len;
-}
-
-static int win_chr_read_poll(Chardev *chr)
-{
- WinChardev *s = WIN_CHARDEV(chr);
-
- s->max_size = qemu_chr_be_can_write(chr);
- return s->max_size;
-}
-
-static void win_chr_readfile(Chardev *chr)
-{
- WinChardev *s = WIN_CHARDEV(chr);
-
- int ret, err;
- uint8_t buf[CHR_READ_BUF_LEN];
- DWORD size;
-
- ZeroMemory(&s->orecv, sizeof(s->orecv));
- s->orecv.hEvent = s->hrecv;
- ret = ReadFile(s->hcom, buf, s->len, &size, &s->orecv);
- if (!ret) {
- err = GetLastError();
- if (err == ERROR_IO_PENDING) {
- ret = GetOverlappedResult(s->hcom, &s->orecv, &size, TRUE);
- }
- }
-
- if (size > 0) {
- qemu_chr_be_write(chr, buf, size);
- }
-}
-
-static void win_chr_read(Chardev *chr)
-{
- WinChardev *s = WIN_CHARDEV(chr);
-
- if (s->len > s->max_size)
- s->len = s->max_size;
- if (s->len == 0)
- return;
-
- win_chr_readfile(chr);
-}
-
-static int win_chr_poll(void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- WinChardev *s = WIN_CHARDEV(opaque);
- COMSTAT status;
- DWORD comerr;
-
- ClearCommError(s->hcom, &comerr, &status);
- if (status.cbInQue > 0) {
- s->len = status.cbInQue;
- win_chr_read_poll(chr);
- win_chr_read(chr);
- return 1;
- }
- return 0;
-}
-
-static int win_chr_pipe_poll(void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- WinChardev *s = WIN_CHARDEV(opaque);
- DWORD size;
-
- PeekNamedPipe(s->hcom, NULL, 0, NULL, &size, NULL);
- if (size > 0) {
- s->len = size;
- win_chr_read_poll(chr);
- win_chr_read(chr);
- return 1;
- }
- return 0;
-}
-
static int win_chr_pipe_init(Chardev *chr, const char *filename,
Error **errp)
{
@@ -1789,30 +1567,6 @@ static void qemu_chr_open_pipe(Chardev *chr,
}
}
-static void qemu_chr_open_win_file(Chardev *chr, HANDLE fd_out)
-{
- WinChardev *s = WIN_CHARDEV(chr);
-
- s->skip_free = true;
- s->hcom = fd_out;
-}
-
-static void char_win_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->chr_write = win_chr_write;
-}
-
-static const TypeInfo char_win_type_info = {
- .name = TYPE_CHARDEV_WIN,
- .parent = TYPE_CHARDEV,
- .instance_size = sizeof(WinChardev),
- .instance_finalize = char_win_finalize,
- .class_init = char_win_class_init,
- .abstract = true,
-};
-
static void qemu_chr_open_win_con(Chardev *chr,
ChardevBackend *backend,
bool *be_opened,
@@ -4202,7 +3956,6 @@ static void register_types(void)
{
type_register_static(&char_type_info);
#ifdef _WIN32
- type_register_static(&char_win_type_info);
type_register_static(&char_win_stdio_type_info);
#endif
type_register_static(&char_socket_type_info);
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index d2f03dc5df..bdf5a112a7 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -4,3 +4,4 @@ chardev-obj-y += char-io.o
chardev-obj-y += char-mux.o
chardev-obj-y += char-null.o
chardev-obj-y += char-ringbuf.o
+chardev-obj-$(CONFIG_WIN32) += char-win.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 31/41] char: move win-stdio into its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (29 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 30/41] char: move win chardev base class " Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 32/41] char: move socket chardev to " Marc-André Lureau
` (11 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
---
chardev/char-win-stdio.h | 29 ++++++
chardev/char-win-stdio.c | 266 +++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 231 +---------------------------------------
chardev/Makefile.objs | 1 +
4 files changed, 298 insertions(+), 229 deletions(-)
create mode 100644 chardev/char-win-stdio.h
create mode 100644 chardev/char-win-stdio.c
diff --git a/chardev/char-win-stdio.h b/chardev/char-win-stdio.h
new file mode 100644
index 0000000000..d7314f734d
--- /dev/null
+++ b/chardev/char-win-stdio.h
@@ -0,0 +1,29 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef CHAR_WIN_STDIO_H
+#define CHAR_WIN_STDIO_H
+
+#define TYPE_CHARDEV_WIN_STDIO "chardev-win-stdio"
+
+#endif /* CHAR_WIN_STDIO_H */
diff --git a/chardev/char-win-stdio.c b/chardev/char-win-stdio.c
new file mode 100644
index 0000000000..eb44afc17a
--- /dev/null
+++ b/chardev/char-win-stdio.c
@@ -0,0 +1,266 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "char-win.h"
+#include "char-win-stdio.h"
+
+typedef struct {
+ Chardev parent;
+ HANDLE hStdIn;
+ HANDLE hInputReadyEvent;
+ HANDLE hInputDoneEvent;
+ HANDLE hInputThread;
+ uint8_t win_stdio_buf;
+} WinStdioChardev;
+
+#define WIN_STDIO_CHARDEV(obj) \
+ OBJECT_CHECK(WinStdioChardev, (obj), TYPE_CHARDEV_WIN_STDIO)
+
+static void win_stdio_wait_func(void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ WinStdioChardev *stdio = WIN_STDIO_CHARDEV(opaque);
+ INPUT_RECORD buf[4];
+ int ret;
+ DWORD dwSize;
+ int i;
+
+ ret = ReadConsoleInput(stdio->hStdIn, buf, ARRAY_SIZE(buf), &dwSize);
+
+ if (!ret) {
+ /* Avoid error storm */
+ qemu_del_wait_object(stdio->hStdIn, NULL, NULL);
+ return;
+ }
+
+ for (i = 0; i < dwSize; i++) {
+ KEY_EVENT_RECORD *kev = &buf[i].Event.KeyEvent;
+
+ if (buf[i].EventType == KEY_EVENT && kev->bKeyDown) {
+ int j;
+ if (kev->uChar.AsciiChar != 0) {
+ for (j = 0; j < kev->wRepeatCount; j++) {
+ if (qemu_chr_be_can_write(chr)) {
+ uint8_t c = kev->uChar.AsciiChar;
+ qemu_chr_be_write(chr, &c, 1);
+ }
+ }
+ }
+ }
+ }
+}
+
+static DWORD WINAPI win_stdio_thread(LPVOID param)
+{
+ WinStdioChardev *stdio = WIN_STDIO_CHARDEV(param);
+ int ret;
+ DWORD dwSize;
+
+ while (1) {
+
+ /* Wait for one byte */
+ ret = ReadFile(stdio->hStdIn, &stdio->win_stdio_buf, 1, &dwSize, NULL);
+
+ /* Exit in case of error, continue if nothing read */
+ if (!ret) {
+ break;
+ }
+ if (!dwSize) {
+ continue;
+ }
+
+ /* Some terminal emulator returns \r\n for Enter, just pass \n */
+ if (stdio->win_stdio_buf == '\r') {
+ continue;
+ }
+
+ /* Signal the main thread and wait until the byte was eaten */
+ if (!SetEvent(stdio->hInputReadyEvent)) {
+ break;
+ }
+ if (WaitForSingleObject(stdio->hInputDoneEvent, INFINITE)
+ != WAIT_OBJECT_0) {
+ break;
+ }
+ }
+
+ qemu_del_wait_object(stdio->hInputReadyEvent, NULL, NULL);
+ return 0;
+}
+
+static void win_stdio_thread_wait_func(void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ WinStdioChardev *stdio = WIN_STDIO_CHARDEV(opaque);
+
+ if (qemu_chr_be_can_write(chr)) {
+ qemu_chr_be_write(chr, &stdio->win_stdio_buf, 1);
+ }
+
+ SetEvent(stdio->hInputDoneEvent);
+}
+
+static void qemu_chr_set_echo_win_stdio(Chardev *chr, bool echo)
+{
+ WinStdioChardev *stdio = WIN_STDIO_CHARDEV(chr);
+ DWORD dwMode = 0;
+
+ GetConsoleMode(stdio->hStdIn, &dwMode);
+
+ if (echo) {
+ SetConsoleMode(stdio->hStdIn, dwMode | ENABLE_ECHO_INPUT);
+ } else {
+ SetConsoleMode(stdio->hStdIn, dwMode & ~ENABLE_ECHO_INPUT);
+ }
+}
+
+static void qemu_chr_open_stdio(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ WinStdioChardev *stdio = WIN_STDIO_CHARDEV(chr);
+ DWORD dwMode;
+ int is_console = 0;
+
+ stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
+ if (stdio->hStdIn == INVALID_HANDLE_VALUE) {
+ error_setg(errp, "cannot open stdio: invalid handle");
+ return;
+ }
+
+ is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0;
+
+ if (is_console) {
+ if (qemu_add_wait_object(stdio->hStdIn,
+ win_stdio_wait_func, chr)) {
+ error_setg(errp, "qemu_add_wait_object: failed");
+ goto err1;
+ }
+ } else {
+ DWORD dwId;
+
+ stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ stdio->hInputDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (stdio->hInputReadyEvent == INVALID_HANDLE_VALUE
+ || stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) {
+ error_setg(errp, "cannot create event");
+ goto err2;
+ }
+ if (qemu_add_wait_object(stdio->hInputReadyEvent,
+ win_stdio_thread_wait_func, chr)) {
+ error_setg(errp, "qemu_add_wait_object: failed");
+ goto err2;
+ }
+ stdio->hInputThread = CreateThread(NULL, 0, win_stdio_thread,
+ chr, 0, &dwId);
+
+ if (stdio->hInputThread == INVALID_HANDLE_VALUE) {
+ error_setg(errp, "cannot create stdio thread");
+ goto err3;
+ }
+ }
+
+ dwMode |= ENABLE_LINE_INPUT;
+
+ if (is_console) {
+ /* set the terminal in raw mode */
+ /* ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS */
+ dwMode |= ENABLE_PROCESSED_INPUT;
+ }
+
+ SetConsoleMode(stdio->hStdIn, dwMode);
+
+ qemu_chr_set_echo_win_stdio(chr, false);
+
+ return;
+
+err3:
+ qemu_del_wait_object(stdio->hInputReadyEvent, NULL, NULL);
+err2:
+ CloseHandle(stdio->hInputReadyEvent);
+ CloseHandle(stdio->hInputDoneEvent);
+err1:
+ qemu_del_wait_object(stdio->hStdIn, NULL, NULL);
+}
+
+static void char_win_stdio_finalize(Object *obj)
+{
+ WinStdioChardev *stdio = WIN_STDIO_CHARDEV(obj);
+
+ if (stdio->hInputReadyEvent != INVALID_HANDLE_VALUE) {
+ CloseHandle(stdio->hInputReadyEvent);
+ }
+ if (stdio->hInputDoneEvent != INVALID_HANDLE_VALUE) {
+ CloseHandle(stdio->hInputDoneEvent);
+ }
+ if (stdio->hInputThread != INVALID_HANDLE_VALUE) {
+ TerminateThread(stdio->hInputThread, 0);
+ }
+}
+
+static int win_stdio_write(Chardev *chr, const uint8_t *buf, int len)
+{
+ HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ DWORD dwSize;
+ int len1;
+
+ len1 = len;
+
+ while (len1 > 0) {
+ if (!WriteFile(hStdOut, buf, len1, &dwSize, NULL)) {
+ break;
+ }
+ buf += dwSize;
+ len1 -= dwSize;
+ }
+
+ return len - len1;
+}
+
+static void char_win_stdio_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->open = qemu_chr_open_stdio;
+ cc->chr_write = win_stdio_write;
+ cc->chr_set_echo = qemu_chr_set_echo_win_stdio;
+}
+
+static const TypeInfo char_win_stdio_type_info = {
+ .name = TYPE_CHARDEV_WIN_STDIO,
+ .parent = TYPE_CHARDEV,
+ .instance_size = sizeof(WinStdioChardev),
+ .instance_finalize = char_win_stdio_finalize,
+ .class_init = char_win_stdio_class_init,
+ .abstract = true,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_win_stdio_type_info);
+}
+
+type_init(register_types);
diff --git a/chardev/char.c b/chardev/char.c
index b80fcae028..8393bb0294 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -90,6 +90,7 @@
#include "char-io.h"
#ifdef _WIN32
#include "char-win.h"
+#include "char-win-stdio.h"
#endif
#define TCP_MAX_FDS 16
@@ -1474,19 +1475,6 @@ static void qemu_chr_open_pp_fd(Chardev *chr,
#define HAVE_CHARDEV_SERIAL 1
-typedef struct {
- Chardev parent;
- HANDLE hStdIn;
- HANDLE hInputReadyEvent;
- HANDLE hInputDoneEvent;
- HANDLE hInputThread;
- uint8_t win_stdio_buf;
-} WinStdioChardev;
-
-#define TYPE_CHARDEV_WIN_STDIO "chardev-win-stdio"
-#define WIN_STDIO_CHARDEV(obj) \
- OBJECT_CHECK(WinStdioChardev, (obj), TYPE_CHARDEV_WIN_STDIO)
-
#define MAXCONNECT 1
#define NTIMEOUT 5000
@@ -1588,215 +1576,6 @@ static const TypeInfo char_console_type_info = {
.class_init = char_console_class_init,
};
-static int win_stdio_write(Chardev *chr, const uint8_t *buf, int len)
-{
- HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
- DWORD dwSize;
- int len1;
-
- len1 = len;
-
- while (len1 > 0) {
- if (!WriteFile(hStdOut, buf, len1, &dwSize, NULL)) {
- break;
- }
- buf += dwSize;
- len1 -= dwSize;
- }
-
- return len - len1;
-}
-
-static void win_stdio_wait_func(void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- WinStdioChardev *stdio = WIN_STDIO_CHARDEV(opaque);
- INPUT_RECORD buf[4];
- int ret;
- DWORD dwSize;
- int i;
-
- ret = ReadConsoleInput(stdio->hStdIn, buf, ARRAY_SIZE(buf), &dwSize);
-
- if (!ret) {
- /* Avoid error storm */
- qemu_del_wait_object(stdio->hStdIn, NULL, NULL);
- return;
- }
-
- for (i = 0; i < dwSize; i++) {
- KEY_EVENT_RECORD *kev = &buf[i].Event.KeyEvent;
-
- if (buf[i].EventType == KEY_EVENT && kev->bKeyDown) {
- int j;
- if (kev->uChar.AsciiChar != 0) {
- for (j = 0; j < kev->wRepeatCount; j++) {
- if (qemu_chr_be_can_write(chr)) {
- uint8_t c = kev->uChar.AsciiChar;
- qemu_chr_be_write(chr, &c, 1);
- }
- }
- }
- }
- }
-}
-
-static DWORD WINAPI win_stdio_thread(LPVOID param)
-{
- WinStdioChardev *stdio = WIN_STDIO_CHARDEV(param);
- int ret;
- DWORD dwSize;
-
- while (1) {
-
- /* Wait for one byte */
- ret = ReadFile(stdio->hStdIn, &stdio->win_stdio_buf, 1, &dwSize, NULL);
-
- /* Exit in case of error, continue if nothing read */
- if (!ret) {
- break;
- }
- if (!dwSize) {
- continue;
- }
-
- /* Some terminal emulator returns \r\n for Enter, just pass \n */
- if (stdio->win_stdio_buf == '\r') {
- continue;
- }
-
- /* Signal the main thread and wait until the byte was eaten */
- if (!SetEvent(stdio->hInputReadyEvent)) {
- break;
- }
- if (WaitForSingleObject(stdio->hInputDoneEvent, INFINITE)
- != WAIT_OBJECT_0) {
- break;
- }
- }
-
- qemu_del_wait_object(stdio->hInputReadyEvent, NULL, NULL);
- return 0;
-}
-
-static void win_stdio_thread_wait_func(void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- WinStdioChardev *stdio = WIN_STDIO_CHARDEV(opaque);
-
- if (qemu_chr_be_can_write(chr)) {
- qemu_chr_be_write(chr, &stdio->win_stdio_buf, 1);
- }
-
- SetEvent(stdio->hInputDoneEvent);
-}
-
-static void qemu_chr_set_echo_win_stdio(Chardev *chr, bool echo)
-{
- WinStdioChardev *stdio = WIN_STDIO_CHARDEV(chr);
- DWORD dwMode = 0;
-
- GetConsoleMode(stdio->hStdIn, &dwMode);
-
- if (echo) {
- SetConsoleMode(stdio->hStdIn, dwMode | ENABLE_ECHO_INPUT);
- } else {
- SetConsoleMode(stdio->hStdIn, dwMode & ~ENABLE_ECHO_INPUT);
- }
-}
-
-static void char_win_stdio_finalize(Object *obj)
-{
- WinStdioChardev *stdio = WIN_STDIO_CHARDEV(obj);
-
- if (stdio->hInputReadyEvent != INVALID_HANDLE_VALUE) {
- CloseHandle(stdio->hInputReadyEvent);
- }
- if (stdio->hInputDoneEvent != INVALID_HANDLE_VALUE) {
- CloseHandle(stdio->hInputDoneEvent);
- }
- if (stdio->hInputThread != INVALID_HANDLE_VALUE) {
- TerminateThread(stdio->hInputThread, 0);
- }
-}
-
-static const TypeInfo char_win_stdio_type_info = {
- .name = TYPE_CHARDEV_WIN_STDIO,
- .parent = TYPE_CHARDEV,
- .instance_size = sizeof(WinStdioChardev),
- .instance_finalize = char_win_stdio_finalize,
- .abstract = true,
-};
-
-static void qemu_chr_open_stdio(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- WinStdioChardev *stdio = WIN_STDIO_CHARDEV(chr);
- DWORD dwMode;
- int is_console = 0;
-
- stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
- if (stdio->hStdIn == INVALID_HANDLE_VALUE) {
- error_setg(errp, "cannot open stdio: invalid handle");
- return;
- }
-
- is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0;
-
- if (is_console) {
- if (qemu_add_wait_object(stdio->hStdIn,
- win_stdio_wait_func, chr)) {
- error_setg(errp, "qemu_add_wait_object: failed");
- goto err1;
- }
- } else {
- DWORD dwId;
-
- stdio->hInputReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- stdio->hInputDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (stdio->hInputReadyEvent == INVALID_HANDLE_VALUE
- || stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) {
- error_setg(errp, "cannot create event");
- goto err2;
- }
- if (qemu_add_wait_object(stdio->hInputReadyEvent,
- win_stdio_thread_wait_func, chr)) {
- error_setg(errp, "qemu_add_wait_object: failed");
- goto err2;
- }
- stdio->hInputThread = CreateThread(NULL, 0, win_stdio_thread,
- chr, 0, &dwId);
-
- if (stdio->hInputThread == INVALID_HANDLE_VALUE) {
- error_setg(errp, "cannot create stdio thread");
- goto err3;
- }
- }
-
- dwMode |= ENABLE_LINE_INPUT;
-
- if (is_console) {
- /* set the terminal in raw mode */
- /* ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS */
- dwMode |= ENABLE_PROCESSED_INPUT;
- }
-
- SetConsoleMode(stdio->hStdIn, dwMode);
-
- qemu_chr_set_echo_win_stdio(chr, false);
-
- return;
-
-err3:
- qemu_del_wait_object(stdio->hInputReadyEvent, NULL, NULL);
-err2:
- CloseHandle(stdio->hInputReadyEvent);
- CloseHandle(stdio->hInputDoneEvent);
-err1:
- qemu_del_wait_object(stdio->hStdIn, NULL, NULL);
-}
#endif /* !_WIN32 */
/***********************************************************/
@@ -2785,11 +2564,8 @@ static void char_stdio_class_init(ObjectClass *oc, void *data)
ChardevClass *cc = CHARDEV_CLASS(oc);
cc->parse = qemu_chr_parse_stdio;
+#ifndef _WIN32
cc->open = qemu_chr_open_stdio;
-#ifdef _WIN32
- cc->chr_write = win_stdio_write;
- cc->chr_set_echo = qemu_chr_set_echo_win_stdio;
-#else
cc->chr_set_echo = qemu_chr_set_echo_stdio;
#endif
}
@@ -3955,9 +3731,6 @@ void qemu_chr_cleanup(void)
static void register_types(void)
{
type_register_static(&char_type_info);
-#ifdef _WIN32
- type_register_static(&char_win_stdio_type_info);
-#endif
type_register_static(&char_socket_type_info);
type_register_static(&char_udp_type_info);
type_register_static(&char_file_type_info);
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index bdf5a112a7..3c4a328de8 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -5,3 +5,4 @@ chardev-obj-y += char-mux.o
chardev-obj-y += char-null.o
chardev-obj-y += char-ringbuf.o
chardev-obj-$(CONFIG_WIN32) += char-win.o
+chardev-obj-$(CONFIG_WIN32) += char-win-stdio.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 32/41] char: move socket chardev to its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (30 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 31/41] char: move win-stdio into " Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 33/41] char: move udp chardev in " Marc-André Lureau
` (10 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
---
include/sysemu/char.h | 1 +
chardev/char-socket.c | 1017 +++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 979 +----------------------------------------------
chardev/Makefile.objs | 1 +
4 files changed, 1020 insertions(+), 978 deletions(-)
create mode 100644 chardev/char-socket.c
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 1a65798e3e..b256e79c31 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -443,6 +443,7 @@ void qemu_chr_set_feature(Chardev *chr,
ChardevFeature feature);
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
int qemu_chr_write_all(Chardev *s, const uint8_t *buf, int len);
+int qemu_chr_wait_connected(Chardev *chr, Error **errp);
#define TYPE_CHARDEV "chardev"
#define CHARDEV(obj) OBJECT_CHECK(Chardev, (obj), TYPE_CHARDEV)
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
new file mode 100644
index 0000000000..4068dc5e52
--- /dev/null
+++ b/chardev/char-socket.c
@@ -0,0 +1,1017 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "sysemu/char.h"
+#include "io/channel-socket.h"
+#include "io/channel-tls.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "qapi/clone-visitor.h"
+
+#include "char-io.h"
+
+/***********************************************************/
+/* TCP Net console */
+
+#define TCP_MAX_FDS 16
+
+typedef struct {
+ Chardev parent;
+ QIOChannel *ioc; /* Client I/O channel */
+ QIOChannelSocket *sioc; /* Client master channel */
+ QIOChannelSocket *listen_ioc;
+ guint listen_tag;
+ QCryptoTLSCreds *tls_creds;
+ int connected;
+ int max_size;
+ int do_telnetopt;
+ int do_nodelay;
+ int is_unix;
+ int *read_msgfds;
+ size_t read_msgfds_num;
+ int *write_msgfds;
+ size_t write_msgfds_num;
+
+ SocketAddress *addr;
+ bool is_listen;
+ bool is_telnet;
+
+ guint reconnect_timer;
+ int64_t reconnect_time;
+ bool connect_err_reported;
+} SocketChardev;
+
+#define SOCKET_CHARDEV(obj) \
+ OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET)
+
+static gboolean socket_reconnect_timeout(gpointer opaque);
+
+static void qemu_chr_socket_restart_timer(Chardev *chr)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ char *name;
+
+ assert(s->connected == 0);
+ s->reconnect_timer = g_timeout_add_seconds(s->reconnect_time,
+ socket_reconnect_timeout, chr);
+ name = g_strdup_printf("chardev-socket-reconnect-%s", chr->label);
+ g_source_set_name_by_id(s->reconnect_timer, name);
+ g_free(name);
+}
+
+static void check_report_connect_error(Chardev *chr,
+ Error *err)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+
+ if (!s->connect_err_reported) {
+ error_report("Unable to connect character device %s: %s",
+ chr->label, error_get_pretty(err));
+ s->connect_err_reported = true;
+ }
+ qemu_chr_socket_restart_timer(chr);
+}
+
+static gboolean tcp_chr_accept(QIOChannel *chan,
+ GIOCondition cond,
+ void *opaque);
+
+/* Called with chr_write_lock held. */
+static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+
+ if (s->connected) {
+ int ret = io_channel_send_full(s->ioc, buf, len,
+ s->write_msgfds,
+ s->write_msgfds_num);
+
+ /* free the written msgfds, no matter what */
+ if (s->write_msgfds_num) {
+ g_free(s->write_msgfds);
+ s->write_msgfds = 0;
+ s->write_msgfds_num = 0;
+ }
+
+ return ret;
+ } else {
+ /* XXX: indicate an error ? */
+ return len;
+ }
+}
+
+static int tcp_chr_read_poll(void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ SocketChardev *s = SOCKET_CHARDEV(opaque);
+ if (!s->connected) {
+ return 0;
+ }
+ s->max_size = qemu_chr_be_can_write(chr);
+ return s->max_size;
+}
+
+#define IAC 255
+#define IAC_BREAK 243
+static void tcp_chr_process_IAC_bytes(Chardev *chr,
+ SocketChardev *s,
+ uint8_t *buf, int *size)
+{
+ /* Handle any telnet client's basic IAC options to satisfy char by
+ * char mode with no echo. All IAC options will be removed from
+ * the buf and the do_telnetopt variable will be used to track the
+ * state of the width of the IAC information.
+ *
+ * IAC commands come in sets of 3 bytes with the exception of the
+ * "IAC BREAK" command and the double IAC.
+ */
+
+ int i;
+ int j = 0;
+
+ for (i = 0; i < *size; i++) {
+ if (s->do_telnetopt > 1) {
+ if ((unsigned char)buf[i] == IAC && s->do_telnetopt == 2) {
+ /* Double IAC means send an IAC */
+ if (j != i) {
+ buf[j] = buf[i];
+ }
+ j++;
+ s->do_telnetopt = 1;
+ } else {
+ if ((unsigned char)buf[i] == IAC_BREAK
+ && s->do_telnetopt == 2) {
+ /* Handle IAC break commands by sending a serial break */
+ qemu_chr_be_event(chr, CHR_EVENT_BREAK);
+ s->do_telnetopt++;
+ }
+ s->do_telnetopt++;
+ }
+ if (s->do_telnetopt >= 4) {
+ s->do_telnetopt = 1;
+ }
+ } else {
+ if ((unsigned char)buf[i] == IAC) {
+ s->do_telnetopt = 2;
+ } else {
+ if (j != i) {
+ buf[j] = buf[i];
+ }
+ j++;
+ }
+ }
+ }
+ *size = j;
+}
+
+static int tcp_get_msgfds(Chardev *chr, int *fds, int num)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+
+ int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num;
+
+ assert(num <= TCP_MAX_FDS);
+
+ if (to_copy) {
+ int i;
+
+ memcpy(fds, s->read_msgfds, to_copy * sizeof(int));
+
+ /* Close unused fds */
+ for (i = to_copy; i < s->read_msgfds_num; i++) {
+ close(s->read_msgfds[i]);
+ }
+
+ g_free(s->read_msgfds);
+ s->read_msgfds = 0;
+ s->read_msgfds_num = 0;
+ }
+
+ return to_copy;
+}
+
+static int tcp_set_msgfds(Chardev *chr, int *fds, int num)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+
+ /* clear old pending fd array */
+ g_free(s->write_msgfds);
+ s->write_msgfds = NULL;
+ s->write_msgfds_num = 0;
+
+ if (!s->connected ||
+ !qio_channel_has_feature(s->ioc,
+ QIO_CHANNEL_FEATURE_FD_PASS)) {
+ return -1;
+ }
+
+ if (num) {
+ s->write_msgfds = g_new(int, num);
+ memcpy(s->write_msgfds, fds, num * sizeof(int));
+ }
+
+ s->write_msgfds_num = num;
+
+ return 0;
+}
+
+static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ struct iovec iov = { .iov_base = buf, .iov_len = len };
+ int ret;
+ size_t i;
+ int *msgfds = NULL;
+ size_t msgfds_num = 0;
+
+ if (qio_channel_has_feature(s->ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
+ ret = qio_channel_readv_full(s->ioc, &iov, 1,
+ &msgfds, &msgfds_num,
+ NULL);
+ } else {
+ ret = qio_channel_readv_full(s->ioc, &iov, 1,
+ NULL, NULL,
+ NULL);
+ }
+
+ if (ret == QIO_CHANNEL_ERR_BLOCK) {
+ errno = EAGAIN;
+ ret = -1;
+ } else if (ret == -1) {
+ errno = EIO;
+ }
+
+ if (msgfds_num) {
+ /* close and clean read_msgfds */
+ for (i = 0; i < s->read_msgfds_num; i++) {
+ close(s->read_msgfds[i]);
+ }
+
+ if (s->read_msgfds_num) {
+ g_free(s->read_msgfds);
+ }
+
+ s->read_msgfds = msgfds;
+ s->read_msgfds_num = msgfds_num;
+ }
+
+ for (i = 0; i < s->read_msgfds_num; i++) {
+ int fd = s->read_msgfds[i];
+ if (fd < 0) {
+ continue;
+ }
+
+ /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
+ qemu_set_block(fd);
+
+#ifndef MSG_CMSG_CLOEXEC
+ qemu_set_cloexec(fd);
+#endif
+ }
+
+ return ret;
+}
+
+static GSource *tcp_chr_add_watch(Chardev *chr, GIOCondition cond)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ return qio_channel_create_watch(s->ioc, cond);
+}
+
+static void tcp_chr_free_connection(Chardev *chr)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ int i;
+
+ if (!s->connected) {
+ return;
+ }
+
+ if (s->read_msgfds_num) {
+ for (i = 0; i < s->read_msgfds_num; i++) {
+ close(s->read_msgfds[i]);
+ }
+ g_free(s->read_msgfds);
+ s->read_msgfds = NULL;
+ s->read_msgfds_num = 0;
+ }
+
+ tcp_set_msgfds(chr, NULL, 0);
+ remove_fd_in_watch(chr);
+ object_unref(OBJECT(s->sioc));
+ s->sioc = NULL;
+ object_unref(OBJECT(s->ioc));
+ s->ioc = NULL;
+ g_free(chr->filename);
+ chr->filename = NULL;
+ s->connected = 0;
+}
+
+static char *SocketAddress_to_str(const char *prefix, SocketAddress *addr,
+ bool is_listen, bool is_telnet)
+{
+ switch (addr->type) {
+ case SOCKET_ADDRESS_KIND_INET:
+ return g_strdup_printf("%s%s:%s:%s%s", prefix,
+ is_telnet ? "telnet" : "tcp",
+ addr->u.inet.data->host,
+ addr->u.inet.data->port,
+ is_listen ? ",server" : "");
+ break;
+ case SOCKET_ADDRESS_KIND_UNIX:
+ return g_strdup_printf("%sunix:%s%s", prefix,
+ addr->u.q_unix.data->path,
+ is_listen ? ",server" : "");
+ break;
+ case SOCKET_ADDRESS_KIND_FD:
+ return g_strdup_printf("%sfd:%s%s", prefix, addr->u.fd.data->str,
+ is_listen ? ",server" : "");
+ break;
+ default:
+ abort();
+ }
+}
+
+static void tcp_chr_disconnect(Chardev *chr)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+
+ if (!s->connected) {
+ return;
+ }
+
+ tcp_chr_free_connection(chr);
+
+ if (s->listen_ioc) {
+ s->listen_tag = qio_channel_add_watch(
+ QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL);
+ }
+ chr->filename = SocketAddress_to_str("disconnected:", s->addr,
+ s->is_listen, s->is_telnet);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+ if (s->reconnect_time) {
+ qemu_chr_socket_restart_timer(chr);
+ }
+}
+
+static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ SocketChardev *s = SOCKET_CHARDEV(opaque);
+ uint8_t buf[CHR_READ_BUF_LEN];
+ int len, size;
+
+ if (!s->connected || s->max_size <= 0) {
+ return TRUE;
+ }
+ len = sizeof(buf);
+ if (len > s->max_size) {
+ len = s->max_size;
+ }
+ size = tcp_chr_recv(chr, (void *)buf, len);
+ if (size == 0 || size == -1) {
+ /* connection closed */
+ tcp_chr_disconnect(chr);
+ } else if (size > 0) {
+ if (s->do_telnetopt) {
+ tcp_chr_process_IAC_bytes(chr, s, buf, &size);
+ }
+ if (size > 0) {
+ qemu_chr_be_write(chr, buf, size);
+ }
+ }
+
+ return TRUE;
+}
+
+static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ int size;
+
+ if (!s->connected) {
+ return 0;
+ }
+
+ size = tcp_chr_recv(chr, (void *) buf, len);
+ if (size == 0) {
+ /* connection closed */
+ tcp_chr_disconnect(chr);
+ }
+
+ return size;
+}
+
+static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len,
+ struct sockaddr_storage *ps, socklen_t ps_len,
+ bool is_listen, bool is_telnet)
+{
+ char shost[NI_MAXHOST], sserv[NI_MAXSERV];
+ char phost[NI_MAXHOST], pserv[NI_MAXSERV];
+ const char *left = "", *right = "";
+
+ switch (ss->ss_family) {
+#ifndef _WIN32
+ case AF_UNIX:
+ return g_strdup_printf("unix:%s%s",
+ ((struct sockaddr_un *)(ss))->sun_path,
+ is_listen ? ",server" : "");
+#endif
+ case AF_INET6:
+ left = "[";
+ right = "]";
+ /* fall through */
+ case AF_INET:
+ getnameinfo((struct sockaddr *) ss, ss_len, shost, sizeof(shost),
+ sserv, sizeof(sserv), NI_NUMERICHOST | NI_NUMERICSERV);
+ getnameinfo((struct sockaddr *) ps, ps_len, phost, sizeof(phost),
+ pserv, sizeof(pserv), NI_NUMERICHOST | NI_NUMERICSERV);
+ return g_strdup_printf("%s:%s%s%s:%s%s <-> %s%s%s:%s",
+ is_telnet ? "telnet" : "tcp",
+ left, shost, right, sserv,
+ is_listen ? ",server" : "",
+ left, phost, right, pserv);
+
+ default:
+ return g_strdup_printf("unknown");
+ }
+}
+
+static void tcp_chr_connect(void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ SocketChardev *s = SOCKET_CHARDEV(opaque);
+
+ g_free(chr->filename);
+ chr->filename = sockaddr_to_str(
+ &s->sioc->localAddr, s->sioc->localAddrLen,
+ &s->sioc->remoteAddr, s->sioc->remoteAddrLen,
+ s->is_listen, s->is_telnet);
+
+ s->connected = 1;
+ if (s->ioc) {
+ chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
+ tcp_chr_read_poll,
+ tcp_chr_read,
+ chr, NULL);
+ }
+ qemu_chr_be_generic_open(chr);
+}
+
+static void tcp_chr_update_read_handler(Chardev *chr,
+ GMainContext *context)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+
+ if (!s->connected) {
+ return;
+ }
+
+ remove_fd_in_watch(chr);
+ if (s->ioc) {
+ chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
+ tcp_chr_read_poll,
+ tcp_chr_read, chr,
+ context);
+ }
+}
+
+typedef struct {
+ Chardev *chr;
+ char buf[12];
+ size_t buflen;
+} TCPChardevTelnetInit;
+
+static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
+ GIOCondition cond G_GNUC_UNUSED,
+ gpointer user_data)
+{
+ TCPChardevTelnetInit *init = user_data;
+ ssize_t ret;
+
+ ret = qio_channel_write(ioc, init->buf, init->buflen, NULL);
+ if (ret < 0) {
+ if (ret == QIO_CHANNEL_ERR_BLOCK) {
+ ret = 0;
+ } else {
+ tcp_chr_disconnect(init->chr);
+ return FALSE;
+ }
+ }
+ init->buflen -= ret;
+
+ if (init->buflen == 0) {
+ tcp_chr_connect(init->chr);
+ return FALSE;
+ }
+
+ memmove(init->buf, init->buf + ret, init->buflen);
+
+ return TRUE;
+}
+
+static void tcp_chr_telnet_init(Chardev *chr)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ TCPChardevTelnetInit *init = g_new0(TCPChardevTelnetInit, 1);
+ size_t n = 0;
+
+ init->chr = chr;
+ init->buflen = 12;
+
+#define IACSET(x, a, b, c) \
+ do { \
+ x[n++] = a; \
+ x[n++] = b; \
+ x[n++] = c; \
+ } while (0)
+
+ /* Prep the telnet negotion to put telnet in binary,
+ * no echo, single char mode */
+ IACSET(init->buf, 0xff, 0xfb, 0x01); /* IAC WILL ECHO */
+ IACSET(init->buf, 0xff, 0xfb, 0x03); /* IAC WILL Suppress go ahead */
+ IACSET(init->buf, 0xff, 0xfb, 0x00); /* IAC WILL Binary */
+ IACSET(init->buf, 0xff, 0xfd, 0x00); /* IAC DO Binary */
+
+#undef IACSET
+
+ qio_channel_add_watch(
+ s->ioc, G_IO_OUT,
+ tcp_chr_telnet_init_io,
+ init, NULL);
+}
+
+
+static void tcp_chr_tls_handshake(QIOTask *task,
+ gpointer user_data)
+{
+ Chardev *chr = user_data;
+ SocketChardev *s = user_data;
+
+ if (qio_task_propagate_error(task, NULL)) {
+ tcp_chr_disconnect(chr);
+ } else {
+ if (s->do_telnetopt) {
+ tcp_chr_telnet_init(chr);
+ } else {
+ tcp_chr_connect(chr);
+ }
+ }
+}
+
+
+static void tcp_chr_tls_init(Chardev *chr)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ QIOChannelTLS *tioc;
+ Error *err = NULL;
+ gchar *name;
+
+ if (s->is_listen) {
+ tioc = qio_channel_tls_new_server(
+ s->ioc, s->tls_creds,
+ NULL, /* XXX Use an ACL */
+ &err);
+ } else {
+ tioc = qio_channel_tls_new_client(
+ s->ioc, s->tls_creds,
+ s->addr->u.inet.data->host,
+ &err);
+ }
+ if (tioc == NULL) {
+ error_free(err);
+ tcp_chr_disconnect(chr);
+ return;
+ }
+ name = g_strdup_printf("chardev-tls-%s-%s",
+ s->is_listen ? "server" : "client",
+ chr->label);
+ qio_channel_set_name(QIO_CHANNEL(tioc), name);
+ g_free(name);
+ object_unref(OBJECT(s->ioc));
+ s->ioc = QIO_CHANNEL(tioc);
+
+ qio_channel_tls_handshake(tioc,
+ tcp_chr_tls_handshake,
+ chr,
+ NULL);
+}
+
+
+static void tcp_chr_set_client_ioc_name(Chardev *chr,
+ QIOChannelSocket *sioc)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ char *name;
+ name = g_strdup_printf("chardev-tcp-%s-%s",
+ s->is_listen ? "server" : "client",
+ chr->label);
+ qio_channel_set_name(QIO_CHANNEL(sioc), name);
+ g_free(name);
+
+}
+
+static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+
+ if (s->ioc != NULL) {
+ return -1;
+ }
+
+ s->ioc = QIO_CHANNEL(sioc);
+ object_ref(OBJECT(sioc));
+ s->sioc = sioc;
+ object_ref(OBJECT(sioc));
+
+ qio_channel_set_blocking(s->ioc, false, NULL);
+
+ if (s->do_nodelay) {
+ qio_channel_set_delay(s->ioc, false);
+ }
+ if (s->listen_tag) {
+ g_source_remove(s->listen_tag);
+ s->listen_tag = 0;
+ }
+
+ if (s->tls_creds) {
+ tcp_chr_tls_init(chr);
+ } else {
+ if (s->do_telnetopt) {
+ tcp_chr_telnet_init(chr);
+ } else {
+ tcp_chr_connect(chr);
+ }
+ }
+
+ return 0;
+}
+
+
+static int tcp_chr_add_client(Chardev *chr, int fd)
+{
+ int ret;
+ QIOChannelSocket *sioc;
+
+ sioc = qio_channel_socket_new_fd(fd, NULL);
+ if (!sioc) {
+ return -1;
+ }
+ tcp_chr_set_client_ioc_name(chr, sioc);
+ ret = tcp_chr_new_client(chr, sioc);
+ object_unref(OBJECT(sioc));
+ return ret;
+}
+
+static gboolean tcp_chr_accept(QIOChannel *channel,
+ GIOCondition cond,
+ void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ QIOChannelSocket *sioc;
+
+ sioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(channel),
+ NULL);
+ if (!sioc) {
+ return TRUE;
+ }
+
+ tcp_chr_new_client(chr, sioc);
+
+ object_unref(OBJECT(sioc));
+
+ return TRUE;
+}
+
+static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ QIOChannelSocket *sioc;
+
+ /* It can't wait on s->connected, since it is set asynchronously
+ * in TLS and telnet cases, only wait for an accepted socket */
+ while (!s->ioc) {
+ if (s->is_listen) {
+ error_report("QEMU waiting for connection on: %s",
+ chr->filename);
+ qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), true, NULL);
+ tcp_chr_accept(QIO_CHANNEL(s->listen_ioc), G_IO_IN, chr);
+ qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), false, NULL);
+ } else {
+ sioc = qio_channel_socket_new();
+ tcp_chr_set_client_ioc_name(chr, sioc);
+ if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
+ object_unref(OBJECT(sioc));
+ return -1;
+ }
+ tcp_chr_new_client(chr, sioc);
+ object_unref(OBJECT(sioc));
+ }
+ }
+
+ return 0;
+}
+
+static void char_socket_finalize(Object *obj)
+{
+ Chardev *chr = CHARDEV(obj);
+ SocketChardev *s = SOCKET_CHARDEV(obj);
+
+ tcp_chr_free_connection(chr);
+
+ if (s->reconnect_timer) {
+ g_source_remove(s->reconnect_timer);
+ s->reconnect_timer = 0;
+ }
+ qapi_free_SocketAddress(s->addr);
+ if (s->listen_tag) {
+ g_source_remove(s->listen_tag);
+ s->listen_tag = 0;
+ }
+ if (s->listen_ioc) {
+ object_unref(OBJECT(s->listen_ioc));
+ }
+ if (s->tls_creds) {
+ object_unref(OBJECT(s->tls_creds));
+ }
+
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+}
+
+static void qemu_chr_socket_connected(QIOTask *task, void *opaque)
+{
+ QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
+ Chardev *chr = CHARDEV(opaque);
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ Error *err = NULL;
+
+ if (qio_task_propagate_error(task, &err)) {
+ check_report_connect_error(chr, err);
+ error_free(err);
+ goto cleanup;
+ }
+
+ s->connect_err_reported = false;
+ tcp_chr_new_client(chr, sioc);
+
+cleanup:
+ object_unref(OBJECT(sioc));
+}
+
+static gboolean socket_reconnect_timeout(gpointer opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ SocketChardev *s = SOCKET_CHARDEV(opaque);
+ QIOChannelSocket *sioc;
+
+ s->reconnect_timer = 0;
+
+ if (chr->be_open) {
+ return false;
+ }
+
+ sioc = qio_channel_socket_new();
+ tcp_chr_set_client_ioc_name(chr, sioc);
+ qio_channel_socket_connect_async(sioc, s->addr,
+ qemu_chr_socket_connected,
+ chr, NULL);
+
+ return false;
+}
+
+static void qmp_chardev_open_socket(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ ChardevSocket *sock = backend->u.socket.data;
+ SocketAddress *addr = sock->addr;
+ bool do_nodelay = sock->has_nodelay ? sock->nodelay : false;
+ bool is_listen = sock->has_server ? sock->server : true;
+ bool is_telnet = sock->has_telnet ? sock->telnet : false;
+ bool is_waitconnect = sock->has_wait ? sock->wait : false;
+ int64_t reconnect = sock->has_reconnect ? sock->reconnect : 0;
+ QIOChannelSocket *sioc = NULL;
+
+ s->is_unix = addr->type == SOCKET_ADDRESS_KIND_UNIX;
+ s->is_listen = is_listen;
+ s->is_telnet = is_telnet;
+ s->do_nodelay = do_nodelay;
+ if (sock->tls_creds) {
+ Object *creds;
+ creds = object_resolve_path_component(
+ object_get_objects_root(), sock->tls_creds);
+ if (!creds) {
+ error_setg(errp, "No TLS credentials with id '%s'",
+ sock->tls_creds);
+ goto error;
+ }
+ s->tls_creds = (QCryptoTLSCreds *)
+ object_dynamic_cast(creds,
+ TYPE_QCRYPTO_TLS_CREDS);
+ if (!s->tls_creds) {
+ error_setg(errp, "Object with id '%s' is not TLS credentials",
+ sock->tls_creds);
+ goto error;
+ }
+ object_ref(OBJECT(s->tls_creds));
+ if (is_listen) {
+ if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
+ error_setg(errp, "%s",
+ "Expected TLS credentials for server endpoint");
+ goto error;
+ }
+ } else {
+ if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
+ error_setg(errp, "%s",
+ "Expected TLS credentials for client endpoint");
+ goto error;
+ }
+ }
+ }
+
+ s->addr = QAPI_CLONE(SocketAddress, sock->addr);
+
+ qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE);
+ if (s->is_unix) {
+ qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS);
+ }
+
+ /* be isn't opened until we get a connection */
+ *be_opened = false;
+
+ chr->filename = SocketAddress_to_str("disconnected:",
+ addr, is_listen, is_telnet);
+
+ if (is_listen) {
+ if (is_telnet) {
+ s->do_telnetopt = 1;
+ }
+ } else if (reconnect > 0) {
+ s->reconnect_time = reconnect;
+ }
+
+ if (s->reconnect_time) {
+ sioc = qio_channel_socket_new();
+ tcp_chr_set_client_ioc_name(chr, sioc);
+ qio_channel_socket_connect_async(sioc, s->addr,
+ qemu_chr_socket_connected,
+ chr, NULL);
+ } else {
+ if (s->is_listen) {
+ char *name;
+ sioc = qio_channel_socket_new();
+
+ name = g_strdup_printf("chardev-tcp-listener-%s", chr->label);
+ qio_channel_set_name(QIO_CHANNEL(sioc), name);
+ g_free(name);
+
+ if (qio_channel_socket_listen_sync(sioc, s->addr, errp) < 0) {
+ goto error;
+ }
+ s->listen_ioc = sioc;
+ if (is_waitconnect &&
+ qemu_chr_wait_connected(chr, errp) < 0) {
+ return;
+ }
+ if (!s->ioc) {
+ s->listen_tag = qio_channel_add_watch(
+ QIO_CHANNEL(s->listen_ioc), G_IO_IN,
+ tcp_chr_accept, chr, NULL);
+ }
+ } else if (qemu_chr_wait_connected(chr, errp) < 0) {
+ goto error;
+ }
+ }
+
+ return;
+
+error:
+ if (sioc) {
+ object_unref(OBJECT(sioc));
+ }
+}
+
+static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
+{
+ bool is_listen = qemu_opt_get_bool(opts, "server", false);
+ bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true);
+ bool is_telnet = qemu_opt_get_bool(opts, "telnet", false);
+ bool do_nodelay = !qemu_opt_get_bool(opts, "delay", true);
+ int64_t reconnect = qemu_opt_get_number(opts, "reconnect", 0);
+ const char *path = qemu_opt_get(opts, "path");
+ const char *host = qemu_opt_get(opts, "host");
+ const char *port = qemu_opt_get(opts, "port");
+ const char *tls_creds = qemu_opt_get(opts, "tls-creds");
+ SocketAddress *addr;
+ ChardevSocket *sock;
+
+ backend->type = CHARDEV_BACKEND_KIND_SOCKET;
+ if (!path) {
+ if (!host) {
+ error_setg(errp, "chardev: socket: no host given");
+ return;
+ }
+ if (!port) {
+ error_setg(errp, "chardev: socket: no port given");
+ return;
+ }
+ } else {
+ if (tls_creds) {
+ error_setg(errp, "TLS can only be used over TCP socket");
+ return;
+ }
+ }
+
+ sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
+
+ sock->has_nodelay = true;
+ sock->nodelay = do_nodelay;
+ sock->has_server = true;
+ sock->server = is_listen;
+ sock->has_telnet = true;
+ sock->telnet = is_telnet;
+ sock->has_wait = true;
+ sock->wait = is_waitconnect;
+ sock->has_reconnect = true;
+ sock->reconnect = reconnect;
+ sock->tls_creds = g_strdup(tls_creds);
+
+ addr = g_new0(SocketAddress, 1);
+ if (path) {
+ UnixSocketAddress *q_unix;
+ addr->type = SOCKET_ADDRESS_KIND_UNIX;
+ q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
+ q_unix->path = g_strdup(path);
+ } else {
+ addr->type = SOCKET_ADDRESS_KIND_INET;
+ addr->u.inet.data = g_new(InetSocketAddress, 1);
+ *addr->u.inet.data = (InetSocketAddress) {
+ .host = g_strdup(host),
+ .port = g_strdup(port),
+ .has_to = qemu_opt_get(opts, "to"),
+ .to = qemu_opt_get_number(opts, "to", 0),
+ .has_ipv4 = qemu_opt_get(opts, "ipv4"),
+ .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
+ .has_ipv6 = qemu_opt_get(opts, "ipv6"),
+ .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
+ };
+ }
+ sock->addr = addr;
+}
+
+static void char_socket_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->parse = qemu_chr_parse_socket;
+ cc->open = qmp_chardev_open_socket;
+ cc->chr_wait_connected = tcp_chr_wait_connected;
+ cc->chr_write = tcp_chr_write;
+ cc->chr_sync_read = tcp_chr_sync_read;
+ cc->chr_disconnect = tcp_chr_disconnect;
+ cc->get_msgfds = tcp_get_msgfds;
+ cc->set_msgfds = tcp_set_msgfds;
+ cc->chr_add_client = tcp_chr_add_client;
+ cc->chr_add_watch = tcp_chr_add_watch;
+ cc->chr_update_read_handler = tcp_chr_update_read_handler;
+}
+
+static const TypeInfo char_socket_type_info = {
+ .name = TYPE_CHARDEV_SOCKET,
+ .parent = TYPE_CHARDEV,
+ .instance_size = sizeof(SocketChardev),
+ .instance_finalize = char_socket_finalize,
+ .class_init = char_socket_class_init,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_socket_type_info);
+}
+
+type_init(register_types);
diff --git a/chardev/char.c b/chardev/char.c
index 8393bb0294..73b6663aa4 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -93,71 +93,6 @@
#include "char-win-stdio.h"
#endif
-#define TCP_MAX_FDS 16
-
-/***********************************************************/
-/* Socket address helpers */
-
-static char *SocketAddress_to_str(const char *prefix, SocketAddress *addr,
- bool is_listen, bool is_telnet)
-{
- switch (addr->type) {
- case SOCKET_ADDRESS_KIND_INET:
- return g_strdup_printf("%s%s:%s:%s%s", prefix,
- is_telnet ? "telnet" : "tcp",
- addr->u.inet.data->host,
- addr->u.inet.data->port,
- is_listen ? ",server" : "");
- break;
- case SOCKET_ADDRESS_KIND_UNIX:
- return g_strdup_printf("%sunix:%s%s", prefix,
- addr->u.q_unix.data->path,
- is_listen ? ",server" : "");
- break;
- case SOCKET_ADDRESS_KIND_FD:
- return g_strdup_printf("%sfd:%s%s", prefix, addr->u.fd.data->str,
- is_listen ? ",server" : "");
- break;
- default:
- abort();
- }
-}
-
-static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len,
- struct sockaddr_storage *ps, socklen_t ps_len,
- bool is_listen, bool is_telnet)
-{
- char shost[NI_MAXHOST], sserv[NI_MAXSERV];
- char phost[NI_MAXHOST], pserv[NI_MAXSERV];
- const char *left = "", *right = "";
-
- switch (ss->ss_family) {
-#ifndef _WIN32
- case AF_UNIX:
- return g_strdup_printf("unix:%s%s",
- ((struct sockaddr_un *)(ss))->sun_path,
- is_listen ? ",server" : "");
-#endif
- case AF_INET6:
- left = "[";
- right = "]";
- /* fall through */
- case AF_INET:
- getnameinfo((struct sockaddr *) ss, ss_len, shost, sizeof(shost),
- sserv, sizeof(sserv), NI_NUMERICHOST | NI_NUMERICSERV);
- getnameinfo((struct sockaddr *) ps, ps_len, phost, sizeof(phost),
- pserv, sizeof(pserv), NI_NUMERICHOST | NI_NUMERICSERV);
- return g_strdup_printf("%s:%s%s%s:%s%s <-> %s%s%s:%s",
- is_telnet ? "telnet" : "tcp",
- left, shost, right, sserv,
- is_listen ? ",server" : "",
- left, phost, right, pserv);
-
- default:
- return g_strdup_printf("unknown");
- }
-}
-
/***********************************************************/
/* character device */
@@ -1672,640 +1607,7 @@ static void char_udp_finalize(Object *obj)
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
-/***********************************************************/
-/* TCP Net console */
-
-typedef struct {
- Chardev parent;
- QIOChannel *ioc; /* Client I/O channel */
- QIOChannelSocket *sioc; /* Client master channel */
- QIOChannelSocket *listen_ioc;
- guint listen_tag;
- QCryptoTLSCreds *tls_creds;
- int connected;
- int max_size;
- int do_telnetopt;
- int do_nodelay;
- int is_unix;
- int *read_msgfds;
- size_t read_msgfds_num;
- int *write_msgfds;
- size_t write_msgfds_num;
-
- SocketAddress *addr;
- bool is_listen;
- bool is_telnet;
-
- guint reconnect_timer;
- int64_t reconnect_time;
- bool connect_err_reported;
-} SocketChardev;
-
-#define SOCKET_CHARDEV(obj) \
- OBJECT_CHECK(SocketChardev, (obj), TYPE_CHARDEV_SOCKET)
-
-static gboolean socket_reconnect_timeout(gpointer opaque);
-
-static void qemu_chr_socket_restart_timer(Chardev *chr)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
- char *name;
-
- assert(s->connected == 0);
- s->reconnect_timer = g_timeout_add_seconds(s->reconnect_time,
- socket_reconnect_timeout, chr);
- name = g_strdup_printf("chardev-socket-reconnect-%s", chr->label);
- g_source_set_name_by_id(s->reconnect_timer, name);
- g_free(name);
-}
-
-static void check_report_connect_error(Chardev *chr,
- Error *err)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
-
- if (!s->connect_err_reported) {
- error_report("Unable to connect character device %s: %s",
- chr->label, error_get_pretty(err));
- s->connect_err_reported = true;
- }
- qemu_chr_socket_restart_timer(chr);
-}
-
-static gboolean tcp_chr_accept(QIOChannel *chan,
- GIOCondition cond,
- void *opaque);
-
-/* Called with chr_write_lock held. */
-static int tcp_chr_write(Chardev *chr, const uint8_t *buf, int len)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
-
- if (s->connected) {
- int ret = io_channel_send_full(s->ioc, buf, len,
- s->write_msgfds,
- s->write_msgfds_num);
-
- /* free the written msgfds, no matter what */
- if (s->write_msgfds_num) {
- g_free(s->write_msgfds);
- s->write_msgfds = 0;
- s->write_msgfds_num = 0;
- }
-
- return ret;
- } else {
- /* XXX: indicate an error ? */
- return len;
- }
-}
-
-static int tcp_chr_read_poll(void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- SocketChardev *s = SOCKET_CHARDEV(opaque);
- if (!s->connected)
- return 0;
- s->max_size = qemu_chr_be_can_write(chr);
- return s->max_size;
-}
-
-#define IAC 255
-#define IAC_BREAK 243
-static void tcp_chr_process_IAC_bytes(Chardev *chr,
- SocketChardev *s,
- uint8_t *buf, int *size)
-{
- /* Handle any telnet client's basic IAC options to satisfy char by
- * char mode with no echo. All IAC options will be removed from
- * the buf and the do_telnetopt variable will be used to track the
- * state of the width of the IAC information.
- *
- * IAC commands come in sets of 3 bytes with the exception of the
- * "IAC BREAK" command and the double IAC.
- */
-
- int i;
- int j = 0;
-
- for (i = 0; i < *size; i++) {
- if (s->do_telnetopt > 1) {
- if ((unsigned char)buf[i] == IAC && s->do_telnetopt == 2) {
- /* Double IAC means send an IAC */
- if (j != i)
- buf[j] = buf[i];
- j++;
- s->do_telnetopt = 1;
- } else {
- if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) {
- /* Handle IAC break commands by sending a serial break */
- qemu_chr_be_event(chr, CHR_EVENT_BREAK);
- s->do_telnetopt++;
- }
- s->do_telnetopt++;
- }
- if (s->do_telnetopt >= 4) {
- s->do_telnetopt = 1;
- }
- } else {
- if ((unsigned char)buf[i] == IAC) {
- s->do_telnetopt = 2;
- } else {
- if (j != i)
- buf[j] = buf[i];
- j++;
- }
- }
- }
- *size = j;
-}
-
-static int tcp_get_msgfds(Chardev *chr, int *fds, int num)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
-
- int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num;
-
- assert(num <= TCP_MAX_FDS);
-
- if (to_copy) {
- int i;
-
- memcpy(fds, s->read_msgfds, to_copy * sizeof(int));
-
- /* Close unused fds */
- for (i = to_copy; i < s->read_msgfds_num; i++) {
- close(s->read_msgfds[i]);
- }
-
- g_free(s->read_msgfds);
- s->read_msgfds = 0;
- s->read_msgfds_num = 0;
- }
-
- return to_copy;
-}
-
-static int tcp_set_msgfds(Chardev *chr, int *fds, int num)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
-
- /* clear old pending fd array */
- g_free(s->write_msgfds);
- s->write_msgfds = NULL;
- s->write_msgfds_num = 0;
-
- if (!s->connected ||
- !qio_channel_has_feature(s->ioc,
- QIO_CHANNEL_FEATURE_FD_PASS)) {
- return -1;
- }
-
- if (num) {
- s->write_msgfds = g_new(int, num);
- memcpy(s->write_msgfds, fds, num * sizeof(int));
- }
-
- s->write_msgfds_num = num;
-
- return 0;
-}
-
-static ssize_t tcp_chr_recv(Chardev *chr, char *buf, size_t len)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
- struct iovec iov = { .iov_base = buf, .iov_len = len };
- int ret;
- size_t i;
- int *msgfds = NULL;
- size_t msgfds_num = 0;
-
- if (qio_channel_has_feature(s->ioc, QIO_CHANNEL_FEATURE_FD_PASS)) {
- ret = qio_channel_readv_full(s->ioc, &iov, 1,
- &msgfds, &msgfds_num,
- NULL);
- } else {
- ret = qio_channel_readv_full(s->ioc, &iov, 1,
- NULL, NULL,
- NULL);
- }
-
- if (ret == QIO_CHANNEL_ERR_BLOCK) {
- errno = EAGAIN;
- ret = -1;
- } else if (ret == -1) {
- errno = EIO;
- }
-
- if (msgfds_num) {
- /* close and clean read_msgfds */
- for (i = 0; i < s->read_msgfds_num; i++) {
- close(s->read_msgfds[i]);
- }
-
- if (s->read_msgfds_num) {
- g_free(s->read_msgfds);
- }
-
- s->read_msgfds = msgfds;
- s->read_msgfds_num = msgfds_num;
- }
-
- for (i = 0; i < s->read_msgfds_num; i++) {
- int fd = s->read_msgfds[i];
- if (fd < 0) {
- continue;
- }
-
- /* O_NONBLOCK is preserved across SCM_RIGHTS so reset it */
- qemu_set_block(fd);
-
-#ifndef MSG_CMSG_CLOEXEC
- qemu_set_cloexec(fd);
-#endif
- }
-
- return ret;
-}
-
-static GSource *tcp_chr_add_watch(Chardev *chr, GIOCondition cond)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
- return qio_channel_create_watch(s->ioc, cond);
-}
-
-static void tcp_chr_free_connection(Chardev *chr)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
- int i;
-
- if (!s->connected) {
- return;
- }
-
- if (s->read_msgfds_num) {
- for (i = 0; i < s->read_msgfds_num; i++) {
- close(s->read_msgfds[i]);
- }
- g_free(s->read_msgfds);
- s->read_msgfds = NULL;
- s->read_msgfds_num = 0;
- }
-
- tcp_set_msgfds(chr, NULL, 0);
- remove_fd_in_watch(chr);
- object_unref(OBJECT(s->sioc));
- s->sioc = NULL;
- object_unref(OBJECT(s->ioc));
- s->ioc = NULL;
- g_free(chr->filename);
- chr->filename = NULL;
- s->connected = 0;
-}
-
-static void tcp_chr_disconnect(Chardev *chr)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
-
- if (!s->connected) {
- return;
- }
-
- tcp_chr_free_connection(chr);
-
- if (s->listen_ioc) {
- s->listen_tag = qio_channel_add_watch(
- QIO_CHANNEL(s->listen_ioc), G_IO_IN, tcp_chr_accept, chr, NULL);
- }
- chr->filename = SocketAddress_to_str("disconnected:", s->addr,
- s->is_listen, s->is_telnet);
- qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
- if (s->reconnect_time) {
- qemu_chr_socket_restart_timer(chr);
- }
-}
-
-static gboolean tcp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- SocketChardev *s = SOCKET_CHARDEV(opaque);
- uint8_t buf[CHR_READ_BUF_LEN];
- int len, size;
-
- if (!s->connected || s->max_size <= 0) {
- return TRUE;
- }
- len = sizeof(buf);
- if (len > s->max_size)
- len = s->max_size;
- size = tcp_chr_recv(chr, (void *)buf, len);
- if (size == 0 || size == -1) {
- /* connection closed */
- tcp_chr_disconnect(chr);
- } else if (size > 0) {
- if (s->do_telnetopt)
- tcp_chr_process_IAC_bytes(chr, s, buf, &size);
- if (size > 0)
- qemu_chr_be_write(chr, buf, size);
- }
-
- return TRUE;
-}
-
-static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
- int size;
-
- if (!s->connected) {
- return 0;
- }
-
- size = tcp_chr_recv(chr, (void *) buf, len);
- if (size == 0) {
- /* connection closed */
- tcp_chr_disconnect(chr);
- }
-
- return size;
-}
-
-static void tcp_chr_connect(void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- SocketChardev *s = SOCKET_CHARDEV(opaque);
-
- g_free(chr->filename);
- chr->filename = sockaddr_to_str(
- &s->sioc->localAddr, s->sioc->localAddrLen,
- &s->sioc->remoteAddr, s->sioc->remoteAddrLen,
- s->is_listen, s->is_telnet);
-
- s->connected = 1;
- if (s->ioc) {
- chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
- tcp_chr_read_poll,
- tcp_chr_read,
- chr, NULL);
- }
- qemu_chr_be_generic_open(chr);
-}
-
-static void tcp_chr_update_read_handler(Chardev *chr,
- GMainContext *context)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
-
- if (!s->connected) {
- return;
- }
-
- remove_fd_in_watch(chr);
- if (s->ioc) {
- chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
- tcp_chr_read_poll,
- tcp_chr_read, chr,
- context);
- }
-}
-
-typedef struct {
- Chardev *chr;
- char buf[12];
- size_t buflen;
-} TCPChardevTelnetInit;
-
-static gboolean tcp_chr_telnet_init_io(QIOChannel *ioc,
- GIOCondition cond G_GNUC_UNUSED,
- gpointer user_data)
-{
- TCPChardevTelnetInit *init = user_data;
- ssize_t ret;
-
- ret = qio_channel_write(ioc, init->buf, init->buflen, NULL);
- if (ret < 0) {
- if (ret == QIO_CHANNEL_ERR_BLOCK) {
- ret = 0;
- } else {
- tcp_chr_disconnect(init->chr);
- return FALSE;
- }
- }
- init->buflen -= ret;
-
- if (init->buflen == 0) {
- tcp_chr_connect(init->chr);
- return FALSE;
- }
-
- memmove(init->buf, init->buf + ret, init->buflen);
-
- return TRUE;
-}
-
-static void tcp_chr_telnet_init(Chardev *chr)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
- TCPChardevTelnetInit *init = g_new0(TCPChardevTelnetInit, 1);
- size_t n = 0;
-
- init->chr = chr;
- init->buflen = 12;
-
-#define IACSET(x, a, b, c) \
- do { \
- x[n++] = a; \
- x[n++] = b; \
- x[n++] = c; \
- } while (0)
-
- /* Prep the telnet negotion to put telnet in binary,
- * no echo, single char mode */
- IACSET(init->buf, 0xff, 0xfb, 0x01); /* IAC WILL ECHO */
- IACSET(init->buf, 0xff, 0xfb, 0x03); /* IAC WILL Suppress go ahead */
- IACSET(init->buf, 0xff, 0xfb, 0x00); /* IAC WILL Binary */
- IACSET(init->buf, 0xff, 0xfd, 0x00); /* IAC DO Binary */
-
-#undef IACSET
-
- qio_channel_add_watch(
- s->ioc, G_IO_OUT,
- tcp_chr_telnet_init_io,
- init, NULL);
-}
-
-
-static void tcp_chr_tls_handshake(QIOTask *task,
- gpointer user_data)
-{
- Chardev *chr = user_data;
- SocketChardev *s = user_data;
-
- if (qio_task_propagate_error(task, NULL)) {
- tcp_chr_disconnect(chr);
- } else {
- if (s->do_telnetopt) {
- tcp_chr_telnet_init(chr);
- } else {
- tcp_chr_connect(chr);
- }
- }
-}
-
-
-static void tcp_chr_tls_init(Chardev *chr)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
- QIOChannelTLS *tioc;
- Error *err = NULL;
- gchar *name;
-
- if (s->is_listen) {
- tioc = qio_channel_tls_new_server(
- s->ioc, s->tls_creds,
- NULL, /* XXX Use an ACL */
- &err);
- } else {
- tioc = qio_channel_tls_new_client(
- s->ioc, s->tls_creds,
- s->addr->u.inet.data->host,
- &err);
- }
- if (tioc == NULL) {
- error_free(err);
- tcp_chr_disconnect(chr);
- return;
- }
- name = g_strdup_printf("chardev-tls-%s-%s",
- s->is_listen ? "server" : "client",
- chr->label);
- qio_channel_set_name(QIO_CHANNEL(tioc), name);
- g_free(name);
- object_unref(OBJECT(s->ioc));
- s->ioc = QIO_CHANNEL(tioc);
-
- qio_channel_tls_handshake(tioc,
- tcp_chr_tls_handshake,
- chr,
- NULL);
-}
-
-
-static void tcp_chr_set_client_ioc_name(Chardev *chr,
- QIOChannelSocket *sioc)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
- char *name;
- name = g_strdup_printf("chardev-tcp-%s-%s",
- s->is_listen ? "server" : "client",
- chr->label);
- qio_channel_set_name(QIO_CHANNEL(sioc), name);
- g_free(name);
-
-}
-
-static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
-
- if (s->ioc != NULL) {
- return -1;
- }
-
- s->ioc = QIO_CHANNEL(sioc);
- object_ref(OBJECT(sioc));
- s->sioc = sioc;
- object_ref(OBJECT(sioc));
-
- qio_channel_set_blocking(s->ioc, false, NULL);
-
- if (s->do_nodelay) {
- qio_channel_set_delay(s->ioc, false);
- }
- if (s->listen_tag) {
- g_source_remove(s->listen_tag);
- s->listen_tag = 0;
- }
-
- if (s->tls_creds) {
- tcp_chr_tls_init(chr);
- } else {
- if (s->do_telnetopt) {
- tcp_chr_telnet_init(chr);
- } else {
- tcp_chr_connect(chr);
- }
- }
-
- return 0;
-}
-
-
-static int tcp_chr_add_client(Chardev *chr, int fd)
-{
- int ret;
- QIOChannelSocket *sioc;
-
- sioc = qio_channel_socket_new_fd(fd, NULL);
- if (!sioc) {
- return -1;
- }
- tcp_chr_set_client_ioc_name(chr, sioc);
- ret = tcp_chr_new_client(chr, sioc);
- object_unref(OBJECT(sioc));
- return ret;
-}
-
-static gboolean tcp_chr_accept(QIOChannel *channel,
- GIOCondition cond,
- void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- QIOChannelSocket *sioc;
-
- sioc = qio_channel_socket_accept(QIO_CHANNEL_SOCKET(channel),
- NULL);
- if (!sioc) {
- return TRUE;
- }
-
- tcp_chr_new_client(chr, sioc);
-
- object_unref(OBJECT(sioc));
-
- return TRUE;
-}
-
-static int tcp_chr_wait_connected(Chardev *chr, Error **errp)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
- QIOChannelSocket *sioc;
-
- /* It can't wait on s->connected, since it is set asynchronously
- * in TLS and telnet cases, only wait for an accepted socket */
- while (!s->ioc) {
- if (s->is_listen) {
- error_report("QEMU waiting for connection on: %s",
- chr->filename);
- qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), true, NULL);
- tcp_chr_accept(QIO_CHANNEL(s->listen_ioc), G_IO_IN, chr);
- qio_channel_set_blocking(QIO_CHANNEL(s->listen_ioc), false, NULL);
- } else {
- sioc = qio_channel_socket_new();
- tcp_chr_set_client_ioc_name(chr, sioc);
- if (qio_channel_socket_connect_sync(sioc, s->addr, errp) < 0) {
- object_unref(OBJECT(sioc));
- return -1;
- }
- tcp_chr_new_client(chr, sioc);
- object_unref(OBJECT(sioc));
- }
- }
-
- return 0;
-}
-
-static int qemu_chr_wait_connected(Chardev *chr, Error **errp)
+int qemu_chr_wait_connected(Chardev *chr, Error **errp)
{
ChardevClass *cc = CHARDEV_GET_CLASS(chr);
@@ -2326,54 +1628,6 @@ int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp)
return qemu_chr_wait_connected(be->chr, errp);
}
-static void char_socket_finalize(Object *obj)
-{
- Chardev *chr = CHARDEV(obj);
- SocketChardev *s = SOCKET_CHARDEV(obj);
-
- tcp_chr_free_connection(chr);
-
- if (s->reconnect_timer) {
- g_source_remove(s->reconnect_timer);
- s->reconnect_timer = 0;
- }
- qapi_free_SocketAddress(s->addr);
- if (s->listen_tag) {
- g_source_remove(s->listen_tag);
- s->listen_tag = 0;
- }
- if (s->listen_ioc) {
- object_unref(OBJECT(s->listen_ioc));
- }
- if (s->tls_creds) {
- object_unref(OBJECT(s->tls_creds));
- }
-
- qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
-}
-
-
-static void qemu_chr_socket_connected(QIOTask *task, void *opaque)
-{
- QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(qio_task_get_source(task));
- Chardev *chr = CHARDEV(opaque);
- SocketChardev *s = SOCKET_CHARDEV(chr);
- Error *err = NULL;
-
- if (qio_task_propagate_error(task, &err)) {
- check_report_connect_error(chr, err);
- error_free(err);
- goto cleanup;
- }
-
- s->connect_err_reported = false;
- tcp_chr_new_client(chr, sioc);
-
- cleanup:
- object_unref(OBJECT(sioc));
-}
-
-
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
{
char host[65], port[33], width[8], height[8];
@@ -2651,76 +1905,6 @@ static const TypeInfo char_pipe_type_info = {
.class_init = char_pipe_class_init,
};
-static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
- Error **errp)
-{
- bool is_listen = qemu_opt_get_bool(opts, "server", false);
- bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true);
- bool is_telnet = qemu_opt_get_bool(opts, "telnet", false);
- bool do_nodelay = !qemu_opt_get_bool(opts, "delay", true);
- int64_t reconnect = qemu_opt_get_number(opts, "reconnect", 0);
- const char *path = qemu_opt_get(opts, "path");
- const char *host = qemu_opt_get(opts, "host");
- const char *port = qemu_opt_get(opts, "port");
- const char *tls_creds = qemu_opt_get(opts, "tls-creds");
- SocketAddress *addr;
- ChardevSocket *sock;
-
- backend->type = CHARDEV_BACKEND_KIND_SOCKET;
- if (!path) {
- if (!host) {
- error_setg(errp, "chardev: socket: no host given");
- return;
- }
- if (!port) {
- error_setg(errp, "chardev: socket: no port given");
- return;
- }
- } else {
- if (tls_creds) {
- error_setg(errp, "TLS can only be used over TCP socket");
- return;
- }
- }
-
- sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
- qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
-
- sock->has_nodelay = true;
- sock->nodelay = do_nodelay;
- sock->has_server = true;
- sock->server = is_listen;
- sock->has_telnet = true;
- sock->telnet = is_telnet;
- sock->has_wait = true;
- sock->wait = is_waitconnect;
- sock->has_reconnect = true;
- sock->reconnect = reconnect;
- sock->tls_creds = g_strdup(tls_creds);
-
- addr = g_new0(SocketAddress, 1);
- if (path) {
- UnixSocketAddress *q_unix;
- addr->type = SOCKET_ADDRESS_KIND_UNIX;
- q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
- q_unix->path = g_strdup(path);
- } else {
- addr->type = SOCKET_ADDRESS_KIND_INET;
- addr->u.inet.data = g_new(InetSocketAddress, 1);
- *addr->u.inet.data = (InetSocketAddress) {
- .host = g_strdup(host),
- .port = g_strdup(port),
- .has_to = qemu_opt_get(opts, "to"),
- .to = qemu_opt_get_number(opts, "to", 0),
- .has_ipv4 = qemu_opt_get(opts, "ipv4"),
- .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
- .has_ipv6 = qemu_opt_get(opts, "ipv6"),
- .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
- };
- }
- sock->addr = addr;
-}
-
static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
{
@@ -3426,166 +2610,6 @@ static const TypeInfo char_serial_type_info = {
};
#endif
-static gboolean socket_reconnect_timeout(gpointer opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- SocketChardev *s = SOCKET_CHARDEV(opaque);
- QIOChannelSocket *sioc;
-
- s->reconnect_timer = 0;
-
- if (chr->be_open) {
- return false;
- }
-
- sioc = qio_channel_socket_new();
- tcp_chr_set_client_ioc_name(chr, sioc);
- qio_channel_socket_connect_async(sioc, s->addr,
- qemu_chr_socket_connected,
- chr, NULL);
-
- return false;
-}
-
-static void qmp_chardev_open_socket(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- SocketChardev *s = SOCKET_CHARDEV(chr);
- ChardevSocket *sock = backend->u.socket.data;
- SocketAddress *addr = sock->addr;
- bool do_nodelay = sock->has_nodelay ? sock->nodelay : false;
- bool is_listen = sock->has_server ? sock->server : true;
- bool is_telnet = sock->has_telnet ? sock->telnet : false;
- bool is_waitconnect = sock->has_wait ? sock->wait : false;
- int64_t reconnect = sock->has_reconnect ? sock->reconnect : 0;
- QIOChannelSocket *sioc = NULL;
-
- s->is_unix = addr->type == SOCKET_ADDRESS_KIND_UNIX;
- s->is_listen = is_listen;
- s->is_telnet = is_telnet;
- s->do_nodelay = do_nodelay;
- if (sock->tls_creds) {
- Object *creds;
- creds = object_resolve_path_component(
- object_get_objects_root(), sock->tls_creds);
- if (!creds) {
- error_setg(errp, "No TLS credentials with id '%s'",
- sock->tls_creds);
- goto error;
- }
- s->tls_creds = (QCryptoTLSCreds *)
- object_dynamic_cast(creds,
- TYPE_QCRYPTO_TLS_CREDS);
- if (!s->tls_creds) {
- error_setg(errp, "Object with id '%s' is not TLS credentials",
- sock->tls_creds);
- goto error;
- }
- object_ref(OBJECT(s->tls_creds));
- if (is_listen) {
- if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
- error_setg(errp, "%s",
- "Expected TLS credentials for server endpoint");
- goto error;
- }
- } else {
- if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
- error_setg(errp, "%s",
- "Expected TLS credentials for client endpoint");
- goto error;
- }
- }
- }
-
- s->addr = QAPI_CLONE(SocketAddress, sock->addr);
-
- qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE);
- if (s->is_unix) {
- qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS);
- }
-
- /* be isn't opened until we get a connection */
- *be_opened = false;
-
- chr->filename = SocketAddress_to_str("disconnected:",
- addr, is_listen, is_telnet);
-
- if (is_listen) {
- if (is_telnet) {
- s->do_telnetopt = 1;
- }
- } else if (reconnect > 0) {
- s->reconnect_time = reconnect;
- }
-
- if (s->reconnect_time) {
- sioc = qio_channel_socket_new();
- tcp_chr_set_client_ioc_name(chr, sioc);
- qio_channel_socket_connect_async(sioc, s->addr,
- qemu_chr_socket_connected,
- chr, NULL);
- } else {
- if (s->is_listen) {
- char *name;
- sioc = qio_channel_socket_new();
-
- name = g_strdup_printf("chardev-tcp-listener-%s", chr->label);
- qio_channel_set_name(QIO_CHANNEL(sioc), name);
- g_free(name);
-
- if (qio_channel_socket_listen_sync(sioc, s->addr, errp) < 0) {
- goto error;
- }
- s->listen_ioc = sioc;
- if (is_waitconnect &&
- qemu_chr_wait_connected(chr, errp) < 0) {
- return;
- }
- if (!s->ioc) {
- s->listen_tag = qio_channel_add_watch(
- QIO_CHANNEL(s->listen_ioc), G_IO_IN,
- tcp_chr_accept, chr, NULL);
- }
- } else if (qemu_chr_wait_connected(chr, errp) < 0) {
- goto error;
- }
- }
-
- return;
-
-error:
- if (sioc) {
- object_unref(OBJECT(sioc));
- }
-}
-
-static void char_socket_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->parse = qemu_chr_parse_socket;
- cc->open = qmp_chardev_open_socket;
- cc->chr_wait_connected = tcp_chr_wait_connected;
- cc->chr_write = tcp_chr_write;
- cc->chr_sync_read = tcp_chr_sync_read;
- cc->chr_disconnect = tcp_chr_disconnect;
- cc->get_msgfds = tcp_get_msgfds;
- cc->set_msgfds = tcp_set_msgfds;
- cc->chr_add_client = tcp_chr_add_client;
- cc->chr_add_watch = tcp_chr_add_watch;
- cc->chr_update_read_handler = tcp_chr_update_read_handler;
-}
-
-static const TypeInfo char_socket_type_info = {
- .name = TYPE_CHARDEV_SOCKET,
- .parent = TYPE_CHARDEV,
- .instance_size = sizeof(SocketChardev),
- .instance_finalize = char_socket_finalize,
- .class_init = char_socket_class_init,
-};
-
static void qmp_chardev_open_udp(Chardev *chr,
ChardevBackend *backend,
bool *be_opened,
@@ -3731,7 +2755,6 @@ void qemu_chr_cleanup(void)
static void register_types(void)
{
type_register_static(&char_type_info);
- type_register_static(&char_socket_type_info);
type_register_static(&char_udp_type_info);
type_register_static(&char_file_type_info);
type_register_static(&char_stdio_type_info);
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index 3c4a328de8..c57c375d5b 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -4,5 +4,6 @@ chardev-obj-y += char-io.o
chardev-obj-y += char-mux.o
chardev-obj-y += char-null.o
chardev-obj-y += char-ringbuf.o
+chardev-obj-y += char-socket.o
chardev-obj-$(CONFIG_WIN32) += char-win.o
chardev-obj-$(CONFIG_WIN32) += char-win-stdio.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 33/41] char: move udp chardev in its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (31 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 32/41] char: move socket chardev to " Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 34/41] char: move file " Marc-André Lureau
` (9 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
---
chardev/char-udp.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 198 ------------------------------------------
chardev/Makefile.objs | 1 +
3 files changed, 234 insertions(+), 198 deletions(-)
create mode 100644 chardev/char-udp.c
diff --git a/chardev/char-udp.c b/chardev/char-udp.c
new file mode 100644
index 0000000000..2c6c7ddd73
--- /dev/null
+++ b/chardev/char-udp.c
@@ -0,0 +1,233 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "sysemu/char.h"
+#include "io/channel-socket.h"
+#include "qapi/error.h"
+
+#include "char-io.h"
+
+/***********************************************************/
+/* UDP Net console */
+
+typedef struct {
+ Chardev parent;
+ QIOChannel *ioc;
+ uint8_t buf[CHR_READ_BUF_LEN];
+ int bufcnt;
+ int bufptr;
+ int max_size;
+} UdpChardev;
+
+#define UDP_CHARDEV(obj) OBJECT_CHECK(UdpChardev, (obj), TYPE_CHARDEV_UDP)
+
+/* Called with chr_write_lock held. */
+static int udp_chr_write(Chardev *chr, const uint8_t *buf, int len)
+{
+ UdpChardev *s = UDP_CHARDEV(chr);
+
+ return qio_channel_write(
+ s->ioc, (const char *)buf, len, NULL);
+}
+
+static int udp_chr_read_poll(void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ UdpChardev *s = UDP_CHARDEV(opaque);
+
+ s->max_size = qemu_chr_be_can_write(chr);
+
+ /* If there were any stray characters in the queue process them
+ * first
+ */
+ while (s->max_size > 0 && s->bufptr < s->bufcnt) {
+ qemu_chr_be_write(chr, &s->buf[s->bufptr], 1);
+ s->bufptr++;
+ s->max_size = qemu_chr_be_can_write(chr);
+ }
+ return s->max_size;
+}
+
+static gboolean udp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ UdpChardev *s = UDP_CHARDEV(opaque);
+ ssize_t ret;
+
+ if (s->max_size == 0) {
+ return TRUE;
+ }
+ ret = qio_channel_read(
+ s->ioc, (char *)s->buf, sizeof(s->buf), NULL);
+ if (ret <= 0) {
+ remove_fd_in_watch(chr);
+ return FALSE;
+ }
+ s->bufcnt = ret;
+
+ s->bufptr = 0;
+ while (s->max_size > 0 && s->bufptr < s->bufcnt) {
+ qemu_chr_be_write(chr, &s->buf[s->bufptr], 1);
+ s->bufptr++;
+ s->max_size = qemu_chr_be_can_write(chr);
+ }
+
+ return TRUE;
+}
+
+static void udp_chr_update_read_handler(Chardev *chr,
+ GMainContext *context)
+{
+ UdpChardev *s = UDP_CHARDEV(chr);
+
+ remove_fd_in_watch(chr);
+ if (s->ioc) {
+ chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
+ udp_chr_read_poll,
+ udp_chr_read, chr,
+ context);
+ }
+}
+
+static void char_udp_finalize(Object *obj)
+{
+ Chardev *chr = CHARDEV(obj);
+ UdpChardev *s = UDP_CHARDEV(obj);
+
+ remove_fd_in_watch(chr);
+ if (s->ioc) {
+ object_unref(OBJECT(s->ioc));
+ }
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+}
+
+static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
+{
+ const char *host = qemu_opt_get(opts, "host");
+ const char *port = qemu_opt_get(opts, "port");
+ const char *localaddr = qemu_opt_get(opts, "localaddr");
+ const char *localport = qemu_opt_get(opts, "localport");
+ bool has_local = false;
+ SocketAddress *addr;
+ ChardevUdp *udp;
+
+ backend->type = CHARDEV_BACKEND_KIND_UDP;
+ if (host == NULL || strlen(host) == 0) {
+ host = "localhost";
+ }
+ if (port == NULL || strlen(port) == 0) {
+ error_setg(errp, "chardev: udp: remote port not specified");
+ return;
+ }
+ if (localport == NULL || strlen(localport) == 0) {
+ localport = "0";
+ } else {
+ has_local = true;
+ }
+ if (localaddr == NULL || strlen(localaddr) == 0) {
+ localaddr = "";
+ } else {
+ has_local = true;
+ }
+
+ udp = backend->u.udp.data = g_new0(ChardevUdp, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevUdp_base(udp));
+
+ addr = g_new0(SocketAddress, 1);
+ addr->type = SOCKET_ADDRESS_KIND_INET;
+ addr->u.inet.data = g_new(InetSocketAddress, 1);
+ *addr->u.inet.data = (InetSocketAddress) {
+ .host = g_strdup(host),
+ .port = g_strdup(port),
+ .has_ipv4 = qemu_opt_get(opts, "ipv4"),
+ .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
+ .has_ipv6 = qemu_opt_get(opts, "ipv6"),
+ .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
+ };
+ udp->remote = addr;
+
+ if (has_local) {
+ udp->has_local = true;
+ addr = g_new0(SocketAddress, 1);
+ addr->type = SOCKET_ADDRESS_KIND_INET;
+ addr->u.inet.data = g_new(InetSocketAddress, 1);
+ *addr->u.inet.data = (InetSocketAddress) {
+ .host = g_strdup(localaddr),
+ .port = g_strdup(localport),
+ };
+ udp->local = addr;
+ }
+}
+
+static void qmp_chardev_open_udp(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ ChardevUdp *udp = backend->u.udp.data;
+ QIOChannelSocket *sioc = qio_channel_socket_new();
+ char *name;
+ UdpChardev *s = UDP_CHARDEV(chr);
+
+ if (qio_channel_socket_dgram_sync(sioc,
+ udp->local, udp->remote,
+ errp) < 0) {
+ object_unref(OBJECT(sioc));
+ return;
+ }
+
+ name = g_strdup_printf("chardev-udp-%s", chr->label);
+ qio_channel_set_name(QIO_CHANNEL(sioc), name);
+ g_free(name);
+
+ s->ioc = QIO_CHANNEL(sioc);
+ /* be isn't opened until we get a connection */
+ *be_opened = false;
+}
+
+static void char_udp_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->parse = qemu_chr_parse_udp;
+ cc->open = qmp_chardev_open_udp;
+ cc->chr_write = udp_chr_write;
+ cc->chr_update_read_handler = udp_chr_update_read_handler;
+}
+
+static const TypeInfo char_udp_type_info = {
+ .name = TYPE_CHARDEV_UDP,
+ .parent = TYPE_CHARDEV,
+ .instance_size = sizeof(UdpChardev),
+ .instance_finalize = char_udp_finalize,
+ .class_init = char_udp_class_init,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_udp_type_info);
+}
+
+type_init(register_types);
diff --git a/chardev/char.c b/chardev/char.c
index 73b6663aa4..05fceb0d73 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -1513,100 +1513,6 @@ static const TypeInfo char_console_type_info = {
#endif /* !_WIN32 */
-/***********************************************************/
-/* UDP Net console */
-
-typedef struct {
- Chardev parent;
- QIOChannel *ioc;
- uint8_t buf[CHR_READ_BUF_LEN];
- int bufcnt;
- int bufptr;
- int max_size;
-} UdpChardev;
-
-#define UDP_CHARDEV(obj) OBJECT_CHECK(UdpChardev, (obj), TYPE_CHARDEV_UDP)
-
-/* Called with chr_write_lock held. */
-static int udp_chr_write(Chardev *chr, const uint8_t *buf, int len)
-{
- UdpChardev *s = UDP_CHARDEV(chr);
-
- return qio_channel_write(
- s->ioc, (const char *)buf, len, NULL);
-}
-
-static int udp_chr_read_poll(void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- UdpChardev *s = UDP_CHARDEV(opaque);
-
- s->max_size = qemu_chr_be_can_write(chr);
-
- /* If there were any stray characters in the queue process them
- * first
- */
- while (s->max_size > 0 && s->bufptr < s->bufcnt) {
- qemu_chr_be_write(chr, &s->buf[s->bufptr], 1);
- s->bufptr++;
- s->max_size = qemu_chr_be_can_write(chr);
- }
- return s->max_size;
-}
-
-static gboolean udp_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- UdpChardev *s = UDP_CHARDEV(opaque);
- ssize_t ret;
-
- if (s->max_size == 0) {
- return TRUE;
- }
- ret = qio_channel_read(
- s->ioc, (char *)s->buf, sizeof(s->buf), NULL);
- if (ret <= 0) {
- remove_fd_in_watch(chr);
- return FALSE;
- }
- s->bufcnt = ret;
-
- s->bufptr = 0;
- while (s->max_size > 0 && s->bufptr < s->bufcnt) {
- qemu_chr_be_write(chr, &s->buf[s->bufptr], 1);
- s->bufptr++;
- s->max_size = qemu_chr_be_can_write(chr);
- }
-
- return TRUE;
-}
-
-static void udp_chr_update_read_handler(Chardev *chr,
- GMainContext *context)
-{
- UdpChardev *s = UDP_CHARDEV(chr);
-
- remove_fd_in_watch(chr);
- if (s->ioc) {
- chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
- udp_chr_read_poll,
- udp_chr_read, chr,
- context);
- }
-}
-
-static void char_udp_finalize(Object *obj)
-{
- Chardev *chr = CHARDEV(obj);
- UdpChardev *s = UDP_CHARDEV(obj);
-
- remove_fd_in_watch(chr);
- if (s->ioc) {
- object_unref(OBJECT(s->ioc));
- }
- qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
-}
-
int qemu_chr_wait_connected(Chardev *chr, Error **errp)
{
ChardevClass *cc = CHARDEV_GET_CLASS(chr);
@@ -1905,65 +1811,6 @@ static const TypeInfo char_pipe_type_info = {
.class_init = char_pipe_class_init,
};
-static void qemu_chr_parse_udp(QemuOpts *opts, ChardevBackend *backend,
- Error **errp)
-{
- const char *host = qemu_opt_get(opts, "host");
- const char *port = qemu_opt_get(opts, "port");
- const char *localaddr = qemu_opt_get(opts, "localaddr");
- const char *localport = qemu_opt_get(opts, "localport");
- bool has_local = false;
- SocketAddress *addr;
- ChardevUdp *udp;
-
- backend->type = CHARDEV_BACKEND_KIND_UDP;
- if (host == NULL || strlen(host) == 0) {
- host = "localhost";
- }
- if (port == NULL || strlen(port) == 0) {
- error_setg(errp, "chardev: udp: remote port not specified");
- return;
- }
- if (localport == NULL || strlen(localport) == 0) {
- localport = "0";
- } else {
- has_local = true;
- }
- if (localaddr == NULL || strlen(localaddr) == 0) {
- localaddr = "";
- } else {
- has_local = true;
- }
-
- udp = backend->u.udp.data = g_new0(ChardevUdp, 1);
- qemu_chr_parse_common(opts, qapi_ChardevUdp_base(udp));
-
- addr = g_new0(SocketAddress, 1);
- addr->type = SOCKET_ADDRESS_KIND_INET;
- addr->u.inet.data = g_new(InetSocketAddress, 1);
- *addr->u.inet.data = (InetSocketAddress) {
- .host = g_strdup(host),
- .port = g_strdup(port),
- .has_ipv4 = qemu_opt_get(opts, "ipv4"),
- .ipv4 = qemu_opt_get_bool(opts, "ipv4", 0),
- .has_ipv6 = qemu_opt_get(opts, "ipv6"),
- .ipv6 = qemu_opt_get_bool(opts, "ipv6", 0),
- };
- udp->remote = addr;
-
- if (has_local) {
- udp->has_local = true;
- addr = g_new0(SocketAddress, 1);
- addr->type = SOCKET_ADDRESS_KIND_INET;
- addr->u.inet.data = g_new(InetSocketAddress, 1);
- *addr->u.inet.data = (InetSocketAddress) {
- .host = g_strdup(localaddr),
- .port = g_strdup(localport),
- };
- udp->local = addr;
- }
-}
-
static const ChardevClass *char_get_class(const char *driver, Error **errp)
{
ObjectClass *oc;
@@ -2610,50 +2457,6 @@ static const TypeInfo char_serial_type_info = {
};
#endif
-static void qmp_chardev_open_udp(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- ChardevUdp *udp = backend->u.udp.data;
- QIOChannelSocket *sioc = qio_channel_socket_new();
- char *name;
- UdpChardev *s = UDP_CHARDEV(chr);
-
- if (qio_channel_socket_dgram_sync(sioc,
- udp->local, udp->remote,
- errp) < 0) {
- object_unref(OBJECT(sioc));
- return;
- }
-
- name = g_strdup_printf("chardev-udp-%s", chr->label);
- qio_channel_set_name(QIO_CHANNEL(sioc), name);
- g_free(name);
-
- s->ioc = QIO_CHANNEL(sioc);
- /* be isn't opened until we get a connection */
- *be_opened = false;
-}
-
-static void char_udp_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->parse = qemu_chr_parse_udp;
- cc->open = qmp_chardev_open_udp;
- cc->chr_write = udp_chr_write;
- cc->chr_update_read_handler = udp_chr_update_read_handler;
-}
-
-static const TypeInfo char_udp_type_info = {
- .name = TYPE_CHARDEV_UDP,
- .parent = TYPE_CHARDEV,
- .instance_size = sizeof(UdpChardev),
- .instance_finalize = char_udp_finalize,
- .class_init = char_udp_class_init,
-};
-
bool qemu_chr_has_feature(Chardev *chr,
ChardevFeature feature)
{
@@ -2755,7 +2558,6 @@ void qemu_chr_cleanup(void)
static void register_types(void)
{
type_register_static(&char_type_info);
- type_register_static(&char_udp_type_info);
type_register_static(&char_file_type_info);
type_register_static(&char_stdio_type_info);
#ifdef HAVE_CHARDEV_SERIAL
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index c57c375d5b..dddef029e7 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -5,5 +5,6 @@ chardev-obj-y += char-mux.o
chardev-obj-y += char-null.o
chardev-obj-y += char-ringbuf.o
chardev-obj-y += char-socket.o
+chardev-obj-y += char-udp.o
chardev-obj-$(CONFIG_WIN32) += char-win.o
chardev-obj-$(CONFIG_WIN32) += char-win-stdio.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 34/41] char: move file chardev in its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (32 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 33/41] char: move udp chardev in " Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 35/41] char: move stdio " Marc-André Lureau
` (8 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
---
chardev/char-file.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 106 --------------------------------------
chardev/Makefile.objs | 1 +
3 files changed, 140 insertions(+), 106 deletions(-)
create mode 100644 chardev/char-file.c
diff --git a/chardev/char-file.c b/chardev/char-file.c
new file mode 100644
index 0000000000..8bae25350d
--- /dev/null
+++ b/chardev/char-file.c
@@ -0,0 +1,139 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "sysemu/char.h"
+
+#ifdef _WIN32
+#include "char-win.h"
+#else
+#include "char-fd.h"
+#endif
+
+static void qmp_chardev_open_file(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ ChardevFile *file = backend->u.file.data;
+#ifdef _WIN32
+ HANDLE out;
+ DWORD accessmode;
+ DWORD flags;
+
+ if (file->has_in) {
+ error_setg(errp, "input file not supported");
+ return;
+ }
+
+ if (file->has_append && file->append) {
+ /* Append to file if it already exists. */
+ accessmode = FILE_GENERIC_WRITE & ~FILE_WRITE_DATA;
+ flags = OPEN_ALWAYS;
+ } else {
+ /* Truncate file if it already exists. */
+ accessmode = GENERIC_WRITE;
+ flags = CREATE_ALWAYS;
+ }
+
+ out = CreateFile(file->out, accessmode, FILE_SHARE_READ, NULL, flags,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (out == INVALID_HANDLE_VALUE) {
+ error_setg(errp, "open %s failed", file->out);
+ return;
+ }
+
+ qemu_chr_open_win_file(chr, out);
+#else
+ int flags, in = -1, out;
+
+ flags = O_WRONLY | O_CREAT | O_BINARY;
+ if (file->has_append && file->append) {
+ flags |= O_APPEND;
+ } else {
+ flags |= O_TRUNC;
+ }
+
+ out = qmp_chardev_open_file_source(file->out, flags, errp);
+ if (out < 0) {
+ return;
+ }
+
+ if (file->has_in) {
+ flags = O_RDONLY;
+ in = qmp_chardev_open_file_source(file->in, flags, errp);
+ if (in < 0) {
+ qemu_close(out);
+ return;
+ }
+ }
+
+ qemu_chr_open_fd(chr, in, out);
+#endif
+}
+
+static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
+{
+ const char *path = qemu_opt_get(opts, "path");
+ ChardevFile *file;
+
+ backend->type = CHARDEV_BACKEND_KIND_FILE;
+ if (path == NULL) {
+ error_setg(errp, "chardev: file: no filename given");
+ return;
+ }
+ file = backend->u.file.data = g_new0(ChardevFile, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevFile_base(file));
+ file->out = g_strdup(path);
+
+ file->has_append = true;
+ file->append = qemu_opt_get_bool(opts, "append", false);
+}
+
+static void char_file_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->parse = qemu_chr_parse_file_out;
+ cc->open = qmp_chardev_open_file;
+}
+
+static const TypeInfo char_file_type_info = {
+ .name = TYPE_CHARDEV_FILE,
+#ifdef _WIN32
+ .parent = TYPE_CHARDEV_WIN,
+#else
+ .parent = TYPE_CHARDEV_FD,
+#endif
+ .class_init = char_file_class_init,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_file_type_info);
+}
+
+type_init(register_types);
diff --git a/chardev/char.c b/chardev/char.c
index 05fceb0d73..7ec867ffc8 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -1687,26 +1687,6 @@ void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend)
backend->logappend = qemu_opt_get_bool(opts, "logappend", false);
}
-
-static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
- Error **errp)
-{
- const char *path = qemu_opt_get(opts, "path");
- ChardevFile *file;
-
- backend->type = CHARDEV_BACKEND_KIND_FILE;
- if (path == NULL) {
- error_setg(errp, "chardev: file: no filename given");
- return;
- }
- file = backend->u.file.data = g_new0(ChardevFile, 1);
- qemu_chr_parse_common(opts, qapi_ChardevFile_base(file));
- file->out = g_strdup(path);
-
- file->has_append = true;
- file->append = qemu_opt_get_bool(opts, "append", false);
-}
-
static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
{
@@ -2260,41 +2240,6 @@ QemuOptsList qemu_chardev_opts = {
#ifdef _WIN32
-static void qmp_chardev_open_file(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- ChardevFile *file = backend->u.file.data;
- HANDLE out;
- DWORD accessmode;
- DWORD flags;
-
- if (file->has_in) {
- error_setg(errp, "input file not supported");
- return;
- }
-
- if (file->has_append && file->append) {
- /* Append to file if it already exists. */
- accessmode = FILE_GENERIC_WRITE & ~FILE_WRITE_DATA;
- flags = OPEN_ALWAYS;
- } else {
- /* Truncate file if it already exists. */
- accessmode = GENERIC_WRITE;
- flags = CREATE_ALWAYS;
- }
-
- out = CreateFile(file->out, accessmode, FILE_SHARE_READ, NULL, flags,
- FILE_ATTRIBUTE_NORMAL, NULL);
- if (out == INVALID_HANDLE_VALUE) {
- error_setg(errp, "open %s failed", file->out);
- return;
- }
-
- qemu_chr_open_win_file(chr, out);
-}
-
static void qmp_chardev_open_serial(Chardev *chr,
ChardevBackend *backend,
bool *be_opened,
@@ -2307,38 +2252,6 @@ static void qmp_chardev_open_serial(Chardev *chr,
#else /* WIN32 */
-static void qmp_chardev_open_file(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- ChardevFile *file = backend->u.file.data;
- int flags, in = -1, out;
-
- flags = O_WRONLY | O_CREAT | O_BINARY;
- if (file->has_append && file->append) {
- flags |= O_APPEND;
- } else {
- flags |= O_TRUNC;
- }
-
- out = qmp_chardev_open_file_source(file->out, flags, errp);
- if (out < 0) {
- return;
- }
-
- if (file->has_in) {
- flags = O_RDONLY;
- in = qmp_chardev_open_file_source(file->in, flags, errp);
- if (in < 0) {
- qemu_close(out);
- return;
- }
- }
-
- qemu_chr_open_fd(chr, in, out);
-}
-
#ifdef HAVE_CHARDEV_SERIAL
static void qmp_chardev_open_serial(Chardev *chr,
ChardevBackend *backend,
@@ -2415,24 +2328,6 @@ static const TypeInfo char_parallel_type_info = {
#endif /* WIN32 */
-static void char_file_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->parse = qemu_chr_parse_file_out;
- cc->open = qmp_chardev_open_file;
-}
-
-static const TypeInfo char_file_type_info = {
- .name = TYPE_CHARDEV_FILE,
-#ifdef _WIN32
- .parent = TYPE_CHARDEV_WIN,
-#else
- .parent = TYPE_CHARDEV_FD,
-#endif
- .class_init = char_file_class_init,
-};
-
#ifdef HAVE_CHARDEV_SERIAL
static void char_serial_class_init(ObjectClass *oc, void *data)
@@ -2558,7 +2453,6 @@ void qemu_chr_cleanup(void)
static void register_types(void)
{
type_register_static(&char_type_info);
- type_register_static(&char_file_type_info);
type_register_static(&char_stdio_type_info);
#ifdef HAVE_CHARDEV_SERIAL
type_register_static(&char_serial_type_info);
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index dddef029e7..0051a7a819 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -1,5 +1,6 @@
chardev-obj-y += char.o
chardev-obj-$(CONFIG_POSIX) += char-fd.o
+chardev-obj-y += char-file.o
chardev-obj-y += char-io.o
chardev-obj-y += char-mux.o
chardev-obj-y += char-null.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 35/41] char: move stdio in its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (33 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 34/41] char: move file " Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 36/41] char: move console " Marc-André Lureau
` (7 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
---
chardev/char-stdio.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 120 ------------------------------------
chardev/Makefile.objs | 1 +
3 files changed, 165 insertions(+), 120 deletions(-)
create mode 100644 chardev/char-stdio.c
diff --git a/chardev/char-stdio.c b/chardev/char-stdio.c
new file mode 100644
index 0000000000..be4a65962c
--- /dev/null
+++ b/chardev/char-stdio.c
@@ -0,0 +1,164 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qemu/sockets.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "sysemu/char.h"
+
+#ifdef _WIN32
+#include "char-win.h"
+#include "char-win-stdio.h"
+#else
+#include <termios.h>
+#include "char-fd.h"
+#endif
+
+#ifndef _WIN32
+/* init terminal so that we can grab keys */
+static struct termios oldtty;
+static int old_fd0_flags;
+static bool stdio_in_use;
+static bool stdio_allow_signal;
+static bool stdio_echo_state;
+
+static void term_exit(void)
+{
+ tcsetattr(0, TCSANOW, &oldtty);
+ fcntl(0, F_SETFL, old_fd0_flags);
+}
+
+static void qemu_chr_set_echo_stdio(Chardev *chr, bool echo)
+{
+ struct termios tty;
+
+ stdio_echo_state = echo;
+ tty = oldtty;
+ if (!echo) {
+ tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
+ | INLCR | IGNCR | ICRNL | IXON);
+ tty.c_oflag |= OPOST;
+ tty.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
+ tty.c_cflag &= ~(CSIZE | PARENB);
+ tty.c_cflag |= CS8;
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VTIME] = 0;
+ }
+ if (!stdio_allow_signal) {
+ tty.c_lflag &= ~ISIG;
+ }
+
+ tcsetattr(0, TCSANOW, &tty);
+}
+
+static void term_stdio_handler(int sig)
+{
+ /* restore echo after resume from suspend. */
+ qemu_chr_set_echo_stdio(NULL, stdio_echo_state);
+}
+
+static void qemu_chr_open_stdio(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ ChardevStdio *opts = backend->u.stdio.data;
+ struct sigaction act;
+
+ if (is_daemonized()) {
+ error_setg(errp, "cannot use stdio with -daemonize");
+ return;
+ }
+
+ if (stdio_in_use) {
+ error_setg(errp, "cannot use stdio by multiple character devices");
+ return;
+ }
+
+ stdio_in_use = true;
+ old_fd0_flags = fcntl(0, F_GETFL);
+ tcgetattr(0, &oldtty);
+ qemu_set_nonblock(0);
+ atexit(term_exit);
+
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = term_stdio_handler;
+ sigaction(SIGCONT, &act, NULL);
+
+ qemu_chr_open_fd(chr, 0, 1);
+
+ if (opts->has_signal) {
+ stdio_allow_signal = opts->signal;
+ }
+ qemu_chr_set_echo_stdio(chr, false);
+}
+#endif
+
+static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
+{
+ ChardevStdio *stdio;
+
+ backend->type = CHARDEV_BACKEND_KIND_STDIO;
+ stdio = backend->u.stdio.data = g_new0(ChardevStdio, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevStdio_base(stdio));
+ stdio->has_signal = true;
+ stdio->signal = qemu_opt_get_bool(opts, "signal", true);
+}
+
+static void char_stdio_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->parse = qemu_chr_parse_stdio;
+#ifndef _WIN32
+ cc->open = qemu_chr_open_stdio;
+ cc->chr_set_echo = qemu_chr_set_echo_stdio;
+#endif
+}
+
+static void char_stdio_finalize(Object *obj)
+{
+#ifndef _WIN32
+ term_exit();
+#endif
+}
+
+static const TypeInfo char_stdio_type_info = {
+ .name = TYPE_CHARDEV_STDIO,
+#ifdef _WIN32
+ .parent = TYPE_CHARDEV_WIN_STDIO,
+#else
+ .parent = TYPE_CHARDEV_FD,
+#endif
+ .instance_finalize = char_stdio_finalize,
+ .class_init = char_stdio_class_init,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_stdio_type_info);
+}
+
+type_init(register_types);
diff --git a/chardev/char.c b/chardev/char.c
index 7ec867ffc8..e93dfb8d86 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -90,7 +90,6 @@
#include "char-io.h"
#ifdef _WIN32
#include "char-win.h"
-#include "char-win-stdio.h"
#endif
/***********************************************************/
@@ -687,90 +686,6 @@ static void qemu_chr_open_pipe(Chardev *chr,
qemu_chr_open_fd(chr, fd_in, fd_out);
}
-/* init terminal so that we can grab keys */
-static struct termios oldtty;
-static int old_fd0_flags;
-static bool stdio_in_use;
-static bool stdio_allow_signal;
-static bool stdio_echo_state;
-
-static void qemu_chr_set_echo_stdio(Chardev *chr, bool echo);
-
-static void term_exit(void)
-{
- tcsetattr (0, TCSANOW, &oldtty);
- fcntl(0, F_SETFL, old_fd0_flags);
-}
-
-static void term_stdio_handler(int sig)
-{
- /* restore echo after resume from suspend. */
- qemu_chr_set_echo_stdio(NULL, stdio_echo_state);
-}
-
-static void qemu_chr_set_echo_stdio(Chardev *chr, bool echo)
-{
- struct termios tty;
-
- stdio_echo_state = echo;
- tty = oldtty;
- if (!echo) {
- tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
- |INLCR|IGNCR|ICRNL|IXON);
- tty.c_oflag |= OPOST;
- tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
- tty.c_cflag &= ~(CSIZE|PARENB);
- tty.c_cflag |= CS8;
- tty.c_cc[VMIN] = 1;
- tty.c_cc[VTIME] = 0;
- }
- if (!stdio_allow_signal)
- tty.c_lflag &= ~ISIG;
-
- tcsetattr (0, TCSANOW, &tty);
-}
-
-static void char_stdio_finalize(Object *obj)
-{
- term_exit();
-}
-
-static void qemu_chr_open_stdio(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- ChardevStdio *opts = backend->u.stdio.data;
- struct sigaction act;
-
- if (is_daemonized()) {
- error_setg(errp, "cannot use stdio with -daemonize");
- return;
- }
-
- if (stdio_in_use) {
- error_setg(errp, "cannot use stdio by multiple character devices");
- return;
- }
-
- stdio_in_use = true;
- old_fd0_flags = fcntl(0, F_GETFL);
- tcgetattr(0, &oldtty);
- qemu_set_nonblock(0);
- atexit(term_exit);
-
- memset(&act, 0, sizeof(act));
- act.sa_handler = term_stdio_handler;
- sigaction(SIGCONT, &act, NULL);
-
- qemu_chr_open_fd(chr, 0, 1);
-
- if (opts->has_signal) {
- stdio_allow_signal = opts->signal;
- }
- qemu_chr_set_echo_stdio(chr, false);
-}
-
#if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
|| defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
|| defined(__GLIBC__)
@@ -1687,40 +1602,6 @@ void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend)
backend->logappend = qemu_opt_get_bool(opts, "logappend", false);
}
-static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend,
- Error **errp)
-{
- ChardevStdio *stdio;
-
- backend->type = CHARDEV_BACKEND_KIND_STDIO;
- stdio = backend->u.stdio.data = g_new0(ChardevStdio, 1);
- qemu_chr_parse_common(opts, qapi_ChardevStdio_base(stdio));
- stdio->has_signal = true;
- stdio->signal = qemu_opt_get_bool(opts, "signal", true);
-}
-
-static void char_stdio_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->parse = qemu_chr_parse_stdio;
-#ifndef _WIN32
- cc->open = qemu_chr_open_stdio;
- cc->chr_set_echo = qemu_chr_set_echo_stdio;
-#endif
-}
-
-static const TypeInfo char_stdio_type_info = {
- .name = TYPE_CHARDEV_STDIO,
-#ifdef _WIN32
- .parent = TYPE_CHARDEV_WIN_STDIO,
-#else
- .parent = TYPE_CHARDEV_FD,
- .instance_finalize = char_stdio_finalize,
-#endif
- .class_init = char_stdio_class_init,
-};
-
#ifdef HAVE_CHARDEV_SERIAL
static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
@@ -2453,7 +2334,6 @@ void qemu_chr_cleanup(void)
static void register_types(void)
{
type_register_static(&char_type_info);
- type_register_static(&char_stdio_type_info);
#ifdef HAVE_CHARDEV_SERIAL
type_register_static(&char_serial_type_info);
#endif
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index 0051a7a819..ee40e8a1d7 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -6,6 +6,7 @@ chardev-obj-y += char-mux.o
chardev-obj-y += char-null.o
chardev-obj-y += char-ringbuf.o
chardev-obj-y += char-socket.o
+chardev-obj-y += char-stdio.o
chardev-obj-y += char-udp.o
chardev-obj-$(CONFIG_WIN32) += char-win.o
chardev-obj-$(CONFIG_WIN32) += char-win-stdio.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 36/41] char: move console in its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (34 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 35/41] char: move stdio " Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 37/41] char: move pipe chardev " Marc-André Lureau
` (6 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
---
chardev/char-console.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 3 ---
chardev/Makefile.objs | 1 +
3 files changed, 54 insertions(+), 3 deletions(-)
create mode 100644 chardev/char-console.c
diff --git a/chardev/char-console.c b/chardev/char-console.c
new file mode 100644
index 0000000000..c824937fe6
--- /dev/null
+++ b/chardev/char-console.c
@@ -0,0 +1,53 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "char-win.h"
+
+static void qemu_chr_open_win_con(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ qemu_chr_open_win_file(chr, GetStdHandle(STD_OUTPUT_HANDLE));
+}
+
+static void char_console_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->open = qemu_chr_open_win_con;
+}
+
+static const TypeInfo char_console_type_info = {
+ .name = TYPE_CHARDEV_CONSOLE,
+ .parent = TYPE_CHARDEV_WIN,
+ .class_init = char_console_class_init,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_console_type_info);
+}
+
+type_init(register_types);
diff --git a/chardev/char.c b/chardev/char.c
index e93dfb8d86..8ae8b5a4c3 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -2343,9 +2343,6 @@ static void register_types(void)
#ifdef HAVE_CHARDEV_PTY
type_register_static(&char_pty_type_info);
#endif
-#ifdef _WIN32
- type_register_static(&char_console_type_info);
-#endif
type_register_static(&char_pipe_type_info);
/* this must be done after machine init, since we register FEs with muxes
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index ee40e8a1d7..265a6dad5d 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -1,4 +1,5 @@
chardev-obj-y += char.o
+chardev-obj-$(CONFIG_WIN32) += char-console.o
chardev-obj-$(CONFIG_POSIX) += char-fd.o
chardev-obj-y += char-file.o
chardev-obj-y += char-io.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 37/41] char: move pipe chardev in its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (35 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 36/41] char: move console " Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 38/41] char: move pty " Marc-André Lureau
` (5 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
---
chardev/char-pipe.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 166 -------------------------------------------
chardev/Makefile.objs | 1 +
3 files changed, 192 insertions(+), 166 deletions(-)
create mode 100644 chardev/char-pipe.c
diff --git a/chardev/char-pipe.c b/chardev/char-pipe.c
new file mode 100644
index 0000000000..54240c863d
--- /dev/null
+++ b/chardev/char-pipe.c
@@ -0,0 +1,191 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "sysemu/char.h"
+
+#ifdef _WIN32
+#include "char-win.h"
+#else
+#include "char-fd.h"
+#endif
+
+#ifdef _WIN32
+#define MAXCONNECT 1
+#define NTIMEOUT 5000
+
+static int win_chr_pipe_init(Chardev *chr, const char *filename,
+ Error **errp)
+{
+ WinChardev *s = WIN_CHARDEV(chr);
+ OVERLAPPED ov;
+ int ret;
+ DWORD size;
+ char *openname;
+
+ s->fpipe = TRUE;
+
+ s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (!s->hsend) {
+ error_setg(errp, "Failed CreateEvent");
+ goto fail;
+ }
+ s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (!s->hrecv) {
+ error_setg(errp, "Failed CreateEvent");
+ goto fail;
+ }
+
+ openname = g_strdup_printf("\\\\.\\pipe\\%s", filename);
+ s->hcom = CreateNamedPipe(openname,
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
+ PIPE_TYPE_BYTE | PIPE_READMODE_BYTE |
+ PIPE_WAIT,
+ MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL);
+ g_free(openname);
+ if (s->hcom == INVALID_HANDLE_VALUE) {
+ error_setg(errp, "Failed CreateNamedPipe (%lu)", GetLastError());
+ s->hcom = NULL;
+ goto fail;
+ }
+
+ ZeroMemory(&ov, sizeof(ov));
+ ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ ret = ConnectNamedPipe(s->hcom, &ov);
+ if (ret) {
+ error_setg(errp, "Failed ConnectNamedPipe");
+ goto fail;
+ }
+
+ ret = GetOverlappedResult(s->hcom, &ov, &size, TRUE);
+ if (!ret) {
+ error_setg(errp, "Failed GetOverlappedResult");
+ if (ov.hEvent) {
+ CloseHandle(ov.hEvent);
+ ov.hEvent = NULL;
+ }
+ goto fail;
+ }
+
+ if (ov.hEvent) {
+ CloseHandle(ov.hEvent);
+ ov.hEvent = NULL;
+ }
+ qemu_add_polling_cb(win_chr_pipe_poll, chr);
+ return 0;
+
+ fail:
+ return -1;
+}
+
+static void qemu_chr_open_pipe(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ ChardevHostdev *opts = backend->u.pipe.data;
+ const char *filename = opts->device;
+
+ if (win_chr_pipe_init(chr, filename, errp) < 0) {
+ return;
+ }
+}
+
+#else
+
+static void qemu_chr_open_pipe(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ ChardevHostdev *opts = backend->u.pipe.data;
+ int fd_in, fd_out;
+ char *filename_in;
+ char *filename_out;
+ const char *filename = opts->device;
+
+ filename_in = g_strdup_printf("%s.in", filename);
+ filename_out = g_strdup_printf("%s.out", filename);
+ TFR(fd_in = qemu_open(filename_in, O_RDWR | O_BINARY));
+ TFR(fd_out = qemu_open(filename_out, O_RDWR | O_BINARY));
+ g_free(filename_in);
+ g_free(filename_out);
+ if (fd_in < 0 || fd_out < 0) {
+ if (fd_in >= 0) {
+ close(fd_in);
+ }
+ if (fd_out >= 0) {
+ close(fd_out);
+ }
+ TFR(fd_in = fd_out = qemu_open(filename, O_RDWR | O_BINARY));
+ if (fd_in < 0) {
+ error_setg_file_open(errp, errno, filename);
+ return;
+ }
+ }
+ qemu_chr_open_fd(chr, fd_in, fd_out);
+}
+
+#endif /* !_WIN32 */
+
+static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
+{
+ const char *device = qemu_opt_get(opts, "path");
+ ChardevHostdev *dev;
+
+ if (device == NULL) {
+ error_setg(errp, "chardev: pipe: no device path given");
+ return;
+ }
+ backend->type = CHARDEV_BACKEND_KIND_PIPE;
+ dev = backend->u.pipe.data = g_new0(ChardevHostdev, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(dev));
+ dev->device = g_strdup(device);
+}
+
+static void char_pipe_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->parse = qemu_chr_parse_pipe;
+ cc->open = qemu_chr_open_pipe;
+}
+
+static const TypeInfo char_pipe_type_info = {
+ .name = TYPE_CHARDEV_PIPE,
+#ifdef _WIN32
+ .parent = TYPE_CHARDEV_WIN,
+#else
+ .parent = TYPE_CHARDEV_FD,
+#endif
+ .class_init = char_pipe_class_init,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_pipe_type_info);
+}
+
+type_init(register_types);
diff --git a/chardev/char.c b/chardev/char.c
index 8ae8b5a4c3..b542c25cec 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -655,36 +655,6 @@ void qemu_chr_fe_take_focus(CharBackend *b)
}
#ifndef _WIN32
-static void qemu_chr_open_pipe(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- ChardevHostdev *opts = backend->u.pipe.data;
- int fd_in, fd_out;
- char *filename_in;
- char *filename_out;
- const char *filename = opts->device;
-
- filename_in = g_strdup_printf("%s.in", filename);
- filename_out = g_strdup_printf("%s.out", filename);
- TFR(fd_in = qemu_open(filename_in, O_RDWR | O_BINARY));
- TFR(fd_out = qemu_open(filename_out, O_RDWR | O_BINARY));
- g_free(filename_in);
- g_free(filename_out);
- if (fd_in < 0 || fd_out < 0) {
- if (fd_in >= 0)
- close(fd_in);
- if (fd_out >= 0)
- close(fd_out);
- TFR(fd_in = fd_out = qemu_open(filename, O_RDWR | O_BINARY));
- if (fd_in < 0) {
- error_setg_file_open(errp, errno, filename);
- return;
- }
- }
- qemu_chr_open_fd(chr, fd_in, fd_out);
-}
#if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
|| defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
@@ -1325,107 +1295,6 @@ static void qemu_chr_open_pp_fd(Chardev *chr,
#define HAVE_CHARDEV_SERIAL 1
-#define MAXCONNECT 1
-#define NTIMEOUT 5000
-
-static int win_chr_pipe_init(Chardev *chr, const char *filename,
- Error **errp)
-{
- WinChardev *s = WIN_CHARDEV(chr);
- OVERLAPPED ov;
- int ret;
- DWORD size;
- char *openname;
-
- s->fpipe = TRUE;
-
- s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (!s->hsend) {
- error_setg(errp, "Failed CreateEvent");
- goto fail;
- }
- s->hrecv = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (!s->hrecv) {
- error_setg(errp, "Failed CreateEvent");
- goto fail;
- }
-
- openname = g_strdup_printf("\\\\.\\pipe\\%s", filename);
- s->hcom = CreateNamedPipe(openname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
- PIPE_TYPE_BYTE | PIPE_READMODE_BYTE |
- PIPE_WAIT,
- MAXCONNECT, NSENDBUF, NRECVBUF, NTIMEOUT, NULL);
- g_free(openname);
- if (s->hcom == INVALID_HANDLE_VALUE) {
- error_setg(errp, "Failed CreateNamedPipe (%lu)", GetLastError());
- s->hcom = NULL;
- goto fail;
- }
-
- ZeroMemory(&ov, sizeof(ov));
- ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- ret = ConnectNamedPipe(s->hcom, &ov);
- if (ret) {
- error_setg(errp, "Failed ConnectNamedPipe");
- goto fail;
- }
-
- ret = GetOverlappedResult(s->hcom, &ov, &size, TRUE);
- if (!ret) {
- error_setg(errp, "Failed GetOverlappedResult");
- if (ov.hEvent) {
- CloseHandle(ov.hEvent);
- ov.hEvent = NULL;
- }
- goto fail;
- }
-
- if (ov.hEvent) {
- CloseHandle(ov.hEvent);
- ov.hEvent = NULL;
- }
- qemu_add_polling_cb(win_chr_pipe_poll, chr);
- return 0;
-
- fail:
- return -1;
-}
-
-
-static void qemu_chr_open_pipe(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- ChardevHostdev *opts = backend->u.pipe.data;
- const char *filename = opts->device;
-
- if (win_chr_pipe_init(chr, filename, errp) < 0) {
- return;
- }
-}
-
-static void qemu_chr_open_win_con(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- qemu_chr_open_win_file(chr, GetStdHandle(STD_OUTPUT_HANDLE));
-}
-
-static void char_console_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->open = qemu_chr_open_win_con;
-}
-
-static const TypeInfo char_console_type_info = {
- .name = TYPE_CHARDEV_CONSOLE,
- .parent = TYPE_CHARDEV_WIN,
- .class_init = char_console_class_init,
-};
-
#endif /* !_WIN32 */
int qemu_chr_wait_connected(Chardev *chr, Error **errp)
@@ -1638,40 +1507,6 @@ static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
}
#endif
-static void qemu_chr_parse_pipe(QemuOpts *opts, ChardevBackend *backend,
- Error **errp)
-{
- const char *device = qemu_opt_get(opts, "path");
- ChardevHostdev *dev;
-
- backend->type = CHARDEV_BACKEND_KIND_PIPE;
- if (device == NULL) {
- error_setg(errp, "chardev: pipe: no device path given");
- return;
- }
- dev = backend->u.pipe.data = g_new0(ChardevHostdev, 1);
- qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(dev));
- dev->device = g_strdup(device);
-}
-
-static void char_pipe_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->parse = qemu_chr_parse_pipe;
- cc->open = qemu_chr_open_pipe;
-}
-
-static const TypeInfo char_pipe_type_info = {
- .name = TYPE_CHARDEV_PIPE,
-#ifdef _WIN32
- .parent = TYPE_CHARDEV_WIN,
-#else
- .parent = TYPE_CHARDEV_FD,
-#endif
- .class_init = char_pipe_class_init,
-};
-
static const ChardevClass *char_get_class(const char *driver, Error **errp)
{
ObjectClass *oc;
@@ -2343,7 +2178,6 @@ static void register_types(void)
#ifdef HAVE_CHARDEV_PTY
type_register_static(&char_pty_type_info);
#endif
- type_register_static(&char_pipe_type_info);
/* this must be done after machine init, since we register FEs with muxes
* as part of realize functions like serial_isa_realizefn when -nographic
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index 265a6dad5d..778b312377 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -5,6 +5,7 @@ chardev-obj-y += char-file.o
chardev-obj-y += char-io.o
chardev-obj-y += char-mux.o
chardev-obj-y += char-null.o
+chardev-obj-y += char-pipe.o
chardev-obj-y += char-ringbuf.o
chardev-obj-y += char-socket.o
chardev-obj-y += char-stdio.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 38/41] char: move pty chardev in its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (36 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 37/41] char: move pipe chardev " Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 39/41] char: move serial chardev to " Marc-André Lureau
` (4 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
---
chardev/char-pty.c | 300 ++++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 258 -------------------------------------------
chardev/Makefile.objs | 1 +
3 files changed, 301 insertions(+), 258 deletions(-)
create mode 100644 chardev/char-pty.c
diff --git a/chardev/char-pty.c b/chardev/char-pty.c
new file mode 100644
index 0000000000..27eb85f505
--- /dev/null
+++ b/chardev/char-pty.c
@@ -0,0 +1,300 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "sysemu/char.h"
+#include "io/channel-file.h"
+#include "qemu/sockets.h"
+#include "qemu/error-report.h"
+
+#include "char-io.h"
+
+#if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
+ || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
+ || defined(__GLIBC__)
+
+typedef struct {
+ Chardev parent;
+ QIOChannel *ioc;
+ int read_bytes;
+
+ /* Protected by the Chardev chr_write_lock. */
+ int connected;
+ guint timer_tag;
+ guint open_tag;
+} PtyChardev;
+
+#define PTY_CHARDEV(obj) OBJECT_CHECK(PtyChardev, (obj), TYPE_CHARDEV_PTY)
+
+static void pty_chr_update_read_handler_locked(Chardev *chr);
+static void pty_chr_state(Chardev *chr, int connected);
+
+static gboolean pty_chr_timer(gpointer opaque)
+{
+ struct Chardev *chr = CHARDEV(opaque);
+ PtyChardev *s = PTY_CHARDEV(opaque);
+
+ qemu_mutex_lock(&chr->chr_write_lock);
+ s->timer_tag = 0;
+ s->open_tag = 0;
+ if (!s->connected) {
+ /* Next poll ... */
+ pty_chr_update_read_handler_locked(chr);
+ }
+ qemu_mutex_unlock(&chr->chr_write_lock);
+ return FALSE;
+}
+
+/* Called with chr_write_lock held. */
+static void pty_chr_rearm_timer(Chardev *chr, int ms)
+{
+ PtyChardev *s = PTY_CHARDEV(chr);
+ char *name;
+
+ if (s->timer_tag) {
+ g_source_remove(s->timer_tag);
+ s->timer_tag = 0;
+ }
+
+ if (ms == 1000) {
+ name = g_strdup_printf("pty-timer-secs-%s", chr->label);
+ s->timer_tag = g_timeout_add_seconds(1, pty_chr_timer, chr);
+ } else {
+ name = g_strdup_printf("pty-timer-ms-%s", chr->label);
+ s->timer_tag = g_timeout_add(ms, pty_chr_timer, chr);
+ }
+ g_source_set_name_by_id(s->timer_tag, name);
+ g_free(name);
+}
+
+/* Called with chr_write_lock held. */
+static void pty_chr_update_read_handler_locked(Chardev *chr)
+{
+ PtyChardev *s = PTY_CHARDEV(chr);
+ GPollFD pfd;
+ int rc;
+ QIOChannelFile *fioc = QIO_CHANNEL_FILE(s->ioc);
+
+ pfd.fd = fioc->fd;
+ pfd.events = G_IO_OUT;
+ pfd.revents = 0;
+ do {
+ rc = g_poll(&pfd, 1, 0);
+ } while (rc == -1 && errno == EINTR);
+ assert(rc >= 0);
+
+ if (pfd.revents & G_IO_HUP) {
+ pty_chr_state(chr, 0);
+ } else {
+ pty_chr_state(chr, 1);
+ }
+}
+
+static void pty_chr_update_read_handler(Chardev *chr,
+ GMainContext *context)
+{
+ qemu_mutex_lock(&chr->chr_write_lock);
+ pty_chr_update_read_handler_locked(chr);
+ qemu_mutex_unlock(&chr->chr_write_lock);
+}
+
+/* Called with chr_write_lock held. */
+static int char_pty_chr_write(Chardev *chr, const uint8_t *buf, int len)
+{
+ PtyChardev *s = PTY_CHARDEV(chr);
+
+ if (!s->connected) {
+ /* guest sends data, check for (re-)connect */
+ pty_chr_update_read_handler_locked(chr);
+ if (!s->connected) {
+ return 0;
+ }
+ }
+ return io_channel_send(s->ioc, buf, len);
+}
+
+static GSource *pty_chr_add_watch(Chardev *chr, GIOCondition cond)
+{
+ PtyChardev *s = PTY_CHARDEV(chr);
+ if (!s->connected) {
+ return NULL;
+ }
+ return qio_channel_create_watch(s->ioc, cond);
+}
+
+static int pty_chr_read_poll(void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ PtyChardev *s = PTY_CHARDEV(opaque);
+
+ s->read_bytes = qemu_chr_be_can_write(chr);
+ return s->read_bytes;
+}
+
+static gboolean pty_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ PtyChardev *s = PTY_CHARDEV(opaque);
+ gsize len;
+ uint8_t buf[CHR_READ_BUF_LEN];
+ ssize_t ret;
+
+ len = sizeof(buf);
+ if (len > s->read_bytes) {
+ len = s->read_bytes;
+ }
+ if (len == 0) {
+ return TRUE;
+ }
+ ret = qio_channel_read(s->ioc, (char *)buf, len, NULL);
+ if (ret <= 0) {
+ pty_chr_state(chr, 0);
+ return FALSE;
+ } else {
+ pty_chr_state(chr, 1);
+ qemu_chr_be_write(chr, buf, ret);
+ }
+ return TRUE;
+}
+
+static gboolean qemu_chr_be_generic_open_func(gpointer opaque)
+{
+ Chardev *chr = CHARDEV(opaque);
+ PtyChardev *s = PTY_CHARDEV(opaque);
+
+ s->open_tag = 0;
+ qemu_chr_be_generic_open(chr);
+ return FALSE;
+}
+
+/* Called with chr_write_lock held. */
+static void pty_chr_state(Chardev *chr, int connected)
+{
+ PtyChardev *s = PTY_CHARDEV(chr);
+
+ if (!connected) {
+ if (s->open_tag) {
+ g_source_remove(s->open_tag);
+ s->open_tag = 0;
+ }
+ remove_fd_in_watch(chr);
+ s->connected = 0;
+ /* (re-)connect poll interval for idle guests: once per second.
+ * We check more frequently in case the guests sends data to
+ * the virtual device linked to our pty. */
+ pty_chr_rearm_timer(chr, 1000);
+ } else {
+ if (s->timer_tag) {
+ g_source_remove(s->timer_tag);
+ s->timer_tag = 0;
+ }
+ if (!s->connected) {
+ g_assert(s->open_tag == 0);
+ s->connected = 1;
+ s->open_tag = g_idle_add(qemu_chr_be_generic_open_func, chr);
+ }
+ if (!chr->fd_in_tag) {
+ chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
+ pty_chr_read_poll,
+ pty_chr_read,
+ chr, NULL);
+ }
+ }
+}
+
+static void char_pty_finalize(Object *obj)
+{
+ Chardev *chr = CHARDEV(obj);
+ PtyChardev *s = PTY_CHARDEV(obj);
+
+ qemu_mutex_lock(&chr->chr_write_lock);
+ pty_chr_state(chr, 0);
+ object_unref(OBJECT(s->ioc));
+ if (s->timer_tag) {
+ g_source_remove(s->timer_tag);
+ s->timer_tag = 0;
+ }
+ qemu_mutex_unlock(&chr->chr_write_lock);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+}
+
+static void char_pty_open(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ PtyChardev *s;
+ int master_fd, slave_fd;
+ char pty_name[PATH_MAX];
+ char *name;
+
+ master_fd = qemu_openpty_raw(&slave_fd, pty_name);
+ if (master_fd < 0) {
+ error_setg_errno(errp, errno, "Failed to create PTY");
+ return;
+ }
+
+ close(slave_fd);
+ qemu_set_nonblock(master_fd);
+
+ chr->filename = g_strdup_printf("pty:%s", pty_name);
+ error_report("char device redirected to %s (label %s)",
+ pty_name, chr->label);
+
+ s = PTY_CHARDEV(chr);
+ s->ioc = QIO_CHANNEL(qio_channel_file_new_fd(master_fd));
+ name = g_strdup_printf("chardev-pty-%s", chr->label);
+ qio_channel_set_name(QIO_CHANNEL(s->ioc), name);
+ g_free(name);
+ s->timer_tag = 0;
+ *be_opened = false;
+}
+
+static void char_pty_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->open = char_pty_open;
+ cc->chr_write = char_pty_chr_write;
+ cc->chr_update_read_handler = pty_chr_update_read_handler;
+ cc->chr_add_watch = pty_chr_add_watch;
+}
+
+static const TypeInfo char_pty_type_info = {
+ .name = TYPE_CHARDEV_PTY,
+ .parent = TYPE_CHARDEV,
+ .instance_size = sizeof(PtyChardev),
+ .instance_finalize = char_pty_finalize,
+ .class_init = char_pty_class_init,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_pty_type_info);
+}
+
+type_init(register_types);
+
+#endif
diff --git a/chardev/char.c b/chardev/char.c
index b542c25cec..6d4cb7c71e 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -661,261 +661,6 @@ void qemu_chr_fe_take_focus(CharBackend *b)
|| defined(__GLIBC__)
#define HAVE_CHARDEV_SERIAL 1
-#define HAVE_CHARDEV_PTY 1
-
-typedef struct {
- Chardev parent;
- QIOChannel *ioc;
- int read_bytes;
-
- /* Protected by the Chardev chr_write_lock. */
- int connected;
- guint timer_tag;
- guint open_tag;
-} PtyChardev;
-
-#define PTY_CHARDEV(obj) OBJECT_CHECK(PtyChardev, (obj), TYPE_CHARDEV_PTY)
-
-static void pty_chr_update_read_handler_locked(Chardev *chr);
-static void pty_chr_state(Chardev *chr, int connected);
-
-static gboolean pty_chr_timer(gpointer opaque)
-{
- struct Chardev *chr = CHARDEV(opaque);
- PtyChardev *s = PTY_CHARDEV(opaque);
-
- qemu_mutex_lock(&chr->chr_write_lock);
- s->timer_tag = 0;
- s->open_tag = 0;
- if (!s->connected) {
- /* Next poll ... */
- pty_chr_update_read_handler_locked(chr);
- }
- qemu_mutex_unlock(&chr->chr_write_lock);
- return FALSE;
-}
-
-/* Called with chr_write_lock held. */
-static void pty_chr_rearm_timer(Chardev *chr, int ms)
-{
- PtyChardev *s = PTY_CHARDEV(chr);
- char *name;
-
- if (s->timer_tag) {
- g_source_remove(s->timer_tag);
- s->timer_tag = 0;
- }
-
- if (ms == 1000) {
- name = g_strdup_printf("pty-timer-secs-%s", chr->label);
- s->timer_tag = g_timeout_add_seconds(1, pty_chr_timer, chr);
- } else {
- name = g_strdup_printf("pty-timer-ms-%s", chr->label);
- s->timer_tag = g_timeout_add(ms, pty_chr_timer, chr);
- }
- g_source_set_name_by_id(s->timer_tag, name);
- g_free(name);
-}
-
-/* Called with chr_write_lock held. */
-static void pty_chr_update_read_handler_locked(Chardev *chr)
-{
- PtyChardev *s = PTY_CHARDEV(chr);
- GPollFD pfd;
- int rc;
- QIOChannelFile *fioc = QIO_CHANNEL_FILE(s->ioc);
-
- pfd.fd = fioc->fd;
- pfd.events = G_IO_OUT;
- pfd.revents = 0;
- do {
- rc = g_poll(&pfd, 1, 0);
- } while (rc == -1 && errno == EINTR);
- assert(rc >= 0);
-
- if (pfd.revents & G_IO_HUP) {
- pty_chr_state(chr, 0);
- } else {
- pty_chr_state(chr, 1);
- }
-}
-
-static void pty_chr_update_read_handler(Chardev *chr,
- GMainContext *context)
-{
- qemu_mutex_lock(&chr->chr_write_lock);
- pty_chr_update_read_handler_locked(chr);
- qemu_mutex_unlock(&chr->chr_write_lock);
-}
-
-/* Called with chr_write_lock held. */
-static int char_pty_chr_write(Chardev *chr, const uint8_t *buf, int len)
-{
- PtyChardev *s = PTY_CHARDEV(chr);
-
- if (!s->connected) {
- /* guest sends data, check for (re-)connect */
- pty_chr_update_read_handler_locked(chr);
- if (!s->connected) {
- return 0;
- }
- }
- return io_channel_send(s->ioc, buf, len);
-}
-
-static GSource *pty_chr_add_watch(Chardev *chr, GIOCondition cond)
-{
- PtyChardev *s = PTY_CHARDEV(chr);
- if (!s->connected) {
- return NULL;
- }
- return qio_channel_create_watch(s->ioc, cond);
-}
-
-static int pty_chr_read_poll(void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- PtyChardev *s = PTY_CHARDEV(opaque);
-
- s->read_bytes = qemu_chr_be_can_write(chr);
- return s->read_bytes;
-}
-
-static gboolean pty_chr_read(QIOChannel *chan, GIOCondition cond, void *opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- PtyChardev *s = PTY_CHARDEV(opaque);
- gsize len;
- uint8_t buf[CHR_READ_BUF_LEN];
- ssize_t ret;
-
- len = sizeof(buf);
- if (len > s->read_bytes)
- len = s->read_bytes;
- if (len == 0) {
- return TRUE;
- }
- ret = qio_channel_read(s->ioc, (char *)buf, len, NULL);
- if (ret <= 0) {
- pty_chr_state(chr, 0);
- return FALSE;
- } else {
- pty_chr_state(chr, 1);
- qemu_chr_be_write(chr, buf, ret);
- }
- return TRUE;
-}
-
-static gboolean qemu_chr_be_generic_open_func(gpointer opaque)
-{
- Chardev *chr = CHARDEV(opaque);
- PtyChardev *s = PTY_CHARDEV(opaque);
-
- s->open_tag = 0;
- qemu_chr_be_generic_open(chr);
- return FALSE;
-}
-
-/* Called with chr_write_lock held. */
-static void pty_chr_state(Chardev *chr, int connected)
-{
- PtyChardev *s = PTY_CHARDEV(chr);
-
- if (!connected) {
- if (s->open_tag) {
- g_source_remove(s->open_tag);
- s->open_tag = 0;
- }
- remove_fd_in_watch(chr);
- s->connected = 0;
- /* (re-)connect poll interval for idle guests: once per second.
- * We check more frequently in case the guests sends data to
- * the virtual device linked to our pty. */
- pty_chr_rearm_timer(chr, 1000);
- } else {
- if (s->timer_tag) {
- g_source_remove(s->timer_tag);
- s->timer_tag = 0;
- }
- if (!s->connected) {
- g_assert(s->open_tag == 0);
- s->connected = 1;
- s->open_tag = g_idle_add(qemu_chr_be_generic_open_func, chr);
- }
- if (!chr->fd_in_tag) {
- chr->fd_in_tag = io_add_watch_poll(chr, s->ioc,
- pty_chr_read_poll,
- pty_chr_read,
- chr, NULL);
- }
- }
-}
-
-static void char_pty_finalize(Object *obj)
-{
- Chardev *chr = CHARDEV(obj);
- PtyChardev *s = PTY_CHARDEV(obj);
-
- qemu_mutex_lock(&chr->chr_write_lock);
- pty_chr_state(chr, 0);
- object_unref(OBJECT(s->ioc));
- if (s->timer_tag) {
- g_source_remove(s->timer_tag);
- s->timer_tag = 0;
- }
- qemu_mutex_unlock(&chr->chr_write_lock);
- qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
-}
-
-static void char_pty_open(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- PtyChardev *s;
- int master_fd, slave_fd;
- char pty_name[PATH_MAX];
- char *name;
-
- master_fd = qemu_openpty_raw(&slave_fd, pty_name);
- if (master_fd < 0) {
- error_setg_errno(errp, errno, "Failed to create PTY");
- return;
- }
-
- close(slave_fd);
- qemu_set_nonblock(master_fd);
-
- chr->filename = g_strdup_printf("pty:%s", pty_name);
- error_report("char device redirected to %s (label %s)",
- pty_name, chr->label);
-
- s = PTY_CHARDEV(chr);
- s->ioc = QIO_CHANNEL(qio_channel_file_new_fd(master_fd));
- name = g_strdup_printf("chardev-pty-%s", chr->label);
- qio_channel_set_name(QIO_CHANNEL(s->ioc), name);
- g_free(name);
- s->timer_tag = 0;
- *be_opened = false;
-}
-
-static void char_pty_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->open = char_pty_open;
- cc->chr_write = char_pty_chr_write;
- cc->chr_update_read_handler = pty_chr_update_read_handler;
- cc->chr_add_watch = pty_chr_add_watch;
-}
-
-static const TypeInfo char_pty_type_info = {
- .name = TYPE_CHARDEV_PTY,
- .parent = TYPE_CHARDEV,
- .instance_size = sizeof(PtyChardev),
- .instance_finalize = char_pty_finalize,
- .class_init = char_pty_class_init,
-};
static void tty_serial_init(int fd, int speed,
int parity, int data_bits, int stop_bits)
@@ -2175,9 +1920,6 @@ static void register_types(void)
#ifdef HAVE_CHARDEV_PARPORT
type_register_static(&char_parallel_type_info);
#endif
-#ifdef HAVE_CHARDEV_PTY
- type_register_static(&char_pty_type_info);
-#endif
/* this must be done after machine init, since we register FEs with muxes
* as part of realize functions like serial_isa_realizefn when -nographic
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index 778b312377..b2c14fe795 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -6,6 +6,7 @@ chardev-obj-y += char-io.o
chardev-obj-y += char-mux.o
chardev-obj-y += char-null.o
chardev-obj-y += char-pipe.o
+chardev-obj-$(CONFIG_POSIX) += char-pty.o
chardev-obj-y += char-ringbuf.o
chardev-obj-y += char-socket.o
chardev-obj-y += char-stdio.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 39/41] char: move serial chardev to its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (37 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 38/41] char: move pty " Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 40/41] char: move parallel chardev in " Marc-André Lureau
` (3 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
---
chardev/char-serial.h | 35 ++++++
chardev/char-serial.c | 318 ++++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 278 +------------------------------------------
chardev/Makefile.objs | 1 +
4 files changed, 356 insertions(+), 276 deletions(-)
create mode 100644 chardev/char-serial.h
create mode 100644 chardev/char-serial.c
diff --git a/chardev/char-serial.h b/chardev/char-serial.h
new file mode 100644
index 0000000000..64a27f63b1
--- /dev/null
+++ b/chardev/char-serial.h
@@ -0,0 +1,35 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef CHAR_SERIAL_H
+#define CHAR_SERIAL_H
+
+#ifdef _WIN32
+#define HAVE_CHARDEV_SERIAL 1
+#elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
+ || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
+ || defined(__GLIBC__)
+#define HAVE_CHARDEV_SERIAL 1
+#endif
+
+#endif
diff --git a/chardev/char-serial.c b/chardev/char-serial.c
new file mode 100644
index 0000000000..094e08dca5
--- /dev/null
+++ b/chardev/char-serial.c
@@ -0,0 +1,318 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qemu/sockets.h"
+#include "io/channel-file.h"
+#include "qapi/error.h"
+
+#ifdef _WIN32
+#include "char-win.h"
+#else
+#include <sys/ioctl.h>
+#include <termios.h>
+#include "char-fd.h"
+#endif
+
+#include "char-serial.h"
+
+#ifdef _WIN32
+
+static void qmp_chardev_open_serial(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ ChardevHostdev *serial = backend->u.serial.data;
+
+ win_chr_init(chr, serial->device, errp);
+}
+
+#elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
+ || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
+ || defined(__GLIBC__)
+
+static void tty_serial_init(int fd, int speed,
+ int parity, int data_bits, int stop_bits)
+{
+ struct termios tty;
+ speed_t spd;
+
+#if 0
+ printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n",
+ speed, parity, data_bits, stop_bits);
+#endif
+ tcgetattr(fd, &tty);
+
+#define check_speed(val) if (speed <= val) { spd = B##val; break; }
+ speed = speed * 10 / 11;
+ do {
+ check_speed(50);
+ check_speed(75);
+ check_speed(110);
+ check_speed(134);
+ check_speed(150);
+ check_speed(200);
+ check_speed(300);
+ check_speed(600);
+ check_speed(1200);
+ check_speed(1800);
+ check_speed(2400);
+ check_speed(4800);
+ check_speed(9600);
+ check_speed(19200);
+ check_speed(38400);
+ /* Non-Posix values follow. They may be unsupported on some systems. */
+ check_speed(57600);
+ check_speed(115200);
+#ifdef B230400
+ check_speed(230400);
+#endif
+#ifdef B460800
+ check_speed(460800);
+#endif
+#ifdef B500000
+ check_speed(500000);
+#endif
+#ifdef B576000
+ check_speed(576000);
+#endif
+#ifdef B921600
+ check_speed(921600);
+#endif
+#ifdef B1000000
+ check_speed(1000000);
+#endif
+#ifdef B1152000
+ check_speed(1152000);
+#endif
+#ifdef B1500000
+ check_speed(1500000);
+#endif
+#ifdef B2000000
+ check_speed(2000000);
+#endif
+#ifdef B2500000
+ check_speed(2500000);
+#endif
+#ifdef B3000000
+ check_speed(3000000);
+#endif
+#ifdef B3500000
+ check_speed(3500000);
+#endif
+#ifdef B4000000
+ check_speed(4000000);
+#endif
+ spd = B115200;
+ } while (0);
+
+ cfsetispeed(&tty, spd);
+ cfsetospeed(&tty, spd);
+
+ tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
+ | INLCR | IGNCR | ICRNL | IXON);
+ tty.c_oflag |= OPOST;
+ tty.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
+ tty.c_cflag &= ~(CSIZE | PARENB | PARODD | CRTSCTS | CSTOPB);
+ switch (data_bits) {
+ default:
+ case 8:
+ tty.c_cflag |= CS8;
+ break;
+ case 7:
+ tty.c_cflag |= CS7;
+ break;
+ case 6:
+ tty.c_cflag |= CS6;
+ break;
+ case 5:
+ tty.c_cflag |= CS5;
+ break;
+ }
+ switch (parity) {
+ default:
+ case 'N':
+ break;
+ case 'E':
+ tty.c_cflag |= PARENB;
+ break;
+ case 'O':
+ tty.c_cflag |= PARENB | PARODD;
+ break;
+ }
+ if (stop_bits == 2) {
+ tty.c_cflag |= CSTOPB;
+ }
+
+ tcsetattr(fd, TCSANOW, &tty);
+}
+
+static int tty_serial_ioctl(Chardev *chr, int cmd, void *arg)
+{
+ FDChardev *s = FD_CHARDEV(chr);
+ QIOChannelFile *fioc = QIO_CHANNEL_FILE(s->ioc_in);
+
+ switch (cmd) {
+ case CHR_IOCTL_SERIAL_SET_PARAMS:
+ {
+ QEMUSerialSetParams *ssp = arg;
+ tty_serial_init(fioc->fd,
+ ssp->speed, ssp->parity,
+ ssp->data_bits, ssp->stop_bits);
+ }
+ break;
+ case CHR_IOCTL_SERIAL_SET_BREAK:
+ {
+ int enable = *(int *)arg;
+ if (enable) {
+ tcsendbreak(fioc->fd, 1);
+ }
+ }
+ break;
+ case CHR_IOCTL_SERIAL_GET_TIOCM:
+ {
+ int sarg = 0;
+ int *targ = (int *)arg;
+ ioctl(fioc->fd, TIOCMGET, &sarg);
+ *targ = 0;
+ if (sarg & TIOCM_CTS) {
+ *targ |= CHR_TIOCM_CTS;
+ }
+ if (sarg & TIOCM_CAR) {
+ *targ |= CHR_TIOCM_CAR;
+ }
+ if (sarg & TIOCM_DSR) {
+ *targ |= CHR_TIOCM_DSR;
+ }
+ if (sarg & TIOCM_RI) {
+ *targ |= CHR_TIOCM_RI;
+ }
+ if (sarg & TIOCM_DTR) {
+ *targ |= CHR_TIOCM_DTR;
+ }
+ if (sarg & TIOCM_RTS) {
+ *targ |= CHR_TIOCM_RTS;
+ }
+ }
+ break;
+ case CHR_IOCTL_SERIAL_SET_TIOCM:
+ {
+ int sarg = *(int *)arg;
+ int targ = 0;
+ ioctl(fioc->fd, TIOCMGET, &targ);
+ targ &= ~(CHR_TIOCM_CTS | CHR_TIOCM_CAR | CHR_TIOCM_DSR
+ | CHR_TIOCM_RI | CHR_TIOCM_DTR | CHR_TIOCM_RTS);
+ if (sarg & CHR_TIOCM_CTS) {
+ targ |= TIOCM_CTS;
+ }
+ if (sarg & CHR_TIOCM_CAR) {
+ targ |= TIOCM_CAR;
+ }
+ if (sarg & CHR_TIOCM_DSR) {
+ targ |= TIOCM_DSR;
+ }
+ if (sarg & CHR_TIOCM_RI) {
+ targ |= TIOCM_RI;
+ }
+ if (sarg & CHR_TIOCM_DTR) {
+ targ |= TIOCM_DTR;
+ }
+ if (sarg & CHR_TIOCM_RTS) {
+ targ |= TIOCM_RTS;
+ }
+ ioctl(fioc->fd, TIOCMSET, &targ);
+ }
+ break;
+ default:
+ return -ENOTSUP;
+ }
+ return 0;
+}
+
+static void qmp_chardev_open_serial(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ ChardevHostdev *serial = backend->u.serial.data;
+ int fd;
+
+ fd = qmp_chardev_open_file_source(serial->device, O_RDWR, errp);
+ if (fd < 0) {
+ return;
+ }
+ qemu_set_nonblock(fd);
+ tty_serial_init(fd, 115200, 'N', 8, 1);
+
+ qemu_chr_open_fd(chr, fd, fd);
+}
+#endif /* __linux__ || __sun__ */
+
+#ifdef HAVE_CHARDEV_SERIAL
+static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
+{
+ const char *device = qemu_opt_get(opts, "path");
+ ChardevHostdev *serial;
+
+ if (device == NULL) {
+ error_setg(errp, "chardev: serial/tty: no device path given");
+ return;
+ }
+ backend->type = CHARDEV_BACKEND_KIND_SERIAL;
+ serial = backend->u.serial.data = g_new0(ChardevHostdev, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(serial));
+ serial->device = g_strdup(device);
+}
+
+static void char_serial_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->parse = qemu_chr_parse_serial;
+ cc->open = qmp_chardev_open_serial;
+#ifndef _WIN32
+ cc->chr_ioctl = tty_serial_ioctl;
+#endif
+}
+
+
+static const TypeInfo char_serial_type_info = {
+ .name = TYPE_CHARDEV_SERIAL,
+#ifdef _WIN32
+ .parent = TYPE_CHARDEV_WIN,
+#else
+ .parent = TYPE_CHARDEV_FD,
+#endif
+ .class_init = char_serial_class_init,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_serial_type_info);
+}
+
+type_init(register_types);
+
+#endif
diff --git a/chardev/char.c b/chardev/char.c
index 6d4cb7c71e..faba68db21 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -36,7 +36,6 @@
#include "qapi-visit.h"
#include "qemu/base64.h"
#include "io/channel-socket.h"
-#include "io/channel-file.h"
#include "io/channel-tls.h"
#include "sysemu/replay.h"
#include "qemu/help_option.h"
@@ -46,7 +45,6 @@
#ifndef _WIN32
#include <sys/times.h>
#include <sys/wait.h>
-#include <termios.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/socket.h>
@@ -91,6 +89,7 @@
#ifdef _WIN32
#include "char-win.h"
#endif
+#include "char-serial.h"
/***********************************************************/
/* character device */
@@ -656,198 +655,6 @@ void qemu_chr_fe_take_focus(CharBackend *b)
#ifndef _WIN32
-#if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
- || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
- || defined(__GLIBC__)
-
-#define HAVE_CHARDEV_SERIAL 1
-
-static void tty_serial_init(int fd, int speed,
- int parity, int data_bits, int stop_bits)
-{
- struct termios tty;
- speed_t spd;
-
-#if 0
- printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n",
- speed, parity, data_bits, stop_bits);
-#endif
- tcgetattr (fd, &tty);
-
-#define check_speed(val) if (speed <= val) { spd = B##val; break; }
- speed = speed * 10 / 11;
- do {
- check_speed(50);
- check_speed(75);
- check_speed(110);
- check_speed(134);
- check_speed(150);
- check_speed(200);
- check_speed(300);
- check_speed(600);
- check_speed(1200);
- check_speed(1800);
- check_speed(2400);
- check_speed(4800);
- check_speed(9600);
- check_speed(19200);
- check_speed(38400);
- /* Non-Posix values follow. They may be unsupported on some systems. */
- check_speed(57600);
- check_speed(115200);
-#ifdef B230400
- check_speed(230400);
-#endif
-#ifdef B460800
- check_speed(460800);
-#endif
-#ifdef B500000
- check_speed(500000);
-#endif
-#ifdef B576000
- check_speed(576000);
-#endif
-#ifdef B921600
- check_speed(921600);
-#endif
-#ifdef B1000000
- check_speed(1000000);
-#endif
-#ifdef B1152000
- check_speed(1152000);
-#endif
-#ifdef B1500000
- check_speed(1500000);
-#endif
-#ifdef B2000000
- check_speed(2000000);
-#endif
-#ifdef B2500000
- check_speed(2500000);
-#endif
-#ifdef B3000000
- check_speed(3000000);
-#endif
-#ifdef B3500000
- check_speed(3500000);
-#endif
-#ifdef B4000000
- check_speed(4000000);
-#endif
- spd = B115200;
- } while (0);
-
- cfsetispeed(&tty, spd);
- cfsetospeed(&tty, spd);
-
- tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
- |INLCR|IGNCR|ICRNL|IXON);
- tty.c_oflag |= OPOST;
- tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
- tty.c_cflag &= ~(CSIZE|PARENB|PARODD|CRTSCTS|CSTOPB);
- switch(data_bits) {
- default:
- case 8:
- tty.c_cflag |= CS8;
- break;
- case 7:
- tty.c_cflag |= CS7;
- break;
- case 6:
- tty.c_cflag |= CS6;
- break;
- case 5:
- tty.c_cflag |= CS5;
- break;
- }
- switch(parity) {
- default:
- case 'N':
- break;
- case 'E':
- tty.c_cflag |= PARENB;
- break;
- case 'O':
- tty.c_cflag |= PARENB | PARODD;
- break;
- }
- if (stop_bits == 2)
- tty.c_cflag |= CSTOPB;
-
- tcsetattr (fd, TCSANOW, &tty);
-}
-
-static int tty_serial_ioctl(Chardev *chr, int cmd, void *arg)
-{
- FDChardev *s = FD_CHARDEV(chr);
- QIOChannelFile *fioc = QIO_CHANNEL_FILE(s->ioc_in);
-
- switch(cmd) {
- case CHR_IOCTL_SERIAL_SET_PARAMS:
- {
- QEMUSerialSetParams *ssp = arg;
- tty_serial_init(fioc->fd,
- ssp->speed, ssp->parity,
- ssp->data_bits, ssp->stop_bits);
- }
- break;
- case CHR_IOCTL_SERIAL_SET_BREAK:
- {
- int enable = *(int *)arg;
- if (enable) {
- tcsendbreak(fioc->fd, 1);
- }
- }
- break;
- case CHR_IOCTL_SERIAL_GET_TIOCM:
- {
- int sarg = 0;
- int *targ = (int *)arg;
- ioctl(fioc->fd, TIOCMGET, &sarg);
- *targ = 0;
- if (sarg & TIOCM_CTS)
- *targ |= CHR_TIOCM_CTS;
- if (sarg & TIOCM_CAR)
- *targ |= CHR_TIOCM_CAR;
- if (sarg & TIOCM_DSR)
- *targ |= CHR_TIOCM_DSR;
- if (sarg & TIOCM_RI)
- *targ |= CHR_TIOCM_RI;
- if (sarg & TIOCM_DTR)
- *targ |= CHR_TIOCM_DTR;
- if (sarg & TIOCM_RTS)
- *targ |= CHR_TIOCM_RTS;
- }
- break;
- case CHR_IOCTL_SERIAL_SET_TIOCM:
- {
- int sarg = *(int *)arg;
- int targ = 0;
- ioctl(fioc->fd, TIOCMGET, &targ);
- targ &= ~(CHR_TIOCM_CTS | CHR_TIOCM_CAR | CHR_TIOCM_DSR
- | CHR_TIOCM_RI | CHR_TIOCM_DTR | CHR_TIOCM_RTS);
- if (sarg & CHR_TIOCM_CTS)
- targ |= TIOCM_CTS;
- if (sarg & CHR_TIOCM_CAR)
- targ |= TIOCM_CAR;
- if (sarg & CHR_TIOCM_DSR)
- targ |= TIOCM_DSR;
- if (sarg & CHR_TIOCM_RI)
- targ |= TIOCM_RI;
- if (sarg & CHR_TIOCM_DTR)
- targ |= TIOCM_DTR;
- if (sarg & CHR_TIOCM_RTS)
- targ |= TIOCM_RTS;
- ioctl(fioc->fd, TIOCMSET, &targ);
- }
- break;
- default:
- return -ENOTSUP;
- }
- return 0;
-}
-#endif /* __linux__ || __sun__ */
-
#if defined(__linux__)
#define HAVE_CHARDEV_PARPORT 1
@@ -1036,10 +843,6 @@ static void qemu_chr_open_pp_fd(Chardev *chr,
}
#endif
-#else /* _WIN32 */
-
-#define HAVE_CHARDEV_SERIAL 1
-
#endif /* !_WIN32 */
int qemu_chr_wait_connected(Chardev *chr, Error **errp)
@@ -1216,24 +1019,6 @@ void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend)
backend->logappend = qemu_opt_get_bool(opts, "logappend", false);
}
-#ifdef HAVE_CHARDEV_SERIAL
-static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend,
- Error **errp)
-{
- const char *device = qemu_opt_get(opts, "path");
- ChardevHostdev *serial;
-
- backend->type = CHARDEV_BACKEND_KIND_SERIAL;
- if (device == NULL) {
- error_setg(errp, "chardev: serial/tty: no device path given");
- return;
- }
- serial = backend->u.serial.data = g_new0(ChardevHostdev, 1);
- qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(serial));
- serial->device = g_strdup(device);
-}
-#endif
-
#ifdef HAVE_CHARDEV_PARPORT
static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
@@ -1699,39 +1484,7 @@ QemuOptsList qemu_chardev_opts = {
},
};
-#ifdef _WIN32
-
-static void qmp_chardev_open_serial(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- ChardevHostdev *serial = backend->u.serial.data;
-
- win_chr_init(chr, serial->device, errp);
-}
-
-#else /* WIN32 */
-
-#ifdef HAVE_CHARDEV_SERIAL
-static void qmp_chardev_open_serial(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- ChardevHostdev *serial = backend->u.serial.data;
- int fd;
-
- fd = qmp_chardev_open_file_source(serial->device, O_RDWR, errp);
- if (fd < 0) {
- return;
- }
- qemu_set_nonblock(fd);
- tty_serial_init(fd, 115200, 'N', 8, 1);
-
- qemu_chr_open_fd(chr, fd, fd);
-}
-#endif
+#ifndef _WIN32
#ifdef HAVE_CHARDEV_PARPORT
static void qmp_chardev_open_parallel(Chardev *chr,
@@ -1789,30 +1542,6 @@ static const TypeInfo char_parallel_type_info = {
#endif /* WIN32 */
-#ifdef HAVE_CHARDEV_SERIAL
-
-static void char_serial_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->parse = qemu_chr_parse_serial;
- cc->open = qmp_chardev_open_serial;
-#ifndef _WIN32
- cc->chr_ioctl = tty_serial_ioctl;
-#endif
-}
-
-static const TypeInfo char_serial_type_info = {
- .name = TYPE_CHARDEV_SERIAL,
-#ifdef _WIN32
- .parent = TYPE_CHARDEV_WIN,
-#else
- .parent = TYPE_CHARDEV_FD,
-#endif
- .class_init = char_serial_class_init,
-};
-#endif
-
bool qemu_chr_has_feature(Chardev *chr,
ChardevFeature feature)
{
@@ -1914,9 +1643,6 @@ void qemu_chr_cleanup(void)
static void register_types(void)
{
type_register_static(&char_type_info);
-#ifdef HAVE_CHARDEV_SERIAL
- type_register_static(&char_serial_type_info);
-#endif
#ifdef HAVE_CHARDEV_PARPORT
type_register_static(&char_parallel_type_info);
#endif
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index b2c14fe795..45fc8af0c4 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -8,6 +8,7 @@ chardev-obj-y += char-null.o
chardev-obj-y += char-pipe.o
chardev-obj-$(CONFIG_POSIX) += char-pty.o
chardev-obj-y += char-ringbuf.o
+chardev-obj-y += char-serial.o
chardev-obj-y += char-socket.o
chardev-obj-y += char-stdio.o
chardev-obj-y += char-udp.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 40/41] char: move parallel chardev in its own file
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (38 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 39/41] char: move serial chardev to " Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 16:21 ` [Qemu-devel] [PULL 41/41] char: headers clean-up Marc-André Lureau
` (2 subsequent siblings)
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
---
chardev/char-parallel.h | 32 +++++
chardev/char-parallel.c | 316 ++++++++++++++++++++++++++++++++++++++++++++++++
chardev/char.c | 287 +------------------------------------------
chardev/Makefile.objs | 1 +
4 files changed, 350 insertions(+), 286 deletions(-)
create mode 100644 chardev/char-parallel.h
create mode 100644 chardev/char-parallel.c
diff --git a/chardev/char-parallel.h b/chardev/char-parallel.h
new file mode 100644
index 0000000000..26742f9d5c
--- /dev/null
+++ b/chardev/char-parallel.h
@@ -0,0 +1,32 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef CHAR_PARALLEL_H
+#define CHAR_PARALLEL_H
+
+#if defined(__linux__) || defined(__FreeBSD__) || \
+ defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+#define HAVE_CHARDEV_PARPORT 1
+#endif
+
+#endif /* CHAR_PARALLEL_H */
diff --git a/chardev/char-parallel.c b/chardev/char-parallel.c
new file mode 100644
index 0000000000..3fa22ce29d
--- /dev/null
+++ b/chardev/char-parallel.c
@@ -0,0 +1,316 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "sysemu/char.h"
+#include "qapi/error.h"
+#include <sys/ioctl.h>
+
+#ifdef CONFIG_BSD
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+#include <dev/ppbus/ppi.h>
+#include <dev/ppbus/ppbconf.h>
+#elif defined(__DragonFly__)
+#include <dev/misc/ppi/ppi.h>
+#include <bus/ppbus/ppbconf.h>
+#endif
+#else
+#ifdef __linux__
+#include <linux/ppdev.h>
+#include <linux/parport.h>
+#endif
+#endif
+
+#include "char-fd.h"
+#include "char-parallel.h"
+
+#if defined(__linux__)
+
+typedef struct {
+ Chardev parent;
+ int fd;
+ int mode;
+} ParallelChardev;
+
+#define PARALLEL_CHARDEV(obj) \
+ OBJECT_CHECK(ParallelChardev, (obj), TYPE_CHARDEV_PARALLEL)
+
+static int pp_hw_mode(ParallelChardev *s, uint16_t mode)
+{
+ if (s->mode != mode) {
+ int m = mode;
+ if (ioctl(s->fd, PPSETMODE, &m) < 0) {
+ return 0;
+ }
+ s->mode = mode;
+ }
+ return 1;
+}
+
+static int pp_ioctl(Chardev *chr, int cmd, void *arg)
+{
+ ParallelChardev *drv = PARALLEL_CHARDEV(chr);
+ int fd = drv->fd;
+ uint8_t b;
+
+ switch (cmd) {
+ case CHR_IOCTL_PP_READ_DATA:
+ if (ioctl(fd, PPRDATA, &b) < 0) {
+ return -ENOTSUP;
+ }
+ *(uint8_t *)arg = b;
+ break;
+ case CHR_IOCTL_PP_WRITE_DATA:
+ b = *(uint8_t *)arg;
+ if (ioctl(fd, PPWDATA, &b) < 0) {
+ return -ENOTSUP;
+ }
+ break;
+ case CHR_IOCTL_PP_READ_CONTROL:
+ if (ioctl(fd, PPRCONTROL, &b) < 0) {
+ return -ENOTSUP;
+ }
+ /* Linux gives only the lowest bits, and no way to know data
+ direction! For better compatibility set the fixed upper
+ bits. */
+ *(uint8_t *)arg = b | 0xc0;
+ break;
+ case CHR_IOCTL_PP_WRITE_CONTROL:
+ b = *(uint8_t *)arg;
+ if (ioctl(fd, PPWCONTROL, &b) < 0) {
+ return -ENOTSUP;
+ }
+ break;
+ case CHR_IOCTL_PP_READ_STATUS:
+ if (ioctl(fd, PPRSTATUS, &b) < 0) {
+ return -ENOTSUP;
+ }
+ *(uint8_t *)arg = b;
+ break;
+ case CHR_IOCTL_PP_DATA_DIR:
+ if (ioctl(fd, PPDATADIR, (int *)arg) < 0) {
+ return -ENOTSUP;
+ }
+ break;
+ case CHR_IOCTL_PP_EPP_READ_ADDR:
+ if (pp_hw_mode(drv, IEEE1284_MODE_EPP | IEEE1284_ADDR)) {
+ struct ParallelIOArg *parg = arg;
+ int n = read(fd, parg->buffer, parg->count);
+ if (n != parg->count) {
+ return -EIO;
+ }
+ }
+ break;
+ case CHR_IOCTL_PP_EPP_READ:
+ if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) {
+ struct ParallelIOArg *parg = arg;
+ int n = read(fd, parg->buffer, parg->count);
+ if (n != parg->count) {
+ return -EIO;
+ }
+ }
+ break;
+ case CHR_IOCTL_PP_EPP_WRITE_ADDR:
+ if (pp_hw_mode(drv, IEEE1284_MODE_EPP | IEEE1284_ADDR)) {
+ struct ParallelIOArg *parg = arg;
+ int n = write(fd, parg->buffer, parg->count);
+ if (n != parg->count) {
+ return -EIO;
+ }
+ }
+ break;
+ case CHR_IOCTL_PP_EPP_WRITE:
+ if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) {
+ struct ParallelIOArg *parg = arg;
+ int n = write(fd, parg->buffer, parg->count);
+ if (n != parg->count) {
+ return -EIO;
+ }
+ }
+ break;
+ default:
+ return -ENOTSUP;
+ }
+ return 0;
+}
+
+static void qemu_chr_open_pp_fd(Chardev *chr,
+ int fd,
+ bool *be_opened,
+ Error **errp)
+{
+ ParallelChardev *drv = PARALLEL_CHARDEV(chr);
+
+ if (ioctl(fd, PPCLAIM) < 0) {
+ error_setg_errno(errp, errno, "not a parallel port");
+ close(fd);
+ return;
+ }
+
+ drv->fd = fd;
+ drv->mode = IEEE1284_MODE_COMPAT;
+}
+#endif /* __linux__ */
+
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
+
+typedef struct {
+ Chardev parent;
+ int fd;
+} ParallelChardev;
+
+#define PARALLEL_CHARDEV(obj) \
+ OBJECT_CHECK(ParallelChardev, (obj), TYPE_CHARDEV_PARALLEL)
+
+static int pp_ioctl(Chardev *chr, int cmd, void *arg)
+{
+ ParallelChardev *drv = PARALLEL_CHARDEV(chr);
+ uint8_t b;
+
+ switch (cmd) {
+ case CHR_IOCTL_PP_READ_DATA:
+ if (ioctl(drv->fd, PPIGDATA, &b) < 0) {
+ return -ENOTSUP;
+ }
+ *(uint8_t *)arg = b;
+ break;
+ case CHR_IOCTL_PP_WRITE_DATA:
+ b = *(uint8_t *)arg;
+ if (ioctl(drv->fd, PPISDATA, &b) < 0) {
+ return -ENOTSUP;
+ }
+ break;
+ case CHR_IOCTL_PP_READ_CONTROL:
+ if (ioctl(drv->fd, PPIGCTRL, &b) < 0) {
+ return -ENOTSUP;
+ }
+ *(uint8_t *)arg = b;
+ break;
+ case CHR_IOCTL_PP_WRITE_CONTROL:
+ b = *(uint8_t *)arg;
+ if (ioctl(drv->fd, PPISCTRL, &b) < 0) {
+ return -ENOTSUP;
+ }
+ break;
+ case CHR_IOCTL_PP_READ_STATUS:
+ if (ioctl(drv->fd, PPIGSTATUS, &b) < 0) {
+ return -ENOTSUP;
+ }
+ *(uint8_t *)arg = b;
+ break;
+ default:
+ return -ENOTSUP;
+ }
+ return 0;
+}
+
+static void qemu_chr_open_pp_fd(Chardev *chr,
+ int fd,
+ bool *be_opened,
+ Error **errp)
+{
+ ParallelChardev *drv = PARALLEL_CHARDEV(chr);
+ drv->fd = fd;
+ *be_opened = false;
+}
+#endif
+
+#ifdef HAVE_CHARDEV_PARPORT
+static void qmp_chardev_open_parallel(Chardev *chr,
+ ChardevBackend *backend,
+ bool *be_opened,
+ Error **errp)
+{
+ ChardevHostdev *parallel = backend->u.parallel.data;
+ int fd;
+
+ fd = qmp_chardev_open_file_source(parallel->device, O_RDWR, errp);
+ if (fd < 0) {
+ return;
+ }
+ qemu_chr_open_pp_fd(chr, fd, be_opened, errp);
+}
+
+static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
+ Error **errp)
+{
+ const char *device = qemu_opt_get(opts, "path");
+ ChardevHostdev *parallel;
+
+ if (device == NULL) {
+ error_setg(errp, "chardev: parallel: no device path given");
+ return;
+ }
+ backend->type = CHARDEV_BACKEND_KIND_PARALLEL;
+ parallel = backend->u.parallel.data = g_new0(ChardevHostdev, 1);
+ qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(parallel));
+ parallel->device = g_strdup(device);
+}
+
+static void char_parallel_class_init(ObjectClass *oc, void *data)
+{
+ ChardevClass *cc = CHARDEV_CLASS(oc);
+
+ cc->parse = qemu_chr_parse_parallel;
+ cc->open = qmp_chardev_open_parallel;
+#if defined(__linux__)
+ cc->chr_ioctl = pp_ioctl;
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
+ defined(__DragonFly__)
+ cc->chr_ioctl = pp_ioctl;
+#endif
+}
+
+static void char_parallel_finalize(Object *obj)
+{
+#if defined(__linux__)
+ Chardev *chr = CHARDEV(obj);
+ ParallelChardev *drv = PARALLEL_CHARDEV(chr);
+ int fd = drv->fd;
+
+ pp_hw_mode(drv, IEEE1284_MODE_COMPAT);
+ ioctl(fd, PPRELEASE);
+ close(fd);
+ qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
+ defined(__DragonFly__)
+ /* FIXME: close fd? */
+#endif
+}
+
+static const TypeInfo char_parallel_type_info = {
+ .name = TYPE_CHARDEV_PARALLEL,
+ .parent = TYPE_CHARDEV,
+ .instance_size = sizeof(ParallelChardev),
+ .instance_finalize = char_parallel_finalize,
+ .class_init = char_parallel_class_init,
+};
+
+static void register_types(void)
+{
+ type_register_static(&char_parallel_type_info);
+}
+
+type_init(register_types);
+
+#endif
diff --git a/chardev/char.c b/chardev/char.c
index faba68db21..a9daf9956c 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -53,19 +53,6 @@
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/select.h>
-#ifdef CONFIG_BSD
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-#include <dev/ppbus/ppi.h>
-#include <dev/ppbus/ppbconf.h>
-#elif defined(__DragonFly__)
-#include <dev/misc/ppi/ppi.h>
-#include <bus/ppbus/ppbconf.h>
-#endif
-#else
-#ifdef __linux__
-#include <linux/ppdev.h>
-#include <linux/parport.h>
-#endif
#ifdef __sun__
#include <sys/ethernet.h>
#include <sys/sockio.h>
@@ -78,17 +65,16 @@
#include <netinet/tcp.h>
#endif
#endif
-#endif
#include "qemu/sockets.h"
#include "ui/qemu-spice.h"
#include "char-mux.h"
-#include "char-fd.h"
#include "char-io.h"
#ifdef _WIN32
#include "char-win.h"
#endif
+#include "char-parallel.h"
#include "char-serial.h"
/***********************************************************/
@@ -653,198 +639,6 @@ void qemu_chr_fe_take_focus(CharBackend *b)
}
}
-#ifndef _WIN32
-
-#if defined(__linux__)
-
-#define HAVE_CHARDEV_PARPORT 1
-
-typedef struct {
- Chardev parent;
- int fd;
- int mode;
-} ParallelChardev;
-
-#define PARALLEL_CHARDEV(obj) \
- OBJECT_CHECK(ParallelChardev, (obj), TYPE_CHARDEV_PARALLEL)
-
-static int pp_hw_mode(ParallelChardev *s, uint16_t mode)
-{
- if (s->mode != mode) {
- int m = mode;
- if (ioctl(s->fd, PPSETMODE, &m) < 0)
- return 0;
- s->mode = mode;
- }
- return 1;
-}
-
-static int pp_ioctl(Chardev *chr, int cmd, void *arg)
-{
- ParallelChardev *drv = PARALLEL_CHARDEV(chr);
- int fd = drv->fd;
- uint8_t b;
-
- switch(cmd) {
- case CHR_IOCTL_PP_READ_DATA:
- if (ioctl(fd, PPRDATA, &b) < 0)
- return -ENOTSUP;
- *(uint8_t *)arg = b;
- break;
- case CHR_IOCTL_PP_WRITE_DATA:
- b = *(uint8_t *)arg;
- if (ioctl(fd, PPWDATA, &b) < 0)
- return -ENOTSUP;
- break;
- case CHR_IOCTL_PP_READ_CONTROL:
- if (ioctl(fd, PPRCONTROL, &b) < 0)
- return -ENOTSUP;
- /* Linux gives only the lowest bits, and no way to know data
- direction! For better compatibility set the fixed upper
- bits. */
- *(uint8_t *)arg = b | 0xc0;
- break;
- case CHR_IOCTL_PP_WRITE_CONTROL:
- b = *(uint8_t *)arg;
- if (ioctl(fd, PPWCONTROL, &b) < 0)
- return -ENOTSUP;
- break;
- case CHR_IOCTL_PP_READ_STATUS:
- if (ioctl(fd, PPRSTATUS, &b) < 0)
- return -ENOTSUP;
- *(uint8_t *)arg = b;
- break;
- case CHR_IOCTL_PP_DATA_DIR:
- if (ioctl(fd, PPDATADIR, (int *)arg) < 0)
- return -ENOTSUP;
- break;
- case CHR_IOCTL_PP_EPP_READ_ADDR:
- if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) {
- struct ParallelIOArg *parg = arg;
- int n = read(fd, parg->buffer, parg->count);
- if (n != parg->count) {
- return -EIO;
- }
- }
- break;
- case CHR_IOCTL_PP_EPP_READ:
- if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) {
- struct ParallelIOArg *parg = arg;
- int n = read(fd, parg->buffer, parg->count);
- if (n != parg->count) {
- return -EIO;
- }
- }
- break;
- case CHR_IOCTL_PP_EPP_WRITE_ADDR:
- if (pp_hw_mode(drv, IEEE1284_MODE_EPP|IEEE1284_ADDR)) {
- struct ParallelIOArg *parg = arg;
- int n = write(fd, parg->buffer, parg->count);
- if (n != parg->count) {
- return -EIO;
- }
- }
- break;
- case CHR_IOCTL_PP_EPP_WRITE:
- if (pp_hw_mode(drv, IEEE1284_MODE_EPP)) {
- struct ParallelIOArg *parg = arg;
- int n = write(fd, parg->buffer, parg->count);
- if (n != parg->count) {
- return -EIO;
- }
- }
- break;
- default:
- return -ENOTSUP;
- }
- return 0;
-}
-
-static void qemu_chr_open_pp_fd(Chardev *chr,
- int fd,
- bool *be_opened,
- Error **errp)
-{
- ParallelChardev *drv = PARALLEL_CHARDEV(chr);
-
- if (ioctl(fd, PPCLAIM) < 0) {
- error_setg_errno(errp, errno, "not a parallel port");
- close(fd);
- return;
- }
-
- drv->fd = fd;
- drv->mode = IEEE1284_MODE_COMPAT;
-}
-#endif /* __linux__ */
-
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
-
-#define HAVE_CHARDEV_PARPORT 1
-
-typedef struct {
- Chardev parent;
- int fd;
-} ParallelChardev;
-
-#define PARALLEL_CHARDEV(obj) \
- OBJECT_CHECK(ParallelChardev, (obj), TYPE_CHARDEV_PARALLEL)
-
-static int pp_ioctl(Chardev *chr, int cmd, void *arg)
-{
- ParallelChardev *drv = PARALLEL_CHARDEV(chr);
- uint8_t b;
-
- switch (cmd) {
- case CHR_IOCTL_PP_READ_DATA:
- if (ioctl(drv->fd, PPIGDATA, &b) < 0) {
- return -ENOTSUP;
- }
- *(uint8_t *)arg = b;
- break;
- case CHR_IOCTL_PP_WRITE_DATA:
- b = *(uint8_t *)arg;
- if (ioctl(drv->fd, PPISDATA, &b) < 0) {
- return -ENOTSUP;
- }
- break;
- case CHR_IOCTL_PP_READ_CONTROL:
- if (ioctl(drv->fd, PPIGCTRL, &b) < 0) {
- return -ENOTSUP;
- }
- *(uint8_t *)arg = b;
- break;
- case CHR_IOCTL_PP_WRITE_CONTROL:
- b = *(uint8_t *)arg;
- if (ioctl(drv->fd, PPISCTRL, &b) < 0) {
- return -ENOTSUP;
- }
- break;
- case CHR_IOCTL_PP_READ_STATUS:
- if (ioctl(drv->fd, PPIGSTATUS, &b) < 0) {
- return -ENOTSUP;
- }
- *(uint8_t *)arg = b;
- break;
- default:
- return -ENOTSUP;
- }
- return 0;
-}
-
-static void qemu_chr_open_pp_fd(Chardev *chr,
- int fd,
- bool *be_opened,
- Error **errp)
-{
- ParallelChardev *drv = PARALLEL_CHARDEV(chr);
- drv->fd = fd;
- *be_opened = false;
-}
-#endif
-
-#endif /* !_WIN32 */
-
int qemu_chr_wait_connected(Chardev *chr, Error **errp)
{
ChardevClass *cc = CHARDEV_GET_CLASS(chr);
@@ -1019,24 +813,6 @@ void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend)
backend->logappend = qemu_opt_get_bool(opts, "logappend", false);
}
-#ifdef HAVE_CHARDEV_PARPORT
-static void qemu_chr_parse_parallel(QemuOpts *opts, ChardevBackend *backend,
- Error **errp)
-{
- const char *device = qemu_opt_get(opts, "path");
- ChardevHostdev *parallel;
-
- backend->type = CHARDEV_BACKEND_KIND_PARALLEL;
- if (device == NULL) {
- error_setg(errp, "chardev: parallel: no device path given");
- return;
- }
- parallel = backend->u.parallel.data = g_new0(ChardevHostdev, 1);
- qemu_chr_parse_common(opts, qapi_ChardevHostdev_base(parallel));
- parallel->device = g_strdup(device);
-}
-#endif
-
static const ChardevClass *char_get_class(const char *driver, Error **errp)
{
ObjectClass *oc;
@@ -1484,64 +1260,6 @@ QemuOptsList qemu_chardev_opts = {
},
};
-#ifndef _WIN32
-
-#ifdef HAVE_CHARDEV_PARPORT
-static void qmp_chardev_open_parallel(Chardev *chr,
- ChardevBackend *backend,
- bool *be_opened,
- Error **errp)
-{
- ChardevHostdev *parallel = backend->u.parallel.data;
- int fd;
-
- fd = qmp_chardev_open_file_source(parallel->device, O_RDWR, errp);
- if (fd < 0) {
- return;
- }
- qemu_chr_open_pp_fd(chr, fd, be_opened, errp);
-}
-
-static void char_parallel_class_init(ObjectClass *oc, void *data)
-{
- ChardevClass *cc = CHARDEV_CLASS(oc);
-
- cc->parse = qemu_chr_parse_parallel;
- cc->open = qmp_chardev_open_parallel;
-#if defined(__linux__)
- cc->chr_ioctl = pp_ioctl;
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
- cc->chr_ioctl = pp_ioctl;
-#endif
-}
-
-static void char_parallel_finalize(Object *obj)
-{
-#if defined(__linux__)
- Chardev *chr = CHARDEV(obj);
- ParallelChardev *drv = PARALLEL_CHARDEV(chr);
- int fd = drv->fd;
-
- pp_hw_mode(drv, IEEE1284_MODE_COMPAT);
- ioctl(fd, PPRELEASE);
- close(fd);
- qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
-#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
- /* FIXME: close fd? */
-#endif
-}
-
-static const TypeInfo char_parallel_type_info = {
- .name = TYPE_CHARDEV_PARALLEL,
- .parent = TYPE_CHARDEV,
- .instance_size = sizeof(ParallelChardev),
- .instance_finalize = char_parallel_finalize,
- .class_init = char_parallel_class_init,
-};
-#endif
-
-#endif /* WIN32 */
-
bool qemu_chr_has_feature(Chardev *chr,
ChardevFeature feature)
{
@@ -1643,9 +1361,6 @@ void qemu_chr_cleanup(void)
static void register_types(void)
{
type_register_static(&char_type_info);
-#ifdef HAVE_CHARDEV_PARPORT
- type_register_static(&char_parallel_type_info);
-#endif
/* this must be done after machine init, since we register FEs with muxes
* as part of realize functions like serial_isa_realizefn when -nographic
diff --git a/chardev/Makefile.objs b/chardev/Makefile.objs
index 45fc8af0c4..1feda0f0ed 100644
--- a/chardev/Makefile.objs
+++ b/chardev/Makefile.objs
@@ -5,6 +5,7 @@ chardev-obj-y += char-file.o
chardev-obj-y += char-io.o
chardev-obj-y += char-mux.o
chardev-obj-y += char-null.o
+chardev-obj-$(CONFIG_POSIX) += char-parallel.o
chardev-obj-y += char-pipe.o
chardev-obj-$(CONFIG_POSIX) += char-pty.o
chardev-obj-y += char-ringbuf.o
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* [Qemu-devel] [PULL 41/41] char: headers clean-up
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (39 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 40/41] char: move parallel chardev in " Marc-André Lureau
@ 2017-01-31 16:21 ` Marc-André Lureau
2017-01-31 17:57 ` [Qemu-devel] [PULL 00/41] Chr split patches no-reply
2017-01-31 18:41 ` Peter Maydell
42 siblings, 0 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 16:21 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, Marc-André Lureau
Those could probably be squashed with earlier patches, however I
couldn't easily identify them, test them or check if there are still
necessary on various platforms.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
include/sysemu/char.h | 5 -----
chardev/char.c | 40 +---------------------------------------
hmp.c | 1 +
monitor.c | 1 +
qmp.c | 1 +
tests/vhost-user-test.c | 1 +
6 files changed, 5 insertions(+), 44 deletions(-)
diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index b256e79c31..450881d42c 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -2,12 +2,7 @@
#define QEMU_CHAR_H
#include "qemu-common.h"
-#include "qemu/queue.h"
#include "qemu/option.h"
-#include "qemu/config-file.h"
-#include "block/aio.h"
-#include "qapi/qmp/qobject.h"
-#include "qapi/qmp/qstring.h"
#include "qemu/main-loop.h"
#include "qemu/bitmap.h"
#include "qom/object.h"
diff --git a/chardev/char.c b/chardev/char.c
index a9daf9956c..abd525f75e 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -26,54 +26,16 @@
#include "qemu/cutils.h"
#include "monitor/monitor.h"
#include "sysemu/sysemu.h"
-#include "sysemu/block-backend.h"
+#include "qemu/config-file.h"
#include "qemu/error-report.h"
-#include "qemu/timer.h"
#include "sysemu/char.h"
-#include "hw/usb.h"
#include "qmp-commands.h"
-#include "qapi/clone-visitor.h"
#include "qapi-visit.h"
-#include "qemu/base64.h"
-#include "io/channel-socket.h"
-#include "io/channel-tls.h"
#include "sysemu/replay.h"
#include "qemu/help_option.h"
-#include <zlib.h>
-
-#ifndef _WIN32
-#include <sys/times.h>
-#include <sys/wait.h>
-#include <sys/ioctl.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <net/if.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <sys/select.h>
-#ifdef __sun__
-#include <sys/ethernet.h>
-#include <sys/sockio.h>
-#include <netinet/arp.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h> // must come after ip.h
-#include <netinet/udp.h>
-#include <netinet/tcp.h>
-#endif
-#endif
-
-#include "qemu/sockets.h"
-#include "ui/qemu-spice.h"
-
#include "char-mux.h"
#include "char-io.h"
-#ifdef _WIN32
-#include "char-win.h"
-#endif
#include "char-parallel.h"
#include "char-serial.h"
diff --git a/hmp.c b/hmp.c
index 8522efea26..2bc4f062bb 100644
--- a/hmp.c
+++ b/hmp.c
@@ -19,6 +19,7 @@
#include "net/eth.h"
#include "sysemu/char.h"
#include "sysemu/block-backend.h"
+#include "qemu/config-file.h"
#include "qemu/option.h"
#include "qemu/timer.h"
#include "qmp-commands.h"
diff --git a/monitor.c b/monitor.c
index 25a480a95e..b0181cb0e6 100644
--- a/monitor.c
+++ b/monitor.c
@@ -40,6 +40,7 @@
#include "sysemu/sysemu.h"
#include "sysemu/numa.h"
#include "monitor/monitor.h"
+#include "qemu/config-file.h"
#include "qemu/readline.h"
#include "ui/console.h"
#include "ui/input.h"
diff --git a/qmp.c b/qmp.c
index 2834f02b69..dfaabac1a6 100644
--- a/qmp.c
+++ b/qmp.c
@@ -18,6 +18,7 @@
#include "qemu/cutils.h"
#include "monitor/monitor.h"
#include "sysemu/sysemu.h"
+#include "qemu/config-file.h"
#include "qemu/uuid.h"
#include "qmp-commands.h"
#include "sysemu/char.h"
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index f3ac6ea21a..2c45c7b29f 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -12,6 +12,7 @@
#include "libqtest.h"
#include "qapi/error.h"
+#include "qemu/config-file.h"
#include "qemu/option.h"
#include "qemu/range.h"
#include "qemu/sockets.h"
--
2.11.0.295.gd7dffce1c.dirty
^ permalink raw reply related [flat|nested] 49+ messages in thread
* Re: [Qemu-devel] [PULL 00/41] Chr split patches
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (40 preceding siblings ...)
2017-01-31 16:21 ` [Qemu-devel] [PULL 41/41] char: headers clean-up Marc-André Lureau
@ 2017-01-31 17:57 ` no-reply
2017-01-31 18:41 ` Peter Maydell
42 siblings, 0 replies; 49+ messages in thread
From: no-reply @ 2017-01-31 17:57 UTC (permalink / raw)
To: marcandre.lureau; +Cc: famz, qemu-devel, peter.maydell
Hi,
Your series seems to have some coding style problems. See output below for
more information:
Type: series
Subject: [Qemu-devel] [PULL 00/41] Chr split patches
Message-id: 20170131162122.29408-1-marcandre.lureau@redhat.com
=== TEST SCRIPT BEGIN ===
#!/bin/bash
BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0
# Useful git options
git config --local diff.renamelimit 0
git config --local diff.renames True
commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done
exit $failed
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
* [new tag] patchew/20170131162122.29408-1-marcandre.lureau@redhat.com -> patchew/20170131162122.29408-1-marcandre.lureau@redhat.com
- [tag update] patchew/cover.1485878688.git.berto@igalia.com -> patchew/cover.1485878688.git.berto@igalia.com
Switched to a new branch 'test'
95ffd75 char: headers clean-up
21c900a char: move parallel chardev in its own file
55df019 char: move serial chardev to its own file
e7e9361 char: move pty chardev in its own file
f715f19 char: move pipe chardev in its own file
262f7e3 char: move console in its own file
9a9d6eb char: move stdio in its own file
5ffc3c6 char: move file chardev in its own file
050e718 char: move udp chardev in its own file
74b2905 char: move socket chardev to its own file
e65f01f char: move win-stdio into its own file
d77168a char: move win chardev base class in its own file
eac8509 char: move fd chardev in its own file
701cd50 char: move QIOChannel-related stuff to char-io.h
d2193c2 char: remove unused READ_RETRIES
e63481d char: rename and move to header CHR_READ_BUF_LEN
359c68c char: move ringbuf/memory to its own file
318282b char: move mux to its own file
20c8425 char: move null chardev to its own file
793d26c char: make null_chr_write() the default method
479d2f7 char: create chardev-obj-y
e52f6c3 char: move to chardev/
53335b9 char: remove class kind field
fba7593 char: rename remaining CharDriver to Chardev
768322b char: get rid of CharDriver
23766b7 char: remove chr_free
df541a5 char-fd: convert to finalize
6fddb56 char-win: convert to finalize
f90dce0 char-win: do not override chr_free
010dcf3 char-win-stdio: convert to finalize
da6b699 char-stdio: convert to finalize
676ec0e char-parallel: convert parallel to finalize
122b1e6 char-ringbuf: convert to finalize
ae17198 char-pty: convert to finalize
a9dd8b2 char-socket: convert to finalize
7ac8d6b char-udp: convert to finalize
c0062a9 mux: convert to finalize
42d5c45 msmouse: convert to finalize
a03aea1 baum: convert to finalize
0026a57 spice-qemu-char: convert to finalize
cbe8a1d MAINTAINERS: add myself to qemu-char.c
=== OUTPUT BEGIN ===
Checking PATCH 1/41: MAINTAINERS: add myself to qemu-char.c...
Checking PATCH 2/41: spice-qemu-char: convert to finalize...
Checking PATCH 3/41: baum: convert to finalize...
Checking PATCH 4/41: msmouse: convert to finalize...
Checking PATCH 5/41: mux: convert to finalize...
Checking PATCH 6/41: char-udp: convert to finalize...
Checking PATCH 7/41: char-socket: convert to finalize...
Checking PATCH 8/41: char-pty: convert to finalize...
Checking PATCH 9/41: char-ringbuf: convert to finalize...
Checking PATCH 10/41: char-parallel: convert parallel to finalize...
WARNING: architecture specific defines should be avoided
#49: FILE: qemu-char.c:4699:
+#if defined(__linux__)
WARNING: line over 80 characters
#58: FILE: qemu-char.c:4708:
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
total: 0 errors, 2 warnings, 52 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 11/41: char-stdio: convert to finalize...
Checking PATCH 12/41: char-win-stdio: convert to finalize...
Checking PATCH 13/41: char-win: do not override chr_free...
Checking PATCH 14/41: char-win: convert to finalize...
Checking PATCH 15/41: char-fd: convert to finalize...
Checking PATCH 16/41: char: remove chr_free...
Checking PATCH 17/41: char: get rid of CharDriver...
Checking PATCH 18/41: char: rename remaining CharDriver to Chardev...
Checking PATCH 19/41: char: remove class kind field...
Checking PATCH 20/41: char: move to chardev/...
Checking PATCH 21/41: char: create chardev-obj-y...
Checking PATCH 22/41: char: make null_chr_write() the default method...
Checking PATCH 23/41: char: move null chardev to its own file...
Checking PATCH 24/41: char: move mux to its own file...
Checking PATCH 25/41: char: move ringbuf/memory to its own file...
Checking PATCH 26/41: char: rename and move to header CHR_READ_BUF_LEN...
Checking PATCH 27/41: char: remove unused READ_RETRIES...
Checking PATCH 28/41: char: move QIOChannel-related stuff to char-io.h...
Checking PATCH 29/41: char: move fd chardev in its own file...
Checking PATCH 30/41: char: move win chardev base class in its own file...
Checking PATCH 31/41: char: move win-stdio into its own file...
Checking PATCH 32/41: char: move socket chardev to its own file...
Checking PATCH 33/41: char: move udp chardev in its own file...
Checking PATCH 34/41: char: move file chardev in its own file...
Checking PATCH 35/41: char: move stdio in its own file...
Checking PATCH 36/41: char: move console in its own file...
Checking PATCH 37/41: char: move pipe chardev in its own file...
Checking PATCH 38/41: char: move pty chardev in its own file...
WARNING: architecture specific defines should be avoided
#64: FILE: chardev/char-pty.c:34:
+#if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
total: 0 errors, 1 warnings, 577 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 39/41: char: move serial chardev to its own file...
ERROR: if this code is redundant consider removing it
#91: FILE: chardev/char-serial.c:61:
+#if 0
ERROR: braces {} are necessary for all arms of this statement
#97: FILE: chardev/char-serial.c:67:
+#define check_speed(val) if (speed <= val) { spd = B##val; break; }
[...]
total: 2 errors, 0 warnings, 692 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 40/41: char: move parallel chardev in its own file...
WARNING: architecture specific defines should be avoided
#60: FILE: chardev/char-parallel.c:30:
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
WARNING: architecture specific defines should be avoided
#68: FILE: chardev/char-parallel.c:38:
+#ifdef __linux__
WARNING: architecture specific defines should be avoided
#77: FILE: chardev/char-parallel.c:47:
+#if defined(__linux__)
WARNING: line over 80 characters
#205: FILE: chardev/char-parallel.c:175:
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
WARNING: architecture specific defines should be avoided
#205: FILE: chardev/char-parallel.c:175:
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
WARNING: architecture specific defines should be avoided
#306: FILE: chardev/char-parallel.c:276:
+#if defined(__linux__)
WARNING: architecture specific defines should be avoided
#316: FILE: chardev/char-parallel.c:286:
+#if defined(__linux__)
WARNING: architecture specific defines should be avoided
#379: FILE: chardev/char-parallel.h:27:
+#if defined(__linux__) || defined(__FreeBSD__) || \
total: 0 errors, 8 warnings, 687 lines checked
Your patch has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 41/41: char: headers clean-up...
=== OUTPUT END ===
Test command exited with code: 1
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org
^ permalink raw reply [flat|nested] 49+ messages in thread
* Re: [Qemu-devel] [PULL 00/41] Chr split patches
2017-01-31 16:20 [Qemu-devel] [PULL 00/41] Chr split patches Marc-André Lureau
` (41 preceding siblings ...)
2017-01-31 17:57 ` [Qemu-devel] [PULL 00/41] Chr split patches no-reply
@ 2017-01-31 18:41 ` Peter Maydell
2017-01-31 18:55 ` Marc-André Lureau
42 siblings, 1 reply; 49+ messages in thread
From: Peter Maydell @ 2017-01-31 18:41 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: QEMU Developers
On 31 January 2017 at 16:20, Marc-André Lureau
<marcandre.lureau@redhat.com> wrote:
> The following changes since commit a0def594286d9110a6035e02eef558cf3cf5d847:
>
> Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging (2017-01-30 10:23:20 +0000)
>
> are available in the git repository at:
>
> https://github.com/elmarco/qemu.git tags/chr-split-pull-request
>
> for you to fetch changes up to 3766519be2843e0947425cafd1e7e205dd63f0fd:
>
> char: headers clean-up (2017-01-31 13:03:48 +0400)
>
> ----------------------------------------------------------------
>
'make check' fails on a linux-user-targets-only build:
tests/test-char.o: In function `char_stdio_test_subprocess':
/home/petmay01/linaro/qemu-for-merges/tests/test-char.c:47: undefined
reference to `qemu_chr_new'
/home/petmay01/linaro/qemu-for-merges/tests/test-char.c:50: undefined
reference to `qemu_chr_fe_init'
/home/petmay01/linaro/qemu-for-merges/tests/test-char.c:51: undefined
reference to `qemu_chr_fe_set_open'
/home/petmay01/linaro/qemu-for-merges/tests/test-char.c:52: undefined
reference to `qemu_chr_fe_write'
[etc etc etc]
thanks
-- PMM
^ permalink raw reply [flat|nested] 49+ messages in thread
* Re: [Qemu-devel] [PULL 00/41] Chr split patches
2017-01-31 18:41 ` Peter Maydell
@ 2017-01-31 18:55 ` Marc-André Lureau
2017-01-31 19:00 ` Eric Blake
0 siblings, 1 reply; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 18:55 UTC (permalink / raw)
To: Peter Maydell; +Cc: QEMU Developers, Eric Blake
Hi!
On Tue, Jan 31, 2017 at 10:42 PM Peter Maydell <peter.maydell@linaro.org>
wrote:
> On 31 January 2017 at 16:20, Marc-André Lureau
> <marcandre.lureau@redhat.com> wrote:
> > The following changes since commit
> a0def594286d9110a6035e02eef558cf3cf5d847:
> >
> > Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into
> staging (2017-01-30 10:23:20 +0000)
> >
> > are available in the git repository at:
> >
> > https://github.com/elmarco/qemu.git tags/chr-split-pull-request
> >
> > for you to fetch changes up to 3766519be2843e0947425cafd1e7e205dd63f0fd:
> >
> > char: headers clean-up (2017-01-31 13:03:48 +0400)
> >
> > ----------------------------------------------------------------
> >
>
> 'make check' fails on a linux-user-targets-only build:
>
> tests/test-char.o: In function `char_stdio_test_subprocess':
> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:47: undefined
> reference to `qemu_chr_new'
> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:50: undefined
> reference to `qemu_chr_fe_init'
> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:51: undefined
> reference to `qemu_chr_fe_set_open'
> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:52: undefined
> reference to `qemu_chr_fe_write'
> [etc etc etc]
>
>
Oh good catch. We want to have chardev-obj-y defined globally, but only
linked with -softmmu target.
A possible fix to squash with chardev-obj-j patch is:
Eric, do you want me to resend the patch for review or is that enough for
you to ack?
diff --git a/Makefile.objs b/Makefile.objs
index 91a4794f28..b09a9588fc 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -4,6 +4,8 @@ stub-obj-y = stubs/ crypto/
util-obj-y = util/ qobject/ qapi/
util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
+chardev-obj-y = chardev/
+
#######################################################################
# block-obj-y is code used by both qemu system emulation and qemu-img
@@ -78,8 +80,6 @@ common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
common-obj-$(CONFIG_FDT) += device_tree.o
-chardev-obj-y = chardev/
-
######################################################################
# qapi
diff --git a/Makefile.target b/Makefile.target
index 5a487b5187..054db85e9e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -188,10 +188,9 @@ dummy := $(call unnest-vars,.., \
common-obj-m)
target-obj-y := $(target-obj-y-save)
all-obj-y += $(common-obj-y)
-all-obj-y += $(chardev-obj-y)
all-obj-y += $(target-obj-y)
all-obj-y += $(qom-obj-y)
-all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y)
+all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y) $(chardev-obj-y)
all-obj-$(CONFIG_USER_ONLY) += $(crypto-aes-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)
--
Marc-André Lureau
^ permalink raw reply related [flat|nested] 49+ messages in thread
* Re: [Qemu-devel] [PULL 00/41] Chr split patches
2017-01-31 18:55 ` Marc-André Lureau
@ 2017-01-31 19:00 ` Eric Blake
2017-01-31 19:37 ` Marc-André Lureau
0 siblings, 1 reply; 49+ messages in thread
From: Eric Blake @ 2017-01-31 19:00 UTC (permalink / raw)
To: Marc-André Lureau, Peter Maydell; +Cc: QEMU Developers
[-- Attachment #1: Type: text/plain, Size: 2529 bytes --]
On 01/31/2017 12:55 PM, Marc-André Lureau wrote:
>> 'make check' fails on a linux-user-targets-only build:
>>
>> tests/test-char.o: In function `char_stdio_test_subprocess':
>> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:47: undefined
>> reference to `qemu_chr_new'
>> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:50: undefined
>> reference to `qemu_chr_fe_init'
>> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:51: undefined
>> reference to `qemu_chr_fe_set_open'
>> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:52: undefined
>> reference to `qemu_chr_fe_write'
>> [etc etc etc]
>>
>>
> Oh good catch. We want to have chardev-obj-y defined globally, but only
> linked with -softmmu target.
>
> A possible fix to squash with chardev-obj-j patch is:
>
> Eric, do you want me to resend the patch for review or is that enough for
> you to ack?
>
I'm okay ack'ing the interdiff (that is, squash this in, and you can
keep the R-b you already have).
> diff --git a/Makefile.objs b/Makefile.objs
> index 91a4794f28..b09a9588fc 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -4,6 +4,8 @@ stub-obj-y = stubs/ crypto/
> util-obj-y = util/ qobject/ qapi/
> util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
>
> +chardev-obj-y = chardev/
> +
> #######################################################################
> # block-obj-y is code used by both qemu system emulation and qemu-img
>
> @@ -78,8 +80,6 @@ common-obj-$(CONFIG_SECCOMP) += qemu-seccomp.o
>
> common-obj-$(CONFIG_FDT) += device_tree.o
>
> -chardev-obj-y = chardev/
> -
> ######################################################################
> # qapi
>
> diff --git a/Makefile.target b/Makefile.target
> index 5a487b5187..054db85e9e 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -188,10 +188,9 @@ dummy := $(call unnest-vars,.., \
> common-obj-m)
> target-obj-y := $(target-obj-y-save)
> all-obj-y += $(common-obj-y)
> -all-obj-y += $(chardev-obj-y)
> all-obj-y += $(target-obj-y)
> all-obj-y += $(qom-obj-y)
> -all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y)
> +all-obj-$(CONFIG_SOFTMMU) += $(block-obj-y) $(chardev-obj-y)
> all-obj-$(CONFIG_USER_ONLY) += $(crypto-aes-obj-y)
> all-obj-$(CONFIG_SOFTMMU) += $(crypto-obj-y)
> all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)
>
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 49+ messages in thread
* Re: [Qemu-devel] [PULL 00/41] Chr split patches
2017-01-31 19:00 ` Eric Blake
@ 2017-01-31 19:37 ` Marc-André Lureau
2017-01-31 20:02 ` Peter Maydell
2017-02-02 11:03 ` Peter Maydell
0 siblings, 2 replies; 49+ messages in thread
From: Marc-André Lureau @ 2017-01-31 19:37 UTC (permalink / raw)
To: Eric Blake, Peter Maydell; +Cc: QEMU Developers
Hi
On Tue, Jan 31, 2017 at 11:00 PM Eric Blake <eblake@redhat.com> wrote:
> On 01/31/2017 12:55 PM, Marc-André Lureau wrote:
>
> >> 'make check' fails on a linux-user-targets-only build:
> >>
> >> tests/test-char.o: In function `char_stdio_test_subprocess':
> >> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:47: undefined
> >> reference to `qemu_chr_new'
> >> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:50: undefined
> >> reference to `qemu_chr_fe_init'
> >> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:51: undefined
> >> reference to `qemu_chr_fe_set_open'
> >> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:52: undefined
> >> reference to `qemu_chr_fe_write'
> >> [etc etc etc]
> >>
> >>
> > Oh good catch. We want to have chardev-obj-y defined globally, but only
> > linked with -softmmu target.
> >
> > A possible fix to squash with chardev-obj-j patch is:
> >
> > Eric, do you want me to resend the patch for review or is that enough for
> > you to ack?
> >
>
> I'm okay ack'ing the interdiff (that is, squash this in, and you can
> keep the R-b you already have).
>
>
Thanks, patch updated, tag updated.
Peter, let me know if you want me to resend the pull request.
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 49+ messages in thread
* Re: [Qemu-devel] [PULL 00/41] Chr split patches
2017-01-31 19:37 ` Marc-André Lureau
@ 2017-01-31 20:02 ` Peter Maydell
2017-02-02 11:03 ` Peter Maydell
1 sibling, 0 replies; 49+ messages in thread
From: Peter Maydell @ 2017-01-31 20:02 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: Eric Blake, QEMU Developers
On 31 January 2017 at 19:37, Marc-André Lureau
<marcandre.lureau@gmail.com> wrote:
> Thanks, patch updated, tag updated.
>
> Peter, let me know if you want me to resend the pull request.
I'll put it back on my list. NB that the guaranteed reliable way
for me to spot that you want me to reprocess a respin is to
send a new cover letter email (you need not resend all the
individual patch mails if they're basically the same). That
will cause my filters to spot the cover letter email and
put it back in the folder of things to process. Doing anything
else is relying on my happening to read your email informally
asking for a re-run, which in this case I did but if you're
unlucky I might miss it.
TLDR: resending the cover letter entrusts your fate to the hands
of an infallible unsleeping robot; informal requests leave you
reliant on a careless human. The robot is your friend.
thanks
-- PMM
^ permalink raw reply [flat|nested] 49+ messages in thread
* Re: [Qemu-devel] [PULL 00/41] Chr split patches
2017-01-31 19:37 ` Marc-André Lureau
2017-01-31 20:02 ` Peter Maydell
@ 2017-02-02 11:03 ` Peter Maydell
1 sibling, 0 replies; 49+ messages in thread
From: Peter Maydell @ 2017-02-02 11:03 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: Eric Blake, QEMU Developers
On 31 January 2017 at 19:37, Marc-André Lureau
<marcandre.lureau@gmail.com> wrote:
> Hi
>
> On Tue, Jan 31, 2017 at 11:00 PM Eric Blake <eblake@redhat.com> wrote:
>>
>> On 01/31/2017 12:55 PM, Marc-André Lureau wrote:
>>
>> >> 'make check' fails on a linux-user-targets-only build:
>> >>
>> >> tests/test-char.o: In function `char_stdio_test_subprocess':
>> >> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:47: undefined
>> >> reference to `qemu_chr_new'
>> >> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:50: undefined
>> >> reference to `qemu_chr_fe_init'
>> >> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:51: undefined
>> >> reference to `qemu_chr_fe_set_open'
>> >> /home/petmay01/linaro/qemu-for-merges/tests/test-char.c:52: undefined
>> >> reference to `qemu_chr_fe_write'
>> >> [etc etc etc]
>> >>
>> >>
>> > Oh good catch. We want to have chardev-obj-y defined globally, but only
>> > linked with -softmmu target.
>> >
>> > A possible fix to squash with chardev-obj-j patch is:
>> >
>> > Eric, do you want me to resend the patch for review or is that enough
>> > for
>> > you to ack?
>> >
>>
>> I'm okay ack'ing the interdiff (that is, squash this in, and you can
>> keep the R-b you already have).
>>
>
> Thanks, patch updated, tag updated.
>
> Peter, let me know if you want me to resend the pull request.
Now applied, thanks.
-- PMM
^ permalink raw reply [flat|nested] 49+ messages in thread