/*
 * PEAQ 2-in-1 WMI hotkey driver
 * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
 *
 * 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/acpi.h>
#include <linux/input-polldev.h>
#include <linux/kernel.h>
#include <linux/module.h>

#define PEAQ_DOLBY_BUTTON_GUID		"ABBC0F6F-8EA1-11D1-00A0-C90629100000"
#define PEAQ_DOLBY_BUTTON_METHOD_ID	5
#define PEAQ_POLL_INTERVAL_MS		250
#define PEAQ_POLL_IGNORE_MS		500
#define PEAQ_POLL_MAX_MS		1000

MODULE_ALIAS("wmi:"PEAQ_DOLBY_BUTTON_GUID);

static unsigned int peaq_ignore_events_counter;
static struct input_polled_dev *peaq_poll_dev;

/*
 * The Dolby button (yes really a Dolby button) causes an ACPI variable to get
 * set on both press and release. The WMI method checks and clears that flag.
 * So for a press + release we will get back One from the WMI method either once
 * (if polling after the release) or twice (polling between press and release).
 * We ignore events for 0.5s after the first event to avoid reporting 2 presses.
 */
static void peaq_wmi_poll(struct input_polled_dev *dev)
{
	union acpi_object obj;
	acpi_status status;
	u32 dummy = 0;

	struct acpi_buffer input = { sizeof(dummy), &dummy };
	struct acpi_buffer output = { sizeof(obj), &obj };

	status = wmi_evaluate_method(PEAQ_DOLBY_BUTTON_GUID, 0,
				     PEAQ_DOLBY_BUTTON_METHOD_ID,
				     &input, &output);
	if (ACPI_FAILURE(status))
		return;

	if (obj.type != ACPI_TYPE_INTEGER) {
		dev_err(&peaq_poll_dev->input->dev,
			"Error WMBC did not return an integer\n");
		return;
	}

	if (peaq_ignore_events_counter && peaq_ignore_events_counter--)
		return;

	if (obj.integer.value) {
		input_event(peaq_poll_dev->input, EV_KEY, KEY_SOUND, 1);
		input_sync(peaq_poll_dev->input);
		input_event(peaq_poll_dev->input, EV_KEY, KEY_SOUND, 0);
		input_sync(peaq_poll_dev->input);
		peaq_ignore_events_counter = max(1u,
			PEAQ_POLL_IGNORE_MS / peaq_poll_dev->poll_interval);
	}
}

static int __init peaq_wmi_init(void)
{
	if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID))
		return -ENODEV;

	peaq_poll_dev = input_allocate_polled_device();
	if (!peaq_poll_dev)
		return -ENOMEM;

	peaq_poll_dev->poll = peaq_wmi_poll;
	peaq_poll_dev->poll_interval = PEAQ_POLL_INTERVAL_MS;
	peaq_poll_dev->poll_interval_max = PEAQ_POLL_MAX_MS;
	peaq_poll_dev->input->name = "PEAQ WMI hotkeys";
	peaq_poll_dev->input->phys = "wmi/input0";
	peaq_poll_dev->input->id.bustype = BUS_HOST;
	input_set_capability(peaq_poll_dev->input, EV_KEY, KEY_SOUND);

	return input_register_polled_device(peaq_poll_dev);
}

static void __exit peaq_wmi_exit(void)
{
	if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID))
		return;

	input_unregister_polled_device(peaq_poll_dev);
}

module_init(peaq_wmi_init);
module_exit(peaq_wmi_exit);

MODULE_DESCRIPTION("PEAQ 2-in-1 WMI hotkey driver");
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
MODULE_LICENSE("GPL");
