Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: add skeleton for simple polled devices

input-polldev provides a skeleton for supporting simple input
devices that need to be periodically scanned or polled to
detect changes in their state.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

+229
+11
drivers/input/misc/Kconfig
··· 90 90 To compile this driver as a module, choose M here: the 91 91 module will be called uinput. 92 92 93 + config INPUT_POLLDEV 94 + tristate "Polled input device skeleton" 95 + help 96 + Say Y here if you are using a driver for an input 97 + device that periodically polls hardware state. This 98 + option is only useful for out-of-tree drivers since 99 + in-tree drivers select it automatically. 100 + 101 + To compile this driver as a module, choose M here: the 102 + module will be called input-polldev. 103 + 93 104 config HP_SDC_RTC 94 105 tristate "HP SDC Real Time Clock" 95 106 depends on GSC || HP300
+1
drivers/input/misc/Makefile
··· 4 4 5 5 # Each configuration option enables a list of files. 6 6 7 + obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o 7 8 obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o 8 9 obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o 9 10 obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
+171
drivers/input/misc/input-polldev.c
··· 1 + /* 2 + * Generic implementation of a polled input device 3 + 4 + * Copyright (c) 2007 Dmitry Torokhov 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License version 2 as published by 8 + * the Free Software Foundation. 9 + */ 10 + 11 + #include <linux/jiffies.h> 12 + #include <linux/mutex.h> 13 + #include <linux/input-polldev.h> 14 + 15 + static DEFINE_MUTEX(polldev_mutex); 16 + static int polldev_users; 17 + static struct workqueue_struct *polldev_wq; 18 + 19 + static int input_polldev_start_workqueue(void) 20 + { 21 + int retval; 22 + 23 + retval = mutex_lock_interruptible(&polldev_mutex); 24 + if (retval) 25 + return retval; 26 + 27 + if (!polldev_users) { 28 + polldev_wq = create_singlethread_workqueue("ipolldevd"); 29 + if (!polldev_wq) { 30 + printk(KERN_ERR "input-polldev: failed to create " 31 + "ipolldevd workqueue\n"); 32 + retval = -ENOMEM; 33 + goto out; 34 + } 35 + } 36 + 37 + polldev_users++; 38 + 39 + out: 40 + mutex_unlock(&polldev_mutex); 41 + return retval; 42 + } 43 + 44 + static void input_polldev_stop_workqueue(void) 45 + { 46 + mutex_lock(&polldev_mutex); 47 + 48 + if (!--polldev_users) 49 + destroy_workqueue(polldev_wq); 50 + 51 + mutex_unlock(&polldev_mutex); 52 + } 53 + 54 + static void input_polled_device_work(struct work_struct *work) 55 + { 56 + struct input_polled_dev *dev = 57 + container_of(work, struct input_polled_dev, work.work); 58 + 59 + dev->poll(dev); 60 + queue_delayed_work(polldev_wq, &dev->work, 61 + msecs_to_jiffies(dev->poll_interval)); 62 + } 63 + 64 + static int input_open_polled_device(struct input_dev *input) 65 + { 66 + struct input_polled_dev *dev = input->private; 67 + int error; 68 + 69 + error = input_polldev_start_workqueue(); 70 + if (error) 71 + return error; 72 + 73 + if (dev->flush) 74 + dev->flush(dev); 75 + 76 + queue_delayed_work(polldev_wq, &dev->work, 77 + msecs_to_jiffies(dev->poll_interval)); 78 + 79 + return 0; 80 + } 81 + 82 + static void input_close_polled_device(struct input_dev *input) 83 + { 84 + struct input_polled_dev *dev = input->private; 85 + 86 + cancel_rearming_delayed_workqueue(polldev_wq, &dev->work); 87 + input_polldev_stop_workqueue(); 88 + } 89 + 90 + /** 91 + * input_allocate_polled_device - allocated memory polled device 92 + * 93 + * The function allocates memory for a polled device and also 94 + * for an input device associated with this polled device. 95 + */ 96 + struct input_polled_dev *input_allocate_polled_device(void) 97 + { 98 + struct input_polled_dev *dev; 99 + 100 + dev = kzalloc(sizeof(struct input_polled_dev), GFP_KERNEL); 101 + if (!dev) 102 + return NULL; 103 + 104 + dev->input = input_allocate_device(); 105 + if (!dev->input) { 106 + kfree(dev); 107 + return NULL; 108 + } 109 + 110 + return dev; 111 + } 112 + EXPORT_SYMBOL(input_allocate_polled_device); 113 + 114 + /** 115 + * input_free_polled_device - free memory allocated for polled device 116 + * @dev: device to free 117 + * 118 + * The function frees memory allocated for polling device and drops 119 + * reference to the associated input device (if present). 120 + */ 121 + void input_free_polled_device(struct input_polled_dev *dev) 122 + { 123 + if (dev) { 124 + input_free_device(dev->input); 125 + kfree(dev); 126 + } 127 + } 128 + EXPORT_SYMBOL(input_free_polled_device); 129 + 130 + /** 131 + * input_register_polled_device - register polled device 132 + * @dev: device to register 133 + * 134 + * The function registers previously initialized polled input device 135 + * with input layer. The device should be allocated with call to 136 + * input_allocate_polled_device(). Callers should also set up poll() 137 + * method and set up capabilities (id, name, phys, bits) of the 138 + * corresponing input_dev structure. 139 + */ 140 + int input_register_polled_device(struct input_polled_dev *dev) 141 + { 142 + struct input_dev *input = dev->input; 143 + 144 + INIT_DELAYED_WORK(&dev->work, input_polled_device_work); 145 + if (!dev->poll_interval) 146 + dev->poll_interval = 500; 147 + input->private = dev; 148 + input->open = input_open_polled_device; 149 + input->close = input_close_polled_device; 150 + 151 + return input_register_device(input); 152 + } 153 + EXPORT_SYMBOL(input_register_polled_device); 154 + 155 + /** 156 + * input_unregister_polled_device - unregister polled device 157 + * @dev: device to unregister 158 + * 159 + * The function unregisters previously registered polled input 160 + * device from input layer. Polling is stopped and device is 161 + * ready to be freed with call to input_free_polled_device(). 162 + * Callers should not attempt to access dev->input pointer 163 + * after calling this function. 164 + */ 165 + void input_unregister_polled_device(struct input_polled_dev *dev) 166 + { 167 + input_unregister_device(dev->input); 168 + dev->input = NULL; 169 + } 170 + EXPORT_SYMBOL(input_unregister_polled_device); 171 +
+46
include/linux/input-polldev.h
··· 1 + #ifndef _INPUT_POLLDEV_H 2 + #define _INPUT_POLLDEV_H 3 + 4 + /* 5 + * Copyright (c) 2007 Dmitry Torokhov 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License version 2 as published by 9 + * the Free Software Foundation. 10 + */ 11 + 12 + #include <linux/input.h> 13 + #include <linux/workqueue.h> 14 + 15 + /** 16 + * struct input_polled_dev - simple polled input device 17 + * @private: private driver data 18 + * @flush: driver-supplied method that flushes device's state upon 19 + * opening (optional) 20 + * @poll: driver-supplied method that polls the device and posts 21 + * input events (mandatory). 22 + * @poll_interval: specifies how often the poll() method shoudl be called. 23 + * @input: input device structire associated with the polled device. 24 + * Must be properly initialized by the driver (id, name, phys, bits). 25 + * 26 + * Polled input device provides a skeleton for supporting simple input 27 + * devices that do not raise interrupts but have to be periodically 28 + * scanned or polled to detect changes in their state. 29 + */ 30 + struct input_polled_dev { 31 + void *private; 32 + 33 + void (*flush)(struct input_polled_dev *dev); 34 + void (*poll)(struct input_polled_dev *dev); 35 + unsigned int poll_interval; /* msec */ 36 + 37 + struct input_dev *input; 38 + struct delayed_work work; 39 + }; 40 + 41 + struct input_polled_dev *input_allocate_polled_device(void); 42 + void input_free_polled_device(struct input_polled_dev *dev); 43 + int input_register_polled_device(struct input_polled_dev *dev); 44 + void input_unregister_polled_device(struct input_polled_dev *dev); 45 + 46 + #endif