From: Wayne W. <wh...@ma...> - 2003-02-06 17:07:56
|
On Thu, 6 Feb 2003, Zephaniah E. Hull wrote: > On Mon, Jan 27, 2003 at 10:31:17AM -0800, Wayne Whitney wrote: > > > Adreas Shuldei mentioned on lin...@li... that > > you have been writing a patch to XFree86 for an Input driver using the > > Linux /dev/input/eventX interface. As of November he indicated that the > > patch worked for point devices, and that you were working on keyboards. > > [ . . . ] > > If there is solid interest in this, I can get the keyboard stuff working > and shove the patches upstream. Well, I am definitely interested, for one. I am currently using the patch below, which I adapted from Miguel Freitas' very hackish patch <http://cambuca.ldhs.cetuc.puc-rio.br/multiuser/> to make it slightly less hackish. It works for me, although I haven't extensively tested it. Cheers, Wayne diff -ru xc/programs/Xserver/hw/xfree86/common/xf86Config.c xd/programs/Xserver/hw/xfree86/common/xf86Config.c --- xc/programs/Xserver/hw/xfree86/common/xf86Config.c 2003-01-26 12:09:35.000000000 -0800 +++ xd/programs/Xserver/hw/xfree86/common/xf86Config.c 2003-02-02 16:22:55.000000000 -0800 @@ -1076,6 +1076,24 @@ xf86Info.kbdProc = xf86KbdProc; xf86Info.kbdEvents = xf86KbdEvents; xfree(s); + } else if (xf86NameCmp(s, "linuxevent") == 0) { + xf86Info.kbdProc = xf86KbdProc; + xf86Info.kbdEvents = xf86LinuxEventKbdEvents; + xfree(s); + s = xf86SetStrOption(inputp->commonOptions, "Device", NULL); + xf86Msg(X_CONFIG, "Keyboard: Protocol: linuxevent\n"); + if (s == NULL) { + xf86ConfigError("A \"device\" option is required with" + " the \"linuxevent\" keyboard protocol"); + return FALSE; + } + xf86Info.kbdFd = open(s, O_RDWR | O_NONBLOCK | O_EXCL); + if (xf86Info.kbdFd == -1) { + xf86ConfigError("cannot open \"%s\"", s); + xfree(s); + return FALSE; + } + xfree(s); } else if (xf86NameCmp(s, "xqueue") == 0) { #ifdef XQUEUE xf86Info.kbdProc = xf86XqueKbdProc; diff -ru xc/programs/Xserver/hw/xfree86/common/xf86Privstr.h xd/programs/Xserver/hw/xfree86/common/xf86Privstr.h --- xc/programs/Xserver/hw/xfree86/common/xf86Privstr.h 2003-01-26 12:09:35.000000000 -0800 +++ xd/programs/Xserver/hw/xfree86/common/xf86Privstr.h 2003-02-02 16:22:55.000000000 -0800 @@ -59,6 +59,7 @@ int bell_pitch; int bell_duration; Bool autoRepeat; + int ledsave; unsigned long leds; unsigned long xleds; char * vtinit; diff -ru xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_io.c xd/programs/Xserver/hw/xfree86/os-support/linux/lnx_io.c --- xc/programs/Xserver/hw/xfree86/os-support/linux/lnx_io.c 2003-01-26 12:09:39.000000000 -0800 +++ xd/programs/Xserver/hw/xfree86/os-support/linux/lnx_io.c 2003-02-02 16:22:55.000000000 -0800 @@ -34,12 +34,18 @@ #include "xf86Priv.h" #include "xf86_OSlib.h" +#define EV_LED 0x11 /* <linux/input.h> */ +#define LED_NUML 0x00 /* <linux/input.h> */ +#define LED_CAPSL 0x01 /* <linux/input.h> */ +#define LED_SCROLLL 0x02 /* <linux/input.h> */ + + #define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */ void xf86SoundKbdBell(int loudness, int pitch, int duration) { - if (loudness && pitch) + if (loudness && pitch && xf86Info.kbdEvents != xf86LinuxEventKbdEvents) { ioctl(xf86Info.consoleFd, KDMKTONE, ((1193190 / pitch) & 0xffff) | @@ -51,16 +57,44 @@ void xf86SetKbdLeds(int leds) { + struct s_output_event { + struct timeval time; + unsigned short type; + unsigned short code; + unsigned int value; + } output_event; + + if (xf86Info.kbdEvents != xf86LinuxEventKbdEvents) ioctl(xf86Info.consoleFd, KDSETLED, leds); + else { + output_event.type = EV_LED; + output_event.code = LED_NUML; + output_event.value = (leds&(LED_NUM)) ? 1 : 0; + write( xf86Info.kbdFd, (char *)&output_event, sizeof(output_event)); + + output_event.type = EV_LED; + output_event.code = LED_CAPSL; + output_event.value = (leds&(LED_CAP)) ? 1 : 0; + write( xf86Info.kbdFd, (char *)&output_event, sizeof(output_event)); + + output_event.type = EV_LED; + output_event.code = LED_SCROLLL; + output_event.value = (leds&(LED_SCR)) ? 1 : 0; + write( xf86Info.kbdFd, (char *)&output_event, sizeof(output_event)); + + xf86Info.ledsave = leds; + } } int xf86GetKbdLeds() { int leds = 0; - + if (xf86Info.kbdEvents != xf86LinuxEventKbdEvents) { ioctl(xf86Info.consoleFd, KDGETLED, &leds); return(leds); + } else + return(xf86Info.ledsave); } /* kbd rate stuff based on kbdrate.c from Rik Faith <fa...@cs...> et.al. @@ -177,6 +211,9 @@ if (xf86Info.kbdDelay >= 0) delay = xf86Info.kbdDelay; +/* FIXME: just returning so we don't mess with any other keyboards... */ + if (xf86Info.kbdEvents == xf86LinuxEventKbdEvents) + return; if(KDKBDREP_ioctl_ok(rate, delay)) /* m68k? */ return; @@ -228,8 +265,10 @@ void xf86KbdInit() { + if (xf86Info.kbdEvents != xf86LinuxEventKbdEvents) { ioctl (xf86Info.consoleFd, KDGKBMODE, &kbdtrans); tcgetattr (xf86Info.consoleFd, &kbdtty); + } } int @@ -242,6 +281,7 @@ ioctl(xf86Info.consoleFd, KDSKBMODE, K_MEDIUMRAW); else #endif + if (xf86Info.kbdEvents != xf86LinuxEventKbdEvents) { ioctl(xf86Info.consoleFd, KDSKBMODE, K_RAW); nTty = kbdtty; @@ -255,13 +295,18 @@ cfsetospeed(&nTty, 9600); tcsetattr(xf86Info.consoleFd, TCSANOW, &nTty); return(xf86Info.consoleFd); + } else + return(xf86Info.kbdFd); } int xf86KbdOff() { + if (xf86Info.kbdEvents != xf86LinuxEventKbdEvents) { ioctl(xf86Info.consoleFd, KDSKBMODE, kbdtrans); tcsetattr(xf86Info.consoleFd, TCSANOW, &kbdtty); return(xf86Info.consoleFd); + } else + return(xf86Info.kbdFd); } diff -ru xc/programs/Xserver/hw/xfree86/os-support/shared/std_kbdEv.c xd/programs/Xserver/hw/xfree86/os-support/shared/std_kbdEv.c --- xc/programs/Xserver/hw/xfree86/os-support/shared/std_kbdEv.c 2003-01-26 12:09:47.000000000 -0800 +++ xd/programs/Xserver/hw/xfree86/os-support/shared/std_kbdEv.c 2003-02-02 16:22:55.000000000 -0800 @@ -30,6 +30,90 @@ #include "xf86Priv.h" #include "xf86_OSlib.h" +#define EV_KEY 0x01 /* <linux/input.h> */ +#define KEY_SYSRQ 99 /* <linux/input.h> */ +#define KEY_PAUSE 119 /* <linux/input.h> */ + + +static unsigned short x86_keycodes[256] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 43, 85, 86, 87, 88,115,119,120,121,375,123, 90, + 284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339, + 367,294,293,286,350, 92,334,512,116,377,109,111,373,347,348,349, + 360, 93, 94, 95, 98,376,100,101,357,316,354,304,289,102,351,355, + 103,104,105,275,281,272,306,106,274,107,288,364,358,363,362,361, + 291,108,381,290,287,292,279,305,280, 99,112,257,258,113,270,114, + 118,117,125,374,379,259,260,261,262,263,264,265,266,267,268,269, + 271,273,276,277,278,282,283,295,296,297,299,300,301,302,303,307, + 308,310,313,314,315,317,318,319,320,321,322,323,324,325,326,330, + 332,340,341,342,343,344,345,346,356,359,365,368,369,370,371,372 }; + +static void handle_scancode(unsigned char scancode, int down) +{ + char up_flag = down ? 0 : 0200; + + xf86PostKbdEvent(scancode | up_flag); +} + +static int emulate_raw(unsigned int keycode, int down) +{ + if (keycode > 255 || !x86_keycodes[keycode]) + return -1; + + if (keycode == KEY_PAUSE) { + handle_scancode(0xe1, 1); + handle_scancode(0x1d, down); + handle_scancode(0x45, down); + return 0; + } + + if (x86_keycodes[keycode] & 0x100) + handle_scancode(0xe0, 1); + + handle_scancode(x86_keycodes[keycode] & 0x7f, down); + + if (keycode == KEY_SYSRQ) { + handle_scancode(0xe0, 1); + handle_scancode(0x37, down); + } + + return 0; +} + + +static void keybdev_event(unsigned int type, unsigned int code, int down) +{ + if (type != EV_KEY) return; + + emulate_raw(code, down); +} + + +void xf86LinuxEventKbdEvents() +{ + struct s_input_event { + struct timeval time; + unsigned short type; + unsigned short code; + unsigned int value; + } input_event; + + if (xf86Info.consoleFd != -1) { + close(xf86Info.consoleFd); + xf86Info.consoleFd = -1; + close(2); + } + + while(read(xf86Info.kbdFd, (char *)&input_event, sizeof(input_event)) == sizeof(input_event)) + { + keybdev_event( input_event.type, input_event.code, input_event.value ); + } +} + void xf86KbdEvents() { diff -ru xc/programs/Xserver/hw/xfree86/os-support/xf86_OSproc.h xd/programs/Xserver/hw/xfree86/os-support/xf86_OSproc.h --- xc/programs/Xserver/hw/xfree86/os-support/xf86_OSproc.h 2002-01-25 13:56:17.000000000 -0800 +++ xd/programs/Xserver/hw/xfree86/os-support/xf86_OSproc.h 2003-02-02 16:22:55.000000000 -0800 @@ -228,6 +228,7 @@ extern int xf86KbdOn(void); extern int xf86KbdOff(void); extern void xf86KbdEvents(void); +extern void xf86LinuxEventKbdEvents(void); #ifdef XQUEUE extern int xf86XqueKbdProc(DeviceIntPtr, int); extern void xf86XqueEvents(void); |