// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Copyright (c) 1999-2001 Vojtech Pavlik
 */

/*
 * Creative Labs Blaster GamePad Cobra driver for Linux
 */

/*
 */

#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	"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 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 = input_get_drvdata(dev);

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

static void cobra_close(struct input_dev *dev)
{
	struct cobra *cobra = input_get_drvdata(dev);

	gameport_stop_polling(cobra->gameport);
}

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

	cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL);
	if (!cobra)
		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)
			continue;

		cobra->dev[i] = input_dev = input_allocate_device();
		if (!input_dev) {
			err = -ENOMEM;
			goto fail3;
		}

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

		input_dev->name = "Creative Labs Blaster GamePad Cobra";
		input_dev->phys = cobra->phys[i];
		input_dev->id.bustype = BUS_GAMEPORT;
		input_dev->id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
		input_dev->id.product = 0x0008;
		input_dev->id.version = 0x0100;
		input_dev->dev.parent = &gameport->dev;

		input_set_drvdata(input_dev, cobra);

		input_dev->open = cobra_open;
		input_dev->close = cobra_close;

		input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
		input_set_abs_params(input_dev, ABS_X, -1, 1, 0, 0);
		input_set_abs_params(input_dev, ABS_Y, -1, 1, 0, 0);
		for (j = 0; cobra_btn[j]; j++)
			set_bit(cobra_btn[j], input_dev->keybit);

		err = input_register_device(cobra->dev[i]);
		if (err)
			goto fail4;
	}

	return 0;

 fail4:	input_free_device(cobra->dev[i]);
 fail3:	while (--i >= 0)
		if (cobra->dev[i])
			input_unregister_device(cobra->dev[i]);
 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,
};

module_gameport_driver(cobra_drv);
