/*
 *  Copyright (c) 1998-2001 Vojtech Pavlik
 */

/*
 * FP-Gaming Assassin 3D joystick driver for Linux
 */

/*
 * 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/slab.h>
#include <linux/gameport.h>
#include <linux/input.h>
#include <linux/jiffies.h>

#define DRIVER_DESC	"FP-Gaming Assassin 3D joystick driver"

MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

#define A3D_MAX_START		600	/* 600 us */
#define A3D_MAX_STROBE		80	/* 80 us */
#define A3D_MAX_LENGTH		40	/* 40*3 bits */

#define A3D_MODE_A3D		1	/* Assassin 3D */
#define A3D_MODE_PAN		2	/* Panther */
#define A3D_MODE_OEM		3	/* Panther OEM version */
#define A3D_MODE_PXL		4	/* Panther XL */

static char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", "OEM Panther",
			"MadCatz Panther XL", "MadCatz Panther XL w/ rudder" };

struct a3d {
	struct gameport *gameport;
	struct gameport *adc;
	struct input_dev *dev;
	int axes[4];
	int buttons;
	int mode;
	int length;
	int reads;
	int bads;
	char phys[32];
};

/*
 * a3d_read_packet() reads an Assassin 3D packet.
 */

static int a3d_read_packet(struct gameport *gameport, int length, char *data)
{
	unsigned long flags;
	unsigned char u, v;
	unsigned int t, s;
	int i;

	i = 0;
	t = gameport_time(gameport, A3D_MAX_START);
	s = gameport_time(gameport, A3D_MAX_STROBE);

	local_irq_save(flags);
	gameport_trigger(gameport);
	v = gameport_read(gameport);

	while (t > 0 && i < length) {
		t--;
		u = v; v = gameport_read(gameport);
		if (~v & u & 0x10) {
			data[i++] = v >> 5;
			t = s;
		}
	}

	local_irq_restore(flags);

	return i;
}

/*
 * a3d_csum() computes checksum of triplet packet
 */

static int a3d_csum(char *data, int count)
{
	int i, csum = 0;

	for (i = 0; i < count - 2; i++)
		csum += data[i];
	return (csum & 0x3f) != ((data[count - 2] << 3) | data[count - 1]);
}

static void a3d_read(struct a3d *a3d, unsigned char *data)
{
	struct input_dev *dev = a3d->dev;

	switch (a3d->mode) {

		case A3D_MODE_A3D:
		case A3D_MODE_OEM:
		case A3D_MODE_PAN:

			input_report_rel(dev, REL_X, ((data[5] << 6) | (data[6] << 3) | data[ 7]) - ((data[5] & 4) << 7));
			input_report_rel(dev, REL_Y, ((data[8] << 6) | (data[9] << 3) | data[10]) - ((data[8] & 4) << 7));

			input_report_key(dev, BTN_RIGHT,  data[2] & 1);
			input_report_key(dev, BTN_LEFT,   data[3] & 2);
			input_report_key(dev, BTN_MIDDLE, data[3] & 4);

			input_sync(dev);

			a3d->axes[0] = ((signed char)((data[11] << 6) | (data[12] << 3) | (data[13]))) + 128;
			a3d->axes[1] = ((signed char)((data[14] << 6) | (data[15] << 3) | (data[16]))) + 128;
			a3d->axes[2] = ((signed char)((data[17] << 6) | (data[18] << 3) | (data[19]))) + 128;
			a3d->axes[3] = ((signed char)((data[20] << 6) | (data[21] << 3) | (data[22]))) + 128;

			a3d->buttons = ((data[3] << 3) | data[4]) & 0xf;

			break;

		case A3D_MODE_PXL:

			input_report_rel(dev, REL_X, ((data[ 9] << 6) | (data[10] << 3) | data[11]) - ((data[ 9] & 4) << 7));
			input_report_rel(dev, REL_Y, ((data[12] << 6) | (data[13] << 3) | data[14]) - ((data[12] & 4) << 7));

			input_report_key(dev, BTN_RIGHT,  data[2] & 1);
			input_report_key(dev, BTN_LEFT,   data[3] & 2);
			input_report_key(dev, BTN_MIDDLE, data[3] & 4);
			input_report_key(dev, BTN_SIDE,   data[7] & 2);
			input_report_key(dev, BTN_EXTRA,  data[7] & 4);

			input_report_abs(dev, ABS_X,        ((signed char)((data[15] << 6) | (data[16] << 3) | (data[17]))) + 128);
			input_report_abs(dev, ABS_Y,        ((signed char)((data[18] << 6) | (data[19] << 3) | (data[20]))) + 128);
			input_report_abs(dev, ABS_RUDDER,   ((signed char)((data[21] << 6) | (data[22] << 3) | (data[23]))) + 128);
			input_report_abs(dev, ABS_THROTTLE, ((signed char)((data[24] << 6) | (data[25] << 3) | (data[26]))) + 128);

			input_report_abs(dev, ABS_HAT0X, ( data[5]       & 1) - ((data[5] >> 2) & 1));
			input_report_abs(dev, ABS_HAT0Y, ((data[5] >> 1) & 1) - ((data[6] >> 2) & 1));
			input_report_abs(dev, ABS_HAT1X, ((data[4] >> 1) & 1) - ( data[3]       & 1));
			input_report_abs(dev, ABS_HAT1Y, ((data[4] >> 2) & 1) - ( data[4]       & 1));

			input_report_key(dev, BTN_TRIGGER, data[8] & 1);
			input_report_key(dev, BTN_THUMB,   data[8] & 2);
			input_report_key(dev, BTN_TOP,     data[8] & 4);
			input_report_key(dev, BTN_PINKIE,  data[7] & 1);

			input_sync(dev);

			break;
	}
}


/*
 * a3d_poll() reads and analyzes A3D joystick data.
 */

static void a3d_poll(struct gameport *gameport)
{
	struct a3d *a3d = gameport_get_drvdata(gameport);
	unsigned char data[A3D_MAX_LENGTH];

	a3d->reads++;
	if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length ||
	    data[0] != a3d->mode || a3d_csum(data, a3d->length))
		a3d->bads++;
	else
		a3d_read(a3d, data);
}

/*
 * a3d_adc_cooked_read() copies the acis and button data to the
 * callers arrays. It could do the read itself, but the caller could
 * call this more than 50 times a second, which would use too much CPU.
 */

static int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
	struct a3d *a3d = gameport->port_data;
	int i;

	for (i = 0; i < 4; i++)
		axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1;
	*buttons = a3d->buttons;
	return 0;
}

/*
 * a3d_adc_open() is the gameport open routine. It refuses to serve
 * any but cooked data.
 */

static int a3d_adc_open(struct gameport *gameport, int mode)
{
	struct a3d *a3d = gameport->port_data;

	if (mode != GAMEPORT_MODE_COOKED)
		return -1;

	gameport_start_polling(a3d->gameport);
	return 0;
}

/*
 * a3d_adc_close() is a callback from the input close routine.
 */

static void a3d_adc_close(struct gameport *gameport)
{
	struct a3d *a3d = gameport->port_data;

	gameport_stop_polling(a3d->gameport);
}

/*
 * a3d_open() is a callback from the input open routine.
 */

static int a3d_open(struct input_dev *dev)
{
	struct a3d *a3d = input_get_drvdata(dev);

	gameport_start_polling(a3d->gameport);
	return 0;
}

/*
 * a3d_close() is a callback from the input close routine.
 */

static void a3d_close(struct input_dev *dev)
{
	struct a3d *a3d = input_get_drvdata(dev);

	gameport_stop_polling(a3d->gameport);
}

/*
 * a3d_connect() probes for A3D joysticks.
 */

static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
{
	struct a3d *a3d;
	struct input_dev *input_dev;
	struct gameport *adc;
	unsigned char data[A3D_MAX_LENGTH];
	int i;
	int err;

	a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!a3d || !input_dev) {
		err = -ENOMEM;
		goto fail1;
	}

	a3d->dev = input_dev;
	a3d->gameport = gameport;

	gameport_set_drvdata(gameport, a3d);

	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
	if (err)
		goto fail1;

	i = a3d_read_packet(gameport, A3D_MAX_LENGTH, data);

	if (!i || a3d_csum(data, i)) {
		err = -ENODEV;
		goto fail2;
	}

	a3d->mode = data[0];

	if (!a3d->mode || a3d->mode > 5) {
		printk(KERN_WARNING "a3d.c: Unknown A3D device detected "
			"(%s, id=%d), contact <vojtech@ucw.cz>\n", gameport->phys, a3d->mode);
		err = -ENODEV;
		goto fail2;
	}

	gameport_set_poll_handler(gameport, a3d_poll);
	gameport_set_poll_interval(gameport, 20);

	snprintf(a3d->phys, sizeof(a3d->phys), "%s/input0", gameport->phys);

	input_dev->name = a3d_names[a3d->mode];
	input_dev->phys = a3d->phys;
	input_dev->id.bustype = BUS_GAMEPORT;
	input_dev->id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
	input_dev->id.product = a3d->mode;
	input_dev->id.version = 0x0100;
	input_dev->dev.parent = &gameport->dev;
	input_dev->open = a3d_open;
	input_dev->close = a3d_close;

	input_set_drvdata(input_dev, a3d);

	if (a3d->mode == A3D_MODE_PXL) {

		int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER };

		a3d->length = 33;

		input_dev->evbit[0] |= BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY) |
			BIT_MASK(EV_REL);
		input_dev->relbit[0] |= BIT_MASK(REL_X) | BIT_MASK(REL_Y);
		input_dev->absbit[0] |= BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
			BIT_MASK(ABS_THROTTLE) | BIT_MASK(ABS_RUDDER) |
			BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) |
			BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y);
		input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_RIGHT) |
			BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) |
			BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
		input_dev->keybit[BIT_WORD(BTN_JOYSTICK)] |=
			BIT_MASK(BTN_TRIGGER) | BIT_MASK(BTN_THUMB) |
			BIT_MASK(BTN_TOP) | BIT_MASK(BTN_PINKIE);

		a3d_read(a3d, data);

		for (i = 0; i < 4; i++) {
			if (i < 2)
				input_set_abs_params(input_dev, axes[i],
					48, input_abs_get_val(input_dev, axes[i]) * 2 - 48, 0, 8);
			else
				input_set_abs_params(input_dev, axes[i], 2, 253, 0, 0);
			input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0);
		}

	} else {
		a3d->length = 29;

		input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
		input_dev->relbit[0] |= BIT_MASK(REL_X) | BIT_MASK(REL_Y);
		input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_RIGHT) |
			BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE);

		a3d_read(a3d, data);

		if (!(a3d->adc = adc = gameport_allocate_port()))
			printk(KERN_ERR "a3d: Not enough memory for ADC port\n");
		else {
			adc->port_data = a3d;
			adc->open = a3d_adc_open;
			adc->close = a3d_adc_close;
			adc->cooked_read = a3d_adc_cooked_read;
			adc->fuzz = 1;

			gameport_set_name(adc, a3d_names[a3d->mode]);
			gameport_set_phys(adc, "%s/gameport0", gameport->phys);
			adc->dev.parent = &gameport->dev;

			gameport_register_port(adc);
		}
	}

	err = input_register_device(a3d->dev);
	if (err)
		goto fail3;

	return 0;

 fail3:	if (a3d->adc)
		gameport_unregister_port(a3d->adc);
 fail2:	gameport_close(gameport);
 fail1:	gameport_set_drvdata(gameport, NULL);
	input_free_device(input_dev);
	kfree(a3d);
	return err;
}

static void a3d_disconnect(struct gameport *gameport)
{
	struct a3d *a3d = gameport_get_drvdata(gameport);

	input_unregister_device(a3d->dev);
	if (a3d->adc)
		gameport_unregister_port(a3d->adc);
	gameport_close(gameport);
	gameport_set_drvdata(gameport, NULL);
	kfree(a3d);
}

static struct gameport_driver a3d_drv = {
	.driver		= {
		.name	= "adc",
		.owner	= THIS_MODULE,
	},
	.description	= DRIVER_DESC,
	.connect	= a3d_connect,
	.disconnect	= a3d_disconnect,
};

module_gameport_driver(a3d_drv);
