input/powermac: Cleanup of mac_hid and support for ctrl+click and command+click

Michael Hanselmann linux-kernel at hansmi.ch
Sun May 21 00:12:48 EST 2006


This patch cleans up mac_hid and adds support for Ctrl+Click (right
click) and Command+Click (middle click) emulation. The latter is similar
to Mac OS X.

Signed-off-by: Michael Hanselmann <linux-kernel at hansmi.ch>

---
diff -Nrup --exclude-from linux-exclude-from linux-2.6.17-rc4.orig/drivers/char/keyboard.c linux-2.6.17-rc4/drivers/char/keyboard.c
--- linux-2.6.17-rc4.orig/drivers/char/keyboard.c	2006-05-13 12:33:45.000000000 +0200
+++ linux-2.6.17-rc4/drivers/char/keyboard.c	2006-05-19 23:33:17.000000000 +0200
@@ -40,6 +40,10 @@
 #include <linux/sysrq.h>
 #include <linux/input.h>
 
+#ifdef CONFIG_MAC_EMUMOUSEBTN
+#include <asm/mac_hid.h>
+#endif
+
 static void kbd_disconnect(struct input_handle *handle);
 extern void ctrl_alt_del(void);
 
@@ -1052,10 +1056,6 @@ static unsigned short x86_keycodes[256] 
 	308,310,313,314,315,317,318,319,320,357,322,323,324,325,276,330,
 	332,340,365,342,343,344,345,346,356,270,341,368,369,370,371,372 };
 
-#ifdef CONFIG_MAC_EMUMOUSEBTN
-extern int mac_hid_mouse_emulate_buttons(int, int, int);
-#endif /* CONFIG_MAC_EMUMOUSEBTN */
-
 #ifdef CONFIG_SPARC
 static int sparc_l1_a_state = 0;
 extern void sun_do_break(void);
@@ -1151,7 +1151,7 @@ static void kbd_keycode(unsigned int key
 	rep = (down == 2);
 
 #ifdef CONFIG_MAC_EMUMOUSEBTN
-	if (mac_hid_mouse_emulate_buttons(1, keycode, down))
+	if (mac_hid_mouse_emulate_buttons(keycode, down))
 		return;
 #endif /* CONFIG_MAC_EMUMOUSEBTN */
 
diff -Nrup --exclude-from linux-exclude-from linux-2.6.17-rc4.orig/drivers/input/input.c linux-2.6.17-rc4/drivers/input/input.c
--- linux-2.6.17-rc4.orig/drivers/input/input.c	2006-05-13 12:33:45.000000000 +0200
+++ linux-2.6.17-rc4/drivers/input/input.c	2006-05-20 13:43:41.000000000 +0200
@@ -24,6 +24,10 @@
 #include <linux/device.h>
 #include <linux/mutex.h>
 
+#ifdef CONFIG_MAC_EMUMOUSEBTN
+#include <asm/mac_hid.h>
+#endif
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech at suse.cz>");
 MODULE_DESCRIPTION("Input core");
 MODULE_LICENSE("GPL");
@@ -194,8 +198,16 @@ static void input_repeat_key(unsigned lo
 	if (!test_bit(dev->repeat_key, dev->key))
 		return;
 
-	input_event(dev, EV_KEY, dev->repeat_key, 2);
-	input_sync(dev);
+#ifdef CONFIG_MAC_EMUMOUSEBTN
+	if (!mac_hid_repeat_key(dev->repeat_key)) {
+#endif
+
+		input_event(dev, EV_KEY, dev->repeat_key, 2);
+		input_sync(dev);
+
+#ifdef CONFIG_MAC_EMUMOUSEBTN
+	}
+#endif
 
 	if (dev->rep[REP_PERIOD])
 		mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD]));
diff -Nrup --exclude-from linux-exclude-from linux-2.6.17-rc4.orig/drivers/input/mousedev.c linux-2.6.17-rc4/drivers/input/mousedev.c
--- linux-2.6.17-rc4.orig/drivers/input/mousedev.c	2006-05-13 12:33:46.000000000 +0200
+++ linux-2.6.17-rc4/drivers/input/mousedev.c	2006-05-20 00:48:58.000000000 +0200
@@ -27,6 +27,9 @@
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
 #include <linux/miscdevice.h>
 #endif
+#ifdef CONFIG_MAC_EMUMOUSEBTN
+#include <asm/mac_hid.h>
+#endif
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech at ucw.cz>");
 MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces");
@@ -316,8 +319,12 @@ static void mousedev_event(struct input_
 			if (value != 2) {
 				if (code == BTN_TOUCH && test_bit(BTN_TOOL_FINGER, handle->dev->keybit))
 					mousedev_touchpad_touch(mousedev, value);
-				else
+				else {
+#ifdef CONFIG_MAC_EMUMOUSEBTN
+					code = mac_hid_mouse_click(code, value);
+#endif
 					mousedev_key_event(mousedev, code, value);
+				}
 			}
 			break;
 
diff -Nrup --exclude-from linux-exclude-from linux-2.6.17-rc4.orig/drivers/macintosh/Kconfig linux-2.6.17-rc4/drivers/macintosh/Kconfig
--- linux-2.6.17-rc4.orig/drivers/macintosh/Kconfig	2006-05-13 12:33:46.000000000 +0200
+++ linux-2.6.17-rc4/drivers/macintosh/Kconfig	2006-05-20 13:29:07.000000000 +0200
@@ -144,6 +144,10 @@ config MAC_EMUMOUSEBTN
 	  /proc/sys/dev/mac_hid/mouse_button_emulation
 	  /proc/sys/dev/mac_hid/mouse_button2_keycode
 	  /proc/sys/dev/mac_hid/mouse_button3_keycode
+	  /proc/sys/dev/mac_hid/key_click
+
+	  When key_click is enabled by writing a value other than 0 into it,
+	  Ctrl+Click is for right click and Command+Click for middle click.
 
 	  If you have an Apple machine with a 1-button mouse, say Y here.
 
diff -Nrup --exclude-from linux-exclude-from linux-2.6.17-rc4.orig/drivers/macintosh/mac_hid.c linux-2.6.17-rc4/drivers/macintosh/mac_hid.c
--- linux-2.6.17-rc4.orig/drivers/macintosh/mac_hid.c	2006-05-13 12:33:46.000000000 +0200
+++ linux-2.6.17-rc4/drivers/macintosh/mac_hid.c	2006-05-20 14:03:20.000000000 +0200
@@ -4,8 +4,7 @@
  * HID support stuff for Macintosh computers.
  *
  * Copyright (C) 2000 Franz Sirl.
- *
- * This file will soon be removed in favor of an uinput userspace tool.
+ * Copyright (C) 2006 Michael Hanselmann <linux-kernel at hansmi.ch>
  */
 
 #include <linux/config.h>
@@ -14,16 +13,19 @@
 #include <linux/sysctl.h>
 #include <linux/input.h>
 #include <linux/module.h>
-
+#include <asm/mac_hid.h>
 
 static struct input_dev *emumousebtn;
-static int emumousebtn_input_register(void);
-static int mouse_emulate_buttons = 0;
+static int mouse_emulate_buttons;
 static int mouse_button2_keycode = KEY_RIGHTCTRL;	/* right control key */
 static int mouse_button3_keycode = KEY_RIGHTALT;	/* right option key */
-static int mouse_last_keycode = 0;
+static int key_click;
+static int key_click_active;
+static int key_click_button;
+static int key_pressed;
+static int inside_mouse_click;
 
-#if defined(CONFIG_SYSCTL)
+#ifdef CONFIG_SYSCTL
 /* file(s) in /proc/sys/dev/mac_hid */
 ctl_table mac_hid_files[] = {
 	{
@@ -50,6 +52,14 @@ ctl_table mac_hid_files[] = {
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
+	{
+		.ctl_name	= DEV_MAC_HID_KEY_CLICK,
+		.procname	= "key_click",
+		.data		= &key_click,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 	{ .ctl_name = 0 }
 };
 
@@ -79,33 +89,91 @@ ctl_table mac_hid_root_dir[] = {
 
 static struct ctl_table_header *mac_hid_sysctl_header;
 
-#endif /* endif CONFIG_SYSCTL */
+#endif /* CONFIG_SYSCTL */
 
-int mac_hid_mouse_emulate_buttons(int caller, unsigned int keycode, int down)
+/* Emulate mouse buttons with keys */
+int mac_hid_mouse_emulate_buttons(unsigned int keycode, int down)
 {
-	switch (caller) {
-	case 1:
-		/* Called from keyboard.c */
-		if (mouse_emulate_buttons
-		    && (keycode == mouse_button2_keycode
-			|| keycode == mouse_button3_keycode)) {
-			if (mouse_emulate_buttons == 1) {
-				input_report_key(emumousebtn,
-						 keycode == mouse_button2_keycode ? BTN_MIDDLE : BTN_RIGHT,
-						 down);
+	if (inside_mouse_click)
+		return 0;
+
+	if (key_click &&
+	    (keycode == KEY_LEFTCTRL || keycode == KEY_RIGHTCTRL ||
+	     keycode == KEY_LEFTMETA || keycode == KEY_RIGHTMETA)) {
+		if (down && !key_pressed && !key_click_active)
+			key_pressed = keycode;
+		else if (!down && keycode == key_pressed) {
+			key_pressed = 0;
+
+			if (key_click_active > 0) {
+				input_report_key(emumousebtn, key_click_active, 0);
 				input_sync(emumousebtn);
-				return 1;
+
+				key_click_active = -1;
 			}
-			mouse_last_keycode = down ? keycode : 0;
 		}
-		break;
 	}
+
+	if (mouse_emulate_buttons) {
+		if (keycode == mouse_button2_keycode)
+			input_report_key(emumousebtn, BTN_RIGHT, down);
+		else if (keycode == mouse_button3_keycode)
+			input_report_key(emumousebtn, BTN_MIDDLE, down);
+
+		input_sync(emumousebtn);
+
+		return 1;
+	}
+
 	return 0;
 }
 
-EXPORT_SYMBOL(mac_hid_mouse_emulate_buttons);
+/* Modify mouse button value if the Control key is pressed */
+int mac_hid_mouse_click(unsigned int code, int value)
+{
+	if (!key_click || code != BTN_LEFT || inside_mouse_click)
+		return code;
+
+	inside_mouse_click = 1;
+
+	if (value && key_pressed && !key_click_active) {
+		key_click_active = key_pressed;
+
+		input_report_key(emumousebtn, key_click_active, 0);
+		input_sync(emumousebtn);
+
+		if (key_click_active == KEY_LEFTMETA ||
+		    key_click_active == KEY_RIGHTMETA)
+			code = BTN_MIDDLE;
+		else
+			code = BTN_RIGHT;
+
+		key_click_button = code;
+	} else if (!value && key_click_active) {
+		if (key_click_active > 0) {
+			input_report_key(emumousebtn, key_click_active, 1);
+			input_sync(emumousebtn);
+		}
 
-static int emumousebtn_input_register(void)
+		key_click_active = 0;
+
+		code = key_click_button;
+	}
+
+	inside_mouse_click = 0;
+
+	return code;
+}
+
+/* This function returns true if the given keycode should not
+ * be repeated.
+ */
+int mac_hid_repeat_key(unsigned int keycode)
+{
+	return (key_click && key_click_active == keycode);
+}
+
+int __init mac_hid_init(void)
 {
 	emumousebtn = input_allocate_device();
 	if (!emumousebtn)
@@ -121,24 +189,22 @@ static int emumousebtn_input_register(vo
 	emumousebtn->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
 	emumousebtn->relbit[0] = BIT(REL_X) | BIT(REL_Y);
 
-	input_register_device(emumousebtn);
-
-	return 0;
-}
+	set_bit(KEY_LEFTCTRL, emumousebtn->keybit);
+	set_bit(KEY_RIGHTCTRL, emumousebtn->keybit);
+	set_bit(KEY_LEFTMETA, emumousebtn->keybit);
+	set_bit(KEY_RIGHTMETA, emumousebtn->keybit);
 
-int __init mac_hid_init(void)
-{
-	int err;
-
-	err = emumousebtn_input_register();
-	if (err)
-		return err;
+	input_register_device(emumousebtn);
 
-#if defined(CONFIG_SYSCTL)
+#ifdef CONFIG_SYSCTL
 	mac_hid_sysctl_header = register_sysctl_table(mac_hid_root_dir, 1);
-#endif /* CONFIG_SYSCTL */
+#endif
 
 	return 0;
 }
 
 device_initcall(mac_hid_init);
+
+EXPORT_SYMBOL(mac_hid_mouse_emulate_buttons);
+EXPORT_SYMBOL_GPL(mac_hid_mouse_click);
+EXPORT_SYMBOL_GPL(mac_hid_repeat_key);
diff -Nrup --exclude-from linux-exclude-from linux-2.6.17-rc4.orig/include/asm-powerpc/mac_hid.h linux-2.6.17-rc4/include/asm-powerpc/mac_hid.h
--- linux-2.6.17-rc4.orig/include/asm-powerpc/mac_hid.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17-rc4/include/asm-powerpc/mac_hid.h	2006-05-20 00:49:22.000000000 +0200
@@ -0,0 +1,13 @@
+/*
+ * HID support stuff for Macintosh computers.
+ */
+#ifndef __ASM_POWERPC_MAC_HID_H
+#define __ASM_POWERPC_MAC_HID_H
+#ifdef __KERNEL__
+
+extern int mac_hid_mouse_emulate_buttons(unsigned int keycode, int down);
+extern int mac_hid_mouse_click(unsigned int code, int value);
+extern int mac_hid_repeat_key(unsigned int keycode);
+
+#endif
+#endif
diff -Nrup --exclude-from linux-exclude-from linux-2.6.17-rc4.orig/include/linux/sysctl.h linux-2.6.17-rc4/include/linux/sysctl.h
--- linux-2.6.17-rc4.orig/include/linux/sysctl.h	2006-05-13 12:34:00.000000000 +0200
+++ linux-2.6.17-rc4/include/linux/sysctl.h	2006-05-20 12:31:23.000000000 +0200
@@ -870,7 +870,8 @@ enum {
 	DEV_MAC_HID_MOUSE_BUTTON_EMULATION=3,
 	DEV_MAC_HID_MOUSE_BUTTON2_KEYCODE=4,
 	DEV_MAC_HID_MOUSE_BUTTON3_KEYCODE=5,
-	DEV_MAC_HID_ADB_MOUSE_SENDS_KEYCODES=6
+	DEV_MAC_HID_ADB_MOUSE_SENDS_KEYCODES=6,
+	DEV_MAC_HID_KEY_CLICK=7,
 };
 
 /* /proc/sys/dev/scsi */



More information about the Linuxppc-dev mailing list