Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/dtor/input.git manually
Some manual fixups required due to clashes with the PF_FREEZE cleanups.
This commit is contained in:
@@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
|
||||
obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o
|
||||
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
|
||||
|
||||
psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o
|
||||
psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o
|
||||
|
||||
+31
-21
@@ -30,10 +30,11 @@
|
||||
|
||||
#define ALPS_DUALPOINT 0x01
|
||||
#define ALPS_WHEEL 0x02
|
||||
#define ALPS_FW_BK 0x04
|
||||
#define ALPS_FW_BK_1 0x04
|
||||
#define ALPS_4BTN 0x08
|
||||
#define ALPS_OLDPROTO 0x10
|
||||
#define ALPS_PASS 0x20
|
||||
#define ALPS_FW_BK_2 0x40
|
||||
|
||||
static struct alps_model_info alps_model_data[] = {
|
||||
{ { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */
|
||||
@@ -43,11 +44,11 @@ static struct alps_model_info alps_model_data[] = {
|
||||
{ { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
|
||||
{ { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 },
|
||||
{ { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */
|
||||
{ { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK }, /* NEC Versa L320 */
|
||||
{ { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */
|
||||
{ { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 },
|
||||
{ { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */
|
||||
{ { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
|
||||
{ { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
|
||||
{ { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */
|
||||
{ { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
|
||||
{ { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
|
||||
{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
|
||||
@@ -61,11 +62,11 @@ static struct alps_model_info alps_model_data[] = {
|
||||
|
||||
/*
|
||||
* ALPS abolute Mode - new format
|
||||
*
|
||||
* byte 0: 1 ? ? ? 1 ? ? ?
|
||||
*
|
||||
* byte 0: 1 ? ? ? 1 ? ? ?
|
||||
* byte 1: 0 x6 x5 x4 x3 x2 x1 x0
|
||||
* byte 2: 0 x10 x9 x8 x7 ? fin ges
|
||||
* byte 3: 0 y9 y8 y7 1 M R L
|
||||
* byte 3: 0 y9 y8 y7 1 M R L
|
||||
* byte 4: 0 y6 y5 y4 y3 y2 y1 y0
|
||||
* byte 5: 0 z6 z5 z4 z3 z2 z1 z0
|
||||
*
|
||||
@@ -81,11 +82,12 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
|
||||
struct input_dev *dev = &psmouse->dev;
|
||||
struct input_dev *dev2 = &priv->dev2;
|
||||
int x, y, z, ges, fin, left, right, middle;
|
||||
int back = 0, forward = 0;
|
||||
|
||||
input_regs(dev, regs);
|
||||
|
||||
if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */
|
||||
input_report_key(dev2, BTN_LEFT, packet[0] & 1);
|
||||
input_report_key(dev2, BTN_LEFT, packet[0] & 1);
|
||||
input_report_key(dev2, BTN_RIGHT, packet[0] & 2);
|
||||
input_report_key(dev2, BTN_MIDDLE, packet[0] & 4);
|
||||
input_report_rel(dev2, REL_X,
|
||||
@@ -112,6 +114,18 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
|
||||
z = packet[5];
|
||||
}
|
||||
|
||||
if (priv->i->flags & ALPS_FW_BK_1) {
|
||||
back = packet[2] & 4;
|
||||
forward = packet[0] & 0x10;
|
||||
}
|
||||
|
||||
if (priv->i->flags & ALPS_FW_BK_2) {
|
||||
back = packet[3] & 4;
|
||||
forward = packet[2] & 4;
|
||||
if ((middle = forward && back))
|
||||
forward = back = 0;
|
||||
}
|
||||
|
||||
ges = packet[2] & 1;
|
||||
fin = packet[2] & 2;
|
||||
|
||||
@@ -155,13 +169,12 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
|
||||
input_report_abs(dev, ABS_PRESSURE, z);
|
||||
input_report_key(dev, BTN_TOOL_FINGER, z > 0);
|
||||
|
||||
|
||||
if (priv->i->flags & ALPS_WHEEL)
|
||||
input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08));
|
||||
|
||||
if (priv->i->flags & ALPS_FW_BK) {
|
||||
input_report_key(dev, BTN_FORWARD, packet[0] & 0x10);
|
||||
input_report_key(dev, BTN_BACK, packet[2] & 0x04);
|
||||
if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
|
||||
input_report_key(dev, BTN_FORWARD, forward);
|
||||
input_report_key(dev, BTN_BACK, back);
|
||||
}
|
||||
|
||||
input_sync(dev);
|
||||
@@ -257,7 +270,6 @@ static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *vers
|
||||
static int alps_passthrough_mode(struct psmouse *psmouse, int enable)
|
||||
{
|
||||
struct ps2dev *ps2dev = &psmouse->ps2dev;
|
||||
unsigned char param[3];
|
||||
int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11;
|
||||
|
||||
if (ps2_command(ps2dev, NULL, cmd) ||
|
||||
@@ -267,7 +279,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, int enable)
|
||||
return -1;
|
||||
|
||||
/* we may get 3 more bytes, just ignore them */
|
||||
ps2_command(ps2dev, param, 0x0300);
|
||||
ps2_drain(ps2dev, 3, 100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -425,7 +437,7 @@ int alps_init(struct psmouse *psmouse)
|
||||
psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
|
||||
}
|
||||
|
||||
if (priv->i->flags & ALPS_FW_BK) {
|
||||
if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
|
||||
psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
|
||||
psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
|
||||
}
|
||||
@@ -436,8 +448,8 @@ int alps_init(struct psmouse *psmouse)
|
||||
priv->dev2.id.bustype = BUS_I8042;
|
||||
priv->dev2.id.vendor = 0x0002;
|
||||
priv->dev2.id.product = PSMOUSE_ALPS;
|
||||
priv->dev2.id.version = 0x0000;
|
||||
|
||||
priv->dev2.id.version = 0x0000;
|
||||
|
||||
priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
|
||||
priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
|
||||
priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
|
||||
@@ -461,17 +473,15 @@ init_fail:
|
||||
int alps_detect(struct psmouse *psmouse, int set_properties)
|
||||
{
|
||||
int version;
|
||||
struct alps_model_info *model;
|
||||
struct alps_model_info *model;
|
||||
|
||||
if (!(model = alps_get_model(psmouse, &version)))
|
||||
return -1;
|
||||
|
||||
if (set_properties) {
|
||||
psmouse->vendor = "ALPS";
|
||||
if (model->flags & ALPS_DUALPOINT)
|
||||
psmouse->name = "DualPoint TouchPad";
|
||||
else
|
||||
psmouse->name = "GlidePoint";
|
||||
psmouse->name = model->flags & ALPS_DUALPOINT ?
|
||||
"DualPoint TouchPad" : "GlidePoint";
|
||||
psmouse->model = version;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -33,7 +33,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
|
||||
MODULE_DESCRIPTION("Amiga mouse driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int amimouse_used = 0;
|
||||
static int amimouse_lastx, amimouse_lasty;
|
||||
static struct input_dev amimouse_dev;
|
||||
|
||||
@@ -81,16 +80,12 @@ static int amimouse_open(struct input_dev *dev)
|
||||
{
|
||||
unsigned short joy0dat;
|
||||
|
||||
if (amimouse_used++)
|
||||
return 0;
|
||||
|
||||
joy0dat = custom.joy0dat;
|
||||
|
||||
amimouse_lastx = joy0dat & 0xff;
|
||||
amimouse_lasty = joy0dat >> 8;
|
||||
|
||||
if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) {
|
||||
amimouse_used--;
|
||||
printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB);
|
||||
return -EBUSY;
|
||||
}
|
||||
@@ -100,8 +95,7 @@ static int amimouse_open(struct input_dev *dev)
|
||||
|
||||
static void amimouse_close(struct input_dev *dev)
|
||||
{
|
||||
if (!--amimouse_used)
|
||||
free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt);
|
||||
free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt);
|
||||
}
|
||||
|
||||
static int __init amimouse_init(void)
|
||||
|
||||
@@ -17,18 +17,18 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
@@ -87,29 +87,23 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)");
|
||||
|
||||
__obsolete_setup("inport_irq=");
|
||||
|
||||
static int inport_used;
|
||||
|
||||
static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
|
||||
|
||||
static int inport_open(struct input_dev *dev)
|
||||
{
|
||||
if (!inport_used++) {
|
||||
if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
|
||||
return -EBUSY;
|
||||
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
|
||||
outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
|
||||
}
|
||||
if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
|
||||
return -EBUSY;
|
||||
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
|
||||
outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void inport_close(struct input_dev *dev)
|
||||
{
|
||||
if (!--inport_used) {
|
||||
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
|
||||
outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
|
||||
free_irq(inport_irq, NULL);
|
||||
}
|
||||
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
|
||||
outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
|
||||
free_irq(inport_irq, NULL);
|
||||
}
|
||||
|
||||
static struct input_dev inport_dev = {
|
||||
@@ -120,11 +114,11 @@ static struct input_dev inport_dev = {
|
||||
.close = inport_close,
|
||||
.name = INPORT_NAME,
|
||||
.phys = "isa023c/input0",
|
||||
.id = {
|
||||
.bustype = BUS_ISA,
|
||||
.vendor = INPORT_VENDOR,
|
||||
.product = 0x0001,
|
||||
.version = 0x0100,
|
||||
.id = {
|
||||
.bustype = BUS_ISA,
|
||||
.vendor = INPORT_VENDOR,
|
||||
.product = 0x0001,
|
||||
.version = 0x0100,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Fujitsu B-series Lifebook PS/2 TouchScreen driver
|
||||
*
|
||||
* Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
|
||||
* Copyright (c) 2005 Kenan Esau <kenan.esau@conan.de>
|
||||
*
|
||||
* TouchScreen detection, absolute mode setting and packet layout is taken from
|
||||
* Harald Hoyer's description of the device.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/serio.h>
|
||||
#include <linux/libps2.h>
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#include "psmouse.h"
|
||||
#include "lifebook.h"
|
||||
|
||||
static struct dmi_system_id lifebook_dmi_table[] = {
|
||||
{
|
||||
.ident = "Lifebook B",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
|
||||
{
|
||||
unsigned char *packet = psmouse->packet;
|
||||
struct input_dev *dev = &psmouse->dev;
|
||||
|
||||
if (psmouse->pktcnt != 3)
|
||||
return PSMOUSE_GOOD_DATA;
|
||||
|
||||
input_regs(dev, regs);
|
||||
|
||||
/* calculate X and Y */
|
||||
if ((packet[0] & 0x08) == 0x00) {
|
||||
input_report_abs(dev, ABS_X,
|
||||
(packet[1] | ((packet[0] & 0x30) << 4)));
|
||||
input_report_abs(dev, ABS_Y,
|
||||
1024 - (packet[2] | ((packet[0] & 0xC0) << 2)));
|
||||
} else {
|
||||
input_report_rel(dev, REL_X,
|
||||
((packet[0] & 0x10) ? packet[1] - 256 : packet[1]));
|
||||
input_report_rel(dev, REL_Y,
|
||||
-(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2]));
|
||||
}
|
||||
|
||||
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
|
||||
input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
|
||||
input_report_key(dev, BTN_TOUCH, packet[0] & 0x04);
|
||||
|
||||
input_sync(dev);
|
||||
|
||||
return PSMOUSE_FULL_PACKET;
|
||||
}
|
||||
|
||||
static int lifebook_absolute_mode(struct psmouse *psmouse)
|
||||
{
|
||||
struct ps2dev *ps2dev = &psmouse->ps2dev;
|
||||
unsigned char param;
|
||||
|
||||
if (psmouse_reset(psmouse))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
Enable absolute output -- ps2_command fails always but if
|
||||
you leave this call out the touchsreen will never send
|
||||
absolute coordinates
|
||||
*/
|
||||
param = 0x07;
|
||||
ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution)
|
||||
{
|
||||
unsigned char params[] = { 0, 1, 2, 2, 3 };
|
||||
|
||||
if (resolution == 0 || resolution > 400)
|
||||
resolution = 400;
|
||||
|
||||
ps2_command(&psmouse->ps2dev, ¶ms[resolution / 100], PSMOUSE_CMD_SETRES);
|
||||
psmouse->resolution = 50 << params[resolution / 100];
|
||||
}
|
||||
|
||||
static void lifebook_disconnect(struct psmouse *psmouse)
|
||||
{
|
||||
psmouse_reset(psmouse);
|
||||
}
|
||||
|
||||
int lifebook_detect(struct psmouse *psmouse, int set_properties)
|
||||
{
|
||||
if (!dmi_check_system(lifebook_dmi_table))
|
||||
return -1;
|
||||
|
||||
if (set_properties) {
|
||||
psmouse->vendor = "Fujitsu";
|
||||
psmouse->name = "Lifebook TouchScreen";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lifebook_init(struct psmouse *psmouse)
|
||||
{
|
||||
if (lifebook_absolute_mode(psmouse))
|
||||
return -1;
|
||||
|
||||
psmouse->dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
|
||||
psmouse->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
|
||||
psmouse->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
|
||||
psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
|
||||
input_set_abs_params(&psmouse->dev, ABS_X, 0, 1024, 0, 0);
|
||||
input_set_abs_params(&psmouse->dev, ABS_Y, 0, 1024, 0, 0);
|
||||
|
||||
psmouse->protocol_handler = lifebook_process_byte;
|
||||
psmouse->set_resolution = lifebook_set_resolution;
|
||||
psmouse->disconnect = lifebook_disconnect;
|
||||
psmouse->reconnect = lifebook_absolute_mode;
|
||||
psmouse->pktsize = 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Fujitsu B-series Lifebook PS/2 TouchScreen driver
|
||||
*
|
||||
* Copyright (c) 2005 Vojtech Pavlik
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _LIFEBOOK_H
|
||||
#define _LIFEBOOK_H
|
||||
|
||||
int lifebook_detect(struct psmouse *psmouse, int set_properties);
|
||||
int lifebook_init(struct psmouse *psmouse);
|
||||
|
||||
#endif
|
||||
@@ -18,18 +18,18 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*
|
||||
* Should you need to contact me, the author, you can do so either by
|
||||
* e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
|
||||
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
|
||||
@@ -77,16 +77,11 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)");
|
||||
|
||||
__obsolete_setup("logibm_irq=");
|
||||
|
||||
static int logibm_used = 0;
|
||||
|
||||
static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
|
||||
|
||||
static int logibm_open(struct input_dev *dev)
|
||||
{
|
||||
if (logibm_used++)
|
||||
return 0;
|
||||
if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
|
||||
logibm_used--;
|
||||
printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
|
||||
return -EBUSY;
|
||||
}
|
||||
@@ -96,8 +91,6 @@ static int logibm_open(struct input_dev *dev)
|
||||
|
||||
static void logibm_close(struct input_dev *dev)
|
||||
{
|
||||
if (--logibm_used)
|
||||
return;
|
||||
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
|
||||
free_irq(logibm_irq, NULL);
|
||||
}
|
||||
@@ -167,7 +160,7 @@ static int __init logibm_init(void)
|
||||
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
|
||||
|
||||
input_register_device(&logibm_dev);
|
||||
|
||||
|
||||
printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $
|
||||
* SEGA Dreamcast mouse driver
|
||||
* SEGA Dreamcast mouse driver
|
||||
* Based on drivers/usb/usbmouse.c
|
||||
*/
|
||||
|
||||
@@ -15,80 +15,51 @@
|
||||
MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>");
|
||||
MODULE_DESCRIPTION("SEGA Dreamcast mouse driver");
|
||||
|
||||
struct dc_mouse {
|
||||
struct input_dev dev;
|
||||
int open;
|
||||
};
|
||||
|
||||
|
||||
static void dc_mouse_callback(struct mapleq *mq)
|
||||
{
|
||||
int buttons, relx, rely, relz;
|
||||
struct maple_device *mapledev = mq->dev;
|
||||
struct dc_mouse *mouse = mapledev->private_data;
|
||||
struct input_dev *dev = &mouse->dev;
|
||||
struct input_dev *dev = mapledev->private_data;
|
||||
unsigned char *res = mq->recvbuf;
|
||||
|
||||
buttons = ~res[8];
|
||||
relx=*(unsigned short *)(res+12)-512;
|
||||
rely=*(unsigned short *)(res+14)-512;
|
||||
relz=*(unsigned short *)(res+16)-512;
|
||||
relx = *(unsigned short *)(res + 12) - 512;
|
||||
rely = *(unsigned short *)(res + 14) - 512;
|
||||
relz = *(unsigned short *)(res + 16) - 512;
|
||||
|
||||
input_report_key(dev, BTN_LEFT, buttons&4);
|
||||
input_report_key(dev, BTN_MIDDLE, buttons&9);
|
||||
input_report_key(dev, BTN_RIGHT, buttons&2);
|
||||
input_report_key(dev, BTN_LEFT, buttons & 4);
|
||||
input_report_key(dev, BTN_MIDDLE, buttons & 9);
|
||||
input_report_key(dev, BTN_RIGHT, buttons & 2);
|
||||
input_report_rel(dev, REL_X, relx);
|
||||
input_report_rel(dev, REL_Y, rely);
|
||||
input_report_rel(dev, REL_WHEEL, relz);
|
||||
input_sync(dev);
|
||||
}
|
||||
|
||||
|
||||
static int dc_mouse_open(struct input_dev *dev)
|
||||
{
|
||||
struct dc_mouse *mouse = dev->private;
|
||||
mouse->open++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void dc_mouse_close(struct input_dev *dev)
|
||||
{
|
||||
struct dc_mouse *mouse = dev->private;
|
||||
mouse->open--;
|
||||
}
|
||||
|
||||
|
||||
static int dc_mouse_connect(struct maple_device *dev)
|
||||
{
|
||||
unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
|
||||
struct dc_mouse *mouse;
|
||||
struct input_dev *input_dev;
|
||||
|
||||
if (!(mouse = kmalloc(sizeof(struct dc_mouse), GFP_KERNEL)))
|
||||
if (!(input_dev = kmalloc(sizeof(struct input_dev), GFP_KERNEL)))
|
||||
return -1;
|
||||
memset(mouse, 0, sizeof(struct dc_mouse));
|
||||
|
||||
dev->private_data = mouse;
|
||||
dev->private_data = input_dev;
|
||||
|
||||
mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
|
||||
mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
|
||||
mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
|
||||
memset(input_dev, 0, sizeof(struct dc_mouse));
|
||||
init_input_dev(input_dev);
|
||||
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
|
||||
input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
|
||||
input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
|
||||
|
||||
init_input_dev(&mouse->dev);
|
||||
input_dev->name = dev->product_name;
|
||||
input_dev->id.bustype = BUS_MAPLE;
|
||||
|
||||
mouse->dev.private = mouse;
|
||||
mouse->dev.open = dc_mouse_open;
|
||||
mouse->dev.close = dc_mouse_close;
|
||||
mouse->dev.event = NULL;
|
||||
|
||||
mouse->dev.name = dev->product_name;
|
||||
mouse->dev.id.bustype = BUS_MAPLE;
|
||||
|
||||
input_register_device(&mouse->dev);
|
||||
input_register_device(input_dev);
|
||||
|
||||
maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE);
|
||||
|
||||
printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, mouse->dev.name);
|
||||
printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, input_dev->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -96,10 +67,10 @@ static int dc_mouse_connect(struct maple_device *dev)
|
||||
|
||||
static void dc_mouse_disconnect(struct maple_device *dev)
|
||||
{
|
||||
struct dc_mouse *mouse = dev->private_data;
|
||||
struct input_dev *input_dev = dev->private_data;
|
||||
|
||||
input_unregister_device(&mouse->dev);
|
||||
kfree(mouse);
|
||||
input_unregister_device(input_dev);
|
||||
kfree(input_dev);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Copyright (c) 2000-2001 Vojtech Pavlik
|
||||
*
|
||||
* Based on the work of:
|
||||
* Alan Cox Robin O'Leary
|
||||
* Alan Cox Robin O'Leary
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -56,7 +56,6 @@ static int pc110pad_io = 0x15e0;
|
||||
static struct input_dev pc110pad_dev;
|
||||
static int pc110pad_data[3];
|
||||
static int pc110pad_count;
|
||||
static int pc110pad_used;
|
||||
|
||||
static char *pc110pad_name = "IBM PC110 TouchPad";
|
||||
static char *pc110pad_phys = "isa15e0/input0";
|
||||
@@ -74,7 +73,7 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
|
||||
|
||||
if (pc110pad_count < 3)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
|
||||
input_regs(&pc110pad_dev, regs);
|
||||
input_report_key(&pc110pad_dev, BTN_TOUCH,
|
||||
pc110pad_data[0] & 0x01);
|
||||
@@ -90,15 +89,11 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
|
||||
|
||||
static void pc110pad_close(struct input_dev *dev)
|
||||
{
|
||||
if (!--pc110pad_used)
|
||||
outb(PC110PAD_OFF, pc110pad_io + 2);
|
||||
outb(PC110PAD_OFF, pc110pad_io + 2);
|
||||
}
|
||||
|
||||
static int pc110pad_open(struct input_dev *dev)
|
||||
{
|
||||
if (pc110pad_used++)
|
||||
return 0;
|
||||
|
||||
pc110pad_interrupt(0,NULL,NULL);
|
||||
pc110pad_interrupt(0,NULL,NULL);
|
||||
pc110pad_interrupt(0,NULL,NULL);
|
||||
@@ -145,7 +140,7 @@ static int __init pc110pad_init(void)
|
||||
|
||||
pc110pad_dev.absmax[ABS_X] = 0x1ff;
|
||||
pc110pad_dev.absmax[ABS_Y] = 0x0ff;
|
||||
|
||||
|
||||
pc110pad_dev.open = pc110pad_open;
|
||||
pc110pad_dev.close = pc110pad_close;
|
||||
|
||||
@@ -156,17 +151,17 @@ static int __init pc110pad_init(void)
|
||||
pc110pad_dev.id.product = 0x0001;
|
||||
pc110pad_dev.id.version = 0x0100;
|
||||
|
||||
input_register_device(&pc110pad_dev);
|
||||
input_register_device(&pc110pad_dev);
|
||||
|
||||
printk(KERN_INFO "input: %s at %#x irq %d\n",
|
||||
pc110pad_name, pc110pad_io, pc110pad_irq);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void __exit pc110pad_exit(void)
|
||||
{
|
||||
input_unregister_device(&pc110pad_dev);
|
||||
input_unregister_device(&pc110pad_dev);
|
||||
|
||||
outb(PC110PAD_OFF, pc110pad_io + 2);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "synaptics.h"
|
||||
#include "logips2pp.h"
|
||||
#include "alps.h"
|
||||
#include "lifebook.h"
|
||||
|
||||
#define DRIVER_DESC "PS/2 mouse driver"
|
||||
|
||||
@@ -31,10 +32,9 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static unsigned int psmouse_max_proto = -1U;
|
||||
static unsigned int psmouse_max_proto = PSMOUSE_AUTO;
|
||||
static int psmouse_set_maxproto(const char *val, struct kernel_param *kp);
|
||||
static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp);
|
||||
static char *psmouse_proto_abbrev[] = { NULL, "bare", NULL, NULL, NULL, "imps", "exps", NULL, NULL, NULL };
|
||||
#define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int)
|
||||
#define param_set_proto_abbrev psmouse_set_maxproto
|
||||
#define param_get_proto_abbrev psmouse_get_maxproto
|
||||
@@ -57,6 +57,7 @@ static unsigned int psmouse_resetafter;
|
||||
module_param_named(resetafter, psmouse_resetafter, uint, 0644);
|
||||
MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
|
||||
|
||||
PSMOUSE_DEFINE_ATTR(protocol);
|
||||
PSMOUSE_DEFINE_ATTR(rate);
|
||||
PSMOUSE_DEFINE_ATTR(resolution);
|
||||
PSMOUSE_DEFINE_ATTR(resetafter);
|
||||
@@ -67,7 +68,23 @@ __obsolete_setup("psmouse_smartscroll=");
|
||||
__obsolete_setup("psmouse_resetafter=");
|
||||
__obsolete_setup("psmouse_rate=");
|
||||
|
||||
static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "ThinkPS/2", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2" };
|
||||
/*
|
||||
* psmouse_sem protects all operations changing state of mouse
|
||||
* (connecting, disconnecting, changing rate or resolution via
|
||||
* sysfs). We could use a per-device semaphore but since there
|
||||
* rarely more than one PS/2 mouse connected and since semaphore
|
||||
* is taken in "slow" paths it is not worth it.
|
||||
*/
|
||||
static DECLARE_MUTEX(psmouse_sem);
|
||||
|
||||
struct psmouse_protocol {
|
||||
enum psmouse_type type;
|
||||
char *name;
|
||||
char *alias;
|
||||
int maxproto;
|
||||
int (*detect)(struct psmouse *, int);
|
||||
int (*init)(struct psmouse *);
|
||||
};
|
||||
|
||||
/*
|
||||
* psmouse_process_byte() analyzes the PS/2 data stream and reports
|
||||
@@ -407,12 +424,15 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties)
|
||||
*/
|
||||
static int ps2bare_detect(struct psmouse *psmouse, int set_properties)
|
||||
{
|
||||
if (!psmouse->vendor) psmouse->vendor = "Generic";
|
||||
if (!psmouse->name) psmouse->name = "Mouse";
|
||||
if (set_properties) {
|
||||
if (!psmouse->vendor) psmouse->vendor = "Generic";
|
||||
if (!psmouse->name) psmouse->name = "Mouse";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* psmouse_extensions() probes for any extensions to the basic PS/2 protocol
|
||||
* the mouse may have.
|
||||
@@ -423,6 +443,17 @@ static int psmouse_extensions(struct psmouse *psmouse,
|
||||
{
|
||||
int synaptics_hardware = 0;
|
||||
|
||||
/*
|
||||
* We always check for lifebook because it does not disturb mouse
|
||||
* (it only checks DMI information).
|
||||
*/
|
||||
if (lifebook_detect(psmouse, set_properties) == 0) {
|
||||
if (max_proto > PSMOUSE_IMEX) {
|
||||
if (!set_properties || lifebook_init(psmouse) == 0)
|
||||
return PSMOUSE_LIFEBOOK;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Try Kensington ThinkingMouse (we try first, because synaptics probe
|
||||
* upsets the thinkingmouse).
|
||||
@@ -506,6 +537,103 @@ static int psmouse_extensions(struct psmouse *psmouse,
|
||||
return PSMOUSE_PS2;
|
||||
}
|
||||
|
||||
static struct psmouse_protocol psmouse_protocols[] = {
|
||||
{
|
||||
.type = PSMOUSE_PS2,
|
||||
.name = "PS/2",
|
||||
.alias = "bare",
|
||||
.maxproto = 1,
|
||||
.detect = ps2bare_detect,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_PS2PP,
|
||||
.name = "PS2++",
|
||||
.alias = "logitech",
|
||||
.detect = ps2pp_init,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_THINKPS,
|
||||
.name = "ThinkPS/2",
|
||||
.alias = "thinkps",
|
||||
.detect = thinking_detect,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_GENPS,
|
||||
.name = "GenPS/2",
|
||||
.alias = "genius",
|
||||
.detect = genius_detect,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_IMPS,
|
||||
.name = "ImPS/2",
|
||||
.alias = "imps",
|
||||
.maxproto = 1,
|
||||
.detect = intellimouse_detect,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_IMEX,
|
||||
.name = "ImExPS/2",
|
||||
.alias = "exps",
|
||||
.maxproto = 1,
|
||||
.detect = im_explorer_detect,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_SYNAPTICS,
|
||||
.name = "SynPS/2",
|
||||
.alias = "synaptics",
|
||||
.detect = synaptics_detect,
|
||||
.init = synaptics_init,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_ALPS,
|
||||
.name = "AlpsPS/2",
|
||||
.alias = "alps",
|
||||
.detect = alps_detect,
|
||||
.init = alps_init,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_LIFEBOOK,
|
||||
.name = "LBPS/2",
|
||||
.alias = "lifebook",
|
||||
.init = lifebook_init,
|
||||
},
|
||||
{
|
||||
.type = PSMOUSE_AUTO,
|
||||
.name = "auto",
|
||||
.alias = "any",
|
||||
.maxproto = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++)
|
||||
if (psmouse_protocols[i].type == type)
|
||||
return &psmouse_protocols[i];
|
||||
|
||||
WARN_ON(1);
|
||||
return &psmouse_protocols[0];
|
||||
}
|
||||
|
||||
static struct psmouse_protocol *psmouse_protocol_by_name(const char *name, size_t len)
|
||||
{
|
||||
struct psmouse_protocol *p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) {
|
||||
p = &psmouse_protocols[i];
|
||||
|
||||
if ((strlen(p->name) == len && !strncmp(p->name, name, len)) ||
|
||||
(strlen(p->alias) == len && !strncmp(p->alias, name, len)))
|
||||
return &psmouse_protocols[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* psmouse_probe() probes for a PS/2 mouse.
|
||||
*/
|
||||
@@ -653,30 +781,84 @@ static void psmouse_cleanup(struct serio *serio)
|
||||
|
||||
static void psmouse_disconnect(struct serio *serio)
|
||||
{
|
||||
struct psmouse *psmouse, *parent;
|
||||
struct psmouse *psmouse, *parent = NULL;
|
||||
|
||||
psmouse = serio_get_drvdata(serio);
|
||||
|
||||
device_remove_file(&serio->dev, &psmouse_attr_protocol);
|
||||
device_remove_file(&serio->dev, &psmouse_attr_rate);
|
||||
device_remove_file(&serio->dev, &psmouse_attr_resolution);
|
||||
device_remove_file(&serio->dev, &psmouse_attr_resetafter);
|
||||
|
||||
psmouse = serio_get_drvdata(serio);
|
||||
down(&psmouse_sem);
|
||||
|
||||
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
if (parent->pt_deactivate)
|
||||
parent->pt_deactivate(parent);
|
||||
psmouse_deactivate(parent);
|
||||
}
|
||||
|
||||
if (psmouse->disconnect)
|
||||
psmouse->disconnect(psmouse);
|
||||
|
||||
if (parent && parent->pt_deactivate)
|
||||
parent->pt_deactivate(parent);
|
||||
|
||||
psmouse_set_state(psmouse, PSMOUSE_IGNORE);
|
||||
|
||||
input_unregister_device(&psmouse->dev);
|
||||
serio_close(serio);
|
||||
serio_set_drvdata(serio, NULL);
|
||||
kfree(psmouse);
|
||||
|
||||
if (parent)
|
||||
psmouse_activate(parent);
|
||||
|
||||
up(&psmouse_sem);
|
||||
}
|
||||
|
||||
static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto)
|
||||
{
|
||||
memset(&psmouse->dev, 0, sizeof(struct input_dev));
|
||||
|
||||
init_input_dev(&psmouse->dev);
|
||||
|
||||
psmouse->dev.private = psmouse;
|
||||
psmouse->dev.dev = &psmouse->ps2dev.serio->dev;
|
||||
|
||||
psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
|
||||
psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
|
||||
psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
|
||||
|
||||
psmouse->set_rate = psmouse_set_rate;
|
||||
psmouse->set_resolution = psmouse_set_resolution;
|
||||
psmouse->protocol_handler = psmouse_process_byte;
|
||||
psmouse->pktsize = 3;
|
||||
|
||||
if (proto && (proto->detect || proto->init)) {
|
||||
if (proto->detect && proto->detect(psmouse, 1) < 0)
|
||||
return -1;
|
||||
|
||||
if (proto->init && proto->init(psmouse) < 0)
|
||||
return -1;
|
||||
|
||||
psmouse->type = proto->type;
|
||||
}
|
||||
else
|
||||
psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
|
||||
|
||||
sprintf(psmouse->devname, "%s %s %s",
|
||||
psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);
|
||||
|
||||
psmouse->dev.name = psmouse->devname;
|
||||
psmouse->dev.phys = psmouse->phys;
|
||||
psmouse->dev.id.bustype = BUS_I8042;
|
||||
psmouse->dev.id.vendor = 0x0002;
|
||||
psmouse->dev.id.product = psmouse->type;
|
||||
psmouse->dev.id.version = psmouse->model;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -688,6 +870,8 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
|
||||
struct psmouse *psmouse, *parent = NULL;
|
||||
int retval;
|
||||
|
||||
down(&psmouse_sem);
|
||||
|
||||
/*
|
||||
* If this is a pass-through port deactivate parent so the device
|
||||
* connected to this port can be successfully identified
|
||||
@@ -697,20 +881,14 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
|
||||
psmouse_deactivate(parent);
|
||||
}
|
||||
|
||||
if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL))) {
|
||||
if (!(psmouse = kcalloc(1, sizeof(struct psmouse), GFP_KERNEL))) {
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memset(psmouse, 0, sizeof(struct psmouse));
|
||||
|
||||
ps2_init(&psmouse->ps2dev, serio);
|
||||
sprintf(psmouse->phys, "%s/input0", serio->phys);
|
||||
psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
|
||||
psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
|
||||
psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
|
||||
psmouse->dev.private = psmouse;
|
||||
psmouse->dev.dev = &serio->dev;
|
||||
|
||||
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
|
||||
|
||||
serio_set_drvdata(serio, psmouse);
|
||||
@@ -734,25 +912,10 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
|
||||
psmouse->resolution = psmouse_resolution;
|
||||
psmouse->resetafter = psmouse_resetafter;
|
||||
psmouse->smartscroll = psmouse_smartscroll;
|
||||
psmouse->set_rate = psmouse_set_rate;
|
||||
psmouse->set_resolution = psmouse_set_resolution;
|
||||
psmouse->protocol_handler = psmouse_process_byte;
|
||||
psmouse->pktsize = 3;
|
||||
|
||||
psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1);
|
||||
|
||||
sprintf(psmouse->devname, "%s %s %s",
|
||||
psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
|
||||
|
||||
psmouse->dev.name = psmouse->devname;
|
||||
psmouse->dev.phys = psmouse->phys;
|
||||
psmouse->dev.id.bustype = BUS_I8042;
|
||||
psmouse->dev.id.vendor = 0x0002;
|
||||
psmouse->dev.id.product = psmouse->type;
|
||||
psmouse->dev.id.version = psmouse->model;
|
||||
psmouse_switch_protocol(psmouse, NULL);
|
||||
|
||||
input_register_device(&psmouse->dev);
|
||||
|
||||
printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
|
||||
|
||||
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
|
||||
@@ -762,6 +925,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
|
||||
if (parent && parent->pt_activate)
|
||||
parent->pt_activate(parent);
|
||||
|
||||
device_create_file(&serio->dev, &psmouse_attr_protocol);
|
||||
device_create_file(&serio->dev, &psmouse_attr_rate);
|
||||
device_create_file(&serio->dev, &psmouse_attr_resolution);
|
||||
device_create_file(&serio->dev, &psmouse_attr_resetafter);
|
||||
@@ -771,10 +935,11 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
|
||||
retval = 0;
|
||||
|
||||
out:
|
||||
/* If this is a pass-through port the parent awaits to be activated */
|
||||
/* If this is a pass-through port the parent needs to be re-activated */
|
||||
if (parent)
|
||||
psmouse_activate(parent);
|
||||
|
||||
up(&psmouse_sem);
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -791,6 +956,8 @@ static int psmouse_reconnect(struct serio *serio)
|
||||
return -1;
|
||||
}
|
||||
|
||||
down(&psmouse_sem);
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
psmouse_deactivate(parent);
|
||||
@@ -823,6 +990,7 @@ out:
|
||||
if (parent)
|
||||
psmouse_activate(parent);
|
||||
|
||||
up(&psmouse_sem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -893,26 +1061,109 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
|
||||
|
||||
if (serio->drv != &psmouse_drv) {
|
||||
retval = -ENODEV;
|
||||
goto out;
|
||||
goto out_unpin;
|
||||
}
|
||||
|
||||
retval = down_interruptible(&psmouse_sem);
|
||||
if (retval)
|
||||
goto out_unpin;
|
||||
|
||||
if (psmouse->state == PSMOUSE_IGNORE) {
|
||||
retval = -ENODEV;
|
||||
goto out_up;
|
||||
}
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
psmouse_deactivate(parent);
|
||||
}
|
||||
|
||||
psmouse_deactivate(psmouse);
|
||||
|
||||
retval = handler(psmouse, buf, count);
|
||||
|
||||
psmouse_activate(psmouse);
|
||||
if (retval != -ENODEV)
|
||||
psmouse_activate(psmouse);
|
||||
|
||||
if (parent)
|
||||
psmouse_activate(parent);
|
||||
|
||||
out:
|
||||
out_up:
|
||||
up(&psmouse_sem);
|
||||
out_unpin:
|
||||
serio_unpin_driver(serio);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name);
|
||||
}
|
||||
|
||||
static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count)
|
||||
{
|
||||
struct serio *serio = psmouse->ps2dev.serio;
|
||||
struct psmouse *parent = NULL;
|
||||
struct psmouse_protocol *proto;
|
||||
int retry = 0;
|
||||
|
||||
if (!(proto = psmouse_protocol_by_name(buf, count)))
|
||||
return -EINVAL;
|
||||
|
||||
if (psmouse->type == proto->type)
|
||||
return count;
|
||||
|
||||
while (serio->child) {
|
||||
if (++retry > 3) {
|
||||
printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
up(&psmouse_sem);
|
||||
serio_unpin_driver(serio);
|
||||
serio_unregister_child_port(serio);
|
||||
serio_pin_driver_uninterruptible(serio);
|
||||
down(&psmouse_sem);
|
||||
|
||||
if (serio->drv != &psmouse_drv)
|
||||
return -ENODEV;
|
||||
|
||||
if (psmouse->type == proto->type)
|
||||
return count; /* switched by other thread */
|
||||
}
|
||||
|
||||
if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
|
||||
parent = serio_get_drvdata(serio->parent);
|
||||
if (parent->pt_deactivate)
|
||||
parent->pt_deactivate(parent);
|
||||
}
|
||||
|
||||
if (psmouse->disconnect)
|
||||
psmouse->disconnect(psmouse);
|
||||
|
||||
psmouse_set_state(psmouse, PSMOUSE_IGNORE);
|
||||
input_unregister_device(&psmouse->dev);
|
||||
|
||||
psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
|
||||
|
||||
if (psmouse_switch_protocol(psmouse, proto) < 0) {
|
||||
psmouse_reset(psmouse);
|
||||
/* default to PSMOUSE_PS2 */
|
||||
psmouse_switch_protocol(psmouse, &psmouse_protocols[0]);
|
||||
}
|
||||
|
||||
psmouse_initialize(psmouse);
|
||||
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
|
||||
|
||||
input_register_device(&psmouse->dev);
|
||||
printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
|
||||
|
||||
if (parent && parent->pt_activate)
|
||||
parent->pt_activate(parent);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", psmouse->rate);
|
||||
@@ -969,34 +1220,26 @@ static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char *
|
||||
|
||||
static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
|
||||
{
|
||||
int i;
|
||||
struct psmouse_protocol *proto;
|
||||
|
||||
if (!val)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strncmp(val, "any", 3)) {
|
||||
*((unsigned int *)kp->arg) = -1U;
|
||||
return 0;
|
||||
}
|
||||
proto = psmouse_protocol_by_name(val, strlen(val));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(psmouse_proto_abbrev); i++) {
|
||||
if (!psmouse_proto_abbrev[i])
|
||||
continue;
|
||||
if (!proto || !proto->maxproto)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strncmp(val, psmouse_proto_abbrev[i], strlen(psmouse_proto_abbrev[i]))) {
|
||||
*((unsigned int *)kp->arg) = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*((unsigned int *)kp->arg) = proto->type;
|
||||
|
||||
return -EINVAL; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
|
||||
{
|
||||
return sprintf(buffer, "%s\n",
|
||||
psmouse_max_proto < ARRAY_SIZE(psmouse_proto_abbrev) ?
|
||||
psmouse_proto_abbrev[psmouse_max_proto] : "any");
|
||||
int type = *((unsigned int *)kp->arg);
|
||||
|
||||
return sprintf(buffer, "%s\n", psmouse_protocol_by_type(type)->name);
|
||||
}
|
||||
|
||||
static int __init psmouse_init(void)
|
||||
|
||||
@@ -77,6 +77,8 @@ enum psmouse_type {
|
||||
PSMOUSE_IMEX,
|
||||
PSMOUSE_SYNAPTICS,
|
||||
PSMOUSE_ALPS,
|
||||
PSMOUSE_LIFEBOOK,
|
||||
PSMOUSE_AUTO /* This one should always be last */
|
||||
};
|
||||
|
||||
int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command);
|
||||
@@ -99,7 +101,7 @@ static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute
|
||||
{ \
|
||||
return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \
|
||||
} \
|
||||
static struct device_attribute psmouse_attr_##_name = \
|
||||
static struct device_attribute psmouse_attr_##_name = \
|
||||
__ATTR(_name, S_IWUSR | S_IRUGO, \
|
||||
psmouse_do_show_##_name, psmouse_do_set_##_name);
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
|
||||
b = (short) (__raw_readl(0xe0310000) ^ 0x70);
|
||||
|
||||
dx = x - rpcmouse_lastx;
|
||||
dy = y - rpcmouse_lasty;
|
||||
dy = y - rpcmouse_lasty;
|
||||
|
||||
rpcmouse_lastx = x;
|
||||
rpcmouse_lasty = y;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers)
|
||||
* DEC VSXXX-GA mouse (rectangular mouse, with ball)
|
||||
* DEC VSXXX-AB tablet (digitizer with hair cross or stylus)
|
||||
* DEC VSXXX-GA mouse (rectangular mouse, with ball)
|
||||
* DEC VSXXX-AB tablet (digitizer with hair cross or stylus)
|
||||
*
|
||||
* Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de>
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user