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:
commit
8724fdb53d
|
@ -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");
|
||||
|
|
|
@ -40,26 +40,26 @@ module_param_named(set, atkbd_set, int, 0);
|
|||
MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3 = PS/2 native)");
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__hppa__)
|
||||
static int atkbd_reset;
|
||||
static bool atkbd_reset;
|
||||
#else
|
||||
static int atkbd_reset = 1;
|
||||
static bool atkbd_reset = true;
|
||||
#endif
|
||||
module_param_named(reset, atkbd_reset, bool, 0);
|
||||
MODULE_PARM_DESC(reset, "Reset keyboard during initialization");
|
||||
|
||||
static int atkbd_softrepeat;
|
||||
static bool atkbd_softrepeat;
|
||||
module_param_named(softrepeat, atkbd_softrepeat, bool, 0);
|
||||
MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat");
|
||||
|
||||
static int atkbd_softraw = 1;
|
||||
static bool atkbd_softraw = true;
|
||||
module_param_named(softraw, atkbd_softraw, bool, 0);
|
||||
MODULE_PARM_DESC(softraw, "Use software generated rawmode");
|
||||
|
||||
static int atkbd_scroll;
|
||||
static bool atkbd_scroll;
|
||||
module_param_named(scroll, atkbd_scroll, bool, 0);
|
||||
MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
|
||||
|
||||
static int atkbd_extra;
|
||||
static bool atkbd_extra;
|
||||
module_param_named(extra, atkbd_extra, bool, 0);
|
||||
MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards");
|
||||
|
||||
|
@ -153,16 +153,16 @@ static const unsigned short atkbd_unxlate_table[128] = {
|
|||
#define ATKBD_RET_HANGEUL 0xf2
|
||||
#define ATKBD_RET_ERR 0xff
|
||||
|
||||
#define ATKBD_KEY_UNKNOWN 0
|
||||
#define ATKBD_KEY_UNKNOWN 0
|
||||
#define ATKBD_KEY_NULL 255
|
||||
|
||||
#define ATKBD_SCR_1 254
|
||||
#define ATKBD_SCR_2 253
|
||||
#define ATKBD_SCR_4 252
|
||||
#define ATKBD_SCR_8 251
|
||||
#define ATKBD_SCR_CLICK 250
|
||||
#define ATKBD_SCR_LEFT 249
|
||||
#define ATKBD_SCR_RIGHT 248
|
||||
#define ATKBD_SCR_1 0xfffe
|
||||
#define ATKBD_SCR_2 0xfffd
|
||||
#define ATKBD_SCR_4 0xfffc
|
||||
#define ATKBD_SCR_8 0xfffb
|
||||
#define ATKBD_SCR_CLICK 0xfffa
|
||||
#define ATKBD_SCR_LEFT 0xfff9
|
||||
#define ATKBD_SCR_RIGHT 0xfff8
|
||||
|
||||
#define ATKBD_SPECIAL ATKBD_SCR_RIGHT
|
||||
|
||||
|
@ -177,7 +177,7 @@ static const unsigned short atkbd_unxlate_table[128] = {
|
|||
#define ATKBD_XL_HANJA 0x20
|
||||
|
||||
static const struct {
|
||||
unsigned char keycode;
|
||||
unsigned short keycode;
|
||||
unsigned char set2;
|
||||
} atkbd_scroll_keys[] = {
|
||||
{ ATKBD_SCR_1, 0xc5 },
|
||||
|
@ -206,18 +206,18 @@ struct atkbd {
|
|||
unsigned short keycode[ATKBD_KEYMAP_SIZE];
|
||||
DECLARE_BITMAP(force_release_mask, ATKBD_KEYMAP_SIZE);
|
||||
unsigned char set;
|
||||
unsigned char translated;
|
||||
unsigned char extra;
|
||||
unsigned char write;
|
||||
unsigned char softrepeat;
|
||||
unsigned char softraw;
|
||||
unsigned char scroll;
|
||||
unsigned char enabled;
|
||||
bool translated;
|
||||
bool extra;
|
||||
bool write;
|
||||
bool softrepeat;
|
||||
bool softraw;
|
||||
bool scroll;
|
||||
bool enabled;
|
||||
|
||||
/* Accessed only from interrupt */
|
||||
unsigned char emul;
|
||||
unsigned char resend;
|
||||
unsigned char release;
|
||||
bool resend;
|
||||
bool release;
|
||||
unsigned long xl_bit;
|
||||
unsigned int last;
|
||||
unsigned long time;
|
||||
|
@ -301,18 +301,18 @@ static const unsigned int xl_table[] = {
|
|||
* Checks if we should mangle the scancode to extract 'release' bit
|
||||
* in translated mode.
|
||||
*/
|
||||
static int atkbd_need_xlate(unsigned long xl_bit, unsigned char code)
|
||||
static bool atkbd_need_xlate(unsigned long xl_bit, unsigned char code)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1)
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(xl_table); i++)
|
||||
if (code == xl_table[i])
|
||||
return test_bit(i, &xl_bit);
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -359,7 +359,7 @@ static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code
|
|||
*/
|
||||
|
||||
static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
|
||||
unsigned int flags)
|
||||
unsigned int flags)
|
||||
{
|
||||
struct atkbd *atkbd = serio_get_drvdata(serio);
|
||||
struct input_dev *dev = atkbd->dev;
|
||||
|
@ -368,20 +368,18 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
|
|||
int value;
|
||||
unsigned short keycode;
|
||||
|
||||
#ifdef ATKBD_DEBUG
|
||||
printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
|
||||
#endif
|
||||
dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags);
|
||||
|
||||
#if !defined(__i386__) && !defined (__x86_64__)
|
||||
if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) {
|
||||
printk(KERN_WARNING "atkbd.c: frame/parity error: %02x\n", flags);
|
||||
dev_warn(&serio->dev, "Frame/parity error: %02x\n", flags);
|
||||
serio_write(serio, ATKBD_CMD_RESEND);
|
||||
atkbd->resend = 1;
|
||||
atkbd->resend = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!flags && data == ATKBD_RET_ACK)
|
||||
atkbd->resend = 0;
|
||||
atkbd->resend = false;
|
||||
#endif
|
||||
|
||||
if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK))
|
||||
|
@ -412,32 +410,32 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
|
|||
}
|
||||
|
||||
switch (code) {
|
||||
case ATKBD_RET_BAT:
|
||||
atkbd->enabled = 0;
|
||||
serio_reconnect(atkbd->ps2dev.serio);
|
||||
goto out;
|
||||
case ATKBD_RET_EMUL0:
|
||||
atkbd->emul = 1;
|
||||
goto out;
|
||||
case ATKBD_RET_EMUL1:
|
||||
atkbd->emul = 2;
|
||||
goto out;
|
||||
case ATKBD_RET_RELEASE:
|
||||
atkbd->release = 1;
|
||||
goto out;
|
||||
case ATKBD_RET_ACK:
|
||||
case ATKBD_RET_NAK:
|
||||
if (printk_ratelimit())
|
||||
printk(KERN_WARNING "atkbd.c: Spurious %s on %s. "
|
||||
"Some program might be trying access hardware directly.\n",
|
||||
data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
|
||||
goto out;
|
||||
case ATKBD_RET_ERR:
|
||||
atkbd->err_count++;
|
||||
#ifdef ATKBD_DEBUG
|
||||
printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
|
||||
#endif
|
||||
goto out;
|
||||
case ATKBD_RET_BAT:
|
||||
atkbd->enabled = false;
|
||||
serio_reconnect(atkbd->ps2dev.serio);
|
||||
goto out;
|
||||
case ATKBD_RET_EMUL0:
|
||||
atkbd->emul = 1;
|
||||
goto out;
|
||||
case ATKBD_RET_EMUL1:
|
||||
atkbd->emul = 2;
|
||||
goto out;
|
||||
case ATKBD_RET_RELEASE:
|
||||
atkbd->release = true;
|
||||
goto out;
|
||||
case ATKBD_RET_ACK:
|
||||
case ATKBD_RET_NAK:
|
||||
if (printk_ratelimit())
|
||||
dev_warn(&serio->dev,
|
||||
"Spurious %s on %s. "
|
||||
"Some program might be trying access hardware directly.\n",
|
||||
data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
|
||||
goto out;
|
||||
case ATKBD_RET_ERR:
|
||||
atkbd->err_count++;
|
||||
dev_dbg(&serio->dev, "Keyboard on %s reports too many keys pressed.\n",
|
||||
serio->phys);
|
||||
goto out;
|
||||
}
|
||||
|
||||
code = atkbd_compat_scancode(atkbd, code);
|
||||
|
@ -451,71 +449,72 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
|
|||
input_event(dev, EV_MSC, MSC_SCAN, code);
|
||||
|
||||
switch (keycode) {
|
||||
case ATKBD_KEY_NULL:
|
||||
break;
|
||||
case ATKBD_KEY_UNKNOWN:
|
||||
printk(KERN_WARNING
|
||||
"atkbd.c: Unknown key %s (%s set %d, code %#x on %s).\n",
|
||||
atkbd->release ? "released" : "pressed",
|
||||
atkbd->translated ? "translated" : "raw",
|
||||
atkbd->set, code, serio->phys);
|
||||
printk(KERN_WARNING
|
||||
"atkbd.c: Use 'setkeycodes %s%02x <keycode>' to make it known.\n",
|
||||
code & 0x80 ? "e0" : "", code & 0x7f);
|
||||
input_sync(dev);
|
||||
break;
|
||||
case ATKBD_SCR_1:
|
||||
scroll = 1 - atkbd->release * 2;
|
||||
break;
|
||||
case ATKBD_SCR_2:
|
||||
scroll = 2 - atkbd->release * 4;
|
||||
break;
|
||||
case ATKBD_SCR_4:
|
||||
scroll = 4 - atkbd->release * 8;
|
||||
break;
|
||||
case ATKBD_SCR_8:
|
||||
scroll = 8 - atkbd->release * 16;
|
||||
break;
|
||||
case ATKBD_SCR_CLICK:
|
||||
click = !atkbd->release;
|
||||
break;
|
||||
case ATKBD_SCR_LEFT:
|
||||
hscroll = -1;
|
||||
break;
|
||||
case ATKBD_SCR_RIGHT:
|
||||
hscroll = 1;
|
||||
break;
|
||||
default:
|
||||
if (atkbd->release) {
|
||||
value = 0;
|
||||
atkbd->last = 0;
|
||||
} else if (!atkbd->softrepeat && test_bit(keycode, dev->key)) {
|
||||
/* Workaround Toshiba laptop multiple keypress */
|
||||
value = time_before(jiffies, atkbd->time) && atkbd->last == code ? 1 : 2;
|
||||
} else {
|
||||
value = 1;
|
||||
atkbd->last = code;
|
||||
atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2;
|
||||
}
|
||||
case ATKBD_KEY_NULL:
|
||||
break;
|
||||
case ATKBD_KEY_UNKNOWN:
|
||||
dev_warn(&serio->dev,
|
||||
"Unknown key %s (%s set %d, code %#x on %s).\n",
|
||||
atkbd->release ? "released" : "pressed",
|
||||
atkbd->translated ? "translated" : "raw",
|
||||
atkbd->set, code, serio->phys);
|
||||
dev_warn(&serio->dev,
|
||||
"Use 'setkeycodes %s%02x <keycode>' to make it known.\n",
|
||||
code & 0x80 ? "e0" : "", code & 0x7f);
|
||||
input_sync(dev);
|
||||
break;
|
||||
case ATKBD_SCR_1:
|
||||
scroll = 1;
|
||||
break;
|
||||
case ATKBD_SCR_2:
|
||||
scroll = 2;
|
||||
break;
|
||||
case ATKBD_SCR_4:
|
||||
scroll = 4;
|
||||
break;
|
||||
case ATKBD_SCR_8:
|
||||
scroll = 8;
|
||||
break;
|
||||
case ATKBD_SCR_CLICK:
|
||||
click = !atkbd->release;
|
||||
break;
|
||||
case ATKBD_SCR_LEFT:
|
||||
hscroll = -1;
|
||||
break;
|
||||
case ATKBD_SCR_RIGHT:
|
||||
hscroll = 1;
|
||||
break;
|
||||
default:
|
||||
if (atkbd->release) {
|
||||
value = 0;
|
||||
atkbd->last = 0;
|
||||
} else if (!atkbd->softrepeat && test_bit(keycode, dev->key)) {
|
||||
/* Workaround Toshiba laptop multiple keypress */
|
||||
value = time_before(jiffies, atkbd->time) && atkbd->last == code ? 1 : 2;
|
||||
} else {
|
||||
value = 1;
|
||||
atkbd->last = code;
|
||||
atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2;
|
||||
}
|
||||
|
||||
input_event(dev, EV_KEY, keycode, value);
|
||||
input_sync(dev);
|
||||
input_event(dev, EV_KEY, keycode, value);
|
||||
input_sync(dev);
|
||||
|
||||
if (value && test_bit(code, atkbd->force_release_mask)) {
|
||||
input_report_key(dev, keycode, 0);
|
||||
input_sync(dev);
|
||||
}
|
||||
if (value && test_bit(code, atkbd->force_release_mask)) {
|
||||
input_report_key(dev, keycode, 0);
|
||||
input_sync(dev);
|
||||
}
|
||||
}
|
||||
|
||||
if (atkbd->scroll) {
|
||||
if (click != -1)
|
||||
input_report_key(dev, BTN_MIDDLE, click);
|
||||
input_report_rel(dev, REL_WHEEL, scroll);
|
||||
input_report_rel(dev, REL_WHEEL,
|
||||
atkbd->release ? -scroll : scroll);
|
||||
input_report_rel(dev, REL_HWHEEL, hscroll);
|
||||
input_sync(dev);
|
||||
}
|
||||
|
||||
atkbd->release = 0;
|
||||
atkbd->release = false;
|
||||
out:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -634,17 +633,18 @@ static int atkbd_event(struct input_dev *dev,
|
|||
|
||||
switch (type) {
|
||||
|
||||
case EV_LED:
|
||||
atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT);
|
||||
return 0;
|
||||
case EV_LED:
|
||||
atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT);
|
||||
return 0;
|
||||
|
||||
case EV_REP:
|
||||
if (!atkbd->softrepeat)
|
||||
atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT);
|
||||
return 0;
|
||||
case EV_REP:
|
||||
if (!atkbd->softrepeat)
|
||||
atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -655,7 +655,7 @@ static int atkbd_event(struct input_dev *dev,
|
|||
static inline void atkbd_enable(struct atkbd *atkbd)
|
||||
{
|
||||
serio_pause_rx(atkbd->ps2dev.serio);
|
||||
atkbd->enabled = 1;
|
||||
atkbd->enabled = true;
|
||||
serio_continue_rx(atkbd->ps2dev.serio);
|
||||
}
|
||||
|
||||
|
@ -667,7 +667,7 @@ static inline void atkbd_enable(struct atkbd *atkbd)
|
|||
static inline void atkbd_disable(struct atkbd *atkbd)
|
||||
{
|
||||
serio_pause_rx(atkbd->ps2dev.serio);
|
||||
atkbd->enabled = 0;
|
||||
atkbd->enabled = false;
|
||||
serio_continue_rx(atkbd->ps2dev.serio);
|
||||
}
|
||||
|
||||
|
@ -688,7 +688,9 @@ static int atkbd_probe(struct atkbd *atkbd)
|
|||
|
||||
if (atkbd_reset)
|
||||
if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_BAT))
|
||||
printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", ps2dev->serio->phys);
|
||||
dev_warn(&ps2dev->serio->dev,
|
||||
"keyboard reset failed on %s\n",
|
||||
ps2dev->serio->phys);
|
||||
|
||||
/*
|
||||
* Then we check the keyboard ID. We should get 0xab83 under normal conditions.
|
||||
|
@ -718,8 +720,9 @@ static int atkbd_probe(struct atkbd *atkbd)
|
|||
atkbd->id = (param[0] << 8) | param[1];
|
||||
|
||||
if (atkbd->id == 0xaca1 && atkbd->translated) {
|
||||
printk(KERN_ERR "atkbd.c: NCD terminal keyboards are only supported on non-translating\n");
|
||||
printk(KERN_ERR "atkbd.c: controllers. Use i8042.direct=1 to disable translation.\n");
|
||||
dev_err(&ps2dev->serio->dev,
|
||||
"NCD terminal keyboards are only supported on non-translating controlelrs. "
|
||||
"Use i8042.direct=1 to disable translation.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -737,7 +740,7 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra
|
|||
struct ps2dev *ps2dev = &atkbd->ps2dev;
|
||||
unsigned char param[2];
|
||||
|
||||
atkbd->extra = 0;
|
||||
atkbd->extra = false;
|
||||
/*
|
||||
* For known special keyboards we can go ahead and set the correct set.
|
||||
* We check for NCD PS/2 Sun, NorthGate OmniKey 101 and
|
||||
|
@ -756,7 +759,7 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra
|
|||
if (allow_extra) {
|
||||
param[0] = 0x71;
|
||||
if (!ps2_command(ps2dev, param, ATKBD_CMD_EX_ENABLE)) {
|
||||
atkbd->extra = 1;
|
||||
atkbd->extra = true;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
@ -821,7 +824,8 @@ static int atkbd_activate(struct atkbd *atkbd)
|
|||
*/
|
||||
|
||||
if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) {
|
||||
printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n",
|
||||
dev_err(&ps2dev->serio->dev,
|
||||
"Failed to enable keyboard on %s\n",
|
||||
ps2dev->serio->phys);
|
||||
return -1;
|
||||
}
|
||||
|
@ -1070,9 +1074,13 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd)
|
|||
input_dev->keycodesize = sizeof(unsigned short);
|
||||
input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode);
|
||||
|
||||
for (i = 0; i < ATKBD_KEYMAP_SIZE; i++)
|
||||
if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL)
|
||||
for (i = 0; i < ATKBD_KEYMAP_SIZE; i++) {
|
||||
if (atkbd->keycode[i] != KEY_RESERVED &&
|
||||
atkbd->keycode[i] != ATKBD_KEY_NULL &&
|
||||
atkbd->keycode[i] < ATKBD_SPECIAL) {
|
||||
__set_bit(atkbd->keycode[i], input_dev->keybit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1100,12 +1108,14 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
|
|||
|
||||
switch (serio->id.type) {
|
||||
|
||||
case SERIO_8042_XL:
|
||||
atkbd->translated = 1;
|
||||
case SERIO_8042:
|
||||
if (serio->write)
|
||||
atkbd->write = 1;
|
||||
break;
|
||||
case SERIO_8042_XL:
|
||||
atkbd->translated = true;
|
||||
/* Fall through */
|
||||
|
||||
case SERIO_8042:
|
||||
if (serio->write)
|
||||
atkbd->write = true;
|
||||
break;
|
||||
}
|
||||
|
||||
atkbd->softraw = atkbd_softraw;
|
||||
|
@ -1113,7 +1123,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
|
|||
atkbd->scroll = atkbd_scroll;
|
||||
|
||||
if (atkbd->softrepeat)
|
||||
atkbd->softraw = 1;
|
||||
atkbd->softraw = true;
|
||||
|
||||
serio_set_drvdata(serio, atkbd);
|
||||
|
||||
|
@ -1172,7 +1182,8 @@ static int atkbd_reconnect(struct serio *serio)
|
|||
int retval = -1;
|
||||
|
||||
if (!atkbd || !drv) {
|
||||
printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
|
||||
dev_dbg(&serio->dev,
|
||||
"reconnect request, but serio is disconnected, ignoring...\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1286,7 +1297,8 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
|
|||
struct input_dev *old_dev, *new_dev;
|
||||
unsigned long value;
|
||||
int err;
|
||||
unsigned char old_extra, old_set;
|
||||
bool old_extra;
|
||||
unsigned char old_set;
|
||||
|
||||
if (!atkbd->write)
|
||||
return -EIO;
|
||||
|
@ -1369,7 +1381,7 @@ static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t cou
|
|||
struct input_dev *old_dev, *new_dev;
|
||||
unsigned long value;
|
||||
int err;
|
||||
unsigned char old_scroll;
|
||||
bool old_scroll;
|
||||
|
||||
if (strict_strtoul(buf, 10, &value) || value > 1)
|
||||
return -EINVAL;
|
||||
|
@ -1413,7 +1425,8 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count)
|
|||
struct input_dev *old_dev, *new_dev;
|
||||
unsigned long value;
|
||||
int err;
|
||||
unsigned char old_set, old_extra;
|
||||
unsigned char old_set;
|
||||
bool old_extra;
|
||||
|
||||
if (!atkbd->write)
|
||||
return -EIO;
|
||||
|
@ -1463,7 +1476,7 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t
|
|||
struct input_dev *old_dev, *new_dev;
|
||||
unsigned long value;
|
||||
int err;
|
||||
unsigned char old_softrepeat, old_softraw;
|
||||
bool old_softrepeat, old_softraw;
|
||||
|
||||
if (!atkbd->write)
|
||||
return -EIO;
|
||||
|
@ -1483,7 +1496,7 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t
|
|||
atkbd->dev = new_dev;
|
||||
atkbd->softrepeat = value;
|
||||
if (atkbd->softrepeat)
|
||||
atkbd->softraw = 1;
|
||||
atkbd->softraw = true;
|
||||
atkbd_set_device_attrs(atkbd);
|
||||
|
||||
err = input_register_device(atkbd->dev);
|
||||
|
@ -1513,7 +1526,7 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co
|
|||
struct input_dev *old_dev, *new_dev;
|
||||
unsigned long value;
|
||||
int err;
|
||||
unsigned char old_softraw;
|
||||
bool old_softraw;
|
||||
|
||||
if (strict_strtoul(buf, 10, &value) || value > 1)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -0,0 +1,594 @@
|
|||
/*
|
||||
* Driver for the IMX keypad port.
|
||||
* Copyright (C) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* <<Power management needs to be implemented>>.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/input/matrix_keypad.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
/*
|
||||
* Keypad Controller registers (halfword)
|
||||
*/
|
||||
#define KPCR 0x00 /* Keypad Control Register */
|
||||
|
||||
#define KPSR 0x02 /* Keypad Status Register */
|
||||
#define KBD_STAT_KPKD (0x1 << 0) /* Key Press Interrupt Status bit (w1c) */
|
||||
#define KBD_STAT_KPKR (0x1 << 1) /* Key Release Interrupt Status bit (w1c) */
|
||||
#define KBD_STAT_KDSC (0x1 << 2) /* Key Depress Synch Chain Status bit (w1c)*/
|
||||
#define KBD_STAT_KRSS (0x1 << 3) /* Key Release Synch Status bit (w1c)*/
|
||||
#define KBD_STAT_KDIE (0x1 << 8) /* Key Depress Interrupt Enable Status bit */
|
||||
#define KBD_STAT_KRIE (0x1 << 9) /* Key Release Interrupt Enable */
|
||||
#define KBD_STAT_KPPEN (0x1 << 10) /* Keypad Clock Enable */
|
||||
|
||||
#define KDDR 0x04 /* Keypad Data Direction Register */
|
||||
#define KPDR 0x06 /* Keypad Data Register */
|
||||
|
||||
#define MAX_MATRIX_KEY_ROWS 8
|
||||
#define MAX_MATRIX_KEY_COLS 8
|
||||
#define MATRIX_ROW_SHIFT 3
|
||||
|
||||
#define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS)
|
||||
|
||||
struct imx_keypad {
|
||||
|
||||
struct clk *clk;
|
||||
struct input_dev *input_dev;
|
||||
void __iomem *mmio_base;
|
||||
|
||||
int irq;
|
||||
struct timer_list check_matrix_timer;
|
||||
|
||||
/*
|
||||
* The matrix is stable only if no changes are detected after
|
||||
* IMX_KEYPAD_SCANS_FOR_STABILITY scans
|
||||
*/
|
||||
#define IMX_KEYPAD_SCANS_FOR_STABILITY 3
|
||||
int stable_count;
|
||||
|
||||
bool enabled;
|
||||
|
||||
/* Masks for enabled rows/cols */
|
||||
unsigned short rows_en_mask;
|
||||
unsigned short cols_en_mask;
|
||||
|
||||
unsigned short keycodes[MAX_MATRIX_KEY_NUM];
|
||||
|
||||
/*
|
||||
* Matrix states:
|
||||
* -stable: achieved after a complete debounce process.
|
||||
* -unstable: used in the debouncing process.
|
||||
*/
|
||||
unsigned short matrix_stable_state[MAX_MATRIX_KEY_COLS];
|
||||
unsigned short matrix_unstable_state[MAX_MATRIX_KEY_COLS];
|
||||
};
|
||||
|
||||
/* Scan the matrix and return the new state in *matrix_volatile_state. */
|
||||
static void imx_keypad_scan_matrix(struct imx_keypad *keypad,
|
||||
unsigned short *matrix_volatile_state)
|
||||
{
|
||||
int col;
|
||||
unsigned short reg_val;
|
||||
|
||||
for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
|
||||
if ((keypad->cols_en_mask & (1 << col)) == 0)
|
||||
continue;
|
||||
/*
|
||||
* Discharge keypad capacitance:
|
||||
* 2. write 1s on column data.
|
||||
* 3. configure columns as totem-pole to discharge capacitance.
|
||||
* 4. configure columns as open-drain.
|
||||
*/
|
||||
reg_val = readw(keypad->mmio_base + KPDR);
|
||||
reg_val |= 0xff00;
|
||||
writew(reg_val, keypad->mmio_base + KPDR);
|
||||
|
||||
reg_val = readw(keypad->mmio_base + KPCR);
|
||||
reg_val &= ~((keypad->cols_en_mask & 0xff) << 8);
|
||||
writew(reg_val, keypad->mmio_base + KPCR);
|
||||
|
||||
udelay(2);
|
||||
|
||||
reg_val = readw(keypad->mmio_base + KPCR);
|
||||
reg_val |= (keypad->cols_en_mask & 0xff) << 8;
|
||||
writew(reg_val, keypad->mmio_base + KPCR);
|
||||
|
||||
/*
|
||||
* 5. Write a single column to 0, others to 1.
|
||||
* 6. Sample row inputs and save data.
|
||||
* 7. Repeat steps 2 - 6 for remaining columns.
|
||||
*/
|
||||
reg_val = readw(keypad->mmio_base + KPDR);
|
||||
reg_val &= ~(1 << (8 + col));
|
||||
writew(reg_val, keypad->mmio_base + KPDR);
|
||||
|
||||
/*
|
||||
* Delay added to avoid propagating the 0 from column to row
|
||||
* when scanning.
|
||||
*/
|
||||
udelay(5);
|
||||
|
||||
/*
|
||||
* 1s in matrix_volatile_state[col] means key pressures
|
||||
* throw data from non enabled rows.
|
||||
*/
|
||||
reg_val = readw(keypad->mmio_base + KPDR);
|
||||
matrix_volatile_state[col] = (~reg_val) & keypad->rows_en_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return in standby mode:
|
||||
* 9. write 0s to columns
|
||||
*/
|
||||
reg_val = readw(keypad->mmio_base + KPDR);
|
||||
reg_val &= 0x00ff;
|
||||
writew(reg_val, keypad->mmio_base + KPDR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare the new matrix state (volatile) with the stable one stored in
|
||||
* keypad->matrix_stable_state and fire events if changes are detected.
|
||||
*/
|
||||
static void imx_keypad_fire_events(struct imx_keypad *keypad,
|
||||
unsigned short *matrix_volatile_state)
|
||||
{
|
||||
struct input_dev *input_dev = keypad->input_dev;
|
||||
int row, col;
|
||||
|
||||
for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) {
|
||||
unsigned short bits_changed;
|
||||
int code;
|
||||
|
||||
if ((keypad->cols_en_mask & (1 << col)) == 0)
|
||||
continue; /* Column is not enabled */
|
||||
|
||||
bits_changed = keypad->matrix_stable_state[col] ^
|
||||
matrix_volatile_state[col];
|
||||
|
||||
if (bits_changed == 0)
|
||||
continue; /* Column does not contain changes */
|
||||
|
||||
for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) {
|
||||
if ((keypad->rows_en_mask & (1 << row)) == 0)
|
||||
continue; /* Row is not enabled */
|
||||
if ((bits_changed & (1 << row)) == 0)
|
||||
continue; /* Row does not contain changes */
|
||||
|
||||
code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT);
|
||||
input_event(input_dev, EV_MSC, MSC_SCAN, code);
|
||||
input_report_key(input_dev, keypad->keycodes[code],
|
||||
matrix_volatile_state[col] & (1 << row));
|
||||
dev_dbg(&input_dev->dev, "Event code: %d, val: %d",
|
||||
keypad->keycodes[code],
|
||||
matrix_volatile_state[col] & (1 << row));
|
||||
}
|
||||
}
|
||||
input_sync(input_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* imx_keypad_check_for_events is the timer handler.
|
||||
*/
|
||||
static void imx_keypad_check_for_events(unsigned long data)
|
||||
{
|
||||
struct imx_keypad *keypad = (struct imx_keypad *) data;
|
||||
unsigned short matrix_volatile_state[MAX_MATRIX_KEY_COLS];
|
||||
unsigned short reg_val;
|
||||
bool state_changed, is_zero_matrix;
|
||||
int i;
|
||||
|
||||
memset(matrix_volatile_state, 0, sizeof(matrix_volatile_state));
|
||||
|
||||
imx_keypad_scan_matrix(keypad, matrix_volatile_state);
|
||||
|
||||
state_changed = false;
|
||||
for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) {
|
||||
if ((keypad->cols_en_mask & (1 << i)) == 0)
|
||||
continue;
|
||||
|
||||
if (keypad->matrix_unstable_state[i] ^ matrix_volatile_state[i]) {
|
||||
state_changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the matrix state is changed from the previous scan
|
||||
* (Re)Begin the debouncing process, saving the new state in
|
||||
* keypad->matrix_unstable_state.
|
||||
* else
|
||||
* Increase the count of number of scans with a stable state.
|
||||
*/
|
||||
if (state_changed) {
|
||||
memcpy(keypad->matrix_unstable_state, matrix_volatile_state,
|
||||
sizeof(matrix_volatile_state));
|
||||
keypad->stable_count = 0;
|
||||
} else
|
||||
keypad->stable_count++;
|
||||
|
||||
/*
|
||||
* If the matrix is not as stable as we want reschedule scan
|
||||
* in the near future.
|
||||
*/
|
||||
if (keypad->stable_count < IMX_KEYPAD_SCANS_FOR_STABILITY) {
|
||||
mod_timer(&keypad->check_matrix_timer,
|
||||
jiffies + msecs_to_jiffies(10));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the matrix state is stable, fire the events and save the new
|
||||
* stable state. Note, if the matrix is kept stable for longer
|
||||
* (keypad->stable_count > IMX_KEYPAD_SCANS_FOR_STABILITY) all
|
||||
* events have already been generated.
|
||||
*/
|
||||
if (keypad->stable_count == IMX_KEYPAD_SCANS_FOR_STABILITY) {
|
||||
imx_keypad_fire_events(keypad, matrix_volatile_state);
|
||||
|
||||
memcpy(keypad->matrix_stable_state, matrix_volatile_state,
|
||||
sizeof(matrix_volatile_state));
|
||||
}
|
||||
|
||||
is_zero_matrix = true;
|
||||
for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) {
|
||||
if (matrix_volatile_state[i] != 0) {
|
||||
is_zero_matrix = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (is_zero_matrix) {
|
||||
/*
|
||||
* All keys have been released. Enable only the KDI
|
||||
* interrupt for future key presses (clear the KDI
|
||||
* status bit and its sync chain before that).
|
||||
*/
|
||||
reg_val = readw(keypad->mmio_base + KPSR);
|
||||
reg_val |= KBD_STAT_KPKD | KBD_STAT_KDSC;
|
||||
writew(reg_val, keypad->mmio_base + KPSR);
|
||||
|
||||
reg_val = readw(keypad->mmio_base + KPSR);
|
||||
reg_val |= KBD_STAT_KDIE;
|
||||
reg_val &= ~KBD_STAT_KRIE;
|
||||
writew(reg_val, keypad->mmio_base + KPSR);
|
||||
} else {
|
||||
/*
|
||||
* Some keys are still pressed. Schedule a rescan in
|
||||
* attempt to detect multiple key presses and enable
|
||||
* the KRI interrupt to react quickly to key release
|
||||
* event.
|
||||
*/
|
||||
mod_timer(&keypad->check_matrix_timer,
|
||||
jiffies + msecs_to_jiffies(60));
|
||||
|
||||
reg_val = readw(keypad->mmio_base + KPSR);
|
||||
reg_val |= KBD_STAT_KPKR | KBD_STAT_KRSS;
|
||||
writew(reg_val, keypad->mmio_base + KPSR);
|
||||
|
||||
reg_val = readw(keypad->mmio_base + KPSR);
|
||||
reg_val |= KBD_STAT_KRIE;
|
||||
reg_val &= ~KBD_STAT_KDIE;
|
||||
writew(reg_val, keypad->mmio_base + KPSR);
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t imx_keypad_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct imx_keypad *keypad = dev_id;
|
||||
unsigned short reg_val;
|
||||
|
||||
reg_val = readw(keypad->mmio_base + KPSR);
|
||||
|
||||
/* Disable both interrupt types */
|
||||
reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
|
||||
/* Clear interrupts status bits */
|
||||
reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
|
||||
writew(reg_val, keypad->mmio_base + KPSR);
|
||||
|
||||
if (keypad->enabled) {
|
||||
/* The matrix is supposed to be changed */
|
||||
keypad->stable_count = 0;
|
||||
|
||||
/* Schedule the scanning procedure near in the future */
|
||||
mod_timer(&keypad->check_matrix_timer,
|
||||
jiffies + msecs_to_jiffies(2));
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void imx_keypad_config(struct imx_keypad *keypad)
|
||||
{
|
||||
unsigned short reg_val;
|
||||
|
||||
/*
|
||||
* Include enabled rows in interrupt generation (KPCR[7:0])
|
||||
* Configure keypad columns as open-drain (KPCR[15:8])
|
||||
*/
|
||||
reg_val = readw(keypad->mmio_base + KPCR);
|
||||
reg_val |= keypad->rows_en_mask & 0xff; /* rows */
|
||||
reg_val |= (keypad->cols_en_mask & 0xff) << 8; /* cols */
|
||||
writew(reg_val, keypad->mmio_base + KPCR);
|
||||
|
||||
/* Write 0's to KPDR[15:8] (Colums) */
|
||||
reg_val = readw(keypad->mmio_base + KPDR);
|
||||
reg_val &= 0x00ff;
|
||||
writew(reg_val, keypad->mmio_base + KPDR);
|
||||
|
||||
/* Configure columns as output, rows as input (KDDR[15:0]) */
|
||||
writew(0xff00, keypad->mmio_base + KDDR);
|
||||
|
||||
/*
|
||||
* Clear Key Depress and Key Release status bit.
|
||||
* Clear both synchronizer chain.
|
||||
*/
|
||||
reg_val = readw(keypad->mmio_base + KPSR);
|
||||
reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD |
|
||||
KBD_STAT_KDSC | KBD_STAT_KRSS;
|
||||
writew(reg_val, keypad->mmio_base + KPSR);
|
||||
|
||||
/* Enable KDI and disable KRI (avoid false release events). */
|
||||
reg_val |= KBD_STAT_KDIE;
|
||||
reg_val &= ~KBD_STAT_KRIE;
|
||||
writew(reg_val, keypad->mmio_base + KPSR);
|
||||
}
|
||||
|
||||
static void imx_keypad_inhibit(struct imx_keypad *keypad)
|
||||
{
|
||||
unsigned short reg_val;
|
||||
|
||||
/* Inhibit KDI and KRI interrupts. */
|
||||
reg_val = readw(keypad->mmio_base + KPSR);
|
||||
reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
|
||||
writew(reg_val, keypad->mmio_base + KPSR);
|
||||
|
||||
/* Colums as open drain and disable all rows */
|
||||
writew(0xff00, keypad->mmio_base + KPCR);
|
||||
}
|
||||
|
||||
static void imx_keypad_close(struct input_dev *dev)
|
||||
{
|
||||
struct imx_keypad *keypad = input_get_drvdata(dev);
|
||||
|
||||
dev_dbg(&dev->dev, ">%s\n", __func__);
|
||||
|
||||
/* Mark keypad as being inactive */
|
||||
keypad->enabled = false;
|
||||
synchronize_irq(keypad->irq);
|
||||
del_timer_sync(&keypad->check_matrix_timer);
|
||||
|
||||
imx_keypad_inhibit(keypad);
|
||||
|
||||
/* Disable clock unit */
|
||||
clk_disable(keypad->clk);
|
||||
}
|
||||
|
||||
static int imx_keypad_open(struct input_dev *dev)
|
||||
{
|
||||
struct imx_keypad *keypad = input_get_drvdata(dev);
|
||||
|
||||
dev_dbg(&dev->dev, ">%s\n", __func__);
|
||||
|
||||
/* We became active from now */
|
||||
keypad->enabled = true;
|
||||
|
||||
/* Enable the kpp clock */
|
||||
clk_enable(keypad->clk);
|
||||
imx_keypad_config(keypad);
|
||||
|
||||
/* Sanity control, not all the rows must be actived now. */
|
||||
if ((readw(keypad->mmio_base + KPDR) & keypad->rows_en_mask) == 0) {
|
||||
dev_err(&dev->dev,
|
||||
"too many keys pressed, control pins initialisation\n");
|
||||
goto open_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
open_err:
|
||||
imx_keypad_close(dev);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int __devinit imx_keypad_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data;
|
||||
struct imx_keypad *keypad;
|
||||
struct input_dev *input_dev;
|
||||
struct resource *res;
|
||||
int irq, error, i;
|
||||
|
||||
if (keymap_data == NULL) {
|
||||
dev_err(&pdev->dev, "no keymap defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "no irq defined in platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "no I/O memory defined in platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
res = request_mem_region(res->start, resource_size(res), pdev->name);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "failed to request I/O memory\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev) {
|
||||
dev_err(&pdev->dev, "failed to allocate the input device\n");
|
||||
error = -ENOMEM;
|
||||
goto failed_rel_mem;
|
||||
}
|
||||
|
||||
keypad = kzalloc(sizeof(struct imx_keypad), GFP_KERNEL);
|
||||
if (!keypad) {
|
||||
dev_err(&pdev->dev, "not enough memory for driver data\n");
|
||||
error = -ENOMEM;
|
||||
goto failed_free_input;
|
||||
}
|
||||
|
||||
keypad->input_dev = input_dev;
|
||||
keypad->irq = irq;
|
||||
keypad->stable_count = 0;
|
||||
|
||||
setup_timer(&keypad->check_matrix_timer,
|
||||
imx_keypad_check_for_events, (unsigned long) keypad);
|
||||
|
||||
keypad->mmio_base = ioremap(res->start, resource_size(res));
|
||||
if (keypad->mmio_base == NULL) {
|
||||
dev_err(&pdev->dev, "failed to remap I/O memory\n");
|
||||
error = -ENOMEM;
|
||||
goto failed_free_priv;
|
||||
}
|
||||
|
||||
keypad->clk = clk_get(&pdev->dev, "kpp");
|
||||
if (IS_ERR(keypad->clk)) {
|
||||
dev_err(&pdev->dev, "failed to get keypad clock\n");
|
||||
error = PTR_ERR(keypad->clk);
|
||||
goto failed_unmap;
|
||||
}
|
||||
|
||||
/* Search for rows and cols enabled */
|
||||
for (i = 0; i < keymap_data->keymap_size; i++) {
|
||||
keypad->rows_en_mask |= 1 << KEY_ROW(keymap_data->keymap[i]);
|
||||
keypad->cols_en_mask |= 1 << KEY_COL(keymap_data->keymap[i]);
|
||||
}
|
||||
|
||||
if (keypad->rows_en_mask > ((1 << MAX_MATRIX_KEY_ROWS) - 1) ||
|
||||
keypad->cols_en_mask > ((1 << MAX_MATRIX_KEY_COLS) - 1)) {
|
||||
dev_err(&pdev->dev,
|
||||
"invalid key data (too many rows or colums)\n");
|
||||
error = -EINVAL;
|
||||
goto failed_clock_put;
|
||||
}
|
||||
dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask);
|
||||
dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask);
|
||||
|
||||
/* Init the Input device */
|
||||
input_dev->name = pdev->name;
|
||||
input_dev->id.bustype = BUS_HOST;
|
||||
input_dev->dev.parent = &pdev->dev;
|
||||
input_dev->open = imx_keypad_open;
|
||||
input_dev->close = imx_keypad_close;
|
||||
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
|
||||
input_dev->keycode = keypad->keycodes;
|
||||
input_dev->keycodesize = sizeof(keypad->keycodes[0]);
|
||||
input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes);
|
||||
|
||||
matrix_keypad_build_keymap(keymap_data, MATRIX_ROW_SHIFT,
|
||||
keypad->keycodes, input_dev->keybit);
|
||||
|
||||
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
|
||||
input_set_drvdata(input_dev, keypad);
|
||||
|
||||
/* Ensure that the keypad will stay dormant until opened */
|
||||
imx_keypad_inhibit(keypad);
|
||||
|
||||
error = request_irq(irq, imx_keypad_irq_handler, IRQF_DISABLED,
|
||||
pdev->name, keypad);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to request IRQ\n");
|
||||
goto failed_clock_put;
|
||||
}
|
||||
|
||||
/* Register the input device */
|
||||
error = input_register_device(input_dev);
|
||||
if (error) {
|
||||
dev_err(&pdev->dev, "failed to register input device\n");
|
||||
goto failed_free_irq;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, keypad);
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
|
||||
return 0;
|
||||
|
||||
failed_free_irq:
|
||||
free_irq(irq, pdev);
|
||||
failed_clock_put:
|
||||
clk_put(keypad->clk);
|
||||
failed_unmap:
|
||||
iounmap(keypad->mmio_base);
|
||||
failed_free_priv:
|
||||
kfree(keypad);
|
||||
failed_free_input:
|
||||
input_free_device(input_dev);
|
||||
failed_rel_mem:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __devexit imx_keypad_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct imx_keypad *keypad = platform_get_drvdata(pdev);
|
||||
struct resource *res;
|
||||
|
||||
dev_dbg(&pdev->dev, ">%s\n", __func__);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
input_unregister_device(keypad->input_dev);
|
||||
|
||||
free_irq(keypad->irq, keypad);
|
||||
clk_put(keypad->clk);
|
||||
|
||||
iounmap(keypad->mmio_base);
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
|
||||
kfree(keypad);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver imx_keypad_driver = {
|
||||
.driver = {
|
||||
.name = "imx-keypad",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = imx_keypad_probe,
|
||||
.remove = __devexit_p(imx_keypad_remove),
|
||||
};
|
||||
|
||||
static int __init imx_keypad_init(void)
|
||||
{
|
||||
return platform_driver_register(&imx_keypad_driver);
|
||||
}
|
||||
|
||||
static void __exit imx_keypad_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&imx_keypad_driver);
|
||||
}
|
||||
|
||||
module_init(imx_keypad_init);
|
||||
module_exit(imx_keypad_exit);
|
||||
|
||||
MODULE_AUTHOR("Alberto Panizzo <maramaopercheseimorto@gmail.com>");
|
||||
MODULE_DESCRIPTION("IMX Keypad Port Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:imx-keypad");
|
|
@ -362,7 +362,7 @@ static int __devexit qt2160_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_device_id qt2160_idtable[] = {
|
||||
static const struct i2c_device_id qt2160_idtable[] = {
|
||||
{ "qt2160", 0, },
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -19,101 +19,141 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/sh_keysc.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#define KYCR1_OFFS 0x00
|
||||
#define KYCR2_OFFS 0x04
|
||||
#define KYINDR_OFFS 0x08
|
||||
#define KYOUTDR_OFFS 0x0c
|
||||
|
||||
#define KYCR2_IRQ_LEVEL 0x10
|
||||
#define KYCR2_IRQ_DISABLED 0x00
|
||||
|
||||
static const struct {
|
||||
unsigned char kymd, keyout, keyin;
|
||||
} sh_keysc_mode[] = {
|
||||
[SH_KEYSC_MODE_1] = { 0, 6, 5 },
|
||||
[SH_KEYSC_MODE_2] = { 1, 5, 6 },
|
||||
[SH_KEYSC_MODE_3] = { 2, 4, 7 },
|
||||
[SH_KEYSC_MODE_4] = { 3, 6, 6 },
|
||||
[SH_KEYSC_MODE_5] = { 4, 6, 7 },
|
||||
[SH_KEYSC_MODE_6] = { 5, 7, 7 },
|
||||
};
|
||||
|
||||
struct sh_keysc_priv {
|
||||
void __iomem *iomem_base;
|
||||
struct clk *clk;
|
||||
unsigned long last_keys;
|
||||
DECLARE_BITMAP(last_keys, SH_KEYSC_MAXKEYS);
|
||||
struct input_dev *input;
|
||||
struct sh_keysc_info pdata;
|
||||
};
|
||||
|
||||
#define KYCR1 0
|
||||
#define KYCR2 1
|
||||
#define KYINDR 2
|
||||
#define KYOUTDR 3
|
||||
|
||||
#define KYCR2_IRQ_LEVEL 0x10
|
||||
#define KYCR2_IRQ_DISABLED 0x00
|
||||
|
||||
static unsigned long sh_keysc_read(struct sh_keysc_priv *p, int reg_nr)
|
||||
{
|
||||
return ioread16(p->iomem_base + (reg_nr << 2));
|
||||
}
|
||||
|
||||
static void sh_keysc_write(struct sh_keysc_priv *p, int reg_nr,
|
||||
unsigned long value)
|
||||
{
|
||||
iowrite16(value, p->iomem_base + (reg_nr << 2));
|
||||
}
|
||||
|
||||
static void sh_keysc_level_mode(struct sh_keysc_priv *p,
|
||||
unsigned long keys_set)
|
||||
{
|
||||
struct sh_keysc_info *pdata = &p->pdata;
|
||||
|
||||
sh_keysc_write(p, KYOUTDR, 0);
|
||||
sh_keysc_write(p, KYCR2, KYCR2_IRQ_LEVEL | (keys_set << 8));
|
||||
|
||||
if (pdata->kycr2_delay)
|
||||
udelay(pdata->kycr2_delay);
|
||||
}
|
||||
|
||||
static void sh_keysc_map_dbg(struct device *dev, unsigned long *map,
|
||||
const char *str)
|
||||
{
|
||||
int k;
|
||||
|
||||
for (k = 0; k < BITS_TO_LONGS(SH_KEYSC_MAXKEYS); k++)
|
||||
dev_dbg(dev, "%s[%d] 0x%lx\n", str, k, map[k]);
|
||||
}
|
||||
|
||||
static irqreturn_t sh_keysc_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct platform_device *pdev = dev_id;
|
||||
struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
|
||||
struct sh_keysc_info *pdata = &priv->pdata;
|
||||
unsigned long keys, keys1, keys0, mask;
|
||||
int keyout_nr = sh_keysc_mode[pdata->mode].keyout;
|
||||
int keyin_nr = sh_keysc_mode[pdata->mode].keyin;
|
||||
DECLARE_BITMAP(keys, SH_KEYSC_MAXKEYS);
|
||||
DECLARE_BITMAP(keys0, SH_KEYSC_MAXKEYS);
|
||||
DECLARE_BITMAP(keys1, SH_KEYSC_MAXKEYS);
|
||||
unsigned char keyin_set, tmp;
|
||||
int i, k;
|
||||
int i, k, n;
|
||||
|
||||
dev_dbg(&pdev->dev, "isr!\n");
|
||||
|
||||
keys1 = ~0;
|
||||
keys0 = 0;
|
||||
bitmap_fill(keys1, SH_KEYSC_MAXKEYS);
|
||||
bitmap_zero(keys0, SH_KEYSC_MAXKEYS);
|
||||
|
||||
do {
|
||||
keys = 0;
|
||||
bitmap_zero(keys, SH_KEYSC_MAXKEYS);
|
||||
keyin_set = 0;
|
||||
|
||||
iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS);
|
||||
sh_keysc_write(priv, KYCR2, KYCR2_IRQ_DISABLED);
|
||||
|
||||
for (i = 0; i < sh_keysc_mode[pdata->mode].keyout; i++) {
|
||||
iowrite16(0xfff ^ (3 << (i * 2)),
|
||||
priv->iomem_base + KYOUTDR_OFFS);
|
||||
for (i = 0; i < keyout_nr; i++) {
|
||||
n = keyin_nr * i;
|
||||
|
||||
/* drive one KEYOUT pin low, read KEYIN pins */
|
||||
sh_keysc_write(priv, KYOUTDR, 0xffff ^ (3 << (i * 2)));
|
||||
udelay(pdata->delay);
|
||||
tmp = ioread16(priv->iomem_base + KYINDR_OFFS);
|
||||
keys |= tmp << (sh_keysc_mode[pdata->mode].keyin * i);
|
||||
tmp ^= (1 << sh_keysc_mode[pdata->mode].keyin) - 1;
|
||||
keyin_set |= tmp;
|
||||
tmp = sh_keysc_read(priv, KYINDR);
|
||||
|
||||
/* set bit if key press has been detected */
|
||||
for (k = 0; k < keyin_nr; k++) {
|
||||
if (tmp & (1 << k))
|
||||
__set_bit(n + k, keys);
|
||||
}
|
||||
|
||||
/* keep track of which KEYIN bits that have been set */
|
||||
keyin_set |= tmp ^ ((1 << keyin_nr) - 1);
|
||||
}
|
||||
|
||||
iowrite16(0, priv->iomem_base + KYOUTDR_OFFS);
|
||||
iowrite16(KYCR2_IRQ_LEVEL | (keyin_set << 8),
|
||||
priv->iomem_base + KYCR2_OFFS);
|
||||
sh_keysc_level_mode(priv, keyin_set);
|
||||
|
||||
if (pdata->kycr2_delay)
|
||||
udelay(pdata->kycr2_delay);
|
||||
bitmap_complement(keys, keys, SH_KEYSC_MAXKEYS);
|
||||
bitmap_and(keys1, keys1, keys, SH_KEYSC_MAXKEYS);
|
||||
bitmap_or(keys0, keys0, keys, SH_KEYSC_MAXKEYS);
|
||||
|
||||
keys ^= ~0;
|
||||
keys &= (1 << (sh_keysc_mode[pdata->mode].keyin *
|
||||
sh_keysc_mode[pdata->mode].keyout)) - 1;
|
||||
keys1 &= keys;
|
||||
keys0 |= keys;
|
||||
sh_keysc_map_dbg(&pdev->dev, keys, "keys");
|
||||
|
||||
dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys);
|
||||
} while (sh_keysc_read(priv, KYCR2) & 0x01);
|
||||
|
||||
} while (ioread16(priv->iomem_base + KYCR2_OFFS) & 0x01);
|
||||
|
||||
dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n",
|
||||
priv->last_keys, keys0, keys1);
|
||||
sh_keysc_map_dbg(&pdev->dev, priv->last_keys, "last_keys");
|
||||
sh_keysc_map_dbg(&pdev->dev, keys0, "keys0");
|
||||
sh_keysc_map_dbg(&pdev->dev, keys1, "keys1");
|
||||
|
||||
for (i = 0; i < SH_KEYSC_MAXKEYS; i++) {
|
||||
k = pdata->keycodes[i];
|
||||
if (!k)
|
||||
continue;
|
||||
|
||||
mask = 1 << i;
|
||||
|
||||
if (!((priv->last_keys ^ keys0) & mask))
|
||||
if (test_bit(i, keys0) == test_bit(i, priv->last_keys))
|
||||
continue;
|
||||
|
||||
if ((keys1 | keys0) & mask) {
|
||||
if (test_bit(i, keys1) || test_bit(i, keys0)) {
|
||||
input_event(priv->input, EV_KEY, k, 1);
|
||||
priv->last_keys |= mask;
|
||||
__set_bit(i, priv->last_keys);
|
||||
}
|
||||
|
||||
if (!(keys1 & mask)) {
|
||||
if (!test_bit(i, keys1)) {
|
||||
input_event(priv->input, EV_KEY, k, 0);
|
||||
priv->last_keys &= ~mask;
|
||||
__clear_bit(i, priv->last_keys);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -122,8 +162,6 @@ static irqreturn_t sh_keysc_isr(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#define res_size(res) ((res)->end - (res)->start + 1)
|
||||
|
||||
static int __devinit sh_keysc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sh_keysc_priv *priv;
|
||||
|
@ -164,7 +202,7 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev)
|
|||
memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata));
|
||||
pdata = &priv->pdata;
|
||||
|
||||
priv->iomem_base = ioremap_nocache(res->start, res_size(res));
|
||||
priv->iomem_base = ioremap_nocache(res->start, resource_size(res));
|
||||
if (priv->iomem_base == NULL) {
|
||||
dev_err(&pdev->dev, "failed to remap I/O memory\n");
|
||||
error = -ENXIO;
|
||||
|
@ -220,10 +258,9 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev)
|
|||
|
||||
clk_enable(priv->clk);
|
||||
|
||||
iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) |
|
||||
pdata->scan_timing, priv->iomem_base + KYCR1_OFFS);
|
||||
iowrite16(0, priv->iomem_base + KYOUTDR_OFFS);
|
||||
iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS);
|
||||
sh_keysc_write(priv, KYCR1, (sh_keysc_mode[pdata->mode].kymd << 8) |
|
||||
pdata->scan_timing);
|
||||
sh_keysc_level_mode(priv, 0);
|
||||
|
||||
device_init_wakeup(&pdev->dev, 1);
|
||||
|
||||
|
@ -248,7 +285,7 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct sh_keysc_priv *priv = platform_get_drvdata(pdev);
|
||||
|
||||
iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS);
|
||||
sh_keysc_write(priv, KYCR2, KYCR2_IRQ_DISABLED);
|
||||
|
||||
input_unregister_device(priv->input);
|
||||
free_irq(platform_get_irq(pdev, 0), pdev);
|
||||
|
@ -270,7 +307,7 @@ static int sh_keysc_suspend(struct device *dev)
|
|||
int irq = platform_get_irq(pdev, 0);
|
||||
unsigned short value;
|
||||
|
||||
value = ioread16(priv->iomem_base + KYCR1_OFFS);
|
||||
value = sh_keysc_read(priv, KYCR1);
|
||||
|
||||
if (device_may_wakeup(dev)) {
|
||||
value |= 0x80;
|
||||
|
@ -279,7 +316,7 @@ static int sh_keysc_suspend(struct device *dev)
|
|||
value &= ~0x80;
|
||||
}
|
||||
|
||||
iowrite16(value, priv->iomem_base + KYCR1_OFFS);
|
||||
sh_keysc_write(priv, KYCR1, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ static void apanel_shutdown(struct i2c_client *client)
|
|||
apanel_remove(client);
|
||||
}
|
||||
|
||||
static struct i2c_device_id apanel_id[] = {
|
||||
static const struct i2c_device_id apanel_id[] = {
|
||||
{ "fujitsu_apanel", 0 },
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -152,6 +152,13 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
|
|||
goto exit_unregister_input;
|
||||
}
|
||||
|
||||
err = gpio_direction_input(pdata->gpio_a);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "unable to set GPIO %d for input\n",
|
||||
pdata->gpio_a);
|
||||
goto exit_unregister_input;
|
||||
}
|
||||
|
||||
err = gpio_request(pdata->gpio_b, DRV_NAME);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "unable to request GPIO %d\n",
|
||||
|
@ -159,6 +166,13 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev)
|
|||
goto exit_free_gpio_a;
|
||||
}
|
||||
|
||||
err = gpio_direction_input(pdata->gpio_b);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "unable to set GPIO %d for input\n",
|
||||
pdata->gpio_b);
|
||||
goto exit_free_gpio_a;
|
||||
}
|
||||
|
||||
/* request the IRQs */
|
||||
err = request_irq(encoder->irq_a, &rotary_encoder_irq,
|
||||
IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE,
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/uinput.h>
|
||||
|
@ -284,7 +283,6 @@ static int uinput_open(struct inode *inode, struct file *file)
|
|||
if (!newdev)
|
||||
return -ENOMEM;
|
||||
|
||||
lock_kernel();
|
||||
mutex_init(&newdev->mutex);
|
||||
spin_lock_init(&newdev->requests_lock);
|
||||
init_waitqueue_head(&newdev->requests_waitq);
|
||||
|
@ -292,7 +290,7 @@ static int uinput_open(struct inode *inode, struct file *file)
|
|||
newdev->state = UIST_NEW_DEVICE;
|
||||
|
||||
file->private_data = newdev;
|
||||
unlock_kernel();
|
||||
nonseekable_open(inode, file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -538,6 +538,7 @@ wbcir_reset_irdata(struct wbcir_data *data)
|
|||
data->irdata_count = 0;
|
||||
data->irdata_off = 0;
|
||||
data->irdata_error = 0;
|
||||
data->idle_count = 0;
|
||||
}
|
||||
|
||||
/* Adds one bit of irdata */
|
||||
|
@ -1006,7 +1007,6 @@ wbcir_irq_handler(int irqno, void *cookie)
|
|||
}
|
||||
|
||||
wbcir_reset_irdata(data);
|
||||
data->idle_count = 0;
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -1018,7 +1018,7 @@ out:
|
|||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* SUSPEND/RESUME FUNCTIONS
|
||||
* SETUP/INIT/SUSPEND/RESUME FUNCTIONS
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
@ -1197,7 +1197,16 @@ finish:
|
|||
}
|
||||
|
||||
/* Disable interrupts */
|
||||
wbcir_select_bank(data, WBCIR_BANK_0);
|
||||
outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
|
||||
|
||||
/*
|
||||
* ACPI will set the HW disable bit for SP3 which means that the
|
||||
* output signals are left in an undefined state which may cause
|
||||
* spurious interrupts which we need to ignore until the hardware
|
||||
* is reinitialized.
|
||||
*/
|
||||
disable_irq(data->irq);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1207,37 +1216,15 @@ wbcir_suspend(struct pnp_dev *device, pm_message_t state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wbcir_resume(struct pnp_dev *device)
|
||||
{
|
||||
struct wbcir_data *data = pnp_get_drvdata(device);
|
||||
|
||||
/* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */
|
||||
wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
|
||||
|
||||
/* Clear CEIR_EN */
|
||||
wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01);
|
||||
|
||||
/* Enable interrupts */
|
||||
wbcir_reset_irdata(data);
|
||||
outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* SETUP/INIT FUNCTIONS
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static void
|
||||
wbcir_cfg_ceir(struct wbcir_data *data)
|
||||
wbcir_init_hw(struct wbcir_data *data)
|
||||
{
|
||||
u8 tmp;
|
||||
|
||||
/* Disable interrupts */
|
||||
wbcir_select_bank(data, WBCIR_BANK_0);
|
||||
outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
|
||||
|
||||
/* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */
|
||||
tmp = protocol << 4;
|
||||
if (invert)
|
||||
|
@ -1264,6 +1251,93 @@ wbcir_cfg_ceir(struct wbcir_data *data)
|
|||
* set SP3_IRRX_SW to binary 01, helpfully not documented
|
||||
*/
|
||||
outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS);
|
||||
|
||||
/* Enable extended mode */
|
||||
wbcir_select_bank(data, WBCIR_BANK_2);
|
||||
outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1);
|
||||
|
||||
/*
|
||||
* Configure baud generator, IR data will be sampled at
|
||||
* a bitrate of: (24Mhz * prescaler) / (divisor * 16).
|
||||
*
|
||||
* The ECIR registers include a flag to change the
|
||||
* 24Mhz clock freq to 48Mhz.
|
||||
*
|
||||
* It's not documented in the specs, but fifo levels
|
||||
* other than 16 seems to be unsupported.
|
||||
*/
|
||||
|
||||
/* prescaler 1.0, tx/rx fifo lvl 16 */
|
||||
outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2);
|
||||
|
||||
/* Set baud divisor to generate one byte per bit/cell */
|
||||
switch (protocol) {
|
||||
case IR_PROTOCOL_RC5:
|
||||
outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL);
|
||||
break;
|
||||
case IR_PROTOCOL_RC6:
|
||||
outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL);
|
||||
break;
|
||||
case IR_PROTOCOL_NEC:
|
||||
outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL);
|
||||
break;
|
||||
}
|
||||
outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH);
|
||||
|
||||
/* Set CEIR mode */
|
||||
wbcir_select_bank(data, WBCIR_BANK_0);
|
||||
outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR);
|
||||
inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */
|
||||
inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */
|
||||
|
||||
/* Disable RX demod, run-length encoding/decoding, set freq span */
|
||||
wbcir_select_bank(data, WBCIR_BANK_7);
|
||||
outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG);
|
||||
|
||||
/* Disable timer */
|
||||
wbcir_select_bank(data, WBCIR_BANK_4);
|
||||
outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1);
|
||||
|
||||
/* Enable MSR interrupt, Clear AUX_IRX */
|
||||
wbcir_select_bank(data, WBCIR_BANK_5);
|
||||
outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2);
|
||||
|
||||
/* Disable CRC */
|
||||
wbcir_select_bank(data, WBCIR_BANK_6);
|
||||
outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3);
|
||||
|
||||
/* Set RX/TX (de)modulation freq, not really used */
|
||||
wbcir_select_bank(data, WBCIR_BANK_7);
|
||||
outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC);
|
||||
outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC);
|
||||
|
||||
/* Set invert and pin direction */
|
||||
if (invert)
|
||||
outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4);
|
||||
else
|
||||
outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4);
|
||||
|
||||
/* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */
|
||||
wbcir_select_bank(data, WBCIR_BANK_0);
|
||||
outb(0x97, data->sbase + WBCIR_REG_SP3_FCR);
|
||||
|
||||
/* Clear AUX status bits */
|
||||
outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR);
|
||||
|
||||
/* Enable interrupts */
|
||||
wbcir_reset_irdata(data);
|
||||
outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER);
|
||||
}
|
||||
|
||||
static int
|
||||
wbcir_resume(struct pnp_dev *device)
|
||||
{
|
||||
struct wbcir_data *data = pnp_get_drvdata(device);
|
||||
|
||||
wbcir_init_hw(data);
|
||||
enable_irq(data->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
|
@ -1393,86 +1467,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
|
|||
|
||||
device_init_wakeup(&device->dev, 1);
|
||||
|
||||
wbcir_cfg_ceir(data);
|
||||
|
||||
/* Disable interrupts */
|
||||
wbcir_select_bank(data, WBCIR_BANK_0);
|
||||
outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER);
|
||||
|
||||
/* Enable extended mode */
|
||||
wbcir_select_bank(data, WBCIR_BANK_2);
|
||||
outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1);
|
||||
|
||||
/*
|
||||
* Configure baud generator, IR data will be sampled at
|
||||
* a bitrate of: (24Mhz * prescaler) / (divisor * 16).
|
||||
*
|
||||
* The ECIR registers include a flag to change the
|
||||
* 24Mhz clock freq to 48Mhz.
|
||||
*
|
||||
* It's not documented in the specs, but fifo levels
|
||||
* other than 16 seems to be unsupported.
|
||||
*/
|
||||
|
||||
/* prescaler 1.0, tx/rx fifo lvl 16 */
|
||||
outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2);
|
||||
|
||||
/* Set baud divisor to generate one byte per bit/cell */
|
||||
switch (protocol) {
|
||||
case IR_PROTOCOL_RC5:
|
||||
outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL);
|
||||
break;
|
||||
case IR_PROTOCOL_RC6:
|
||||
outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL);
|
||||
break;
|
||||
case IR_PROTOCOL_NEC:
|
||||
outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL);
|
||||
break;
|
||||
}
|
||||
outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH);
|
||||
|
||||
/* Set CEIR mode */
|
||||
wbcir_select_bank(data, WBCIR_BANK_0);
|
||||
outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR);
|
||||
inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */
|
||||
inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */
|
||||
|
||||
/* Disable RX demod, run-length encoding/decoding, set freq span */
|
||||
wbcir_select_bank(data, WBCIR_BANK_7);
|
||||
outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG);
|
||||
|
||||
/* Disable timer */
|
||||
wbcir_select_bank(data, WBCIR_BANK_4);
|
||||
outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1);
|
||||
|
||||
/* Enable MSR interrupt, Clear AUX_IRX */
|
||||
wbcir_select_bank(data, WBCIR_BANK_5);
|
||||
outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2);
|
||||
|
||||
/* Disable CRC */
|
||||
wbcir_select_bank(data, WBCIR_BANK_6);
|
||||
outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3);
|
||||
|
||||
/* Set RX/TX (de)modulation freq, not really used */
|
||||
wbcir_select_bank(data, WBCIR_BANK_7);
|
||||
outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC);
|
||||
outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC);
|
||||
|
||||
/* Set invert and pin direction */
|
||||
if (invert)
|
||||
outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4);
|
||||
else
|
||||
outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4);
|
||||
|
||||
/* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */
|
||||
wbcir_select_bank(data, WBCIR_BANK_0);
|
||||
outb(0x97, data->sbase + WBCIR_REG_SP3_FCR);
|
||||
|
||||
/* Clear AUX status bits */
|
||||
outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR);
|
||||
|
||||
/* Enable interrupts */
|
||||
outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER);
|
||||
wbcir_init_hw(data);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -68,10 +68,6 @@ module_param(post_interrupt_delay, int, 0644);
|
|||
MODULE_PARM_DESC(post_interrupt_delay,
|
||||
"delay (ms) before recal after recal interrupt detected");
|
||||
|
||||
static int autorecal = 1;
|
||||
module_param(autorecal, int, 0644);
|
||||
MODULE_PARM_DESC(autorecal, "enable recalibration in the driver");
|
||||
|
||||
/*
|
||||
* When the touchpad gets ultra-sensitive, one can keep their finger 1/2"
|
||||
* above the pad and still have it send packets. This causes a jump cursor
|
||||
|
|
|
@ -186,7 +186,7 @@ static void __devexit pcips2_remove(struct pci_dev *dev)
|
|||
pci_disable_device(dev);
|
||||
}
|
||||
|
||||
static struct pci_device_id pcips2_ids[] = {
|
||||
static const struct pci_device_id pcips2_ids[] = {
|
||||
{
|
||||
.vendor = 0x14f2, /* MOBILITY */
|
||||
.device = 0x0123, /* Keyboard */
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/serio.h>
|
||||
|
@ -119,11 +121,10 @@ static int serio_bind_driver(struct serio *serio, struct serio_driver *drv)
|
|||
|
||||
error = device_bind_driver(&serio->dev);
|
||||
if (error) {
|
||||
printk(KERN_WARNING
|
||||
"serio: device_bind_driver() failed "
|
||||
"for %s (%s) and %s, error: %d\n",
|
||||
serio->phys, serio->name,
|
||||
drv->description, error);
|
||||
dev_warn(&serio->dev,
|
||||
"device_bind_driver() failed for %s (%s) and %s, error: %d\n",
|
||||
serio->phys, serio->name,
|
||||
drv->description, error);
|
||||
serio_disconnect_driver(serio);
|
||||
serio->dev.driver = NULL;
|
||||
return error;
|
||||
|
@ -138,9 +139,9 @@ static void serio_find_driver(struct serio *serio)
|
|||
|
||||
error = device_attach(&serio->dev);
|
||||
if (error < 0)
|
||||
printk(KERN_WARNING
|
||||
"serio: device_attach() failed for %s (%s), error: %d\n",
|
||||
serio->phys, serio->name, error);
|
||||
dev_warn(&serio->dev,
|
||||
"device_attach() failed for %s (%s), error: %d\n",
|
||||
serio->phys, serio->name, error);
|
||||
}
|
||||
|
||||
|
||||
|
@ -194,17 +195,14 @@ static int serio_queue_event(void *object, struct module *owner,
|
|||
|
||||
event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC);
|
||||
if (!event) {
|
||||
printk(KERN_ERR
|
||||
"serio: 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
|
||||
"serio: 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;
|
||||
|
@ -230,14 +228,12 @@ static void serio_free_event(struct serio_event *event)
|
|||
|
||||
static void serio_remove_duplicate_events(struct serio_event *event)
|
||||
{
|
||||
struct list_head *node, *next;
|
||||
struct serio_event *e;
|
||||
struct serio_event *e, *next;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&serio_event_lock, flags);
|
||||
|
||||
list_for_each_safe(node, next, &serio_event_list) {
|
||||
e = list_entry(node, struct serio_event, node);
|
||||
list_for_each_entry_safe(e, next, &serio_event_list, node) {
|
||||
if (event->object == e->object) {
|
||||
/*
|
||||
* If this event is of different type we should not
|
||||
|
@ -247,7 +243,7 @@ static void serio_remove_duplicate_events(struct serio_event *event)
|
|||
if (event->type != e->type)
|
||||
break;
|
||||
|
||||
list_del_init(node);
|
||||
list_del_init(&e->node);
|
||||
serio_free_event(e);
|
||||
}
|
||||
}
|
||||
|
@ -258,23 +254,18 @@ static void serio_remove_duplicate_events(struct serio_event *event)
|
|||
|
||||
static struct serio_event *serio_get_event(void)
|
||||
{
|
||||
struct serio_event *event;
|
||||
struct list_head *node;
|
||||
struct serio_event *event = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&serio_event_lock, flags);
|
||||
|
||||
if (list_empty(&serio_event_list)) {
|
||||
spin_unlock_irqrestore(&serio_event_lock, flags);
|
||||
return NULL;
|
||||
if (!list_empty(&serio_event_list)) {
|
||||
event = list_first_entry(&serio_event_list,
|
||||
struct serio_event, node);
|
||||
list_del_init(&event->node);
|
||||
}
|
||||
|
||||
node = serio_event_list.next;
|
||||
event = list_entry(node, struct serio_event, node);
|
||||
list_del_init(node);
|
||||
|
||||
spin_unlock_irqrestore(&serio_event_lock, flags);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
|
@ -287,29 +278,27 @@ static void serio_handle_event(void)
|
|||
while ((event = serio_get_event())) {
|
||||
|
||||
switch (event->type) {
|
||||
case SERIO_REGISTER_PORT:
|
||||
serio_add_port(event->object);
|
||||
break;
|
||||
|
||||
case SERIO_RECONNECT_PORT:
|
||||
serio_reconnect_port(event->object);
|
||||
break;
|
||||
case SERIO_REGISTER_PORT:
|
||||
serio_add_port(event->object);
|
||||
break;
|
||||
|
||||
case SERIO_RESCAN_PORT:
|
||||
serio_disconnect_port(event->object);
|
||||
serio_find_driver(event->object);
|
||||
break;
|
||||
case SERIO_RECONNECT_PORT:
|
||||
serio_reconnect_port(event->object);
|
||||
break;
|
||||
|
||||
case SERIO_RECONNECT_CHAIN:
|
||||
serio_reconnect_chain(event->object);
|
||||
break;
|
||||
case SERIO_RESCAN_PORT:
|
||||
serio_disconnect_port(event->object);
|
||||
serio_find_driver(event->object);
|
||||
break;
|
||||
|
||||
case SERIO_ATTACH_DRIVER:
|
||||
serio_attach_driver(event->object);
|
||||
break;
|
||||
case SERIO_RECONNECT_CHAIN:
|
||||
serio_reconnect_chain(event->object);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
case SERIO_ATTACH_DRIVER:
|
||||
serio_attach_driver(event->object);
|
||||
break;
|
||||
}
|
||||
|
||||
serio_remove_duplicate_events(event);
|
||||
|
@ -325,16 +314,14 @@ static void serio_handle_event(void)
|
|||
*/
|
||||
static void serio_remove_pending_events(void *object)
|
||||
{
|
||||
struct list_head *node, *next;
|
||||
struct serio_event *event;
|
||||
struct serio_event *event, *next;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&serio_event_lock, flags);
|
||||
|
||||
list_for_each_safe(node, next, &serio_event_list) {
|
||||
event = list_entry(node, struct serio_event, node);
|
||||
list_for_each_entry_safe(event, next, &serio_event_list, node) {
|
||||
if (event->object == object) {
|
||||
list_del_init(node);
|
||||
list_del_init(&event->node);
|
||||
serio_free_event(event);
|
||||
}
|
||||
}
|
||||
|
@ -380,7 +367,6 @@ static int serio_thread(void *nothing)
|
|||
kthread_should_stop() || !list_empty(&serio_event_list));
|
||||
} while (!kthread_should_stop());
|
||||
|
||||
printk(KERN_DEBUG "serio: kseriod exiting\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -445,6 +431,11 @@ static struct attribute_group serio_id_attr_group = {
|
|||
.attrs = serio_device_id_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *serio_device_attr_groups[] = {
|
||||
&serio_id_attr_group,
|
||||
NULL
|
||||
};
|
||||
|
||||
static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
|
@ -532,6 +523,7 @@ static void serio_init_port(struct serio *serio)
|
|||
(long)atomic_inc_return(&serio_no) - 1);
|
||||
serio->dev.bus = &serio_bus;
|
||||
serio->dev.release = serio_release_port;
|
||||
serio->dev.groups = serio_device_attr_groups;
|
||||
if (serio->parent) {
|
||||
serio->dev.parent = &serio->parent->dev;
|
||||
serio->depth = serio->parent->depth + 1;
|
||||
|
@ -555,21 +547,15 @@ static void serio_add_port(struct serio *serio)
|
|||
}
|
||||
|
||||
list_add_tail(&serio->node, &serio_list);
|
||||
|
||||
if (serio->start)
|
||||
serio->start(serio);
|
||||
|
||||
error = device_add(&serio->dev);
|
||||
if (error)
|
||||
printk(KERN_ERR
|
||||
"serio: device_add() failed for %s (%s), error: %d\n",
|
||||
dev_err(&serio->dev,
|
||||
"device_add() failed for %s (%s), error: %d\n",
|
||||
serio->phys, serio->name, error);
|
||||
else {
|
||||
serio->registered = true;
|
||||
error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
|
||||
if (error)
|
||||
printk(KERN_ERR
|
||||
"serio: sysfs_create_group() failed for %s (%s), error: %d\n",
|
||||
serio->phys, serio->name, error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -596,11 +582,8 @@ static void serio_destroy_port(struct serio *serio)
|
|||
serio->parent = NULL;
|
||||
}
|
||||
|
||||
if (serio->registered) {
|
||||
sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group);
|
||||
if (device_is_registered(&serio->dev))
|
||||
device_del(&serio->dev);
|
||||
serio->registered = false;
|
||||
}
|
||||
|
||||
list_del_init(&serio->node);
|
||||
serio_remove_pending_events(serio);
|
||||
|
@ -798,9 +781,8 @@ static void serio_attach_driver(struct serio_driver *drv)
|
|||
|
||||
error = driver_attach(&drv->driver);
|
||||
if (error)
|
||||
printk(KERN_WARNING
|
||||
"serio: driver_attach() failed for %s with error %d\n",
|
||||
drv->driver.name, error);
|
||||
pr_warning("driver_attach() failed for %s with error %d\n",
|
||||
drv->driver.name, error);
|
||||
}
|
||||
|
||||
int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name)
|
||||
|
@ -820,8 +802,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons
|
|||
|
||||
error = driver_register(&drv->driver);
|
||||
if (error) {
|
||||
printk(KERN_ERR
|
||||
"serio: driver_register() failed for %s, error: %d\n",
|
||||
pr_err("driver_register() failed for %s, error: %d\n",
|
||||
drv->driver.name, error);
|
||||
return error;
|
||||
}
|
||||
|
@ -987,7 +968,7 @@ irqreturn_t serio_interrupt(struct serio *serio,
|
|||
|
||||
if (likely(serio->drv)) {
|
||||
ret = serio->drv->interrupt(serio, data, dfl);
|
||||
} else if (!dfl && serio->registered) {
|
||||
} else if (!dfl && device_is_registered(&serio->dev)) {
|
||||
serio_rescan(serio);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
@ -1018,7 +999,7 @@ static int __init serio_init(void)
|
|||
|
||||
error = bus_register(&serio_bus);
|
||||
if (error) {
|
||||
printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error);
|
||||
pr_err("Failed to register serio bus, error: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1026,7 +1007,7 @@ static int __init serio_init(void)
|
|||
if (IS_ERR(serio_task)) {
|
||||
bus_unregister(&serio_bus);
|
||||
error = PTR_ERR(serio_task);
|
||||
printk(KERN_ERR "serio: Failed to start kseriod, error: %d\n", error);
|
||||
pr_err("Failed to start kseriod, error: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -270,7 +270,7 @@ static int __devinit xps2_of_probe(struct of_device *ofdev,
|
|||
drvdata->irq = r_irq.start;
|
||||
|
||||
phys_addr = r_mem.start;
|
||||
remap_size = r_mem.end - r_mem.start + 1;
|
||||
remap_size = resource_size(&r_mem);
|
||||
if (!request_mem_region(phys_addr, remap_size, DRIVER_NAME)) {
|
||||
dev_err(dev, "Couldn't lock memory region at 0x%08llX\n",
|
||||
(unsigned long long)phys_addr);
|
||||
|
@ -344,7 +344,7 @@ static int __devexit xps2_of_remove(struct of_device *of_dev)
|
|||
if (of_address_to_resource(of_dev->node, 0, &r_mem))
|
||||
dev_err(dev, "invalid address\n");
|
||||
else
|
||||
release_mem_region(r_mem.start, r_mem.end - r_mem.start + 1);
|
||||
release_mem_region(r_mem.start, resource_size(&r_mem));
|
||||
|
||||
kfree(drvdata);
|
||||
|
||||
|
@ -354,7 +354,7 @@ static int __devexit xps2_of_remove(struct of_device *of_dev)
|
|||
}
|
||||
|
||||
/* Match table for of_platform binding */
|
||||
static struct of_device_id xps2_of_match[] __devinitdata = {
|
||||
static const struct of_device_id xps2_of_match[] __devinitconst = {
|
||||
{ .compatible = "xlnx,xps-ps2-1.00.a", },
|
||||
{ /* end of list */ },
|
||||
};
|
||||
|
|
|
@ -92,7 +92,7 @@ Scott Hill shill@gtcocalcomp.com
|
|||
/* DATA STRUCTURES */
|
||||
|
||||
/* Device table */
|
||||
static struct usb_device_id gtco_usbid_table [] = {
|
||||
static const struct usb_device_id gtco_usbid_table[] = {
|
||||
{ USB_DEVICE(VENDOR_ID_GTCO, PID_400) },
|
||||
{ USB_DEVICE(VENDOR_ID_GTCO, PID_401) },
|
||||
{ USB_DEVICE(VENDOR_ID_GTCO, PID_1000) },
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/usb/input.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
@ -120,6 +121,8 @@ struct wacom_combo {
|
|||
struct urb *urb;
|
||||
};
|
||||
|
||||
extern const struct usb_device_id wacom_ids[];
|
||||
|
||||
extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo);
|
||||
extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data);
|
||||
extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data);
|
||||
|
@ -142,7 +145,5 @@ extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wa
|
|||
extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
|
||||
extern __u16 wacom_le16_to_cpu(unsigned char *data);
|
||||
extern __u16 wacom_be16_to_cpu(unsigned char *data);
|
||||
extern struct wacom_features *get_wacom_feature(const struct usb_device_id *id);
|
||||
extern const struct usb_device_id *get_device_table(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -211,7 +211,8 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
|||
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) |
|
||||
BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) |
|
||||
BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2);
|
||||
input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_DISTANCE,
|
||||
0, wacom_wac->features.distance_max, 0, 0);
|
||||
}
|
||||
|
||||
void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
||||
|
@ -261,7 +262,8 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
|||
BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) |
|
||||
BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) |
|
||||
BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2);
|
||||
input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_DISTANCE,
|
||||
0, wacom_wac->features.distance_max, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
|
||||
|
@ -282,17 +284,19 @@ void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
|||
|
||||
void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
||||
{
|
||||
if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP ||
|
||||
wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) {
|
||||
input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->x_phy, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->y_phy, 0, 0);
|
||||
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP);
|
||||
struct wacom_features *features = &wacom_wac->features;
|
||||
|
||||
if (features->device_type == BTN_TOOL_DOUBLETAP ||
|
||||
features->device_type == BTN_TOOL_TRIPLETAP) {
|
||||
input_set_abs_params(input_dev, ABS_RX, 0, features->x_phy, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_RY, 0, features->y_phy, 0, 0);
|
||||
__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
|
||||
}
|
||||
}
|
||||
|
||||
void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
||||
{
|
||||
if (wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) {
|
||||
if (wacom_wac->features.device_type == BTN_TOOL_TRIPLETAP) {
|
||||
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP);
|
||||
input_dev->evbit[0] |= BIT_MASK(EV_MSC);
|
||||
input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL);
|
||||
|
@ -532,21 +536,38 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
|||
struct wacom_wac *wacom_wac;
|
||||
struct wacom_features *features;
|
||||
struct input_dev *input_dev;
|
||||
int error = -ENOMEM;
|
||||
int error;
|
||||
|
||||
if (!id->driver_info)
|
||||
return -EINVAL;
|
||||
|
||||
wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
|
||||
wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
if (!wacom || !input_dev || !wacom_wac)
|
||||
if (!wacom || !input_dev || !wacom_wac) {
|
||||
error = -ENOMEM;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX, GFP_KERNEL, &wacom->data_dma);
|
||||
if (!wacom_wac->data)
|
||||
wacom_wac->features = *((struct wacom_features *)id->driver_info);
|
||||
features = &wacom_wac->features;
|
||||
if (features->pktlen > WACOM_PKGLEN_MAX) {
|
||||
error = -EINVAL;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX,
|
||||
GFP_KERNEL, &wacom->data_dma);
|
||||
if (!wacom_wac->data) {
|
||||
error = -ENOMEM;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!wacom->irq)
|
||||
if (!wacom->irq) {
|
||||
error = -ENOMEM;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
wacom->usbdev = dev;
|
||||
wacom->dev = input_dev;
|
||||
|
@ -555,11 +576,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
|||
usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
|
||||
strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
|
||||
|
||||
wacom_wac->features = features = get_wacom_feature(id);
|
||||
BUG_ON(features->pktlen > WACOM_PKGLEN_MAX);
|
||||
|
||||
input_dev->name = wacom_wac->features->name;
|
||||
wacom->wacom_wac = wacom_wac;
|
||||
usb_to_input_id(dev, &input_dev->id);
|
||||
|
||||
input_dev->dev.parent = &intf->dev;
|
||||
|
@ -576,6 +592,19 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
|||
if (error)
|
||||
goto fail2;
|
||||
|
||||
strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
|
||||
|
||||
if (features->type == TABLETPC || features->type == TABLETPC2FG) {
|
||||
/* Append the device type to the name */
|
||||
strlcat(wacom_wac->name,
|
||||
features->device_type == BTN_TOOL_PEN ?
|
||||
" Pen" : " Finger",
|
||||
sizeof(wacom_wac->name));
|
||||
}
|
||||
|
||||
input_dev->name = wacom_wac->name;
|
||||
wacom->wacom_wac = wacom_wac;
|
||||
|
||||
input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
||||
input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH);
|
||||
|
||||
|
@ -640,7 +669,7 @@ static int wacom_suspend(struct usb_interface *intf, pm_message_t message)
|
|||
static int wacom_resume(struct usb_interface *intf)
|
||||
{
|
||||
struct wacom *wacom = usb_get_intfdata(intf);
|
||||
struct wacom_features *features = wacom->wacom_wac->features;
|
||||
struct wacom_features *features = &wacom->wacom_wac->features;
|
||||
int rv;
|
||||
|
||||
mutex_lock(&wacom->lock);
|
||||
|
@ -663,6 +692,7 @@ static int wacom_reset_resume(struct usb_interface *intf)
|
|||
|
||||
static struct usb_driver wacom_driver = {
|
||||
.name = "wacom",
|
||||
.id_table = wacom_ids,
|
||||
.probe = wacom_probe,
|
||||
.disconnect = wacom_disconnect,
|
||||
.suspend = wacom_suspend,
|
||||
|
@ -674,7 +704,7 @@ static struct usb_driver wacom_driver = {
|
|||
static int __init wacom_init(void)
|
||||
{
|
||||
int result;
|
||||
wacom_driver.id_table = get_device_table();
|
||||
|
||||
result = usb_register(&wacom_driver);
|
||||
if (result == 0)
|
||||
printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
|
||||
|
|
|
@ -55,6 +55,7 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
|
||||
static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
|
||||
{
|
||||
struct wacom_features *features = &wacom->features;
|
||||
unsigned char *data = wacom->data;
|
||||
int prox, pressure;
|
||||
|
||||
|
@ -68,9 +69,9 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
if (prox) {
|
||||
wacom->id[0] = ERASER_DEVICE_ID;
|
||||
pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
|
||||
if (wacom->features->pressure_max > 255)
|
||||
if (features->pressure_max > 255)
|
||||
pressure = (pressure << 1) | ((data[4] >> 6) & 1);
|
||||
pressure += (wacom->features->pressure_max + 1) / 2;
|
||||
pressure += (features->pressure_max + 1) / 2;
|
||||
|
||||
/*
|
||||
* if going from out of proximity into proximity select between the eraser
|
||||
|
@ -152,6 +153,7 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
|
||||
static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
|
||||
{
|
||||
struct wacom_features *features = &wacom->features;
|
||||
unsigned char *data = wacom->data;
|
||||
int x, y, rw;
|
||||
static int penData = 0;
|
||||
|
@ -179,8 +181,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
|
||||
case 2: /* Mouse with wheel */
|
||||
wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04);
|
||||
if (wacom->features->type == WACOM_G4 ||
|
||||
wacom->features->type == WACOM_MO) {
|
||||
if (features->type == WACOM_G4 || features->type == WACOM_MO) {
|
||||
rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
|
||||
wacom_report_rel(wcombo, REL_WHEEL, -rw);
|
||||
} else
|
||||
|
@ -192,8 +193,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
wacom->id[0] = CURSOR_DEVICE_ID;
|
||||
wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);
|
||||
wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);
|
||||
if (wacom->features->type == WACOM_G4 ||
|
||||
wacom->features->type == WACOM_MO)
|
||||
if (features->type == WACOM_G4 || features->type == WACOM_MO)
|
||||
wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f);
|
||||
else
|
||||
wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f);
|
||||
|
@ -230,7 +230,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
}
|
||||
|
||||
/* send pad data */
|
||||
switch (wacom->features->type) {
|
||||
switch (features->type) {
|
||||
case WACOM_G4:
|
||||
if (data[7] & 0xf8) {
|
||||
if (penData) {
|
||||
|
@ -300,11 +300,12 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
|
||||
static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
|
||||
{
|
||||
struct wacom_features *features = &wacom->features;
|
||||
unsigned char *data = wacom->data;
|
||||
int idx = 0;
|
||||
|
||||
/* tool number */
|
||||
if (wacom->features->type == INTUOS)
|
||||
if (features->type == INTUOS)
|
||||
idx = data[1] & 0x01;
|
||||
|
||||
/* Enter report */
|
||||
|
@ -402,7 +403,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
|
|||
wacom_report_key(wcombo, BTN_STYLUS2, 0);
|
||||
wacom_report_key(wcombo, BTN_TOUCH, 0);
|
||||
wacom_report_abs(wcombo, ABS_WHEEL, 0);
|
||||
if (wacom->features->type >= INTUOS3S)
|
||||
if (features->type >= INTUOS3S)
|
||||
wacom_report_abs(wcombo, ABS_Z, 0);
|
||||
}
|
||||
wacom_report_key(wcombo, wacom->tool[idx], 0);
|
||||
|
@ -416,13 +417,14 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
|
|||
|
||||
static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo)
|
||||
{
|
||||
struct wacom_features *features = &wacom->features;
|
||||
unsigned char *data = wacom->data;
|
||||
unsigned int t;
|
||||
|
||||
/* general pen packet */
|
||||
if ((data[1] & 0xb8) == 0xa0) {
|
||||
t = (data[6] << 2) | ((data[7] >> 6) & 3);
|
||||
if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L)
|
||||
if (features->type >= INTUOS4S && features->type <= INTUOS4L)
|
||||
t = (t << 1) | (data[1] & 1);
|
||||
wacom_report_abs(wcombo, ABS_PRESSURE, t);
|
||||
wacom_report_abs(wcombo, ABS_TILT_X,
|
||||
|
@ -446,6 +448,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo)
|
|||
|
||||
static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
|
||||
{
|
||||
struct wacom_features *features = &wacom->features;
|
||||
unsigned char *data = wacom->data;
|
||||
unsigned int t;
|
||||
int idx = 0, result;
|
||||
|
@ -457,7 +460,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
}
|
||||
|
||||
/* tool number */
|
||||
if (wacom->features->type == INTUOS)
|
||||
if (features->type == INTUOS)
|
||||
idx = data[1] & 0x01;
|
||||
|
||||
/* pad packets. Works as a second tool and is always in prox */
|
||||
|
@ -466,7 +469,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
if (wacom->tool[1] != BTN_TOOL_FINGER)
|
||||
wacom->tool[1] = BTN_TOOL_FINGER;
|
||||
|
||||
if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) {
|
||||
if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
|
||||
wacom_report_key(wcombo, BTN_0, (data[2] & 0x01));
|
||||
wacom_report_key(wcombo, BTN_1, (data[3] & 0x01));
|
||||
wacom_report_key(wcombo, BTN_2, (data[3] & 0x02));
|
||||
|
@ -480,7 +483,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
/* Out of proximity, clear wheel value. */
|
||||
wacom_report_abs(wcombo, ABS_WHEEL, 0);
|
||||
}
|
||||
if (wacom->features->type != INTUOS4S) {
|
||||
if (features->type != INTUOS4S) {
|
||||
wacom_report_key(wcombo, BTN_7, (data[3] & 0x40));
|
||||
wacom_report_key(wcombo, BTN_8, (data[3] & 0x80));
|
||||
}
|
||||
|
@ -528,18 +531,20 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
return 0;
|
||||
|
||||
/* Only large Intuos support Lense Cursor */
|
||||
if ((wacom->tool[idx] == BTN_TOOL_LENS)
|
||||
&& ((wacom->features->type == INTUOS3)
|
||||
|| (wacom->features->type == INTUOS3S)
|
||||
|| (wacom->features->type == INTUOS4)
|
||||
|| (wacom->features->type == INTUOS4S)))
|
||||
if (wacom->tool[idx] == BTN_TOOL_LENS &&
|
||||
(features->type == INTUOS3 ||
|
||||
features->type == INTUOS3S ||
|
||||
features->type == INTUOS4 ||
|
||||
features->type == INTUOS4S)) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Cintiq doesn't send data when RDY bit isn't set */
|
||||
if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
|
||||
if (features->type == CINTIQ && !(data[1] & 0x40))
|
||||
return 0;
|
||||
|
||||
if (wacom->features->type >= INTUOS3S) {
|
||||
if (features->type >= INTUOS3S) {
|
||||
wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
|
||||
wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
|
||||
wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
|
||||
|
@ -557,7 +562,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
|
||||
if (data[1] & 0x02) {
|
||||
/* Rotation packet */
|
||||
if (wacom->features->type >= INTUOS3S) {
|
||||
if (features->type >= INTUOS3S) {
|
||||
/* I3 marker pen rotation */
|
||||
t = (data[6] << 3) | ((data[7] >> 5) & 7);
|
||||
t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
|
||||
|
@ -570,7 +575,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
((t - 1) / 2) : -t / 2);
|
||||
}
|
||||
|
||||
} else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3S) {
|
||||
} else if (!(data[1] & 0x10) && features->type < INTUOS3S) {
|
||||
/* 4D mouse packet */
|
||||
wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01);
|
||||
wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
|
||||
|
@ -583,7 +588,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
|
||||
} else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
|
||||
/* I4 mouse */
|
||||
if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) {
|
||||
if (features->type >= INTUOS4S && features->type <= INTUOS4L) {
|
||||
wacom_report_key(wcombo, BTN_LEFT, data[6] & 0x01);
|
||||
wacom_report_key(wcombo, BTN_MIDDLE, data[6] & 0x02);
|
||||
wacom_report_key(wcombo, BTN_RIGHT, data[6] & 0x04);
|
||||
|
@ -604,13 +609,13 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
- ((data[8] & 0x02) >> 1));
|
||||
|
||||
/* I3 2D mouse side buttons */
|
||||
if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) {
|
||||
if (features->type >= INTUOS3S && features->type <= INTUOS3L) {
|
||||
wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40);
|
||||
wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20);
|
||||
}
|
||||
}
|
||||
} else if ((wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L ||
|
||||
wacom->features->type == INTUOS4L) &&
|
||||
} else if ((features->type < INTUOS3S || features->type == INTUOS3L ||
|
||||
features->type == INTUOS4L) &&
|
||||
wacom->tool[idx] == BTN_TOOL_LENS) {
|
||||
/* Lens cursor packets */
|
||||
wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01);
|
||||
|
@ -718,6 +723,7 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo)
|
|||
|
||||
static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
|
||||
{
|
||||
struct wacom_features *features = &wacom->features;
|
||||
char *data = wacom->data;
|
||||
int prox = 0, pressure, idx = -1;
|
||||
static int stylusInProx, touchInProx = 1, touchOut;
|
||||
|
@ -791,7 +797,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
|
||||
pressure = ((data[7] & 0x01) << 8) | data[6];
|
||||
if (pressure < 0)
|
||||
pressure = wacom->features->pressure_max + pressure + 1;
|
||||
pressure = features->pressure_max + pressure + 1;
|
||||
wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
|
||||
wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05);
|
||||
} else {
|
||||
|
@ -815,7 +821,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
|
|||
|
||||
int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
|
||||
{
|
||||
switch (wacom_wac->features->type) {
|
||||
switch (wacom_wac->features.type) {
|
||||
case PENPARTNER:
|
||||
return wacom_penpartner_irq(wacom_wac, wcombo);
|
||||
|
||||
|
@ -853,7 +859,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
|
|||
|
||||
void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
|
||||
{
|
||||
switch (wacom_wac->features->type) {
|
||||
switch (wacom_wac->features.type) {
|
||||
case WACOM_MO:
|
||||
input_dev_mo(input_dev, wacom_wac);
|
||||
case WACOM_G4:
|
||||
|
@ -888,7 +894,7 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w
|
|||
/* fall through */
|
||||
case TABLETPC:
|
||||
input_dev_tpc(input_dev, wacom_wac);
|
||||
if (wacom_wac->features->device_type != BTN_TOOL_PEN)
|
||||
if (wacom_wac->features.device_type != BTN_TOOL_PEN)
|
||||
break; /* no need to process stylus stuff */
|
||||
|
||||
/* fall through */
|
||||
|
@ -903,153 +909,201 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w
|
|||
return;
|
||||
}
|
||||
|
||||
static struct wacom_features wacom_features[] = {
|
||||
{ "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, 0, PENPARTNER },
|
||||
{ "Wacom Graphire", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE },
|
||||
{ "Wacom Graphire2 4x5", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE },
|
||||
{ "Wacom Graphire2 5x7", WACOM_PKGLEN_GRAPHIRE, 13918, 10206, 511, 63, GRAPHIRE },
|
||||
{ "Wacom Graphire3", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, GRAPHIRE },
|
||||
{ "Wacom Graphire3 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE },
|
||||
{ "Wacom Graphire4 4x5", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, WACOM_G4 },
|
||||
{ "Wacom Graphire4 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, WACOM_G4 },
|
||||
{ "Wacom BambooFun 4x5", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO },
|
||||
{ "Wacom BambooFun 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 511, 63, WACOM_MO },
|
||||
{ "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE },
|
||||
{ "Wacom Volito", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE },
|
||||
{ "Wacom PenStation2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 255, 63, GRAPHIRE },
|
||||
{ "Wacom Volito2 4x5", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE },
|
||||
{ "Wacom Volito2 2x3", WACOM_PKGLEN_GRAPHIRE, 3248, 2320, 511, 63, GRAPHIRE },
|
||||
{ "Wacom PenPartner2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 511, 63, GRAPHIRE },
|
||||
{ "Wacom Bamboo", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO },
|
||||
{ "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE },
|
||||
{ "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS },
|
||||
{ "Wacom Intuos 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS },
|
||||
{ "Wacom Intuos 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS },
|
||||
{ "Wacom Intuos 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS },
|
||||
{ "Wacom Intuos 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS },
|
||||
{ "Wacom PL400", WACOM_PKGLEN_GRAPHIRE, 5408, 4056, 255, 0, PL },
|
||||
{ "Wacom PL500", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 255, 0, PL },
|
||||
{ "Wacom PL600", WACOM_PKGLEN_GRAPHIRE, 6126, 4604, 255, 0, PL },
|
||||
{ "Wacom PL600SX", WACOM_PKGLEN_GRAPHIRE, 6260, 5016, 255, 0, PL },
|
||||
{ "Wacom PL550", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 511, 0, PL },
|
||||
{ "Wacom PL800", WACOM_PKGLEN_GRAPHIRE, 7220, 5780, 511, 0, PL },
|
||||
{ "Wacom PL700", WACOM_PKGLEN_GRAPHIRE, 6758, 5406, 511, 0, PL },
|
||||
{ "Wacom PL510", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL },
|
||||
{ "Wacom DTU710", WACOM_PKGLEN_GRAPHIRE, 34080, 27660, 511, 0, PL },
|
||||
{ "Wacom DTF521", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL },
|
||||
{ "Wacom DTF720", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL },
|
||||
{ "Wacom DTF720a", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL },
|
||||
{ "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE, 20480, 15360, 511, 0, PTU },
|
||||
{ "Wacom Intuos2 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS },
|
||||
{ "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS },
|
||||
{ "Wacom Intuos2 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS },
|
||||
{ "Wacom Intuos2 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS },
|
||||
{ "Wacom Intuos2 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS },
|
||||
{ "Wacom Intuos3 4x5", WACOM_PKGLEN_INTUOS, 25400, 20320, 1023, 63, INTUOS3S },
|
||||
{ "Wacom Intuos3 6x8", WACOM_PKGLEN_INTUOS, 40640, 30480, 1023, 63, INTUOS3 },
|
||||
{ "Wacom Intuos3 9x12", WACOM_PKGLEN_INTUOS, 60960, 45720, 1023, 63, INTUOS3 },
|
||||
{ "Wacom Intuos3 12x12", WACOM_PKGLEN_INTUOS, 60960, 60960, 1023, 63, INTUOS3L },
|
||||
{ "Wacom Intuos3 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 1023, 63, INTUOS3L },
|
||||
{ "Wacom Intuos3 6x11", WACOM_PKGLEN_INTUOS, 54204, 31750, 1023, 63, INTUOS3 },
|
||||
{ "Wacom Intuos3 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 1023, 63, INTUOS3S },
|
||||
{ "Wacom Intuos4 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, 63, INTUOS4S },
|
||||
{ "Wacom Intuos4 6x9", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS4 },
|
||||
{ "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, 63, INTUOS4L },
|
||||
{ "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, 63, INTUOS4L },
|
||||
{ "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ },
|
||||
{ "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023, 63, WACOM_BEE },
|
||||
{ "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE },
|
||||
{ "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL },
|
||||
{ "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC },
|
||||
{ "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC },
|
||||
{ "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC },
|
||||
{ "Wacom ISDv4 9F", WACOM_PKGLEN_PENABLED, 26202, 16325, 255, 0, TABLETPC },
|
||||
{ "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG },
|
||||
{ "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG },
|
||||
{ "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS },
|
||||
static const struct wacom_features wacom_features_0x00 =
|
||||
{ "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, 0, PENPARTNER };
|
||||
static const struct wacom_features wacom_features_0x10 =
|
||||
{ "Wacom Graphire", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE };
|
||||
static const struct wacom_features wacom_features_0x11 =
|
||||
{ "Wacom Graphire2 4x5", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE };
|
||||
static const struct wacom_features wacom_features_0x12 =
|
||||
{ "Wacom Graphire2 5x7", WACOM_PKGLEN_GRAPHIRE, 13918, 10206, 511, 63, GRAPHIRE };
|
||||
static const struct wacom_features wacom_features_0x13 =
|
||||
{ "Wacom Graphire3", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, GRAPHIRE };
|
||||
static const struct wacom_features wacom_features_0x14 =
|
||||
{ "Wacom Graphire3 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE };
|
||||
static const struct wacom_features wacom_features_0x15 =
|
||||
{ "Wacom Graphire4 4x5", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, WACOM_G4 };
|
||||
static const struct wacom_features wacom_features_0x16 =
|
||||
{ "Wacom Graphire4 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, WACOM_G4 };
|
||||
static const struct wacom_features wacom_features_0x17 =
|
||||
{ "Wacom BambooFun 4x5", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO };
|
||||
static const struct wacom_features wacom_features_0x18 =
|
||||
{ "Wacom BambooFun 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 511, 63, WACOM_MO };
|
||||
static const struct wacom_features wacom_features_0x19 =
|
||||
{ "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE };
|
||||
static const struct wacom_features wacom_features_0x60 =
|
||||
{ "Wacom Volito", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE };
|
||||
static const struct wacom_features wacom_features_0x61 =
|
||||
{ "Wacom PenStation2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 255, 63, GRAPHIRE };
|
||||
static const struct wacom_features wacom_features_0x62 =
|
||||
{ "Wacom Volito2 4x5", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE };
|
||||
static const struct wacom_features wacom_features_0x63 =
|
||||
{ "Wacom Volito2 2x3", WACOM_PKGLEN_GRAPHIRE, 3248, 2320, 511, 63, GRAPHIRE };
|
||||
static const struct wacom_features wacom_features_0x64 =
|
||||
{ "Wacom PenPartner2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 511, 63, GRAPHIRE };
|
||||
static const struct wacom_features wacom_features_0x65 =
|
||||
{ "Wacom Bamboo", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO };
|
||||
static const struct wacom_features wacom_features_0x69 =
|
||||
{ "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE };
|
||||
static const struct wacom_features wacom_features_0x20 =
|
||||
{ "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS };
|
||||
static const struct wacom_features wacom_features_0x21 =
|
||||
{ "Wacom Intuos 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS };
|
||||
static const struct wacom_features wacom_features_0x22 =
|
||||
{ "Wacom Intuos 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS };
|
||||
static const struct wacom_features wacom_features_0x23 =
|
||||
{ "Wacom Intuos 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS };
|
||||
static const struct wacom_features wacom_features_0x24 =
|
||||
{ "Wacom Intuos 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS };
|
||||
static const struct wacom_features wacom_features_0x30 =
|
||||
{ "Wacom PL400", WACOM_PKGLEN_GRAPHIRE, 5408, 4056, 255, 0, PL };
|
||||
static const struct wacom_features wacom_features_0x31 =
|
||||
{ "Wacom PL500", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 255, 0, PL };
|
||||
static const struct wacom_features wacom_features_0x32 =
|
||||
{ "Wacom PL600", WACOM_PKGLEN_GRAPHIRE, 6126, 4604, 255, 0, PL };
|
||||
static const struct wacom_features wacom_features_0x33 =
|
||||
{ "Wacom PL600SX", WACOM_PKGLEN_GRAPHIRE, 6260, 5016, 255, 0, PL };
|
||||
static const struct wacom_features wacom_features_0x34 =
|
||||
{ "Wacom PL550", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 511, 0, PL };
|
||||
static const struct wacom_features wacom_features_0x35 =
|
||||
{ "Wacom PL800", WACOM_PKGLEN_GRAPHIRE, 7220, 5780, 511, 0, PL };
|
||||
static const struct wacom_features wacom_features_0x37 =
|
||||
{ "Wacom PL700", WACOM_PKGLEN_GRAPHIRE, 6758, 5406, 511, 0, PL };
|
||||
static const struct wacom_features wacom_features_0x38 =
|
||||
{ "Wacom PL510", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL };
|
||||
static const struct wacom_features wacom_features_0x39 =
|
||||
{ "Wacom DTU710", WACOM_PKGLEN_GRAPHIRE, 34080, 27660, 511, 0, PL };
|
||||
static const struct wacom_features wacom_features_0xC4 =
|
||||
{ "Wacom DTF521", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL };
|
||||
static const struct wacom_features wacom_features_0xC0 =
|
||||
{ "Wacom DTF720", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL };
|
||||
static const struct wacom_features wacom_features_0xC2 =
|
||||
{ "Wacom DTF720a", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL };
|
||||
static const struct wacom_features wacom_features_0x03 =
|
||||
{ "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE, 20480, 15360, 511, 0, PTU };
|
||||
static const struct wacom_features wacom_features_0x41 =
|
||||
{ "Wacom Intuos2 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS };
|
||||
static const struct wacom_features wacom_features_0x42 =
|
||||
{ "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS };
|
||||
static const struct wacom_features wacom_features_0x43 =
|
||||
{ "Wacom Intuos2 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS };
|
||||
static const struct wacom_features wacom_features_0x44 =
|
||||
{ "Wacom Intuos2 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS };
|
||||
static const struct wacom_features wacom_features_0x45 =
|
||||
{ "Wacom Intuos2 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS };
|
||||
static const struct wacom_features wacom_features_0xB0 =
|
||||
{ "Wacom Intuos3 4x5", WACOM_PKGLEN_INTUOS, 25400, 20320, 1023, 63, INTUOS3S };
|
||||
static const struct wacom_features wacom_features_0xB1 =
|
||||
{ "Wacom Intuos3 6x8", WACOM_PKGLEN_INTUOS, 40640, 30480, 1023, 63, INTUOS3 };
|
||||
static const struct wacom_features wacom_features_0xB2 =
|
||||
{ "Wacom Intuos3 9x12", WACOM_PKGLEN_INTUOS, 60960, 45720, 1023, 63, INTUOS3 };
|
||||
static const struct wacom_features wacom_features_0xB3 =
|
||||
{ "Wacom Intuos3 12x12", WACOM_PKGLEN_INTUOS, 60960, 60960, 1023, 63, INTUOS3L };
|
||||
static const struct wacom_features wacom_features_0xB4 =
|
||||
{ "Wacom Intuos3 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 1023, 63, INTUOS3L };
|
||||
static const struct wacom_features wacom_features_0xB5 =
|
||||
{ "Wacom Intuos3 6x11", WACOM_PKGLEN_INTUOS, 54204, 31750, 1023, 63, INTUOS3 };
|
||||
static const struct wacom_features wacom_features_0xB7 =
|
||||
{ "Wacom Intuos3 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 1023, 63, INTUOS3S };
|
||||
static const struct wacom_features wacom_features_0xB8 =
|
||||
{ "Wacom Intuos4 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, 63, INTUOS4S };
|
||||
static const struct wacom_features wacom_features_0xB9 =
|
||||
{ "Wacom Intuos4 6x9", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS4 };
|
||||
static const struct wacom_features wacom_features_0xBA =
|
||||
{ "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, 63, INTUOS4L };
|
||||
static const struct wacom_features wacom_features_0xBB =
|
||||
{ "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, 63, INTUOS4L };
|
||||
static const struct wacom_features wacom_features_0x3F =
|
||||
{ "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ };
|
||||
static const struct wacom_features wacom_features_0xC5 =
|
||||
{ "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023, 63, WACOM_BEE };
|
||||
static const struct wacom_features wacom_features_0xC6 =
|
||||
{ "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE };
|
||||
static const struct wacom_features wacom_features_0xC7 =
|
||||
{ "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL };
|
||||
static const struct wacom_features wacom_features_0x90 =
|
||||
{ "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC };
|
||||
static const struct wacom_features wacom_features_0x93 =
|
||||
{ "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC };
|
||||
static const struct wacom_features wacom_features_0x9A =
|
||||
{ "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC };
|
||||
static const struct wacom_features wacom_features_0x9F =
|
||||
{ "Wacom ISDv4 9F", WACOM_PKGLEN_PENABLED, 26202, 16325, 255, 0, TABLETPC };
|
||||
static const struct wacom_features wacom_features_0xE2 =
|
||||
{ "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG };
|
||||
static const struct wacom_features wacom_features_0xE3 =
|
||||
{ "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG };
|
||||
static const struct wacom_features wacom_features_0x47 =
|
||||
{ "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS };
|
||||
|
||||
#define USB_DEVICE_WACOM(prod) \
|
||||
USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \
|
||||
.driver_info = (kernel_ulong_t)&wacom_features_##prod
|
||||
|
||||
const struct usb_device_id wacom_ids[] = {
|
||||
{ USB_DEVICE_WACOM(0x00) },
|
||||
{ USB_DEVICE_WACOM(0x10) },
|
||||
{ USB_DEVICE_WACOM(0x11) },
|
||||
{ USB_DEVICE_WACOM(0x12) },
|
||||
{ USB_DEVICE_WACOM(0x13) },
|
||||
{ USB_DEVICE_WACOM(0x14) },
|
||||
{ USB_DEVICE_WACOM(0x15) },
|
||||
{ USB_DEVICE_WACOM(0x16) },
|
||||
{ USB_DEVICE_WACOM(0x17) },
|
||||
{ USB_DEVICE_WACOM(0x18) },
|
||||
{ USB_DEVICE_WACOM(0x19) },
|
||||
{ USB_DEVICE_WACOM(0x60) },
|
||||
{ USB_DEVICE_WACOM(0x61) },
|
||||
{ USB_DEVICE_WACOM(0x62) },
|
||||
{ USB_DEVICE_WACOM(0x63) },
|
||||
{ USB_DEVICE_WACOM(0x64) },
|
||||
{ USB_DEVICE_WACOM(0x65) },
|
||||
{ USB_DEVICE_WACOM(0x69) },
|
||||
{ USB_DEVICE_WACOM(0x20) },
|
||||
{ USB_DEVICE_WACOM(0x21) },
|
||||
{ USB_DEVICE_WACOM(0x22) },
|
||||
{ USB_DEVICE_WACOM(0x23) },
|
||||
{ USB_DEVICE_WACOM(0x24) },
|
||||
{ USB_DEVICE_WACOM(0x30) },
|
||||
{ USB_DEVICE_WACOM(0x31) },
|
||||
{ USB_DEVICE_WACOM(0x32) },
|
||||
{ USB_DEVICE_WACOM(0x33) },
|
||||
{ USB_DEVICE_WACOM(0x34) },
|
||||
{ USB_DEVICE_WACOM(0x35) },
|
||||
{ USB_DEVICE_WACOM(0x37) },
|
||||
{ USB_DEVICE_WACOM(0x38) },
|
||||
{ USB_DEVICE_WACOM(0x39) },
|
||||
{ USB_DEVICE_WACOM(0xC4) },
|
||||
{ USB_DEVICE_WACOM(0xC0) },
|
||||
{ USB_DEVICE_WACOM(0xC2) },
|
||||
{ USB_DEVICE_WACOM(0x03) },
|
||||
{ USB_DEVICE_WACOM(0x41) },
|
||||
{ USB_DEVICE_WACOM(0x42) },
|
||||
{ USB_DEVICE_WACOM(0x43) },
|
||||
{ USB_DEVICE_WACOM(0x44) },
|
||||
{ USB_DEVICE_WACOM(0x45) },
|
||||
{ USB_DEVICE_WACOM(0xB0) },
|
||||
{ USB_DEVICE_WACOM(0xB1) },
|
||||
{ USB_DEVICE_WACOM(0xB2) },
|
||||
{ USB_DEVICE_WACOM(0xB3) },
|
||||
{ USB_DEVICE_WACOM(0xB4) },
|
||||
{ USB_DEVICE_WACOM(0xB5) },
|
||||
{ USB_DEVICE_WACOM(0xB7) },
|
||||
{ USB_DEVICE_WACOM(0xB8) },
|
||||
{ USB_DEVICE_WACOM(0xB9) },
|
||||
{ USB_DEVICE_WACOM(0xBA) },
|
||||
{ USB_DEVICE_WACOM(0xBB) },
|
||||
{ USB_DEVICE_WACOM(0x3F) },
|
||||
{ USB_DEVICE_WACOM(0xC5) },
|
||||
{ USB_DEVICE_WACOM(0xC6) },
|
||||
{ USB_DEVICE_WACOM(0xC7) },
|
||||
{ USB_DEVICE_WACOM(0x90) },
|
||||
{ USB_DEVICE_WACOM(0x93) },
|
||||
{ USB_DEVICE_WACOM(0x9A) },
|
||||
{ USB_DEVICE_WACOM(0x9F) },
|
||||
{ USB_DEVICE_WACOM(0xE2) },
|
||||
{ USB_DEVICE_WACOM(0xE3) },
|
||||
{ USB_DEVICE_WACOM(0x47) },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct usb_device_id wacom_ids[] = {
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x17) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x18) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x19) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x69) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC2) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB8) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB9) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBA) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBB) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC7) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9F) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE2) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE3) },
|
||||
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
|
||||
{ }
|
||||
};
|
||||
|
||||
const struct usb_device_id *get_device_table(void)
|
||||
{
|
||||
const struct usb_device_id *id_table = wacom_ids;
|
||||
|
||||
return id_table;
|
||||
}
|
||||
|
||||
struct wacom_features * get_wacom_feature(const struct usb_device_id *id)
|
||||
{
|
||||
int index = id - wacom_ids;
|
||||
struct wacom_features *wf = &wacom_features[index];
|
||||
|
||||
return wf;
|
||||
}
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, wacom_ids);
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
/* packet length for individual models */
|
||||
#define WACOM_PKGLEN_PENPRTN 7
|
||||
#define WACOM_PKGLEN_GRAPHIRE 8
|
||||
#define WACOM_PKGLEN_BBFUN 9
|
||||
#define WACOM_PKGLEN_INTUOS 10
|
||||
#define WACOM_PKGLEN_BBFUN 9
|
||||
#define WACOM_PKGLEN_INTUOS 10
|
||||
#define WACOM_PKGLEN_PENABLED 8
|
||||
#define WACOM_PKGLEN_TPC1FG 5
|
||||
#define WACOM_PKGLEN_TPC2FG 14
|
||||
#define WACOM_PKGLEN_TPC2FG 14
|
||||
|
||||
/* device IDs */
|
||||
#define STYLUS_DEVICE_ID 0x02
|
||||
|
@ -58,7 +58,7 @@ enum {
|
|||
};
|
||||
|
||||
struct wacom_features {
|
||||
char *name;
|
||||
const char *name;
|
||||
int pktlen;
|
||||
int x_max;
|
||||
int y_max;
|
||||
|
@ -73,11 +73,12 @@ struct wacom_features {
|
|||
};
|
||||
|
||||
struct wacom_wac {
|
||||
char name[64];
|
||||
unsigned char *data;
|
||||
int tool[2];
|
||||
int id[2];
|
||||
__u32 serial[2];
|
||||
struct wacom_features *features;
|
||||
int tool[2];
|
||||
int id[2];
|
||||
__u32 serial[2];
|
||||
struct wacom_features features;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -90,7 +90,6 @@ config TOUCHSCREEN_CORGI
|
|||
tristate "SharpSL (Corgi and Spitz series) touchscreen driver (DEPRECATED)"
|
||||
depends on PXA_SHARPSL
|
||||
select CORGI_SSP_DEPRECATED
|
||||
default y
|
||||
help
|
||||
Say Y here to enable the driver for the touchscreen on the
|
||||
Sharp SL-C7xx and SL-Cxx00 series of PDAs.
|
||||
|
@ -537,6 +536,11 @@ config TOUCHSCREEN_USB_ETT_TC5UH
|
|||
bool "ET&T TC5UH touchscreen controler support" if EMBEDDED
|
||||
depends on TOUCHSCREEN_USB_COMPOSITE
|
||||
|
||||
config TOUCHSCREEN_USB_NEXIO
|
||||
default y
|
||||
bool "NEXIO/iNexio device support" if EMBEDDED
|
||||
depends on TOUCHSCREEN_USB_COMPOSITE
|
||||
|
||||
config TOUCHSCREEN_TOUCHIT213
|
||||
tristate "Sahara TouchIT-213 touchscreen"
|
||||
select SERIO
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/gpio.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/ads7846.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
/*
|
||||
|
@ -85,6 +86,7 @@ struct ads7846 {
|
|||
char name[32];
|
||||
|
||||
struct spi_device *spi;
|
||||
struct regulator *reg;
|
||||
|
||||
#if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE)
|
||||
struct attribute_group *attr_group;
|
||||
|
@ -788,6 +790,8 @@ static void ads7846_disable(struct ads7846 *ts)
|
|||
}
|
||||
}
|
||||
|
||||
regulator_disable(ts->reg);
|
||||
|
||||
/* we know the chip's in lowpower mode since we always
|
||||
* leave it that way after every request
|
||||
*/
|
||||
|
@ -799,6 +803,8 @@ static void ads7846_enable(struct ads7846 *ts)
|
|||
if (!ts->disabled)
|
||||
return;
|
||||
|
||||
regulator_enable(ts->reg);
|
||||
|
||||
ts->disabled = 0;
|
||||
ts->irq_disabled = 0;
|
||||
enable_irq(ts->spi->irq);
|
||||
|
@ -1139,6 +1145,19 @@ static int __devinit ads7846_probe(struct spi_device *spi)
|
|||
|
||||
ts->last_msg = m;
|
||||
|
||||
ts->reg = regulator_get(&spi->dev, "vcc");
|
||||
if (IS_ERR(ts->reg)) {
|
||||
dev_err(&spi->dev, "unable to get regulator: %ld\n",
|
||||
PTR_ERR(ts->reg));
|
||||
goto err_free_gpio;
|
||||
}
|
||||
|
||||
err = regulator_enable(ts->reg);
|
||||
if (err) {
|
||||
dev_err(&spi->dev, "unable to enable regulator: %d\n", err);
|
||||
goto err_put_regulator;
|
||||
}
|
||||
|
||||
if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING,
|
||||
spi->dev.driver->name, ts)) {
|
||||
dev_info(&spi->dev,
|
||||
|
@ -1148,7 +1167,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
|
|||
spi->dev.driver->name, ts);
|
||||
if (err) {
|
||||
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
|
||||
goto err_free_gpio;
|
||||
goto err_disable_regulator;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1180,6 +1199,10 @@ static int __devinit ads7846_probe(struct spi_device *spi)
|
|||
ads784x_hwmon_unregister(spi, ts);
|
||||
err_free_irq:
|
||||
free_irq(spi->irq, ts);
|
||||
err_disable_regulator:
|
||||
regulator_disable(ts->reg);
|
||||
err_put_regulator:
|
||||
regulator_put(ts->reg);
|
||||
err_free_gpio:
|
||||
if (ts->gpio_pendown != -1)
|
||||
gpio_free(ts->gpio_pendown);
|
||||
|
@ -1208,6 +1231,9 @@ static int __devexit ads7846_remove(struct spi_device *spi)
|
|||
/* suspend left the IRQ disabled */
|
||||
enable_irq(ts->spi->irq);
|
||||
|
||||
regulator_disable(ts->reg);
|
||||
regulator_put(ts->reg);
|
||||
|
||||
if (ts->gpio_pendown != -1)
|
||||
gpio_free(ts->gpio_pendown);
|
||||
|
||||
|
|
|
@ -72,45 +72,49 @@ static void elo_process_data_10(struct elo *elo, unsigned char data)
|
|||
struct input_dev *dev = elo->dev;
|
||||
|
||||
elo->data[elo->idx] = data;
|
||||
switch (elo->idx++) {
|
||||
case 0:
|
||||
elo->csum = 0xaa;
|
||||
if (data != ELO10_LEAD_BYTE) {
|
||||
pr_debug("elo: unsynchronized data: 0x%02x\n", data);
|
||||
elo->idx = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 9:
|
||||
switch (elo->idx++) {
|
||||
case 0:
|
||||
elo->csum = 0xaa;
|
||||
if (data != ELO10_LEAD_BYTE) {
|
||||
dev_dbg(&elo->serio->dev,
|
||||
"unsynchronized data: 0x%02x\n", data);
|
||||
elo->idx = 0;
|
||||
if (data != elo->csum) {
|
||||
pr_debug("elo: bad checksum: 0x%02x, expected 0x%02x\n",
|
||||
data, elo->csum);
|
||||
break;
|
||||
}
|
||||
if (elo->data[1] != elo->expected_packet) {
|
||||
if (elo->data[1] != ELO10_TOUCH_PACKET)
|
||||
pr_debug("elo: unexpected packet: 0x%02x\n",
|
||||
elo->data[1]);
|
||||
break;
|
||||
}
|
||||
if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) {
|
||||
input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]);
|
||||
input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]);
|
||||
if (elo->data[2] & ELO10_PRESSURE)
|
||||
input_report_abs(dev, ABS_PRESSURE,
|
||||
(elo->data[8] << 8) | elo->data[7]);
|
||||
input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH);
|
||||
input_sync(dev);
|
||||
} else if (elo->data[1] == ELO10_ACK_PACKET) {
|
||||
if (elo->data[2] == '0')
|
||||
elo->expected_packet = ELO10_TOUCH_PACKET;
|
||||
complete(&elo->cmd_done);
|
||||
} else {
|
||||
memcpy(elo->response, &elo->data[1], ELO10_PACKET_LEN);
|
||||
elo->expected_packet = ELO10_ACK_PACKET;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 9:
|
||||
elo->idx = 0;
|
||||
if (data != elo->csum) {
|
||||
dev_dbg(&elo->serio->dev,
|
||||
"bad checksum: 0x%02x, expected 0x%02x\n",
|
||||
data, elo->csum);
|
||||
break;
|
||||
}
|
||||
if (elo->data[1] != elo->expected_packet) {
|
||||
if (elo->data[1] != ELO10_TOUCH_PACKET)
|
||||
dev_dbg(&elo->serio->dev,
|
||||
"unexpected packet: 0x%02x\n",
|
||||
elo->data[1]);
|
||||
break;
|
||||
}
|
||||
if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) {
|
||||
input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]);
|
||||
input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]);
|
||||
if (elo->data[2] & ELO10_PRESSURE)
|
||||
input_report_abs(dev, ABS_PRESSURE,
|
||||
(elo->data[8] << 8) | elo->data[7]);
|
||||
input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH);
|
||||
input_sync(dev);
|
||||
} else if (elo->data[1] == ELO10_ACK_PACKET) {
|
||||
if (elo->data[2] == '0')
|
||||
elo->expected_packet = ELO10_TOUCH_PACKET;
|
||||
complete(&elo->cmd_done);
|
||||
} else {
|
||||
memcpy(elo->response, &elo->data[1], ELO10_PACKET_LEN);
|
||||
elo->expected_packet = ELO10_ACK_PACKET;
|
||||
}
|
||||
break;
|
||||
}
|
||||
elo->csum += data;
|
||||
}
|
||||
|
@ -123,42 +127,53 @@ static void elo_process_data_6(struct elo *elo, unsigned char data)
|
|||
|
||||
switch (elo->idx++) {
|
||||
|
||||
case 0: if ((data & 0xc0) != 0xc0) elo->idx = 0; break;
|
||||
case 1: if ((data & 0xc0) != 0x80) elo->idx = 0; break;
|
||||
case 2: if ((data & 0xc0) != 0x40) elo->idx = 0; break;
|
||||
case 0:
|
||||
if ((data & 0xc0) != 0xc0)
|
||||
elo->idx = 0;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (data & 0xc0) {
|
||||
elo->idx = 0;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
if ((data & 0xc0) != 0x80)
|
||||
elo->idx = 0;
|
||||
break;
|
||||
|
||||
input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f));
|
||||
input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f));
|
||||
case 2:
|
||||
if ((data & 0xc0) != 0x40)
|
||||
elo->idx = 0;
|
||||
break;
|
||||
|
||||
if (elo->id == 2) {
|
||||
input_report_key(dev, BTN_TOUCH, 1);
|
||||
input_sync(dev);
|
||||
elo->idx = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (data) {
|
||||
input_sync(dev);
|
||||
elo->idx = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if ((data & 0xf0) == 0) {
|
||||
input_report_abs(dev, ABS_PRESSURE, elo->data[5]);
|
||||
input_report_key(dev, BTN_TOUCH, !!elo->data[5]);
|
||||
}
|
||||
input_sync(dev);
|
||||
case 3:
|
||||
if (data & 0xc0) {
|
||||
elo->idx = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f));
|
||||
input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f));
|
||||
|
||||
if (elo->id == 2) {
|
||||
input_report_key(dev, BTN_TOUCH, 1);
|
||||
input_sync(dev);
|
||||
elo->idx = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (data) {
|
||||
input_sync(dev);
|
||||
elo->idx = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if ((data & 0xf0) == 0) {
|
||||
input_report_abs(dev, ABS_PRESSURE, elo->data[5]);
|
||||
input_report_key(dev, BTN_TOUCH, !!elo->data[5]);
|
||||
}
|
||||
input_sync(dev);
|
||||
elo->idx = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,17 +185,17 @@ static void elo_process_data_3(struct elo *elo, unsigned char data)
|
|||
|
||||
switch (elo->idx++) {
|
||||
|
||||
case 0:
|
||||
if ((data & 0x7f) != 0x01)
|
||||
elo->idx = 0;
|
||||
break;
|
||||
case 2:
|
||||
input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80));
|
||||
input_report_abs(dev, ABS_X, elo->data[1]);
|
||||
input_report_abs(dev, ABS_Y, elo->data[2]);
|
||||
input_sync(dev);
|
||||
case 0:
|
||||
if ((data & 0x7f) != 0x01)
|
||||
elo->idx = 0;
|
||||
break;
|
||||
break;
|
||||
case 2:
|
||||
input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80));
|
||||
input_report_abs(dev, ABS_X, elo->data[1]);
|
||||
input_report_abs(dev, ABS_Y, elo->data[2]);
|
||||
input_sync(dev);
|
||||
elo->idx = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,19 +204,19 @@ static irqreturn_t elo_interrupt(struct serio *serio,
|
|||
{
|
||||
struct elo *elo = serio_get_drvdata(serio);
|
||||
|
||||
switch(elo->id) {
|
||||
case 0:
|
||||
elo_process_data_10(elo, data);
|
||||
break;
|
||||
switch (elo->id) {
|
||||
case 0:
|
||||
elo_process_data_10(elo, data);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
elo_process_data_6(elo, data);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
elo_process_data_6(elo, data);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
elo_process_data_3(elo, data);
|
||||
break;
|
||||
case 3:
|
||||
elo_process_data_3(elo, data);
|
||||
break;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
@ -261,10 +276,10 @@ static int elo_setup_10(struct elo *elo)
|
|||
if (packet[3] & ELO10_PRESSURE)
|
||||
input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0);
|
||||
|
||||
printk(KERN_INFO "elo: %sTouch touchscreen, fw: %02x.%02x, "
|
||||
"features: 0x%02x, controller: 0x%02x\n",
|
||||
elo_types[(packet[1] -'0') & 0x03],
|
||||
packet[5], packet[4], packet[3], packet[7]);
|
||||
dev_info(&elo->serio->dev,
|
||||
"%sTouch touchscreen, fw: %02x.%02x, features: 0x%02x, controller: 0x%02x\n",
|
||||
elo_types[(packet[1] -'0') & 0x03],
|
||||
packet[5], packet[4], packet[3], packet[7]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -330,24 +345,24 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
|
|||
|
||||
switch (elo->id) {
|
||||
|
||||
case 0: /* 10-byte protocol */
|
||||
if (elo_setup_10(elo))
|
||||
goto fail3;
|
||||
case 0: /* 10-byte protocol */
|
||||
if (elo_setup_10(elo))
|
||||
goto fail3;
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 1: /* 6-byte protocol */
|
||||
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0);
|
||||
case 1: /* 6-byte protocol */
|
||||
input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0);
|
||||
|
||||
case 2: /* 4-byte protocol */
|
||||
input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0);
|
||||
break;
|
||||
case 2: /* 4-byte protocol */
|
||||
input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0);
|
||||
break;
|
||||
|
||||
case 3: /* 3-byte protocol */
|
||||
input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0);
|
||||
break;
|
||||
case 3: /* 3-byte protocol */
|
||||
input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0);
|
||||
input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
err = input_register_device(elo->dev);
|
||||
|
|
|
@ -153,6 +153,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm)
|
|||
if (pressure)
|
||||
p = MODR;
|
||||
|
||||
dev_dbg(wm->dev, "Raw coordinates: x=%x, y=%x, p=%x\n",
|
||||
x, y, p);
|
||||
|
||||
/* are samples valid */
|
||||
if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X ||
|
||||
(y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y ||
|
||||
|
|
|
@ -128,27 +128,29 @@ static void touch_timer_fire(unsigned long data)
|
|||
|
||||
down = get_down(data0, data1);
|
||||
|
||||
if (ts.count == (1 << ts.shift)) {
|
||||
ts.xp >>= ts.shift;
|
||||
ts.yp >>= ts.shift;
|
||||
|
||||
dev_dbg(ts.dev, "%s: X=%lu, Y=%lu, count=%d\n",
|
||||
__func__, ts.xp, ts.yp, ts.count);
|
||||
|
||||
input_report_abs(ts.input, ABS_X, ts.xp);
|
||||
input_report_abs(ts.input, ABS_Y, ts.yp);
|
||||
|
||||
input_report_key(ts.input, BTN_TOUCH, 1);
|
||||
input_sync(ts.input);
|
||||
|
||||
ts.xp = 0;
|
||||
ts.yp = 0;
|
||||
ts.count = 0;
|
||||
}
|
||||
|
||||
if (down) {
|
||||
if (ts.count == (1 << ts.shift)) {
|
||||
ts.xp >>= ts.shift;
|
||||
ts.yp >>= ts.shift;
|
||||
|
||||
dev_dbg(ts.dev, "%s: X=%lu, Y=%lu, count=%d\n",
|
||||
__func__, ts.xp, ts.yp, ts.count);
|
||||
|
||||
input_report_abs(ts.input, ABS_X, ts.xp);
|
||||
input_report_abs(ts.input, ABS_Y, ts.yp);
|
||||
|
||||
input_report_key(ts.input, BTN_TOUCH, 1);
|
||||
input_sync(ts.input);
|
||||
|
||||
ts.xp = 0;
|
||||
ts.yp = 0;
|
||||
ts.count = 0;
|
||||
}
|
||||
|
||||
s3c_adc_start(ts.client, 0, 1 << ts.shift);
|
||||
} else {
|
||||
ts.xp = 0;
|
||||
ts.yp = 0;
|
||||
ts.count = 0;
|
||||
|
||||
input_report_key(ts.input, BTN_TOUCH, 0);
|
||||
|
@ -401,6 +403,7 @@ static int s3c2410ts_resume(struct device *dev)
|
|||
struct s3c2410_ts_mach_info *info = pdev->dev.platform_data;
|
||||
|
||||
clk_enable(ts.clock);
|
||||
enable_irq(ts.irq_tc);
|
||||
|
||||
/* Initialise registers */
|
||||
if ((info->delay & 0xffff) > 0)
|
||||
|
|
|
@ -358,7 +358,7 @@ static int __devexit tsc2007_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_device_id tsc2007_idtable[] = {
|
||||
static const struct i2c_device_id tsc2007_idtable[] = {
|
||||
{ "tsc2007", 0 },
|
||||
{ }
|
||||
};
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
* - GoTop Super_Q2/GogoPen/PenPower tablets
|
||||
* - JASTEC USB touch controller/DigiTech DTR-02U
|
||||
* - Zytronic capacitive touchscreen
|
||||
* - NEXIO/iNexio
|
||||
*
|
||||
* Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch>
|
||||
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
|
||||
|
@ -95,6 +96,7 @@ struct usbtouch_device_info {
|
|||
|
||||
int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt);
|
||||
int (*init) (struct usbtouch_usb *usbtouch);
|
||||
void (*exit) (struct usbtouch_usb *usbtouch);
|
||||
};
|
||||
|
||||
/* a usbtouch device */
|
||||
|
@ -104,11 +106,12 @@ struct usbtouch_usb {
|
|||
unsigned char *buffer;
|
||||
int buf_len;
|
||||
struct urb *irq;
|
||||
struct usb_device *udev;
|
||||
struct usb_interface *interface;
|
||||
struct input_dev *input;
|
||||
struct usbtouch_device_info *type;
|
||||
char name[128];
|
||||
char phys[64];
|
||||
void *priv;
|
||||
|
||||
int x, y;
|
||||
int touch, press;
|
||||
|
@ -133,6 +136,7 @@ enum {
|
|||
DEVTYPE_E2I,
|
||||
DEVTYPE_ZYTRONIC,
|
||||
DEVTYPE_TC5UH,
|
||||
DEVTYPE_NEXIO,
|
||||
};
|
||||
|
||||
#define USB_DEVICE_HID_CLASS(vend, prod) \
|
||||
|
@ -144,7 +148,7 @@ enum {
|
|||
.bInterfaceClass = USB_INTERFACE_CLASS_HID, \
|
||||
.bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE
|
||||
|
||||
static struct usb_device_id usbtouch_devices[] = {
|
||||
static const struct usb_device_id usbtouch_devices[] = {
|
||||
#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX
|
||||
/* ignore the HID capable devices, handled by usbhid */
|
||||
{USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE},
|
||||
|
@ -222,6 +226,14 @@ static struct usb_device_id usbtouch_devices[] = {
|
|||
{USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC5UH},
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
|
||||
/* data interface only */
|
||||
{USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00),
|
||||
.driver_info = DEVTYPE_NEXIO},
|
||||
{USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00),
|
||||
.driver_info = DEVTYPE_NEXIO},
|
||||
#endif
|
||||
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -234,8 +246,9 @@ static struct usb_device_id usbtouch_devices[] = {
|
|||
static int e2i_init(struct usbtouch_usb *usbtouch)
|
||||
{
|
||||
int ret;
|
||||
struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
|
||||
|
||||
ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
|
||||
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
0x01, 0x02, 0x0000, 0x0081,
|
||||
NULL, 0, USB_CTRL_SET_TIMEOUT);
|
||||
|
||||
|
@ -344,8 +357,9 @@ static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
|
|||
static int mtouch_init(struct usbtouch_usb *usbtouch)
|
||||
{
|
||||
int ret, i;
|
||||
struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
|
||||
|
||||
ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
|
||||
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
MTOUCHUSB_RESET,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
|
||||
|
@ -356,7 +370,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
|
|||
msleep(150);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
|
||||
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
MTOUCHUSB_ASYNC_REPORT,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
|
||||
|
@ -489,7 +503,7 @@ static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
|
|||
|
||||
static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
|
||||
{
|
||||
struct usb_device *dev = usbtouch->udev;
|
||||
struct usb_device *dev = interface_to_usbdev(usbtouch->interface);
|
||||
int ret = -ENOMEM;
|
||||
unsigned char *buf;
|
||||
|
||||
|
@ -689,6 +703,229 @@ static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* NEXIO Part
|
||||
*/
|
||||
#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
|
||||
|
||||
#define NEXIO_TIMEOUT 5000
|
||||
#define NEXIO_BUFSIZE 1024
|
||||
#define NEXIO_THRESHOLD 50
|
||||
|
||||
struct nexio_priv {
|
||||
struct urb *ack;
|
||||
unsigned char *ack_buf;
|
||||
};
|
||||
|
||||
struct nexio_touch_packet {
|
||||
u8 flags; /* 0xe1 = touch, 0xe1 = release */
|
||||
__be16 data_len; /* total bytes of touch data */
|
||||
__be16 x_len; /* bytes for X axis */
|
||||
__be16 y_len; /* bytes for Y axis */
|
||||
u8 data[];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static unsigned char nexio_ack_pkt[2] = { 0xaa, 0x02 };
|
||||
static unsigned char nexio_init_pkt[4] = { 0x82, 0x04, 0x0a, 0x0f };
|
||||
|
||||
static void nexio_ack_complete(struct urb *urb)
|
||||
{
|
||||
}
|
||||
|
||||
static int nexio_init(struct usbtouch_usb *usbtouch)
|
||||
{
|
||||
struct usb_device *dev = interface_to_usbdev(usbtouch->interface);
|
||||
struct usb_host_interface *interface = usbtouch->interface->cur_altsetting;
|
||||
struct nexio_priv *priv;
|
||||
int ret = -ENOMEM;
|
||||
int actual_len, i;
|
||||
unsigned char *buf;
|
||||
char *firmware_ver = NULL, *device_name = NULL;
|
||||
int input_ep = 0, output_ep = 0;
|
||||
|
||||
/* find first input and output endpoint */
|
||||
for (i = 0; i < interface->desc.bNumEndpoints; i++) {
|
||||
if (!input_ep &&
|
||||
usb_endpoint_dir_in(&interface->endpoint[i].desc))
|
||||
input_ep = interface->endpoint[i].desc.bEndpointAddress;
|
||||
if (!output_ep &&
|
||||
usb_endpoint_dir_out(&interface->endpoint[i].desc))
|
||||
output_ep = interface->endpoint[i].desc.bEndpointAddress;
|
||||
}
|
||||
if (!input_ep || !output_ep)
|
||||
return -ENXIO;
|
||||
|
||||
buf = kmalloc(NEXIO_BUFSIZE, GFP_KERNEL);
|
||||
if (!buf)
|
||||
goto out_buf;
|
||||
|
||||
/* two empty reads */
|
||||
for (i = 0; i < 2; i++) {
|
||||
ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep),
|
||||
buf, NEXIO_BUFSIZE, &actual_len,
|
||||
NEXIO_TIMEOUT);
|
||||
if (ret < 0)
|
||||
goto out_buf;
|
||||
}
|
||||
|
||||
/* send init command */
|
||||
memcpy(buf, nexio_init_pkt, sizeof(nexio_init_pkt));
|
||||
ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, output_ep),
|
||||
buf, sizeof(nexio_init_pkt), &actual_len,
|
||||
NEXIO_TIMEOUT);
|
||||
if (ret < 0)
|
||||
goto out_buf;
|
||||
|
||||
/* read replies */
|
||||
for (i = 0; i < 3; i++) {
|
||||
memset(buf, 0, NEXIO_BUFSIZE);
|
||||
ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep),
|
||||
buf, NEXIO_BUFSIZE, &actual_len,
|
||||
NEXIO_TIMEOUT);
|
||||
if (ret < 0 || actual_len < 1 || buf[1] != actual_len)
|
||||
continue;
|
||||
switch (buf[0]) {
|
||||
case 0x83: /* firmware version */
|
||||
if (!firmware_ver)
|
||||
firmware_ver = kstrdup(&buf[2], GFP_KERNEL);
|
||||
break;
|
||||
case 0x84: /* device name */
|
||||
if (!device_name)
|
||||
device_name = kstrdup(&buf[2], GFP_KERNEL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Nexio device: %s, firmware version: %s\n",
|
||||
device_name, firmware_ver);
|
||||
|
||||
kfree(firmware_ver);
|
||||
kfree(device_name);
|
||||
|
||||
/* prepare ACK URB */
|
||||
ret = -ENOMEM;
|
||||
|
||||
usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL);
|
||||
if (!usbtouch->priv)
|
||||
goto out_buf;
|
||||
|
||||
priv = usbtouch->priv;
|
||||
|
||||
priv->ack_buf = kmalloc(sizeof(nexio_ack_pkt), GFP_KERNEL);
|
||||
if (!priv->ack_buf)
|
||||
goto err_priv;
|
||||
|
||||
memcpy(priv->ack_buf, nexio_ack_pkt, sizeof(nexio_ack_pkt));
|
||||
|
||||
priv->ack = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!priv->ack) {
|
||||
dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__);
|
||||
goto err_ack_buf;
|
||||
}
|
||||
|
||||
usb_fill_bulk_urb(priv->ack, dev, usb_sndbulkpipe(dev, output_ep),
|
||||
priv->ack_buf, sizeof(nexio_ack_pkt),
|
||||
nexio_ack_complete, usbtouch);
|
||||
ret = 0;
|
||||
goto out_buf;
|
||||
|
||||
err_ack_buf:
|
||||
kfree(priv->ack_buf);
|
||||
err_priv:
|
||||
kfree(priv);
|
||||
out_buf:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void nexio_exit(struct usbtouch_usb *usbtouch)
|
||||
{
|
||||
struct nexio_priv *priv = usbtouch->priv;
|
||||
|
||||
usb_kill_urb(priv->ack);
|
||||
usb_free_urb(priv->ack);
|
||||
kfree(priv->ack_buf);
|
||||
kfree(priv);
|
||||
}
|
||||
|
||||
static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt)
|
||||
{
|
||||
int x, y, begin_x, begin_y, end_x, end_y, w, h, ret;
|
||||
struct nexio_touch_packet *packet = (void *) pkt;
|
||||
struct nexio_priv *priv = usbtouch->priv;
|
||||
|
||||
/* got touch data? */
|
||||
if ((pkt[0] & 0xe0) != 0xe0)
|
||||
return 0;
|
||||
|
||||
/* send ACK */
|
||||
ret = usb_submit_urb(priv->ack, GFP_ATOMIC);
|
||||
|
||||
if (!usbtouch->type->max_xc) {
|
||||
usbtouch->type->max_xc = 2 * be16_to_cpu(packet->x_len);
|
||||
input_set_abs_params(usbtouch->input, ABS_X, 0,
|
||||
2 * be16_to_cpu(packet->x_len), 0, 0);
|
||||
usbtouch->type->max_yc = 2 * be16_to_cpu(packet->y_len);
|
||||
input_set_abs_params(usbtouch->input, ABS_Y, 0,
|
||||
2 * be16_to_cpu(packet->y_len), 0, 0);
|
||||
}
|
||||
/*
|
||||
* The device reports state of IR sensors on X and Y axes.
|
||||
* Each byte represents "darkness" percentage (0-100) of one element.
|
||||
* 17" touchscreen reports only 64 x 52 bytes so the resolution is low.
|
||||
* This also means that there's a limited multi-touch capability but
|
||||
* it's disabled (and untested) here as there's no X driver for that.
|
||||
*/
|
||||
begin_x = end_x = begin_y = end_y = -1;
|
||||
for (x = 0; x < be16_to_cpu(packet->x_len); x++) {
|
||||
if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) {
|
||||
begin_x = x;
|
||||
continue;
|
||||
}
|
||||
if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) {
|
||||
end_x = x - 1;
|
||||
for (y = be16_to_cpu(packet->x_len);
|
||||
y < be16_to_cpu(packet->data_len); y++) {
|
||||
if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) {
|
||||
begin_y = y - be16_to_cpu(packet->x_len);
|
||||
continue;
|
||||
}
|
||||
if (end_y == -1 &&
|
||||
begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) {
|
||||
end_y = y - 1 - be16_to_cpu(packet->x_len);
|
||||
w = end_x - begin_x;
|
||||
h = end_y - begin_y;
|
||||
#if 0
|
||||
/* multi-touch */
|
||||
input_report_abs(usbtouch->input,
|
||||
ABS_MT_TOUCH_MAJOR, max(w,h));
|
||||
input_report_abs(usbtouch->input,
|
||||
ABS_MT_TOUCH_MINOR, min(x,h));
|
||||
input_report_abs(usbtouch->input,
|
||||
ABS_MT_POSITION_X, 2*begin_x+w);
|
||||
input_report_abs(usbtouch->input,
|
||||
ABS_MT_POSITION_Y, 2*begin_y+h);
|
||||
input_report_abs(usbtouch->input,
|
||||
ABS_MT_ORIENTATION, w > h);
|
||||
input_mt_sync(usbtouch->input);
|
||||
#endif
|
||||
/* single touch */
|
||||
usbtouch->x = 2 * begin_x + w;
|
||||
usbtouch->y = 2 * begin_y + h;
|
||||
usbtouch->touch = packet->flags & 0x01;
|
||||
begin_y = end_y = -1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
begin_x = end_x = -1;
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* the different device descriptors
|
||||
*/
|
||||
|
@ -873,6 +1110,16 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
|
|||
.read_data = tc5uh_read_data,
|
||||
},
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO
|
||||
[DEVTYPE_NEXIO] = {
|
||||
.rept_size = 128,
|
||||
.irq_always = true,
|
||||
.read_data = nexio_read_data,
|
||||
.init = nexio_init,
|
||||
.exit = nexio_exit,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -998,6 +1245,7 @@ static void usbtouch_irq(struct urb *urb)
|
|||
case -ECONNRESET:
|
||||
case -ENOENT:
|
||||
case -ESHUTDOWN:
|
||||
case -EPIPE:
|
||||
/* this urb is terminated, clean up */
|
||||
dbg("%s - urb shutting down with status: %d",
|
||||
__func__, urb->status);
|
||||
|
@ -1021,7 +1269,7 @@ static int usbtouch_open(struct input_dev *input)
|
|||
{
|
||||
struct usbtouch_usb *usbtouch = input_get_drvdata(input);
|
||||
|
||||
usbtouch->irq->dev = usbtouch->udev;
|
||||
usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface);
|
||||
|
||||
if (!usbtouch->type->irq_always) {
|
||||
if (usb_submit_urb(usbtouch->irq, GFP_KERNEL))
|
||||
|
@ -1048,13 +1296,23 @@ static void usbtouch_free_buffers(struct usb_device *udev,
|
|||
kfree(usbtouch->buffer);
|
||||
}
|
||||
|
||||
static struct usb_endpoint_descriptor *
|
||||
usbtouch_get_input_endpoint(struct usb_host_interface *interface)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < interface->desc.bNumEndpoints; i++)
|
||||
if (usb_endpoint_dir_in(&interface->endpoint[i].desc))
|
||||
return &interface->endpoint[i].desc;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int usbtouch_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct usbtouch_usb *usbtouch;
|
||||
struct input_dev *input_dev;
|
||||
struct usb_host_interface *interface;
|
||||
struct usb_endpoint_descriptor *endpoint;
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
struct usbtouch_device_info *type;
|
||||
|
@ -1064,8 +1322,9 @@ static int usbtouch_probe(struct usb_interface *intf,
|
|||
if (id->driver_info == DEVTYPE_IGNORE)
|
||||
return -ENODEV;
|
||||
|
||||
interface = intf->cur_altsetting;
|
||||
endpoint = &interface->endpoint[0].desc;
|
||||
endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting);
|
||||
if (!endpoint)
|
||||
return -ENXIO;
|
||||
|
||||
usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
|
@ -1094,7 +1353,7 @@ static int usbtouch_probe(struct usb_interface *intf,
|
|||
goto out_free_buffers;
|
||||
}
|
||||
|
||||
usbtouch->udev = udev;
|
||||
usbtouch->interface = intf;
|
||||
usbtouch->input = input_dev;
|
||||
|
||||
if (udev->manufacturer)
|
||||
|
@ -1133,12 +1392,18 @@ static int usbtouch_probe(struct usb_interface *intf,
|
|||
input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press,
|
||||
type->max_press, 0, 0);
|
||||
|
||||
usb_fill_int_urb(usbtouch->irq, usbtouch->udev,
|
||||
usb_rcvintpipe(usbtouch->udev, endpoint->bEndpointAddress),
|
||||
if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT)
|
||||
usb_fill_int_urb(usbtouch->irq, udev,
|
||||
usb_rcvintpipe(udev, endpoint->bEndpointAddress),
|
||||
usbtouch->data, type->rept_size,
|
||||
usbtouch_irq, usbtouch, endpoint->bInterval);
|
||||
else
|
||||
usb_fill_bulk_urb(usbtouch->irq, udev,
|
||||
usb_rcvbulkpipe(udev, endpoint->bEndpointAddress),
|
||||
usbtouch->data, type->rept_size,
|
||||
usbtouch_irq, usbtouch);
|
||||
|
||||
usbtouch->irq->dev = usbtouch->udev;
|
||||
usbtouch->irq->dev = udev;
|
||||
usbtouch->irq->transfer_dma = usbtouch->data_dma;
|
||||
usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
|
||||
|
@ -1147,23 +1412,37 @@ static int usbtouch_probe(struct usb_interface *intf,
|
|||
err = type->init(usbtouch);
|
||||
if (err) {
|
||||
dbg("%s - type->init() failed, err: %d", __func__, err);
|
||||
goto out_free_buffers;
|
||||
goto out_free_urb;
|
||||
}
|
||||
}
|
||||
|
||||
err = input_register_device(usbtouch->input);
|
||||
if (err) {
|
||||
dbg("%s - input_register_device failed, err: %d", __func__, err);
|
||||
goto out_free_buffers;
|
||||
goto out_do_exit;
|
||||
}
|
||||
|
||||
usb_set_intfdata(intf, usbtouch);
|
||||
|
||||
if (usbtouch->type->irq_always)
|
||||
usb_submit_urb(usbtouch->irq, GFP_KERNEL);
|
||||
if (usbtouch->type->irq_always) {
|
||||
err = usb_submit_urb(usbtouch->irq, GFP_KERNEL);
|
||||
if (err) {
|
||||
err("%s - usb_submit_urb failed with result: %d",
|
||||
__func__, err);
|
||||
goto out_unregister_input;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_unregister_input:
|
||||
input_unregister_device(input_dev);
|
||||
input_dev = NULL;
|
||||
out_do_exit:
|
||||
if (type->exit)
|
||||
type->exit(usbtouch);
|
||||
out_free_urb:
|
||||
usb_free_urb(usbtouch->irq);
|
||||
out_free_buffers:
|
||||
usbtouch_free_buffers(udev, usbtouch);
|
||||
out_free:
|
||||
|
@ -1186,6 +1465,8 @@ static void usbtouch_disconnect(struct usb_interface *intf)
|
|||
/* this will stop IO via close */
|
||||
input_unregister_device(usbtouch->input);
|
||||
usb_free_urb(usbtouch->irq);
|
||||
if (usbtouch->type->exit)
|
||||
usbtouch->type->exit(usbtouch);
|
||||
usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch);
|
||||
kfree(usbtouch);
|
||||
}
|
||||
|
|
|
@ -118,6 +118,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm)
|
|||
if (pressure)
|
||||
p = MODR;
|
||||
|
||||
dev_dbg(wm->dev, "Raw coordinates: x=%x, y=%x, p=%x\n",
|
||||
x, y, p);
|
||||
|
||||
/* are samples valid */
|
||||
if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X ||
|
||||
(y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y ||
|
||||
|
|
|
@ -321,7 +321,7 @@ InitWait:
|
|||
}
|
||||
}
|
||||
|
||||
static struct xenbus_device_id xenkbd_ids[] = {
|
||||
static const struct xenbus_device_id xenkbd_ids[] = {
|
||||
{ "vkbd" },
|
||||
{ "" }
|
||||
};
|
||||
|
|
|
@ -171,8 +171,8 @@ config INPUT_ADBHID
|
|||
If unsure, say Y.
|
||||
|
||||
config MAC_EMUMOUSEBTN
|
||||
bool "Support for mouse button 2+3 emulation"
|
||||
select INPUT
|
||||
tristate "Support for mouse button 2+3 emulation"
|
||||
depends on SYSCTL && INPUT
|
||||
help
|
||||
This provides generic support for emulating the 2nd and 3rd mouse
|
||||
button with keypresses. If you say Y here, the emulation is still
|
||||
|
@ -184,6 +184,9 @@ config MAC_EMUMOUSEBTN
|
|||
|
||||
If you have an Apple machine with a 1-button mouse, say Y here.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called mac_hid.
|
||||
|
||||
config THERM_WINDTUNNEL
|
||||
tristate "Support for thermal management on Windtunnel G4s"
|
||||
depends on I2C && I2C_POWERMAC && PPC_PMAC && !PPC_PMAC64
|
||||
|
|
|
@ -13,17 +13,197 @@
|
|||
#include <linux/sysctl.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kbd_kern.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static struct input_dev *emumousebtn;
|
||||
static int emumousebtn_input_register(void);
|
||||
static int mouse_emulate_buttons;
|
||||
static int mouse_button2_keycode = KEY_RIGHTCTRL; /* right control key */
|
||||
static int mouse_button3_keycode = KEY_RIGHTALT; /* right option key */
|
||||
static int mouse_last_keycode;
|
||||
|
||||
#if defined(CONFIG_SYSCTL)
|
||||
static struct input_dev *mac_hid_emumouse_dev;
|
||||
|
||||
static int mac_hid_create_emumouse(void)
|
||||
{
|
||||
static struct lock_class_key mac_hid_emumouse_dev_event_class;
|
||||
static struct lock_class_key mac_hid_emumouse_dev_mutex_class;
|
||||
int err;
|
||||
|
||||
mac_hid_emumouse_dev = input_allocate_device();
|
||||
if (!mac_hid_emumouse_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
lockdep_set_class(&mac_hid_emumouse_dev->event_lock,
|
||||
&mac_hid_emumouse_dev_event_class);
|
||||
lockdep_set_class(&mac_hid_emumouse_dev->mutex,
|
||||
&mac_hid_emumouse_dev_mutex_class);
|
||||
|
||||
mac_hid_emumouse_dev->name = "Macintosh mouse button emulation";
|
||||
mac_hid_emumouse_dev->id.bustype = BUS_ADB;
|
||||
mac_hid_emumouse_dev->id.vendor = 0x0001;
|
||||
mac_hid_emumouse_dev->id.product = 0x0001;
|
||||
mac_hid_emumouse_dev->id.version = 0x0100;
|
||||
|
||||
mac_hid_emumouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
|
||||
mac_hid_emumouse_dev->keybit[BIT_WORD(BTN_MOUSE)] =
|
||||
BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
|
||||
mac_hid_emumouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
|
||||
|
||||
err = input_register_device(mac_hid_emumouse_dev);
|
||||
if (err) {
|
||||
input_free_device(mac_hid_emumouse_dev);
|
||||
mac_hid_emumouse_dev = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mac_hid_destroy_emumouse(void)
|
||||
{
|
||||
input_unregister_device(mac_hid_emumouse_dev);
|
||||
mac_hid_emumouse_dev = NULL;
|
||||
}
|
||||
|
||||
static bool mac_hid_emumouse_filter(struct input_handle *handle,
|
||||
unsigned int type, unsigned int code,
|
||||
int value)
|
||||
{
|
||||
unsigned int btn;
|
||||
|
||||
if (type != EV_KEY)
|
||||
return false;
|
||||
|
||||
if (code == mouse_button2_keycode)
|
||||
btn = BTN_MIDDLE;
|
||||
else if (code == mouse_button3_keycode)
|
||||
btn = BTN_RIGHT;
|
||||
else
|
||||
return false;
|
||||
|
||||
input_report_key(mac_hid_emumouse_dev, btn, value);
|
||||
input_sync(mac_hid_emumouse_dev);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int mac_hid_emumouse_connect(struct input_handler *handler,
|
||||
struct input_dev *dev,
|
||||
const struct input_device_id *id)
|
||||
{
|
||||
struct input_handle *handle;
|
||||
int error;
|
||||
|
||||
/* Don't bind to ourselves */
|
||||
if (dev == mac_hid_emumouse_dev)
|
||||
return -ENODEV;
|
||||
|
||||
handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
|
||||
if (!handle)
|
||||
return -ENOMEM;
|
||||
|
||||
handle->dev = dev;
|
||||
handle->handler = handler;
|
||||
handle->name = "mac-button-emul";
|
||||
|
||||
error = input_register_handle(handle);
|
||||
if (error) {
|
||||
printk(KERN_ERR
|
||||
"mac_hid: Failed to register button emulation handle, "
|
||||
"error %d\n", error);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
error = input_open_device(handle);
|
||||
if (error) {
|
||||
printk(KERN_ERR
|
||||
"mac_hid: Failed to open input device, error %d\n",
|
||||
error);
|
||||
goto err_unregister;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister:
|
||||
input_unregister_handle(handle);
|
||||
err_free:
|
||||
kfree(handle);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void mac_hid_emumouse_disconnect(struct input_handle *handle)
|
||||
{
|
||||
input_close_device(handle);
|
||||
input_unregister_handle(handle);
|
||||
kfree(handle);
|
||||
}
|
||||
|
||||
static const struct input_device_id mac_hid_emumouse_ids[] = {
|
||||
{
|
||||
.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
|
||||
.evbit = { BIT_MASK(EV_KEY) },
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(input, mac_hid_emumouse_ids);
|
||||
|
||||
static struct input_handler mac_hid_emumouse_handler = {
|
||||
.filter = mac_hid_emumouse_filter,
|
||||
.connect = mac_hid_emumouse_connect,
|
||||
.disconnect = mac_hid_emumouse_disconnect,
|
||||
.name = "mac-button-emul",
|
||||
.id_table = mac_hid_emumouse_ids,
|
||||
};
|
||||
|
||||
static int mac_hid_start_emulation(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mac_hid_create_emumouse();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = input_register_handler(&mac_hid_emumouse_handler);
|
||||
if (err) {
|
||||
mac_hid_destroy_emumouse();
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mac_hid_stop_emulation(void)
|
||||
{
|
||||
input_unregister_handler(&mac_hid_emumouse_handler);
|
||||
mac_hid_destroy_emumouse();
|
||||
}
|
||||
|
||||
static int mac_hid_toggle_emumouse(ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
{
|
||||
int *valp = table->data;
|
||||
int old_val = *valp;
|
||||
int rc;
|
||||
|
||||
rc = proc_dointvec(table, write, buffer, lenp, ppos);
|
||||
|
||||
if (rc == 0 && write && *valp != old_val) {
|
||||
if (*valp == 1)
|
||||
rc = mac_hid_start_emulation();
|
||||
else if (*valp == 0)
|
||||
mac_hid_stop_emulation();
|
||||
else
|
||||
rc = -EINVAL;
|
||||
}
|
||||
|
||||
/* Restore the old value in case of error */
|
||||
if (rc)
|
||||
*valp = old_val;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* file(s) in /proc/sys/dev/mac_hid */
|
||||
static ctl_table mac_hid_files[] = {
|
||||
{
|
||||
|
@ -31,7 +211,7 @@ static ctl_table mac_hid_files[] = {
|
|||
.data = &mouse_emulate_buttons,
|
||||
.maxlen = sizeof(int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec,
|
||||
.proc_handler = mac_hid_toggle_emumouse,
|
||||
},
|
||||
{
|
||||
.procname = "mouse_button2_keycode",
|
||||
|
@ -74,75 +254,21 @@ static ctl_table mac_hid_root_dir[] = {
|
|||
|
||||
static struct ctl_table_header *mac_hid_sysctl_header;
|
||||
|
||||
#endif /* endif CONFIG_SYSCTL */
|
||||
|
||||
int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down)
|
||||
{
|
||||
switch (caller) {
|
||||
case 1:
|
||||
/* Called from keyboard.c */
|
||||
if (mouse_emulate_buttons
|
||||
&& (keycode == mouse_button2_keycode
|
||||
|| keycode == mouse_button3_keycode)) {
|
||||
if (mouse_emulate_buttons == 1) {
|
||||
input_report_key(emumousebtn,
|
||||
keycode == mouse_button2_keycode ? BTN_MIDDLE : BTN_RIGHT,
|
||||
down);
|
||||
input_sync(emumousebtn);
|
||||
return 1;
|
||||
}
|
||||
mouse_last_keycode = down ? keycode : 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct lock_class_key emumousebtn_event_class;
|
||||
static struct lock_class_key emumousebtn_mutex_class;
|
||||
|
||||
static int emumousebtn_input_register(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
emumousebtn = input_allocate_device();
|
||||
if (!emumousebtn)
|
||||
return -ENOMEM;
|
||||
|
||||
lockdep_set_class(&emumousebtn->event_lock, &emumousebtn_event_class);
|
||||
lockdep_set_class(&emumousebtn->mutex, &emumousebtn_mutex_class);
|
||||
|
||||
emumousebtn->name = "Macintosh mouse button emulation";
|
||||
emumousebtn->id.bustype = BUS_ADB;
|
||||
emumousebtn->id.vendor = 0x0001;
|
||||
emumousebtn->id.product = 0x0001;
|
||||
emumousebtn->id.version = 0x0100;
|
||||
|
||||
emumousebtn->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
|
||||
emumousebtn->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
|
||||
BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
|
||||
emumousebtn->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
|
||||
|
||||
ret = input_register_device(emumousebtn);
|
||||
if (ret)
|
||||
input_free_device(emumousebtn);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init mac_hid_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = emumousebtn_input_register();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
#if defined(CONFIG_SYSCTL)
|
||||
mac_hid_sysctl_header = register_sysctl_table(mac_hid_root_dir);
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
if (!mac_hid_sysctl_header)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(mac_hid_init);
|
||||
|
||||
device_initcall(mac_hid_init);
|
||||
static void __exit mac_hid_exit(void)
|
||||
{
|
||||
unregister_sysctl_table(mac_hid_sysctl_header);
|
||||
|
||||
if (mouse_emulate_buttons)
|
||||
mac_hid_stop_emulation();
|
||||
}
|
||||
module_exit(mac_hid_exit);
|
||||
|
|
|
@ -46,7 +46,6 @@ struct gameport {
|
|||
struct mutex drv_mutex; /* protects serio->drv so attributes can pin driver */
|
||||
|
||||
struct device dev;
|
||||
unsigned int registered; /* port has been fully registered with driver core */
|
||||
|
||||
struct list_head node;
|
||||
};
|
||||
|
|
|
@ -10,6 +10,7 @@ struct gpio_keys_button {
|
|||
int type; /* input event type (EV_KEY, EV_SW) */
|
||||
int wakeup; /* configure the button as a wake-up source */
|
||||
int debounce_interval; /* debounce ticks interval in msecs */
|
||||
bool can_disable;
|
||||
};
|
||||
|
||||
struct gpio_keys_platform_data {
|
||||
|
|
|
@ -378,7 +378,7 @@ struct input_absinfo {
|
|||
#define KEY_WIMAX 246
|
||||
#define KEY_RFKILL 247 /* Key that controls all radios */
|
||||
|
||||
/* Range 248 - 255 is reserved for special needs of AT keyboard driver */
|
||||
/* Code 255 is reserved for special needs of AT keyboard driver */
|
||||
|
||||
#define BTN_MISC 0x100
|
||||
#define BTN_0 0x100
|
||||
|
@ -597,6 +597,7 @@ struct input_absinfo {
|
|||
#define KEY_NUMERIC_POUND 0x20b
|
||||
|
||||
#define KEY_CAMERA_FOCUS 0x210
|
||||
#define KEY_WPS_BUTTON 0x211 /* WiFi Protected Setup key */
|
||||
|
||||
#define BTN_TRIGGER_HAPPY 0x2c0
|
||||
#define BTN_TRIGGER_HAPPY1 0x2c0
|
||||
|
@ -1242,6 +1243,10 @@ struct input_handle;
|
|||
* @event: event handler. This method is being called by input core with
|
||||
* interrupts disabled and dev->event_lock spinlock held and so
|
||||
* it may not sleep
|
||||
* @filter: similar to @event; separates normal event handlers from
|
||||
* "filters".
|
||||
* @match: called after comparing device's id with handler's id_table
|
||||
* to perform fine-grained matching between device and handler
|
||||
* @connect: called when attaching a handler to an input device
|
||||
* @disconnect: disconnects a handler from input device
|
||||
* @start: starts handler for given handle. This function is called by
|
||||
|
@ -1253,8 +1258,6 @@ struct input_handle;
|
|||
* @name: name of the handler, to be shown in /proc/bus/input/handlers
|
||||
* @id_table: pointer to a table of input_device_ids this driver can
|
||||
* handle
|
||||
* @blacklist: pointer to a table of input_device_ids this driver should
|
||||
* ignore even if they match @id_table
|
||||
* @h_list: list of input handles associated with the handler
|
||||
* @node: for placing the driver onto input_handler_list
|
||||
*
|
||||
|
@ -1263,6 +1266,11 @@ struct input_handle;
|
|||
* same time. All of them will get their copy of input event generated by
|
||||
* the device.
|
||||
*
|
||||
* The very same structure is used to implement input filters. Input core
|
||||
* allows filters to run first and will not pass event to regular handlers
|
||||
* if any of the filters indicate that the event should be filtered (by
|
||||
* returning %true from their filter() method).
|
||||
*
|
||||
* Note that input core serializes calls to connect() and disconnect()
|
||||
* methods.
|
||||
*/
|
||||
|
@ -1271,6 +1279,8 @@ struct input_handler {
|
|||
void *private;
|
||||
|
||||
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
|
||||
bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
|
||||
bool (*match)(struct input_handler *handler, struct input_dev *dev);
|
||||
int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
|
||||
void (*disconnect)(struct input_handle *handle);
|
||||
void (*start)(struct input_handle *handle);
|
||||
|
@ -1280,7 +1290,6 @@ struct input_handler {
|
|||
const char *name;
|
||||
|
||||
const struct input_device_id *id_table;
|
||||
const struct input_device_id *blacklist;
|
||||
|
||||
struct list_head h_list;
|
||||
struct list_head node;
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
#ifndef __SH_KEYSC_H__
|
||||
#define __SH_KEYSC_H__
|
||||
|
||||
#define SH_KEYSC_MAXKEYS 30
|
||||
#define SH_KEYSC_MAXKEYS 49
|
||||
|
||||
struct sh_keysc_info {
|
||||
enum { SH_KEYSC_MODE_1, SH_KEYSC_MODE_2, SH_KEYSC_MODE_3 } mode;
|
||||
enum { SH_KEYSC_MODE_1, SH_KEYSC_MODE_2, SH_KEYSC_MODE_3,
|
||||
SH_KEYSC_MODE_4, SH_KEYSC_MODE_5, SH_KEYSC_MODE_6 } mode;
|
||||
int scan_timing; /* 0 -> 7, see KYCR1, SCN[2:0] */
|
||||
int delay;
|
||||
int kycr2_delay;
|
||||
int keycodes[SH_KEYSC_MAXKEYS];
|
||||
int keycodes[SH_KEYSC_MAXKEYS]; /* KEYIN * KEYOUT */
|
||||
};
|
||||
|
||||
#endif /* __SH_KEYSC_H__ */
|
||||
|
|
|
@ -161,7 +161,4 @@ static inline void con_schedule_flip(struct tty_struct *t)
|
|||
schedule_delayed_work(&t->buf.work, 0);
|
||||
}
|
||||
|
||||
/* mac_hid.c */
|
||||
extern int mac_hid_mouse_emulate_buttons(int, unsigned int, int);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,7 +30,6 @@ struct serio {
|
|||
char phys[32];
|
||||
|
||||
bool manual_bind;
|
||||
bool registered; /* port has been fully registered with driver core */
|
||||
|
||||
struct serio_device_id id;
|
||||
|
||||
|
|
Loading…
Reference in New Issue