diff options
Diffstat (limited to '0001-Simulate-fake-Fn-key-on-PS-2-keyboards-w-o-one-eg.-C.patch')
| -rw-r--r-- | 0001-Simulate-fake-Fn-key-on-PS-2-keyboards-w-o-one-eg.-C.patch | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/0001-Simulate-fake-Fn-key-on-PS-2-keyboards-w-o-one-eg.-C.patch b/0001-Simulate-fake-Fn-key-on-PS-2-keyboards-w-o-one-eg.-C.patch new file mode 100644 index 00000000000000..8f3b191874c7d4 --- /dev/null +++ b/0001-Simulate-fake-Fn-key-on-PS-2-keyboards-w-o-one-eg.-C.patch @@ -0,0 +1,157 @@ +>From 2b68920c417303e3adb90631ed9a9cbf864c0a94 Mon Sep 17 00:00:00 2001 +From: Dirk Hohndel <dirk@hohndel.org> +Date: Wed, 1 May 2013 11:23:28 -0700 +Subject: [PATCH 1/1] Simulate fake Fn key on PS/2 keyboards w/o one (eg. + Chromebook Pixel) + +This establishes a somewhat generic way to do this and implements a +specific solution for the Pixel where the right ALT key is redefined +to be an Fn key. + +Press/release events for the fake Fn key are no longer reported up, +but if the fake Fn key is pressed, then other keys are potentially +translated. + +Implemented in this patch are the following mappings: + BS -> Delete + Up -> PgUp + Down -> PgDn + Left -> Home + Right -> End + +Signed-off-by: Dirk Hohndel <dirk@hohndel.org> +--- + drivers/input/keyboard/atkbd.c | 80 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 80 insertions(+) + +--- a/drivers/input/keyboard/atkbd.c ++++ b/drivers/input/keyboard/atkbd.c +@@ -161,6 +161,19 @@ static const unsigned short atkbd_unxlat + #define ATKBD_KEY_UNKNOWN 0 + #define ATKBD_KEY_NULL 255 + ++#define ATKBD_KEY_IGNORE 0x8000 ++#define ATKBD_KEY_BS 0x0e ++#define ATKBD_KEY_DEL 0x53 /* actually E0 53 - same for the rest here */ ++#define ATKBD_KEY_ALT_R 0x38 ++#define ATKBD_KEY_HOME 0x47 ++#define ATKBD_KEY_UP 0x48 ++#define ATKBD_KEY_PGUP 0x49 ++#define ATKBD_KEY_LEFT 0x4b ++#define ATKBD_KEY_RIGHT 0x4d ++#define ATKBD_KEY_END 0x4f ++#define ATKBD_KEY_DOWN 0x50 ++#define ATKBD_KEY_PGDN 0x51 ++ + #define ATKBD_SCR_1 0xfffe + #define ATKBD_SCR_2 0xfffd + #define ATKBD_SCR_4 0xfffc +@@ -218,6 +231,7 @@ struct atkbd { + bool softraw; + bool scroll; + bool enabled; ++ bool fake_fn; + + /* Accessed only from interrupt */ + unsigned char emul; +@@ -242,6 +256,7 @@ struct atkbd { + static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); + static void *atkbd_platform_fixup_data; + static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int); ++static unsigned int (*atkbd_fake_fn_fixup)(struct atkbd *, unsigned int); + + static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, + ssize_t (*handler)(struct atkbd *, char *)); +@@ -398,6 +413,13 @@ static irqreturn_t atkbd_interrupt(struc + if (!atkbd->enabled) + goto out; + ++ if (atkbd_fake_fn_fixup) { ++ code = atkbd_fake_fn_fixup(atkbd, code); ++ if (code == ATKBD_KEY_IGNORE) ++ /* fake Fn key pressed - ignore */ ++ goto out; ++ } ++ + input_event(dev, EV_MSC, MSC_RAW, code); + + if (atkbd_platform_scancode_fixup) +@@ -988,6 +1010,48 @@ static unsigned int atkbd_oqo_01plus_sca + } + + /* ++ * Google Chromebook Pixel is lacking an Fn key. In order to use as ++ * a regular Linux laptop we steal the left Alt key and turn it into ++ * an Fn key ++ */ ++static unsigned int atkbd_pixel_fake_fn_fixup(struct atkbd *atkbd, unsigned int code) ++{ ++ if (atkbd->emul != 1) { ++ /* handle backspace here as it's the only one w/o ++ * a leading E0/E1 (i.e., emul == 0) */ ++ if (atkbd->emul == 0 && atkbd->fake_fn && (code & 0x7f) == ATKBD_KEY_BS) { ++ /* when pretending that Delete was pressed we need ++ * to set emul as well as Delete is E0 53 */ ++ atkbd->emul = 1; ++ code = (code & 0x80) | ATKBD_KEY_DEL; ++ } ++ } else if ((code & 0x7f) == ATKBD_KEY_ALT_R) { ++ atkbd->fake_fn = (code & 0x80) ? 0 : 1; ++ atkbd->emul = 0; ++ code = ATKBD_KEY_IGNORE; ++ } else if (atkbd->fake_fn) { ++ unsigned int oldcode = code; ++ switch(code & 0x7f) { ++ case ATKBD_KEY_UP: ++ code = ATKBD_KEY_PGUP; ++ break; ++ case ATKBD_KEY_DOWN: ++ code = ATKBD_KEY_PGDN; ++ break; ++ case ATKBD_KEY_LEFT: ++ code = ATKBD_KEY_HOME; ++ break; ++ case ATKBD_KEY_RIGHT: ++ code = ATKBD_KEY_END; ++ break; ++ } ++ code |= oldcode & 0x80; ++ } ++ return code; ++} ++ ++ ++/* + * atkbd_set_keycode_table() initializes keyboard's keycode table + * according to the selected scancode set + */ +@@ -1638,6 +1702,13 @@ static int __init atkbd_setup_scancode_f + return 1; + } + ++static int __init atkbd_setup_fake_fn_fixup(const struct dmi_system_id *id) ++{ ++ atkbd_fake_fn_fixup = id->driver_data; ++ ++ return 1; ++} ++ + static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = { + { + .matches = { +@@ -1775,6 +1846,15 @@ static const struct dmi_system_id atkbd_ + .callback = atkbd_setup_scancode_fixup, + .driver_data = atkbd_oqo_01plus_scancode_fixup, + }, ++ { ++ /* Google Chromebook Pixel */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Link"), ++ }, ++ .callback = atkbd_setup_fake_fn_fixup, ++ .driver_data = atkbd_pixel_fake_fn_fixup, ++ }, + { } + }; + |
