Search Linux Wireless

Re: [PATCH] rfkill: create useful userspace interface

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

 



Would everybody be happy with this rolled in?

johannes

Subject: rfkill: userspace API improvements

This adds the two following things to /dev/rfkill:
 1) notification to userspace with a new operation
    RFKILL_OP_NVS_REPORT about default states restored
    from platform non-volatile storage
 2) the ability to ignore input events in the kernel
    while a handler daemon is connected, if the input
    part is compiled in.

Signed-off-by: Johannes Berg <johannes@xxxxxxxxxxxxxxxx>
---
 include/linux/rfkill.h |    8 +++++
 net/rfkill/core.c      |   67 ++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 74 insertions(+), 1 deletion(-)

--- wireless-testing.orig/net/rfkill/core.c	2009-06-01 09:43:26.000000000 +0200
+++ wireless-testing/net/rfkill/core.c	2009-06-01 14:10:48.000000000 +0200
@@ -85,6 +85,7 @@ struct rfkill_data {
 	struct list_head	events;
 	struct mutex		mtx;
 	wait_queue_head_t	read_wait;
+	bool			input_handler;
 };
 
 
@@ -115,7 +116,7 @@ MODULE_PARM_DESC(default_state,
 		 "Default initial state for all radio types, 0 = radio off");
 
 static struct {
-	bool cur, def;
+	bool cur, def, restored;
 } rfkill_global_states[NUM_RFKILL_TYPES];
 
 static unsigned long rfkill_states_default_locked;
@@ -318,6 +319,8 @@ static void rfkill_set_block(struct rfki
 }
 
 #ifdef CONFIG_RFKILL_INPUT
+static atomic_t rfkill_input_disabled = ATOMIC_INIT(0);
+
 /**
  * __rfkill_switch_all - Toggle state of all switches of given type
  * @type: type of interfaces to be affected
@@ -354,6 +357,9 @@ static void __rfkill_switch_all(const en
  */
 void rfkill_switch_all(enum rfkill_type type, bool blocked)
 {
+	if (atomic_read(&rfkill_input_disabled))
+		return;
+
 	mutex_lock(&rfkill_global_mutex);
 
 	if (!rfkill_epo_lock_active)
@@ -376,6 +382,9 @@ void rfkill_epo(void)
 	struct rfkill *rfkill;
 	int i;
 
+	if (atomic_read(&rfkill_input_disabled))
+		return;
+
 	mutex_lock(&rfkill_global_mutex);
 
 	rfkill_epo_lock_active = true;
@@ -401,6 +410,9 @@ void rfkill_restore_states(void)
 {
 	int i;
 
+	if (atomic_read(&rfkill_input_disabled))
+		return;
+
 	mutex_lock(&rfkill_global_mutex);
 
 	rfkill_epo_lock_active = false;
@@ -417,6 +429,9 @@ void rfkill_restore_states(void)
  */
 void rfkill_remove_epo_lock(void)
 {
+	if (atomic_read(&rfkill_input_disabled))
+		return;
+
 	mutex_lock(&rfkill_global_mutex);
 	rfkill_epo_lock_active = false;
 	mutex_unlock(&rfkill_global_mutex);
@@ -451,6 +466,8 @@ bool rfkill_get_global_sw_state(const en
 
 void rfkill_set_global_sw_state(const enum rfkill_type type, bool blocked)
 {
+	BUG_ON(type == RFKILL_TYPE_ALL);
+
 	mutex_lock(&rfkill_global_mutex);
 
 	/* don't allow unblock when epo */
@@ -465,6 +482,7 @@ void rfkill_set_global_sw_state(const en
 
 	rfkill_global_states[type].cur = blocked;
 	rfkill_global_states[type].def = blocked;
+	rfkill_global_states[type].restored = true;
  out:
 	mutex_unlock(&rfkill_global_mutex);
 }
@@ -939,6 +957,7 @@ static int rfkill_fop_open(struct inode 
 	struct rfkill_data *data;
 	struct rfkill *rfkill;
 	struct rfkill_int_event *ev, *tmp;
+	enum rfkill_type i;
 
 	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
@@ -963,6 +982,19 @@ static int rfkill_fop_open(struct inode 
 		rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD);
 		list_add_tail(&ev->list, &data->events);
 	}
+
+	for (i = 0; i < NUM_RFKILL_TYPES; i++) {
+		if (!rfkill_global_states[i].restored)
+			continue;
+		ev = kzalloc(sizeof(*ev), GFP_KERNEL);
+		if (!ev)
+			goto free;
+		ev->ev.idx = 0;
+		ev->ev.type = RFKILL_TYPE_ALL;
+		ev->ev.op = RFKILL_OP_NVS_REPORT;
+		list_add_tail(&ev->list, &data->events);
+	}
+
 	mutex_unlock(&data->mtx);
 	mutex_unlock(&rfkill_global_mutex);
 
@@ -1103,17 +1135,50 @@ static int rfkill_fop_release(struct ino
 	list_for_each_entry_safe(ev, tmp, &data->events, list)
 		kfree(ev);
 
+#ifdef CONFIG_RFKILL_INPUT
+	if (data->input_handler)
+		atomic_dec(&rfkill_input_disabled);
+#endif
+
 	kfree(data);
 
 	return 0;
 }
 
+#ifdef CONFIG_RFKILL_INPUT
+static long rfkill_fop_ioctl(struct file *file, unsigned int cmd,
+			     unsigned long arg)
+{
+	struct rfkill_data *data = file->private_data;
+
+	if (_IOC_TYPE(cmd) != RFKILL_IOC_MAGIC)
+		return -ENOSYS;
+
+	if (_IOC_NR(cmd) != RFKILL_IOC_NOINPUT)
+		return -ENOSYS;
+
+	mutex_lock(&data->mtx);
+
+	if (!data->input_handler) {
+		atomic_inc(&rfkill_input_disabled);
+		data->input_handler = true;
+	}
+
+	mutex_unlock(&data->mtx);
+
+	return 0;
+}
+#endif
+
 static const struct file_operations rfkill_fops = {
 	.open		= rfkill_fop_open,
 	.read		= rfkill_fop_read,
 	.write		= rfkill_fop_write,
 	.poll		= rfkill_fop_poll,
 	.release	= rfkill_fop_release,
+#ifdef CONFIG_RFKILL_INPUT
+	.unlocked_ioctl	= rfkill_fop_ioctl,
+#endif
 };
 
 static struct miscdevice rfkill_miscdev = {
--- wireless-testing.orig/include/linux/rfkill.h	2009-06-01 13:49:36.000000000 +0200
+++ wireless-testing/include/linux/rfkill.h	2009-06-01 14:08:35.000000000 +0200
@@ -56,12 +56,15 @@ enum rfkill_type {
  * @RFKILL_OP_DEL: a device was removed
  * @RFKILL_OP_CHANGE: a device's state changed -- userspace changes one device
  * @RFKILL_OP_CHANGE_ALL: userspace changes all devices (of a type, or all)
+ * @RFKILL_OP_NVS_REPORT: kernel report about default state that was
+ *	restored from platform non-volatile storage
  */
 enum rfkill_operation {
 	RFKILL_OP_ADD = 0,
 	RFKILL_OP_DEL,
 	RFKILL_OP_CHANGE,
 	RFKILL_OP_CHANGE_ALL,
+	RFKILL_OP_NVS_REPORT,
 };
 
 /**
@@ -82,6 +85,11 @@ struct rfkill_event {
 	__u8  soft, hard;
 } __packed;
 
+/* ioctl for turning off rfkill-input (if present) */
+#define RFKILL_IOC_MAGIC	'R'
+#define RFKILL_IOC_NOINPUT	1
+#define RFKILL_IOCTL_NOINPUT	_IO(RFKILL_IOC_MAGIC, RFKILL_IOC_NOINPUT)
+
 /* and that's all userspace gets */
 #ifdef __KERNEL__
 /* don't allow anyone to use these in the kernel */


--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux