public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Add rfkill plugin
@ 2009-07-28 16:34 Bastien Nocera
  2009-07-28 20:06 ` Marcel Holtmann
  2009-07-29 15:13 ` Bastien Nocera
  0 siblings, 2 replies; 15+ messages in thread
From: Bastien Nocera @ 2009-07-28 16:34 UTC (permalink / raw)
  To: BlueZ development

[-- Attachment #1: Type: text/plain, Size: 213 bytes --]

The plugin allows us to restore the previous power state on
adapters when the killswitch on them has been unblocked.

Otherwise we end up with the adapter disabled when coming back from a
soft killswitch.

Cheers

[-- Attachment #2: 0001-Add-rfkill-plugin.patch --]
[-- Type: text/x-patch, Size: 7193 bytes --]

>From bf8b7c07542bd7acb4f9f98ba2165475f0ad9d65 Mon Sep 17 00:00:00 2001
From: Bastien Nocera <hadess@hadess.net>
Date: Tue, 28 Jul 2009 17:25:34 +0100
Subject: [PATCH] Add rfkill plugin

The plugin allows us to restore the previous power state on
adapters when the killswitch on them has been unblocked.
---
 plugins/Makefile.am |    3 +
 plugins/rfkill.c    |  199 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/adapter.c       |   23 ++++--
 src/adapter.h       |    1 +
 4 files changed, 219 insertions(+), 7 deletions(-)
 create mode 100644 plugins/rfkill.c

diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 9d9f970..9ba8180 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -15,6 +15,9 @@ endif
 builtin_modules += hciops
 builtin_sources += hciops.c
 
+builtin_modules += rfkill
+builtin_sources += rfkill.c
+
 if NETLINK
 plugin_LTLIBRARIES += netlink.la
 netlink_la_LIBADD = @NETLINK_LIBS@
diff --git a/plugins/rfkill.c b/plugins/rfkill.c
new file mode 100644
index 0000000..fad8b47
--- /dev/null
+++ b/plugins/rfkill.c
@@ -0,0 +1,199 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2009  Bastien Nocera <hadess@hadess.net>
+ *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
+ *
+ * Author:
+ * Bastien Nocera <bnocera@redhat.com>, based on code by
+ * Johannes Berg <johannes@sipsolutions.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <glib.h>
+
+#include <dbus/dbus.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+
+#include "hcid.h"
+#include "plugin.h"
+#include "logging.h"
+
+#include "manager.h"
+#include "adapter.h"
+#include "device.h"
+
+enum rfkill_type {
+	RFKILL_TYPE_ALL = 0,
+	RFKILL_TYPE_WLAN,
+	RFKILL_TYPE_BLUETOOTH,
+	RFKILL_TYPE_UWB,
+	RFKILL_TYPE_WIMAX,
+	RFKILL_TYPE_WWAN,
+};
+
+enum rfkill_operation {
+	RFKILL_OP_ADD = 0,
+	RFKILL_OP_DEL,
+	RFKILL_OP_CHANGE,
+	RFKILL_OP_CHANGE_ALL,
+};
+
+struct rfkill_event {
+	uint32_t idx;
+	uint8_t  type;
+	uint8_t  op;
+	uint8_t  soft;
+	uint8_t  hard;
+};
+
+static char *get_name(__u32 idx)
+{
+	char *filename, *name, *pos;
+
+	filename = g_strdup_printf("/sys/class/rfkill/rfkill%u/name", idx);
+	if (g_file_get_contents(filename, &name, NULL, NULL) == FALSE) {
+		g_free(filename);
+		return NULL;
+	}
+
+	g_free(filename);
+
+	pos = strchr(name, '\n');
+	if (pos)
+		*pos = '\0';
+
+	return name;
+}
+
+static gboolean rfkill_event(GIOChannel *chan,
+				GIOCondition cond, gpointer data)
+{
+	unsigned char buf[32];
+	struct rfkill_event *event = (void *) buf;
+	char *sysname;
+	gboolean blocked;
+	gsize len;
+	GIOError err;
+
+	if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
+		return FALSE;
+
+	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;
+	}
+
+	if (len != sizeof(struct rfkill_event))
+		return TRUE;
+
+	debug("idx %u type %u op %u soft %u hard %u",
+					event->idx, event->type, event->op,
+						event->soft, event->hard);
+
+	blocked = (event->soft || event->hard) ? TRUE : FALSE;
+	/* We already disable devices correctly when rfkilled */
+	if (blocked)
+		return TRUE;
+
+	sysname = get_name(event->idx);
+	if (sysname == NULL)
+		return TRUE;
+	if (g_str_has_prefix(sysname, "hci") == FALSE) {
+		debug("Ignoring unblocked killswitch '%s'", sysname);
+		g_free(sysname);
+		return TRUE;
+	}
+
+	switch (event->type) {
+	case RFKILL_TYPE_ALL:
+	case RFKILL_TYPE_BLUETOOTH: {
+		struct btd_adapter *adapter;
+		int id;
+
+		id = atoi(sysname + strlen("hci"));
+		adapter = manager_find_adapter_by_id(id);
+		if (adapter)
+			adapter_set_powered(adapter, TRUE);
+		break;
+		}
+	default:
+		break;
+	}
+
+	g_free(sysname);
+
+	return TRUE;
+}
+
+static GIOChannel *channel = NULL;
+
+static int rfkill_init(void)
+{
+	int fd;
+
+	debug("Init rfkill plugin");
+
+	if (main_opts.remember_powered == FALSE)
+		return 0;
+
+	fd = open("/dev/rfkill", O_RDWR);
+	if (fd < 0) {
+		debug("No rfkill support in the kernel");
+		return -EIO;
+	}
+
+	channel = g_io_channel_unix_new(fd);
+	g_io_channel_set_close_on_unref(channel, TRUE);
+
+	g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
+							rfkill_event, NULL);
+
+	return 0;
+}
+
+static void rfkill_exit(void)
+{
+	debug("Cleanup rfkill plugin");
+
+	if (channel == NULL)
+		return;
+
+	g_io_channel_shutdown(channel, TRUE, NULL);
+	g_io_channel_unref(channel);
+
+	channel = NULL;
+}
+
+BLUETOOTH_PLUGIN_DEFINE(rfkill, VERSION,
+			BLUETOOTH_PLUGIN_PRIORITY_DEFAULT, rfkill_init, rfkill_exit)
diff --git a/src/adapter.c b/src/adapter.c
index 06640e7..06c3018 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -483,21 +483,30 @@ done:
 	return 0;
 }
 
-static DBusMessage *set_powered(DBusConnection *conn, DBusMessage *msg,
-				gboolean powered, void *data)
+int adapter_set_powered(struct btd_adapter *adapter, gboolean powered)
 {
-	struct btd_adapter *adapter = data;
 	uint8_t mode;
-	int err;
 
 	mode = powered ? get_mode(&adapter->bdaddr, "on") : MODE_OFF;
 
 	if (mode == adapter->mode)
-		return dbus_message_new_method_return(msg);
+		return -EALREADY;
 
-	err = set_mode(adapter, mode);
-	if (err < 0)
+	return set_mode(adapter, mode);
+}
+
+static DBusMessage *set_powered(DBusConnection *conn, DBusMessage *msg,
+				gboolean powered, void *data)
+{
+	struct btd_adapter *adapter = data;
+	int err;
+
+	err = adapter_set_powered(adapter, powered);
+	if (err < 0) {
+		if (err == -EALREADY)
+			return dbus_message_new_method_return(msg);
 		return failed_strerror(msg, -err);
+	}
 
 	return dbus_message_new_method_return(msg);
 }
diff --git a/src/adapter.h b/src/adapter.h
index d34fb80..fa02d5d 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -110,6 +110,7 @@ void adapter_get_address(struct btd_adapter *adapter, bdaddr_t *bdaddr);
 void adapter_set_state(struct btd_adapter *adapter, int state);
 int adapter_get_state(struct btd_adapter *adapter);
 gboolean adapter_is_ready(struct btd_adapter *adapter);
+int adapter_set_powered(struct btd_adapter *adapter, gboolean powered);
 struct remote_dev_info *adapter_search_found_devices(struct btd_adapter *adapter,
 						struct remote_dev_info *match);
 void adapter_update_found_devices(struct btd_adapter *adapter, bdaddr_t *bdaddr,
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2009-07-30 10:23 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-28 16:34 [PATCH] Add rfkill plugin Bastien Nocera
2009-07-28 20:06 ` Marcel Holtmann
2009-07-28 20:12   ` Bastien Nocera
2009-07-28 20:21     ` Marcel Holtmann
2009-07-29 15:13 ` Bastien Nocera
2009-07-29 19:49   ` Marcel Holtmann
2009-07-29 20:15     ` Bastien Nocera
2009-07-29 20:23       ` Marcel Holtmann
2009-07-29 20:40         ` Bastien Nocera
2009-07-29 21:44         ` Johan Hedberg
2009-07-29 21:45           ` Bastien Nocera
2009-07-30  2:10           ` Luiz Augusto von Dentz
2009-07-30  2:27             ` Marcel Holtmann
2009-07-30  2:30           ` Marcel Holtmann
2009-07-30 10:23             ` Johan Hedberg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox