aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorShawn Nematbakhsh <shawnn@chromium.org>2012-12-31 15:53:35 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-01-21 20:31:40 -0500
commitbe2d7e4233a4fe439125b825470020cef83407d5 (patch)
treef7c8b61c3e66070d0b3a44cb5498effcb268b2f4 /drivers/input
parent4a31ba37b7ed39c9c7178da6e6df7bce63ffc56f (diff)
Input: atkbd - fix multi-byte scancode handling on reconnect
On resume from suspend there is a possibility for multi-byte scancodes to be handled incorrectly. atkbd_reconnect disables the processing of scancodes in software by calling atkbd_disable, but the keyboard may still be active because no disconnect command was sent. Later, software handling is re-enabled. If a multi-byte scancode sent from the keyboard straddles the re-enable, only the latter byte(s) will be handled. In practice, this leads to cases where multi-byte break codes (ex. "e0 4d" - break code for right-arrow) are misread as make codes ("4d" - make code for numeric 6), leading to one or more unwanted, untyped characters being interpreted. The solution implemented here involves sending command f5 (reset disable) to the keyboard prior to disabling software handling of codes. Later, the command to re-enable the keyboard is sent only after we are prepared to handle scancodes. Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/keyboard/atkbd.c72
1 files changed, 51 insertions, 21 deletions
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 33d0fcde441c..2626773ff29b 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -676,6 +676,39 @@ static inline void atkbd_disable(struct atkbd *atkbd)
676 serio_continue_rx(atkbd->ps2dev.serio); 676 serio_continue_rx(atkbd->ps2dev.serio);
677} 677}
678 678
679static int atkbd_activate(struct atkbd *atkbd)
680{
681 struct ps2dev *ps2dev = &atkbd->ps2dev;
682
683/*
684 * Enable the keyboard to receive keystrokes.
685 */
686
687 if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) {
688 dev_err(&ps2dev->serio->dev,
689 "Failed to enable keyboard on %s\n",
690 ps2dev->serio->phys);
691 return -1;
692 }
693
694 return 0;
695}
696
697/*
698 * atkbd_deactivate() resets and disables the keyboard from sending
699 * keystrokes.
700 */
701
702static void atkbd_deactivate(struct atkbd *atkbd)
703{
704 struct ps2dev *ps2dev = &atkbd->ps2dev;
705
706 if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_DIS))
707 dev_err(&ps2dev->serio->dev,
708 "Failed to deactivate keyboard on %s\n",
709 ps2dev->serio->phys);
710}
711
679/* 712/*
680 * atkbd_probe() probes for an AT keyboard on a serio port. 713 * atkbd_probe() probes for an AT keyboard on a serio port.
681 */ 714 */
@@ -731,6 +764,12 @@ static int atkbd_probe(struct atkbd *atkbd)
731 return -1; 764 return -1;
732 } 765 }
733 766
767/*
768 * Make sure nothing is coming from the keyboard and disturbs our
769 * internal state.
770 */
771 atkbd_deactivate(atkbd);
772
734 return 0; 773 return 0;
735} 774}
736 775
@@ -825,24 +864,6 @@ static int atkbd_reset_state(struct atkbd *atkbd)
825 return 0; 864 return 0;
826} 865}
827 866
828static int atkbd_activate(struct atkbd *atkbd)
829{
830 struct ps2dev *ps2dev = &atkbd->ps2dev;
831
832/*
833 * Enable the keyboard to receive keystrokes.
834 */
835
836 if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) {
837 dev_err(&ps2dev->serio->dev,
838 "Failed to enable keyboard on %s\n",
839 ps2dev->serio->phys);
840 return -1;
841 }
842
843 return 0;
844}
845
846/* 867/*
847 * atkbd_cleanup() restores the keyboard state so that BIOS is happy after a 868 * atkbd_cleanup() restores the keyboard state so that BIOS is happy after a
848 * reboot. 869 * reboot.
@@ -1150,7 +1171,6 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
1150 1171
1151 atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra); 1172 atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
1152 atkbd_reset_state(atkbd); 1173 atkbd_reset_state(atkbd);
1153 atkbd_activate(atkbd);
1154 1174
1155 } else { 1175 } else {
1156 atkbd->set = 2; 1176 atkbd->set = 2;
@@ -1165,6 +1185,8 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
1165 goto fail3; 1185 goto fail3;
1166 1186
1167 atkbd_enable(atkbd); 1187 atkbd_enable(atkbd);
1188 if (serio->write)
1189 atkbd_activate(atkbd);
1168 1190
1169 err = input_register_device(atkbd->dev); 1191 err = input_register_device(atkbd->dev);
1170 if (err) 1192 if (err)
@@ -1208,8 +1230,6 @@ static int atkbd_reconnect(struct serio *serio)
1208 if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra)) 1230 if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra))
1209 goto out; 1231 goto out;
1210 1232
1211 atkbd_activate(atkbd);
1212
1213 /* 1233 /*
1214 * Restore LED state and repeat rate. While input core 1234 * Restore LED state and repeat rate. While input core
1215 * will do this for us at resume time reconnect may happen 1235 * will do this for us at resume time reconnect may happen
@@ -1223,7 +1243,17 @@ static int atkbd_reconnect(struct serio *serio)
1223 1243
1224 } 1244 }
1225 1245
1246 /*
1247 * Reset our state machine in case reconnect happened in the middle
1248 * of multi-byte scancode.
1249 */
1250 atkbd->xl_bit = 0;
1251 atkbd->emul = 0;
1252
1226 atkbd_enable(atkbd); 1253 atkbd_enable(atkbd);
1254 if (atkbd->write)
1255 atkbd_activate(atkbd);
1256
1227 retval = 0; 1257 retval = 0;
1228 1258
1229 out: 1259 out: