|
@@ -648,15 +648,26 @@ static ssize_t rfkill_state_store(struct device *dev,
|
|
|
struct device_attribute *attr,
|
|
|
const char *buf, size_t count)
|
|
|
{
|
|
|
- /*
|
|
|
- * The intention was that userspace can only take control over
|
|
|
- * a given device when/if rfkill-input doesn't control it due
|
|
|
- * to user_claim. Since user_claim is currently unsupported,
|
|
|
- * we never support changing the state from userspace -- this
|
|
|
- * can be implemented again later.
|
|
|
- */
|
|
|
+ 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 != RFKILL_USER_STATE_SOFT_BLOCKED &&
|
|
|
+ state != RFKILL_USER_STATE_UNBLOCKED)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ mutex_lock(&rfkill_global_mutex);
|
|
|
+ rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED);
|
|
|
+ mutex_unlock(&rfkill_global_mutex);
|
|
|
|
|
|
- return -EPERM;
|
|
|
+ return err ?: count;
|
|
|
}
|
|
|
|
|
|
static ssize_t rfkill_claim_show(struct device *dev,
|