/*
 *	SEGA Dreamcast controller driver
 *	Based on drivers/usb/iforce.c
 *
 *	Copyright Yaegashi Takeshi, 2001
 *	Adrian McMenamin, 2008 - 2009
 */

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/maple.h>

MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>");
MODULE_DESCRIPTION("SEGA Dreamcast controller driver");
MODULE_LICENSE("GPL");

struct dc_pad {
	struct input_dev *dev;
	struct maple_device *mdev;
};

static void dc_pad_callback(struct mapleq *mq)
{
	unsigned short buttons;
	struct maple_device *mapledev = mq->dev;
	struct dc_pad *pad = maple_get_drvdata(mapledev);
	struct input_dev *dev = pad->dev;
	unsigned char *res = mq->recvbuf->buf;

	buttons = ~le16_to_cpup((__le16 *)(res + 8));

	input_report_abs(dev, ABS_HAT0Y,
		(buttons & 0x0010 ? -1 : 0) + (buttons & 0x0020 ? 1 : 0));
	input_report_abs(dev, ABS_HAT0X,
		(buttons & 0x0040 ? -1 : 0) + (buttons & 0x0080 ? 1 : 0));
	input_report_abs(dev, ABS_HAT1Y,
		(buttons & 0x1000 ? -1 : 0) + (buttons & 0x2000 ? 1 : 0));
	input_report_abs(dev, ABS_HAT1X,
		(buttons & 0x4000 ? -1 : 0) + (buttons & 0x8000 ? 1 : 0));

	input_report_key(dev, BTN_C,      buttons & 0x0001);
	input_report_key(dev, BTN_B,      buttons & 0x0002);
	input_report_key(dev, BTN_A,      buttons & 0x0004);
	input_report_key(dev, BTN_START,  buttons & 0x0008);
	input_report_key(dev, BTN_Z,      buttons & 0x0100);
	input_report_key(dev, BTN_Y,      buttons & 0x0200);
	input_report_key(dev, BTN_X,      buttons & 0x0400);
	input_report_key(dev, BTN_SELECT, buttons & 0x0800);

	input_report_abs(dev, ABS_GAS,    res[10]);
	input_report_abs(dev, ABS_BRAKE,  res[11]);
	input_report_abs(dev, ABS_X,      res[12]);
	input_report_abs(dev, ABS_Y,      res[13]);
	input_report_abs(dev, ABS_RX,     res[14]);
	input_report_abs(dev, ABS_RY,     res[15]);
}

static int dc_pad_open(struct input_dev *dev)
{
	struct dc_pad *pad = dev_get_platdata(&dev->dev);

	maple_getcond_callback(pad->mdev, dc_pad_callback, HZ/20,
		MAPLE_FUNC_CONTROLLER);

	return 0;
}

static void dc_pad_close(struct input_dev *dev)
{
	struct dc_pad *pad = dev_get_platdata(&dev->dev);

	maple_getcond_callback(pad->mdev, dc_pad_callback, 0,
		MAPLE_FUNC_CONTROLLER);
}

/* allow the controller to be used */
static int probe_maple_controller(struct device *dev)
{
	static const short btn_bit[32] = {
		BTN_C, BTN_B, BTN_A, BTN_START, -1, -1, -1, -1,
		BTN_Z, BTN_Y, BTN_X, BTN_SELECT, -1, -1, -1, -1,
		-1, -1, -1, -1, -1, -1, -1, -1,
		-1, -1, -1, -1, -1, -1, -1, -1,
	};

	static const short abs_bit[32] = {
		-1, -1, -1, -1, ABS_HAT0Y, ABS_HAT0Y, ABS_HAT0X, ABS_HAT0X,
		-1, -1, -1, -1, ABS_HAT1Y, ABS_HAT1Y, ABS_HAT1X, ABS_HAT1X,
		ABS_GAS, ABS_BRAKE, ABS_X, ABS_Y, ABS_RX, ABS_RY, -1, -1,
		-1, -1, -1, -1, -1, -1, -1, -1,
	};

	struct maple_device *mdev = to_maple_dev(dev);
	struct maple_driver *mdrv = to_maple_driver(dev->driver);
	int i, error;
	struct dc_pad *pad;
	struct input_dev *idev;
	unsigned long data = be32_to_cpu(mdev->devinfo.function_data[0]);

	pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL);
	idev = input_allocate_device();
	if (!pad || !idev) {
		error = -ENOMEM;
		goto fail;
	}

	pad->dev = idev;
	pad->mdev = mdev;

	idev->open = dc_pad_open;
	idev->close = dc_pad_close;

	for (i = 0; i < 32; i++) {
		if (data & (1 << i)) {
			if (btn_bit[i] >= 0)
				__set_bit(btn_bit[i], idev->keybit);
			else if (abs_bit[i] >= 0)
				__set_bit(abs_bit[i], idev->absbit);
		}
	}

	if (idev->keybit[BIT_WORD(BTN_JOYSTICK)])
		idev->evbit[0] |= BIT_MASK(EV_KEY);

	if (idev->absbit[0])
		idev->evbit[0] |= BIT_MASK(EV_ABS);

	for (i = ABS_X; i <= ABS_BRAKE; i++)
		input_set_abs_params(idev, i, 0, 255, 0, 0);

	for (i = ABS_HAT0X; i <= ABS_HAT3Y; i++)
		input_set_abs_params(idev, i, 1, -1, 0, 0);

	idev->dev.platform_data = pad;
	idev->dev.parent = &mdev->dev;
	idev->name = mdev->product_name;
	idev->id.bustype = BUS_HOST;
	input_set_drvdata(idev, pad);

	error = input_register_device(idev);
	if (error)
		goto fail;

	mdev->driver = mdrv;
	maple_set_drvdata(mdev, pad);

	return 0;

fail:
	input_free_device(idev);
	kfree(pad);
	maple_set_drvdata(mdev, NULL);
	return error;
}

static int remove_maple_controller(struct device *dev)
{
	struct maple_device *mdev = to_maple_dev(dev);
	struct dc_pad *pad = maple_get_drvdata(mdev);

	mdev->callback = NULL;
	input_unregister_device(pad->dev);
	maple_set_drvdata(mdev, NULL);
	kfree(pad);

	return 0;
}

static struct maple_driver dc_pad_driver = {
	.function =	MAPLE_FUNC_CONTROLLER,
	.drv = {
		.name	= "Dreamcast_controller",
		.probe	= probe_maple_controller,
		.remove	= remove_maple_controller,
	},
};

static int __init dc_pad_init(void)
{
	return maple_driver_register(&dc_pad_driver);
}

static void __exit dc_pad_exit(void)
{
	maple_driver_unregister(&dc_pad_driver);
}

module_init(dc_pad_init);
module_exit(dc_pad_exit);
