blob: 73ad0791050344c8218fac95cfbe3d32d86a170a [file] [log] [blame]
/*
* Copyright © 1997 C. Scott Ananian
* Copyright © 1998-2000 Bruce Kalk
* Copyright © 2001 Stefan Gmeiner
* Copyright © 2002 Linuxcare Inc. David Kennedy
* Copyright © 2003 Fred Hucht
* Copyright © 2004 Arne Schwabe
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of Red Hat
* not be used in advertising or publicity pertaining to distribution
* of the software without specific, written prior permission. Red
* Hat makes no representations about the suitability of this software
* for any purpose. It is provided "as is" without express or implied
* warranty.
*
* THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
* NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Authors:
* Stefan Gmeiner (riddlebox@freesurf.ch)
* C. Scott Ananian (cananian@alumni.priceton.edu)
* Bruce Kalk (kall@compass.com)
* Linuxcare Inc. David Kennedy (dkennedy@linuxcare.com)
* Fred Hucht (fred@thp.Uni-Duisburg.de)
* Arne Schwabe <schwabe@uni-paderborn.de>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <xorg-server.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mouse.h>
#include <errno.h>
#include <string.h>
#include "synproto.h"
#include "synaptics.h"
#include "synapticsstr.h"
#include "ps2comm.h" /* ps2_print_ident() */
#include <xf86.h>
#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
/*
* Identify Touchpad
* See also the SYN_ID_* macros
*/
static Bool
psm_synaptics_identify(int fd, synapticshw_t *ident)
{
int ret;
SYSCALL(ret = ioctl(fd, MOUSE_SYN_GETHWINFO, ident));
if (ret == 0)
return TRUE;
else
return FALSE;
}
/* This define is used in a ioctl but not in mouse.h :/ */
#define PSM_LEVEL_NATIVE 2
static Bool
PSMQueryIsSynaptics(InputInfoPtr pInfo)
{
int ret;
int level = PSM_LEVEL_NATIVE;
mousehw_t mhw;
/* Put the device in native protocol mode to be sure
* Otherwise HWINFO will not return the right id
* And we will need native mode anyway ...
*/
SYSCALL(ret = ioctl(pInfo->fd, MOUSE_SETLEVEL, &level));
if (ret != 0) {
xf86Msg(X_ERROR, "%s Can't set native mode\n", pInfo->name);
return FALSE;
}
SYSCALL(ret = ioctl(pInfo->fd, MOUSE_GETHWINFO, &mhw));
if (ret != 0) {
xf86Msg(X_ERROR, "%s Can't get hardware info\n", pInfo->name);
return FALSE;
}
if (mhw.model == MOUSE_MODEL_SYNAPTICS) {
return TRUE;
} else {
xf86Msg(X_ERROR, "%s Found no Synaptics, found Mouse model %d instead\n",
pInfo->name, mhw.model);
return FALSE;
}
}
static void
convert_hw_info(const synapticshw_t *psm_ident, struct PS2SynapticsHwInfo *synhw)
{
memset(synhw, 0, sizeof(*synhw));
synhw->model_id = ((psm_ident->infoRot180 << 23) |
(psm_ident->infoPortrait << 22) |
(psm_ident->infoSensor << 16) |
(psm_ident->infoHardware << 9) |
(psm_ident->infoNewAbs << 7) |
(psm_ident->capPen << 6) |
(psm_ident->infoSimplC << 5) |
(psm_ident->infoGeometry));
synhw->capabilities = ((psm_ident->capExtended << 23) |
(psm_ident->capPassthrough << 7) |
(psm_ident->capSleep << 4) |
(psm_ident->capFourButtons << 3) |
(psm_ident->capMultiFinger << 1) |
(psm_ident->capPalmDetect));
synhw->ext_cap = 0;
synhw->identity = ((psm_ident->infoMajor) |
(0x47 << 8) |
(psm_ident->infoMinor << 16));
}
static Bool
PSMQueryHardware(InputInfoPtr pInfo)
{
synapticshw_t psm_ident;
struct PS2SynapticsHwInfo *synhw;
SynapticsPrivate *priv;
priv = (SynapticsPrivate *)pInfo->private;
if(!priv->proto_data)
priv->proto_data = calloc(1, sizeof(struct PS2SynapticsHwInfo));
synhw = (struct PS2SynapticsHwInfo*)priv->proto_data;
/* is the synaptics touchpad active? */
if (!PSMQueryIsSynaptics(pInfo))
return FALSE;
xf86Msg(X_PROBED, "%s synaptics touchpad found\n", pInfo->name);
if (!psm_synaptics_identify(pInfo->fd, &psm_ident))
return FALSE;
convert_hw_info(&psm_ident, synhw);
ps2_print_ident(synhw);
return TRUE;
}
static Bool
PSMReadHwState(InputInfoPtr pInfo,
struct CommData *comm, struct SynapticsHwState *hwRet)
{
return PS2ReadHwStateProto(pInfo, &psm_proto_operations, comm, hwRet);
}
struct SynapticsProtocolOperations psm_proto_operations = {
NULL,
NULL,
PSMQueryHardware,
PSMReadHwState,
NULL,
NULL
};