Commit f2e1d89f 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: (40 commits)
  Input: use full RCU API
  Input: remove tsdev interface
  Input: add support for Blackfin BF54x Keypad controller
  Input: appletouch - another fix for idle reset logic
  HWMON: hdaps - switch to using input-polldev
  Input: add support for SEGA Dreamcast keyboard
  Input: omap-keyboard - don't pretend we support changing keymap
  Input: lifebook - fix X and Y axis range
  Input: usbtouchscreen - add support for GeneralTouch devices
  Input: fix open count handling in input interfaces
  Input: keyboard - add CapsShift lock
  Input: adbhid - produce all CapsLock key events
  Input: ALPS - add signature for ThinkPad R61
  Input: jornada720_kbd - send MSC_SCAN events
  Input: add support for the HP Jornada 7xx (710/720/728) touchscreen
  Input: add support for HP Jornada 7xx onboard keyboard
  Input: add support for HP Jornada onboard keyboard (HP6XX)
  Input: ucb1400_ts - use schedule_timeout_uninterruptible
  Input: xpad - fix dependancy on LEDS class
  Input: auto-select INPUT for MAC_EMUMOUSEBTN option
  ...

Resolved conflicts manually in drivers/hwmon/applesmc.c: converting from
a class device to a device and converting to use input-polldev created a
few apparently trivial clashes..
parents 85ffdd28 82ba56c2
......@@ -205,20 +205,6 @@ Who: Len Brown <len.brown@intel.com>
---------------------------
What: Compaq touchscreen device emulation
When: Oct 2007
Files: drivers/input/tsdev.c
Why: The code says it was obsolete when it was written in 2001.
tslib is a userspace library which does anything tsdev can do and
much more besides in userspace where this code belongs. There is no
longer any need for tsdev and applications should have converted to
use tslib by now.
The name "tsdev" is also extremely confusing and lots of people have
it loaded when they don't need/use it.
Who: Richard Purdie <rpurdie@rpsys.net>
---------------------------
What: i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers
When: September 2007
Why: Obsolete. The new i2c-gpio driver replaces all hardware-specific
......
......@@ -1890,9 +1890,6 @@ and is between 256 and 4096 characters. It is defined in the file
Format:
<io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq>
tsdev.xres= [TS] Horizontal screen resolution.
tsdev.yres= [TS] Vertical screen resolution.
turbografx.map[2|3]= [HW,JOY]
TurboGraFX parallel port interface
Format:
......
......@@ -88,7 +88,7 @@ static struct platform_device bf54x_lq043_device = {
#endif
#if defined(CONFIG_KEYBOARD_BFIN) || defined(CONFIG_KEYBOARD_BFIN_MODULE)
static int bf548_keymap[] = {
static const unsigned int bf548_keymap[] = {
KEYVAL(0, 0, KEY_ENTER),
KEYVAL(0, 1, KEY_HELP),
KEYVAL(0, 2, KEY_0),
......
/*
* linux/drivers/char/ec3104_keyb.c
*
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
*
* based on linux/drivers/char/pc_keyb.c, which had the following comments:
*
* Separation of the PC low-level part by Geert Uytterhoeven, May 1997
* See keyboard.c for the whole history.
*
* Major cleanup by Martin Mares, May 1997
*
* Combined the keyboard and PS/2 mouse handling into one file,
* because they share the same hardware.
* Johan Myreen <jem@iki.fi> 1998-10-08.
*
* Code fixes to handle mouse ACKs properly.
* C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
*/
/* EC3104 note:
* This code was written without any documentation about the EC3104 chip. While
* I hope I got most of the basic functionality right, the register names I use
* are most likely completely different from those in the chip documentation.
*
* If you have any further information about the EC3104, please tell me
* (prumpf@tux.org).
*/
#include <linux/spinlock.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/mm.h>
#include <linux/signal.h>
#include <linux/init.h>
#include <linux/kbd_ll.h>
#include <linux/delay.h>
#include <linux/random.h>
#include <linux/poll.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/kbd_kern.h>
#include <linux/bitops.h>
#include <asm/keyboard.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/ec3104.h>
#include <asm/io.h>
/* Some configuration switches are present in the include file... */
#include <linux/pc_keyb.h>
#define MSR_CTS 0x10
#define MCR_RTS 0x02
#define LSR_DR 0x01
#define LSR_BOTH_EMPTY 0x60
static struct e5_struct {
u8 packet[8];
int pos;
int length;
u8 cached_mcr;
u8 last_msr;
} ec3104_keyb;
/* Simple translation table for the SysRq keys */
#ifdef CONFIG_MAGIC_SYSRQ
unsigned char ec3104_kbd_sysrq_xlate[128] =
"\000\0331234567890-=\177\t" /* 0x00 - 0x0f */
"qwertyuiop[]\r\000as" /* 0x10 - 0x1f */
"dfghjkl;'`\000\\zxcv" /* 0x20 - 0x2f */
"bnm,./\000*\000 \000\201\202\203\204\205" /* 0x30 - 0x3f */
"\206\207\210\211\212\000\000789-456+1" /* 0x40 - 0x4f */
"230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
"\r\000/"; /* 0x60 - 0x6f */
#endif
static void kbd_write_command_w(int data);
static void kbd_write_output_w(int data);
#ifdef CONFIG_PSMOUSE
static void aux_write_ack(int val);
static void __aux_write_ack(int val);
#endif
static DEFINE_SPINLOCK(kbd_controller_lock);
static unsigned char handle_kbd_event(void);
/* used only by send_data - set by keyboard_interrupt */
static volatile unsigned char reply_expected;
static volatile unsigned char acknowledge;
static volatile unsigned char resend;
int ec3104_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
{
return 0;
}
int ec3104_kbd_getkeycode(unsigned int scancode)
{
return 0;
}
/* yes, it probably would be faster to use an array. I don't care. */
static inline unsigned char ec3104_scan2key(unsigned char scancode)
{
switch (scancode) {
case 1: /* '`' */
return 41;
case 2 ... 27:
return scancode;
case 28: /* '\\' */
return 43;
case 29 ... 39:
return scancode + 1;
case 40: /* '\r' */
return 28;
case 41 ... 50:
return scancode + 3;
case 51: /* ' ' */
return 57;
case 52: /* escape */
return 1;
case 54: /* insert/delete (labelled delete) */
/* this should arguably be 110, but I'd like to have ctrl-alt-del
* working with a standard keymap */
return 111;
case 55: /* left */
return 105;
case 56: /* home */
return 102;
case 57: /* end */
return 107;
case 58: /* up */
return 103;
case 59: /* down */
return 108;
case 60: /* pgup */
return 104;
case 61: /* pgdown */
return 109;
case 62: /* right */
return 106;
case 79 ... 88: /* f1 - f10 */
return scancode - 20;
case 89 ... 90: /* f11 - f12 */
return scancode - 2;
case 91: /* left shift */
return 42;
case 92: /* right shift */
return 54;
case 93: /* left alt */
return 56;
case 94: /* right alt */
return 100;
case 95: /* left ctrl */
return 29;
case 96: /* right ctrl */
return 97;
case 97: /* caps lock */
return 58;
case 102: /* left windows */
return 125;
case 103: /* right windows */
return 126;
case 106: /* Fn */
/* this is wrong. */
return 84;
default:
return 0;
}
}
int ec3104_kbd_translate(unsigned char scancode, unsigned char *keycode,
char raw_mode)
{
scancode &= 0x7f;
*keycode = ec3104_scan2key(scancode);
return 1;
}
char ec3104_kbd_unexpected_up(unsigned char keycode)
{
return 0200;
}
static inline void handle_keyboard_event(unsigned char scancode)
{
#ifdef CONFIG_VT
handle_scancode(scancode, !(scancode & 0x80));
#endif
tasklet_schedule(&keyboard_tasklet);
}
void ec3104_kbd_leds(unsigned char leds)
{
}
static u8 e5_checksum(u8 *packet, int count)
{
int i;
u8 sum = 0;
for (i=0; i<count; i++)
sum ^= packet[i];
if (sum & 0x80)
sum ^= 0xc0;
return sum;
}
static void e5_wait_for_cts(struct e5_struct *k)
{
u8 msr;
do {
msr = ctrl_inb(EC3104_SER4_MSR);
} while (!(msr & MSR_CTS));
}
static void e5_send_byte(u8 byte, struct e5_struct *k)
{
u8 status;
do {
status = ctrl_inb(EC3104_SER4_LSR);
} while ((status & LSR_BOTH_EMPTY) != LSR_BOTH_EMPTY);
printk("<%02x>", byte);
ctrl_outb(byte, EC3104_SER4_DATA);
do {
status = ctrl_inb(EC3104_SER4_LSR);
} while ((status & LSR_BOTH_EMPTY) != LSR_BOTH_EMPTY);
}
static int e5_send_packet(u8 *packet, int count, struct e5_struct *k)
{
int i;
disable_irq(EC3104_IRQ_SER4);
if (k->cached_mcr & MCR_RTS) {
printk("e5_send_packet: too slow\n");
enable_irq(EC3104_IRQ_SER4);
return -EAGAIN;
}
k->cached_mcr |= MCR_RTS;
ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
e5_wait_for_cts(k);
printk("p: ");
for(i=0; i<count; i++)
e5_send_byte(packet[i], k);
e5_send_byte(e5_checksum(packet, count), k);
printk("\n");
udelay(1500);
k->cached_mcr &= ~MCR_RTS;
ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
set_current_state(TASK_UNINTERRUPTIBLE);
enable_irq(EC3104_IRQ_SER4);
return 0;
}
/*
* E5 packets we know about:
* E5->host 0x80 0x05 <checksum> - resend packet
* host->E5 0x83 0x43 <contrast> - set LCD contrast
* host->E5 0x85 0x41 0x02 <brightness> 0x02 - set LCD backlight
* E5->host 0x87 <ps2 packet> 0x00 <checksum> - external PS2
* E5->host 0x88 <scancode> <checksum> - key press
*/
static void e5_receive(struct e5_struct *k)
{
k->packet[k->pos++] = ctrl_inb(EC3104_SER4_DATA);
if (k->pos == 1) {
switch(k->packet[0]) {
case 0x80:
k->length = 3;
break;
case 0x87: /* PS2 ext */
k->length = 6;
break;
case 0x88: /* keyboard */
k->length = 3;
break;
default:
k->length = 1;
printk(KERN_WARNING "unknown E5 packet %02x\n",
k->packet[0]);
}
}
if (k->pos == k->length) {
int i;
if (e5_checksum(k->packet, k->length) != 0)
printk(KERN_WARNING "E5: wrong checksum\n");
#if 0
printk("E5 packet [");
for(i=0; i<k->length; i++) {
printk("%02x ", k->packet[i]);
}
printk("(%02x)]\n", e5_checksum(k->packet, k->length-1));
#endif
switch(k->packet[0]) {
case 0x80:
case 0x88:
handle_keyboard_event(k->packet[1]);
break;
}
k->pos = k->length = 0;
}
}
static void ec3104_keyb_interrupt(int irq, void *data)
{
struct e5_struct *k = &ec3104_keyb;
u8 msr, lsr;
msr = ctrl_inb(EC3104_SER4_MSR);
if ((msr & MSR_CTS) && !(k->last_msr & MSR_CTS)) {
if (k->cached_mcr & MCR_RTS)
printk("confused: RTS already high\n");
/* CTS went high. Send RTS. */
k->cached_mcr |= MCR_RTS;
ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
} else if ((!(msr & MSR_CTS)) && (k->last_msr & MSR_CTS)) {
/* CTS went low. */
if (!(k->cached_mcr & MCR_RTS))
printk("confused: RTS already low\n");
k->cached_mcr &= ~MCR_RTS;
ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
}
k->last_msr = msr;
lsr = ctrl_inb(EC3104_SER4_LSR);
if (lsr & LSR_DR)
e5_receive(k);
}
static void ec3104_keyb_clear_state(void)
{
struct e5_struct *k = &ec3104_keyb;
u8 msr, lsr;
/* we want CTS to be low */
k->last_msr = 0;
for (;;) {
msleep(100);
msr = ctrl_inb(EC3104_SER4_MSR);
lsr = ctrl_inb(EC3104_SER4_LSR);
if (lsr & LSR_DR) {
e5_receive(k);
continue;
}
if ((msr & MSR_CTS) && !(k->last_msr & MSR_CTS)) {
if (k->cached_mcr & MCR_RTS)
printk("confused: RTS already high\n");
/* CTS went high. Send RTS. */
k->cached_mcr |= MCR_RTS;
ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
} else if ((!(msr & MSR_CTS)) && (k->last_msr & MSR_CTS)) {
/* CTS went low. */
if (!(k->cached_mcr & MCR_RTS))
printk("confused: RTS already low\n");
k->cached_mcr &= ~MCR_RTS;
ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
} else
break;
k->last_msr = msr;
continue;
}
}
void __init ec3104_kbd_init_hw(void)
{
ec3104_keyb.last_msr = ctrl_inb(EC3104_SER4_MSR);
ec3104_keyb.cached_mcr = ctrl_inb(EC3104_SER4_MCR);
ec3104_keyb_clear_state();
/* Ok, finally allocate the IRQ, and off we go.. */
request_irq(EC3104_IRQ_SER4, ec3104_keyb_interrupt, 0, "keyboard", NULL);
}
......@@ -158,6 +158,7 @@ config SENSORS_K8TEMP
config SENSORS_AMS
tristate "Apple Motion Sensor driver"
depends on PPC_PMAC && !PPC64 && INPUT && ((ADB_PMU && I2C = y) || (ADB_PMU && !I2C) || I2C) && EXPERIMENTAL
select INPUT_POLLDEV
help
Support for the motion sensor included in PowerBooks. Includes
implementations for PMU and I2C.
......@@ -701,6 +702,7 @@ config SENSORS_W83627EHF
config SENSORS_HDAPS
tristate "IBM Hard Drive Active Protection System (hdaps)"
depends on INPUT && X86
select INPUT_POLLDEV
default n
help
This driver provides support for the IBM Hard Drive Active Protection
......@@ -722,6 +724,7 @@ config SENSORS_APPLESMC
depends on INPUT && X86
select NEW_LEDS
select LEDS_CLASS
select INPUT_POLLDEV
default n
help
This driver provides support for the Apple System Management
......
......@@ -27,11 +27,11 @@ static unsigned int invert;
module_param(invert, bool, 0644);
MODULE_PARM_DESC(invert, "Invert input data on X and Y axis");
static int ams_input_kthread(void *data)
static void ams_idev_poll(struct input_polled_dev *dev)
{
struct input_dev *idev = dev->input;
s8 x, y, z;
while (!kthread_should_stop()) {
mutex_lock(&ams_info.lock);
ams_sensors(&x, &y, &z);
......@@ -40,34 +40,19 @@ static int ams_input_kthread(void *data)
y -= ams_info.ycalib;
z -= ams_info.zcalib;
input_report_abs(ams_info.idev, ABS_X, invert ? -x : x);
input_report_abs(ams_info.idev, ABS_Y, invert ? -y : y);
input_report_abs(ams_info.idev, ABS_Z, z);
input_report_abs(idev, ABS_X, invert ? -x : x);
input_report_abs(idev, ABS_Y, invert ? -y : y);
input_report_abs(idev, ABS_Z, z);
input_sync(ams_info.idev);
input_sync(idev);
mutex_unlock(&ams_info.lock);
msleep(25);
}
return 0;
}
static int ams_input_open(struct input_dev *dev)
{
ams_info.kthread = kthread_run(ams_input_kthread, NULL, "kams");
return IS_ERR(ams_info.kthread) ? PTR_ERR(ams_info.kthread) : 0;
}
static void ams_input_close(struct input_dev *dev)
{
kthread_stop(ams_info.kthread);
}
/* Call with ams_info.lock held! */
static void ams_input_enable(void)
{
struct input_dev *input;
s8 x, y, z;
if (ams_info.idev)
......@@ -78,27 +63,29 @@ static void ams_input_enable(void)
ams_info.ycalib = y;
ams_info.zcalib = z;
ams_info.idev = input_allocate_device();
ams_info.idev = input_allocate_polled_device();
if (!ams_info.idev)
return;
ams_info.idev->name = "Apple Motion Sensor";
ams_info.idev->id.bustype = ams_info.bustype;
ams_info.idev->id.vendor = 0;
ams_info.idev->open = ams_input_open;
ams_info.idev->close = ams_input_close;
ams_info.idev->dev.parent = &ams_info.of_dev->dev;
ams_info.idev->poll = ams_idev_poll;
ams_info.idev->poll_interval = 25;
input = ams_info.idev->input;
input->name = "Apple Motion Sensor";
input->id.bustype = ams_info.bustype;
input->id.vendor = 0;
input->dev.parent = &ams_info.of_dev->dev;
input_set_abs_params(ams_info.idev, ABS_X, -50, 50, 3, 0);
input_set_abs_params(ams_info.idev, ABS_Y, -50, 50, 3, 0);
input_set_abs_params(ams_info.idev, ABS_Z, -50, 50, 3, 0);
input_set_abs_params(input, ABS_X, -50, 50, 3, 0);
input_set_abs_params(input, ABS_Y, -50, 50, 3, 0);
input_set_abs_params(input, ABS_Z, -50, 50, 3, 0);
set_bit(EV_ABS, ams_info.idev->evbit);
set_bit(EV_KEY, ams_info.idev->evbit);
set_bit(BTN_TOUCH, ams_info.idev->keybit);
set_bit(EV_ABS, input->evbit);
set_bit(EV_KEY, input->evbit);
set_bit(BTN_TOUCH, input->keybit);
if (input_register_device(ams_info.idev)) {
input_free_device(ams_info.idev);
if (input_register_polled_device(ams_info.idev)) {
input_free_polled_device(ams_info.idev);
ams_info.idev = NULL;
return;
}
......@@ -108,7 +95,8 @@ static void ams_input_enable(void)
static void ams_input_disable(void)
{
if (ams_info.idev) {
input_unregister_device(ams_info.idev);
input_unregister_polled_device(ams_info.idev);
input_free_polled_device(ams_info.idev);
ams_info.idev = NULL;
}
}
......
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/kthread.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
......@@ -52,8 +52,7 @@ struct ams {
#endif
/* Joystick emulation */
struct task_struct *kthread;
struct input_dev *idev;
struct input_polled_dev *idev;
__u16 bustype;
/* calibrated null values */
......
......@@ -28,7 +28,7 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/timer.h>
......@@ -103,7 +103,7 @@ static const char* fan_speed_keys[] = {
#define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */
#define INIT_WAIT_MSECS 50 /* ... in 50ms increments */
#define APPLESMC_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */
#define APPLESMC_POLL_INTERVAL 50 /* msecs */
#define APPLESMC_INPUT_FUZZ 4 /* input event threshold */
#define APPLESMC_INPUT_FLAT 4
......@@ -125,9 +125,8 @@ static const int debug;
static struct platform_device *pdev;
static s16 rest_x;
static s16 rest_y;
static struct timer_list applesmc_timer;
static struct input_dev *applesmc_idev;
static struct device *hwmon_dev;
static struct input_polled_dev *applesmc_idev;
/* Indicates whether this computer has an accelerometer. */
static unsigned int applesmc_accelerometer;
......@@ -138,7 +137,7 @@ static unsigned int applesmc_light;
/* Indicates which temperature sensors set to use. */
static unsigned int applesmc_temperature_set;
static struct mutex applesmc_lock;
static DEFINE_MUTEX(applesmc_lock);
/*
* Last index written to key_at_index sysfs file, and value to use for all other
......@@ -455,27 +454,12 @@ static void applesmc_calibrate(void)
rest_x = -rest_x;
}
static int applesmc_idev_open(struct input_dev *dev)
{
add_timer(&applesmc_timer);
return 0;
}
static void applesmc_idev_close(struct input_dev *dev)
{
del_timer_sync(&applesmc_timer);
}
static void applesmc_idev_poll(unsigned long unused)
static void applesmc_idev_poll(struct input_polled_dev *dev)
{
struct input_dev *idev = dev->input;
s16 x, y;
/* Cannot sleep. Try nonblockingly. If we fail, try again later. */
if (!mutex_trylock(&applesmc_lock)) {
mod_timer(&applesmc_timer, jiffies + APPLESMC_POLL_PERIOD);
return;
}
mutex_lock(&applesmc_lock);
if (applesmc_read_motion_sensor(SENSOR_X, &x))
goto out;
......@@ -483,13 +467,11 @@ static void applesmc_idev_poll(unsigned long unused)
goto out;
x = -x;
input_report_abs(applesmc_idev, ABS_X, x - rest_x);
input_report_abs(applesmc_idev, ABS_Y, y - rest_y);
input_sync(applesmc_idev);
input_report_abs(idev, ABS_X, x - rest_x);
input_report_abs(idev, ABS_Y, y - rest_y);
input_sync(idev);
out:
mod_timer(&applesmc_timer, jiffies + APPLESMC_POLL_PERIOD);
mutex_unlock(&applesmc_lock);
}
......@@ -821,8 +803,7 @@ static ssize_t applesmc_key_at_index_read_show(struct device *dev,
if (!ret) {
return info[0];
}
else {
} else {
return ret;
}
}
......@@ -1093,6 +1074,7 @@ static int applesmc_dmi_match(const struct dmi_system_id *id)
/* Create accelerometer ressources */
static int applesmc_create_accelerometer(void)
{
struct input_dev *idev;
int ret;
ret = sysfs_create_group(&pdev->dev.kobj,
......@@ -1100,40 +1082,37 @@ static int applesmc_create_accelerometer(void)
if (ret)
goto out;
applesmc_idev = input_allocate_device();
applesmc_idev = input_allocate_polled_device();
if (!applesmc_idev) {
ret = -ENOMEM;
goto out_sysfs;
}
applesmc_idev->poll = applesmc_idev_poll;
applesmc_idev->poll_interval = APPLESMC_POLL_INTERVAL;
/* initial calibrate for the input device */
applesmc_calibrate();
/* initialize the input class */
applesmc_idev->name = "applesmc";
applesmc_idev->id.bustype = BUS_HOST;
applesmc_idev->dev.parent = &pdev->dev;
applesmc_idev->evbit[0] = BIT(EV_ABS);
applesmc_idev->open = applesmc_idev_open;
applesmc_idev->close = applesmc_idev_close;
input_set_abs_params(applesmc_idev, ABS_X,
/* initialize the input device */
idev = applesmc_idev->input;
idev->name = "applesmc";
idev->id.bustype = BUS_HOST;
idev->dev.parent = &pdev->dev;
idev->evbit[0] = BIT(EV_ABS);
input_set_abs_params(idev, ABS_X,
-256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
input_set_abs_params(applesmc_idev, ABS_Y,
input_set_abs_params(idev, ABS_Y,
-256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT);
ret = input_register_device(applesmc_idev);
ret = input_register_polled_device(applesmc_idev);
if (ret)
goto out_idev;
/* start up our timer for the input device */
init_timer(&applesmc_timer);
applesmc_timer.function = applesmc_idev_poll;
applesmc_timer.expires = jiffies + APPLESMC_POLL_PERIOD;
return 0;
out_idev:
input_free_device(applesmc_idev);
input_free_polled_device(applesmc_idev);
out_sysfs:
sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
......@@ -1146,8 +1125,8 @@ static int applesmc_create_accelerometer(void)
/* Release all ressources used by the accelerometer */
static void applesmc_release_accelerometer(void)
{
del_timer_sync(&applesmc_timer);
input_unregister_device(applesmc_idev);
input_unregister_polled_device(applesmc_idev);
input_free_polled_device(applesmc_idev);
sysfs_remove_group(&pdev->dev.kobj, &accelerometer_attributes_group);
}
......@@ -1184,8 +1163,6 @@ static int __init applesmc_init(void)
int count;
int i;
mutex_init(&applesmc_lock);
if (!dmi_check_system(applesmc_whitelist)) {
printk(KERN_WARNING "applesmc: supported laptop not found!\n");
ret = -ENODEV;
......
......@@ -28,7 +28,7 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/input-polldev.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/module.h>
......@@ -61,13 +61,12 @@
#define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */
#define INIT_WAIT_MSECS 200 /* ... in 200ms increments */
#define HDAPS_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */
#define HDAPS_POLL_INTERVAL 50 /* poll for input every 1/20s (50 ms)*/
#define HDAPS_INPUT_FUZZ 4 /* input event threshold */
#define HDAPS_INPUT_FLAT 4
static struct timer_list hdaps_timer;
static struct platform_device *pdev;
static struct input_dev *hdaps_idev;
static struct input_polled_dev *hdaps_idev;
static unsigned int hdaps_invert;
static u8 km_activity;
static int rest_x;
......@@ -323,24 +322,19 @@ static void hdaps_calibrate(void)
__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y);
}
static void hdaps_mousedev_poll(unsigned long unused)
static void hdaps_mousedev_poll(struct input_polled_dev *dev)
{
struct input_dev *input_dev = dev->input;
int x, y;
/* Cannot sleep. Try nonblockingly. If we fail, try again later. */
if (mutex_trylock(&hdaps_mtx)) {
mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD);
return;
}
mutex_lock(&hdaps_mtx);
if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
goto out;
input_report_abs(hdaps_idev, ABS_X, x - rest_x);
input_report_abs(hdaps_idev, ABS_Y, y - rest_y);
input_sync(hdaps_idev);
mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD);
input_report_abs(input_dev, ABS_X, x - rest_x);
input_report_abs(input_dev, ABS_Y, y - rest_y);
input_sync(input_dev);
out:
mutex_unlock(&hdaps_mtx);
......@@ -536,6 +530,7 @@ static struct dmi_system_id __initdata hdaps_whitelist[] = {
static int __init hdaps_init(void)
{
struct input_dev *idev;
int ret;
if (!dmi_check_system(hdaps_whitelist)) {
......@@ -563,39 +558,37 @@ static int __init hdaps_init(void)
if (ret)
goto out_device;
hdaps_idev = input_allocate_device();
hdaps_idev = input_allocate_polled_device();
if (!hdaps_idev) {
ret = -ENOMEM;
goto out_group;
}
hdaps_idev->poll = hdaps_mousedev_poll;
hdaps_idev->poll_interval = HDAPS_POLL_INTERVAL;
/* initial calibrate for the input device */
hdaps_calibrate();
/* initialize the input class */
hdaps_idev->name = "hdaps";
hdaps_idev->dev.parent = &pdev->dev;
hdaps_idev->evbit[0] = BIT(EV_ABS);
input_set_abs_params(hdaps_idev, ABS_X,
idev = hdaps_idev->input;
idev->name = "hdaps";
idev->dev.parent = &pdev->dev;
idev->evbit[0] = BIT(EV_ABS);
input_set_abs_params(idev, ABS_X,
-256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
input_set_abs_params(hdaps_idev, ABS_Y,
input_set_abs_params(idev, ABS_Y,
-256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
ret = input_register_device(hdaps_idev);
ret = input_register_polled_device(hdaps_idev);
if (ret)
goto out_idev;
/* start up our timer for the input device */
init_timer(&hdaps_timer);
hdaps_timer.function = hdaps_mousedev_poll;
hdaps_timer.expires = jiffies + HDAPS_POLL_PERIOD;
add_timer(&hdaps_timer);
printk(KERN_INFO "hdaps: driver successfully loaded.\n");
return 0;
out_idev:
input_free_device(hdaps_idev);
input_free_polled_device(hdaps_idev);
out_group:
sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
out_device:
......@@ -611,8 +604,8 @@ static int __init hdaps_init(void)
static void __exit hdaps_exit(void)
{
del_timer_sync(&hdaps_timer);
input_unregister_device(hdaps_idev);
input_unregister_polled_device(hdaps_idev);
input_free_polled_device(hdaps_idev);
sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
platform_device_unregister(pdev);
platform_driver_unregister(&hdaps_driver);
......
......@@ -114,28 +114,6 @@ config INPUT_JOYDEV
To compile this driver as a module, choose M here: the
module will be called joydev.
config INPUT_TSDEV
tristate "Touchscreen interface"
---help---
Say Y here if you have an application that only can understand the
Compaq touchscreen protocol for absolute pointer data. This is
useful namely for embedded configurations.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called tsdev.
config INPUT_TSDEV_SCREEN_X
int "Horizontal screen resolution"
depends on INPUT_TSDEV
default "240"
config INPUT_TSDEV_SCREEN_Y
int "Vertical screen resolution"
depends on INPUT_TSDEV
default "320"
config INPUT_EVDEV
tristate "Event interface"
help
......
......@@ -13,7 +13,6 @@ obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o
obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o
obj-$(CONFIG_INPUT_JOYDEV) += joydev.o
obj-$(CONFIG_INPUT_EVDEV) += evdev.o
obj-$(CONFIG_INPUT_TSDEV) += tsdev.o
obj-$(CONFIG_INPUT_EVBUG) += evbug.o
obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/
......
This diff is collapsed.
......@@ -70,6 +70,7 @@ static int input_open_polled_device(struct input_dev *input)
{
struct input_polled_dev *dev = input->private;
int error;
unsigned long ticks;
error = input_polldev_start_workqueue();
if (error)
......@@ -78,8 +79,10 @@ static int input_open_polled_device(struct input_dev *input)
if (dev->flush)
dev->flush(dev);
queue_delayed_work(polldev_wq, &dev->work,
msecs_to_jiffies(dev->poll_interval));
ticks = msecs_to_jiffies(dev->poll_interval);
if (ticks >= HZ)
ticks = round_jiffies(ticks);
queue_delayed_work(polldev_wq, &dev->work, ticks);
return 0;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -223,12 +223,16 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
struct input_dev *dev = xpad->dev;
/* left stick */
input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12]));
input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14]));
input_report_abs(dev, ABS_X,
(__s16) le16_to_cpup((__le16 *)(data + 12)));
input_report_abs(dev, ABS_Y,
(__s16) le16_to_cpup((__le16 *)(data + 14)));
/* right stick */
input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16]));
input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18]));
input_report_abs(dev, ABS_RX,
(__s16) le16_to_cpup((__le16 *)(data + 16)));
input_report_abs(dev, ABS_RY,
(__s16) le16_to_cpup((__le16 *)(data + 18)));
/* triggers left/right */
input_report_abs(dev, ABS_Z, data[10]);
......@@ -236,8 +240,10 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
/* digital pad */
if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) {
input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04));
input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01));
input_report_abs(dev, ABS_HAT0X,
!!(data[2] & 0x08) - !!(data[2] & 0x04));
input_report_abs(dev, ABS_HAT0Y,
!!(data[2] & 0x02) - !!(data[2] & 0x01));
} else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ {
input_report_key(dev, BTN_LEFT, data[2] & 0x04);
input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
......@@ -274,14 +280,17 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
* http://www.free60.org/wiki/Gamepad
*/
static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
static void xpad360_process_packet(struct usb_xpad *xpad,
u16 cmd, unsigned char *data)
{
struct input_dev *dev = xpad->dev;
/* digital pad */
if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) {
input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04));
input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01));
input_report_abs(dev, ABS_HAT0X,
!!(data[2] & 0x08) - !!(data[2] & 0x04));
input_report_abs(dev, ABS_HAT0Y,
!!(data[2] & 0x02) - !!(data[2] & 0x01));
} else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) {
/* dpad as buttons (right, left, down, up) */
input_report_key(dev, BTN_LEFT, data[2] & 0x04);
......@@ -308,12 +317,16 @@ static void xpad360_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char
input_report_key(dev, BTN_MODE, data[3] & 0x04);
/* left stick */
input_report_abs(dev, ABS_X, (__s16) (((__s16)data[7] << 8) | (__s16)data[6]));
input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[9] << 8) | (__s16)data[8]));
input_report_abs(dev, ABS_X,
(__s16) le16_to_cpup((__le16 *)(data + 6)));
input_report_abs(dev, ABS_Y,
(__s16) le16_to_cpup((__le16 *)(data + 8)));
/* right stick */
input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[11] << 8) | (__s16)data[10]));
input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[13] << 8) | (__s16)data[12]));
input_report_abs(dev, ABS_RX,
(__s16) le16_to_cpup((__le16 *)(data + 10)));
input_report_abs(dev, ABS_RY,
(__s16) le16_to_cpup((__le16 *)(data + 12)));
/* triggers left/right */
input_report_abs(dev, ABS_Z, data[4]);
......@@ -335,10 +348,12 @@ static void xpad_irq_in(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
dbg("%s - urb shutting down with status: %d",
__FUNCTION__, urb->status);
return;
default:
dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
dbg("%s - nonzero urb status received: %d",
__FUNCTION__, urb->status);
goto exit;
}
......@@ -367,10 +382,12 @@ static void xpad_irq_out(struct urb *urb)
case -ENOENT:
case -ESHUTDOWN:
/* this urb is terminated, clean up */
dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
dbg("%s - urb shutting down with status: %d",
__FUNCTION__, urb->status);
return;
default:
dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
dbg("%s - nonzero urb status received: %d",
__FUNCTION__, urb->status);
goto exit;
}
......@@ -595,7 +612,7 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev (intf);
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_xpad *xpad;
struct input_dev *input_dev;
struct usb_endpoint_descriptor *ep_irq_in;
......
......@@ -208,6 +208,27 @@ config KEYBOARD_HIL
This driver implements support for HIL-keyboards attached
to your machine, so normally you should say Y here.
config KEYBOARD_HP6XX
tristate "HP Jornada 6XX Keyboard support"
depends on SH_HP6XX
select INPUT_POLLDEV
help
This adds support for the onboard keyboard found on
HP Jornada 620/660/680/690.
To compile this driver as a module, choose M here: the
module will be called jornada680_kbd.
config KEYBOARD_HP7XX
tristate "HP Jornada 7XX Keyboard Driver"
depends on SA1100_JORNADA720_SSP && SA1100_SSP
help
Say Y here to add support for the HP Jornada 7xx (710/720/728)
onboard keyboard.
To compile this driver as a module, choose M here: the
module will be called jornada720_kbd.
config KEYBOARD_OMAP
tristate "TI OMAP keypad support"
depends on (ARCH_OMAP1 || ARCH_OMAP2)
......@@ -253,4 +274,23 @@ config KEYBOARD_GPIO
To compile this driver as a module, choose M here: the
module will be called gpio-keys.
config KEYBOARD_MAPLE
tristate "Maple bus keyboard"
depends on SH_DREAMCAST && MAPLE
help
Say Y here if you have a Dreamcast console running Linux and have
a keyboard attached to its Maple bus.
To compile this driver as a module, choose M here: the
module will be called maple_keyb.
config KEYBOARD_BFIN
tristate "Blackfin BF54x keypad support"
depends on BF54x
help
Say Y here if you want to use the BF54x keypad.
To compile this driver as a module, choose M here: the
module will be called bf54x-keys.
endif
......@@ -21,4 +21,7 @@ obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o
obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
/*
* File: drivers/input/keyboard/bf54x-keys.c
* Based on:
* Author: Michael Hennerich <hennerich@blackfin.uclinux.org>
*
* Created:
* Description: keypad driver for Analog Devices Blackfin BF54x Processors
*
*
* Modified:
* Copyright 2007 Analog Devices Inc.
*
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
* 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, see the file COPYING, or write
* to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <asm/portmux.h>
#include <asm/mach/bf54x_keys.h>
#define DRV_NAME "bf54x-keys"
#define TIME_SCALE 100 /* 100 ns */
#define MAX_MULT (0xFF * TIME_SCALE)
#define MAX_RC 8 /* Max Row/Col */
static const u16 per_rows[] = {
P_KEY_ROW7,
P_KEY_ROW6,
P_KEY_ROW5,
P_KEY_ROW4,
P_KEY_ROW3,
P_KEY_ROW2,
P_KEY_ROW1,
P_KEY_ROW0,
0
};
static const u16 per_cols[] = {
P_KEY_COL7,
P_KEY_COL6,
P_KEY_COL5,
P_KEY_COL4,
P_KEY_COL3,
P_KEY_COL2,
P_KEY_COL1,
P_KEY_COL0,
0
};
struct bf54x_kpad {
struct input_dev *input;
int irq;
unsigned short lastkey;
unsigned short *keycode;
struct timer_list timer;
unsigned int keyup_test_jiffies;
};
static inline int bfin_kpad_find_key(struct bf54x_kpad *bf54x_kpad,
struct input_dev *input, u16 keyident)
{
u16 i;
for (i = 0; i < input->keycodemax; i++)
if (bf54x_kpad->keycode[i + input->keycodemax] == keyident)
return bf54x_kpad->keycode[i];
return -1;
}
static inline void bfin_keycodecpy(unsigned short *keycode,
const unsigned int *pdata_kc,
unsigned short keymapsize)
{
unsigned int i;
for (i = 0; i < keymapsize; i++) {
keycode[i] = pdata_kc[i] & 0xffff;
keycode[i + keymapsize] = pdata_kc[i] >> 16;
}
}
static inline u16 bfin_kpad_get_prescale(u32 timescale)
{
u32 sclk = get_sclk();
return ((((sclk / 1000) * timescale) / 1024) - 1);
}
static inline u16 bfin_kpad_get_keypressed(struct bf54x_kpad *bf54x_kpad)
{
return (bfin_read_KPAD_STAT() & KPAD_PRESSED);
}
static inline void bfin_kpad_clear_irq(void)
{
bfin_write_KPAD_STAT(0xFFFF);
bfin_write_KPAD_ROWCOL(0xFFFF);
}
static void bfin_kpad_timer(unsigned long data)
{
struct platform_device *pdev = (struct platform_device *) data;
struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
if (bfin_kpad_get_keypressed(bf54x_kpad)) {
/* Try again later */
mod_timer(&bf54x_kpad->timer,
jiffies + bf54x_kpad->keyup_test_jiffies);
return;
}
input_report_key(bf54x_kpad->input, bf54x_kpad->lastkey, 0);
input_sync(bf54x_kpad->input);
/* Clear IRQ Status */
bfin_kpad_clear_irq();
enable_irq(bf54x_kpad->irq);
}
static irqreturn_t bfin_kpad_isr(int irq, void *dev_id)
{
struct platform_device *pdev = dev_id;
struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
struct input_dev *input = bf54x_kpad->input;
int key;
u16 rowcol = bfin_read_KPAD_ROWCOL();
key = bfin_kpad_find_key(bf54x_kpad, input, rowcol);
input_report_key(input, key, 1);
input_sync(input);
if (bfin_kpad_get_keypressed(bf54x_kpad)) {
disable_irq(bf54x_kpad->irq);
bf54x_kpad->lastkey = key;
mod_timer(&bf54x_kpad->timer,
jiffies + bf54x_kpad->keyup_test_jiffies);
} else {
input_report_key(input, key, 0);
input_sync(input);
bfin_kpad_clear_irq();
}
return IRQ_HANDLED;
}
static int __devinit bfin_kpad_probe(struct platform_device *pdev)
{
struct bf54x_kpad *bf54x_kpad;
struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data;
struct input_dev *input;
int i, error;
if (!pdata->rows || !pdata->cols || !pdata->keymap) {
printk(KERN_ERR DRV_NAME
": No rows, cols or keymap from pdata\n");
return -EINVAL;
}
if (!pdata->keymapsize ||
pdata->keymapsize > (pdata->rows * pdata->cols)) {
printk(KERN_ERR DRV_NAME ": Invalid keymapsize\n");
return -EINVAL;
}
bf54x_kpad = kzalloc(sizeof(struct bf54x_kpad), GFP_KERNEL);
if (!bf54x_kpad)
return -ENOMEM;
platform_set_drvdata(pdev, bf54x_kpad);
/* Allocate memory for keymap followed by private LUT */
bf54x_kpad->keycode = kmalloc(pdata->keymapsize *
sizeof(unsigned short) * 2, GFP_KERNEL);
if (!bf54x_kpad->keycode) {
error = -ENOMEM;
goto out;
}
if (!pdata->debounce_time || !pdata->debounce_time > MAX_MULT ||
!pdata->coldrive_time || !pdata->coldrive_time > MAX_MULT) {
printk(KERN_ERR DRV_NAME
": Invalid Debounce/Columdrive Time from pdata\n");
bfin_write_KPAD_MSEL(0xFF0); /* Default MSEL */
} else {
bfin_write_KPAD_MSEL(
((pdata->debounce_time / TIME_SCALE)
& DBON_SCALE) |
(((pdata->coldrive_time / TIME_SCALE) << 8)
& COLDRV_SCALE));
}
if (!pdata->keyup_test_interval)
bf54x_kpad->keyup_test_jiffies = msecs_to_jiffies(50);
else
bf54x_kpad->keyup_test_jiffies =
msecs_to_jiffies(pdata->keyup_test_interval);
if (peripheral_request_list((u16 *)&per_rows[MAX_RC - pdata->rows],
DRV_NAME)) {
printk(KERN_ERR DRV_NAME
": Requesting Peripherals failed\n");
error = -EFAULT;
goto out0;
}
if (peripheral_request_list((u16 *)&per_cols[MAX_RC - pdata->cols],
DRV_NAME)) {
printk(KERN_ERR DRV_NAME
": Requesting Peripherals failed\n");
error = -EFAULT;
goto out1;
}
bf54x_kpad->irq = platform_get_irq(pdev, 0);
if (bf54x_kpad->irq < 0) {
error = -ENODEV;
goto out2;
}
error = request_irq(bf54x_kpad->irq, bfin_kpad_isr,
IRQF_SAMPLE_RANDOM, DRV_NAME, pdev);
if (error) {
printk(KERN_ERR DRV_NAME
": unable to claim irq %d; error %d\n",
bf54x_kpad->irq, error);
error = -EBUSY;
goto out2;
}
input = input_allocate_device();
if (!input) {
error = -ENOMEM;
goto out3;
}
bf54x_kpad->input = input;
input->name = pdev->name;
input->phys = "bf54x-keys/input0";
input->dev.parent = &pdev->dev;
input_set_drvdata(input, bf54x_kpad);
input->id.bustype = BUS_HOST;
input->id.vendor = 0x0001;
input->id.product = 0x0001;
input->id.version = 0x0100;
input->keycodesize = sizeof(unsigned short);
input->keycodemax = pdata->keymapsize;
input->keycode = bf54x_kpad->keycode;
bfin_keycodecpy(bf54x_kpad->keycode, pdata->keymap, pdata->keymapsize);
/* setup input device */
__set_bit(EV_KEY, input->evbit);
if (pdata->repeat)
__set_bit(EV_REP, input->evbit);
for (i = 0; i < input->keycodemax; i++)
__set_bit(bf54x_kpad->keycode[i] & KEY_MAX, input->keybit);
__clear_bit(KEY_RESERVED, input->keybit);
error = input_register_device(input);
if (error) {
printk(KERN_ERR DRV_NAME
": Unable to register input device (%d)\n", error);
goto out4;
}
/* Init Keypad Key Up/Release test timer */
setup_timer(&bf54x_kpad->timer, bfin_kpad_timer, (unsigned long) pdev);
bfin_write_KPAD_PRESCALE(bfin_kpad_get_prescale(TIME_SCALE));
bfin_write_KPAD_CTL((((pdata->cols - 1) << 13) & KPAD_COLEN) |
(((pdata->rows - 1) << 10) & KPAD_ROWEN) |
(2 & KPAD_IRQMODE));
bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN);
printk(KERN_ERR DRV_NAME
": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq);
return 0;
out4:
input_free_device(input);
out3:
free_irq(bf54x_kpad->irq, pdev);
out2:
peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]);
out1:
peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]);
out0:
kfree(bf54x_kpad->keycode);
out:
kfree(bf54x_kpad);
platform_set_drvdata(pdev, NULL);
return error;
}
static int __devexit bfin_kpad_remove(struct platform_device *pdev)
{
struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data;
struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
del_timer_sync(&bf54x_kpad->timer);
free_irq(bf54x_kpad->irq, pdev);
input_unregister_device(bf54x_kpad->input);
peripheral_free_list((u16 *)&per_rows[MAX_RC - pdata->rows]);
peripheral_free_list((u16 *)&per_cols[MAX_RC - pdata->cols]);
kfree(bf54x_kpad->keycode);
kfree(bf54x_kpad);
platform_set_drvdata(pdev, NULL);
return 0;
}
struct platform_driver bfin_kpad_device_driver = {
.probe = bfin_kpad_probe,
.remove = __devexit_p(bfin_kpad_remove),
.driver = {
.name = DRV_NAME,
}
};
static int __init bfin_kpad_init(void)
{
return platform_driver_register(&bfin_kpad_device_driver);
}
static void __exit bfin_kpad_exit(void)
{
platform_driver_unregister(&bfin_kpad_device_driver);
}
module_init(bfin_kpad_init);
module_exit(bfin_kpad_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Keypad driver for BF54x Processors");
......@@ -54,6 +54,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
struct input_dev *input;
int i, error;
int wakeup = 0;
input = input_allocate_device();
if (!input)
......@@ -77,31 +78,51 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
int irq = gpio_to_irq(button->gpio);
unsigned int type = button->type ?: EV_KEY;
set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
error = request_irq(irq, gpio_keys_isr, IRQF_SAMPLE_RANDOM,
if (irq < 0) {
error = irq;
printk(KERN_ERR
"gpio-keys: "
"Unable to get irq number for GPIO %d,"
"error %d\n",
button->gpio, error);
goto fail;
}
error = request_irq(irq, gpio_keys_isr,
IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING,
button->desc ? button->desc : "gpio_keys",
pdev);
if (error) {
printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n",
printk(KERN_ERR
"gpio-keys: Unable to claim irq %d; error %d\n",
irq, error);
goto fail;
}
if (button->wakeup)
wakeup = 1;
input_set_capability(input, type, button->code);
}
error = input_register_device(input);
if (error) {
printk(KERN_ERR "Unable to register gpio-keys input device\n");
printk(KERN_ERR
"gpio-keys: Unable to register input device, "
"error: %d\n", error);
goto fail;
}
device_init_wakeup(&pdev->dev, wakeup);
return 0;
fail:
for (i = i - 1; i >= 0; i--)
while (--i >= 0)
free_irq(gpio_to_irq(pdata->buttons[i].gpio), pdev);
platform_set_drvdata(pdev, NULL);
input_free_device(input);
return error;
......@@ -113,6 +134,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
struct input_dev *input = platform_get_drvdata(pdev);
int i;
device_init_wakeup(&pdev->dev, 0);
for (i = 0; i < pdata->nbuttons; i++) {
int irq = gpio_to_irq(pdata->buttons[i].gpio);
free_irq(irq, pdev);
......@@ -123,9 +146,53 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM
static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state)
{
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);
enable_irq_wake(irq);
}
}
}
return 0;
}
static int gpio_keys_resume(struct platform_device *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);
}
}
}
return 0;
}
#else
#define gpio_keys_suspend NULL
#define gpio_keys_resume NULL
#endif
struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe,
.remove = __devexit_p(gpio_keys_remove),
.suspend = gpio_keys_suspend,
.resume = gpio_keys_resume,
.driver = {
.name = "gpio-keys",
}
......
/*
* drivers/input/keyboard/jornada680_kbd.c
*
* HP Jornada 620/660/680/690 scan keyboard platform driver
* Copyright (C) 2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
*
* Based on hp680_keyb.c
* Copyright (C) 2006 Paul Mundt
* Copyright (C) 2005 Andriy Skulysh
* Split from drivers/input/keyboard/hp600_keyb.c
* Copyright (C) 2000 Yaegashi Takeshi (hp6xx kbd scan routine and translation table)
* Copyright (C) 2000 Niibe Yutaka (HP620 Keyb translation table)
*
* 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/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input-polldev.h>
#include <linux/jiffies.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <asm/delay.h>
#include <asm/io.h>
#define PCCR 0xa4000104
#define PDCR 0xa4000106
#define PECR 0xa4000108
#define PFCR 0xa400010a
#define PCDR 0xa4000124
#define PDDR 0xa4000126
#define PEDR 0xa4000128
#define PFDR 0xa400012a
#define PGDR 0xa400012c
#define PHDR 0xa400012e
#define PJDR 0xa4000130
#define PKDR 0xa4000132
#define PLDR 0xa4000134
static const unsigned short jornada_scancodes[] = {
/* PTD1 */ KEY_CAPSLOCK, KEY_MACRO, KEY_LEFTCTRL, 0, KEY_ESC, 0, 0, 0, /* 1 -> 8 */
KEY_F1, KEY_F2, KEY_F3, KEY_F8, KEY_F7, KEY_F2, KEY_F4, KEY_F5, /* 9 -> 16 */
/* PTD5 */ KEY_SLASH, KEY_APOSTROPHE, KEY_ENTER, 0, KEY_Z, 0, 0, 0, /* 17 -> 24 */
KEY_X, KEY_C, KEY_V, KEY_DOT, KEY_COMMA, KEY_M, KEY_B, KEY_N, /* 25 -> 32 */
/* PTD7 */ KEY_KP2, KEY_KP6, 0, 0, 0, 0, 0, 0, /* 33 -> 40 */
0, 0, 0, KEY_KP4, 0, 0, KEY_LEFTALT, KEY_HANJA, /* 41 -> 48 */
/* PTE0 */ 0, 0, 0, 0, KEY_FINANCE, 0, 0, 0, /* 49 -> 56 */
KEY_LEFTCTRL, 0, KEY_SPACE, KEY_KPDOT, KEY_VOLUMEUP, 249, 0, 0, /* 57 -> 64 */
/* PTE1 */ KEY_SEMICOLON, KEY_RIGHTBRACE, KEY_BACKSLASH, 0, KEY_A, 0, 0, 0,/* 65 -> 72 */
KEY_S, KEY_D, KEY_F, KEY_L, KEY_K, KEY_J, KEY_G, KEY_H, /* 73 -> 80 */
/* PTE3 */ KEY_KP8, KEY_LEFTMETA, KEY_RIGHTSHIFT, 0, KEY_TAB, 0, 0,0, /* 81 -> 88 */
0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 89 -> 96 */
/* PTE6 */ KEY_P, KEY_LEFTBRACE, KEY_BACKSPACE, 0, KEY_Q, 0, 0, 0, /* 97 -> 104 */
KEY_W, KEY_E, KEY_R, KEY_O, KEY_I, KEY_U, KEY_T, KEY_R, /* 105 -> 112 */
/* PTE7 */ KEY_0, KEY_MINUS, KEY_EQUAL, 0, KEY_1, 0, 0, 0, /* 113 -> 120 */
KEY_2, KEY_3, KEY_4, KEY_9, KEY_8, KEY_7, KEY_5, KEY_6, /* 121 -> 128 */
/* **** */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0
};
#define JORNADA_SCAN_SIZE 18
struct jornadakbd {
struct input_polled_dev *poll_dev;
unsigned short keymap[ARRAY_SIZE(jornada_scancodes)];
unsigned char length;
unsigned char old_scan[JORNADA_SCAN_SIZE];
unsigned char new_scan[JORNADA_SCAN_SIZE];
};
static void jornada_parse_kbd(struct jornadakbd *jornadakbd)
{
struct input_dev *input_dev = jornadakbd->poll_dev->input;
unsigned short *keymap = jornadakbd->keymap;
unsigned int sync_me = 0;
unsigned int i, j;
for (i = 0; i < JORNADA_SCAN_SIZE; i++) {
unsigned char new = jornadakbd->new_scan[i];
unsigned char old = jornadakbd->old_scan[i];
unsigned int xor = new ^ old;
if (xor == 0)
continue;
for (j = 0; j < 8; j++) {
unsigned int bit = 1 << j;
if (xor & bit) {
unsigned int scancode = (i << 3) + j;
input_event(input_dev,
EV_MSC, MSC_SCAN, scancode);
input_report_key(input_dev,
keymap[scancode],
!(new & bit));
sync_me = 1;
}
}
}
if (sync_me)
input_sync(input_dev);
}
static void jornada_scan_keyb(unsigned char *s)
{
int i;
unsigned short ec_static, dc_static; /* = UINT16_t */
unsigned char matrix_switch[] = {
0xfd, 0xff, /* PTD1 PD(1) */
0xdf, 0xff, /* PTD5 PD(5) */
0x7f, 0xff, /* PTD7 PD(7) */
0xff, 0xfe, /* PTE0 PE(0) */
0xff, 0xfd, /* PTE1 PE(1) */
0xff, 0xf7, /* PTE3 PE(3) */
0xff, 0xbf, /* PTE6 PE(6) */
0xff, 0x7f, /* PTE7 PE(7) */
}, *t = matrix_switch;
/* PD(x) :
1. 0xcc0c & (1~(1 << (2*(x)+1)))))
2. (0xf0cf & 0xfffff) */
/* PE(x) :
1. 0xcc0c & 0xffff
2. 0xf0cf & (1~(1 << (2*(x)+1))))) */
unsigned short matrix_PDE[] = {
0xcc04, 0xf0cf, /* PD(1) */
0xc40c, 0xf0cf, /* PD(5) */
0x4c0c, 0xf0cf, /* PD(7) */
0xcc0c, 0xf0cd, /* PE(0) */
0xcc0c, 0xf0c7, /* PE(1) */
0xcc0c, 0xf04f, /* PE(3) */
0xcc0c, 0xd0cf, /* PE(6) */
0xcc0c, 0x70cf, /* PE(7) */
}, *y = matrix_PDE;
/* Save these control reg bits */
dc_static = (ctrl_inw(PDCR) & (~0xcc0c));
ec_static = (ctrl_inw(PECR) & (~0xf0cf));
for (i = 0; i < 8; i++) {
/* disable output for all but the one we want to scan */
ctrl_outw((dc_static | *y++), PDCR);
ctrl_outw((ec_static | *y++), PECR);
udelay(5);
/* Get scanline row */
ctrl_outb(*t++, PDDR);
ctrl_outb(*t++, PEDR);
udelay(50);
/* Read data */
*s++ = ctrl_inb(PCDR);
*s++ = ctrl_inb(PFDR);
}
/* Scan no lines */
ctrl_outb(0xff, PDDR);
ctrl_outb(0xff, PEDR);
/* Enable all scanlines */
ctrl_outw((dc_static | (0x5555 & 0xcc0c)),PDCR);
ctrl_outw((ec_static | (0x5555 & 0xf0cf)),PECR);
/* Ignore extra keys and events */
*s++ = ctrl_inb(PGDR);
*s++ = ctrl_inb(PHDR);
}
static void jornadakbd680_poll(struct input_polled_dev *dev)
{
struct jornadakbd *jornadakbd = dev->private;
jornada_scan_keyb(jornadakbd->new_scan);
jornada_parse_kbd(jornadakbd);
memcpy(jornadakbd->old_scan, jornadakbd->new_scan, JORNADA_SCAN_SIZE);
}
static int __devinit jornada680kbd_probe(struct platform_device *pdev)
{
struct jornadakbd *jornadakbd;
struct input_polled_dev *poll_dev;
struct input_dev *input_dev;
int i, error;
jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL);
if (!jornadakbd)
return -ENOMEM;
poll_dev = input_allocate_polled_device();
if (!poll_dev) {
error = -ENOMEM;
goto failed;
}
platform_set_drvdata(pdev, jornadakbd);
jornadakbd->poll_dev = poll_dev;
memcpy(jornadakbd->keymap, jornada_scancodes,
sizeof(jornadakbd->keymap));
poll_dev->private = jornadakbd;
poll_dev->poll = jornadakbd680_poll;
poll_dev->poll_interval = 50; /* msec */
input_dev = poll_dev->input;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
input_dev->name = "HP Jornada 680 keyboard";
input_dev->phys = "jornadakbd/input0";
input_dev->keycode = jornadakbd->keymap;
input_dev->keycodesize = sizeof(unsigned short);
input_dev->keycodemax = ARRAY_SIZE(jornada_scancodes);
input_dev->dev.parent = &pdev->dev;
input_dev->id.bustype = BUS_HOST;
for (i = 0; i < 128; i++)
if (jornadakbd->keymap[i])
__set_bit(jornadakbd->keymap[i], input_dev->keybit);
__clear_bit(KEY_RESERVED, input_dev->keybit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
error = input_register_polled_device(jornadakbd->poll_dev);
if (error)
goto failed;
return 0;
failed:
printk(KERN_ERR "Jornadakbd: failed to register driver, error: %d\n",
error);
platform_set_drvdata(pdev, NULL);
input_free_polled_device(poll_dev);
kfree(jornadakbd);
return error;
}
static int __devexit jornada680kbd_remove(struct platform_device *pdev)
{
struct jornadakbd *jornadakbd = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
input_unregister_polled_device(jornadakbd->poll_dev);
input_free_polled_device(jornadakbd->poll_dev);
kfree(jornadakbd);
return 0;
}
static struct platform_driver jornada680kbd_driver = {
.driver = {
.name = "jornada680_kbd",
},
.probe = jornada680kbd_probe,
.remove = __devexit_p(jornada680kbd_remove),
};
static int __init jornada680kbd_init(void)
{
return platform_driver_register(&jornada680kbd_driver);
}
static void __exit jornada680kbd_exit(void)
{
platform_driver_unregister(&jornada680kbd_driver);
}
module_init(jornada680kbd_init);
module_exit(jornada680kbd_exit);
MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
MODULE_DESCRIPTION("HP Jornada 620/660/680/690 Keyboard Driver");
MODULE_LICENSE("GPLv2");
/*
* drivers/input/keyboard/jornada720_kbd.c
*
* HP Jornada 720 keyboard platform driver
*
* Copyright (C) 2006/2007 Kristoffer Ericson <Kristoffer.Ericson@Gmail.com>
*
* Copyright (C) 2006 jornada 720 kbd driver by
Filip Zyzniewsk <Filip.Zyzniewski@tefnet.plX
* based on (C) 2004 jornada 720 kbd driver by
Alex Lange <chicken@handhelds.org>
*
* 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/device.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <asm/arch/jornada720.h>
#include <asm/hardware.h>
MODULE_AUTHOR("Kristoffer Ericson <Kristoffer.Ericson@gmail.com>");
MODULE_DESCRIPTION("HP Jornada 710/720/728 keyboard driver");
MODULE_LICENSE("GPLv2");
static unsigned short jornada_std_keymap[128] = { /* ROW */
0, KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, /* #1 */
KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE, /* -> */
0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, /* #2 */
KEY_0, KEY_MINUS, KEY_EQUAL,0, 0, 0, /* -> */
0, KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, KEY_O, /* #3 */
KEY_P, KEY_BACKSLASH, KEY_BACKSPACE, 0, 0, 0, /* -> */
0, KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, /* #4 */
KEY_SEMICOLON, KEY_LEFTBRACE, KEY_RIGHTBRACE, 0, 0, 0, /* -> */
0, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_COMMA, /* #5 */
KEY_DOT, KEY_KPMINUS, KEY_APOSTROPHE, KEY_ENTER, 0, 0,0, /* -> */
0, KEY_TAB, 0, KEY_LEFTSHIFT, 0, KEY_APOSTROPHE, 0, 0, 0, 0, /* #6 */
KEY_UP, 0, KEY_RIGHTSHIFT, 0, 0, 0,0, 0, 0, 0, 0, KEY_LEFTALT, KEY_GRAVE, /* -> */
0, 0, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0,0, KEY_KPASTERISK, /* -> */
KEY_LEFTCTRL, 0, KEY_SPACE, 0, 0, 0, KEY_SLASH, KEY_DELETE, 0, 0, /* -> */
0, 0, 0, KEY_POWER, /* -> */
};
struct jornadakbd {
unsigned short keymap[ARRAY_SIZE(jornada_std_keymap)];
struct input_dev *input;
};
static irqreturn_t jornada720_kbd_interrupt(int irq, void *dev_id)
{
struct platform_device *pdev = dev_id;
struct jornadakbd *jornadakbd = platform_get_drvdata(pdev);
struct input_dev *input = jornadakbd->input;
u8 count, kbd_data, scan_code;
/* startup ssp with spinlock */
jornada_ssp_start();
if (jornada_ssp_inout(GETSCANKEYCODE) != TXDUMMY) {
printk(KERN_DEBUG
"jornada720_kbd: "
"GetKeycode command failed with ETIMEDOUT, "
"flushed bus\n");
} else {
/* How many keycodes are waiting for us? */
count = jornada_ssp_byte(TXDUMMY);
/* Lets drag them out one at a time */
while (count--) {
/* Exchange TxDummy for location (keymap[kbddata]) */
kbd_data = jornada_ssp_byte(TXDUMMY);
scan_code = kbd_data & 0x7f;
input_event(input, EV_MSC, MSC_SCAN, scan_code);
input_report_key(input, jornadakbd->keymap[scan_code],
!(kbd_data & 0x80));
input_sync(input);
}
}
/* release spinlock and turn off ssp */
jornada_ssp_end();
return IRQ_HANDLED;
};
static int __devinit jornada720_kbd_probe(struct platform_device *pdev)
{
struct jornadakbd *jornadakbd;
struct input_dev *input_dev;
int i, err;
jornadakbd = kzalloc(sizeof(struct jornadakbd), GFP_KERNEL);
input_dev = input_allocate_device();
if (!jornadakbd || !input_dev) {
err = -ENOMEM;
goto fail1;
}
platform_set_drvdata(pdev, jornadakbd);
memcpy(jornadakbd->keymap, jornada_std_keymap,
sizeof(jornada_std_keymap));
jornadakbd->input = input_dev;
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
input_dev->name = "HP Jornada 720 keyboard";
input_dev->phys = "jornadakbd/input0";
input_dev->keycode = jornadakbd->keymap;
input_dev->keycodesize = sizeof(unsigned short);
input_dev->keycodemax = ARRAY_SIZE(jornada_std_keymap);
input_dev->id.bustype = BUS_HOST;
input_dev->dev.parent = &pdev->dev;
for (i = 0; i < ARRAY_SIZE(jornadakbd->keymap); i++)
__set_bit(jornadakbd->keymap[i], input_dev->keybit);
__clear_bit(KEY_RESERVED, input_dev->keybit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
err = request_irq(IRQ_GPIO0,
jornada720_kbd_interrupt,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
"jornadakbd", pdev);
if (err) {
printk(KERN_INFO "jornadakbd720_kbd: Unable to grab IRQ\n");
goto fail1;
}
err = input_register_device(jornadakbd->input);
if (err)
goto fail2;
return 0;
fail2: /* IRQ, DEVICE, MEMORY */
free_irq(IRQ_GPIO0, pdev);
fail1: /* DEVICE, MEMORY */
platform_set_drvdata(pdev, NULL);
input_free_device(input_dev);
kfree(jornadakbd);
return err;
};
static int __devexit jornada720_kbd_remove(struct platform_device *pdev)
{
struct jornadakbd *jornadakbd = platform_get_drvdata(pdev);
free_irq(IRQ_GPIO0, pdev);
platform_set_drvdata(pdev, NULL);
input_unregister_device(jornadakbd->input);
kfree(jornadakbd);
return 0;
}
static struct platform_driver jornada720_kbd_driver = {
.driver = {
.name = "jornada720_kbd",
},
.probe = jornada720_kbd_probe,
.remove = __devexit_p(jornada720_kbd_remove),
};
static int __init jornada720_kbd_init(void)
{
return platform_driver_register(&jornada720_kbd_driver);
}
static void __exit jornada720_kbd_exit(void)
{
platform_driver_unregister(&jornada720_kbd_driver);
}
module_init(jornada720_kbd_init);
module_exit(jornada720_kbd_exit);
/*
* SEGA Dreamcast keyboard driver
* Based on drivers/usb/usbkbd.c
* Copyright YAEGASHI Takeshi, 2001
* Porting to 2.6 Copyright Adrian McMenamin, 2007
*
* 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, see the file COPYING, or write
* to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/maple.h>
#include <asm/mach/maple.h>
/* Very simple mutex to ensure proper cleanup */
static DEFINE_MUTEX(maple_keyb_mutex);
#define NR_SCANCODES 256
MODULE_AUTHOR("YAEGASHI Takeshi, Adrian McMenamin");
MODULE_DESCRIPTION("SEGA Dreamcast keyboard driver");
MODULE_LICENSE("GPL");
struct dc_kbd {
struct input_dev *dev;
unsigned short keycode[NR_SCANCODES];
unsigned char new[8];
unsigned char old[8];
};
static const unsigned short dc_kbd_keycode[NR_SCANCODES] = {
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_A, KEY_B, KEY_C, KEY_D,
KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L,
KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,
KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2,
KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0,
KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB, KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE,
KEY_RIGHTBRACE, KEY_BACKSLASH, KEY_BACKSLASH, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA,
KEY_DOT, KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6,
KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_SYSRQ,
KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP, KEY_DELETE,
KEY_END, KEY_PAGEDOWN, KEY_RIGHT, KEY_LEFT, KEY_DOWN, KEY_UP,
KEY_NUMLOCK, KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS, KEY_KPENTER, KEY_KP1, KEY_KP2,
KEY_KP3, KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT,
KEY_102ND, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL, KEY_F13, KEY_F14, KEY_F15,
KEY_F16, KEY_F17, KEY_F18, KEY_F19, KEY_F20,
KEY_F21, KEY_F22, KEY_F23, KEY_F24, KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT,
KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY, KEY_PASTE, KEY_FIND, KEY_MUTE,
KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_KPCOMMA, KEY_RESERVED, KEY_RO, KEY_KATAKANAHIRAGANA , KEY_YEN,
KEY_HENKAN, KEY_MUHENKAN, KEY_KPJPCOMMA, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_HANGEUL, KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA, KEY_ZENKAKUHANKAKU, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_LEFTMETA, KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA,
KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG, KEY_NEXTSONG, KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE,
KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP, KEY_FIND, KEY_SCROLLUP, KEY_SCROLLDOWN, KEY_EDIT, KEY_SLEEP,
KEY_SCREENLOCK, KEY_REFRESH, KEY_CALC, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED
};
static void dc_scan_kbd(struct dc_kbd *kbd)
{
struct input_dev *dev = kbd->dev;
void *ptr;
int code, keycode;
int i;
for (i = 0; i < 8; i++) {
code = i + 224;
keycode = kbd->keycode[code];
input_event(dev, EV_MSC, MSC_SCAN, code);
input_report_key(dev, keycode, (kbd->new[0] >> i) & 1);
}
for (i = 2; i < 8; i++) {
ptr = memchr(kbd->new + 2, kbd->old[i], 6);
code = kbd->old[i];
if (code > 3 && ptr == NULL) {
keycode = kbd->keycode[code];
if (keycode) {
input_event(dev, EV_MSC, MSC_SCAN, code);
input_report_key(dev, keycode, 0);
} else
printk(KERN_DEBUG "maple_keyb: "
"Unknown key (scancode %#x) released.",
code);
}
ptr = memchr(kbd->old + 2, kbd->new[i], 6);
code = kbd->new[i];
if (code > 3 && ptr) {
keycode = kbd->keycode[code];
if (keycode) {
input_event(dev, EV_MSC, MSC_SCAN, code);
input_report_key(dev, keycode, 1);
} else
printk(KERN_DEBUG "maple_keyb: "
"Unknown key (scancode %#x) pressed.",
code);
}
}
input_sync(dev);
memcpy(kbd->old, kbd->new, 8);
}
static void dc_kbd_callback(struct mapleq *mq)
{
struct maple_device *mapledev = mq->dev;
struct dc_kbd *kbd = mapledev->private_data;
unsigned long *buf = mq->recvbuf;
/*
* We should always be getting the lock because the only
* time it may be locked if driver is in cleanup phase.
*/
if (likely(mutex_trylock(&maple_keyb_mutex))) {
if (buf[1] == mapledev->function) {
memcpy(kbd->new, buf + 2, 8);
dc_scan_kbd(kbd);
}
mutex_unlock(&maple_keyb_mutex);
}
}
static int dc_kbd_connect(struct maple_device *mdev)
{
int i, error;
struct dc_kbd *kbd;
struct input_dev *dev;
if (!(mdev->function & MAPLE_FUNC_KEYBOARD))
return -EINVAL;
kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL);
dev = input_allocate_device();
if (!kbd || !dev) {
error = -ENOMEM;
goto fail;
}
mdev->private_data = kbd;
kbd->dev = dev;
memcpy(kbd->keycode, dc_kbd_keycode, sizeof(kbd->keycode));
dev->name = mdev->product_name;
dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
dev->keycode = kbd->keycode;
dev->keycodesize = sizeof (unsigned short);
dev->keycodemax = ARRAY_SIZE(kbd->keycode);
dev->id.bustype = BUS_HOST;
dev->dev.parent = &mdev->dev;
for (i = 0; i < NR_SCANCODES; i++)
__set_bit(dc_kbd_keycode[i], dev->keybit);
__clear_bit(KEY_RESERVED, dev->keybit);
input_set_capability(dev, EV_MSC, MSC_SCAN);
input_set_drvdata(dev, kbd);
error = input_register_device(dev);
if (error)
goto fail;
/* Maple polling is locked to VBLANK - which may be just 50/s */
maple_getcond_callback(mdev, dc_kbd_callback, HZ/50, MAPLE_FUNC_KEYBOARD);
return 0;
fail:
input_free_device(dev);
kfree(kbd);
mdev->private_data = NULL;
return error;
}
static void dc_kbd_disconnect(struct maple_device *mdev)
{
struct dc_kbd *kbd;
mutex_lock(&maple_keyb_mutex);
kbd = mdev->private_data;
mdev->private_data = NULL;
input_unregister_device(kbd->dev);
kfree(kbd);
mutex_unlock(&maple_keyb_mutex);
}
/* allow the keyboard to be used */
static int probe_maple_kbd(struct device *dev)
{
struct maple_device *mdev = to_maple_dev(dev);
struct maple_driver *mdrv = to_maple_driver(dev->driver);
int error;
error = dc_kbd_connect(mdev);
if (error)
return error;
mdev->driver = mdrv;
mdev->registered = 1;
return 0;
}
static struct maple_driver dc_kbd_driver = {
.function = MAPLE_FUNC_KEYBOARD,
.connect = dc_kbd_connect,
.disconnect = dc_kbd_disconnect,
.drv = {
.name = "Dreamcast_keyboard",
.probe = probe_maple_kbd,
},
};
static int __init dc_kbd_init(void)
{
return maple_driver_register(&dc_kbd_driver.drv);
}
static void __exit dc_kbd_exit(void)
{
driver_unregister(&dc_kbd_driver.drv);
}
module_init(dc_kbd_init);
module_exit(dc_kbd_exit);
......@@ -318,7 +318,7 @@ static int __init omap_kp_probe(struct platform_device *pdev)
keymap = pdata->keymap;
if (pdata->rep)
set_bit(EV_REP, input_dev->evbit);
__set_bit(EV_REP, input_dev->evbit);
if (pdata->delay)
omap_kp->delay = pdata->delay;
......@@ -365,9 +365,9 @@ static int __init omap_kp_probe(struct platform_device *pdev)
goto err2;
/* setup input device */
set_bit(EV_KEY, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
for (i = 0; keymap[i] != 0; i++)
set_bit(keymap[i] & KEY_MAX, input_dev->keybit);
__set_bit(keymap[i] & KEY_MAX, input_dev->keybit);
input_dev->name = "omap-keypad";
input_dev->phys = "omap-keypad/input0";
input_dev->dev.parent = &pdev->dev;
......@@ -377,10 +377,6 @@ static int __init omap_kp_probe(struct platform_device *pdev)
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
input_dev->keycode = keymap;
input_dev->keycodesize = sizeof(unsigned int);
input_dev->keycodemax = pdata->keymapsize;
ret = input_register_device(omap_kp->input);
if (ret < 0) {
printk(KERN_ERR "Unable to register omap-keypad input device\n");
......@@ -411,7 +407,7 @@ static int __init omap_kp_probe(struct platform_device *pdev)
}
return 0;
err5:
for (i = irq_idx-1; i >=0; i--)
for (i = irq_idx - 1; i >=0; i--)
free_irq(row_gpios[i], 0);
err4:
input_unregister_device(omap_kp->input);
......
......@@ -48,11 +48,13 @@ static const struct alps_model_info alps_model_data[] = {
{ { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */
{ { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 },
{ { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */
{ { 0x73, 0x00, 0x0a }, 0xf8, 0xf8, ALPS_DUALPOINT }, /* ThinkPad R61 8918-5QG */
{ { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
{ { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */
{ { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
{ { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
{ { 0x73, 0x02, 0x50 }, 0xcf, 0xff, ALPS_FW_BK_1 } /* Dell Vostro 1400 */
};
/*
......
......@@ -502,18 +502,23 @@ static void atp_complete(struct urb* urb)
/* reset the accumulator on release */
memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
}
/* Geyser 3 will continue to send packets continually after
the first touch unless reinitialised. Do so if it's been
idle for a while in order to avoid waking the kernel up
several hundred times a second */
if (!key && atp_is_geyser_3(dev)) {
if (atp_is_geyser_3(dev)) {
if (!x && !y && !key) {
dev->idlecount++;
if (dev->idlecount == 10) {
dev->valid = 0;
schedule_work(&dev->work);
}
}
else
dev->idlecount = 0;
}
input_report_key(dev->input, BTN_LEFT, key);
......
......@@ -96,6 +96,14 @@ static const struct dmi_system_id lifebook_dmi_table[] = {
},
.callback = lifebook_set_6byte_proto,
},
{
.ident = "CF-72",
.matches = {
DMI_MATCH(DMI_PRODUCT_NAME, "CF-72"),
},
.callback = lifebook_set_serio_phys,
.driver_data = "isa0060/serio3",
},
{
.ident = "Lifebook B142",
.matches = {
......@@ -282,7 +290,7 @@ static int lifebook_create_relative_device(struct psmouse *psmouse)
int lifebook_init(struct psmouse *psmouse)
{
struct input_dev *dev1 = psmouse->dev;
int max_coord = lifebook_use_6byte_proto ? 1024 : 4096;
int max_coord = lifebook_use_6byte_proto ? 4096 : 1024;
if (lifebook_absolute_mode(psmouse))
return -1;
......
......@@ -648,9 +648,10 @@ static int psmouse_extensions(struct psmouse *psmouse,
/*
* Reset to defaults in case the device got confused by extended
* protocol probes. Note that we do full reset becuase some mice
* put themselves to sleep when see PSMOUSE_RESET_DIS.
* protocol probes. Note that we follow up with full reset because
* some mice put themselves to sleep when they see PSMOUSE_RESET_DIS.
*/
ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS);
psmouse_reset(psmouse);
if (max_proto >= PSMOUSE_IMEX && im_explorer_detect(psmouse, set_properties) == 0)
......
This diff is collapsed.
......@@ -385,6 +385,8 @@ static int i8042_enable_kbd_port(void)
i8042_ctr |= I8042_CTR_KBDINT;
if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
i8042_ctr &= ~I8042_CTR_KBDINT;
i8042_ctr |= I8042_CTR_KBDDIS;
printk(KERN_ERR "i8042.c: Failed to enable KBD port.\n");
return -EIO;
}
......@@ -402,6 +404,8 @@ static int i8042_enable_aux_port(void)
i8042_ctr |= I8042_CTR_AUXINT;
if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
i8042_ctr &= ~I8042_CTR_AUXINT;
i8042_ctr |= I8042_CTR_AUXDIS;
printk(KERN_ERR "i8042.c: Failed to enable AUX port.\n");
return -EIO;
}
......
......@@ -126,6 +126,16 @@ config TOUCHSCREEN_HP600
To compile this driver as a module, choose M here: the
module will be called hp680_ts_input.
config TOUCHSCREEN_HP7XX
tristate "HP Jornada 710/720/728 touchscreen"
depends on SA1100_JORNADA720_SSP
help
Say Y here if you have a HP Jornada 710/720/728 and want
to support the built-in touchscreen.
To compile this driver as a module, choose M here: the
module will be called jornada720_ts.
config TOUCHSCREEN_PENMOUNT
tristate "Penmount serial touchscreen"
select SERIO
......@@ -191,6 +201,7 @@ config TOUCHSCREEN_USB_COMPOSITE
- Gunze AHL61
- DMC TSC-10/25
- IRTOUCHSYSTEMS/UNITOP
- IdealTEK URTC1000
Have a look at <http://linux.chapter7.ch/touchkit/> for
a usage description and the required user-space stuff.
......@@ -238,4 +249,14 @@ config TOUCHSCREEN_USB_IRTOUCH
bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_IDEALTEK
default y
bool "IdealTEK URTC1000 device support" if EMBEDDED
depends on TOUCHSCREEN_USB_COMPOSITE
config TOUCHSCREEN_USB_GENERAL_TOUCH
default y
bool "GeneralTouch Touchscreen device support" if EMBEDDED
depends on TOUCHSCREEN_USB_COMPOSITE
endif
......@@ -13,6 +13,7 @@ obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o
obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
......
This diff is collapsed.
......@@ -130,8 +130,7 @@ static unsigned int ucb1400_adc_read(struct ucb1400 *ucb, u16 adc_channel)
if (val & UCB_ADC_DAT_VALID)
break;
/* yield to other processes */
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1);
schedule_timeout_uninterruptible(1);
}
return UCB_ADC_DAT_VALUE(val);
......
This diff is collapsed.
This diff is collapsed.
......@@ -172,6 +172,7 @@ config INPUT_ADBHID
config MAC_EMUMOUSEBTN
bool "Support for mouse button 2+3 emulation"
select INPUT
help
This provides generic support for emulating the 2nd and 3rd mouse
button with keypresses. If you say Y here, the emulation is still
......
This diff is collapsed.
#ifndef _BFIN_KPAD_H
#define _BFIN_KPAD_H
struct bfin_kpad_platform_data {
int rows;
int cols;
const unsigned int *keymap;
unsigned short keymapsize;
unsigned short repeat;
u32 debounce_time; /* in ns */
u32 coldrive_time; /* in ns */
u32 keyup_test_interval; /* in ms */
};
#define KEYVAL(col, row, val) (((1 << col) << 24) | ((1 << row) << 16) | (val))
#endif
......@@ -8,6 +8,7 @@ struct gpio_keys_button {
int active_low;
char *desc;
int type; /* input event type (EV_KEY, EV_SW) */
int wakeup; /* configure the button as a wake-up source */
};
struct gpio_keys_platform_data {
......
This diff is collapsed.
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