enhance sysfs rfkill interface
florian@mickler.org [Fri, 26 Feb 2010 11:01:34 +0000 (12:01 +0100)]
This commit introduces two new sysfs knobs.

/sys/class/rfkill/rfkill[0-9]+/blocked_hw: (ro)
hardblock kill state
/sys/class/rfkill/rfkill[0-9]+/blocked_sw: (rw)
softblock kill state

Signed-off-by: Florian Mickler <florian@mickler.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Documentation/ABI/stable/sysfs-class-rfkill
net/rfkill/core.c

index 97d5064..b91c3f3 100644 (file)
@@ -40,3 +40,28 @@ Description:         Whether the soft blocked state is initialised from non-volatile
 Values:        A numeric value.
                0: false
                1: true
+
+
+What:          /sys/class/rfkill/rfkill[0-9]+/blocked_hw
+Date:          23-Feb-2010
+KernelVersion  v2.6.34
+Contact:       linux-wireless@vger.kernel.org
+Description:   Current hardblock state. This file is read only.
+Values:        A numeric value.
+               0: inactive
+                       The transmitter is (potentially) active.
+               1: active
+                       The transmitter is forced off by something outside of
+                       the driver's control.
+
+
+What:          /sys/class/rfkill/rfkill[0-9]+/blocked_sw
+Date:          23-Feb-2010
+KernelVersion  v2.6.34
+Contact:       linux-wireless@vger.kernel.org
+Description:   Current softblock state. This file is read and write.
+Values:        A numeric value.
+               0: inactive
+                       The transmitter is (potentially) active.
+               1: active
+                       The transmitter is turned off by software.
index c218e07..5f33151 100644 (file)
@@ -628,6 +628,61 @@ static ssize_t rfkill_persistent_show(struct device *dev,
        return sprintf(buf, "%d\n", rfkill->persistent);
 }
 
+static ssize_t rfkill_blocked_hw_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       struct rfkill *rfkill = to_rfkill(dev);
+       unsigned long flags;
+       u32 state;
+
+       spin_lock_irqsave(&rfkill->lock, flags);
+       state = rfkill->state;
+       spin_unlock_irqrestore(&rfkill->lock, flags);
+
+       return sprintf(buf, "%d\n", (state & RFKILL_BLOCK_HW) ? 1 : 0 );
+}
+
+static ssize_t rfkill_blocked_sw_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf)
+{
+       struct rfkill *rfkill = to_rfkill(dev);
+       unsigned long flags;
+       u32 state;
+
+       spin_lock_irqsave(&rfkill->lock, flags);
+       state = rfkill->state;
+       spin_unlock_irqrestore(&rfkill->lock, flags);
+
+       return sprintf(buf, "%d\n", (state & RFKILL_BLOCK_SW) ? 1 : 0 );
+}
+
+static ssize_t rfkill_blocked_sw_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count)
+{
+       struct rfkill *rfkill = to_rfkill(dev);
+       unsigned long state;
+       int err;
+
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
+       err = strict_strtoul(buf, 0, &state);
+       if (err)
+               return err;
+
+       if (state > 1 )
+               return -EINVAL;
+
+       mutex_lock(&rfkill_global_mutex);
+       rfkill_set_block(rfkill, state);
+       mutex_unlock(&rfkill_global_mutex);
+
+       return err ?: count;
+}
+
 static u8 user_state_from_blocked(unsigned long state)
 {
        if (state & RFKILL_BLOCK_HW)
@@ -700,6 +755,9 @@ static struct device_attribute rfkill_dev_attrs[] = {
        __ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL),
        __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store),
        __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store),
+       __ATTR(sw, S_IRUGO|S_IWUSR, rfkill_blocked_sw_show,
+                       rfkill_blocked_sw_store),
+       __ATTR(hw, S_IRUGO, rfkill_blocked_hw_show, NULL),
        __ATTR_NULL
 };