* old behaviour for all userspace, unless it explicitly opts in to the
* rules outlined here by using the new &struct rfkill_event_ext.
*
- * Additionally, some other userspace (bluez, g-s-d) was reading with a
- * large size but as streaming reads rather than message-based, or with
- * too strict checks for the returned size. So eventually, we completely
- * reverted this, and extended messages need to be opted in to by using
- * an ioctl:
- *
- * ioctl(fd, RFKILL_IOCTL_MAX_SIZE, sizeof(struct rfkill_event_ext));
- *
- * Userspace using &struct rfkill_event_ext and the ioctl must adhere to
- * the following rules:
+ * Userspace using &struct rfkill_event_ext must adhere to the following
+ * rules
*
* 1. accept short writes, optionally using them to detect that it's
* running on an older kernel;
#define RFKILL_IOC_MAGIC 'R'
#define RFKILL_IOC_NOINPUT 1
#define RFKILL_IOCTL_NOINPUT _IO(RFKILL_IOC_MAGIC, RFKILL_IOC_NOINPUT)
-#define RFKILL_IOC_MAX_SIZE 2
-#define RFKILL_IOCTL_MAX_SIZE _IOW(RFKILL_IOC_MAGIC, RFKILL_IOC_EXT_SIZE, __u32)
/* and that's all userspace gets */
struct mutex mtx;
wait_queue_head_t read_wait;
bool input_handler;
- u8 max_size;
};
if (!data)
return -ENOMEM;
- data->max_size = RFKILL_EVENT_SIZE_V1;
-
INIT_LIST_HEAD(&data->events);
mutex_init(&data->mtx);
init_waitqueue_head(&data->read_wait);
list);
sz = min_t(unsigned long, sizeof(ev->ev), count);
- sz = min_t(unsigned long, sz, data->max_size);
ret = sz;
if (copy_to_user(buf, &ev->ev, sz))
ret = -EFAULT;
static ssize_t rfkill_fop_write(struct file *file, const char __user *buf,
size_t count, loff_t *pos)
{
- struct rfkill_data *data = file->private_data;
struct rfkill *rfkill;
struct rfkill_event_ext ev;
int ret;
* our API version even in a write() call, if it cares.
*/
count = min(count, sizeof(ev));
- count = min_t(size_t, count, data->max_size);
if (copy_from_user(&ev, buf, count))
return -EFAULT;
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;
- int ret = -ENOSYS;
- u32 size;
if (_IOC_TYPE(cmd) != RFKILL_IOC_MAGIC)
return -ENOSYS;
+ if (_IOC_NR(cmd) != RFKILL_IOC_NOINPUT)
+ return -ENOSYS;
+
mutex_lock(&data->mtx);
- switch (_IOC_NR(cmd)) {
-#ifdef CONFIG_RFKILL_INPUT
- case RFKILL_IOC_NOINPUT:
- if (!data->input_handler) {
- if (atomic_inc_return(&rfkill_input_disabled) == 1)
- printk(KERN_DEBUG "rfkill: input handler disabled\n");
- data->input_handler = true;
- }
- ret = 0;
- break;
-#endif
- case RFKILL_IOC_MAX_SIZE:
- if (get_user(size, (__u32 __user *)arg)) {
- ret = -EFAULT;
- break;
- }
- if (size < RFKILL_EVENT_SIZE_V1 || size > U8_MAX) {
- ret = -EINVAL;
- break;
- }
- data->max_size = size;
- ret = 0;
- break;
- default:
- break;
+
+ if (!data->input_handler) {
+ if (atomic_inc_return(&rfkill_input_disabled) == 1)
+ printk(KERN_DEBUG "rfkill: input handler disabled\n");
+ data->input_handler = true;
}
+
mutex_unlock(&data->mtx);
- return ret;
+ return 0;
}
+#endif
static const struct file_operations rfkill_fops = {
.owner = THIS_MODULE,
.write = rfkill_fop_write,
.poll = rfkill_fop_poll,
.release = rfkill_fop_release,
+#ifdef CONFIG_RFKILL_INPUT
.unlocked_ioctl = rfkill_fop_ioctl,
.compat_ioctl = compat_ptr_ioctl,
+#endif
.llseek = no_llseek,
};