1 /* Portions of this file were derived from the following files:
3 **********************************************************************
5 * Xserver/hw/kdrive/linux/ps2.c
7 * Copyright (c) 1999 by Keith Packard
9 * Permission to use, copy, modify, distribute, and sell this software and its
10 * documentation for any purpose is hereby granted without fee, provided that
11 * the above copyright notice appear in all copies and that both that
12 * copyright notice and this permission notice appear in supporting
13 * documentation, and that the name of Keith Packard not be used in
14 * advertising or publicity pertaining to distribution of the software without
15 * specific, written prior permission. Keith Packard makes no
16 * representations about the suitability of this software for any purpose. It
17 * is provided "as is" without express or implied warranty.
19 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
21 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
22 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
23 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
24 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
25 * PERFORMANCE OF THIS SOFTWARE.
30 * Copyright 2001,2003 Red Hat Inc., Durham, North Carolina.
32 * All Rights Reserved.
34 * Permission is hereby granted, free of charge, to any person obtaining
35 * a copy of this software and associated documentation files (the
36 * "Software"), to deal in the Software without restriction, including
37 * without limitation on the rights to use, copy, modify, merge,
38 * publish, distribute, sublicense, and/or sell copies of the Software,
39 * and to permit persons to whom the Software is furnished to do so,
40 * subject to the following conditions:
42 * The above copyright notice and this permission notice (including the
43 * next paragraph) shall be included in all copies or substantial
44 * portions of the Software.
46 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
47 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
48 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
49 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
50 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
51 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
52 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
58 * Rickard E. (Rik) Faith <faith@redhat.com>
64 * This code implements a low-level device driver for a serial MS mouse.
65 * The code is derived from code by Keith Packard (see the source code
66 * for complete references). */
68 #ifdef HAVE_DMX_CONFIG_H
69 #include <dmx-config.h>
77 /*****************************************************************************/
78 /* Define some macros to make it easier to move this file to another
79 * part of the Xserver tree. All calls to the dmx* layer are #defined
80 * here for the .c file. The .h file will also have to be edited. */
81 #include "dmxinputinit.h"
84 #define GETPRIV myPrivate *priv \
85 = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
87 #define LOG0(f) dmxLog(dmxDebug,f)
88 #define LOG1(f,a) dmxLog(dmxDebug,f,a)
89 #define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b)
90 #define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
91 #define FATAL0(f) dmxLog(dmxFatal,f)
92 #define FATAL1(f,a) dmxLog(dmxFatal,f,a)
93 #define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b)
94 #define MOTIONPROC dmxMotionProcPtr
95 #define ENQUEUEPROC dmxEnqueueProcPtr
96 #define CHECKPROC dmxCheckSpecialProcPtr
97 #define BLOCK DMXBlockType
99 /* End of interface definitions. */
100 /*****************************************************************************/
102 /* Private area for PS/2 devices. */
103 typedef struct _myPrivate
{
116 ps2LinuxReadBytes(int fd
, unsigned char *buf
, int len
, int min
)
124 n
= read(fd
, buf
, len
);
135 tv
.tv_usec
= 100 * 1000;
136 n
= select(fd
+ 1, &set
, 0, 0, &tv
);
144 ps2LinuxButton(DevicePtr pDev
, ENQUEUEPROC enqueue
, int buttons
, BLOCK block
)
150 enqueue(pDev, ButtonPress, 0, 0, NULL, block); \
155 enqueue(pDev, ButtonRelease, 0, 0, NULL, block); \
158 if ((buttons
& button1
) && !(priv
->buttons
& button1
))
160 if (!(buttons
& button1
) && (priv
->buttons
& button1
))
163 if ((buttons
& button2
) && !(priv
->buttons
& button2
))
165 if (!(buttons
& button2
) && (priv
->buttons
& button2
))
168 if ((buttons
& button3
) && !(priv
->buttons
& button3
))
170 if (!(buttons
& button3
) && (priv
->buttons
& button3
))
173 if ((buttons
& button4
) && !(priv
->buttons
& button4
))
175 if (!(buttons
& button4
) && (priv
->buttons
& button4
))
178 if ((buttons
& button5
) && !(priv
->buttons
& button5
))
180 if (!(buttons
& button5
) && (priv
->buttons
& button5
))
183 priv
->buttons
= buttons
;
186 /** Read an event from the \a pDev device. If the event is a motion
187 * event, enqueue it with the \a motion function. Otherwise, check for
188 * special keys with the \a checkspecial function and enqueue the event
189 * with the \a enqueue function. The \a block type is passed to the
190 * functions so that they may block SIGIO handling as appropriate to the
191 * caller of this function. */
193 ps2LinuxRead(DevicePtr pDev
, MOTIONPROC motion
,
194 ENQUEUEPROC enqueue
, CHECKPROC checkspecial
, BLOCK block
)
197 unsigned char buf
[3 * 200]; /* RATS: Use ok */
202 while ((n
= ps2LinuxReadBytes(priv
->fd
, buf
, sizeof(buf
), 3)) > 0) {
205 dx
= b
[1] - ((b
[0] & 0x10) ? 256 : 0);
206 dy
= -b
[2] + ((b
[0] & 0x20) ? 256 : 0);
210 motion(pDev
, v
, 0, 2, 1, block
);
211 ps2LinuxButton(pDev
, enqueue
, (((b
[0] & 4) ? button2
: 0)
212 | ((b
[0] & 2) ? button3
: 0)
213 | ((b
[0] & 1) ? button1
: 0)),
221 /** Initialize \a pDev. */
223 ps2LinuxInit(DevicePtr pDev
)
226 const char *names
[] = { "/dev/mouse", "/dev/psaux", NULL
};
232 for (i
= 0; names
[i
]; i
++) {
233 if ((priv
->fd
= open(names
[i
], O_RDWR
| O_NONBLOCK
, 0)) >= 0)
237 FATAL1("ps2LinuxInit: Cannot open mouse port (%s)\n", strerror(errno
));
240 /** Turn \a pDev on (i.e., take input from \a pDev). */
242 ps2LinuxOn(DevicePtr pDev
)
251 /** Turn \a pDev off (i.e., stop taking input from \a pDev). */
253 ps2LinuxOff(DevicePtr pDev
)
262 ps2LinuxGetMap(DevicePtr pDev
, unsigned char *map
, int *nButtons
)
269 for (i
= 0; i
<= *nButtons
; i
++)
273 /** Currently unused hook called prior to an VT switch. */
275 ps2LinuxVTPreSwitch(pointer p
)
279 /** Currently unused hook called after returning from a VT switch. */
281 ps2LinuxVTPostSwitch(pointer p
)
285 /** Create a private structure for use within this file. */
287 ps2LinuxCreatePrivate(DeviceIntPtr pMouse
)
289 myPrivate
*priv
= calloc(1, sizeof(*priv
));
292 priv
->pMouse
= pMouse
;
296 /** Destroy a private structure. */
298 ps2LinuxDestroyPrivate(pointer priv
)
303 /** Fill the \a info structure with information needed to initialize \a
306 ps2LinuxGetInfo(DevicePtr pDev
, DMXLocalInitInfoPtr info
)
308 info
->buttonClass
= 1;
309 ps2LinuxGetMap(pDev
, info
->map
, &info
->numButtons
);
310 info
->valuatorClass
= 1;
311 info
->numRelAxes
= 2;
317 info
->ptrFeedbackClass
= 1;