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:
parent
401d7d108f
commit
4c076eb0cf
|
@ -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.
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue