Commit 3b3ef308 authored by Linus Torvalds's avatar Linus Torvalds

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: sentelic - fix left/right horizontal scroll mapping
  Input: pmouse - move Sentelic probe down the list
  Input: add compat support for sysfs and /proc capabilities output
  Input: i8042 - add Dritek quirk for Acer Aspire 5610.
  Input: xbox - do not use GFP_KERNEL under spinlock
  Input: psmouse - fix Synaptics detection when protocol is disabled
  Input: bcm5974 - report ABS_MT events
  Input: davinci_keyscan - add device_enable method to platform data
  Input: evdev - be less aggressive about sending SIGIO notifies
  Input: atkbd - fix canceling event_work in disconnect
  Input: serio - fix potential deadlock when unbinding drivers
  Input: gf2k - fix &&/|| confusion in gf2k_connect()
parents 9fc81917 c332e9fc
...@@ -29,6 +29,7 @@ enum davinci_matrix_types { ...@@ -29,6 +29,7 @@ enum davinci_matrix_types {
}; };
struct davinci_ks_platform_data { struct davinci_ks_platform_data {
int (*device_enable)(struct device *dev);
unsigned short *keymap; unsigned short *keymap;
u32 keymapsize; u32 keymapsize;
u8 rep:1; u8 rep:1;
......
...@@ -59,7 +59,8 @@ static void evdev_pass_event(struct evdev_client *client, ...@@ -59,7 +59,8 @@ static void evdev_pass_event(struct evdev_client *client,
client->head &= EVDEV_BUFFER_SIZE - 1; client->head &= EVDEV_BUFFER_SIZE - 1;
spin_unlock(&client->buffer_lock); spin_unlock(&client->buffer_lock);
kill_fasync(&client->fasync, SIGIO, POLL_IN); if (event->type == EV_SYN)
kill_fasync(&client->fasync, SIGIO, POLL_IN);
} }
/* /*
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include "input-compat.h"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("Input core"); MODULE_DESCRIPTION("Input core");
...@@ -764,6 +765,40 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han ...@@ -764,6 +765,40 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han
return error; return error;
} }
#ifdef CONFIG_COMPAT
static int input_bits_to_string(char *buf, int buf_size,
unsigned long bits, bool skip_empty)
{
int len = 0;
if (INPUT_COMPAT_TEST) {
u32 dword = bits >> 32;
if (dword || !skip_empty)
len += snprintf(buf, buf_size, "%x ", dword);
dword = bits & 0xffffffffUL;
if (dword || !skip_empty || len)
len += snprintf(buf + len, max(buf_size - len, 0),
"%x", dword);
} else {
if (bits || !skip_empty)
len += snprintf(buf, buf_size, "%lx", bits);
}
return len;
}
#else /* !CONFIG_COMPAT */
static int input_bits_to_string(char *buf, int buf_size,
unsigned long bits, bool skip_empty)
{
return bits || !skip_empty ?
snprintf(buf, buf_size, "%lx", bits) : 0;
}
#endif
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
...@@ -832,14 +867,25 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name, ...@@ -832,14 +867,25 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
unsigned long *bitmap, int max) unsigned long *bitmap, int max)
{ {
int i; int i;
bool skip_empty = true;
for (i = BITS_TO_LONGS(max) - 1; i > 0; i--) char buf[18];
if (bitmap[i])
break;
seq_printf(seq, "B: %s=", name); seq_printf(seq, "B: %s=", name);
for (; i >= 0; i--)
seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : ""); for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) {
if (input_bits_to_string(buf, sizeof(buf),
bitmap[i], skip_empty)) {
skip_empty = false;
seq_printf(seq, "%s%s", buf, i > 0 ? " " : "");
}
}
/*
* If no output was produced print a single 0.
*/
if (skip_empty)
seq_puts(seq, "0");
seq_putc(seq, '\n'); seq_putc(seq, '\n');
} }
...@@ -1128,14 +1174,23 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, ...@@ -1128,14 +1174,23 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
{ {
int i; int i;
int len = 0; int len = 0;
bool skip_empty = true;
for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) {
len += input_bits_to_string(buf + len, max(buf_size - len, 0),
bitmap[i], skip_empty);
if (len) {
skip_empty = false;
if (i > 0)
len += snprintf(buf + len, max(buf_size - len, 0), " ");
}
}
for (i = BITS_TO_LONGS(max) - 1; i > 0; i--) /*
if (bitmap[i]) * If no output was produced print a single 0.
break; */
if (len == 0)
for (; i >= 0; i--) len = snprintf(buf, buf_size, "%d", 0);
len += snprintf(buf + len, max(buf_size - len, 0),
"%lx%s", bitmap[i], i > 0 ? " " : "");
if (add_cr) if (add_cr)
len += snprintf(buf + len, max(buf_size - len, 0), "\n"); len += snprintf(buf + len, max(buf_size - len, 0), "\n");
...@@ -1150,7 +1205,8 @@ static ssize_t input_dev_show_cap_##bm(struct device *dev, \ ...@@ -1150,7 +1205,8 @@ static ssize_t input_dev_show_cap_##bm(struct device *dev, \
{ \ { \
struct input_dev *input_dev = to_input_dev(dev); \ struct input_dev *input_dev = to_input_dev(dev); \
int len = input_print_bitmap(buf, PAGE_SIZE, \ int len = input_print_bitmap(buf, PAGE_SIZE, \
input_dev->bm##bit, ev##_MAX, 1); \ input_dev->bm##bit, ev##_MAX, \
true); \
return min_t(int, len, PAGE_SIZE); \ return min_t(int, len, PAGE_SIZE); \
} \ } \
static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL) static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL)
...@@ -1214,7 +1270,7 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env, ...@@ -1214,7 +1270,7 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
len = input_print_bitmap(&env->buf[env->buflen - 1], len = input_print_bitmap(&env->buf[env->buflen - 1],
sizeof(env->buf) - env->buflen, sizeof(env->buf) - env->buflen,
bitmap, max, 0); bitmap, max, false);
if (len >= (sizeof(env->buf) - env->buflen)) if (len >= (sizeof(env->buf) - env->buflen))
return -ENOMEM; return -ENOMEM;
......
...@@ -277,7 +277,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) ...@@ -277,7 +277,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
} }
#ifdef RESET_WORKS #ifdef RESET_WORKS
if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) || if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) &&
(gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5)))) { (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5)))) {
err = -ENODEV; err = -ENODEV;
goto fail2; goto fail2;
......
...@@ -446,7 +446,7 @@ static void xpad_irq_in(struct urb *urb) ...@@ -446,7 +446,7 @@ static void xpad_irq_in(struct urb *urb)
} }
exit: exit:
retval = usb_submit_urb (urb, GFP_ATOMIC); retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval) if (retval)
err ("%s - usb_submit_urb failed with result %d", err ("%s - usb_submit_urb failed with result %d",
__func__, retval); __func__, retval);
...@@ -571,7 +571,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, ...@@ -571,7 +571,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
xpad->odata[6] = 0x00; xpad->odata[6] = 0x00;
xpad->odata[7] = 0x00; xpad->odata[7] = 0x00;
xpad->irq_out->transfer_buffer_length = 8; xpad->irq_out->transfer_buffer_length = 8;
usb_submit_urb(xpad->irq_out, GFP_KERNEL); usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
} }
return 0; return 0;
......
...@@ -225,8 +225,10 @@ struct atkbd { ...@@ -225,8 +225,10 @@ struct atkbd {
struct delayed_work event_work; struct delayed_work event_work;
unsigned long event_jiffies; unsigned long event_jiffies;
struct mutex event_mutex;
unsigned long event_mask; unsigned long event_mask;
/* Serializes reconnect(), attr->set() and event work */
struct mutex mutex;
}; };
/* /*
...@@ -577,7 +579,7 @@ static void atkbd_event_work(struct work_struct *work) ...@@ -577,7 +579,7 @@ static void atkbd_event_work(struct work_struct *work)
{ {
struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work); struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work);
mutex_lock(&atkbd->event_mutex); mutex_lock(&atkbd->mutex);
if (!atkbd->enabled) { if (!atkbd->enabled) {
/* /*
...@@ -596,7 +598,7 @@ static void atkbd_event_work(struct work_struct *work) ...@@ -596,7 +598,7 @@ static void atkbd_event_work(struct work_struct *work)
atkbd_set_repeat_rate(atkbd); atkbd_set_repeat_rate(atkbd);
} }
mutex_unlock(&atkbd->event_mutex); mutex_unlock(&atkbd->mutex);
} }
/* /*
...@@ -612,7 +614,7 @@ static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit) ...@@ -612,7 +614,7 @@ static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit)
atkbd->event_jiffies = jiffies; atkbd->event_jiffies = jiffies;
set_bit(event_bit, &atkbd->event_mask); set_bit(event_bit, &atkbd->event_mask);
wmb(); mb();
schedule_delayed_work(&atkbd->event_work, delay); schedule_delayed_work(&atkbd->event_work, delay);
} }
...@@ -849,13 +851,20 @@ static void atkbd_disconnect(struct serio *serio) ...@@ -849,13 +851,20 @@ static void atkbd_disconnect(struct serio *serio)
{ {
struct atkbd *atkbd = serio_get_drvdata(serio); struct atkbd *atkbd = serio_get_drvdata(serio);
sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
atkbd_disable(atkbd); atkbd_disable(atkbd);
/* make sure we don't have a command in flight */ input_unregister_device(atkbd->dev);
/*
* Make sure we don't have a command in flight.
* Note that since atkbd->enabled is false event work will keep
* rescheduling itself until it gets canceled and will not try
* accessing freed input device or serio port.
*/
cancel_delayed_work_sync(&atkbd->event_work); cancel_delayed_work_sync(&atkbd->event_work);
sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
input_unregister_device(atkbd->dev);
serio_close(serio); serio_close(serio);
serio_set_drvdata(serio, NULL); serio_set_drvdata(serio, NULL);
kfree(atkbd); kfree(atkbd);
...@@ -1087,7 +1096,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) ...@@ -1087,7 +1096,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
atkbd->dev = dev; atkbd->dev = dev;
ps2_init(&atkbd->ps2dev, serio); ps2_init(&atkbd->ps2dev, serio);
INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work); INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work);
mutex_init(&atkbd->event_mutex); mutex_init(&atkbd->mutex);
switch (serio->id.type) { switch (serio->id.type) {
...@@ -1160,19 +1169,23 @@ static int atkbd_reconnect(struct serio *serio) ...@@ -1160,19 +1169,23 @@ static int atkbd_reconnect(struct serio *serio)
{ {
struct atkbd *atkbd = serio_get_drvdata(serio); struct atkbd *atkbd = serio_get_drvdata(serio);
struct serio_driver *drv = serio->drv; struct serio_driver *drv = serio->drv;
int retval = -1;
if (!atkbd || !drv) { if (!atkbd || !drv) {
printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n"); printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
return -1; return -1;
} }
mutex_lock(&atkbd->mutex);
atkbd_disable(atkbd); atkbd_disable(atkbd);
if (atkbd->write) { if (atkbd->write) {
if (atkbd_probe(atkbd)) if (atkbd_probe(atkbd))
return -1; goto out;
if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra)) if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
return -1; goto out;
atkbd_activate(atkbd); atkbd_activate(atkbd);
...@@ -1190,8 +1203,11 @@ static int atkbd_reconnect(struct serio *serio) ...@@ -1190,8 +1203,11 @@ static int atkbd_reconnect(struct serio *serio)
} }
atkbd_enable(atkbd); atkbd_enable(atkbd);
retval = 0;
return 0; out:
mutex_unlock(&atkbd->mutex);
return retval;
} }
static struct serio_device_id atkbd_serio_ids[] = { static struct serio_device_id atkbd_serio_ids[] = {
...@@ -1235,47 +1251,28 @@ static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, ...@@ -1235,47 +1251,28 @@ static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
ssize_t (*handler)(struct atkbd *, char *)) ssize_t (*handler)(struct atkbd *, char *))
{ {
struct serio *serio = to_serio_port(dev); struct serio *serio = to_serio_port(dev);
int retval; struct atkbd *atkbd = serio_get_drvdata(serio);
retval = serio_pin_driver(serio);
if (retval)
return retval;
if (serio->drv != &atkbd_drv) {
retval = -ENODEV;
goto out;
}
retval = handler((struct atkbd *)serio_get_drvdata(serio), buf);
out: return handler(atkbd, buf);
serio_unpin_driver(serio);
return retval;
} }
static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count, static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
ssize_t (*handler)(struct atkbd *, const char *, size_t)) ssize_t (*handler)(struct atkbd *, const char *, size_t))
{ {
struct serio *serio = to_serio_port(dev); struct serio *serio = to_serio_port(dev);
struct atkbd *atkbd; struct atkbd *atkbd = serio_get_drvdata(serio);
int retval; int retval;
retval = serio_pin_driver(serio); retval = mutex_lock_interruptible(&atkbd->mutex);
if (retval) if (retval)
return retval; return retval;
if (serio->drv != &atkbd_drv) {
retval = -ENODEV;
goto out;
}
atkbd = serio_get_drvdata(serio);
atkbd_disable(atkbd); atkbd_disable(atkbd);
retval = handler(atkbd, buf, count); retval = handler(atkbd, buf, count);
atkbd_enable(atkbd); atkbd_enable(atkbd);
out: mutex_unlock(&atkbd->mutex);
serio_unpin_driver(serio);
return retval; return retval;
} }
......
...@@ -174,6 +174,14 @@ static int __init davinci_ks_probe(struct platform_device *pdev) ...@@ -174,6 +174,14 @@ static int __init davinci_ks_probe(struct platform_device *pdev)
struct davinci_ks_platform_data *pdata = pdev->dev.platform_data; struct davinci_ks_platform_data *pdata = pdev->dev.platform_data;
int error, i; int error, i;
if (pdata->device_enable) {
error = pdata->device_enable(dev);
if (error < 0) {
dev_dbg(dev, "device enable function failed\n");
return error;
}
}
if (!pdata->keymap) { if (!pdata->keymap) {
dev_dbg(dev, "no keymap from pdata\n"); dev_dbg(dev, "no keymap from pdata\n");
return -EINVAL; return -EINVAL;
......
...@@ -139,6 +139,7 @@ struct tp_finger { ...@@ -139,6 +139,7 @@ struct tp_finger {
/* trackpad finger data size, empirically at least ten fingers */ /* trackpad finger data size, empirically at least ten fingers */
#define SIZEOF_FINGER sizeof(struct tp_finger) #define SIZEOF_FINGER sizeof(struct tp_finger)
#define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER) #define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER)
#define MAX_FINGER_ORIENTATION 16384
/* device-specific parameters */ /* device-specific parameters */
struct bcm5974_param { struct bcm5974_param {
...@@ -284,6 +285,26 @@ static void setup_events_to_report(struct input_dev *input_dev, ...@@ -284,6 +285,26 @@ static void setup_events_to_report(struct input_dev *input_dev,
input_set_abs_params(input_dev, ABS_Y, input_set_abs_params(input_dev, ABS_Y,
0, cfg->y.dim, cfg->y.fuzz, 0); 0, cfg->y.dim, cfg->y.fuzz, 0);
/* finger touch area */
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
cfg->w.devmin, cfg->w.devmax, 0, 0);
input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR,
cfg->w.devmin, cfg->w.devmax, 0, 0);
/* finger approach area */
input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR,
cfg->w.devmin, cfg->w.devmax, 0, 0);
input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR,
cfg->w.devmin, cfg->w.devmax, 0, 0);
/* finger orientation */
input_set_abs_params(input_dev, ABS_MT_ORIENTATION,
-MAX_FINGER_ORIENTATION,
MAX_FINGER_ORIENTATION, 0, 0);
/* finger position */
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
cfg->x.devmin, cfg->x.devmax, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
cfg->y.devmin, cfg->y.devmax, 0, 0);
__set_bit(EV_KEY, input_dev->evbit); __set_bit(EV_KEY, input_dev->evbit);
__set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(BTN_TOOL_FINGER, input_dev->keybit); __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
...@@ -310,13 +331,29 @@ static int report_bt_state(struct bcm5974 *dev, int size) ...@@ -310,13 +331,29 @@ static int report_bt_state(struct bcm5974 *dev, int size)
return 0; return 0;
} }
static void report_finger_data(struct input_dev *input,
const struct bcm5974_config *cfg,
const struct tp_finger *f)
{
input_report_abs(input, ABS_MT_TOUCH_MAJOR, raw2int(f->force_major));
input_report_abs(input, ABS_MT_TOUCH_MINOR, raw2int(f->force_minor));
input_report_abs(input, ABS_MT_WIDTH_MAJOR, raw2int(f->size_major));
input_report_abs(input, ABS_MT_WIDTH_MINOR, raw2int(f->size_minor));
input_report_abs(input, ABS_MT_ORIENTATION,
MAX_FINGER_ORIENTATION - raw2int(f->orientation));
input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x));
input_report_abs(input, ABS_MT_POSITION_Y,
cfg->y.devmin + cfg->y.devmax - raw2int(f->abs_y));
input_mt_sync(input);
}
/* report trackpad data as logical trackpad state */ /* report trackpad data as logical trackpad state */
static int report_tp_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 bcm5974_config *c = &dev->cfg;
const struct tp_finger *f; const struct tp_finger *f;
struct input_dev *input = dev->input; struct input_dev *input = dev->input;
int raw_p, raw_w, raw_x, raw_y, raw_n; int raw_p, raw_w, raw_x, raw_y, raw_n, i;
int ptest, origin, ibt = 0, nmin = 0, nmax = 0; int ptest, origin, ibt = 0, nmin = 0, nmax = 0;
int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
...@@ -329,6 +366,11 @@ static int report_tp_state(struct bcm5974 *dev, int size) ...@@ -329,6 +366,11 @@ static int report_tp_state(struct bcm5974 *dev, int size)
/* always track the first finger; when detached, start over */ /* always track the first finger; when detached, start over */
if (raw_n) { if (raw_n) {
/* report raw trackpad data */
for (i = 0; i < raw_n; i++)
report_finger_data(input, c, &f[i]);
raw_p = raw2int(f->force_major); raw_p = raw2int(f->force_major);
raw_w = raw2int(f->size_major); raw_w = raw2int(f->size_major);
raw_x = raw2int(f->abs_x); raw_x = raw2int(f->abs_x);
......
...@@ -627,8 +627,15 @@ static int psmouse_extensions(struct psmouse *psmouse, ...@@ -627,8 +627,15 @@ static int psmouse_extensions(struct psmouse *psmouse,
synaptics_hardware = true; synaptics_hardware = true;
if (max_proto > PSMOUSE_IMEX) { if (max_proto > PSMOUSE_IMEX) {
if (!set_properties || synaptics_init(psmouse) == 0) /*
* Try activating protocol, but check if support is enabled first, since
* we try detecting Synaptics even when protocol is disabled.
*/
if (synaptics_supported() &&
(!set_properties || synaptics_init(psmouse) == 0)) {
return PSMOUSE_SYNAPTICS; return PSMOUSE_SYNAPTICS;
}
/* /*
* Some Synaptics touchpads can emulate extended protocols (like IMPS/2). * Some Synaptics touchpads can emulate extended protocols (like IMPS/2).
* Unfortunately Logitech/Genius probes confuse some firmware versions so * Unfortunately Logitech/Genius probes confuse some firmware versions so
...@@ -683,19 +690,6 @@ static int psmouse_extensions(struct psmouse *psmouse, ...@@ -683,19 +690,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
max_proto = PSMOUSE_IMEX; max_proto = PSMOUSE_IMEX;
} }
/*
* Try Finger Sensing Pad
*/
if (max_proto > PSMOUSE_IMEX) {
if (fsp_detect(psmouse, set_properties) == 0) {
if (!set_properties || fsp_init(psmouse) == 0)
return PSMOUSE_FSP;
/*
* Init failed, try basic relative protocols
*/
max_proto = PSMOUSE_IMEX;
}
}
if (max_proto > PSMOUSE_IMEX) { if (max_proto > PSMOUSE_IMEX) {
if (genius_detect(psmouse, set_properties) == 0) if (genius_detect(psmouse, set_properties) == 0)
...@@ -711,6 +705,21 @@ static int psmouse_extensions(struct psmouse *psmouse, ...@@ -711,6 +705,21 @@ static int psmouse_extensions(struct psmouse *psmouse,
return PSMOUSE_TOUCHKIT_PS2; return PSMOUSE_TOUCHKIT_PS2;
} }
/*
* Try Finger Sensing Pad. We do it here because its probe upsets
* Trackpoint devices (causing TP_READ_ID command to time out).
*/
if (max_proto > PSMOUSE_IMEX) {
if (fsp_detect(psmouse, set_properties) == 0) {
if (!set_properties || fsp_init(psmouse) == 0)
return PSMOUSE_FSP;
/*
* Init failed, try basic relative protocols
*/
max_proto = PSMOUSE_IMEX;
}
}
/* /*
* Reset to defaults in case the device got confused by extended * Reset to defaults in case the device got confused by extended
* protocol probes. Note that we follow up with full reset because * protocol probes. Note that we follow up with full reset because
...@@ -1450,24 +1459,10 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *de ...@@ -1450,24 +1459,10 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *de
struct serio *serio = to_serio_port(dev); struct serio *serio = to_serio_port(dev);
struct psmouse_attribute *attr = to_psmouse_attr(devattr); struct psmouse_attribute *attr = to_psmouse_attr(devattr);
struct psmouse *psmouse; struct psmouse *psmouse;
int retval;
retval = serio_pin_driver(serio);
if (retval)
return retval;
if (serio->drv != &psmouse_drv) {
retval = -ENODEV;
goto out;
}
psmouse = serio_get_drvdata(serio); psmouse = serio_get_drvdata(serio);
retval = attr->show(psmouse, attr->data, buf); return attr->show(psmouse, attr->data, buf);
out:
serio_unpin_driver(serio);
return retval;
} }
ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr, ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr,
...@@ -1478,18 +1473,9 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev ...@@ -1478,18 +1473,9 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
struct psmouse *psmouse, *parent = NULL; struct psmouse *psmouse, *parent = NULL;
int retval; int retval;
retval = serio_pin_driver(serio);
if (retval)
return retval;
if (serio->drv != &psmouse_drv) {
retval = -ENODEV;
goto out_unpin;
}
retval = mutex_lock_interruptible(&psmouse_mutex); retval = mutex_lock_interruptible(&psmouse_mutex);
if (retval) if (retval)
goto out_unpin; goto out;
psmouse = serio_get_drvdata(serio); psmouse = serio_get_drvdata(serio);
...@@ -1519,8 +1505,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev ...@@ -1519,8 +1505,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
out_unlock: out_unlock:
mutex_unlock(&psmouse_mutex); mutex_unlock(&psmouse_mutex);
out_unpin: out:
serio_unpin_driver(serio);
return retval; return retval;
} }
...@@ -1582,9 +1567,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co ...@@ -1582,9 +1567,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
} }
mutex_unlock(&psmouse_mutex); mutex_unlock(&psmouse_mutex);
serio_unpin_driver(serio);
serio_unregister_child_port(serio); serio_unregister_child_port(serio);
serio_pin_driver_uninterruptible(serio);
mutex_lock(&psmouse_mutex); mutex_lock(&psmouse_mutex);
if (serio->drv != &psmouse_drv) { if (serio->drv != &psmouse_drv) {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* Finger Sensing Pad PS/2 mouse driver. * Finger Sensing Pad PS/2 mouse driver.
* *
* Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd.
* Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation. * Copyright (C) 2005-2010 Tai-hwa Liang, Sentelic Corporation.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -658,9 +658,9 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) ...@@ -658,9 +658,9 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
if (packet[3] & BIT(1)) if (packet[3] & BIT(1))
button_status |= 0x0f; /* wheel up */ button_status |= 0x0f; /* wheel up */
if (packet[3] & BIT(2)) if (packet[3] & BIT(2))
button_status |= BIT(5);/* horizontal left */ button_status |= BIT(4);/* horizontal left */
if (packet[3] & BIT(3)) if (packet[3] & BIT(3))
button_status |= BIT(4);/* horizontal right */ button_status |= BIT(5);/* horizontal right */
/* push back to packet queue */ /* push back to packet queue */
if (button_status != 0) if (button_status != 0)
packet[3] = button_status; packet[3] = button_status;
......
...@@ -743,6 +743,11 @@ int synaptics_init(struct psmouse *psmouse) ...@@ -743,6 +743,11 @@ int synaptics_init(struct psmouse *psmouse)
return -1; return -1;
} }
bool synaptics_supported(void)
{
return true;
}
#else /* CONFIG_MOUSE_PS2_SYNAPTICS */ #else /* CONFIG_MOUSE_PS2_SYNAPTICS */
void __init synaptics_module_init(void) void __init synaptics_module_init(void)
...@@ -754,5 +759,10 @@ int synaptics_init(struct psmouse *psmouse) ...@@ -754,5 +759,10 @@ int synaptics_init(struct psmouse *psmouse)
return -ENOSYS; return -ENOSYS;
} }
bool synaptics_supported(void)
{
return false;
}
#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */ #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
...@@ -109,5 +109,6 @@ void synaptics_module_init(void); ...@@ -109,5 +109,6 @@ void synaptics_module_init(void);
int synaptics_detect(struct psmouse *psmouse, bool set_properties); int synaptics_detect(struct psmouse *psmouse, bool set_properties);
int synaptics_init(struct psmouse *psmouse); int synaptics_init(struct psmouse *psmouse);
void synaptics_reset(struct psmouse *psmouse); void synaptics_reset(struct psmouse *psmouse);
bool synaptics_supported(void);
#endif /* _SYNAPTICS_H */ #endif /* _SYNAPTICS_H */
...@@ -523,6 +523,13 @@ static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = { ...@@ -523,6 +523,13 @@ static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = {
* have turned up in 2007 that also need this again. * have turned up in 2007 that also need this again.
*/ */
static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = { static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = {
{
/* Acer Aspire 5610 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
},
},
{ {
/* Acer Aspire 5630 */ /* Acer Aspire 5630 */
.matches = { .matches = {
......
...@@ -136,25 +136,6 @@ static inline void serio_continue_rx(struct serio *serio) ...@@ -136,25 +136,6 @@ static inline void serio_continue_rx(struct serio *serio)
spin_unlock_irq(&serio->lock); spin_unlock_irq(&serio->lock);
} }
/*
* Use the following functions to pin serio's driver in process context
*/
static inline int serio_pin_driver(struct serio *serio)
{
return mutex_lock_interruptible(&serio->drv_mutex);
}
static inline void serio_pin_driver_uninterruptible(struct serio *serio)
{
mutex_lock(&serio->drv_mutex);
}
static inline void serio_unpin_driver(struct serio *serio)
{
mutex_unlock(&serio->drv_mutex);
}
#endif #endif
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment