Commit fa395aae authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 3e746831 1f26978a
......@@ -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">
......
......@@ -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
......
......@@ -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
* -------------------------------------------------------------------- */
......
......@@ -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
......
......@@ -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 */
......
......@@ -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 */
......
......@@ -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 {
......
/*
* 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
......@@ -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 void kd_nosound(unsigned long ignored)
static int kd_sound_helper(struct input_handle *handle, void *data)
{
struct input_handle *handle;
unsigned int *hz = data;
struct input_dev *dev = handle->dev;
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);
}
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)
{
static unsigned int zero;
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.
*/
int kbd_rate(struct kbd_repeat *rep)
static int kbd_rate_helper(struct input_handle *handle, void *data)
{
struct list_head *node;
unsigned int d = 0;
unsigned int p = 0;
list_for_each(node, &kbd_handler.h_list) {
struct input_handle *handle = to_handle_h(node);
struct input_dev *dev = handle->dev;
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];
}
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];
}
rep->delay = d;
rep->period = p;
return 0;
}
int kbd_rate(struct kbd_repeat *rep)
{
struct kbd_repeat data[2] = { *rep };
input_handler_for_each_handle(&kbd_handler, data, kbd_rate_helper);
*rep = data[1]; /* Copy currently used settings */
return 0;
}
......@@ -997,36 +1010,36 @@ static inline unsigned char getleds(void)
return leds;
}
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 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, ...) => ...
* 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);
}
......
......@@ -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;
......
......@@ -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;
......
......@@ -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
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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);
......@@ -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);
......
......@@ -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 */
{ }
};
......
......@@ -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)
......
......@@ -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
......
......@@ -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"),
......
/*
* DaVinci Key Scan Driver for TI platforms
*
* Copyright (C) 2009 Texas Instruments, Inc
*
* Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
*
* Intial Code: Sandeep Paulraj <s-paulraj@ti.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
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
#include <asm/irq.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <mach/keyscan.h>
/* Key scan registers */
#define DAVINCI_KEYSCAN_KEYCTRL 0x0000
#define DAVINCI_KEYSCAN_INTENA 0x0004
#define DAVINCI_KEYSCAN_INTFLAG 0x0008
#define DAVINCI_KEYSCAN_INTCLR 0x000c
#define DAVINCI_KEYSCAN_STRBWIDTH 0x0010
#define DAVINCI_KEYSCAN_INTERVAL 0x0014
#define DAVINCI_KEYSCAN_CONTTIME 0x0018
#define DAVINCI_KEYSCAN_CURRENTST 0x001c
#define DAVINCI_KEYSCAN_PREVSTATE 0x0020
#define DAVINCI_KEYSCAN_EMUCTRL 0x0024
#define DAVINCI_KEYSCAN_IODFTCTRL 0x002c
/* Key Control Register (KEYCTRL) */
#define DAVINCI_KEYSCAN_KEYEN 0x00000001
#define DAVINCI_KEYSCAN_PREVMODE 0x00000002
#define DAVINCI_KEYSCAN_CHATOFF 0x00000004
#define DAVINCI_KEYSCAN_AUTODET 0x00000008
#define DAVINCI_KEYSCAN_SCANMODE 0x00000010
#define DAVINCI_KEYSCAN_OUTTYPE 0x00000020
/* Masks for the interrupts */
#define DAVINCI_KEYSCAN_INT_CONT 0x00000008
#define DAVINCI_KEYSCAN_INT_OFF 0x00000004
#define DAVINCI_KEYSCAN_INT_ON 0x00000002
#define DAVINCI_KEYSCAN_INT_CHANGE 0x00000001
#define DAVINCI_KEYSCAN_INT_ALL 0x0000000f
struct davinci_ks {
struct input_dev *input;
struct davinci_ks_platform_data *pdata;
int irq;
void __iomem *base;
resource_size_t pbase;
size_t base_size;
unsigned short keymap[];
};
/* Initializing the kp Module */
static int __init davinci_ks_initialize(struct davinci_ks *davinci_ks)
{
struct device *dev = &davinci_ks->input->dev;
struct davinci_ks_platform_data *pdata = davinci_ks->pdata;
u32 matrix_ctrl;
/* Enable all interrupts */
__raw_writel(DAVINCI_KEYSCAN_INT_ALL,
davinci_ks->base + DAVINCI_KEYSCAN_INTENA);
/* Clear interrupts if any */
__raw_writel(DAVINCI_KEYSCAN_INT_ALL,
davinci_ks->base + DAVINCI_KEYSCAN_INTCLR);
/* Setup the scan period = strobe + interval */
__raw_writel(pdata->strobe,
davinci_ks->base + DAVINCI_KEYSCAN_STRBWIDTH);
__raw_writel(pdata->interval,
davinci_ks->base + DAVINCI_KEYSCAN_INTERVAL);
__raw_writel(0x01,
davinci_ks->base + DAVINCI_KEYSCAN_CONTTIME);
/* Define matrix type */
switch (pdata->matrix_type) {
case DAVINCI_KEYSCAN_MATRIX_4X4:
matrix_ctrl = 0;
break;
case DAVINCI_KEYSCAN_MATRIX_5X3:
matrix_ctrl = (1 << 6);
break;
default:
dev_err(dev->parent, "wrong matrix type\n");
return -EINVAL;
}
/* Enable key scan module and set matrix type */
__raw_writel(DAVINCI_KEYSCAN_AUTODET | DAVINCI_KEYSCAN_KEYEN |
matrix_ctrl, davinci_ks->base + DAVINCI_KEYSCAN_KEYCTRL);
return 0;
}
static irqreturn_t davinci_ks_interrupt(int irq, void *dev_id)
{
struct davinci_ks *davinci_ks = dev_id;
struct device *dev = &davinci_ks->input->dev;
unsigned short *keymap = davinci_ks->keymap;
int keymapsize = davinci_ks->pdata->keymapsize;
u32 prev_status, new_status, changed;
bool release;
int keycode = KEY_UNKNOWN;
int i;
/* Disable interrupt */
__raw_writel(0x0, davinci_ks->base + DAVINCI_KEYSCAN_INTENA);
/* Reading previous and new status of the key scan */
prev_status = __raw_readl(davinci_ks->base + DAVINCI_KEYSCAN_PREVSTATE);
new_status = __raw_readl(davinci_ks->base + DAVINCI_KEYSCAN_CURRENTST);
changed = prev_status ^ new_status;
if (changed) {
/*
* It goes through all bits in 'changed' to ensure
* that no key changes are being missed
*/
for (i = 0 ; i < keymapsize; i++) {
if ((changed>>i) & 0x1) {
keycode = keymap[i];
release = (new_status >> i) & 0x1;
dev_dbg(dev->parent, "key %d %s\n", keycode,
release ? "released" : "pressed");
input_report_key(davinci_ks->input, keycode,
!release);
input_sync(davinci_ks->input);
}
}
/* Clearing interrupt */
__raw_writel(DAVINCI_KEYSCAN_INT_ALL,
davinci_ks->base + DAVINCI_KEYSCAN_INTCLR);
}
/* Enable interrupts */
__raw_writel(0x1, davinci_ks->base + DAVINCI_KEYSCAN_INTENA);
return IRQ_HANDLED;
}
static int __init davinci_ks_probe(struct platform_device *pdev)
{
struct davinci_ks *davinci_ks;
struct input_dev *key_dev;
struct resource *res, *mem;
struct device *dev = &pdev->dev;
struct davinci_ks_platform_data *pdata = pdev->dev.platform_data;
int error, i;
if (!pdata->keymap) {
dev_dbg(dev, "no keymap from pdata\n");
return -EINVAL;
}
davinci_ks = kzalloc(sizeof(struct davinci_ks) +
sizeof(unsigned short) * pdata->keymapsize, GFP_KERNEL);
if (!davinci_ks) {
dev_dbg(dev, "could not allocate memory for private data\n");
return -ENOMEM;
}
memcpy(davinci_ks->keymap, pdata->keymap,
sizeof(unsigned short) * pdata->keymapsize);
key_dev = input_allocate_device();
if (!key_dev) {
dev_dbg(dev, "could not allocate input device\n");
error = -ENOMEM;
goto fail1;
}
davinci_ks->input = key_dev;
davinci_ks->irq = platform_get_irq(pdev, 0);
if (davinci_ks->irq < 0) {
dev_err(dev, "no key scan irq\n");
error = davinci_ks->irq;
goto fail2;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "no mem resource\n");
error = -EINVAL;
goto fail2;
}
davinci_ks->pbase = res->start;
davinci_ks->base_size = resource_size(res);
mem = request_mem_region(davinci_ks->pbase, davinci_ks->base_size,
pdev->name);
if (!mem) {
dev_err(dev, "key scan registers at %08x are not free\n",
davinci_ks->pbase);
error = -EBUSY;
goto fail2;
}
davinci_ks->base = ioremap(davinci_ks->pbase, davinci_ks->base_size);
if (!davinci_ks->base) {
dev_err(dev, "can't ioremap MEM resource.\n");
error = -ENOMEM;
goto fail3;
}
/* Enable auto repeat feature of Linux input subsystem */
if (pdata->rep)
__set_bit(EV_REP, key_dev->evbit);
/* Setup input device */
__set_bit(EV_KEY, key_dev->evbit);
/* Setup the platform data */
davinci_ks->pdata = pdata;
for (i = 0; i < davinci_ks->pdata->keymapsize; i++)
__set_bit(davinci_ks->pdata->keymap[i], key_dev->keybit);
key_dev->name = "davinci_keyscan";
key_dev->phys = "davinci_keyscan/input0";
key_dev->dev.parent = &pdev->dev;
key_dev->id.bustype = BUS_HOST;
key_dev->id.vendor = 0x0001;
key_dev->id.product = 0x0001;
key_dev->id.version = 0x0001;
key_dev->keycode = davinci_ks->keymap;
key_dev->keycodesize = sizeof(davinci_ks->keymap[0]);
key_dev->keycodemax = davinci_ks->pdata->keymapsize;
error = input_register_device(davinci_ks->input);
if (error < 0) {
dev_err(dev, "unable to register davinci key scan device\n");
goto fail4;
}
error = request_irq(davinci_ks->irq, davinci_ks_interrupt,
IRQF_DISABLED, pdev->name, davinci_ks);
if (error < 0) {
dev_err(dev, "unable to register davinci key scan interrupt\n");
goto fail5;
}
error = davinci_ks_initialize(davinci_ks);
if (error < 0) {
dev_err(dev, "unable to initialize davinci key scan device\n");
goto fail6;
}
platform_set_drvdata(pdev, davinci_ks);
return 0;
fail6:
free_irq(davinci_ks->irq, davinci_ks);
fail5:
input_unregister_device(davinci_ks->input);
key_dev = NULL;
fail4:
iounmap(davinci_ks->base);
fail3:
release_mem_region(davinci_ks->pbase, davinci_ks->base_size);
fail2:
input_free_device(key_dev);
fail1:
kfree(davinci_ks);
return error;
}
static int __devexit davinci_ks_remove(struct platform_device *pdev)
{
struct davinci_ks *davinci_ks = platform_get_drvdata(pdev);
free_irq(davinci_ks->irq, davinci_ks);
input_unregister_device(davinci_ks->input);
iounmap(davinci_ks->base);
release_mem_region(davinci_ks->pbase, davinci_ks->base_size);
platform_set_drvdata(pdev, NULL);
kfree(davinci_ks);
return 0;
}
static struct platform_driver davinci_ks_driver = {
.driver = {
.name = "davinci_keyscan",
.owner = THIS_MODULE,
},
.remove = __devexit_p(davinci_ks_remove),
};
static int __init davinci_ks_init(void)
{
return platform_driver_probe(&davinci_ks_driver, davinci_ks_probe);
}
module_init(davinci_ks_init);
static void __exit davinci_ks_exit(void)
{
platform_driver_unregister(&davinci_ks_driver);
}
module_exit(davinci_ks_exit);
MODULE_AUTHOR("Miguel Aguilar");
MODULE_DESCRIPTION("Texas Instruments DaVinci Key Scan Driver");
MODULE_LICENSE("GPL");
......@@ -23,8 +23,7 @@
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/workqueue.h>
#include <asm/gpio.h>
#include <linux/gpio.h>
struct gpio_button_data {
struct gpio_keys_button *button;
......@@ -38,10 +37,8 @@ struct gpio_keys_drvdata {
struct gpio_button_data data[0];
};
static void gpio_keys_report_event(struct work_struct *work)
static void gpio_keys_report_event(struct gpio_button_data *bdata)
{
struct gpio_button_data *bdata =
container_of(work, struct gpio_button_data, work);
struct gpio_keys_button *button = bdata->button;
struct input_dev *input = bdata->input;
unsigned int type = button->type ?: EV_KEY;
......@@ -51,6 +48,14 @@ static void gpio_keys_report_event(struct work_struct *work)
input_sync(input);
}
static void gpio_keys_work_func(struct work_struct *work)
{
struct gpio_button_data *bdata =
container_of(work, struct gpio_button_data, work);
gpio_keys_report_event(bdata);
}
static void gpio_keys_timer(unsigned long _data)
{
struct gpio_button_data *data = (struct gpio_button_data *)_data;
......@@ -74,10 +79,62 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
static int __devinit gpio_keys_setup_key(struct device *dev,
struct gpio_button_data *bdata,
struct gpio_keys_button *button)
{
char *desc = button->desc ? button->desc : "gpio_keys";
int irq, error;
setup_timer(&bdata->timer, gpio_keys_timer, (unsigned long)bdata);
INIT_WORK(&bdata->work, gpio_keys_work_func);
error = gpio_request(button->gpio, desc);
if (error < 0) {
dev_err(dev, "failed to request GPIO %d, error %d\n",
button->gpio, error);
goto fail2;
}
error = gpio_direction_input(button->gpio);
if (error < 0) {
dev_err(dev, "failed to configure"
" direction for GPIO %d, error %d\n",
button->gpio, error);
goto fail3;
}
irq = gpio_to_irq(button->gpio);
if (irq < 0) {
error = irq;
dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n",
button->gpio, error);
goto fail3;
}
error = request_irq(irq, gpio_keys_isr,
IRQF_SHARED |
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
desc, bdata);
if (error) {
dev_err(dev, "Unable to claim irq %d; error %d\n",
irq, error);
goto fail3;
}
return 0;
fail3:
gpio_free(button->gpio);
fail2:
return error;
}
static int __devinit gpio_keys_probe(struct platform_device *pdev)
{
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct gpio_keys_drvdata *ddata;
struct device *dev = &pdev->dev;
struct input_dev *input;
int i, error;
int wakeup = 0;
......@@ -87,6 +144,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
GFP_KERNEL);
input = input_allocate_device();
if (!ddata || !input) {
dev_err(dev, "failed to allocate state\n");
error = -ENOMEM;
goto fail1;
}
......@@ -111,52 +169,14 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
struct gpio_button_data *bdata = &ddata->data[i];
int irq;
unsigned int type = button->type ?: EV_KEY;
bdata->input = input;
bdata->button = button;
setup_timer(&bdata->timer,
gpio_keys_timer, (unsigned long)bdata);
INIT_WORK(&bdata->work, gpio_keys_report_event);
error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
if (error < 0) {
pr_err("gpio-keys: failed to request GPIO %d,"
" error %d\n", button->gpio, error);
goto fail2;
}
error = gpio_direction_input(button->gpio);
if (error < 0) {
pr_err("gpio-keys: failed to configure input"
" direction for GPIO %d, error %d\n",
button->gpio, error);
gpio_free(button->gpio);
goto fail2;
}
irq = gpio_to_irq(button->gpio);
if (irq < 0) {
error = irq;
pr_err("gpio-keys: Unable to get irq number"
" for GPIO %d, error %d\n",
button->gpio, error);
gpio_free(button->gpio);
goto fail2;
}
error = request_irq(irq, gpio_keys_isr,
IRQF_SHARED |
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
button->desc ? button->desc : "gpio_keys",
bdata);
if (error) {
pr_err("gpio-keys: Unable to claim irq %d; error %d\n",
irq, error);
gpio_free(button->gpio);
error = gpio_keys_setup_key(dev, bdata, button);
if (error)
goto fail2;
}
if (button->wakeup)
wakeup = 1;
......@@ -166,11 +186,16 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
error = input_register_device(input);
if (error) {
pr_err("gpio-keys: Unable to register input device, "
dev_err(dev, "Unable to register input device, "
"error: %d\n", error);
goto fail2;
}
/* get current state of buttons */
for (i = 0; i < pdata->nbuttons; i++)
gpio_keys_report_event(&ddata->data[i]);
input_sync(input);
device_init_wakeup(&pdev->dev, wakeup);
return 0;
......@@ -239,18 +264,21 @@ static int gpio_keys_suspend(struct device *dev)
static int gpio_keys_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev);
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
int i;
if (device_may_wakeup(&pdev->dev)) {
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
if (button->wakeup) {
int irq = gpio_to_irq(button->gpio);
disable_irq_wake(irq);
}
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
if (button->wakeup && device_may_wakeup(&pdev->dev)) {
int irq = gpio_to_irq(button->gpio);
disable_irq_wake(irq);
}
gpio_keys_report_event(&ddata->data[i]);
}
input_sync(ddata->input);
return 0;
}
......
This diff is collapsed.
......@@ -213,8 +213,9 @@ static void matrix_keypad_stop(struct input_dev *dev)
}
#ifdef CONFIG_PM
static int matrix_keypad_suspend(struct platform_device *pdev, pm_message_t state)
static int matrix_keypad_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
int i;
......@@ -228,8 +229,9 @@ static int matrix_keypad_suspend(struct platform_device *pdev, pm_message_t stat
return 0;
}
static int matrix_keypad_resume(struct platform_device *pdev)
static int matrix_keypad_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
int i;
......@@ -242,9 +244,9 @@ static int matrix_keypad_resume(struct platform_device *pdev)
return 0;
}
#else
#define matrix_keypad_suspend NULL
#define matrix_keypad_resume NULL
static const SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops,
matrix_keypad_suspend, matrix_keypad_resume);
#endif
static int __devinit init_matrix_gpio(struct platform_device *pdev,
......@@ -417,11 +419,12 @@ static int __devexit matrix_keypad_remove(struct platform_device *pdev)
static struct platform_driver matrix_keypad_driver = {
.probe = matrix_keypad_probe,
.remove = __devexit_p(matrix_keypad_remove),
.suspend = matrix_keypad_suspend,
.resume = matrix_keypad_resume,
.driver = {
.name = "matrix-keypad",
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &matrix_keypad_pm_ops,
#endif
},
};
......
......@@ -80,6 +80,7 @@ config INPUT_WISTRON_BTNS
tristate "x86 Wistron laptop button interface"
depends on X86 && !X86_64
select INPUT_POLLDEV
select INPUT_SPARSEKMAP
select NEW_LEDS
select LEDS_CLASS
select CHECK_SIGNATURE
......@@ -281,6 +282,7 @@ config INPUT_RB532_BUTTON
config INPUT_DM355EVM
tristate "TI DaVinci DM355 EVM Keypad and IR Remote"
depends on MFD_DM355EVM_MSP
select INPUT_SPARSEKMAP
help
Supports the pushbuttons and IR remote used with
the DM355 EVM board.
......
......@@ -766,7 +766,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
ati_remote->interface = interface;
usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys));
strlcpy(ati_remote->phys, "/input0", sizeof(ati_remote->phys));
strlcat(ati_remote->phys, "/input0", sizeof(ati_remote->phys));
if (udev->manufacturer)
strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name));
......
......@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
......@@ -33,12 +34,8 @@ struct dm355evm_keys {
int irq;
};
/* These initial keycodes can be remapped by dm355evm_setkeycode(). */
static struct {
u16 event;
u16 keycode;
} dm355evm_keys[] = {
/* These initial keycodes can be remapped */
static const struct key_entry dm355evm_keys[] = {
/*
* Pushbuttons on the EVM board ... note that the labels for these
* are SW10/SW11/etc on the PC board. The left/right orientation
......@@ -47,11 +44,11 @@ static struct {
* is to the right. (That is, rotate the board counter-clockwise
* by 90 degrees from the SW10/etc and "DM355 EVM" labels.)
*/
{ 0x00d8, KEY_OK, }, /* SW12 */
{ 0x00b8, KEY_UP, }, /* SW13 */
{ 0x00e8, KEY_DOWN, }, /* SW11 */
{ 0x0078, KEY_LEFT, }, /* SW14 */
{ 0x00f0, KEY_RIGHT, }, /* SW10 */
{ KE_KEY, 0x00d8, { KEY_OK } }, /* SW12 */
{ KE_KEY, 0x00b8, { KEY_UP } }, /* SW13 */
{ KE_KEY, 0x00e8, { KEY_DOWN } }, /* SW11 */
{ KE_KEY, 0x0078, { KEY_LEFT } }, /* SW14 */
{ KE_KEY, 0x00f0, { KEY_RIGHT } }, /* SW10 */
/*
* IR buttons ... codes assigned to match the universal remote
......@@ -65,35 +62,35 @@ static struct {
* RC5 codes are 14 bits, with two start bits (0x3 prefix)
* and a toggle bit (masked out below).
*/
{ 0x300c, KEY_POWER, }, /* NOTE: docs omit this */
{ 0x3000, KEY_NUMERIC_0, },
{ 0x3001, KEY_NUMERIC_1, },
{ 0x3002, KEY_NUMERIC_2, },
{ 0x3003, KEY_NUMERIC_3, },
{ 0x3004, KEY_NUMERIC_4, },
{ 0x3005, KEY_NUMERIC_5, },
{ 0x3006, KEY_NUMERIC_6, },
{ 0x3007, KEY_NUMERIC_7, },
{ 0x3008, KEY_NUMERIC_8, },
{ 0x3009, KEY_NUMERIC_9, },
{ 0x3022, KEY_ENTER, },
{ 0x30ec, KEY_MODE, }, /* "tv/vcr/..." */
{ 0x300f, KEY_SELECT, }, /* "info" */
{ 0x3020, KEY_CHANNELUP, }, /* "up" */
{ 0x302e, KEY_MENU, }, /* "in/out" */
{ 0x3011, KEY_VOLUMEDOWN, }, /* "left" */
{ 0x300d, KEY_MUTE, }, /* "ok" */
{ 0x3010, KEY_VOLUMEUP, }, /* "right" */
{ 0x301e, KEY_SUBTITLE, }, /* "cc" */
{ 0x3021, KEY_CHANNELDOWN, }, /* "down" */
{ 0x3022, KEY_PREVIOUS, },
{ 0x3026, KEY_SLEEP, },
{ 0x3172, KEY_REWIND, }, /* NOTE: docs wrongly say 0x30ca */
{ 0x3175, KEY_PLAY, },
{ 0x3174, KEY_FASTFORWARD, },
{ 0x3177, KEY_RECORD, },
{ 0x3176, KEY_STOP, },
{ 0x3169, KEY_PAUSE, },
{ KE_KEY, 0x300c, { KEY_POWER } }, /* NOTE: docs omit this */
{ KE_KEY, 0x3000, { KEY_NUMERIC_0 } },
{ KE_KEY, 0x3001, { KEY_NUMERIC_1 } },
{ KE_KEY, 0x3002, { KEY_NUMERIC_2 } },
{ KE_KEY, 0x3003, { KEY_NUMERIC_3 } },
{ KE_KEY, 0x3004, { KEY_NUMERIC_4 } },
{ KE_KEY, 0x3005, { KEY_NUMERIC_5 } },
{ KE_KEY, 0x3006, { KEY_NUMERIC_6 } },
{ KE_KEY, 0x3007, { KEY_NUMERIC_7 } },
{ KE_KEY, 0x3008, { KEY_NUMERIC_8 } },
{ KE_KEY, 0x3009, { KEY_NUMERIC_9 } },
{ KE_KEY, 0x3022, { KEY_ENTER } },
{ KE_KEY, 0x30ec, { KEY_MODE } }, /* "tv/vcr/..." */
{ KE_KEY, 0x300f, { KEY_SELECT } }, /* "info" */
{ KE_KEY, 0x3020, { KEY_CHANNELUP } }, /* "up" */
{ KE_KEY, 0x302e, { KEY_MENU } }, /* "in/out" */
{ KE_KEY, 0x3011, { KEY_VOLUMEDOWN } }, /* "left" */
{ KE_KEY, 0x300d, { KEY_MUTE } }, /* "ok" */
{ KE_KEY, 0x3010, { KEY_VOLUMEUP } }, /* "right" */
{ KE_KEY, 0x301e, { KEY_SUBTITLE } }, /* "cc" */
{ KE_KEY, 0x3021, { KEY_CHANNELDOWN } },/* "down" */
{ KE_KEY, 0x3022, { KEY_PREVIOUS } },
{ KE_KEY, 0x3026, { KEY_SLEEP } },
{ KE_KEY, 0x3172, { KEY_REWIND } }, /* NOTE: docs wrongly say 0x30ca */
{ KE_KEY, 0x3175, { KEY_PLAY } },
{ KE_KEY, 0x3174, { KEY_FASTFORWARD } },
{ KE_KEY, 0x3177, { KEY_RECORD } },
{ KE_KEY, 0x3176, { KEY_STOP } },
{ KE_KEY, 0x3169, { KEY_PAUSE } },
};
/*
......@@ -105,19 +102,18 @@ static struct {
*/
static irqreturn_t dm355evm_keys_irq(int irq, void *_keys)
{
struct dm355evm_keys *keys = _keys;
int status;
static u16 last_event;
struct dm355evm_keys *keys = _keys;
const struct key_entry *ke;
unsigned int keycode;
int status;
u16 event;
/* For simplicity we ignore INPUT_COUNT and just read
* events until we get the "queue empty" indicator.
* Reading INPUT_LOW decrements the count.
*/
for (;;) {
static u16 last_event;
u16 event;
int keycode;
int i;
status = dm355evm_msp_read(DM355EVM_MSP_INPUT_HIGH);
if (status < 0) {
dev_dbg(keys->dev, "input high err %d\n",
......@@ -156,14 +152,9 @@ static irqreturn_t dm355evm_keys_irq(int irq, void *_keys)
/* ignore the RC5 toggle bit */
event &= ~0x0800;
/* find the key, or leave it as unknown */
keycode = KEY_UNKNOWN;
for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) {
if (dm355evm_keys[i].event != event)
continue;
keycode = dm355evm_keys[i].keycode;
break;
}
/* find the key, or report it as unknown */
ke = sparse_keymap_entry_from_scancode(keys->input, event);
keycode = ke ? ke->keycode : KEY_UNKNOWN;
dev_dbg(keys->dev,
"input event 0x%04x--> keycode %d\n",
event, keycode);
......@@ -174,36 +165,8 @@ static irqreturn_t dm355evm_keys_irq(int irq, void *_keys)
input_report_key(keys->input, keycode, 0);
input_sync(keys->input);
}
return IRQ_HANDLED;
}
static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode)
{
u16 old_keycode;
unsigned i;
if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys))
return -EINVAL;
old_keycode = dm355evm_keys[index].keycode;
dm355evm_keys[index].keycode = keycode;
set_bit(keycode, dev->keybit);
for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) {
if (dm355evm_keys[index].keycode == old_keycode)
goto done;
}
clear_bit(old_keycode, dev->keybit);
done:
return 0;
}
static int dm355evm_getkeycode(struct input_dev *dev, int index, int *keycode)
{
if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys))
return -EINVAL;
return dm355evm_keys[index].keycode;
return IRQ_HANDLED;
}
/*----------------------------------------------------------------------*/
......@@ -213,7 +176,6 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev)
struct dm355evm_keys *keys;
struct input_dev *input;
int status;
int i;
/* allocate instance struct and input dev */
keys = kzalloc(sizeof *keys, GFP_KERNEL);
......@@ -242,31 +204,30 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev)
input->id.product = 0x0355;
input->id.version = dm355evm_msp_read(DM355EVM_MSP_FIRMREV);
input->evbit[0] = BIT(EV_KEY);
for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++)
__set_bit(dm355evm_keys[i].keycode, input->keybit);
input->setkeycode = dm355evm_setkeycode;
input->getkeycode = dm355evm_getkeycode;
status = sparse_keymap_setup(input, dm355evm_keys, NULL);
if (status)
goto fail1;
/* REVISIT: flush the event queue? */
status = request_threaded_irq(keys->irq, NULL, dm355evm_keys_irq,
IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), keys);
if (status < 0)
goto fail1;
goto fail2;
/* register */
status = input_register_device(input);
if (status < 0)
goto fail2;
goto fail3;
platform_set_drvdata(pdev, keys);
return 0;
fail2:
fail3:
free_irq(keys->irq, keys);
fail2:
sparse_keymap_free(input);
fail1:
input_free_device(input);
kfree(keys);
......@@ -280,6 +241,7 @@ static int __devexit dm355evm_keys_remove(struct platform_device *pdev)
struct dm355evm_keys *keys = platform_get_drvdata(pdev);
free_irq(keys->irq, keys);
sparse_keymap_free(keys->input);
input_unregister_device(keys->input);
kfree(keys);
......
......@@ -338,7 +338,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
pm->input = input_dev;
usb_make_path(udev, pm->phys, sizeof(pm->phys));
strlcpy(pm->phys, "/input0", sizeof(pm->phys));
strlcat(pm->phys, "/input0", sizeof(pm->phys));
spin_lock_init(&pm->lock);
......
This diff is collapsed.
......@@ -28,13 +28,16 @@
#define dbg(format, arg...) do {} while (0)
#endif
#define ALPS_DUALPOINT 0x01
#define ALPS_WHEEL 0x02
#define ALPS_FW_BK_1 0x04
#define ALPS_4BTN 0x08
#define ALPS_OLDPROTO 0x10
#define ALPS_PASS 0x20
#define ALPS_FW_BK_2 0x40
#define ALPS_OLDPROTO 0x01 /* old style input */
#define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */
#define ALPS_PASS 0x04 /* device has a pass-through port */
#define ALPS_WHEEL 0x08 /* hardware wheel present */
#define ALPS_FW_BK_1 0x10 /* front & back buttons present */
#define ALPS_FW_BK_2 0x20 /* front & back buttons present */
#define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */
static const struct alps_model_info alps_model_data[] = {
{ { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
......@@ -56,7 +59,7 @@ static const struct alps_model_info alps_model_data[] = {
{ { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
{ { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */
{ { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 }, /* Dell Vostro 1400 */
{ { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */
};
/*
......@@ -83,6 +86,7 @@ static const struct alps_model_info alps_model_data[] = {
static void alps_process_packet(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
const struct alps_model_info *model = priv->i;
unsigned char *packet = psmouse->packet;
struct input_dev *dev = psmouse->dev;
struct input_dev *dev2 = priv->dev2;
......@@ -101,7 +105,7 @@ static void alps_process_packet(struct psmouse *psmouse)
return;
}
if (priv->i->flags & ALPS_OLDPROTO) {
if (model->flags & ALPS_OLDPROTO) {
left = packet[2] & 0x10;
right = packet[2] & 0x08;
middle = 0;
......@@ -117,12 +121,12 @@ static void alps_process_packet(struct psmouse *psmouse)
z = packet[5];
}
if (priv->i->flags & ALPS_FW_BK_1) {
if (model->flags & ALPS_FW_BK_1) {
back = packet[0] & 0x10;
forward = packet[2] & 4;
}
if (priv->i->flags & ALPS_FW_BK_2) {
if (model->flags & ALPS_FW_BK_2) {
back = packet[3] & 4;
forward = packet[2] & 4;
if ((middle = forward && back))
......@@ -132,7 +136,7 @@ static void alps_process_packet(struct psmouse *psmouse)
ges = packet[2] & 1;
fin = packet[2] & 2;
if ((priv->i->flags & ALPS_DUALPOINT) && z == 127) {
if ((model->flags & ALPS_DUALPOINT) && z == 127) {
input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x));
input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
......@@ -150,7 +154,8 @@ static void alps_process_packet(struct psmouse *psmouse)
input_report_key(dev, BTN_MIDDLE, middle);
/* Convert hardware tap to a reasonable Z value */
if (ges && !fin) z = 40;
if (ges && !fin)
z = 40;
/*
* A "tap and drag" operation is reported by the hardware as a transition
......@@ -166,8 +171,10 @@ static void alps_process_packet(struct psmouse *psmouse)
}
priv->prev_fin = fin;
if (z > 30) input_report_key(dev, BTN_TOUCH, 1);
if (z < 25) input_report_key(dev, BTN_TOUCH, 0);
if (z > 30)
input_report_key(dev, BTN_TOUCH, 1);
if (z < 25)
input_report_key(dev, BTN_TOUCH, 0);
if (z > 0) {
input_report_abs(dev, ABS_X, x);
......@@ -177,14 +184,21 @@ static void alps_process_packet(struct psmouse *psmouse)
input_report_abs(dev, ABS_PRESSURE, z);
input_report_key(dev, BTN_TOOL_FINGER, z > 0);
if (priv->i->flags & ALPS_WHEEL)
if (model->flags & ALPS_WHEEL)
input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07));
if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
input_report_key(dev, BTN_FORWARD, forward);
input_report_key(dev, BTN_BACK, back);
}
if (model->flags & ALPS_FOUR_BUTTONS) {
input_report_key(dev, BTN_0, packet[2] & 4);
input_report_key(dev, BTN_1, packet[0] & 0x10);
input_report_key(dev, BTN_2, packet[3] & 4);
input_report_key(dev, BTN_3, packet[0] & 0x20);
}
input_sync(dev);
}
......@@ -393,15 +407,12 @@ static int alps_poll(struct psmouse *psmouse)
return 0;
}
static int alps_hw_init(struct psmouse *psmouse, int *version)
static int alps_hw_init(struct psmouse *psmouse)
{
struct alps_data *priv = psmouse->private;
const struct alps_model_info *model = priv->i;
priv->i = alps_get_model(psmouse, version);
if (!priv->i)
return -1;
if ((priv->i->flags & ALPS_PASS) &&
if ((model->flags & ALPS_PASS) &&
alps_passthrough_mode(psmouse, true)) {
return -1;
}
......@@ -416,7 +427,7 @@ static int alps_hw_init(struct psmouse *psmouse, int *version)
return -1;
}
if ((priv->i->flags & ALPS_PASS) &&
if ((model->flags & ALPS_PASS) &&
alps_passthrough_mode(psmouse, false)) {
return -1;
}
......@@ -432,12 +443,15 @@ static int alps_hw_init(struct psmouse *psmouse, int *version)
static int alps_reconnect(struct psmouse *psmouse)
{
const struct alps_model_info *model;
psmouse_reset(psmouse);
if (alps_hw_init(psmouse, NULL))
model = alps_get_model(psmouse, NULL);
if (!model)
return -1;
return 0;
return alps_hw_init(psmouse);
}
static void alps_disconnect(struct psmouse *psmouse)
......@@ -452,6 +466,7 @@ static void alps_disconnect(struct psmouse *psmouse)
int alps_init(struct psmouse *psmouse)
{
struct alps_data *priv;
const struct alps_model_info *model;
struct input_dev *dev1 = psmouse->dev, *dev2;
int version;
......@@ -463,33 +478,48 @@ int alps_init(struct psmouse *psmouse)
priv->dev2 = dev2;
psmouse->private = priv;
if (alps_hw_init(psmouse, &version))
model = alps_get_model(psmouse, &version);
if (!model)
goto init_fail;
priv->i = model;
if (alps_hw_init(psmouse))
goto init_fail;
dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY);
dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER);
dev1->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
dev1->keybit[BIT_WORD(BTN_LEFT)] |=
BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0);
input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0);
input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
if (priv->i->flags & ALPS_WHEEL) {
if (model->flags & ALPS_WHEEL) {
dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL);
dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL);
}
if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD);
dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK);
}
if (model->flags & ALPS_FOUR_BUTTONS) {
dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0);
dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
} else {
dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE);
}
snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys);
dev2->phys = priv->phys;
dev2->name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
dev2->name = (model->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
dev2->id.bustype = BUS_I8042;
dev2->id.vendor = 0x0002;
dev2->id.product = PSMOUSE_ALPS;
......@@ -497,9 +527,9 @@ int alps_init(struct psmouse *psmouse)
dev2->dev.parent = &psmouse->ps2dev.serio->dev;
dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
dev2->relbit[BIT_WORD(REL_X)] |= BIT_MASK(REL_X) | BIT_MASK(REL_Y);
dev2->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) |
BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
dev2->keybit[BIT_WORD(BTN_LEFT)] =
BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
if (input_register_device(priv->dev2))
goto init_fail;
......
......@@ -420,6 +420,7 @@ static void elantech_set_input_params(struct psmouse *psmouse)
__set_bit(EV_KEY, dev->evbit);
__set_bit(EV_ABS, dev->evbit);
__clear_bit(EV_REL, dev->evbit);
__set_bit(BTN_LEFT, dev->keybit);
__set_bit(BTN_RIGHT, dev->keybit);
......
......@@ -430,19 +430,6 @@ static int hgpk_register(struct psmouse *psmouse)
struct input_dev *dev = psmouse->dev;
int err;
/* unset the things that psmouse-base sets which we don't have */
__clear_bit(BTN_MIDDLE, dev->keybit);
/* set the things we do have */
__set_bit(EV_KEY, dev->evbit);
__set_bit(EV_REL, dev->evbit);
__set_bit(REL_X, dev->relbit);
__set_bit(REL_Y, dev->relbit);
__set_bit(BTN_LEFT, dev->keybit);
__set_bit(BTN_RIGHT, dev->keybit);
/* register handlers */
psmouse->protocol_handler = hgpk_process_byte;
psmouse->poll = hgpk_poll;
......
......@@ -25,11 +25,13 @@ struct lifebook_data {
char phys[32];
};
static bool lifebook_present;
static const char *desired_serio_phys;
static int lifebook_set_serio_phys(const struct dmi_system_id *d)
static int lifebook_limit_serio3(const struct dmi_system_id *d)
{
desired_serio_phys = d->driver_data;
desired_serio_phys = "isa0060/serio3";
return 0;
}
......@@ -41,53 +43,53 @@ static int lifebook_set_6byte_proto(const struct dmi_system_id *d)
return 0;
}
static const struct dmi_system_id lifebook_dmi_table[] = {
static const struct dmi_system_id __initconst lifebook_dmi_table[] = {
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
{
.ident = "FLORA-ie 55mi",
/* FLORA-ie 55mi */
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "FLORA-ie 55mi"),
},
},
{
.ident = "LifeBook B",
/* LifeBook B */
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"),
},
},
{
.ident = "Lifebook B",
/* Lifebook B */
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
},
},
{
.ident = "Lifebook B-2130",
/* Lifebook B-2130 */
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "ZEPHYR"),
},
},
{
.ident = "Lifebook B213x/B2150",
/* Lifebook B213x/B2150 */
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"),
},
},
{
.ident = "Zephyr",
/* Zephyr */
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"),
},
},
{
.ident = "CF-18",
/* Panasonic CF-18 */
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"),
},
.callback = lifebook_set_serio_phys,
.driver_data = "isa0060/serio3",
.callback = lifebook_limit_serio3,
},
{
.ident = "Panasonic CF-28",
/* Panasonic CF-28 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
DMI_MATCH(DMI_PRODUCT_NAME, "CF-28"),
......@@ -95,7 +97,7 @@ static const struct dmi_system_id lifebook_dmi_table[] = {
.callback = lifebook_set_6byte_proto,
},
{
.ident = "Panasonic CF-29",
/* Panasonic CF-29 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
......@@ -103,21 +105,27 @@ static const struct dmi_system_id lifebook_dmi_table[] = {
.callback = lifebook_set_6byte_proto,
},
{
.ident = "CF-72",
/* Panasonic CF-72 */
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "CF-72"),
},
.callback = lifebook_set_6byte_proto,
},
{
.ident = "Lifebook B142",
/* Lifebook B142 */
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"),
},
},
{ }
#endif
};
void __init lifebook_module_init(void)
{
lifebook_present = dmi_check_system(lifebook_dmi_table);
}
static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse)
{
struct lifebook_data *priv = psmouse->private;
......@@ -198,10 +206,10 @@ static int lifebook_absolute_mode(struct psmouse *psmouse)
return -1;
/*
Enable absolute output -- ps2_command fails always but if
you leave this call out the touchsreen will never send
absolute coordinates
*/
* Enable absolute output -- ps2_command fails always but if
* you leave this call out the touchsreen will never send
* absolute coordinates
*/
param = lifebook_use_6byte_proto ? 0x08 : 0x07;
ps2_command(ps2dev, &param, PSMOUSE_CMD_SETRES);
......@@ -243,7 +251,7 @@ static void lifebook_disconnect(struct psmouse *psmouse)
int lifebook_detect(struct psmouse *psmouse, bool set_properties)
{
if (!dmi_check_system(lifebook_dmi_table))
if (!lifebook_present)
return -1;
if (desired_serio_phys &&
......@@ -283,8 +291,8 @@ static int lifebook_create_relative_device(struct psmouse *psmouse)
dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
dev2->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) |
BIT_MASK(BTN_RIGHT);
dev2->keybit[BIT_WORD(BTN_LEFT)] =
BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
error = input_register_device(priv->dev2);
if (error)
......@@ -309,6 +317,7 @@ int lifebook_init(struct psmouse *psmouse)
dev1->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
dev1->relbit[0] = 0;
dev1->keybit[BIT_WORD(BTN_MOUSE)] = 0;
dev1->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(dev1, ABS_X, 0, max_coord, 0, 0);
input_set_abs_params(dev1, ABS_Y, 0, max_coord, 0, 0);
......
......@@ -12,9 +12,13 @@
#define _LIFEBOOK_H
#ifdef CONFIG_MOUSE_PS2_LIFEBOOK
void lifebook_module_init(void);
int lifebook_detect(struct psmouse *psmouse, bool set_properties);
int lifebook_init(struct psmouse *psmouse);
#else
inline void lifebook_module_init(void)
{
}
inline int lifebook_detect(struct psmouse *psmouse, bool set_properties)
{
return -ENOSYS;
......
......@@ -404,8 +404,8 @@ int ps2pp_init(struct psmouse *psmouse, bool set_properties)
}
}
if (buttons < 3)
__clear_bit(BTN_MIDDLE, psmouse->dev->keybit);
if (buttons >= 3)
__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
if (model_info)
ps2pp_set_model_properties(psmouse, model_info, use_ps2pp);
......
......@@ -425,6 +425,7 @@ static int genius_detect(struct psmouse *psmouse, bool set_properties)
return -1;
if (set_properties) {
__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
__set_bit(BTN_EXTRA, psmouse->dev->keybit);
__set_bit(BTN_SIDE, psmouse->dev->keybit);
__set_bit(REL_WHEEL, psmouse->dev->relbit);
......@@ -460,8 +461,10 @@ static int intellimouse_detect(struct psmouse *psmouse, bool set_properties)
__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
__set_bit(REL_WHEEL, psmouse->dev->relbit);
if (!psmouse->vendor) psmouse->vendor = "Generic";
if (!psmouse->name) psmouse->name = "Wheel Mouse";
if (!psmouse->vendor)
psmouse->vendor = "Generic";
if (!psmouse->name)
psmouse->name = "Wheel Mouse";
psmouse->pktsize = 4;
}
......@@ -504,8 +507,10 @@ static int im_explorer_detect(struct psmouse *psmouse, bool set_properties)
__set_bit(BTN_SIDE, psmouse->dev->keybit);
__set_bit(BTN_EXTRA, psmouse->dev->keybit);
if (!psmouse->vendor) psmouse->vendor = "Generic";
if (!psmouse->name) psmouse->name = "Explorer Mouse";
if (!psmouse->vendor)
psmouse->vendor = "Generic";
if (!psmouse->name)
psmouse->name = "Explorer Mouse";
psmouse->pktsize = 4;
}
......@@ -536,6 +541,7 @@ static int thinking_detect(struct psmouse *psmouse, bool set_properties)
return -1;
if (set_properties) {
__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
__set_bit(BTN_EXTRA, psmouse->dev->keybit);
psmouse->vendor = "Kensington";
......@@ -551,8 +557,16 @@ static int thinking_detect(struct psmouse *psmouse, bool set_properties)
static int ps2bare_detect(struct psmouse *psmouse, bool set_properties)
{
if (set_properties) {
if (!psmouse->vendor) psmouse->vendor = "Generic";
if (!psmouse->name) psmouse->name = "Mouse";
if (!psmouse->vendor)
psmouse->vendor = "Generic";
if (!psmouse->name)
psmouse->name = "Mouse";
/*
* We have no way of figuring true number of buttons so let's
* assume that the device has 3.
*/
__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
}
return 0;
......@@ -567,6 +581,8 @@ static int cortron_detect(struct psmouse *psmouse, bool set_properties)
if (set_properties) {
psmouse->vendor = "Cortron";
psmouse->name = "PS/2 Trackball";
__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
__set_bit(BTN_SIDE, psmouse->dev->keybit);
}
......@@ -1184,15 +1200,16 @@ static void psmouse_disconnect(struct serio *serio)
mutex_unlock(&psmouse_mutex);
}
static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse_protocol *proto)
static int psmouse_switch_protocol(struct psmouse *psmouse,
const struct psmouse_protocol *proto)
{
struct input_dev *input_dev = psmouse->dev;
input_dev->dev.parent = &psmouse->ps2dev.serio->dev;
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
input_dev->keybit[BIT_WORD(BTN_MOUSE)] =
BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
psmouse->set_rate = psmouse_set_rate;
......@@ -1209,8 +1226,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse
return -1;
psmouse->type = proto->type;
}
else
} else
psmouse->type = psmouse_extensions(psmouse,
psmouse_max_proto, true);
......@@ -1680,6 +1696,9 @@ static int __init psmouse_init(void)
{
int err;
lifebook_module_init();
synaptics_module_init();
kpsmoused_wq = create_singlethread_workqueue("kpsmoused");
if (!kpsmoused_wq) {
printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n");
......
......@@ -836,6 +836,7 @@ int fsp_init(struct psmouse *psmouse)
priv->flags |= FSPDRV_FLAG_EN_OPC;
/* Set up various supported input event bits */
__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
__set_bit(BTN_BACK, psmouse->dev->keybit);
__set_bit(BTN_FORWARD, psmouse->dev->keybit);
__set_bit(REL_WHEEL, psmouse->dev->relbit);
......
......@@ -24,6 +24,7 @@
*/
#include <linux/module.h>
#include <linux/dmi.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/libps2.h>
......@@ -629,25 +630,26 @@ static int synaptics_reconnect(struct psmouse *psmouse)
return 0;
}
#if defined(__i386__)
#include <linux/dmi.h>
static const struct dmi_system_id toshiba_dmi_table[] = {
static bool impaired_toshiba_kbc;
static const struct dmi_system_id __initconst toshiba_dmi_table[] = {
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
{
.ident = "Toshiba Satellite",
/* Toshiba Satellite */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"),
},
},
{
.ident = "Toshiba Dynabook",
/* Toshiba Dynabook */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"),
},
},
{
.ident = "Toshiba Portege M300",
/* Toshiba Portege M300 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
......@@ -655,7 +657,7 @@ static const struct dmi_system_id toshiba_dmi_table[] = {
},
{
.ident = "Toshiba Portege M300",
/* Toshiba Portege M300 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"),
......@@ -664,8 +666,13 @@ static const struct dmi_system_id toshiba_dmi_table[] = {
},
{ }
};
#endif
};
void __init synaptics_module_init(void)
{
impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
}
int synaptics_init(struct psmouse *psmouse)
{
......@@ -718,18 +725,16 @@ int synaptics_init(struct psmouse *psmouse)
if (SYN_CAP_PASS_THROUGH(priv->capabilities))
synaptics_pt_create(psmouse);
#if defined(__i386__)
/*
* Toshiba's KBC seems to have trouble handling data from
* Synaptics as full rate, switch to lower rate which is roughly
* thye same as rate of standard PS/2 mouse.
*/
if (psmouse->rate >= 80 && dmi_check_system(toshiba_dmi_table)) {
if (psmouse->rate >= 80 && impaired_toshiba_kbc) {
printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n",
dmi_get_system_info(DMI_PRODUCT_NAME));
psmouse->rate = 40;
}
#endif
return 0;
......@@ -740,6 +745,10 @@ int synaptics_init(struct psmouse *psmouse)
#else /* CONFIG_MOUSE_PS2_SYNAPTICS */
void __init synaptics_module_init(void)
{
}
int synaptics_init(struct psmouse *psmouse)
{
return -ENOSYS;
......
......@@ -105,6 +105,7 @@ struct synaptics_data {
int scroll;
};
void synaptics_module_init(void);
int synaptics_detect(struct psmouse *psmouse, bool set_properties);
int synaptics_init(struct psmouse *psmouse);
void synaptics_reset(struct psmouse *psmouse);
......
......@@ -420,8 +420,8 @@ static void synaptics_i2c_check_params(struct synaptics_i2c *touch)
}
/* Control the Device polling rate / Work Handler sleep time */
unsigned long synaptics_i2c_adjust_delay(struct synaptics_i2c *touch,
bool have_data)
static unsigned long synaptics_i2c_adjust_delay(struct synaptics_i2c *touch,
bool have_data)
{
unsigned long delay, nodata_count_thres;
......@@ -520,7 +520,7 @@ static void synaptics_i2c_set_input_params(struct synaptics_i2c *touch)
__set_bit(BTN_LEFT, input->keybit);
}
struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client)
static struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client)
{
struct synaptics_i2c *touch;
......
......@@ -86,7 +86,8 @@ int touchkit_ps2_detect(struct psmouse *psmouse, bool set_properties)
if (set_properties) {
dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
__set_bit(BTN_TOUCH, dev->keybit);
dev->keybit[BIT_WORD(BTN_MOUSE)] = 0;
dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0);
input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0);
......
......@@ -284,7 +284,6 @@ static int trackpoint_reconnect(struct psmouse *psmouse)
int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
{
struct trackpoint_data *priv;
struct ps2dev *ps2dev = &psmouse->ps2dev;
unsigned char firmware_id;
unsigned char button_info;
......@@ -301,8 +300,8 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
button_info = 0;
}
psmouse->private = priv = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
if (!priv)
psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
if (!psmouse->private)
return -1;
psmouse->vendor = "IBM";
......@@ -311,7 +310,10 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
psmouse->reconnect = trackpoint_reconnect;
psmouse->disconnect = trackpoint_disconnect;
trackpoint_defaults(priv);
if ((button_info & 0x0f) >= 3)
__set_bit(BTN_MIDDLE, psmouse->dev->keybit);
trackpoint_defaults(psmouse->private);
trackpoint_sync(psmouse);
error = sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group);
......@@ -319,7 +321,8 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
printk(KERN_ERR
"trackpoint.c: failed to create sysfs attributes, error: %d\n",
error);
kfree(priv);
kfree(psmouse->private);
psmouse->private = NULL;
return -1;
}
......
This diff is collapsed.
......@@ -201,4 +201,12 @@ config SERIO_XILINX_XPS_PS2
To compile this driver as a module, choose M here: the
module will be called xilinx_ps2.
config SERIO_ALTERA_PS2
tristate "Altera UP PS/2 controller"
help
Say Y here if you have Altera University Program PS/2 ports.
To compile this driver as a module, choose M here: the
module will be called altera_ps2.
endif
......@@ -22,3 +22,4 @@ obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o
obj-$(CONFIG_SERIO_LIBPS2) += libps2.o
obj-$(CONFIG_SERIO_RAW) += serio_raw.o
obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o
obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o
/*
* Altera University Program PS2 controller driver
*
* Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw>
*
* Based on sa1111ps2.c, which is:
* Copyright (C) 2002 Russell King
*
* 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.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#define DRV_NAME "altera_ps2"
struct ps2if {
struct serio *io;
struct resource *iomem_res;
void __iomem *base;
unsigned irq;
};
/*
* Read all bytes waiting in the PS2 port. There should be
* at the most one, but we loop for safety.
*/
static irqreturn_t altera_ps2_rxint(int irq, void *dev_id)
{
struct ps2if *ps2if = dev_id;
unsigned int status;
int handled = IRQ_NONE;
while ((status = readl(ps2if->base)) & 0xffff0000) {
serio_interrupt(ps2if->io, status & 0xff, 0);
handled = IRQ_HANDLED;
}
return handled;
}
/*
* Write a byte to the PS2 port.
*/
static int altera_ps2_write(struct serio *io, unsigned char val)
{
struct ps2if *ps2if = io->port_data;
writel(val, ps2if->base);
return 0;
}
static int altera_ps2_open(struct serio *io)
{
struct ps2if *ps2if = io->port_data;
/* clear fifo */
while (readl(ps2if->base) & 0xffff0000)
/* empty */;
writel(1, ps2if->base + 4); /* enable rx irq */
return 0;
}
static void altera_ps2_close(struct serio *io)
{
struct ps2if *ps2if = io->port_data;
writel(0, ps2if->base); /* disable rx irq */
}
/*
* Add one device to this driver.
*/
static int altera_ps2_probe(struct platform_device *pdev)
{
struct ps2if *ps2if;
struct serio *serio;
int error;
ps2if = kzalloc(sizeof(struct ps2if), GFP_KERNEL);
serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!ps2if || !serio) {
error = -ENOMEM;
goto err_free_mem;
}
serio->id.type = SERIO_8042;
serio->write = altera_ps2_write;
serio->open = altera_ps2_open;
serio->close = altera_ps2_close;
strlcpy(serio->name, dev_name(&pdev->dev), sizeof(serio->name));
strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
serio->port_data = ps2if;
serio->dev.parent = &pdev->dev;
ps2if->io = serio;
ps2if->iomem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (ps2if->iomem_res == NULL) {
error = -ENOENT;
goto err_free_mem;
}
ps2if->irq = platform_get_irq(pdev, 0);
if (ps2if->irq < 0) {
error = -ENXIO;
goto err_free_mem;
}
if (!request_mem_region(ps2if->iomem_res->start,
resource_size(ps2if->iomem_res), pdev->name)) {
error = -EBUSY;
goto err_free_mem;
}
ps2if->base = ioremap(ps2if->iomem_res->start,
resource_size(ps2if->iomem_res));
if (!ps2if->base) {
error = -ENOMEM;
goto err_free_res;
}
error = request_irq(ps2if->irq, altera_ps2_rxint, 0, pdev->name, ps2if);
if (error) {
dev_err(&pdev->dev, "could not allocate IRQ %d: %d\n",
ps2if->irq, error);
goto err_unmap;
}
dev_info(&pdev->dev, "base %p, irq %d\n", ps2if->base, ps2if->irq);
serio_register_port(ps2if->io);
platform_set_drvdata(pdev, ps2if);
return 0;
err_unmap:
iounmap(ps2if->base);
err_free_res:
release_mem_region(ps2if->iomem_res->start,
resource_size(ps2if->iomem_res));
err_free_mem:
kfree(ps2if);
kfree(serio);
return error;
}
/*
* Remove one device from this driver.
*/
static int altera_ps2_remove(struct platform_device *pdev)
{
struct ps2if *ps2if = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
serio_unregister_port(ps2if->io);
free_irq(ps2if->irq, ps2if);
iounmap(ps2if->base);
release_mem_region(ps2if->iomem_res->start,
resource_size(ps2if->iomem_res));
kfree(ps2if);
return 0;
}
/*
* Our device driver structure
*/
static struct platform_driver altera_ps2_driver = {
.probe = altera_ps2_probe,
.remove = altera_ps2_remove,
.driver = {
.name = DRV_NAME,
},
};
static int __init altera_ps2_init(void)
{
return platform_driver_register(&altera_ps2_driver);
}
static void __exit altera_ps2_exit(void)
{
platform_driver_unregister(&altera_ps2_driver);
}
module_init(altera_ps2_init);
module_exit(altera_ps2_exit);
MODULE_DESCRIPTION("Altera University Program PS2 controller driver");
MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
This diff is collapsed.
/*
* Generic support for sparse keymaps
*
* Copyright (c) 2009 Dmitry Torokhov
*
* Derived from wistron button driver:
* Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
* Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
* Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
*
* 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.
*/
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
MODULE_DESCRIPTION("Generic support for sparse keymaps");
MODULE_LICENSE("GPL v2");
MODULE_VERSION("0.1");
/**
* sparse_keymap_entry_from_scancode - perform sparse keymap lookup
* @dev: Input device using sparse keymap
* @code: Scan code
*
* This function is used to perform &struct key_entry lookup in an
* input device using sparse keymap.
*/
struct key_entry *sparse_keymap_entry_from_scancode(struct input_dev *dev,
unsigned int code)
{
struct key_entry *key;
for (key = dev->keycode; key->type != KE_END; key++)
if (code == key->code)
return key;
return NULL;
}
EXPORT_SYMBOL(sparse_keymap_entry_from_scancode);
/**
* sparse_keymap_entry_from_keycode - perform sparse keymap lookup
* @dev: Input device using sparse keymap
* @keycode: Key code
*
* This function is used to perform &struct key_entry lookup in an
* input device using sparse keymap.
*/
struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev,
unsigned int keycode)
{
struct key_entry *key;
for (key = dev->keycode; key->type != KE_END; key++)
if (key->type == KE_KEY && keycode == key->keycode)
return key;
return NULL;
}
EXPORT_SYMBOL(sparse_keymap_entry_from_keycode);
static int sparse_keymap_getkeycode(struct input_dev *dev,
int scancode, int *keycode)
{
const struct key_entry *key =
sparse_keymap_entry_from_scancode(dev, scancode);
if (key && key->type == KE_KEY) {
*keycode = key->keycode;
return 0;
}
return -EINVAL;
}
static int sparse_keymap_setkeycode(struct input_dev *dev,
int scancode, int keycode)
{
struct key_entry *key;
int old_keycode;
if (keycode < 0 || keycode > KEY_MAX)
return -EINVAL;
key = sparse_keymap_entry_from_scancode(dev, scancode);
if (key && key->type == KE_KEY) {
old_keycode = key->keycode;
key->keycode = keycode;
set_bit(keycode, dev->keybit);
if (!sparse_keymap_entry_from_keycode(dev, old_keycode))
clear_bit(old_keycode, dev->keybit);
return 0;
}
return -EINVAL;
}
/**
* sparse_keymap_setup - set up sparse keymap for an input device
* @dev: Input device
* @keymap: Keymap in form of array of &key_entry structures ending
* with %KE_END type entry
* @setup: Function that can be used to adjust keymap entries
* depending on device's deeds, may be %NULL
*
* The function calculates size and allocates copy of the original
* keymap after which sets up input device event bits appropriately.
* Before destroying input device allocated keymap should be freed
* with a call to sparse_keymap_free().
*/
int sparse_keymap_setup(struct input_dev *dev,
const struct key_entry *keymap,
int (*setup)(struct input_dev *, struct key_entry *))
{
size_t map_size = 1; /* to account for the last KE_END entry */
const struct key_entry *e;
struct key_entry *map, *entry;
int i;
int error;
for (e = keymap; e->type != KE_END; e++)
map_size++;
map = kcalloc(map_size, sizeof (struct key_entry), GFP_KERNEL);
if (!map)
return -ENOMEM;
memcpy(map, keymap, map_size * sizeof (struct key_entry));
for (i = 0; i < map_size; i++) {
entry = &map[i];
if (setup) {
error = setup(dev, entry);
if (error)
goto err_out;
}
switch (entry->type) {
case KE_KEY:
__set_bit(EV_KEY, dev->evbit);
__set_bit(entry->keycode, dev->keybit);
break;
case KE_SW:
__set_bit(EV_SW, dev->evbit);
__set_bit(entry->sw.code, dev->swbit);
break;
}
}
dev->keycode = map;
dev->keycodemax = map_size;
dev->getkeycode = sparse_keymap_getkeycode;
dev->setkeycode = sparse_keymap_setkeycode;
return 0;
err_out:
kfree(keymap);
return error;
}
EXPORT_SYMBOL(sparse_keymap_setup);
/**
* sparse_keymap_free - free memory allocated for sparse keymap
* @dev: Input device using sparse keymap
*
* This function is used to free memory allocated by sparse keymap
* in an input device that was set up by sparse_keymap_setup().
*/
void sparse_keymap_free(struct input_dev *dev)
{
kfree(dev->keycode);
dev->keycode = NULL;
dev->keycodemax = 0;
dev->getkeycode = NULL;
dev->setkeycode = NULL;
}
EXPORT_SYMBOL(sparse_keymap_free);
/**
* sparse_keymap_report_entry - report event corresponding to given key entry
* @dev: Input device for which event should be reported
* @ke: key entry describing event
* @value: Value that should be reported (ignored by %KE_SW entries)
* @autorelease: Signals whether release event should be emitted for %KE_KEY
* entries right after reporting press event, ignored by all other
* entries
*
* This function is used to report input event described by given
* &struct key_entry.
*/
void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *ke,
unsigned int value, bool autorelease)
{
switch (ke->type) {
case KE_KEY:
input_report_key(dev, ke->keycode, value);
input_sync(dev);
if (value && autorelease) {
input_report_key(dev, ke->keycode, 0);
input_sync(dev);
}
break;
case KE_SW:
value = ke->sw.value;
/* fall through */
case KE_VSW:
input_report_switch(dev, ke->sw.code, value);
break;
}
}
EXPORT_SYMBOL(sparse_keymap_report_entry);
/**
* sparse_keymap_report_event - report event corresponding to given scancode
* @dev: Input device using sparse keymap
* @code: Scan code
* @value: Value that should be reported (ignored by %KE_SW entries)
* @autorelease: Signals whether release event should be emitted for %KE_KEY
* entries right after reporting press event, ignored by all other
* entries
*
* This function is used to perform lookup in an input device using sparse
* keymap and report corresponding event. Returns %true if lookup was
* successful and %false otherwise.
*/
bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code,
unsigned int value, bool autorelease)
{
const struct key_entry *ke =
sparse_keymap_entry_from_scancode(dev, code);
if (ke) {
sparse_keymap_report_entry(dev, ke, value, autorelease);
return true;
}
return false;
}
EXPORT_SYMBOL(sparse_keymap_report_event);
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -215,5 +215,6 @@ static inline void serio_unpin_driver(struct serio *serio)
#define SERIO_INEXIO 0x37
#define SERIO_TOUCHIT213 0x38
#define SERIO_W8001 0x39
#define SERIO_DYNAPRO 0x3a
#endif
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment