| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * The input core |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 1999-2002 Vojtech Pavlik |
|---|
| 5 | 6 | */ |
|---|
| 6 | 7 | |
|---|
| 7 | | -/* |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 9 | | - * under the terms of the GNU General Public License version 2 as published by |
|---|
| 10 | | - * the Free Software Foundation. |
|---|
| 11 | | - */ |
|---|
| 12 | 8 | |
|---|
| 13 | 9 | #define pr_fmt(fmt) KBUILD_BASENAME ": " fmt |
|---|
| 14 | 10 | |
|---|
| .. | .. |
|---|
| 28 | 24 | #include <linux/mutex.h> |
|---|
| 29 | 25 | #include <linux/rcupdate.h> |
|---|
| 30 | 26 | #include "input-compat.h" |
|---|
| 27 | +#include "input-poller.h" |
|---|
| 31 | 28 | |
|---|
| 32 | 29 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); |
|---|
| 33 | 30 | MODULE_DESCRIPTION("Input core"); |
|---|
| .. | .. |
|---|
| 49 | 46 | static DEFINE_MUTEX(input_mutex); |
|---|
| 50 | 47 | |
|---|
| 51 | 48 | static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 }; |
|---|
| 49 | + |
|---|
| 50 | +static const unsigned int input_max_code[EV_CNT] = { |
|---|
| 51 | + [EV_KEY] = KEY_MAX, |
|---|
| 52 | + [EV_REL] = REL_MAX, |
|---|
| 53 | + [EV_ABS] = ABS_MAX, |
|---|
| 54 | + [EV_MSC] = MSC_MAX, |
|---|
| 55 | + [EV_SW] = SW_MAX, |
|---|
| 56 | + [EV_LED] = LED_MAX, |
|---|
| 57 | + [EV_SND] = SND_MAX, |
|---|
| 58 | + [EV_FF] = FF_MAX, |
|---|
| 59 | +}; |
|---|
| 52 | 60 | |
|---|
| 53 | 61 | static inline int is_event_supported(unsigned int code, |
|---|
| 54 | 62 | unsigned long *bm, unsigned int max) |
|---|
| .. | .. |
|---|
| 615 | 623 | |
|---|
| 616 | 624 | handle->open++; |
|---|
| 617 | 625 | |
|---|
| 618 | | - if (!dev->users++ && dev->open) |
|---|
| 619 | | - retval = dev->open(dev); |
|---|
| 626 | + if (dev->users++) { |
|---|
| 627 | + /* |
|---|
| 628 | + * Device is already opened, so we can exit immediately and |
|---|
| 629 | + * report success. |
|---|
| 630 | + */ |
|---|
| 631 | + goto out; |
|---|
| 632 | + } |
|---|
| 620 | 633 | |
|---|
| 621 | | - if (retval) { |
|---|
| 622 | | - dev->users--; |
|---|
| 623 | | - if (!--handle->open) { |
|---|
| 634 | + if (dev->open) { |
|---|
| 635 | + retval = dev->open(dev); |
|---|
| 636 | + if (retval) { |
|---|
| 637 | + dev->users--; |
|---|
| 638 | + handle->open--; |
|---|
| 624 | 639 | /* |
|---|
| 625 | 640 | * Make sure we are not delivering any more events |
|---|
| 626 | 641 | * through this handle |
|---|
| 627 | 642 | */ |
|---|
| 628 | 643 | synchronize_rcu(); |
|---|
| 644 | + goto out; |
|---|
| 629 | 645 | } |
|---|
| 630 | 646 | } |
|---|
| 647 | + |
|---|
| 648 | + if (dev->poller) |
|---|
| 649 | + input_dev_poller_start(dev->poller); |
|---|
| 631 | 650 | |
|---|
| 632 | 651 | out: |
|---|
| 633 | 652 | mutex_unlock(&dev->mutex); |
|---|
| .. | .. |
|---|
| 667 | 686 | |
|---|
| 668 | 687 | __input_release_device(handle); |
|---|
| 669 | 688 | |
|---|
| 670 | | - if (!--dev->users && dev->close) |
|---|
| 671 | | - dev->close(dev); |
|---|
| 689 | + if (!--dev->users) { |
|---|
| 690 | + if (dev->poller) |
|---|
| 691 | + input_dev_poller_stop(dev->poller); |
|---|
| 692 | + |
|---|
| 693 | + if (dev->close) |
|---|
| 694 | + dev->close(dev); |
|---|
| 695 | + } |
|---|
| 672 | 696 | |
|---|
| 673 | 697 | if (!--handle->open) { |
|---|
| 674 | 698 | /* |
|---|
| .. | .. |
|---|
| 1204 | 1228 | return seq_open(file, &input_devices_seq_ops); |
|---|
| 1205 | 1229 | } |
|---|
| 1206 | 1230 | |
|---|
| 1207 | | -static const struct file_operations input_devices_fileops = { |
|---|
| 1208 | | - .owner = THIS_MODULE, |
|---|
| 1209 | | - .open = input_proc_devices_open, |
|---|
| 1210 | | - .poll = input_proc_devices_poll, |
|---|
| 1211 | | - .read = seq_read, |
|---|
| 1212 | | - .llseek = seq_lseek, |
|---|
| 1213 | | - .release = seq_release, |
|---|
| 1231 | +static const struct proc_ops input_devices_proc_ops = { |
|---|
| 1232 | + .proc_open = input_proc_devices_open, |
|---|
| 1233 | + .proc_poll = input_proc_devices_poll, |
|---|
| 1234 | + .proc_read = seq_read, |
|---|
| 1235 | + .proc_lseek = seq_lseek, |
|---|
| 1236 | + .proc_release = seq_release, |
|---|
| 1214 | 1237 | }; |
|---|
| 1215 | 1238 | |
|---|
| 1216 | 1239 | static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) |
|---|
| .. | .. |
|---|
| 1268 | 1291 | return seq_open(file, &input_handlers_seq_ops); |
|---|
| 1269 | 1292 | } |
|---|
| 1270 | 1293 | |
|---|
| 1271 | | -static const struct file_operations input_handlers_fileops = { |
|---|
| 1272 | | - .owner = THIS_MODULE, |
|---|
| 1273 | | - .open = input_proc_handlers_open, |
|---|
| 1274 | | - .read = seq_read, |
|---|
| 1275 | | - .llseek = seq_lseek, |
|---|
| 1276 | | - .release = seq_release, |
|---|
| 1294 | +static const struct proc_ops input_handlers_proc_ops = { |
|---|
| 1295 | + .proc_open = input_proc_handlers_open, |
|---|
| 1296 | + .proc_read = seq_read, |
|---|
| 1297 | + .proc_lseek = seq_lseek, |
|---|
| 1298 | + .proc_release = seq_release, |
|---|
| 1277 | 1299 | }; |
|---|
| 1278 | 1300 | |
|---|
| 1279 | 1301 | static int __init input_proc_init(void) |
|---|
| .. | .. |
|---|
| 1285 | 1307 | return -ENOMEM; |
|---|
| 1286 | 1308 | |
|---|
| 1287 | 1309 | entry = proc_create("devices", 0, proc_bus_input_dir, |
|---|
| 1288 | | - &input_devices_fileops); |
|---|
| 1310 | + &input_devices_proc_ops); |
|---|
| 1289 | 1311 | if (!entry) |
|---|
| 1290 | 1312 | goto fail1; |
|---|
| 1291 | 1313 | |
|---|
| 1292 | 1314 | entry = proc_create("handlers", 0, proc_bus_input_dir, |
|---|
| 1293 | | - &input_handlers_fileops); |
|---|
| 1315 | + &input_handlers_proc_ops); |
|---|
| 1294 | 1316 | if (!entry) |
|---|
| 1295 | 1317 | goto fail2; |
|---|
| 1296 | 1318 | |
|---|
| .. | .. |
|---|
| 1520 | 1542 | &input_dev_attr_group, |
|---|
| 1521 | 1543 | &input_dev_id_attr_group, |
|---|
| 1522 | 1544 | &input_dev_caps_attr_group, |
|---|
| 1545 | + &input_poller_attribute_group, |
|---|
| 1523 | 1546 | NULL |
|---|
| 1524 | 1547 | }; |
|---|
| 1525 | 1548 | |
|---|
| .. | .. |
|---|
| 1529 | 1552 | |
|---|
| 1530 | 1553 | input_ff_destroy(dev); |
|---|
| 1531 | 1554 | input_mt_destroy_slots(dev); |
|---|
| 1555 | + kfree(dev->poller); |
|---|
| 1532 | 1556 | kfree(dev->absinfo); |
|---|
| 1533 | 1557 | kfree(dev->vals); |
|---|
| 1534 | 1558 | kfree(dev); |
|---|
| .. | .. |
|---|
| 1963 | 1987 | */ |
|---|
| 1964 | 1988 | void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code) |
|---|
| 1965 | 1989 | { |
|---|
| 1990 | + if (type < EV_CNT && input_max_code[type] && |
|---|
| 1991 | + code > input_max_code[type]) { |
|---|
| 1992 | + pr_err("%s: invalid code %u for type %u\n", __func__, code, |
|---|
| 1993 | + type); |
|---|
| 1994 | + dump_stack(); |
|---|
| 1995 | + return; |
|---|
| 1996 | + } |
|---|
| 1997 | + |
|---|
| 1966 | 1998 | switch (type) { |
|---|
| 1967 | 1999 | case EV_KEY: |
|---|
| 1968 | 2000 | __set_bit(code, dev->keybit); |
|---|
| .. | .. |
|---|
| 2193 | 2225 | if (!dev->setkeycode) |
|---|
| 2194 | 2226 | dev->setkeycode = input_default_setkeycode; |
|---|
| 2195 | 2227 | |
|---|
| 2228 | + if (dev->poller) |
|---|
| 2229 | + input_dev_poller_finalize(dev->poller); |
|---|
| 2230 | + |
|---|
| 2196 | 2231 | error = device_add(&dev->dev); |
|---|
| 2197 | 2232 | if (error) |
|---|
| 2198 | 2233 | goto err_free_vals; |
|---|