Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (51 commits)
  Input: appletouch - give up maintainership
  Input: dm355evm_kbd - switch to using sparse keymap library
  Input: wistron_btns - switch to using sparse keymap library
  Input: add generic support for sparse keymaps
  Input: fix memory leak in force feedback core
  Input: wistron - remove identification strings from DMI table
  Input: psmouse - remove identification strings from DMI tables
  Input: atkbd - remove identification strings from DMI table
  Input: i8042 - remove identification strings from DMI tables
  DMI: allow omitting ident strings in DMI tables
  Input: psmouse - do not carry DMI data around
  Input: matrix-keypad - switch to using dev_pm_ops
  Input: keyboard - fix lack of locking when traversing handler->h_list
  Input: gpio_keys - scan gpio state at probe and resume time
  Input: keyboard - add locking around event handling
  Input: usbtouchscreen - add support for ET&T TC5UH touchscreen controller
  Input: xpad - add two new Xbox 360 devices
  Input: polled device - do not start polling if interval is zero
  Input: polled device - schedule first poll immediately
  Input: add S3C24XX touchscreen driver
  ...
This commit is contained in:
Linus Torvalds
2009-12-09 19:52:01 -08:00
63 changed files with 3095 additions and 1152 deletions
+13
View File
@@ -293,10 +293,23 @@ X!Idrivers/video/console/fonts.c
<chapter id="input_subsystem">
<title>Input Subsystem</title>
<sect1><title>Input core</title>
!Iinclude/linux/input.h
!Edrivers/input/input.c
!Edrivers/input/ff-core.c
!Edrivers/input/ff-memless.c
</sect1>
<sect1><title>Polled input devices</title>
!Iinclude/linux/input-polldev.h
!Edrivers/input/input-polldev.c
</sect1>
<sect1><title>Matrix keyboars/keypads</title>
!Iinclude/linux/input/matrix_keypad.h
</sect1>
<sect1><title>Sparse keymap support</title>
!Iinclude/linux/input/sparse-keymap.h
!Edrivers/input/sparse-keymap.c
</sect1>
</chapter>
<chapter id="spi">
-7
View File
@@ -486,13 +486,6 @@ S: Maintained
F: drivers/net/appletalk/
F: net/appletalk/
APPLETOUCH TOUCHPAD DRIVER
M: Johannes Berg <johannes@sipsolutions.net>
L: linux-input@vger.kernel.org
S: Maintained
F: Documentation/input/appletouch.txt
F: drivers/input/mouse/appletouch.c
ARC FRAMEBUFFER DRIVER
M: Jaya Kumar <jayalk@intworks.biz>
S: Maintained
+51
View File
@@ -865,6 +865,57 @@ static void __init at91_add_device_rtc(void) {}
#endif
/* --------------------------------------------------------------------
* Touchscreen
* -------------------------------------------------------------------- */
#if defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) || defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC_MODULE)
static u64 tsadcc_dmamask = DMA_BIT_MASK(32);
static struct at91_tsadcc_data tsadcc_data;
static struct resource tsadcc_resources[] = {
[0] = {
.start = AT91SAM9G45_BASE_TSC,
.end = AT91SAM9G45_BASE_TSC + SZ_16K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = AT91SAM9G45_ID_TSC,
.end = AT91SAM9G45_ID_TSC,
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device at91sam9g45_tsadcc_device = {
.name = "atmel_tsadcc",
.id = -1,
.dev = {
.dma_mask = &tsadcc_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &tsadcc_data,
},
.resource = tsadcc_resources,
.num_resources = ARRAY_SIZE(tsadcc_resources),
};
void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data)
{
if (!data)
return;
at91_set_gpio_input(AT91_PIN_PD20, 0); /* AD0_XR */
at91_set_gpio_input(AT91_PIN_PD21, 0); /* AD1_XL */
at91_set_gpio_input(AT91_PIN_PD22, 0); /* AD2_YT */
at91_set_gpio_input(AT91_PIN_PD23, 0); /* AD3_TB */
tsadcc_data = *data;
platform_device_register(&at91sam9g45_tsadcc_device);
}
#else
void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
#endif
/* --------------------------------------------------------------------
* RTT
* -------------------------------------------------------------------- */
+8 -2
View File
@@ -622,6 +622,7 @@ static void __init at91_add_device_tc(void) { }
#if defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) || defined(CONFIG_TOUCHSCREEN_ATMEL_TSADCC_MODULE)
static u64 tsadcc_dmamask = DMA_BIT_MASK(32);
static struct at91_tsadcc_data tsadcc_data;
static struct resource tsadcc_resources[] = {
[0] = {
@@ -642,22 +643,27 @@ static struct platform_device at91sam9rl_tsadcc_device = {
.dev = {
.dma_mask = &tsadcc_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
.platform_data = &tsadcc_data,
},
.resource = tsadcc_resources,
.num_resources = ARRAY_SIZE(tsadcc_resources),
};
void __init at91_add_device_tsadcc(void)
void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data)
{
if (!data)
return;
at91_set_A_periph(AT91_PIN_PA17, 0); /* AD0_XR */
at91_set_A_periph(AT91_PIN_PA18, 0); /* AD1_XL */
at91_set_A_periph(AT91_PIN_PA19, 0); /* AD2_YT */
at91_set_A_periph(AT91_PIN_PA20, 0); /* AD3_TB */
tsadcc_data = *data;
platform_device_register(&at91sam9rl_tsadcc_device);
}
#else
void __init at91_add_device_tsadcc(void) {}
void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
#endif
+12
View File
@@ -228,6 +228,16 @@ static struct atmel_lcdfb_info __initdata ek_lcdc_data;
#endif
/*
* Touchscreen
*/
static struct at91_tsadcc_data ek_tsadcc_data = {
.adc_clock = 300000,
.pendet_debounce = 0x0d,
.ts_sample_hold_time = 0x0a,
};
/*
* GPIO Buttons
*/
@@ -379,6 +389,8 @@ static void __init ek_board_init(void)
at91_add_device_i2c(0, NULL, 0);
/* LCD Controller */
at91_add_device_lcdc(&ek_lcdc_data);
/* Touch Screen */
at91_add_device_tsadcc(&ek_tsadcc_data);
/* Push Buttons */
ek_add_device_buttons();
/* AC97 */
+11 -1
View File
@@ -242,6 +242,16 @@ static struct gpio_led ek_leds[] = {
};
/*
* Touchscreen
*/
static struct at91_tsadcc_data ek_tsadcc_data = {
.adc_clock = 1000000,
.pendet_debounce = 0x0f,
.ts_sample_hold_time = 0x03,
};
/*
* GPIO Buttons
*/
@@ -310,7 +320,7 @@ static void __init ek_board_init(void)
/* AC97 */
at91_add_device_ac97(&ek_ac97_data);
/* Touch Screen Controller */
at91_add_device_tsadcc();
at91_add_device_tsadcc(&ek_tsadcc_data);
/* LEDs */
at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
/* Push Buttons */
+6 -1
View File
@@ -187,7 +187,12 @@ extern void __init at91_add_device_ac97(struct ac97c_platform_data *data);
extern void __init at91_add_device_isi(void);
/* Touchscreen Controller */
extern void __init at91_add_device_tsadcc(void);
struct at91_tsadcc_data {
unsigned int adc_clock;
u8 pendet_debounce;
u8 ts_sample_hold_time;
};
extern void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data);
/* CAN */
struct at91_can_data {
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2009 Texas Instruments, Inc
*
* Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef DAVINCI_KEYSCAN_H
#define DAVINCI_KEYSCAN_H
#include <linux/io.h>
enum davinci_matrix_types {
DAVINCI_KEYSCAN_MATRIX_4X4,
DAVINCI_KEYSCAN_MATRIX_5X3,
};
struct davinci_ks_platform_data {
unsigned short *keymap;
u32 keymapsize;
u8 rep:1;
u8 strobe;
u8 interval;
u8 matrix_type;
};
#endif
+113 -98
View File
@@ -46,8 +46,6 @@
extern void ctrl_alt_del(void);
#define to_handle_h(n) container_of(n, struct input_handle, h_node)
/*
* Exported functions/variables
*/
@@ -132,6 +130,7 @@ int shift_state = 0;
*/
static struct input_handler kbd_handler;
static DEFINE_SPINLOCK(kbd_event_lock);
static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */
static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
static int dead_key_next;
@@ -190,78 +189,85 @@ EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
* etc.). So this means that scancodes for the extra function keys won't
* be valid for the first event device, but will be for the second.
*/
struct getset_keycode_data {
unsigned int scancode;
unsigned int keycode;
int error;
};
static int getkeycode_helper(struct input_handle *handle, void *data)
{
struct getset_keycode_data *d = data;
d->error = input_get_keycode(handle->dev, d->scancode, &d->keycode);
return d->error == 0; /* stop as soon as we successfully get one */
}
int getkeycode(unsigned int scancode)
{
struct input_handle *handle;
int keycode;
int error = -ENODEV;
struct getset_keycode_data d = { scancode, 0, -ENODEV };
list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
error = input_get_keycode(handle->dev, scancode, &keycode);
if (!error)
return keycode;
}
input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper);
return error;
return d.error ?: d.keycode;
}
static int setkeycode_helper(struct input_handle *handle, void *data)
{
struct getset_keycode_data *d = data;
d->error = input_set_keycode(handle->dev, d->scancode, d->keycode);
return d->error == 0; /* stop as soon as we successfully set one */
}
int setkeycode(unsigned int scancode, unsigned int keycode)
{
struct input_handle *handle;
int error = -ENODEV;
struct getset_keycode_data d = { scancode, keycode, -ENODEV };
list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
error = input_set_keycode(handle->dev, scancode, keycode);
if (!error)
break;
}
input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper);
return error;
return d.error;
}
/*
* Making beeps and bells.
*/
static int kd_sound_helper(struct input_handle *handle, void *data)
{
unsigned int *hz = data;
struct input_dev *dev = handle->dev;
if (test_bit(EV_SND, dev->evbit)) {
if (test_bit(SND_TONE, dev->sndbit))
input_inject_event(handle, EV_SND, SND_TONE, *hz);
if (test_bit(SND_BELL, handle->dev->sndbit))
input_inject_event(handle, EV_SND, SND_BELL, *hz ? 1 : 0);
}
return 0;
}
static void kd_nosound(unsigned long ignored)
{
struct input_handle *handle;
static unsigned int zero;
list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit))
input_inject_event(handle, EV_SND, SND_TONE, 0);
if (test_bit(SND_BELL, handle->dev->sndbit))
input_inject_event(handle, EV_SND, SND_BELL, 0);
}
}
input_handler_for_each_handle(&kbd_handler, &zero, kd_sound_helper);
}
static DEFINE_TIMER(kd_mksound_timer, kd_nosound, 0, 0);
void kd_mksound(unsigned int hz, unsigned int ticks)
{
struct list_head *node;
del_timer_sync(&kd_mksound_timer);
del_timer(&kd_mksound_timer);
input_handler_for_each_handle(&kbd_handler, &hz, kd_sound_helper);
if (hz) {
list_for_each_prev(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
if (test_bit(EV_SND, handle->dev->evbit)) {
if (test_bit(SND_TONE, handle->dev->sndbit)) {
input_inject_event(handle, EV_SND, SND_TONE, hz);
break;
}
if (test_bit(SND_BELL, handle->dev->sndbit)) {
input_inject_event(handle, EV_SND, SND_BELL, 1);
break;
}
}
}
if (ticks)
mod_timer(&kd_mksound_timer, jiffies + ticks);
} else
kd_nosound(0);
if (hz && ticks)
mod_timer(&kd_mksound_timer, jiffies + ticks);
}
EXPORT_SYMBOL(kd_mksound);
@@ -269,27 +275,34 @@ EXPORT_SYMBOL(kd_mksound);
* Setting the keyboard rate.
*/
static int kbd_rate_helper(struct input_handle *handle, void *data)
{
struct input_dev *dev = handle->dev;
struct kbd_repeat *rep = data;
if (test_bit(EV_REP, dev->evbit)) {
if (rep[0].delay > 0)
input_inject_event(handle,
EV_REP, REP_DELAY, rep[0].delay);
if (rep[0].period > 0)
input_inject_event(handle,
EV_REP, REP_PERIOD, rep[0].period);
rep[1].delay = dev->rep[REP_DELAY];
rep[1].period = dev->rep[REP_PERIOD];
}
return 0;
}
int kbd_rate(struct kbd_repeat *rep)
{
struct list_head *node;
unsigned int d = 0;
unsigned int p = 0;
struct kbd_repeat data[2] = { *rep };
list_for_each(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
struct input_dev *dev = handle->dev;
input_handler_for_each_handle(&kbd_handler, data, kbd_rate_helper);
*rep = data[1]; /* Copy currently used settings */
if (test_bit(EV_REP, dev->evbit)) {
if (rep->delay > 0)
input_inject_event(handle, EV_REP, REP_DELAY, rep->delay);
if (rep->period > 0)
input_inject_event(handle, EV_REP, REP_PERIOD, rep->period);
d = dev->rep[REP_DELAY];
p = dev->rep[REP_PERIOD];
}
}
rep->delay = d;
rep->period = p;
return 0;
}
@@ -997,36 +1010,36 @@ static inline unsigned char getleds(void)
return leds;
}
/*
* This routine is the bottom half of the keyboard interrupt
* routine, and runs with all interrupts enabled. It does
* console changing, led setting and copy_to_cooked, which can
* take a reasonably long time.
*
* Aside from timing (which isn't really that important for
* keyboard interrupts as they happen often), using the software
* interrupt routines for this thing allows us to easily mask
* this when we don't want any of the above to happen.
* This allows for easy and efficient race-condition prevention
* for kbd_start => input_inject_event(dev, EV_LED, ...) => ...
*/
static int kbd_update_leds_helper(struct input_handle *handle, void *data)
{
unsigned char leds = *(unsigned char *)data;
if (test_bit(EV_LED, handle->dev->evbit)) {
input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
}
return 0;
}
/*
* This is the tasklet that updates LED state on all keyboards
* attached to the box. The reason we use tasklet is that we
* need to handle the scenario when keyboard handler is not
* registered yet but we already getting updates form VT to
* update led state.
*/
static void kbd_bh(unsigned long dummy)
{
struct list_head *node;
unsigned char leds = getleds();
if (leds != ledstate) {
list_for_each(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
}
input_handler_for_each_handle(&kbd_handler, &leds,
kbd_update_leds_helper);
ledstate = leds;
}
ledstate = leds;
}
DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0);
@@ -1136,7 +1149,7 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char u
static void kbd_rawcode(unsigned char data)
{
struct vc_data *vc = vc_cons[fg_console].d;
kbd = kbd_table + fg_console;
kbd = kbd_table + vc->vc_num;
if (kbd->kbdmode == VC_RAW)
put_queue(vc, data);
}
@@ -1157,7 +1170,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
tty->driver_data = vc;
}
kbd = kbd_table + fg_console;
kbd = kbd_table + vc->vc_num;
if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
sysrq_alt = down ? keycode : 0;
@@ -1296,10 +1309,16 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
static void kbd_event(struct input_handle *handle, unsigned int event_type,
unsigned int event_code, int value)
{
/* We are called with interrupts disabled, just take the lock */
spin_lock(&kbd_event_lock);
if (event_type == EV_MSC && event_code == MSC_RAW && HW_RAW(handle->dev))
kbd_rawcode(value);
if (event_type == EV_KEY)
kbd_keycode(event_code, value, HW_RAW(handle->dev));
spin_unlock(&kbd_event_lock);
tasklet_schedule(&keyboard_tasklet);
do_poke_blanked_console = 1;
schedule_console_callback();
@@ -1363,15 +1382,11 @@ static void kbd_disconnect(struct input_handle *handle)
*/
static void kbd_start(struct input_handle *handle)
{
unsigned char leds = ledstate;
tasklet_disable(&keyboard_tasklet);
if (leds != 0xff) {
input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01));
input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02));
input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04));
input_inject_event(handle, EV_SYN, SYN_REPORT, 0);
}
if (ledstate != 0xff)
kbd_update_leds_helper(handle, &ledstate);
tasklet_enable(&keyboard_tasklet);
}
+12 -3
View File
@@ -429,7 +429,7 @@ static bool dmi_matches(const struct dmi_system_id *dmi)
for (i = 0; i < ARRAY_SIZE(dmi->matches); i++) {
int s = dmi->matches[i].slot;
if (s == DMI_NONE)
continue;
break;
if (dmi_ident[s]
&& strstr(dmi_ident[s], dmi->matches[i].substr))
continue;
@@ -439,6 +439,15 @@ static bool dmi_matches(const struct dmi_system_id *dmi)
return true;
}
/**
* dmi_is_end_of_table - check for end-of-table marker
* @dmi: pointer to the dmi_system_id structure to check
*/
static bool dmi_is_end_of_table(const struct dmi_system_id *dmi)
{
return dmi->matches[0].slot == DMI_NONE;
}
/**
* dmi_check_system - check system DMI data
* @list: array of dmi_system_id structures to match against
@@ -457,7 +466,7 @@ int dmi_check_system(const struct dmi_system_id *list)
int count = 0;
const struct dmi_system_id *d;
for (d = list; d->ident; d++)
for (d = list; !dmi_is_end_of_table(d); d++)
if (dmi_matches(d)) {
count++;
if (d->callback && d->callback(d))
@@ -484,7 +493,7 @@ const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list)
{
const struct dmi_system_id *d;
for (d = list; d->ident; d++)
for (d = list; !dmi_is_end_of_table(d); d++)
if (dmi_matches(d))
return d;
+1 -1
View File
@@ -266,7 +266,7 @@ static int usb_kbd_probe(struct usb_interface *iface,
le16_to_cpu(dev->descriptor.idProduct));
usb_make_path(dev, kbd->phys, sizeof(kbd->phys));
strlcpy(kbd->phys, "/input0", sizeof(kbd->phys));
strlcat(kbd->phys, "/input0", sizeof(kbd->phys));
input_dev->name = kbd->name;
input_dev->phys = kbd->phys;
+20 -8
View File
@@ -8,7 +8,7 @@ menu "Input device support"
config INPUT
tristate "Generic input layer (needed for keyboard, mouse, ...)" if EMBEDDED
default y
---help---
help
Say Y here if you have any input device (mouse, keyboard, tablet,
joystick, steering wheel ...) connected to your system and want
it to be available to applications. This includes standard PS/2
@@ -27,8 +27,7 @@ if INPUT
config INPUT_FF_MEMLESS
tristate "Support for memoryless force-feedback devices"
default n
---help---
help
Say Y here if you have memoryless force-feedback input device
such as Logitech WingMan Force 3D, ThrustMaster FireStorm Dual
Power 2, or similar. You will also need to enable hardware-specific
@@ -52,12 +51,25 @@ config INPUT_POLLDEV
To compile this driver as a module, choose M here: the
module will be called input-polldev.
config INPUT_SPARSEKMAP
tristate "Sparse keymap support library"
help
Say Y here if you are using a driver for an input
device that uses sparse keymap. This option is only
useful for out-of-tree drivers since in-tree drivers
select it automatically.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called sparse-keymap.
comment "Userland interfaces"
config INPUT_MOUSEDEV
tristate "Mouse interface" if EMBEDDED
default y
---help---
help
Say Y here if you want your mouse to be accessible as char devices
13:32+ - /dev/input/mouseX and 13:63 - /dev/input/mice as an
emulated IntelliMouse Explorer PS/2 mouse. That way, all user space
@@ -73,7 +85,7 @@ config INPUT_MOUSEDEV_PSAUX
bool "Provide legacy /dev/psaux device"
default y
depends on INPUT_MOUSEDEV
---help---
help
Say Y here if you want your mouse also be accessible as char device
10:1 - /dev/psaux. The data available through /dev/psaux is exactly
the same as the data from /dev/input/mice.
@@ -103,7 +115,7 @@ config INPUT_MOUSEDEV_SCREEN_Y
config INPUT_JOYDEV
tristate "Joystick interface"
---help---
help
Say Y here if you want your joystick or gamepad to be
accessible as char device 13:0+ - /dev/input/jsX device.
@@ -125,7 +137,7 @@ config INPUT_EVDEV
config INPUT_EVBUG
tristate "Event debugging"
---help---
help
Say Y here if you have a problem with the input subsystem and
want all events (keypresses, mouse movements), to be output to
the system log. While this is useful for debugging, it's also
@@ -140,7 +152,7 @@ config INPUT_EVBUG
config INPUT_APMPOWER
tristate "Input Power Event -> APM Bridge" if EMBEDDED
depends on INPUT && APM_EMULATION
---help---
help
Say Y here if you want suspend key events to trigger a user
requested suspend through APM. This is useful on embedded
systems where such behaviour is desired without userspace
+1
View File
@@ -9,6 +9,7 @@ input-core-objs := input.o input-compat.o ff-core.o
obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o
obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o
obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
+2 -1
View File
@@ -353,7 +353,7 @@ int input_ff_create(struct input_dev *dev, int max_effects)
EXPORT_SYMBOL_GPL(input_ff_create);
/**
* input_ff_free() - frees force feedback portion of input device
* input_ff_destroy() - frees force feedback portion of input device
* @dev: input device supporting force feedback
*
* This function is only needed in error path as input core will
@@ -369,6 +369,7 @@ void input_ff_destroy(struct input_dev *dev)
if (ff->destroy)
ff->destroy(ff);
kfree(ff->private);
kfree(ff->effects);
kfree(ff);
dev->ff = NULL;
}
+123 -14
View File
@@ -56,14 +56,10 @@ static void input_polldev_stop_workqueue(void)
mutex_unlock(&polldev_mutex);
}
static void input_polled_device_work(struct work_struct *work)
static void input_polldev_queue_work(struct input_polled_dev *dev)
{
struct input_polled_dev *dev =
container_of(work, struct input_polled_dev, work.work);
unsigned long delay;
dev->poll(dev);
delay = msecs_to_jiffies(dev->poll_interval);
if (delay >= HZ)
delay = round_jiffies_relative(delay);
@@ -71,6 +67,15 @@ static void input_polled_device_work(struct work_struct *work)
queue_delayed_work(polldev_wq, &dev->work, delay);
}
static void input_polled_device_work(struct work_struct *work)
{
struct input_polled_dev *dev =
container_of(work, struct input_polled_dev, work.work);
dev->poll(dev);
input_polldev_queue_work(dev);
}
static int input_open_polled_device(struct input_dev *input)
{
struct input_polled_dev *dev = input_get_drvdata(input);
@@ -80,11 +85,12 @@ static int input_open_polled_device(struct input_dev *input)
if (error)
return error;
if (dev->flush)
dev->flush(dev);
if (dev->open)
dev->open(dev);
queue_delayed_work(polldev_wq, &dev->work,
msecs_to_jiffies(dev->poll_interval));
/* Only start polling if polling is enabled */
if (dev->poll_interval > 0)
queue_delayed_work(polldev_wq, &dev->work, 0);
return 0;
}
@@ -95,8 +101,88 @@ static void input_close_polled_device(struct input_dev *input)
cancel_delayed_work_sync(&dev->work);
input_polldev_stop_workqueue();
if (dev->close)
dev->close(dev);
}
/* SYSFS interface */
static ssize_t input_polldev_get_poll(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct input_polled_dev *polldev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", polldev->poll_interval);
}
static ssize_t input_polldev_set_poll(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
struct input_polled_dev *polldev = dev_get_drvdata(dev);
struct input_dev *input = polldev->input;
unsigned long interval;
if (strict_strtoul(buf, 0, &interval))
return -EINVAL;
if (interval < polldev->poll_interval_min)
return -EINVAL;
if (interval > polldev->poll_interval_max)
return -EINVAL;
mutex_lock(&input->mutex);
polldev->poll_interval = interval;
if (input->users) {
cancel_delayed_work_sync(&polldev->work);
if (polldev->poll_interval > 0)
input_polldev_queue_work(polldev);
}
mutex_unlock(&input->mutex);
return count;
}
static DEVICE_ATTR(poll, S_IRUGO | S_IWUSR, input_polldev_get_poll,
input_polldev_set_poll);
static ssize_t input_polldev_get_max(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct input_polled_dev *polldev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", polldev->poll_interval_max);
}
static DEVICE_ATTR(max, S_IRUGO, input_polldev_get_max, NULL);
static ssize_t input_polldev_get_min(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct input_polled_dev *polldev = dev_get_drvdata(dev);
return sprintf(buf, "%d\n", polldev->poll_interval_min);
}
static DEVICE_ATTR(min, S_IRUGO, input_polldev_get_min, NULL);
static struct attribute *sysfs_attrs[] = {
&dev_attr_poll.attr,
&dev_attr_max.attr,
&dev_attr_min.attr,
NULL
};
static struct attribute_group input_polldev_attribute_group = {
.attrs = sysfs_attrs
};
/**
* input_allocate_polled_device - allocated memory polled device
*
@@ -126,7 +212,7 @@ EXPORT_SYMBOL(input_allocate_polled_device);
* @dev: device to free
*
* The function frees memory allocated for polling device and drops
* reference to the associated input device (if present).
* reference to the associated input device.
*/
void input_free_polled_device(struct input_polled_dev *dev)
{
@@ -150,15 +236,38 @@ EXPORT_SYMBOL(input_free_polled_device);
int input_register_polled_device(struct input_polled_dev *dev)
{
struct input_dev *input = dev->input;
int error;
input_set_drvdata(input, dev);
INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
if (!dev->poll_interval)
dev->poll_interval = 500;
if (!dev->poll_interval_max)
dev->poll_interval_max = dev->poll_interval;
input->open = input_open_polled_device;
input->close = input_close_polled_device;
return input_register_device(input);
error = input_register_device(input);
if (error)
return error;
error = sysfs_create_group(&input->dev.kobj,
&input_polldev_attribute_group);
if (error) {
input_unregister_device(input);
return error;
}
/*
* Take extra reference to the underlying input device so
* that it survives call to input_unregister_polled_device()
* and is deleted only after input_free_polled_device()
* has been invoked. This is needed to ease task of freeing
* sparse keymaps.
*/
input_get_device(input);
return 0;
}
EXPORT_SYMBOL(input_register_polled_device);
@@ -169,13 +278,13 @@ EXPORT_SYMBOL(input_register_polled_device);
* The function unregisters previously registered polled input
* device from input layer. Polling is stopped and device is
* ready to be freed with call to input_free_polled_device().
* Callers should not attempt to access dev->input pointer
* after calling this function.
*/
void input_unregister_polled_device(struct input_polled_dev *dev)
{
sysfs_remove_group(&dev->input->dev.kobj,
&input_polldev_attribute_group);
input_unregister_device(dev->input);
dev->input = NULL;
}
EXPORT_SYMBOL(input_unregister_polled_device);
+35 -2
View File
@@ -1657,6 +1657,38 @@ void input_unregister_handler(struct input_handler *handler)
}
EXPORT_SYMBOL(input_unregister_handler);
/**
* input_handler_for_each_handle - handle iterator
* @handler: input handler to iterate
* @data: data for the callback
* @fn: function to be called for each handle
*
* Iterate over @bus's list of devices, and call @fn for each, passing
* it @data and stop when @fn returns a non-zero value. The function is
* using RCU to traverse the list and therefore may be usind in atonic
* contexts. The @fn callback is invoked from RCU critical section and
* thus must not sleep.
*/
int input_handler_for_each_handle(struct input_handler *handler, void *data,
int (*fn)(struct input_handle *, void *))
{
struct input_handle *handle;
int retval = 0;
rcu_read_lock();
list_for_each_entry_rcu(handle, &handler->h_list, h_node) {
retval = fn(handle, data);
if (retval)
break;
}
rcu_read_unlock();
return retval;
}
EXPORT_SYMBOL(input_handler_for_each_handle);
/**
* input_register_handle - register a new input handle
* @handle: handle to register
@@ -1690,7 +1722,7 @@ int input_register_handle(struct input_handle *handle)
* we can't be racing with input_unregister_handle()
* and so separate lock is not needed here.
*/
list_add_tail(&handle->h_node, &handler->h_list);
list_add_tail_rcu(&handle->h_node, &handler->h_list);
if (handler->start)
handler->start(handle);
@@ -1713,7 +1745,7 @@ void input_unregister_handle(struct input_handle *handle)
{
struct input_dev *dev = handle->dev;
list_del_init(&handle->h_node);
list_del_rcu(&handle->h_node);
/*
* Take dev->mutex to prevent race with input_release_device().
@@ -1721,6 +1753,7 @@ void input_unregister_handle(struct input_handle *handle)
mutex_lock(&dev->mutex);
list_del_rcu(&handle->d_node);
mutex_unlock(&dev->mutex);
synchronize_rcu();
}
EXPORT_SYMBOL(input_unregister_handle);
+3
View File
@@ -125,6 +125,7 @@ static const struct xpad_device {
{ 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0c12, 0x880a, "Pelican Eclipse PL-2023", MAP_DPAD_TO_AXES, XTYPE_XBOX },
@@ -146,6 +147,7 @@ static const struct xpad_device {
{ 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN }
};
@@ -212,6 +214,7 @@ static struct usb_device_id xpad_table [] = {
XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */
XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */
XPAD_XBOX360_VENDOR(0x1bad), /* Rock Band Drums */
XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */
{ }
};
+10
View File
@@ -361,6 +361,16 @@ config KEYBOARD_SH_KEYSC
To compile this driver as a module, choose M here: the
module will be called sh_keysc.
config KEYBOARD_DAVINCI
tristate "TI DaVinci Key Scan"
depends on ARCH_DAVINCI_DM365
help
Say Y to enable keypad module support for the TI DaVinci
platforms (DM365).
To compile this driver as a module, choose M here: the
module will be called davinci_keyscan.
config KEYBOARD_OMAP
tristate "TI OMAP keypad support"
depends on (ARCH_OMAP1 || ARCH_OMAP2)
+1
View File
@@ -11,6 +11,7 @@ obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o
obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o
obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
+9 -17
View File
@@ -1567,9 +1567,8 @@ static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id)
return 0;
}
static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = {
{
.ident = "Dell Laptop",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
@@ -1578,7 +1577,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_dell_laptop_forced_release_keys,
},
{
.ident = "Dell Laptop",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
@@ -1587,7 +1585,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_dell_laptop_forced_release_keys,
},
{
.ident = "HP 2133",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "HP 2133"),
@@ -1596,7 +1593,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_hp_forced_release_keys,
},
{
.ident = "HP Pavilion ZV6100",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"),
@@ -1605,7 +1601,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_volume_forced_release_keys,
},
{
.ident = "HP Presario R4000",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"),
@@ -1614,7 +1609,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_volume_forced_release_keys,
},
{
.ident = "HP Presario R4100",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"),
@@ -1623,7 +1617,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_volume_forced_release_keys,
},
{
.ident = "HP Presario R4200",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"),
@@ -1632,7 +1625,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_volume_forced_release_keys,
},
{
.ident = "Inventec Symphony",
/* Inventec Symphony */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"),
DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"),
@@ -1641,7 +1634,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_volume_forced_release_keys,
},
{
.ident = "Samsung NC10",
/* Samsung NC10 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
@@ -1650,7 +1643,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_samsung_forced_release_keys,
},
{
.ident = "Samsung NC20",
/* Samsung NC20 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "NC20"),
@@ -1659,7 +1652,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_samsung_forced_release_keys,
},
{
.ident = "Samsung SQ45S70S",
/* Samsung SQ45S70S */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
@@ -1668,7 +1661,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_samsung_forced_release_keys,
},
{
.ident = "Fujitsu Amilo PA 1510",
/* Fujitsu Amilo PA 1510 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 1510"),
@@ -1677,7 +1670,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_volume_forced_release_keys,
},
{
.ident = "Fujitsu Amilo Pi 3525",
/* Fujitsu Amilo Pi 3525 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 3525"),
@@ -1686,7 +1679,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_amilo_pi3525_forced_release_keys,
},
{
.ident = "Fujitsu Amilo Xi 3650",
/* Fujitsu Amilo Xi 3650 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 3650"),
@@ -1695,7 +1688,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkbd_amilo_xi3650_forced_release_keys,
},
{
.ident = "Soltech Corporation TA12",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Soltech Corporation"),
DMI_MATCH(DMI_PRODUCT_NAME, "TA12"),
@@ -1704,7 +1696,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.driver_data = atkdb_soltech_ta12_forced_release_keys,
},
{
.ident = "OQO Model 01+",
/* OQO Model 01+ */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),

Some files were not shown because too many files have changed in this diff Show More