2 * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation on the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * Rickard E. (Rik) Faith <faith@redhat.com>
36 * Routines that are common between \a usb-keyboard.c, \a usb-mouse.c, and
39 #ifdef HAVE_DMX_CONFIG_H
40 #include <dmx-config.h>
43 #include "usb-private.h"
45 #define USB_COMMON_DEBUG 1
47 /*****************************************************************************/
48 /* Define some macros to make it easier to move this file to another
49 * part of the Xserver tree. All calls to the dmx* layer are #defined
50 * here for the .c file. The .h file will also have to be edited. */
51 #include "usb-mouse.h"
53 #define GETPRIV myPrivate *priv \
54 = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
56 #define GETNAME ((DMXLocalInputInfoPtr)(pDevice->public.devicePrivate)) \
59 #define LOG0(f) dmxLog(dmxDebug,f)
60 #define LOG1(f,a) dmxLog(dmxDebug,f,a)
61 #define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b)
62 #define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
63 #define LOG1INPUT(p,f,a) dmxLogInput(p->dmxInput,f,a)
64 #define LOG3INPUT(p,f,a,b,c) dmxLogInput(p->dmxInput,f,a,b,c)
65 #define LOG5INPUT(p,f,a,b,c,d,e) dmxLogInput(p->dmxInput,f,a,b,c,d,e)
66 #define FATAL0(f) dmxLog(dmxFatal,f)
67 #define FATAL1(f,a) dmxLog(dmxFatal,f,a)
68 #define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b)
69 #define MOTIONPROC dmxMotionProcPtr
70 #define ENQUEUEPROC dmxEnqueueProcPtr
71 #define CHECKPROC dmxCheckSpecialProcPtr
72 #define BLOCK DMXBlockType
74 /* End of interface definitions. */
75 /*****************************************************************************/
77 /** Read an event from the \a pDev device. If the event is a motion
78 * event, enqueue it with the \a motion function. Otherwise, enqueue
79 * the event with the \a enqueue function. The \a block type is passed
80 * to the functions so that they may block SIGIO handling as appropriate
81 * to the caller of this function.
83 * Since USB devices return EV_KEY events for buttons and keys, \a
84 * minButton is used to decide if a Button or Key event should be
87 usbRead(DevicePtr pDev
,
88 MOTIONPROC motion
, ENQUEUEPROC enqueue
, int minButton
, BLOCK block
)
91 struct input_event raw
;
97 enqueue(pDev, ButtonPress, 0, 0, NULL, block); \
102 enqueue(pDev, ButtonRelease, 0, 0, NULL, block); \
105 while (read(priv
->fd
, &raw
, sizeof(raw
)) > 0) {
106 #if USB_COMMON_DEBUG > 1
107 LOG3("USB: type = %d, code = 0x%02x, value = %d\n",
108 raw
.type
, raw
.code
, raw
.value
);
112 /* raw.value = 1 for first, 2 for repeat */
113 if (raw
.code
> minButton
) {
115 PRESS((raw
.code
& 0x0f) + 1);
117 RELEASE((raw
.code
& 0x0f) + 1);
120 enqueue(pDev
, raw
.value
? KeyPress
: KeyRelease
,
129 motion(pDev
, v
, 0, 2, DMX_RELATIVE
, block
);
134 motion(pDev
, v
, 0, 2, DMX_RELATIVE
, block
);
137 if ((int) raw
.value
> 0) {
141 else if ((int) raw
.value
< 0) {
147 memset(v
, 0, sizeof(v
));
148 axis
= priv
->relmap
[raw
.code
];
150 motion(pDev
, v
, axis
, 1, DMX_RELATIVE
, block
);
154 memset(v
, 0, sizeof(v
));
155 axis
= priv
->absmap
[raw
.code
];
157 motion(pDev
, v
, axis
, 1, DMX_ABSOLUTE
, block
);
163 #define test_bit(bit) (priv->mask[(bit)/8] & (1 << ((bit)%8)))
164 #define test_bits(bit) (bits[(bit)/8] & (1 << ((bit)%8)))
167 usbPrint(myPrivate
* priv
, const char *filename
, const char *devname
, int fd
)
170 DeviceIntPtr pDevice
= priv
->pDevice
;
171 unsigned char bits
[KEY_MAX
/ 8 + 1]; /* RATS: Use ok assuming that
172 * KEY_MAX is greater than
173 * REL_MAX, ABS_MAX, SND_MAX, and
176 LOG3INPUT(priv
, "%s (%s) using %s\n", pDevice
->name
, GETNAME
, filename
);
177 LOG1INPUT(priv
, " %s\n", devname
);
178 for (j
= 0; j
< EV_MAX
; j
++) {
180 const char *type
= "unknown";
181 char extra
[256]; /* FIXME: may cause buffer overflow */
186 type
= "keys/buttons";
190 memset(bits
, 0, sizeof(bits
));
191 ioctl(priv
->fd
, EVIOCGBIT(EV_REL
, sizeof(bits
)), bits
);
192 for (k
= 0; k
< REL_MAX
; k
++) {
205 strcat(extra
, " HWheel");
208 strcat(extra
, " Dial");
211 strcat(extra
, " Wheel");
214 strcat(extra
, " Misc");
221 memset(bits
, 0, sizeof(bits
));
222 ioctl(priv
->fd
, EVIOCGBIT(EV_ABS
, sizeof(bits
)), bits
);
223 for (k
= 0; k
< ABS_MAX
; k
++) {
236 strcat(extra
, " RX");
239 strcat(extra
, " RY");
242 strcat(extra
, " RZ");
245 strcat(extra
, " Throttle");
248 strcat(extra
, " Rudder");
251 strcat(extra
, " Wheel");
254 strcat(extra
, " Gas");
257 strcat(extra
, " Break");
260 strcat(extra
, " Hat0X");
263 strcat(extra
, " Hat0Y");
266 strcat(extra
, " Hat1X");
269 strcat(extra
, " Hat1Y");
272 strcat(extra
, " Hat2X");
275 strcat(extra
, " Hat2Y");
278 strcat(extra
, " Hat3X");
281 strcat(extra
, " Hat3Y");
284 strcat(extra
, " Pressure");
287 strcat(extra
, " Distance");
290 strcat(extra
, " TiltX");
293 strcat(extra
, " TiltY");
296 strcat(extra
, " Misc");
306 memset(bits
, 0, sizeof(bits
));
307 ioctl(priv
->fd
, EVIOCGBIT(EV_LED
, sizeof(bits
)), bits
);
308 for (k
= 0; k
< LED_MAX
; k
++) {
312 strcat(extra
, " NumLock");
315 strcat(extra
, " CapsLock");
318 strcat(extra
, " ScrlLock");
321 strcat(extra
, " Compose");
324 strcat(extra
, " Kana");
327 strcat(extra
, " Sleep");
330 strcat(extra
, " Suspend");
333 strcat(extra
, " Mute");
336 strcat(extra
, " Misc");
343 memset(bits
, 0, sizeof(bits
));
344 ioctl(priv
->fd
, EVIOCGBIT(EV_SND
, sizeof(bits
)), bits
);
345 for (k
= 0; k
< SND_MAX
; k
++) {
349 strcat(extra
, " Click");
352 strcat(extra
, " Bell");
364 LOG5INPUT(priv
, " Feature 0x%02x = %s%s%s%s\n", j
, type
,
365 extra
[0] ? " [" : "",
366 extra
[0] ? extra
+ 1 : "", extra
[0] ? "]" : "");
371 /** Initialized \a pDev as a \a usbMouse, \a usbKeyboard, or \a usbOther
374 usbInit(DevicePtr pDev
, usbType type
)
377 char name
[64]; /* RATS: Only used in snprintf */
379 char buf
[256] = { 0, }; /* RATS: Use ok */
381 unsigned char bits
[KEY_MAX
/ 8 + 1]; /* RATS: Use ok assuming that
382 * KEY_MAX is greater than
383 * REL_MAX, ABS_MAX, SND_MAX, and
389 for (i
= 0; i
< 32; i
++) {
390 snprintf(name
, sizeof(name
), "/dev/input/event%d", i
);
391 if ((priv
->fd
= open(name
, O_RDWR
| O_NONBLOCK
, 0)) >= 0) {
392 ioctl(priv
->fd
, EVIOCGVERSION
, &version
);
393 ioctl(priv
->fd
, EVIOCGNAME(sizeof(buf
)), buf
);
394 memset(priv
->mask
, 0, sizeof(priv
->mask
));
395 ioctl(priv
->fd
, EVIOCGBIT(0, sizeof(priv
->mask
)), priv
->mask
);
397 for (j
= 0; j
< EV_MAX
; j
++) {
401 memset(bits
, 0, sizeof(bits
));
402 ioctl(priv
->fd
, EVIOCGBIT(EV_REL
, sizeof(bits
)), bits
);
403 for (k
= 0; k
< REL_MAX
; k
++) {
410 priv
->relmap
[k
] = 2 + priv
->numAbs
;
416 memset(bits
, 0, sizeof(bits
));
417 ioctl(priv
->fd
, EVIOCGBIT(EV_ABS
, sizeof(bits
)), bits
);
418 for (k
= 0; k
< ABS_MAX
; k
++) {
420 priv
->absmap
[k
] = priv
->numAbs
;
426 memset(bits
, 0, sizeof(bits
));
427 ioctl(priv
->fd
, EVIOCGBIT(EV_LED
, sizeof(bits
)), bits
);
428 for (k
= 0; k
< LED_MAX
; k
++) {
438 if (test_bit(EV_REL
) && test_bit(EV_KEY
))
442 if (test_bit(EV_KEY
) && test_bit(EV_LED
) && !test_bit(EV_ABS
))
446 if (!(test_bit(EV_REL
) && test_bit(EV_KEY
))
447 && !(test_bit(EV_KEY
) && test_bit(EV_LED
)
448 && !test_bit(EV_ABS
)))
457 FATAL1("usbInit: Cannot open /dev/input/event* port (%s)\n"
458 " If you have not done so, you may need to:\n"
459 " rmmod mousedev; rmmod keybdev\n"
460 " modprobe evdev\n", strerror(errno
));
462 usbPrint(priv
, name
, buf
, priv
->fd
);
465 /** Turn \a pDev off (i.e., stop taking input from \a pDev). */
467 usbOff(DevicePtr pDev
)
476 /** Create a private structure for use within this file. */
478 usbCreatePrivate(DeviceIntPtr pDevice
)
480 myPrivate
*priv
= calloc(1, sizeof(*priv
));
483 priv
->pDevice
= pDevice
;
487 /** Destroy a private structure. */
489 usbDestroyPrivate(pointer priv
)