qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 37/54] char: move mux to its own file


From: Marc-André Lureau
Subject: [Qemu-devel] [PATCH 37/54] char: move mux to its own file
Date: Tue, 13 Dec 2016 01:43:08 +0300

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 <address@hidden>
---
 chardev/char-mux.c    | 332 +++++++++++++++++++++++++++++++++++++++++++++++
 chardev/char.c        | 348 +-------------------------------------------------
 chardev/Makefile.objs |   1 +
 chardev/char-mux.h    |  40 ++++++
 include/sysemu/char.h |   3 +-
 5 files changed, 377 insertions(+), 347 deletions(-)
 create mode 100644 chardev/char-mux.c
 create mode 100644 chardev/char-mux.h

diff --git a/chardev/char-mux.c b/chardev/char-mux.c
new file mode 100644
index 0000000000..ca7fb75841
--- /dev/null
+++ b/chardev/char-mux.c
@@ -0,0 +1,332 @@
+#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(d, (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(MuxChardev *d, int focus)
+{
+    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;
+    }
+    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 d31ba110ca..3138bfcd19 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(MuxChardev *d, 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(d, (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,82 +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(MuxChardev *d, int focus)
-{
-    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);
-}
-
 Chardev *qemu_chr_fe_get_driver(CharBackend *be)
 {
     return be->chr;
@@ -3941,40 +3634,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;
-
-    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)
 {
@@ -5075,7 +4734,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
diff --git a/chardev/char-mux.h b/chardev/char-mux.h
new file mode 100644
index 0000000000..c0a000838a
--- /dev/null
+++ b/chardev/char-mux.h
@@ -0,0 +1,40 @@
+#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 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;
+} 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(MuxChardev *d, 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 297add973c..dd91c4c03e 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -439,6 +439,7 @@ bool qemu_chr_has_feature(Chardev *chr,
 void qemu_chr_set_feature(Chardev *chr,
                           CharDriverFeature 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)
@@ -461,8 +462,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) \
-- 
2.11.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]