Skip to content

Commit 9d17ad2

Browse files
Rajat Jaindtor
authored andcommitted
Input: atkbd - receive and use physcode->keycode mapping from FW
Allow the firmware to specify the mapping between the scan code and the linux keycode. This takes the form of a "linux,keymap" property which is an array of u32 values, each value specifying mapping for a key. Signed-off-by: Rajat Jain <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Torokhov <[email protected]>
1 parent 8f7b057 commit 9d17ad2

File tree

1 file changed

+40
-1
lines changed

1 file changed

+40
-1
lines changed

drivers/input/keyboard/atkbd.c

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ MODULE_PARM_DESC(terminal, "Enable break codes on an IBM Terminal keyboard conne
6666

6767
#define MAX_FUNCTION_ROW_KEYS 24
6868

69+
#define SCANCODE(keymap) ((keymap >> 16) & 0xFFFF)
70+
#define KEYCODE(keymap) (keymap & 0xFFFF)
71+
6972
/*
7073
* Scancode to keycode tables. These are just the default setting, and
7174
* are loadable via a userland utility.
@@ -1032,20 +1035,56 @@ static unsigned int atkbd_oqo_01plus_scancode_fixup(struct atkbd *atkbd,
10321035
return code;
10331036
}
10341037

1038+
static int atkbd_get_keymap_from_fwnode(struct atkbd *atkbd)
1039+
{
1040+
struct device *dev = &atkbd->ps2dev.serio->dev;
1041+
int i, n;
1042+
u32 *ptr;
1043+
u16 scancode, keycode;
1044+
1045+
/* Parse "linux,keymap" property */
1046+
n = device_property_count_u32(dev, "linux,keymap");
1047+
if (n <= 0 || n > ATKBD_KEYMAP_SIZE)
1048+
return -ENXIO;
1049+
1050+
ptr = kcalloc(n, sizeof(u32), GFP_KERNEL);
1051+
if (!ptr)
1052+
return -ENOMEM;
1053+
1054+
if (device_property_read_u32_array(dev, "linux,keymap", ptr, n)) {
1055+
dev_err(dev, "problem parsing FW keymap property\n");
1056+
kfree(ptr);
1057+
return -EINVAL;
1058+
}
1059+
1060+
memset(atkbd->keycode, 0, sizeof(atkbd->keycode));
1061+
for (i = 0; i < n; i++) {
1062+
scancode = SCANCODE(ptr[i]);
1063+
keycode = KEYCODE(ptr[i]);
1064+
atkbd->keycode[scancode] = keycode;
1065+
}
1066+
1067+
kfree(ptr);
1068+
return 0;
1069+
}
1070+
10351071
/*
10361072
* atkbd_set_keycode_table() initializes keyboard's keycode table
10371073
* according to the selected scancode set
10381074
*/
10391075

10401076
static void atkbd_set_keycode_table(struct atkbd *atkbd)
10411077
{
1078+
struct device *dev = &atkbd->ps2dev.serio->dev;
10421079
unsigned int scancode;
10431080
int i, j;
10441081

10451082
memset(atkbd->keycode, 0, sizeof(atkbd->keycode));
10461083
bitmap_zero(atkbd->force_release_mask, ATKBD_KEYMAP_SIZE);
10471084

1048-
if (atkbd->translated) {
1085+
if (!atkbd_get_keymap_from_fwnode(atkbd)) {
1086+
dev_dbg(dev, "Using FW keymap\n");
1087+
} else if (atkbd->translated) {
10491088
for (i = 0; i < 128; i++) {
10501089
scancode = atkbd_unxlate_table[i];
10511090
atkbd->keycode[i] = atkbd_set2_keycode[scancode];

0 commit comments

Comments
 (0)