// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Copyright (c) 2001 Vojtech Pavlik
 *
 *  Based on the work of:
 *	Toby Deshane
 */

/*
 * InterAct digital gamepad/joystick driver for Linux
 */

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

#define DRIVER_DESC	"InterAct digital joystick driver"

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

#define INTERACT_MAX_START	600	/* 400 us */
#define INTERACT_MAX_STROBE	60	/* 40 us */
#define INTERACT_MAX_LENGTH	32	/* 32 bits */

#define INTERACT_TYPE_HHFX	0	/* HammerHead/FX */
#define INTERACT_TYPE_PP8D	1	/* ProPad 8 */

struct interact {
	struct gameport *gameport;
	struct input_dev *dev;
	int bads;
	int reads;
	unsigned char type;
	unsigned char length;
	char phys[32];
};

static short interact_abs_hhfx[] =
	{ ABS_RX, ABS_RY, ABS_X, ABS_Y, ABS_HAT0X, ABS_HAT0Y, -1 };
static short interact_abs_pp8d[] =
	{ ABS_X, ABS_Y, -1 };

static short interact_btn_hhfx[] =
	{ BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL, BTN_TL2, BTN_TR2, BTN_MODE, BTN_SELECT, -1 };
static short interact_btn_pp8d[] =
	{ BTN_C, BTN_TL, BTN_TR, BTN_A, BTN_B, BTN_Y, BTN_Z, BTN_X, -1 };

struct interact_type {
	int id;
	short *abs;
	short *btn;
	char *name;
	unsigned char length;
	unsigned char b8;
};

static struct interact_type interact_type[] = {
	{ 0x6202, interact_abs_hhfx, interact_btn_hhfx, "InterAct HammerHead/FX",    32, 4 },
	{ 0x53f8, interact_abs_pp8d, interact_btn_pp8d, "InterAct ProPad 8 Digital", 16, 0 },
	{ 0 }};

/*
 * interact_read_packet() reads and InterAct joystick data.
 */

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

	i = 0;
	data[0] = data[1] = data[2] = 0;
	t = gameport_time(gameport, INTERACT_MAX_START);
	s = gameport_time(gameport, INTERACT_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 & 0x40) {
			data[0] = (data[0] << 1) | ((v >> 4) & 1);
			data[1] = (data[1] << 1) | ((v >> 5) & 1);
			data[2] = (data[2] << 1) | ((v >> 7) & 1);
			i++;
			t = s;
		}
	}

	local_irq_restore(flags);

	return i;
}

/*
 * interact_poll() reads and analyzes InterAct joystick data.
 */

static void interact_poll(struct gameport *gameport)
{
	struct interact *interact = gameport_get_drvdata(gameport);
	struct input_dev *dev = interact->dev;
	u32 data[3];
	int i;

	interact->reads++;

	if (interact_read_packet(interact->gameport, interact->length, data) < interact->length) {
		interact->bads++;
	} else {

		for (i = 0; i < 3; i++)
			data[i] <<= INTERACT_MAX_LENGTH - interact->length;

		switch (interact->type) {

			case INTERACT_TYPE_HHFX:

				for (i = 0; i < 4; i++)
					input_report_abs(dev, interact_abs_hhfx[i], (data[i & 1] >> ((i >> 1) << 3)) & 0xff);

				for (i = 0; i < 2; i++)
					input_report_abs(dev, ABS_HAT0Y - i,
						((data[1] >> ((i << 1) + 17)) & 1)  - ((data[1] >> ((i << 1) + 16)) & 1));

				for (i = 0; i < 8; i++)
					input_report_key(dev, interact_btn_hhfx[i], (data[0] >> (i + 16)) & 1);

				for (i = 0; i < 4; i++)
					input_report_key(dev, interact_btn_hhfx[i + 8], (data[1] >> (i + 20)) & 1);

				break;

			case INTERACT_TYPE_PP8D:

				for (i = 0; i < 2; i++)
					input_report_abs(dev, interact_abs_pp8d[i],
						((data[0] >> ((i << 1) + 20)) & 1)  - ((data[0] >> ((i << 1) + 21)) & 1));

				for (i = 0; i < 8; i++)
					input_report_key(dev, interact_btn_pp8d[i], (data[1] >> (i + 16)) & 1);

				break;
		}
	}

	input_sync(dev);
}

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

static int interact_open(struct input_dev *dev)
{
	struct interact *interact = input_get_drvdata(dev);

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

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

static void interact_close(struct input_dev *dev)
{
	struct interact *interact = input_get_drvdata(dev);

	gameport_stop_polling(interact->gameport);
}

/*
 * interact_connect() probes for InterAct joysticks.
 */

static int interact_connect(struct gameport *gameport, struct gameport_driver *drv)
{
	struct interact *interact;
	struct input_dev *input_dev;
	__u32 data[3];
	int i, t;
	int err;

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

	interact->gameport = gameport;
	interact->dev = input_dev;

	gameport_set_drvdata(gameport, interact);

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

	i = interact_read_packet(gameport, INTERACT_MAX_LENGTH * 2, data);

	if (i != 32 || (data[0] >> 24) != 0x0c || (data[1] >> 24) != 0x02) {
		err = -ENODEV;
		goto fail2;
	}

	for (i = 0; interact_type[i].length; i++)
		if (interact_type[i].id == (data[2] >> 16))
			break;

	if (!interact_type[i].length) {
		printk(KERN_WARNING "interact.c: Unknown joystick on %s. [len %d d0 %08x d1 %08x i2 %08x]\n",
			gameport->phys, i, data[0], data[1], data[2]);
		err = -ENODEV;
		goto fail2;
	}

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

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

	interact->type = i;
	interact->length = interact_type[i].length;

	input_dev->name = interact_type[i].name;
	input_dev->phys = interact->phys;
	input_dev->id.bustype = BUS_GAMEPORT;
	input_dev->id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
	input_dev->id.product = interact_type[i].id;
	input_dev->id.version = 0x0100;
	input_dev->dev.parent = &gameport->dev;

	input_set_drvdata(input_dev, interact);

	input_dev->open = interact_open;
	input_dev->close = interact_close;

	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);

	for (i = 0; (t = interact_type[interact->type].abs[i]) >= 0; i++) {
		if (i < interact_type[interact->type].b8)
			input_set_abs_params(input_dev, t, 0, 255, 0, 0);
		else
			input_set_abs_params(input_dev, t, -1, 1, 0, 0);
	}

	for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++)
		__set_bit(t, input_dev->keybit);

	err = input_register_device(interact->dev);
	if (err)
		goto fail2;

	return 0;

fail2:	gameport_close(gameport);
fail1:  gameport_set_drvdata(gameport, NULL);
	input_free_device(input_dev);
	kfree(interact);
	return err;
}

static void interact_disconnect(struct gameport *gameport)
{
	struct interact *interact = gameport_get_drvdata(gameport);

	input_unregister_device(interact->dev);
	gameport_close(gameport);
	gameport_set_drvdata(gameport, NULL);
	kfree(interact);
}

static struct gameport_driver interact_drv = {
	.driver		= {
		.name	= "interact",
	},
	.description	= DRIVER_DESC,
	.connect	= interact_connect,
	.disconnect	= interact_disconnect,
};

module_gameport_driver(interact_drv);
