Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4c076eb0 authored by Mathieu J. Poirier's avatar Mathieu J. Poirier Committed by Dmitry Torokhov
Browse files

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: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Acked-by: default avatarGrant Likely <grant.likely@linaro.org>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 401d7d10
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
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.
+42 −0
Original line number Diff line number Diff line
@@ -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);