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:
@@ -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);
|
||||
@@ -373,12 +390,18 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
|
||||
break;
|
||||
tries--;
|
||||
elantech_debug("elantech.c: retrying read (%d).\n",
|
||||
tries);
|
||||
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;
|
||||
|
Reference in New Issue
Block a user