diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 15:20:36 -0700 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/input/joystick |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/input/joystick')
32 files changed, 11225 insertions, 0 deletions
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig new file mode 100644 index 00000000000..67519ef0ef9 --- /dev/null +++ b/drivers/input/joystick/Kconfig @@ -0,0 +1,256 @@ +# +# Joystick driver configuration +# +menuconfig INPUT_JOYSTICK + bool "Joysticks" + help + If you have a joystick, 6dof controller, gamepad, steering wheel, + weapon control system or something like that you can say Y here + and the list of supported devices will be displayed. This option + doesn't affect the kernel. + + Please read the file <file:Documentation/input/joystick.txt> which + contains more information. + +if INPUT_JOYSTICK + +config JOYSTICK_ANALOG + tristate "Classic PC analog joysticks and gamepads" + select GAMEPORT + ---help--- + Say Y here if you have a joystick that connects to the PC + gameport. In addition to the usual PC analog joystick, this driver + supports many extensions, including joysticks with throttle control, + with rudders, additional hats and buttons compatible with CH + Flightstick Pro, ThrustMaster FCS, 6 and 8 button gamepads, or + Saitek Cyborg joysticks. + + Please read the file <file:Documentation/input/joystick.txt> which + contains more information. + + To compile this driver as a module, choose M here: the + module will be called analog. + +config JOYSTICK_A3D + tristate "Assasin 3D and MadCatz Panther devices" + select GAMEPORT + help + Say Y here if you have an FPGaming or MadCatz controller using the + A3D protocol over the PC gameport. + + To compile this driver as a module, choose M here: the + module will be called a3d. + +config JOYSTICK_ADI + tristate "Logitech ADI digital joysticks and gamepads" + select GAMEPORT + help + Say Y here if you have a Logitech controller using the ADI + protocol over the PC gameport. + + To compile this driver as a module, choose M here: the + module will be called adi. + +config JOYSTICK_COBRA + tristate "Creative Labs Blaster Cobra gamepad" + select GAMEPORT + help + Say Y here if you have a Creative Labs Blaster Cobra gamepad. + + To compile this driver as a module, choose M here: the + module will be called cobra. + +config JOYSTICK_GF2K + tristate "Genius Flight2000 Digital joysticks and gamepads" + select GAMEPORT + help + Say Y here if you have a Genius Flight2000 or MaxFighter digitally + communicating joystick or gamepad. + + To compile this driver as a module, choose M here: the + module will be called gf2k. + +config JOYSTICK_GRIP + tristate "Gravis GrIP joysticks and gamepads" + select GAMEPORT + help + Say Y here if you have a Gravis controller using the GrIP protocol + over the PC gameport. + + To compile this driver as a module, choose M here: the + module will be called grip. + +config JOYSTICK_GRIP_MP + tristate "Gravis GrIP MultiPort" + select GAMEPORT + help + Say Y here if you have the original Gravis GrIP MultiPort, a hub + that connects to the gameport and you connect gamepads to it. + + To compile this driver as a module, choose M here: the + module will be called grip_mp. + +config JOYSTICK_GUILLEMOT + tristate "Guillemot joysticks and gamepads" + select GAMEPORT + help + Say Y here if you have a Guillemot joystick using a digital + protocol over the PC gameport. + + To compile this driver as a module, choose M here: the + module will be called guillemot. + +config JOYSTICK_INTERACT + tristate "InterAct digital joysticks and gamepads" + select GAMEPORT + help + Say Y here if you have an InterAct gameport or joystick + communicating digitally over the gameport. + + To compile this driver as a module, choose M here: the + module will be called interact. + +config JOYSTICK_SIDEWINDER + tristate "Microsoft SideWinder digital joysticks and gamepads" + select GAMEPORT + help + Say Y here if you have a Microsoft controller using the Digital + Overdrive protocol over PC gameport. + + To compile this driver as a module, choose M here: the + module will be called sidewinder. + +config JOYSTICK_TMDC + tristate "ThrustMaster DirectConnect joysticks and gamepads" + select GAMEPORT + help + Say Y here if you have a ThrustMaster controller using the + DirectConnect (BSP) protocol over the PC gameport. + + To compile this driver as a module, choose M here: the + module will be called tmdc. + +source "drivers/input/joystick/iforce/Kconfig" + +config JOYSTICK_WARRIOR + tristate "Logitech WingMan Warrior joystick" + select SERIO + help + Say Y here if you have a Logitech WingMan Warrior joystick connected + to your computer's serial port. + + To compile this driver as a module, choose M here: the + module will be called warrior. + +config JOYSTICK_MAGELLAN + tristate "LogiCad3d Magellan/SpaceMouse 6dof controllers" + select SERIO + help + Say Y here if you have a Magellan or Space Mouse 6DOF controller + connected to your computer's serial port. + + To compile this driver as a module, choose M here: the + module will be called magellan. + +config JOYSTICK_SPACEORB + tristate "SpaceTec SpaceOrb/Avenger 6dof controllers" + select SERIO + help + Say Y here if you have a SpaceOrb 360 or SpaceBall Avenger 6DOF + controller connected to your computer's serial port. + + To compile this driver as a module, choose M here: the + module will be called spaceorb. + +config JOYSTICK_SPACEBALL + tristate "SpaceTec SpaceBall 6dof controllers" + select SERIO + help + Say Y here if you have a SpaceTec SpaceBall 2003/3003/4000 FLX + controller connected to your computer's serial port. For the + SpaceBall 4000 USB model, use the USB HID driver. + + To compile this driver as a module, choose M here: the + module will be called spaceball. + +config JOYSTICK_STINGER + tristate "Gravis Stinger gamepad" + select SERIO + help + Say Y here if you have a Gravis Stinger connected to one of your + serial ports. + + To compile this driver as a module, choose M here: the + module will be called stinger. + +config JOYSTICK_TWIDJOY + tristate "Twiddler as a joystick" + select SERIO + help + Say Y here if you have a Handykey Twiddler connected to your + computer's serial port and want to use it as a joystick. + + To compile this driver as a module, choose M here: the + module will be called twidjoy. + +config JOYSTICK_DB9 + tristate "Multisystem, Sega Genesis, Saturn joysticks and gamepads" + depends on PARPORT + ---help--- + Say Y here if you have a Sega Master System gamepad, Sega Genesis + gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga, + Commodore, Amstrad CPC joystick connected to your parallel port. + For more information on how to use the driver please read + <file:Documentation/input/joystick-parport.txt>. + + To compile this driver as a module, choose M here: the + module will be called db9. + +config JOYSTICK_GAMECON + tristate "Multisystem, NES, SNES, N64, PSX joysticks and gamepads" + depends on PARPORT + ---help--- + Say Y here if you have a Nintendo Entertainment System gamepad, + Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad, + Sony PlayStation gamepad or a Multisystem -- Atari, Amiga, + Commodore, Amstrad CPC joystick connected to your parallel port. + For more information on how to use the driver please read + <file:Documentation/input/joystick-parport.txt>. + + To compile this driver as a module, choose M here: the + module will be called gamecon. + +config JOYSTICK_TURBOGRAFX + tristate "Multisystem joysticks via TurboGraFX device" + depends on PARPORT + help + Say Y here if you have the TurboGraFX interface by Steffen Schwenke, + and want to use it with Multisystem -- Atari, Amiga, Commodore, + Amstrad CPC joystick. For more information on how to use the driver + please read <file:Documentation/input/joystick-parport.txt>. + + To compile this driver as a module, choose M here: the + module will be called turbografx. + +config JOYSTICK_AMIGA + tristate "Amiga joysticks" + depends on AMIGA + help + Say Y here if you have an Amiga with a digital joystick connected + to it. + + To compile this driver as a module, choose M here: the + module will be called amijoy. + +config JOYSTICK_JOYDUMP + tristate "Gameport data dumper" + select GAMEPORT + help + Say Y here if you want to dump data from your joystick into the system + log for debugging purposes. Say N if you are making a production + configuration or aren't sure. + + To compile this driver as a module, choose M here: the + module will be called joydump. + +endif diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile new file mode 100644 index 00000000000..5231f6ff75b --- /dev/null +++ b/drivers/input/joystick/Makefile @@ -0,0 +1,30 @@ +# +# Makefile for the input core drivers. +# + +# Each configuration option enables a list of files. + +obj-$(CONFIG_JOYSTICK_A3D) += a3d.o +obj-$(CONFIG_JOYSTICK_ADI) += adi.o +obj-$(CONFIG_JOYSTICK_AMIGA) += amijoy.o +obj-$(CONFIG_JOYSTICK_ANALOG) += analog.o +obj-$(CONFIG_JOYSTICK_COBRA) += cobra.o +obj-$(CONFIG_JOYSTICK_DB9) += db9.o +obj-$(CONFIG_JOYSTICK_GAMECON) += gamecon.o +obj-$(CONFIG_JOYSTICK_GF2K) += gf2k.o +obj-$(CONFIG_JOYSTICK_GRIP) += grip.o +obj-$(CONFIG_JOYSTICK_GRIP_MP) += grip_mp.o +obj-$(CONFIG_JOYSTICK_GUILLEMOT) += guillemot.o +obj-$(CONFIG_JOYSTICK_INTERACT) += interact.o +obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o +obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o +obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o +obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o +obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o +obj-$(CONFIG_JOYSTICK_STINGER) += stinger.o +obj-$(CONFIG_JOYSTICK_TMDC) += tmdc.o +obj-$(CONFIG_JOYSTICK_TURBOGRAFX) += turbografx.o +obj-$(CONFIG_JOYSTICK_TWIDJOY) += twidjoy.o +obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o + +obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/ diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c new file mode 100644 index 00000000000..ad39fe4bf35 --- /dev/null +++ b/drivers/input/joystick/a3d.c @@ -0,0 +1,417 @@ +/* + * $Id: a3d.c,v 1.21 2002/01/22 20:11:50 vojtech Exp $ + * + * Copyright (c) 1998-2001 Vojtech Pavlik + */ + +/* + * FP-Gaming Assasin 3D joystick 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 "FP-Gaming Assasin 3D joystick driver" + +MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +#define A3D_MAX_START 600 /* 600 us */ +#define A3D_MAX_STROBE 80 /* 80 us */ +#define A3D_MAX_LENGTH 40 /* 40*3 bits */ + +#define A3D_MODE_A3D 1 /* Assassin 3D */ +#define A3D_MODE_PAN 2 /* Panther */ +#define A3D_MODE_OEM 3 /* Panther OEM version */ +#define A3D_MODE_PXL 4 /* Panther XL */ + +static char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", "OEM Panther", + "MadCatz Panther XL", "MadCatz Panther XL w/ rudder" }; + +struct a3d { + struct gameport *gameport; + struct gameport *adc; + struct input_dev dev; + int axes[4]; + int buttons; + int mode; + int length; + int reads; + int bads; + char phys[32]; +}; + +/* + * a3d_read_packet() reads an Assassin 3D packet. + */ + +static int a3d_read_packet(struct gameport *gameport, int length, char *data) +{ + unsigned long flags; + unsigned char u, v; + unsigned int t, s; + int i; + + i = 0; + t = gameport_time(gameport, A3D_MAX_START); + s = gameport_time(gameport, A3D_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 & 0x10) { + data[i++] = v >> 5; + t = s; + } + } + + local_irq_restore(flags); + + return i; +} + +/* + * a3d_csum() computes checksum of triplet packet + */ + +static int a3d_csum(char *data, int count) +{ + int i, csum = 0; + + for (i = 0; i < count - 2; i++) + csum += data[i]; + return (csum & 0x3f) != ((data[count - 2] << 3) | data[count - 1]); +} + +static void a3d_read(struct a3d *a3d, unsigned char *data) +{ + struct input_dev *dev = &a3d->dev; + + switch (a3d->mode) { + + case A3D_MODE_A3D: + case A3D_MODE_OEM: + case A3D_MODE_PAN: + + input_report_rel(dev, REL_X, ((data[5] << 6) | (data[6] << 3) | data[ 7]) - ((data[5] & 4) << 7)); + input_report_rel(dev, REL_Y, ((data[8] << 6) | (data[9] << 3) | data[10]) - ((data[8] & 4) << 7)); + + input_report_key(dev, BTN_RIGHT, data[2] & 1); + input_report_key(dev, BTN_LEFT, data[3] & 2); + input_report_key(dev, BTN_MIDDLE, data[3] & 4); + + input_sync(dev); + + a3d->axes[0] = ((signed char)((data[11] << 6) | (data[12] << 3) | (data[13]))) + 128; + a3d->axes[1] = ((signed char)((data[14] << 6) | (data[15] << 3) | (data[16]))) + 128; + a3d->axes[2] = ((signed char)((data[17] << 6) | (data[18] << 3) | (data[19]))) + 128; + a3d->axes[3] = ((signed char)((data[20] << 6) | (data[21] << 3) | (data[22]))) + 128; + + a3d->buttons = ((data[3] << 3) | data[4]) & 0xf; + + break; + + case A3D_MODE_PXL: + + input_report_rel(dev, REL_X, ((data[ 9] << 6) | (data[10] << 3) | data[11]) - ((data[ 9] & 4) << 7)); + input_report_rel(dev, REL_Y, ((data[12] << 6) | (data[13] << 3) | data[14]) - ((data[12] & 4) << 7)); + + input_report_key(dev, BTN_RIGHT, data[2] & 1); + input_report_key(dev, BTN_LEFT, data[3] & 2); + input_report_key(dev, BTN_MIDDLE, data[3] & 4); + input_report_key(dev, BTN_SIDE, data[7] & 2); + input_report_key(dev, BTN_EXTRA, data[7] & 4); + + input_report_abs(dev, ABS_X, ((signed char)((data[15] << 6) | (data[16] << 3) | (data[17]))) + 128); + input_report_abs(dev, ABS_Y, ((signed char)((data[18] << 6) | (data[19] << 3) | (data[20]))) + 128); + input_report_abs(dev, ABS_RUDDER, ((signed char)((data[21] << 6) | (data[22] << 3) | (data[23]))) + 128); + input_report_abs(dev, ABS_THROTTLE, ((signed char)((data[24] << 6) | (data[25] << 3) | (data[26]))) + 128); + + input_report_abs(dev, ABS_HAT0X, ( data[5] & 1) - ((data[5] >> 2) & 1)); + input_report_abs(dev, ABS_HAT0Y, ((data[5] >> 1) & 1) - ((data[6] >> 2) & 1)); + input_report_abs(dev, ABS_HAT1X, ((data[4] >> 1) & 1) - ( data[3] & 1)); + input_report_abs(dev, ABS_HAT1Y, ((data[4] >> 2) & 1) - ( data[4] & 1)); + + input_report_key(dev, BTN_TRIGGER, data[8] & 1); + input_report_key(dev, BTN_THUMB, data[8] & 2); + input_report_key(dev, BTN_TOP, data[8] & 4); + input_report_key(dev, BTN_PINKIE, data[7] & 1); + + input_sync(dev); + + break; + } +} + + +/* + * a3d_poll() reads and analyzes A3D joystick data. + */ + +static void a3d_poll(struct gameport *gameport) +{ + struct a3d *a3d = gameport_get_drvdata(gameport); + unsigned char data[A3D_MAX_LENGTH]; + + a3d->reads++; + if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length || + data[0] != a3d->mode || a3d_csum(data, a3d->length)) + a3d->bads++; + else + a3d_read(a3d, data); +} + +/* + * a3d_adc_cooked_read() copies the acis and button data to the + * callers arrays. It could do the read itself, but the caller could + * call this more than 50 times a second, which would use too much CPU. + */ + +static int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons) +{ + struct a3d *a3d = gameport->port_data; + int i; + + for (i = 0; i < 4; i++) + axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1; + *buttons = a3d->buttons; + return 0; +} + +/* + * a3d_adc_open() is the gameport open routine. It refuses to serve + * any but cooked data. + */ + +static int a3d_adc_open(struct gameport *gameport, int mode) +{ + struct a3d *a3d = gameport->port_data; + + if (mode != GAMEPORT_MODE_COOKED) + return -1; + + gameport_start_polling(a3d->gameport); + return 0; +} + +/* + * a3d_adc_close() is a callback from the input close routine. + */ + +static void a3d_adc_close(struct gameport *gameport) +{ + struct a3d *a3d = gameport->port_data; + + gameport_stop_polling(a3d->gameport); +} + +/* + * a3d_open() is a callback from the input open routine. + */ + +static int a3d_open(struct input_dev *dev) +{ + struct a3d *a3d = dev->private; + + gameport_start_polling(a3d->gameport); + return 0; +} + +/* + * a3d_close() is a callback from the input close routine. + */ + +static void a3d_close(struct input_dev *dev) +{ + struct a3d *a3d = dev->private; + + gameport_stop_polling(a3d->gameport); +} + +/* + * a3d_connect() probes for A3D joysticks. + */ + +static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) +{ + struct a3d *a3d; + struct gameport *adc; + unsigned char data[A3D_MAX_LENGTH]; + int i; + int err; + + if (!(a3d = kcalloc(1, sizeof(struct a3d), GFP_KERNEL))) + return -ENOMEM; + + a3d->gameport = gameport; + + gameport_set_drvdata(gameport, a3d); + + err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW); + if (err) + goto fail1; + + i = a3d_read_packet(gameport, A3D_MAX_LENGTH, data); + + if (!i || a3d_csum(data, i)) { + err = -ENODEV; + goto fail2; + } + + a3d->mode = data[0]; + + if (!a3d->mode || a3d->mode > 5) { + printk(KERN_WARNING "a3d.c: Unknown A3D device detected " + "(%s, id=%d), contact <vojtech@ucw.cz>\n", gameport->phys, a3d->mode); + err = -ENODEV; + goto fail2; + } + + gameport_set_poll_handler(gameport, a3d_poll); + gameport_set_poll_interval(gameport, 20); + + sprintf(a3d->phys, "%s/input0", gameport->phys); + + if (a3d->mode == A3D_MODE_PXL) { + + int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER }; + + a3d->length = 33; + + init_input_dev(&a3d->dev); + + a3d->dev.evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL); + a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y); + a3d->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER) + | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y); + + a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE) + | BIT(BTN_SIDE) | BIT(BTN_EXTRA); + + a3d->dev.keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_PINKIE); + + a3d_read(a3d, data); + + for (i = 0; i < 4; i++) { + if (i < 2) + input_set_abs_params(&a3d->dev, axes[i], 48, a3d->dev.abs[axes[i]] * 2 - 48, 0, 8); + else + input_set_abs_params(&a3d->dev, axes[i], 2, 253, 0, 0); + input_set_abs_params(&a3d->dev, ABS_HAT0X + i, -1, 1, 0, 0); + } + + } else { + a3d->length = 29; + + init_input_dev(&a3d->dev); + + a3d->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL); + a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y); + a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE); + + a3d_read(a3d, data); + + if (!(a3d->adc = adc = gameport_allocate_port())) + printk(KERN_ERR "a3d: Not enough memory for ADC port\n"); + else { + adc->port_data = a3d; + adc->open = a3d_adc_open; + adc->close = a3d_adc_close; + adc->cooked_read = a3d_adc_cooked_read; + adc->fuzz = 1; + + gameport_set_name(adc, a3d_names[a3d->mode]); + gameport_set_phys(adc, "%s/gameport0", gameport->phys); + adc->dev.parent = &gameport->dev; + + gameport_register_port(adc); + } + } + + a3d->dev.private = a3d; + a3d->dev.open = a3d_open; + a3d->dev.close = a3d_close; + + a3d->dev.name = a3d_names[a3d->mode]; + a3d->dev.phys = a3d->phys; + a3d->dev.id.bustype = BUS_GAMEPORT; + a3d->dev.id.vendor = GAMEPORT_ID_VENDOR_MADCATZ; + a3d->dev.id.product = a3d->mode; + a3d->dev.id.version = 0x0100; + + input_register_device(&a3d->dev); + printk(KERN_INFO "input: %s on %s\n", a3d_names[a3d->mode], a3d->phys); + + return 0; + +fail2: gameport_close(gameport); +fail1: gameport_set_drvdata(gameport, NULL); + kfree(a3d); + return err; +} + +static void a3d_disconnect(struct gameport *gameport) +{ + struct a3d *a3d = gameport_get_drvdata(gameport); + + input_unregister_device(&a3d->dev); + if (a3d->adc) { + gameport_unregister_port(a3d->adc); + a3d->adc = NULL; + } + gameport_close(gameport); + gameport_set_drvdata(gameport, NULL); + kfree(a3d); +} + +static struct gameport_driver a3d_drv = { + .driver = { + .name = "adc", + }, + .description = DRIVER_DESC, + .connect = a3d_connect, + .disconnect = a3d_disconnect, +}; + +static int __init a3d_init(void) +{ + gameport_register_driver(&a3d_drv); + return 0; +} + +static void __exit a3d_exit(void) +{ + gameport_unregister_driver(&a3d_drv); +} + +module_init(a3d_init); +module_exit(a3d_exit); diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c new file mode 100644 index 00000000000..83f6dafc171 --- /dev/null +++ b/drivers/input/joystick/adi.c @@ -0,0 +1,560 @@ +/* + * Copyright (c) 1998-2005 Vojtech Pavlik + */ + +/* + * Logitech ADI joystick family 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/delay.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/gameport.h> +#include <linux/init.h> + +#define DRIVER_DESC "Logitech ADI joystick family driver" + +MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + +/* + * Times, array sizes, flags, ids. + */ + +#define ADI_MAX_START 200 /* Trigger to packet timeout [200us] */ +#define ADI_MAX_STROBE 40 /* Single bit timeout [40us] */ +#define ADI_INIT_DELAY 10 /* Delay after init packet [10ms] */ +#define ADI_DATA_DELAY 4 /* Delay after data packet [4ms] */ + +#define ADI_MAX_LENGTH 256 +#define ADI_MIN_LENGTH 8 +#define ADI_MIN_LEN_LENGTH 10 +#define ADI_MIN_ID_LENGTH 66 +#define ADI_MAX_NAME_LENGTH 48 +#define ADI_MAX_CNAME_LENGTH 16 +#define ADI_MAX_PHYS_LENGTH 64 + +#define ADI_FLAG_HAT 0x04 +#define ADI_FLAG_10BIT 0x08 + +#define ADI_ID_TPD 0x01 +#define ADI_ID_WGP 0x06 +#define ADI_ID_WGPE 0x08 +#define ADI_ID_MAX 0x0a + +/* + * Names, buttons, axes ... + */ + +static char *adi_names[] = { "WingMan Extreme Digital", "ThunderPad Digital", "SideCar", "CyberMan 2", + "WingMan Interceptor", "WingMan Formula", "WingMan GamePad", + "WingMan Extreme Digital 3D", "WingMan GamePad Extreme", + "WingMan GamePad USB", "Unknown Device %#x" }; + +static char adi_wmgpe_abs[] = { ABS_X, ABS_Y, ABS_HAT0X, ABS_HAT0Y }; +static char adi_wmi_abs[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y }; +static char adi_wmed3d_abs[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RZ, ABS_HAT0X, ABS_HAT0Y }; +static char adi_cm2_abs[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ }; +static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y }; + +static short adi_wmgpe_key[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT }; +static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA }; +static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 }; +static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 }; + +static char* adi_abs[] = { adi_wmi_abs, adi_wmgpe_abs, adi_wmf_abs, adi_cm2_abs, adi_wmi_abs, adi_wmf_abs, + adi_wmgpe_abs, adi_wmed3d_abs, adi_wmgpe_abs, adi_wmgpe_abs, adi_wmi_abs }; + +static short* adi_key[] = { adi_wmi_key, adi_wmgpe_key, adi_cm2_key, adi_cm2_key, adi_wmi_key, adi_cm2_key, + adi_wmgpe_key, adi_wmed3d_key, adi_wmgpe_key, adi_wmgpe_key, adi_wmi_key }; + +/* + * Hat to axis conversion arrays. + */ + +static struct { + int x; + int y; +} adi_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}}; + |