Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/dtor/input

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: do not pass injected events back to the originating handler
  Input: pcf8574_keypad - fix error handling in pcf8574_kp_probe
  Input: acecad - fix a memory leak in usb_acecad_probe error path
  Input: atkbd - add 'terminal' parameter for IBM Terminal keyboards
  Input: i8042 - add Sony VAIOs to MUX blacklist
  kgdboc: reset input devices (keyboards) when exiting debugger
  Input: export input_reset_device() for use in KGDB
  Input: adp5588-keys - unify common header defines
  • Loading branch information
torvalds committed Nov 12, 2010
2 parents 522a991 + 5fdbe44 commit 7803c05
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 92 deletions.
87 changes: 61 additions & 26 deletions drivers/input/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz)
* dev->event_lock held and interrupts disabled.
*/
static void input_pass_event(struct input_dev *dev,
struct input_handler *src_handler,
unsigned int type, unsigned int code, int value)
{
struct input_handler *handler;
Expand All @@ -92,6 +93,15 @@ static void input_pass_event(struct input_dev *dev,
continue;

handler = handle->handler;

/*
* If this is the handler that injected this
* particular event we want to skip it to avoid
* filters firing again and again.
*/
if (handler == src_handler)
continue;

if (!handler->filter) {
if (filtered)
break;
Expand Down Expand Up @@ -121,7 +131,7 @@ static void input_repeat_key(unsigned long data)
if (test_bit(dev->repeat_key, dev->key) &&
is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) {

input_pass_event(dev, EV_KEY, dev->repeat_key, 2);
input_pass_event(dev, NULL, EV_KEY, dev->repeat_key, 2);

if (dev->sync) {
/*
Expand All @@ -130,7 +140,7 @@ static void input_repeat_key(unsigned long data)
* Otherwise assume that the driver will send
* SYN_REPORT once it's done.
*/
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
}

if (dev->rep[REP_PERIOD])
Expand Down Expand Up @@ -163,6 +173,7 @@ static void input_stop_autorepeat(struct input_dev *dev)
#define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE)

static int input_handle_abs_event(struct input_dev *dev,
struct input_handler *src_handler,
unsigned int code, int *pval)
{
bool is_mt_event;
Expand Down Expand Up @@ -206,13 +217,15 @@ static int input_handle_abs_event(struct input_dev *dev,
/* Flush pending "slot" event */
if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) {
input_abs_set_val(dev, ABS_MT_SLOT, dev->slot);
input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot);
input_pass_event(dev, src_handler,
EV_ABS, ABS_MT_SLOT, dev->slot);
}

return INPUT_PASS_TO_HANDLERS;
}

static void input_handle_event(struct input_dev *dev,
struct input_handler *src_handler,
unsigned int type, unsigned int code, int value)
{
int disposition = INPUT_IGNORE_EVENT;
Expand Down Expand Up @@ -265,7 +278,8 @@ static void input_handle_event(struct input_dev *dev,

case EV_ABS:
if (is_event_supported(code, dev->absbit, ABS_MAX))
disposition = input_handle_abs_event(dev, code, &value);
disposition = input_handle_abs_event(dev, src_handler,
code, &value);

break;

Expand Down Expand Up @@ -323,7 +337,7 @@ static void input_handle_event(struct input_dev *dev,
dev->event(dev, type, code, value);

if (disposition & INPUT_PASS_TO_HANDLERS)
input_pass_event(dev, type, code, value);
input_pass_event(dev, src_handler, type, code, value);
}

/**
Expand Down Expand Up @@ -352,7 +366,7 @@ void input_event(struct input_dev *dev,

spin_lock_irqsave(&dev->event_lock, flags);
add_input_randomness(type, code, value);
input_handle_event(dev, type, code, value);
input_handle_event(dev, NULL, type, code, value);
spin_unlock_irqrestore(&dev->event_lock, flags);
}
}
Expand Down Expand Up @@ -382,7 +396,8 @@ void input_inject_event(struct input_handle *handle,
rcu_read_lock();
grab = rcu_dereference(dev->grab);
if (!grab || grab == handle)
input_handle_event(dev, type, code, value);
input_handle_event(dev, handle->handler,
type, code, value);
rcu_read_unlock();

spin_unlock_irqrestore(&dev->event_lock, flags);
Expand Down Expand Up @@ -595,10 +610,10 @@ static void input_dev_release_keys(struct input_dev *dev)
for (code = 0; code <= KEY_MAX; code++) {
if (is_event_supported(code, dev->keybit, KEY_MAX) &&
__test_and_clear_bit(code, dev->key)) {
input_pass_event(dev, EV_KEY, code, 0);
input_pass_event(dev, NULL, EV_KEY, code, 0);
}
}
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
}
}

Expand Down Expand Up @@ -873,9 +888,9 @@ int input_set_keycode(struct input_dev *dev,
!is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
__test_and_clear_bit(old_keycode, dev->key)) {

input_pass_event(dev, EV_KEY, old_keycode, 0);
input_pass_event(dev, NULL, EV_KEY, old_keycode, 0);
if (dev->sync)
input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1);
}

out:
Expand Down Expand Up @@ -1565,8 +1580,7 @@ static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env)
} \
} while (0)

#ifdef CONFIG_PM
static void input_dev_reset(struct input_dev *dev, bool activate)
static void input_dev_toggle(struct input_dev *dev, bool activate)
{
if (!dev->event)
return;
Expand All @@ -1580,12 +1594,44 @@ static void input_dev_reset(struct input_dev *dev, bool activate)
}
}

/**
* input_reset_device() - reset/restore the state of input device
* @dev: input device whose state needs to be reset
*
* This function tries to reset the state of an opened input device and
* bring internal state and state if the hardware in sync with each other.
* We mark all keys as released, restore LED state, repeat rate, etc.
*/
void input_reset_device(struct input_dev *dev)
{
mutex_lock(&dev->mutex);

if (dev->users) {
input_dev_toggle(dev, true);

/*
* Keys that have been pressed at suspend time are unlikely
* to be still pressed when we resume.
*/
spin_lock_irq(&dev->event_lock);
input_dev_release_keys(dev);
spin_unlock_irq(&dev->event_lock);
}

mutex_unlock(&dev->mutex);
}
EXPORT_SYMBOL(input_reset_device);

#ifdef CONFIG_PM
static int input_dev_suspend(struct device *dev)
{
struct input_dev *input_dev = to_input_dev(dev);

mutex_lock(&input_dev->mutex);
input_dev_reset(input_dev, false);

if (input_dev->users)
input_dev_toggle(input_dev, false);

mutex_unlock(&input_dev->mutex);

return 0;
Expand All @@ -1595,18 +1641,7 @@ static int input_dev_resume(struct device *dev)
{
struct input_dev *input_dev = to_input_dev(dev);

mutex_lock(&input_dev->mutex);
input_dev_reset(input_dev, true);

/*
* Keys that have been pressed at suspend time are unlikely
* to be still pressed when we resume.
*/
spin_lock_irq(&input_dev->event_lock);
input_dev_release_keys(input_dev);
spin_unlock_irq(&input_dev->event_lock);

mutex_unlock(&input_dev->mutex);
input_reset_device(input_dev);

return 0;
}
Expand Down
74 changes: 25 additions & 49 deletions drivers/input/keyboard/adp5588-keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* I2C QWERTY Keypad and IO Expander
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
* Copyright (C) 2008-2009 Analog Devices Inc.
* Copyright (C) 2008-2010 Analog Devices Inc.
* Licensed under the GPL-2 or later.
*/

Expand All @@ -24,29 +24,6 @@

#include <linux/i2c/adp5588.h>

/* Configuration Register1 */
#define AUTO_INC (1 << 7)
#define GPIEM_CFG (1 << 6)
#define OVR_FLOW_M (1 << 5)
#define INT_CFG (1 << 4)
#define OVR_FLOW_IEN (1 << 3)
#define K_LCK_IM (1 << 2)
#define GPI_IEN (1 << 1)
#define KE_IEN (1 << 0)

/* Interrupt Status Register */
#define CMP2_INT (1 << 5)
#define CMP1_INT (1 << 4)
#define OVR_FLOW_INT (1 << 3)
#define K_LCK_INT (1 << 2)
#define GPI_INT (1 << 1)
#define KE_INT (1 << 0)

/* Key Lock and Event Counter Register */
#define K_LCK_EN (1 << 6)
#define LCK21 0x30
#define KEC 0xF

/* Key Event Register xy */
#define KEY_EV_PRESSED (1 << 7)
#define KEY_EV_MASK (0x7F)
Expand All @@ -55,10 +32,6 @@

#define KEYP_MAX_EVENT 10

#define MAXGPIO 18
#define ADP_BANK(offs) ((offs) >> 3)
#define ADP_BIT(offs) (1u << ((offs) & 0x7))

/*
* Early pre 4.0 Silicon required to delay readout by at least 25ms,
* since the Event Counter Register updated 25ms after the interrupt
Expand All @@ -75,7 +48,7 @@ struct adp5588_kpad {
const struct adp5588_gpi_map *gpimap;
unsigned short gpimapsize;
#ifdef CONFIG_GPIOLIB
unsigned char gpiomap[MAXGPIO];
unsigned char gpiomap[ADP5588_MAXGPIO];
bool export_gpio;
struct gpio_chip gc;
struct mutex gpio_lock; /* Protect cached dir, dat_out */
Expand Down Expand Up @@ -103,8 +76,8 @@ static int adp5588_write(struct i2c_client *client, u8 reg, u8 val)
static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned off)
{
struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);
unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);

return !!(adp5588_read(kpad->client, GPIO_DAT_STAT1 + bank) & bit);
}
Expand All @@ -113,8 +86,8 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip,
unsigned off, int val)
{
struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);
unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);

mutex_lock(&kpad->gpio_lock);

Expand All @@ -132,8 +105,8 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip,
static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned off)
{
struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);
unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
int ret;

mutex_lock(&kpad->gpio_lock);
Expand All @@ -150,8 +123,8 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip,
unsigned off, int val)
{
struct adp5588_kpad *kpad = container_of(chip, struct adp5588_kpad, gc);
unsigned int bank = ADP_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP_BIT(kpad->gpiomap[off]);
unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]);
unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]);
int ret;

mutex_lock(&kpad->gpio_lock);
Expand All @@ -176,7 +149,7 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip,
static int __devinit adp5588_build_gpiomap(struct adp5588_kpad *kpad,
const struct adp5588_kpad_platform_data *pdata)
{
bool pin_used[MAXGPIO];
bool pin_used[ADP5588_MAXGPIO];
int n_unused = 0;
int i;

Expand All @@ -191,7 +164,7 @@ static int __devinit adp5588_build_gpiomap(struct adp5588_kpad *kpad,
for (i = 0; i < kpad->gpimapsize; i++)
pin_used[kpad->gpimap[i].pin - GPI_PIN_BASE] = true;

for (i = 0; i < MAXGPIO; i++)
for (i = 0; i < ADP5588_MAXGPIO; i++)
if (!pin_used[i])
kpad->gpiomap[n_unused++] = i;

Expand Down Expand Up @@ -234,7 +207,7 @@ static int __devinit adp5588_gpio_add(struct adp5588_kpad *kpad)
return error;
}

for (i = 0; i <= ADP_BANK(MAXGPIO); i++) {
for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
kpad->dat_out[i] = adp5588_read(kpad->client,
GPIO_DAT_OUT1 + i);
kpad->dir[i] = adp5588_read(kpad->client, GPIO_DIR1 + i);
Expand Down Expand Up @@ -318,11 +291,11 @@ static void adp5588_work(struct work_struct *work)

status = adp5588_read(client, INT_STAT);

if (status & OVR_FLOW_INT) /* Unlikely and should never happen */
if (status & ADP5588_OVR_FLOW_INT) /* Unlikely and should never happen */
dev_err(&client->dev, "Event Overflow Error\n");

if (status & KE_INT) {
ev_cnt = adp5588_read(client, KEY_LCK_EC_STAT) & KEC;
if (status & ADP5588_KE_INT) {
ev_cnt = adp5588_read(client, KEY_LCK_EC_STAT) & ADP5588_KEC;
if (ev_cnt) {
adp5588_report_events(kpad, ev_cnt);
input_sync(kpad->input);
Expand Down Expand Up @@ -360,7 +333,7 @@ static int __devinit adp5588_setup(struct i2c_client *client)
if (pdata->en_keylock) {
ret |= adp5588_write(client, UNLOCK1, pdata->unlock_key1);
ret |= adp5588_write(client, UNLOCK2, pdata->unlock_key2);
ret |= adp5588_write(client, KEY_LCK_EC_STAT, K_LCK_EN);
ret |= adp5588_write(client, KEY_LCK_EC_STAT, ADP5588_K_LCK_EN);
}

for (i = 0; i < KEYP_MAX_EVENT; i++)
Expand All @@ -384,19 +357,22 @@ static int __devinit adp5588_setup(struct i2c_client *client)
}

if (gpio_data) {
for (i = 0; i <= ADP_BANK(MAXGPIO); i++) {
for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
int pull_mask = gpio_data->pullup_dis_mask;

ret |= adp5588_write(client, GPIO_PULL1 + i,
(pull_mask >> (8 * i)) & 0xFF);
}
}

ret |= adp5588_write(client, INT_STAT, CMP2_INT | CMP1_INT |
OVR_FLOW_INT | K_LCK_INT |
GPI_INT | KE_INT); /* Status is W1C */
ret |= adp5588_write(client, INT_STAT,
ADP5588_CMP2_INT | ADP5588_CMP1_INT |
ADP5588_OVR_FLOW_INT | ADP5588_K_LCK_INT |
ADP5588_GPI_INT | ADP5588_KE_INT); /* Status is W1C */

ret |= adp5588_write(client, CFG, INT_CFG | OVR_FLOW_IEN | KE_IEN);
ret |= adp5588_write(client, CFG, ADP5588_INT_CFG |
ADP5588_OVR_FLOW_IEN |
ADP5588_KE_IEN);

if (ret < 0) {
dev_err(&client->dev, "Write Error\n");
Expand Down
Loading

0 comments on commit 7803c05

Please sign in to comment.