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