moused.c revision 29849
116566Ssos/** 216566Ssos ** Copyright (c) 1995 Michael Smith, All rights reserved. 316566Ssos ** 416566Ssos ** Redistribution and use in source and binary forms, with or without 516566Ssos ** modification, are permitted provided that the following conditions 616566Ssos ** are met: 716566Ssos ** 1. Redistributions of source code must retain the above copyright 816566Ssos ** notice, this list of conditions and the following disclaimer as 916566Ssos ** the first lines of this file unmodified. 1016566Ssos ** 2. Redistributions in binary form must reproduce the above copyright 1116566Ssos ** notice, this list of conditions and the following disclaimer in the 1216566Ssos ** documentation and/or other materials provided with the distribution. 1316566Ssos ** 3. All advertising materials mentioning features or use of this software 1416566Ssos ** must display the following acknowledgment: 1516566Ssos ** This product includes software developed by Michael Smith. 1616566Ssos ** 4. The name of the author may not be used to endorse or promote products 1716566Ssos ** derived from this software without specific prior written permission. 1816566Ssos ** 1916566Ssos ** 2016566Ssos ** THIS SOFTWARE IS PROVIDED BY Michael Smith ``AS IS'' AND ANY 2116566Ssos ** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2216566Ssos ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2316566Ssos ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Michael Smith BE LIABLE FOR 2416566Ssos ** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2516566Ssos ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2616566Ssos ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 2716566Ssos ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2816566Ssos ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 2916566Ssos ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 3016566Ssos ** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3116566Ssos ** 3216566Ssos **/ 3316566Ssos 3416566Ssos/** 3516566Ssos ** MOUSED.C 3616566Ssos ** 3716566Ssos ** Mouse daemon : listens to serial port for mouse data stream, 3816566Ssos ** interprets same and passes ioctls off to the console driver. 3916566Ssos ** 4016566Ssos ** The mouse interface functions are derived closely from the mouse 4116566Ssos ** handler in the XFree86 X server. Many thanks to the XFree86 people 4216566Ssos ** for their great work! 4316566Ssos ** 4416566Ssos **/ 4516566Ssos 4629849Scharnier#ifndef lint 4729849Scharnierstatic const char rcsid[] = 4829849Scharnier "$Id$"; 4929849Scharnier#endif /* not lint */ 5029849Scharnier 5129849Scharnier#include <err.h> 5229849Scharnier#include <errno.h> 5329849Scharnier#include <fcntl.h> 5429849Scharnier#include <limits.h> 5516566Ssos#include <stdio.h> 5616566Ssos#include <stdlib.h> 5716566Ssos#include <string.h> 5816566Ssos#include <termios.h> 5916566Ssos#include <machine/console.h> 6021885Ssos#include <sys/types.h> 6121885Ssos#include <sys/time.h> 6221885Ssos#include <unistd.h> 6316566Ssos 6416566Ssos#define debug(fmt,args...) \ 6529849Scharnier if (debug&&nodaemon) warnx(fmt, ##args) 6616566Ssos 6716566Ssosint debug = 0; 6816566Ssosint nodaemon = 0; 6916566Ssos 7016566Ssosvoid usage(void); 7116566Ssos 7216566Ssos#define R_UNKNOWN 0 7316566Ssos#define R_MICROSOFT 1 7416566Ssos#define R_MOUSESYS 2 7516566Ssos#define R_MMSERIES 3 7616566Ssos#define R_LOGITECH 4 7716566Ssos#define R_BUSMOUSE 5 7816566Ssos#define R_LOGIMAN 6 7916566Ssos#define R_PS_2 7 8018222Speter#define R_MMHITAB 8 8116566Ssos 8216566Ssoschar *rnames[] = { 8316566Ssos "xxx", 8416566Ssos "microsoft", 8516566Ssos "mousesystems", 8616566Ssos "mmseries", 8716566Ssos "logitech", 8816566Ssos "busmouse", 8916566Ssos "mouseman", 9016566Ssos "ps/2", 9118222Speter "mmhitab", 9216566Ssos NULL 9316566Ssos}; 9416566Ssos 9516566Ssosunsigned short rodentcflags[] = 9616566Ssos{ 9716566Ssos 0, /* nomouse */ 9816566Ssos (CS7 | CREAD | CLOCAL | HUPCL ), /* MicroSoft */ 9916566Ssos (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* MouseSystems */ 10016566Ssos (CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL ), /* MMSeries */ 10116566Ssos (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* Logitech */ 10216566Ssos 0, /* BusMouse */ 10316566Ssos (CS7 | CREAD | CLOCAL | HUPCL ), /* MouseMan */ 10418222Speter 0, /* PS/2 */ 10518222Speter (CS8 | CREAD | CLOCAL | HUPCL ), /* MMHitTablet */ 10616566Ssos}; 10716566Ssos 10816566Ssos 10916566Ssostypedef struct 11016566Ssos{ 11116566Ssos int 11216566Ssos dx,dy, 11316566Ssos buttons; 11416566Ssos} ACTIVITY; 11516566Ssos 11616566Ssos 11716566Ssosstruct rodentparam 11816566Ssos{ 11916566Ssos int 12016566Ssos baudrate, 12116566Ssos samplerate, 12216566Ssos flags, 12316566Ssos rtype, 12416566Ssos lastbuttons, 12516566Ssos buttons, 12618222Speter mfd, 12718222Speter cleardtr, 12818222Speter clearrts; 12916566Ssos 13016566Ssos char 13116566Ssos *portname; 13216566Ssos 13316566Ssos} rodent = { baudrate : 1200, 13416566Ssos samplerate : 0, 13516566Ssos flags : 0, 13616566Ssos rtype : R_UNKNOWN, 13716566Ssos lastbuttons : 0, 13816566Ssos buttons : 0, 13916566Ssos mfd : -1, 14018222Speter portname : NULL, 14118222Speter cleardtr : 0, 14218222Speter clearrts : 0}; 14316566Ssos 14416566Ssos#define ChordMiddle 1 14516566Ssos 14616566Ssosvoid r_init(void); 14716566SsosACTIVITY *r_protocol(u_char b); 14818222Spetervoid setmousespeed(int old, int new, unsigned cflag); 14916566Ssos 15016566Ssosvoid 15116566Ssosmain(int argc, char *argv[]) 15216566Ssos{ 15316566Ssos int c,i,cfd; 15416566Ssos u_char b; 15516566Ssos ACTIVITY *act; 15616566Ssos struct mouse_info mouse; 15721885Ssos fd_set fds; 15816566Ssos 15924428Simp while((c = getopt(argc,argv,"cdfr:sp:t:h?RDS:")) != -1) 16016566Ssos switch(c) 16116566Ssos { 16216566Ssos case 'c': 16316566Ssos rodent.flags |= ChordMiddle; 16416566Ssos break; 16516566Ssos 16616566Ssos case 'd': 16716566Ssos debug = 1; 16816566Ssos break; 16916566Ssos 17016566Ssos case 'f': 17116566Ssos nodaemon = 1; 17216566Ssos break; 17316566Ssos 17416566Ssos case 'p': 17516566Ssos rodent.portname = optarg; 17616566Ssos break; 17716566Ssos 17824377Speter case 'r': 17924377Speter rodent.samplerate = atoi(optarg); 18024377Speter break; 18124377Speter 18216566Ssos case 's': 18316566Ssos rodent.baudrate = 9600; 18418222Speter break; 18516566Ssos 18618222Speter case 'R': 18718222Speter rodent.clearrts = 1; 18818222Speter break; 18918222Speter 19018222Speter case 'D': 19118222Speter rodent.cleardtr = 1; 19218222Speter break; 19318222Speter 19418222Speter case 'S': 19518222Speter rodent.baudrate = atoi(optarg); 19618222Speter debug("rodent baudrate %d", rodent.baudrate); 19718222Speter break; 19818222Speter 19916566Ssos case 't': 20016566Ssos for (i = 0; rnames[i]; i++) 20116566Ssos if (!strcmp(optarg,rnames[i])) 20216566Ssos { 20316566Ssos debug("rodent is %s",rnames[i]); 20416566Ssos rodent.rtype = i; 20516566Ssos break; 20616566Ssos } 20716566Ssos if (rnames[i]) 20816566Ssos break; 20918222Speter warnx("no such mouse type `%s'",optarg); 21016566Ssos usage(); 21116566Ssos 21216566Ssos case 'h': 21316566Ssos case '?': 21416566Ssos default: 21516566Ssos usage(); 21616566Ssos } 21716566Ssos 21816566Ssos switch(rodent.rtype) 21916566Ssos { 22016566Ssos case R_BUSMOUSE: 22116566Ssos if (!rodent.portname) 22216566Ssos rodent.portname = "/dev/mse0"; 22316566Ssos break; 22416566Ssos case R_PS_2: 22516566Ssos if (!rodent.portname) 22616566Ssos rodent.portname = "/dev/psm0"; 22716566Ssos break; 22816566Ssos default: 22916566Ssos if (rodent.portname) 23016566Ssos break; 23129849Scharnier warnx("no port name specified"); 23216566Ssos usage(); 23316566Ssos } 23416566Ssos 23516566Ssos if ((rodent.mfd = open(rodent.portname, O_RDWR, 0)) == -1) 23616566Ssos { 23729849Scharnier warn("can't open %s",rodent.portname); 23816566Ssos usage(); 23916566Ssos } 24016566Ssos r_init(); /* call init function */ 24116566Ssos 24218190Ssos if ((cfd = open("/dev/consolectl", O_RDWR, 0)) == -1) 24318222Speter err(1, "open(/dev/consolectl)"); 24416566Ssos 24516566Ssos if (!nodaemon) 24616566Ssos if (daemon(0,0)) 24716566Ssos { 24818222Speter err(1, "daemon() failed"); 24916566Ssos } 25016566Ssos 25116566Ssos for(;;) 25216566Ssos { 25321885Ssos FD_ZERO(&fds); 25421885Ssos FD_SET(rodent.mfd,&fds); 25521885Ssos select(FD_SETSIZE,&fds,NULL,&fds,NULL); 25616566Ssos i = read(rodent.mfd,&b,1); /* get a byte */ 25716566Ssos if (i != 1) /* read returned or error; goodbye */ 25816566Ssos { 25916566Ssos debug("read returned %d : %s exiting",i,strerror(errno)); 26016566Ssos close(rodent.mfd); 26116566Ssos exit(1); 26216566Ssos } 26316566Ssos act = r_protocol(b); /* pass byte to handler */ 26416566Ssos if (act) /* handler detected action */ 26516566Ssos { 26616693Ssos mouse.operation = MOUSE_ACTION; 26716693Ssos mouse.u.data.x = act->dx; 26816693Ssos mouse.u.data.y = act->dy; 26916693Ssos mouse.u.data.buttons = act->buttons; 27016566Ssos ioctl(cfd, CONS_MOUSECTL, &mouse); 27129849Scharnier debug("activity : buttons 0x%02x dx %d dy %d", 27216566Ssos act->buttons,act->dx,act->dy); 27316566Ssos } 27416566Ssos } 27516566Ssos} 27616566Ssos 27716566Ssos 27816566Ssos/** 27916566Ssos ** usage 28016566Ssos ** 28116566Ssos ** Complain, and free the CPU for more worthy tasks 28216566Ssos **/ 28316566Ssosvoid 28416566Ssosusage(void) 28516566Ssos{ 28629849Scharnier fprintf(stderr, "%s\n%s\n", 28729849Scharnier "usage: moused [-DRcdfs] [-r samplerate] [-S baudrate]", 28829849Scharnier " -p <port> -t <mousetype>"); 28916566Ssos exit(1); 29016566Ssos} 29116566Ssos 29216566Ssos 29316566Ssos/** 29416566Ssos ** Mouse interface code, courtesy of XFree86 3.1.2. 29516566Ssos ** 29616566Ssos ** Note: Various bits have been trimmed, and in my shortsighted enthusiasm 29716566Ssos ** to clean, reformat and rationalise naming, it's quite possible that 29816566Ssos ** some things in here have been broken. 29916566Ssos ** 30016566Ssos ** I hope not 8) 30116566Ssos ** 30216566Ssos ** The following code is derived from a module marked : 30316566Ssos **/ 30416566Ssos 30516566Ssos/* $XConsortium: xf86_Mouse.c,v 1.2 94/10/12 20:33:21 kaleb Exp $ */ 30616566Ssos/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86_Mouse.c,v 3.2 1995/01/28 30716566Ssos 17:03:40 dawes Exp $ */ 30816566Ssos/* 30916566Ssos * 31016566Ssos * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. 31116566Ssos * Copyright 1993 by David Dawes <dawes@physics.su.oz.au> 31216566Ssos * 31316566Ssos * Permission to use, copy, modify, distribute, and sell this software and its 31416566Ssos * documentation for any purpose is hereby granted without fee, provided that 31516566Ssos * the above copyright notice appear in all copies and that both that 31616566Ssos * copyright notice and this permission notice appear in supporting 31716566Ssos * documentation, and that the names of Thomas Roell and David Dawes not be 31816566Ssos * used in advertising or publicity pertaining to distribution of the 31916566Ssos * software without specific, written prior permission. Thomas Roell 32016566Ssos * and David Dawes makes no representations about the suitability of this 32116566Ssos * software for any purpose. It is provided "as is" without express or 32216566Ssos * implied warranty. 32316566Ssos * 32416566Ssos * THOMAS ROELL AND DAVID DAWES DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 32516566Ssos * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 32616566Ssos * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR DAVID DAWES BE LIABLE FOR ANY 32716566Ssos * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 32816566Ssos * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 32916566Ssos * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 33016566Ssos * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 33116566Ssos * 33216566Ssos */ 33316566Ssos 33416566Ssos 33516566Ssosvoid 33616566Ssosr_init(void) 33716566Ssos{ 33816566Ssos /** 33916566Ssos ** This comment is a little out of context here, but it contains 34016566Ssos ** some useful information... 34116566Ssos ******************************************************************** 34216566Ssos ** 34316566Ssos ** The following lines take care of the Logitech MouseMan protocols. 34416566Ssos ** 34516566Ssos ** NOTE: There are different versions of both MouseMan and TrackMan! 34616566Ssos ** Hence I add another protocol P_LOGIMAN, which the user can 34716566Ssos ** specify as MouseMan in his XF86Config file. This entry was 34816566Ssos ** formerly handled as a special case of P_MS. However, people 34916566Ssos ** who don't have the middle button problem, can still specify 35016566Ssos ** Microsoft and use P_MS. 35116566Ssos ** 35216566Ssos ** By default, these mice should use a 3 byte Microsoft protocol 35316566Ssos ** plus a 4th byte for the middle button. However, the mouse might 35416566Ssos ** have switched to a different protocol before we use it, so I send 35516566Ssos ** the proper sequence just in case. 35616566Ssos ** 35716566Ssos ** NOTE: - all commands to (at least the European) MouseMan have to 35816566Ssos ** be sent at 1200 Baud. 35916566Ssos ** - each command starts with a '*'. 36016566Ssos ** - whenever the MouseMan receives a '*', it will switch back 36116566Ssos ** to 1200 Baud. Hence I have to select the desired protocol 36216566Ssos ** first, then select the baud rate. 36316566Ssos ** 36416566Ssos ** The protocols supported by the (European) MouseMan are: 36516566Ssos ** - 5 byte packed binary protocol, as with the Mouse Systems 36616566Ssos ** mouse. Selected by sequence "*U". 36716566Ssos ** - 2 button 3 byte MicroSoft compatible protocol. Selected 36816566Ssos ** by sequence "*V". 36916566Ssos ** - 3 button 3+1 byte MicroSoft compatible protocol (default). 37016566Ssos ** Selected by sequence "*X". 37116566Ssos ** 37216566Ssos ** The following baud rates are supported: 37316566Ssos ** - 1200 Baud (default). Selected by sequence "*n". 37416566Ssos ** - 9600 Baud. Selected by sequence "*q". 37516566Ssos ** 37616566Ssos ** Selecting a sample rate is no longer supported with the MouseMan! 37716566Ssos ** Some additional lines in xf86Config.c take care of ill configured 37816566Ssos ** baud rates and sample rates. (The user will get an error.) 37916566Ssos */ 38016566Ssos 38116566Ssos 38216566Ssos if (rodent.rtype == R_LOGIMAN) 38316566Ssos { 38418222Speter setmousespeed(1200, 1200, rodentcflags[R_LOGIMAN]); 38516566Ssos write(rodent.mfd, "*X", 2); 38618222Speter setmousespeed(1200, rodent.baudrate, rodentcflags[R_LOGIMAN]); 38718222Speter } else { 38818222Speter if ((rodent.rtype != R_BUSMOUSE) && (rodent.rtype != R_PS_2)) 38918222Speter { 39018222Speter /* try all likely settings */ 39118222Speter setmousespeed(9600, rodent.baudrate, rodentcflags[rodent.rtype]); 39218222Speter setmousespeed(4800, rodent.baudrate, rodentcflags[rodent.rtype]); 39318222Speter setmousespeed(2400, rodent.baudrate, rodentcflags[rodent.rtype]); 39418222Speter setmousespeed(1200, rodent.baudrate, rodentcflags[rodent.rtype]); 39518222Speter 39618222Speter if (rodent.rtype == R_LOGITECH) { 39718222Speter write(rodent.mfd, "S", 1); 39818222Speter setmousespeed(rodent.baudrate, rodent.baudrate, 39918222Speter rodentcflags[R_MMSERIES]); 40018222Speter } 40118222Speter 40218222Speter if (rodent.rtype == R_MMHITAB) { 40318222Speter char speedcmd; 40418222Speter /* 40518222Speter * Initialize Hitachi PUMA Plus - Model 1212E to desired settings. 40618222Speter * The tablet must be configured to be in MM mode, NO parity, 40718222Speter * Binary Format. xf86Info.sampleRate controls the sensativity 40818222Speter * of the tablet. We only use this tablet for it's 4-button puck 40918222Speter * so we don't run in "Absolute Mode" 41018222Speter */ 41118222Speter write(rodent.mfd, "z8", 2); /* Set Parity = "NONE" */ 41218222Speter usleep(50000); 41318222Speter write(rodent.mfd, "zb", 2); /* Set Format = "Binary" */ 41418222Speter usleep(50000); 41518222Speter write(rodent.mfd, "@", 1); /* Set Report Mode = "Stream" */ 41618222Speter usleep(50000); 41718222Speter write(rodent.mfd, "R", 1); /* Set Output Rate = "45 rps" */ 41818222Speter usleep(50000); 41918222Speter write(rodent.mfd, "I\x20", 2); /* Set Incrememtal Mode "20" */ 42018222Speter usleep(50000); 42118222Speter write(rodent.mfd, "E", 1); /* Set Data Type = "Relative */ 42218222Speter usleep(50000); 42318222Speter 42418222Speter /* These sample rates translate to 'lines per inch' on the 42518222Speter Hitachi tablet */ 42618222Speter if (rodent.samplerate <= 40) speedcmd = 'g'; 42718222Speter else if (rodent.samplerate <= 100) speedcmd = 'd'; 42818222Speter else if (rodent.samplerate <= 200) speedcmd = 'e'; 42918222Speter else if (rodent.samplerate <= 500) speedcmd = 'h'; 43018222Speter else if (rodent.samplerate <= 1000) speedcmd = 'j'; 43118222Speter else speedcmd = 'd'; 43218222Speter write(rodent.mfd, &speedcmd, 1); 43318222Speter usleep(50000); 43418222Speter 43518222Speter write(rodent.mfd, "\021", 1); /* Resume DATA output */ 43618222Speter } else { 43718222Speter if (rodent.samplerate <= 0) write(rodent.mfd, "O", 1); 43818222Speter else if (rodent.samplerate <= 15) write(rodent.mfd, "J", 1); 43918222Speter else if (rodent.samplerate <= 27) write(rodent.mfd, "K", 1); 44018222Speter else if (rodent.samplerate <= 42) write(rodent.mfd, "L", 1); 44118222Speter else if (rodent.samplerate <= 60) write(rodent.mfd, "R", 1); 44218222Speter else if (rodent.samplerate <= 85) write(rodent.mfd, "M", 1); 44318222Speter else if (rodent.samplerate <= 125) write(rodent.mfd, "Q", 1); 44418222Speter else write(rodent.mfd, "N", 1); 44518222Speter } 44618222Speter } 44716566Ssos } 44818222Speter if (rodent.rtype == R_MOUSESYS && (rodent.cleardtr)) 44916566Ssos { 45016566Ssos int val = TIOCM_DTR; 45118222Speter ioctl(rodent.mfd, TIOCMBIC, &val); 45216566Ssos } 45318222Speter if (rodent.rtype == R_MOUSESYS && (rodent.clearrts)) 45416566Ssos { 45516566Ssos int val = TIOCM_RTS; 45618222Speter ioctl(rodent.mfd, TIOCMBIC, &val); 45716566Ssos } 45816566Ssos} 45916566Ssos 46016566SsosACTIVITY * 46116566Ssosr_protocol(u_char rBuf) 46216566Ssos{ 46316566Ssos static int pBufP = 0; 46416566Ssos static unsigned char pBuf[8]; 46516566Ssos static ACTIVITY act; 46616566Ssos 46718222Speter static unsigned char proto[10][5] = { 46816566Ssos /* hd_mask hd_id dp_mask dp_id nobytes */ 46916566Ssos { 0, 0, 0, 0, 0 }, /* nomouse */ 47016566Ssos { 0x40, 0x40, 0x40, 0x00, 3 }, /* MicroSoft */ 47116566Ssos { 0xf8, 0x80, 0x00, 0x00, 5 }, /* MouseSystems */ 47216566Ssos { 0xe0, 0x80, 0x80, 0x00, 3 }, /* MMSeries */ 47316566Ssos { 0xe0, 0x80, 0x80, 0x00, 3 }, /* Logitech */ 47416566Ssos { 0xf8, 0x80, 0x00, 0x00, 5 }, /* BusMouse */ 47516566Ssos { 0x40, 0x40, 0x40, 0x00, 3 }, /* MouseMan */ 47616566Ssos { 0xc0, 0x00, 0x00, 0x00, 3 }, /* PS/2 mouse */ 47718222Speter { 0xe0, 0x80, 0x80, 0x00, 3 }, /* MM_HitTablet */ 47816566Ssos }; 47916566Ssos 48016566Ssos debug("received char 0x%x",(int)rBuf); 48116566Ssos 48216566Ssos /* 48316566Ssos * Hack for resyncing: We check here for a package that is: 48416566Ssos * a) illegal (detected by wrong data-package header) 48516566Ssos * b) invalid (0x80 == -128 and that might be wrong for MouseSystems) 48616566Ssos * c) bad header-package 48716566Ssos * 48816566Ssos * NOTE: b) is a voilation of the MouseSystems-Protocol, since values of 48916566Ssos * -128 are allowed, but since they are very seldom we can easily 49016566Ssos * use them as package-header with no button pressed. 49116566Ssos * NOTE/2: On a PS/2 mouse any byte is valid as a data byte. Furthermore, 49216566Ssos * 0x80 is not valid as a header byte. For a PS/2 mouse we skip 49316566Ssos * checking data bytes. 49416566Ssos * For resyncing a PS/2 mouse we require the two most significant 49516566Ssos * bits in the header byte to be 0. These are the overflow bits, 49616566Ssos * and in case of an overflow we actually lose sync. Overflows 49716566Ssos * are very rare, however, and we quickly gain sync again after 49816566Ssos * an overflow condition. This is the best we can do. (Actually, 49916566Ssos * we could use bit 0x08 in the header byte for resyncing, since 50016566Ssos * that bit is supposed to be always on, but nobody told 50116566Ssos * Microsoft...) 50216566Ssos */ 50316566Ssos 50416566Ssos if (pBufP != 0 && rodent.rtype != R_PS_2 && 50516566Ssos ((rBuf & proto[rodent.rtype][2]) != proto[rodent.rtype][3] 50616566Ssos || rBuf == 0x80)) 50716566Ssos { 50816566Ssos pBufP = 0; /* skip package */ 50916566Ssos } 51016566Ssos 51116566Ssos if (pBufP == 0 && 51216566Ssos (rBuf & proto[rodent.rtype][0]) != proto[rodent.rtype][1]) 51316566Ssos { 51416566Ssos /* 51516566Ssos * Hack for Logitech MouseMan Mouse - Middle button 51616566Ssos * 51716566Ssos * Unfortunately this mouse has variable length packets: the standard 51816566Ssos * Microsoft 3 byte packet plus an optional 4th byte whenever the 51916566Ssos * middle button status changes. 52016566Ssos * 52116566Ssos * We have already processed the standard packet with the movement 52216566Ssos * and button info. Now post an event message with the old status 52316566Ssos * of the left and right buttons and the updated middle button. 52416566Ssos */ 52516566Ssos 52616566Ssos /* 52716566Ssos * Even worse, different MouseMen and TrackMen differ in the 4th 52816566Ssos * byte: some will send 0x00/0x20, others 0x01/0x21, or even 52916566Ssos * 0x02/0x22, so I have to strip off the lower bits. 53016566Ssos */ 53116566Ssos if ((rodent.rtype == R_MICROSOFT || rodent.rtype == R_LOGIMAN) 53216566Ssos && (char)(rBuf & ~0x23) == 0) 53316566Ssos { 53416566Ssos act.buttons = ((int)(rBuf & 0x20) >> 4) 53516566Ssos | (rodent.lastbuttons & 0x05); 53616566Ssos rodent.lastbuttons = act.buttons; /* save new button state */ 53716566Ssos return(&act); 53816566Ssos } 53916566Ssos 54016566Ssos return(NULL); /* skip package */ 54116566Ssos } 54216566Ssos 54316566Ssos pBuf[pBufP++] = rBuf; 54416566Ssos if (pBufP != proto[rodent.rtype][4]) return(NULL); 54516566Ssos 54616566Ssos /* 54716566Ssos * assembly full package 54816566Ssos */ 54916566Ssos 55029849Scharnier debug("assembled full packet (len %d) %x,%x,%x,%x,%x", 55116566Ssos proto[rodent.rtype][4], pBuf[0],pBuf[1],pBuf[2],pBuf[3],pBuf[4]); 55216566Ssos 55316566Ssos switch(rodent.rtype) 55416566Ssos { 55516566Ssos case R_LOGIMAN: /* MouseMan / TrackMan */ 55616566Ssos case R_MICROSOFT: /* Microsoft */ 55716566Ssos if (rodent.flags & ChordMiddle) 55816566Ssos act.buttons = (((int) pBuf[0] & 0x30) == 0x30) ? 2 : 55916566Ssos ((int)(pBuf[0]&0x20)>>3) | ((int)(pBuf[0]&0x10)>>4); 56016566Ssos else 56116566Ssos act.buttons = (rodent.lastbuttons & 2) 56216566Ssos | ((int)(pBuf[0] & 0x20) >> 3) 56316566Ssos | ((int)(pBuf[0] & 0x10) >> 4); 56416566Ssos act.dx = (char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F)); 56516566Ssos act.dy = (char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F)); 56616566Ssos break; 56716566Ssos 56816566Ssos case R_MOUSESYS: /* Mouse Systems Corp */ 56916566Ssos act.buttons = (~pBuf[0]) & 0x07; 57016566Ssos act.dx = (char)(pBuf[1]) + (char)(pBuf[3]); 57116566Ssos act.dy = - ((char)(pBuf[2]) + (char)(pBuf[4])); 57216566Ssos break; 57316566Ssos 57418222Speter case R_MMHITAB: /* MM_HitTablet */ 57518222Speter act.buttons = pBuf[0] & 0x07; 57618222Speter if (act.buttons != 0) 57718222Speter act.buttons = 1 << (act.buttons - 1); 57818222Speter act.dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1]; 57918222Speter act.dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2]; 58018222Speter break; 58118222Speter 58216566Ssos case R_MMSERIES: /* MM Series */ 58316566Ssos case R_LOGITECH: /* Logitech Mice */ 58416566Ssos act.buttons = pBuf[0] & 0x07; 58516566Ssos act.dx = (pBuf[0] & 0x10) ? pBuf[1] : - pBuf[1]; 58616566Ssos act.dy = (pBuf[0] & 0x08) ? - pBuf[2] : pBuf[2]; 58716566Ssos break; 58816566Ssos 58916566Ssos case R_BUSMOUSE: /* BusMouse */ 59016566Ssos act.buttons = (~pBuf[0]) & 0x07; 59116566Ssos act.dx = (char)pBuf[1]; 59216566Ssos act.dy = - (char)pBuf[2]; 59316566Ssos break; 59416566Ssos 59516566Ssos case R_PS_2: /* PS/2 mouse */ 59616566Ssos act.buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */ 59716566Ssos (pBuf[0] & 0x02) >> 1 | /* Right */ 59816566Ssos (pBuf[0] & 0x01) << 2; /* Left */ 59916566Ssos act.dx = (pBuf[0] & 0x10) ? pBuf[1]-256 : pBuf[1]; 60016566Ssos act.dy = (pBuf[0] & 0x20) ? -(pBuf[2]-256) : -pBuf[2]; 60116566Ssos break; 60216566Ssos } 60316566Ssos pBufP = 0; 60416566Ssos return(&act); 60516566Ssos} 60618222Speter 60718222Speter/* $XConsortium: posix_tty.c,v 1.3 95/01/05 20:42:55 kaleb Exp $ */ 60818222Speter/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/shared/posix_tty.c,v 3.4 1995/01/28 17:05:03 dawes Exp $ */ 60918222Speter/* 61018222Speter * Copyright 1993 by David Dawes <dawes@physics.su.oz.au> 61118222Speter * 61218222Speter * Permission to use, copy, modify, distribute, and sell this software and its 61318222Speter * documentation for any purpose is hereby granted without fee, provided that 61418222Speter * the above copyright notice appear in all copies and that both that 61518222Speter * copyright notice and this permission notice appear in supporting 61618222Speter * documentation, and that the name of David Dawes 61718222Speter * not be used in advertising or publicity pertaining to distribution of 61818222Speter * the software without specific, written prior permission. 61918222Speter * David Dawes makes no representations about the suitability of this 62018222Speter * software for any purpose. It is provided "as is" without express or 62118222Speter * implied warranty. 62218222Speter * 62318222Speter * DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD TO 62418222Speter * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 62518222Speter * FITNESS, IN NO EVENT SHALL DAVID DAWES BE LIABLE FOR 62618222Speter * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 62718222Speter * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 62818222Speter * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 62918222Speter * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 63018222Speter * 63118222Speter */ 63218222Speter 63318222Speter 63418222Spetervoid 63518222Spetersetmousespeed(old, new, cflag) 63618222Speterint old; 63718222Speterint new; 63818222Speterunsigned cflag; 63918222Speter{ 64018222Speter struct termios tty; 64118222Speter char *c; 64218222Speter 64318222Speter if (tcgetattr(rodent.mfd, &tty) < 0) 64418222Speter { 64529849Scharnier err(1, "warning: unable to get status of mouse fd"); 64618222Speter } 64718222Speter 64818222Speter tty.c_iflag = IGNBRK | IGNPAR; 64918222Speter tty.c_oflag = 0; 65018222Speter tty.c_lflag = 0; 65118222Speter tty.c_cflag = (tcflag_t)cflag; 65218222Speter tty.c_cc[VTIME] = 0; 65318222Speter tty.c_cc[VMIN] = 1; 65418222Speter 65518222Speter switch (old) 65618222Speter { 65718222Speter case 9600: 65818222Speter cfsetispeed(&tty, B9600); 65918222Speter cfsetospeed(&tty, B9600); 66018222Speter break; 66118222Speter case 4800: 66218222Speter cfsetispeed(&tty, B4800); 66318222Speter cfsetospeed(&tty, B4800); 66418222Speter break; 66518222Speter case 2400: 66618222Speter cfsetispeed(&tty, B2400); 66718222Speter cfsetospeed(&tty, B2400); 66818222Speter break; 66918222Speter case 1200: 67018222Speter default: 67118222Speter cfsetispeed(&tty, B1200); 67218222Speter cfsetospeed(&tty, B1200); 67318222Speter } 67418222Speter 67518222Speter if (tcsetattr(rodent.mfd, TCSADRAIN, &tty) < 0) 67618222Speter { 67729849Scharnier err(1, "unable to set status of mouse fd"); 67818222Speter } 67918222Speter 68018222Speter switch (new) 68118222Speter { 68218222Speter case 9600: 68318222Speter c = "*q"; 68418222Speter cfsetispeed(&tty, B9600); 68518222Speter cfsetospeed(&tty, B9600); 68618222Speter break; 68718222Speter case 4800: 68818222Speter c = "*p"; 68918222Speter cfsetispeed(&tty, B4800); 69018222Speter cfsetospeed(&tty, B4800); 69118222Speter break; 69218222Speter case 2400: 69318222Speter c = "*o"; 69418222Speter cfsetispeed(&tty, B2400); 69518222Speter cfsetospeed(&tty, B2400); 69618222Speter break; 69718222Speter case 1200: 69818222Speter default: 69918222Speter c = "*n"; 70018222Speter cfsetispeed(&tty, B1200); 70118222Speter cfsetospeed(&tty, B1200); 70218222Speter } 70318222Speter 70418222Speter if (rodent.rtype == R_LOGIMAN || rodent.rtype == R_LOGITECH) 70518222Speter { 70618222Speter if (write(rodent.mfd, c, 2) != 2) 70718222Speter { 70829849Scharnier err(1, "unable to write to mouse fd"); 70918222Speter } 71018222Speter } 71118222Speter usleep(100000); 71218222Speter 71318222Speter if (tcsetattr(rodent.mfd, TCSADRAIN, &tty) < 0) 71418222Speter { 71529849Scharnier err(1,"unable to set status of mouse fd"); 71618222Speter } 71718222Speter} 718