4 * Copyright (c) 2003-2008 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 #include "qemu/osdep.h"
25 #include "chardev/char-io.h"
27 typedef struct IOWatchPoll
{
33 IOCanReadHandler
*fd_can_read
;
36 GMainContext
*context
;
39 static IOWatchPoll
*io_watch_poll_from_source(GSource
*source
)
41 return container_of(source
, IOWatchPoll
, parent
);
44 static gboolean
io_watch_poll_prepare(GSource
*source
,
47 IOWatchPoll
*iwp
= io_watch_poll_from_source(source
);
48 bool now_active
= iwp
->fd_can_read(iwp
->opaque
) > 0;
49 bool was_active
= iwp
->src
!= NULL
;
50 if (was_active
== now_active
) {
55 * We do not register the QIOChannel watch as a child GSource.
56 * The 'prepare' function on the parent GSource will be
57 * skipped if a child GSource's 'prepare' function indicates
58 * readiness. We need this prepare function be guaranteed
59 * to run on *every* iteration of the main loop, because
60 * it is critical to ensure we remove the QIOChannel watch
61 * if 'fd_can_read' indicates the frontend cannot receive
65 iwp
->src
= qio_channel_create_watch(
66 iwp
->ioc
, G_IO_IN
| G_IO_ERR
| G_IO_HUP
| G_IO_NVAL
);
67 g_source_set_callback(iwp
->src
, iwp
->fd_read
, iwp
->opaque
, NULL
);
68 g_source_attach(iwp
->src
, iwp
->context
);
70 g_source_destroy(iwp
->src
);
71 g_source_unref(iwp
->src
);
77 static gboolean
io_watch_poll_check(GSource
*source
)
82 static gboolean
io_watch_poll_dispatch(GSource
*source
, GSourceFunc callback
,
88 static void io_watch_poll_finalize(GSource
*source
)
90 IOWatchPoll
*iwp
= io_watch_poll_from_source(source
);
92 g_source_destroy(iwp
->src
);
93 g_source_unref(iwp
->src
);
98 static GSourceFuncs io_watch_poll_funcs
= {
99 .prepare
= io_watch_poll_prepare
,
100 .check
= io_watch_poll_check
,
101 .dispatch
= io_watch_poll_dispatch
,
102 .finalize
= io_watch_poll_finalize
,
105 GSource
*io_add_watch_poll(Chardev
*chr
,
107 IOCanReadHandler
*fd_can_read
,
108 QIOChannelFunc fd_read
,
110 GMainContext
*context
)
115 iwp
= (IOWatchPoll
*) g_source_new(&io_watch_poll_funcs
,
116 sizeof(IOWatchPoll
));
117 iwp
->fd_can_read
= fd_can_read
;
118 iwp
->opaque
= user_data
;
120 #pragma GCC diagnostic ignored "-Wcast-function-type"
121 iwp
->fd_read
= (GSourceFunc
) fd_read
;
123 iwp
->context
= context
;
125 name
= g_strdup_printf("chardev-iowatch-%s", chr
->label
);
126 g_source_set_name((GSource
*)iwp
, name
);
129 g_source_attach(&iwp
->parent
, context
);
130 g_source_unref(&iwp
->parent
);
131 return (GSource
*)iwp
;
134 static void io_remove_watch_poll(GSource
*source
)
138 iwp
= io_watch_poll_from_source(source
);
139 g_source_destroy(&iwp
->parent
);
142 void remove_fd_in_watch(Chardev
*chr
)
145 io_remove_watch_poll(chr
->gsource
);
150 int io_channel_send_full(QIOChannel
*ioc
,
151 const void *buf
, size_t len
,
152 int *fds
, size_t nfds
)
156 while (offset
< len
) {
158 struct iovec iov
= { .iov_base
= (char *)buf
+ offset
,
159 .iov_len
= len
- offset
};
161 ret
= qio_channel_writev_full(
164 if (ret
== QIO_CHANNEL_ERR_BLOCK
) {
171 } else if (ret
< 0) {
182 int io_channel_send(QIOChannel
*ioc
, const void *buf
, size_t len
)
184 return io_channel_send_full(ioc
, buf
, len
, NULL
, 0);