[gnome-settings-daemon/benzea/rfkill-gudev: 3/3] rfkill: Use GUdev to monitor rfkill device presence
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-settings-daemon/benzea/rfkill-gudev: 3/3] rfkill: Use GUdev to monitor rfkill device presence
- Date: Tue, 8 Jan 2019 19:44:54 +0000 (UTC)
commit e4bc5b81dea5c0bfbfb42a929ea273fe19e72d7c
Author: Benjamin Berg <bberg redhat com>
Date: Tue Aug 28 13:05:59 2018 +0200
rfkill: Use GUdev to monitor rfkill device presence
This adds the required code to use GUdev to monitor for the existence of
the rfkill device. This is relevant as the rfkill device might not exist
initially if the rfkill module is not loaded during login.
Fixes issue #52
meson.build | 1 +
plugins/rfkill/meson.build | 7 +++-
plugins/rfkill/rfkill-glib.c | 99 ++++++++++++++++++++++++++++++++++++++------
3 files changed, 94 insertions(+), 13 deletions(-)
---
diff --git a/meson.build b/meson.build
index c94c4f85..7510f816 100644
--- a/meson.build
+++ b/meson.build
@@ -182,6 +182,7 @@ enable_rfkill = get_option('rfkill')
assert(enable_rfkill or not host_is_linux, 'rfkill is not optional on Linux platforms')
if enable_rfkill
assert(cc.has_header('linux/rfkill.h'), 'rfkill support requested but RFKill headers not found')
+ assert(enable_gudev, 'GUdev is required for rfkill support')
udev_dir = get_option('udev_dir')
if udev_dir == ''
diff --git a/plugins/rfkill/meson.build b/plugins/rfkill/meson.build
index b85620b4..4d70352a 100644
--- a/plugins/rfkill/meson.build
+++ b/plugins/rfkill/meson.build
@@ -9,7 +9,12 @@ sources = files(
'main.c'
)
-deps = plugins_deps + [gio_unix_dep]
+deps = plugins_deps
+deps += [
+ gio_unix_dep,
+ gudev_dep,
+ m_dep
+]
executable(
'gsd-' + plugin_name,
diff --git a/plugins/rfkill/rfkill-glib.c b/plugins/rfkill/rfkill-glib.c
index 9862105e..0dc26f92 100644
--- a/plugins/rfkill/rfkill-glib.c
+++ b/plugins/rfkill/rfkill-glib.c
@@ -38,6 +38,7 @@
#include <gio/gunixoutputstream.h>
#include "rfkill-glib.h"
+#include <gudev/gudev.h>
enum {
CHANGED,
@@ -53,11 +54,15 @@ static int signals[LAST_SIGNAL] = { 0 };
struct _CcRfkillGlib {
GObject parent;
+ GUdevClient *udev;
+ gchar *device_file;
+
GOutputStream *stream;
GIOChannel *channel;
guint watch_id;
/* rfkill-input inhibitor */
+ gboolean noinput;
int noinput_fd;
/* Pending Bluetooth enablement.
@@ -374,12 +379,13 @@ event_cb (GIOChannel *source,
static void
cc_rfkill_glib_init (CcRfkillGlib *rfkill)
{
+ rfkill->device_file = NULL;
rfkill->noinput_fd = -1;
}
-gboolean
-cc_rfkill_glib_open (CcRfkillGlib *rfkill,
- GError **error)
+static gboolean
+_cc_rfkill_glib_open (CcRfkillGlib *rfkill,
+ GError **error)
{
int fd;
int ret;
@@ -387,8 +393,10 @@ cc_rfkill_glib_open (CcRfkillGlib *rfkill,
g_return_val_if_fail (CC_RFKILL_IS_GLIB (rfkill), FALSE);
g_return_val_if_fail (rfkill->stream == NULL, FALSE);
+ g_assert (rfkill->device_file);
+
+ fd = open (rfkill->device_file, O_RDWR);
- fd = open("/dev/rfkill", O_RDWR);
if (fd < 0) {
g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (errno),
"Could not open RFKILL control device, please verify your installation");
@@ -455,6 +463,60 @@ cc_rfkill_glib_open (CcRfkillGlib *rfkill,
return TRUE;
}
+static void
+uevent_cb (GUdevClient *client,
+ gchar *action,
+ GUdevDevice *device,
+ gpointer user_data)
+{
+ CcRfkillGlib *rfkill = CC_RFKILL_GLIB (user_data);
+
+ if (g_strcmp0 (action, "add") != 0)
+ return;
+
+ if (g_strcmp0 (g_udev_device_get_name (device), "rfkill") == 0) {
+ g_autoptr(GError) error = NULL;
+
+ g_debug ("Rfkill device has been created");
+
+ if (g_udev_device_get_device_file (device)) {
+ g_clear_pointer (&rfkill->device_file, g_free);
+ rfkill->device_file = g_strdup (g_udev_device_get_device_file (device));
+ } else {
+ g_warning ("rfkill udev device does not have a device file!");
+ }
+
+ if (!_cc_rfkill_glib_open (rfkill, &error))
+ g_warning ("Could not open rfkill device: %s", error->message);
+ else
+ g_debug ("Opened rfkill device after uevent");
+
+ g_clear_object (&rfkill->udev);
+
+ /* Sync rfkill input inhibition state*/
+ cc_rfkill_glib_set_rfkill_input_inhibited (rfkill, rfkill->noinput);
+ }
+}
+
+gboolean
+cc_rfkill_glib_open (CcRfkillGlib *rfkill,
+ GError **error)
+{
+ const char * const subsystems[] = { "misc", NULL };
+ GUdevDevice *device;
+
+ rfkill->udev = g_udev_client_new (subsystems);
+ g_debug ("Setting up uevent listener");
+ g_signal_connect (rfkill->udev, "uevent", G_CALLBACK (uevent_cb), rfkill);
+
+ /* Simulate uevent if device already exists. */
+ device = g_udev_client_query_by_subsystem_and_name (rfkill->udev, "misc", "rfkill");
+ if (device)
+ uevent_cb (rfkill->udev, "add", device, rfkill);
+
+ return TRUE;
+}
+
#define RFKILL_INPUT_INHIBITED(rfkill) (rfkill->noinput_fd >= 0)
gboolean
@@ -462,7 +524,7 @@ 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);
+ return rfkill->noinput;
}
void
@@ -471,21 +533,28 @@ cc_rfkill_glib_set_rfkill_input_inhibited (CcRfkillGlib *rfkill,
{
g_return_if_fail (CC_RFKILL_IS_GLIB (rfkill));
- /* Nothing to do if the states already match. */
- if (RFKILL_INPUT_INHIBITED(rfkill) == inhibit)
+ /* Shortcut in case we don't have an rfkill device */
+ if (!rfkill->stream) {
+ if (rfkill->noinput == inhibit)
+ return;
+
+ rfkill->noinput = inhibit;
+ g_object_notify (G_OBJECT (rfkill), "rfkill-input-inhibited");
+
return;
+ }
if (!inhibit && RFKILL_INPUT_INHIBITED(rfkill)) {
close (rfkill->noinput_fd);
- rfkill->noinput_fd = -1;
-
g_debug ("Closed rfkill noinput FD.");
+
+ rfkill->noinput_fd = -1;
}
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);
+ fd = open (rfkill->device_file, O_WRONLY);
if (fd < 0) {
if (errno == EACCES)
g_warning ("Could not open RFKILL control device, please verify your
installation");
@@ -506,7 +575,10 @@ cc_rfkill_glib_set_rfkill_input_inhibited (CcRfkillGlib *rfkill,
rfkill->noinput_fd = fd;
}
- g_object_notify (G_OBJECT (rfkill), "rfkill-input-inhibited");
+ if (rfkill->noinput != RFKILL_INPUT_INHIBITED(rfkill)) {
+ rfkill->noinput = RFKILL_INPUT_INHIBITED(rfkill);
+ g_object_notify (G_OBJECT (rfkill), "rfkill-input-inhibited");
+ }
}
static void
@@ -537,7 +609,7 @@ cc_rfkill_glib_get_property (GObject *object,
switch (prop_id) {
case PROP_RFKILL_INPUT_INHIBITED:
- g_value_set_boolean (value, RFKILL_INPUT_INHIBITED(rfkill));
+ g_value_set_boolean (value, rfkill->noinput);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -566,6 +638,9 @@ cc_rfkill_glib_finalize (GObject *object)
rfkill->noinput_fd = -1;
}
+ g_clear_pointer (&rfkill->device_file, g_free);
+ g_clear_object (&rfkill->udev);
+
G_OBJECT_CLASS(cc_rfkill_glib_parent_class)->finalize(object);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]