mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
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:
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 }
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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+ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
/*
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user