#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "qemu/module.h"
#include "qemu/option.h"
#include "chardev/char.h"
#include "sysemu/block-backend.h"
-#include "sysemu/sysemu.h"
-#include "chardev/char-mux.h"
+#include "qapi/qapi-commands-control.h"
+#include "chardev-internal.h"
/* MUX driver for serial I/O splitting */
+/*
+ * Set to false by suspend_mux_open. Open events are delayed until
+ * resume_mux_open. Usually suspend_mux_open is called before
+ * command line processing and resume_mux_open afterwards.
+ */
+static bool muxes_opened = true;
+
/* Called with chr_write_lock held. */
static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len)
{
}
}
-static void mux_chr_send_event(MuxChardev *d, int mux_nr, int event)
+static void mux_chr_send_event(MuxChardev *d, int mux_nr, QEMUChrEvent event)
{
CharBackend *be = d->backends[mux_nr];
}
}
-static void mux_chr_be_event(Chardev *chr, int event)
+static void mux_chr_be_event(Chardev *chr, QEMUChrEvent event)
{
MuxChardev *d = MUX_CHARDEV(chr);
{
const char *term = "QEMU: Terminated\n\r";
qemu_chr_write_all(chr, (uint8_t *)term, strlen(term));
- exit(0);
+ qmp_quit(NULL);
break;
}
case 's':
}
}
-void mux_chr_send_all_event(Chardev *chr, int event)
+void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event)
{
MuxChardev *d = MUX_CHARDEV(chr);
int i;
- if (!machine_init_done) {
+ if (!muxes_opened) {
return;
}
}
}
-static void mux_chr_event(void *opaque, int event)
+static void mux_chr_event(void *opaque, QEMUChrEvent event)
{
mux_chr_send_all_event(CHARDEV(opaque), event);
}
/* only default to opened state if we've realized the initial
* set of muxes
*/
- *be_opened = machine_init_done;
+ *be_opened = muxes_opened;
qemu_chr_fe_init(&d->chr, drv, errp);
}
* mux will receive CHR_EVENT_OPENED notifications for the BE
* immediately.
*/
-static int open_muxes(Chardev *chr)
+static void open_muxes(Chardev *chr)
{
/* send OPENED to all already-attached FEs */
mux_chr_send_all_event(chr, CHR_EVENT_OPENED);
+
/*
* mark mux as OPENED so any new FEs will immediately receive
* OPENED event
*/
chr->be_open = 1;
+}
+
+void suspend_mux_open(void)
+{
+ muxes_opened = false;
+}
+
+static int chardev_options_parsed_cb(Object *child, void *opaque)
+{
+ Chardev *chr = (Chardev *)child;
+
+ if (!chr->be_open && CHARDEV_IS_MUX(chr)) {
+ open_muxes(chr);
+ }
return 0;
}
+void resume_mux_open(void)
+{
+ muxes_opened = true;
+ object_child_foreach(get_chardevs_root(),
+ chardev_options_parsed_cb, NULL);
+}
+
static void char_mux_class_init(ObjectClass *oc, void *data)
{
ChardevClass *cc = CHARDEV_CLASS(oc);
cc->chr_accept_input = mux_chr_accept_input;
cc->chr_add_watch = mux_chr_add_watch;
cc->chr_be_event = mux_chr_be_event;
- cc->chr_machine_done = open_muxes;
cc->chr_update_read_handler = mux_chr_update_read_handlers;
}