Commit e76b0d3f authored by Peter Osterlund's avatar Peter Osterlund Committed by Vojtech Pavlik

input: Add Synaptics touchpad absolute mode support.

parent f739babf
...@@ -28,6 +28,19 @@ config MOUSE_PS2 ...@@ -28,6 +28,19 @@ config MOUSE_PS2
The module will be called psmouse. If you want to compile it as a The module will be called psmouse. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. module, say M here and read <file:Documentation/modules.txt>.
config MOUSE_PS2_SYNAPTICS
bool "Synaptics TouchPad"
default n
depends on INPUT && INPUT_MOUSE && SERIO && MOUSE_PS2
---help---
Say Y here if you have a Synaptics TouchPad connected to your system.
This touchpad is found on many modern laptop computers.
Note that you also need a user space driver to interpret the data
generated by the kernel. A compatible driver for XFree86 is available
from http://...
If unsure, say Y.
config MOUSE_SERIAL config MOUSE_SERIAL
tristate "Serial mouse" tristate "Serial mouse"
depends on INPUT && INPUT_MOUSE && SERIO depends on INPUT && INPUT_MOUSE && SERIO
......
...@@ -13,3 +13,8 @@ obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o ...@@ -13,3 +13,8 @@ obj-$(CONFIG_MOUSE_PC110PAD) += pc110pad.o
obj-$(CONFIG_MOUSE_PC9800) += 98busmouse.o obj-$(CONFIG_MOUSE_PC9800) += 98busmouse.o
obj-$(CONFIG_MOUSE_PS2) += psmouse.o obj-$(CONFIG_MOUSE_PS2) += psmouse.o
obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o
psmouse-objs := psmouse-base.o
ifeq ($(CONFIG_MOUSE_PS2_SYNAPTICS),y)
psmouse-objs += synaptics.o
endif
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/serio.h> #include <linux/serio.h>
#include <linux/init.h> #include <linux/init.h>
#include "psmouse.h"
#include "synaptics.h"
MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("PS/2 mouse driver"); MODULE_DESCRIPTION("PS/2 mouse driver");
...@@ -25,48 +27,7 @@ MODULE_LICENSE("GPL"); ...@@ -25,48 +27,7 @@ MODULE_LICENSE("GPL");
static int psmouse_noext; static int psmouse_noext;
#define PSMOUSE_CMD_SETSCALE11 0x00e6 static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2", "Synaptics"};
#define PSMOUSE_CMD_SETRES 0x10e8
#define PSMOUSE_CMD_GETINFO 0x03e9
#define PSMOUSE_CMD_SETSTREAM 0x00ea
#define PSMOUSE_CMD_POLL 0x03eb
#define PSMOUSE_CMD_GETID 0x02f2
#define PSMOUSE_CMD_SETRATE 0x10f3
#define PSMOUSE_CMD_ENABLE 0x00f4
#define PSMOUSE_CMD_RESET_DIS 0x00f6
#define PSMOUSE_CMD_RESET_BAT 0x02ff
#define PSMOUSE_RET_BAT 0xaa
#define PSMOUSE_RET_ACK 0xfa
#define PSMOUSE_RET_NAK 0xfe
struct psmouse {
struct input_dev dev;
struct serio *serio;
char *vendor;
char *name;
unsigned char cmdbuf[8];
unsigned char packet[8];
unsigned char cmdcnt;
unsigned char pktcnt;
unsigned char type;
unsigned char model;
unsigned long last;
char acking;
volatile char ack;
char error;
char devname[64];
char phys[32];
};
#define PSMOUSE_PS2 1
#define PSMOUSE_PS2PP 2
#define PSMOUSE_PS2TPP 3
#define PSMOUSE_GENPS 4
#define PSMOUSE_IMPS 5
#define PSMOUSE_IMEX 6
static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2" };
/* /*
* psmouse_process_packet() anlyzes the PS/2 mouse packet contents and * psmouse_process_packet() anlyzes the PS/2 mouse packet contents and
...@@ -209,6 +170,16 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, ...@@ -209,6 +170,16 @@ static irqreturn_t psmouse_interrupt(struct serio *serio,
goto out; goto out;
} }
if (psmouse->pktcnt == 1 && psmouse->type == PSMOUSE_SYNAPTICS) {
/*
* The synaptics driver has its own resync logic,
* so it needs to receive all bytes one at a time.
*/
synaptics_process_byte(psmouse, regs);
psmouse->pktcnt = 0;
goto out;
}
if (psmouse->pktcnt == 1 && psmouse->packet[0] == PSMOUSE_RET_BAT) { if (psmouse->pktcnt == 1 && psmouse->packet[0] == PSMOUSE_RET_BAT) {
serio_rescan(serio); serio_rescan(serio);
goto out; goto out;
...@@ -244,7 +215,7 @@ static int psmouse_sendbyte(struct psmouse *psmouse, unsigned char byte) ...@@ -244,7 +215,7 @@ static int psmouse_sendbyte(struct psmouse *psmouse, unsigned char byte)
* then waits for the response and puts it in the param array. * then waits for the response and puts it in the param array.
*/ */
static int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command) int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
{ {
int timeout = 500000; /* 500 msec */ int timeout = 500000; /* 500 msec */
int send = (command >> 12) & 0xf; int send = (command >> 12) & 0xf;
...@@ -343,12 +314,12 @@ static int psmouse_extensions(struct psmouse *psmouse) ...@@ -343,12 +314,12 @@ static int psmouse_extensions(struct psmouse *psmouse)
psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO); psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
if (param[1] == 0x47) { if (param[1] == 0x47) {
/* We could do more here. But it's sufficient just psmouse->vendor = "Synaptics";
to stop the subsequent probes from screwing the psmouse->name = "TouchPad";
thing up. */ if (!synaptics_init(psmouse))
psmouse->vendor = "Synaptics"; return PSMOUSE_SYNAPTICS;
psmouse->name = "TouchPad"; else
return PSMOUSE_PS2; return PSMOUSE_PS2;
} }
/* /*
...@@ -598,6 +569,7 @@ static void psmouse_disconnect(struct serio *serio) ...@@ -598,6 +569,7 @@ static void psmouse_disconnect(struct serio *serio)
struct psmouse *psmouse = serio->private; struct psmouse *psmouse = serio->private;
input_unregister_device(&psmouse->dev); input_unregister_device(&psmouse->dev);
serio_close(serio); serio_close(serio);
synaptics_disconnect(psmouse);
kfree(psmouse); kfree(psmouse);
} }
......
#ifndef _PSMOUSE_H
#define _PSMOUSE_H
#define PSMOUSE_CMD_SETSCALE11 0x00e6
#define PSMOUSE_CMD_SETRES 0x10e8
#define PSMOUSE_CMD_GETINFO 0x03e9
#define PSMOUSE_CMD_SETSTREAM 0x00ea
#define PSMOUSE_CMD_POLL 0x03eb
#define PSMOUSE_CMD_GETID 0x02f2
#define PSMOUSE_CMD_SETRATE 0x10f3
#define PSMOUSE_CMD_ENABLE 0x00f4
#define PSMOUSE_CMD_RESET_DIS 0x00f6
#define PSMOUSE_CMD_RESET_BAT 0x02ff
#define PSMOUSE_RET_BAT 0xaa
#define PSMOUSE_RET_ACK 0xfa
#define PSMOUSE_RET_NAK 0xfe
struct psmouse {
void *private;
struct input_dev dev;
struct serio *serio;
char *vendor;
char *name;
unsigned char cmdbuf[8];
unsigned char packet[8];
unsigned char cmdcnt;
unsigned char pktcnt;
unsigned char type;
unsigned char model;
unsigned long last;
char acking;
volatile char ack;
char error;
char devname[64];
char phys[32];
};
#define PSMOUSE_PS2 1
#define PSMOUSE_PS2PP 2
#define PSMOUSE_PS2TPP 3
#define PSMOUSE_GENPS 4
#define PSMOUSE_IMPS 5
#define PSMOUSE_IMEX 6
#define PSMOUSE_SYNAPTICS 7
int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command);
#endif /* _PSMOUSE_H */
This diff is collapsed.
/*
* Synaptics TouchPad PS/2 mouse driver
*
* 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 _SYNAPTICS_H
#define _SYNAPTICS_H
#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
extern int synaptics_init(struct psmouse *psmouse);
extern void synaptics_disconnect(struct psmouse *psmouse);
#else
static inline void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs) {}
static inline int synaptics_init(struct psmouse *psmouse) { return -1; }
static inline void synaptics_disconnect(struct psmouse *psmouse) {}
#endif
/* synaptics queries */
#define SYN_QUE_IDENTIFY 0x00
#define SYN_QUE_MODES 0x01
#define SYN_QUE_CAPABILITIES 0x02
#define SYN_QUE_MODEL 0x03
#define SYN_QUE_SERIAL_NUMBER_PREFIX 0x06
#define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07
#define SYN_QUE_RESOLUTION 0x08
/* synatics modes */
#define SYN_BIT_ABSOLUTE_MODE (1 << 7)
#define SYN_BIT_HIGH_RATE (1 << 6)
#define SYN_BIT_SLEEP_MODE (1 << 3)
#define SYN_BIT_DISABLE_GESTURE (1 << 2)
#define SYN_BIT_W_MODE (1 << 0)
/* synaptics model ID bits */
#define SYN_MODEL_ROT180(m) ((m) & (1 << 23))
#define SYN_MODEL_PORTRAIT(m) ((m) & (1 << 22))
#define SYN_MODEL_SENSOR(m) (((m) >> 16) & 0x3f)
#define SYN_MODEL_HARDWARE(m) (((m) >> 9) & 0x7f)
#define SYN_MODEL_NEWABS(m) ((m) & (1 << 7))
#define SYN_MODEL_PEN(m) ((m) & (1 << 6))
#define SYN_MODEL_SIMPLIC(m) ((m) & (1 << 5))
#define SYN_MODEL_GEOMETRY(m) ((m) & 0x0f)
/* synaptics capability bits */
#define SYN_CAP_EXTENDED(c) ((c) & (1 << 23))
#define SYN_CAP_SLEEP(c) ((c) & (1 << 4))
#define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3))
#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1))
#define SYN_CAP_PALMDETECT(c) ((c) & (1 << 0))
#define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47)
/* synaptics modes query bits */
#define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7))
#define SYN_MODE_RATE(m) ((m) & (1 << 6))
#define SYN_MODE_BAUD_SLEEP(m) ((m) & (1 << 3))
#define SYN_MODE_DISABLE_GESTURE(m) ((m) & (1 << 2))
#define SYN_MODE_PACKSIZE(m) ((m) & (1 << 1))
#define SYN_MODE_WMODE(m) ((m) & (1 << 0))
/* synaptics identify query bits */
#define SYN_ID_MODEL(i) (((i) >> 4) & 0x0f)
#define SYN_ID_MAJOR(i) ((i) & 0x0f)
#define SYN_ID_MINOR(i) (((i) >> 16) & 0xff)
#define SYN_ID_IS_SYNAPTICS(i) ((((i) >> 8) & 0xff) == 0x47)
/*
* A structure to describe the state of the touchpad hardware (buttons and pad)
*/
struct synaptics_hw_state {
int x;
int y;
int z;
int w;
int left;
int right;
int up;
int down;
};
struct synaptics_data {
/* Data read from the touchpad */
unsigned long int model_id; /* Model-ID */
unsigned long int capabilities; /* Capabilities */
unsigned long int identity; /* Identification */
/* Data for normal processing */
unsigned char proto_buf[6]; /* Buffer for Packet */
unsigned char last_byte; /* last received byte */
int inSync; /* Packets in sync */
int proto_buf_tail;
int old_w; /* Previous w value */
};
#endif /* _SYNAPTICS_H */
...@@ -530,6 +530,7 @@ struct input_absinfo { ...@@ -530,6 +530,7 @@ struct input_absinfo {
#define MSC_SERIAL 0x00 #define MSC_SERIAL 0x00
#define MSC_PULSELED 0x01 #define MSC_PULSELED 0x01
#define MSC_GESTURE 0x02
#define MSC_MAX 0x07 #define MSC_MAX 0x07
/* /*
......
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