Commit 907e4b7b authored by Andries E. Brouwer's avatar Andries E. Brouwer Committed by Linus Torvalds

[PATCH] another keyboard problem solved

A colleague reported that the keyboard of his brandnew laptop
is dead under 2.6 while 2.4 works.

Now I once wrote

  In order to avoid interference between scancode sequences
  or mouse packets and the reponses given to commands,
  the keyboard or mouse should always be disabled before
  giving a command that requires a response, and probably
  enabled afterwards. Some keyboards or mice do the disable
  automatically in this situation, but still require an
  explicit enable afterwards. 

(http://www.win.tue.nl/~aeb/linux/kbd/scancodes-9.html)

This is what happens on this laptop. The routine atkbd_probe()
probes for a keyboard, and after detecting it, enables it.
But immediately afterwards the routine atkbd_set_3() reads
the current scancode set and sets the desired set, and as a
side effect of these commands, the keyboard gets disabled again.

Thus, the keyboard enable must be moved after all command sending
has been done.

Now that I patch this area anyway: we are almost always in
scancode set 2 but send the ATKBD_CMD_SETALL_MB command
that only works in scancode set 3. At best this is useless.
At worst it confuses the keyboard. So, I put this command
in a separate routine and call that only when we really
are in scancode set 3.
parent 71d1c9ff
...@@ -321,6 +321,16 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co ...@@ -321,6 +321,16 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
return -1; return -1;
} }
/*
* Enable keyboard.
*/
static void atkbd_enable(struct atkbd *atkbd)
{
if (atkbd_command(atkbd, NULL, ATKBD_CMD_ENABLE))
printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n",
atkbd->serio->phys);
}
/* /*
* atkbd_set_3 checks if a keyboard has a working Set 3 support, and * atkbd_set_3 checks if a keyboard has a working Set 3 support, and
* sets it into that. Unfortunately there are keyboards that can be switched * sets it into that. Unfortunately there are keyboards that can be switched
...@@ -399,7 +409,9 @@ static int atkbd_probe(struct atkbd *atkbd) ...@@ -399,7 +409,9 @@ static int atkbd_probe(struct atkbd *atkbd)
if (atkbd_reset) if (atkbd_reset)
if (atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_BAT)) if (atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_BAT))
printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", atkbd->serio->phys); printk(KERN_WARNING
"atkbd.c: keyboard reset failed on %s\n",
atkbd->serio->phys);
/* /*
* Then we check the keyboard ID. We should get 0xab83 under normal conditions. * Then we check the keyboard ID. We should get 0xab83 under normal conditions.
...@@ -433,24 +445,20 @@ static int atkbd_probe(struct atkbd *atkbd) ...@@ -433,24 +445,20 @@ static int atkbd_probe(struct atkbd *atkbd)
if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS)) if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS))
return -1; return -1;
return 0;
}
/* /*
* Disable autorepeat. We don't need it, as we do it in software anyway, * Disable autorepeat. We don't need it, as we do it in software anyway,
* because that way can get faster repeat, and have less system load (less * because that way can get faster repeat, and have less system load (less
* accesses to the slow ISA hardware). If this fails, we don't care, and will * accesses to the slow ISA hardware). If this fails, we don't care, and will
* just ignore the repeated keys. * just ignore the repeated keys.
*
* This command is for scancode set 3 only.
*/ */
static void atkbd_disable_autorepeat(struct atkbd *atkbd)
{
atkbd_command(atkbd, NULL, ATKBD_CMD_SETALL_MB); atkbd_command(atkbd, NULL, ATKBD_CMD_SETALL_MB);
/*
* Last, we enable the keyboard to make sure that we get keypresses from it.
*/
if (atkbd_command(atkbd, NULL, ATKBD_CMD_ENABLE))
printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n",
atkbd->serio->phys);
return 0;
} }
/* /*
...@@ -477,7 +485,7 @@ static void atkbd_disconnect(struct serio *serio) ...@@ -477,7 +485,7 @@ static void atkbd_disconnect(struct serio *serio)
} }
/* /*
* atkbd_connect() is called when the serio module finds and interface * atkbd_connect() is called when the serio module finds an interface
* that isn't handled yet by an appropriate device driver. We check if * that isn't handled yet by an appropriate device driver. We check if
* there is an AT keyboard out there and if yes, we register ourselves * there is an AT keyboard out there and if yes, we register ourselves
* to the input module. * to the input module.
...@@ -531,7 +539,9 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev) ...@@ -531,7 +539,9 @@ static void atkbd_connect(struct serio *serio, struct serio_dev *dev)
} }
atkbd->set = atkbd_set_3(atkbd); atkbd->set = atkbd_set_3(atkbd);
if (atkbd->set == 3)
atkbd_disable_autorepeat(atkbd);
atkbd_enable(atkbd);
} else { } else {
atkbd->set = 2; atkbd->set = 2;
atkbd->id = 0xab00; atkbd->id = 0xab00;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment