Re: pc_keyb.c 3 button mouse emulation

From: Pavel Machek (pavel@suse.cz)
Date: Sun Jul 30 2000 - 15:05:12 EST


Hi!

> I would like to use the "Windows" key on my PC compatible notebook as the
> middle mouse button. I would prefer to do this at the driver level as is
> done on the Macintosh port rather than at the application level.

BAD idea.

Such emulation belongs to gpm -R, then X can see already "emulated"
features. Notice that what you want is very similar to me wanting
mouse-on-keyboard emulation [and you definitely don't want *that* in
kernelspace, do you].

I actually did mouse-on-keyboard emulation with trivial patch called
keylink some time ago. [It basically created /dev/keylink and whenever
you pressed interesting key it send char through that device].

> Anyway, I am hoping that one of the current maintainers of this code might
> see the use in such a feature and help. Since the ps/2 mouse and keyboard
> drivers are now part of the same file, this hack may not even be so ugly.
> If there is an existing way to do what I am wanting, then I apologize for
> this message, but would then like very much to know what that way is.

I hope this hack does not get through. Doing it right (userspace)
would be much better.

                                                                Pavel
[here it is, for reference; I do even have mouse emulation daemon, and
it was really trivial with gpm's "mix two mice into one" feature]
Hi!

I've created simple way for keyboard to talk to userland. I used to
use kerneld, but there is no such thing any more. It allows for
example pasting from keyboard (really usefull - mouse is usefull for
text selection, but why touch it for pasting of text?), I also use it
for mouse emulation on keyboard.

It also includes my previous blank-from-keyboard patch, and it does
mirror cleaning up of peaces it touches.

                                                        Pavel
PS: relative to 2.1.90.

--- /dev/null Sun Jun 2 15:30:20 1996
+++ linux/drivers/char/keylink.c Sun Mar 22 16:26:16 1998
@@ -0,0 +1,128 @@
+/*
+ * Keylink - for making keyboard combinations call userland
+ *
+ * Copyright 1998 Pavel Machek <pavel@ucw.cz>, distribute
+ * under terms of GPL
+ *
+ * Loosely based on msbusmouse.c.
+ */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+
+static struct wait_queue *wait;
+static int active = 0;
+
+#define RING 0x100
+static char ringbuf[ RING ];
+static int head = 0, tail = 0;
+
+#define INC( a ) a = (a+1) & (RING-1)
+
+void keylink_pushkey( char c )
+{
+ INC( head );
+ if (head == tail)
+ printk( "keylink: ring buffer overrun, keys lost\n" );
+ ringbuf[ head ] = c;
+ wake_up_interruptible(&wait);
+}
+
+static int release_keylink(struct inode * inode, struct file * file)
+{
+ if (--active)
+ return 0;
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int open_keylink(struct inode * inode, struct file * file)
+{
+ if (active++)
+ return 0;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static ssize_t write_keylink(struct file * file,
+ const char * buffer, size_t count, loff_t *ppos)
+{
+ return -EINVAL;
+}
+
+static ssize_t read_keylink(struct file * file,
+ char * buffer, size_t count, loff_t *ppos)
+{
+ int i;
+
+ if (head==tail)
+ interruptible_sleep_on( &wait );
+ for (i = 0; i < count; i++) {
+ if (head==tail)
+ break;
+ INC( tail );
+ put_user(ringbuf[tail], buffer + i);
+ }
+ return i;
+}
+
+static unsigned int keylink_poll(struct file *file, poll_table * local_wait)
+{
+ poll_wait(file, &wait, local_wait);
+ return 0;
+}
+
+struct file_operations keylink_fops = {
+ NULL, /* keylink_seek */
+ read_keylink,
+ write_keylink,
+ NULL, /* keylink_readdir */
+ keylink_poll, /* keylink_poll */
+ NULL, /* keylink_ioctl */
+ NULL, /* keylink_mmap */
+ open_keylink,
+ release_keylink,
+ NULL,
+};
+
+static struct miscdevice misc_keylink = {
+ KEYLINK_MINOR, "keylink", &keylink_fops
+};
+
+__initfunc(int keylink_init(void))
+{
+ head = tail = 0;
+ wait = NULL;
+
+
+ printk(KERN_INFO "Keylink installed.\n");
+ misc_register(&misc_keylink);
+ return 0;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+ return keylink_init();
+}
+
+void cleanup_module(void)
+{
+ misc_deregister(&misc_keylink);
+}
+#endif
+
--- clean/drivers/char/Config.in Wed Mar 18 12:56:09 1998
+++ linux/drivers/char/Config.in Sun Mar 22 19:18:46 1998
@@ -7,6 +7,7 @@
 bool 'Virtual terminal' CONFIG_VT
 if [ "$CONFIG_VT" = "y" ]; then
   bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE
+ bool 'Keylink support' CONFIG_KEYLINK
 fi
 tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL
 if [ "$CONFIG_SERIAL" = "y" ]; then
diff -u clean/drivers/char/Makefile linux/drivers/char/Makefile
--- clean/drivers/char/Makefile Wed Jan 14 21:45:43 1998
+++ linux/drivers/char/Makefile Sun Mar 22 19:20:49 1998
@@ -39,6 +39,10 @@
 
 ifndef CONFIG_SUN_KEYBOARD
 ifdef CONFIG_VT
+ifdef CONFIG_KEYLINK
+L_OBJS += keylink.o
+M = y
+endif
 L_OBJS += keyboard.o
 endif
 ifneq ($(ARCH),m68k)
diff -u clean/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- clean/drivers/char/keyboard.c Thu Feb 12 12:32:35 1998
+++ linux/drivers/char/keyboard.c Sun Mar 22 21:24:31 1998
@@ -19,6 +19,8 @@
  * parts by Geert Uytterhoeven, May 1997
  *
  * 27-05-97: Added support for the Magic SysRq Key (Martin Mares)
+ *
+ * 29-07-97: Added blank console key and possiblity to call userland (Pavel Machek)
  */
 
 #include <linux/config.h>
@@ -104,31 +107,33 @@
 
 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_ignore;
+ do_meta, do_ascii, do_lock, do_lowercase, do_slock, do_keylink, do_ignore;
 
 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_ignore, do_ignore, do_ignore
+ do_keylink, do_ignore, do_ignore
 };
 
 /* 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 << 13))
 
 typedef void (*void_fnp)(void);
 typedef void (void_fn)(void);
 
 static void_fn do_null, enter, show_ptregs, send_intr, lastcons, caps_toggle,
         num, hold, scroll_forw, scroll_back, boot_it, caps_on, compose,
- SAK, decr_console, incr_console, spawn_console, bare_num;
+ SAK, decr_console, incr_console, spawn_console, bare_num,
+ blank_now;
 
 static void_fnp spec_fn_table[] = {
         do_null, enter, show_ptregs, show_mem,
         show_state, send_intr, lastcons, caps_toggle,
         num, hold, scroll_forw, scroll_back,
         boot_it, caps_on, compose, SAK,
- decr_console, incr_console, spawn_console, bare_num
+ decr_console, incr_console, spawn_console, bare_num,
+ blank_now
 };
 
 #define SPECIALS_ALLOWED_IN_RAW_MODE (1 << KVAL(K_SAK))
@@ -138,7 +143,7 @@
         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
+ NR_LOCK - 1, 255
 };
 
 const int NR_TYPES = SIZE(max_vals);
@@ -195,8 +200,11 @@
         char up_flag; /* 0 or 0200 */
         char raw_mode;
 
- do_poke_blanked_console = 1;
- mark_bh(CONSOLE_BH);
+ if (scancode < 0x80)
+ {
+ do_poke_blanked_console = 1;
+ mark_bh(CONSOLE_BH);
+ }
         add_keyboard_randomness(scancode);
 
         tty = ttytab[fg_console];
@@ -406,6 +414,11 @@
         if (!rep)
                 chg_vc_kbd_led(kbd,VC_NUMLOCK);
 }
+static void blank_now(void)
+{
+ do_poke_blanked_console = 0;
+ do_blank_screen(0);
+}
 
 static void lastcons(void)
 {
@@ -490,6 +503,14 @@
 #endif
 }
 
+static void do_keylink(unsigned char value, char up_flag)
+{
+#ifdef CONFIG_KEYLINK
+ if (!up_flag)
+ keylink_pushkey( value );
+#endif
+}
+
 static void do_ignore(unsigned char value, char up_flag)
 {
 }
@@ -511,6 +532,10 @@
         spec_fn_table[value]();
 }
 
+/*
+ * You do not want to clear this procedure and reuse its place...
+ * this is where normal characters reside
+ */
 static void do_lowercase(unsigned char value, char up_flag)
 {
         printk(KERN_ERR "keyboard.c: do_lowercase was called - impossible\n");
diff -u clean/drivers/char/mem.c linux/drivers/char/mem.c
--- clean/drivers/char/mem.c Sun Mar 8 12:49:55 1998
+++ linux/drivers/char/mem.c Sun Mar 22 21:18:02 1998
@@ -32,9 +32,6 @@
 #ifdef CONFIG_ISDN
 int isdn_init(void);
 #endif
-#ifdef CONFIG_PCWATCHDOG
-int pcwatchdog_init(void);
-#endif
 #ifdef CONFIG_VIDEO_DEV
 extern int videodev_init(void);
 #endif
@@ -532,7 +529,8 @@
     defined (CONFIG_AMIGAMOUSE) || defined (CONFIG_ATARIMOUSE) || \
     defined (CONFIG_PCWATCHDOG) || \
     defined (CONFIG_APM) || defined (CONFIG_RTC) || \
- defined (CONFIG_SUN_MOUSE) || defined (CONFIG_NVRAM)
+ defined (CONFIG_SUN_MOUSE) || defined (CONFIG_NVRAM) || \
+ defined (CONFIG_KEYLINK)
         misc_init();
 #endif
 #ifdef CONFIG_SOUND
diff -u clean/drivers/char/misc.c linux/drivers/char/misc.c
--- clean/drivers/char/misc.c Wed Mar 18 12:56:09 1998
+++ linux/drivers/char/misc.c Sun Mar 22 21:16:05 1998
@@ -81,9 +85,7 @@
 extern int nvram_init(void);
 extern int radio_init(void);
 extern void hfmodem_init(void);
-#ifdef CONFIG_PC110_PAD
 extern int pc110pad_init(void);
-#endif
 
 #ifdef CONFIG_PROC_FS
 static int misc_read_proc(char *buf, char **start, off_t offset,
@@ -269,6 +271,9 @@
 #endif
 #ifdef CONFIG_HFMODEM
         hfmodem_init();
+#endif
+#ifdef CONFIG_KEYLINK
+ keylink_init();
 #endif
 #endif /* !MODULE */
         if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
--- clean/include/linux/miscdevice.h Wed Jan 14 21:46:06 1998
+++ linux/include/linux/miscdevice.h Sun Mar 22 00:05:47 1998
@@ -9,6 +9,7 @@
 #define ATARIMOUSE_MINOR 5
 #define SUN_MOUSE_MINOR 6
 #define PC110PAD_MINOR 9
+#define KEYLINK_MINOR 127
 #define WATCHDOG_MINOR 130 /* Watchdog timer */
 #define TEMP_MINOR 131 /* Temperature Sensor */
 #define RTC_MINOR 135
--- kbd-0.93/src/ksyms.c.ofic Fri Apr 4 22:14:02 1997
+++ kbd-0.93/src/ksyms.c Sun Mar 22 13:44:49 1998
@@ -714,7 +714,7 @@
 };
 
 static char *spec_syms[] = {
- "VoidSymbol",
+ "VoidSymbol", /* 0 */
         "Return",
         "Show_Registers",
         "Show_Memory",
@@ -724,7 +724,7 @@
         "Caps_Lock",
         "Num_Lock",
         "Scroll_Lock",
- "Scroll_Forward",
+ "Scroll_Forward", /* 10 */
         "Scroll_Backward",
         "Boot",
         "Caps_On",
@@ -733,7 +733,17 @@
         "Decr_Console",
         "Incr_Console",
         "Spawn_Console",
- "Bare_Num_Lock"
+ "Bare_Num_Lock",
+ "Blank_Now", /* 20 */
+ "__Spec_21",
+ "__Spec_22",
+ "__Spec_23",
+ "__Spec_24",
+ "__Spec_25",
+ "__Spec_26",
+ "__Spec_27",
+ "__Spec_28",
+ "__Spec_29"
 };
 
 static char *pad_syms[] = {
@@ -1033,6 +1043,265 @@
         "SCtrlR"
 };
 
+static char *keylink_syms[] = {
+ "Keylink_Paste", /* 0 */
+ "Keylink_LeftDown",
+ "Keylink_Down",
+ "Keylink_RightDown",
+ "Keylink_Left",
+ "Keylink_5", /* 5 */
+ "Keylink_Right",
+ "Keylink_LeftUp",
+ "Keylink_Up",
+ "Keylink_RightUp",
+ "Keylink_Fast_LeftDown",/* 10 */
+ "Keylink_Fast_Down",
+ "Keylink_Fast_RightDown",
+ "Keylink_Fast_Left",
+ "Keylink_14",
+ "Keylink_Fast_Right", /* 15 */
+ "Keylink_Fast_LeftUp",
+ "Keylink_Fast_Up",
+ "Keylink_Fast_RightUp",
+ "Keylink_19",
+ "Keylink_Click_1", /* 20 */
+ "Keylink_Click_2",
+ "Keylink_Click_3",
+ "Keylink_Toggle_1",
+ "Keylink_Toggle_2",
+ "Keylink_Toggle_3",
+ "Keylink_DoubleClick_1",
+ "Keylink_DoubleClick_2",
+ "Keylink_DoubleClick_3",
+ "Keylink_29",
+ "Keylink_30",
+ "Keylink_31",
+ "Keylink_32",
+ "Keylink_33",
+ "Keylink_34",
+ "Keylink_35",
+ "Keylink_36",
+ "Keylink_37",
+ "Keylink_38",
+ "Keylink_39",
+ "Keylink_40",
+ "Keylink_41",
+ "Keylink_42",
+ "Keylink_43",
+ "Keylink_44",
+ "Keylink_45",
+ "Keylink_46",
+ "Keylink_47",
+ "Keylink_48",
+ "Keylink_49",
+ "Keylink_50",
+ "Keylink_51",
+ "Keylink_52",
+ "Keylink_53",
+ "Keylink_54",
+ "Keylink_55",
+ "Keylink_56",
+ "Keylink_57",
+ "Keylink_58",
+ "Keylink_59",
+ "Keylink_60",
+ "Keylink_61",
+ "Keylink_62",
+ "Keylink_63",
+ "Keylink_64",
+ "Keylink_65",
+ "Keylink_66",
+ "Keylink_67",
+ "Keylink_68",
+ "Keylink_69",
+ "Keylink_70",
+ "Keylink_71",
+ "Keylink_72",
+ "Keylink_73",
+ "Keylink_74",
+ "Keylink_75",
+ "Keylink_76",
+ "Keylink_77",
+ "Keylink_78",
+ "Keylink_79",
+ "Keylink_80",
+ "Keylink_81",
+ "Keylink_82",
+ "Keylink_83",
+ "Keylink_84",
+ "Keylink_85",
+ "Keylink_86",
+ "Keylink_87",
+ "Keylink_88",
+ "Keylink_89",
+ "Keylink_90",
+ "Keylink_91",
+ "Keylink_92",
+ "Keylink_93",
+ "Keylink_94",
+ "Keylink_95",
+ "Keylink_96",
+ "Keylink_97",
+ "Keylink_98",
+ "Keylink_99",
+ "Keylink_100",
+ "Keylink_101",
+ "Keylink_102",
+ "Keylink_103",
+ "Keylink_104",
+ "Keylink_105",
+ "Keylink_106",
+ "Keylink_107",
+ "Keylink_108",
+ "Keylink_109",
+ "Keylink_110",
+ "Keylink_111",
+ "Keylink_112",
+ "Keylink_113",
+ "Keylink_114",
+ "Keylink_115",
+ "Keylink_116",
+ "Keylink_117",
+ "Keylink_118",
+ "Keylink_119",
+ "Keylink_120",
+ "Keylink_121",
+ "Keylink_122",
+ "Keylink_123",
+ "Keylink_124",
+ "Keylink_125",
+ "Keylink_126",
+ "Keylink_127",
+ "Keylink_128",
+ "Keylink_129",
+ "Keylink_130",
+ "Keylink_131",
+ "Keylink_132",
+ "Keylink_133",
+ "Keylink_134",
+ "Keylink_135",
+ "Keylink_136",
+ "Keylink_137",
+ "Keylink_138",
+ "Keylink_139",
+ "Keylink_140",
+ "Keylink_141",
+ "Keylink_142",
+ "Keylink_143",
+ "Keylink_144",
+ "Keylink_145",
+ "Keylink_146",
+ "Keylink_147",
+ "Keylink_148",
+ "Keylink_149",
+ "Keylink_150",
+ "Keylink_151",
+ "Keylink_152",
+ "Keylink_153",
+ "Keylink_154",
+ "Keylink_155",
+ "Keylink_156",
+ "Keylink_157",
+ "Keylink_158",
+ "Keylink_159",
+ "Keylink_160",
+ "Keylink_161",
+ "Keylink_162",
+ "Keylink_163",
+ "Keylink_164",
+ "Keylink_165",
+ "Keylink_166",
+ "Keylink_167",
+ "Keylink_168",
+ "Keylink_169",
+ "Keylink_170",
+ "Keylink_171",
+ "Keylink_172",
+ "Keylink_173",
+ "Keylink_174",
+ "Keylink_175",
+ "Keylink_176",
+ "Keylink_177",
+ "Keylink_178",
+ "Keylink_179",
+ "Keylink_180",
+ "Keylink_181",
+ "Keylink_182",
+ "Keylink_183",
+ "Keylink_184",
+ "Keylink_185",
+ "Keylink_186",
+ "Keylink_187",
+ "Keylink_188",
+ "Keylink_189",
+ "Keylink_190",
+ "Keylink_191",
+ "Keylink_192",
+ "Keylink_193",
+ "Keylink_194",
+ "Keylink_195",
+ "Keylink_196",
+ "Keylink_197",
+ "Keylink_198",
+ "Keylink_199",
+ "Keylink_200",
+ "Keylink_201",
+ "Keylink_202",
+ "Keylink_203",
+ "Keylink_204",
+ "Keylink_205",
+ "Keylink_206",
+ "Keylink_207",
+ "Keylink_208",
+ "Keylink_209",
+ "Keylink_210",
+ "Keylink_211",
+ "Keylink_212",
+ "Keylink_213",
+ "Keylink_214",
+ "Keylink_215",
+ "Keylink_216",
+ "Keylink_217",
+ "Keylink_218",
+ "Keylink_219",
+ "Keylink_220",
+ "Keylink_221",
+ "Keylink_222",
+ "Keylink_223",
+ "Keylink_224",
+ "Keylink_225",
+ "Keylink_226",
+ "Keylink_227",
+ "Keylink_228",
+ "Keylink_229",
+ "Keylink_230",
+ "Keylink_231",
+ "Keylink_232",
+ "Keylink_233",
+ "Keylink_234",
+ "Keylink_235",
+ "Keylink_236",
+ "Keylink_237",
+ "Keylink_238",
+ "Keylink_239",
+ "Keylink_240",
+ "Keylink_241",
+ "Keylink_242",
+ "Keylink_243",
+ "Keylink_244",
+ "Keylink_245",
+ "Keylink_246",
+ "Keylink_247",
+ "Keylink_248",
+ "Keylink_249",
+ "Keylink_250",
+ "Keylink_251",
+ "Keylink_252",
+ "Keylink_253",
+ "Keylink_254",
+ "Keylink_255" };
+
+
 #define E(x) { x, sizeof(x) / sizeof(char **) }
 
 syms_entry syms[] = {
@@ -1048,7 +1317,8 @@
         E(ascii_syms),
         E(lock_syms),
         { 0, 0 },
- E(sticky_syms)
+ E(sticky_syms),
+ E(keylink_syms)
 };
 
 #undef E

-- 
I'm pavel@ucw.cz. "In my country we have almost anarchy and I don't care."
Panos Katsaloulis describing me w.r.t. patents at discuss@linmodems.org

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Jul 31 2000 - 21:00:33 EST