Commit ce1d5b23 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: wacom - add support for Cintiq 20WSX
  Input: ucb1400_ts - IRQ probe fix
  Input: at32psif - update MODULE_AUTHOR with new email
  Input: mac_hid - add lockdep annotation to emumousebtn
  Input: i8042 - fix incorrect usage of strncpy and strncat
  Input: bf54x-keys - add infrastructure for keypad wakeups
  Input: add MODULE_ALIAS() to hotpluggable platform modules
  Input: drivers/char/keyboard.c - use time_after
  Input: fix ordering in joystick Makefile
  Input: wm97xx-core - support use as a wakeup source
  Input: wm97xx-core - use IRQF_SAMPLE_RANDOM
  Input: wm97xx-core - only schedule interrupt handler if not already scheduled
  Input: add Zhen Hua driver
  Input: aiptek - add support for Genius G-PEN 560 tablet
  Input: wacom - implement suspend and autosuspend
  Input: xpad - set proper buffer length for outgoing requests
  Input: omap-keypad - fix build warning
  Input: gpio_keys - irq handling cleanup
  Input: add PS/2 serio driver for AVR32 devices
  Input: put ledstate in the keyboard notifier
  ...
parents ad5e1b0f 308f0a58
......@@ -4356,6 +4356,16 @@ L: linux-wireless@vger.kernel.org
W: http://oops.ghostprotocols.net:81/blog
S: Maintained
WM97XX TOUCHSCREEN DRIVERS
P: Mark Brown
M: broonie@opensource.wolfsonmicro.com
P: Liam Girdwood
M: liam.girdwood@wolfsonmicro.com
L: linux-input@vger.kernel.org
T: git git://opensource.wolfsonmicro.com/linux-2.6-touch
W: http://opensource.wolfsonmicro.com/node/7
S: Supported
X.25 NETWORK LAYER
P: Henner Eisen
M: eis@baty.hanse.de
......
......@@ -42,6 +42,7 @@
#include <linux/input.h>
#include <linux/reboot.h>
#include <linux/notifier.h>
#include <linux/jiffies.h>
extern void ctrl_alt_del(void);
......@@ -928,7 +929,8 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag)
if (up_flag) {
if (brl_timeout) {
if (!committing ||
jiffies - releasestart > (brl_timeout * HZ) / 1000) {
time_after(jiffies,
releasestart + msecs_to_jiffies(brl_timeout))) {
committing = pressed;
releasestart = jiffies;
}
......@@ -1238,6 +1240,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
}
param.shift = shift_final = (shift_state | kbd->slockstate) ^ kbd->lockstate;
param.ledstate = kbd->ledflagstate;
key_map = key_maps[shift_final];
if (atomic_notifier_call_chain(&keyboard_notifier_list, KBD_KEYCODE, &param) == NOTIFY_STOP || !key_map) {
......@@ -1286,6 +1289,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
(*k_handler[type])(vc, keysym & 0xff, !down);
param.ledstate = kbd->ledflagstate;
atomic_notifier_call_chain(&keyboard_notifier_list, KBD_POST_KEYSYM, &param);
if (type != KT_SLOCK)
......
......@@ -405,6 +405,9 @@
#define USB_VENDOR_ID_YEALINK 0x6993
#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001
#define USB_VENDOR_ID_KYE 0x0458
#define USB_DEVICE_ID_KYE_GPEN_560 0x5003
/*
* Alphabetically sorted blacklist by quirk type.
*/
......@@ -698,6 +701,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_63, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_64, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560, HID_QUIRK_IGNORE },
{ 0, 0 }
};
......
......@@ -73,7 +73,7 @@ static void input_polled_device_work(struct work_struct *work)
static int input_open_polled_device(struct input_dev *input)
{
struct input_polled_dev *dev = input->private;
struct input_polled_dev *dev = input_get_drvdata(input);
int error;
error = input_polldev_start_workqueue();
......@@ -91,7 +91,7 @@ static int input_open_polled_device(struct input_dev *input)
static void input_close_polled_device(struct input_dev *input)
{
struct input_polled_dev *dev = input->private;
struct input_polled_dev *dev = input_get_drvdata(input);
cancel_delayed_work_sync(&dev->work);
input_polldev_stop_workqueue();
......@@ -151,10 +151,10 @@ int input_register_polled_device(struct input_polled_dev *dev)
{
struct input_dev *input = dev->input;
input_set_drvdata(input, dev);
INIT_DELAYED_WORK(&dev->work, input_polled_device_work);
if (!dev->poll_interval)
dev->poll_interval = 500;
input->private = dev;
input->open = input_open_polled_device;
input->close = input_close_polled_device;
......
......@@ -193,6 +193,18 @@ config JOYSTICK_TWIDJOY
To compile this driver as a module, choose M here: the
module will be called twidjoy.
config JOYSTICK_ZHENHUA
tristate "5-byte Zhenhua RC transmitter"
select SERIO
help
Say Y here if you have a Zhen Hua PPM-4CH transmitter which is
supplied with a ready to fly micro electric indoor helicopters
such as EasyCopter, Lama, MiniCopter, DragonFly or Jabo and want
to use it via serial cable as a joystick.
To compile this driver as a module, choose M here: the
module will be called zhenhua.
config JOYSTICK_DB9
tristate "Multisystem, Sega Genesis, Saturn joysticks and gamepads"
depends on PARPORT
......
......@@ -15,6 +15,7 @@ obj-$(CONFIG_JOYSTICK_GF2K) += gf2k.o
obj-$(CONFIG_JOYSTICK_GRIP) += grip.o
obj-$(CONFIG_JOYSTICK_GRIP_MP) += grip_mp.o
obj-$(CONFIG_JOYSTICK_GUILLEMOT) += guillemot.o
obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/
obj-$(CONFIG_JOYSTICK_INTERACT) += interact.o
obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o
obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o
......@@ -27,5 +28,5 @@ obj-$(CONFIG_JOYSTICK_TURBOGRAFX) += turbografx.o
obj-$(CONFIG_JOYSTICK_TWIDJOY) += twidjoy.o
obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o
obj-$(CONFIG_JOYSTICK_XPAD) += xpad.o
obj-$(CONFIG_JOYSTICK_ZHENHUA) += zhenhua.o
obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/
This diff is collapsed.
/*
* derived from "twidjoy.c"
*
* Copyright (c) 2008 Martin Kebert
* Copyright (c) 2001 Arndt Schoenewald
* Copyright (c) 2000-2001 Vojtech Pavlik
* Copyright (c) 2000 Mark Fletcher
*
*/
/*
* Driver to use 4CH RC transmitter using Zhen Hua 5-byte protocol (Walkera Lama,
* EasyCopter etc.) as a joystick under Linux.
*
* RC transmitters using Zhen Hua 5-byte protocol are cheap four channels
* transmitters for control a RC planes or RC helicopters with possibility to
* connect on a serial port.
* Data coming from transmitter is in this order:
* 1. byte = synchronisation byte
* 2. byte = X axis
* 3. byte = Y axis
* 4. byte = RZ axis
* 5. byte = Z axis
* (and this is repeated)
*
* For questions or feedback regarding this driver module please contact:
* Martin Kebert <gkmarty@gmail.com> - but I am not a C-programmer nor kernel
* coder :-(
*/
/*
* 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/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/init.h>
#define DRIVER_DESC "RC transmitter with 5-byte Zhen Hua protocol joystick driver"
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
/*
* Constants.
*/
#define ZHENHUA_MAX_LENGTH 5
/*
* Zhen Hua data.
*/
struct zhenhua {
struct input_dev *dev;
int idx;
unsigned char data[ZHENHUA_MAX_LENGTH];
char phys[32];
};
/* bits in all incoming bytes needs to be "reversed" */
static int zhenhua_bitreverse(int x)
{
x = ((x & 0xaa) >> 1) | ((x & 0x55) << 1);
x = ((x & 0xcc) >> 2) | ((x & 0x33) << 2);
x = ((x & 0xf0) >> 4) | ((x & 0x0f) << 4);
return x;
}
/*
* zhenhua_process_packet() decodes packets the driver receives from the
* RC transmitter. It updates the data accordingly.
*/
static void zhenhua_process_packet(struct zhenhua *zhenhua)
{
struct input_dev *dev = zhenhua->dev;
unsigned char *data = zhenhua->data;
input_report_abs(dev, ABS_Y, data[1]);
input_report_abs(dev, ABS_X, data[2]);
input_report_abs(dev, ABS_RZ, data[3]);
input_report_abs(dev, ABS_Z, data[4]);
input_sync(dev);
}
/*
* zhenhua_interrupt() is called by the low level driver when characters
* are ready for us. We then buffer them for further processing, or call the
* packet processing routine.
*/
static irqreturn_t zhenhua_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
{
struct zhenhua *zhenhua = serio_get_drvdata(serio);
/* All Zhen Hua packets are 5 bytes. The fact that the first byte
* is allways 0xf7 and all others are in range 0x32 - 0xc8 (50-200)
* can be used to check and regain sync. */
if (data == 0xef)
zhenhua->idx = 0; /* this byte starts a new packet */
else if (zhenhua->idx == 0)
return IRQ_HANDLED; /* wrong MSB -- ignore this byte */
if (zhenhua->idx < ZHENHUA_MAX_LENGTH)
zhenhua->data[zhenhua->idx++] = zhenhua_bitreverse(data);
if (zhenhua->idx == ZHENHUA_MAX_LENGTH) {
zhenhua_process_packet(zhenhua);
zhenhua->idx = 0;
}
return IRQ_HANDLED;
}
/*
* zhenhua_disconnect() is the opposite of zhenhua_connect()
*/
static void zhenhua_disconnect(struct serio *serio)
{
struct zhenhua *zhenhua = serio_get_drvdata(serio);
serio_close(serio);
serio_set_drvdata(serio, NULL);
input_unregister_device(zhenhua->dev);
kfree(zhenhua);
}
/*
* zhenhua_connect() is the routine that is called when someone adds a
* new serio device. It looks for the Twiddler, and if found, registers
* it as an input device.
*/
static int zhenhua_connect(struct serio *serio, struct serio_driver *drv)
{
struct zhenhua *zhenhua;
struct input_dev *input_dev;
int err = -ENOMEM;
zhenhua = kzalloc(sizeof(struct zhenhua), GFP_KERNEL);
input_dev = input_allocate_device();
if (!zhenhua || !input_dev)
goto fail1;
zhenhua->dev = input_dev;
snprintf(zhenhua->phys, sizeof(zhenhua->phys), "%s/input0", serio->phys);
input_dev->name = "Zhen Hua 5-byte device";
input_dev->phys = zhenhua->phys;
input_dev->id.bustype = BUS_RS232;
input_dev->id.vendor = SERIO_ZHENHUA;
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0100;
input_dev->dev.parent = &serio->dev;
input_dev->evbit[0] = BIT(EV_ABS);
input_set_abs_params(input_dev, ABS_X, 50, 200, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 50, 200, 0, 0);
input_set_abs_params(input_dev, ABS_Z, 50, 200, 0, 0);
input_set_abs_params(input_dev, ABS_RZ, 50, 200, 0, 0);
serio_set_drvdata(serio, zhenhua);
err = serio_open(serio, drv);
if (err)
goto fail2;
err = input_register_device(zhenhua->dev);
if (err)
goto fail3;
return 0;
fail3: serio_close(serio);
fail2: serio_set_drvdata(serio, NULL);
fail1: input_free_device(input_dev);
kfree(zhenhua);
return err;
}
/*
* The serio driver structure.
*/
static struct serio_device_id zhenhua_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_ZHENHUA,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, zhenhua_serio_ids);
static struct serio_driver zhenhua_drv = {
.driver = {
.name = "zhenhua",
},
.description = DRIVER_DESC,
.id_table = zhenhua_serio_ids,
.interrupt = zhenhua_interrupt,
.connect = zhenhua_connect,
.disconnect = zhenhua_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
static int __init zhenhua_init(void)
{
return serio_register_driver(&zhenhua_drv);
}
static void __exit zhenhua_exit(void)
{
serio_unregister_driver(&zhenhua_drv);
}
module_init(zhenhua_init);
module_exit(zhenhua_exit);
......@@ -156,11 +156,15 @@ static int __devexit aaedkbd_remove(struct platform_device *pdev)
return 0;
}
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:aaed2000-keyboard");
static struct platform_driver aaedkbd_driver = {
.probe = aaedkbd_probe,
.remove = __devexit_p(aaedkbd_remove),
.driver = {
.name = "aaed2000-keyboard",
.owner = THIS_MODULE,
},
};
......
......@@ -312,6 +312,8 @@ static int __devinit bfin_kpad_probe(struct platform_device *pdev)
bfin_write_KPAD_CTL(bfin_read_KPAD_CTL() | KPAD_EN);
device_init_wakeup(&pdev->dev, 1);
printk(KERN_ERR DRV_NAME
": Blackfin BF54x Keypad registered IRQ %d\n", bf54x_kpad->irq);
......@@ -354,12 +356,40 @@ static int __devexit bfin_kpad_remove(struct platform_device *pdev)
return 0;
}
#ifdef CONFIG_PM
static int bfin_kpad_suspend(struct platform_device *pdev, pm_message_t state)
{
struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
if (device_may_wakeup(&pdev->dev))
enable_irq_wake(bf54x_kpad->irq);
return 0;
}
static int bfin_kpad_resume(struct platform_device *pdev)
{
struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev);
if (device_may_wakeup(&pdev->dev))
disable_irq_wake(bf54x_kpad->irq);
return 0;
}
#else
# define bfin_kpad_suspend NULL
# define bfin_kpad_resume NULL
#endif
struct platform_driver bfin_kpad_device_driver = {
.probe = bfin_kpad_probe,
.remove = __devexit_p(bfin_kpad_remove),
.driver = {
.name = DRV_NAME,
}
.owner = THIS_MODULE,
},
.probe = bfin_kpad_probe,
.remove = __devexit_p(bfin_kpad_remove),
.suspend = bfin_kpad_suspend,
.resume = bfin_kpad_resume,
};
static int __init bfin_kpad_init(void)
......@@ -378,3 +408,4 @@ module_exit(bfin_kpad_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("Keypad driver for BF54x Processors");
MODULE_ALIAS("platform:bf54x-keys");
......@@ -393,6 +393,7 @@ static struct platform_driver corgikbd_driver = {
.resume = corgikbd_resume,
.driver = {
.name = "corgi-keyboard",
.owner = THIS_MODULE,
},
};
......@@ -412,3 +413,4 @@ module_exit(corgikbd_exit);
MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
MODULE_DESCRIPTION("Corgi Keyboard Driver");
MODULE_LICENSE("GPLv2");
MODULE_ALIAS("platform:corgi-keyboard");
......@@ -43,10 +43,11 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
input_event(input, type, button->code, !!state);
input_sync(input);
return IRQ_HANDLED;
}
}
return IRQ_HANDLED;
return IRQ_NONE;
}
static int __devinit gpio_keys_probe(struct platform_device *pdev)
......@@ -213,6 +214,7 @@ struct platform_driver gpio_keys_device_driver = {
.resume = gpio_keys_resume,
.driver = {
.name = "gpio-keys",
.owner = THIS_MODULE,
}
};
......@@ -232,3 +234,4 @@ module_exit(gpio_keys_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>");
MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs");
MODULE_ALIAS("platform:gpio-keys");
......@@ -254,6 +254,7 @@ static int __devexit jornada680kbd_remove(struct platform_device *pdev)
static struct platform_driver jornada680kbd_driver = {
.driver = {
.name = "jornada680_kbd",
.owner = THIS_MODULE,
},
.probe = jornada680kbd_probe,
.remove = __devexit_p(jornada680kbd_remove),
......@@ -275,3 +276,4 @@ 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");
MODULE_ALIAS("platform:jornada680_kbd");
......@@ -162,9 +162,13 @@ static int __devexit jornada720_kbd_remove(struct platform_device *pdev)
return 0;
}
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:jornada720_kbd");
static struct platform_driver jornada720_kbd_driver = {
.driver = {
.name = "jornada720_kbd",
.owner = THIS_MODULE,
},
.probe = jornada720_kbd_probe,
.remove = __devexit_p(jornada720_kbd_remove),
......
/*
* Copyright (c) 2005 John Lenz
* LoCoMo keyboard driver for Linux-based ARM PDAs:
* - SHARP Zaurus Collie (SL-5500)
* - SHARP Zaurus Poodle (SL-5600)
*
* Copyright (c) 2005 John Lenz
* Based on from xtkbd.c
*/
/*
* LoCoMo keyboard driver for Linux/ARM
*/
/*
*
*
* 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
......@@ -47,7 +45,8 @@ MODULE_LICENSE("GPL");
#define KEY_CONTACT KEY_F18
#define KEY_CENTER KEY_F15
static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
static const unsigned char
locomokbd_keycode[LOCOMOKBD_NUMKEYS] __devinitconst = {
0, KEY_ESC, KEY_ACTIVITY, 0, 0, 0, 0, 0, 0, 0, /* 0 - 9 */
0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_HOME, KEY_CONTACT, /* 10 - 19 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 29 */
......@@ -67,22 +66,21 @@ static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
#define KB_COLS 8
#define KB_ROWMASK(r) (1 << (r))
#define SCANCODE(c,r) ( ((c)<<4) + (r) + 1 )
#define NR_SCANCODES 128
#define KB_DELAY 8
#define SCAN_INTERVAL (HZ/10)
#define LOCOMOKBD_PRESSED 1
struct locomokbd {
unsigned char keycode[LOCOMOKBD_NUMKEYS];
struct input_dev *input;
char phys[32];
struct locomo_dev *ldev;
unsigned long base;
spinlock_t lock;
struct timer_list timer;
unsigned long suspend_jiffies;
unsigned int count_cancel;
};
/* helper functions for reading the keyboard matrix */
......@@ -128,7 +126,7 @@ static inline void locomokbd_reset_col(unsigned long membase, int col)
/* Scan the hardware keyboard and push any changes up through the input layer */
static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
{
unsigned int row, col, rowd, scancode;
unsigned int row, col, rowd;
unsigned long flags;
unsigned int num_pressed;
unsigned long membase = locomokbd->base;
......@@ -145,13 +143,33 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
rowd = ~locomo_readl(membase + LOCOMO_KIB);
for (row = 0; row < KB_ROWS; row++) {
unsigned int scancode, pressed, key;
scancode = SCANCODE(col, row);
if (rowd & KB_ROWMASK(row)) {
num_pressed += 1;
input_report_key(locomokbd->input, locomokbd->keycode[scancode], 1);
} else {
input_report_key(locomokbd->input, locomokbd->keycode[scancode], 0);
}
pressed = rowd & KB_ROWMASK(row);
key = locomokbd->keycode[scancode];
input_report_key(locomokbd->input, key, pressed);
if (likely(!pressed))
continue;
num_pressed++;
/* The "Cancel/ESC" key is labeled "On/Off" on
* Collie and Poodle and should suspend the device
* if it was pressed for more than a second. */
if (unlikely(key == KEY_ESC)) {
if (!time_after(jiffies,
locomokbd->suspend_jiffies + HZ))
continue;
if (locomokbd->count_cancel++
!= (HZ/SCAN_INTERVAL + 1))
continue;
input_event(locomokbd->input, EV_PWR,
KEY_SUSPEND, 1);
locomokbd->suspend_jiffies = jiffies;
} else
locomokbd->count_cancel = 0;
}
locomokbd_reset_col(membase, col);
}
......@@ -162,6 +180,8 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
/* if any keys are pressed, enable the timer */
if (num_pressed)
mod_timer(&locomokbd->timer, jiffies + SCAN_INTERVAL);
else
locomokbd->count_cancel = 0;
spin_unlock_irqrestore(&locomokbd->lock, flags);
}
......@@ -186,10 +206,11 @@ static irqreturn_t locomokbd_interrupt(int irq, void *dev_id)
static void locomokbd_timer_callback(unsigned long data)
{
struct locomokbd *locomokbd = (struct locomokbd *) data;
locomokbd_scankeyboard(locomokbd);
}
static int locomokbd_probe(struct locomo_dev *dev)
static int __devinit locomokbd_probe(struct locomo_dev *dev)
{
struct locomokbd *locomokbd;
struct input_dev *input_dev;
......@@ -211,7 +232,6 @@ static int locomokbd_probe(struct locomo_dev *dev)
goto err_free_mem;
}
locomokbd->ldev = dev;
locomo_set_drvdata(dev, locomokbd);
locomokbd->base = (unsigned long) dev->mapbase;
......@@ -222,6 +242,8 @@ static int locomokbd_probe(struct locomo_dev *dev)
locomokbd->timer.function = locomokbd_timer_callback;
locomokbd->timer.data = (unsigned long) locomokbd;
locomokbd->suspend_jiffies = jiffies;
locomokbd->input = input_dev;
strcpy(locomokbd->phys, "locomokbd/input0");
......@@ -233,9 +255,10 @@ static int locomokbd_probe(struct locomo_dev *dev)
input_dev->id.version = 0x0100;
input_dev->dev.parent = &dev->dev;
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
BIT_MASK(EV_PWR);
input_dev->keycode = locomokbd->keycode;
input_dev->keycodesize = sizeof(unsigned char);
input_dev->keycodesize = sizeof(locomokbd_keycode[0]);
input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode);
memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode));
......@@ -268,7 +291,7 @@ static int locomokbd_probe(struct locomo_dev *dev)
return err;
}
static int locomokbd_remove(struct locomo_dev *dev)
static int __devexit locomokbd_remove(struct locomo_dev *dev)
{
struct locomokbd *locomokbd = locomo_get_drvdata(dev);
......@@ -292,7 +315,7 @@ static struct locomo_driver keyboard_driver = {
},
.devid = LOCOMO_DEVID_KEYBOARD,
.probe = locomokbd_probe,
.remove = locomokbd_remove,
.remove = __devexit_p(locomokbd_remove),
};
static int __init locomokbd_init(void)
......
......@@ -352,6 +352,9 @@ static int __init omap_kp_probe(struct platform_device *pdev)
}
omap_set_gpio_direction(row_gpios[row_idx], 1);
}
} else {
col_idx = 0;
row_idx = 0;
}
setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp);
......@@ -415,10 +418,10 @@ err4:
err3:
device_remove_file(&pdev->dev, &dev_attr_enable);
err2:
for (i = row_idx-1; i >=0; i--)
for (i = row_idx - 1; i >=0; i--)
omap_free_gpio(row_gpios[i]);
err1:
for (i = col_idx-1; i >=0; i--)
for (i = col_idx - 1; i >=0; i--)
omap_free_gpio(col_gpios[i]);
kfree(omap_kp);
......@@ -464,6 +467,7 @@ static struct platform_driver omap_kp_driver = {
.resume = omap_kp_resume,
.driver = {
.name = "omap-keypad",
.owner = THIS_MODULE,
},
};
......@@ -484,3 +488,4 @@ module_exit(omap_kp_exit);
MODULE_AUTHOR("Timo Teräs");
MODULE_DESCRIPTION("OMAP Keypad Driver");
MODULE_LICENSE("GPL");