[gnome-settings-daemon] rfkill: Add property to Rfkill helper to inhibit kernel handling



commit 3810072d2b3776c1183303adc8cd9f50732841a2
Author: Benjamin Berg <bberg redhat com>
Date:   Tue Apr 18 11:56:09 2017 +0200

    rfkill: Add property to Rfkill helper to inhibit kernel handling
    
    The kernel will handle input events by default which is causing race
    conditions and can for example make it impossible to disable airplane
    mode again. Add API to allow disabling the kernel handler.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=760517

 plugins/rfkill/rfkill-glib.c |  114 ++++++++++++++++++++++++++++++++++++++++++
 plugins/rfkill/rfkill-glib.h |    4 ++
 2 files changed, 118 insertions(+), 0 deletions(-)
---
diff --git a/plugins/rfkill/rfkill-glib.c b/plugins/rfkill/rfkill-glib.c
index 3ba4f89..a0e423b 100644
--- a/plugins/rfkill/rfkill-glib.c
+++ b/plugins/rfkill/rfkill-glib.c
@@ -31,6 +31,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <string.h>
+#include <sys/ioctl.h>
 
 #include <glib.h>
 #include <gio/gio.h>
@@ -43,6 +44,10 @@ enum {
        LAST_SIGNAL
 };
 
+enum {
+       PROP_RFKILL_INPUT_INHIBITED = 1
+};
+
 static int signals[LAST_SIGNAL] = { 0 };
 
 struct _CcRfkillGlib {
@@ -52,6 +57,9 @@ struct _CcRfkillGlib {
        GIOChannel *channel;
        guint watch_id;
 
+       /* rfkill-input inhibitor */
+       int noinput_fd;
+
        /* Pending Bluetooth enablement.
         * If (@change_all_timeout_id != 0), then (task != NULL). The converse
         * does not necessarily hold. */
@@ -356,6 +364,7 @@ event_cb (GIOChannel   *source,
 static void
 cc_rfkill_glib_init (CcRfkillGlib *rfkill)
 {
+       rfkill->noinput_fd = -1;
 }
 
 gboolean
@@ -435,6 +444,96 @@ cc_rfkill_glib_open (CcRfkillGlib  *rfkill,
        return TRUE;
 }
 
+#define RFKILL_INPUT_INHIBITED(rfkill) (rfkill->noinput_fd >= 0)
+
+gboolean
+cc_rfkill_glib_get_rfkill_input_inhibited (CcRfkillGlib        *rfkill)
+{
+       g_return_val_if_fail (CC_RFKILL_IS_GLIB (rfkill), FALSE);
+
+       return RFKILL_INPUT_INHIBITED(rfkill);
+}
+
+void
+cc_rfkill_glib_set_rfkill_input_inhibited (CcRfkillGlib *rfkill,
+                                          gboolean      inhibit)
+{
+       g_return_if_fail (CC_RFKILL_IS_GLIB (rfkill));
+
+       /* Nothing to do if the states already match. */
+       if (RFKILL_INPUT_INHIBITED(rfkill) == inhibit)
+               return;
+
+       if (!inhibit && RFKILL_INPUT_INHIBITED(rfkill)) {
+               close (rfkill->noinput_fd);
+               rfkill->noinput_fd = -1;
+
+               g_debug ("Closed rfkill noinput FD.");
+       }
+
+       if (inhibit && !RFKILL_INPUT_INHIBITED(rfkill)) {
+               int fd, res;
+               /* Open write only as we don't want to do any IO to it ever. */
+               fd = open ("/dev/rfkill", O_WRONLY);
+               if (fd < 0) {
+                       if (errno == EACCES)
+                               g_warning ("Could not open RFKILL control device, please verify your 
installation");
+                       else
+                               g_debug ("Could not open RFKILL control device: %s", g_strerror (errno));
+                       return;
+               }
+
+               res = ioctl (fd, RFKILL_IOCTL_NOINPUT, (long) 0);
+               if (res != 0) {
+                       g_warning ("Could not disable kernel handling of RFKILL related keys: %s", g_strerror 
(errno));
+                       close (fd);
+                       return;
+               }
+
+               g_debug ("Opened rfkill-input inhibitor.");
+
+               rfkill->noinput_fd = fd;
+       }
+
+       g_object_notify (G_OBJECT (rfkill), "kernel-noinput");
+}
+
+static void
+cc_rfkill_glib_set_property (GObject      *object,
+                        guint         prop_id,
+                        const GValue *value,
+                        GParamSpec   *pspec)
+{
+       CcRfkillGlib *rfkill = CC_RFKILL_GLIB (object);
+
+       switch (prop_id) {
+       case PROP_RFKILL_INPUT_INHIBITED:
+               cc_rfkill_glib_set_rfkill_input_inhibited (rfkill, g_value_get_boolean (value));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
+static void
+cc_rfkill_glib_get_property (GObject    *object,
+                        guint       prop_id,
+                        GValue     *value,
+                        GParamSpec *pspec)
+{
+       CcRfkillGlib *rfkill = CC_RFKILL_GLIB (object);
+
+       switch (prop_id) {
+       case PROP_RFKILL_INPUT_INHIBITED:
+               g_value_set_boolean (value, RFKILL_INPUT_INHIBITED(rfkill));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+               break;
+       }
+}
+
 static void
 cc_rfkill_glib_finalize (GObject *object)
 {
@@ -451,6 +550,11 @@ cc_rfkill_glib_finalize (GObject *object)
        }
        g_clear_object (&rfkill->stream);
 
+       if (RFKILL_INPUT_INHIBITED(rfkill)) {
+               close (rfkill->noinput_fd);
+               rfkill->noinput_fd = -1;
+       }
+
        G_OBJECT_CLASS(cc_rfkill_glib_parent_class)->finalize(object);
 }
 
@@ -459,8 +563,18 @@ cc_rfkill_glib_class_init(CcRfkillGlibClass *klass)
 {
        GObjectClass *object_class = (GObjectClass *) klass;
 
+       object_class->set_property = cc_rfkill_glib_set_property;
+       object_class->get_property = cc_rfkill_glib_get_property;
        object_class->finalize = cc_rfkill_glib_finalize;
 
+       g_object_class_install_property (object_class,
+                                        PROP_RFKILL_INPUT_INHIBITED,
+                                        g_param_spec_boolean ("rfkill-input-inhibited",
+                                                              "Rfkill input inhibited",
+                                                              "Whether to prevent the kernel from handling 
RFKILL related key events.",
+                                                              FALSE,
+                                                              G_PARAM_READWRITE));
+
        signals[CHANGED] =
                g_signal_new ("changed",
                              G_TYPE_FROM_CLASS (klass),
diff --git a/plugins/rfkill/rfkill-glib.h b/plugins/rfkill/rfkill-glib.h
index 9468407..0655eb4 100644
--- a/plugins/rfkill/rfkill-glib.h
+++ b/plugins/rfkill/rfkill-glib.h
@@ -37,6 +37,10 @@ CcRfkillGlib *cc_rfkill_glib_new               (void);
 gboolean      cc_rfkill_glib_open              (CcRfkillGlib  *rfkill,
                                                 GError       **error);
 
+gboolean      cc_rfkill_glib_get_rfkill_input_inhibited (CcRfkillGlib        *rfkill);
+void          cc_rfkill_glib_set_rfkill_input_inhibited (CcRfkillGlib        *rfkill,
+                                                        gboolean             noinput);
+
 void          cc_rfkill_glib_send_change_all_event        (CcRfkillGlib        *rfkill,
                                                           guint                rfkill_type,
                                                           gboolean             enable,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]