#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
-#include "qapi-visit.h"
+#include "qapi/qmp/qerror.h"
#include "sysemu/replay.h"
#include "chardev/char-fe.h"
int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len)
{
Chardev *s = be->chr;
- int offset = 0, counter = 10;
+ int offset = 0;
int res;
if (!s || !CHARDEV_GET_CLASS(s)->chr_sync_read) {
}
offset += res;
-
- if (!counter--) {
- break;
- }
}
if (qemu_chr_replay(s) && replay_mode == REPLAY_MODE_RECORD) {
Chardev *qemu_chr_fe_get_driver(CharBackend *be)
{
+ /* this is unsafe for the users that support chardev hotswap */
+ assert(be->chr_be_change == NULL);
return be->chr;
}
+bool qemu_chr_fe_backend_connected(CharBackend *be)
+{
+ return !!be->chr;
+}
+
+bool qemu_chr_fe_backend_open(CharBackend *be)
+{
+ return be->chr && be->chr->be_open;
+}
+
bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp)
{
int tag = 0;
- if (CHARDEV_IS_MUX(s)) {
- MuxChardev *d = MUX_CHARDEV(s);
+ if (s) {
+ if (CHARDEV_IS_MUX(s)) {
+ MuxChardev *d = MUX_CHARDEV(s);
- if (d->mux_cnt >= MAX_MUX) {
+ if (d->mux_cnt >= MAX_MUX) {
+ goto unavailable;
+ }
+
+ d->backends[d->mux_cnt] = b;
+ tag = d->mux_cnt++;
+ } else if (s->be) {
goto unavailable;
+ } else {
+ s->be = b;
}
-
- d->backends[d->mux_cnt] = b;
- tag = d->mux_cnt++;
- } else if (s->be) {
- goto unavailable;
- } else {
- s->be = b;
}
b->fe_open = false;
assert(b);
if (b->chr) {
- qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL, true);
+ qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL, NULL, true);
if (b->chr->be == b) {
b->chr->be = NULL;
}
d->backends[b->tag] = NULL;
}
if (del) {
- object_unparent(OBJECT(b->chr));
+ Object *obj = OBJECT(b->chr);
+ if (obj->parent) {
+ object_unparent(obj);
+ } else {
+ object_unref(obj);
+ }
}
b->chr = NULL;
}
}
-void qemu_chr_fe_set_handlers(CharBackend *b,
- IOCanReadHandler *fd_can_read,
- IOReadHandler *fd_read,
- IOEventHandler *fd_event,
- void *opaque,
- GMainContext *context,
- bool set_open)
+void qemu_chr_fe_set_handlers_full(CharBackend *b,
+ IOCanReadHandler *fd_can_read,
+ IOReadHandler *fd_read,
+ IOEventHandler *fd_event,
+ BackendChangeHandler *be_change,
+ void *opaque,
+ GMainContext *context,
+ bool set_open,
+ bool sync_state)
{
Chardev *s;
- ChardevClass *cc;
int fe_open;
s = b->chr;
return;
}
- cc = CHARDEV_GET_CLASS(s);
if (!opaque && !fd_can_read && !fd_read && !fd_event) {
fe_open = 0;
remove_fd_in_watch(s);
b->chr_can_read = fd_can_read;
b->chr_read = fd_read;
b->chr_event = fd_event;
+ b->chr_be_change = be_change;
b->opaque = opaque;
- if (cc->chr_update_read_handler) {
- cc->chr_update_read_handler(s, context);
- }
+
+ qemu_chr_be_update_read_handlers(s, context);
if (set_open) {
qemu_chr_fe_set_open(b, fe_open);
qemu_chr_fe_take_focus(b);
/* We're connecting to an already opened device, so let's make sure we
also get the open event */
- if (s->be_open) {
+ if (sync_state && s->be_open) {
qemu_chr_be_event(s, CHR_EVENT_OPENED);
}
}
+}
- if (CHARDEV_IS_MUX(s)) {
- mux_chr_set_handlers(s, context);
- }
+void qemu_chr_fe_set_handlers(CharBackend *b,
+ IOCanReadHandler *fd_can_read,
+ IOReadHandler *fd_read,
+ IOEventHandler *fd_event,
+ BackendChangeHandler *be_change,
+ void *opaque,
+ GMainContext *context,
+ bool set_open)
+{
+ qemu_chr_fe_set_handlers_full(b, fd_can_read, fd_read, fd_event, be_change,
+ opaque, context, set_open,
+ true);
}
void qemu_chr_fe_take_focus(CharBackend *b)
}
g_source_set_callback(src, (GSourceFunc)func, user_data, NULL);
- tag = g_source_attach(src, NULL);
+ tag = g_source_attach(src, s->gcontext);
g_source_unref(src);
return tag;