Release 4.11 drivers/input/input.c
/*
* The input core
*
* Copyright (c) 1999-2002 Vojtech Pavlik
*/
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
#include <linux/init.h>
#include <linux/types.h>
#include <linux/idr.h>
#include <linux/input/mt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <linux/major.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/poll.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/rcupdate.h>
#include "input-compat.h"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input core");
MODULE_LICENSE("GPL");
#define INPUT_MAX_CHAR_DEVICES 1024
#define INPUT_FIRST_DYNAMIC_DEV 256
static DEFINE_IDA(input_ida);
static LIST_HEAD(input_dev_list);
static LIST_HEAD(input_handler_list);
/*
* input_mutex protects access to both input_dev_list and input_handler_list.
* This also causes input_[un]register_device and input_[un]register_handler
* be mutually exclusive which simplifies locking in drivers implementing
* input handlers.
*/
static DEFINE_MUTEX(input_mutex);
static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 };
static inline int is_event_supported(unsigned int code,
unsigned long *bm, unsigned int max)
{
return code <= max && test_bit(code, bm);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 32 | 100.00% | 1 | 100.00% |
Total | 32 | 100.00% | 1 | 100.00% |
static int input_defuzz_abs_event(int value, int old_val, int fuzz)
{
if (fuzz) {
if (value > old_val - fuzz / 2 && value < old_val + fuzz / 2)
return old_val;
if (value > old_val - fuzz && value < old_val + fuzz)
return (old_val * 3 + value) / 4;
if (value > old_val - fuzz * 2 && value < old_val + fuzz * 2)
return (old_val + value) / 2;
}
return value;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 97 | 100.00% | 1 | 100.00% |
Total | 97 | 100.00% | 1 | 100.00% |
static void input_start_autorepeat(struct input_dev *dev, int code)
{
if (test_bit(EV_REP, dev->evbit) &&
dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] &&
dev->timer.data) {
dev->repeat_key = code;
mod_timer(&dev->timer,
jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Henrik Rydberg | 64 | 87.67% | 1 | 33.33% |
Linus Torvalds (pre-git) | 8 | 10.96% | 1 | 33.33% |
Dmitry Torokhov | 1 | 1.37% | 1 | 33.33% |
Total | 73 | 100.00% | 3 | 100.00% |
static void input_stop_autorepeat(struct input_dev *dev)
{
del_timer(&dev->timer);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Henrik Rydberg | 19 | 100.00% | 1 | 100.00% |
Total | 19 | 100.00% | 1 | 100.00% |
/*
* Pass event first through all filters and then, if event has not been
* filtered out, through all open handles. This function is called with
* dev->event_lock held and interrupts disabled.
*/
static unsigned int input_to_handler(struct input_handle *handle,
struct input_value *vals, unsigned int count)
{
struct input_handler *handler = handle->handler;
struct input_value *end = vals;
struct input_value *v;
if (handler->filter) {
for (v = vals; v != vals + count; v++) {
if (handler->filter(handle, v->type, v->code, v->value))
continue;
if (end != v)
*end = *v;
end++;
}
count = end - vals;
}
if (!count)
return 0;
if (handler->events)
handler->events(handle, vals, count);
else if (handler->event)
for (v = vals; v != vals + count; v++)
handler->event(handle, v->type, v->code, v->value);
return count;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Henrik Rydberg | 106 | 59.22% | 1 | 11.11% |
Dmitry Torokhov | 28 | 15.64% | 3 | 33.33% |
Vojtech Pavlik | 19 | 10.61% | 2 | 22.22% |
Linus Torvalds (pre-git) | 13 | 7.26% | 1 | 11.11% |
Anshul Garg | 11 | 6.15% | 1 | 11.11% |
Matt Mackall | 2 | 1.12% | 1 | 11.11% |
Total | 179 | 100.00% | 9 | 100.00% |
/*
* Pass values first through all filters and then, if event has not been
* filtered out, through all open handles. This function is called with
* dev->event_lock held and interrupts disabled.
*/
static void input_pass_values(struct input_dev *dev,
struct input_value *vals, unsigned int count)
{
struct input_handle *handle;
struct input_value *v;
if (!count)
return;
rcu_read_lock();
handle = rcu_dereference(dev->grab);
if (handle) {
count = input_to_handler(handle, vals, count);
} else {
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
if (handle->open) {
count = input_to_handler(handle, vals, count);
if (!count)
break;
}
}
rcu_read_unlock();
/* trigger auto repeat for key events */
if (test_bit(EV_REP, dev->evbit) && test_bit(EV_KEY, dev->evbit)) {
for (v = vals; v != vals + count; v++) {
if (v->type == EV_KEY && v->value != 2) {
if (v->value)
input_start_autorepeat(dev, v->code);
else
input_stop_autorepeat(dev);
}
}
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Henrik Rydberg | 106 | 58.56% | 2 | 18.18% |
Dmitry Torokhov | 33 | 18.23% | 3 | 27.27% |
Anshul Garg | 30 | 16.57% | 2 | 18.18% |
Linus Torvalds (pre-git) | 6 | 3.31% | 1 | 9.09% |
Vojtech Pavlik | 5 | 2.76% | 2 | 18.18% |
Matt Mackall | 1 | 0.55% | 1 | 9.09% |
Total | 181 | 100.00% | 11 | 100.00% |
static void input_pass_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
struct input_value vals[] = { { type, code, value } };
input_pass_values(dev, vals, ARRAY_SIZE(vals));
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Henrik Rydberg | 37 | 75.51% | 2 | 33.33% |
Dmitry Torokhov | 9 | 18.37% | 3 | 50.00% |
Vojtech Pavlik | 3 | 6.12% | 1 | 16.67% |
Total | 49 | 100.00% | 6 | 100.00% |
/*
* Generate software autorepeat event. Note that we take
* dev->event_lock here to avoid racing with input_event
* which may cause keys get "stuck".
*/
static void input_repeat_key(unsigned long data)
{
struct input_dev *dev = (void *) data;
unsigned long flags;
spin_lock_irqsave(&dev->event_lock, flags);
if (test_bit(dev->repeat_key, dev->key) &&
is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {
struct input_value vals[] = {
{ EV_KEY, dev->repeat_key, 2 },
input_value_sync
};
input_pass_values(dev, vals, ARRAY_SIZE(vals));
if (dev->rep[REP_PERIOD])
mod_timer(&dev->timer, jiffies +
msecs_to_jiffies(dev->rep[REP_PERIOD]));
}
spin_unlock_irqrestore(&dev->event_lock, flags);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 92 | 69.17% | 1 | 25.00% |
Henrik Rydberg | 20 | 15.04% | 1 | 25.00% |
Linus Torvalds (pre-git) | 17 | 12.78% | 1 | 25.00% |
Vojtech Pavlik | 4 | 3.01% | 1 | 25.00% |
Total | 133 | 100.00% | 4 | 100.00% |
#define INPUT_IGNORE_EVENT 0
#define INPUT_PASS_TO_HANDLERS 1
#define INPUT_PASS_TO_DEVICE 2
#define INPUT_SLOT 4
#define INPUT_FLUSH 8
#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)
static int input_handle_abs_event(struct input_dev *dev,
unsigned int code, int *pval)
{
struct input_mt *mt = dev->mt;
bool is_mt_event;
int *pold;
if (code == ABS_MT_SLOT) {
/*
* "Stage" the event; we'll flush it later, when we
* get actual touch data.
*/
if (mt && *pval >= 0 && *pval < mt->num_slots)
mt->slot = *pval;
return INPUT_IGNORE_EVENT;
}
is_mt_event = input_is_mt_value(code);
if (!is_mt_event) {
pold = &dev->absinfo[code].value;
} else if (mt) {
pold = &mt->slots[mt->slot].abs[code - ABS_MT_FIRST];
} else {
/*
* Bypass filtering for multi-touch events when
* not employing slots.
*/
pold = NULL;
}
if (pold) {
*pval = input_defuzz_abs_event(*pval, *pold,
dev->absinfo[code].fuzz);
if (*pold == *pval)
return INPUT_IGNORE_EVENT;
*pold = *pval;
}
/* Flush pending "slot" event */
if (is_mt_event && mt && mt->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
input_abs_set_val(dev, ABS_MT_SLOT, mt->slot);
return INPUT_PASS_TO_HANDLERS | INPUT_SLOT;
}
return INPUT_PASS_TO_HANDLERS;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Henrik Rydberg | 197 | 92.49% | 4 | 57.14% |
Daniel Mack | 14 | 6.57% | 2 | 28.57% |
Dmitry Torokhov | 2 | 0.94% | 1 | 14.29% |
Total | 213 | 100.00% | 7 | 100.00% |
static int input_get_disposition(struct input_dev *dev,
unsigned int type, unsigned int code, int *pval)
{
int disposition = INPUT_IGNORE_EVENT;
int value = *pval;
switch (type) {
case EV_SYN:
switch (code) {
case SYN_CONFIG:
disposition = INPUT_PASS_TO_ALL;
break;
case SYN_REPORT:
disposition = INPUT_PASS_TO_HANDLERS | INPUT_FLUSH;
break;
case SYN_MT_REPORT:
disposition = INPUT_PASS_TO_HANDLERS;
break;
}
break;
case EV_KEY:
if (is_event_supported(code, dev->keybit, KEY_MAX)) {
/* auto-repeat bypasses state updates */
if (value == 2) {
disposition = INPUT_PASS_TO_HANDLERS;
break;
}
if (!!test_bit(code, dev->key) != !!value) {
__change_bit(code, dev->key);
disposition = INPUT_PASS_TO_HANDLERS;
}
}
break;
case EV_SW:
if (is_event_supported(code, dev->swbit, SW_MAX) &&
!!test_bit(code, dev->sw) != !!value) {
__change_bit(code, dev->sw);
disposition = INPUT_PASS_TO_HANDLERS;
}
break;
case EV_ABS:
if (is_event_supported(code, dev->absbit, ABS_MAX))
disposition = input_handle_abs_event(dev, code, &value);
break;
case EV_REL:
if (is_event_supported(code, dev->relbit, REL_MAX) && value)
disposition = INPUT_PASS_TO_HANDLERS;
break;
case EV_MSC:
if (is_event_supported(code, dev->mscbit, MSC_MAX))
disposition = INPUT_PASS_TO_ALL;
break;
case EV_LED:
if (is_event_supported(code, dev->ledbit, LED_MAX) &&
!!test_bit(code, dev->led) != !!value) {
__change_bit(code, dev->led);
disposition = INPUT_PASS_TO_ALL;
}
break;
case EV_SND:
if (is_event_supported(code, dev->sndbit, SND_MAX)) {
if (!!test_bit(code, dev->snd) != !!value)
__change_bit(code, dev->snd);
disposition = INPUT_PASS_TO_ALL;
}
break;
case EV_REP:
if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) {
dev->rep[code] = value;
disposition = INPUT_PASS_TO_ALL;
}
break;
case EV_FF:
if (value >= 0)
disposition = INPUT_PASS_TO_ALL;
break;
case EV_PWR:
disposition = INPUT_PASS_TO_ALL;
break;
}
*pval = value;
return disposition;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 175 | 41.18% | 3 | 23.08% |
Henrik Rydberg | 116 | 27.29% | 5 | 38.46% |
Linus Torvalds (pre-git) | 94 | 22.12% | 2 | 15.38% |
Richard Purdie | 25 | 5.88% | 1 | 7.69% |
Linus Torvalds | 12 | 2.82% | 1 | 7.69% |
Vojtech Pavlik | 3 | 0.71% | 1 | 7.69% |
Total | 425 | 100.00% | 13 | 100.00% |
static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
int disposition = input_get_disposition(dev, type, code, &value);
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
add_input_randomness(type, code, value);
if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
dev->event(dev, type, code, value);
if (!dev->vals)
return;
if (disposition & INPUT_PASS_TO_HANDLERS) {
struct input_value *v;
if (disposition & INPUT_SLOT) {
v = &dev->vals[dev->num_vals++];
v->type = EV_ABS;
v->code = ABS_MT_SLOT;
v->value = dev->mt->slot;
}
v = &dev->vals[dev->num_vals++];
v->type = type;
v->code = code;
v->value = value;
}
if (disposition & INPUT_FLUSH) {
if (dev->num_vals >= 2)
input_pass_values(dev, dev->vals, dev->num_vals);
dev->num_vals = 0;
} else if (dev->num_vals >= dev->max_vals - 2) {
dev->vals[dev->num_vals++] = input_value_sync;
input_pass_values(dev, dev->vals, dev->num_vals);
dev->num_vals = 0;
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Henrik Rydberg | 186 | 72.37% | 1 | 7.69% |
Dmitry Torokhov | 36 | 14.01% | 5 | 38.46% |
Linus Torvalds (pre-git) | 14 | 5.45% | 1 | 7.69% |
Zephaniah E. Hull | 11 | 4.28% | 1 | 7.69% |
Vojtech Pavlik | 4 | 1.56% | 2 | 15.38% |
Patrick Mochel | 3 | 1.17% | 1 | 7.69% |
Richard Purdie | 2 | 0.78% | 1 | 7.69% |
Linus Torvalds | 1 | 0.39% | 1 | 7.69% |
Total | 257 | 100.00% | 13 | 100.00% |
/**
* input_event() - report new input event
* @dev: 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 to report input events. See also input_inject_event().
*
* NOTE: input_event() may be safely used right after input device was
* allocated with input_allocate_device(), even before it is registered
* with input_register_device(), but the event will not reach any of the
* input handlers. Such early invocation of input_event() may be used
* to 'seed' initial state of a switch or initial position of absolute
* axis, etc.
*/
void input_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
unsigned long flags;
if (is_event_supported(type, dev->evbit, EV_MAX)) {
spin_lock_irqsave(&dev->event_lock, flags);
input_handle_event(dev, type, code, value);
spin_unlock_irqrestore(&dev->event_lock, flags);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 57 | 80.28% | 1 | 33.33% |
Linus Torvalds (pre-git) | 14 | 19.72% | 2 | 66.67% |
Total | 71 | 100.00% | 3 | 100.00% |
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)
{
struct input_dev *dev = handle->dev;
struct input_handle *grab;
unsigned long flags;
if (is_event_supported(type, dev->evbit, EV_MAX)) {
spin_lock_irqsave(&dev->event_lock, flags);
rcu_read_lock();
grab = rcu_dereference(dev->grab);
if (!grab || grab == handle)
input_handle_event(dev, type, code, value);
rcu_read_unlock();
spin_unlock_irqrestore(&dev->event_lock, flags);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 109 | 100.00% | 3 | 100.00% |
Total | 109 | 100.00% | 3 | 100.00% |
EXPORT_SYMBOL(input_inject_event);
/**
* input_alloc_absinfo - allocates array of input_absinfo structs
* @dev: the input device emitting absolute events
*
* If the absinfo struct the caller asked for is already allocated, this
* functions will not do anything.
*/
void input_alloc_absinfo(struct input_dev *dev)
{
if (!dev->absinfo)
dev->absinfo = kcalloc(ABS_CNT, sizeof(struct input_absinfo),
GFP_KERNEL);
WARN(!dev->absinfo, "%s(): kcalloc() failed?\n", __func__);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Daniel Mack | 46 | 100.00% | 1 | 100.00% |
Total | 46 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL(input_alloc_absinfo);
void input_set_abs_params(struct input_dev *dev, unsigned int axis,
int min, int max, int fuzz, int flat)
{
struct input_absinfo *absinfo;
input_alloc_absinfo(dev);
if (!dev->absinfo)
return;
absinfo = &dev->absinfo[axis];
absinfo->minimum = min;
absinfo->maximum = max;
absinfo->fuzz = fuzz;
absinfo->flat = flat;
__set_bit(EV_ABS, dev->evbit);
__set_bit(axis, dev->absbit);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Daniel Mack | 85 | 88.54% | 1 | 50.00% |
Dmitry Torokhov | 11 | 11.46% | 1 | 50.00% |
Total | 96 | 100.00% | 2 | 100.00% |
EXPORT_SYMBOL(input_set_abs_params);
/**
* input_grab_device - grabs device for exclusive use
* @handle: input handle that wants to own the device
*
* When a device is grabbed by an input handle all events generated by
* the device are delivered only to this handle. Also events injected
* by other input handles are ignored while device is grabbed.
*/
int input_grab_device(struct input_handle *handle)
{
struct input_dev *dev = handle->dev;
int retval;
retval = mutex_lock_interruptible(&dev->mutex);
if (retval)
return retval;
if (dev->grab) {
retval = -EBUSY;
goto out;
}
rcu_assign_pointer(dev->grab, handle);
out:
mutex_unlock(&dev->mutex);
return retval;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 46 | 59.74% | 2 | 33.33% |
Zephaniah E. Hull | 16 | 20.78% | 1 | 16.67% |
Linus Torvalds (pre-git) | 11 | 14.29% | 1 | 16.67% |
Vojtech Pavlik | 4 | 5.19% | 2 | 33.33% |
Total | 77 | 100.00% | 6 | 100.00% |
EXPORT_SYMBOL(input_grab_device);
static void __input_release_device(struct input_handle *handle)
{
struct input_dev *dev = handle->dev;
struct input_handle *grabber;
grabber = rcu_dereference_protected(dev->grab,
lockdep_is_held(&dev->mutex));
if (grabber == handle) {
rcu_assign_pointer(dev->grab, NULL);
/* Make sure input_pass_event() notices that grab is gone */
synchronize_rcu();
list_for_each_entry(handle, &dev->h_list, d_node)
if (handle->open && handle->handler->start)
handle->handler->start(handle);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 63 | 68.48% | 4 | 66.67% |
Zephaniah E. Hull | 21 | 22.83% | 1 | 16.67% |
Andrew Morton | 8 | 8.70% | 1 | 16.67% |
Total | 92 | 100.00% | 6 | 100.00% |
/**
* input_release_device - release previously grabbed device
* @handle: input handle that owns the device
*
* Releases previously grabbed device so that other input handles can
* start receiving input events. Upon release all handlers attached
* to the device have their start() method called so they have a change
* to synchronize device state with the rest of the system.
*/
void input_release_device(struct input_handle *handle)
{
struct input_dev *dev = handle->dev;
mutex_lock(&dev->mutex);
__input_release_device(handle);
mutex_unlock(&dev->mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 39 | 97.50% | 1 | 50.00% |
Zephaniah E. Hull | 1 | 2.50% | 1 | 50.00% |
Total | 40 | 100.00% | 2 | 100.00% |
EXPORT_SYMBOL(input_release_device);
/**
* input_open_device - open input device
* @handle: handle through which device is being accessed
*
* This function should be called by input handlers when they
* want to start receive events from given input device.
*/
int input_open_device(struct input_handle *handle)
{
struct input_dev *dev = handle->dev;
int retval;
retval = mutex_lock_interruptible(&dev->mutex);
if (retval)
return retval;
if (dev->going_away) {
retval = -ENODEV;
goto out;
}
handle->open++;
if (!dev->users++ && dev->open)
retval = dev->open(dev);
if (retval) {
dev->users--;
if (!--handle->open) {
/*
* Make sure we are not delivering any more events
* through this handle
*/
synchronize_rcu();
}
}
out:
mutex_unlock(&dev->mutex);
return retval;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 83 | 69.75% | 3 | 50.00% |
Linus Torvalds (pre-git) | 32 | 26.89% | 2 | 33.33% |
Jes Sorensen | 4 | 3.36% | 1 | 16.67% |
Total | 119 | 100.00% | 6 | 100.00% |
EXPORT_SYMBOL(input_open_device);
int input_flush_device(struct input_handle *handle, struct file *file)
{
struct input_dev *dev = handle->dev;
int retval;
retval = mutex_lock_interruptible(&dev->mutex);
if (retval)
return retval;
if (dev->flush)
retval = dev->flush(dev, file);
mutex_unlock(&dev->mutex);
return retval;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 40 | 55.56% | 1 | 50.00% |
Vojtech Pavlik | 32 | 44.44% | 1 | 50.00% |
Total | 72 | 100.00% | 2 | 100.00% |
EXPORT_SYMBOL(input_flush_device);
/**
* input_close_device - close input device
* @handle: handle through which device is being accessed
*
* This function should be called by input handlers when they
* want to stop receive events from given input device.
*/
void input_close_device(struct input_handle *handle)
{
struct input_dev *dev = handle->dev;
mutex_lock(&dev->mutex);
__input_release_device(handle);
if (!--dev->users && dev->close)
dev->close(dev);
if (!--handle->open) {
/*
* synchronize_rcu() makes sure that input_pass_event()
* completed and that no more input events are delivered
* through this handle
*/
synchronize_rcu();
}
mutex_unlock(&dev->mutex);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 41 | 56.16% | 3 | 50.00% |
Linus Torvalds (pre-git) | 28 | 38.36% | 2 | 33.33% |
Jes Sorensen | 4 | 5.48% | 1 | 16.67% |
Total | 73 | 100.00% | 6 | 100.00% |
EXPORT_SYMBOL(input_close_device);
/*
* Simulate keyup events for all keys that are marked as pressed.
* The function must be called with dev->event_lock held.
*/
static void input_dev_release_keys(struct input_dev *dev)
{
bool need_sync = false;
int code;
if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) {
for_each_set_bit(code, dev->key, KEY_CNT) {
input_pass_event(dev, EV_KEY, code, 0);
need_sync = true;
}
if (need_sync)
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
memset(dev->key, 0, sizeof(dev->key));
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dmitry Torokhov | 68 | 75.56% | 2 | 50.00% |
Anshul Garg | 20 | 22.22% | 1 | 25.00% |
Oliver Neukum | 2 | 2.22% | 1 | 25.00% |
Total | 90 | 100.00% | 4 | 100.00% |
/*
* Prepare device for unregistering
*/
static void input_disconnect_device(struct input_dev *dev)
{
struct input_handle *handle;
/*
* Mark device as going away. Note that we take dev->mutex here
* not to protect access to dev->going_away but rather to ensure
* that there are no threads in the middle of input_open_device()
*/
mutex_lock(&dev->mutex);
dev->going_away = true;
mutex_unlock(&dev->mutex);
spin_lock_irq(&dev->event_lock);
/*
* Simulate keyup events for all pressed keys so that handlers
* are not left with "stuck" keys. The driver may continue
* generate events even after we done here but they will not
* reach any handlers.
*/
input_dev_release_keys(dev);
list_for_each_entry(handle, &dev->h_list, d_node)
handle->open = 0;
spin_unlock_irq(&dev->event_lock);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Oliver Neukum | 52 | 69.33% | 1 | 50.00% |
Dmitry Torokhov | 23 | 30.67% | 1 | 50.00% |
Total | 75 | 100.00% | 2 | 100.00% |
/**
* input_scancode_to_scalar() - converts scancode in &struct input_keymap_entry
* @ke: keymap entry containing scancode to be converted.
* @scancode: pointer to the location where converted scancode should
* be stored.
*
* This function is used to convert scancode stored in &struct keymap_entry
* into scalar form understood by legacy keymap handling methods. These
* methods expect scancodes to be represented as 'unsigned int'.
*/
int input_scancode_to_scalar(const struct input_keymap_entry *ke,
unsigned int *scancode)
{
switch (ke->len) {
case 1:
*scancode = *((u8 *)ke->scancode);
break;
case 2:
*scancode = *((u16 *)ke->scancode);
break;
case 4:
*scancode = *((u32 *)ke->scancode);
break;
default:
return -EINVAL;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Mauro Carvalho Chehab | 86 | 100.00% | 1 | 100.00% |
Total | 86 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL(input_scancode_to_scalar);
/*
* Those routines handle the default case where no [gs]etkeycode() is
* defined. In this case, an array indexed by the scancode is used.
*/
static unsigned int input_fetch_keycode(struct input_dev *dev,
unsigned int index)
{
switch (dev->keycodesize)