/*
 * $Id: cobra.c,v 1.19 2002/01/22 20:26:52 vojtech Exp $
 *
 *  Copyright (c) 1999-2001 Vojtech Pavlik
 */

/*
 * Creative Labs Blaster GamePad Cobra 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
 *
 * Should you need to contact me, the author, you can do so either by
 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
 */

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

#define DRIVER_DESC	"Creative Labs Blaster GamePad Cobra driver"

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

#define COBRA_MAX_STROBE	45	/* 45 us max wait for first strobe */
#define COBRA_LENGTH		36

static char* cobra_name = "Creative Labs Blaster GamePad Cobra";

static int cobra_btn[] = { BTN_START, BTN_SELECT, BTN_TL, BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL2, BTN_TR2, 0 };

struct cobra {
	struct gameport *gameport;
	struct input_dev dev[2];
	int reads;
	int bads;
	unsigned char exists;
	char phys[2][32];
};

static unsigned char cobra_read_packet(struct gameport *gameport, unsigned int *data)
{
	unsigned long flags;
	unsigned char u, v, w;
	__u64 buf[2];
	int r[2], t[2];
	int i, j, ret;

	int strobe = gameport_time(gameport, COBRA_MAX_STROBE);

	for (i = 0; i < 2; i++) {
		r[i] = buf[i] = 0;
		t[i] = COBRA_MAX_STROBE;
	}

	local_irq_save(flags);

	u = gameport_read(gameport);

	do {
		t[0]--; t[1]--;
		v = gameport_read(gameport);
		for (i = 0, w = u ^ v; i < 2 && w; i++, w >>= 2)
			if (w & 0x30) {
				if ((w & 0x30) < 0x30 && r[i] < COBRA_LENGTH && t[i] > 0) {
					buf[i] |= (__u64)((w >> 5) & 1) << r[i]++;
					t[i] = strobe;
					u = v;
				} else t[i] = 0;
			}
	} while (t[0] > 0 || t[1] > 0);

	local_irq_restore(flags);

	ret = 0;

	for (i = 0; i < 2; i++) {

		if (r[i] != COBRA_LENGTH) continue;

		for (j = 0; j < COBRA_LENGTH && (buf[i] & 0x04104107f) ^ 0x041041040; j++)
			buf[i] = (buf[i] >> 1) | ((__u64)(buf[i] & 1) << (COBRA_LENGTH - 1));

		if (j < COBRA_LENGTH) ret |= (1 << i);

		data[i] = ((buf[i] >>  7) & 0x000001f) | ((buf[i] >>  8) & 0x00003e0)
			| ((buf[i] >>  9) & 0x0007c00) | ((buf[i] >> 10) & 0x00f8000)
			| ((buf[i] >> 11) & 0x1f00000);

	}

	return ret;
}

static void cobra_poll(struct gameport *gameport)
{
	struct cobra *cobra = gameport_get_drvdata(gameport);
	struct input_dev *dev;
	unsigned int data[2];
	int i, j, r;

	cobra->reads++;

	if ((r = cobra_read_packet(gameport, data)) != cobra->exists) {
		cobra->bads++;
		return;
	}

	for (i = 0; i < 2; i++)
		if (cobra->exists & r & (1 << i)) {

			dev = cobra->dev + i;

			input_report_abs(dev, ABS_X, ((data[i] >> 4) & 1) - ((data[i] >> 3) & 1));
			input_report_abs(dev, ABS_Y, ((data[i] >> 2) & 1) - ((data[i] >> 1) & 1));

			for (j = 0; cobra_btn[j]; j++)
				input_report_key(dev, cobra_btn[j], data[i] & (0x20 << j));

			input_sync(dev);

		}
}

static int cobra_open(struct input_dev *dev)
{
	struct cobra *cobra = dev->private;

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

static void cobra_close(struct input_dev *dev)
{
	struct cobra *cobra = dev->private;

	gameport_stop_polling(cobra->gameport);
}

static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
{
	struct cobra *cobra;
	unsigned int data[2];
	int i, j;
	int err;

	if (!(cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL)))
		return -ENOMEM;

	cobra->gameport = gameport;

	gameport_set_drvdata(gameport, cobra);

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

	cobra->exists = cobra_read_packet(gameport, data);

	for (i = 0; i < 2; i++)
		if ((cobra->exists >> i) & data[i] & 1) {
			printk(KERN_WARNING "cobra.c: Device %d on %s has the Ext bit set. ID is: %d"
				" Contact vojtech@ucw.cz\n", i, gameport->phys, (data[i] >> 2) & 7);
			cobra->exists &= ~(1 << i);
		}

	if (!cobra->exists) {
		err = -ENODEV;
		goto fail2;
	}

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

	for (i = 0; i < 2; i++)
		if ((cobra->exists >> i) & 1) {

			sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i);

			cobra->dev[i].private = cobra;
			cobra->dev[i].open = cobra_open;
			cobra->dev[i].close = cobra_close;

			cobra->dev[i].name = cobra_name;
			cobra->dev[i].phys = cobra->phys[i];
			cobra->dev[i].id.bustype = BUS_GAMEPORT;
			cobra->dev[i].id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
			cobra->dev[i].id.product = 0x0008;
			cobra->dev[i].id.version = 0x0100;

			cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);

			input_set_abs_params(&cobra->dev[i], ABS_X, -1, 1, 0, 0);
			input_set_abs_params(&cobra->dev[i], ABS_Y, -1, 1, 0, 0);

			for (j = 0; cobra_btn[j]; j++)
				set_bit(cobra_btn[j], cobra->dev[i].keybit);

			input_register_device(&cobra->dev[i]);
			printk(KERN_INFO "input: %s on %s\n", cobra_name, gameport->phys);
		}

	return 0;

fail2:	gameport_close(gameport);
fail1:	gameport_set_drvdata(gameport, NULL);
	kfree(cobra);
	return err;
}

static void cobra_disconnect(struct gameport *gameport)
{
	struct cobra *cobra = gameport_get_drvdata(gameport);
	int i;

	for (i = 0; i < 2; i++)
		if ((cobra->exists >> i) & 1)
			input_unregister_device(cobra->dev + i);
	gameport_close(gameport);
	gameport_set_drvdata(gameport, NULL);
	kfree(cobra);
}

static struct gameport_driver cobra_drv = {
	.driver		= {
		.name	= "cobra",
	},
	.description	= DRIVER_DESC,
	.connect	= cobra_connect,
	.disconnect	= cobra_disconnect,
};

static int __init cobra_init(void)
{
	gameport_register_driver(&cobra_drv);
	return 0;
}

static void __exit cobra_exit(void)
{
	gameport_unregister_driver(&cobra_drv);
}

module_init(cobra_init);
module_exit(cobra_exit);
