Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 18349
b: refs/heads/master
c: eab9edd
h: refs/heads/master
i:
  18347: e37da9a
v: v3
  • Loading branch information
Michael Hanselmann authored and Dmitry Torokhov committed Jan 14, 2006
1 parent 7c91020 commit 210c8a8
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1e27ffd4d7d39783c5196daa2584cca5785d1f95
refs/heads/master: eab9edd27f7ceaad6b57085817d63287bda15190
10 changes: 10 additions & 0 deletions trunk/drivers/usb/input/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ config USB_HIDINPUT

If unsure, say Y.

config USB_HIDINPUT_POWERBOOK
bool "Enable support for iBook/PowerBook special keys"
default n
depends on USB_HIDINPUT
help
Say Y here if you want support for the special keys (Fn, Numlock) on
Apple iBooks and PowerBooks.

If unsure, say N.

config HID_FF
bool "Force feedback support (EXPERIMENTAL)"
depends on USB_HIDINPUT && EXPERIMENTAL
Expand Down
8 changes: 8 additions & 0 deletions trunk/drivers/usb/input/hid-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1585,6 +1585,14 @@ static const struct hid_blacklist {

{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },

{ USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },

{ 0, 0 }
};

Expand Down
166 changes: 164 additions & 2 deletions trunk/drivers/usb/input/hid-input.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,160 @@ static const struct {
#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
#define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0)

#ifdef CONFIG_USB_HIDINPUT_POWERBOOK

struct hidinput_key_translation {
u16 from;
u16 to;
u8 flags;
};

#define POWERBOOK_FLAG_FKEY 0x01

static struct hidinput_key_translation powerbook_fn_keys[] = {
{ KEY_BACKSPACE, KEY_DELETE },
{ KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY },
{ KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY },
{ KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY },
{ KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY },
{ KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY },
{ KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY },
{ KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY },
{ KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY },
{ KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY },
{ KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY },
{ KEY_UP, KEY_PAGEUP },
{ KEY_DOWN, KEY_PAGEDOWN },
{ KEY_LEFT, KEY_HOME },
{ KEY_RIGHT, KEY_END },
{ }
};

static struct hidinput_key_translation powerbook_numlock_keys[] = {
{ KEY_J, KEY_KP1 },
{ KEY_K, KEY_KP2 },
{ KEY_L, KEY_KP3 },
{ KEY_U, KEY_KP4 },
{ KEY_I, KEY_KP5 },
{ KEY_O, KEY_KP6 },
{ KEY_7, KEY_KP7 },
{ KEY_8, KEY_KP8 },
{ KEY_9, KEY_KP9 },
{ KEY_M, KEY_KP0 },
{ KEY_DOT, KEY_KPDOT },
{ KEY_SLASH, KEY_KPPLUS },
{ KEY_SEMICOLON, KEY_KPMINUS },
{ KEY_P, KEY_KPASTERISK },
{ KEY_MINUS, KEY_KPEQUAL },
{ KEY_0, KEY_KPSLASH },
{ KEY_F6, KEY_NUMLOCK },
{ KEY_KPENTER, KEY_KPENTER },
{ KEY_BACKSPACE, KEY_BACKSPACE },
{ }
};

static int usbhid_pb_fnmode = 1;
module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644);
MODULE_PARM_DESC(pb_fnmode,
"Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");

static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from)
{
struct hidinput_key_translation *trans;

/* Look for the translation */
for (trans = table; trans->from; trans++)
if (trans->from == from)
return trans;

return NULL;
}

static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
struct hid_usage *usage, __s32 value)
{
struct hidinput_key_translation *trans;

if (usage->code == KEY_FN) {
if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON;
else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON;

input_event(input, usage->type, usage->code, value);

return 1;
}

if (usbhid_pb_fnmode) {
int do_translate;

trans = find_translation(powerbook_fn_keys, usage->code);
if (trans) {
if (test_bit(usage->code, hid->pb_pressed_fn))
do_translate = 1;
else if (trans->flags & POWERBOOK_FLAG_FKEY)
do_translate =
(usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
(usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
else
do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON);

if (do_translate) {
if (value)
set_bit(usage->code, hid->pb_pressed_fn);
else
clear_bit(usage->code, hid->pb_pressed_fn);

input_event(input, usage->type, trans->to, value);

return 1;
}
}

if (test_bit(usage->code, hid->pb_pressed_numlock) ||
test_bit(LED_NUML, input->led)) {
trans = find_translation(powerbook_numlock_keys, usage->code);

if (trans) {
if (value)
set_bit(usage->code, hid->pb_pressed_numlock);
else
clear_bit(usage->code, hid->pb_pressed_numlock);

input_event(input, usage->type, trans->to, value);
}

return 1;
}
}

return 0;
}

static void hidinput_pb_setup(struct input_dev *input)
{
struct hidinput_key_translation *trans;

set_bit(KEY_NUMLOCK, input->keybit);

/* Enable all needed keys */
for (trans = powerbook_fn_keys; trans->from; trans++)
set_bit(trans->to, input->keybit);

for (trans = powerbook_numlock_keys; trans->from; trans++)
set_bit(trans->to, input->keybit);
}
#else
static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
struct hid_usage *usage, __s32 value)
{
return 0;
}

static inline void hidinput_pb_setup(struct input_dev *input)
{
}
#endif

static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
struct hid_usage *usage)
{
Expand Down Expand Up @@ -336,7 +490,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel

set_bit(EV_REP, input->evbit);
switch(usage->hid & HID_USAGE) {
case 0x003: map_key_clear(KEY_FN); break;
case 0x003:
/* The fn key on Apple PowerBooks */
map_key_clear(KEY_FN);
hidinput_pb_setup(input);
break;

default: goto ignore;
}
break;
Expand Down Expand Up @@ -493,6 +652,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
return;
}

if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value))
return;

if (usage->hat_min < usage->hat_max || usage->hat_dir) {
int hat_dir = usage->hat_dir;
if (!hat_dir)
Expand Down Expand Up @@ -535,7 +697,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
return;
}

if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */
return;

input_event(input, usage->type, usage->code, value);
Expand Down
31 changes: 19 additions & 12 deletions trunk/drivers/usb/input/hid.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,18 +235,20 @@ struct hid_item {
* HID device quirks.
*/

#define HID_QUIRK_INVERT 0x001
#define HID_QUIRK_NOTOUCH 0x002
#define HID_QUIRK_IGNORE 0x004
#define HID_QUIRK_NOGET 0x008
#define HID_QUIRK_HIDDEV 0x010
#define HID_QUIRK_BADPAD 0x020
#define HID_QUIRK_MULTI_INPUT 0x040
#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_2WHEEL_POWERMOUSE 0x400
#define HID_QUIRK_CYMOTION 0x800
#define HID_QUIRK_INVERT 0x00000001
#define HID_QUIRK_NOTOUCH 0x00000002
#define HID_QUIRK_IGNORE 0x00000004
#define HID_QUIRK_NOGET 0x00000008
#define HID_QUIRK_HIDDEV 0x00000010
#define HID_QUIRK_BADPAD 0x00000020
#define HID_QUIRK_MULTI_INPUT 0x00000040
#define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080
#define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200
#define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400
#define HID_QUIRK_CYMOTION 0x00000800
#define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000
#define HID_QUIRK_POWERBOOK_FN_ON 0x00002000

/*
* This is the global environment of the parser. This information is
Expand Down Expand Up @@ -432,6 +434,11 @@ struct hid_device { /* device report descriptor */
void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */
int (*ff_event)(struct hid_device *hid, struct input_dev *input,
unsigned int type, unsigned int code, int value);

#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
unsigned long pb_pressed_fn[NBITS(KEY_MAX)];
unsigned long pb_pressed_numlock[NBITS(KEY_MAX)];
#endif
};

#define HID_GLOBAL_STACK_SIZE 4
Expand Down

0 comments on commit 210c8a8

Please sign in to comment.