1*1c809fa0SDaniel P. Berrange /* 2*1c809fa0SDaniel P. Berrange * QEMU I/O channels watch helper APIs 3*1c809fa0SDaniel P. Berrange * 4*1c809fa0SDaniel P. Berrange * Copyright (c) 2015 Red Hat, Inc. 5*1c809fa0SDaniel P. Berrange * 6*1c809fa0SDaniel P. Berrange * This library is free software; you can redistribute it and/or 7*1c809fa0SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 8*1c809fa0SDaniel P. Berrange * License as published by the Free Software Foundation; either 9*1c809fa0SDaniel P. Berrange * version 2 of the License, or (at your option) any later version. 10*1c809fa0SDaniel P. Berrange * 11*1c809fa0SDaniel P. Berrange * This library is distributed in the hope that it will be useful, 12*1c809fa0SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*1c809fa0SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14*1c809fa0SDaniel P. Berrange * Lesser General Public License for more details. 15*1c809fa0SDaniel P. Berrange * 16*1c809fa0SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 17*1c809fa0SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18*1c809fa0SDaniel P. Berrange * 19*1c809fa0SDaniel P. Berrange */ 20*1c809fa0SDaniel P. Berrange 21*1c809fa0SDaniel P. Berrange #include "io/channel-watch.h" 22*1c809fa0SDaniel P. Berrange 23*1c809fa0SDaniel P. Berrange typedef struct QIOChannelFDSource QIOChannelFDSource; 24*1c809fa0SDaniel P. Berrange struct QIOChannelFDSource { 25*1c809fa0SDaniel P. Berrange GSource parent; 26*1c809fa0SDaniel P. Berrange GPollFD fd; 27*1c809fa0SDaniel P. Berrange QIOChannel *ioc; 28*1c809fa0SDaniel P. Berrange GIOCondition condition; 29*1c809fa0SDaniel P. Berrange }; 30*1c809fa0SDaniel P. Berrange 31*1c809fa0SDaniel P. Berrange 32*1c809fa0SDaniel P. Berrange typedef struct QIOChannelFDPairSource QIOChannelFDPairSource; 33*1c809fa0SDaniel P. Berrange struct QIOChannelFDPairSource { 34*1c809fa0SDaniel P. Berrange GSource parent; 35*1c809fa0SDaniel P. Berrange GPollFD fdread; 36*1c809fa0SDaniel P. Berrange GPollFD fdwrite; 37*1c809fa0SDaniel P. Berrange QIOChannel *ioc; 38*1c809fa0SDaniel P. Berrange GIOCondition condition; 39*1c809fa0SDaniel P. Berrange }; 40*1c809fa0SDaniel P. Berrange 41*1c809fa0SDaniel P. Berrange 42*1c809fa0SDaniel P. Berrange static gboolean 43*1c809fa0SDaniel P. Berrange qio_channel_fd_source_prepare(GSource *source G_GNUC_UNUSED, 44*1c809fa0SDaniel P. Berrange gint *timeout) 45*1c809fa0SDaniel P. Berrange { 46*1c809fa0SDaniel P. Berrange *timeout = -1; 47*1c809fa0SDaniel P. Berrange 48*1c809fa0SDaniel P. Berrange return FALSE; 49*1c809fa0SDaniel P. Berrange } 50*1c809fa0SDaniel P. Berrange 51*1c809fa0SDaniel P. Berrange 52*1c809fa0SDaniel P. Berrange static gboolean 53*1c809fa0SDaniel P. Berrange qio_channel_fd_source_check(GSource *source) 54*1c809fa0SDaniel P. Berrange { 55*1c809fa0SDaniel P. Berrange QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; 56*1c809fa0SDaniel P. Berrange 57*1c809fa0SDaniel P. Berrange return ssource->fd.revents & ssource->condition; 58*1c809fa0SDaniel P. Berrange } 59*1c809fa0SDaniel P. Berrange 60*1c809fa0SDaniel P. Berrange 61*1c809fa0SDaniel P. Berrange static gboolean 62*1c809fa0SDaniel P. Berrange qio_channel_fd_source_dispatch(GSource *source, 63*1c809fa0SDaniel P. Berrange GSourceFunc callback, 64*1c809fa0SDaniel P. Berrange gpointer user_data) 65*1c809fa0SDaniel P. Berrange { 66*1c809fa0SDaniel P. Berrange QIOChannelFunc func = (QIOChannelFunc)callback; 67*1c809fa0SDaniel P. Berrange QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; 68*1c809fa0SDaniel P. Berrange 69*1c809fa0SDaniel P. Berrange return (*func)(ssource->ioc, 70*1c809fa0SDaniel P. Berrange ssource->fd.revents & ssource->condition, 71*1c809fa0SDaniel P. Berrange user_data); 72*1c809fa0SDaniel P. Berrange } 73*1c809fa0SDaniel P. Berrange 74*1c809fa0SDaniel P. Berrange 75*1c809fa0SDaniel P. Berrange static void 76*1c809fa0SDaniel P. Berrange qio_channel_fd_source_finalize(GSource *source) 77*1c809fa0SDaniel P. Berrange { 78*1c809fa0SDaniel P. Berrange QIOChannelFDSource *ssource = (QIOChannelFDSource *)source; 79*1c809fa0SDaniel P. Berrange 80*1c809fa0SDaniel P. Berrange object_unref(OBJECT(ssource->ioc)); 81*1c809fa0SDaniel P. Berrange } 82*1c809fa0SDaniel P. Berrange 83*1c809fa0SDaniel P. Berrange 84*1c809fa0SDaniel P. Berrange static gboolean 85*1c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_prepare(GSource *source G_GNUC_UNUSED, 86*1c809fa0SDaniel P. Berrange gint *timeout) 87*1c809fa0SDaniel P. Berrange { 88*1c809fa0SDaniel P. Berrange *timeout = -1; 89*1c809fa0SDaniel P. Berrange 90*1c809fa0SDaniel P. Berrange return FALSE; 91*1c809fa0SDaniel P. Berrange } 92*1c809fa0SDaniel P. Berrange 93*1c809fa0SDaniel P. Berrange 94*1c809fa0SDaniel P. Berrange static gboolean 95*1c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_check(GSource *source) 96*1c809fa0SDaniel P. Berrange { 97*1c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 98*1c809fa0SDaniel P. Berrange GIOCondition poll_condition = ssource->fdread.revents | 99*1c809fa0SDaniel P. Berrange ssource->fdwrite.revents; 100*1c809fa0SDaniel P. Berrange 101*1c809fa0SDaniel P. Berrange return poll_condition & ssource->condition; 102*1c809fa0SDaniel P. Berrange } 103*1c809fa0SDaniel P. Berrange 104*1c809fa0SDaniel P. Berrange 105*1c809fa0SDaniel P. Berrange static gboolean 106*1c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_dispatch(GSource *source, 107*1c809fa0SDaniel P. Berrange GSourceFunc callback, 108*1c809fa0SDaniel P. Berrange gpointer user_data) 109*1c809fa0SDaniel P. Berrange { 110*1c809fa0SDaniel P. Berrange QIOChannelFunc func = (QIOChannelFunc)callback; 111*1c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 112*1c809fa0SDaniel P. Berrange GIOCondition poll_condition = ssource->fdread.revents | 113*1c809fa0SDaniel P. Berrange ssource->fdwrite.revents; 114*1c809fa0SDaniel P. Berrange 115*1c809fa0SDaniel P. Berrange return (*func)(ssource->ioc, 116*1c809fa0SDaniel P. Berrange poll_condition & ssource->condition, 117*1c809fa0SDaniel P. Berrange user_data); 118*1c809fa0SDaniel P. Berrange } 119*1c809fa0SDaniel P. Berrange 120*1c809fa0SDaniel P. Berrange 121*1c809fa0SDaniel P. Berrange static void 122*1c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_finalize(GSource *source) 123*1c809fa0SDaniel P. Berrange { 124*1c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source; 125*1c809fa0SDaniel P. Berrange 126*1c809fa0SDaniel P. Berrange object_unref(OBJECT(ssource->ioc)); 127*1c809fa0SDaniel P. Berrange } 128*1c809fa0SDaniel P. Berrange 129*1c809fa0SDaniel P. Berrange 130*1c809fa0SDaniel P. Berrange GSourceFuncs qio_channel_fd_source_funcs = { 131*1c809fa0SDaniel P. Berrange qio_channel_fd_source_prepare, 132*1c809fa0SDaniel P. Berrange qio_channel_fd_source_check, 133*1c809fa0SDaniel P. Berrange qio_channel_fd_source_dispatch, 134*1c809fa0SDaniel P. Berrange qio_channel_fd_source_finalize 135*1c809fa0SDaniel P. Berrange }; 136*1c809fa0SDaniel P. Berrange 137*1c809fa0SDaniel P. Berrange 138*1c809fa0SDaniel P. Berrange GSourceFuncs qio_channel_fd_pair_source_funcs = { 139*1c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_prepare, 140*1c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_check, 141*1c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_dispatch, 142*1c809fa0SDaniel P. Berrange qio_channel_fd_pair_source_finalize 143*1c809fa0SDaniel P. Berrange }; 144*1c809fa0SDaniel P. Berrange 145*1c809fa0SDaniel P. Berrange 146*1c809fa0SDaniel P. Berrange GSource *qio_channel_create_fd_watch(QIOChannel *ioc, 147*1c809fa0SDaniel P. Berrange int fd, 148*1c809fa0SDaniel P. Berrange GIOCondition condition) 149*1c809fa0SDaniel P. Berrange { 150*1c809fa0SDaniel P. Berrange GSource *source; 151*1c809fa0SDaniel P. Berrange QIOChannelFDSource *ssource; 152*1c809fa0SDaniel P. Berrange 153*1c809fa0SDaniel P. Berrange source = g_source_new(&qio_channel_fd_source_funcs, 154*1c809fa0SDaniel P. Berrange sizeof(QIOChannelFDSource)); 155*1c809fa0SDaniel P. Berrange ssource = (QIOChannelFDSource *)source; 156*1c809fa0SDaniel P. Berrange 157*1c809fa0SDaniel P. Berrange ssource->ioc = ioc; 158*1c809fa0SDaniel P. Berrange object_ref(OBJECT(ioc)); 159*1c809fa0SDaniel P. Berrange 160*1c809fa0SDaniel P. Berrange ssource->condition = condition; 161*1c809fa0SDaniel P. Berrange 162*1c809fa0SDaniel P. Berrange ssource->fd.fd = fd; 163*1c809fa0SDaniel P. Berrange ssource->fd.events = condition; 164*1c809fa0SDaniel P. Berrange 165*1c809fa0SDaniel P. Berrange g_source_add_poll(source, &ssource->fd); 166*1c809fa0SDaniel P. Berrange 167*1c809fa0SDaniel P. Berrange return source; 168*1c809fa0SDaniel P. Berrange } 169*1c809fa0SDaniel P. Berrange 170*1c809fa0SDaniel P. Berrange 171*1c809fa0SDaniel P. Berrange GSource *qio_channel_create_fd_pair_watch(QIOChannel *ioc, 172*1c809fa0SDaniel P. Berrange int fdread, 173*1c809fa0SDaniel P. Berrange int fdwrite, 174*1c809fa0SDaniel P. Berrange GIOCondition condition) 175*1c809fa0SDaniel P. Berrange { 176*1c809fa0SDaniel P. Berrange GSource *source; 177*1c809fa0SDaniel P. Berrange QIOChannelFDPairSource *ssource; 178*1c809fa0SDaniel P. Berrange 179*1c809fa0SDaniel P. Berrange source = g_source_new(&qio_channel_fd_pair_source_funcs, 180*1c809fa0SDaniel P. Berrange sizeof(QIOChannelFDPairSource)); 181*1c809fa0SDaniel P. Berrange ssource = (QIOChannelFDPairSource *)source; 182*1c809fa0SDaniel P. Berrange 183*1c809fa0SDaniel P. Berrange ssource->ioc = ioc; 184*1c809fa0SDaniel P. Berrange object_ref(OBJECT(ioc)); 185*1c809fa0SDaniel P. Berrange 186*1c809fa0SDaniel P. Berrange ssource->condition = condition; 187*1c809fa0SDaniel P. Berrange 188*1c809fa0SDaniel P. Berrange ssource->fdread.fd = fdread; 189*1c809fa0SDaniel P. Berrange ssource->fdread.events = condition & G_IO_IN; 190*1c809fa0SDaniel P. Berrange 191*1c809fa0SDaniel P. Berrange ssource->fdwrite.fd = fdwrite; 192*1c809fa0SDaniel P. Berrange ssource->fdwrite.events = condition & G_IO_OUT; 193*1c809fa0SDaniel P. Berrange 194*1c809fa0SDaniel P. Berrange g_source_add_poll(source, &ssource->fdread); 195*1c809fa0SDaniel P. Berrange g_source_add_poll(source, &ssource->fdwrite); 196*1c809fa0SDaniel P. Berrange 197*1c809fa0SDaniel P. Berrange return source; 198*1c809fa0SDaniel P. Berrange } 199