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: (62 commits)
  Input: atkbd - release previously reserved keycodes 248 - 254
  Input: add KEY_WPS_BUTTON definition
  Input: ads7846 - add regulator support
  Input: winbond-cir - fix suspend/resume
  Input: gamecon - use pr_err() and friends
  Input: gamecon - constify some of the setup structures
  Input: gamecon - simplify pad type handling
  Input: gamecon - simplify coordinate calculation for PSX
  Input: gamecon - fix some formatting issues
  Input: gamecon - add rumble support for N64 pads
  Input: wacom - add device type to device name string
  Input: s3c24xx_ts - report touch only when stylus is down
  Input: s3c24xx_ts - re-enable IRQ on resume
  Input: wacom - constify product features data
  Input: wacom - use per-device instance of wacom_features
  Input: sh_keysc - enable building on SH-Mobile ARM
  Input: wacom - get features from driver info
  Input: rotary-encoder - set gpio direction for each requested gpio
  Input: sh_keysc - update the driver with mode 6
  Input: sh_keysc - switch to using bitmaps
  ...
This commit is contained in:
Linus Torvalds
2010-03-01 10:38:09 -08:00
53 changed files with 3260 additions and 1344 deletions

View File

@@ -538,3 +538,26 @@ Why: Duplicate functionality with the gspca_zc3xx driver, zc0301 only
sensors) wich are also supported by the gspca_zc3xx driver
(which supports 53 USB-ID's in total)
Who: Hans de Goede <hdegoede@redhat.com>
----------------------------
What: corgikbd, spitzkbd, tosakbd driver
When: 2.6.35
Files: drivers/input/keyboard/{corgi,spitz,tosa}kbd.c
Why: We now have a generic GPIO based matrix keyboard driver that
are fully capable of handling all the keys on these devices.
The original drivers manipulate the GPIO registers directly
and so are difficult to maintain.
Who: Eric Miao <eric.y.miao@gmail.com>
----------------------------
What: corgi_ssp and corgi_ts driver
When: 2.6.35
Files: arch/arm/mach-pxa/corgi_ssp.c, drivers/input/touchscreen/corgi_ts.c
Why: The corgi touchscreen is now deprecated in favour of the generic
ads7846.c driver. The noise reduction technique used in corgi_ts.c,
that's to wait till vsync before ADC sampling, is also integrated into
ads7846 driver now. Provided that the original driver is not generic
and is difficult to maintain, it will be removed later.
Who: Eric Miao <eric.y.miao@gmail.com>

View File

@@ -1,5 +1,5 @@
Copyright (C) 2002-2008 Sentelic Corporation.
Last update: Oct-31-2008
Copyright (C) 2002-2010 Sentelic Corporation.
Last update: Jan-13-2010
==============================================================================
* Finger Sensing Pad Intellimouse Mode(scrolling wheel, 4th and 5th buttons)
@@ -44,7 +44,7 @@ B) MSID 6: Horizontal and Vertical scrolling.
Packet 1
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |Y|X|y|x|1|M|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 | | |B|F|l|r|u|d|
1 |Y|X|y|x|1|M|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 | | |B|F|r|l|u|d|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7 => Y overflow
@@ -59,15 +59,15 @@ Byte 2: X Movement(9-bit 2's complement integers)
Byte 3: Y Movement(9-bit 2's complement integers)
Byte 4: Bit0 => the Vertical scrolling movement downward.
Bit1 => the Vertical scrolling movement upward.
Bit2 => the Vertical scrolling movement rightward.
Bit3 => the Vertical scrolling movement leftward.
Bit2 => the Horizontal scrolling movement leftward.
Bit3 => the Horizontal scrolling movement rightward.
Bit4 => 1 = 4th mouse button is pressed, Forward one page.
0 = 4th mouse button is not pressed.
Bit5 => 1 = 5th mouse button is pressed, Backward one page.
0 = 5th mouse button is not pressed.
C) MSID 7:
# FSP uses 2 packets(8 Bytes) data to represent Absolute Position
# FSP uses 2 packets (8 Bytes) to represent Absolute Position.
so we have PACKET NUMBER to identify packets.
If PACKET NUMBER is 0, the packet is Packet 1.
If PACKET NUMBER is 1, the packet is Packet 2.
@@ -129,7 +129,7 @@ Byte 3: Message Type => 0x00 (Disabled)
Byte 4: Bit7~Bit0 => Don't Care
==============================================================================
* Absolute position for STL3888-A0.
* Absolute position for STL3888-Ax.
==============================================================================
Packet 1 (ABSOLUTE POSITION)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
@@ -179,14 +179,14 @@ Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit5~Bit4 => y2_g
Bit7~Bit6 => x2_g
Notify Packet for STL3888-A0
Notify Packet for STL3888-Ax
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |1|0|1|P|1|M|R|L| 2 |C|C|C|C|C|C|C|C| 3 |0|0|F|F|0|0|0|i| 4 |r|l|d|u|0|0|0|0|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 01, Absolute coordinates packet
=> 10, Notify packet
Bit5 => 1
Bit4 => when in absolute coordinates mode (valid when EN_PKT_GO is 1):
@@ -205,15 +205,106 @@ Byte 4: Bit7 => scroll right button
Bit6 => scroll left button
Bit5 => scroll down button
Bit4 => scroll up button
* Note that if gesture and additional button (Bit4~Bit7)
happen at the same time, the button information will not
be sent.
* Note that if gesture and additional buttoni (Bit4~Bit7)
happen at the same time, the button information will not
be sent.
Bit3~Bit0 => Reserved
Sample sequence of Multi-finger, Multi-coordinate mode:
notify packet (valid bit == 1), abs pkt 1, abs pkt 2, abs pkt 1,
abs pkt 2, ..., notify packet(valid bit == 0)
abs pkt 2, ..., notify packet (valid bit == 0)
==============================================================================
* Absolute position for STL3888-B0.
==============================================================================
Packet 1(ABSOLUTE POSITION)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|V|F|1|0|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |r|l|u|d|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordinates packet
=> 10, Notify packet
Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
When both fingers are up, the last two reports have zero valid
bit.
Bit4 => finger up/down information. 1: finger down, 0: finger up.
Bit3 => 1
Bit2 => finger index, 0 is the first finger, 1 is the second finger.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit4 => scroll down button
Bit5 => scroll up button
Bit6 => scroll left button
Bit7 => scroll right button
Packet 2 (ABSOLUTE POSITION)
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |0|1|V|F|1|1|R|L| 2 |X|X|X|X|X|X|X|X| 3 |Y|Y|Y|Y|Y|Y|Y|Y| 4 |r|l|u|d|X|X|Y|Y|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
Bit5 => Valid bit, 0 means that the coordinate is invalid or finger up.
When both fingers are up, the last two reports have zero valid
bit.
Bit4 => finger up/down information. 1: finger down, 0: finger up.
Bit3 => 1
Bit2 => finger index, 0 is the first finger, 1 is the second finger.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: X coordinate (xpos[9:2])
Byte 3: Y coordinate (ypos[9:2])
Byte 4: Bit1~Bit0 => Y coordinate (xpos[1:0])
Bit3~Bit2 => X coordinate (ypos[1:0])
Bit4 => scroll down button
Bit5 => scroll up button
Bit6 => scroll left button
Bit7 => scroll right button
Notify Packet for STL3888-B0
Bit 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
BYTE |---------------|BYTE |---------------|BYTE|---------------|BYTE|---------------|
1 |1|0|1|P|1|M|R|L| 2 |C|C|C|C|C|C|C|C| 3 |0|0|F|F|0|0|0|i| 4 |r|l|u|d|0|0|0|0|
|---------------| |---------------| |---------------| |---------------|
Byte 1: Bit7~Bit6 => 00, Normal data packet
=> 01, Absolute coordination packet
=> 10, Notify packet
Bit5 => 1
Bit4 => when in absolute coordinate mode (valid when EN_PKT_GO is 1):
0: left button is generated by the on-pad command
1: left button is generated by the external button
Bit3 => 1
Bit2 => Middle Button, 1 is pressed, 0 is not pressed.
Bit1 => Right Button, 1 is pressed, 0 is not pressed.
Bit0 => Left Button, 1 is pressed, 0 is not pressed.
Byte 2: Message Type => 0xB7 (Multi Finger, Multi Coordinate mode)
Byte 3: Bit7~Bit6 => Don't care
Bit5~Bit4 => Number of fingers
Bit3~Bit1 => Reserved
Bit0 => 1: enter gesture mode; 0: leaving gesture mode
Byte 4: Bit7 => scroll right button
Bit6 => scroll left button
Bit5 => scroll up button
Bit4 => scroll down button
* Note that if gesture and additional button(Bit4~Bit7)
happen at the same time, the button information will not
be sent.
Bit3~Bit0 => Reserved
Sample sequence of Multi-finger, Multi-coordinate mode:
notify packet (valid bit == 1), abs pkt 1, abs pkt 2, abs pkt 1,
abs pkt 2, ..., notify packet (valid bit == 0)
==============================================================================
* FSP Enable/Disable packet
@@ -409,7 +500,8 @@ offset width default r/w name
0: read only, 1: read/write enable
(Note that following registers does not require clock gating being
enabled prior to write: 05 06 07 08 09 0c 0f 10 11 12 16 17 18 23 2e
40 41 42 43.)
40 41 42 43. In addition to that, this bit must be 1 when gesture
mode is enabled)
0x31 RW on-pad command detection
bit7 0 RW on-pad command left button down tag
@@ -463,6 +555,10 @@ offset width default r/w name
absolute coordinates; otherwise, host only receives packets with
relative coordinate.)
bit7 0 RW EN_PS2_F2: PS/2 gesture mode 2nd
finger packet enable
0: disable, 1: enable
0x43 RW on-pad control
bit0 0 RW on-pad control enable
0: disable, 1: enable

View File

@@ -5,6 +5,8 @@
#ifndef __ASM_ARCH_EP93XX_KEYPAD_H
#define __ASM_ARCH_EP93XX_KEYPAD_H
struct matrix_keymap_data;
/* flags for the ep93xx_keypad driver */
#define EP93XX_KEYPAD_DISABLE_3_KEY (1<<0) /* disable 3-key reset */
#define EP93XX_KEYPAD_DIAG_MODE (1<<1) /* diagnostic mode */
@@ -15,15 +17,13 @@
/**
* struct ep93xx_keypad_platform_data - platform specific device structure
* @matrix_key_map: array of keycodes defining the keypad matrix
* @matrix_key_map_size: ARRAY_SIZE(matrix_key_map)
* @debounce: debounce start count; terminal count is 0xff
* @prescale: row/column counter pre-scaler load value
* @flags: see above
* @keymap_data: pointer to &matrix_keymap_data
* @debounce: debounce start count; terminal count is 0xff
* @prescale: row/column counter pre-scaler load value
* @flags: see above
*/
struct ep93xx_keypad_platform_data {
unsigned int *matrix_key_map;
int matrix_key_map_size;
struct matrix_keymap_data *keymap_data;
unsigned int debounce;
unsigned int prescale;
unsigned int flags;

View File

@@ -1185,11 +1185,6 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
rep = (down == 2);
#ifdef CONFIG_MAC_EMUMOUSEBTN
if (mac_hid_mouse_emulate_buttons(1, keycode, down))
return;
#endif /* CONFIG_MAC_EMUMOUSEBTN */
if ((raw_mode = (kbd->kbdmode == VC_RAW)) && !hw_raw)
if (emulate_raw(vc, keycode, !down << 7))
if (keycode < BTN_MISC && printk_ratelimit())
@@ -1328,6 +1323,21 @@ static void kbd_event(struct input_handle *handle, unsigned int event_type,
schedule_console_callback();
}
static bool kbd_match(struct input_handler *handler, struct input_dev *dev)
{
int i;
if (test_bit(EV_SND, dev->evbit))
return true;
if (test_bit(EV_KEY, dev->evbit))
for (i = KEY_RESERVED; i < BTN_MISC; i++)
if (test_bit(i, dev->keybit))
return true;
return false;
}
/*
* When a keyboard (or other input device) is found, the kbd_connect
* function is called. The function then looks at the device, and if it
@@ -1339,14 +1349,6 @@ static int kbd_connect(struct input_handler *handler, struct input_dev *dev,
{
struct input_handle *handle;
int error;
int i;
for (i = KEY_RESERVED; i < BTN_MISC; i++)
if (test_bit(i, dev->keybit))
break;
if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit))
return -ENODEV;
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
if (!handle)
@@ -1412,6 +1414,7 @@ MODULE_DEVICE_TABLE(input, kbd_ids);
static struct input_handler kbd_handler = {
.event = kbd_event,
.match = kbd_match,
.connect = kbd_connect,
.disconnect = kbd_disconnect,
.start = kbd_start,

View File

@@ -278,6 +278,8 @@ static int evdev_open(struct inode *inode, struct file *file)
goto err_free_client;
file->private_data = client;
nonseekable_open(inode, file);
return 0;
err_free_client:

View File

@@ -46,7 +46,7 @@ struct emu {
int size;
};
static struct pci_device_id emu_tbl[] = {
static const struct pci_device_id emu_tbl[] = {
{ 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */
{ 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */

View File

@@ -140,7 +140,7 @@ static void __devexit fm801_gp_remove(struct pci_dev *pci)
}
}
static struct pci_device_id fm801_gp_id_table[] = {
static const struct pci_device_id fm801_gp_id_table[] = {
{ PCI_VENDOR_ID_FORTEMEDIA, PCI_DEVICE_ID_FM801_GP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0 }
};

View File

@@ -11,6 +11,8 @@
* the Free Software Foundation.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/ioport.h>
@@ -190,9 +192,8 @@ static int gameport_bind_driver(struct gameport *gameport, struct gameport_drive
error = device_bind_driver(&gameport->dev);
if (error) {
printk(KERN_WARNING
"gameport: device_bind_driver() failed "
"for %s (%s) and %s, error: %d\n",
dev_warn(&gameport->dev,
"device_bind_driver() failed for %s (%s) and %s, error: %d\n",
gameport->phys, gameport->name,
drv->description, error);
drv->disconnect(gameport);
@@ -209,9 +210,9 @@ static void gameport_find_driver(struct gameport *gameport)
error = device_attach(&gameport->dev);
if (error < 0)
printk(KERN_WARNING
"gameport: device_attach() failed for %s (%s), error: %d\n",
gameport->phys, gameport->name, error);
dev_warn(&gameport->dev,
"device_attach() failed for %s (%s), error: %d\n",
gameport->phys, gameport->name, error);
}
@@ -262,17 +263,14 @@ static int gameport_queue_event(void *object, struct module *owner,
event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC);
if (!event) {
printk(KERN_ERR
"gameport: Not enough memory to queue event %d\n",
event_type);
pr_err("Not enough memory to queue event %d\n", event_type);
retval = -ENOMEM;
goto out;
}
if (!try_module_get(owner)) {
printk(KERN_WARNING
"gameport: Can't get module reference, dropping event %d\n",
event_type);
pr_warning("Can't get module reference, dropping event %d\n",
event_type);
kfree(event);
retval = -EINVAL;
goto out;
@@ -298,14 +296,12 @@ static void gameport_free_event(struct gameport_event *event)
static void gameport_remove_duplicate_events(struct gameport_event *event)
{
struct list_head *node, *next;
struct gameport_event *e;
struct gameport_event *e, *next;
unsigned long flags;
spin_lock_irqsave(&gameport_event_lock, flags);
list_for_each_safe(node, next, &gameport_event_list) {
e = list_entry(node, struct gameport_event, node);
list_for_each_entry_safe(e, next, &gameport_event_list, node) {
if (event->object == e->object) {
/*
* If this event is of different type we should not
@@ -315,7 +311,7 @@ static void gameport_remove_duplicate_events(struct gameport_event *event)
if (event->type != e->type)
break;
list_del_init(node);
list_del_init(&e->node);
gameport_free_event(e);
}
}
@@ -325,23 +321,18 @@ static void gameport_remove_duplicate_events(struct gameport_event *event)
static struct gameport_event *gameport_get_event(void)
{
struct gameport_event *event;
struct list_head *node;
struct gameport_event *event = NULL;
unsigned long flags;
spin_lock_irqsave(&gameport_event_lock, flags);
if (list_empty(&gameport_event_list)) {
spin_unlock_irqrestore(&gameport_event_lock, flags);
return NULL;
if (!list_empty(&gameport_event_list)) {
event = list_first_entry(&gameport_event_list,
struct gameport_event, node);
list_del_init(&event->node);
}
node = gameport_event_list.next;
event = list_entry(node, struct gameport_event, node);
list_del_init(node);
spin_unlock_irqrestore(&gameport_event_lock, flags);
return event;
}
@@ -360,16 +351,14 @@ static void gameport_handle_event(void)
if ((event = gameport_get_event())) {
switch (event->type) {
case GAMEPORT_REGISTER_PORT:
gameport_add_port(event->object);
break;
case GAMEPORT_ATTACH_DRIVER:
gameport_attach_driver(event->object);
break;
case GAMEPORT_REGISTER_PORT:
gameport_add_port(event->object);
break;
default:
break;
case GAMEPORT_ATTACH_DRIVER:
gameport_attach_driver(event->object);
break;
}
gameport_remove_duplicate_events(event);
@@ -385,16 +374,14 @@ static void gameport_handle_event(void)
*/
static void gameport_remove_pending_events(void *object)
{
struct list_head *node, *next;
struct gameport_event *event;
struct gameport_event *event, *next;
unsigned long flags;
spin_lock_irqsave(&gameport_event_lock, flags);
list_for_each_safe(node, next, &gameport_event_list) {
event = list_entry(node, struct gameport_event, node);
list_for_each_entry_safe(event, next, &gameport_event_list, node) {
if (event->object == object) {
list_del_init(node);
list_del_init(&event->node);
gameport_free_event(event);
}
}
@@ -441,7 +428,6 @@ static int gameport_thread(void *nothing)
kthread_should_stop() || !list_empty(&gameport_event_list));
} while (!kthread_should_stop());
printk(KERN_DEBUG "gameport: kgameportd exiting\n");
return 0;
}
@@ -453,6 +439,7 @@ static int gameport_thread(void *nothing)
static ssize_t gameport_show_description(struct device *dev, struct device_attribute *attr, char *buf)
{
struct gameport *gameport = to_gameport_port(dev);
return sprintf(buf, "%s\n", gameport->name);
}
@@ -521,7 +508,8 @@ static void gameport_init_port(struct gameport *gameport)
mutex_init(&gameport->drv_mutex);
device_initialize(&gameport->dev);
dev_set_name(&gameport->dev, "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1);
dev_set_name(&gameport->dev, "gameport%lu",
(unsigned long)atomic_inc_return(&gameport_no) - 1);
gameport->dev.bus = &gameport_bus;
gameport->dev.release = gameport_release_port;
if (gameport->parent)
@@ -550,19 +538,17 @@ static void gameport_add_port(struct gameport *gameport)
list_add_tail(&gameport->node, &gameport_list);
if (gameport->io)
printk(KERN_INFO "gameport: %s is %s, io %#x, speed %dkHz\n",
gameport->name, gameport->phys, gameport->io, gameport->speed);
dev_info(&gameport->dev, "%s is %s, io %#x, speed %dkHz\n",
gameport->name, gameport->phys, gameport->io, gameport->speed);
else
printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n",
dev_info(&gameport->dev, "%s is %s, speed %dkHz\n",
gameport->name, gameport->phys, gameport->speed);
error = device_add(&gameport->dev);
if (error)
printk(KERN_ERR
"gameport: device_add() failed for %s (%s), error: %d\n",
dev_err(&gameport->dev,
"device_add() failed for %s (%s), error: %d\n",
gameport->phys, gameport->name, error);
else
gameport->registered = 1;
}
/*
@@ -584,10 +570,8 @@ static void gameport_destroy_port(struct gameport *gameport)
gameport->parent = NULL;
}
if (gameport->registered) {
if (device_is_registered(&gameport->dev))
device_del(&gameport->dev);
gameport->registered = 0;
}
list_del_init(&gameport->node);
@@ -705,8 +689,7 @@ static void gameport_attach_driver(struct gameport_driver *drv)
error = driver_attach(&drv->driver);
if (error)
printk(KERN_ERR
"gameport: driver_attach() failed for %s, error: %d\n",
pr_err("driver_attach() failed for %s, error: %d\n",
drv->driver.name, error);
}
@@ -727,8 +710,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner
error = driver_register(&drv->driver);
if (error) {
printk(KERN_ERR
"gameport: driver_register() failed for %s, error: %d\n",
pr_err("driver_register() failed for %s, error: %d\n",
drv->driver.name, error);
return error;
}
@@ -828,7 +810,7 @@ static int __init gameport_init(void)
error = bus_register(&gameport_bus);
if (error) {
printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error);
pr_err("failed to register gameport bus, error: %d\n", error);
return error;
}
@@ -836,7 +818,7 @@ static int __init gameport_init(void)
if (IS_ERR(gameport_task)) {
bus_unregister(&gameport_bus);
error = PTR_ERR(gameport_task);
printk(KERN_ERR "gameport: Failed to start kgameportd, error: %d\n", error);
pr_err("Failed to start kgameportd, error: %d\n", error);
return error;
}

View File

@@ -166,7 +166,7 @@ static int ns558_isa_probe(int io)
#ifdef CONFIG_PNP
static struct pnp_device_id pnp_devids[] = {
static const struct pnp_device_id pnp_devids[] = {
{ .id = "@P@0001", .driver_data = 0 }, /* ALS 100 */
{ .id = "@P@0020", .driver_data = 0 }, /* ALS 200 */
{ .id = "@P@1001", .driver_data = 0 }, /* ALS 100+ */

View File

@@ -87,12 +87,14 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz)
}
/*
* Pass event through all open handles. This function is called with
* Pass event first through all filters and then, if event has not been
* filtered out, through all open handles. This function is called with
* dev->event_lock held and interrupts disabled.
*/
static void input_pass_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
struct input_handler *handler;
struct input_handle *handle;
rcu_read_lock();
@@ -100,11 +102,25 @@ static void input_pass_event(struct input_dev *dev,
handle = rcu_dereference(dev->grab);
if (handle)
handle->handler->event(handle, type, code, value);
else
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
if (handle->open)
handle->handler->event(handle,
type, code, value);
else {
bool filtered = false;
list_for_each_entry_rcu(handle, &dev->h_list, d_node) {
if (!handle->open)
continue;
handler = handle->handler;
if (!handler->filter) {
if (filtered)
break;
handler->event(handle, type, code, value);
} else if (handler->filter(handle, type, code, value))
filtered = true;
}
}
rcu_read_unlock();
}
@@ -615,12 +631,12 @@ static int input_default_setkeycode(struct input_dev *dev,
}
}
clear_bit(old_keycode, dev->keybit);
set_bit(keycode, dev->keybit);
__clear_bit(old_keycode, dev->keybit);
__set_bit(keycode, dev->keybit);
for (i = 0; i < dev->keycodemax; i++) {
if (input_fetch_keycode(dev, i) == old_keycode) {
set_bit(old_keycode, dev->keybit);
__set_bit(old_keycode, dev->keybit);
break; /* Setting the bit twice is useless, so break */
}
}
@@ -678,6 +694,9 @@ int input_set_keycode(struct input_dev *dev, int scancode, int keycode)
if (retval)
goto out;
/* Make sure KEY_RESERVED did not get enabled. */
__clear_bit(KEY_RESERVED, dev->keybit);
/*
* Simulate keyup event if keycode is not present
* in the keymap anymore
@@ -705,12 +724,13 @@ EXPORT_SYMBOL(input_set_keycode);
if (i != BITS_TO_LONGS(max)) \
continue;
static const struct input_device_id *input_match_device(const struct input_device_id *id,
static const struct input_device_id *input_match_device(struct input_handler *handler,
struct input_dev *dev)
{
const struct input_device_id *id;
int i;
for (; id->flags || id->driver_info; id++) {
for (id = handler->id_table; id->flags || id->driver_info; id++) {
if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)
if (id->bustype != dev->id.bustype)
@@ -738,7 +758,8 @@ static const struct input_device_id *input_match_device(const struct input_devic
MATCH_BIT(ffbit, FF_MAX);
MATCH_BIT(swbit, SW_MAX);
return id;
if (!handler->match || handler->match(handler, dev))
return id;
}
return NULL;
@@ -749,10 +770,7 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han
const struct input_device_id *id;
int error;
if (handler->blacklist && input_match_device(handler->blacklist, dev))
return -ENODEV;
id = input_match_device(handler->id_table, dev);
id = input_match_device(handler, dev);
if (!id)
return -ENODEV;
@@ -988,6 +1006,8 @@ static int input_handlers_seq_show(struct seq_file *seq, void *v)
union input_seq_state *state = (union input_seq_state *)&seq->private;
seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name);
if (handler->filter)
seq_puts(seq, " (filter)");
if (handler->fops)
seq_printf(seq, " Minor=%d", handler->minor);
seq_putc(seq, '\n');
@@ -1551,6 +1571,25 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
}
EXPORT_SYMBOL(input_set_capability);
#define INPUT_CLEANSE_BITMASK(dev, type, bits) \
do { \
if (!test_bit(EV_##type, dev->evbit)) \
memset(dev->bits##bit, 0, \
sizeof(dev->bits##bit)); \
} while (0)
static void input_cleanse_bitmasks(struct input_dev *dev)
{
INPUT_CLEANSE_BITMASK(dev, KEY, key);
INPUT_CLEANSE_BITMASK(dev, REL, rel);
INPUT_CLEANSE_BITMASK(dev, ABS, abs);
INPUT_CLEANSE_BITMASK(dev, MSC, msc);
INPUT_CLEANSE_BITMASK(dev, LED, led);
INPUT_CLEANSE_BITMASK(dev, SND, snd);
INPUT_CLEANSE_BITMASK(dev, FF, ff);
INPUT_CLEANSE_BITMASK(dev, SW, sw);
}
/**
* input_register_device - register device with input core
* @dev: device to be registered
@@ -1570,13 +1609,19 @@ int input_register_device(struct input_dev *dev)
const char *path;
int error;
/* Every input device generates EV_SYN/SYN_REPORT events. */
__set_bit(EV_SYN, dev->evbit);
/* KEY_RESERVED is not supposed to be transmitted to userspace. */
__clear_bit(KEY_RESERVED, dev->keybit);
/* Make sure that bitmasks not mentioned in dev->evbit are clean. */
input_cleanse_bitmasks(dev);
/*
* If delay and period are pre-set by the driver, then autorepeating
* is handled by the driver itself and we don't do it in input.c.
*/
init_timer(&dev->timer);
if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
dev->timer.data = (long) dev;
@@ -1776,7 +1821,16 @@ int input_register_handle(struct input_handle *handle)
error = mutex_lock_interruptible(&dev->mutex);
if (error)
return error;
list_add_tail_rcu(&handle->d_node, &dev->h_list);
/*
* Filters go to the head of the list, normal handlers
* to the tail.
*/
if (handler->filter)
list_add_rcu(&handle->d_node, &dev->h_list);
else
list_add_tail_rcu(&handle->d_node, &dev->h_list);
mutex_unlock(&dev->mutex);
/*

View File

@@ -286,6 +286,8 @@ static int joydev_open(struct inode *inode, struct file *file)
goto err_free_client;
file->private_data = client;
nonseekable_open(inode, file);
return 0;
err_free_client:
@@ -775,6 +777,20 @@ static void joydev_cleanup(struct joydev *joydev)
input_close_device(handle);
}
static bool joydev_match(struct input_handler *handler, struct input_dev *dev)
{
/* Avoid touchpads and touchscreens */
if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_TOUCH, dev->keybit))
return false;
/* Avoid tablets, digitisers and similar devices */
if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_DIGI, dev->keybit))
return false;
return true;
}
static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
@@ -894,22 +910,6 @@ static void joydev_disconnect(struct input_handle *handle)
put_device(&joydev->dev);
}
static const struct input_device_id joydev_blacklist[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
INPUT_DEVICE_ID_MATCH_KEYBIT,
.evbit = { BIT_MASK(EV_KEY) },
.keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
}, /* Avoid itouchpads and touchscreens */
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
INPUT_DEVICE_ID_MATCH_KEYBIT,
.evbit = { BIT_MASK(EV_KEY) },
.keybit = { [BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_DIGI) },
}, /* Avoid tablets, digitisers and similar devices */
{ } /* Terminating entry */
};
static const struct input_device_id joydev_ids[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
@@ -936,13 +936,13 @@ MODULE_DEVICE_TABLE(input, joydev_ids);
static struct input_handler joydev_handler = {
.event = joydev_event,
.match = joydev_match,
.connect = joydev_connect,
.disconnect = joydev_disconnect,
.fops = &joydev_fops,
.minor = JOYDEV_MINOR_BASE,
.name = "joydev",
.id_table = joydev_ids,
.blacklist = joydev_blacklist,
};
static int __init joydev_init(void)

View File

@@ -221,6 +221,7 @@ config JOYSTICK_DB9
config JOYSTICK_GAMECON
tristate "Multisystem, NES, SNES, N64, PSX joysticks and gamepads"
depends on PARPORT
select INPUT_FF_MEMLESS
---help---
Say Y here if you have a Nintendo Entertainment System gamepad,
Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad,

File diff suppressed because it is too large Load Diff

View File

@@ -86,9 +86,8 @@
/* xbox d-pads should map to buttons, as is required for DDR pads
but we map them to axes when possible to simplify things */
#define MAP_DPAD_TO_BUTTONS 0
#define MAP_DPAD_TO_AXES 1
#define MAP_DPAD_UNKNOWN 2
#define MAP_DPAD_TO_BUTTONS (1 << 0)
#define MAP_TRIGGERS_TO_BUTTONS (1 << 1)
#define XTYPE_XBOX 0
#define XTYPE_XBOX360 1
@@ -99,57 +98,61 @@ static int dpad_to_buttons;
module_param(dpad_to_buttons, bool, S_IRUGO);
MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads");
static int triggers_to_buttons;
module_param(triggers_to_buttons, bool, S_IRUGO);
MODULE_PARM_DESC(triggers_to_buttons, "Map triggers to buttons rather than axes for unknown pads");
static const struct xpad_device {
u16 idVendor;
u16 idProduct;
char *name;
u8 dpad_mapping;
u8 mapping;
u8 xtype;
} xpad_device[] = {
{ 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX },
{ 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX },
{ 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX },
{ 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX },
{ 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
{ 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x046d, 0xc242, "Logitech Chillstream Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
{ 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 },
{ 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX },
{ 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX },
{ 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX },
{ 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", 0, XTYPE_XBOX },
{ 0x0738, 0x4516, "Mad Catz Control Pad", 0, XTYPE_XBOX },
{ 0x0738, 0x4522, "Mad Catz LumiCON", 0, XTYPE_XBOX },
{ 0x0738, 0x4526, "Mad Catz Control Pad Pro", 0, XTYPE_XBOX },
{ 0x0738, 0x4536, "Mad Catz MicroCON", 0, XTYPE_XBOX },
{ 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", 0, XTYPE_XBOX },
{ 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", 0, XTYPE_XBOX360 },
{ 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0c12, 0x880a, "Pelican Eclipse PL-2023", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },
{ 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX },
{ 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },
{ 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX },
{ 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX },
{ 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX },
{ 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX },
{ 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX },
{ 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX },
{ 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 },
{ 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX },
{ 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX },
{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
{ 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
{ 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 },
{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
{ 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
{ 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
{ 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_DPAD_TO_AXES, XTYPE_XBOX360 },
{ 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX },
{ 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN }
{ 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
{ 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX },
{ 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN }
};
/* buttons shared with xbox and xbox360 */
@@ -165,13 +168,20 @@ static const signed short xpad_btn[] = {
-1 /* terminating entry */
};
/* only used if MAP_DPAD_TO_BUTTONS */
/* used when dpad is mapped to nuttons */
static const signed short xpad_btn_pad[] = {
BTN_LEFT, BTN_RIGHT, /* d-pad left, right */
BTN_0, BTN_1, /* d-pad up, down (XXX names??) */
-1 /* terminating entry */
};
/* used when triggers are mapped to buttons */
static const signed short xpad_btn_triggers[] = {
BTN_TL2, BTN_TR2, /* triggers left/right */
-1
};
static const signed short xpad360_btn[] = { /* buttons for x360 controller */
BTN_TL, BTN_TR, /* Button LB/RB */
BTN_MODE, /* The big X button */
@@ -181,16 +191,21 @@ static const signed short xpad360_btn[] = { /* buttons for x360 controller */
static const signed short xpad_abs[] = {
ABS_X, ABS_Y, /* left stick */
ABS_RX, ABS_RY, /* right stick */
ABS_Z, ABS_RZ, /* triggers left/right */
-1 /* terminating entry */
};
/* only used if MAP_DPAD_TO_AXES */
/* used when dpad is mapped to axes */
static const signed short xpad_abs_pad[] = {
ABS_HAT0X, ABS_HAT0Y, /* d-pad axes */
-1 /* terminating entry */
};
/* used when triggers are mapped to axes */
static const signed short xpad_abs_triggers[] = {
ABS_Z, ABS_RZ, /* triggers left/right */
-1
};
/* Xbox 360 has a vendor-specific class, so we cannot match it with only
* USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we
* match against vendor id as well. Wired Xbox 360 devices have protocol 1,
@@ -246,7 +261,7 @@ struct usb_xpad {
char phys[64]; /* physical device path */
int dpad_mapping; /* map d-pad to buttons or to axes */
int mapping; /* map d-pad to buttons or to axes */
int xtype; /* type of xbox device */
};
@@ -277,20 +292,25 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d
~(__s16) le16_to_cpup((__le16 *)(data + 18)));
/* triggers left/right */
input_report_abs(dev, ABS_Z, data[10]);
input_report_abs(dev, ABS_RZ, data[11]);
if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
input_report_key(dev, BTN_TL2, data[10]);
input_report_key(dev, BTN_TR2, data[11]);
} else {
input_report_abs(dev, ABS_Z, data[10]);
input_report_abs(dev, ABS_RZ, data[11]);
}
/* 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));
} else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ {
if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
input_report_key(dev, BTN_LEFT, data[2] & 0x04);
input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
input_report_key(dev, BTN_0, data[2] & 0x01); /* up */
input_report_key(dev, BTN_1, data[2] & 0x02); /* down */
} else {
input_report_abs(dev, ABS_HAT0X,
!!(data[2] & 0x08) - !!(data[2] & 0x04));
input_report_abs(dev, ABS_HAT0Y,
!!(data[2] & 0x02) - !!(data[2] & 0x01));
}
/* start/back buttons and stick press left/right */
@@ -328,17 +348,17 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
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));
} else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) {
if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
/* dpad as buttons (right, left, down, up) */
input_report_key(dev, BTN_LEFT, data[2] & 0x04);
input_report_key(dev, BTN_RIGHT, data[2] & 0x08);
input_report_key(dev, BTN_0, data[2] & 0x01); /* up */
input_report_key(dev, BTN_1, data[2] & 0x02); /* down */
} else {
input_report_abs(dev, ABS_HAT0X,
!!(data[2] & 0x08) - !!(data[2] & 0x04));
input_report_abs(dev, ABS_HAT0Y,
!!(data[2] & 0x02) - !!(data[2] & 0x01));
}
/* start/back buttons */
@@ -371,8 +391,13 @@ static void xpad360_process_packet(struct usb_xpad *xpad,
~(__s16) le16_to_cpup((__le16 *)(data + 12)));
/* triggers left/right */
input_report_abs(dev, ABS_Z, data[4]);
input_report_abs(dev, ABS_RZ, data[5]);
if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
input_report_key(dev, BTN_TL2, data[4]);
input_report_key(dev, BTN_TR2, data[5]);
} else {
input_report_abs(dev, ABS_Z, data[4]);
input_report_abs(dev, ABS_RZ, data[5]);
}
input_sync(dev);
}
@@ -505,7 +530,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
struct usb_endpoint_descriptor *ep_irq_out;
int error = -ENOMEM;
if (xpad->xtype != XTYPE_XBOX360)
if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
return 0;
xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN,
@@ -535,13 +560,13 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad)
static void xpad_stop_output(struct usb_xpad *xpad)
{
if (xpad->xtype == XTYPE_XBOX360)
if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX)
usb_kill_urb(xpad->irq_out);
}
static void xpad_deinit_output(struct usb_xpad *xpad)
{
if (xpad->xtype == XTYPE_XBOX360) {
if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) {
usb_free_urb(xpad->irq_out);
usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
xpad->odata, xpad->odata_dma);
@@ -554,24 +579,45 @@ static void xpad_stop_output(struct usb_xpad *xpad) {}
#endif
#ifdef CONFIG_JOYSTICK_XPAD_FF
static int xpad_play_effect(struct input_dev *dev, void *data,
struct ff_effect *effect)
static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
{
struct usb_xpad *xpad = input_get_drvdata(dev);
if (effect->type == FF_RUMBLE) {
__u16 strong = effect->u.rumble.strong_magnitude;
__u16 weak = effect->u.rumble.weak_magnitude;
xpad->odata[0] = 0x00;
xpad->odata[1] = 0x08;
xpad->odata[2] = 0x00;
xpad->odata[3] = strong / 256;
xpad->odata[4] = weak / 256;
xpad->odata[5] = 0x00;
xpad->odata[6] = 0x00;
xpad->odata[7] = 0x00;
xpad->irq_out->transfer_buffer_length = 8;
usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
switch (xpad->xtype) {
case XTYPE_XBOX:
xpad->odata[0] = 0x00;
xpad->odata[1] = 0x06;
xpad->odata[2] = 0x00;
xpad->odata[3] = strong / 256; /* left actuator */
xpad->odata[4] = 0x00;
xpad->odata[5] = weak / 256; /* right actuator */
xpad->irq_out->transfer_buffer_length = 6;
return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
case XTYPE_XBOX360:
xpad->odata[0] = 0x00;
xpad->odata[1] = 0x08;
xpad->odata[2] = 0x00;
xpad->odata[3] = strong / 256; /* left actuator? */
xpad->odata[4] = weak / 256; /* right actuator? */
xpad->odata[5] = 0x00;
xpad->odata[6] = 0x00;
xpad->odata[7] = 0x00;
xpad->irq_out->transfer_buffer_length = 8;
return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
default:
dbg("%s - rumble command sent to unsupported xpad type: %d",
__func__, xpad->xtype);
return -1;
}
}
return 0;
@@ -579,7 +625,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
static int xpad_init_ff(struct usb_xpad *xpad)
{
if (xpad->xtype != XTYPE_XBOX360)
if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
return 0;
input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
@@ -712,11 +758,11 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
input_set_abs_params(input_dev, abs, -32768, 32767, 16, 128);
break;
case ABS_Z:
case ABS_RZ: /* the triggers */
case ABS_RZ: /* the triggers (if mapped to axes) */
input_set_abs_params(input_dev, abs, 0, 255, 0, 0);
break;
case ABS_HAT0X:
case ABS_HAT0Y: /* the d-pad (only if MAP_DPAD_TO_AXES) */
case ABS_HAT0Y: /* the d-pad (only if dpad is mapped to axes */
input_set_abs_params(input_dev, abs, -1, 1, 0, 0);
break;
}
@@ -752,10 +798,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
goto fail2;
xpad->udev = udev;
xpad->dpad_mapping = xpad_device[i].dpad_mapping;
xpad->mapping = xpad_device[i].mapping;
xpad->xtype = xpad_device[i].xtype;
if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN)
xpad->dpad_mapping = !dpad_to_buttons;
if (xpad->xtype == XTYPE_UNKNOWN) {
if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
if (intf->cur_altsetting->desc.bInterfaceProtocol == 129)
@@ -764,7 +809,13 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->xtype = XTYPE_XBOX360;
} else
xpad->xtype = XTYPE_XBOX;
if (dpad_to_buttons)
xpad->mapping |= MAP_DPAD_TO_BUTTONS;
if (triggers_to_buttons)
xpad->mapping |= MAP_TRIGGERS_TO_BUTTONS;
}
xpad->dev = input_dev;
usb_make_path(udev, xpad->phys, sizeof(xpad->phys));
strlcat(xpad->phys, "/input0", sizeof(xpad->phys));
@@ -781,25 +832,37 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
/* set up buttons */
/* set up standard buttons and axes */
for (i = 0; xpad_common_btn[i] >= 0; i++)
set_bit(xpad_common_btn[i], input_dev->keybit);
if ((xpad->xtype == XTYPE_XBOX360) || (xpad->xtype == XTYPE_XBOX360W))
for (i = 0; xpad360_btn[i] >= 0; i++)
set_bit(xpad360_btn[i], input_dev->keybit);
else
for (i = 0; xpad_btn[i] >= 0; i++)
set_bit(xpad_btn[i], input_dev->keybit);
if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS)
for (i = 0; xpad_btn_pad[i] >= 0; i++)
set_bit(xpad_btn_pad[i], input_dev->keybit);
__set_bit(xpad_common_btn[i], input_dev->keybit);
/* set up axes */
for (i = 0; xpad_abs[i] >= 0; i++)
xpad_set_up_abs(input_dev, xpad_abs[i]);
if (xpad->dpad_mapping == MAP_DPAD_TO_AXES)
/* Now set up model-specific ones */
if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W) {
for (i = 0; xpad360_btn[i] >= 0; i++)
__set_bit(xpad360_btn[i], input_dev->keybit);
} else {
for (i = 0; xpad_btn[i] >= 0; i++)
__set_bit(xpad_btn[i], input_dev->keybit);
}
if (xpad->mapping & MAP_DPAD_TO_BUTTONS) {
for (i = 0; xpad_btn_pad[i] >= 0; i++)
__set_bit(xpad_btn_pad[i], input_dev->keybit);
} else {
for (i = 0; xpad_abs_pad[i] >= 0; i++)
xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
}
if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) {
for (i = 0; xpad_btn_triggers[i] >= 0; i++)
__set_bit(xpad_btn_triggers[i], input_dev->keybit);
} else {
for (i = 0; xpad_abs_triggers[i] >= 0; i++)
xpad_set_up_abs(input_dev, xpad_abs_triggers[i]);
}
error = xpad_init_output(intf, xpad);
if (error)

View File

@@ -35,10 +35,10 @@ config KEYBOARD_ADP5520
be called adp5520-keys.
config KEYBOARD_ADP5588
tristate "ADP5588 I2C QWERTY Keypad and IO Expander"
tristate "ADP5588/87 I2C QWERTY Keypad and IO Expander"
depends on I2C
help
Say Y here if you want to use a ADP5588 attached to your
Say Y here if you want to use a ADP5588/87 attached to your
system I2C bus.
To compile this driver as a module, choose M here: the
@@ -144,13 +144,15 @@ config KEYBOARD_BFIN
module will be called bf54x-keys.
config KEYBOARD_CORGI
tristate "Corgi keyboard"
tristate "Corgi keyboard (deprecated)"
depends on PXA_SHARPSL
default y
help
Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx
series of PDAs.
This driver is now deprecated, use generic GPIO based matrix
keyboard driver instead.
To compile this driver as a module, choose M here: the
module will be called corgikbd.
@@ -292,6 +294,15 @@ config KEYBOARD_MAX7359
To compile this driver as a module, choose M here: the
module will be called max7359_keypad.
config KEYBOARD_IMX
tristate "IMX keypad support"
depends on ARCH_MXC
help
Enable support for IMX keypad port.
To compile this driver as a module, choose M here: the
module will be called imx_keypad.
config KEYBOARD_NEWTON
tristate "Newton keyboard"
select SERIO
@@ -329,13 +340,15 @@ config KEYBOARD_PXA930_ROTARY
module will be called pxa930_rotary.
config KEYBOARD_SPITZ
tristate "Spitz keyboard"
tristate "Spitz keyboard (deprecated)"
depends on PXA_SHARPSL
default y
help
Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
SL-C3000 and Sl-C3100 series of PDAs.
This driver is now deprecated, use generic GPIO based matrix
keyboard driver instead.
To compile this driver as a module, choose M here: the
module will be called spitzkbd.
@@ -363,7 +376,7 @@ config KEYBOARD_SUNKBD
config KEYBOARD_SH_KEYSC
tristate "SuperH KEYSC keypad support"
depends on SUPERH
depends on SUPERH || ARCH_SHMOBILE
help
Say Y here if you want to use a keypad attached to the KEYSC block
on SuperH processors such as sh7722 and sh7343.
@@ -402,12 +415,14 @@ config KEYBOARD_TWL4030
module will be called twl4030_keypad.
config KEYBOARD_TOSA
tristate "Tosa keyboard"
tristate "Tosa keyboard (deprecated)"
depends on MACH_TOSA
default y
help
Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa)
This driver is now deprecated, use generic GPIO based matrix
keyboard driver instead.
To compile this driver as a module, choose M here: the
module will be called tosakbd.

View File

@@ -17,6 +17,7 @@ obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o
obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o

View File

@@ -1,6 +1,7 @@
/*
* File: drivers/input/keyboard/adp5588_keys.c
* Description: keypad driver for ADP5588 I2C QWERTY Keypad and IO Expander
* Description: keypad driver for ADP5588 and ADP5587
* I2C QWERTY Keypad and IO Expander
* Bugs: Enter bugs at http://blackfin.uclinux.org/
*
* Copyright (C) 2008-2009 Analog Devices Inc.
@@ -327,6 +328,7 @@ static const struct dev_pm_ops adp5588_dev_pm_ops = {
static const struct i2c_device_id adp5588_id[] = {
{ KBUILD_MODNAME, 0 },
{ "adp5587-keys", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adp5588_id);
@@ -357,5 +359,5 @@ module_exit(adp5588_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
MODULE_DESCRIPTION("ADP5588 Keypad driver");
MODULE_DESCRIPTION("ADP5588/87 Keypad driver");
MODULE_ALIAS("platform:adp5588-keys");

File diff suppressed because it is too large Load Diff

View File

@@ -69,7 +69,7 @@ struct ep93xx_keypad {
void __iomem *mmio_base;
unsigned int matrix_keycodes[EP93XX_MATRIX_SIZE];
unsigned short keycodes[EP93XX_MATRIX_SIZE];
int key1;
int key2;
@@ -79,24 +79,6 @@ struct ep93xx_keypad {
bool enabled;
};
static void ep93xx_keypad_build_keycode(struct ep93xx_keypad *keypad)
{
struct ep93xx_keypad_platform_data *pdata = keypad->pdata;
struct input_dev *input_dev = keypad->input_dev;
unsigned int *key;
int i;
key = &pdata->matrix_key_map[0];
for (i = 0; i < pdata->matrix_key_map_size; i++, key++) {
int row = KEY_ROW(*key);
int col = KEY_COL(*key);
int code = KEY_VAL(*key);
keypad->matrix_keycodes[(row << 3) + col] = code;
__set_bit(code, input_dev->keybit);
}
}
static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id)
{
struct ep93xx_keypad *keypad = dev_id;
@@ -107,10 +89,10 @@ static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id)
status = __raw_readl(keypad->mmio_base + KEY_REG);
keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT;
key1 = keypad->matrix_keycodes[keycode];
key1 = keypad->keycodes[keycode];
keycode = (status & KEY_REG_KEY2_MASK) >> KEY_REG_KEY2_SHIFT;
key2 = keypad->matrix_keycodes[keycode];
key2 = keypad->keycodes[keycode];
if (status & KEY_REG_2KEYS) {
if (keypad->key1 && key1 != keypad->key1 && key2 != keypad->key1)
@@ -256,6 +238,7 @@ static int ep93xx_keypad_resume(struct platform_device *pdev)
static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
{
struct ep93xx_keypad *keypad;
const struct matrix_keymap_data *keymap_data;
struct input_dev *input_dev;
struct resource *res;
int err;
@@ -270,6 +253,12 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
goto failed_free;
}
keymap_data = keypad->pdata->keymap_data;
if (!keymap_data) {
err = -EINVAL;
goto failed_free;
}
keypad->irq = platform_get_irq(pdev, 0);
if (!keypad->irq) {
err = -ENXIO;
@@ -317,9 +306,9 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
input_dev->open = ep93xx_keypad_open;
input_dev->close = ep93xx_keypad_close;
input_dev->dev.parent = &pdev->dev;
input_dev->keycode = keypad->matrix_keycodes;
input_dev->keycodesize = sizeof(keypad->matrix_keycodes[0]);
input_dev->keycodemax = ARRAY_SIZE(keypad->matrix_keycodes);
input_dev->keycode = keypad->keycodes;
input_dev->keycodesize = sizeof(keypad->keycodes[0]);
input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes);
input_set_drvdata(input_dev, keypad);
@@ -327,7 +316,8 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev)
if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT)
input_dev->evbit[0] |= BIT_MASK(EV_REP);
ep93xx_keypad_build_keycode(keypad);
matrix_keypad_build_keymap(keymap_data, 3,
input_dev->keycode, input_dev->keybit);
platform_set_drvdata(pdev, keypad);
err = request_irq(keypad->irq, ep93xx_keypad_irq_handler,

View File

@@ -30,13 +30,289 @@ struct gpio_button_data {
struct input_dev *input;
struct timer_list timer;
struct work_struct work;
bool disabled;
};
struct gpio_keys_drvdata {
struct input_dev *input;
struct mutex disable_lock;
unsigned int n_buttons;
struct gpio_button_data data[0];
};
/*
* SYSFS interface for enabling/disabling keys and switches:
*
* There are 4 attributes under /sys/devices/platform/gpio-keys/
* keys [ro] - bitmap of keys (EV_KEY) which can be
* disabled
* switches [ro] - bitmap of switches (EV_SW) which can be
* disabled
* disabled_keys [rw] - bitmap of keys currently disabled
* disabled_switches [rw] - bitmap of switches currently disabled
*
* Userland can change these values and hence disable event generation
* for each key (or switch). Disabling a key means its interrupt line
* is disabled.
*
* For example, if we have following switches set up as gpio-keys:
* SW_DOCK = 5
* SW_CAMERA_LENS_COVER = 9
* SW_KEYPAD_SLIDE = 10
* SW_FRONT_PROXIMITY = 11
* This is read from switches:
* 11-9,5
* Next we want to disable proximity (11) and dock (5), we write:
* 11,5
* to file disabled_switches. Now proximity and dock IRQs are disabled.
* This can be verified by reading the file disabled_switches:
* 11,5
* If we now want to enable proximity (11) switch we write:
* 5
* to disabled_switches.
*
* We can disable only those keys which don't allow sharing the irq.
*/
/**
* get_n_events_by_type() - returns maximum number of events per @type
* @type: type of button (%EV_KEY, %EV_SW)
*
* Return value of this function can be used to allocate bitmap
* large enough to hold all bits for given type.
*/
static inline int get_n_events_by_type(int type)
{
BUG_ON(type != EV_SW && type != EV_KEY);
return (type == EV_KEY) ? KEY_CNT : SW_CNT;
}
/**
* gpio_keys_disable_button() - disables given GPIO button
* @bdata: button data for button to be disabled
*
* Disables button pointed by @bdata. This is done by masking
* IRQ line. After this function is called, button won't generate
* input events anymore. Note that one can only disable buttons
* that don't share IRQs.
*
* Make sure that @bdata->disable_lock is locked when entering
* this function to avoid races when concurrent threads are
* disabling buttons at the same time.
*/
static void gpio_keys_disable_button(struct gpio_button_data *bdata)
{
if (!bdata->disabled) {
/*
* Disable IRQ and possible debouncing timer.
*/
disable_irq(gpio_to_irq(bdata->button->gpio));
if (bdata->button->debounce_interval)
del_timer_sync(&bdata->timer);
bdata->disabled = true;
}
}
/**
* gpio_keys_enable_button() - enables given GPIO button
* @bdata: button data for button to be disabled
*
* Enables given button pointed by @bdata.
*
* Make sure that @bdata->disable_lock is locked when entering
* this function to avoid races with concurrent threads trying
* to enable the same button at the same time.
*/
static void gpio_keys_enable_button(struct gpio_button_data *bdata)
{
if (bdata->disabled) {
enable_irq(gpio_to_irq(bdata->button->gpio));
bdata->disabled = false;
}
}
/**
* gpio_keys_attr_show_helper() - fill in stringified bitmap of buttons
* @ddata: pointer to drvdata
* @buf: buffer where stringified bitmap is written
* @type: button type (%EV_KEY, %EV_SW)
* @only_disabled: does caller want only those buttons that are
* currently disabled or all buttons that can be
* disabled
*
* This function writes buttons that can be disabled to @buf. If
* @only_disabled is true, then @buf contains only those buttons
* that are currently disabled. Returns 0 on success or negative
* errno on failure.
*/
static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata,
char *buf, unsigned int type,
bool only_disabled)
{
int n_events = get_n_events_by_type(type);
unsigned long *bits;
ssize_t ret;
int i;
bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL);
if (!bits)
return -ENOMEM;
for (i = 0; i < ddata->n_buttons; i++) {
struct gpio_button_data *bdata = &ddata->data[i];
if (bdata->button->type != type)
continue;
if (only_disabled && !bdata->disabled)
continue;
__set_bit(bdata->button->code, bits);
}
ret = bitmap_scnlistprintf(buf, PAGE_SIZE - 2, bits, n_events);
buf[ret++] = '\n';
buf[ret] = '\0';
kfree(bits);
return ret;
}
/**
* gpio_keys_attr_store_helper() - enable/disable buttons based on given bitmap
* @ddata: pointer to drvdata
* @buf: buffer from userspace that contains stringified bitmap
* @type: button type (%EV_KEY, %EV_SW)
*
* This function parses stringified bitmap from @buf and disables/enables
* GPIO buttons accordinly. Returns 0 on success and negative error
* on failure.
*/
static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata,
const char *buf, unsigned int type)
{
int n_events = get_n_events_by_type(type);
unsigned long *bits;
ssize_t error;
int i;
bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL);
if (!bits)
return -ENOMEM;
error = bitmap_parselist(buf, bits, n_events);
if (error)
goto out;
/* First validate */
for (i = 0; i < ddata->n_buttons; i++) {
struct gpio_button_data *bdata = &ddata->data[i];
if (bdata->button->type != type)
continue;
if (test_bit(bdata->button->code, bits) &&
!bdata->button->can_disable) {
error = -EINVAL;
goto out;
}
}
mutex_lock(&ddata->disable_lock);
for (i = 0; i < ddata->n_buttons; i++) {
struct gpio_button_data *bdata = &ddata->data[i];
if (bdata->button->type != type)
continue;
if (test_bit(bdata->button->code, bits))
gpio_keys_disable_button(bdata);
else
gpio_keys_enable_button(bdata);
}
mutex_unlock(&ddata->disable_lock);
out:
kfree(bits);
return error;
}
#define ATTR_SHOW_FN(name, type, only_disabled) \
static ssize_t gpio_keys_show_##name(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
struct platform_device *pdev = to_platform_device(dev); \
struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \
\
return gpio_keys_attr_show_helper(ddata, buf, \
type, only_disabled); \
}
ATTR_SHOW_FN(keys, EV_KEY, false);
ATTR_SHOW_FN(switches, EV_SW, false);
ATTR_SHOW_FN(disabled_keys, EV_KEY, true);
ATTR_SHOW_FN(disabled_switches, EV_SW, true);
/*
* ATTRIBUTES:
*
* /sys/devices/platform/gpio-keys/keys [ro]
* /sys/devices/platform/gpio-keys/switches [ro]
*/
static DEVICE_ATTR(keys, S_IRUGO, gpio_keys_show_keys, NULL);
static DEVICE_ATTR(switches, S_IRUGO, gpio_keys_show_switches, NULL);
#define ATTR_STORE_FN(name, type) \
static ssize_t gpio_keys_store_##name(struct device *dev, \
struct device_attribute *attr, \
const char *buf, \
size_t count) \
{ \
struct platform_device *pdev = to_platform_device(dev); \
struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \
ssize_t error; \
\
error = gpio_keys_attr_store_helper(ddata, buf, type); \
if (error) \
return error; \
\
return count; \
}
ATTR_STORE_FN(disabled_keys, EV_KEY);
ATTR_STORE_FN(disabled_switches, EV_SW);
/*
* ATTRIBUTES:
*
* /sys/devices/platform/gpio-keys/disabled_keys [rw]
* /sys/devices/platform/gpio-keys/disables_switches [rw]
*/
static DEVICE_ATTR(disabled_keys, S_IWUSR | S_IRUGO,
gpio_keys_show_disabled_keys,
gpio_keys_store_disabled_keys);
static DEVICE_ATTR(disabled_switches, S_IWUSR | S_IRUGO,
gpio_keys_show_disabled_switches,
gpio_keys_store_disabled_switches);
static struct attribute *gpio_keys_attrs[] = {
&dev_attr_keys.attr,
&dev_attr_switches.attr,
&dev_attr_disabled_keys.attr,
&dev_attr_disabled_switches.attr,
NULL,
};
static struct attribute_group gpio_keys_attr_group = {
.attrs = gpio_keys_attrs,
};
static void gpio_keys_report_event(struct gpio_button_data *bdata)
{
struct gpio_keys_button *button = bdata->button;
@@ -79,11 +355,13 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
static int __devinit gpio_keys_setup_key(struct device *dev,
static int __devinit gpio_keys_setup_key(struct platform_device *pdev,
struct gpio_button_data *bdata,
struct gpio_keys_button *button)
{
char *desc = button->desc ? button->desc : "gpio_keys";
struct device *dev = &pdev->dev;
unsigned long irqflags;
int irq, error;
setup_timer(&bdata->timer, gpio_keys_timer, (unsigned long)bdata);
@@ -112,10 +390,15 @@ static int __devinit gpio_keys_setup_key(struct device *dev,
goto fail3;
}
error = request_irq(irq, gpio_keys_isr,
IRQF_SHARED |
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
desc, bdata);
irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
/*
* If platform has specified that the button can be disabled,
* we don't want it to share the interrupt line.
*/
if (!button->can_disable)
irqflags |= IRQF_SHARED;
error = request_irq(irq, gpio_keys_isr, irqflags, desc, bdata);
if (error) {
dev_err(dev, "Unable to claim irq %d; error %d\n",
irq, error);
@@ -149,6 +432,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
goto fail1;
}
ddata->input = input;
ddata->n_buttons = pdata->nbuttons;
mutex_init(&ddata->disable_lock);
platform_set_drvdata(pdev, ddata);
input->name = pdev->name;
@@ -164,8 +451,6 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
if (pdata->rep)
__set_bit(EV_REP, input->evbit);
ddata->input = input;
for (i = 0; i < pdata->nbuttons; i++) {
struct gpio_keys_button *button = &pdata->buttons[i];
struct gpio_button_data *bdata = &ddata->data[i];
@@ -174,7 +459,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
bdata->input = input;
bdata->button = button;
error = gpio_keys_setup_key(dev, bdata, button);
error = gpio_keys_setup_key(pdev, bdata, button);
if (error)
goto fail2;
@@ -184,11 +469,18 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
input_set_capability(input, type, button->code);
}
error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group);
if (error) {
dev_err(dev, "Unable to export keys/switches, error: %d\n",
error);
goto fail2;
}
error = input_register_device(input);
if (error) {
dev_err(dev, "Unable to register input device, "
"error: %d\n", error);
goto fail2;
dev_err(dev, "Unable to register input device, error: %d\n",
error);
goto fail3;
}
/* get current state of buttons */
@@ -200,6 +492,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
return 0;
fail3:
sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
fail2:
while (--i >= 0) {
free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
@@ -224,6 +518,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
struct input_dev *input = ddata->input;
int i;
sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
device_init_wakeup(&pdev->dev, 0);
for (i = 0; i < pdata->nbuttons; i++) {

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