Input: sysrq - DT binding for key sequence

Adding a simple device tree binding for the specification of key
sequences. Definition of the keys found in the sequence are located in
'include/uapi/linux/input.h'.

For the sysrq driver, holding the sequence of keys down for a specific
amount of time will reset the system.

Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Acked-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
This commit is contained in:
Mathieu J. Poirier 2013-08-03 17:22:08 -07:00 committed by Dmitry Torokhov
parent 401d7d108f
commit 4c076eb0cf
2 changed files with 75 additions and 0 deletions

View File

@ -0,0 +1,33 @@
Input: sysrq reset sequence
A simple binding to represent a set of keys as described in
include/uapi/linux/input.h. This is to communicate a sequence of keys to the
sysrq driver. Upon holding the keys for a specified amount of time (if
specified) the system is sync'ed and reset.
Key sequences are global to the system but all the keys in a set must be coming
from the same input device.
The /chosen node should contain a 'linux,sysrq-reset-seq' child node to define
a set of keys.
Required property:
sysrq-reset-seq: array of Linux keycodes, one keycode per cell.
Optional property:
timeout-ms: duration keys must be pressed together in milliseconds before
generating a sysrq. If omitted the system is rebooted immediately when a valid
sequence has been recognized.
Example:
chosen {
linux,sysrq-reset-seq {
keyset = <0x03
0x04
0x0a>;
timeout-ms = <3000>;
};
};
Would represent KEY_2, KEY_3 and KEY_9.

View File

@ -45,6 +45,7 @@
#include <linux/moduleparam.h>
#include <linux/jiffies.h>
#include <linux/syscalls.h>
#include <linux/of.h>
#include <asm/ptrace.h>
#include <asm/irq_regs.h>
@ -681,6 +682,40 @@ static void sysrq_detect_reset_sequence(struct sysrq_state *state,
}
}
#ifdef CONFIG_OF
static void sysrq_of_get_keyreset_config(void)
{
u32 key;
struct device_node *np;
struct property *prop;
const __be32 *p;
np = of_find_node_by_path("/chosen/linux,sysrq-reset-seq");
if (!np) {
pr_debug("No sysrq node found");
return;
}
/* Reset in case a __weak definition was present */
sysrq_reset_seq_len = 0;
of_property_for_each_u32(np, "keyset", prop, p, key) {
if (key == KEY_RESERVED || key > KEY_MAX ||
sysrq_reset_seq_len == SYSRQ_KEY_RESET_MAX)
break;
sysrq_reset_seq[sysrq_reset_seq_len++] = (unsigned short)key;
}
/* Get reset timeout if any. */
of_property_read_u32(np, "timeout-ms", &sysrq_reset_downtime_ms);
}
#else
static void sysrq_of_get_keyreset_config(void)
{
}
#endif
static void sysrq_reinject_alt_sysrq(struct work_struct *work)
{
struct sysrq_state *sysrq =
@ -914,6 +949,7 @@ static inline void sysrq_register_handler(void)
int error;
int i;
/* First check if a __weak interface was instantiated. */
for (i = 0; i < ARRAY_SIZE(sysrq_reset_seq); i++) {
key = platform_sysrq_reset_seq[i];
if (key == KEY_RESERVED || key > KEY_MAX)
@ -922,6 +958,12 @@ static inline void sysrq_register_handler(void)
sysrq_reset_seq[sysrq_reset_seq_len++] = key;
}
/*
* DT configuration takes precedence over anything that would
* have been defined via the __weak interface.
*/
sysrq_of_get_keyreset_config();
error = input_register_handler(&sysrq_handler);
if (error)
pr_err("Failed to register input handler, error %d", error);