/*
 * HP WMI hotkeys
 *
 * Copyright (C) 2008 Red Hat <mjg@redhat.com>
 *
 * Portions based on wistron_btns.c:
 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/input.h>
#include <acpi/acpi_drivers.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
#include <linux/rfkill.h>
#include <linux/string.h>

MODULE_AUTHOR("Matthew Garrett <mjg59@srcf.ucam.org>");
MODULE_DESCRIPTION("HP laptop WMI hotkeys driver");
MODULE_LICENSE("GPL");

MODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C");
MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");

#define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C"
#define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4"

#define HPWMI_DISPLAY_QUERY 0x1
#define HPWMI_HDDTEMP_QUERY 0x2
#define HPWMI_ALS_QUERY 0x3
#define HPWMI_DOCK_QUERY 0x4
#define HPWMI_WIRELESS_QUERY 0x5
#define HPWMI_HOTKEY_QUERY 0xc

static int __init hp_wmi_bios_setup(struct platform_device *device);
static int __exit hp_wmi_bios_remove(struct platform_device *device);
static int hp_wmi_resume_handler(struct platform_device *device);

struct bios_args {
	u32 signature;
	u32 command;
	u32 commandtype;
	u32 datasize;
	u32 data;
};

struct bios_return {
	u32 sigpass;
	u32 return_code;
	u32 value;
};

struct key_entry {
	char type;		/* See KE_* below */
	u16 code;
	u16 keycode;
};

enum { KE_KEY, KE_SW, KE_END };

static struct key_entry hp_wmi_keymap[] = {
	{KE_SW, 0x01, SW_DOCK},
	{KE_KEY, 0x02, KEY_BRIGHTNESSUP},
	{KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
	{KE_KEY, 0x20e6, KEY_PROG1},
	{KE_KEY, 0x2142, KEY_MEDIA},
	{KE_KEY, 0x213b, KEY_INFO},
	{KE_KEY, 0x231b, KEY_HELP},
	{KE_END, 0}
};

static struct input_dev *hp_wmi_input_dev;
static struct platform_device *hp_wmi_platform_dev;

static struct rfkill *wifi_rfkill;
static struct rfkill *bluetooth_rfkill;
static struct rfkill *wwan_rfkill;

static struct platform_driver hp_wmi_driver = {
	.driver = {
		   .name = "hp-wmi",
		   .owner = THIS_MODULE,
	},
	.probe = hp_wmi_bios_setup,
	.remove = hp_wmi_bios_remove,
	.resume = hp_wmi_resume_handler,
};

static int hp_wmi_perform_query(int query, int write, int value)
{
	struct bios_return bios_return;
	acpi_status status;
	union acpi_object *obj;
	struct bios_args args = {
		.signature = 0x55434553,
		.command = write ? 0x2 : 0x1,
		.commandtype = query,
		.datasize = write ? 0x4 : 0,
		.data = value,
	};
	struct acpi_buffer input = { sizeof(struct bios_args), &args };
	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };

	status = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output);

	obj = output.pointer;

	if (!obj || obj->type != ACPI_TYPE_BUFFER)
		return -EINVAL;

	bios_return = *((struct bios_return *)obj->buffer.pointer);
	if (bios_return.return_code > 0)
		return bios_return.return_code * -1;
	else
		return bios_return.value;
}

static int hp_wmi_display_state(void)
{
	return hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, 0);
}

static int hp_wmi_hddtemp_state(void)
{
	return hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, 0);
}

static int hp_wmi_als_state(void)
{
	return hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, 0);
}

static int hp_wmi_dock_state(void)
{
	return hp_wmi_perform_query(HPWMI_DOCK_QUERY, 0, 0);
}

static int hp_wmi_wifi_set(void *data, enum rfkill_state state)
{
	if (state)
		return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x101);
	else
		return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x100);
}

static int hp_wmi_bluetooth_set(void *data, enum rfkill_state state)
{
	if (state)
		return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x202);
	else
		return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x200);
}

static int hp_wmi_wwan_set(void *data, enum rfkill_state state)
{
	if (state)
		return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x404);
	else
		return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, 0x400);
}

static int hp_wmi_wifi_state(void)
{
	int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);

	if (wireless & 0x100)
		return RFKILL_STATE_UNBLOCKED;
	else
		return RFKILL_STATE_SOFT_BLOCKED;
}

static int hp_wmi_bluetooth_state(void)
{
	int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);

	if (wireless & 0x10000)
		return RFKILL_STATE_UNBLOCKED;
	else
		return RFKILL_STATE_SOFT_BLOCKED;
}

static int hp_wmi_wwan_state(void)
{
	int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);

	if (wireless & 0x1000000)
		return RFKILL_STATE_UNBLOCKED;
	else
		return RFKILL_STATE_SOFT_BLOCKED;
}

static ssize_t show_display(struct device *dev, struct device_attribute *attr,
			    char *buf)
{
	int value = hp_wmi_display_state();
	if (value < 0)
		return -EINVAL;
	return sprintf(buf, "%d\n", value);
}

static ssize_t show_hddtemp(struct device *dev, struct device_attribute *attr,
			    char *buf)
{
	int value = hp_wmi_hddtemp_state();
	if (value < 0)
		return -EINVAL;
	return sprintf(buf, "%d\n", value);
}

static ssize_t show_als(struct device *dev, struct device_attribute *attr,
			char *buf)
{
	int value = hp_wmi_als_state();
	if (value < 0)
		return -EINVAL;
	return sprintf(buf, "%d\n", value);
}

static ssize_t show_dock(struct device *dev, struct device_attribute *attr,
			 char *buf)
{
	int value = hp_wmi_dock_state();
	if (value < 0)
		return -EINVAL;
	return sprintf(buf, "%d\n", value);
}

static ssize_t set_als(struct device *dev, struct device_attribute *attr,
		       const char *buf, size_t count)
{
	u32 tmp = simple_strtoul(buf, NULL, 10);
	hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, tmp);
	return count;
}

static DEVICE_ATTR(display, S_IRUGO, show_display, NULL);
static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL);
static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);

static struct key_entry *hp_wmi_get_entry_by_scancode(int code)
{
	struct key_entry *key;

	for (key = hp_wmi_keymap; key->type != KE_END; key++)
		if (code == key->code)
			return key;

	return NULL;
}

static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode)
{
	struct key_entry *key;

	for (key = hp_wmi_keymap; key->type != KE_END; key++)
		if (key->type == KE_KEY && keycode == key->keycode)
			return key;

	return NULL;
}

static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode)
{
	struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode);

	if (key && key->type == KE_KEY) {
		*keycode = key->keycode;
		return 0;
	}

	return -EINVAL;
}

static int hp_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode)
{
	struct key_entry *key;
	int old_keycode;

	if (keycode < 0 || keycode > KEY_MAX)
		return -EINVAL;

	key = hp_wmi_get_entry_by_scancode(scancode);
	if (key && key->type == KE_KEY) {
		old_keycode = key->keycode;
		key->keycode = keycode;
		set_bit(keycode, dev->keybit);
		if (!hp_wmi_get_entry_by_keycode(old_keycode))
			clear_bit(old_keycode, dev->keybit);
		return 0;
	}

	return -EINVAL;
}

static void hp_wmi_notify(u32 value, void *context)
{
	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
	static struct key_entry *key;
	union acpi_object *obj;

	wmi_get_event_data(value, &response);

	obj = (union acpi_object *)response.pointer;

	if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == 8) {
		int eventcode = *((u8 *) obj->buffer.pointer);
		if (eventcode == 0x4)
			eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
							 0);
		key = hp_wmi_get_entry_by_scancode(eventcode);
		if (key) {
			switch (key->type) {
			case KE_KEY:
				input_report_key(hp_wmi_input_dev,
						 key->keycode, 1);
				input_sync(hp_wmi_input_dev);
				input_report_key(hp_wmi_input_dev,
						 key->keycode, 0);
				input_sync(hp_wmi_input_dev);
				break;
			case KE_SW:
				input_report_switch(hp_wmi_input_dev,
						    key->keycode,
						    hp_wmi_dock_state());
				input_sync(hp_wmi_input_dev);
				break;
			}
		} else if (eventcode == 0x5) {
			if (wifi_rfkill)
				rfkill_force_state(wifi_rfkill,
						   hp_wmi_wifi_state());
			if (bluetooth_rfkill)
				rfkill_force_state(bluetooth_rfkill,
						   hp_wmi_bluetooth_state());
			if (wwan_rfkill)
				rfkill_force_state(wwan_rfkill,
						   hp_wmi_wwan_state());
		} else
			printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
			       eventcode);
	} else
		printk(KERN_INFO "HP WMI: Unknown response received\n");
}

static int __init hp_wmi_input_setup(void)
{
	struct key_entry *key;
	int err;

	hp_wmi_input_dev = input_allocate_device();

	hp_wmi_input_dev->name = "HP WMI hotkeys";
	hp_wmi_input_dev->phys = "wmi/input0";
	hp_wmi_input_dev->id.bustype = BUS_HOST;
	hp_wmi_input_dev->getkeycode = hp_wmi_getkeycode;
	hp_wmi_input_dev->setkeycode = hp_wmi_setkeycode;

	for (key = hp_wmi_keymap; key->type != KE_END; key++) {
		switch (key->type) {
		case KE_KEY:
			set_bit(EV_KEY, hp_wmi_input_dev->evbit);
			set_bit(key->keycode, hp_wmi_input_dev->keybit);
			break;
		case KE_SW:
			set_bit(EV_SW, hp_wmi_input_dev->evbit);
			set_bit(key->keycode, hp_wmi_input_dev->swbit);

			/* Set initial dock state */
			input_report_switch(hp_wmi_input_dev, key->keycode,
					    hp_wmi_dock_state());
			input_sync(hp_wmi_input_dev);
			break;
		}
	}

	err = input_register_device(hp_wmi_input_dev);

	if (err) {
		input_free_device(hp_wmi_input_dev);
		return err;
	}

	return 0;
}

static void cleanup_sysfs(struct platform_device *device)
{
	device_remove_file(&device->dev, &dev_attr_display);
	device_remove_file(&device->dev, &dev_attr_hddtemp);
	device_remove_file(&device->dev, &dev_attr_als);
	device_remove_file(&device->dev, &dev_attr_dock);
}

static int __init hp_wmi_bios_setup(struct platform_device *device)
{
	int err;
	int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);

	err = device_create_file(&device->dev, &dev_attr_display);
	if (err)
		goto add_sysfs_error;
	err = device_create_file(&device->dev, &dev_attr_hddtemp);
	if (err)
		goto add_sysfs_error;
	err = device_create_file(&device->dev, &dev_attr_als);
	if (err)
		goto add_sysfs_error;
	err = device_create_file(&device->dev, &dev_attr_dock);
	if (err)
		goto add_sysfs_error;

	if (wireless & 0x1) {
		wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN);
		wifi_rfkill->name = "hp-wifi";
		wifi_rfkill->state = hp_wmi_wifi_state();
		wifi_rfkill->toggle_radio = hp_wmi_wifi_set;
		wifi_rfkill->user_claim_unsupported = 1;
		err = rfkill_register(wifi_rfkill);
		if (err)
			goto add_sysfs_error;
	}

	if (wireless & 0x2) {
		bluetooth_rfkill = rfkill_allocate(&device->dev,
						   RFKILL_TYPE_BLUETOOTH);
		bluetooth_rfkill->name = "hp-bluetooth";
		bluetooth_rfkill->state = hp_wmi_bluetooth_state();
		bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set;
		bluetooth_rfkill->user_claim_unsupported = 1;
		err = rfkill_register(bluetooth_rfkill);
		if (err)
			goto register_bluetooth_error;
	}

	if (wireless & 0x4) {
		wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN);
		wwan_rfkill->name = "hp-wwan";
		wwan_rfkill->state = hp_wmi_wwan_state();
		wwan_rfkill->toggle_radio = hp_wmi_wwan_set;
		wwan_rfkill->user_claim_unsupported = 1;
		err = rfkill_register(wwan_rfkill);
		if (err)
			goto register_wwan_err;
	}

	return 0;
register_wwan_err:
	if (bluetooth_rfkill)
		rfkill_unregister(bluetooth_rfkill);
register_bluetooth_error:
	if (wifi_rfkill)
		rfkill_unregister(wifi_rfkill);
add_sysfs_error:
	cleanup_sysfs(device);
	return err;
}

static int __exit hp_wmi_bios_remove(struct platform_device *device)
{
	cleanup_sysfs(device);

	if (wifi_rfkill)
		rfkill_unregister(wifi_rfkill);
	if (bluetooth_rfkill)
		rfkill_unregister(bluetooth_rfkill);
	if (wwan_rfkill)
		rfkill_unregister(wwan_rfkill);

	return 0;
}

static int hp_wmi_resume_handler(struct platform_device *device)
{
	struct key_entry *key;

	/*
	 * Docking state may have changed while suspended, so trigger
	 * an input event for the current state. As this is a switch,
	 * the input layer will only actually pass it on if the state
	 * changed.
	 */
	for (key = hp_wmi_keymap; key->type != KE_END; key++) {
		switch (key->type) {
		case KE_SW:
			input_report_switch(hp_wmi_input_dev, key->keycode,
					    hp_wmi_dock_state());
			input_sync(hp_wmi_input_dev);
			break;
		}
	}

	return 0;
}

static int __init hp_wmi_init(void)
{
	int err;

	if (wmi_has_guid(HPWMI_EVENT_GUID)) {
		err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
						 hp_wmi_notify, NULL);
		if (!err)
			hp_wmi_input_setup();
	}

	if (wmi_has_guid(HPWMI_BIOS_GUID)) {
		err = platform_driver_register(&hp_wmi_driver);
		if (err)
			return 0;
		hp_wmi_platform_dev = platform_device_alloc("hp-wmi", -1);
		if (!hp_wmi_platform_dev) {
			platform_driver_unregister(&hp_wmi_driver);
			return 0;
		}
		platform_device_add(hp_wmi_platform_dev);
	}

	return 0;
}

static void __exit hp_wmi_exit(void)
{
	if (wmi_has_guid(HPWMI_EVENT_GUID)) {
		wmi_remove_notify_handler(HPWMI_EVENT_GUID);
		input_unregister_device(hp_wmi_input_dev);
	}
	if (hp_wmi_platform_dev) {
		platform_device_del(hp_wmi_platform_dev);
		platform_driver_unregister(&hp_wmi_driver);
	}
}

module_init(hp_wmi_init);
module_exit(hp_wmi_exit);
