
From: Stelian Pop <stelian@popies.net>

On newer Apple Powerbooks (post February 2005 ones at least) the ADB
keyboard has been replaced with an USB one conforming to the HID spec.

The 'Fn' modifier key on this keyboard is a soft key reported using an
application specific hid code.  This key should act as a modifier in order
to make Home/End/Page Up/Page Down etc.  work.

The attached patch makes the Fn key report a modifier keycode
(KEY_RIGHTCTRL) to the input layer by adding a quirk to the USB HID input
driver.  Johannes Berg <johannes@sipsolutions.net> should be credited for
the original version of this patch.

'Right control' is not the best choice for this key, especially since it is
physically placed on the keyboard on the left bottom corner.  However, this
laptop already has left shift, control, alt and meta (apple) keys, and
right meta and shift keys.  The only modifiers left are 'right control' and
'right alt' and the first one was chosen.  Choosing an already defined
modifier key eases the handling of this key especially in X (where it can
be mapped to SuperL or whatever).

Signed-off-by: Stelian Pop <stelian@popies.net>
Cc: Vojtech Pavlik <vojtech@suse.cz>
Cc: Dmitry Torokhov <dtor_core@ameritech.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 drivers/usb/input/hid-core.c  |    7 +++++++
 drivers/usb/input/hid-input.c |    8 ++++++++
 drivers/usb/input/hid.h       |    1 +
 3 files changed, 16 insertions(+)

diff -puN drivers/usb/input/hid-core.c~input-quirk-for-the-fn-key-on-powerbooks-with-an-usb drivers/usb/input/hid-core.c
--- devel/drivers/usb/input/hid-core.c~input-quirk-for-the-fn-key-on-powerbooks-with-an-usb	2005-07-29 23:30:58.000000000 -0700
+++ devel-akpm/drivers/usb/input/hid-core.c	2005-07-29 23:30:58.000000000 -0700
@@ -1445,6 +1445,10 @@ void hid_init_reports(struct hid_device 
  * Alphabetically sorted blacklist by quirk type.
  */
 
+#define USB_VENDOR_ID_APPLE		0x05AC
+#define USB_DEVICE_ID_POWERBOOK_KB_US	0x020E
+#define USB_DEVICE_ID_POWERBOOK_KB_UK	0x020F
+
 static struct hid_blacklist {
 	__u16 idVendor;
 	__u16 idProduct;
@@ -1557,6 +1561,9 @@ static struct hid_blacklist {
 	{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
 
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_POWERBOOK_KB_US, HID_QUIRK_POWERBOOK_FN_BUTTON },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_POWERBOOK_KB_UK, HID_QUIRK_POWERBOOK_FN_BUTTON },
+
 	{ 0, 0 }
 };
 
diff -puN drivers/usb/input/hid.h~input-quirk-for-the-fn-key-on-powerbooks-with-an-usb drivers/usb/input/hid.h
--- devel/drivers/usb/input/hid.h~input-quirk-for-the-fn-key-on-powerbooks-with-an-usb	2005-07-29 23:30:58.000000000 -0700
+++ devel-akpm/drivers/usb/input/hid.h	2005-07-29 23:30:58.000000000 -0700
@@ -245,6 +245,7 @@ struct hid_item {
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_7		0x080
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_5		0x100
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON		0x200
+#define HID_QUIRK_POWERBOOK_FN_BUTTON		0x400
 
 /*
  * This is the global environment of the parser. This information is
diff -puN drivers/usb/input/hid-input.c~input-quirk-for-the-fn-key-on-powerbooks-with-an-usb drivers/usb/input/hid-input.c
--- devel/drivers/usb/input/hid-input.c~input-quirk-for-the-fn-key-on-powerbooks-with-an-usb	2005-07-29 23:30:58.000000000 -0700
+++ devel-akpm/drivers/usb/input/hid-input.c	2005-07-29 23:30:58.000000000 -0700
@@ -107,6 +107,10 @@ static void hidinput_configure_usage(str
 			} else
 				map_key(KEY_UNKNOWN);
 
+			if ((device->quirks & HID_QUIRK_POWERBOOK_FN_BUTTON) &&
+			    (hid_keyboard[usage->hid & HID_USAGE] == KEY_RIGHTCTRL))
+				map_key(KEY_UNKNOWN);
+
 			break;
 
 		case HID_UP_BUTTON:
@@ -372,6 +376,10 @@ static void hidinput_configure_usage(str
 
 		default:
 		unknown:
+			if ((device->quirks & HID_QUIRK_POWERBOOK_FN_BUTTON) && (usage->hid == 0x00ff0003)) {
+				map_key_clear(KEY_RIGHTCTRL);
+				break;
+			}
 			if (field->report_size == 1) {
 				if (field->report->type == HID_OUTPUT_REPORT) {
 					map_led(LED_MISC);
_
