@@ -65,6 +65,10 @@ static bool atkbd_terminal;
module_param_named(terminal, atkbd_terminal, bool, 0);
MODULE_PARM_DESC(terminal, "Enable break codes on an IBM Terminal keyboard connected via AT/PS2");
+static int atkbd_skip_commands;
+module_param_named(skip_commands, atkbd_skip_commands, int, 0444);
+MODULE_PARM_DESC(skip_commands, "Bitfield where each bits skips a specific keyboard cmd (0 - 0x3f)");
+
#define SCANCODE(keymap) ((keymap >> 16) & 0xFFFF)
#define KEYCODE(keymap) (keymap & 0xFFFF)
@@ -182,6 +186,13 @@ static const unsigned short atkbd_unxlate_table[128] = {
#define ATKBD_XL_HANGEUL 0x10
#define ATKBD_XL_HANJA 0x20
+#define ATKBD_SKIP_GETID 0x01l
+#define ATKBD_SKIP_ACTIVATE 0x02l
+#define ATKBD_SKIP_DEACTIVATE 0x04l
+#define ATKBD_SKIP_SETREP 0x08l
+#define ATKBD_SKIP_SETLEDS 0x10l
+#define ATKBD_SKIP_RESET_DEF 0x20l
+
static const struct {
unsigned short keycode;
unsigned char set2;
@@ -592,6 +603,9 @@ static int atkbd_set_repeat_rate(struct atkbd *atkbd)
unsigned char param;
int i = 0, j = 0;
+ if (atkbd_skip_commands & ATKBD_SKIP_SETREP)
+ return 0;
+
while (i < ARRAY_SIZE(period) - 1 && period[i] < dev->rep[REP_PERIOD])
i++;
dev->rep[REP_PERIOD] = period[i];
@@ -609,6 +623,9 @@ static int atkbd_set_leds(struct atkbd *atkbd)
struct input_dev *dev = atkbd->dev;
unsigned char param[2];
+ if (atkbd_skip_commands & ATKBD_SKIP_SETLEDS)
+ return 0;
+
param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0)
| (test_bit(LED_NUML, dev->led) ? 2 : 0)
| (test_bit(LED_CAPSL, dev->led) ? 4 : 0);
@@ -736,6 +753,9 @@ static int atkbd_activate(struct atkbd *atkbd)
{
struct ps2dev *ps2dev = &atkbd->ps2dev;
+ if (atkbd_skip_commands & ATKBD_SKIP_ACTIVATE)
+ return 0;
+
/*
* Enable the keyboard to receive keystrokes.
*/
@@ -759,6 +779,9 @@ static void atkbd_deactivate(struct atkbd *atkbd)
{
struct ps2dev *ps2dev = &atkbd->ps2dev;
+ if (atkbd_skip_commands & ATKBD_SKIP_DEACTIVATE)
+ return;
+
if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_DIS))
dev_err(&ps2dev->serio->dev,
"Failed to deactivate keyboard on %s\n",
@@ -786,6 +809,13 @@ static int atkbd_probe(struct atkbd *atkbd)
"keyboard reset failed on %s\n",
ps2dev->serio->phys);
+/* Only skip probe for translated keyboards to avoid mis-identifying mice */
+ if (atkbd->translated && (atkbd_skip_commands & ATKBD_SKIP_GETID)) {
+ atkbd->id = 0xab00;
+ atkbd_deactivate(atkbd);
+ return 0;
+ }
+
/*
* Then we check the keyboard ID. We should get 0xab83 under normal conditions.
* Some keyboards report different values, but the first byte is always 0xab or
@@ -802,7 +832,8 @@ static int atkbd_probe(struct atkbd *atkbd)
* the LEDs off, which we want anyway.
*/
param[0] = 0;
- if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
+ if (!(atkbd_skip_commands & ATKBD_SKIP_SETLEDS) &&
+ ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
return -1;
atkbd->id = 0xabba;
return 0;
@@ -906,17 +937,21 @@ static int atkbd_reset_state(struct atkbd *atkbd)
* Set the LEDs to a predefined state (all off).
*/
- param[0] = 0;
- if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
- return -1;
+ if (!(atkbd_skip_commands & ATKBD_SKIP_SETLEDS)) {
+ param[0] = 0;
+ if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
+ return -1;
+ }
/*
* Set autorepeat to fastest possible.
*/
- param[0] = 0;
- if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP))
- return -1;
+ if (!(atkbd_skip_commands & ATKBD_SKIP_SETREP)) {
+ param[0] = 0;
+ if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP))
+ return -1;
+ }
return 0;
}
@@ -931,7 +966,8 @@ static void atkbd_cleanup(struct serio *serio)
struct atkbd *atkbd = atkbd_from_serio(serio);
atkbd_disable(atkbd);
- ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_DEF);
+ if (!(atkbd_skip_commands & ATKBD_SKIP_RESET_DEF))
+ ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_DEF);
}
While debugging a keyboard issue on some HP laptops (see link) adding i8042.dumbkbd helped to avoid the issue. So one of the commands send by atkbd.c seemed to be the culprit. Add a skip_commands option to help debug cases like this by adding a bit-field which allows disabling a subset of the ps2_command() calls the atkbd driver makes. This also avoids the need to add special flags for each command which atkbd needs to skip on certain models, like e.g. the existing atkbd_skip_deactivate flag. Link: https://bugzilla.redhat.com/show_bug.cgi?id=2086156 Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- The next patch in this series replaces the atkbd_skip_deactivate flag with using atbkd_skip_commands to avoid having 2 deactivate skip checks. --- drivers/input/keyboard/atkbd.c | 52 ++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 8 deletions(-)