1 /* Portions of this file were derived from the following files:
3 **********************************************************************
5 * Xserver/hw/kdrive/linux/ms.c
7 * Copyright (c) 2001 by Juliusz Chroboczek
8 * Copyright (c) 1999 by Keith Packard
10 * Permission is hereby granted, free of charge, to any person obtaining
11 * a copy of this software and associated documentation files (the
12 * "Software"), to deal in the Software without restriction, including
13 * without limitation the rights to use, copy, modify, merge, publish,
14 * distribute, sublicense, and/or sell copies of the Software, and to
15 * permit persons to whom the Software is furnished to do so, subject to
16 * the following conditions:
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
25 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
26 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina.
35 * All Rights Reserved.
37 * Permission is hereby granted, free of charge, to any person obtaining
38 * a copy of this software and associated documentation files (the
39 * "Software"), to deal in the Software without restriction, including
40 * without limitation on the rights to use, copy, modify, merge,
41 * publish, distribute, sublicense, and/or sell copies of the Software,
42 * and to permit persons to whom the Software is furnished to do so,
43 * subject to the following conditions:
45 * The above copyright notice and this permission notice (including the
46 * next paragraph) shall be included in all copies or substantial
47 * portions of the Software.
49 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
50 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
51 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
52 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
53 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
54 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
55 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
61 * Rickard E. (Rik) Faith <faith@redhat.com>
67 * This code implements a low-level device driver for a serial MS mouse.
68 * The code is derived from code by Juliusz Chroboczek and Keith Packard
69 * (see the source code for complete references). */
71 #ifdef HAVE_DMX_CONFIG_H
72 #include <dmx-config.h>
80 /*****************************************************************************/
81 /* Define some macros to make it easier to move this file to another
82 * part of the Xserver tree. All calls to the dmx* layer are #defined
83 * here for the .c file. The .h file will also have to be edited. */
84 #include "dmxinputinit.h"
87 #define GETPRIV myPrivate *priv \
88 = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
90 #define LOG0(f) dmxLog(dmxDebug,f)
91 #define LOG1(f,a) dmxLog(dmxDebug,f,a)
92 #define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b)
93 #define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
94 #define FATAL0(f) dmxLog(dmxFatal,f)
95 #define FATAL1(f,a) dmxLog(dmxFatal,f,a)
96 #define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b)
97 #define MOTIONPROC dmxMotionProcPtr
98 #define ENQUEUEPROC dmxEnqueueProcPtr
99 #define CHECKPROC dmxCheckSpecialProcPtr
100 #define BLOCK DMXBlockType
102 /* End of interface definitions. */
103 /*****************************************************************************/
105 /* Private area for MS mouse devices. */
106 typedef struct _myPrivate
{
120 msLinuxReadBytes(int fd
, unsigned char *buf
, int len
, int min
)
128 n
= read(fd
, buf
, len
);
139 tv
.tv_usec
= 100 * 1000;
140 n
= select(fd
+ 1, &set
, 0, 0, &tv
);
148 msLinuxButton(DevicePtr pDev
, ENQUEUEPROC enqueue
, int buttons
, BLOCK block
)
154 enqueue(pDev, ButtonPress, 0, 0, NULL, block); \
159 enqueue(pDev, ButtonRelease, 0, 0, NULL, block); \
162 if ((buttons
& button1
) && !(priv
->buttons
& button1
))
164 if (!(buttons
& button1
) && (priv
->buttons
& button1
))
167 if ((buttons
& button2
) && !(priv
->buttons
& button2
))
169 if (!(buttons
& button2
) && (priv
->buttons
& button2
))
172 if ((buttons
& button3
) && !(priv
->buttons
& button3
))
174 if (!(buttons
& button3
) && (priv
->buttons
& button3
))
177 if ((buttons
& button4
) && !(priv
->buttons
& button4
))
179 if (!(buttons
& button4
) && (priv
->buttons
& button4
))
182 if ((buttons
& button5
) && !(priv
->buttons
& button5
))
184 if (!(buttons
& button5
) && (priv
->buttons
& button5
))
187 priv
->buttons
= buttons
;
190 /** Read an event from the \a pDev device. If the event is a motion
191 * event, enqueue it with the \a motion function. Otherwise, check for
192 * special keys with the \a checkspecial function and enqueue the event
193 * with the \a enqueue function. The \a block type is passed to the
194 * functions so that they may block SIGIO handling as appropriate to the
195 * caller of this function. */
197 msLinuxRead(DevicePtr pDev
,
199 ENQUEUEPROC enqueue
, CHECKPROC checkspecial
, BLOCK block
)
202 unsigned char buf
[3 * 200]; /* RATS: Use ok */
207 while ((n
= msLinuxReadBytes(priv
->fd
, buf
, sizeof(buf
), 3)) > 0) {
210 dx
= (char) (((b
[0] & 0x03) << 6) | (b
[1] & 0x3f));
211 dy
= (char) (((b
[0] & 0x0c) << 4) | (b
[2] & 0x3f));
215 motion(pDev
, v
, 0, 2, 1, block
);
216 msLinuxButton(pDev
, enqueue
, (((b
[0] & 0x10) ? button3
: 0)
217 | ((b
[0] & 0x20) ? button1
: 0)),
225 /** Initialize \a pDev. */
227 msLinuxInit(DevicePtr pDev
)
230 const char *names
[] = { "/dev/serialmouse", "/dev/mouse", NULL
};
236 for (i
= 0; names
[i
]; i
++) {
237 if ((priv
->fd
= open(names
[i
], O_RDWR
| O_NONBLOCK
, 0)) >= 0)
241 FATAL1("msLinuxInit: Cannot open mouse port (%s)\n", strerror(errno
));
243 if (!isatty(priv
->fd
))
244 FATAL1("msLinuxInit: Mouse port %s is not a tty\n", names
[i
]);
246 if (tcgetattr(priv
->fd
, &priv
->tty
) < 0)
247 FATAL1("msLinuxInit: tcgetattr failed (%s)\n", strerror(errno
));
249 write(priv
->fd
, "*n", 2); /* 1200 baud */
253 /** Turn \a pDev on (i.e., take input from \a pDev). */
255 msLinuxOn(DevicePtr pDev
)
264 nTty
.c_iflag
&= ~(IGNBRK
| BRKINT
| PARMRK
| ISTRIP
| INLCR
265 | IGNCR
| ICRNL
| IXON
| IXOFF
);
266 nTty
.c_oflag
&= ~OPOST
;
267 nTty
.c_lflag
&= ~(ECHO
| ECHONL
| ICANON
| ISIG
| IEXTEN
);
268 nTty
.c_cflag
&= ~(CSIZE
| PARENB
);
269 nTty
.c_cflag
|= CS8
| CLOCAL
| CSTOPB
;
270 nTty
.c_cc
[VTIME
] = 0;
272 cfsetispeed(&nTty
, B1200
);
273 cfsetospeed(&nTty
, B1200
);
274 if (tcsetattr(priv
->fd
, TCSANOW
, &nTty
) < 0)
275 FATAL1("msLinuxInit: tcsetattr failed (%s)\n", strerror(errno
));
276 write(priv
->fd
, "*V", 2); /* 2 button 3 byte protocol */
280 /** Turn \a pDev off (i.e., stop taking input from \a pDev). */
282 msLinuxOff(DevicePtr pDev
)
286 tcsetattr(priv
->fd
, TCSANOW
, &priv
->tty
);
292 msLinuxGetMap(DevicePtr pDev
, unsigned char *map
, int *nButtons
)
299 for (i
= 0; i
<= *nButtons
; i
++)
303 /** Currently unused hook called prior to an VT switch. */
305 msLinuxVTPreSwitch(pointer p
)
309 /** Currently unused hook called after returning from a VT switch. */
311 msLinuxVTPostSwitch(pointer p
)
315 /** Create a private structure for use within this file. */
317 msLinuxCreatePrivate(DeviceIntPtr pMouse
)
319 myPrivate
*priv
= calloc(1, sizeof(*priv
));
322 priv
->pMouse
= pMouse
;
326 /** Destroy a private structure. */
328 msLinuxDestroyPrivate(pointer priv
)
333 /** Fill the \a info structure with information needed to initialize \a
336 msLinuxGetInfo(DevicePtr pDev
, DMXLocalInitInfoPtr info
)
338 info
->buttonClass
= 1;
339 msLinuxGetMap(pDev
, info
->map
, &info
->numButtons
);
340 info
->valuatorClass
= 1;
341 info
->numRelAxes
= 2;
347 info
->ptrFeedbackClass
= 1;