psmcomm.c revision 28515619
1b85037dbSmrg/*
2b85037dbSmrg * Copyright � 1997 C. Scott Ananian
3b85037dbSmrg * Copyright � 1998-2000 Bruce Kalk
4b85037dbSmrg * Copyright � 2001 Stefan Gmeiner
5b85037dbSmrg * Copyright � 2002 Linuxcare Inc. David Kennedy
6b85037dbSmrg * Copyright � 2003 Fred Hucht
7b85037dbSmrg * Copyright � 2004 Arne Schwabe
8b85037dbSmrg *
9b85037dbSmrg * Permission to use, copy, modify, distribute, and sell this software
10b85037dbSmrg * and its documentation for any purpose is hereby granted without
11b85037dbSmrg * fee, provided that the above copyright notice appear in all copies
12b85037dbSmrg * and that both that copyright notice and this permission notice
13b85037dbSmrg * appear in supporting documentation, and that the name of Red Hat
14b85037dbSmrg * not be used in advertising or publicity pertaining to distribution
15b85037dbSmrg * of the software without specific, written prior permission.  Red
16b85037dbSmrg * Hat makes no representations about the suitability of this software
17b85037dbSmrg * for any purpose.  It is provided "as is" without express or implied
18b85037dbSmrg * warranty.
19b85037dbSmrg *
20b85037dbSmrg * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
21b85037dbSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
22b85037dbSmrg * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
23b85037dbSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
24b85037dbSmrg * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
25b85037dbSmrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
26b85037dbSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27b85037dbSmrg *
28b85037dbSmrg * Authors:
29b85037dbSmrg *      Stefan Gmeiner (riddlebox@freesurf.ch)
30b85037dbSmrg *      C. Scott Ananian (cananian@alumni.priceton.edu)
31b85037dbSmrg *      Bruce Kalk (kall@compass.com)
32b85037dbSmrg *      Linuxcare Inc. David Kennedy (dkennedy@linuxcare.com)
33b85037dbSmrg *      Fred Hucht (fred@thp.Uni-Duisburg.de)
34b85037dbSmrg *      Arne Schwabe <schwabe@uni-paderborn.de>
35b85037dbSmrg */
36b85037dbSmrg
37b85037dbSmrg#ifdef HAVE_CONFIG_H
38b85037dbSmrg#include "config.h"
39b85037dbSmrg#endif
40b85037dbSmrg
41b85037dbSmrg#include <xorg-server.h>
42b85037dbSmrg#include <unistd.h>
43b85037dbSmrg#include <sys/ioctl.h>
44b85037dbSmrg#include <sys/mouse.h>
45b85037dbSmrg#include <errno.h>
46b85037dbSmrg#include <string.h>
47b85037dbSmrg#include "synproto.h"
48b85037dbSmrg#include "synapticsstr.h"
4928515619Smrg#include "ps2comm.h"            /* ps2_print_ident() */
50b85037dbSmrg#include <xf86.h>
51b85037dbSmrg
52b85037dbSmrg#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
53b85037dbSmrg
54b85037dbSmrg/*
55b85037dbSmrg * Identify Touchpad
56b85037dbSmrg * See also the SYN_ID_* macros
57b85037dbSmrg */
58b85037dbSmrgstatic Bool
5928515619Smrgpsm_synaptics_identify(int fd, synapticshw_t * ident)
60b85037dbSmrg{
61b85037dbSmrg    int ret;
62b85037dbSmrg
63b85037dbSmrg    SYSCALL(ret = ioctl(fd, MOUSE_SYN_GETHWINFO, ident));
64b85037dbSmrg    if (ret == 0)
6528515619Smrg        return TRUE;
66b85037dbSmrg    else
6728515619Smrg        return FALSE;
68b85037dbSmrg}
69b85037dbSmrg
70b85037dbSmrg/* This define is used in a ioctl but not in mouse.h :/ */
71b85037dbSmrg#define PSM_LEVEL_NATIVE	2
72b85037dbSmrg
73b85037dbSmrgstatic Bool
74302b15bdSmrgPSMQueryIsSynaptics(InputInfoPtr pInfo)
75b85037dbSmrg{
76b85037dbSmrg    int ret;
77b85037dbSmrg    int level = PSM_LEVEL_NATIVE;
78b85037dbSmrg    mousehw_t mhw;
79b85037dbSmrg
80b85037dbSmrg    /* Put the device in native protocol mode to be sure
81b85037dbSmrg     * Otherwise HWINFO will not return the right id
82b85037dbSmrg     * And we will need native mode anyway ...
83b85037dbSmrg     */
84302b15bdSmrg    SYSCALL(ret = ioctl(pInfo->fd, MOUSE_SETLEVEL, &level));
85b85037dbSmrg    if (ret != 0) {
8628515619Smrg        xf86IDrvMsg(pInfo, X_ERROR, "%s Can't set native mode\n", pInfo->name);
8728515619Smrg        return FALSE;
88b85037dbSmrg    }
89302b15bdSmrg    SYSCALL(ret = ioctl(pInfo->fd, MOUSE_GETHWINFO, &mhw));
90b85037dbSmrg    if (ret != 0) {
9128515619Smrg        xf86IDrvMsg(pInfo, X_ERROR, "%s Can't get hardware info\n",
9228515619Smrg                    pInfo->name);
9328515619Smrg        return FALSE;
94b85037dbSmrg    }
95b85037dbSmrg
96b85037dbSmrg    if (mhw.model == MOUSE_MODEL_SYNAPTICS) {
9728515619Smrg        return TRUE;
9828515619Smrg    }
9928515619Smrg    else {
10028515619Smrg        xf86IDrvMsg(pInfo, X_ERROR,
10128515619Smrg                    "%s Found no Synaptics, found Mouse model %d instead\n",
10228515619Smrg                    pInfo->name, mhw.model);
10328515619Smrg        return FALSE;
104b85037dbSmrg    }
105b85037dbSmrg}
106b85037dbSmrg
107b85037dbSmrgstatic void
10828515619Smrgconvert_hw_info(const synapticshw_t * psm_ident,
10928515619Smrg                struct PS2SynapticsHwInfo *synhw)
110b85037dbSmrg{
111b85037dbSmrg    memset(synhw, 0, sizeof(*synhw));
112b85037dbSmrg    synhw->model_id = ((psm_ident->infoRot180 << 23) |
11328515619Smrg                       (psm_ident->infoPortrait << 22) |
11428515619Smrg                       (psm_ident->infoSensor << 16) |
11528515619Smrg                       (psm_ident->infoHardware << 9) |
11628515619Smrg                       (psm_ident->infoNewAbs << 7) |
11728515619Smrg                       (psm_ident->capPen << 6) |
11828515619Smrg                       (psm_ident->infoSimplC << 5) |
11928515619Smrg                       (psm_ident->infoGeometry));
120b85037dbSmrg    synhw->capabilities = ((psm_ident->capExtended << 23) |
12128515619Smrg                           (psm_ident->capPassthrough << 7) |
12228515619Smrg                           (psm_ident->capSleep << 4) |
12328515619Smrg                           (psm_ident->capFourButtons << 3) |
12428515619Smrg                           (psm_ident->capMultiFinger << 1) |
12528515619Smrg                           (psm_ident->capPalmDetect));
126b85037dbSmrg    synhw->ext_cap = 0;
127b85037dbSmrg    synhw->identity = ((psm_ident->infoMajor) |
12828515619Smrg                       (0x47 << 8) | (psm_ident->infoMinor << 16));
129b85037dbSmrg}
130b85037dbSmrg
131b85037dbSmrgstatic Bool
132302b15bdSmrgPSMQueryHardware(InputInfoPtr pInfo)
133b85037dbSmrg{
134b85037dbSmrg    synapticshw_t psm_ident;
13528515619Smrg    struct PS2SynapticsHwInfo *synhw;
136b85037dbSmrg    SynapticsPrivate *priv;
137b85037dbSmrg
13828515619Smrg    priv = (SynapticsPrivate *) pInfo->private;
139b85037dbSmrg
14028515619Smrg    if (!priv->proto_data)
14128515619Smrg        priv->proto_data = calloc(1, sizeof(struct PS2SynapticsHwInfo));
14228515619Smrg    synhw = (struct PS2SynapticsHwInfo *) priv->proto_data;
143b85037dbSmrg
144b85037dbSmrg    /* is the synaptics touchpad active? */
145302b15bdSmrg    if (!PSMQueryIsSynaptics(pInfo))
14628515619Smrg        return FALSE;
147b85037dbSmrg
14828515619Smrg    xf86IDrvMsg(pInfo, X_PROBED, "synaptics touchpad found\n");
149b85037dbSmrg
150302b15bdSmrg    if (!psm_synaptics_identify(pInfo->fd, &psm_ident))
15128515619Smrg        return FALSE;
152b85037dbSmrg
153b85037dbSmrg    convert_hw_info(&psm_ident, synhw);
154b85037dbSmrg
15528515619Smrg    ps2_print_ident(pInfo, synhw);
156b85037dbSmrg
157b85037dbSmrg    return TRUE;
158b85037dbSmrg}
159b85037dbSmrg
160b85037dbSmrgstatic Bool
161302b15bdSmrgPSMReadHwState(InputInfoPtr pInfo,
16228515619Smrg               struct CommData *comm, struct SynapticsHwState *hwRet)
163b85037dbSmrg{
16428515619Smrg    return PS2ReadHwStateProto(pInfo, &psm_proto_operations, comm, hwRet);
165b85037dbSmrg}
166b85037dbSmrg
167b85037dbSmrgstruct SynapticsProtocolOperations psm_proto_operations = {
168b85037dbSmrg    NULL,
169b85037dbSmrg    NULL,
170b85037dbSmrg    PSMQueryHardware,
171b85037dbSmrg    PSMReadHwState,
17228515619Smrg    NULL,
17328515619Smrg    NULL
174b85037dbSmrg};
175