static struct input_handler *input_table[8];
+/**
+ * input_event() - report new input event
+ * @handle: device that generated the event
+ * @type: type of the event
+ * @code: event code
+ * @value: value of the event
+ *
+ * This function should be used by drivers implementing various input devices
+ * See also input_inject_event()
+ */
void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct input_handle *handle;
break;
case EV_FF:
+
+ if (value < 0)
+ return;
+
if (dev->event)
dev->event(dev, type, code, value);
break;
}
EXPORT_SYMBOL(input_event);
+/**
+ * input_inject_event() - send input event from input handler
+ * @handle: input handle to send event through
+ * @type: type of the event
+ * @code: event code
+ * @value: value of the event
+ *
+ * Similar to input_event() but will ignore event if device is "grabbed" and handle
+ * injecting event is not the one that owns the device.
+ */
+void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
+{
+ if (!handle->dev->grab || handle->dev->grab == handle)
+ input_event(handle->dev, type, code, value);
+}
+EXPORT_SYMBOL(input_inject_event);
+
static void input_repeat_key(unsigned long data)
{
struct input_dev *dev = (void *) data;
mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD]));
}
-int input_accept_process(struct input_handle *handle, struct file *file)
-{
- if (handle->dev->accept)
- return handle->dev->accept(handle->dev, file);
-
- return 0;
-}
-EXPORT_SYMBOL(input_accept_process);
-
int input_grab_device(struct input_handle *handle)
{
if (handle->dev->grab)
void input_release_device(struct input_handle *handle)
{
- if (handle->dev->grab == handle)
- handle->dev->grab = NULL;
+ struct input_dev *dev = handle->dev;
+
+ if (dev->grab == handle) {
+ dev->grab = NULL;
+
+ list_for_each_entry(handle, &dev->h_list, d_node)
+ if (handle->handler->start)
+ handle->handler->start(handle);
+ }
}
EXPORT_SYMBOL(input_release_device);
if (i != NBITS(max)) \
continue;
-static struct input_device_id *input_match_device(struct input_device_id *id, struct input_dev *dev)
+static const struct input_device_id *input_match_device(const struct input_device_id *id,
+ struct input_dev *dev)
{
int i;
{
struct input_dev *dev = to_input_dev(class_dev);
+ input_ff_destroy(dev);
kfree(dev);
+
module_put(THIS_MODULE);
}
dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
if (dev) {
- dev->dynalloc = 1;
dev->cdev.class = &input_class;
class_device_initialize(&dev->cdev);
mutex_init(&dev->mutex);
INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node);
+
+ __module_get(THIS_MODULE);
}
return dev;
static atomic_t input_no = ATOMIC_INIT(0);
struct input_handle *handle;
struct input_handler *handler;
- struct input_device_id *id;
+ const struct input_device_id *id;
const char *path;
int error;
- if (!dev->dynalloc) {
- printk(KERN_WARNING "input: device %s is statically allocated, will not register\n"
- "Please convert to input_allocate_device() or contact dtor_core@ameritech.net\n",
- dev->name ? dev->name : "<Unknown>");
- return -EINVAL;
- }
-
set_bit(EV_SYN, dev->evbit);
/*
dev->rep[REP_PERIOD] = 33;
}
- INIT_LIST_HEAD(&dev->h_list);
list_add_tail(&dev->node, &input_dev_list);
- dev->cdev.class = &input_class;
snprintf(dev->cdev.class_id, sizeof(dev->cdev.class_id),
"input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
if (error)
goto fail3;
- __module_get(THIS_MODULE);
-
path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL);
printk(KERN_INFO "input: %s as %s\n",
dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
list_for_each_entry(handler, &input_handler_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
- if ((handle = handler->connect(handler, dev, id)))
+ if ((handle = handler->connect(handler, dev, id))) {
input_link_handle(handle);
+ if (handler->start)
+ handler->start(handle);
+ }
input_wakeup_procfs_readers();
void input_unregister_device(struct input_dev *dev)
{
struct list_head *node, *next;
+ int code;
- if (!dev)
- return;
+ for (code = 0; code <= KEY_MAX; code++)
+ if (test_bit(code, dev->key))
+ input_report_key(dev, code, 0);
+ input_sync(dev);
del_timer_sync(&dev->timer);
}
EXPORT_SYMBOL(input_unregister_device);
-void input_register_handler(struct input_handler *handler)
+int input_register_handler(struct input_handler *handler)
{
struct input_dev *dev;
struct input_handle *handle;
- struct input_device_id *id;
-
- if (!handler)
- return;
+ const struct input_device_id *id;
INIT_LIST_HEAD(&handler->h_list);
- if (handler->fops != NULL)
+ if (handler->fops != NULL) {
+ if (input_table[handler->minor >> 5])
+ return -EBUSY;
+
input_table[handler->minor >> 5] = handler;
+ }
list_add_tail(&handler->node, &input_handler_list);
list_for_each_entry(dev, &input_dev_list, node)
if (!handler->blacklist || !input_match_device(handler->blacklist, dev))
if ((id = input_match_device(handler->id_table, dev)))
- if ((handle = handler->connect(handler, dev, id)))
+ if ((handle = handler->connect(handler, dev, id))) {
input_link_handle(handle);
+ if (handler->start)
+ handler->start(handle);
+ }
input_wakeup_procfs_readers();
+ return 0;
}
EXPORT_SYMBOL(input_register_handler);