@@ -363,6 +363,43 @@ static void to_utf8(struct vc_data *vc, uint c)
}
}
+#ifdef CONFIG_KDB_KEYBOARD
+static int kbd_clear_keys_helper(struct input_handle *handle, void *data)
+{
+ unsigned int *keycode = data;
+ input_inject_event(handle, EV_KEY, *keycode, 0);
+ return 0;
+}
+
+static void kbd_clear_keys_callback(struct work_struct *dummy)
+{
+ unsigned int i, j, k;
+
+ for (i = 0; i < ARRAY_SIZE(key_down); i++) {
+ if (!key_down[i])
+ continue;
+
+ k = i * BITS_PER_LONG;
+
+ for (j = 0; j < BITS_PER_LONG; j++, k++) {
+ if (!test_bit(k, key_down))
+ continue;
+ input_handler_for_each_handle(&kbd_handler, &k,
+ kbd_clear_keys_helper);
+ }
+ }
+}
+
+static DECLARE_WORK(kbd_clear_keys_work, kbd_clear_keys_callback);
+
+/* Called to clear any key presses after resuming the kernel. */
+void kbd_dbg_clear_keys(void)
+{
+ schedule_work(&kbd_clear_keys_work);
+}
+EXPORT_SYMBOL_GPL(kbd_dbg_clear_keys);
+#endif /* CONFIG_KDB_KEYBOARD */
+
/*
* Called after returning from RAW mode or when changing consoles - recompute
* shift_down[] and shift_state from key_down[] maybe called when keymap is
@@ -18,6 +18,7 @@
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/vt_kern.h>
+#include <linux/kbd_kern.h>
#define MAX_CONFIG_LEN 40
@@ -37,12 +38,16 @@ static struct tty_driver *kgdb_tty_driver;
static int kgdb_tty_line;
#ifdef CONFIG_KDB_KEYBOARD
+static bool kgdboc_use_kbd;
+
static int kgdboc_register_kbd(char **cptr)
{
+ kgdboc_use_kbd = false;
if (strncmp(*cptr, "kbd", 3) == 0) {
if (kdb_poll_idx < KDB_POLL_FUNC_MAX) {
kdb_poll_funcs[kdb_poll_idx] = kdb_get_kbd_char;
kdb_poll_idx++;
+ kgdboc_use_kbd = true;
if (cptr[0][3] == ',')
*cptr += 4;
else
@@ -65,9 +70,16 @@ static void kgdboc_unregister_kbd(void)
}
}
}
+
+static inline void kgdboc_clear_kbd(void)
+{
+ if (kgdboc_use_kbd)
+ kbd_dbg_clear_keys(); /* Release all pressed keys */
+}
#else /* ! CONFIG_KDB_KEYBOARD */
#define kgdboc_register_kbd(x) 0
#define kgdboc_unregister_kbd()
+#define kgdboc_clear_kbd()
#endif /* ! CONFIG_KDB_KEYBOARD */
static int kgdboc_option_setup(char *opt)
@@ -231,6 +243,7 @@ static void kgdboc_post_exp_handler(void)
dbg_restore_graphics = 0;
con_debug_leave();
}
+ kgdboc_clear_kbd();
}
static struct kgdb_io kgdboc_io_ops = {
@@ -144,6 +144,7 @@ struct console;
int getkeycode(unsigned int scancode);
int setkeycode(unsigned int scancode, unsigned int keycode);
void compute_shiftstate(void);
+void kbd_dbg_clear_keys(void);
/* defkeymap.c */