.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * AT and PS/2 keyboard driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 1999-2002 Vojtech Pavlik |
---|
5 | 6 | */ |
---|
6 | 7 | |
---|
7 | | -/* |
---|
8 | | - * This program is free software; you can redistribute it and/or modify it |
---|
9 | | - * under the terms of the GNU General Public License version 2 as published by |
---|
10 | | - * the Free Software Foundation. |
---|
11 | | - */ |
---|
12 | 8 | |
---|
13 | 9 | /* |
---|
14 | 10 | * This driver can handle standard AT keyboards and PS/2 keyboards in |
---|
.. | .. |
---|
28 | 24 | #include <linux/libps2.h> |
---|
29 | 25 | #include <linux/mutex.h> |
---|
30 | 26 | #include <linux/dmi.h> |
---|
| 27 | +#include <linux/property.h> |
---|
31 | 28 | |
---|
32 | 29 | #define DRIVER_DESC "AT and PS/2 keyboard driver" |
---|
33 | 30 | |
---|
.. | .. |
---|
66 | 63 | static bool atkbd_terminal; |
---|
67 | 64 | module_param_named(terminal, atkbd_terminal, bool, 0); |
---|
68 | 65 | MODULE_PARM_DESC(terminal, "Enable break codes on an IBM Terminal keyboard connected via AT/PS2"); |
---|
| 66 | + |
---|
| 67 | +#define MAX_FUNCTION_ROW_KEYS 24 |
---|
| 68 | + |
---|
| 69 | +#define SCANCODE(keymap) ((keymap >> 16) & 0xFFFF) |
---|
| 70 | +#define KEYCODE(keymap) (keymap & 0xFFFF) |
---|
69 | 71 | |
---|
70 | 72 | /* |
---|
71 | 73 | * Scancode to keycode tables. These are just the default setting, and |
---|
.. | .. |
---|
234 | 236 | |
---|
235 | 237 | /* Serializes reconnect(), attr->set() and event work */ |
---|
236 | 238 | struct mutex mutex; |
---|
| 239 | + |
---|
| 240 | + u32 function_row_physmap[MAX_FUNCTION_ROW_KEYS]; |
---|
| 241 | + int num_function_row_keys; |
---|
237 | 242 | }; |
---|
238 | 243 | |
---|
239 | 244 | /* |
---|
.. | .. |
---|
287 | 292 | __ATTR(_name, S_IRUGO, atkbd_do_show_##_name, NULL); |
---|
288 | 293 | |
---|
289 | 294 | ATKBD_DEFINE_RO_ATTR(err_count); |
---|
| 295 | +ATKBD_DEFINE_RO_ATTR(function_row_physmap); |
---|
290 | 296 | |
---|
291 | 297 | static struct attribute *atkbd_attributes[] = { |
---|
292 | 298 | &atkbd_attr_extra.attr, |
---|
.. | .. |
---|
296 | 302 | &atkbd_attr_softrepeat.attr, |
---|
297 | 303 | &atkbd_attr_softraw.attr, |
---|
298 | 304 | &atkbd_attr_err_count.attr, |
---|
| 305 | + &atkbd_attr_function_row_physmap.attr, |
---|
299 | 306 | NULL |
---|
300 | 307 | }; |
---|
301 | 308 | |
---|
| 309 | +static ssize_t atkbd_show_function_row_physmap(struct atkbd *atkbd, char *buf) |
---|
| 310 | +{ |
---|
| 311 | + ssize_t size = 0; |
---|
| 312 | + int i; |
---|
| 313 | + |
---|
| 314 | + if (!atkbd->num_function_row_keys) |
---|
| 315 | + return 0; |
---|
| 316 | + |
---|
| 317 | + for (i = 0; i < atkbd->num_function_row_keys; i++) |
---|
| 318 | + size += scnprintf(buf + size, PAGE_SIZE - size, "%02X ", |
---|
| 319 | + atkbd->function_row_physmap[i]); |
---|
| 320 | + size += scnprintf(buf + size, PAGE_SIZE - size, "\n"); |
---|
| 321 | + return size; |
---|
| 322 | +} |
---|
| 323 | + |
---|
| 324 | +static umode_t atkbd_attr_is_visible(struct kobject *kobj, |
---|
| 325 | + struct attribute *attr, int i) |
---|
| 326 | +{ |
---|
| 327 | + struct device *dev = container_of(kobj, struct device, kobj); |
---|
| 328 | + struct serio *serio = to_serio_port(dev); |
---|
| 329 | + struct atkbd *atkbd = serio_get_drvdata(serio); |
---|
| 330 | + |
---|
| 331 | + if (attr == &atkbd_attr_function_row_physmap.attr && |
---|
| 332 | + !atkbd->num_function_row_keys) |
---|
| 333 | + return 0; |
---|
| 334 | + |
---|
| 335 | + return attr->mode; |
---|
| 336 | +} |
---|
| 337 | + |
---|
302 | 338 | static struct attribute_group atkbd_attribute_group = { |
---|
303 | 339 | .attrs = atkbd_attributes, |
---|
| 340 | + .is_visible = atkbd_attr_is_visible, |
---|
304 | 341 | }; |
---|
305 | 342 | |
---|
306 | 343 | static const unsigned int xl_table[] = { |
---|
.. | .. |
---|
400 | 437 | if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_CMD)) |
---|
401 | 438 | if (ps2_handle_response(&atkbd->ps2dev, data)) |
---|
402 | 439 | goto out; |
---|
| 440 | + |
---|
| 441 | + pm_wakeup_event(&serio->dev, 0); |
---|
403 | 442 | |
---|
404 | 443 | if (!atkbd->enabled) |
---|
405 | 444 | goto out; |
---|
.. | .. |
---|
841 | 880 | if (param[0] != 3) { |
---|
842 | 881 | param[0] = 2; |
---|
843 | 882 | if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET)) |
---|
844 | | - return 2; |
---|
| 883 | + return 2; |
---|
845 | 884 | } |
---|
846 | 885 | |
---|
847 | 886 | ps2_command(ps2dev, param, ATKBD_CMD_SETALL_MBR); |
---|
.. | .. |
---|
996 | 1035 | return code; |
---|
997 | 1036 | } |
---|
998 | 1037 | |
---|
| 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 | + |
---|
999 | 1071 | /* |
---|
1000 | 1072 | * atkbd_set_keycode_table() initializes keyboard's keycode table |
---|
1001 | 1073 | * according to the selected scancode set |
---|
.. | .. |
---|
1003 | 1075 | |
---|
1004 | 1076 | static void atkbd_set_keycode_table(struct atkbd *atkbd) |
---|
1005 | 1077 | { |
---|
| 1078 | + struct device *dev = &atkbd->ps2dev.serio->dev; |
---|
1006 | 1079 | unsigned int scancode; |
---|
1007 | 1080 | int i, j; |
---|
1008 | 1081 | |
---|
1009 | 1082 | memset(atkbd->keycode, 0, sizeof(atkbd->keycode)); |
---|
1010 | 1083 | bitmap_zero(atkbd->force_release_mask, ATKBD_KEYMAP_SIZE); |
---|
1011 | 1084 | |
---|
1012 | | - if (atkbd->translated) { |
---|
| 1085 | + if (!atkbd_get_keymap_from_fwnode(atkbd)) { |
---|
| 1086 | + dev_dbg(dev, "Using FW keymap\n"); |
---|
| 1087 | + } else if (atkbd->translated) { |
---|
1013 | 1088 | for (i = 0; i < 128; i++) { |
---|
1014 | 1089 | scancode = atkbd_unxlate_table[i]; |
---|
1015 | 1090 | atkbd->keycode[i] = atkbd_set2_keycode[scancode]; |
---|
.. | .. |
---|
1123 | 1198 | } |
---|
1124 | 1199 | } |
---|
1125 | 1200 | |
---|
| 1201 | +static void atkbd_parse_fwnode_data(struct serio *serio) |
---|
| 1202 | +{ |
---|
| 1203 | + struct atkbd *atkbd = serio_get_drvdata(serio); |
---|
| 1204 | + struct device *dev = &serio->dev; |
---|
| 1205 | + int n; |
---|
| 1206 | + |
---|
| 1207 | + /* Parse "function-row-physmap" property */ |
---|
| 1208 | + n = device_property_count_u32(dev, "function-row-physmap"); |
---|
| 1209 | + if (n > 0 && n <= MAX_FUNCTION_ROW_KEYS && |
---|
| 1210 | + !device_property_read_u32_array(dev, "function-row-physmap", |
---|
| 1211 | + atkbd->function_row_physmap, n)) { |
---|
| 1212 | + atkbd->num_function_row_keys = n; |
---|
| 1213 | + dev_dbg(dev, "FW reported %d function-row key locations\n", n); |
---|
| 1214 | + } |
---|
| 1215 | +} |
---|
| 1216 | + |
---|
1126 | 1217 | /* |
---|
1127 | 1218 | * atkbd_connect() is called when the serio module finds an interface |
---|
1128 | 1219 | * that isn't handled yet by an appropriate device driver. We check if |
---|
.. | .. |
---|
1150 | 1241 | |
---|
1151 | 1242 | case SERIO_8042_XL: |
---|
1152 | 1243 | atkbd->translated = true; |
---|
1153 | | - /* Fall through */ |
---|
| 1244 | + fallthrough; |
---|
1154 | 1245 | |
---|
1155 | 1246 | case SERIO_8042: |
---|
1156 | 1247 | if (serio->write) |
---|
.. | .. |
---|
1186 | 1277 | atkbd->id = 0xab00; |
---|
1187 | 1278 | } |
---|
1188 | 1279 | |
---|
| 1280 | + atkbd_parse_fwnode_data(serio); |
---|
| 1281 | + |
---|
1189 | 1282 | atkbd_set_keycode_table(atkbd); |
---|
1190 | 1283 | atkbd_set_device_attrs(atkbd); |
---|
1191 | 1284 | |
---|