/*
 *  HID driver for eGalax dual-touch panels
 *
 *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
 *
 */

/*
 * 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.
 */

#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/slab.h>
#include "usbhid/usbhid.h"

MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
MODULE_DESCRIPTION("eGalax dual-touch panel");
MODULE_LICENSE("GPL");

#include "hid-ids.h"

struct egalax_data {
	__u16 x, y, z;
	__u8 id;
	bool first;		/* is this the first finger in the frame? */
	bool valid;		/* valid finger data, or just placeholder? */
	bool activity;		/* at least one active finger previously? */
	__u16 lastx, lasty, lastz;	/* latest valid (x, y, z) in the frame */
};

static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
		struct hid_field *field, struct hid_usage *usage,
		unsigned long **bit, int *max)
{
	switch (usage->hid & HID_USAGE_PAGE) {

	case HID_UP_GENDESK:
		switch (usage->hid) {
		case HID_GD_X:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_POSITION_X);
			/* touchscreen emulation */
			input_set_abs_params(hi->input, ABS_X,
						field->logical_minimum,
						field->logical_maximum, 0, 0);
			return 1;
		case HID_GD_Y:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_POSITION_Y);
			/* touchscreen emulation */
			input_set_abs_params(hi->input, ABS_Y,
						field->logical_minimum,
						field->logical_maximum, 0, 0);
			return 1;
		}
		return 0;

	case HID_UP_DIGITIZER:
		switch (usage->hid) {
		case HID_DG_TIPSWITCH:
			/* touchscreen emulation */
			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
			return 1;
		case HID_DG_INRANGE:
		case HID_DG_CONFIDENCE:
		case HID_DG_CONTACTCOUNT:
		case HID_DG_CONTACTMAX:
			return -1;
		case HID_DG_CONTACTID:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_TRACKING_ID);
			return 1;
		case HID_DG_TIPPRESSURE:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_PRESSURE);
			/* touchscreen emulation */
			input_set_abs_params(hi->input, ABS_PRESSURE,
						field->logical_minimum,
						field->logical_maximum, 0, 0);
			return 1;
		}
		return 0;
	}

	/* ignore others (from other reports we won't get anyway) */
	return -1;
}

static int egalax_input_mapped(struct hid_device *hdev, struct hid_input *hi,
		struct hid_field *field, struct hid_usage *usage,
		unsigned long **bit, int *max)
{
	if (usage->type == EV_KEY || usage->type == EV_ABS)
		clear_bit(usage->code, *bit);

	return 0;
}

/*
 * this function is called when a whole finger has been parsed,
 * so that it can decide what to send to the input layer.
 */
static void egalax_filter_event(struct egalax_data *td, struct input_dev *input)
{
	td->first = !td->first; /* touchscreen emulation */

	if (td->valid) {
		/* emit multitouch events */
		input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
		input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x >> 3);
		input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y >> 3);
		input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z);

		input_mt_sync(input);

		/*
		 * touchscreen emulation: store (x, y) as
		 * the last valid values in this frame
		 */
		td->lastx = td->x;
		td->lasty = td->y;
		td->lastz = td->z;
	}

	/*
	 * touchscreen emulation: if this is the second finger and at least
	 * one in this frame is valid, the latest valid in the frame is
	 * the oldest on the panel, the one we want for single touch
	 */
	if (!td->first && td->activity) {
		input_event(input, EV_ABS, ABS_X, td->lastx >> 3);
		input_event(input, EV_ABS, ABS_Y, td->lasty >> 3);
 		input_event(input, EV_ABS, ABS_PRESSURE, td->lastz);
	}

	if (!td->valid) {
		/*
		 * touchscreen emulation: if the first finger is invalid
		 * and there previously was finger activity, this is a release
		 */ 
		if (td->first && td->activity) {
			input_event(input, EV_KEY, BTN_TOUCH, 0);
			td->activity = false;
		}
		return;
	}


	/* touchscreen emulation: if no previous activity, emit touch event */
	if (!td->activity) {
		input_event(input, EV_KEY, BTN_TOUCH, 1);
		td->activity = true;
	}
}


static int egalax_event(struct hid_device *hid, struct hid_field *field,
				struct hid_usage *usage, __s32 value)
{
	struct egalax_data *td = hid_get_drvdata(hid);

	/* Note, eGalax has two product lines: the first is resistive and
	 * uses a standard parallel multitouch protocol (product ID ==
	 * 48xx).  The second is capacitive and uses an unusual "serial"
	 * protocol with a different message for each multitouch finger
	 * (product ID == 72xx).  We do not yet generate a correct event
	 * sequence for the capacitive/serial protocol.
	 */
	if (hid->claimed & HID_CLAIMED_INPUT) {
		struct input_dev *input = field->hidinput->input;

		switch (usage->hid) {
		case HID_DG_INRANGE:
		case HID_DG_CONFIDENCE:
			/* avoid interference from generic hidinput handling */
			break;
		case HID_DG_TIPSWITCH:
			td->valid = value;
			break;
		case HID_DG_TIPPRESSURE:
			td->z = value;
			break;
		case HID_DG_CONTACTID:
			td->id = value;
			break;
		case HID_GD_X:
			td->x = value;
			break;
		case HID_GD_Y:
			td->y = value;
			/* this is the last field in a finger */
			egalax_filter_event(td, input);
			break;
		case HID_DG_CONTACTCOUNT:
			/* touch emulation: this is the last field in a frame */
			td->first = false;
			break;

		default:
			/* fallback to the generic hidinput handling */
			return 0;
		}
	}

	/* we have handled the hidinput part, now remains hiddev */
	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
		hid->hiddev_hid_event(hid, field, usage, value);

	return 1;
}

static int egalax_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
	int ret;
	struct egalax_data *td;
	struct hid_report *report;

	td = kzalloc(sizeof(struct egalax_data), GFP_KERNEL);
	if (!td) {
		dev_err(&hdev->dev, "cannot allocate eGalax data\n");
		return -ENOMEM;
	}
	hid_set_drvdata(hdev, td);

	ret = hid_parse(hdev);
	if (ret)
		goto end;

	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
	if (ret)
		goto end;

	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[5]; 
	if (report) {
		report->field[0]->value[0] = 2;
		usbhid_submit_report(hdev, report, USB_DIR_OUT);
	}

end:
	if (ret)
		kfree(td);

	return ret;
}

static void egalax_remove(struct hid_device *hdev)
{
	hid_hw_stop(hdev);
	kfree(hid_get_drvdata(hdev));
	hid_set_drvdata(hdev, NULL);
}

static const struct hid_device_id egalax_devices[] = {
	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
	{ }
};
MODULE_DEVICE_TABLE(hid, egalax_devices);

static const struct hid_usage_id egalax_grabbed_usages[] = {
	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
};

static struct hid_driver egalax_driver = {
	.name = "egalax-touch",
	.id_table = egalax_devices,
	.probe = egalax_probe,
	.remove = egalax_remove,
	.input_mapping = egalax_input_mapping,
	.input_mapped = egalax_input_mapped,
	.usage_table = egalax_grabbed_usages,
	.event = egalax_event,
};

static int __init egalax_init(void)
{
	return hid_register_driver(&egalax_driver);
}

static void __exit egalax_exit(void)
{
	hid_unregister_driver(&egalax_driver);
}

module_init(egalax_init);
module_exit(egalax_exit);

