// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  WMI hotkeys support for Dell All-In-One series
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/input.h>
#include <linux/input/sparse-keymap.h>
#include <linux/acpi.h>
#include <linux/string.h>

MODULE_DESCRIPTION("WMI hotkeys driver for Dell All-In-One series");
MODULE_LICENSE("GPL");

#define EVENT_GUID1 "284A0E6B-380E-472A-921F-E52786257FB4"
#define EVENT_GUID2 "02314822-307C-4F66-BF0E-48AEAEB26CC8"

struct dell_wmi_event {
	u16	length;
	/* 0x000: A hot key pressed or an event occurred
	 * 0x00F: A sequence of hot keys are pressed */
	u16	type;
	u16	event[];
};

static const char *dell_wmi_aio_guids[] = {
	EVENT_GUID1,
	EVENT_GUID2,
	NULL
};

MODULE_ALIAS("wmi:"EVENT_GUID1);
MODULE_ALIAS("wmi:"EVENT_GUID2);

static const struct key_entry dell_wmi_aio_keymap[] = {
	{ KE_KEY, 0xc0, { KEY_VOLUMEUP } },
	{ KE_KEY, 0xc1, { KEY_VOLUMEDOWN } },
	{ KE_KEY, 0xe030, { KEY_VOLUMEUP } },
	{ KE_KEY, 0xe02e, { KEY_VOLUMEDOWN } },
	{ KE_KEY, 0xe020, { KEY_MUTE } },
	{ KE_KEY, 0xe027, { KEY_DISPLAYTOGGLE } },
	{ KE_KEY, 0xe006, { KEY_BRIGHTNESSUP } },
	{ KE_KEY, 0xe005, { KEY_BRIGHTNESSDOWN } },
	{ KE_KEY, 0xe00b, { KEY_SWITCHVIDEOMODE } },
	{ KE_END, 0 }
};

static struct input_dev *dell_wmi_aio_input_dev;

/*
 * The new WMI event data format will follow the dell_wmi_event structure
 * So, we will check if the buffer matches the format
 */
static bool dell_wmi_aio_event_check(u8 *buffer, int length)
{
	struct dell_wmi_event *event = (struct dell_wmi_event *)buffer;

	if (event == NULL || length < 6)
		return false;

	if ((event->type == 0 || event->type == 0xf) &&
			event->length >= 2)
		return true;

	return false;
}

static void dell_wmi_aio_notify(union acpi_object *obj, void *context)
{
	struct dell_wmi_event *event;

	if (obj) {
		unsigned int scancode = 0;

		switch (obj->type) {
		case ACPI_TYPE_INTEGER:
			/* Most All-In-One correctly return integer scancode */
			scancode = obj->integer.value;
			sparse_keymap_report_event(dell_wmi_aio_input_dev,
				scancode, 1, true);
			break;
		case ACPI_TYPE_BUFFER:
			if (dell_wmi_aio_event_check(obj->buffer.pointer,
						obj->buffer.length)) {
				event = (struct dell_wmi_event *)
					obj->buffer.pointer;
				scancode = event->event[0];
			} else {
				/* Broken machines return the scancode in a
				   buffer */
				if (obj->buffer.pointer &&
						obj->buffer.length > 0)
					scancode = obj->buffer.pointer[0];
			}
			if (scancode)
				sparse_keymap_report_event(
					dell_wmi_aio_input_dev,
					scancode, 1, true);
			break;
		}
	}
}

static int __init dell_wmi_aio_input_setup(void)
{
	int err;

	dell_wmi_aio_input_dev = input_allocate_device();

	if (!dell_wmi_aio_input_dev)
		return -ENOMEM;

	dell_wmi_aio_input_dev->name = "Dell AIO WMI hotkeys";
	dell_wmi_aio_input_dev->phys = "wmi/input0";
	dell_wmi_aio_input_dev->id.bustype = BUS_HOST;

	err = sparse_keymap_setup(dell_wmi_aio_input_dev,
			dell_wmi_aio_keymap, NULL);
	if (err) {
		pr_err("Unable to setup input device keymap\n");
		goto err_free_dev;
	}
	err = input_register_device(dell_wmi_aio_input_dev);
	if (err) {
		pr_info("Unable to register input device\n");
		goto err_free_dev;
	}
	return 0;

err_free_dev:
	input_free_device(dell_wmi_aio_input_dev);
	return err;
}

static const char *dell_wmi_aio_find(void)
{
	int i;

	for (i = 0; dell_wmi_aio_guids[i] != NULL; i++)
		if (wmi_has_guid(dell_wmi_aio_guids[i]))
			return dell_wmi_aio_guids[i];

	return NULL;
}

static int __init dell_wmi_aio_init(void)
{
	int err;
	const char *guid;

	guid = dell_wmi_aio_find();
	if (!guid) {
		pr_warn("No known WMI GUID found\n");
		return -ENXIO;
	}

	err = dell_wmi_aio_input_setup();
	if (err)
		return err;

	err = wmi_install_notify_handler(guid, dell_wmi_aio_notify, NULL);
	if (err) {
		pr_err("Unable to register notify handler - %d\n", err);
		input_unregister_device(dell_wmi_aio_input_dev);
		return err;
	}

	return 0;
}

static void __exit dell_wmi_aio_exit(void)
{
	const char *guid;

	guid = dell_wmi_aio_find();
	wmi_remove_notify_handler(guid);
	input_unregister_device(dell_wmi_aio_input_dev);
}

module_init(dell_wmi_aio_init);
module_exit(dell_wmi_aio_exit);
