diff -u -r -x Makefile -x '*~' -x '.*' -x '*.o' -x '*.a' -x '*.o.flags' linux-2.4.20-rc1/CREDITS linux/CREDITS --- linux-2.4.20-rc1/CREDITS 2002-11-07 18:03:20.000000000 -0500 +++ linux/CREDITS 2002-11-07 16:57:48.000000000 -0500 @@ -3044,6 +3044,15 @@ S: 10200 Prague 10, Hostivar S: Czech Republic +N: Rick van Rein +E: vanrein@cs.utwente.nl +W: http://www.cs.utwente.nl/~vanrein +D: Funkey, the support for nonstd function keys through the /dev/funkey device. +S: Binnenes 67 +S: 9407 CX Assen +S: The Netherlands + + N: James R. Van Zandt E: jrv@vanzandt.mv.com P: 1024/E298966D F0 37 4F FD E5 7E C5 E6 F1 A0 1E 22 6F 46 DA 0C diff -u -r -x Makefile -x '*~' -x '.*' -x '*.o' -x '*.a' -x '*.o.flags' linux-2.4.20-rc1/Documentation/Configure.help linux/Documentation/Configure.help --- linux-2.4.20-rc1/Documentation/Configure.help 2002-11-07 18:03:20.000000000 -0500 +++ linux/Documentation/Configure.help 2002-11-07 16:57:48.000000000 -0500 @@ -4206,6 +4206,17 @@ CPU. Generally SMP PowerMacs can answer Y. SMP IBM CHRP boxes or Power3 boxes should say N for now. +Funny Functional Key support +CONFIG_FUNKEY + New keyboards are sometimes equipped with special keys for functions + such as volume control, that should not generate text but invoke a + function instead. Handling through the console is dependent of the + kbd_mode and is generally unsupported under XFree86. + By selecting this option, a character special device /dev/funkey can + be tapped for such keys. + Sail to http://rick.vanrein.org/linux/funkey for information and the + matching "funky" daemon. + Video mode selection support CONFIG_VIDEO_SELECT This enables support for text mode selection on kernel startup. If diff -u -r -x Makefile -x '*~' -x '.*' -x '*.o' -x '*.a' -x '*.o.flags' linux-2.4.20-rc1/drivers/char/Config.in linux/drivers/char/Config.in --- linux-2.4.20-rc1/drivers/char/Config.in 2002-11-07 18:03:28.000000000 -0500 +++ linux/drivers/char/Config.in 2002-11-07 16:57:49.000000000 -0500 @@ -11,6 +11,7 @@ bool ' Support for Lasi/Dino PS2 port' CONFIG_GSC_PS2 fi fi +bool 'Funny/Function Key support' CONFIG_FUNKEY tristate 'Standard/generic (8250/16550 and compatible UARTs) serial support' CONFIG_SERIAL if [ "$CONFIG_SERIAL" = "y" ]; then bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE diff -u -r -x Makefile -x '*~' -x '.*' -x '*.o' -x '*.a' -x '*.o.flags' linux-2.4.20-rc1/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- linux-2.4.20-rc1/drivers/char/keyboard.c 2002-08-02 20:39:43.000000000 -0400 +++ linux/drivers/char/keyboard.c 2002-11-18 22:09:27.000000000 -0500 @@ -4,6 +4,8 @@ * Written for linux by Johan Myreen as a translation from * the assembly version by Linus (with diacriticals added) * + * Support for /dev/funkey added by Rick van Rein, April 2000 + * * Some additional features added by Christoph Niemann (ChN), March 1993 * * Loadable keymaps by Risto Kankkunen, May 1993 @@ -32,9 +34,12 @@ #include #include #include +#include +#include #include #include +#include #include #include @@ -103,17 +108,25 @@ static k_handfn do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_dead2, +#ifdef CONFIG_FUNKEY + do_funkey, do_ignore; +#else do_ignore; +#endif static k_hand key_handler[16] = { do_self, do_fn, do_spec, do_pad, do_dead, do_cons, do_cur, do_shift, do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_dead2, +#ifdef CONFIG_FUNKEY + do_funkey, do_ignore +#else do_ignore, do_ignore +#endif }; /* Key types processed even in raw modes */ -#define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_SHIFT)) +#define TYPES_ALLOWED_IN_RAW_MODE ((1 << KT_SPEC) | (1 << KT_SHIFT) | (1 << KT_FUNKEY)) typedef void (*void_fnp)(void); typedef void (void_fn)(void); @@ -137,7 +150,13 @@ 255, SIZE(func_table) - 1, SIZE(spec_fn_table) - 1, NR_PAD - 1, NR_DEAD - 1, 255, 3, NR_SHIFT - 1, 255, NR_ASCII - 1, NR_LOCK - 1, 255, - NR_LOCK - 1, 255 + NR_LOCK - 1, +#ifdef CONFIG_FUNKEY + 255, 127 +#else + 255 +#endif + }; const int NR_TYPES = SIZE(max_vals); @@ -380,6 +399,35 @@ put_queue(10); } +#ifdef CONFIG_FUNKEY + +DECLARE_WAIT_QUEUE_HEAD(funkey_wait); +static unsigned char funkey_queue [256]; +static unsigned char funkey_wpos=0; +static unsigned char funkey_rpos=0; + +static void put_funkey_queue (int ch) +{ + funkey_queue [funkey_wpos++] = ch & 0xff; + if (funkey_wpos != funkey_rpos) { + wake_up(&funkey_wait); + } +} + +static int get_funkey_queue (struct file *f) +{ + if (funkey_wpos == funkey_rpos) { + if (f->f_flags & O_NONBLOCK) + return -EAGAIN; + interruptible_sleep_on(&funkey_wait); + if (funkey_wpos == funkey_rpos) + return 0; + } + return funkey_queue[funkey_rpos++]; +} + +#endif + static void caps_toggle(void) { if (rep) @@ -636,6 +684,15 @@ printk(KERN_ERR "do_fn called with value=%d\n", value); } +#ifdef CONFIG_FUNKEY +static void do_funkey(unsigned char value, char up_flag) +{ + if (up_flag) + value |= 0x80; + put_funkey_queue (value); +} +#endif + static void do_pad(unsigned char value, char up_flag) { static const char *pad_chars = "0123456789+-*/\015,.?()"; @@ -890,6 +947,87 @@ return leds; } +#ifdef CONFIG_FUNKEY + +loff_t llseek_funkey (struct file *f, loff_t off, int whence) +{ + return -ESPIPE; +} + +ssize_t read_funkey (struct file *f, char *buf, size_t toget, loff_t *offs) +{ + int keycode; + int err; + keycode = get_funkey_queue(f); + if (keycode < 0) /* EAGAIN for non-blocking read */ + return keycode; + if (!keycode) + return -EINTR; + if ((err = verify_area(VERIFY_WRITE, buf, 1L))) + return err; + put_user((unsigned char) keycode, buf); + return 1; +} + +ssize_t write_funkey (struct file *f, const char *buf, size_t toget, loff_t *offs) +{ + return -EINVAL; +} + +unsigned int poll_funkey (struct file *f, poll_table *wait) +{ + poll_wait(f, &funkey_wait, wait); + if (funkey_wpos == funkey_rpos) + return 0; + else + return POLLIN | POLLRDNORM; +} + +static int funkey_opencnt=0; +int open_funkey (struct inode *in, struct file *f) +{ + if (funkey_opencnt) + return -EBUSY; + funkey_opencnt++; + funkey_rpos=funkey_wpos; + return 0; +} + +int close_funkey (struct inode *in, struct file *f) +{ + funkey_opencnt--; + return 0; +} + +/* The /dev/funkey device broadcasts the key codes from the + * keyboard, regardless of the kbd_mode of the console and regardless of + * settings in the keymaps. + */ +static struct file_operations funkey_file_operations = { + NULL, /* owner */ + llseek_funkey, /* seek */ + read_funkey, + write_funkey, + NULL, /* readdir */ + poll_funkey, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + open_funkey, + NULL, /* flush */ + close_funkey, + NULL, /* fsync */ + NULL /* fasync */ +}; + + + +void init_dev_funkey (void) +{ + register_chrdev (0, "funkey", &funkey_file_operations); +} + +#endif + /* * This routine is the bottom half of the keyboard interrupt * routine, and runs with all interrupts enabled. It does @@ -946,5 +1084,9 @@ pm_kbd = pm_register(PM_SYS_DEV, PM_SYS_KBC, pm_kbd_request_override); +#ifdef CONFIG_FUNKEY + init_dev_funkey(); +#endif + return 0; } diff -u -r -x Makefile -x '*~' -x '.*' -x '*.o' -x '*.a' -x '*.o.flags' linux-2.4.20-rc1/include/linux/keyboard.h linux/include/linux/keyboard.h --- linux-2.4.20-rc1/include/linux/keyboard.h 2002-08-02 20:39:45.000000000 -0400 +++ linux/include/linux/keyboard.h 2002-11-07 16:57:49.000000000 -0500 @@ -44,6 +44,7 @@ #define KT_ASCII 9 #define KT_LOCK 10 #define KT_SLOCK 12 +#define KT_FUNKEY 14 #define K(t,v) (((t)<<8)|(v)) #define KTYP(x) ((x) >> 8)