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()
This commit is contained in:
commit
3b3ef30833
14 changed files with 207 additions and 120 deletions
|
@ -29,6 +29,7 @@ enum davinci_matrix_types {
|
|||
};
|
||||
|
||||
struct davinci_ks_platform_data {
|
||||
int (*device_enable)(struct device *dev);
|
||||
unsigned short *keymap;
|
||||
u32 keymapsize;
|
||||
u8 rep:1;
|
||||
|
|
|
@ -59,7 +59,8 @@ static void evdev_pass_event(struct evdev_client *client,
|
|||
client->head &= EVDEV_BUFFER_SIZE - 1;
|
||||
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 @@
|
|||
#include <linux/mutex.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include "input-compat.h"
|
||||
|
||||
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
|
||||
MODULE_DESCRIPTION("Input core");
|
||||
|
@ -764,6 +765,40 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han
|
|||
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
|
||||
|
||||
|
@ -832,14 +867,25 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
|
|||
unsigned long *bitmap, int max)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = BITS_TO_LONGS(max) - 1; i > 0; i--)
|
||||
if (bitmap[i])
|
||||
break;
|
||||
bool skip_empty = true;
|
||||
char buf[18];
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
|
@ -1128,14 +1174,23 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap,
|
|||
{
|
||||
int i;
|
||||
int len = 0;
|
||||
bool skip_empty = true;
|
||||
|
||||
for (i = BITS_TO_LONGS(max) - 1; i > 0; i--)
|
||||
if (bitmap[i])
|
||||
break;
|
||||
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 >= 0; i--)
|
||||
len += snprintf(buf + len, max(buf_size - len, 0),
|
||||
"%lx%s", bitmap[i], i > 0 ? " " : "");
|
||||
/*
|
||||
* If no output was produced print a single 0.
|
||||
*/
|
||||
if (len == 0)
|
||||
len = snprintf(buf, buf_size, "%d", 0);
|
||||
|
||||
if (add_cr)
|
||||
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, \
|
|||
{ \
|
||||
struct input_dev *input_dev = to_input_dev(dev); \
|
||||
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); \
|
||||
} \
|
||||
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,
|
|||
|
||||
len = input_print_bitmap(&env->buf[env->buflen - 1],
|
||||
sizeof(env->buf) - env->buflen,
|
||||
bitmap, max, 0);
|
||||
bitmap, max, false);
|
||||
if (len >= (sizeof(env->buf) - env->buflen))
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -277,7 +277,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
|
|||
}
|
||||
|
||||
#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)))) {
|
||||
err = -ENODEV;
|
||||
goto fail2;
|
||||
|
|
|
@ -446,7 +446,7 @@ static void xpad_irq_in(struct urb *urb)
|
|||
}
|
||||
|
||||
exit:
|
||||
retval = usb_submit_urb (urb, GFP_ATOMIC);
|
||||
retval = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (retval)
|
||||
err ("%s - usb_submit_urb failed with result %d",
|
||||
__func__, retval);
|
||||
|
@ -571,7 +571,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data,
|
|||
xpad->odata[6] = 0x00;
|
||||
xpad->odata[7] = 0x00;
|
||||
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;
|
||||
|
|
|
@ -225,8 +225,10 @@ struct atkbd {
|
|||
|
||||
struct delayed_work event_work;
|
||||
unsigned long event_jiffies;
|
||||
struct mutex event_mutex;
|
||||
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)
|
|||
{
|
||||
struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work);
|
||||
|
||||
mutex_lock(&atkbd->event_mutex);
|
||||
mutex_lock(&atkbd->mutex);
|
||||
|
||||
if (!atkbd->enabled) {
|
||||
/*
|
||||
|
@ -596,7 +598,7 @@ static void atkbd_event_work(struct work_struct *work)
|
|||
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)
|
|||
|
||||
atkbd->event_jiffies = jiffies;
|
||||
set_bit(event_bit, &atkbd->event_mask);
|
||||
wmb();
|
||||
mb();
|
||||
schedule_delayed_work(&atkbd->event_work, delay);
|
||||
}
|
||||
|
||||
|
@ -849,13 +851,20 @@ static void atkbd_disconnect(struct serio *serio)
|
|||
{
|
||||
struct atkbd *atkbd = serio_get_drvdata(serio);
|
||||
|
||||
sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
|
||||
|
||||
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);
|
||||
|
||||
sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
|
||||
input_unregister_device(atkbd->dev);
|
||||
serio_close(serio);
|
||||
serio_set_drvdata(serio, NULL);
|
||||
kfree(atkbd);
|
||||
|
@ -1087,7 +1096,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
|
|||
atkbd->dev = dev;
|
||||
ps2_init(&atkbd->ps2dev, serio);
|
||||
INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work);
|
||||
mutex_init(&atkbd->event_mutex);
|
||||
mutex_init(&atkbd->mutex);
|
||||
|
||||
switch (serio->id.type) {
|
||||
|
||||
|
@ -1160,19 +1169,23 @@ static int atkbd_reconnect(struct serio *serio)
|
|||
{
|
||||
struct atkbd *atkbd = serio_get_drvdata(serio);
|
||||
struct serio_driver *drv = serio->drv;
|
||||
int retval = -1;
|
||||
|
||||
if (!atkbd || !drv) {
|
||||
printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mutex_lock(&atkbd->mutex);
|
||||
|
||||
atkbd_disable(atkbd);
|
||||
|
||||
if (atkbd->write) {
|
||||
if (atkbd_probe(atkbd))
|
||||
return -1;
|
||||
goto out;
|
||||
|
||||
if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
|
||||
return -1;
|
||||
goto out;
|
||||
|
||||
atkbd_activate(atkbd);
|
||||
|
||||
|
@ -1190,8 +1203,11 @@ static int atkbd_reconnect(struct serio *serio)
|
|||
}
|
||||
|
||||
atkbd_enable(atkbd);
|
||||
retval = 0;
|
||||
|
||||
return 0;
|
||||
out:
|
||||
mutex_unlock(&atkbd->mutex);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static struct serio_device_id atkbd_serio_ids[] = {
|
||||
|
@ -1235,47 +1251,28 @@ static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
|
|||
ssize_t (*handler)(struct atkbd *, char *))
|
||||
{
|
||||
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:
|
||||
serio_unpin_driver(serio);
|
||||
return retval;
|
||||
return handler(atkbd, buf);
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
struct serio *serio = to_serio_port(dev);
|
||||
struct atkbd *atkbd;
|
||||
struct atkbd *atkbd = serio_get_drvdata(serio);
|
||||
int retval;
|
||||
|
||||
retval = serio_pin_driver(serio);
|
||||
retval = mutex_lock_interruptible(&atkbd->mutex);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (serio->drv != &atkbd_drv) {
|
||||
retval = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
atkbd = serio_get_drvdata(serio);
|
||||
atkbd_disable(atkbd);
|
||||
retval = handler(atkbd, buf, count);
|
||||
atkbd_enable(atkbd);
|
||||
|
||||
out:
|
||||
serio_unpin_driver(serio);
|
||||
mutex_unlock(&atkbd->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
@ -174,6 +174,14 @@ static int __init davinci_ks_probe(struct platform_device *pdev)
|
|||
struct davinci_ks_platform_data *pdata = pdev->dev.platform_data;
|
||||
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) {
|
||||
dev_dbg(dev, "no keymap from pdata\n");
|
||||
return -EINVAL;
|
||||
|
|
|
@ -139,6 +139,7 @@ struct tp_finger {
|
|||
/* trackpad finger data size, empirically at least ten fingers */
|
||||
#define SIZEOF_FINGER sizeof(struct tp_finger)
|
||||
#define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER)
|
||||
#define MAX_FINGER_ORIENTATION 16384
|
||||
|
||||
/* device-specific parameters */
|
||||
struct bcm5974_param {
|
||||
|
@ -284,6 +285,26 @@ static void setup_events_to_report(struct input_dev *input_dev,
|
|||
input_set_abs_params(input_dev, ABS_Y,
|
||||
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(BTN_TOUCH, 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)
|
|||
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 */
|
||||
static int report_tp_state(struct bcm5974 *dev, int size)
|
||||
{
|
||||
const struct bcm5974_config *c = &dev->cfg;
|
||||
const struct tp_finger *f;
|
||||
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 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)
|
|||
|
||||
/* always track the first finger; when detached, start over */
|
||||
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_w = raw2int(f->size_major);
|
||||
raw_x = raw2int(f->abs_x);
|
||||
|
|
|
@ -627,8 +627,15 @@ static int psmouse_extensions(struct psmouse *psmouse,
|
|||
synaptics_hardware = true;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some Synaptics touchpads can emulate extended protocols (like IMPS/2).
|
||||
* Unfortunately Logitech/Genius probes confuse some firmware versions so
|
||||
|
@ -683,19 +690,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
|
|||
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 (genius_detect(psmouse, set_properties) == 0)
|
||||
|
@ -711,6 +705,21 @@ static int psmouse_extensions(struct psmouse *psmouse,
|
|||
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
|
||||
* 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
|
|||
struct serio *serio = to_serio_port(dev);
|
||||
struct psmouse_attribute *attr = to_psmouse_attr(devattr);
|
||||
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);
|
||||
|
||||
retval = attr->show(psmouse, attr->data, buf);
|
||||
|
||||
out:
|
||||
serio_unpin_driver(serio);
|
||||
return retval;
|
||||
return attr->show(psmouse, attr->data, buf);
|
||||
}
|
||||
|
||||
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
|
|||
struct psmouse *psmouse, *parent = NULL;
|
||||
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);
|
||||
if (retval)
|
||||
goto out_unpin;
|
||||
goto out;
|
||||
|
||||
psmouse = serio_get_drvdata(serio);
|
||||
|
||||
|
@ -1519,8 +1505,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev
|
|||
|
||||
out_unlock:
|
||||
mutex_unlock(&psmouse_mutex);
|
||||
out_unpin:
|
||||
serio_unpin_driver(serio);
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -1582,9 +1567,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
|
|||
}
|
||||
|
||||
mutex_unlock(&psmouse_mutex);
|
||||
serio_unpin_driver(serio);
|
||||
serio_unregister_child_port(serio);
|
||||
serio_pin_driver_uninterruptible(serio);
|
||||
mutex_lock(&psmouse_mutex);
|
||||
|
||||
if (serio->drv != &psmouse_drv) {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Finger Sensing Pad PS/2 mouse driver.
|
||||
*
|
||||
* 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
|
||||
* 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)
|
|||
if (packet[3] & BIT(1))
|
||||
button_status |= 0x0f; /* wheel up */
|
||||
if (packet[3] & BIT(2))
|
||||
button_status |= BIT(5);/* horizontal left */
|
||||
button_status |= BIT(4);/* horizontal left */
|
||||
if (packet[3] & BIT(3))
|
||||
button_status |= BIT(4);/* horizontal right */
|
||||
button_status |= BIT(5);/* horizontal right */
|
||||
/* push back to packet queue */
|
||||
if (button_status != 0)
|
||||
packet[3] = button_status;
|
||||
|
|
|
@ -743,6 +743,11 @@ int synaptics_init(struct psmouse *psmouse)
|
|||
return -1;
|
||||
}
|
||||
|
||||
bool synaptics_supported(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#else /* CONFIG_MOUSE_PS2_SYNAPTICS */
|
||||
|
||||
void __init synaptics_module_init(void)
|
||||
|
@ -754,5 +759,10 @@ int synaptics_init(struct psmouse *psmouse)
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
bool synaptics_supported(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MOUSE_PS2_SYNAPTICS */
|
||||
|
||||
|
|
|
@ -109,5 +109,6 @@ void synaptics_module_init(void);
|
|||
int synaptics_detect(struct psmouse *psmouse, bool set_properties);
|
||||
int synaptics_init(struct psmouse *psmouse);
|
||||
void synaptics_reset(struct psmouse *psmouse);
|
||||
bool synaptics_supported(void);
|
||||
|
||||
#endif /* _SYNAPTICS_H */
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
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 */
|
||||
.matches = {
|
||||
|
|
|
@ -136,25 +136,6 @@ static inline void serio_continue_rx(struct serio *serio)
|
|||
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
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue