/*
 * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
 *
 *  Copyright (c) 1999-2004	Vojtech Pavlik <vojtech@suse.cz>
 *  Copyright (c) 2004		Peter Nelson <rufus-kernel@hackish.org>
 *
 *  Based on the work of:
 *	Andree Borrmann		John Dahlstrom
 *	David Kuder		Nathan Hand
 */

/*
 * 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/delay.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/parport.h>
#include <linux/input.h>

MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
MODULE_LICENSE("GPL");

#define GC_MAX_PORTS		3
#define GC_MAX_DEVICES		5

struct gc_config {
	int args[GC_MAX_DEVICES + 1];
	int nargs;
};

static struct gc_config gc[GC_MAX_PORTS] __initdata;

module_param_array_named(map, gc[0].args, int, &gc[0].nargs, 0);
MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
module_param_array_named(map2, gc[1].args, int, &gc[1].nargs, 0);
MODULE_PARM_DESC(map2, "Describes second set of devices");
module_param_array_named(map3, gc[2].args, int, &gc[2].nargs, 0);
MODULE_PARM_DESC(map3, "Describes third set of devices");

__obsolete_setup("gc=");
__obsolete_setup("gc_2=");
__obsolete_setup("gc_3=");

/* see also gs_psx_delay parameter in PSX support section */

#define GC_SNES		1
#define GC_NES		2
#define GC_NES4		3
#define GC_MULTI	4
#define GC_MULTI2	5
#define GC_N64		6
#define GC_PSX		7
#define GC_DDR		8

#define GC_MAX		8

#define GC_REFRESH_TIME	HZ/100

struct gc {
	struct pardevice *pd;
	struct input_dev *dev[GC_MAX_DEVICES];
	struct timer_list timer;
	unsigned char pads[GC_MAX + 1];
	int used;
	struct semaphore sem;
	char phys[GC_MAX_DEVICES][32];
};

static struct gc *gc_base[3];

static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };

static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
				"Multisystem 2-button joystick", "N64 controller", "PSX controller",
				"PSX DDR controller" };
/*
 * N64 support.
 */

static unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 };
static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START };

#define GC_N64_LENGTH		32		/* N64 bit length, not including stop bit */
#define GC_N64_REQUEST_LENGTH	37		/* transmit request sequence is 9 bits long */
#define GC_N64_DELAY		133		/* delay between transmit request, and response ready (us) */
#define GC_N64_REQUEST		0x1dd1111111ULL /* the request data command (encoded for 000000011) */
#define GC_N64_DWS		3		/* delay between write segments (required for sound playback because of ISA DMA) */
						/* GC_N64_DWS > 24 is known to fail */
#define GC_N64_POWER_W		0xe2		/* power during write (transmit request) */
#define GC_N64_POWER_R		0xfd		/* power during read */
#define GC_N64_OUT		0x1d		/* output bits to the 4 pads */
						/* Reading the main axes of any N64 pad is known to fail if the corresponding bit */
						/* in GC_N64_OUT is pulled low on the output port (by any routine) for more */
						/* than 123 us */
#define GC_N64_CLOCK		0x02		/* clock bits for read */

/*
 * gc_n64_read_packet() reads an N64 packet.
 * Each pad uses one bit per byte. So all pads connected to this port are read in parallel.
 */

static void gc_n64_read_packet(struct gc *gc, unsigned char *data)
{
	int i;
	unsigned long flags;

/*
 * Request the pad to transmit data
 */

	local_irq_save(flags);
	for (i = 0; i < GC_N64_REQUEST_LENGTH; i++) {
		parport_write_data(gc->pd->port, GC_N64_POWER_W | ((GC_N64_REQUEST >> i) & 1 ? GC_N64_OUT : 0));
		udelay(GC_N64_DWS);
	}
	local_irq_restore(flags);

/*
 * Wait for the pad response to be loaded into the 33-bit register of the adapter
 */

	udelay(GC_N64_DELAY);

/*
 * Grab data (ignoring the last bit, which is a stop bit)
 */

	for (i = 0; i < GC_N64_LENGTH; i++) {
		parport_write_data(gc->pd->port, GC_N64_POWER_R);
		data[i] = parport_read_status(gc->pd->port);
		parport_write_data(gc->pd->port, GC_N64_POWER_R | GC_N64_CLOCK);
	 }

/*
 * We must wait 200 ms here for the controller to reinitialize before the next read request.
 * No worries as long as gc_read is polled less frequently than this.
 */

}

/*
 * NES/SNES support.
 */

#define GC_NES_DELAY	6	/* Delay between bits - 6us */
#define GC_NES_LENGTH	8	/* The NES pads use 8 bits of data */
#define GC_SNES_LENGTH	12	/* The SNES true length is 16, but the last 4 bits are unused */

#define GC_NES_POWER	0xfc
#define GC_NES_CLOCK	0x01
#define GC_NES_LATCH	0x02

static unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 };
static unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 };
static short gc_snes_btn[] = { BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR };

/*
 * gc_nes_read_packet() reads a NES/SNES packet.
 * Each pad uses one bit per byte. So all pads connected to
 * this port are read in parallel.
 */

static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data)
{
	int i;

	parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK | GC_NES_LATCH);
	udelay(GC_NES_DELAY * 2);
	parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK);

	for (i = 0; i < length; i++) {
		udelay(GC_NES_DELAY);
		parport_write_data(gc->pd->port, GC_NES_POWER);
		data[i] = parport_read_status(gc->pd->port) ^ 0x7f;
		udelay(GC_NES_DELAY);
		parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK);
	}
}

/*
 * Multisystem joystick support
 */

#define GC_MULTI_LENGTH		5	/* Multi system joystick packet length is 5 */
#define GC_MULTI2_LENGTH	6	/* One more bit for one more button */

/*
 * gc_multi_read_packet() reads a Multisystem joystick packet.
 */

static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
{
	int i;

	for (i = 0; i < length; i++) {
		parport_write_data(gc->pd->port, ~(1 << i));
		data[i] = parport_read_status(gc->pd->port) ^ 0x7f;
	}
}

/*
 * PSX support
 *
 * See documentation at:
 *	http://www.dim.com/~mackys/psxmemcard/ps-eng2.txt
 *	http://www.gamesx.com/controldata/psxcont/psxcont.htm
 *	ftp://milano.usal.es/pablo/
 *
 */

#define GC_PSX_DELAY	25		/* 25 usec */
#define GC_PSX_LENGTH	8		/* talk to the controller in bits */
#define GC_PSX_BYTES	6		/* the maximum number of bytes to read off the controller */

#define GC_PSX_MOUSE	1		/* Mouse */
#define GC_PSX_NEGCON	2		/* NegCon */
#define GC_PSX_NORMAL	4		/* Digital / Analog or Rumble in Digital mode  */
#define GC_PSX_ANALOG	5		/* Analog in Analog mode / Rumble in Green mode */
#define GC_PSX_RUMBLE	7		/* Rumble in Red mode */

#define GC_PSX_CLOCK	0x04		/* Pin 4 */
#define GC_PSX_COMMAND	0x01		/* Pin 2 */
#define GC_PSX_POWER	0xf8		/* Pins 5-9 */
#define GC_PSX_SELECT	0x02		/* Pin 3 */

#define GC_PSX_ID(x)	((x) >> 4)	/* High nibble is device type */
#define GC_PSX_LEN(x)	(((x) & 0xf) << 1)	/* Low nibble is length in bytes/2 */

static int gc_psx_delay = GC_PSX_DELAY;
module_param_named(psx_delay, gc_psx_delay, uint, 0);
MODULE_PARM_DESC(psx_delay, "Delay when accessing Sony PSX controller (usecs)");

__obsolete_setup("gc_psx_delay=");

static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y };
static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y,
				BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR };
static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 };

/*
 * gc_psx_command() writes 8bit command and reads 8bit data from
 * the psx pad.
 */

static void gc_psx_command(struct gc *gc, int b, unsigned char data[5])
{
	int i, j, cmd, read;
	for (i = 0; i < 5; i++)
		data[i] = 0;

	for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) {
		cmd = (b & 1) ? GC_PSX_COMMAND : 0;
		parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
		udelay(gc_psx_delay);
		read = parport_read_status(gc->pd->port) ^ 0x80;
		for (j = 0; j < 5; j++)
			data[j] |= (read & gc_status_bit[j] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) ? (1 << i) : 0;
		parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
		udelay(gc_psx_delay);
	}
}

/*
 * gc_psx_read_packet() reads a whole psx packet and returns
 * device identifier code.
 */

static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES], unsigned char id[5])
{
	int i, j, max_len = 0;
	unsigned long flags;
	unsigned char data2[5];

	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);	/* Select pad */
	udelay(gc_psx_delay);
	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER);			/* Deselect, begin command */
	udelay(gc_psx_delay);

	local_irq_save(flags);

	gc_psx_command(gc, 0x01, data2);						/* Access pad */
	gc_psx_command(gc, 0x42, id);							/* Get device ids */
	gc_psx_command(gc, 0, data2);							/* Dump status */

	for (i =0; i < 5; i++)								/* Find the longest pad */
		if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR]))
			&& (GC_PSX_LEN(id[i]) > max_len)
			&& (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES))
			max_len = GC_PSX_LEN(id[i]);

	for (i = 0; i < max_len; i++) {						/* Read in all the data */
		gc_psx_command(gc, 0, data2);
		for (j = 0; j < 5; j++)
			data[j][i] = data2[j];
	}

	local_irq_restore(flags);

	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);

	for(i = 0; i < 5; i++)								/* Set id's to the real value */
		id[i] = GC_PSX_ID(id[i]);
}

/*
 * gc_timer() reads and analyzes console pads data.
 */

#define GC_MAX_LENGTH GC_N64_LENGTH

static void gc_timer(unsigned long private)
{
	struct gc *gc = (void *) private;
	unsigned char data[GC_MAX_LENGTH];
	unsigned char data_psx[5][GC_PSX_BYTES];
	int i, j, s;

/*
 * N64 pads - must be read first, any read confuses them for 200 us
 */

	if (gc->pads[GC_N64]) {

		gc_n64_read_packet(gc, data);

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

			s = gc_status_bit[i];

			if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) {

				signed char axes[2];
				axes[0] = axes[1] = 0;

				for (j = 0; j < 8; j++) {
					if (data[23 - j] & s) axes[0] |= 1 << j;
					if (data[31 - j] & s) axes[1] |= 1 << j;
				}

				input_report_abs(gc->dev[i], ABS_X,  axes[0]);
				input_report_abs(gc->dev[i], ABS_Y, -axes[1]);

				input_report_abs(gc->dev[i], ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
				input_report_abs(gc->dev[i], ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));

				for (j = 0; j < 10; j++)
					input_report_key(gc->dev[i], gc_n64_btn[j], s & data[gc_n64_bytes[j]]);

				input_sync(gc->dev[i]);
			}
		}
	}

/*
 * NES and SNES pads
 */

	if (gc->pads[GC_NES] || gc->pads[GC_SNES]) {

		gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);

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

			s = gc_status_bit[i];

			if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
				input_report_abs(gc->dev[i], ABS_X, !(s & data[6]) - !(s & data[7]));
				input_report_abs(gc->dev[i], ABS_Y, !(s & data[4]) - !(s & data[5]));
			}

			if (s & gc->pads[GC_NES])
				for (j = 0; j < 4; j++)
					input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_nes_bytes[j]]);

			if (s & gc->pads[GC_SNES])
				for (j = 0; j < 8; j++)
					input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_snes_bytes[j]]);

			input_sync(gc->dev[i]);
		}
	}

/*
 * Multi and Multi2 joysticks
 */

	if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2]) {

		gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data);

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

			s = gc_status_bit[i];

			if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
				input_report_abs(gc->dev[i], ABS_X,  !(s & data[2]) - !(s & data[3]));
				input_report_abs(gc->dev[i], ABS_Y,  !(s & data[0]) - !(s & data[1]));
				input_report_key(gc->dev[i], BTN_TRIGGER, s & data[4]);
			}

			if (s & gc->pads[GC_MULTI2])
				input_report_key(gc->dev[i], BTN_THUMB, s & data[5]);

			input_sync(gc->dev[i]);
		}
	}

/*
 * PSX controllers
 */

	if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) {

		gc_psx_read_packet(gc, data_psx, data);

		for (i = 0; i < 5; i++) {
			switch (data[i]) {

				case GC_PSX_RUMBLE:

					input_report_key(gc->dev[i], BTN_THUMBL, ~data_psx[i][0] & 0x04);
					input_report_key(gc->dev[i], BTN_THUMBR, ~data_psx[i][0] & 0x02);

				case GC_PSX_NEGCON:
				case GC_PSX_ANALOG:

					if (gc->pads[GC_DDR] & gc_status_bit[i]) {
						for(j = 0; j < 4; j++)
							input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
					} else {
						for (j = 0; j < 4; j++)
							input_report_abs(gc->dev[i], gc_psx_abs[j+2], data_psx[i][j + 2]);

						input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
						input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
					}

					for (j = 0; j < 8; j++)
						input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));

					input_report_key(gc->dev[i], BTN_START,  ~data_psx[i][0] & 0x08);
					input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);

					input_sync(gc->dev[i]);

					break;

				case GC_PSX_NORMAL:
					if (gc->pads[GC_DDR] & gc_status_bit[i]) {
						for(j = 0; j < 4; j++)
							input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
					} else {
						input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
						input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);

						/* for some reason if the extra axes are left unset they drift */
						/* for (j = 0; j < 4; j++)
							input_report_abs(gc->dev[i], gc_psx_abs[j+2], 128);
						 * This needs to be debugged properly,
						 * maybe fuzz processing needs to be done in input_sync()
						 *				 --vojtech
						 */
					}

					for (j = 0; j < 8; j++)
						input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j));

					input_report_key(gc->dev[i], BTN_START,  ~data_psx[i][0] & 0x08);
					input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01);

					input_sync(gc->dev[i]);

					break;

				case 0: /* not a pad, ignore */
					break;
			}
		}
	}

	mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
}

static int gc_open(struct input_dev *dev)
{
	struct gc *gc = dev->private;
	int err;

	err = down_interruptible(&gc->sem);
	if (err)
		return err;

	if (!gc->used++) {
		parport_claim(gc->pd);
		parport_write_control(gc->pd->port, 0x04);
		mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
	}

	up(&gc->sem);
	return 0;
}

static void gc_close(struct input_dev *dev)
{
	struct gc *gc = dev->private;

	down(&gc->sem);
	if (!--gc->used) {
		del_timer_sync(&gc->timer);
		parport_write_control(gc->pd->port, 0x00);
		parport_release(gc->pd);
	}
	up(&gc->sem);
}

static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
{
	struct input_dev *input_dev;
	int i;

	if (!pad_type)
		return 0;

	if (pad_type < 1 || pad_type > GC_MAX) {
		printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", pad_type);
		return -EINVAL;
	}

	gc->dev[idx] = input_dev = input_allocate_device();
	if (!input_dev) {
		printk(KERN_ERR "gamecon.c: Not enough memory for input device\n");
		return -ENOMEM;
	}

	input_dev->name = gc_names[pad_type];
	input_dev->phys = gc->phys[idx];
	input_dev->id.bustype = BUS_PARPORT;
	input_dev->id.vendor = 0x0001;
	input_dev->id.product = pad_type;
	input_dev->id.version = 0x0100;
	input_dev->private = gc;

	input_dev->open = gc_open;
	input_dev->close = gc_close;

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

	for (i = 0; i < 2; i++)
		input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);

	gc->pads[0] |= gc_status_bit[idx];
	gc->pads[pad_type] |= gc_status_bit[idx];

	switch (pad_type) {

		case GC_N64:
			for (i = 0; i < 10; i++)
				set_bit(gc_n64_btn[i], input_dev->keybit);

			for (i = 0; i < 2; i++) {
				input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2);
				input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0);
			}

			break;

		case GC_SNES:
			for (i = 4; i < 8; i++)
				set_bit(gc_snes_btn[i], input_dev->keybit);
		case GC_NES:
			for (i = 0; i < 4; i++)
				set_bit(gc_snes_btn[i], input_dev->keybit);
			break;

		case GC_MULTI2:
			set_bit(BTN_THUMB, input_dev->keybit);
		case GC_MULTI:
			set_bit(BTN_TRIGGER, input_dev->keybit);
			break;

		case GC_PSX:
			for (i = 0; i < 6; i++)
				input_set_abs_params(input_dev, gc_psx_abs[i], 4, 252, 0, 2);
			for (i = 0; i < 12; i++)
				set_bit(gc_psx_btn[i], input_dev->keybit);

			break;

		case GC_DDR:
			for (i = 0; i < 4; i++)
				set_bit(gc_psx_ddr_btn[i], input_dev->keybit);
			for (i = 0; i < 12; i++)
				set_bit(gc_psx_btn[i], input_dev->keybit);

			break;
	}

	return 0;
}

static struct gc __init *gc_probe(int parport, int *pads, int n_pads)
{
	struct gc *gc;
	struct parport *pp;
	struct pardevice *pd;
	int i;
	int err;

	pp = parport_find_number(parport);
	if (!pp) {
		printk(KERN_ERR "gamecon.c: no such parport\n");
		err = -EINVAL;
		goto err_out;
	}

	pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
	if (!pd) {
		printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
		err = -EBUSY;
		goto err_put_pp;
	}

	gc = kzalloc(sizeof(struct gc), GFP_KERNEL);
	if (!gc) {
		printk(KERN_ERR "gamecon.c: Not enough memory\n");
		err = -ENOMEM;
		goto err_unreg_pardev;
	}

	init_MUTEX(&gc->sem);
	gc->pd = pd;
	init_timer(&gc->timer);
	gc->timer.data = (long) gc;
	gc->timer.function = gc_timer;

	for (i = 0; i < n_pads; i++) {
		if (!pads[i])
			continue;

		sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
		err = gc_setup_pad(gc, i, pads[i]);
		if (err)
			goto err_free_devs;

		input_register_device(gc->dev[i]);
	}

	if (!gc->pads[0]) {
		printk(KERN_ERR "gamecon.c: No valid devices specified\n");
		err = -EINVAL;
		goto err_free_gc;
	}

	parport_put_port(pp);
	return gc;

 err_free_devs:
	while (--i >= 0)
		input_unregister_device(gc->dev[i]);
 err_free_gc:
	kfree(gc);
 err_unreg_pardev:
	parport_unregister_device(pd);
 err_put_pp:
	parport_put_port(pp);
 err_out:
	return ERR_PTR(err);
}

static void __exit gc_remove(struct gc *gc)
{
	int i;

	for (i = 0; i < GC_MAX_DEVICES; i++)
		if (gc->dev[i])
			input_unregister_device(gc->dev[i]);
	parport_unregister_device(gc->pd);
	kfree(gc);
}

static int __init gc_init(void)
{
	int i;
	int have_dev = 0;
	int err = 0;

	for (i = 0; i < GC_MAX_PORTS; i++) {
		if (gc[i].nargs == 0 || gc[i].args[0] < 0)
			continue;

		if (gc[i].nargs < 2) {
			printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
			err = -EINVAL;
			break;
		}

		gc_base[i] = gc_probe(gc[i].args[0], gc[i].args + 1, gc[i].nargs - 1);
		if (IS_ERR(gc_base[i])) {
			err = PTR_ERR(gc_base[i]);
			break;
		}

		have_dev = 1;
	}

	if (err) {
		while (--i >= 0)
			gc_remove(gc_base[i]);
		return err;
	}

	return have_dev ? 0 : -ENODEV;
}

static void __exit gc_exit(void)
{
	int i;

	for (i = 0; i < GC_MAX_PORTS; i++)
		if (gc_base[i])
			gc_remove(gc_base[i]);
}

module_init(gc_init);
module_exit(gc_exit);
