1706f2543Smrg/* 2706f2543Smrg * Copyright © 2004 Keith Packard 3706f2543Smrg * 4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 6706f2543Smrg * the above copyright notice appear in all copies and that both that 7706f2543Smrg * copyright notice and this permission notice appear in supporting 8706f2543Smrg * documentation, and that the name of Keith Packard not be used in 9706f2543Smrg * advertising or publicity pertaining to distribution of the software without 10706f2543Smrg * specific, written prior permission. Keith Packard makes no 11706f2543Smrg * representations about the suitability of this software for any purpose. It 12706f2543Smrg * is provided "as is" without express or implied warranty. 13706f2543Smrg * 14706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE. 21706f2543Smrg */ 22706f2543Smrg 23706f2543Smrg#ifdef HAVE_CONFIG_H 24706f2543Smrg#include <kdrive-config.h> 25706f2543Smrg#endif 26706f2543Smrg#include <errno.h> 27706f2543Smrg#include <linux/input.h> 28706f2543Smrg#include <X11/X.h> 29706f2543Smrg#include <X11/Xproto.h> 30706f2543Smrg#include <X11/Xpoll.h> 31706f2543Smrg#include "inputstr.h" 32706f2543Smrg#include "scrnintstr.h" 33706f2543Smrg#include "kdrive.h" 34706f2543Smrg 35706f2543Smrg#define NUM_EVENTS 128 36706f2543Smrg#define ABS_UNSET -65535 37706f2543Smrg 38706f2543Smrg#define BITS_PER_LONG (sizeof(long) * 8) 39706f2543Smrg#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) 40706f2543Smrg#define ISBITSET(x,y) ((x)[LONG(y)] & BIT(y)) 41706f2543Smrg#define OFF(x) ((x)%BITS_PER_LONG) 42706f2543Smrg#define LONG(x) ((x)/BITS_PER_LONG) 43706f2543Smrg#define BIT(x) (1 << OFF(x)) 44706f2543Smrg 45706f2543Smrgtypedef struct _kevdev { 46706f2543Smrg /* current device state */ 47706f2543Smrg int rel[REL_MAX + 1]; 48706f2543Smrg int abs[ABS_MAX + 1]; 49706f2543Smrg int prevabs[ABS_MAX + 1]; 50706f2543Smrg long key[NBITS(KEY_MAX + 1)]; 51706f2543Smrg 52706f2543Smrg /* supported device info */ 53706f2543Smrg long relbits[NBITS(REL_MAX + 1)]; 54706f2543Smrg long absbits[NBITS(ABS_MAX + 1)]; 55706f2543Smrg long keybits[NBITS(KEY_MAX + 1)]; 56706f2543Smrg struct input_absinfo absinfo[ABS_MAX + 1]; 57706f2543Smrg int max_rel; 58706f2543Smrg int max_abs; 59706f2543Smrg 60706f2543Smrg int fd; 61706f2543Smrg} Kevdev; 62706f2543Smrg 63706f2543Smrgstatic void 64706f2543SmrgEvdevPtrBtn (KdPointerInfo *pi, struct input_event *ev) 65706f2543Smrg{ 66706f2543Smrg int flags = KD_MOUSE_DELTA | pi->buttonState; 67706f2543Smrg 68706f2543Smrg if (ev->code >= BTN_MOUSE && ev->code < BTN_JOYSTICK) { 69706f2543Smrg switch (ev->code) { 70706f2543Smrg case BTN_LEFT: 71706f2543Smrg if (ev->value == 1) 72706f2543Smrg flags |= KD_BUTTON_1; 73706f2543Smrg else 74706f2543Smrg flags &= ~KD_BUTTON_1; 75706f2543Smrg break; 76706f2543Smrg case BTN_MIDDLE: 77706f2543Smrg if (ev->value == 1) 78706f2543Smrg flags |= KD_BUTTON_2; 79706f2543Smrg else 80706f2543Smrg flags &= ~KD_BUTTON_2; 81706f2543Smrg break; 82706f2543Smrg case BTN_RIGHT: 83706f2543Smrg if (ev->value == 1) 84706f2543Smrg flags |= KD_BUTTON_3; 85706f2543Smrg else 86706f2543Smrg flags &= ~KD_BUTTON_3; 87706f2543Smrg break; 88706f2543Smrg default: 89706f2543Smrg /* Unknow button */ 90706f2543Smrg break; 91706f2543Smrg } 92706f2543Smrg 93706f2543Smrg KdEnqueuePointerEvent (pi, flags, 0, 0, 0); 94706f2543Smrg } 95706f2543Smrg} 96706f2543Smrgstatic void 97706f2543SmrgEvdevPtrMotion (KdPointerInfo *pi, struct input_event *ev) 98706f2543Smrg{ 99706f2543Smrg Kevdev *ke = pi->driverPrivate; 100706f2543Smrg int i; 101706f2543Smrg int flags = KD_MOUSE_DELTA | pi->buttonState; 102706f2543Smrg 103706f2543Smrg for (i = 0; i <= ke->max_rel; i++) 104706f2543Smrg if (ke->rel[i]) 105706f2543Smrg { 106706f2543Smrg int a; 107706f2543Smrg for (a = 0; a <= ke->max_rel; a++) 108706f2543Smrg { 109706f2543Smrg if (ISBITSET (ke->relbits, a)) 110706f2543Smrg { 111706f2543Smrg if (a == 0) 112706f2543Smrg KdEnqueuePointerEvent(pi, flags, ke->rel[a], 0, 0); 113706f2543Smrg else if (a == 1) 114706f2543Smrg KdEnqueuePointerEvent(pi, flags, 0, ke->rel[a], 0); 115706f2543Smrg } 116706f2543Smrg ke->rel[a] = 0; 117706f2543Smrg } 118706f2543Smrg break; 119706f2543Smrg } 120706f2543Smrg for (i = 0; i < ke->max_abs; i++) 121706f2543Smrg if (ke->abs[i] != ke->prevabs[i]) 122706f2543Smrg { 123706f2543Smrg int a; 124706f2543Smrg ErrorF ("abs"); 125706f2543Smrg for (a = 0; a <= ke->max_abs; a++) 126706f2543Smrg { 127706f2543Smrg if (ISBITSET (ke->absbits, a)) 128706f2543Smrg ErrorF (" %d=%d", a, ke->abs[a]); 129706f2543Smrg ke->prevabs[a] = ke->abs[a]; 130706f2543Smrg } 131706f2543Smrg ErrorF ("\n"); 132706f2543Smrg break; 133706f2543Smrg } 134706f2543Smrg 135706f2543Smrg if (ev->code == REL_WHEEL) { 136706f2543Smrg for (i = 0; i < abs (ev->value); i++) 137706f2543Smrg { 138706f2543Smrg if (ev->value > 0) 139706f2543Smrg flags |= KD_BUTTON_4; 140706f2543Smrg else 141706f2543Smrg flags |= KD_BUTTON_5; 142706f2543Smrg 143706f2543Smrg KdEnqueuePointerEvent (pi, flags, 0, 0, 0); 144706f2543Smrg 145706f2543Smrg if (ev->value > 0) 146706f2543Smrg flags &= ~KD_BUTTON_4; 147706f2543Smrg else 148706f2543Smrg flags &= ~KD_BUTTON_5; 149706f2543Smrg 150706f2543Smrg KdEnqueuePointerEvent (pi, flags, 0, 0, 0); 151706f2543Smrg } 152706f2543Smrg } 153706f2543Smrg 154706f2543Smrg} 155706f2543Smrg 156706f2543Smrgstatic void 157706f2543SmrgEvdevPtrRead (int evdevPort, void *closure) 158706f2543Smrg{ 159706f2543Smrg KdPointerInfo *pi = closure; 160706f2543Smrg Kevdev *ke = pi->driverPrivate; 161706f2543Smrg int i; 162706f2543Smrg struct input_event events[NUM_EVENTS]; 163706f2543Smrg int n; 164706f2543Smrg 165706f2543Smrg n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event)); 166706f2543Smrg if (n <= 0) { 167706f2543Smrg if (errno == ENODEV) 168706f2543Smrg DeleteInputDeviceRequest(pi->dixdev); 169706f2543Smrg return; 170706f2543Smrg } 171706f2543Smrg 172706f2543Smrg n /= sizeof (struct input_event); 173706f2543Smrg for (i = 0; i < n; i++) 174706f2543Smrg { 175706f2543Smrg switch (events[i].type) { 176706f2543Smrg case EV_SYN: 177706f2543Smrg break; 178706f2543Smrg case EV_KEY: 179706f2543Smrg EvdevPtrBtn (pi, &events[i]); 180706f2543Smrg break; 181706f2543Smrg case EV_REL: 182706f2543Smrg ke->rel[events[i].code] += events[i].value; 183706f2543Smrg EvdevPtrMotion (pi, &events[i]); 184706f2543Smrg break; 185706f2543Smrg case EV_ABS: 186706f2543Smrg ke->abs[events[i].code] = events[i].value; 187706f2543Smrg EvdevPtrMotion (pi, &events[i]); 188706f2543Smrg break; 189706f2543Smrg } 190706f2543Smrg } 191706f2543Smrg} 192706f2543Smrg 193706f2543Smrgchar *kdefaultEvdev[] = { 194706f2543Smrg "/dev/input/event0", 195706f2543Smrg "/dev/input/event1", 196706f2543Smrg "/dev/input/event2", 197706f2543Smrg "/dev/input/event3", 198706f2543Smrg}; 199706f2543Smrg 200706f2543Smrg#define NUM_DEFAULT_EVDEV (sizeof (kdefaultEvdev) / sizeof (kdefaultEvdev[0])) 201706f2543Smrg 202706f2543Smrgstatic Status 203706f2543SmrgEvdevPtrInit (KdPointerInfo *pi) 204706f2543Smrg{ 205706f2543Smrg int i; 206706f2543Smrg int fd; 207706f2543Smrg 208706f2543Smrg if (!pi->path) { 209706f2543Smrg for (i = 0; i < NUM_DEFAULT_EVDEV; i++) { 210706f2543Smrg fd = open (kdefaultEvdev[i], 2); 211706f2543Smrg if (fd >= 0) { 212706f2543Smrg pi->path = strdup (kdefaultEvdev[i]); 213706f2543Smrg break; 214706f2543Smrg } 215706f2543Smrg } 216706f2543Smrg } 217706f2543Smrg else { 218706f2543Smrg fd = open (pi->path, O_RDWR); 219706f2543Smrg if (fd < 0) { 220706f2543Smrg ErrorF("Failed to open evdev device %s\n", pi->path); 221706f2543Smrg return BadMatch; 222706f2543Smrg } 223706f2543Smrg } 224706f2543Smrg 225706f2543Smrg close(fd); 226706f2543Smrg 227706f2543Smrg pi->name = strdup("Evdev mouse"); 228706f2543Smrg 229706f2543Smrg return Success; 230706f2543Smrg} 231706f2543Smrg 232706f2543Smrgstatic Status 233706f2543SmrgEvdevPtrEnable (KdPointerInfo *pi) 234706f2543Smrg{ 235706f2543Smrg int fd; 236706f2543Smrg unsigned long ev[NBITS(EV_MAX)]; 237706f2543Smrg Kevdev *ke; 238706f2543Smrg 239706f2543Smrg if (!pi || !pi->path) 240706f2543Smrg return BadImplementation; 241706f2543Smrg 242706f2543Smrg fd = open(pi->path, 2); 243706f2543Smrg if (fd < 0) 244706f2543Smrg return BadMatch; 245706f2543Smrg 246706f2543Smrg if (ioctl (fd, EVIOCGRAB, 1) < 0) 247706f2543Smrg perror ("Grabbing evdev mouse device failed"); 248706f2543Smrg 249706f2543Smrg if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0) 250706f2543Smrg { 251706f2543Smrg perror ("EVIOCGBIT 0"); 252706f2543Smrg close (fd); 253706f2543Smrg return BadMatch; 254706f2543Smrg } 255706f2543Smrg ke = calloc(1, sizeof (Kevdev)); 256706f2543Smrg if (!ke) 257706f2543Smrg { 258706f2543Smrg close (fd); 259706f2543Smrg return BadAlloc; 260706f2543Smrg } 261706f2543Smrg if (ISBITSET (ev, EV_KEY)) 262706f2543Smrg { 263706f2543Smrg if (ioctl (fd, EVIOCGBIT (EV_KEY, sizeof (ke->keybits)), 264706f2543Smrg ke->keybits) < 0) 265706f2543Smrg { 266706f2543Smrg perror ("EVIOCGBIT EV_KEY"); 267706f2543Smrg free(ke); 268706f2543Smrg close (fd); 269706f2543Smrg return BadMatch; 270706f2543Smrg } 271706f2543Smrg } 272706f2543Smrg if (ISBITSET (ev, EV_REL)) 273706f2543Smrg { 274706f2543Smrg if (ioctl (fd, EVIOCGBIT (EV_REL, sizeof (ke->relbits)), 275706f2543Smrg ke->relbits) < 0) 276706f2543Smrg { 277706f2543Smrg perror ("EVIOCGBIT EV_REL"); 278706f2543Smrg free(ke); 279706f2543Smrg close (fd); 280706f2543Smrg return BadMatch; 281706f2543Smrg } 282706f2543Smrg for (ke->max_rel = REL_MAX; ke->max_rel >= 0; ke->max_rel--) 283706f2543Smrg if (ISBITSET(ke->relbits, ke->max_rel)) 284706f2543Smrg break; 285706f2543Smrg } 286706f2543Smrg if (ISBITSET (ev, EV_ABS)) 287706f2543Smrg { 288706f2543Smrg int i; 289706f2543Smrg 290706f2543Smrg if (ioctl (fd, EVIOCGBIT (EV_ABS, sizeof (ke->absbits)), 291706f2543Smrg ke->absbits) < 0) 292706f2543Smrg { 293706f2543Smrg perror ("EVIOCGBIT EV_ABS"); 294706f2543Smrg free(ke); 295706f2543Smrg close (fd); 296706f2543Smrg return BadMatch; 297706f2543Smrg } 298706f2543Smrg for (ke->max_abs = ABS_MAX; ke->max_abs >= 0; ke->max_abs--) 299706f2543Smrg if (ISBITSET(ke->absbits, ke->max_abs)) 300706f2543Smrg break; 301706f2543Smrg for (i = 0; i <= ke->max_abs; i++) 302706f2543Smrg { 303706f2543Smrg if (ISBITSET (ke->absbits, i)) 304706f2543Smrg if (ioctl (fd, EVIOCGABS(i), &ke->absinfo[i]) < 0) 305706f2543Smrg { 306706f2543Smrg perror ("EVIOCGABS"); 307706f2543Smrg break; 308706f2543Smrg } 309706f2543Smrg ke->prevabs[i] = ABS_UNSET; 310706f2543Smrg } 311706f2543Smrg if (i <= ke->max_abs) 312706f2543Smrg { 313706f2543Smrg free(ke); 314706f2543Smrg close (fd); 315706f2543Smrg return BadValue; 316706f2543Smrg } 317706f2543Smrg } 318706f2543Smrg if (!KdRegisterFd (fd, EvdevPtrRead, pi)) { 319706f2543Smrg free(ke); 320706f2543Smrg close (fd); 321706f2543Smrg return BadAlloc; 322706f2543Smrg } 323706f2543Smrg pi->driverPrivate = ke; 324706f2543Smrg ke->fd = fd; 325706f2543Smrg 326706f2543Smrg return Success; 327706f2543Smrg} 328706f2543Smrg 329706f2543Smrgstatic void 330706f2543SmrgEvdevPtrDisable (KdPointerInfo *pi) 331706f2543Smrg{ 332706f2543Smrg Kevdev *ke; 333706f2543Smrg 334706f2543Smrg ke = pi->driverPrivate; 335706f2543Smrg 336706f2543Smrg if (!pi || !pi->driverPrivate) 337706f2543Smrg return; 338706f2543Smrg 339706f2543Smrg KdUnregisterFd (pi, ke->fd, TRUE); 340706f2543Smrg 341706f2543Smrg if (ioctl (ke->fd, EVIOCGRAB, 0) < 0) 342706f2543Smrg perror ("Ungrabbing evdev mouse device failed"); 343706f2543Smrg 344706f2543Smrg free(ke); 345706f2543Smrg pi->driverPrivate = 0; 346706f2543Smrg} 347706f2543Smrg 348706f2543Smrgstatic void 349706f2543SmrgEvdevPtrFini (KdPointerInfo *pi) 350706f2543Smrg{ 351706f2543Smrg} 352706f2543Smrg 353706f2543Smrg 354706f2543Smrg/* 355706f2543Smrg * Evdev keyboard functions 356706f2543Smrg */ 357706f2543Smrg 358706f2543Smrgstatic void 359706f2543SmrgreadMapping (KdKeyboardInfo *ki) 360706f2543Smrg{ 361706f2543Smrg if (!ki) 362706f2543Smrg return; 363706f2543Smrg 364706f2543Smrg ki->minScanCode = 0; 365706f2543Smrg ki->maxScanCode = 247; 366706f2543Smrg} 367706f2543Smrg 368706f2543Smrgstatic void 369706f2543SmrgEvdevKbdRead (int evdevPort, void *closure) 370706f2543Smrg{ 371706f2543Smrg KdKeyboardInfo *ki = closure; 372706f2543Smrg struct input_event events[NUM_EVENTS]; 373706f2543Smrg int i, n; 374706f2543Smrg 375706f2543Smrg n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event)); 376706f2543Smrg if (n <= 0) { 377706f2543Smrg if (errno == ENODEV) 378706f2543Smrg DeleteInputDeviceRequest(ki->dixdev); 379706f2543Smrg return; 380706f2543Smrg } 381706f2543Smrg 382706f2543Smrg n /= sizeof (struct input_event); 383706f2543Smrg for (i = 0; i < n; i++) 384706f2543Smrg { 385706f2543Smrg if (events[i].type == EV_KEY) 386706f2543Smrg KdEnqueueKeyboardEvent (ki, events[i].code, !events[i].value); 387706f2543Smrg/* FIXME: must implement other types of events 388706f2543Smrg else 389706f2543Smrg ErrorF("Event type (%d) not delivered\n", events[i].type); 390706f2543Smrg*/ 391706f2543Smrg } 392706f2543Smrg} 393706f2543Smrg 394706f2543Smrgstatic Status 395706f2543SmrgEvdevKbdInit (KdKeyboardInfo *ki) 396706f2543Smrg{ 397706f2543Smrg int fd; 398706f2543Smrg 399706f2543Smrg if (!ki->path) { 400706f2543Smrg ErrorF("Couldn't find evdev device path\n"); 401706f2543Smrg return BadValue; 402706f2543Smrg } 403706f2543Smrg else { 404706f2543Smrg fd = open (ki->path, O_RDWR); 405706f2543Smrg if (fd < 0) { 406706f2543Smrg ErrorF("Failed to open evdev device %s\n", ki->path); 407706f2543Smrg return BadMatch; 408706f2543Smrg } 409706f2543Smrg } 410706f2543Smrg 411706f2543Smrg close (fd); 412706f2543Smrg 413706f2543Smrg ki->name = strdup("Evdev keyboard"); 414706f2543Smrg 415706f2543Smrg readMapping(ki); 416706f2543Smrg 417706f2543Smrg return Success; 418706f2543Smrg} 419706f2543Smrg 420706f2543Smrgstatic Status 421706f2543SmrgEvdevKbdEnable (KdKeyboardInfo *ki) 422706f2543Smrg{ 423706f2543Smrg unsigned long ev[NBITS(EV_MAX)]; 424706f2543Smrg Kevdev *ke; 425706f2543Smrg int fd; 426706f2543Smrg 427706f2543Smrg if (!ki || !ki->path) 428706f2543Smrg return BadImplementation; 429706f2543Smrg 430706f2543Smrg fd = open(ki->path, O_RDWR); 431706f2543Smrg if (fd < 0) 432706f2543Smrg return BadMatch; 433706f2543Smrg 434706f2543Smrg if (ioctl (fd, EVIOCGRAB, 1) < 0) 435706f2543Smrg perror ("Grabbing evdev keyboard device failed"); 436706f2543Smrg 437706f2543Smrg if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0) { 438706f2543Smrg perror ("EVIOCGBIT 0"); 439706f2543Smrg close (fd); 440706f2543Smrg return BadMatch; 441706f2543Smrg } 442706f2543Smrg 443706f2543Smrg ke = calloc(1, sizeof (Kevdev)); 444706f2543Smrg if (!ke) { 445706f2543Smrg close (fd); 446706f2543Smrg return BadAlloc; 447706f2543Smrg } 448706f2543Smrg 449706f2543Smrg if (!KdRegisterFd (fd, EvdevKbdRead, ki)) { 450706f2543Smrg free(ke); 451706f2543Smrg close (fd); 452706f2543Smrg return BadAlloc; 453706f2543Smrg } 454706f2543Smrg ki->driverPrivate = ke; 455706f2543Smrg ke->fd = fd; 456706f2543Smrg 457706f2543Smrg return Success; 458706f2543Smrg} 459706f2543Smrg 460706f2543Smrgstatic void 461706f2543SmrgEvdevKbdLeds (KdKeyboardInfo *ki, int leds) 462706f2543Smrg{ 463706f2543Smrg/* struct input_event event; 464706f2543Smrg Kevdev *ke; 465706f2543Smrg 466706f2543Smrg ki->driverPrivate = ke; 467706f2543Smrg 468706f2543Smrg memset(&event, 0, sizeof(event)); 469706f2543Smrg 470706f2543Smrg event.type = EV_LED; 471706f2543Smrg event.code = LED_CAPSL; 472706f2543Smrg event.value = leds & (1 << 0) ? 1 : 0; 473706f2543Smrg write(ke->fd, (char *) &event, sizeof(event)); 474706f2543Smrg 475706f2543Smrg event.type = EV_LED; 476706f2543Smrg event.code = LED_NUML; 477706f2543Smrg event.value = leds & (1 << 1) ? 1 : 0; 478706f2543Smrg write(ke->fd, (char *) &event, sizeof(event)); 479706f2543Smrg 480706f2543Smrg event.type = EV_LED; 481706f2543Smrg event.code = LED_SCROLLL; 482706f2543Smrg event.value = leds & (1 << 2) ? 1 : 0; 483706f2543Smrg write(ke->fd, (char *) &event, sizeof(event)); 484706f2543Smrg 485706f2543Smrg event.type = EV_LED; 486706f2543Smrg event.code = LED_COMPOSE; 487706f2543Smrg event.value = leds & (1 << 3) ? 1 : 0; 488706f2543Smrg write(ke->fd, (char *) &event, sizeof(event)); 489706f2543Smrg*/ 490706f2543Smrg} 491706f2543Smrg 492706f2543Smrgstatic void 493706f2543SmrgEvdevKbdBell (KdKeyboardInfo *ki, int volume, int frequency, int duration) 494706f2543Smrg{ 495706f2543Smrg} 496706f2543Smrg 497706f2543Smrgstatic void 498706f2543SmrgEvdevKbdDisable (KdKeyboardInfo *ki) 499706f2543Smrg{ 500706f2543Smrg Kevdev *ke; 501706f2543Smrg 502706f2543Smrg ke = ki->driverPrivate; 503706f2543Smrg 504706f2543Smrg if (!ki || !ki->driverPrivate) 505706f2543Smrg return; 506706f2543Smrg 507706f2543Smrg KdUnregisterFd (ki, ke->fd, TRUE); 508706f2543Smrg 509706f2543Smrg if (ioctl (ke->fd, EVIOCGRAB, 0) < 0) 510706f2543Smrg perror ("Ungrabbing evdev keyboard device failed"); 511706f2543Smrg 512706f2543Smrg free(ke); 513706f2543Smrg ki->driverPrivate = 0; 514706f2543Smrg} 515706f2543Smrg 516706f2543Smrgstatic void 517706f2543SmrgEvdevKbdFini (KdKeyboardInfo *ki) 518706f2543Smrg{ 519706f2543Smrg} 520706f2543Smrg 521706f2543SmrgKdPointerDriver LinuxEvdevMouseDriver = { 522706f2543Smrg "evdev", 523706f2543Smrg EvdevPtrInit, 524706f2543Smrg EvdevPtrEnable, 525706f2543Smrg EvdevPtrDisable, 526706f2543Smrg EvdevPtrFini, 527706f2543Smrg NULL, 528706f2543Smrg}; 529706f2543Smrg 530706f2543SmrgKdKeyboardDriver LinuxEvdevKeyboardDriver = { 531706f2543Smrg "evdev", 532706f2543Smrg EvdevKbdInit, 533706f2543Smrg EvdevKbdEnable, 534706f2543Smrg EvdevKbdLeds, 535706f2543Smrg EvdevKbdBell, 536706f2543Smrg EvdevKbdDisable, 537706f2543Smrg EvdevKbdFini, 538706f2543Smrg NULL, 539706f2543Smrg}; 540