diff -uNr linux.orig/CREDITS linux/CREDITS --- linux.orig/CREDITS 2002-08-15 11:28:06.000000000 +0200 +++ linux/CREDITS 2002-08-15 11:54:02.000000000 +0200 @@ -3033,6 +3033,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 -uNr linux.orig/Documentation/Configure.help linux/Documentation/Configure.help --- linux.orig/Documentation/Configure.help 2002-08-15 11:28:07.000000000 +0200 +++ linux/Documentation/Configure.help 2002-08-15 11:54:02.000000000 +0200 @@ -4021,6 +4021,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 -uNr linux.orig/drivers/char/Config.in linux/drivers/char/Config.in --- linux.orig/drivers/char/Config.in Tue Feb 13 17:13:43 2001 +++ linux/drivers/char/Config.in Sun Mar 25 09:47:23 2001 @@ -8,6 +8,7 @@ if [ "$CONFIG_VT" = "y" ]; then bool ' Support for console on virtual terminal' CONFIG_VT_CONSOLE 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 -uNr linux.orig/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- linux.orig/drivers/char/keyboard.c 2002-08-15 11:28:25.000000000 +0200 +++ linux/drivers/char/keyboard.c 2002-08-15 11:54:02.000000000 +0200 @@ -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,11 @@ #include #include #include +#include #include #include +#include #include #include @@ -103,17 +107,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 +149,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 +398,33 @@ 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; + +void put_funkey_queue (int ch) +{ + funkey_queue [funkey_wpos++] = ch & 0xff; + if (funkey_wpos != funkey_rpos) { + wake_up(&funkey_wait); + } +} + +unsigned char get_funkey_queue (void) +{ + if (funkey_wpos == funkey_rpos) { + 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 +681,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 +944,70 @@ return leds; } +#ifdef CONFIG_FUNKEY + +ssize_t read_funkey (struct file *f, char *buf, size_t toget, loff_t *offs) +{ + unsigned char keycode=get_funkey_queue (); + int err; + if (!keycode) + return -EINTR; + if ((err = verify_area(VERIFY_WRITE, buf, 1L))) + return err; + put_user (keycode, buf); + return 1; +} + +ssize_t write_funkey (struct file *f, char *buf, size_t toget, loff_t *offs) +{ + return -EINVAL; +} + +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, /* Module ? */ + NULL, /* seek */ + read_funkey, + write_funkey, + NULL, /* readdir */ + NULL, /* poll */ + NULL, /* ioctl */ + NULL, /* mmap */ + open_funkey, + NULL, /* flush */ + close_funkey, + NULL, /* revalidate */ + NULL /* sync */ +}; + + + +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 +1064,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 -uNr linux.orig/drivers/char/testkeys linux/drivers/char/testkeys --- linux.orig/drivers/char/testkeys 1970-01-01 02:00:00.000000000 +0200 +++ linux/drivers/char/testkeys 2002-08-15 11:54:02.000000000 +0200 @@ -0,0 +1 @@ +keycode 123 = F40 diff -uNr linux.orig/include/linux/keyboard.h linux/include/linux/keyboard.h --- linux.orig/include/linux/keyboard.h 2002-08-15 11:29:33.000000000 +0200 +++ linux/include/linux/keyboard.h 2002-08-15 11:54:02.000000000 +0200 @@ -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)