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

Unverified Commit 9e6fdda0 authored by derfelot's avatar derfelot
Browse files

misc: Force a crash on powerkey long press as in Sony kernel

Taken from Sony 47.2.A.10.107 stock kernel
parent 070bf821
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -605,6 +605,13 @@ config RAMDUMP_MEMDESC
	  and split the contents and exports it as /proc/mem_desc
	  in Ramdump mode to support ramdump functionality

config POWERKEY_FORCECRASH
	tristate "Force a crash on powerkey long press"
	default n
	help
	  Say Y here if you want force crash functionality through power
	  key. Triggers panic if power key is hold for more than 10secs.

config NFC_PN553_DEVICES
	tristate "Nxp pn553 NCI protocol driver (I2C) devices"
	default y
+1 −0
Original line number Diff line number Diff line
@@ -72,4 +72,5 @@ obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o
obj-$(CONFIG_LDO_VIBRATOR) += ldo_vibrator.o
obj-$(CONFIG_RAMDUMP_TAGS) += rdtags.o
obj-$(CONFIG_RAMDUMP_MEMDESC) += ramdump_mem_desc.o
obj-$(CONFIG_POWERKEY_FORCECRASH) += powerkey_forcecrash.o
obj-$(CONFIG_MMTUNER_MN8855x) += mm_tuner/
+168 −0
Original line number Diff line number Diff line
/*
 *  drivers/misc/powerkey_forcecrash.c
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
/*
 * Copyright (C) 2015 Sony Mobile Communications Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2, as
 * published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <linux/wakelock.h>

#define FORCE_CRASH_TIMEOUT 10
static struct timer_list forcecrash_timer;

#define PKEY_FORCECRASH_DEV_NAME "powerkey_forcecrash"
static struct wake_lock powerkey_lock;

static int forcecrash_on;
module_param(forcecrash_on, int, S_IRUGO | S_IWUSR);

static void forcecrash_timeout(unsigned long data)
{
	panic("Force crash triggered!!!\n");
}

static void forcecrash_timer_setup(bool key_pressed)
{
	if (!forcecrash_on)
		return;

	if (key_pressed) {
		pr_debug("Power key pressed..\n");
		mod_timer(&forcecrash_timer,
				jiffies + FORCE_CRASH_TIMEOUT * HZ);
		wake_lock(&powerkey_lock);
	} else {
		pr_debug("released.\n");
		del_timer(&forcecrash_timer);
		wake_unlock(&powerkey_lock);
	}
}

static void powerkey_input_event(struct input_handle *handle, unsigned int type,
		unsigned int code, int value)
{
	switch (code) {
	case KEY_POWER:
		forcecrash_timer_setup(value);
		break;
	default:
		break;
	}
}

static const char *powerkey_match_tbl[] = {
	"qpnp_pon",
	NULL
};

static bool powerkey_input_match(struct input_handler *handler,
		struct input_dev *dev)
{
	const char *match = powerkey_match_tbl[0];

	while (*match) {
		size_t len = strlen(match);
		if (!strncmp(dev->name, match, len))
			return true;
		match++;
	}

	pr_info("Ignoring %s handle for %s\n", handler->name, dev->name);

	return false;
}

static int powerkey_input_connect(struct input_handler *handler,
		struct input_dev *dev, const struct input_device_id *id)
{
	struct input_handle *handle;
	int error;

	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
	if (!handle)
		return -ENOMEM;

	handle->dev = dev;
	handle->handler = handler;
	handle->name = "powerkey_handle";
	pr_info("registering %s handle for %s\n", handle->name, dev->name);

	error = input_register_handle(handle);
	if (error)
		goto err2;

	error = input_open_device(handle);
	if (error)
		goto err1;

	return 0;
err1:
	input_unregister_handle(handle);
err2:
	kfree(handle);
	return error;
}

static void powerkey_input_disconnect(struct input_handle *handle)
{
	input_close_device(handle);
	input_unregister_handle(handle);
	kfree(handle);
}

static const struct input_device_id input_dev_ids[] = {
	/* Only Powerkey inputs */
	{
		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
		.evbit = { BIT_MASK(EV_KEY) },
		.keybit = { [BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER) },
	},
	{ },
};

static struct input_handler powerkey_input_handler = {
	.event		= powerkey_input_event,
	.match		= powerkey_input_match,
	.connect	= powerkey_input_connect,
	.disconnect	= powerkey_input_disconnect,
	.name		= "powerkey_handler",
	.id_table	= input_dev_ids,
};

static int __init powerkey_forcecrash_init(void)
{
	init_timer(&forcecrash_timer);
	forcecrash_timer.function = forcecrash_timeout;
	wake_lock_init(&powerkey_lock, WAKE_LOCK_SUSPEND,
			PKEY_FORCECRASH_DEV_NAME);
	return input_register_handler(&powerkey_input_handler);
}

static void __exit powerkey_forcecrash_exit(void)
{
	del_timer(&forcecrash_timer);
	wake_lock_destroy(&powerkey_lock);
	input_unregister_handler(&powerkey_input_handler);
}

module_init(powerkey_forcecrash_init);
module_exit(powerkey_forcecrash_exit);

MODULE_AUTHOR("Srinivasa Nagaraju <srinavasa.x.nagaraju@sonymobile.com>");
MODULE_DESCRIPTION("Force crash on power key long press of 10 secs");
MODULE_LICENSE("GPL V2");