diff -ur build-tree/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c --- build-tree/xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c 2003-03-26 19:53:47.000000000 -0500 +++ xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_kbd.c 2003-03-15 08:46:16.000000000 -0500 @@ -22,6 +22,7 @@ #include "xf86OSKbd.h" #include "atKeynames.h" #include "lnx_kbd.h" +#include "lnx_evdev.h" #define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */ @@ -481,8 +482,8 @@ return TRUE; } -Bool -xf86OSKbdPreInit(InputInfoPtr pInfo) +static Bool +stdKbdPreInit(InputInfoPtr pInfo, char *protocol) { KbdDevPtr pKbd = pInfo->private; @@ -521,3 +522,381 @@ #endif return TRUE; } + +typedef struct _evdevKbdRec { + int packetSize; + char *buffer; + evdevDriver evdev; +} evdevKbdRec, *evdevKbdPtr; + +static void +evdevKbdReadInput(InputInfoPtr pInfo) +{ + KbdDevPtr pKbd; + evdevKbdPtr evdevKbd; + struct input_event *ev; + int n; + int code; + + pKbd = (KbdDevPtr) pInfo->private; + evdevKbd = pKbd->private; + ev = (struct input_event *) evdevKbd->buffer; + + if (pInfo->fd == -1) + return; + + do { + n = read(pInfo->fd, ev, sizeof(struct input_event)); + if (n == -1) { + xf86Msg(X_ERROR, "%s: Error in reading! (%s) Disabiling.\n", + pInfo->name, strerror(errno)); + RemoveEnabledDevice(pInfo->fd); + close (pInfo->fd); + pInfo->dev->public.on = FALSE; + pInfo->fd = -1; + return; + } + if (n != sizeof(struct input_event)) { + xf86Msg(X_WARNING, "%s: incomplete packet, size %d\n", pInfo->name, n); + return; + } + + switch (ev->type) { + case EV_KEY: + if ((ev->code <= EV_KEY_RESERVED)||(ev->code >= EV_KEY_UNKNOWN)) + break; + switch (ev->code) { + case EV_KEY_103RD: + case EV_KEY_102ND: + case EV_KEY_LINEFEED: + case EV_KEY_MACRO: + case EV_KEY_MUTE: + case EV_KEY_VOLUMEDOWN: + case EV_KEY_VOLUMEUP: + case EV_KEY_POWER: + case EV_KEY_KPPLUSMINUS: + case EV_KEY_F18: + case EV_KEY_F19: + case EV_KEY_F20: + case EV_KEY_F21: + case EV_KEY_F22: + case EV_KEY_F23: + case EV_KEY_F24: + case EV_KEY_KPCOMMA: + case EV_KEY_COMPOSE: + code = KEY_UNKNOWN; + break; + case EV_KEY_F13: + code = KEY_F13; + break; + case EV_KEY_F14: + code = KEY_F14; + break; + case EV_KEY_F15: + code = KEY_F15; + break; + case EV_KEY_F16: + code = KEY_F16; + break; + case EV_KEY_F17: + code = KEY_F17; + break; + case EV_KEY_KPENTER: + code = KEY_KP_Enter; + break; + case EV_KEY_RIGHTCTRL: + code = KEY_RCtrl; + break; + case EV_KEY_KPSLASH: + code = KEY_KP_Divide; + break; + case EV_KEY_SYSRQ: + code = KEY_SysReqest; + break; + case EV_KEY_RIGHTALT: + code = KEY_AltLang; + break; + case EV_KEY_HOME: + code = KEY_Home; + break; + case EV_KEY_UP: + code = KEY_Up; + break; + case EV_KEY_PAGEUP: + code = KEY_PgUp; + break; + case EV_KEY_LEFT: + code = KEY_Left; + break; + case EV_KEY_RIGHT: + code = KEY_Right; + break; + case EV_KEY_END: + code = KEY_End; + break; + case EV_KEY_DOWN: + code = KEY_Down; + break; + case EV_KEY_PAGEDOWN: + code = KEY_PgDown; + break; + case EV_KEY_INSERT: + code = KEY_Insert; + break; + case EV_KEY_DELETE: + code = KEY_Delete; + break; + case EV_KEY_KPEQUAL: + code = KEY_KP_Equal; + break; + case EV_KEY_PAUSE: + code = KEY_Pause; + break; + case EV_KEY_LEFTMETA: + code = KEY_LMeta; + break; + case EV_KEY_RIGHTMETA: + code = KEY_RMeta; + break; + default: + code = ev->code; + break; + } + if (code >= 127) + code = KEY_UNKNOWN; + + if (ev->value) + pKbd->PostEvent(pInfo, code, TRUE); + else + pKbd->PostEvent(pInfo, code, FALSE); + break; + } + } while (xf86WaitForInput(pInfo->fd, 0)); + + return; +} + +static int +evdevKbdInit(InputInfoPtr pInfo, int what) +{ + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + evdevKbdPtr evdevKbd = (evdevKbdPtr) pKbd->private; + + evdevKbd->evdev.name = xf86SetStrOption(pInfo->options,"Dev Name",NULL); + evdevKbd->evdev.phys = xf86SetStrOption(pInfo->options,"Dev Phys",NULL); + evdevKbd->evdev.cb_data = pInfo->dev; + evdevKbd->evdev.callback = pInfo->device_control; + if (!evdevNewDriver (&evdevKbd->evdev)) { + xf86Msg(X_ERROR, "%s: cannot register with evdev brain\n", pInfo->name); + return BadRequest; + } + if ((pInfo->fd = evdevGetFDForDriver (&evdevKbd->evdev)) == -1) { + xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name); + return BadRequest; + } + + close(pInfo->fd); + pInfo->fd = -1; + + return Success; +} + +static int +evdevKbdOn(InputInfoPtr pInfo, int what) +{ + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + evdevKbdPtr evdevKbd = (evdevKbdPtr) pKbd->private; + unsigned long mask; + + if ((pInfo->fd = evdevGetFDForDriver (&evdevKbd->evdev)) == -1) { + xf86Msg(X_ERROR, "%s: cannot open input device (name: '%s', phys: '%s')\n", pInfo->name, evdevKbd->evdev.name, evdevKbd->evdev.phys); + return BadRequest; + } + /* + * Grab the keyboard for ourselves. + */ + if (ioctl(pInfo->fd, EVIOCGMASK, &mask) < 0) { + xf86Msg(X_INFO, "%s: unable to use input device masking '%s', trying grabbing.\n", pInfo->name, strerror(errno)); + if (ioctl(pInfo->fd, EVIOCGRAB, 1) < 0) { + xf86Msg(X_ERROR, "%s: unable to grab device '%s', you may have problems.\n", pInfo->name, strerror(errno)); + } + return Success; + } + + mask |= BIT(2); + ioctl(pInfo->fd, EVIOCSMASK, mask); + + ioctl(pInfo->fd, EVIOCGDMASK, &mask); + mask &= ~BIT(0); + mask |= BIT(2); + ioctl(pInfo->fd, EVIOCSDMASK, mask); + xf86Msg(X_INFO, "%s: Using input device masking.\n", pInfo->name); + + return Success; +} + +static int +evdevKbdOff(InputInfoPtr pInfo, int what) +{ + if (pInfo->fd != -1) { + unsigned long mask; + + if (ioctl(pInfo->fd, EVIOCGDMASK, &mask) >= 0) { + mask |= BIT(0); + ioctl(pInfo->fd, EVIOCSDMASK, mask); + } + + close (pInfo->fd); + pInfo->fd = -1; + } + return Success; +} + +static void +evdevSoundBell(InputInfoPtr pInfo, int loudness, int pitch, int duration) +{ +} + +static void +evdevSetKbdLeds(InputInfoPtr pInfo, int leds) +{ + struct input_event event; + + memset(&event, 0, sizeof(event)); + event.type = EV_LED; + event.code = EV_LED_CAPSL; + event.value = (leds & XLED1) ? 1 : 0; + write(pInfo->fd, (char *) &event, sizeof(event)); + + event.type = EV_LED; + event.code = EV_LED_NUML; + event.value = (leds & XLED2) ? 1 : 0; + write(pInfo->fd, (char *) &event, sizeof(event)); + + event.type = EV_LED; + event.code = EV_LED_SCROLLL; + event.value = (leds & XLED3) ? 1 : 0; + write(pInfo->fd, (char *) &event, sizeof(event)); + + event.type = EV_LED; + event.code = EV_LED_COMPOSE; + event.value = (leds & XLED4) ? 1 : 0; + write(pInfo->fd, (char *) &event, sizeof(event)); +} + +static int +evdevGetKbdLeds(InputInfoPtr pInfo) +{ + unsigned long evleds[NBITS(EV_LED_MAX)]; + int leds = 0; + + ioctl(pInfo->fd, EVIOCGLED(sizeof(evleds)), &evleds); + if (test_bit(EV_LED_CAPSL, evleds)) + leds |= XLED1; + + if (test_bit(EV_LED_NUML, evleds)) + leds |= XLED2; + + if (test_bit(EV_LED_SCROLLL, evleds)) + leds |= XLED3; + + if (test_bit(EV_LED_COMPOSE, evleds)) + leds |= XLED4; + + return leds; +} + +static void +evdevSetKbdRepeat(InputInfoPtr pInfo, char rad) +{ + KbdDevPtr pKbd = (KbdDevPtr) pInfo->private; + int rep_info[2]; + + rep_info[0] = pKbd->delay; + rep_info[1] = pKbd->rate * 10; + ioctl(pInfo->fd, EVIOCSREP, rep_info); +} + +static int +evdevGetSpecialKey(InputInfoPtr pInfo, int scanCode) +{ + return scanCode; +} + +static Bool +evdevOpenKeyboard(InputInfoPtr pInfo) +{ + return TRUE; +} + +static Bool +evdevKbdPreInit(InputInfoPtr pInfo, char *protocol) +{ + KbdDevPtr pKbd = pInfo->private; + evdevKbdPtr evdevKbd; + xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol); + + pKbd->private = evdevKbd = xcalloc(sizeof(evdevKbdRec), 1); + + xf86Msg(X_ERROR, "%s: pInfo->dev: %p\n", pInfo->name, pInfo->dev); + + if (pKbd->private == NULL) { + xf86Msg(X_ERROR, "%s: cannot allocate buffer\n", pInfo->name); + return FALSE; + } + + evdevKbd->buffer = xcalloc(sizeof(struct input_event),1); + + if (evdevKbd->buffer == NULL) { + xf86Msg(X_ERROR, "%s: cannot allocate buffer\n", pInfo->name); + xfree(evdevKbd); + return FALSE; + } + + if (!evdevStart (pInfo->drv)) { + xf86Msg(X_ERROR, "%s: cannot start evdev brain\n", pInfo->name); + xfree(evdevKbd); + xfree(evdevKbd->buffer); + return FALSE; + } + + pKbd->KbdInit = evdevKbdInit; + pKbd->KbdOn = evdevKbdOn; + pKbd->KbdOff = evdevKbdOff; + pKbd->Bell = evdevSoundBell; + pKbd->SetLeds = evdevSetKbdLeds; + pKbd->GetLeds = evdevGetKbdLeds; + pKbd->SetKbdRepeat = evdevSetKbdRepeat; + pKbd->KbdGetMapping = KbdGetMapping; + pKbd->SpecialKey = SpecialKey; + + pKbd->RemapScanCode = NULL; + pKbd->GetSpecialKey = evdevGetSpecialKey; + + pKbd->OpenKeyboard = evdevOpenKeyboard; + pKbd->vtSwitchSupported = FALSE; + pInfo->read_input = evdevKbdReadInput; + + return TRUE; +} + +Bool +xf86OSKbdPreInit(InputInfoPtr pInfo) +{ + char *protocol; + Bool ret; + + protocol = xf86SetStrOption(pInfo->options, "Protocol", NULL); + + if (!protocol) + ret = FALSE; + else if (!strcmp(protocol, "standard")) + ret = stdKbdPreInit(pInfo, protocol); + else if (!strcmp(protocol, "evdev")) + ret = evdevKbdPreInit(pInfo, protocol); + else + ret = FALSE; + + xfree(protocol); + return ret; +}