Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / kdrive / linux / evdev.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright © 2004 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
13 *
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <kdrive-config.h>
25#endif
26#include <errno.h>
27#include <linux/input.h>
28#include <X11/X.h>
29#include <X11/Xproto.h>
30#include <X11/Xpoll.h>
31#include "inputstr.h"
32#include "scrnintstr.h"
33#include "kdrive.h"
34
35#define NUM_EVENTS 128
36#define ABS_UNSET -65535
37
38#define BITS_PER_LONG (sizeof(long) * 8)
39#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
40#define ISBITSET(x,y) ((x)[LONG(y)] & BIT(y))
41#define OFF(x) ((x)%BITS_PER_LONG)
42#define LONG(x) ((x)/BITS_PER_LONG)
43#define BIT(x) (1 << OFF(x))
44
45typedef struct _kevdev {
46 /* current device state */
47 int rel[REL_MAX + 1];
48 int abs[ABS_MAX + 1];
49 int prevabs[ABS_MAX + 1];
50 long key[NBITS(KEY_MAX + 1)];
51
52 /* supported device info */
53 long relbits[NBITS(REL_MAX + 1)];
54 long absbits[NBITS(ABS_MAX + 1)];
55 long keybits[NBITS(KEY_MAX + 1)];
56 struct input_absinfo absinfo[ABS_MAX + 1];
57 int max_rel;
58 int max_abs;
59
60 int fd;
61} Kevdev;
62
63static void
64EvdevPtrBtn(KdPointerInfo * pi, struct input_event *ev)
65{
66 int flags = KD_MOUSE_DELTA | pi->buttonState;
67
68 if (ev->code >= BTN_MOUSE && ev->code < BTN_JOYSTICK) {
69 switch (ev->code) {
70 case BTN_LEFT:
71 if (ev->value == 1)
72 flags |= KD_BUTTON_1;
73 else
74 flags &= ~KD_BUTTON_1;
75 break;
76 case BTN_MIDDLE:
77 if (ev->value == 1)
78 flags |= KD_BUTTON_2;
79 else
80 flags &= ~KD_BUTTON_2;
81 break;
82 case BTN_RIGHT:
83 if (ev->value == 1)
84 flags |= KD_BUTTON_3;
85 else
86 flags &= ~KD_BUTTON_3;
87 break;
88 default:
89 /* Unknow button */
90 break;
91 }
92
93 KdEnqueuePointerEvent(pi, flags, 0, 0, 0);
94 }
95}
96
97static void
98EvdevPtrMotion(KdPointerInfo * pi, struct input_event *ev)
99{
100 Kevdev *ke = pi->driverPrivate;
101 int i;
102 int flags = KD_MOUSE_DELTA | pi->buttonState;
103
104 for (i = 0; i <= ke->max_rel; i++)
105 if (ke->rel[i]) {
106 int a;
107
108 for (a = 0; a <= ke->max_rel; a++) {
109 if (ISBITSET(ke->relbits, a)) {
110 if (a == 0)
111 KdEnqueuePointerEvent(pi, flags, ke->rel[a], 0, 0);
112 else if (a == 1)
113 KdEnqueuePointerEvent(pi, flags, 0, ke->rel[a], 0);
114 }
115 ke->rel[a] = 0;
116 }
117 break;
118 }
119 for (i = 0; i < ke->max_abs; i++)
120 if (ke->abs[i] != ke->prevabs[i]) {
121 int a;
122
123 ErrorF("abs");
124 for (a = 0; a <= ke->max_abs; a++) {
125 if (ISBITSET(ke->absbits, a))
126 ErrorF(" %d=%d", a, ke->abs[a]);
127 ke->prevabs[a] = ke->abs[a];
128 }
129 ErrorF("\n");
130 break;
131 }
132
133 if (ev->code == REL_WHEEL) {
134 for (i = 0; i < abs(ev->value); i++) {
135 if (ev->value > 0)
136 flags |= KD_BUTTON_4;
137 else
138 flags |= KD_BUTTON_5;
139
140 KdEnqueuePointerEvent(pi, flags, 0, 0, 0);
141
142 if (ev->value > 0)
143 flags &= ~KD_BUTTON_4;
144 else
145 flags &= ~KD_BUTTON_5;
146
147 KdEnqueuePointerEvent(pi, flags, 0, 0, 0);
148 }
149 }
150
151}
152
153static void
154EvdevPtrRead(int evdevPort, void *closure)
155{
156 KdPointerInfo *pi = closure;
157 Kevdev *ke = pi->driverPrivate;
158 int i;
159 struct input_event events[NUM_EVENTS];
160 int n;
161
162 n = read(evdevPort, &events, NUM_EVENTS * sizeof(struct input_event));
163 if (n <= 0) {
164 if (errno == ENODEV)
165 DeleteInputDeviceRequest(pi->dixdev);
166 return;
167 }
168
169 n /= sizeof(struct input_event);
170 for (i = 0; i < n; i++) {
171 switch (events[i].type) {
172 case EV_SYN:
173 break;
174 case EV_KEY:
175 EvdevPtrBtn(pi, &events[i]);
176 break;
177 case EV_REL:
178 ke->rel[events[i].code] += events[i].value;
179 EvdevPtrMotion(pi, &events[i]);
180 break;
181 case EV_ABS:
182 ke->abs[events[i].code] = events[i].value;
183 EvdevPtrMotion(pi, &events[i]);
184 break;
185 }
186 }
187}
188
189const char *kdefaultEvdev[] = {
190 "/dev/input/event0",
191 "/dev/input/event1",
192 "/dev/input/event2",
193 "/dev/input/event3",
194};
195
196#define NUM_DEFAULT_EVDEV (sizeof (kdefaultEvdev) / sizeof (kdefaultEvdev[0]))
197
198static Status
199EvdevPtrInit(KdPointerInfo * pi)
200{
201 int i;
202 int fd;
203
204 if (!pi->path) {
205 for (i = 0; i < NUM_DEFAULT_EVDEV; i++) {
206 fd = open(kdefaultEvdev[i], 2);
207 if (fd >= 0) {
208 pi->path = strdup(kdefaultEvdev[i]);
209 break;
210 }
211 }
212 }
213 else {
214 fd = open(pi->path, O_RDWR);
215 if (fd < 0) {
216 ErrorF("Failed to open evdev device %s\n", pi->path);
217 return BadMatch;
218 }
219 }
220
221 close(fd);
222
223 pi->name = strdup("Evdev mouse");
224
225 return Success;
226}
227
228static Status
229EvdevPtrEnable(KdPointerInfo * pi)
230{
231 int fd;
232 unsigned long ev[NBITS(EV_MAX)];
233 Kevdev *ke;
234
235 if (!pi || !pi->path)
236 return BadImplementation;
237
238 fd = open(pi->path, 2);
239 if (fd < 0)
240 return BadMatch;
241
242 if (ioctl(fd, EVIOCGRAB, 1) < 0)
243 perror("Grabbing evdev mouse device failed");
244
245 if (ioctl(fd, EVIOCGBIT(0 /*EV*/, sizeof(ev)), ev) < 0) {
246 perror("EVIOCGBIT 0");
247 close(fd);
248 return BadMatch;
249 }
250 ke = calloc(1, sizeof(Kevdev));
251 if (!ke) {
252 close(fd);
253 return BadAlloc;
254 }
255 if (ISBITSET(ev, EV_KEY)) {
256 if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(ke->keybits)), ke->keybits) < 0) {
257 perror("EVIOCGBIT EV_KEY");
258 free(ke);
259 close(fd);
260 return BadMatch;
261 }
262 }
263 if (ISBITSET(ev, EV_REL)) {
264 if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(ke->relbits)), ke->relbits) < 0) {
265 perror("EVIOCGBIT EV_REL");
266 free(ke);
267 close(fd);
268 return BadMatch;
269 }
270 for (ke->max_rel = REL_MAX; ke->max_rel >= 0; ke->max_rel--)
271 if (ISBITSET(ke->relbits, ke->max_rel))
272 break;
273 }
274 if (ISBITSET(ev, EV_ABS)) {
275 int i;
276
277 if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(ke->absbits)), ke->absbits) < 0) {
278 perror("EVIOCGBIT EV_ABS");
279 free(ke);
280 close(fd);
281 return BadMatch;
282 }
283 for (ke->max_abs = ABS_MAX; ke->max_abs >= 0; ke->max_abs--)
284 if (ISBITSET(ke->absbits, ke->max_abs))
285 break;
286 for (i = 0; i <= ke->max_abs; i++) {
287 if (ISBITSET(ke->absbits, i))
288 if (ioctl(fd, EVIOCGABS(i), &ke->absinfo[i]) < 0) {
289 perror("EVIOCGABS");
290 break;
291 }
292 ke->prevabs[i] = ABS_UNSET;
293 }
294 if (i <= ke->max_abs) {
295 free(ke);
296 close(fd);
297 return BadValue;
298 }
299 }
300 if (!KdRegisterFd(fd, EvdevPtrRead, pi)) {
301 free(ke);
302 close(fd);
303 return BadAlloc;
304 }
305 pi->driverPrivate = ke;
306 ke->fd = fd;
307
308 return Success;
309}
310
311static void
312EvdevPtrDisable(KdPointerInfo * pi)
313{
314 Kevdev *ke;
315
316 ke = pi->driverPrivate;
317
318 if (!pi || !pi->driverPrivate)
319 return;
320
321 KdUnregisterFd(pi, ke->fd, TRUE);
322
323 if (ioctl(ke->fd, EVIOCGRAB, 0) < 0)
324 perror("Ungrabbing evdev mouse device failed");
325
326 free(ke);
327 pi->driverPrivate = 0;
328}
329
330static void
331EvdevPtrFini(KdPointerInfo * pi)
332{
333}
334
335/*
336 * Evdev keyboard functions
337 */
338
339static void
340readMapping(KdKeyboardInfo * ki)
341{
342 if (!ki)
343 return;
344
345 ki->minScanCode = 0;
346 ki->maxScanCode = 247;
347}
348
349static void
350EvdevKbdRead(int evdevPort, void *closure)
351{
352 KdKeyboardInfo *ki = closure;
353 struct input_event events[NUM_EVENTS];
354 int i, n;
355
356 n = read(evdevPort, &events, NUM_EVENTS * sizeof(struct input_event));
357 if (n <= 0) {
358 if (errno == ENODEV)
359 DeleteInputDeviceRequest(ki->dixdev);
360 return;
361 }
362
363 n /= sizeof(struct input_event);
364 for (i = 0; i < n; i++) {
365 if (events[i].type == EV_KEY)
366 KdEnqueueKeyboardEvent(ki, events[i].code, !events[i].value);
367/* FIXME: must implement other types of events
368 else
369 ErrorF("Event type (%d) not delivered\n", events[i].type);
370*/
371 }
372}
373
374static Status
375EvdevKbdInit(KdKeyboardInfo * ki)
376{
377 int fd;
378
379 if (!ki->path) {
380 ErrorF("Couldn't find evdev device path\n");
381 return BadValue;
382 }
383 else {
384 fd = open(ki->path, O_RDWR);
385 if (fd < 0) {
386 ErrorF("Failed to open evdev device %s\n", ki->path);
387 return BadMatch;
388 }
389 }
390
391 close(fd);
392
393 ki->name = strdup("Evdev keyboard");
394
395 readMapping(ki);
396
397 return Success;
398}
399
400static Status
401EvdevKbdEnable(KdKeyboardInfo * ki)
402{
403 unsigned long ev[NBITS(EV_MAX)];
404 Kevdev *ke;
405 int fd;
406
407 if (!ki || !ki->path)
408 return BadImplementation;
409
410 fd = open(ki->path, O_RDWR);
411 if (fd < 0)
412 return BadMatch;
413
414 if (ioctl(fd, EVIOCGRAB, 1) < 0)
415 perror("Grabbing evdev keyboard device failed");
416
417 if (ioctl(fd, EVIOCGBIT(0 /*EV*/, sizeof(ev)), ev) < 0) {
418 perror("EVIOCGBIT 0");
419 close(fd);
420 return BadMatch;
421 }
422
423 ke = calloc(1, sizeof(Kevdev));
424 if (!ke) {
425 close(fd);
426 return BadAlloc;
427 }
428
429 if (!KdRegisterFd(fd, EvdevKbdRead, ki)) {
430 free(ke);
431 close(fd);
432 return BadAlloc;
433 }
434 ki->driverPrivate = ke;
435 ke->fd = fd;
436
437 return Success;
438}
439
440static void
441EvdevKbdLeds(KdKeyboardInfo * ki, int leds)
442{
443/* struct input_event event;
444 Kevdev *ke;
445
446 ki->driverPrivate = ke;
447
448 memset(&event, 0, sizeof(event));
449
450 event.type = EV_LED;
451 event.code = LED_CAPSL;
452 event.value = leds & (1 << 0) ? 1 : 0;
453 write(ke->fd, (char *) &event, sizeof(event));
454
455 event.type = EV_LED;
456 event.code = LED_NUML;
457 event.value = leds & (1 << 1) ? 1 : 0;
458 write(ke->fd, (char *) &event, sizeof(event));
459
460 event.type = EV_LED;
461 event.code = LED_SCROLLL;
462 event.value = leds & (1 << 2) ? 1 : 0;
463 write(ke->fd, (char *) &event, sizeof(event));
464
465 event.type = EV_LED;
466 event.code = LED_COMPOSE;
467 event.value = leds & (1 << 3) ? 1 : 0;
468 write(ke->fd, (char *) &event, sizeof(event));
469*/
470}
471
472static void
473EvdevKbdBell(KdKeyboardInfo * ki, int volume, int frequency, int duration)
474{
475}
476
477static void
478EvdevKbdDisable(KdKeyboardInfo * ki)
479{
480 Kevdev *ke;
481
482 ke = ki->driverPrivate;
483
484 if (!ki || !ki->driverPrivate)
485 return;
486
487 KdUnregisterFd(ki, ke->fd, TRUE);
488
489 if (ioctl(ke->fd, EVIOCGRAB, 0) < 0)
490 perror("Ungrabbing evdev keyboard device failed");
491
492 free(ke);
493 ki->driverPrivate = 0;
494}
495
496static void
497EvdevKbdFini(KdKeyboardInfo * ki)
498{
499}
500
501KdPointerDriver LinuxEvdevMouseDriver = {
502 "evdev",
503 EvdevPtrInit,
504 EvdevPtrEnable,
505 EvdevPtrDisable,
506 EvdevPtrFini,
507 NULL,
508};
509
510KdKeyboardDriver LinuxEvdevKeyboardDriver = {
511 "evdev",
512 EvdevKbdInit,
513 EvdevKbdEnable,
514 EvdevKbdLeds,
515 EvdevKbdBell,
516 EvdevKbdDisable,
517 EvdevKbdFini,
518 NULL,
519};