moused.c revision 24428
1/**
2 ** Copyright (c) 1995 Michael Smith, All rights reserved.
3 **
4 ** Redistribution and use in source and binary forms, with or without
5 ** modification, are permitted provided that the following conditions
6 ** are met:
7 ** 1. Redistributions of source code must retain the above copyright
8 **    notice, this list of conditions and the following disclaimer as
9 **    the first lines of this file unmodified.
10 ** 2. Redistributions in binary form must reproduce the above copyright
11 **    notice, this list of conditions and the following disclaimer in the
12 **    documentation and/or other materials provided with the distribution.
13 ** 3. All advertising materials mentioning features or use of this software
14 **    must display the following acknowledgment:
15 **      This product includes software developed by Michael Smith.
16 ** 4. The name of the author may not be used to endorse or promote products
17 **    derived from this software without specific prior written permission.
18 **
19 **
20 ** THIS SOFTWARE IS PROVIDED BY Michael Smith ``AS IS'' AND ANY
21 ** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Michael Smith BE LIABLE FOR
24 ** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27 ** BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 ** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 **
32 **
33 **      $Id: moused.c,v 1.8 1997/03/29 12:10:26 peter Exp $
34 **/
35
36/**
37 ** MOUSED.C
38 **
39 ** Mouse daemon : listens to serial port for mouse data stream,
40 ** interprets same and passes ioctls off to the console driver.
41 **
42 ** The mouse interface functions are derived closely from the mouse
43 ** handler in the XFree86 X server.  Many thanks to the XFree86 people
44 ** for their great work!
45 **
46 **/
47
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51#include <limits.h>
52#include <errno.h>
53#include <fcntl.h>
54#include <termios.h>
55#include <machine/console.h>
56#include <sys/types.h>
57#include <sys/time.h>
58#include <unistd.h>
59
60#define debug(fmt,args...) \
61	if (debug&&nodaemon) fprintf(stderr,"%s: " fmt "\n", progname, ##args)
62
63char	*progname;
64int	debug = 0;
65int	nodaemon = 0;
66
67void	usage(void);
68
69#define	R_UNKNOWN	0
70#define R_MICROSOFT	1
71#define R_MOUSESYS	2
72#define R_MMSERIES	3
73#define R_LOGITECH	4
74#define R_BUSMOUSE	5
75#define R_LOGIMAN	6
76#define R_PS_2		7
77#define R_MMHITAB	8
78
79char	*rnames[] = {
80    "xxx",
81    "microsoft",
82    "mousesystems",
83    "mmseries",
84    "logitech",
85    "busmouse",
86    "mouseman",
87    "ps/2",
88    "mmhitab",
89    NULL
90};
91
92unsigned short rodentcflags[] =
93{
94    0,							/* nomouse */
95    (CS7	           | CREAD | CLOCAL | HUPCL ),	/* MicroSoft */
96    (CS8 | CSTOPB	   | CREAD | CLOCAL | HUPCL ),	/* MouseSystems */
97    (CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL ),	/* MMSeries */
98    (CS8 | CSTOPB	   | CREAD | CLOCAL | HUPCL ),	/* Logitech */
99    0,							/* BusMouse */
100    (CS7		   | CREAD | CLOCAL | HUPCL ),	/* MouseMan */
101    0,							/* PS/2 */
102    (CS8		   | CREAD | CLOCAL | HUPCL ),	/* MMHitTablet */
103};
104
105
106typedef struct
107{
108    int
109	dx,dy,
110	buttons;
111} ACTIVITY;
112
113
114struct rodentparam
115{
116    int
117	baudrate,
118	samplerate,
119	flags,
120	rtype,
121	lastbuttons,
122	buttons,
123	mfd,
124	cleardtr,
125	clearrts;
126
127    char
128	*portname;
129
130} rodent = { baudrate : 1200,
131	     samplerate : 0,
132             flags : 0,
133             rtype : R_UNKNOWN,
134	     lastbuttons : 0,
135	     buttons : 0,
136	     mfd : -1,
137	     portname : NULL,
138	     cleardtr : 0,
139	     clearrts : 0};
140
141#define	ChordMiddle	1
142
143void		r_init(void);
144ACTIVITY	*r_protocol(u_char b);
145void		setmousespeed(int old, int new, unsigned cflag);
146
147void
148main(int argc, char *argv[])
149{
150    int			c,i,cfd;
151    u_char		b;
152    ACTIVITY		*act;
153    struct termios	t;
154    struct mouse_info 	mouse;
155    int			saved_buttons = 0;
156    fd_set		fds;
157
158    progname = argv[0];
159
160    while((c = getopt(argc,argv,"cdfr:sp:t:h?RDS:")) != -1)
161	switch(c)
162	{
163	case 'c':
164	    rodent.flags |= ChordMiddle;
165	    break;
166
167	case 'd':
168	    debug = 1;
169	    break;
170
171	case 'f':
172	    nodaemon = 1;
173	    break;
174
175	case 'p':
176	    rodent.portname = optarg;
177	    break;
178
179	case 'r':
180	    rodent.samplerate = atoi(optarg);
181	    break;
182
183	case 's':
184	    rodent.baudrate = 9600;
185	    break;
186
187	case 'R':
188	    rodent.clearrts = 1;
189	    break;
190
191	case 'D':
192	    rodent.cleardtr = 1;
193	    break;
194
195	case 'S':
196	    rodent.baudrate = atoi(optarg);
197	    debug("rodent baudrate %d", rodent.baudrate);
198	    break;
199
200	case 't':
201	    for (i = 0; rnames[i]; i++)
202		if (!strcmp(optarg,rnames[i]))
203		{
204		    debug("rodent is %s",rnames[i]);
205		    rodent.rtype = i;
206		    break;
207		}
208	    if (rnames[i])
209		break;
210	    warnx("no such mouse type `%s'",optarg);
211	    usage();
212
213	case 'h':
214	case '?':
215	default:
216	    usage();
217	}
218
219    switch(rodent.rtype)
220    {
221    case R_BUSMOUSE:
222	if (!rodent.portname)
223	    rodent.portname = "/dev/mse0";
224	break;
225    case R_PS_2:
226	if (!rodent.portname)
227	    rodent.portname = "/dev/psm0";
228	break;
229    default:
230	if (rodent.portname)
231	    break;
232	warnx("No port name specified");
233	usage();
234    }
235
236    if ((rodent.mfd = open(rodent.portname, O_RDWR, 0)) == -1)
237    {
238	warn("Can't open %s",rodent.portname);
239	usage();
240    }
241    r_init();				/* call init function */
242
243    if ((cfd = open("/dev/consolectl", O_RDWR, 0)) == -1)
244	err(1, "open(/dev/consolectl)");
245
246    if (!nodaemon)
247	if (daemon(0,0))
248	{
249	    err(1, "daemon() failed");
250	}
251
252    for(;;)
253    {
254	FD_ZERO(&fds);
255	FD_SET(rodent.mfd,&fds);
256	select(FD_SETSIZE,&fds,NULL,&fds,NULL);
257	i = read(rodent.mfd,&b,1);	/* get a byte */
258	if (i != 1)			/* read returned or error; goodbye */
259	{
260	    debug("read returned %d : %s exiting",i,strerror(errno));
261	    close(rodent.mfd);
262	    exit(1);
263	}
264	act = r_protocol(b);		/* pass byte to handler */
265	if (act)			/* handler detected action */
266	{
267	    mouse.operation = MOUSE_ACTION;
268	    mouse.u.data.x = act->dx;
269	    mouse.u.data.y = act->dy;
270	    mouse.u.data.buttons = act->buttons;
271	    ioctl(cfd, CONS_MOUSECTL, &mouse);
272	    debug("Activity : buttons 0x%02x  dx %d  dy %d",
273		    act->buttons,act->dx,act->dy);
274	}
275    }
276}
277
278
279/**
280 ** usage
281 **
282 ** Complain, and free the CPU for more worthy tasks
283 **/
284void
285usage(void)
286{
287    fprintf(stderr,
288	    " Usage is %s [options] -p <port> -t <mousetype>\n"
289	    "  Options are   -s   Select 9600 baud mouse.\n"
290	    "                -f   Don't become a daemon\n"
291	    "                -d   Enable debugging messages\n"
292	    "                -c   Enable ChordMiddle option\n"
293	    "                -R   Lower RTS\n"
294	    "                -D   Lower DTR\n"
295	    "                -S baud  Select explicit baud (1200..9600).\n"
296	    "  <mousetype> should be one of :\n"
297	    "                microsoft\n"
298	    "                mousesystems\n"
299	    "                mmseries\n"
300	    "                logitech\n"
301	    "                busmouse\n"
302	    "                mouseman\n"
303	    "                ps/2\n"
304	    "                mmhittab\n"
305	    ,progname);
306
307    exit(1);
308}
309
310
311/**
312 ** Mouse interface code, courtesy of XFree86 3.1.2.
313 **
314 ** Note: Various bits have been trimmed, and in my shortsighted enthusiasm
315 ** to clean, reformat and rationalise naming, it's quite possible that
316 ** some things in here have been broken.
317 **
318 ** I hope not 8)
319 **
320 ** The following code is derived from a module marked :
321 **/
322
323/* $XConsortium: xf86_Mouse.c,v 1.2 94/10/12 20:33:21 kaleb Exp $ */
324/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86_Mouse.c,v 3.2 1995/01/28
325 17:03:40 dawes Exp $ */
326/*
327 *
328 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
329 * Copyright 1993 by David Dawes <dawes@physics.su.oz.au>
330 *
331 * Permission to use, copy, modify, distribute, and sell this software and its
332 * documentation for any purpose is hereby granted without fee, provided that
333 * the above copyright notice appear in all copies and that both that
334 * copyright notice and this permission notice appear in supporting
335 * documentation, and that the names of Thomas Roell and David Dawes not be
336 * used in advertising or publicity pertaining to distribution of the
337 * software without specific, written prior permission.  Thomas Roell
338 * and David Dawes makes no representations about the suitability of this
339 * software for any purpose.  It is provided "as is" without express or
340 * implied warranty.
341 *
342 * THOMAS ROELL AND DAVID DAWES DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
343 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
344 * FITNESS, IN NO EVENT SHALL THOMAS ROELL OR DAVID DAWES BE LIABLE FOR ANY
345 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
346 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
347 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
348 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
349 *
350 */
351
352
353void
354r_init(void)
355{
356    /**
357     ** This comment is a little out of context here, but it contains
358     ** some useful information...
359     ********************************************************************
360     **
361     ** The following lines take care of the Logitech MouseMan protocols.
362     **
363     ** NOTE: There are different versions of both MouseMan and TrackMan!
364     **       Hence I add another protocol P_LOGIMAN, which the user can
365     **       specify as MouseMan in his XF86Config file. This entry was
366     **       formerly handled as a special case of P_MS. However, people
367     **       who don't have the middle button problem, can still specify
368     **       Microsoft and use P_MS.
369     **
370     ** By default, these mice should use a 3 byte Microsoft protocol
371     ** plus a 4th byte for the middle button. However, the mouse might
372     ** have switched to a different protocol before we use it, so I send
373     ** the proper sequence just in case.
374     **
375     ** NOTE: - all commands to (at least the European) MouseMan have to
376     **         be sent at 1200 Baud.
377     **       - each command starts with a '*'.
378     **       - whenever the MouseMan receives a '*', it will switch back
379     **	 to 1200 Baud. Hence I have to select the desired protocol
380     **	 first, then select the baud rate.
381     **
382     ** The protocols supported by the (European) MouseMan are:
383     **   -  5 byte packed binary protocol, as with the Mouse Systems
384     **      mouse. Selected by sequence "*U".
385     **   -  2 button 3 byte MicroSoft compatible protocol. Selected
386     **      by sequence "*V".
387     **   -  3 button 3+1 byte MicroSoft compatible protocol (default).
388     **      Selected by sequence "*X".
389     **
390     ** The following baud rates are supported:
391     **   -  1200 Baud (default). Selected by sequence "*n".
392     **   -  9600 Baud. Selected by sequence "*q".
393     **
394     ** Selecting a sample rate is no longer supported with the MouseMan!
395     ** Some additional lines in xf86Config.c take care of ill configured
396     ** baud rates and sample rates. (The user will get an error.)
397     */
398
399
400    if (rodent.rtype == R_LOGIMAN)
401    {
402	setmousespeed(1200, 1200, rodentcflags[R_LOGIMAN]);
403	write(rodent.mfd, "*X", 2);
404	setmousespeed(1200, rodent.baudrate, rodentcflags[R_LOGIMAN]);
405    } else {
406	if ((rodent.rtype != R_BUSMOUSE) && (rodent.rtype != R_PS_2))
407	{
408	    /* try all likely settings */
409	    setmousespeed(9600, rodent.baudrate, rodentcflags[rodent.rtype]);
410	    setmousespeed(4800, rodent.baudrate, rodentcflags[rodent.rtype]);
411	    setmousespeed(2400, rodent.baudrate, rodentcflags[rodent.rtype]);
412	    setmousespeed(1200, rodent.baudrate, rodentcflags[rodent.rtype]);
413
414	    if (rodent.rtype == R_LOGITECH) {
415		write(rodent.mfd, "S", 1);
416		setmousespeed(rodent.baudrate, rodent.baudrate,
417			rodentcflags[R_MMSERIES]);
418	    }
419
420	    if (rodent.rtype == R_MMHITAB) {
421		char speedcmd;
422	    /*
423	     * Initialize Hitachi PUMA Plus - Model 1212E to desired settings.
424	     * The tablet must be configured to be in MM mode, NO parity,
425	     * Binary Format.  xf86Info.sampleRate controls the sensativity
426	     * of the tablet.  We only use this tablet for it's 4-button puck
427	     * so we don't run in "Absolute Mode"
428	     */
429		write(rodent.mfd, "z8", 2);	/* Set Parity = "NONE" */
430		usleep(50000);
431		write(rodent.mfd, "zb", 2);	/* Set Format = "Binary" */
432		usleep(50000);
433		write(rodent.mfd, "@", 1);	/* Set Report Mode = "Stream" */
434		usleep(50000);
435		write(rodent.mfd, "R", 1);	/* Set Output Rate = "45 rps" */
436		usleep(50000);
437		write(rodent.mfd, "I\x20", 2);	/* Set Incrememtal Mode "20" */
438		usleep(50000);
439		write(rodent.mfd, "E", 1);	/* Set Data Type = "Relative */
440		usleep(50000);
441
442		/* These sample rates translate to 'lines per inch' on the
443		   Hitachi tablet */
444		if      (rodent.samplerate <=   40) speedcmd = 'g';
445		else if (rodent.samplerate <=  100) speedcmd = 'd';
446		else if (rodent.samplerate <=  200) speedcmd = 'e';
447		else if (rodent.samplerate <=  500) speedcmd = 'h';
448		else if (rodent.samplerate <= 1000) speedcmd = 'j';
449		else                                speedcmd = 'd';
450		write(rodent.mfd, &speedcmd, 1);
451		usleep(50000);
452
453		write(rodent.mfd, "\021", 1);	/* Resume DATA output */
454	    } else {
455		if      (rodent.samplerate <= 0)   write(rodent.mfd, "O", 1);
456		else if (rodent.samplerate <= 15)  write(rodent.mfd, "J", 1);
457		else if (rodent.samplerate <= 27)  write(rodent.mfd, "K", 1);
458		else if (rodent.samplerate <= 42)  write(rodent.mfd, "L", 1);
459		else if (rodent.samplerate <= 60)  write(rodent.mfd, "R", 1);
460		else if (rodent.samplerate <= 85)  write(rodent.mfd, "M", 1);
461		else if (rodent.samplerate <= 125) write(rodent.mfd, "Q", 1);
462		else				   write(rodent.mfd, "N", 1);
463	    }
464	}
465    }
466    if (rodent.rtype == R_MOUSESYS && (rodent.cleardtr))
467    {
468	int val = TIOCM_DTR;
469	ioctl(rodent.mfd, TIOCMBIC, &val);
470    }
471    if (rodent.rtype == R_MOUSESYS && (rodent.clearrts))
472    {
473	int val = TIOCM_RTS;
474	ioctl(rodent.mfd, TIOCMBIC, &val);
475    }
476}
477
478ACTIVITY *
479r_protocol(u_char rBuf)
480{
481    static int           pBufP = 0;
482    static unsigned char pBuf[8];
483    static ACTIVITY	 act;
484
485    static unsigned char proto[10][5] = {
486    /*  hd_mask hd_id   dp_mask dp_id   nobytes */
487    {	0,	0,	0,	0,	0	},  /* nomouse */
488    { 	0x40,	0x40,	0x40,	0x00,	3 	},  /* MicroSoft */
489    {	0xf8,	0x80,	0x00,	0x00,	5	},  /* MouseSystems */
490    {	0xe0,	0x80,	0x80,	0x00,	3	},  /* MMSeries */
491    {	0xe0,	0x80,	0x80,	0x00,	3	},  /* Logitech */
492    {	0xf8,	0x80,	0x00,	0x00,	5	},  /* BusMouse */
493    { 	0x40,	0x40,	0x40,	0x00,	3 	},  /* MouseMan */
494    {	0xc0,	0x00,	0x00,	0x00,	3	},  /* PS/2 mouse */
495    {	0xe0,	0x80,	0x80,	0x00,	3	},  /* MM_HitTablet */
496    };
497
498    debug("received char 0x%x",(int)rBuf);
499
500    /*
501     * Hack for resyncing: We check here for a package that is:
502     *  a) illegal (detected by wrong data-package header)
503     *  b) invalid (0x80 == -128 and that might be wrong for MouseSystems)
504     *  c) bad header-package
505     *
506     * NOTE: b) is a voilation of the MouseSystems-Protocol, since values of
507     *       -128 are allowed, but since they are very seldom we can easily
508     *       use them as package-header with no button pressed.
509     * NOTE/2: On a PS/2 mouse any byte is valid as a data byte. Furthermore,
510     *         0x80 is not valid as a header byte. For a PS/2 mouse we skip
511     *         checking data bytes.
512     *         For resyncing a PS/2 mouse we require the two most significant
513     *         bits in the header byte to be 0. These are the overflow bits,
514     *         and in case of an overflow we actually lose sync. Overflows
515     *         are very rare, however, and we quickly gain sync again after
516     *         an overflow condition. This is the best we can do. (Actually,
517     *         we could use bit 0x08 in the header byte for resyncing, since
518     *         that bit is supposed to be always on, but nobody told
519     *         Microsoft...)
520     */
521
522    if (pBufP != 0 && rodent.rtype != R_PS_2 &&
523	((rBuf & proto[rodent.rtype][2]) != proto[rodent.rtype][3]
524	 || rBuf == 0x80))
525    {
526	pBufP = 0;		/* skip package */
527    }
528
529    if (pBufP == 0 &&
530	(rBuf & proto[rodent.rtype][0]) != proto[rodent.rtype][1])
531    {
532	/*
533	 * Hack for Logitech MouseMan Mouse - Middle button
534	 *
535	 * Unfortunately this mouse has variable length packets: the standard
536	 * Microsoft 3 byte packet plus an optional 4th byte whenever the
537	 * middle button status changes.
538	 *
539	 * We have already processed the standard packet with the movement
540	 * and button info.  Now post an event message with the old status
541	 * of the left and right buttons and the updated middle button.
542	 */
543
544	/*
545	 * Even worse, different MouseMen and TrackMen differ in the 4th
546	 * byte: some will send 0x00/0x20, others 0x01/0x21, or even
547	 * 0x02/0x22, so I have to strip off the lower bits.
548	 */
549	if ((rodent.rtype == R_MICROSOFT || rodent.rtype == R_LOGIMAN)
550	    && (char)(rBuf & ~0x23) == 0)
551	{
552	    act.buttons = ((int)(rBuf & 0x20) >> 4)
553		| (rodent.lastbuttons & 0x05);
554	    rodent.lastbuttons = act.buttons;	/* save new button state */
555	    return(&act);
556	}
557
558	return(NULL);				/* skip package */
559    }
560
561    pBuf[pBufP++] = rBuf;
562    if (pBufP != proto[rodent.rtype][4]) return(NULL);
563
564    /*
565     * assembly full package
566     */
567
568    debug("Assembled full packet (len %d) %x,%x,%x,%x,%x",
569	proto[rodent.rtype][4], pBuf[0],pBuf[1],pBuf[2],pBuf[3],pBuf[4]);
570
571    switch(rodent.rtype)
572    {
573    case R_LOGIMAN:		/* MouseMan / TrackMan */
574    case R_MICROSOFT:		/* Microsoft */
575	if (rodent.flags & ChordMiddle)
576	    act.buttons = (((int) pBuf[0] & 0x30) == 0x30) ? 2 :
577		           ((int)(pBuf[0]&0x20)>>3) | ((int)(pBuf[0]&0x10)>>4);
578	else
579	    act.buttons =   (rodent.lastbuttons & 2)
580		          | ((int)(pBuf[0] & 0x20) >> 3)
581		          | ((int)(pBuf[0] & 0x10) >> 4);
582	act.dx = (char)(((pBuf[0] & 0x03) << 6) | (pBuf[1] & 0x3F));
583	act.dy = (char)(((pBuf[0] & 0x0C) << 4) | (pBuf[2] & 0x3F));
584	break;
585
586    case R_MOUSESYS:		/* Mouse Systems Corp */
587	act.buttons = (~pBuf[0]) & 0x07;
588	act.dx =    (char)(pBuf[1]) + (char)(pBuf[3]);
589	act.dy = - ((char)(pBuf[2]) + (char)(pBuf[4]));
590	break;
591
592    case R_MMHITAB:		/* MM_HitTablet */
593	act.buttons = pBuf[0] & 0x07;
594	if (act.buttons != 0)
595	    act.buttons = 1 << (act.buttons - 1);
596	act.dx = (pBuf[0] & 0x10) ?   pBuf[1] : - pBuf[1];
597	act.dy = (pBuf[0] & 0x08) ? - pBuf[2] :   pBuf[2];
598	break;
599
600    case R_MMSERIES:		/* MM Series */
601    case R_LOGITECH:		/* Logitech Mice */
602	act.buttons = pBuf[0] & 0x07;
603	act.dx = (pBuf[0] & 0x10) ?   pBuf[1] : - pBuf[1];
604	act.dy = (pBuf[0] & 0x08) ? - pBuf[2] :   pBuf[2];
605	break;
606
607    case R_BUSMOUSE:		/* BusMouse */
608	act.buttons = (~pBuf[0]) & 0x07;
609	act.dx =   (char)pBuf[1];
610	act.dy = - (char)pBuf[2];
611	break;
612
613    case R_PS_2:		/* PS/2 mouse */
614	act.buttons = (pBuf[0] & 0x04) >> 1 | /* Middle */
615	              (pBuf[0] & 0x02) >> 1 | /* Right */
616		      (pBuf[0] & 0x01) << 2; /* Left */
617	act.dx = (pBuf[0] & 0x10) ?    pBuf[1]-256  :  pBuf[1];
618	act.dy = (pBuf[0] & 0x20) ?  -(pBuf[2]-256) : -pBuf[2];
619	break;
620    }
621    pBufP = 0;
622    return(&act);
623}
624
625/* $XConsortium: posix_tty.c,v 1.3 95/01/05 20:42:55 kaleb Exp $ */
626/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/shared/posix_tty.c,v 3.4 1995/01/28 17:05:03 dawes Exp $ */
627/*
628 * Copyright 1993 by David Dawes <dawes@physics.su.oz.au>
629 *
630 * Permission to use, copy, modify, distribute, and sell this software and its
631 * documentation for any purpose is hereby granted without fee, provided that
632 * the above copyright notice appear in all copies and that both that
633 * copyright notice and this permission notice appear in supporting
634 * documentation, and that the name of David Dawes
635 * not be used in advertising or publicity pertaining to distribution of
636 * the software without specific, written prior permission.
637 * David Dawes makes no representations about the suitability of this
638 * software for any purpose.  It is provided "as is" without express or
639 * implied warranty.
640 *
641 * DAVID DAWES DISCLAIMS ALL WARRANTIES WITH REGARD TO
642 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
643 * FITNESS, IN NO EVENT SHALL DAVID DAWES BE LIABLE FOR
644 * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
645 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
646 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
647 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
648 *
649 */
650
651
652void
653setmousespeed(old, new, cflag)
654int old;
655int new;
656unsigned cflag;
657{
658	struct termios tty;
659	char *c;
660
661	if (tcgetattr(rodent.mfd, &tty) < 0)
662	{
663		err(1, "Warning: unable to get status of mouse fd");
664	}
665
666	tty.c_iflag = IGNBRK | IGNPAR;
667	tty.c_oflag = 0;
668	tty.c_lflag = 0;
669	tty.c_cflag = (tcflag_t)cflag;
670	tty.c_cc[VTIME] = 0;
671	tty.c_cc[VMIN] = 1;
672
673	switch (old)
674	{
675	case 9600:
676		cfsetispeed(&tty, B9600);
677		cfsetospeed(&tty, B9600);
678		break;
679	case 4800:
680		cfsetispeed(&tty, B4800);
681		cfsetospeed(&tty, B4800);
682		break;
683	case 2400:
684		cfsetispeed(&tty, B2400);
685		cfsetospeed(&tty, B2400);
686		break;
687	case 1200:
688	default:
689		cfsetispeed(&tty, B1200);
690		cfsetospeed(&tty, B1200);
691	}
692
693	if (tcsetattr(rodent.mfd, TCSADRAIN, &tty) < 0)
694	{
695		err(1, "Unable to set status of mouse fd");
696	}
697
698	switch (new)
699	{
700	case 9600:
701		c = "*q";
702		cfsetispeed(&tty, B9600);
703		cfsetospeed(&tty, B9600);
704		break;
705	case 4800:
706		c = "*p";
707		cfsetispeed(&tty, B4800);
708		cfsetospeed(&tty, B4800);
709		break;
710	case 2400:
711		c = "*o";
712		cfsetispeed(&tty, B2400);
713		cfsetospeed(&tty, B2400);
714		break;
715	case 1200:
716	default:
717		c = "*n";
718		cfsetispeed(&tty, B1200);
719		cfsetospeed(&tty, B1200);
720	}
721
722	if (rodent.rtype == R_LOGIMAN || rodent.rtype == R_LOGITECH)
723	{
724		if (write(rodent.mfd, c, 2) != 2)
725		{
726			err(1, "Unable to write to mouse fd");
727		}
728	}
729	usleep(100000);
730
731	if (tcsetattr(rodent.mfd, TCSADRAIN, &tty) < 0)
732	{
733		err(1,"Unable to set status of mouse fd");
734	}
735}
736