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: Input: document the multi-touch (MT) protocol Input: add detailed multi-touch finger data report protocol Input: allow certain EV_ABS events to bypass all filtering Input: bcm5974 - add documentation for the driver Input: bcm5974 - augment debug information Input: bcm5974 - Add support for the Macbook 5 (Unibody) Input: bcm5974 - add quad-finger tapping Input: bcm5974 - prepare for a new trackpad header type Input: appletouch - fix DMA to/from stack buffer Input: wacom - fix TabletPC touch bug Input: lifebook - add DMI entry for Fujitsu B-2130 Input: ALPS - add signature for Toshiba Satellite Pro M10 Input: elantech - make sure touchpad is really in absolute mode Input: elantech - provide a workaround for jumpy cursor on firmware 2.34 Input: ucb1400 - use disable_irq_nosync() in irq handler Input: tsc2007 - use disable_irq_nosync() in irq handler Input: sa1111ps2 - use disable_irq_nosync() in irq handlers Input: omap-keypad - use disable_irq_nosync() in irq handler
This commit is contained in:
commit
8c0c3f7ff0
16 changed files with 446 additions and 51 deletions
65
Documentation/input/bcm5974.txt
Normal file
65
Documentation/input/bcm5974.txt
Normal file
|
@ -0,0 +1,65 @@
|
|||
BCM5974 Driver (bcm5974)
|
||||
------------------------
|
||||
Copyright (C) 2008-2009 Henrik Rydberg <rydberg@euromail.se>
|
||||
|
||||
The USB initialization and package decoding was made by Scott Shawcroft as
|
||||
part of the touchd user-space driver project:
|
||||
Copyright (C) 2008 Scott Shawcroft (scott.shawcroft@gmail.com)
|
||||
|
||||
The BCM5974 driver is based on the appletouch driver:
|
||||
Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
|
||||
Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net)
|
||||
Copyright (C) 2005 Stelian Pop (stelian@popies.net)
|
||||
Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
|
||||
Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
|
||||
Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
|
||||
Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch)
|
||||
|
||||
This driver adds support for the multi-touch trackpad on the new Apple
|
||||
Macbook Air and Macbook Pro laptops. It replaces the appletouch driver on
|
||||
those computers, and integrates well with the synaptics driver of the Xorg
|
||||
system.
|
||||
|
||||
Known to work on Macbook Air, Macbook Pro Penryn and the new unibody
|
||||
Macbook 5 and Macbook Pro 5.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The driver loads automatically for the supported usb device ids, and
|
||||
becomes available both as an event device (/dev/input/event*) and as a
|
||||
mouse via the mousedev driver (/dev/input/mice).
|
||||
|
||||
USB Race
|
||||
--------
|
||||
|
||||
The Apple multi-touch trackpads report both mouse and keyboard events via
|
||||
different interfaces of the same usb device. This creates a race condition
|
||||
with the HID driver, which, if not told otherwise, will find the standard
|
||||
HID mouse and keyboard, and claim the whole device. To remedy, the usb
|
||||
product id must be listed in the mouse_ignore list of the hid driver.
|
||||
|
||||
Debug output
|
||||
------------
|
||||
|
||||
To ease the development for new hardware version, verbose packet output can
|
||||
be switched on with the debug kernel module parameter. The range [1-9]
|
||||
yields different levels of verbosity. Example (as root):
|
||||
|
||||
echo -n 9 > /sys/module/bcm5974/parameters/debug
|
||||
|
||||
tail -f /var/log/debug
|
||||
|
||||
echo -n 0 > /sys/module/bcm5974/parameters/debug
|
||||
|
||||
Trivia
|
||||
------
|
||||
|
||||
The driver was developed at the ubuntu forums in June 2008 [1], and now has
|
||||
a more permanent home at bitmath.org [2].
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
[1] http://ubuntuforums.org/showthread.php?t=840040
|
||||
[2] http://http://bitmath.org/code/
|
140
Documentation/input/multi-touch-protocol.txt
Normal file
140
Documentation/input/multi-touch-protocol.txt
Normal file
|
@ -0,0 +1,140 @@
|
|||
Multi-touch (MT) Protocol
|
||||
-------------------------
|
||||
Copyright (C) 2009 Henrik Rydberg <rydberg@euromail.se>
|
||||
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
In order to utilize the full power of the new multi-touch devices, a way to
|
||||
report detailed finger data to user space is needed. This document
|
||||
describes the multi-touch (MT) protocol which allows kernel drivers to
|
||||
report details for an arbitrary number of fingers.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Anonymous finger details are sent sequentially as separate packets of ABS
|
||||
events. Only the ABS_MT events are recognized as part of a finger
|
||||
packet. The end of a packet is marked by calling the input_mt_sync()
|
||||
function, which generates a SYN_MT_REPORT event. The end of multi-touch
|
||||
transfer is marked by calling the usual input_sync() function.
|
||||
|
||||
A set of ABS_MT events with the desired properties is defined. The events
|
||||
are divided into categories, to allow for partial implementation. The
|
||||
minimum set consists of ABS_MT_TOUCH_MAJOR, ABS_MT_POSITION_X and
|
||||
ABS_MT_POSITION_Y, which allows for multiple fingers to be tracked. If the
|
||||
device supports it, the ABS_MT_WIDTH_MAJOR may be used to provide the size
|
||||
of the approaching finger. Anisotropy and direction may be specified with
|
||||
ABS_MT_TOUCH_MINOR, ABS_MT_WIDTH_MINOR and ABS_MT_ORIENTATION. Devices with
|
||||
more granular information may specify general shapes as blobs, i.e., as a
|
||||
sequence of rectangular shapes grouped together by an
|
||||
ABS_MT_BLOB_ID. Finally, the ABS_MT_TOOL_TYPE may be used to specify
|
||||
whether the touching tool is a finger or a pen or something else.
|
||||
|
||||
|
||||
Event Semantics
|
||||
---------------
|
||||
|
||||
The word "contact" is used to describe a tool which is in direct contact
|
||||
with the surface. A finger, a pen or a rubber all classify as contacts.
|
||||
|
||||
ABS_MT_TOUCH_MAJOR
|
||||
|
||||
The length of the major axis of the contact. The length should be given in
|
||||
surface units. If the surface has an X times Y resolution, the largest
|
||||
possible value of ABS_MT_TOUCH_MAJOR is sqrt(X^2 + Y^2), the diagonal.
|
||||
|
||||
ABS_MT_TOUCH_MINOR
|
||||
|
||||
The length, in surface units, of the minor axis of the contact. If the
|
||||
contact is circular, this event can be omitted.
|
||||
|
||||
ABS_MT_WIDTH_MAJOR
|
||||
|
||||
The length, in surface units, of the major axis of the approaching
|
||||
tool. This should be understood as the size of the tool itself. The
|
||||
orientation of the contact and the approaching tool are assumed to be the
|
||||
same.
|
||||
|
||||
ABS_MT_WIDTH_MINOR
|
||||
|
||||
The length, in surface units, of the minor axis of the approaching
|
||||
tool. Omit if circular.
|
||||
|
||||
The above four values can be used to derive additional information about
|
||||
the contact. The ratio ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR approximates
|
||||
the notion of pressure. The fingers of the hand and the palm all have
|
||||
different characteristic widths [1].
|
||||
|
||||
ABS_MT_ORIENTATION
|
||||
|
||||
The orientation of the ellipse. The value should describe half a revolution
|
||||
clockwise around the touch center. The scale of the value is arbitrary, but
|
||||
zero should be returned for an ellipse aligned along the Y axis of the
|
||||
surface. As an example, an index finger placed straight onto the axis could
|
||||
return zero orientation, something negative when twisted to the left, and
|
||||
something positive when twisted to the right. This value can be omitted if
|
||||
the touching object is circular, or if the information is not available in
|
||||
the kernel driver.
|
||||
|
||||
ABS_MT_POSITION_X
|
||||
|
||||
The surface X coordinate of the center of the touching ellipse.
|
||||
|
||||
ABS_MT_POSITION_Y
|
||||
|
||||
The surface Y coordinate of the center of the touching ellipse.
|
||||
|
||||
ABS_MT_TOOL_TYPE
|
||||
|
||||
The type of approaching tool. A lot of kernel drivers cannot distinguish
|
||||
between different tool types, such as a finger or a pen. In such cases, the
|
||||
event should be omitted. The protocol currently supports MT_TOOL_FINGER and
|
||||
MT_TOOL_PEN [2].
|
||||
|
||||
ABS_MT_BLOB_ID
|
||||
|
||||
The BLOB_ID groups several packets together into one arbitrarily shaped
|
||||
contact. This is a low-level anonymous grouping, and should not be confused
|
||||
with the high-level contactID, explained below. Most kernel drivers will
|
||||
not have this capability, and can safely omit the event.
|
||||
|
||||
|
||||
Finger Tracking
|
||||
---------------
|
||||
|
||||
The kernel driver should generate an arbitrary enumeration of the set of
|
||||
anonymous contacts currently on the surface. The order in which the packets
|
||||
appear in the event stream is not important.
|
||||
|
||||
The process of finger tracking, i.e., to assign a unique contactID to each
|
||||
initiated contact on the surface, is left to user space; preferably the
|
||||
multi-touch X driver [3]. In that driver, the contactID stays the same and
|
||||
unique until the contact vanishes (when the finger leaves the surface). The
|
||||
problem of assigning a set of anonymous fingers to a set of identified
|
||||
fingers is a euclidian bipartite matching problem at each event update, and
|
||||
relies on a sufficiently rapid update rate.
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
In order to stay compatible with existing applications, the data
|
||||
reported in a finger packet must not be recognized as single-touch
|
||||
events. In addition, all finger data must bypass input filtering,
|
||||
since subsequent events of the same type refer to different fingers.
|
||||
|
||||
The first kernel driver to utilize the MT protocol is the bcm5974 driver,
|
||||
where examples can be found.
|
||||
|
||||
[1] With the extension ABS_MT_APPROACH_X and ABS_MT_APPROACH_Y, the
|
||||
difference between the contact position and the approaching tool position
|
||||
could be used to derive tilt.
|
||||
[2] The list can of course be extended.
|
||||
[3] The multi-touch X driver is currently in the prototyping stage. At the
|
||||
time of writing (April 2009), the MT protocol is not yet merged, and the
|
||||
prototype implements finger matching, basic mouse support and two-finger
|
||||
scrolling. The project aims at improving the quality of current multi-touch
|
||||
functionality available in the synaptics X driver, and in addition
|
||||
implement more advanced gestures.
|
|
@ -29,6 +29,23 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
#define INPUT_DEVICES 256
|
||||
|
||||
/*
|
||||
* EV_ABS events which should not be cached are listed here.
|
||||
*/
|
||||
static unsigned int input_abs_bypass_init_data[] __initdata = {
|
||||
ABS_MT_TOUCH_MAJOR,
|
||||
ABS_MT_TOUCH_MINOR,
|
||||
ABS_MT_WIDTH_MAJOR,
|
||||
ABS_MT_WIDTH_MINOR,
|
||||
ABS_MT_ORIENTATION,
|
||||
ABS_MT_POSITION_X,
|
||||
ABS_MT_POSITION_Y,
|
||||
ABS_MT_TOOL_TYPE,
|
||||
ABS_MT_BLOB_ID,
|
||||
0
|
||||
};
|
||||
static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)];
|
||||
|
||||
static LIST_HEAD(input_dev_list);
|
||||
static LIST_HEAD(input_handler_list);
|
||||
|
||||
|
@ -161,6 +178,10 @@ static void input_handle_event(struct input_dev *dev,
|
|||
disposition = INPUT_PASS_TO_HANDLERS;
|
||||
}
|
||||
break;
|
||||
case SYN_MT_REPORT:
|
||||
dev->sync = 0;
|
||||
disposition = INPUT_PASS_TO_HANDLERS;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -192,6 +213,11 @@ static void input_handle_event(struct input_dev *dev,
|
|||
case EV_ABS:
|
||||
if (is_event_supported(code, dev->absbit, ABS_MAX)) {
|
||||
|
||||
if (test_bit(code, input_abs_bypass)) {
|
||||
disposition = INPUT_PASS_TO_HANDLERS;
|
||||
break;
|
||||
}
|
||||
|
||||
value = input_defuzz_abs_event(value,
|
||||
dev->abs[code], dev->absfuzz[code]);
|
||||
|
||||
|
@ -1634,10 +1660,20 @@ static const struct file_operations input_fops = {
|
|||
.open = input_open_file,
|
||||
};
|
||||
|
||||
static void __init input_init_abs_bypass(void)
|
||||
{
|
||||
const unsigned int *p;
|
||||
|
||||
for (p = input_abs_bypass_init_data; *p; p++)
|
||||
input_abs_bypass[BIT_WORD(*p)] |= BIT_MASK(*p);
|
||||
}
|
||||
|
||||
static int __init input_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
input_init_abs_bypass();
|
||||
|
||||
err = class_register(&input_class);
|
||||
if (err) {
|
||||
printk(KERN_ERR "input: unable to register input_dev class\n");
|
||||
|
|
|
@ -100,8 +100,20 @@ static irqreturn_t omap_kp_interrupt(int irq, void *dev_id)
|
|||
/* disable keyboard interrupt and schedule for handling */
|
||||
if (cpu_is_omap24xx()) {
|
||||
int i;
|
||||
for (i = 0; i < omap_kp->rows; i++)
|
||||
disable_irq(gpio_to_irq(row_gpios[i]));
|
||||
|
||||
for (i = 0; i < omap_kp->rows; i++) {
|
||||
int gpio_irq = gpio_to_irq(row_gpios[i]);
|
||||
/*
|
||||
* The interrupt which we're currently handling should
|
||||
* be disabled _nosync() to avoid deadlocks waiting
|
||||
* for this handler to complete. All others should
|
||||
* be disabled the regular way for SMP safety.
|
||||
*/
|
||||
if (gpio_irq == irq)
|
||||
disable_irq_nosync(gpio_irq);
|
||||
else
|
||||
disable_irq(gpio_irq);
|
||||
}
|
||||
} else
|
||||
/* disable keyboard interrupt and schedule for handling */
|
||||
omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#define ALPS_FW_BK_2 0x40
|
||||
|
||||
static const struct alps_model_info alps_model_data[] = {
|
||||
{ { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
|
||||
{ { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */
|
||||
{ { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
|
||||
{ { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
|
||||
|
|
|
@ -255,15 +255,22 @@ MODULE_PARM_DESC(debug, "Activate debugging output");
|
|||
*/
|
||||
static int atp_geyser_init(struct usb_device *udev)
|
||||
{
|
||||
char data[8];
|
||||
char *data;
|
||||
int size;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
data = kmalloc(8, GFP_KERNEL);
|
||||
if (!data) {
|
||||
err("Out of memory");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
||||
ATP_GEYSER_MODE_READ_REQUEST_ID,
|
||||
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
ATP_GEYSER_MODE_REQUEST_VALUE,
|
||||
ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
|
||||
ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000);
|
||||
|
||||
if (size != 8) {
|
||||
dprintk("atp_geyser_init: read error\n");
|
||||
|
@ -271,7 +278,8 @@ static int atp_geyser_init(struct usb_device *udev)
|
|||
dprintk("appletouch[%d]: %d\n", i, data[i]);
|
||||
|
||||
err("Failed to read mode from device.");
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* Apply the mode switch */
|
||||
|
@ -281,7 +289,7 @@ static int atp_geyser_init(struct usb_device *udev)
|
|||
ATP_GEYSER_MODE_WRITE_REQUEST_ID,
|
||||
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
|
||||
ATP_GEYSER_MODE_REQUEST_VALUE,
|
||||
ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
|
||||
ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000);
|
||||
|
||||
if (size != 8) {
|
||||
dprintk("atp_geyser_init: write error\n");
|
||||
|
@ -289,9 +297,13 @@ static int atp_geyser_init(struct usb_device *udev)
|
|||
dprintk("appletouch[%d]: %d\n", i, data[i]);
|
||||
|
||||
err("Failed to request geyser raw mode");
|
||||
return -EIO;
|
||||
ret = -EIO;
|
||||
goto out_free;
|
||||
}
|
||||
return 0;
|
||||
ret = 0;
|
||||
out_free:
|
||||
kfree(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -51,6 +51,10 @@
|
|||
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
|
||||
/* Macbook5,1 (unibody), aka wellspring3 */
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237
|
||||
#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238
|
||||
|
||||
#define BCM5974_DEVICE(prod) { \
|
||||
.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
|
||||
|
@ -72,6 +76,10 @@ static const struct usb_device_id bcm5974_table[] = {
|
|||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
|
||||
/* Macbook5,1 */
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO),
|
||||
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
|
||||
/* Terminating entry */
|
||||
{}
|
||||
};
|
||||
|
@ -96,14 +104,23 @@ struct bt_data {
|
|||
u8 rel_y; /* relative y coordinate */
|
||||
};
|
||||
|
||||
/* trackpad header structure */
|
||||
struct tp_header {
|
||||
u8 unknown1[16]; /* constants, timers, etc */
|
||||
u8 fingers; /* number of fingers on trackpad */
|
||||
u8 unknown2[9]; /* constants, timers, etc */
|
||||
/* trackpad header types */
|
||||
enum tp_type {
|
||||
TYPE1, /* plain trackpad */
|
||||
TYPE2 /* button integrated in trackpad */
|
||||
};
|
||||
|
||||
/* trackpad finger structure */
|
||||
/* trackpad finger data offsets, le16-aligned */
|
||||
#define FINGER_TYPE1 (13 * sizeof(__le16))
|
||||
#define FINGER_TYPE2 (15 * sizeof(__le16))
|
||||
|
||||
/* trackpad button data offsets */
|
||||
#define BUTTON_TYPE2 15
|
||||
|
||||
/* list of device capability bits */
|
||||
#define HAS_INTEGRATED_BUTTON 1
|
||||
|
||||
/* trackpad finger structure, le16-aligned */
|
||||
struct tp_finger {
|
||||
__le16 origin; /* zero when switching track finger */
|
||||
__le16 abs_x; /* absolute x coodinate */
|
||||
|
@ -117,13 +134,11 @@ struct tp_finger {
|
|||
__le16 force_minor; /* trackpad force, minor axis? */
|
||||
__le16 unused[3]; /* zeros */
|
||||
__le16 multi; /* one finger: varies, more fingers: constant */
|
||||
};
|
||||
} __attribute__((packed,aligned(2)));
|
||||
|
||||
/* trackpad data structure, empirically at least ten fingers */
|
||||
struct tp_data {
|
||||
struct tp_header header;
|
||||
struct tp_finger finger[16];
|
||||
};
|
||||
/* trackpad finger data size, empirically at least ten fingers */
|
||||
#define SIZEOF_FINGER sizeof(struct tp_finger)
|
||||
#define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER)
|
||||
|
||||
/* device-specific parameters */
|
||||
struct bcm5974_param {
|
||||
|
@ -136,9 +151,12 @@ struct bcm5974_param {
|
|||
/* device-specific configuration */
|
||||
struct bcm5974_config {
|
||||
int ansi, iso, jis; /* the product id of this device */
|
||||
int caps; /* device capability bitmask */
|
||||
int bt_ep; /* the endpoint of the button interface */
|
||||
int bt_datalen; /* data length of the button interface */
|
||||
int tp_ep; /* the endpoint of the trackpad interface */
|
||||
enum tp_type tp_type; /* type of trackpad interface */
|
||||
int tp_offset; /* offset to trackpad finger data */
|
||||
int tp_datalen; /* data length of the trackpad interface */
|
||||
struct bcm5974_param p; /* finger pressure limits */
|
||||
struct bcm5974_param w; /* finger width limits */
|
||||
|
@ -158,7 +176,7 @@ struct bcm5974 {
|
|||
struct urb *bt_urb; /* button usb request block */
|
||||
struct bt_data *bt_data; /* button transferred data */
|
||||
struct urb *tp_urb; /* trackpad usb request block */
|
||||
struct tp_data *tp_data; /* trackpad transferred data */
|
||||
u8 *tp_data; /* trackpad transferred data */
|
||||
int fingers; /* number of fingers on trackpad */
|
||||
};
|
||||
|
||||
|
@ -183,8 +201,9 @@ static const struct bcm5974_config bcm5974_config_table[] = {
|
|||
USB_DEVICE_ID_APPLE_WELLSPRING_ANSI,
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING_ISO,
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING_JIS,
|
||||
0,
|
||||
0x84, sizeof(struct bt_data),
|
||||
0x81, sizeof(struct tp_data),
|
||||
0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
|
||||
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
|
||||
{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
|
||||
{ DIM_X, DIM_X / SN_COORD, -4824, 5342 },
|
||||
|
@ -194,13 +213,26 @@ static const struct bcm5974_config bcm5974_config_table[] = {
|
|||
USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI,
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING2_ISO,
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING2_JIS,
|
||||
0,
|
||||
0x84, sizeof(struct bt_data),
|
||||
0x81, sizeof(struct tp_data),
|
||||
0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
|
||||
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
|
||||
{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
|
||||
{ DIM_X, DIM_X / SN_COORD, -4824, 4824 },
|
||||
{ DIM_Y, DIM_Y / SN_COORD, -172, 4290 }
|
||||
},
|
||||
{
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI,
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING3_ISO,
|
||||
USB_DEVICE_ID_APPLE_WELLSPRING3_JIS,
|
||||
HAS_INTEGRATED_BUTTON,
|
||||
0x84, sizeof(struct bt_data),
|
||||
0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
|
||||
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
|
||||
{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
|
||||
{ DIM_X, DIM_X / SN_COORD, -4460, 5166 },
|
||||
{ DIM_Y, DIM_Y / SN_COORD, -75, 6700 }
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -257,6 +289,7 @@ static void setup_events_to_report(struct input_dev *input_dev,
|
|||
__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
|
||||
__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
|
||||
__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
|
||||
__set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
|
||||
__set_bit(BTN_LEFT, input_dev->keybit);
|
||||
}
|
||||
|
||||
|
@ -266,6 +299,11 @@ static int report_bt_state(struct bcm5974 *dev, int size)
|
|||
if (size != sizeof(struct bt_data))
|
||||
return -EIO;
|
||||
|
||||
dprintk(7,
|
||||
"bcm5974: button data: %x %x %x %x\n",
|
||||
dev->bt_data->unknown1, dev->bt_data->button,
|
||||
dev->bt_data->rel_x, dev->bt_data->rel_y);
|
||||
|
||||
input_report_key(dev->input, BTN_LEFT, dev->bt_data->button);
|
||||
input_sync(dev->input);
|
||||
|
||||
|
@ -276,29 +314,37 @@ static int report_bt_state(struct bcm5974 *dev, int size)
|
|||
static int report_tp_state(struct bcm5974 *dev, int size)
|
||||
{
|
||||
const struct bcm5974_config *c = &dev->cfg;
|
||||
const struct tp_finger *f = dev->tp_data->finger;
|
||||
const struct tp_finger *f;
|
||||
struct input_dev *input = dev->input;
|
||||
const int fingers = (size - 26) / 28;
|
||||
int raw_p, raw_w, raw_x, raw_y;
|
||||
int ptest = 0, origin = 0, nmin = 0, nmax = 0;
|
||||
int raw_p, raw_w, raw_x, raw_y, raw_n;
|
||||
int ptest = 0, origin = 0, ibt = 0, nmin = 0, nmax = 0;
|
||||
int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
|
||||
|
||||
if (size < 26 || (size - 26) % 28 != 0)
|
||||
if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
|
||||
return -EIO;
|
||||
|
||||
/* finger data, le16-aligned */
|
||||
f = (const struct tp_finger *)(dev->tp_data + c->tp_offset);
|
||||
raw_n = (size - c->tp_offset) / SIZEOF_FINGER;
|
||||
|
||||
/* always track the first finger; when detached, start over */
|
||||
if (fingers) {
|
||||
if (raw_n) {
|
||||
raw_p = raw2int(f->force_major);
|
||||
raw_w = raw2int(f->size_major);
|
||||
raw_x = raw2int(f->abs_x);
|
||||
raw_y = raw2int(f->abs_y);
|
||||
|
||||
dprintk(9,
|
||||
"bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n",
|
||||
raw_p, raw_w, raw_x, raw_y);
|
||||
"bcm5974: "
|
||||
"raw: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
|
||||
raw_p, raw_w, raw_x, raw_y, raw_n);
|
||||
|
||||
ptest = int2bound(&c->p, raw_p);
|
||||
origin = raw2int(f->origin);
|
||||
|
||||
/* set the integrated button if applicable */
|
||||
if (c->tp_type == TYPE2)
|
||||
ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
|
||||
}
|
||||
|
||||
/* while tracking finger still valid, count all fingers */
|
||||
|
@ -307,12 +353,13 @@ static int report_tp_state(struct bcm5974 *dev, int size)
|
|||
abs_w = int2bound(&c->w, raw_w);
|
||||
abs_x = int2bound(&c->x, raw_x - c->x.devmin);
|
||||
abs_y = int2bound(&c->y, c->y.devmax - raw_y);
|
||||
for (; f != dev->tp_data->finger + fingers; f++) {
|
||||
while (raw_n--) {
|
||||
ptest = int2bound(&c->p, raw2int(f->force_major));
|
||||
if (ptest > PRESSURE_LOW)
|
||||
nmax++;
|
||||
if (ptest > PRESSURE_HIGH)
|
||||
nmin++;
|
||||
f++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,7 +371,8 @@ static int report_tp_state(struct bcm5974 *dev, int size)
|
|||
input_report_key(input, BTN_TOUCH, dev->fingers > 0);
|
||||
input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1);
|
||||
input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2);
|
||||
input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2);
|
||||
input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3);
|
||||
input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3);
|
||||
|
||||
input_report_abs(input, ABS_PRESSURE, abs_p);
|
||||
input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
|
||||
|
@ -335,11 +383,15 @@ static int report_tp_state(struct bcm5974 *dev, int size)
|
|||
|
||||
dprintk(8,
|
||||
"bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d "
|
||||
"nmin: %d nmax: %d n: %d\n",
|
||||
abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers);
|
||||
"nmin: %d nmax: %d n: %d ibt: %d\n", abs_p, abs_w,
|
||||
abs_x, abs_y, nmin, nmax, dev->fingers, ibt);
|
||||
|
||||
}
|
||||
|
||||
/* type 2 reports button events via ibt only */
|
||||
if (c->tp_type == TYPE2)
|
||||
input_report_key(input, BTN_LEFT, ibt);
|
||||
|
||||
input_sync(input);
|
||||
|
||||
return 0;
|
||||
|
@ -649,6 +701,8 @@ static int bcm5974_probe(struct usb_interface *iface,
|
|||
input_dev->name = "bcm5974";
|
||||
input_dev->phys = dev->phys;
|
||||
usb_to_input_id(dev->udev, &input_dev->id);
|
||||
/* report driver capabilities via the version field */
|
||||
input_dev->id.version = cfg->caps;
|
||||
input_dev->dev.parent = &iface->dev;
|
||||
|
||||
input_set_drvdata(input_dev, dev);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Elantech Touchpad driver (v5)
|
||||
* Elantech Touchpad driver (v6)
|
||||
*
|
||||
* Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net>
|
||||
* Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net>
|
||||
*
|
||||
* 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
|
||||
|
@ -178,6 +178,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
|
|||
struct elantech_data *etd = psmouse->private;
|
||||
unsigned char *packet = psmouse->packet;
|
||||
int fingers;
|
||||
static int old_fingers;
|
||||
|
||||
if (etd->fw_version_maj == 0x01) {
|
||||
/* byte 0: D U p1 p2 1 p3 R L
|
||||
|
@ -190,6 +191,14 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
|
|||
fingers = (packet[0] & 0xc0) >> 6;
|
||||
}
|
||||
|
||||
if (etd->jumpy_cursor) {
|
||||
/* Discard packets that are likely to have bogus coordinates */
|
||||
if (fingers > old_fingers) {
|
||||
elantech_debug("elantech.c: discarding packet\n");
|
||||
goto discard_packet_v1;
|
||||
}
|
||||
}
|
||||
|
||||
input_report_key(dev, BTN_TOUCH, fingers != 0);
|
||||
|
||||
/* byte 2: x7 x6 x5 x4 x3 x2 x1 x0
|
||||
|
@ -216,6 +225,9 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
|
|||
}
|
||||
|
||||
input_sync(dev);
|
||||
|
||||
discard_packet_v1:
|
||||
old_fingers = fingers;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -363,9 +375,14 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
|
|||
rc = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == 0) {
|
||||
/*
|
||||
* Read back reg 0x10. The touchpad is probably initalising
|
||||
* and not ready until we read back the value we just wrote.
|
||||
* Read back reg 0x10. For hardware version 1 we must make
|
||||
* sure the absolute mode bit is set. For hardware version 2
|
||||
* the touchpad is probably initalising and not ready until
|
||||
* we read back the value we just wrote.
|
||||
*/
|
||||
do {
|
||||
rc = elantech_read_reg(psmouse, 0x10, &val);
|
||||
|
@ -376,9 +393,15 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
|
|||
tries);
|
||||
msleep(ETP_READ_BACK_DELAY);
|
||||
} while (tries > 0);
|
||||
if (rc)
|
||||
|
||||
if (rc) {
|
||||
pr_err("elantech.c: failed to read back register 0x10.\n");
|
||||
break;
|
||||
} else if (etd->hw_version == 1 &&
|
||||
!(val & ETP_R10_ABSOLUTE_MODE)) {
|
||||
pr_err("elantech.c: touchpad refuses "
|
||||
"to switch to absolute mode.\n");
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc)
|
||||
|
@ -662,6 +685,17 @@ int elantech_init(struct psmouse *psmouse)
|
|||
param[0], param[1], param[2]);
|
||||
etd->capabilities = param[0];
|
||||
|
||||
/*
|
||||
* This firmware seems to suffer from misreporting coordinates when
|
||||
* a touch action starts causing the mouse cursor or scrolled page
|
||||
* to jump. Enable a workaround.
|
||||
*/
|
||||
if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) {
|
||||
pr_info("elantech.c: firmware version 2.34 detected, "
|
||||
"enabling jumpy cursor workaround\n");
|
||||
etd->jumpy_cursor = 1;
|
||||
}
|
||||
|
||||
if (elantech_set_absolute_mode(psmouse)) {
|
||||
pr_err("elantech.c: failed to put touchpad into absolute mode.\n");
|
||||
goto init_fail;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Elantech Touchpad driver (v5)
|
||||
* Elantech Touchpad driver (v6)
|
||||
*
|
||||
* Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net>
|
||||
* Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net>
|
||||
*
|
||||
* 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
|
||||
|
@ -104,6 +104,7 @@ struct elantech_data {
|
|||
unsigned char fw_version_min;
|
||||
unsigned char hw_version;
|
||||
unsigned char paritycheck;
|
||||
unsigned char jumpy_cursor;
|
||||
unsigned char parity[256];
|
||||
};
|
||||
|
||||
|
|
|
@ -60,6 +60,12 @@ static const struct dmi_system_id lifebook_dmi_table[] = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Lifebook B-2130",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "ZEPHYR"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.ident = "Lifebook B213x/B2150",
|
||||
.matches = {
|
||||
|
|
|
@ -77,7 +77,7 @@ static irqreturn_t ps2_txint(int irq, void *dev_id)
|
|||
spin_lock(&ps2if->lock);
|
||||
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
|
||||
if (ps2if->head == ps2if->tail) {
|
||||
disable_irq(irq);
|
||||
disable_irq_nosync(irq);
|
||||
/* done */
|
||||
} else if (status & PS2STAT_TXE) {
|
||||
sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* Copyright (c) 2000 Daniel Egger <egger@suse.de>
|
||||
* Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
|
||||
* Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
|
||||
* Copyright (c) 2002-2008 Ping Cheng <pingc@wacom.com>
|
||||
* Copyright (c) 2002-2009 Ping Cheng <pingc@wacom.com>
|
||||
*
|
||||
* ChangeLog:
|
||||
* v0.1 (vp) - Initial release
|
||||
|
@ -67,6 +67,7 @@
|
|||
* v1.47 (pc) - Added support for Bamboo
|
||||
* v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX
|
||||
* v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A)
|
||||
* v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -87,7 +88,7 @@
|
|||
/*
|
||||
* Version Information
|
||||
*/
|
||||
#define DRIVER_VERSION "v1.49"
|
||||
#define DRIVER_VERSION "v1.50"
|
||||
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
|
||||
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
|
||||
#define DRIVER_LICENSE "GPL"
|
||||
|
|
|
@ -289,6 +289,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
|
|||
5000); /* 5 secs */
|
||||
} while (result < 0 && limit++ < 5);
|
||||
|
||||
/* No need to parse the Descriptor. It isn't an error though */
|
||||
if (result < 0)
|
||||
goto out;
|
||||
|
||||
|
@ -368,9 +369,8 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
|
|||
}
|
||||
}
|
||||
|
||||
result = 0;
|
||||
|
||||
out:
|
||||
result = 0;
|
||||
kfree(report);
|
||||
return result;
|
||||
}
|
||||
|
@ -425,6 +425,15 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
|
|||
|
||||
endpoint = &intf->cur_altsetting->endpoint[0].desc;
|
||||
|
||||
/* Initialize touch_x_max and touch_y_max in case it is not defined */
|
||||
if (wacom_wac->features->type == TABLETPC) {
|
||||
features->touch_x_max = 1023;
|
||||
features->touch_y_max = 1023;
|
||||
} else {
|
||||
features->touch_x_max = 0;
|
||||
features->touch_y_max = 0;
|
||||
}
|
||||
|
||||
/* TabletPC need to retrieve the physical and logical maximum from report descriptor */
|
||||
if (wacom_wac->features->type == TABLETPC) {
|
||||
if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
|
||||
|
|
|
@ -235,7 +235,7 @@ static irqreturn_t tsc2007_irq(int irq, void *handle)
|
|||
spin_lock_irqsave(&ts->lock, flags);
|
||||
|
||||
if (likely(ts->get_pendown_state())) {
|
||||
disable_irq(ts->irq);
|
||||
disable_irq_nosync(ts->irq);
|
||||
hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
|
|
|
@ -256,7 +256,7 @@ static irqreturn_t ucb1400_hard_irq(int irqnr, void *devid)
|
|||
struct ucb1400_ts *ucb = devid;
|
||||
|
||||
if (irqnr == ucb->irq) {
|
||||
disable_irq(ucb->irq);
|
||||
disable_irq_nosync(ucb->irq);
|
||||
ucb->irq_pending = 1;
|
||||
wake_up(&ucb->ts_wait);
|
||||
return IRQ_HANDLED;
|
||||
|
|
|
@ -106,6 +106,7 @@ struct input_absinfo {
|
|||
|
||||
#define SYN_REPORT 0
|
||||
#define SYN_CONFIG 1
|
||||
#define SYN_MT_REPORT 2
|
||||
|
||||
/*
|
||||
* Keys and buttons
|
||||
|
@ -445,6 +446,7 @@ struct input_absinfo {
|
|||
#define BTN_STYLUS2 0x14c
|
||||
#define BTN_TOOL_DOUBLETAP 0x14d
|
||||
#define BTN_TOOL_TRIPLETAP 0x14e
|
||||
#define BTN_TOOL_QUADTAP 0x14f /* Four fingers on trackpad */
|
||||
|
||||
#define BTN_WHEEL 0x150
|
||||
#define BTN_GEAR_DOWN 0x150
|
||||
|
@ -644,6 +646,17 @@ struct input_absinfo {
|
|||
#define ABS_TOOL_WIDTH 0x1c
|
||||
#define ABS_VOLUME 0x20
|
||||
#define ABS_MISC 0x28
|
||||
|
||||
#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
|
||||
#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
|
||||
#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
|
||||
#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
|
||||
#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
|
||||
#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
|
||||
#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
|
||||
#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
|
||||
#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
|
||||
|
||||
#define ABS_MAX 0x3f
|
||||
#define ABS_CNT (ABS_MAX+1)
|
||||
|
||||
|
@ -742,6 +755,12 @@ struct input_absinfo {
|
|||
#define BUS_GSC 0x1A
|
||||
#define BUS_ATARI 0x1B
|
||||
|
||||
/*
|
||||
* MT_TOOL types
|
||||
*/
|
||||
#define MT_TOOL_FINGER 0
|
||||
#define MT_TOOL_PEN 1
|
||||
|
||||
/*
|
||||
* Values describing the status of a force-feedback effect
|
||||
*/
|
||||
|
@ -1311,6 +1330,11 @@ static inline void input_sync(struct input_dev *dev)
|
|||
input_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
static inline void input_mt_sync(struct input_dev *dev)
|
||||
{
|
||||
input_event(dev, EV_SYN, SYN_MT_REPORT, 0);
|
||||
}
|
||||
|
||||
void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code);
|
||||
|
||||
static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
|
||||
|
|
Loading…
Reference in a new issue