// 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_obj(*cobra);
	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);
