aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/input.c')
-rw-r--r--drivers/input/input.c114
1 files changed, 53 insertions, 61 deletions
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ace3f7c4226d..53a0ddee7872 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -14,6 +14,7 @@
14 14
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/types.h> 16#include <linux/types.h>
17#include <linux/idr.h>
17#include <linux/input/mt.h> 18#include <linux/input/mt.h>
18#include <linux/module.h> 19#include <linux/module.h>
19#include <linux/slab.h> 20#include <linux/slab.h>
@@ -32,7 +33,9 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
32MODULE_DESCRIPTION("Input core"); 33MODULE_DESCRIPTION("Input core");
33MODULE_LICENSE("GPL"); 34MODULE_LICENSE("GPL");
34 35
35#define INPUT_DEVICES 256 36#define INPUT_MAX_CHAR_DEVICES 1024
37#define INPUT_FIRST_DYNAMIC_DEV 256
38static DEFINE_IDA(input_ida);
36 39
37static LIST_HEAD(input_dev_list); 40static LIST_HEAD(input_dev_list);
38static LIST_HEAD(input_handler_list); 41static LIST_HEAD(input_handler_list);
@@ -45,8 +48,6 @@ static LIST_HEAD(input_handler_list);
45 */ 48 */
46static DEFINE_MUTEX(input_mutex); 49static DEFINE_MUTEX(input_mutex);
47 50
48static struct input_handler *input_table[8];
49
50static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 }; 51static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 };
51 52
52static inline int is_event_supported(unsigned int code, 53static inline int is_event_supported(unsigned int code,
@@ -1218,7 +1219,7 @@ static int input_handlers_seq_show(struct seq_file *seq, void *v)
1218 seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name); 1219 seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name);
1219 if (handler->filter) 1220 if (handler->filter)
1220 seq_puts(seq, " (filter)"); 1221 seq_puts(seq, " (filter)");
1221 if (handler->fops) 1222 if (handler->legacy_minors)
1222 seq_printf(seq, " Minor=%d", handler->minor); 1223 seq_printf(seq, " Minor=%d", handler->minor);
1223 seq_putc(seq, '\n'); 1224 seq_putc(seq, '\n');
1224 1225
@@ -2016,22 +2017,14 @@ EXPORT_SYMBOL(input_unregister_device);
2016int input_register_handler(struct input_handler *handler) 2017int input_register_handler(struct input_handler *handler)
2017{ 2018{
2018 struct input_dev *dev; 2019 struct input_dev *dev;
2019 int retval; 2020 int error;
2020 2021
2021 retval = mutex_lock_interruptible(&input_mutex); 2022 error = mutex_lock_interruptible(&input_mutex);
2022 if (retval) 2023 if (error)
2023 return retval; 2024 return error;
2024 2025
2025 INIT_LIST_HEAD(&handler->h_list); 2026 INIT_LIST_HEAD(&handler->h_list);
2026 2027
2027 if (handler->fops != NULL) {
2028 if (input_table[handler->minor >> 5]) {
2029 retval = -EBUSY;
2030 goto out;
2031 }
2032 input_table[handler->minor >> 5] = handler;
2033 }
2034
2035 list_add_tail(&handler->node, &input_handler_list); 2028 list_add_tail(&handler->node, &input_handler_list);
2036 2029
2037 list_for_each_entry(dev, &input_dev_list, node) 2030 list_for_each_entry(dev, &input_dev_list, node)
@@ -2039,9 +2032,8 @@ int input_register_handler(struct input_handler *handler)
2039 2032
2040 input_wakeup_procfs_readers(); 2033 input_wakeup_procfs_readers();
2041 2034
2042 out:
2043 mutex_unlock(&input_mutex); 2035 mutex_unlock(&input_mutex);
2044 return retval; 2036 return 0;
2045} 2037}
2046EXPORT_SYMBOL(input_register_handler); 2038EXPORT_SYMBOL(input_register_handler);
2047 2039
@@ -2064,9 +2056,6 @@ void input_unregister_handler(struct input_handler *handler)
2064 2056
2065 list_del_init(&handler->node); 2057 list_del_init(&handler->node);
2066 2058
2067 if (handler->fops != NULL)
2068 input_table[handler->minor >> 5] = NULL;
2069
2070 input_wakeup_procfs_readers(); 2059 input_wakeup_procfs_readers();
2071 2060
2072 mutex_unlock(&input_mutex); 2061 mutex_unlock(&input_mutex);
@@ -2183,51 +2172,52 @@ void input_unregister_handle(struct input_handle *handle)
2183} 2172}
2184EXPORT_SYMBOL(input_unregister_handle); 2173EXPORT_SYMBOL(input_unregister_handle);
2185 2174
2186static int input_open_file(struct inode *inode, struct file *file) 2175/**
2176 * input_get_new_minor - allocates a new input minor number
2177 * @legacy_base: beginning or the legacy range to be searched
2178 * @legacy_num: size of legacy range
2179 * @allow_dynamic: whether we can also take ID from the dynamic range
2180 *
2181 * This function allocates a new device minor for from input major namespace.
2182 * Caller can request legacy minor by specifying @legacy_base and @legacy_num
2183 * parameters and whether ID can be allocated from dynamic range if there are
2184 * no free IDs in legacy range.
2185 */
2186int input_get_new_minor(int legacy_base, unsigned int legacy_num,
2187 bool allow_dynamic)
2187{ 2188{
2188 struct input_handler *handler;
2189 const struct file_operations *old_fops, *new_fops = NULL;
2190 int err;
2191
2192 err = mutex_lock_interruptible(&input_mutex);
2193 if (err)
2194 return err;
2195
2196 /* No load-on-demand here? */
2197 handler = input_table[iminor(inode) >> 5];
2198 if (handler)
2199 new_fops = fops_get(handler->fops);
2200
2201 mutex_unlock(&input_mutex);
2202
2203 /* 2189 /*
2204 * That's _really_ odd. Usually NULL ->open means "nothing special", 2190 * This function should be called from input handler's ->connect()
2205 * not "no device". Oh, well... 2191 * methods, which are serialized with input_mutex, so no additional
2192 * locking is needed here.
2206 */ 2193 */
2207 if (!new_fops || !new_fops->open) { 2194 if (legacy_base >= 0) {
2208 fops_put(new_fops); 2195 int minor = ida_simple_get(&input_ida,
2209 err = -ENODEV; 2196 legacy_base,
2210 goto out; 2197 legacy_base + legacy_num,
2198 GFP_KERNEL);
2199 if (minor >= 0 || !allow_dynamic)
2200 return minor;
2211 } 2201 }
2212 2202
2213 old_fops = file->f_op; 2203 return ida_simple_get(&input_ida,
2214 file->f_op = new_fops; 2204 INPUT_FIRST_DYNAMIC_DEV, INPUT_MAX_CHAR_DEVICES,
2215 2205 GFP_KERNEL);
2216 err = new_fops->open(inode, file);
2217 if (err) {
2218 fops_put(file->f_op);
2219 file->f_op = fops_get(old_fops);
2220 }
2221 fops_put(old_fops);
2222out:
2223 return err;
2224} 2206}
2207EXPORT_SYMBOL(input_get_new_minor);
2225 2208
2226static const struct file_operations input_fops = { 2209/**
2227 .owner = THIS_MODULE, 2210 * input_free_minor - release previously allocated minor
2228 .open = input_open_file, 2211 * @minor: minor to be released
2229 .llseek = noop_llseek, 2212 *
2230}; 2213 * This function releases previously allocated input minor so that it can be
2214 * reused later.
2215 */
2216void input_free_minor(unsigned int minor)
2217{
2218 ida_simple_remove(&input_ida, minor);
2219}
2220EXPORT_SYMBOL(input_free_minor);
2231 2221
2232static int __init input_init(void) 2222static int __init input_init(void)
2233{ 2223{
@@ -2243,7 +2233,8 @@ static int __init input_init(void)
2243 if (err) 2233 if (err)
2244 goto fail1; 2234 goto fail1;
2245 2235
2246 err = register_chrdev(INPUT_MAJOR, "input", &input_fops); 2236 err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0),
2237 INPUT_MAX_CHAR_DEVICES, "input");
2247 if (err) { 2238 if (err) {
2248 pr_err("unable to register char major %d", INPUT_MAJOR); 2239 pr_err("unable to register char major %d", INPUT_MAJOR);
2249 goto fail2; 2240 goto fail2;
@@ -2259,7 +2250,8 @@ static int __init input_init(void)
2259static void __exit input_exit(void) 2250static void __exit input_exit(void)
2260{ 2251{
2261 input_proc_exit(); 2252 input_proc_exit();
2262 unregister_chrdev(INPUT_MAJOR, "input"); 2253 unregister_chrdev_region(MKDEV(INPUT_MAJOR, 0),
2254 INPUT_MAX_CHAR_DEVICES);
2263 class_unregister(&input_class); 2255 class_unregister(&input_class);
2264} 2256}
2265 2257