Commit a4ba6e26 authored by Peter Osterlund's avatar Peter Osterlund

Added (untested) support for ALPS touchpads using the 2.4

linux kernel.
parent f1146f67
......@@ -52,8 +52,8 @@ CC = gcc
LDCOMBINEFLAGS = -r
SRCS = synaptics.c ps2comm.c eventcomm.c psmcomm.c
OBJS = synaptics.o ps2comm.o eventcomm.o psmcomm.o
SRCS = synaptics.c ps2comm.c eventcomm.c psmcomm.c alpscomm.c
OBJS = synaptics.o ps2comm.o eventcomm.o psmcomm.o alpscomm.o
.c.o:
$(RM) $@
......@@ -100,6 +100,7 @@ synaptics.o : synaptics.h synproto.h Makefile
ps2comm.o : ps2comm.h synproto.h synaptics.h
eventcomm.o : eventcomm.h linux_input.h synproto.h synaptics.h
psmcomm.o : freebsd_mouse.h psmcomm.h synproto.h synaptics.h ps2comm.h
alpscomm.o : alpscomm.h ps2comm.h synproto.h synaptics.h
synclient.o : synaptics.h
syndaemon.o : synaptics.h
......@@ -117,7 +118,7 @@ distribution : synaptics-$(VERSION).tar.bz2
ALLFILES = COMPATIBILITY FILES INSTALL INSTALL.DE INSTALL.FR LICENSE Makefile \
NEWS README README.alps TODO Xincludes/ alps.patch linux_input.h \
pc_keyb.c.diff.2.4.3 \
synproto.h ps2comm.c ps2comm.h eventcomm.c eventcomm.h \
synproto.h ps2comm.c ps2comm.h eventcomm.c eventcomm.h alpscomm.c alpscomm.h \
psmcomm.c psmcomm.h freebsd_mouse.h \
synaptics.c synaptics.h synaptics.spec \
synclient.c syndaemon.c
......
/* Copyright (C) 2001 Stefan Gmeiner <riddlebox@freesurf.ch>
*
* Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
* Copyright (c) 2003-2004 Peter Osterlund <petero2@telia.com>
*
* 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 (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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include "alpscomm.h"
#include "synproto.h"
#include "synaptics.h"
#include <xf86.h>
/*
* send the ALPSinit sequence, ie 4 consecutive "disable"s before the "enable"
*/
static void
ALPS_initialize(int fd)
{
ps2_synaptics_disable_device(fd);
ps2_synaptics_disable_device(fd);
ps2_synaptics_disable_device(fd);
ps2_synaptics_disable_device(fd);
ps2_synaptics_enable_device(fd);
}
static void
ALPSDeviceOnHook(LocalDevicePtr local)
{
}
static void
ALPSDeviceOffHook(LocalDevicePtr local)
{
}
static Bool
ALPSQueryHardware(LocalDevicePtr local, struct SynapticsHwInfo *synhw)
{
ALPS_initialize(local->fd);
return TRUE;
}
static Bool
ALPS_packet_ok(struct CommData *comm)
{
/* ALPS absolute mode packets start with 0b11111mrl */
if ((comm->protoBuf[0] & 0xf8) == 0xf8)
return TRUE;
return FALSE;
}
static Bool
ALPS_get_packet(struct CommData *comm)
{
int c;
while ((c = XisbRead(comm->buffer)) >= 0) {
unsigned char u = (unsigned char)c;
comm->protoBuf[comm->protoBufTail++] = u;
/* Check that we have a valid packet. If not, we are out of sync,
so we throw away the first byte in the packet.*/
if (comm->protoBufTail >= 6) {
if (!ALPS_packet_ok(comm)) {
int i;
for (i = 0; i < comm->protoBufTail - 1; i++)
comm->protoBuf[i] = comm->protoBuf[i + 1];
comm->protoBufTail--;
}
}
if (comm->protoBufTail >= 6) { /* Full packet received */
comm->protoBufTail = 0;
return TRUE;
}
}
return FALSE;
}
/*
* ALPS abolute Mode
* byte 0: 1 1 1 1 1 mid0 rig0 lef0
* byte 1: 0 x6 x5 x4 x3 x2 x1 x0
* byte 2: 0 x10 x9 x8 x7 up1 fin ges
* byte 3: 0 y9 y8 y7 1 mid1 rig1 lef1
* byte 4: 0 y6 y5 y4 y3 y2 y1 y0
* byte 5: 0 z6 z5 z4 z3 z2 z1 z0
*
* On a dualpoint, {mid,rig,lef}0 are the stick, 1 are the pad.
* We just 'or' them together for now.
*
* The touchpad on an 'Acer Aspire' has 4 buttons:
* left,right,up,down.
* This device always sets {mid,rig,lef}0 to 1 and
* reflects left,right,down,up in lef1,rig1,mid1,up1.
*/
static void
ALPS_process_packet(unsigned char *packet, struct SynapticsHwState *hw)
{
int x, y, z;
int left = 0, right = 0, middle = 0;
x = (packet[1] & 0x7f) | ((packet[2] & 0x78)<<(7-3));
y = (packet[4] & 0x7f) | ((packet[3] & 0x70)<<(7-4));
z = packet[5];
if (z > 0) {
hw->x = x;
hw->y = y;
}
hw->z = z;
hw->numFingers = (z > 0) ? 1 : 0;
hw->fingerWidth = 5;
left |= (packet[2] ) & 1;
left |= (packet[3] ) & 1;
right |= (packet[3] >> 1) & 1;
if (packet[0] == 0xff) {
int back = (packet[3] >> 2) & 1;
int forward = (packet[2] >> 2) & 1;
if (back && forward) {
middle = 1;
back = 0;
forward = 0;
}
hw->down = back;
hw->up = forward;
} else {
left |= (packet[0] ) & 1;
right |= (packet[0] >> 1) & 1;
middle |= (packet[0] >> 2) & 1;
middle |= (packet[3] >> 2) & 1;
}
hw->left = left;
hw->right = right;
hw->middle = middle;
}
static Bool
ALPSReadHwState(LocalDevicePtr local, struct SynapticsHwInfo *synhw,
struct SynapticsProtocolOperations *proto_ops,
struct CommData *comm, struct SynapticsHwState *hwRet)
{
unsigned char *buf = comm->protoBuf;
struct SynapticsHwState *hw = &(comm->hwState);
if (!ALPS_get_packet(comm))
return FALSE;
memset(hw, 0, sizeof(*hw));
ALPS_process_packet(buf, hw);
*hwRet = *hw;
return TRUE;
}
static Bool
ALPSAutoDevProbe(LocalDevicePtr local)
{
return FALSE;
}
struct SynapticsProtocolOperations alps_proto_operations = {
ALPSDeviceOnHook,
ALPSDeviceOffHook,
ALPSQueryHardware,
ALPSReadHwState,
ALPSAutoDevProbe
};
/*
* ALPS touchpad PS/2 mouse driver
*
* Copyright (c) 2004 Peter Osterlund <petero2@telia.com>
*
* 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 (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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _ALPSCOMM_H_
#define _ALPSCOMM_H_
#include "ps2comm.h"
#endif /* _ALPSCOMM_H_ */
......@@ -380,13 +380,13 @@ ps2_synaptics_identify(int fd, struct SynapticsHwInfo *synhw)
return FALSE;
}
static Bool
Bool
ps2_synaptics_enable_device(int fd)
{
return ps2_putbyte(fd, PS2_CMD_ENABLE);
}
static Bool
Bool
ps2_synaptics_disable_device(int fd)
{
xf86FlushInput(fd);
......
......@@ -51,6 +51,9 @@
typedef unsigned char byte;
Bool ps2_synaptics_enable_device(int fd);
Bool ps2_synaptics_disable_device(int fd);
struct SynapticsHwInfo;
void ps2_print_ident(const struct SynapticsHwInfo *synhw);
......
......@@ -177,6 +177,8 @@ SetDeviceAndProtocol(LocalDevicePtr local)
proto = SYN_PROTO_EVENT;
} else if (str_par && !strcmp(str_par, "psm")) {
proto = SYN_PROTO_PSM;
} else if (str_par && !strcmp(str_par, "alps")) {
proto = SYN_PROTO_ALPS;
} else { /* default to auto-dev */
if (event_proto_operations.AutoDevProbe(local))
proto = SYN_PROTO_EVENT;
......@@ -191,6 +193,9 @@ SetDeviceAndProtocol(LocalDevicePtr local)
case SYN_PROTO_PSM:
priv->proto_ops = &psm_proto_operations;
break;
case SYN_PROTO_ALPS:
priv->proto_ops = &alps_proto_operations;
break;
}
}
......
......@@ -67,7 +67,8 @@ struct CommData {
enum SynapticsProtocol {
SYN_PROTO_PSAUX, /* Raw psaux device */
SYN_PROTO_EVENT, /* Linux kernel event interface */
SYN_PROTO_PSM /* FreeBSD psm driver */
SYN_PROTO_PSM, /* FreeBSD psm driver */
SYN_PROTO_ALPS /* ALPS touchpad protocol */
};
struct SynapticsHwInfo;
......@@ -86,6 +87,7 @@ struct SynapticsProtocolOperations {
extern struct SynapticsProtocolOperations psaux_proto_operations;
extern struct SynapticsProtocolOperations event_proto_operations;
extern struct SynapticsProtocolOperations psm_proto_operations;
extern struct SynapticsProtocolOperations alps_proto_operations;
#endif /* _SYNPROTO_H_ */
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