diff options
author | Martin Xu <martin.xu@intel.com> | 2010-01-19 12:34:48 +0800 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2010-01-18 20:57:42 -0800 |
commit | cfda513e5e25808537e362dd208716ed80cf6d63 (patch) | |
tree | cfdd25e05d9309de53e92f8d5c1204a7976c213c /src/rfkill.c | |
parent | 0935c628cf83b096d72ffba5e53a6d6e8029e7ef (diff) | |
download | connman-cfda513e5e25808537e362dd208716ed80cf6d63.tar.gz connman-cfda513e5e25808537e362dd208716ed80cf6d63.tar.bz2 connman-cfda513e5e25808537e362dd208716ed80cf6d63.zip |
Process RFKILL events after opening device
To avoid the case when RFKILL event happens in the device enable stage,
process the initial events after opening the device. The /dev/rfkill
sends out the current RFKIL states after open(). This fixes a race
condition between device enabling and initial RFKILL states.
Diffstat (limited to 'src/rfkill.c')
-rw-r--r-- | src/rfkill.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/src/rfkill.c b/src/rfkill.c index 4b6a61dd..fd38db92 100644 --- a/src/rfkill.c +++ b/src/rfkill.c @@ -56,34 +56,31 @@ struct rfkill_event { uint8_t hard; }; -static gboolean rfkill_event(GIOChannel *chan, - GIOCondition cond, gpointer data) +static GIOStatus rfkill_process(GIOChannel *chan) { + GIOStatus status = G_IO_STATUS_NORMAL; unsigned char buf[32]; struct rfkill_event *event = (void *) buf; char sysname[32]; connman_bool_t blocked; gsize len; - GIOError err; - if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) - return FALSE; + DBG(""); memset(buf, 0, sizeof(buf)); - err = g_io_channel_read(chan, (gchar *) buf, sizeof(buf), &len); - if (err) { - if (err == G_IO_ERROR_AGAIN) - return TRUE; - return FALSE; - } + status = g_io_channel_read_chars(chan, (gchar *) buf, + sizeof(struct rfkill_event), &len, NULL); + + if (status != G_IO_STATUS_NORMAL) + return status; if (len != sizeof(struct rfkill_event)) - return TRUE; + return status; DBG("idx %u type %u op %u soft %u hard %u", - event->idx, event->type, event->op, - event->soft, event->hard); + event->idx, event->type, event->op, + event->soft, event->hard); snprintf(sysname, sizeof(sysname) - 1, "rfkill%d", event->idx); @@ -98,6 +95,21 @@ static gboolean rfkill_event(GIOChannel *chan, break; } + return status; +} + +static gboolean rfkill_event(GIOChannel *chan, + GIOCondition cond, gpointer data) +{ + GIOStatus status; + + if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) + return FALSE; + + status = rfkill_process(chan); + if (status == G_IO_STATUS_ERROR) + return FALSE; + return TRUE; } @@ -105,6 +117,7 @@ static GIOChannel *channel = NULL; int __connman_rfkill_init(void) { + GIOFlags flags; int fd; DBG(""); @@ -118,6 +131,14 @@ int __connman_rfkill_init(void) channel = g_io_channel_unix_new(fd); g_io_channel_set_close_on_unref(channel, TRUE); + flags = g_io_channel_get_flags(channel); + flags |= G_IO_FLAG_NONBLOCK; + g_io_channel_set_flags(channel, flags, NULL); + + /* Process current RFKILL events sent on device open */ + while (rfkill_process(channel) == G_IO_STATUS_NORMAL) + ; + g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR, rfkill_event, NULL); |