diff options
author | Marc-André Lureau <marcandre.lureau@redhat.com> | 2016-12-12 19:12:14 +0300 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@redhat.com> | 2017-01-31 23:31:21 +0400 |
commit | c3b7d620973e443c13a5a73f2c99189fd63239f1 (patch) | |
tree | b6f41d05b76434a82df7c6ca7dae9b11a74b30ca /chardev/char.c | |
parent | 1fcb3841d066dde19619c09b22fee0a87fe0adcb (diff) |
char: move pty chardev in its own file
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'chardev/char.c')
-rw-r--r-- | chardev/char.c | 258 |
1 files changed, 0 insertions, 258 deletions
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 |