psmcomm.c revision b85037db
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 "synaptics.h"
49b85037dbSmrg#include "synapticsstr.h"
50b85037dbSmrg#include "ps2comm.h"			    /* ps2_print_ident() */
51b85037dbSmrg#include <xf86.h>
52b85037dbSmrg
53b85037dbSmrg#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
54b85037dbSmrg
55b85037dbSmrgstruct SynapticsHwInfo {
56b85037dbSmrg    unsigned int model_id;		    /* Model-ID */
57b85037dbSmrg    unsigned int capabilities;		    /* Capabilities */
58b85037dbSmrg    unsigned int ext_cap;		    /* Extended Capabilities */
59b85037dbSmrg    unsigned int identity;		    /* Identification */
60b85037dbSmrg};
61b85037dbSmrg
62b85037dbSmrg/*
63b85037dbSmrg * Identify Touchpad
64b85037dbSmrg * See also the SYN_ID_* macros
65b85037dbSmrg */
66b85037dbSmrgstatic Bool
67b85037dbSmrgpsm_synaptics_identify(int fd, synapticshw_t *ident)
68b85037dbSmrg{
69b85037dbSmrg    int ret;
70b85037dbSmrg
71b85037dbSmrg    SYSCALL(ret = ioctl(fd, MOUSE_SYN_GETHWINFO, ident));
72b85037dbSmrg    if (ret == 0)
73b85037dbSmrg	return TRUE;
74b85037dbSmrg    else
75b85037dbSmrg	return FALSE;
76b85037dbSmrg}
77b85037dbSmrg
78b85037dbSmrg/* This define is used in a ioctl but not in mouse.h :/ */
79b85037dbSmrg#define PSM_LEVEL_NATIVE	2
80b85037dbSmrg
81b85037dbSmrgstatic Bool
82b85037dbSmrgPSMQueryIsSynaptics(LocalDevicePtr local)
83b85037dbSmrg{
84b85037dbSmrg    int ret;
85b85037dbSmrg    int level = PSM_LEVEL_NATIVE;
86b85037dbSmrg    mousehw_t mhw;
87b85037dbSmrg
88b85037dbSmrg    /* Put the device in native protocol mode to be sure
89b85037dbSmrg     * Otherwise HWINFO will not return the right id
90b85037dbSmrg     * And we will need native mode anyway ...
91b85037dbSmrg     */
92b85037dbSmrg    SYSCALL(ret = ioctl(local->fd, MOUSE_SETLEVEL, &level));
93b85037dbSmrg    if (ret != 0) {
94b85037dbSmrg	xf86Msg(X_ERROR, "%s Can't set native mode\n", local->name);
95b85037dbSmrg	return FALSE;
96b85037dbSmrg    }
97b85037dbSmrg    SYSCALL(ret = ioctl(local->fd, MOUSE_GETHWINFO, &mhw));
98b85037dbSmrg    if (ret != 0) {
99b85037dbSmrg	xf86Msg(X_ERROR, "%s Can't get hardware info\n", local->name);
100b85037dbSmrg	return FALSE;
101b85037dbSmrg    }
102b85037dbSmrg
103b85037dbSmrg    if (mhw.model == MOUSE_MODEL_SYNAPTICS) {
104b85037dbSmrg	return TRUE;
105b85037dbSmrg    } else {
106b85037dbSmrg	xf86Msg(X_ERROR, "%s Found no Synaptics, found Mouse model %d instead\n",
107b85037dbSmrg		local->name, mhw.model);
108b85037dbSmrg	return FALSE;
109b85037dbSmrg    }
110b85037dbSmrg}
111b85037dbSmrg
112b85037dbSmrgstatic void
113b85037dbSmrgconvert_hw_info(const synapticshw_t *psm_ident, struct SynapticsHwInfo *synhw)
114b85037dbSmrg{
115b85037dbSmrg    memset(synhw, 0, sizeof(*synhw));
116b85037dbSmrg    synhw->model_id = ((psm_ident->infoRot180 << 23) |
117b85037dbSmrg		       (psm_ident->infoPortrait << 22) |
118b85037dbSmrg		       (psm_ident->infoSensor << 16) |
119b85037dbSmrg		       (psm_ident->infoHardware << 9) |
120b85037dbSmrg		       (psm_ident->infoNewAbs << 7) |
121b85037dbSmrg		       (psm_ident->capPen << 6) |
122b85037dbSmrg		       (psm_ident->infoSimplC << 5) |
123b85037dbSmrg		       (psm_ident->infoGeometry));
124b85037dbSmrg    synhw->capabilities = ((psm_ident->capExtended << 23) |
125b85037dbSmrg			   (psm_ident->capPassthrough << 7) |
126b85037dbSmrg			   (psm_ident->capSleep << 4) |
127b85037dbSmrg			   (psm_ident->capFourButtons << 3) |
128b85037dbSmrg			   (psm_ident->capMultiFinger << 1) |
129b85037dbSmrg			   (psm_ident->capPalmDetect));
130b85037dbSmrg    synhw->ext_cap = 0;
131b85037dbSmrg    synhw->identity = ((psm_ident->infoMajor) |
132b85037dbSmrg		       (0x47 << 8) |
133b85037dbSmrg		       (psm_ident->infoMinor << 16));
134b85037dbSmrg}
135b85037dbSmrg
136b85037dbSmrgstatic Bool
137b85037dbSmrgPSMQueryHardware(LocalDevicePtr local)
138b85037dbSmrg{
139b85037dbSmrg    synapticshw_t psm_ident;
140b85037dbSmrg    struct SynapticsHwInfo *synhw;
141b85037dbSmrg    SynapticsPrivate *priv;
142b85037dbSmrg
143b85037dbSmrg    priv = (SynapticsPrivate *)local->private;
144b85037dbSmrg
145b85037dbSmrg    if(!priv->proto_data)
146b85037dbSmrg        priv->proto_data = calloc(1, sizeof(struct SynapticsHwInfo));
147b85037dbSmrg    synhw = (struct SynapticsHwInfo*)priv->proto_data;
148b85037dbSmrg
149b85037dbSmrg    /* is the synaptics touchpad active? */
150b85037dbSmrg    if (!PSMQueryIsSynaptics(local))
151b85037dbSmrg	return FALSE;
152b85037dbSmrg
153b85037dbSmrg    xf86Msg(X_PROBED, "%s synaptics touchpad found\n", local->name);
154b85037dbSmrg
155b85037dbSmrg    if (!psm_synaptics_identify(local->fd, &psm_ident))
156b85037dbSmrg	return FALSE;
157b85037dbSmrg
158b85037dbSmrg    convert_hw_info(&psm_ident, synhw);
159b85037dbSmrg
160b85037dbSmrg    ps2_print_ident(synhw);
161b85037dbSmrg
162b85037dbSmrg    return TRUE;
163b85037dbSmrg}
164b85037dbSmrg
165b85037dbSmrgstatic Bool
166b85037dbSmrgPSMReadHwState(LocalDevicePtr local,
167b85037dbSmrg	       struct SynapticsProtocolOperations *proto_ops,
168b85037dbSmrg	       struct CommData *comm, struct SynapticsHwState *hwRet)
169b85037dbSmrg{
170b85037dbSmrg    return psaux_proto_operations.ReadHwState(local, proto_ops, comm, hwRet);
171b85037dbSmrg}
172b85037dbSmrg
173b85037dbSmrgstatic Bool PSMAutoDevProbe(LocalDevicePtr local)
174b85037dbSmrg{
175b85037dbSmrg    return FALSE;
176b85037dbSmrg}
177b85037dbSmrg
178b85037dbSmrgstruct SynapticsProtocolOperations psm_proto_operations = {
179b85037dbSmrg    NULL,
180b85037dbSmrg    NULL,
181b85037dbSmrg    PSMQueryHardware,
182b85037dbSmrg    PSMReadHwState,
183b85037dbSmrg    PSMAutoDevProbe,
184b85037dbSmrg    SynapticsDefaultDimensions
185b85037dbSmrg};
186