// 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(u32 value, void *context)
{
	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
	union acpi_object *obj;
	struct dell_wmi_event *event;
	acpi_status status;

	status = wmi_get_event_data(value, &response);
	if (status != AE_OK) {
		pr_info("bad event status 0x%x\n", status);
		return;
	}

	obj = (union acpi_object *)response.pointer;
	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;
		}
	}
	kfree(obj);
}

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);
