aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/joystick
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /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')
-rw-r--r--drivers/input/joystick/Kconfig256
-rw-r--r--drivers/input/joystick/Makefile30
-rw-r--r--drivers/input/joystick/a3d.c417
-rw-r--r--drivers/input/joystick/adi.c560
-rw-r--r--drivers/input/joystick/amijoy.c161
-rw-r--r--drivers/input/joystick/analog.c772
-rw-r--r--drivers/input/joystick/cobra.c264
-rw-r--r--drivers/input/joystick/db9.c647
-rw-r--r--drivers/input/joystick/gamecon.c697
-rw-r--r--drivers/input/joystick/gf2k.c380
-rw-r--r--drivers/input/joystick/grip.c422
-rw-r--r--drivers/input/joystick/grip_mp.c677
-rw-r--r--drivers/input/joystick/guillemot.c289
-rw-r--r--drivers/input/joystick/iforce/Kconfig32
-rw-r--r--drivers/input/joystick/iforce/Makefile20
-rw-r--r--drivers/input/joystick/iforce/iforce-ff.c543
-rw-r--r--drivers/input/joystick/iforce/iforce-main.c557
-rw-r--r--drivers/input/joystick/iforce/iforce-packets.c319
-rw-r--r--drivers/input/joystick/iforce/iforce-serio.c193
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c243
-rw-r--r--drivers/input/joystick/iforce/iforce.h191
-rw-r--r--drivers/input/joystick/interact.c322
-rw-r--r--drivers/input/joystick/joydump.c175
-rw-r--r--drivers/input/joystick/magellan.c247
-rw-r--r--drivers/input/joystick/sidewinder.c807
-rw-r--r--drivers/input/joystick/spaceball.c319
-rw-r--r--drivers/input/joystick/spaceorb.c263
-rw-r--r--drivers/input/joystick/stinger.c236
-rw-r--r--drivers/input/joystick/tmdc.c384
-rw-r--r--drivers/input/joystick/turbografx.c258
-rw-r--r--drivers/input/joystick/twidjoy.c296
-rw-r--r--drivers/input/joystick/warrior.c248
32 files changed, 11225 insertions, 0 deletions
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
new file mode 100644
index 000000000000..67519ef0ef95
--- /dev/null
+++ b/drivers/input/joystick/Kconfig
@@ -0,0 +1,256 @@
1#
2# Joystick driver configuration
3#
4menuconfig INPUT_JOYSTICK
5 bool "Joysticks"
6 help
7 If you have a joystick, 6dof controller, gamepad, steering wheel,
8 weapon control system or something like that you can say Y here
9 and the list of supported devices will be displayed. This option
10 doesn't affect the kernel.
11
12 Please read the file <file:Documentation/input/joystick.txt> which
13 contains more information.
14
15if INPUT_JOYSTICK
16
17config JOYSTICK_ANALOG
18 tristate "Classic PC analog joysticks and gamepads"
19 select GAMEPORT
20 ---help---
21 Say Y here if you have a joystick that connects to the PC
22 gameport. In addition to the usual PC analog joystick, this driver
23 supports many extensions, including joysticks with throttle control,
24 with rudders, additional hats and buttons compatible with CH
25 Flightstick Pro, ThrustMaster FCS, 6 and 8 button gamepads, or
26 Saitek Cyborg joysticks.
27
28 Please read the file <file:Documentation/input/joystick.txt> which
29 contains more information.
30
31 To compile this driver as a module, choose M here: the
32 module will be called analog.
33
34config JOYSTICK_A3D
35 tristate "Assasin 3D and MadCatz Panther devices"
36 select GAMEPORT
37 help
38 Say Y here if you have an FPGaming or MadCatz controller using the
39 A3D protocol over the PC gameport.
40
41 To compile this driver as a module, choose M here: the
42 module will be called a3d.
43
44config JOYSTICK_ADI
45 tristate "Logitech ADI digital joysticks and gamepads"
46 select GAMEPORT
47 help
48 Say Y here if you have a Logitech controller using the ADI
49 protocol over the PC gameport.
50
51 To compile this driver as a module, choose M here: the
52 module will be called adi.
53
54config JOYSTICK_COBRA
55 tristate "Creative Labs Blaster Cobra gamepad"
56 select GAMEPORT
57 help
58 Say Y here if you have a Creative Labs Blaster Cobra gamepad.
59
60 To compile this driver as a module, choose M here: the
61 module will be called cobra.
62
63config JOYSTICK_GF2K
64 tristate "Genius Flight2000 Digital joysticks and gamepads"
65 select GAMEPORT
66 help
67 Say Y here if you have a Genius Flight2000 or MaxFighter digitally
68 communicating joystick or gamepad.
69
70 To compile this driver as a module, choose M here: the
71 module will be called gf2k.
72
73config JOYSTICK_GRIP
74 tristate "Gravis GrIP joysticks and gamepads"
75 select GAMEPORT
76 help
77 Say Y here if you have a Gravis controller using the GrIP protocol
78 over the PC gameport.
79
80 To compile this driver as a module, choose M here: the
81 module will be called grip.
82
83config JOYSTICK_GRIP_MP
84 tristate "Gravis GrIP MultiPort"
85 select GAMEPORT
86 help
87 Say Y here if you have the original Gravis GrIP MultiPort, a hub
88 that connects to the gameport and you connect gamepads to it.
89
90 To compile this driver as a module, choose M here: the
91 module will be called grip_mp.
92
93config JOYSTICK_GUILLEMOT
94 tristate "Guillemot joysticks and gamepads"
95 select GAMEPORT
96 help
97 Say Y here if you have a Guillemot joystick using a digital
98 protocol over the PC gameport.
99
100 To compile this driver as a module, choose M here: the
101 module will be called guillemot.
102
103config JOYSTICK_INTERACT
104 tristate "InterAct digital joysticks and gamepads"
105 select GAMEPORT
106 help
107 Say Y here if you have an InterAct gameport or joystick
108 communicating digitally over the gameport.
109
110 To compile this driver as a module, choose M here: the
111 module will be called interact.
112
113config JOYSTICK_SIDEWINDER
114 tristate "Microsoft SideWinder digital joysticks and gamepads"
115 select GAMEPORT
116 help
117 Say Y here if you have a Microsoft controller using the Digital
118 Overdrive protocol over PC gameport.
119
120 To compile this driver as a module, choose M here: the
121 module will be called sidewinder.
122
123config JOYSTICK_TMDC
124 tristate "ThrustMaster DirectConnect joysticks and gamepads"
125 select GAMEPORT
126 help
127 Say Y here if you have a ThrustMaster controller using the
128 DirectConnect (BSP) protocol over the PC gameport.
129
130 To compile this driver as a module, choose M here: the
131 module will be called tmdc.
132
133source "drivers/input/joystick/iforce/Kconfig"
134
135config JOYSTICK_WARRIOR
136 tristate "Logitech WingMan Warrior joystick"
137 select SERIO
138 help
139 Say Y here if you have a Logitech WingMan Warrior joystick connected
140 to your computer's serial port.
141
142 To compile this driver as a module, choose M here: the
143 module will be called warrior.
144
145config JOYSTICK_MAGELLAN
146 tristate "LogiCad3d Magellan/SpaceMouse 6dof controllers"
147 select SERIO
148 help
149 Say Y here if you have a Magellan or Space Mouse 6DOF controller
150 connected to your computer's serial port.
151
152 To compile this driver as a module, choose M here: the
153 module will be called magellan.
154
155config JOYSTICK_SPACEORB
156 tristate "SpaceTec SpaceOrb/Avenger 6dof controllers"
157 select SERIO
158 help
159 Say Y here if you have a SpaceOrb 360 or SpaceBall Avenger 6DOF
160 controller connected to your computer's serial port.
161
162 To compile this driver as a module, choose M here: the
163 module will be called spaceorb.
164
165config JOYSTICK_SPACEBALL
166 tristate "SpaceTec SpaceBall 6dof controllers"
167 select SERIO
168 help
169 Say Y here if you have a SpaceTec SpaceBall 2003/3003/4000 FLX
170 controller connected to your computer's serial port. For the
171 SpaceBall 4000 USB model, use the USB HID driver.
172
173 To compile this driver as a module, choose M here: the
174 module will be called spaceball.
175
176config JOYSTICK_STINGER
177 tristate "Gravis Stinger gamepad"
178 select SERIO
179 help
180 Say Y here if you have a Gravis Stinger connected to one of your
181 serial ports.
182
183 To compile this driver as a module, choose M here: the
184 module will be called stinger.
185
186config JOYSTICK_TWIDJOY
187 tristate "Twiddler as a joystick"
188 select SERIO
189 help
190 Say Y here if you have a Handykey Twiddler connected to your
191 computer's serial port and want to use it as a joystick.
192
193 To compile this driver as a module, choose M here: the
194 module will be called twidjoy.
195
196config JOYSTICK_DB9
197 tristate "Multisystem, Sega Genesis, Saturn joysticks and gamepads"
198 depends on PARPORT
199 ---help---
200 Say Y here if you have a Sega Master System gamepad, Sega Genesis
201 gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
202 Commodore, Amstrad CPC joystick connected to your parallel port.
203 For more information on how to use the driver please read
204 <file:Documentation/input/joystick-parport.txt>.
205
206 To compile this driver as a module, choose M here: the
207 module will be called db9.
208
209config JOYSTICK_GAMECON
210 tristate "Multisystem, NES, SNES, N64, PSX joysticks and gamepads"
211 depends on PARPORT
212 ---help---
213 Say Y here if you have a Nintendo Entertainment System gamepad,
214 Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad,
215 Sony PlayStation gamepad or a Multisystem -- Atari, Amiga,
216 Commodore, Amstrad CPC joystick connected to your parallel port.
217 For more information on how to use the driver please read
218 <file:Documentation/input/joystick-parport.txt>.
219
220 To compile this driver as a module, choose M here: the
221 module will be called gamecon.
222
223config JOYSTICK_TURBOGRAFX
224 tristate "Multisystem joysticks via TurboGraFX device"
225 depends on PARPORT
226 help
227 Say Y here if you have the TurboGraFX interface by Steffen Schwenke,
228 and want to use it with Multisystem -- Atari, Amiga, Commodore,
229 Amstrad CPC joystick. For more information on how to use the driver
230 please read <file:Documentation/input/joystick-parport.txt>.
231
232 To compile this driver as a module, choose M here: the
233 module will be called turbografx.
234
235config JOYSTICK_AMIGA
236 tristate "Amiga joysticks"
237 depends on AMIGA
238 help
239 Say Y here if you have an Amiga with a digital joystick connected
240 to it.
241
242 To compile this driver as a module, choose M here: the
243 module will be called amijoy.
244
245config JOYSTICK_JOYDUMP
246 tristate "Gameport data dumper"
247 select GAMEPORT
248 help
249 Say Y here if you want to dump data from your joystick into the system
250 log for debugging purposes. Say N if you are making a production
251 configuration or aren't sure.
252
253 To compile this driver as a module, choose M here: the
254 module will be called joydump.
255
256endif
diff --git a/drivers/input/joystick/Makefile b/drivers/input/joystick/Makefile
new file mode 100644
index 000000000000..5231f6ff75b8
--- /dev/null
+++ b/drivers/input/joystick/Makefile
@@ -0,0 +1,30 @@
1#
2# Makefile for the input core drivers.
3#
4
5# Each configuration option enables a list of files.
6
7obj-$(CONFIG_JOYSTICK_A3D) += a3d.o
8obj-$(CONFIG_JOYSTICK_ADI) += adi.o
9obj-$(CONFIG_JOYSTICK_AMIGA) += amijoy.o
10obj-$(CONFIG_JOYSTICK_ANALOG) += analog.o
11obj-$(CONFIG_JOYSTICK_COBRA) += cobra.o
12obj-$(CONFIG_JOYSTICK_DB9) += db9.o
13obj-$(CONFIG_JOYSTICK_GAMECON) += gamecon.o
14obj-$(CONFIG_JOYSTICK_GF2K) += gf2k.o
15obj-$(CONFIG_JOYSTICK_GRIP) += grip.o
16obj-$(CONFIG_JOYSTICK_GRIP_MP) += grip_mp.o
17obj-$(CONFIG_JOYSTICK_GUILLEMOT) += guillemot.o
18obj-$(CONFIG_JOYSTICK_INTERACT) += interact.o
19obj-$(CONFIG_JOYSTICK_JOYDUMP) += joydump.o
20obj-$(CONFIG_JOYSTICK_MAGELLAN) += magellan.o
21obj-$(CONFIG_JOYSTICK_SIDEWINDER) += sidewinder.o
22obj-$(CONFIG_JOYSTICK_SPACEBALL) += spaceball.o
23obj-$(CONFIG_JOYSTICK_SPACEORB) += spaceorb.o
24obj-$(CONFIG_JOYSTICK_STINGER) += stinger.o
25obj-$(CONFIG_JOYSTICK_TMDC) += tmdc.o
26obj-$(CONFIG_JOYSTICK_TURBOGRAFX) += turbografx.o
27obj-$(CONFIG_JOYSTICK_TWIDJOY) += twidjoy.o
28obj-$(CONFIG_JOYSTICK_WARRIOR) += warrior.o
29
30obj-$(CONFIG_JOYSTICK_IFORCE) += iforce/
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
new file mode 100644
index 000000000000..ad39fe4bf35f
--- /dev/null
+++ b/drivers/input/joystick/a3d.c
@@ -0,0 +1,417 @@
1/*
2 * $Id: a3d.c,v 1.21 2002/01/22 20:11:50 vojtech Exp $
3 *
4 * Copyright (c) 1998-2001 Vojtech Pavlik
5 */
6
7/*
8 * FP-Gaming Assasin 3D joystick driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/slab.h>
34#include <linux/init.h>
35#include <linux/gameport.h>
36#include <linux/input.h>
37
38#define DRIVER_DESC "FP-Gaming Assasin 3D joystick driver"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44#define A3D_MAX_START 600 /* 600 us */
45#define A3D_MAX_STROBE 80 /* 80 us */
46#define A3D_MAX_LENGTH 40 /* 40*3 bits */
47
48#define A3D_MODE_A3D 1 /* Assassin 3D */
49#define A3D_MODE_PAN 2 /* Panther */
50#define A3D_MODE_OEM 3 /* Panther OEM version */
51#define A3D_MODE_PXL 4 /* Panther XL */
52
53static char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", "OEM Panther",
54 "MadCatz Panther XL", "MadCatz Panther XL w/ rudder" };
55
56struct a3d {
57 struct gameport *gameport;
58 struct gameport *adc;
59 struct input_dev dev;
60 int axes[4];
61 int buttons;
62 int mode;
63 int length;
64 int reads;
65 int bads;
66 char phys[32];
67};
68
69/*
70 * a3d_read_packet() reads an Assassin 3D packet.
71 */
72
73static int a3d_read_packet(struct gameport *gameport, int length, char *data)
74{
75 unsigned long flags;
76 unsigned char u, v;
77 unsigned int t, s;
78 int i;
79
80 i = 0;
81 t = gameport_time(gameport, A3D_MAX_START);
82 s = gameport_time(gameport, A3D_MAX_STROBE);
83
84 local_irq_save(flags);
85 gameport_trigger(gameport);
86 v = gameport_read(gameport);
87
88 while (t > 0 && i < length) {
89 t--;
90 u = v; v = gameport_read(gameport);
91 if (~v & u & 0x10) {
92 data[i++] = v >> 5;
93 t = s;
94 }
95 }
96
97 local_irq_restore(flags);
98
99 return i;
100}
101
102/*
103 * a3d_csum() computes checksum of triplet packet
104 */
105
106static int a3d_csum(char *data, int count)
107{
108 int i, csum = 0;
109
110 for (i = 0; i < count - 2; i++)
111 csum += data[i];
112 return (csum & 0x3f) != ((data[count - 2] << 3) | data[count - 1]);
113}
114
115static void a3d_read(struct a3d *a3d, unsigned char *data)
116{
117 struct input_dev *dev = &a3d->dev;
118
119 switch (a3d->mode) {
120
121 case A3D_MODE_A3D:
122 case A3D_MODE_OEM:
123 case A3D_MODE_PAN:
124
125 input_report_rel(dev, REL_X, ((data[5] << 6) | (data[6] << 3) | data[ 7]) - ((data[5] & 4) << 7));
126 input_report_rel(dev, REL_Y, ((data[8] << 6) | (data[9] << 3) | data[10]) - ((data[8] & 4) << 7));
127
128 input_report_key(dev, BTN_RIGHT, data[2] & 1);
129 input_report_key(dev, BTN_LEFT, data[3] & 2);
130 input_report_key(dev, BTN_MIDDLE, data[3] & 4);
131
132 input_sync(dev);
133
134 a3d->axes[0] = ((signed char)((data[11] << 6) | (data[12] << 3) | (data[13]))) + 128;
135 a3d->axes[1] = ((signed char)((data[14] << 6) | (data[15] << 3) | (data[16]))) + 128;
136 a3d->axes[2] = ((signed char)((data[17] << 6) | (data[18] << 3) | (data[19]))) + 128;
137 a3d->axes[3] = ((signed char)((data[20] << 6) | (data[21] << 3) | (data[22]))) + 128;
138
139 a3d->buttons = ((data[3] << 3) | data[4]) & 0xf;
140
141 break;
142
143 case A3D_MODE_PXL:
144
145 input_report_rel(dev, REL_X, ((data[ 9] << 6) | (data[10] << 3) | data[11]) - ((data[ 9] & 4) << 7));
146 input_report_rel(dev, REL_Y, ((data[12] << 6) | (data[13] << 3) | data[14]) - ((data[12] & 4) << 7));
147
148 input_report_key(dev, BTN_RIGHT, data[2] & 1);
149 input_report_key(dev, BTN_LEFT, data[3] & 2);
150 input_report_key(dev, BTN_MIDDLE, data[3] & 4);
151 input_report_key(dev, BTN_SIDE, data[7] & 2);
152 input_report_key(dev, BTN_EXTRA, data[7] & 4);
153
154 input_report_abs(dev, ABS_X, ((signed char)((data[15] << 6) | (data[16] << 3) | (data[17]))) + 128);
155 input_report_abs(dev, ABS_Y, ((signed char)((data[18] << 6) | (data[19] << 3) | (data[20]))) + 128);
156 input_report_abs(dev, ABS_RUDDER, ((signed char)((data[21] << 6) | (data[22] << 3) | (data[23]))) + 128);
157 input_report_abs(dev, ABS_THROTTLE, ((signed char)((data[24] << 6) | (data[25] << 3) | (data[26]))) + 128);
158
159 input_report_abs(dev, ABS_HAT0X, ( data[5] & 1) - ((data[5] >> 2) & 1));
160 input_report_abs(dev, ABS_HAT0Y, ((data[5] >> 1) & 1) - ((data[6] >> 2) & 1));
161 input_report_abs(dev, ABS_HAT1X, ((data[4] >> 1) & 1) - ( data[3] & 1));
162 input_report_abs(dev, ABS_HAT1Y, ((data[4] >> 2) & 1) - ( data[4] & 1));
163
164 input_report_key(dev, BTN_TRIGGER, data[8] & 1);
165 input_report_key(dev, BTN_THUMB, data[8] & 2);
166 input_report_key(dev, BTN_TOP, data[8] & 4);
167 input_report_key(dev, BTN_PINKIE, data[7] & 1);
168
169 input_sync(dev);
170
171 break;
172 }
173}
174
175
176/*
177 * a3d_poll() reads and analyzes A3D joystick data.
178 */
179
180static void a3d_poll(struct gameport *gameport)
181{
182 struct a3d *a3d = gameport_get_drvdata(gameport);
183 unsigned char data[A3D_MAX_LENGTH];
184
185 a3d->reads++;
186 if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length ||
187 data[0] != a3d->mode || a3d_csum(data, a3d->length))
188 a3d->bads++;
189 else
190 a3d_read(a3d, data);
191}
192
193/*
194 * a3d_adc_cooked_read() copies the acis and button data to the
195 * callers arrays. It could do the read itself, but the caller could
196 * call this more than 50 times a second, which would use too much CPU.
197 */
198
199static int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons)
200{
201 struct a3d *a3d = gameport->port_data;
202 int i;
203
204 for (i = 0; i < 4; i++)
205 axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1;
206 *buttons = a3d->buttons;
207 return 0;
208}
209
210/*
211 * a3d_adc_open() is the gameport open routine. It refuses to serve
212 * any but cooked data.
213 */
214
215static int a3d_adc_open(struct gameport *gameport, int mode)
216{
217 struct a3d *a3d = gameport->port_data;
218
219 if (mode != GAMEPORT_MODE_COOKED)
220 return -1;
221
222 gameport_start_polling(a3d->gameport);
223 return 0;
224}
225
226/*
227 * a3d_adc_close() is a callback from the input close routine.
228 */
229
230static void a3d_adc_close(struct gameport *gameport)
231{
232 struct a3d *a3d = gameport->port_data;
233
234 gameport_stop_polling(a3d->gameport);
235}
236
237/*
238 * a3d_open() is a callback from the input open routine.
239 */
240
241static int a3d_open(struct input_dev *dev)
242{
243 struct a3d *a3d = dev->private;
244
245 gameport_start_polling(a3d->gameport);
246 return 0;
247}
248
249/*
250 * a3d_close() is a callback from the input close routine.
251 */
252
253static void a3d_close(struct input_dev *dev)
254{
255 struct a3d *a3d = dev->private;
256
257 gameport_stop_polling(a3d->gameport);
258}
259
260/*
261 * a3d_connect() probes for A3D joysticks.
262 */
263
264static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
265{
266 struct a3d *a3d;
267 struct gameport *adc;
268 unsigned char data[A3D_MAX_LENGTH];
269 int i;
270 int err;
271
272 if (!(a3d = kcalloc(1, sizeof(struct a3d), GFP_KERNEL)))
273 return -ENOMEM;
274
275 a3d->gameport = gameport;
276
277 gameport_set_drvdata(gameport, a3d);
278
279 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
280 if (err)
281 goto fail1;
282
283 i = a3d_read_packet(gameport, A3D_MAX_LENGTH, data);
284
285 if (!i || a3d_csum(data, i)) {
286 err = -ENODEV;
287 goto fail2;
288 }
289
290 a3d->mode = data[0];
291
292 if (!a3d->mode || a3d->mode > 5) {
293 printk(KERN_WARNING "a3d.c: Unknown A3D device detected "
294 "(%s, id=%d), contact <vojtech@ucw.cz>\n", gameport->phys, a3d->mode);
295 err = -ENODEV;
296 goto fail2;
297 }
298
299 gameport_set_poll_handler(gameport, a3d_poll);
300 gameport_set_poll_interval(gameport, 20);
301
302 sprintf(a3d->phys, "%s/input0", gameport->phys);
303
304 if (a3d->mode == A3D_MODE_PXL) {
305
306 int axes[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER };
307
308 a3d->length = 33;
309
310 init_input_dev(&a3d->dev);
311
312 a3d->dev.evbit[0] |= BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL);
313 a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
314 a3d->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_RUDDER)
315 | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y) | BIT(ABS_HAT1X) | BIT(ABS_HAT1Y);
316
317 a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE)
318 | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
319
320 a3d->dev.keybit[LONG(BTN_JOYSTICK)] |= BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_PINKIE);
321
322 a3d_read(a3d, data);
323
324 for (i = 0; i < 4; i++) {
325 if (i < 2)
326 input_set_abs_params(&a3d->dev, axes[i], 48, a3d->dev.abs[axes[i]] * 2 - 48, 0, 8);
327 else
328 input_set_abs_params(&a3d->dev, axes[i], 2, 253, 0, 0);
329 input_set_abs_params(&a3d->dev, ABS_HAT0X + i, -1, 1, 0, 0);
330 }
331
332 } else {
333 a3d->length = 29;
334
335 init_input_dev(&a3d->dev);
336
337 a3d->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL);
338 a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
339 a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
340
341 a3d_read(a3d, data);
342
343 if (!(a3d->adc = adc = gameport_allocate_port()))
344 printk(KERN_ERR "a3d: Not enough memory for ADC port\n");
345 else {
346 adc->port_data = a3d;
347 adc->open = a3d_adc_open;
348 adc->close = a3d_adc_close;
349 adc->cooked_read = a3d_adc_cooked_read;
350 adc->fuzz = 1;
351
352 gameport_set_name(adc, a3d_names[a3d->mode]);
353 gameport_set_phys(adc, "%s/gameport0", gameport->phys);
354 adc->dev.parent = &gameport->dev;
355
356 gameport_register_port(adc);
357 }
358 }
359
360 a3d->dev.private = a3d;
361 a3d->dev.open = a3d_open;
362 a3d->dev.close = a3d_close;
363
364 a3d->dev.name = a3d_names[a3d->mode];
365 a3d->dev.phys = a3d->phys;
366 a3d->dev.id.bustype = BUS_GAMEPORT;
367 a3d->dev.id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
368 a3d->dev.id.product = a3d->mode;
369 a3d->dev.id.version = 0x0100;
370
371 input_register_device(&a3d->dev);
372 printk(KERN_INFO "input: %s on %s\n", a3d_names[a3d->mode], a3d->phys);
373
374 return 0;
375
376fail2: gameport_close(gameport);
377fail1: gameport_set_drvdata(gameport, NULL);
378 kfree(a3d);
379 return err;
380}
381
382static void a3d_disconnect(struct gameport *gameport)
383{
384 struct a3d *a3d = gameport_get_drvdata(gameport);
385
386 input_unregister_device(&a3d->dev);
387 if (a3d->adc) {
388 gameport_unregister_port(a3d->adc);
389 a3d->adc = NULL;
390 }
391 gameport_close(gameport);
392 gameport_set_drvdata(gameport, NULL);
393 kfree(a3d);
394}
395
396static struct gameport_driver a3d_drv = {
397 .driver = {
398 .name = "adc",
399 },
400 .description = DRIVER_DESC,
401 .connect = a3d_connect,
402 .disconnect = a3d_disconnect,
403};
404
405static int __init a3d_init(void)
406{
407 gameport_register_driver(&a3d_drv);
408 return 0;
409}
410
411static void __exit a3d_exit(void)
412{
413 gameport_unregister_driver(&a3d_drv);
414}
415
416module_init(a3d_init);
417module_exit(a3d_exit);
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
new file mode 100644
index 000000000000..83f6dafc1716
--- /dev/null
+++ b/drivers/input/joystick/adi.c
@@ -0,0 +1,560 @@
1/*
2 * Copyright (c) 1998-2005 Vojtech Pavlik
3 */
4
5/*
6 * Logitech ADI joystick family driver for Linux
7 */
8
9/*
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Should you need to contact me, the author, you can do so either by
25 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
26 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
27 */
28
29#include <linux/delay.h>
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/string.h>
33#include <linux/slab.h>
34#include <linux/input.h>
35#include <linux/gameport.h>
36#include <linux/init.h>
37
38#define DRIVER_DESC "Logitech ADI joystick family driver"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44/*
45 * Times, array sizes, flags, ids.
46 */
47
48#define ADI_MAX_START 200 /* Trigger to packet timeout [200us] */
49#define ADI_MAX_STROBE 40 /* Single bit timeout [40us] */
50#define ADI_INIT_DELAY 10 /* Delay after init packet [10ms] */
51#define ADI_DATA_DELAY 4 /* Delay after data packet [4ms] */
52
53#define ADI_MAX_LENGTH 256
54#define ADI_MIN_LENGTH 8
55#define ADI_MIN_LEN_LENGTH 10
56#define ADI_MIN_ID_LENGTH 66
57#define ADI_MAX_NAME_LENGTH 48
58#define ADI_MAX_CNAME_LENGTH 16
59#define ADI_MAX_PHYS_LENGTH 64
60
61#define ADI_FLAG_HAT 0x04
62#define ADI_FLAG_10BIT 0x08
63
64#define ADI_ID_TPD 0x01
65#define ADI_ID_WGP 0x06
66#define ADI_ID_WGPE 0x08
67#define ADI_ID_MAX 0x0a
68
69/*
70 * Names, buttons, axes ...
71 */
72
73static char *adi_names[] = { "WingMan Extreme Digital", "ThunderPad Digital", "SideCar", "CyberMan 2",
74 "WingMan Interceptor", "WingMan Formula", "WingMan GamePad",
75 "WingMan Extreme Digital 3D", "WingMan GamePad Extreme",
76 "WingMan GamePad USB", "Unknown Device %#x" };
77
78static char adi_wmgpe_abs[] = { ABS_X, ABS_Y, ABS_HAT0X, ABS_HAT0Y };
79static char adi_wmi_abs[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
80static char adi_wmed3d_abs[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RZ, ABS_HAT0X, ABS_HAT0Y };
81static char adi_cm2_abs[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
82static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
83
84static 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 };
85static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA };
86static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 };
87static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 };
88
89static char* adi_abs[] = { adi_wmi_abs, adi_wmgpe_abs, adi_wmf_abs, adi_cm2_abs, adi_wmi_abs, adi_wmf_abs,
90 adi_wmgpe_abs, adi_wmed3d_abs, adi_wmgpe_abs, adi_wmgpe_abs, adi_wmi_abs };
91
92static short* adi_key[] = { adi_wmi_key, adi_wmgpe_key, adi_cm2_key, adi_cm2_key, adi_wmi_key, adi_cm2_key,
93 adi_wmgpe_key, adi_wmed3d_key, adi_wmgpe_key, adi_wmgpe_key, adi_wmi_key };
94
95/*
96 * Hat to axis conversion arrays.
97 */
98
99static struct {
100 int x;
101 int y;
102} adi_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
103
104/*
105 * Per-port information.
106 */
107
108struct adi {
109 struct input_dev dev;
110 int length;
111 int ret;
112 int idx;
113 unsigned char id;
114 char buttons;
115 char axes10;
116 char axes8;
117 signed char pad;
118 char hats;
119 char *abs;
120 short *key;
121 char name[ADI_MAX_NAME_LENGTH];
122 char cname[ADI_MAX_CNAME_LENGTH];
123 char phys[ADI_MAX_PHYS_LENGTH];
124 unsigned char data[ADI_MAX_LENGTH];
125};
126
127struct adi_port {
128 struct gameport *gameport;
129 struct adi adi[2];
130 int bad;
131 int reads;
132};
133
134/*
135 * adi_read_packet() reads a Logitech ADI packet.
136 */
137
138static void adi_read_packet(struct adi_port *port)
139{
140 struct adi *adi = port->adi;
141 struct gameport *gameport = port->gameport;
142 unsigned char u, v, w, x, z;
143 int t[2], s[2], i;
144 unsigned long flags;
145
146 for (i = 0; i < 2; i++) {
147 adi[i].ret = -1;
148 t[i] = gameport_time(gameport, ADI_MAX_START);
149 s[i] = 0;
150 }
151
152 local_irq_save(flags);
153
154 gameport_trigger(gameport);
155 v = z = gameport_read(gameport);
156
157 do {
158 u = v;
159 w = u ^ (v = x = gameport_read(gameport));
160 for (i = 0; i < 2; i++, w >>= 2, x >>= 2) {
161 t[i]--;
162 if ((w & 0x30) && s[i]) {
163 if ((w & 0x30) < 0x30 && adi[i].ret < ADI_MAX_LENGTH && t[i] > 0) {
164 adi[i].data[++adi[i].ret] = w;
165 t[i] = gameport_time(gameport, ADI_MAX_STROBE);
166 } else t[i] = 0;
167 } else if (!(x & 0x30)) s[i] = 1;
168 }
169 } while (t[0] > 0 || t[1] > 0);
170
171 local_irq_restore(flags);
172
173 return;
174}
175
176/*
177 * adi_move_bits() detects a possible 2-stream mode, and moves
178 * the bits accordingly.
179 */
180
181static void adi_move_bits(struct adi_port *port, int length)
182{
183 int i;
184 struct adi *adi = port->adi;
185
186 adi[0].idx = adi[1].idx = 0;
187
188 if (adi[0].ret <= 0 || adi[1].ret <= 0) return;
189 if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return;
190
191 for (i = 1; i <= adi[1].ret; i++)
192 adi[0].data[((length - 1) >> 1) + i + 1] = adi[1].data[i];
193
194 adi[0].ret += adi[1].ret;
195 adi[1].ret = -1;
196}
197
198/*
199 * adi_get_bits() gathers bits from the data packet.
200 */
201
202static inline int adi_get_bits(struct adi *adi, int count)
203{
204 int bits = 0;
205 int i;
206 if ((adi->idx += count) > adi->ret) return 0;
207 for (i = 0; i < count; i++)
208 bits |= ((adi->data[adi->idx - i] >> 5) & 1) << i;
209 return bits;
210}
211
212/*
213 * adi_decode() decodes Logitech joystick data into input events.
214 */
215
216static int adi_decode(struct adi *adi)
217{
218 struct input_dev *dev = &adi->dev;
219 char *abs = adi->abs;
220 short *key = adi->key;
221 int i, t;
222
223 if (adi->ret < adi->length || adi->id != (adi_get_bits(adi, 4) | (adi_get_bits(adi, 4) << 4)))
224 return -1;
225
226 for (i = 0; i < adi->axes10; i++)
227 input_report_abs(dev, *abs++, adi_get_bits(adi, 10));
228
229 for (i = 0; i < adi->axes8; i++)
230 input_report_abs(dev, *abs++, adi_get_bits(adi, 8));
231
232 for (i = 0; i < adi->buttons && i < 63; i++) {
233 if (i == adi->pad) {
234 t = adi_get_bits(adi, 4);
235 input_report_abs(dev, *abs++, ((t >> 2) & 1) - ( t & 1));
236 input_report_abs(dev, *abs++, ((t >> 1) & 1) - ((t >> 3) & 1));
237 }
238 input_report_key(dev, *key++, adi_get_bits(adi, 1));
239 }
240
241 for (i = 0; i < adi->hats; i++) {
242 if ((t = adi_get_bits(adi, 4)) > 8) t = 0;
243 input_report_abs(dev, *abs++, adi_hat_to_axis[t].x);
244 input_report_abs(dev, *abs++, adi_hat_to_axis[t].y);
245 }
246
247 for (i = 63; i < adi->buttons; i++)
248 input_report_key(dev, *key++, adi_get_bits(adi, 1));
249
250 input_sync(dev);
251
252 return 0;
253}
254
255/*
256 * adi_read() reads the data packet and decodes it.
257 */
258
259static int adi_read(struct adi_port *port)
260{
261 int i;
262 int result = 0;
263
264 adi_read_packet(port);
265 adi_move_bits(port, port->adi[0].length);
266
267 for (i = 0; i < 2; i++)
268 if (port->adi[i].length)
269 result |= adi_decode(port->adi + i);
270
271 return result;
272}
273
274/*
275 * adi_poll() repeatedly polls the Logitech joysticks.
276 */
277
278static void adi_poll(struct gameport *gameport)
279{
280 struct adi_port *port = gameport_get_drvdata(gameport);
281
282 port->bad -= adi_read(port);
283 port->reads++;
284}
285
286/*
287 * adi_open() is a callback from the input open routine.
288 */
289
290static int adi_open(struct input_dev *dev)
291{
292 struct adi_port *port = dev->private;
293
294 gameport_start_polling(port->gameport);
295 return 0;
296}
297
298/*
299 * adi_close() is a callback from the input close routine.
300 */
301
302static void adi_close(struct input_dev *dev)
303{
304 struct adi_port *port = dev->private;
305
306 gameport_stop_polling(port->gameport);
307}
308
309/*
310 * adi_init_digital() sends a trigger & delay sequence
311 * to reset and initialize a Logitech joystick into digital mode.
312 */
313
314static void adi_init_digital(struct gameport *gameport)
315{
316 int seq[] = { 4, -2, -3, 10, -6, -11, -7, -9, 11, 0 };
317 int i;
318
319 for (i = 0; seq[i]; i++) {
320 gameport_trigger(gameport);
321 if (seq[i] > 0) msleep(seq[i]);
322 if (seq[i] < 0) {
323 mdelay(-seq[i]);
324 udelay(-seq[i]*14); /* It looks like mdelay() is off by approx 1.4% */
325 }
326 }
327}
328
329static void adi_id_decode(struct adi *adi, struct adi_port *port)
330{
331 int i, t;
332
333 if (adi->ret < ADI_MIN_ID_LENGTH) /* Minimum ID packet length */
334 return;
335
336 if (adi->ret < (t = adi_get_bits(adi, 10))) {
337 printk(KERN_WARNING "adi: Short ID packet: reported: %d != read: %d\n", t, adi->ret);
338 return;
339 }
340
341 adi->id = adi_get_bits(adi, 4) | (adi_get_bits(adi, 4) << 4);
342
343 if ((t = adi_get_bits(adi, 4)) & ADI_FLAG_HAT) adi->hats++;
344
345 adi->length = adi_get_bits(adi, 10);
346
347 if (adi->length >= ADI_MAX_LENGTH || adi->length < ADI_MIN_LENGTH) {
348 printk(KERN_WARNING "adi: Bad data packet length (%d).\n", adi->length);
349 adi->length = 0;
350 return;
351 }
352
353 adi->axes8 = adi_get_bits(adi, 4);
354 adi->buttons = adi_get_bits(adi, 6);
355
356 if (adi_get_bits(adi, 6) != 8 && adi->hats) {
357 printk(KERN_WARNING "adi: Other than 8-dir POVs not supported yet.\n");
358 adi->length = 0;
359 return;
360 }
361
362 adi->buttons += adi_get_bits(adi, 6);
363 adi->hats += adi_get_bits(adi, 4);
364
365 i = adi_get_bits(adi, 4);
366
367 if (t & ADI_FLAG_10BIT) {
368 adi->axes10 = adi->axes8 - i;
369 adi->axes8 = i;
370 }
371
372 t = adi_get_bits(adi, 4);
373
374 for (i = 0; i < t; i++)
375 adi->cname[i] = adi_get_bits(adi, 8);
376 adi->cname[i] = 0;
377
378 t = 8 + adi->buttons + adi->axes10 * 10 + adi->axes8 * 8 + adi->hats * 4;
379 if (adi->length != t && adi->length != t + (t & 1)) {
380 printk(KERN_WARNING "adi: Expected length %d != data length %d\n", t, adi->length);
381 adi->length = 0;
382 return;
383 }
384
385 switch (adi->id) {
386 case ADI_ID_TPD:
387 adi->pad = 4;
388 adi->buttons -= 4;
389 break;
390 case ADI_ID_WGP:
391 adi->pad = 0;
392 adi->buttons -= 4;
393 break;
394 default:
395 adi->pad = -1;
396 break;
397 }
398}
399
400static void adi_init_input(struct adi *adi, struct adi_port *port, int half)
401{
402 int i, t;
403 char buf[ADI_MAX_NAME_LENGTH];
404
405 if (!adi->length) return;
406
407 init_input_dev(&adi->dev);
408
409 t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX;
410
411 snprintf(buf, ADI_MAX_PHYS_LENGTH, adi_names[t], adi->id);
412 snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s", buf);
413 snprintf(adi->phys, ADI_MAX_PHYS_LENGTH, "%s/input%d", port->gameport->phys, half);
414
415 adi->abs = adi_abs[t];
416 adi->key = adi_key[t];
417
418 adi->dev.open = adi_open;
419 adi->dev.close = adi_close;
420
421 adi->dev.name = adi->name;
422 adi->dev.phys = adi->phys;
423 adi->dev.id.bustype = BUS_GAMEPORT;
424 adi->dev.id.vendor = GAMEPORT_ID_VENDOR_LOGITECH;
425 adi->dev.id.product = adi->id;
426 adi->dev.id.version = 0x0100;
427
428 adi->dev.private = port;
429 adi->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
430
431 for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++)
432 set_bit(adi->abs[i], adi->dev.absbit);
433
434 for (i = 0; i < adi->buttons; i++)
435 set_bit(adi->key[i], adi->dev.keybit);
436}
437
438static void adi_init_center(struct adi *adi)
439{
440 int i, t, x;
441
442 if (!adi->length)
443 return;
444
445 for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) {
446
447 t = adi->abs[i];
448 x = adi->dev.abs[t];
449
450 if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE)
451 x = i < adi->axes10 ? 512 : 128;
452
453 if (i < adi->axes10)
454 input_set_abs_params(&adi->dev, t, 64, x * 2 - 64, 2, 16);
455 else if (i < adi->axes10 + adi->axes8)
456 input_set_abs_params(&adi->dev, t, 48, x * 2 - 48, 1, 16);
457 else
458 input_set_abs_params(&adi->dev, t, -1, 1, 0, 0);
459 }
460}
461
462/*
463 * adi_connect() probes for Logitech ADI joysticks.
464 */
465
466static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
467{
468 struct adi_port *port;
469 int i;
470 int err;
471
472 if (!(port = kcalloc(1, sizeof(struct adi_port), GFP_KERNEL)))
473 return -ENOMEM;
474
475 port->gameport = gameport;
476
477 gameport_set_drvdata(gameport, port);
478
479 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
480 if (err) {
481 kfree(port);
482 return err;
483 }
484
485 adi_init_digital(gameport);
486 adi_read_packet(port);
487
488 if (port->adi[0].ret >= ADI_MIN_LEN_LENGTH)
489 adi_move_bits(port, adi_get_bits(port->adi, 10));
490
491 for (i = 0; i < 2; i++) {
492 adi_id_decode(port->adi + i, port);
493 adi_init_input(port->adi + i, port, i);
494 }
495
496 if (!port->adi[0].length && !port->adi[1].length) {
497 gameport_close(gameport);
498 kfree(port);
499 return -ENODEV;
500 }
501
502 gameport_set_poll_handler(gameport, adi_poll);
503 gameport_set_poll_interval(gameport, 20);
504
505 msleep(ADI_INIT_DELAY);
506 if (adi_read(port)) {
507 msleep(ADI_DATA_DELAY);
508 adi_read(port);
509 }
510
511 for (i = 0; i < 2; i++)
512 if (port->adi[i].length > 0) {
513 adi_init_center(port->adi + i);
514 input_register_device(&port->adi[i].dev);
515 printk(KERN_INFO "input: %s [%s] on %s\n",
516 port->adi[i].name, port->adi[i].cname, gameport->phys);
517 }
518
519 return 0;
520}
521
522static void adi_disconnect(struct gameport *gameport)
523{
524 int i;
525 struct adi_port *port = gameport_get_drvdata(gameport);
526
527 for (i = 0; i < 2; i++)
528 if (port->adi[i].length > 0)
529 input_unregister_device(&port->adi[i].dev);
530 gameport_close(gameport);
531 gameport_set_drvdata(gameport, NULL);
532 kfree(port);
533}
534
535/*
536 * The gameport device structure.
537 */
538
539static struct gameport_driver adi_drv = {
540 .driver = {
541 .name = "adi",
542 },
543 .description = DRIVER_DESC,
544 .connect = adi_connect,
545 .disconnect = adi_disconnect,
546};
547
548static int __init adi_init(void)
549{
550 gameport_register_driver(&adi_drv);
551 return 0;
552}
553
554static void __exit adi_exit(void)
555{
556 gameport_unregister_driver(&adi_drv);
557}
558
559module_init(adi_init);
560module_exit(adi_exit);
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
new file mode 100644
index 000000000000..cf36ca9b92f3
--- /dev/null
+++ b/drivers/input/joystick/amijoy.c
@@ -0,0 +1,161 @@
1/*
2 * $Id: amijoy.c,v 1.13 2002/01/22 20:26:32 vojtech Exp $
3 *
4 * Copyright (c) 1998-2001 Vojtech Pavlik
5 */
6
7/*
8 * Driver for Amiga joysticks for Linux/m68k
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/types.h>
32#include <linux/errno.h>
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36#include <linux/init.h>
37#include <linux/input.h>
38#include <linux/interrupt.h>
39
40#include <asm/system.h>
41#include <asm/amigahw.h>
42#include <asm/amigaints.h>
43
44MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
45MODULE_DESCRIPTION("Driver for Amiga joysticks");
46MODULE_LICENSE("GPL");
47
48static int amijoy[2] = { 0, 1 };
49module_param_array_named(map, amijoy, uint, NULL, 0);
50MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is 0,1)");
51
52__obsolete_setup("amijoy=");
53
54static int amijoy_used[2] = { 0, 0 };
55static struct input_dev amijoy_dev[2];
56static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" };
57
58static char *amijoy_name = "Amiga joystick";
59
60static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp)
61{
62 int i, data = 0, button = 0;
63
64 for (i = 0; i < 2; i++)
65 if (amijoy[i]) {
66
67 switch (i) {
68 case 0: data = ~custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break;
69 case 1: data = ~custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break;
70 }
71
72 input_regs(amijoy_dev + i, fp);
73
74 input_report_key(amijoy_dev + i, BTN_TRIGGER, button);
75
76 input_report_abs(amijoy_dev + i, ABS_X, ((data >> 1) & 1) - ((data >> 9) & 1));
77 data = ~(data ^ (data << 1));
78 input_report_abs(amijoy_dev + i, ABS_Y, ((data >> 1) & 1) - ((data >> 9) & 1));
79
80 input_sync(amijoy_dev + i);
81 }
82 return IRQ_HANDLED;
83}
84
85static int amijoy_open(struct input_dev *dev)
86{
87 int *used = dev->private;
88
89 if ((*used)++)
90 return 0;
91
92 if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) {
93 (*used)--;
94 printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB);
95 return -EBUSY;
96 }
97
98 return 0;
99}
100
101static void amijoy_close(struct input_dev *dev)
102{
103 int *used = dev->private;
104
105 if (!--(*used))
106 free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt);
107}
108
109static int __init amijoy_init(void)
110{
111 int i, j;
112
113 for (i = 0; i < 2; i++)
114 if (amijoy[i]) {
115 if (!request_mem_region(CUSTOM_PHYSADDR+10+i*2, 2,
116 "amijoy [Denise]")) {
117 if (i == 1 && amijoy[0]) {
118 input_unregister_device(amijoy_dev);
119 release_mem_region(CUSTOM_PHYSADDR+10, 2);
120 }
121 return -EBUSY;
122 }
123
124 amijoy_dev[i].open = amijoy_open;
125 amijoy_dev[i].close = amijoy_close;
126 amijoy_dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
127 amijoy_dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
128 amijoy_dev[i].keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
129 for (j = 0; j < 2; j++) {
130 amijoy_dev[i].absmin[ABS_X + j] = -1;
131 amijoy_dev[i].absmax[ABS_X + j] = 1;
132 }
133
134 amijoy_dev[i].name = amijoy_name;
135 amijoy_dev[i].phys = amijoy_phys[i];
136 amijoy_dev[i].id.bustype = BUS_AMIGA;
137 amijoy_dev[i].id.vendor = 0x0001;
138 amijoy_dev[i].id.product = 0x0003;
139 amijoy_dev[i].id.version = 0x0100;
140
141 amijoy_dev[i].private = amijoy_used + i;
142
143 input_register_device(amijoy_dev + i);
144 printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i);
145 }
146 return 0;
147}
148
149static void __exit amijoy_exit(void)
150{
151 int i;
152
153 for (i = 0; i < 2; i++)
154 if (amijoy[i]) {
155 input_unregister_device(amijoy_dev + i);
156 release_mem_region(CUSTOM_PHYSADDR+10+i*2, 2);
157 }
158}
159
160module_init(amijoy_init);
161module_exit(amijoy_exit);
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
new file mode 100644
index 000000000000..504b7d550567
--- /dev/null
+++ b/drivers/input/joystick/analog.c
@@ -0,0 +1,772 @@
1/*
2 * $Id: analog.c,v 1.68 2002/01/22 20:18:32 vojtech Exp $
3 *
4 * Copyright (c) 1996-2001 Vojtech Pavlik
5 */
6
7/*
8 * Analog joystick and gamepad driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/config.h>
32#include <linux/delay.h>
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36#include <linux/slab.h>
37#include <linux/bitops.h>
38#include <linux/init.h>
39#include <linux/input.h>
40#include <linux/gameport.h>
41#include <asm/timex.h>
42
43#define DRIVER_DESC "Analog joystick and gamepad driver"
44
45MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
46MODULE_DESCRIPTION(DRIVER_DESC);
47MODULE_LICENSE("GPL");
48
49/*
50 * Option parsing.
51 */
52
53#define ANALOG_PORTS 16
54
55static char *js[ANALOG_PORTS];
56static int js_nargs;
57static int analog_options[ANALOG_PORTS];
58module_param_array_named(map, js, charp, &js_nargs, 0);
59MODULE_PARM_DESC(map, "Describes analog joysticks type/capabilities");
60
61__obsolete_setup("js=");
62
63/*
64 * Times, feature definitions.
65 */
66
67#define ANALOG_RUDDER 0x00004
68#define ANALOG_THROTTLE 0x00008
69#define ANALOG_AXES_STD 0x0000f
70#define ANALOG_BTNS_STD 0x000f0
71
72#define ANALOG_BTNS_CHF 0x00100
73#define ANALOG_HAT1_CHF 0x00200
74#define ANALOG_HAT2_CHF 0x00400
75#define ANALOG_HAT_FCS 0x00800
76#define ANALOG_HATS_ALL 0x00e00
77#define ANALOG_BTN_TL 0x01000
78#define ANALOG_BTN_TR 0x02000
79#define ANALOG_BTN_TL2 0x04000
80#define ANALOG_BTN_TR2 0x08000
81#define ANALOG_BTNS_TLR 0x03000
82#define ANALOG_BTNS_TLR2 0x0c000
83#define ANALOG_BTNS_GAMEPAD 0x0f000
84
85#define ANALOG_HBTN_CHF 0x10000
86#define ANALOG_ANY_CHF 0x10700
87#define ANALOG_SAITEK 0x20000
88#define ANALOG_EXTENSIONS 0x7ff00
89#define ANALOG_GAMEPAD 0x80000
90
91#define ANALOG_MAX_TIME 3 /* 3 ms */
92#define ANALOG_LOOP_TIME 2000 /* 2 * loop */
93#define ANALOG_SAITEK_DELAY 200 /* 200 us */
94#define ANALOG_SAITEK_TIME 2000 /* 2000 us */
95#define ANALOG_AXIS_TIME 2 /* 2 * refresh */
96#define ANALOG_INIT_RETRIES 8 /* 8 times */
97#define ANALOG_FUZZ_BITS 2 /* 2 bit more */
98#define ANALOG_FUZZ_MAGIC 36 /* 36 u*ms/loop */
99
100#define ANALOG_MAX_NAME_LENGTH 128
101#define ANALOG_MAX_PHYS_LENGTH 32
102
103static short analog_axes[] = { ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE };
104static short analog_hats[] = { ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y };
105static short analog_pads[] = { BTN_Y, BTN_Z, BTN_TL, BTN_TR };
106static short analog_exts[] = { ANALOG_HAT1_CHF, ANALOG_HAT2_CHF, ANALOG_HAT_FCS };
107static short analog_pad_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_TL2, BTN_TR2, BTN_SELECT, BTN_START, BTN_MODE, BTN_BASE };
108static short analog_joy_btn[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2,
109 BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_BASE6 };
110
111static unsigned char analog_chf[] = { 0xf, 0x0, 0x1, 0x9, 0x2, 0x4, 0xc, 0x8, 0x3, 0x5, 0xb, 0x7, 0xd, 0xe, 0xa, 0x6 };
112
113struct analog {
114 struct input_dev dev;
115 int mask;
116 short *buttons;
117 char name[ANALOG_MAX_NAME_LENGTH];
118 char phys[ANALOG_MAX_PHYS_LENGTH];
119};
120
121struct analog_port {
122 struct gameport *gameport;
123 struct analog analog[2];
124 unsigned char mask;
125 char saitek;
126 char cooked;
127 int bads;
128 int reads;
129 int speed;
130 int loop;
131 int fuzz;
132 int axes[4];
133 int buttons;
134 int initial[4];
135 int axtime;
136};
137
138/*
139 * Time macros.
140 */
141
142#ifdef __i386__
143#define GET_TIME(x) do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0)
144#define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? CLOCK_TICK_RATE / HZ : 0)))
145#define TIME_NAME (cpu_has_tsc?"TSC":"PIT")
146static unsigned int get_time_pit(void)
147{
148 extern spinlock_t i8253_lock;
149 unsigned long flags;
150 unsigned int count;
151
152 spin_lock_irqsave(&i8253_lock, flags);
153 outb_p(0x00, 0x43);
154 count = inb_p(0x40);
155 count |= inb_p(0x40) << 8;
156 spin_unlock_irqrestore(&i8253_lock, flags);
157
158 return count;
159}
160#elif defined(__x86_64__)
161#define GET_TIME(x) rdtscl(x)
162#define DELTA(x,y) ((y)-(x))
163#define TIME_NAME "TSC"
164#elif defined(__alpha__)
165#define GET_TIME(x) do { x = get_cycles(); } while (0)
166#define DELTA(x,y) ((y)-(x))
167#define TIME_NAME "PCC"
168#else
169#define FAKE_TIME
170static unsigned long analog_faketime = 0;
171#define GET_TIME(x) do { x = analog_faketime++; } while(0)
172#define DELTA(x,y) ((y)-(x))
173#define TIME_NAME "Unreliable"
174#warning Precise timer not defined for this architecture.
175#endif
176
177/*
178 * analog_decode() decodes analog joystick data and reports input events.
179 */
180
181static void analog_decode(struct analog *analog, int *axes, int *initial, int buttons)
182{
183 struct input_dev *dev = &analog->dev;
184 int i, j;
185
186 if (analog->mask & ANALOG_HAT_FCS)
187 for (i = 0; i < 4; i++)
188 if (axes[3] < ((initial[3] * ((i << 1) + 1)) >> 3)) {
189 buttons |= 1 << (i + 14);
190 break;
191 }
192
193 for (i = j = 0; i < 6; i++)
194 if (analog->mask & (0x10 << i))
195 input_report_key(dev, analog->buttons[j++], (buttons >> i) & 1);
196
197 if (analog->mask & ANALOG_HBTN_CHF)
198 for (i = 0; i < 4; i++)
199 input_report_key(dev, analog->buttons[j++], (buttons >> (i + 10)) & 1);
200
201 if (analog->mask & ANALOG_BTN_TL)
202 input_report_key(dev, analog_pads[0], axes[2] < (initial[2] >> 1));
203 if (analog->mask & ANALOG_BTN_TR)
204 input_report_key(dev, analog_pads[1], axes[3] < (initial[3] >> 1));
205 if (analog->mask & ANALOG_BTN_TL2)
206 input_report_key(dev, analog_pads[2], axes[2] > (initial[2] + (initial[2] >> 1)));
207 if (analog->mask & ANALOG_BTN_TR2)
208 input_report_key(dev, analog_pads[3], axes[3] > (initial[3] + (initial[3] >> 1)));
209
210 for (i = j = 0; i < 4; i++)
211 if (analog->mask & (1 << i))
212 input_report_abs(dev, analog_axes[j++], axes[i]);
213
214 for (i = j = 0; i < 3; i++)
215 if (analog->mask & analog_exts[i]) {
216 input_report_abs(dev, analog_hats[j++],
217 ((buttons >> ((i << 2) + 7)) & 1) - ((buttons >> ((i << 2) + 9)) & 1));
218 input_report_abs(dev, analog_hats[j++],
219 ((buttons >> ((i << 2) + 8)) & 1) - ((buttons >> ((i << 2) + 6)) & 1));
220 }
221
222 input_sync(dev);
223}
224
225/*
226 * analog_cooked_read() reads analog joystick data.
227 */
228
229static int analog_cooked_read(struct analog_port *port)
230{
231 struct gameport *gameport = port->gameport;
232 unsigned int time[4], start, loop, now, loopout, timeout;
233 unsigned char data[4], this, last;
234 unsigned long flags;
235 int i, j;
236
237 loopout = (ANALOG_LOOP_TIME * port->loop) / 1000;
238 timeout = ANALOG_MAX_TIME * port->speed;
239
240 local_irq_save(flags);
241 gameport_trigger(gameport);
242 GET_TIME(now);
243 local_irq_restore(flags);
244
245 start = now;
246 this = port->mask;
247 i = 0;
248
249 do {
250 loop = now;
251 last = this;
252
253 local_irq_disable();
254 this = gameport_read(gameport) & port->mask;
255 GET_TIME(now);
256 local_irq_restore(flags);
257
258 if ((last ^ this) && (DELTA(loop, now) < loopout)) {
259 data[i] = last ^ this;
260 time[i] = now;
261 i++;
262 }
263
264 } while (this && (i < 4) && (DELTA(start, now) < timeout));
265
266 this <<= 4;
267
268 for (--i; i >= 0; i--) {
269 this |= data[i];
270 for (j = 0; j < 4; j++)
271 if (data[i] & (1 << j))
272 port->axes[j] = (DELTA(start, time[i]) << ANALOG_FUZZ_BITS) / port->loop;
273 }
274
275 return -(this != port->mask);
276}
277
278static int analog_button_read(struct analog_port *port, char saitek, char chf)
279{
280 unsigned char u;
281 int t = 1, i = 0;
282 int strobe = gameport_time(port->gameport, ANALOG_SAITEK_TIME);
283
284 u = gameport_read(port->gameport);
285
286 if (!chf) {
287 port->buttons = (~u >> 4) & 0xf;
288 return 0;
289 }
290
291 port->buttons = 0;
292
293 while ((~u & 0xf0) && (i < 16) && t) {
294 port->buttons |= 1 << analog_chf[(~u >> 4) & 0xf];
295 if (!saitek) return 0;
296 udelay(ANALOG_SAITEK_DELAY);
297 t = strobe;
298 gameport_trigger(port->gameport);
299 while (((u = gameport_read(port->gameport)) & port->mask) && t) t--;
300 i++;
301 }
302
303 return -(!t || (i == 16));
304}
305
306/*
307 * analog_poll() repeatedly polls the Analog joysticks.
308 */
309
310static void analog_poll(struct gameport *gameport)
311{
312 struct analog_port *port = gameport_get_drvdata(gameport);
313 int i;
314
315 char saitek = !!(port->analog[0].mask & ANALOG_SAITEK);
316 char chf = !!(port->analog[0].mask & ANALOG_ANY_CHF);
317
318 if (port->cooked) {
319 port->bads -= gameport_cooked_read(port->gameport, port->axes, &port->buttons);
320 if (chf)
321 port->buttons = port->buttons ? (1 << analog_chf[port->buttons]) : 0;
322 port->reads++;
323 } else {
324 if (!port->axtime--) {
325 port->bads -= analog_cooked_read(port);
326 port->bads -= analog_button_read(port, saitek, chf);
327 port->reads++;
328 port->axtime = ANALOG_AXIS_TIME - 1;
329 } else {
330 if (!saitek)
331 analog_button_read(port, saitek, chf);
332 }
333 }
334
335 for (i = 0; i < 2; i++)
336 if (port->analog[i].mask)
337 analog_decode(port->analog + i, port->axes, port->initial, port->buttons);
338}
339
340/*
341 * analog_open() is a callback from the input open routine.
342 */
343
344static int analog_open(struct input_dev *dev)
345{
346 struct analog_port *port = dev->private;
347
348 gameport_start_polling(port->gameport);
349 return 0;
350}
351
352/*
353 * analog_close() is a callback from the input close routine.
354 */
355
356static void analog_close(struct input_dev *dev)
357{
358 struct analog_port *port = dev->private;
359
360 gameport_stop_polling(port->gameport);
361}
362
363/*
364 * analog_calibrate_timer() calibrates the timer and computes loop
365 * and timeout values for a joystick port.
366 */
367
368static void analog_calibrate_timer(struct analog_port *port)
369{
370 struct gameport *gameport = port->gameport;
371 unsigned int i, t, tx, t1, t2, t3;
372 unsigned long flags;
373
374 local_irq_save(flags);
375 GET_TIME(t1);
376#ifdef FAKE_TIME
377 analog_faketime += 830;
378#endif
379 mdelay(1);
380 GET_TIME(t2);
381 GET_TIME(t3);
382 local_irq_restore(flags);
383
384 port->speed = DELTA(t1, t2) - DELTA(t2, t3);
385
386 tx = ~0;
387
388 for (i = 0; i < 50; i++) {
389 local_irq_save(flags);
390 GET_TIME(t1);
391 for (t = 0; t < 50; t++) { gameport_read(gameport); GET_TIME(t2); }
392 GET_TIME(t3);
393 local_irq_restore(flags);
394 udelay(i);
395 t = DELTA(t1, t2) - DELTA(t2, t3);
396 if (t < tx) tx = t;
397 }
398
399 port->loop = tx / 50;
400}
401
402/*
403 * analog_name() constructs a name for an analog joystick.
404 */
405
406static void analog_name(struct analog *analog)
407{
408 sprintf(analog->name, "Analog %d-axis %d-button",
409 hweight8(analog->mask & ANALOG_AXES_STD),
410 hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 +
411 hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4);
412
413 if (analog->mask & ANALOG_HATS_ALL)
414 sprintf(analog->name, "%s %d-hat",
415 analog->name, hweight16(analog->mask & ANALOG_HATS_ALL));
416
417 if (analog->mask & ANALOG_HAT_FCS)
418 strcat(analog->name, " FCS");
419 if (analog->mask & ANALOG_ANY_CHF)
420 strcat(analog->name, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF");
421
422 strcat(analog->name, (analog->mask & ANALOG_GAMEPAD) ? " gamepad": " joystick");
423}
424
425/*
426 * analog_init_device()
427 */
428
429static void analog_init_device(struct analog_port *port, struct analog *analog, int index)
430{
431 int i, j, t, v, w, x, y, z;
432
433 analog_name(analog);
434 sprintf(analog->phys, "%s/input%d", port->gameport->phys, index);
435 analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn;
436
437 init_input_dev(&analog->dev);
438
439 analog->dev.name = analog->name;
440 analog->dev.phys = analog->phys;
441 analog->dev.id.bustype = BUS_GAMEPORT;
442 analog->dev.id.vendor = GAMEPORT_ID_VENDOR_ANALOG;
443 analog->dev.id.product = analog->mask >> 4;
444 analog->dev.id.version = 0x0100;
445
446 analog->dev.open = analog_open;
447 analog->dev.close = analog_close;
448 analog->dev.private = port;
449 analog->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
450
451 for (i = j = 0; i < 4; i++)
452 if (analog->mask & (1 << i)) {
453
454 t = analog_axes[j];
455 x = port->axes[i];
456 y = (port->axes[0] + port->axes[1]) >> 1;
457 z = y - port->axes[i];
458 z = z > 0 ? z : -z;
459 v = (x >> 3);
460 w = (x >> 3);
461
462 set_bit(t, analog->dev.absbit);
463
464 if ((i == 2 || i == 3) && (j == 2 || j == 3) && (z > (y >> 3)))
465 x = y;
466
467 if (analog->mask & ANALOG_SAITEK) {
468 if (i == 2) x = port->axes[i];
469 v = x - (x >> 2);
470 w = (x >> 4);
471 }
472
473 analog->dev.absmax[t] = (x << 1) - v;
474 analog->dev.absmin[t] = v;
475 analog->dev.absfuzz[t] = port->fuzz;
476 analog->dev.absflat[t] = w;
477
478 j++;
479 }
480
481 for (i = j = 0; i < 3; i++)
482 if (analog->mask & analog_exts[i])
483 for (x = 0; x < 2; x++) {
484 t = analog_hats[j++];
485 set_bit(t, analog->dev.absbit);
486 analog->dev.absmax[t] = 1;
487 analog->dev.absmin[t] = -1;
488 }
489
490 for (i = j = 0; i < 4; i++)
491 if (analog->mask & (0x10 << i))
492 set_bit(analog->buttons[j++], analog->dev.keybit);
493
494 if (analog->mask & ANALOG_BTNS_CHF)
495 for (i = 0; i < 2; i++)
496 set_bit(analog->buttons[j++], analog->dev.keybit);
497
498 if (analog->mask & ANALOG_HBTN_CHF)
499 for (i = 0; i < 4; i++)
500 set_bit(analog->buttons[j++], analog->dev.keybit);
501
502 for (i = 0; i < 4; i++)
503 if (analog->mask & (ANALOG_BTN_TL << i))
504 set_bit(analog_pads[i], analog->dev.keybit);
505
506 analog_decode(analog, port->axes, port->initial, port->buttons);
507
508 input_register_device(&analog->dev);
509
510 printk(KERN_INFO "input: %s at %s", analog->name, port->gameport->phys);
511
512 if (port->cooked)
513 printk(" [ADC port]\n");
514 else
515 printk(" [%s timer, %d %sHz clock, %d ns res]\n", TIME_NAME,
516 port->speed > 10000 ? (port->speed + 800) / 1000 : port->speed,
517 port->speed > 10000 ? "M" : "k",
518 port->speed > 10000 ? (port->loop * 1000) / (port->speed / 1000)
519 : (port->loop * 1000000) / port->speed);
520}
521
522/*
523 * analog_init_devices() sets up device-specific values and registers the input devices.
524 */
525
526static int analog_init_masks(struct analog_port *port)
527{
528 int i;
529 struct analog *analog = port->analog;
530 int max[4];
531
532 if (!port->mask)
533 return -1;
534
535 if ((port->mask & 3) != 3 && port->mask != 0xc) {
536 printk(KERN_WARNING "analog.c: Unknown joystick device found "
537 "(data=%#x, %s), probably not analog joystick.\n",
538 port->mask, port->gameport->phys);
539 return -1;
540 }
541
542
543 i = analog_options[0]; /* FIXME !!! - need to specify options for different ports */
544
545 analog[0].mask = i & 0xfffff;
546
547 analog[0].mask &= ~(ANALOG_AXES_STD | ANALOG_HAT_FCS | ANALOG_BTNS_GAMEPAD)
548 | port->mask | ((port->mask << 8) & ANALOG_HAT_FCS)
549 | ((port->mask << 10) & ANALOG_BTNS_TLR) | ((port->mask << 12) & ANALOG_BTNS_TLR2);
550
551 analog[0].mask &= ~(ANALOG_HAT2_CHF)
552 | ((analog[0].mask & ANALOG_HBTN_CHF) ? 0 : ANALOG_HAT2_CHF);
553
554 analog[0].mask &= ~(ANALOG_THROTTLE | ANALOG_BTN_TR | ANALOG_BTN_TR2)
555 | ((~analog[0].mask & ANALOG_HAT_FCS) >> 8)
556 | ((~analog[0].mask & ANALOG_HAT_FCS) << 2)
557 | ((~analog[0].mask & ANALOG_HAT_FCS) << 4);
558
559 analog[0].mask &= ~(ANALOG_THROTTLE | ANALOG_RUDDER)
560 | (((~analog[0].mask & ANALOG_BTNS_TLR ) >> 10)
561 & ((~analog[0].mask & ANALOG_BTNS_TLR2) >> 12));
562
563 analog[1].mask = ((i >> 20) & 0xff) | ((i >> 12) & 0xf0000);
564
565 analog[1].mask &= (analog[0].mask & ANALOG_EXTENSIONS) ? ANALOG_GAMEPAD
566 : (((ANALOG_BTNS_STD | port->mask) & ~analog[0].mask) | ANALOG_GAMEPAD);
567
568 if (port->cooked) {
569
570 for (i = 0; i < 4; i++) max[i] = port->axes[i] << 1;
571
572 if ((analog[0].mask & 0x7) == 0x7) max[2] = (max[0] + max[1]) >> 1;
573 if ((analog[0].mask & 0xb) == 0xb) max[3] = (max[0] + max[1]) >> 1;
574 if ((analog[0].mask & ANALOG_BTN_TL) && !(analog[0].mask & ANALOG_BTN_TL2)) max[2] >>= 1;
575 if ((analog[0].mask & ANALOG_BTN_TR) && !(analog[0].mask & ANALOG_BTN_TR2)) max[3] >>= 1;
576 if ((analog[0].mask & ANALOG_HAT_FCS)) max[3] >>= 1;
577
578 gameport_calibrate(port->gameport, port->axes, max);
579 }
580
581 for (i = 0; i < 4; i++)
582 port->initial[i] = port->axes[i];
583
584 return -!(analog[0].mask || analog[1].mask);
585}
586
587static int analog_init_port(struct gameport *gameport, struct gameport_driver *drv, struct analog_port *port)
588{
589 int i, t, u, v;
590
591 port->gameport = gameport;
592
593 gameport_set_drvdata(gameport, port);
594
595 if (!gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {
596
597 analog_calibrate_timer(port);
598
599 gameport_trigger(gameport);
600 t = gameport_read(gameport);
601 msleep(ANALOG_MAX_TIME);
602 port->mask = (gameport_read(gameport) ^ t) & t & 0xf;
603 port->fuzz = (port->speed * ANALOG_FUZZ_MAGIC) / port->loop / 1000 + ANALOG_FUZZ_BITS;
604
605 for (i = 0; i < ANALOG_INIT_RETRIES; i++) {
606 if (!analog_cooked_read(port))
607 break;
608 msleep(ANALOG_MAX_TIME);
609 }
610
611 u = v = 0;
612
613 msleep(ANALOG_MAX_TIME);
614 t = gameport_time(gameport, ANALOG_MAX_TIME * 1000);
615 gameport_trigger(gameport);
616 while ((gameport_read(port->gameport) & port->mask) && (u < t))
617 u++;
618 udelay(ANALOG_SAITEK_DELAY);
619 t = gameport_time(gameport, ANALOG_SAITEK_TIME);
620 gameport_trigger(gameport);
621 while ((gameport_read(port->gameport) & port->mask) && (v < t))
622 v++;
623
624 if (v < (u >> 1)) { /* FIXME - more than one port */
625 analog_options[0] |= /* FIXME - more than one port */
626 ANALOG_SAITEK | ANALOG_BTNS_CHF | ANALOG_HBTN_CHF | ANALOG_HAT1_CHF;
627 return 0;
628 }
629
630 gameport_close(gameport);
631 }
632
633 if (!gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) {
634
635 for (i = 0; i < ANALOG_INIT_RETRIES; i++)
636 if (!gameport_cooked_read(gameport, port->axes, &port->buttons))
637 break;
638 for (i = 0; i < 4; i++)
639 if (port->axes[i] != -1)
640 port->mask |= 1 << i;
641
642 port->fuzz = gameport->fuzz;
643 port->cooked = 1;
644 return 0;
645 }
646
647 return gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
648}
649
650static int analog_connect(struct gameport *gameport, struct gameport_driver *drv)
651{
652 struct analog_port *port;
653 int i;
654 int err;
655
656 if (!(port = kcalloc(1, sizeof(struct analog_port), GFP_KERNEL)))
657 return - ENOMEM;
658
659 err = analog_init_port(gameport, drv, port);
660 if (err) {
661 kfree(port);
662 return err;
663 }
664
665 err = analog_init_masks(port);
666 if (err) {
667 gameport_close(gameport);
668 gameport_set_drvdata(gameport, NULL);
669 kfree(port);
670 return err;
671 }
672
673 gameport_set_poll_handler(gameport, analog_poll);
674 gameport_set_poll_interval(gameport, 10);
675
676 for (i = 0; i < 2; i++)
677 if (port->analog[i].mask)
678 analog_init_device(port, port->analog + i, i);
679
680 return 0;
681}
682
683static void analog_disconnect(struct gameport *gameport)
684{
685 int i;
686 struct analog_port *port = gameport_get_drvdata(gameport);
687
688 for (i = 0; i < 2; i++)
689 if (port->analog[i].mask)
690 input_unregister_device(&port->analog[i].dev);
691 gameport_close(gameport);
692 gameport_set_drvdata(gameport, NULL);
693 printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on %s failed\n",
694 port->bads, port->reads, port->reads ? (port->bads * 100 / port->reads) : 0,
695 port->gameport->phys);
696 kfree(port);
697}
698
699struct analog_types {
700 char *name;
701 int value;
702};
703
704static struct analog_types analog_types[] = {
705 { "none", 0x00000000 },
706 { "auto", 0x000000ff },
707 { "2btn", 0x0000003f },
708 { "y-joy", 0x0cc00033 },
709 { "y-pad", 0x8cc80033 },
710 { "fcs", 0x000008f7 },
711 { "chf", 0x000002ff },
712 { "fullchf", 0x000007ff },
713 { "gamepad", 0x000830f3 },
714 { "gamepad8", 0x0008f0f3 },
715 { NULL, 0 }
716};
717
718static void analog_parse_options(void)
719{
720 int i, j;
721 char *end;
722
723 for (i = 0; i < js_nargs; i++) {
724
725 for (j = 0; analog_types[j].name; j++)
726 if (!strcmp(analog_types[j].name, js[i])) {
727 analog_options[i] = analog_types[j].value;
728 break;
729 }
730 if (analog_types[j].name) continue;
731
732 analog_options[i] = simple_strtoul(js[i], &end, 0);
733 if (end != js[i]) continue;
734
735 analog_options[i] = 0xff;
736 if (!strlen(js[i])) continue;
737
738 printk(KERN_WARNING "analog.c: Bad config for port %d - \"%s\"\n", i, js[i]);
739 }
740
741 for (; i < ANALOG_PORTS; i++)
742 analog_options[i] = 0xff;
743}
744
745/*
746 * The gameport device structure.
747 */
748
749static struct gameport_driver analog_drv = {
750 .driver = {
751 .name = "analog",
752 },
753 .description = DRIVER_DESC,
754 .connect = analog_connect,
755 .disconnect = analog_disconnect,
756};
757
758static int __init analog_init(void)
759{
760 analog_parse_options();
761 gameport_register_driver(&analog_drv);
762
763 return 0;
764}
765
766static void __exit analog_exit(void)
767{
768 gameport_unregister_driver(&analog_drv);
769}
770
771module_init(analog_init);
772module_exit(analog_exit);
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
new file mode 100644
index 000000000000..a6002205328f
--- /dev/null
+++ b/drivers/input/joystick/cobra.c
@@ -0,0 +1,264 @@
1/*
2 * $Id: cobra.c,v 1.19 2002/01/22 20:26:52 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
6
7/*
8 * Creative Labs Blaster GamePad Cobra driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/slab.h>
34#include <linux/init.h>
35#include <linux/gameport.h>
36#include <linux/input.h>
37
38#define DRIVER_DESC "Creative Labs Blaster GamePad Cobra driver"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44#define COBRA_MAX_STROBE 45 /* 45 us max wait for first strobe */
45#define COBRA_LENGTH 36
46
47static char* cobra_name = "Creative Labs Blaster GamePad Cobra";
48
49static 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 };
50
51struct cobra {
52 struct gameport *gameport;
53 struct input_dev dev[2];
54 int reads;
55 int bads;
56 unsigned char exists;
57 char phys[2][32];
58};
59
60static unsigned char cobra_read_packet(struct gameport *gameport, unsigned int *data)
61{
62 unsigned long flags;
63 unsigned char u, v, w;
64 __u64 buf[2];
65 int r[2], t[2];
66 int i, j, ret;
67
68 int strobe = gameport_time(gameport, COBRA_MAX_STROBE);
69
70 for (i = 0; i < 2; i++) {
71 r[i] = buf[i] = 0;
72 t[i] = COBRA_MAX_STROBE;
73 }
74
75 local_irq_save(flags);
76
77 u = gameport_read(gameport);
78
79 do {
80 t[0]--; t[1]--;
81 v = gameport_read(gameport);
82 for (i = 0, w = u ^ v; i < 2 && w; i++, w >>= 2)
83 if (w & 0x30) {
84 if ((w & 0x30) < 0x30 && r[i] < COBRA_LENGTH && t[i] > 0) {
85 buf[i] |= (__u64)((w >> 5) & 1) << r[i]++;
86 t[i] = strobe;
87 u = v;
88 } else t[i] = 0;
89 }
90 } while (t[0] > 0 || t[1] > 0);
91
92 local_irq_restore(flags);
93
94 ret = 0;
95
96 for (i = 0; i < 2; i++) {
97
98 if (r[i] != COBRA_LENGTH) continue;
99
100 for (j = 0; j < COBRA_LENGTH && (buf[i] & 0x04104107f) ^ 0x041041040; j++)
101 buf[i] = (buf[i] >> 1) | ((__u64)(buf[i] & 1) << (COBRA_LENGTH - 1));
102
103 if (j < COBRA_LENGTH) ret |= (1 << i);
104
105 data[i] = ((buf[i] >> 7) & 0x000001f) | ((buf[i] >> 8) & 0x00003e0)
106 | ((buf[i] >> 9) & 0x0007c00) | ((buf[i] >> 10) & 0x00f8000)
107 | ((buf[i] >> 11) & 0x1f00000);
108
109 }
110
111 return ret;
112}
113
114static void cobra_poll(struct gameport *gameport)
115{
116 struct cobra *cobra = gameport_get_drvdata(gameport);
117 struct input_dev *dev;
118 unsigned int data[2];
119 int i, j, r;
120
121 cobra->reads++;
122
123 if ((r = cobra_read_packet(gameport, data)) != cobra->exists) {
124 cobra->bads++;
125 return;
126 }
127
128 for (i = 0; i < 2; i++)
129 if (cobra->exists & r & (1 << i)) {
130
131 dev = cobra->dev + i;
132
133 input_report_abs(dev, ABS_X, ((data[i] >> 4) & 1) - ((data[i] >> 3) & 1));
134 input_report_abs(dev, ABS_Y, ((data[i] >> 2) & 1) - ((data[i] >> 1) & 1));
135
136 for (j = 0; cobra_btn[j]; j++)
137 input_report_key(dev, cobra_btn[j], data[i] & (0x20 << j));
138
139 input_sync(dev);
140
141 }
142}
143
144static int cobra_open(struct input_dev *dev)
145{
146 struct cobra *cobra = dev->private;
147
148 gameport_start_polling(cobra->gameport);
149 return 0;
150}
151
152static void cobra_close(struct input_dev *dev)
153{
154 struct cobra *cobra = dev->private;
155
156 gameport_stop_polling(cobra->gameport);
157}
158
159static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
160{
161 struct cobra *cobra;
162 unsigned int data[2];
163 int i, j;
164 int err;
165
166 if (!(cobra = kcalloc(1, sizeof(struct cobra), GFP_KERNEL)))
167 return -ENOMEM;
168
169 cobra->gameport = gameport;
170
171 gameport_set_drvdata(gameport, cobra);
172
173 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
174 if (err)
175 goto fail1;
176
177 cobra->exists = cobra_read_packet(gameport, data);
178
179 for (i = 0; i < 2; i++)
180 if ((cobra->exists >> i) & data[i] & 1) {
181 printk(KERN_WARNING "cobra.c: Device %d on %s has the Ext bit set. ID is: %d"
182 " Contact vojtech@ucw.cz\n", i, gameport->phys, (data[i] >> 2) & 7);
183 cobra->exists &= ~(1 << i);
184 }
185
186 if (!cobra->exists) {
187 err = -ENODEV;
188 goto fail2;
189 }
190
191 gameport_set_poll_handler(gameport, cobra_poll);
192 gameport_set_poll_interval(gameport, 20);
193
194 for (i = 0; i < 2; i++)
195 if ((cobra->exists >> i) & 1) {
196
197 sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i);
198
199 cobra->dev[i].private = cobra;
200 cobra->dev[i].open = cobra_open;
201 cobra->dev[i].close = cobra_close;
202
203 cobra->dev[i].name = cobra_name;
204 cobra->dev[i].phys = cobra->phys[i];
205 cobra->dev[i].id.bustype = BUS_GAMEPORT;
206 cobra->dev[i].id.vendor = GAMEPORT_ID_VENDOR_CREATIVE;
207 cobra->dev[i].id.product = 0x0008;
208 cobra->dev[i].id.version = 0x0100;
209
210 cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
211
212 input_set_abs_params(&cobra->dev[i], ABS_X, -1, 1, 0, 0);
213 input_set_abs_params(&cobra->dev[i], ABS_Y, -1, 1, 0, 0);
214
215 for (j = 0; cobra_btn[j]; j++)
216 set_bit(cobra_btn[j], cobra->dev[i].keybit);
217
218 input_register_device(&cobra->dev[i]);
219 printk(KERN_INFO "input: %s on %s\n", cobra_name, gameport->phys);
220 }
221
222 return 0;
223
224fail2: gameport_close(gameport);
225fail1: gameport_set_drvdata(gameport, NULL);
226 kfree(cobra);
227 return err;
228}
229
230static void cobra_disconnect(struct gameport *gameport)
231{
232 struct cobra *cobra = gameport_get_drvdata(gameport);
233 int i;
234
235 for (i = 0; i < 2; i++)
236 if ((cobra->exists >> i) & 1)
237 input_unregister_device(cobra->dev + i);
238 gameport_close(gameport);
239 gameport_set_drvdata(gameport, NULL);
240 kfree(cobra);
241}
242
243static struct gameport_driver cobra_drv = {
244 .driver = {
245 .name = "cobra",
246 },
247 .description = DRIVER_DESC,
248 .connect = cobra_connect,
249 .disconnect = cobra_disconnect,
250};
251
252static int __init cobra_init(void)
253{
254 gameport_register_driver(&cobra_drv);
255 return 0;
256}
257
258static void __exit cobra_exit(void)
259{
260 gameport_unregister_driver(&cobra_drv);
261}
262
263module_init(cobra_init);
264module_exit(cobra_exit);
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
new file mode 100644
index 000000000000..cfdd3acf06a1
--- /dev/null
+++ b/drivers/input/joystick/db9.c
@@ -0,0 +1,647 @@
1/*
2 * $Id: db9.c,v 1.13 2002/04/07 20:13:37 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Andree Borrmann Mats Sjövall
8 */
9
10/*
11 * Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver for Linux
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/kernel.h>
35#include <linux/module.h>
36#include <linux/moduleparam.h>
37#include <linux/delay.h>
38#include <linux/init.h>
39#include <linux/parport.h>
40#include <linux/input.h>
41
42MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
43MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver");
44MODULE_LICENSE("GPL");
45
46static int db9[] __initdata = { -1, 0 };
47static int db9_nargs __initdata = 0;
48module_param_array_named(dev, db9, int, &db9_nargs, 0);
49MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
50
51static int db9_2[] __initdata = { -1, 0 };
52static int db9_nargs_2 __initdata = 0;
53module_param_array_named(dev2, db9_2, int, &db9_nargs_2, 0);
54MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
55
56static int db9_3[] __initdata = { -1, 0 };
57static int db9_nargs_3 __initdata = 0;
58module_param_array_named(dev3, db9_3, int, &db9_nargs_3, 0);
59MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)");
60
61__obsolete_setup("db9=");
62__obsolete_setup("db9_2=");
63__obsolete_setup("db9_3=");
64
65#define DB9_MULTI_STICK 0x01
66#define DB9_MULTI2_STICK 0x02
67#define DB9_GENESIS_PAD 0x03
68#define DB9_GENESIS5_PAD 0x05
69#define DB9_GENESIS6_PAD 0x06
70#define DB9_SATURN_PAD 0x07
71#define DB9_MULTI_0802 0x08
72#define DB9_MULTI_0802_2 0x09
73#define DB9_CD32_PAD 0x0A
74#define DB9_SATURN_DPP 0x0B
75#define DB9_SATURN_DPP_2 0x0C
76#define DB9_MAX_PAD 0x0D
77
78#define DB9_UP 0x01
79#define DB9_DOWN 0x02
80#define DB9_LEFT 0x04
81#define DB9_RIGHT 0x08
82#define DB9_FIRE1 0x10
83#define DB9_FIRE2 0x20
84#define DB9_FIRE3 0x40
85#define DB9_FIRE4 0x80
86
87#define DB9_NORMAL 0x0a
88#define DB9_NOSELECT 0x08
89
90#define DB9_MAX_DEVICES 2
91
92#define DB9_GENESIS6_DELAY 14
93#define DB9_REFRESH_TIME HZ/100
94
95struct db9 {
96 struct input_dev dev[DB9_MAX_DEVICES];
97 struct timer_list timer;
98 struct pardevice *pd;
99 int mode;
100 int used;
101 char phys[2][32];
102};
103
104static struct db9 *db9_base[3];
105
106static short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
107static short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE };
108static short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
109
110static char db9_buttons[DB9_MAX_PAD] = { 0, 1, 2, 4, 0, 6, 8, 9, 1, 1, 7, 9, 9 };
111static short *db9_btn[DB9_MAX_PAD] = { NULL, db9_multi_btn, db9_multi_btn, db9_genesis_btn, NULL, db9_genesis_btn,
112 db9_genesis_btn, db9_cd32_btn, db9_multi_btn, db9_multi_btn, db9_cd32_btn,
113 db9_cd32_btn, db9_cd32_btn };
114static char *db9_name[DB9_MAX_PAD] = { NULL, "Multisystem joystick", "Multisystem joystick (2 fire)", "Genesis pad",
115 NULL, "Genesis 5 pad", "Genesis 6 pad", "Saturn pad", "Multisystem (0.8.0.2) joystick",
116 "Multisystem (0.8.0.2-dual) joystick", "Amiga CD-32 pad", "Saturn dpp", "Saturn dpp dual" };
117
118static const int db9_max_pads[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 6, 1, 2, 1, 6, 12 };
119static const int db9_num_axis[DB9_MAX_PAD] = { 0, 2, 2, 2, 0, 2, 2, 7, 2, 2, 2 ,7, 7 };
120static const short db9_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_RZ, ABS_Z, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
121static const int db9_bidirectional[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0 };
122static const int db9_reverse[DB9_MAX_PAD] = { 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0 };
123
124/*
125 * Saturn controllers
126 */
127#define DB9_SATURN_DELAY 300
128static const int db9_saturn_byte[] = { 1, 1, 1, 2, 2, 2, 2, 2, 1 };
129static const unsigned char db9_saturn_mask[] = { 0x04, 0x01, 0x02, 0x40, 0x20, 0x10, 0x08, 0x80, 0x08 };
130
131/*
132 * db9_saturn_write_sub() writes 2 bit data.
133 */
134static void db9_saturn_write_sub(struct parport *port, int type, unsigned char data, int powered, int pwr_sub)
135{
136 unsigned char c;
137
138 switch (type) {
139 case 1: /* DPP1 */
140 c = 0x80 | 0x30 | (powered ? 0x08 : 0) | (pwr_sub ? 0x04 : 0) | data;
141 parport_write_data(port, c);
142 break;
143 case 2: /* DPP2 */
144 c = 0x40 | data << 4 | (powered ? 0x08 : 0) | (pwr_sub ? 0x04 : 0) | 0x03;
145 parport_write_data(port, c);
146 break;
147 case 0: /* DB9 */
148 c = ((((data & 2) ? 2 : 0) | ((data & 1) ? 4 : 0)) ^ 0x02) | !powered;
149 parport_write_control(port, c);
150 break;
151 }
152}
153
154/*
155 * gc_saturn_read_sub() reads 4 bit data.
156 */
157static unsigned char db9_saturn_read_sub(struct parport *port, int type)
158{
159 unsigned char data;
160
161 if (type) {
162 /* DPP */
163 data = parport_read_status(port) ^ 0x80;
164 return (data & 0x80 ? 1 : 0) | (data & 0x40 ? 2 : 0)
165 | (data & 0x20 ? 4 : 0) | (data & 0x10 ? 8 : 0);
166 } else {
167 /* DB9 */
168 data = parport_read_data(port) & 0x0f;
169 return (data & 0x8 ? 1 : 0) | (data & 0x4 ? 2 : 0)
170 | (data & 0x2 ? 4 : 0) | (data & 0x1 ? 8 : 0);
171 }
172}
173
174/*
175 * db9_saturn_read_analog() sends clock and reads 8 bit data.
176 */
177static unsigned char db9_saturn_read_analog(struct parport *port, int type, int powered)
178{
179 unsigned char data;
180
181 db9_saturn_write_sub(port, type, 0, powered, 0);
182 udelay(DB9_SATURN_DELAY);
183 data = db9_saturn_read_sub(port, type) << 4;
184 db9_saturn_write_sub(port, type, 2, powered, 0);
185 udelay(DB9_SATURN_DELAY);
186 data |= db9_saturn_read_sub(port, type);
187 return data;
188}
189
190/*
191 * db9_saturn_read_packet() reads whole saturn packet at connector
192 * and returns device identifier code.
193 */
194static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char *data, int type, int powered)
195{
196 int i, j;
197 unsigned char tmp;
198
199 db9_saturn_write_sub(port, type, 3, powered, 0);
200 data[0] = db9_saturn_read_sub(port, type);
201 switch (data[0] & 0x0f) {
202 case 0xf:
203 /* 1111 no pad */
204 return data[0] = 0xff;
205 case 0x4: case 0x4 | 0x8:
206 /* ?100 : digital controller */
207 db9_saturn_write_sub(port, type, 0, powered, 1);
208 data[2] = db9_saturn_read_sub(port, type) << 4;
209 db9_saturn_write_sub(port, type, 2, powered, 1);
210 data[1] = db9_saturn_read_sub(port, type) << 4;
211 db9_saturn_write_sub(port, type, 1, powered, 1);
212 data[1] |= db9_saturn_read_sub(port, type);
213 db9_saturn_write_sub(port, type, 3, powered, 1);
214 /* data[2] |= db9_saturn_read_sub(port, type); */
215 data[2] |= data[0];
216 return data[0] = 0x02;
217 case 0x1:
218 /* 0001 : analog controller or multitap */
219 db9_saturn_write_sub(port, type, 2, powered, 0);
220 udelay(DB9_SATURN_DELAY);
221 data[0] = db9_saturn_read_analog(port, type, powered);
222 if (data[0] != 0x41) {
223 /* read analog controller */
224 for (i = 0; i < (data[0] & 0x0f); i++)
225 data[i + 1] = db9_saturn_read_analog(port, type, powered);
226 db9_saturn_write_sub(port, type, 3, powered, 0);
227 return data[0];
228 } else {
229 /* read multitap */
230 if (db9_saturn_read_analog(port, type, powered) != 0x60)
231 return data[0] = 0xff;
232 for (i = 0; i < 60; i += 10) {
233 data[i] = db9_saturn_read_analog(port, type, powered);
234 if (data[i] != 0xff)
235 /* read each pad */
236 for (j = 0; j < (data[i] & 0x0f); j++)
237 data[i + j + 1] = db9_saturn_read_analog(port, type, powered);
238 }
239 db9_saturn_write_sub(port, type, 3, powered, 0);
240 return 0x41;
241 }
242 case 0x0:
243 /* 0000 : mouse */
244 db9_saturn_write_sub(port, type, 2, powered, 0);
245 udelay(DB9_SATURN_DELAY);
246 tmp = db9_saturn_read_analog(port, type, powered);
247 if (tmp == 0xff) {
248 for (i = 0; i < 3; i++)
249 data[i + 1] = db9_saturn_read_analog(port, type, powered);
250 db9_saturn_write_sub(port, type, 3, powered, 0);
251 return data[0] = 0xe3;
252 }
253 default:
254 return data[0];
255 }
256}
257
258/*
259 * db9_saturn_report() analyzes packet and reports.
260 */
261static int db9_saturn_report(unsigned char id, unsigned char data[60], struct input_dev *dev, int n, int max_pads)
262{
263 int tmp, i, j;
264
265 tmp = (id == 0x41) ? 60 : 10;
266 for (j = 0; (j < tmp) && (n < max_pads); j += 10, n++) {
267 switch (data[j]) {
268 case 0x16: /* multi controller (analog 4 axis) */
269 input_report_abs(dev + n, db9_abs[5], data[j + 6]);
270 case 0x15: /* mission stick (analog 3 axis) */
271 input_report_abs(dev + n, db9_abs[3], data[j + 4]);
272 input_report_abs(dev + n, db9_abs[4], data[j + 5]);
273 case 0x13: /* racing controller (analog 1 axis) */
274 input_report_abs(dev + n, db9_abs[2], data[j + 3]);
275 case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */
276 case 0x02: /* digital pad (digital 2 axis + buttons) */
277 input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
278 input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
279 for (i = 0; i < 9; i++)
280 input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
281 break;
282 case 0x19: /* mission stick x2 (analog 6 axis + buttons) */
283 input_report_abs(dev + n, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
284 input_report_abs(dev + n, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
285 for (i = 0; i < 9; i++)
286 input_report_key(dev + n, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
287 input_report_abs(dev + n, db9_abs[2], data[j + 3]);
288 input_report_abs(dev + n, db9_abs[3], data[j + 4]);
289 input_report_abs(dev + n, db9_abs[4], data[j + 5]);
290 /*
291 input_report_abs(dev + n, db9_abs[8], (data[j + 6] & 128 ? 0 : 1) - (data[j + 6] & 64 ? 0 : 1));
292 input_report_abs(dev + n, db9_abs[9], (data[j + 6] & 32 ? 0 : 1) - (data[j + 6] & 16 ? 0 : 1));
293 */
294 input_report_abs(dev + n, db9_abs[6], data[j + 7]);
295 input_report_abs(dev + n, db9_abs[7], data[j + 8]);
296 input_report_abs(dev + n, db9_abs[5], data[j + 9]);
297 break;
298 case 0xd3: /* sankyo ff (analog 1 axis + stop btn) */
299 input_report_key(dev + n, BTN_A, data[j + 3] & 0x80);
300 input_report_abs(dev + n, db9_abs[2], data[j + 3] & 0x7f);
301 break;
302 case 0xe3: /* shuttle mouse (analog 2 axis + buttons. signed value) */
303 input_report_key(dev + n, BTN_START, data[j + 1] & 0x08);
304 input_report_key(dev + n, BTN_A, data[j + 1] & 0x04);
305 input_report_key(dev + n, BTN_C, data[j + 1] & 0x02);
306 input_report_key(dev + n, BTN_B, data[j + 1] & 0x01);
307 input_report_abs(dev + n, db9_abs[2], data[j + 2] ^ 0x80);
308 input_report_abs(dev + n, db9_abs[3], (0xff-(data[j + 3] ^ 0x80))+1); /* */
309 break;
310 case 0xff:
311 default: /* no pad */
312 input_report_abs(dev + n, db9_abs[0], 0);
313 input_report_abs(dev + n, db9_abs[1], 0);
314 for (i = 0; i < 9; i++)
315 input_report_key(dev + n, db9_cd32_btn[i], 0);
316 break;
317 }
318 }
319 return n;
320}
321
322static int db9_saturn(int mode, struct parport *port, struct input_dev *dev)
323{
324 unsigned char id, data[60];
325 int type, n, max_pads;
326 int tmp, i;
327
328 switch (mode) {
329 case DB9_SATURN_PAD:
330 type = 0;
331 n = 1;
332 break;
333 case DB9_SATURN_DPP:
334 type = 1;
335 n = 1;
336 break;
337 case DB9_SATURN_DPP_2:
338 type = 1;
339 n = 2;
340 break;
341 default:
342 return -1;
343 }
344 max_pads = min(db9_max_pads[mode], DB9_MAX_DEVICES);
345 for (tmp = 0, i = 0; i < n; i++) {
346 id = db9_saturn_read_packet(port, data, type + i, 1);
347 tmp = db9_saturn_report(id, data, dev, tmp, max_pads);
348 }
349 return 0;
350}
351
352static void db9_timer(unsigned long private)
353{
354 struct db9 *db9 = (void *) private;
355 struct parport *port = db9->pd->port;
356 struct input_dev *dev = db9->dev;
357 int data, i;
358
359 switch(db9->mode) {
360 case DB9_MULTI_0802_2:
361
362 data = parport_read_data(port) >> 3;
363
364 input_report_abs(dev + 1, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
365 input_report_abs(dev + 1, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
366 input_report_key(dev + 1, BTN_TRIGGER, ~data & DB9_FIRE1);
367
368 case DB9_MULTI_0802:
369
370 data = parport_read_status(port) >> 3;
371
372 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
373 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
374 input_report_key(dev, BTN_TRIGGER, data & DB9_FIRE1);
375 break;
376
377 case DB9_MULTI_STICK:
378
379 data = parport_read_data(port);
380
381 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
382 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
383 input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
384 break;
385
386 case DB9_MULTI2_STICK:
387
388 data = parport_read_data(port);
389
390 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
391 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
392 input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
393 input_report_key(dev, BTN_THUMB, ~data & DB9_FIRE2);
394 break;
395
396 case DB9_GENESIS_PAD:
397
398 parport_write_control(port, DB9_NOSELECT);
399 data = parport_read_data(port);
400
401 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
402 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
403 input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
404 input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
405
406 parport_write_control(port, DB9_NORMAL);
407 data=parport_read_data(port);
408
409 input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
410 input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
411 break;
412
413 case DB9_GENESIS5_PAD:
414
415 parport_write_control(port, DB9_NOSELECT);
416 data=parport_read_data(port);
417
418 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
419 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
420 input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
421 input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
422
423 parport_write_control(port, DB9_NORMAL);
424 data=parport_read_data(port);
425
426 input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
427 input_report_key(dev, BTN_X, ~data & DB9_FIRE2);
428 input_report_key(dev, BTN_Y, ~data & DB9_LEFT);
429 input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
430 break;
431
432 case DB9_GENESIS6_PAD:
433
434 parport_write_control(port, DB9_NOSELECT); /* 1 */
435 udelay(DB9_GENESIS6_DELAY);
436 data=parport_read_data(port);
437
438 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
439 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
440 input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
441 input_report_key(dev, BTN_C, ~data & DB9_FIRE2);
442
443 parport_write_control(port, DB9_NORMAL);
444 udelay(DB9_GENESIS6_DELAY);
445 data=parport_read_data(port);
446
447 input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
448 input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
449
450 parport_write_control(port, DB9_NOSELECT); /* 2 */
451 udelay(DB9_GENESIS6_DELAY);
452 parport_write_control(port, DB9_NORMAL);
453 udelay(DB9_GENESIS6_DELAY);
454 parport_write_control(port, DB9_NOSELECT); /* 3 */
455 udelay(DB9_GENESIS6_DELAY);
456 data=parport_read_data(port);
457
458 input_report_key(dev, BTN_X, ~data & DB9_LEFT);
459 input_report_key(dev, BTN_Y, ~data & DB9_DOWN);
460 input_report_key(dev, BTN_Z, ~data & DB9_UP);
461 input_report_key(dev, BTN_MODE, ~data & DB9_RIGHT);
462
463 parport_write_control(port, DB9_NORMAL);
464 udelay(DB9_GENESIS6_DELAY);
465 parport_write_control(port, DB9_NOSELECT); /* 4 */
466 udelay(DB9_GENESIS6_DELAY);
467 parport_write_control(port, DB9_NORMAL);
468 break;
469
470 case DB9_SATURN_PAD:
471 case DB9_SATURN_DPP:
472 case DB9_SATURN_DPP_2:
473
474 db9_saturn(db9->mode, port, dev);
475 break;
476
477 case DB9_CD32_PAD:
478
479 data=parport_read_data(port);
480
481 input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
482 input_report_abs(dev, ABS_Y, (data & DB9_DOWN ? 0 : 1) - (data & DB9_UP ? 0 : 1));
483
484 parport_write_control(port, 0x0a);
485
486 for (i = 0; i < 7; i++) {
487 data = parport_read_data(port);
488 parport_write_control(port, 0x02);
489 parport_write_control(port, 0x0a);
490 input_report_key(dev, db9_cd32_btn[i], ~data & DB9_FIRE2);
491 }
492
493 parport_write_control(port, 0x00);
494 break;
495 }
496
497 input_sync(dev);
498
499 mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
500}
501
502static int db9_open(struct input_dev *dev)
503{
504 struct db9 *db9 = dev->private;
505 struct parport *port = db9->pd->port;
506
507 if (!db9->used++) {
508 parport_claim(db9->pd);
509 parport_write_data(port, 0xff);
510 if (db9_reverse[db9->mode]) {
511 parport_data_reverse(port);
512 parport_write_control(port, DB9_NORMAL);
513 }
514 mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
515 }
516
517 return 0;
518}
519
520static void db9_close(struct input_dev *dev)
521{
522 struct db9 *db9 = dev->private;
523 struct parport *port = db9->pd->port;
524
525 if (!--db9->used) {
526 del_timer(&db9->timer);
527 parport_write_control(port, 0x00);
528 parport_data_forward(port);
529 parport_release(db9->pd);
530 }
531}
532
533static struct db9 __init *db9_probe(int *config, int nargs)
534{
535 struct db9 *db9;
536 struct parport *pp;
537 int i, j;
538
539 if (config[0] < 0)
540 return NULL;
541
542 if (nargs < 2) {
543 printk(KERN_ERR "db9.c: Device type must be specified.\n");
544 return NULL;
545 }
546
547 if (config[1] < 1 || config[1] >= DB9_MAX_PAD || !db9_buttons[config[1]]) {
548 printk(KERN_ERR "db9.c: bad config\n");
549 return NULL;
550 }
551
552 pp = parport_find_number(config[0]);
553 if (!pp) {
554 printk(KERN_ERR "db9.c: no such parport\n");
555 return NULL;
556 }
557
558 if (db9_bidirectional[config[1]]) {
559 if (!(pp->modes & PARPORT_MODE_TRISTATE)) {
560 printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
561 parport_put_port(pp);
562 return NULL;
563 }
564 }
565
566 if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL))) {
567 parport_put_port(pp);
568 return NULL;
569 }
570 memset(db9, 0, sizeof(struct db9));
571
572 db9->mode = config[1];
573 init_timer(&db9->timer);
574 db9->timer.data = (long) db9;
575 db9->timer.function = db9_timer;
576
577 db9->pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
578 parport_put_port(pp);
579
580 if (!db9->pd) {
581 printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
582 kfree(db9);
583 return NULL;
584 }
585
586 for (i = 0; i < (min(db9_max_pads[db9->mode], DB9_MAX_DEVICES)); i++) {
587
588 sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i);
589
590 db9->dev[i].private = db9;
591 db9->dev[i].open = db9_open;
592 db9->dev[i].close = db9_close;
593
594 db9->dev[i].name = db9_name[db9->mode];
595 db9->dev[i].phys = db9->phys[i];
596 db9->dev[i].id.bustype = BUS_PARPORT;
597 db9->dev[i].id.vendor = 0x0002;
598 db9->dev[i].id.product = config[1];
599 db9->dev[i].id.version = 0x0100;
600
601 db9->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
602 for (j = 0; j < db9_buttons[db9->mode]; j++)
603 set_bit(db9_btn[db9->mode][j], db9->dev[i].keybit);
604 for (j = 0; j < db9_num_axis[db9->mode]; j++) {
605 set_bit(db9_abs[j], db9->dev[i].absbit);
606 if (j < 2) {
607 db9->dev[i].absmin[db9_abs[j]] = -1;
608 db9->dev[i].absmax[db9_abs[j]] = 1;
609 } else {
610 db9->dev[i].absmin[db9_abs[j]] = 1;
611 db9->dev[i].absmax[db9_abs[j]] = 255;
612 db9->dev[i].absflat[db9_abs[j]] = 0;
613 }
614 }
615 input_register_device(db9->dev + i);
616 printk(KERN_INFO "input: %s on %s\n", db9->dev[i].name, db9->pd->port->name);
617 }
618
619 return db9;
620}
621
622static int __init db9_init(void)
623{
624 db9_base[0] = db9_probe(db9, db9_nargs);
625 db9_base[1] = db9_probe(db9_2, db9_nargs_2);
626 db9_base[2] = db9_probe(db9_3, db9_nargs_3);
627
628 if (db9_base[0] || db9_base[1] || db9_base[2])
629 return 0;
630
631 return -ENODEV;
632}
633
634static void __exit db9_exit(void)
635{
636 int i, j;
637
638 for (i = 0; i < 3; i++)
639 if (db9_base[i]) {
640 for (j = 0; j < min(db9_max_pads[db9_base[i]->mode], DB9_MAX_DEVICES); j++)
641 input_unregister_device(db9_base[i]->dev + j);
642 parport_unregister_device(db9_base[i]->pd);
643 }
644}
645
646module_init(db9_init);
647module_exit(db9_exit);
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
new file mode 100644
index 000000000000..8732f52bdd08
--- /dev/null
+++ b/drivers/input/joystick/gamecon.c
@@ -0,0 +1,697 @@
1/*
2 * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
3 *
4 * Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz>
5 * Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org>
6 *
7 * Based on the work of:
8 * Andree Borrmann John Dahlstrom
9 * David Kuder Nathan Hand
10 */
11
12/*
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 * Should you need to contact me, the author, you can do so either by
28 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
29 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
30 */
31
32#include <linux/kernel.h>
33#include <linux/delay.h>
34#include <linux/module.h>
35#include <linux/moduleparam.h>
36#include <linux/init.h>
37#include <linux/parport.h>
38#include <linux/input.h>
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver");
42MODULE_LICENSE("GPL");
43
44static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 };
45static int gc_nargs __initdata = 0;
46module_param_array_named(map, gc, int, &gc_nargs, 0);
47MODULE_PARM_DESC(map, "Describers first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)");
48
49static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 };
50static int gc_nargs_2 __initdata = 0;
51module_param_array_named(map2, gc_2, int, &gc_nargs_2, 0);
52MODULE_PARM_DESC(map2, "Describers second set of devices");
53
54static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 };
55static int gc_nargs_3 __initdata = 0;
56module_param_array_named(map3, gc_3, int, &gc_nargs_3, 0);
57MODULE_PARM_DESC(map3, "Describers third set of devices");
58
59__obsolete_setup("gc=");
60__obsolete_setup("gc_2=");
61__obsolete_setup("gc_3=");
62
63/* see also gs_psx_delay parameter in PSX support section */
64
65#define GC_SNES 1
66#define GC_NES 2
67#define GC_NES4 3
68#define GC_MULTI 4
69#define GC_MULTI2 5
70#define GC_N64 6
71#define GC_PSX 7
72#define GC_DDR 8
73
74#define GC_MAX 8
75
76#define GC_REFRESH_TIME HZ/100
77
78struct gc {
79 struct pardevice *pd;
80 struct input_dev dev[5];
81 struct timer_list timer;
82 unsigned char pads[GC_MAX + 1];
83 int used;
84 char phys[5][32];
85};
86
87static struct gc *gc_base[3];
88
89static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
90
91static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
92 "Multisystem 2-button joystick", "N64 controller", "PSX controller",
93 "PSX DDR controller" };
94/*
95 * N64 support.
96 */
97
98static unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 };
99static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START };
100
101#define GC_N64_LENGTH 32 /* N64 bit length, not including stop bit */
102#define GC_N64_REQUEST_LENGTH 37 /* transmit request sequence is 9 bits long */
103#define GC_N64_DELAY 133 /* delay between transmit request, and response ready (us) */
104#define GC_N64_REQUEST 0x1dd1111111ULL /* the request data command (encoded for 000000011) */
105#define GC_N64_DWS 3 /* delay between write segments (required for sound playback because of ISA DMA) */
106 /* GC_N64_DWS > 24 is known to fail */
107#define GC_N64_POWER_W 0xe2 /* power during write (transmit request) */
108#define GC_N64_POWER_R 0xfd /* power during read */
109#define GC_N64_OUT 0x1d /* output bits to the 4 pads */
110 /* Reading the main axes of any N64 pad is known to fail if the corresponding bit */
111 /* in GC_N64_OUT is pulled low on the output port (by any routine) for more */
112 /* than 123 us */
113#define GC_N64_CLOCK 0x02 /* clock bits for read */
114
115/*
116 * gc_n64_read_packet() reads an N64 packet.
117 * Each pad uses one bit per byte. So all pads connected to this port are read in parallel.
118 */
119
120static void gc_n64_read_packet(struct gc *gc, unsigned char *data)
121{
122 int i;
123 unsigned long flags;
124
125/*
126 * Request the pad to transmit data
127 */
128
129 local_irq_save(flags);
130 for (i = 0; i < GC_N64_REQUEST_LENGTH; i++) {
131 parport_write_data(gc->pd->port, GC_N64_POWER_W | ((GC_N64_REQUEST >> i) & 1 ? GC_N64_OUT : 0));
132 udelay(GC_N64_DWS);
133 }
134 local_irq_restore(flags);
135
136/*
137 * Wait for the pad response to be loaded into the 33-bit register of the adapter
138 */
139
140 udelay(GC_N64_DELAY);
141
142/*
143 * Grab data (ignoring the last bit, which is a stop bit)
144 */
145
146 for (i = 0; i < GC_N64_LENGTH; i++) {
147 parport_write_data(gc->pd->port, GC_N64_POWER_R);
148 data[i] = parport_read_status(gc->pd->port);
149 parport_write_data(gc->pd->port, GC_N64_POWER_R | GC_N64_CLOCK);
150 }
151
152/*
153 * We must wait 200 ms here for the controller to reinitialize before the next read request.
154 * No worries as long as gc_read is polled less frequently than this.
155 */
156
157}
158
159/*
160 * NES/SNES support.
161 */
162
163#define GC_NES_DELAY 6 /* Delay between bits - 6us */
164#define GC_NES_LENGTH 8 /* The NES pads use 8 bits of data */
165#define GC_SNES_LENGTH 12 /* The SNES true length is 16, but the last 4 bits are unused */
166
167#define GC_NES_POWER 0xfc
168#define GC_NES_CLOCK 0x01
169#define GC_NES_LATCH 0x02
170
171static unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 };
172static unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 };
173static short gc_snes_btn[] = { BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR };
174
175/*
176 * gc_nes_read_packet() reads a NES/SNES packet.
177 * Each pad uses one bit per byte. So all pads connected to
178 * this port are read in parallel.
179 */
180
181static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data)
182{
183 int i;
184
185 parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK | GC_NES_LATCH);
186 udelay(GC_NES_DELAY * 2);
187 parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK);
188
189 for (i = 0; i < length; i++) {
190 udelay(GC_NES_DELAY);
191 parport_write_data(gc->pd->port, GC_NES_POWER);
192 data[i] = parport_read_status(gc->pd->port) ^ 0x7f;
193 udelay(GC_NES_DELAY);
194 parport_write_data(gc->pd->port, GC_NES_POWER | GC_NES_CLOCK);
195 }
196}
197
198/*
199 * Multisystem joystick support
200 */
201
202#define GC_MULTI_LENGTH 5 /* Multi system joystick packet length is 5 */
203#define GC_MULTI2_LENGTH 6 /* One more bit for one more button */
204
205/*
206 * gc_multi_read_packet() reads a Multisystem joystick packet.
207 */
208
209static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
210{
211 int i;
212
213 for (i = 0; i < length; i++) {
214 parport_write_data(gc->pd->port, ~(1 << i));
215 data[i] = parport_read_status(gc->pd->port) ^ 0x7f;
216 }
217}
218
219/*
220 * PSX support
221 *
222 * See documentation at:
223 * http://www.dim.com/~mackys/psxmemcard/ps-eng2.txt
224 * http://www.gamesx.com/controldata/psxcont/psxcont.htm
225 * ftp://milano.usal.es/pablo/
226 *
227 */
228
229#define GC_PSX_DELAY 25 /* 25 usec */
230#define GC_PSX_LENGTH 8 /* talk to the controller in bits */
231#define GC_PSX_BYTES 6 /* the maximum number of bytes to read off the controller */
232
233#define GC_PSX_MOUSE 1 /* Mouse */
234#define GC_PSX_NEGCON 2 /* NegCon */
235#define GC_PSX_NORMAL 4 /* Digital / Analog or Rumble in Digital mode */
236#define GC_PSX_ANALOG 5 /* Analog in Analog mode / Rumble in Green mode */
237#define GC_PSX_RUMBLE 7 /* Rumble in Red mode */
238
239#define GC_PSX_CLOCK 0x04 /* Pin 4 */
240#define GC_PSX_COMMAND 0x01 /* Pin 2 */
241#define GC_PSX_POWER 0xf8 /* Pins 5-9 */
242#define GC_PSX_SELECT 0x02 /* Pin 3 */
243
244#define GC_PSX_ID(x) ((x) >> 4) /* High nibble is device type */
245#define GC_PSX_LEN(x) (((x) & 0xf) << 1) /* Low nibble is length in bytes/2 */
246
247static int gc_psx_delay = GC_PSX_DELAY;
248module_param_named(psx_delay, gc_psx_delay, uint, 0);
249MODULE_PARM_DESC(psx_delay, "Delay when accessing Sony PSX controller (usecs)");
250
251__obsolete_setup("gc_psx_delay=");
252
253static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y };
254static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y,
255 BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR };
256static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 };
257
258/*
259 * gc_psx_command() writes 8bit command and reads 8bit data from
260 * the psx pad.
261 */
262
263static void gc_psx_command(struct gc *gc, int b, unsigned char data[5])
264{
265 int i, j, cmd, read;
266 for (i = 0; i < 5; i++)
267 data[i] = 0;
268
269 for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) {
270 cmd = (b & 1) ? GC_PSX_COMMAND : 0;
271 parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
272 udelay(gc_psx_delay);
273 read = parport_read_status(gc->pd->port) ^ 0x80;
274 for (j = 0; j < 5; j++)
275 data[j] |= (read & gc_status_bit[j] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) ? (1 << i) : 0;
276 parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
277 udelay(gc_psx_delay);
278 }
279}
280
281/*
282 * gc_psx_read_packet() reads a whole psx packet and returns
283 * device identifier code.
284 */
285
286static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES], unsigned char id[5])
287{
288 int i, j, max_len = 0;
289 unsigned long flags;
290 unsigned char data2[5];
291
292 parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); /* Select pad */
293 udelay(gc_psx_delay);
294 parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER); /* Deselect, begin command */
295 udelay(gc_psx_delay);
296
297 local_irq_save(flags);
298
299 gc_psx_command(gc, 0x01, data2); /* Access pad */
300 gc_psx_command(gc, 0x42, id); /* Get device ids */
301 gc_psx_command(gc, 0, data2); /* Dump status */
302
303 for (i =0; i < 5; i++) /* Find the longest pad */
304 if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR]))
305 && (GC_PSX_LEN(id[i]) > max_len)
306 && (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES))
307 max_len = GC_PSX_LEN(id[i]);
308
309 for (i = 0; i < max_len; i++) { /* Read in all the data */
310 gc_psx_command(gc, 0, data2);
311 for (j = 0; j < 5; j++)
312 data[j][i] = data2[j];
313 }
314
315 local_irq_restore(flags);
316
317 parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);
318
319 for(i = 0; i < 5; i++) /* Set id's to the real value */
320 id[i] = GC_PSX_ID(id[i]);
321}
322
323/*
324 * gc_timer() reads and analyzes console pads data.
325 */
326
327#define GC_MAX_LENGTH GC_N64_LENGTH
328
329static void gc_timer(unsigned long private)
330{
331 struct gc *gc = (void *) private;
332 struct input_dev *dev = gc->dev;
333 unsigned char data[GC_MAX_LENGTH];
334 unsigned char data_psx[5][GC_PSX_BYTES];
335 int i, j, s;
336
337/*
338 * N64 pads - must be read first, any read confuses them for 200 us
339 */
340
341 if (gc->pads[GC_N64]) {
342
343 gc_n64_read_packet(gc, data);
344
345 for (i = 0; i < 5; i++) {
346
347 s = gc_status_bit[i];
348
349 if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) {
350
351 signed char axes[2];
352 axes[0] = axes[1] = 0;
353
354 for (j = 0; j < 8; j++) {
355 if (data[23 - j] & s) axes[0] |= 1 << j;
356 if (data[31 - j] & s) axes[1] |= 1 << j;
357 }
358
359 input_report_abs(dev + i, ABS_X, axes[0]);
360 input_report_abs(dev + i, ABS_Y, -axes[1]);
361
362 input_report_abs(dev + i, ABS_HAT0X, !(s & data[6]) - !(s & data[7]));
363 input_report_abs(dev + i, ABS_HAT0Y, !(s & data[4]) - !(s & data[5]));
364
365 for (j = 0; j < 10; j++)
366 input_report_key(dev + i, gc_n64_btn[j], s & data[gc_n64_bytes[j]]);
367
368 input_sync(dev + i);
369 }
370 }
371 }
372
373/*
374 * NES and SNES pads
375 */
376
377 if (gc->pads[GC_NES] || gc->pads[GC_SNES]) {
378
379 gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data);
380
381 for (i = 0; i < 5; i++) {
382
383 s = gc_status_bit[i];
384
385 if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) {
386 input_report_abs(dev + i, ABS_X, !(s & data[6]) - !(s & data[7]));
387 input_report_abs(dev + i, ABS_Y, !(s & data[4]) - !(s & data[5]));
388 }
389
390 if (s & gc->pads[GC_NES])
391 for (j = 0; j < 4; j++)
392 input_report_key(dev + i, gc_snes_btn[j], s & data[gc_nes_bytes[j]]);
393
394 if (s & gc->pads[GC_SNES])
395 for (j = 0; j < 8; j++)
396 input_report_key(dev + i, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
397
398 input_sync(dev + i);
399 }
400 }
401
402/*
403 * Multi and Multi2 joysticks
404 */
405
406 if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2]) {
407
408 gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data);
409
410 for (i = 0; i < 5; i++) {
411
412 s = gc_status_bit[i];
413
414 if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) {
415 input_report_abs(dev + i, ABS_X, !(s & data[2]) - !(s & data[3]));
416 input_report_abs(dev + i, ABS_Y, !(s & data[0]) - !(s & data[1]));
417 input_report_key(dev + i, BTN_TRIGGER, s & data[4]);
418 }
419
420 if (s & gc->pads[GC_MULTI2])
421 input_report_key(dev + i, BTN_THUMB, s & data[5]);
422
423 input_sync(dev + i);
424 }
425 }
426
427/*
428 * PSX controllers
429 */
430
431 if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) {
432
433 gc_psx_read_packet(gc, data_psx, data);
434
435 for (i = 0; i < 5; i++) {
436 switch (data[i]) {
437
438 case GC_PSX_RUMBLE:
439
440 input_report_key(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04);
441 input_report_key(dev + i, BTN_THUMBR, ~data_psx[i][0] & 0x02);
442
443 case GC_PSX_NEGCON:
444 case GC_PSX_ANALOG:
445
446 if(gc->pads[GC_DDR] & gc_status_bit[i]) {
447 for(j = 0; j < 4; j++)
448 input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
449 } else {
450 for (j = 0; j < 4; j++)
451 input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]);
452
453 input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
454 input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
455 }
456
457 for (j = 0; j < 8; j++)
458 input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
459
460 input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08);
461 input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
462
463 input_sync(dev + i);
464
465 break;
466
467 case GC_PSX_NORMAL:
468 if(gc->pads[GC_DDR] & gc_status_bit[i]) {
469 for(j = 0; j < 4; j++)
470 input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j));
471 } else {
472 input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128);
473 input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128);
474
475 /* for some reason if the extra axes are left unset they drift */
476 /* for (j = 0; j < 4; j++)
477 input_report_abs(dev + i, gc_psx_abs[j+2], 128);
478 * This needs to be debugged properly,
479 * maybe fuzz processing needs to be done in input_sync()
480 * --vojtech
481 */
482 }
483
484 for (j = 0; j < 8; j++)
485 input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j));
486
487 input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08);
488 input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01);
489
490 input_sync(dev + i);
491
492 break;
493
494 case 0: /* not a pad, ignore */
495 break;
496 }
497 }
498 }
499
500 mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
501}
502
503static int gc_open(struct input_dev *dev)
504{
505 struct gc *gc = dev->private;
506 if (!gc->used++) {
507 parport_claim(gc->pd);
508 parport_write_control(gc->pd->port, 0x04);
509 mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
510 }
511 return 0;
512}
513
514static void gc_close(struct input_dev *dev)
515{
516 struct gc *gc = dev->private;
517 if (!--gc->used) {
518 del_timer(&gc->timer);
519 parport_write_control(gc->pd->port, 0x00);
520 parport_release(gc->pd);
521 }
522}
523
524static struct gc __init *gc_probe(int *config, int nargs)
525{
526 struct gc *gc;
527 struct parport *pp;
528 int i, j;
529
530 if (config[0] < 0)
531 return NULL;
532
533 if (nargs < 2) {
534 printk(KERN_ERR "gamecon.c: at least one device must be specified\n");
535 return NULL;
536 }
537
538 pp = parport_find_number(config[0]);
539
540 if (!pp) {
541 printk(KERN_ERR "gamecon.c: no such parport\n");
542 return NULL;
543 }
544
545 if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) {
546 parport_put_port(pp);
547 return NULL;
548 }
549 memset(gc, 0, sizeof(struct gc));
550
551 gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
552
553 parport_put_port(pp);
554
555 if (!gc->pd) {
556 printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n");
557 kfree(gc);
558 return NULL;
559 }
560
561 parport_claim(gc->pd);
562
563 init_timer(&gc->timer);
564 gc->timer.data = (long) gc;
565 gc->timer.function = gc_timer;
566
567 for (i = 0; i < nargs - 1; i++) {
568
569 if (!config[i + 1])
570 continue;
571
572 if (config[i + 1] < 1 || config[i + 1] > GC_MAX) {
573 printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", config[i + 1]);
574 continue;
575 }
576
577 gc->dev[i].private = gc;
578 gc->dev[i].open = gc_open;
579 gc->dev[i].close = gc_close;
580
581 gc->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
582
583 for (j = 0; j < 2; j++) {
584 set_bit(ABS_X + j, gc->dev[i].absbit);
585 gc->dev[i].absmin[ABS_X + j] = -1;
586 gc->dev[i].absmax[ABS_X + j] = 1;
587 }
588
589 gc->pads[0] |= gc_status_bit[i];
590 gc->pads[config[i + 1]] |= gc_status_bit[i];
591
592 switch(config[i + 1]) {
593
594 case GC_N64:
595 for (j = 0; j < 10; j++)
596 set_bit(gc_n64_btn[j], gc->dev[i].keybit);
597
598 for (j = 0; j < 2; j++) {
599 set_bit(ABS_X + j, gc->dev[i].absbit);
600 gc->dev[i].absmin[ABS_X + j] = -127;
601 gc->dev[i].absmax[ABS_X + j] = 126;
602 gc->dev[i].absflat[ABS_X + j] = 2;
603 set_bit(ABS_HAT0X + j, gc->dev[i].absbit);
604 gc->dev[i].absmin[ABS_HAT0X + j] = -1;
605 gc->dev[i].absmax[ABS_HAT0X + j] = 1;
606 }
607
608 break;
609
610 case GC_SNES:
611 for (j = 4; j < 8; j++)
612 set_bit(gc_snes_btn[j], gc->dev[i].keybit);
613 case GC_NES:
614 for (j = 0; j < 4; j++)
615 set_bit(gc_snes_btn[j], gc->dev[i].keybit);
616 break;
617
618 case GC_MULTI2:
619 set_bit(BTN_THUMB, gc->dev[i].keybit);
620 case GC_MULTI:
621 set_bit(BTN_TRIGGER, gc->dev[i].keybit);
622 break;
623
624 case GC_PSX:
625 case GC_DDR:
626 if(config[i + 1] == GC_DDR) {
627 for (j = 0; j < 4; j++)
628 set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit);
629 } else {
630 for (j = 0; j < 6; j++) {
631 set_bit(gc_psx_abs[j], gc->dev[i].absbit);
632 gc->dev[i].absmin[gc_psx_abs[j]] = 4;
633 gc->dev[i].absmax[gc_psx_abs[j]] = 252;
634 gc->dev[i].absflat[gc_psx_abs[j]] = 2;
635 }
636 }
637
638 for (j = 0; j < 12; j++)
639 set_bit(gc_psx_btn[j], gc->dev[i].keybit);
640
641 break;
642 }
643
644 sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
645
646 gc->dev[i].name = gc_names[config[i + 1]];
647 gc->dev[i].phys = gc->phys[i];
648 gc->dev[i].id.bustype = BUS_PARPORT;
649 gc->dev[i].id.vendor = 0x0001;
650 gc->dev[i].id.product = config[i + 1];
651 gc->dev[i].id.version = 0x0100;
652 }
653
654 parport_release(gc->pd);
655
656 if (!gc->pads[0]) {
657 parport_unregister_device(gc->pd);
658 kfree(gc);
659 return NULL;
660 }
661
662 for (i = 0; i < 5; i++)
663 if (gc->pads[0] & gc_status_bit[i]) {
664 input_register_device(gc->dev + i);
665 printk(KERN_INFO "input: %s on %s\n", gc->dev[i].name, gc->pd->port->name);
666 }
667
668 return gc;
669}
670
671static int __init gc_init(void)
672{
673 gc_base[0] = gc_probe(gc, gc_nargs);
674 gc_base[1] = gc_probe(gc_2, gc_nargs_2);
675 gc_base[2] = gc_probe(gc_3, gc_nargs_3);
676
677 if (gc_base[0] || gc_base[1] || gc_base[2])
678 return 0;
679
680 return -ENODEV;
681}
682
683static void __exit gc_exit(void)
684{
685 int i, j;
686
687 for (i = 0; i < 3; i++)
688 if (gc_base[i]) {
689 for (j = 0; j < 5; j++)
690 if (gc_base[i]->pads[0] & gc_status_bit[j])
691 input_unregister_device(gc_base[i]->dev + j);
692 parport_unregister_device(gc_base[i]->pd);
693 }
694}
695
696module_init(gc_init);
697module_exit(gc_exit);
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
new file mode 100644
index 000000000000..ad13f09a4e71
--- /dev/null
+++ b/drivers/input/joystick/gf2k.c
@@ -0,0 +1,380 @@
1/*
2 * $Id: gf2k.c,v 1.19 2002/01/22 20:27:43 vojtech Exp $
3 *
4 * Copyright (c) 1998-2001 Vojtech Pavlik
5 */
6
7/*
8 * Genius Flight 2000 joystick driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/delay.h>
32#include <linux/kernel.h>
33#include <linux/slab.h>
34#include <linux/module.h>
35#include <linux/init.h>
36#include <linux/input.h>
37#include <linux/gameport.h>
38
39#define DRIVER_DESC "Genius Flight 2000 joystick driver"
40
41MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
42MODULE_DESCRIPTION(DRIVER_DESC);
43MODULE_LICENSE("GPL");
44
45#define GF2K_START 400 /* The time we wait for the first bit [400 us] */
46#define GF2K_STROBE 40 /* The time we wait for the first bit [40 us] */
47#define GF2K_TIMEOUT 4 /* Wait for everything to settle [4 ms] */
48#define GF2K_LENGTH 80 /* Max number of triplets in a packet */
49
50/*
51 * Genius joystick ids ...
52 */
53
54#define GF2K_ID_G09 1
55#define GF2K_ID_F30D 2
56#define GF2K_ID_F30 3
57#define GF2K_ID_F31D 4
58#define GF2K_ID_F305 5
59#define GF2K_ID_F23P 6
60#define GF2K_ID_F31 7
61#define GF2K_ID_MAX 7
62
63static char gf2k_length[] = { 40, 40, 40, 40, 40, 40, 40, 40 };
64static char gf2k_hat_to_axis[][2] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
65
66static char *gf2k_names[] = {"", "Genius G-09D", "Genius F-30D", "Genius F-30", "Genius MaxFighter F-31D",
67 "Genius F-30-5", "Genius Flight2000 F-23", "Genius F-31"};
68static unsigned char gf2k_hats[] = { 0, 2, 0, 0, 2, 0, 2, 0 };
69static unsigned char gf2k_axes[] = { 0, 2, 0, 0, 4, 0, 4, 0 };
70static unsigned char gf2k_joys[] = { 0, 0, 0, 0,10, 0, 8, 0 };
71static unsigned char gf2k_pads[] = { 0, 6, 0, 0, 0, 0, 0, 0 };
72static unsigned char gf2k_lens[] = { 0,18, 0, 0,18, 0,18, 0 };
73
74static unsigned char gf2k_abs[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_GAS, ABS_BRAKE };
75static short gf2k_btn_joy[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4 };
76static short gf2k_btn_pad[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_START, BTN_SELECT };
77
78
79static short gf2k_seq_reset[] = { 240, 340, 0 };
80static short gf2k_seq_digital[] = { 590, 320, 860, 0 };
81
82struct gf2k {
83 struct gameport *gameport;
84 struct input_dev dev;
85 int reads;
86 int bads;
87 unsigned char id;
88 unsigned char length;
89 char phys[32];
90};
91
92/*
93 * gf2k_read_packet() reads a Genius Flight2000 packet.
94 */
95
96static int gf2k_read_packet(struct gameport *gameport, int length, char *data)
97{
98 unsigned char u, v;
99 int i;
100 unsigned int t, p;
101 unsigned long flags;
102
103 t = gameport_time(gameport, GF2K_START);
104 p = gameport_time(gameport, GF2K_STROBE);
105
106 i = 0;
107
108 local_irq_save(flags);
109
110 gameport_trigger(gameport);
111 v = gameport_read(gameport);
112
113 while (t > 0 && i < length) {
114 t--; u = v;
115 v = gameport_read(gameport);
116 if (v & ~u & 0x10) {
117 data[i++] = v >> 5;
118 t = p;
119 }
120 }
121
122 local_irq_restore(flags);
123
124 return i;
125}
126
127/*
128 * gf2k_trigger_seq() initializes a Genius Flight2000 joystick
129 * into digital mode.
130 */
131
132static void gf2k_trigger_seq(struct gameport *gameport, short *seq)
133{
134
135 unsigned long flags;
136 int i, t;
137
138 local_irq_save(flags);
139
140 i = 0;
141 do {
142 gameport_trigger(gameport);
143 t = gameport_time(gameport, GF2K_TIMEOUT * 1000);
144 while ((gameport_read(gameport) & 1) && t) t--;
145 udelay(seq[i]);
146 } while (seq[++i]);
147
148 gameport_trigger(gameport);
149
150 local_irq_restore(flags);
151}
152
153/*
154 * js_sw_get_bits() composes bits from the triplet buffer into a __u64.
155 * Parameter 'pos' is bit number inside packet where to start at, 'num' is number
156 * of bits to be read, 'shift' is offset in the resulting __u64 to start at, bits
157 * is number of bits per triplet.
158 */
159
160#define GB(p,n,s) gf2k_get_bits(data, p, n, s)
161
162static int gf2k_get_bits(unsigned char *buf, int pos, int num, int shift)
163{
164 __u64 data = 0;
165 int i;
166
167 for (i = 0; i < num / 3 + 2; i++)
168 data |= buf[pos / 3 + i] << (i * 3);
169 data >>= pos % 3;
170 data &= (1 << num) - 1;
171 data <<= shift;
172
173 return data;
174}
175
176static void gf2k_read(struct gf2k *gf2k, unsigned char *data)
177{
178 struct input_dev *dev = &gf2k->dev;
179 int i, t;
180
181 for (i = 0; i < 4 && i < gf2k_axes[gf2k->id]; i++)
182 input_report_abs(dev, gf2k_abs[i], GB(i<<3,8,0) | GB(i+46,1,8) | GB(i+50,1,9));
183
184 for (i = 0; i < 2 && i < gf2k_axes[gf2k->id] - 4; i++)
185 input_report_abs(dev, gf2k_abs[i], GB(i*9+60,8,0) | GB(i+54,1,9));
186
187 t = GB(40,4,0);
188
189 for (i = 0; i < gf2k_hats[gf2k->id]; i++)
190 input_report_abs(dev, ABS_HAT0X + i, gf2k_hat_to_axis[t][i]);
191
192 t = GB(44,2,0) | GB(32,8,2) | GB(78,2,10);
193
194 for (i = 0; i < gf2k_joys[gf2k->id]; i++)
195 input_report_key(dev, gf2k_btn_joy[i], (t >> i) & 1);
196
197 for (i = 0; i < gf2k_pads[gf2k->id]; i++)
198 input_report_key(dev, gf2k_btn_pad[i], (t >> i) & 1);
199
200 input_sync(dev);
201}
202
203/*
204 * gf2k_poll() reads and analyzes Genius joystick data.
205 */
206
207static void gf2k_poll(struct gameport *gameport)
208{
209 struct gf2k *gf2k = gameport_get_drvdata(gameport);
210 unsigned char data[GF2K_LENGTH];
211
212 gf2k->reads++;
213
214 if (gf2k_read_packet(gf2k->gameport, gf2k_length[gf2k->id], data) < gf2k_length[gf2k->id])
215 gf2k->bads++;
216 else
217 gf2k_read(gf2k, data);
218}
219
220static int gf2k_open(struct input_dev *dev)
221{
222 struct gf2k *gf2k = dev->private;
223
224 gameport_start_polling(gf2k->gameport);
225 return 0;
226}
227
228static void gf2k_close(struct input_dev *dev)
229{
230 struct gf2k *gf2k = dev->private;
231
232 gameport_stop_polling(gf2k->gameport);
233}
234
235/*
236 * gf2k_connect() probes for Genius id joysticks.
237 */
238
239static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
240{
241 struct gf2k *gf2k;
242 unsigned char data[GF2K_LENGTH];
243 int i, err;
244
245 if (!(gf2k = kcalloc(1, sizeof(struct gf2k), GFP_KERNEL)))
246 return -ENOMEM;
247
248 gf2k->gameport = gameport;
249
250 gameport_set_drvdata(gameport, gf2k);
251
252 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
253 if (err)
254 goto fail1;
255
256 gf2k_trigger_seq(gameport, gf2k_seq_reset);
257
258 msleep(GF2K_TIMEOUT);
259
260 gf2k_trigger_seq(gameport, gf2k_seq_digital);
261
262 msleep(GF2K_TIMEOUT);
263
264 if (gf2k_read_packet(gameport, GF2K_LENGTH, data) < 12) {
265 err = -ENODEV;
266 goto fail2;
267 }
268
269 if (!(gf2k->id = GB(7,2,0) | GB(3,3,2) | GB(0,3,5))) {
270 err = -ENODEV;
271 goto fail2;
272 }
273
274#ifdef RESET_WORKS
275 if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) ||
276 (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5)))) {
277 err = -ENODEV;
278 goto fail2;
279 }
280#else
281 gf2k->id = 6;
282#endif
283
284 if (gf2k->id > GF2K_ID_MAX || !gf2k_axes[gf2k->id]) {
285 printk(KERN_WARNING "gf2k.c: Not yet supported joystick on %s. [id: %d type:%s]\n",
286 gameport->phys, gf2k->id, gf2k->id > GF2K_ID_MAX ? "Unknown" : gf2k_names[gf2k->id]);
287 err = -ENODEV;
288 goto fail2;
289 }
290
291 gameport_set_poll_handler(gameport, gf2k_poll);
292 gameport_set_poll_interval(gameport, 20);
293
294 sprintf(gf2k->phys, "%s/input0", gameport->phys);
295
296 gf2k->length = gf2k_lens[gf2k->id];
297
298 init_input_dev(&gf2k->dev);
299
300 gf2k->dev.private = gf2k;
301 gf2k->dev.open = gf2k_open;
302 gf2k->dev.close = gf2k_close;
303 gf2k->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
304
305 gf2k->dev.name = gf2k_names[gf2k->id];
306 gf2k->dev.phys = gf2k->phys;
307 gf2k->dev.id.bustype = BUS_GAMEPORT;
308 gf2k->dev.id.vendor = GAMEPORT_ID_VENDOR_GENIUS;
309 gf2k->dev.id.product = gf2k->id;
310 gf2k->dev.id.version = 0x0100;
311
312 for (i = 0; i < gf2k_axes[gf2k->id]; i++)
313 set_bit(gf2k_abs[i], gf2k->dev.absbit);
314
315 for (i = 0; i < gf2k_hats[gf2k->id]; i++) {
316 set_bit(ABS_HAT0X + i, gf2k->dev.absbit);
317 gf2k->dev.absmin[ABS_HAT0X + i] = -1;
318 gf2k->dev.absmax[ABS_HAT0X + i] = 1;
319 }
320
321 for (i = 0; i < gf2k_joys[gf2k->id]; i++)
322 set_bit(gf2k_btn_joy[i], gf2k->dev.keybit);
323
324 for (i = 0; i < gf2k_pads[gf2k->id]; i++)
325 set_bit(gf2k_btn_pad[i], gf2k->dev.keybit);
326
327 gf2k_read_packet(gameport, gf2k->length, data);
328 gf2k_read(gf2k, data);
329
330 for (i = 0; i < gf2k_axes[gf2k->id]; i++) {
331 gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 :
332 gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32;
333 gf2k->dev.absmin[gf2k_abs[i]] = 32;
334 gf2k->dev.absfuzz[gf2k_abs[i]] = 8;
335 gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0;
336 }
337
338 input_register_device(&gf2k->dev);
339 printk(KERN_INFO "input: %s on %s\n", gf2k_names[gf2k->id], gameport->phys);
340
341 return 0;
342
343fail2: gameport_close(gameport);
344fail1: gameport_set_drvdata(gameport, NULL);
345 kfree(gf2k);
346 return err;
347}
348
349static void gf2k_disconnect(struct gameport *gameport)
350{
351 struct gf2k *gf2k = gameport_get_drvdata(gameport);
352
353 input_unregister_device(&gf2k->dev);
354 gameport_close(gameport);
355 gameport_set_drvdata(gameport, NULL);
356 kfree(gf2k);
357}
358
359static struct gameport_driver gf2k_drv = {
360 .driver = {
361 .name = "gf2k",
362 },
363 .description = DRIVER_DESC,
364 .connect = gf2k_connect,
365 .disconnect = gf2k_disconnect,
366};
367
368static int __init gf2k_init(void)
369{
370 gameport_register_driver(&gf2k_drv);
371 return 0;
372}
373
374static void __exit gf2k_exit(void)
375{
376 gameport_unregister_driver(&gf2k_drv);
377}
378
379module_init(gf2k_init);
380module_exit(gf2k_exit);
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
new file mode 100644
index 000000000000..d1500d2562d6
--- /dev/null
+++ b/drivers/input/joystick/grip.c
@@ -0,0 +1,422 @@
1/*
2 * $Id: grip.c,v 1.21 2002/01/22 20:27:57 vojtech Exp $
3 *
4 * Copyright (c) 1998-2001 Vojtech Pavlik
5 */
6
7/*
8 * Gravis/Kensington GrIP protocol joystick and gamepad driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/init.h>
34#include <linux/slab.h>
35#include <linux/gameport.h>
36#include <linux/input.h>
37
38#define DRIVER_DESC "Gravis GrIP protocol joystick driver"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44#define GRIP_MODE_GPP 1
45#define GRIP_MODE_BD 2
46#define GRIP_MODE_XT 3
47#define GRIP_MODE_DC 4
48
49#define GRIP_LENGTH_GPP 24
50#define GRIP_STROBE_GPP 200 /* 200 us */
51#define GRIP_LENGTH_XT 4
52#define GRIP_STROBE_XT 64 /* 64 us */
53#define GRIP_MAX_CHUNKS_XT 10
54#define GRIP_MAX_BITS_XT 30
55
56struct grip {
57 struct gameport *gameport;
58 struct input_dev dev[2];
59 unsigned char mode[2];
60 int reads;
61 int bads;
62 char phys[2][32];
63};
64
65static int grip_btn_gpp[] = { BTN_START, BTN_SELECT, BTN_TR2, BTN_Y, 0, BTN_TL2, BTN_A, BTN_B, BTN_X, 0, BTN_TL, BTN_TR, -1 };
66static int grip_btn_bd[] = { BTN_THUMB, BTN_THUMB2, BTN_TRIGGER, BTN_TOP, BTN_BASE, -1 };
67static int grip_btn_xt[] = { BTN_TRIGGER, BTN_THUMB, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_SELECT, BTN_START, BTN_MODE, -1 };
68static int grip_btn_dc[] = { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, -1 };
69
70static int grip_abs_gpp[] = { ABS_X, ABS_Y, -1 };
71static int grip_abs_bd[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
72static int grip_abs_xt[] = { ABS_X, ABS_Y, ABS_BRAKE, ABS_GAS, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, -1 };
73static int grip_abs_dc[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
74
75static char *grip_name[] = { NULL, "Gravis GamePad Pro", "Gravis Blackhawk Digital",
76 "Gravis Xterminator Digital", "Gravis Xterminator DualControl" };
77static int *grip_abs[] = { NULL, grip_abs_gpp, grip_abs_bd, grip_abs_xt, grip_abs_dc };
78static int *grip_btn[] = { NULL, grip_btn_gpp, grip_btn_bd, grip_btn_xt, grip_btn_dc };
79static char grip_anx[] = { 0, 0, 3, 5, 5 };
80static char grip_cen[] = { 0, 0, 2, 2, 4 };
81
82/*
83 * grip_gpp_read_packet() reads a Gravis GamePad Pro packet.
84 */
85
86static int grip_gpp_read_packet(struct gameport *gameport, int shift, unsigned int *data)
87{
88 unsigned long flags;
89 unsigned char u, v;
90 unsigned int t;
91 int i;
92
93 int strobe = gameport_time(gameport, GRIP_STROBE_GPP);
94
95 data[0] = 0;
96 t = strobe;
97 i = 0;
98
99 local_irq_save(flags);
100
101 v = gameport_read(gameport) >> shift;
102
103 do {
104 t--;
105 u = v; v = (gameport_read(gameport) >> shift) & 3;
106 if (~v & u & 1) {
107 data[0] |= (v >> 1) << i++;
108 t = strobe;
109 }
110 } while (i < GRIP_LENGTH_GPP && t > 0);
111
112 local_irq_restore(flags);
113
114 if (i < GRIP_LENGTH_GPP) return -1;
115
116 for (i = 0; i < GRIP_LENGTH_GPP && (data[0] & 0xfe4210) ^ 0x7c0000; i++)
117 data[0] = data[0] >> 1 | (data[0] & 1) << (GRIP_LENGTH_GPP - 1);
118
119 return -(i == GRIP_LENGTH_GPP);
120}
121
122/*
123 * grip_xt_read_packet() reads a Gravis Xterminator packet.
124 */
125
126static int grip_xt_read_packet(struct gameport *gameport, int shift, unsigned int *data)
127{
128 unsigned int i, j, buf, crc;
129 unsigned char u, v, w;
130 unsigned long flags;
131 unsigned int t;
132 char status;
133
134 int strobe = gameport_time(gameport, GRIP_STROBE_XT);
135
136 data[0] = data[1] = data[2] = data[3] = 0;
137 status = buf = i = j = 0;
138 t = strobe;
139
140 local_irq_save(flags);
141
142 v = w = (gameport_read(gameport) >> shift) & 3;
143
144 do {
145 t--;
146 u = (gameport_read(gameport) >> shift) & 3;
147
148 if (u ^ v) {
149
150 if ((u ^ v) & 1) {
151 buf = (buf << 1) | (u >> 1);
152 t = strobe;
153 i++;
154 } else
155
156 if ((((u ^ v) & (v ^ w)) >> 1) & ~(u | v | w) & 1) {
157 if (i == 20) {
158 crc = buf ^ (buf >> 7) ^ (buf >> 14);
159 if (!((crc ^ (0x25cb9e70 >> ((crc >> 2) & 0x1c))) & 0xf)) {
160 data[buf >> 18] = buf >> 4;
161 status |= 1 << (buf >> 18);
162 }
163 j++;
164 }
165 t = strobe;
166 buf = 0;
167 i = 0;
168 }
169 w = v;
170 v = u;
171 }
172
173 } while (status != 0xf && i < GRIP_MAX_BITS_XT && j < GRIP_MAX_CHUNKS_XT && t > 0);
174
175 local_irq_restore(flags);
176
177 return -(status != 0xf);
178}
179
180/*
181 * grip_timer() repeatedly polls the joysticks and generates events.
182 */
183
184static void grip_poll(struct gameport *gameport)
185{
186 struct grip *grip = gameport_get_drvdata(gameport);
187 unsigned int data[GRIP_LENGTH_XT];
188 struct input_dev *dev;
189 int i, j;
190
191 for (i = 0; i < 2; i++) {
192
193 dev = grip->dev + i;
194 grip->reads++;
195
196 switch (grip->mode[i]) {
197
198 case GRIP_MODE_GPP:
199
200 if (grip_gpp_read_packet(grip->gameport, (i << 1) + 4, data)) {
201 grip->bads++;
202 break;
203 }
204
205 input_report_abs(dev, ABS_X, ((*data >> 15) & 1) - ((*data >> 16) & 1));
206 input_report_abs(dev, ABS_Y, ((*data >> 13) & 1) - ((*data >> 12) & 1));
207
208 for (j = 0; j < 12; j++)
209 if (grip_btn_gpp[j])
210 input_report_key(dev, grip_btn_gpp[j], (*data >> j) & 1);
211
212 break;
213
214 case GRIP_MODE_BD:
215
216 if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
217 grip->bads++;
218 break;
219 }
220
221 input_report_abs(dev, ABS_X, (data[0] >> 2) & 0x3f);
222 input_report_abs(dev, ABS_Y, 63 - ((data[0] >> 8) & 0x3f));
223 input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
224
225 input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2] & 1));
226 input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
227
228 for (j = 0; j < 5; j++)
229 input_report_key(dev, grip_btn_bd[j], (data[3] >> (j + 4)) & 1);
230
231 break;
232
233 case GRIP_MODE_XT:
234
235 if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
236 grip->bads++;
237 break;
238 }
239
240 input_report_abs(dev, ABS_X, (data[0] >> 2) & 0x3f);
241 input_report_abs(dev, ABS_Y, 63 - ((data[0] >> 8) & 0x3f));
242 input_report_abs(dev, ABS_BRAKE, (data[1] >> 2) & 0x3f);
243 input_report_abs(dev, ABS_GAS, (data[1] >> 8) & 0x3f);
244 input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
245
246 input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2] & 1));
247 input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
248 input_report_abs(dev, ABS_HAT1X, ((data[2] >> 5) & 1) - ((data[2] >> 4) & 1));
249 input_report_abs(dev, ABS_HAT1Y, ((data[2] >> 6) & 1) - ((data[2] >> 7) & 1));
250
251 for (j = 0; j < 11; j++)
252 input_report_key(dev, grip_btn_xt[j], (data[3] >> (j + 3)) & 1);
253 break;
254
255 case GRIP_MODE_DC:
256
257 if (grip_xt_read_packet(grip->gameport, (i << 1) + 4, data)) {
258 grip->bads++;
259 break;
260 }
261
262 input_report_abs(dev, ABS_X, (data[0] >> 2) & 0x3f);
263 input_report_abs(dev, ABS_Y, (data[0] >> 8) & 0x3f);
264 input_report_abs(dev, ABS_RX, (data[1] >> 2) & 0x3f);
265 input_report_abs(dev, ABS_RY, (data[1] >> 8) & 0x3f);
266 input_report_abs(dev, ABS_THROTTLE, (data[2] >> 8) & 0x3f);
267
268 input_report_abs(dev, ABS_HAT0X, ((data[2] >> 1) & 1) - ( data[2] & 1));
269 input_report_abs(dev, ABS_HAT0Y, ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1));
270
271 for (j = 0; j < 9; j++)
272 input_report_key(dev, grip_btn_dc[j], (data[3] >> (j + 3)) & 1);
273 break;
274
275
276 }
277
278 input_sync(dev);
279 }
280}
281
282static int grip_open(struct input_dev *dev)
283{
284 struct grip *grip = dev->private;
285
286 gameport_start_polling(grip->gameport);
287 return 0;
288}
289
290static void grip_close(struct input_dev *dev)
291{
292 struct grip *grip = dev->private;
293
294 gameport_stop_polling(grip->gameport);
295}
296
297static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
298{
299 struct grip *grip;
300 unsigned int data[GRIP_LENGTH_XT];
301 int i, j, t;
302 int err;
303
304 if (!(grip = kcalloc(1, sizeof(struct grip), GFP_KERNEL)))
305 return -ENOMEM;
306
307 grip->gameport = gameport;
308
309 gameport_set_drvdata(gameport, grip);
310
311 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
312 if (err)
313 goto fail1;
314
315 for (i = 0; i < 2; i++) {
316 if (!grip_gpp_read_packet(gameport, (i << 1) + 4, data)) {
317 grip->mode[i] = GRIP_MODE_GPP;
318 continue;
319 }
320 if (!grip_xt_read_packet(gameport, (i << 1) + 4, data)) {
321 if (!(data[3] & 7)) {
322 grip->mode[i] = GRIP_MODE_BD;
323 continue;
324 }
325 if (!(data[2] & 0xf0)) {
326 grip->mode[i] = GRIP_MODE_XT;
327 continue;
328 }
329 grip->mode[i] = GRIP_MODE_DC;
330 continue;
331 }
332 }
333
334 if (!grip->mode[0] && !grip->mode[1]) {
335 err = -ENODEV;
336 goto fail2;
337 }
338
339 gameport_set_poll_handler(gameport, grip_poll);
340 gameport_set_poll_interval(gameport, 20);
341
342 for (i = 0; i < 2; i++)
343 if (grip->mode[i]) {
344
345 sprintf(grip->phys[i], "%s/input%d", gameport->phys, i);
346
347 grip->dev[i].private = grip;
348
349 grip->dev[i].open = grip_open;
350 grip->dev[i].close = grip_close;
351
352 grip->dev[i].name = grip_name[grip->mode[i]];
353 grip->dev[i].phys = grip->phys[i];
354 grip->dev[i].id.bustype = BUS_GAMEPORT;
355 grip->dev[i].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
356 grip->dev[i].id.product = grip->mode[i];
357 grip->dev[i].id.version = 0x0100;
358
359 grip->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
360
361 for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
362
363 if (j < grip_cen[grip->mode[i]])
364 input_set_abs_params(&grip->dev[i], t, 14, 52, 1, 2);
365 else if (j < grip_anx[grip->mode[i]])
366 input_set_abs_params(&grip->dev[i], t, 3, 57, 1, 0);
367 else
368 input_set_abs_params(&grip->dev[i], t, -1, 1, 0, 0);
369 }
370
371 for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
372 if (t > 0)
373 set_bit(t, grip->dev[i].keybit);
374
375 printk(KERN_INFO "input: %s on %s\n",
376 grip_name[grip->mode[i]], gameport->phys);
377 input_register_device(grip->dev + i);
378 }
379
380 return 0;
381
382fail2: gameport_close(gameport);
383fail1: gameport_set_drvdata(gameport, NULL);
384 kfree(grip);
385 return err;
386}
387
388static void grip_disconnect(struct gameport *gameport)
389{
390 struct grip *grip = gameport_get_drvdata(gameport);
391 int i;
392
393 for (i = 0; i < 2; i++)
394 if (grip->mode[i])
395 input_unregister_device(grip->dev + i);
396 gameport_close(gameport);
397 gameport_set_drvdata(gameport, NULL);
398 kfree(grip);
399}
400
401static struct gameport_driver grip_drv = {
402 .driver = {
403 .name = "grip",
404 },
405 .description = DRIVER_DESC,
406 .connect = grip_connect,
407 .disconnect = grip_disconnect,
408};
409
410static int __init grip_init(void)
411{
412 gameport_register_driver(&grip_drv);
413 return 0;
414}
415
416static void __exit grip_exit(void)
417{
418 gameport_unregister_driver(&grip_drv);
419}
420
421module_init(grip_init);
422module_exit(grip_exit);
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
new file mode 100644
index 000000000000..42e5005d621f
--- /dev/null
+++ b/drivers/input/joystick/grip_mp.c
@@ -0,0 +1,677 @@
1/*
2 * $Id: grip_mp.c,v 1.9 2002/07/20 19:28:45 bonnland Exp $
3 *
4 * Driver for the Gravis Grip Multiport, a gamepad "hub" that
5 * connects up to four 9-pin digital gamepads/joysticks.
6 * Driver tested on SMP and UP kernel versions 2.4.18-4 and 2.4.18-5.
7 *
8 * Thanks to Chris Gassib for helpful advice.
9 *
10 * Copyright (c) 2002 Brian Bonnlander, Bill Soudan
11 * Copyright (c) 1998-2000 Vojtech Pavlik
12 */
13
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/slab.h>
18#include <linux/gameport.h>
19#include <linux/input.h>
20#include <linux/delay.h>
21#include <linux/proc_fs.h>
22
23#define DRIVER_DESC "Gravis Grip Multiport driver"
24
25MODULE_AUTHOR("Brian Bonnlander");
26MODULE_DESCRIPTION(DRIVER_DESC);
27MODULE_LICENSE("GPL");
28
29#ifdef GRIP_DEBUG
30#define dbg(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg)
31#else
32#define dbg(format, arg...) do {} while (0)
33#endif
34
35/*
36 * Grip multiport state
37 */
38
39struct grip_mp {
40 struct gameport *gameport;
41 struct input_dev dev[4];
42 int mode[4];
43 int registered[4];
44 int reads;
45 int bads;
46
47 /* individual gamepad states */
48 int buttons[4];
49 int xaxes[4];
50 int yaxes[4];
51 int dirty[4]; /* has the state been updated? */
52};
53
54/*
55 * Multiport packet interpretation
56 */
57
58#define PACKET_FULL 0x80000000 /* packet is full */
59#define PACKET_IO_FAST 0x40000000 /* 3 bits per gameport read */
60#define PACKET_IO_SLOW 0x20000000 /* 1 bit per gameport read */
61#define PACKET_MP_MORE 0x04000000 /* multiport wants to send more */
62#define PACKET_MP_DONE 0x02000000 /* multiport done sending */
63
64/*
65 * Packet status code interpretation
66 */
67
68#define IO_GOT_PACKET 0x0100 /* Got a packet */
69#define IO_MODE_FAST 0x0200 /* Used 3 data bits per gameport read */
70#define IO_SLOT_CHANGE 0x0800 /* Multiport physical slot status changed */
71#define IO_DONE 0x1000 /* Multiport is done sending packets */
72#define IO_RETRY 0x4000 /* Try again later to get packet */
73#define IO_RESET 0x8000 /* Force multiport to resend all packets */
74
75/*
76 * Gamepad configuration data. Other 9-pin digital joystick devices
77 * may work with the multiport, so this may not be an exhaustive list!
78 * Commodore 64 joystick remains untested.
79 */
80
81#define GRIP_INIT_DELAY 2000 /* 2 ms */
82
83#define GRIP_MODE_NONE 0
84#define GRIP_MODE_RESET 1
85#define GRIP_MODE_GP 2
86#define GRIP_MODE_C64 3
87
88static int grip_btn_gp[] = { BTN_TR, BTN_TL, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, -1 };
89static int grip_btn_c64[] = { BTN_JOYSTICK, -1 };
90
91static int grip_abs_gp[] = { ABS_X, ABS_Y, -1 };
92static int grip_abs_c64[] = { ABS_X, ABS_Y, -1 };
93
94static int *grip_abs[] = { NULL, NULL, grip_abs_gp, grip_abs_c64 };
95static int *grip_btn[] = { NULL, NULL, grip_btn_gp, grip_btn_c64 };
96
97static char *grip_name[] = { NULL, NULL, "Gravis Grip Pad", "Commodore 64 Joystick" };
98
99static const int init_seq[] = {
100 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
101 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1,
102 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
103 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1 };
104
105/* Maps multiport directional values to X,Y axis values (each axis encoded in 3 bits) */
106
107static int axis_map[] = { 5, 9, 1, 5, 6, 10, 2, 6, 4, 8, 0, 4, 5, 9, 1, 5 };
108
109static void register_slot(int i, struct grip_mp *grip);
110
111/*
112 * Returns whether an odd or even number of bits are on in pkt.
113 */
114
115static int bit_parity(u32 pkt)
116{
117 int x = pkt ^ (pkt >> 16);
118 x ^= x >> 8;
119 x ^= x >> 4;
120 x ^= x >> 2;
121 x ^= x >> 1;
122 return x & 1;
123}
124
125/*
126 * Poll gameport; return true if all bits set in 'onbits' are on and
127 * all bits set in 'offbits' are off.
128 */
129
130static inline int poll_until(u8 onbits, u8 offbits, int u_sec, struct gameport* gp, u8 *data)
131{
132 int i, nloops;
133
134 nloops = gameport_time(gp, u_sec);
135 for (i = 0; i < nloops; i++) {
136 *data = gameport_read(gp);
137 if ((*data & onbits) == onbits &&
138 (~(*data) & offbits) == offbits)
139 return 1;
140 }
141 dbg("gameport timed out after %d microseconds.\n", u_sec);
142 return 0;
143}
144
145/*
146 * Gets a 28-bit packet from the multiport.
147 *
148 * After getting a packet successfully, commands encoded by sendcode may
149 * be sent to the multiport.
150 *
151 * The multiport clock value is reflected in gameport bit B4.
152 *
153 * Returns a packet status code indicating whether packet is valid, the transfer
154 * mode, and any error conditions.
155 *
156 * sendflags: current I/O status
157 * sendcode: data to send to the multiport if sendflags is nonzero
158 */
159
160static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *packet)
161{
162 u8 raw_data; /* raw data from gameport */
163 u8 data_mask; /* packet data bits from raw_data */
164 u32 pkt; /* packet temporary storage */
165 int bits_per_read; /* num packet bits per gameport read */
166 int portvals = 0; /* used for port value sanity check */
167 int i;
168
169 /* Gameport bits B0, B4, B5 should first be off, then B4 should come on. */
170
171 *packet = 0;
172 raw_data = gameport_read(gameport);
173 if (raw_data & 1)
174 return IO_RETRY;
175
176 for (i = 0; i < 64; i++) {
177 raw_data = gameport_read(gameport);
178 portvals |= 1 << ((raw_data >> 4) & 3); /* Demux B4, B5 */
179 }
180
181 if (portvals == 1) { /* B4, B5 off */
182 raw_data = gameport_read(gameport);
183 portvals = raw_data & 0xf0;
184
185 if (raw_data & 0x31)
186 return IO_RESET;
187 gameport_trigger(gameport);
188
189 if (!poll_until(0x10, 0, 308, gameport, &raw_data))
190 return IO_RESET;
191 } else
192 return IO_RETRY;
193
194 /* Determine packet transfer mode and prepare for packet construction. */
195
196 if (raw_data & 0x20) { /* 3 data bits/read */
197 portvals |= raw_data >> 4; /* Compare B4-B7 before & after trigger */
198
199 if (portvals != 0xb)
200 return 0;
201 data_mask = 7;
202 bits_per_read = 3;
203 pkt = (PACKET_FULL | PACKET_IO_FAST) >> 28;
204 } else { /* 1 data bit/read */
205 data_mask = 1;
206 bits_per_read = 1;
207 pkt = (PACKET_FULL | PACKET_IO_SLOW) >> 28;
208 }
209
210 /* Construct a packet. Final data bits must be zero. */
211
212 while (1) {
213 if (!poll_until(0, 0x10, 77, gameport, &raw_data))
214 return IO_RESET;
215 raw_data = (raw_data >> 5) & data_mask;
216
217 if (pkt & PACKET_FULL)
218 break;
219 pkt = (pkt << bits_per_read) | raw_data;
220
221 if (!poll_until(0x10, 0, 77, gameport, &raw_data))
222 return IO_RESET;
223 }
224
225 if (raw_data)
226 return IO_RESET;
227
228 /* If 3 bits/read used, drop from 30 bits to 28. */
229
230 if (bits_per_read == 3) {
231 pkt = (pkt & 0xffff0000) | ((pkt << 1) & 0xffff);
232 pkt = (pkt >> 2) | 0xf0000000;
233 }
234
235 if (bit_parity(pkt) == 1)
236 return IO_RESET;
237
238 /* Acknowledge packet receipt */
239
240 if (!poll_until(0x30, 0, 77, gameport, &raw_data))
241 return IO_RESET;
242
243 raw_data = gameport_read(gameport);
244
245 if (raw_data & 1)
246 return IO_RESET;
247
248 gameport_trigger(gameport);
249
250 if (!poll_until(0, 0x20, 77, gameport, &raw_data))
251 return IO_RESET;
252
253 /* Return if we just wanted the packet or multiport wants to send more */
254
255 *packet = pkt;
256 if ((sendflags == 0) || ((sendflags & IO_RETRY) && !(pkt & PACKET_MP_DONE)))
257 return IO_GOT_PACKET;
258
259 if (pkt & PACKET_MP_MORE)
260 return IO_GOT_PACKET | IO_RETRY;
261
262 /* Multiport is done sending packets and is ready to receive data */
263
264 if (!poll_until(0x20, 0, 77, gameport, &raw_data))
265 return IO_GOT_PACKET | IO_RESET;
266
267 raw_data = gameport_read(gameport);
268 if (raw_data & 1)
269 return IO_GOT_PACKET | IO_RESET;
270
271 /* Trigger gameport based on bits in sendcode */
272
273 gameport_trigger(gameport);
274 do {
275 if (!poll_until(0x20, 0x10, 116, gameport, &raw_data))
276 return IO_GOT_PACKET | IO_RESET;
277
278 if (!poll_until(0x30, 0, 193, gameport, &raw_data))
279 return IO_GOT_PACKET | IO_RESET;
280
281 if (raw_data & 1)
282 return IO_GOT_PACKET | IO_RESET;
283
284 if (sendcode & 1)
285 gameport_trigger(gameport);
286
287 sendcode >>= 1;
288 } while (sendcode);
289
290 return IO_GOT_PACKET | IO_MODE_FAST;
291}
292
293/*
294 * Disables and restores interrupts for mp_io(), which does the actual I/O.
295 */
296
297static int multiport_io(struct gameport* gameport, int sendflags, int sendcode, u32 *packet)
298{
299 int status;
300 unsigned long flags;
301
302 local_irq_save(flags);
303 status = mp_io(gameport, sendflags, sendcode, packet);
304 local_irq_restore(flags);
305
306 return status;
307}
308
309/*
310 * Puts multiport into digital mode. Multiport LED turns green.
311 *
312 * Returns true if a valid digital packet was received, false otherwise.
313 */
314
315static int dig_mode_start(struct gameport *gameport, u32 *packet)
316{
317 int i, seq_len = sizeof(init_seq)/sizeof(int);
318 int flags, tries = 0, bads = 0;
319
320 for (i = 0; i < seq_len; i++) { /* Send magic sequence */
321 if (init_seq[i])
322 gameport_trigger(gameport);
323 udelay(GRIP_INIT_DELAY);
324 }
325
326 for (i = 0; i < 16; i++) /* Wait for multiport to settle */
327 udelay(GRIP_INIT_DELAY);
328
329 while (tries < 64 && bads < 8) { /* Reset multiport and try getting a packet */
330
331 flags = multiport_io(gameport, IO_RESET, 0x27, packet);
332
333 if (flags & IO_MODE_FAST)
334 return 1;
335
336 if (flags & IO_RETRY)
337 tries++;
338 else
339 bads++;
340 }
341 return 0;
342}
343
344/*
345 * Packet structure: B0-B15 => gamepad state
346 * B16-B20 => gamepad device type
347 * B21-B24 => multiport slot index (1-4)
348 *
349 * Known device types: 0x1f (grip pad), 0x0 (no device). Others may exist.
350 *
351 * Returns the packet status.
352 */
353
354static int get_and_decode_packet(struct grip_mp *grip, int flags)
355{
356 u32 packet;
357 int joytype = 0;
358 int slot = 0;
359
360 /* Get a packet and check for validity */
361
362 flags &= IO_RESET | IO_RETRY;
363 flags = multiport_io(grip->gameport, flags, 0, &packet);
364 grip->reads++;
365
366 if (packet & PACKET_MP_DONE)
367 flags |= IO_DONE;
368
369 if (flags && !(flags & IO_GOT_PACKET)) {
370 grip->bads++;
371 return flags;
372 }
373
374 /* Ignore non-gamepad packets, e.g. multiport hardware version */
375
376 slot = ((packet >> 21) & 0xf) - 1;
377 if ((slot < 0) || (slot > 3))
378 return flags;
379
380 /*
381 * Handle "reset" packets, which occur at startup, and when gamepads
382 * are removed or plugged in. May contain configuration of a new gamepad.
383 */
384
385 joytype = (packet >> 16) & 0x1f;
386 if (!joytype) {
387
388 if (grip->registered[slot]) {
389 printk(KERN_INFO "grip_mp: removing %s, slot %d\n",
390 grip_name[grip->mode[slot]], slot);
391 input_unregister_device(grip->dev + slot);
392 grip->registered[slot] = 0;
393 }
394 dbg("Reset: grip multiport slot %d\n", slot);
395 grip->mode[slot] = GRIP_MODE_RESET;
396 flags |= IO_SLOT_CHANGE;
397 return flags;
398 }
399
400 /* Interpret a grip pad packet */
401
402 if (joytype == 0x1f) {
403
404 int dir = (packet >> 8) & 0xf; /* eight way directional value */
405 grip->buttons[slot] = (~packet) & 0xff;
406 grip->yaxes[slot] = ((axis_map[dir] >> 2) & 3) - 1;
407 grip->xaxes[slot] = (axis_map[dir] & 3) - 1;
408 grip->dirty[slot] = 1;
409
410 if (grip->mode[slot] == GRIP_MODE_RESET)
411 flags |= IO_SLOT_CHANGE;
412
413 grip->mode[slot] = GRIP_MODE_GP;
414
415 if (!grip->registered[slot]) {
416 dbg("New Grip pad in multiport slot %d.\n", slot);
417 register_slot(slot, grip);
418 }
419 return flags;
420 }
421
422 /* Handle non-grip device codes. For now, just print diagnostics. */
423
424 {
425 static int strange_code = 0;
426 if (strange_code != joytype) {
427 printk(KERN_INFO "Possible non-grip pad/joystick detected.\n");
428 printk(KERN_INFO "Got joy type 0x%x and packet 0x%x.\n", joytype, packet);
429 strange_code = joytype;
430 }
431 }
432 return flags;
433}
434
435/*
436 * Returns true if all multiport slot states appear valid.
437 */
438
439static int slots_valid(struct grip_mp *grip)
440{
441 int flags, slot, invalid = 0, active = 0;
442
443 flags = get_and_decode_packet(grip, 0);
444 if (!(flags & IO_GOT_PACKET))
445 return 0;
446
447 for (slot = 0; slot < 4; slot++) {
448 if (grip->mode[slot] == GRIP_MODE_RESET)
449 invalid = 1;
450 if (grip->mode[slot] != GRIP_MODE_NONE)
451 active = 1;
452 }
453
454 /* Return true if no active slot but multiport sent all its data */
455 if (!active)
456 return (flags & IO_DONE) ? 1 : 0;
457
458 /* Return false if invalid device code received */
459 return invalid ? 0 : 1;
460}
461
462/*
463 * Returns whether the multiport was placed into digital mode and
464 * able to communicate its state successfully.
465 */
466
467static int multiport_init(struct grip_mp *grip)
468{
469 int dig_mode, initialized = 0, tries = 0;
470 u32 packet;
471
472 dig_mode = dig_mode_start(grip->gameport, &packet);
473 while (!dig_mode && tries < 4) {
474 dig_mode = dig_mode_start(grip->gameport, &packet);
475 tries++;
476 }
477
478 if (dig_mode)
479 dbg("multiport_init(): digital mode activated.\n");
480 else {
481 dbg("multiport_init(): unable to activate digital mode.\n");
482 return 0;
483 }
484
485 /* Get packets, store multiport state, and check state's validity */
486 for (tries = 0; tries < 4096; tries++) {
487 if ( slots_valid(grip) ) {
488 initialized = 1;
489 break;
490 }
491 }
492 dbg("multiport_init(): initialized == %d\n", initialized);
493 return initialized;
494}
495
496/*
497 * Reports joystick state to the linux input layer.
498 */
499
500static void report_slot(struct grip_mp *grip, int slot)
501{
502 struct input_dev *dev = &(grip->dev[slot]);
503 int i, buttons = grip->buttons[slot];
504
505 /* Store button states with linux input driver */
506
507 for (i = 0; i < 8; i++)
508 input_report_key(dev, grip_btn_gp[i], (buttons >> i) & 1);
509
510 /* Store axis states with linux driver */
511
512 input_report_abs(dev, ABS_X, grip->xaxes[slot]);
513 input_report_abs(dev, ABS_Y, grip->yaxes[slot]);
514
515 /* Tell the receiver of the events to process them */
516
517 input_sync(dev);
518
519 grip->dirty[slot] = 0;
520}
521
522/*
523 * Get the multiport state.
524 */
525
526static void grip_poll(struct gameport *gameport)
527{
528 struct grip_mp *grip = gameport_get_drvdata(gameport);
529 int i, npkts, flags;
530
531 for (npkts = 0; npkts < 4; npkts++) {
532 flags = IO_RETRY;
533 for (i = 0; i < 32; i++) {
534 flags = get_and_decode_packet(grip, flags);
535 if ((flags & IO_GOT_PACKET) || !(flags & IO_RETRY))
536 break;
537 }
538 if (flags & IO_DONE)
539 break;
540 }
541
542 for (i = 0; i < 4; i++)
543 if (grip->dirty[i])
544 report_slot(grip, i);
545}
546
547/*
548 * Called when a joystick device file is opened
549 */
550
551static int grip_open(struct input_dev *dev)
552{
553 struct grip_mp *grip = dev->private;
554
555 gameport_start_polling(grip->gameport);
556 return 0;
557}
558
559/*
560 * Called when a joystick device file is closed
561 */
562
563static void grip_close(struct input_dev *dev)
564{
565 struct grip_mp *grip = dev->private;
566
567 gameport_start_polling(grip->gameport);
568}
569
570/*
571 * Tell the linux input layer about a newly plugged-in gamepad.
572 */
573
574static void register_slot(int slot, struct grip_mp *grip)
575{
576 int j, t;
577
578 grip->dev[slot].private = grip;
579 grip->dev[slot].open = grip_open;
580 grip->dev[slot].close = grip_close;
581 grip->dev[slot].name = grip_name[grip->mode[slot]];
582 grip->dev[slot].id.bustype = BUS_GAMEPORT;
583 grip->dev[slot].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS;
584 grip->dev[slot].id.product = 0x0100 + grip->mode[slot];
585 grip->dev[slot].id.version = 0x0100;
586 grip->dev[slot].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
587
588 for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++)
589 input_set_abs_params(&grip->dev[slot], t, -1, 1, 0, 0);
590
591 for (j = 0; (t = grip_btn[grip->mode[slot]][j]) >= 0; j++)
592 if (t > 0)
593 set_bit(t, grip->dev[slot].keybit);
594
595 input_register_device(grip->dev + slot);
596 grip->registered[slot] = 1;
597
598 if (grip->dirty[slot]) /* report initial state, if any */
599 report_slot(grip, slot);
600
601 printk(KERN_INFO "grip_mp: added %s, slot %d\n",
602 grip_name[grip->mode[slot]], slot);
603}
604
605static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
606{
607 struct grip_mp *grip;
608 int err;
609
610 if (!(grip = kcalloc(1, sizeof(struct grip_mp), GFP_KERNEL)))
611 return -ENOMEM;
612
613 grip->gameport = gameport;
614
615 gameport_set_drvdata(gameport, grip);
616
617 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
618 if (err)
619 goto fail1;
620
621 gameport_set_poll_handler(gameport, grip_poll);
622 gameport_set_poll_interval(gameport, 20);
623
624 if (!multiport_init(grip)) {
625 err = -ENODEV;
626 goto fail2;
627 }
628
629 if (!grip->mode[0] && !grip->mode[1] && !grip->mode[2] && !grip->mode[3]) {
630 /* nothing plugged in */
631 err = -ENODEV;
632 goto fail2;
633 }
634
635 return 0;
636
637fail2: gameport_close(gameport);
638fail1: gameport_set_drvdata(gameport, NULL);
639 kfree(grip);
640 return err;
641}
642
643static void grip_disconnect(struct gameport *gameport)
644{
645 struct grip_mp *grip = gameport_get_drvdata(gameport);
646 int i;
647
648 for (i = 0; i < 4; i++)
649 if (grip->registered[i])
650 input_unregister_device(grip->dev + i);
651 gameport_close(gameport);
652 gameport_set_drvdata(gameport, NULL);
653 kfree(grip);
654}
655
656static struct gameport_driver grip_drv = {
657 .driver = {
658 .name = "grip_mp",
659 },
660 .description = DRIVER_DESC,
661 .connect = grip_connect,
662 .disconnect = grip_disconnect,
663};
664
665static int __init grip_init(void)
666{
667 gameport_register_driver(&grip_drv);
668 return 0;
669}
670
671static void __exit grip_exit(void)
672{
673 gameport_unregister_driver(&grip_drv);
674}
675
676module_init(grip_init);
677module_exit(grip_exit);
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
new file mode 100644
index 000000000000..f93da7bc082d
--- /dev/null
+++ b/drivers/input/joystick/guillemot.c
@@ -0,0 +1,289 @@
1/*
2 * $Id: guillemot.c,v 1.10 2002/01/22 20:28:12 vojtech Exp $
3 *
4 * Copyright (c) 2001 Vojtech Pavlik
5 */
6
7/*
8 * Guillemot Digital Interface Protocol driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/kernel.h>
32#include <linux/slab.h>
33#include <linux/module.h>
34#include <linux/delay.h>
35#include <linux/init.h>
36#include <linux/gameport.h>
37#include <linux/input.h>
38
39#define DRIVER_DESC "Guillemot Digital joystick driver"
40
41MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
42MODULE_DESCRIPTION(DRIVER_DESC);
43MODULE_LICENSE("GPL");
44
45#define GUILLEMOT_MAX_START 600 /* 600 us */
46#define GUILLEMOT_MAX_STROBE 60 /* 60 us */
47#define GUILLEMOT_MAX_LENGTH 17 /* 17 bytes */
48
49static short guillemot_abs_pad[] =
50 { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, -1 };
51
52static short guillemot_btn_pad[] =
53 { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_MODE, BTN_SELECT, -1 };
54
55static struct {
56 int x;
57 int y;
58} guillemot_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
59
60struct guillemot_type {
61 unsigned char id;
62 short *abs;
63 short *btn;
64 int hat;
65 char *name;
66};
67
68struct guillemot {
69 struct gameport *gameport;
70 struct input_dev dev;
71 int bads;
72 int reads;
73 struct guillemot_type *type;
74 unsigned char length;
75 char phys[32];
76};
77
78static struct guillemot_type guillemot_type[] = {
79 { 0x00, guillemot_abs_pad, guillemot_btn_pad, 1, "Guillemot Pad" },
80 { 0 }};
81
82/*
83 * guillemot_read_packet() reads Guillemot joystick data.
84 */
85
86static int guillemot_read_packet(struct gameport *gameport, u8 *data)
87{
88 unsigned long flags;
89 unsigned char u, v;
90 unsigned int t, s;
91 int i;
92
93 for (i = 0; i < GUILLEMOT_MAX_LENGTH; i++)
94 data[i] = 0;
95
96 i = 0;
97 t = gameport_time(gameport, GUILLEMOT_MAX_START);
98 s = gameport_time(gameport, GUILLEMOT_MAX_STROBE);
99
100 local_irq_save(flags);
101 gameport_trigger(gameport);
102 v = gameport_read(gameport);
103
104 while (t > 0 && i < GUILLEMOT_MAX_LENGTH * 8) {
105 t--;
106 u = v; v = gameport_read(gameport);
107 if (v & ~u & 0x10) {
108 data[i >> 3] |= ((v >> 5) & 1) << (i & 7);
109 i++;
110 t = s;
111 }
112 }
113
114 local_irq_restore(flags);
115
116 return i;
117}
118
119/*
120 * guillemot_poll() reads and analyzes Guillemot joystick data.
121 */
122
123static void guillemot_poll(struct gameport *gameport)
124{
125 struct guillemot *guillemot = gameport_get_drvdata(gameport);
126 struct input_dev *dev = &guillemot->dev;
127 u8 data[GUILLEMOT_MAX_LENGTH];
128 int i;
129
130 guillemot->reads++;
131
132 if (guillemot_read_packet(guillemot->gameport, data) != GUILLEMOT_MAX_LENGTH * 8 ||
133 data[0] != 0x55 || data[16] != 0xaa) {
134 guillemot->bads++;
135 } else {
136
137 for (i = 0; i < 6 && guillemot->type->abs[i] >= 0; i++)
138 input_report_abs(dev, guillemot->type->abs[i], data[i + 5]);
139
140 if (guillemot->type->hat) {
141 input_report_abs(dev, ABS_HAT0X, guillemot_hat_to_axis[data[4] >> 4].x);
142 input_report_abs(dev, ABS_HAT0Y, guillemot_hat_to_axis[data[4] >> 4].y);
143 }
144
145 for (i = 0; i < 16 && guillemot->type->btn[i] >= 0; i++)
146 input_report_key(dev, guillemot->type->btn[i], (data[2 + (i >> 3)] >> (i & 7)) & 1);
147 }
148
149 input_sync(dev);
150}
151
152/*
153 * guillemot_open() is a callback from the input open routine.
154 */
155
156static int guillemot_open(struct input_dev *dev)
157{
158 struct guillemot *guillemot = dev->private;
159
160 gameport_start_polling(guillemot->gameport);
161 return 0;
162}
163
164/*
165 * guillemot_close() is a callback from the input close routine.
166 */
167
168static void guillemot_close(struct input_dev *dev)
169{
170 struct guillemot *guillemot = dev->private;
171
172 gameport_stop_polling(guillemot->gameport);
173}
174
175/*
176 * guillemot_connect() probes for Guillemot joysticks.
177 */
178
179static int guillemot_connect(struct gameport *gameport, struct gameport_driver *drv)
180{
181 struct guillemot *guillemot;
182 u8 data[GUILLEMOT_MAX_LENGTH];
183 int i, t;
184 int err;
185
186 if (!(guillemot = kcalloc(1, sizeof(struct guillemot), GFP_KERNEL)))
187 return -ENOMEM;
188
189 guillemot->gameport = gameport;
190
191 gameport_set_drvdata(gameport, guillemot);
192
193 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
194 if (err)
195 goto fail1;
196
197 i = guillemot_read_packet(gameport, data);
198
199 if (i != GUILLEMOT_MAX_LENGTH * 8 || data[0] != 0x55 || data[16] != 0xaa) {
200 err = -ENODEV;
201 goto fail2;
202 }
203
204 for (i = 0; guillemot_type[i].name; i++)
205 if (guillemot_type[i].id == data[11])
206 break;
207
208 if (!guillemot_type[i].name) {
209 printk(KERN_WARNING "guillemot.c: Unknown joystick on %s. [ %02x%02x:%04x, ver %d.%02d ]\n",
210 gameport->phys, data[12], data[13], data[11], data[14], data[15]);
211 err = -ENODEV;
212 goto fail2;
213 }
214
215 gameport_set_poll_handler(gameport, guillemot_poll);
216 gameport_set_poll_interval(gameport, 20);
217
218 sprintf(guillemot->phys, "%s/input0", gameport->phys);
219
220 guillemot->type = guillemot_type + i;
221
222 guillemot->dev.private = guillemot;
223 guillemot->dev.open = guillemot_open;
224 guillemot->dev.close = guillemot_close;
225
226 guillemot->dev.name = guillemot_type[i].name;
227 guillemot->dev.phys = guillemot->phys;
228 guillemot->dev.id.bustype = BUS_GAMEPORT;
229 guillemot->dev.id.vendor = GAMEPORT_ID_VENDOR_GUILLEMOT;
230 guillemot->dev.id.product = guillemot_type[i].id;
231 guillemot->dev.id.version = (int)data[14] << 8 | data[15];
232
233 guillemot->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
234
235 for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++)
236 input_set_abs_params(&guillemot->dev, t, 0, 255, 0, 0);
237
238 if (guillemot->type->hat) {
239 input_set_abs_params(&guillemot->dev, ABS_HAT0X, -1, 1, 0, 0);
240 input_set_abs_params(&guillemot->dev, ABS_HAT0Y, -1, 1, 0, 0);
241 }
242
243 for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
244 set_bit(t, guillemot->dev.keybit);
245
246 input_register_device(&guillemot->dev);
247 printk(KERN_INFO "input: %s ver %d.%02d on %s\n",
248 guillemot->type->name, data[14], data[15], gameport->phys);
249
250 return 0;
251
252fail2: gameport_close(gameport);
253fail1: gameport_set_drvdata(gameport, NULL);
254 kfree(guillemot);
255 return err;
256}
257
258static void guillemot_disconnect(struct gameport *gameport)
259{
260 struct guillemot *guillemot = gameport_get_drvdata(gameport);
261
262 printk(KERN_INFO "guillemot.c: Failed %d reads out of %d on %s\n", guillemot->reads, guillemot->bads, guillemot->phys);
263 input_unregister_device(&guillemot->dev);
264 gameport_close(gameport);
265 kfree(guillemot);
266}
267
268static struct gameport_driver guillemot_drv = {
269 .driver = {
270 .name = "guillemot",
271 },
272 .description = DRIVER_DESC,
273 .connect = guillemot_connect,
274 .disconnect = guillemot_disconnect,
275};
276
277static int __init guillemot_init(void)
278{
279 gameport_register_driver(&guillemot_drv);
280 return 0;
281}
282
283static void __exit guillemot_exit(void)
284{
285 gameport_unregister_driver(&guillemot_drv);
286}
287
288module_init(guillemot_init);
289module_exit(guillemot_exit);
diff --git a/drivers/input/joystick/iforce/Kconfig b/drivers/input/joystick/iforce/Kconfig
new file mode 100644
index 000000000000..8fde22a021b3
--- /dev/null
+++ b/drivers/input/joystick/iforce/Kconfig
@@ -0,0 +1,32 @@
1#
2# I-Force driver configuration
3#
4config JOYSTICK_IFORCE
5 tristate "I-Force devices"
6 depends on INPUT && INPUT_JOYSTICK
7 help
8 Say Y here if you have an I-Force joystick or steering wheel
9
10 You also must choose at least one of the two options below.
11
12 To compile this driver as a module, choose M here: the
13 module will be called iforce.
14
15config JOYSTICK_IFORCE_USB
16 bool "I-Force USB joysticks and wheels"
17 depends on JOYSTICK_IFORCE && (JOYSTICK_IFORCE=m || USB=y) && USB
18 help
19 Say Y here if you have an I-Force joystick or steering wheel
20 connected to your USB port.
21
22config JOYSTICK_IFORCE_232
23 bool "I-Force Serial joysticks and wheels"
24 depends on JOYSTICK_IFORCE && (JOYSTICK_IFORCE=m || SERIO=y) && SERIO
25 help
26 Say Y here if you have an I-Force joystick or steering wheel
27 connected to your serial (COM) port.
28
29 You will need an additional utility called inputattach, see
30 <file:Documentation/input/joystick.txt>
31 and <file:Documentation/input/ff.txt>.
32
diff --git a/drivers/input/joystick/iforce/Makefile b/drivers/input/joystick/iforce/Makefile
new file mode 100644
index 000000000000..17ae42bf9ffd
--- /dev/null
+++ b/drivers/input/joystick/iforce/Makefile
@@ -0,0 +1,20 @@
1#
2# Makefile for the I-Force driver
3#
4# By Johann Deneux <deneux@ifrance.com>
5#
6
7# Goal definition
8iforce-objs := iforce-ff.o iforce-main.o iforce-packets.o
9
10obj-$(CONFIG_JOYSTICK_IFORCE) += iforce.o
11
12ifeq ($(CONFIG_JOYSTICK_IFORCE_232),y)
13 iforce-objs += iforce-serio.o
14endif
15
16ifeq ($(CONFIG_JOYSTICK_IFORCE_USB),y)
17 iforce-objs += iforce-usb.o
18endif
19
20EXTRA_CFLAGS = -Werror-implicit-function-declaration
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c
new file mode 100644
index 000000000000..4678b6dab43b
--- /dev/null
+++ b/drivers/input/joystick/iforce/iforce-ff.c
@@ -0,0 +1,543 @@
1/*
2 * $Id: iforce-ff.c,v 1.9 2002/02/02 19:28:35 jdeneux Exp $
3 *
4 * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
5 * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
6 *
7 * USB/RS232 I-Force joysticks and wheels.
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * Should you need to contact me, the author, you can do so either by
26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
28 */
29
30#include "iforce.h"
31
32/*
33 * Set the magnitude of a constant force effect
34 * Return error code
35 *
36 * Note: caller must ensure exclusive access to device
37 */
38
39static int make_magnitude_modifier(struct iforce* iforce,
40 struct resource* mod_chunk, int no_alloc, __s16 level)
41{
42 unsigned char data[3];
43
44 if (!no_alloc) {
45 down(&iforce->mem_mutex);
46 if (allocate_resource(&(iforce->device_memory), mod_chunk, 2,
47 iforce->device_memory.start, iforce->device_memory.end, 2L,
48 NULL, NULL)) {
49 up(&iforce->mem_mutex);
50 return -ENOMEM;
51 }
52 up(&iforce->mem_mutex);
53 }
54
55 data[0] = LO(mod_chunk->start);
56 data[1] = HI(mod_chunk->start);
57 data[2] = HIFIX80(level);
58
59 iforce_send_packet(iforce, FF_CMD_MAGNITUDE, data);
60
61 iforce_dump_packet("magnitude: ", FF_CMD_MAGNITUDE, data);
62 return 0;
63}
64
65/*
66 * Upload the component of an effect dealing with the period, phase and magnitude
67 */
68
69static int make_period_modifier(struct iforce* iforce,
70 struct resource* mod_chunk, int no_alloc,
71 __s16 magnitude, __s16 offset, u16 period, u16 phase)
72{
73 unsigned char data[7];
74
75 period = TIME_SCALE(period);
76
77 if (!no_alloc) {
78 down(&iforce->mem_mutex);
79 if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c,
80 iforce->device_memory.start, iforce->device_memory.end, 2L,
81 NULL, NULL)) {
82 up(&iforce->mem_mutex);
83 return -ENOMEM;
84 }
85 up(&iforce->mem_mutex);
86 }
87
88 data[0] = LO(mod_chunk->start);
89 data[1] = HI(mod_chunk->start);
90
91 data[2] = HIFIX80(magnitude);
92 data[3] = HIFIX80(offset);
93 data[4] = HI(phase);
94
95 data[5] = LO(period);
96 data[6] = HI(period);
97
98 iforce_send_packet(iforce, FF_CMD_PERIOD, data);
99
100 return 0;
101}
102
103/*
104 * Uploads the part of an effect setting the envelope of the force
105 */
106
107static int make_envelope_modifier(struct iforce* iforce,
108 struct resource* mod_chunk, int no_alloc,
109 u16 attack_duration, __s16 initial_level,
110 u16 fade_duration, __s16 final_level)
111{
112 unsigned char data[8];
113
114 attack_duration = TIME_SCALE(attack_duration);
115 fade_duration = TIME_SCALE(fade_duration);
116
117 if (!no_alloc) {
118 down(&iforce->mem_mutex);
119 if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e,
120 iforce->device_memory.start, iforce->device_memory.end, 2L,
121 NULL, NULL)) {
122 up(&iforce->mem_mutex);
123 return -ENOMEM;
124 }
125 up(&iforce->mem_mutex);
126 }
127
128 data[0] = LO(mod_chunk->start);
129 data[1] = HI(mod_chunk->start);
130
131 data[2] = LO(attack_duration);
132 data[3] = HI(attack_duration);
133 data[4] = HI(initial_level);
134
135 data[5] = LO(fade_duration);
136 data[6] = HI(fade_duration);
137 data[7] = HI(final_level);
138
139 iforce_send_packet(iforce, FF_CMD_ENVELOPE, data);
140
141 return 0;
142}
143
144/*
145 * Component of spring, friction, inertia... effects
146 */
147
148static int make_condition_modifier(struct iforce* iforce,
149 struct resource* mod_chunk, int no_alloc,
150 __u16 rsat, __u16 lsat, __s16 rk, __s16 lk, u16 db, __s16 center)
151{
152 unsigned char data[10];
153
154 if (!no_alloc) {
155 down(&iforce->mem_mutex);
156 if (allocate_resource(&(iforce->device_memory), mod_chunk, 8,
157 iforce->device_memory.start, iforce->device_memory.end, 2L,
158 NULL, NULL)) {
159 up(&iforce->mem_mutex);
160 return -ENOMEM;
161 }
162 up(&iforce->mem_mutex);
163 }
164
165 data[0] = LO(mod_chunk->start);
166 data[1] = HI(mod_chunk->start);
167
168 data[2] = (100*rk)>>15; /* Dangerous: the sign is extended by gcc on plateforms providing an arith shift */
169 data[3] = (100*lk)>>15; /* This code is incorrect on cpus lacking arith shift */
170
171 center = (500*center)>>15;
172 data[4] = LO(center);
173 data[5] = HI(center);
174
175 db = (1000*db)>>16;
176 data[6] = LO(db);
177 data[7] = HI(db);
178
179 data[8] = (100*rsat)>>16;
180 data[9] = (100*lsat)>>16;
181
182 iforce_send_packet(iforce, FF_CMD_CONDITION, data);
183 iforce_dump_packet("condition", FF_CMD_CONDITION, data);
184
185 return 0;
186}
187
188static unsigned char find_button(struct iforce *iforce, signed short button)
189{
190 int i;
191 for (i = 1; iforce->type->btn[i] >= 0; i++)
192 if (iforce->type->btn[i] == button)
193 return i + 1;
194 return 0;
195}
196
197/*
198 * Analyse the changes in an effect, and tell if we need to send an condition
199 * parameter packet
200 */
201static int need_condition_modifier(struct iforce* iforce, struct ff_effect* new)
202{
203 int id = new->id;
204 struct ff_effect* old = &iforce->core_effects[id].effect;
205 int ret=0;
206 int i;
207
208 if (new->type != FF_SPRING && new->type != FF_FRICTION) {
209 printk(KERN_WARNING "iforce.c: bad effect type in need_condition_modifier\n");
210 return FALSE;
211 }
212
213 for(i=0; i<2; i++) {
214 ret |= old->u.condition[i].right_saturation != new->u.condition[i].right_saturation
215 || old->u.condition[i].left_saturation != new->u.condition[i].left_saturation
216 || old->u.condition[i].right_coeff != new->u.condition[i].right_coeff
217 || old->u.condition[i].left_coeff != new->u.condition[i].left_coeff
218 || old->u.condition[i].deadband != new->u.condition[i].deadband
219 || old->u.condition[i].center != new->u.condition[i].center;
220 }
221 return ret;
222}
223
224/*
225 * Analyse the changes in an effect, and tell if we need to send a magnitude
226 * parameter packet
227 */
228static int need_magnitude_modifier(struct iforce* iforce, struct ff_effect* effect)
229{
230 int id = effect->id;
231 struct ff_effect* old = &iforce->core_effects[id].effect;
232
233 if (effect->type != FF_CONSTANT) {
234 printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n");
235 return FALSE;
236 }
237
238 return (old->u.constant.level != effect->u.constant.level);
239}
240
241/*
242 * Analyse the changes in an effect, and tell if we need to send an envelope
243 * parameter packet
244 */
245static int need_envelope_modifier(struct iforce* iforce, struct ff_effect* effect)
246{
247 int id = effect->id;
248 struct ff_effect* old = &iforce->core_effects[id].effect;
249
250 switch (effect->type) {
251 case FF_CONSTANT:
252 if (old->u.constant.envelope.attack_length != effect->u.constant.envelope.attack_length
253 || old->u.constant.envelope.attack_level != effect->u.constant.envelope.attack_level
254 || old->u.constant.envelope.fade_length != effect->u.constant.envelope.fade_length
255 || old->u.constant.envelope.fade_level != effect->u.constant.envelope.fade_level)
256 return TRUE;
257 break;
258
259 case FF_PERIODIC:
260 if (old->u.periodic.envelope.attack_length != effect->u.periodic.envelope.attack_length
261 || old->u.periodic.envelope.attack_level != effect->u.periodic.envelope.attack_level
262 || old->u.periodic.envelope.fade_length != effect->u.periodic.envelope.fade_length
263 || old->u.periodic.envelope.fade_level != effect->u.periodic.envelope.fade_level)
264 return TRUE;
265 break;
266
267 default:
268 printk(KERN_WARNING "iforce.c: bad effect type in need_envelope_modifier\n");
269 }
270
271 return FALSE;
272}
273
274/*
275 * Analyse the changes in an effect, and tell if we need to send a periodic
276 * parameter effect
277 */
278static int need_period_modifier(struct iforce* iforce, struct ff_effect* new)
279{
280 int id = new->id;
281 struct ff_effect* old = &iforce->core_effects[id].effect;
282
283 if (new->type != FF_PERIODIC) {
284 printk(KERN_WARNING "iforce.c: bad effect type in need_periodic_modifier\n");
285 return FALSE;
286 }
287
288 return (old->u.periodic.period != new->u.periodic.period
289 || old->u.periodic.magnitude != new->u.periodic.magnitude
290 || old->u.periodic.offset != new->u.periodic.offset
291 || old->u.periodic.phase != new->u.periodic.phase);
292}
293
294/*
295 * Analyse the changes in an effect, and tell if we need to send an effect
296 * packet
297 */
298static int need_core(struct iforce* iforce, struct ff_effect* new)
299{
300 int id = new->id;
301 struct ff_effect* old = &iforce->core_effects[id].effect;
302
303 if (old->direction != new->direction
304 || old->trigger.button != new->trigger.button
305 || old->trigger.interval != new->trigger.interval
306 || old->replay.length != new->replay.length
307 || old->replay.delay != new->replay.delay)
308 return TRUE;
309
310 return FALSE;
311}
312/*
313 * Send the part common to all effects to the device
314 */
315static int make_core(struct iforce* iforce, u16 id, u16 mod_id1, u16 mod_id2,
316 u8 effect_type, u8 axes, u16 duration, u16 delay, u16 button,
317 u16 interval, u16 direction)
318{
319 unsigned char data[14];
320
321 duration = TIME_SCALE(duration);
322 delay = TIME_SCALE(delay);
323 interval = TIME_SCALE(interval);
324
325 data[0] = LO(id);
326 data[1] = effect_type;
327 data[2] = LO(axes) | find_button(iforce, button);
328
329 data[3] = LO(duration);
330 data[4] = HI(duration);
331
332 data[5] = HI(direction);
333
334 data[6] = LO(interval);
335 data[7] = HI(interval);
336
337 data[8] = LO(mod_id1);
338 data[9] = HI(mod_id1);
339 data[10] = LO(mod_id2);
340 data[11] = HI(mod_id2);
341
342 data[12] = LO(delay);
343 data[13] = HI(delay);
344
345 /* Stop effect */
346/* iforce_control_playback(iforce, id, 0);*/
347
348 iforce_send_packet(iforce, FF_CMD_EFFECT, data);
349
350 /* If needed, restart effect */
351 if (test_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[id].flags)) {
352 /* BUG: perhaps we should replay n times, instead of 1. But we do not know n */
353 iforce_control_playback(iforce, id, 1);
354 }
355
356 return 0;
357}
358
359/*
360 * Upload a periodic effect to the device
361 * See also iforce_upload_constant.
362 */
363int iforce_upload_periodic(struct iforce* iforce, struct ff_effect* effect, int is_update)
364{
365 u8 wave_code;
366 int core_id = effect->id;
367 struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
368 struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
369 struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
370 int param1_err = 1;
371 int param2_err = 1;
372 int core_err = 0;
373
374 if (!is_update || need_period_modifier(iforce, effect)) {
375 param1_err = make_period_modifier(iforce, mod1_chunk,
376 is_update,
377 effect->u.periodic.magnitude, effect->u.periodic.offset,
378 effect->u.periodic.period, effect->u.periodic.phase);
379 if (param1_err) return param1_err;
380 set_bit(FF_MOD1_IS_USED, core_effect->flags);
381 }
382
383 if (!is_update || need_envelope_modifier(iforce, effect)) {
384 param2_err = make_envelope_modifier(iforce, mod2_chunk,
385 is_update,
386 effect->u.periodic.envelope.attack_length,
387 effect->u.periodic.envelope.attack_level,
388 effect->u.periodic.envelope.fade_length,
389 effect->u.periodic.envelope.fade_level);
390 if (param2_err) return param2_err;
391 set_bit(FF_MOD2_IS_USED, core_effect->flags);
392 }
393
394 switch (effect->u.periodic.waveform) {
395 case FF_SQUARE: wave_code = 0x20; break;
396 case FF_TRIANGLE: wave_code = 0x21; break;
397 case FF_SINE: wave_code = 0x22; break;
398 case FF_SAW_UP: wave_code = 0x23; break;
399 case FF_SAW_DOWN: wave_code = 0x24; break;
400 default: wave_code = 0x20; break;
401 }
402
403 if (!is_update || need_core(iforce, effect)) {
404 core_err = make_core(iforce, effect->id,
405 mod1_chunk->start,
406 mod2_chunk->start,
407 wave_code,
408 0x20,
409 effect->replay.length,
410 effect->replay.delay,
411 effect->trigger.button,
412 effect->trigger.interval,
413 effect->direction);
414 }
415
416 /* If one of the parameter creation failed, we already returned an
417 * error code.
418 * If the core creation failed, we return its error code.
419 * Else: if one parameter at least was created, we return 0
420 * else we return 1;
421 */
422 return core_err < 0 ? core_err : (param1_err && param2_err);
423}
424
425/*
426 * Upload a constant force effect
427 * Return value:
428 * <0 Error code
429 * 0 Ok, effect created or updated
430 * 1 effect did not change since last upload, and no packet was therefore sent
431 */
432int iforce_upload_constant(struct iforce* iforce, struct ff_effect* effect, int is_update)
433{
434 int core_id = effect->id;
435 struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
436 struct resource* mod1_chunk = &(iforce->core_effects[core_id].mod1_chunk);
437 struct resource* mod2_chunk = &(iforce->core_effects[core_id].mod2_chunk);
438 int param1_err = 1;
439 int param2_err = 1;
440 int core_err = 0;
441
442 if (!is_update || need_magnitude_modifier(iforce, effect)) {
443 param1_err = make_magnitude_modifier(iforce, mod1_chunk,
444 is_update,
445 effect->u.constant.level);
446 if (param1_err) return param1_err;
447 set_bit(FF_MOD1_IS_USED, core_effect->flags);
448 }
449
450 if (!is_update || need_envelope_modifier(iforce, effect)) {
451 param2_err = make_envelope_modifier(iforce, mod2_chunk,
452 is_update,
453 effect->u.constant.envelope.attack_length,
454 effect->u.constant.envelope.attack_level,
455 effect->u.constant.envelope.fade_length,
456 effect->u.constant.envelope.fade_level);
457 if (param2_err) return param2_err;
458 set_bit(FF_MOD2_IS_USED, core_effect->flags);
459 }
460
461 if (!is_update || need_core(iforce, effect)) {
462 core_err = make_core(iforce, effect->id,
463 mod1_chunk->start,
464 mod2_chunk->start,
465 0x00,
466 0x20,
467 effect->replay.length,
468 effect->replay.delay,
469 effect->trigger.button,
470 effect->trigger.interval,
471 effect->direction);
472 }
473
474 /* If one of the parameter creation failed, we already returned an
475 * error code.
476 * If the core creation failed, we return its error code.
477 * Else: if one parameter at least was created, we return 0
478 * else we return 1;
479 */
480 return core_err < 0 ? core_err : (param1_err && param2_err);
481}
482
483/*
484 * Upload an condition effect. Those are for example friction, inertia, springs...
485 */
486int iforce_upload_condition(struct iforce* iforce, struct ff_effect* effect, int is_update)
487{
488 int core_id = effect->id;
489 struct iforce_core_effect* core_effect = iforce->core_effects + core_id;
490 struct resource* mod1_chunk = &(core_effect->mod1_chunk);
491 struct resource* mod2_chunk = &(core_effect->mod2_chunk);
492 u8 type;
493 int param_err = 1;
494 int core_err = 0;
495
496 switch (effect->type) {
497 case FF_SPRING: type = 0x40; break;
498 case FF_DAMPER: type = 0x41; break;
499 default: return -1;
500 }
501
502 if (!is_update || need_condition_modifier(iforce, effect)) {
503 param_err = make_condition_modifier(iforce, mod1_chunk,
504 is_update,
505 effect->u.condition[0].right_saturation,
506 effect->u.condition[0].left_saturation,
507 effect->u.condition[0].right_coeff,
508 effect->u.condition[0].left_coeff,
509 effect->u.condition[0].deadband,
510 effect->u.condition[0].center);
511 if (param_err) return param_err;
512 set_bit(FF_MOD1_IS_USED, core_effect->flags);
513
514 param_err = make_condition_modifier(iforce, mod2_chunk,
515 is_update,
516 effect->u.condition[1].right_saturation,
517 effect->u.condition[1].left_saturation,
518 effect->u.condition[1].right_coeff,
519 effect->u.condition[1].left_coeff,
520 effect->u.condition[1].deadband,
521 effect->u.condition[1].center);
522 if (param_err) return param_err;
523 set_bit(FF_MOD2_IS_USED, core_effect->flags);
524
525 }
526
527 if (!is_update || need_core(iforce, effect)) {
528 core_err = make_core(iforce, effect->id,
529 mod1_chunk->start, mod2_chunk->start,
530 type, 0xc0,
531 effect->replay.length, effect->replay.delay,
532 effect->trigger.button, effect->trigger.interval,
533 effect->direction);
534 }
535
536 /* If the parameter creation failed, we already returned an
537 * error code.
538 * If the core creation failed, we return its error code.
539 * Else: if a parameter was created, we return 0
540 * else we return 1;
541 */
542 return core_err < 0 ? core_err : param_err;
543}
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
new file mode 100644
index 000000000000..028f3513629a
--- /dev/null
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -0,0 +1,557 @@
1/*
2 * $Id: iforce-main.c,v 1.19 2002/07/07 10:22:50 jdeneux Exp $
3 *
4 * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
5 * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
6 *
7 * USB/RS232 I-Force joysticks and wheels.
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * Should you need to contact me, the author, you can do so either by
26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
28 */
29
30#include "iforce.h"
31
32MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <deneux@ifrance.com>");
33MODULE_DESCRIPTION("USB/RS232 I-Force joysticks and wheels driver");
34MODULE_LICENSE("GPL");
35
36static signed short btn_joystick[] =
37{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
38 BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, -1 };
39
40static signed short btn_avb_pegasus[] =
41{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
42 BTN_BASE2, BTN_BASE3, BTN_BASE4, -1 };
43
44static signed short btn_wheel[] =
45{ BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE,
46 BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_BASE5, BTN_A, BTN_B, BTN_C, -1 };
47
48static signed short btn_avb_tw[] =
49{ BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE,
50 BTN_BASE2, BTN_BASE3, BTN_BASE4, -1 };
51
52static signed short btn_avb_wheel[] =
53{ BTN_GEAR_DOWN, BTN_GEAR_UP, BTN_BASE, BTN_BASE2, BTN_BASE3,
54 BTN_BASE4, BTN_BASE5, BTN_BASE6, -1 };
55
56static signed short abs_joystick[] =
57{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 };
58
59static signed short abs_avb_pegasus[] =
60{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y,
61 ABS_HAT1X, ABS_HAT1Y, -1 };
62
63static signed short abs_wheel[] =
64{ ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, -1 };
65
66static signed short ff_iforce[] =
67{ FF_PERIODIC, FF_CONSTANT, FF_SPRING, FF_DAMPER,
68 FF_SQUARE, FF_TRIANGLE, FF_SINE, FF_SAW_UP, FF_SAW_DOWN, FF_GAIN,
69 FF_AUTOCENTER, -1 };
70
71static struct iforce_device iforce_device[] = {
72 { 0x044f, 0xa01c, "Thrustmaster Motor Sport GT", btn_wheel, abs_wheel, ff_iforce },
73 { 0x046d, 0xc281, "Logitech WingMan Force", btn_joystick, abs_joystick, ff_iforce },
74 { 0x046d, 0xc291, "Logitech WingMan Formula Force", btn_wheel, abs_wheel, ff_iforce },
75 { 0x05ef, 0x020a, "AVB Top Shot Pegasus", btn_avb_pegasus, abs_avb_pegasus, ff_iforce },
76 { 0x05ef, 0x8884, "AVB Mag Turbo Force", btn_avb_wheel, abs_wheel, ff_iforce },
77 { 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel", btn_avb_tw, abs_wheel, ff_iforce }, //?
78 { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //?
79 { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //?
80 { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //?
81 { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce }
82};
83
84
85
86static int iforce_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
87{
88 struct iforce* iforce = (struct iforce*)(dev->private);
89 unsigned char data[3];
90
91 if (type != EV_FF)
92 return -1;
93
94 switch (code) {
95
96 case FF_GAIN:
97
98 data[0] = value >> 9;
99 iforce_send_packet(iforce, FF_CMD_GAIN, data);
100
101 return 0;
102
103 case FF_AUTOCENTER:
104
105 data[0] = 0x03;
106 data[1] = value >> 9;
107 iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data);
108
109 data[0] = 0x04;
110 data[1] = 0x01;
111 iforce_send_packet(iforce, FF_CMD_AUTOCENTER, data);
112
113 return 0;
114
115 default: /* Play or stop an effect */
116
117 if (!CHECK_OWNERSHIP(code, iforce)) {
118 return -1;
119 }
120 if (value > 0) {
121 set_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[code].flags);
122 }
123 else {
124 clear_bit(FF_CORE_SHOULD_PLAY, iforce->core_effects[code].flags);
125 }
126
127 iforce_control_playback(iforce, code, value);
128 return 0;
129 }
130
131 return -1;
132}
133
134/*
135 * Function called when an ioctl is performed on the event dev entry.
136 * It uploads an effect to the device
137 */
138static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect)
139{
140 struct iforce* iforce = (struct iforce*)(dev->private);
141 int id;
142 int ret;
143 int is_update;
144
145/* Check this effect type is supported by this device */
146 if (!test_bit(effect->type, iforce->dev.ffbit))
147 return -EINVAL;
148
149/*
150 * If we want to create a new effect, get a free id
151 */
152 if (effect->id == -1) {
153
154 for (id=0; id < FF_EFFECTS_MAX; ++id)
155 if (!test_and_set_bit(FF_CORE_IS_USED, iforce->core_effects[id].flags)) break;
156
157 if ( id == FF_EFFECTS_MAX || id >= iforce->dev.ff_effects_max)
158 return -ENOMEM;
159
160 effect->id = id;
161 iforce->core_effects[id].owner = current->pid;
162 iforce->core_effects[id].flags[0] = (1<<FF_CORE_IS_USED); /* Only IS_USED bit must be set */
163
164 is_update = FALSE;
165 }
166 else {
167 /* We want to update an effect */
168 if (!CHECK_OWNERSHIP(effect->id, iforce)) return -EACCES;
169
170 /* Parameter type cannot be updated */
171 if (effect->type != iforce->core_effects[effect->id].effect.type)
172 return -EINVAL;
173
174 /* Check the effect is not already being updated */
175 if (test_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags)) {
176 return -EAGAIN;
177 }
178
179 is_update = TRUE;
180 }
181
182/*
183 * Upload the effect
184 */
185 switch (effect->type) {
186
187 case FF_PERIODIC:
188 ret = iforce_upload_periodic(iforce, effect, is_update);
189 break;
190
191 case FF_CONSTANT:
192 ret = iforce_upload_constant(iforce, effect, is_update);
193 break;
194
195 case FF_SPRING:
196 case FF_DAMPER:
197 ret = iforce_upload_condition(iforce, effect, is_update);
198 break;
199
200 default:
201 return -EINVAL;
202 }
203 if (ret == 0) {
204 /* A packet was sent, forbid new updates until we are notified
205 * that the packet was updated
206 */
207 set_bit(FF_CORE_UPDATE, iforce->core_effects[effect->id].flags);
208 }
209 iforce->core_effects[effect->id].effect = *effect;
210 return ret;
211}
212
213/*
214 * Erases an effect: it frees the effect id and mark as unused the memory
215 * allocated for the parameters
216 */
217static int iforce_erase_effect(struct input_dev *dev, int effect_id)
218{
219 struct iforce* iforce = (struct iforce*)(dev->private);
220 int err = 0;
221 struct iforce_core_effect* core_effect;
222
223 /* Check who is trying to erase this effect */
224 if (iforce->core_effects[effect_id].owner != current->pid) {
225 printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, iforce->core_effects[effect_id].owner);
226 return -EACCES;
227 }
228
229 if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX)
230 return -EINVAL;
231
232 core_effect = iforce->core_effects + effect_id;
233
234 if (test_bit(FF_MOD1_IS_USED, core_effect->flags))
235 err = release_resource(&(iforce->core_effects[effect_id].mod1_chunk));
236
237 if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags))
238 err = release_resource(&(iforce->core_effects[effect_id].mod2_chunk));
239
240 /*TODO: remember to change that if more FF_MOD* bits are added */
241 core_effect->flags[0] = 0;
242
243 return err;
244}
245
246static int iforce_open(struct input_dev *dev)
247{
248 struct iforce *iforce = dev->private;
249
250 switch (iforce->bus) {
251#ifdef CONFIG_JOYSTICK_IFORCE_USB
252 case IFORCE_USB:
253 iforce->irq->dev = iforce->usbdev;
254 if (usb_submit_urb(iforce->irq, GFP_KERNEL))
255 return -EIO;
256 break;
257#endif
258 }
259
260 /* Enable force feedback */
261 iforce_send_packet(iforce, FF_CMD_ENABLE, "\004");
262
263 return 0;
264}
265
266static int iforce_flush(struct input_dev *dev, struct file *file)
267{
268 struct iforce *iforce = dev->private;
269 int i;
270
271 /* Erase all effects this process owns */
272 for (i=0; i<dev->ff_effects_max; ++i) {
273
274 if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) &&
275 current->pid == iforce->core_effects[i].owner) {
276
277 /* Stop effect */
278 input_report_ff(dev, i, 0);
279
280 /* Free ressources assigned to effect */
281 if (iforce_erase_effect(dev, i)) {
282 printk(KERN_WARNING "iforce_flush: erase effect %d failed\n", i);
283 }
284 }
285
286 }
287 return 0;
288}
289
290static void iforce_release(struct input_dev *dev)
291{
292 struct iforce *iforce = dev->private;
293 int i;
294
295 /* Check: no effect should be present in memory */
296 for (i=0; i<dev->ff_effects_max; ++i) {
297 if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags))
298 break;
299 }
300 if (i<dev->ff_effects_max) {
301 printk(KERN_WARNING "iforce_release: Device still owns effects\n");
302 }
303
304 /* Disable force feedback playback */
305 iforce_send_packet(iforce, FF_CMD_ENABLE, "\001");
306
307 switch (iforce->bus) {
308#ifdef CONFIG_JOYSTICK_IFORCE_USB
309 case IFORCE_USB:
310 usb_unlink_urb(iforce->irq);
311
312 /* The device was unplugged before the file
313 * was released */
314 if (iforce->usbdev == NULL) {
315 iforce_delete_device(iforce);
316 kfree(iforce);
317 }
318 break;
319#endif
320 }
321}
322
323void iforce_delete_device(struct iforce *iforce)
324{
325 switch (iforce->bus) {
326#ifdef CONFIG_JOYSTICK_IFORCE_USB
327 case IFORCE_USB:
328 iforce_usb_delete(iforce);
329 break;
330#endif
331#ifdef CONFIG_JOYSTICK_IFORCE_232
332 case IFORCE_232:
333 //TODO: Wait for the last packets to be sent
334 break;
335#endif
336 }
337}
338
339int iforce_init_device(struct iforce *iforce)
340{
341 unsigned char c[] = "CEOV";
342 int i;
343
344 init_waitqueue_head(&iforce->wait);
345 spin_lock_init(&iforce->xmit_lock);
346 init_MUTEX(&iforce->mem_mutex);
347 iforce->xmit.buf = iforce->xmit_data;
348
349 iforce->dev.ff_effects_max = 10;
350
351/*
352 * Input device fields.
353 */
354
355 switch (iforce->bus) {
356#ifdef CONFIG_JOYSTICK_IFORCE_USB
357 case IFORCE_USB:
358 iforce->dev.id.bustype = BUS_USB;
359 iforce->dev.dev = &iforce->usbdev->dev;
360 break;
361#endif
362#ifdef CONFIG_JOYSTICK_IFORCE_232
363 case IFORCE_232:
364 iforce->dev.id.bustype = BUS_RS232;
365 iforce->dev.dev = &iforce->serio->dev;
366 break;
367#endif
368 }
369
370 iforce->dev.private = iforce;
371 iforce->dev.name = "Unknown I-Force device";
372 iforce->dev.open = iforce_open;
373 iforce->dev.close = iforce_release;
374 iforce->dev.flush = iforce_flush;
375 iforce->dev.event = iforce_input_event;
376 iforce->dev.upload_effect = iforce_upload_effect;
377 iforce->dev.erase_effect = iforce_erase_effect;
378
379/*
380 * On-device memory allocation.
381 */
382
383 iforce->device_memory.name = "I-Force device effect memory";
384 iforce->device_memory.start = 0;
385 iforce->device_memory.end = 200;
386 iforce->device_memory.flags = IORESOURCE_MEM;
387 iforce->device_memory.parent = NULL;
388 iforce->device_memory.child = NULL;
389 iforce->device_memory.sibling = NULL;
390
391/*
392 * Wait until device ready - until it sends its first response.
393 */
394
395 for (i = 0; i < 20; i++)
396 if (!iforce_get_id_packet(iforce, "O"))
397 break;
398
399 if (i == 20) { /* 5 seconds */
400 printk(KERN_ERR "iforce-main.c: Timeout waiting for response from device.\n");
401 return -1;
402 }
403
404/*
405 * Get device info.
406 */
407
408 if (!iforce_get_id_packet(iforce, "M"))
409 iforce->dev.id.vendor = (iforce->edata[2] << 8) | iforce->edata[1];
410 else
411 printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet M\n");
412
413 if (!iforce_get_id_packet(iforce, "P"))
414 iforce->dev.id.product = (iforce->edata[2] << 8) | iforce->edata[1];
415 else
416 printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet P\n");
417
418 if (!iforce_get_id_packet(iforce, "B"))
419 iforce->device_memory.end = (iforce->edata[2] << 8) | iforce->edata[1];
420 else
421 printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet B\n");
422
423 if (!iforce_get_id_packet(iforce, "N"))
424 iforce->dev.ff_effects_max = iforce->edata[1];
425 else
426 printk(KERN_WARNING "iforce-main.c: Device does not respond to id packet N\n");
427
428 /* Check if the device can store more effects than the driver can really handle */
429 if (iforce->dev.ff_effects_max > FF_EFFECTS_MAX) {
430 printk(KERN_WARNING "input??: Device can handle %d effects, but N_EFFECTS_MAX is set to %d in iforce.h\n",
431 iforce->dev.ff_effects_max, FF_EFFECTS_MAX);
432 iforce->dev.ff_effects_max = FF_EFFECTS_MAX;
433 }
434
435/*
436 * Display additional info.
437 */
438
439 for (i = 0; c[i]; i++)
440 if (!iforce_get_id_packet(iforce, c + i))
441 iforce_dump_packet("info", iforce->ecmd, iforce->edata);
442
443/*
444 * Disable spring, enable force feedback.
445 * FIXME: We should use iforce_set_autocenter() et al here.
446 */
447
448 iforce_send_packet(iforce, FF_CMD_AUTOCENTER, "\004\000");
449
450/*
451 * Find appropriate device entry
452 */
453
454 for (i = 0; iforce_device[i].idvendor; i++)
455 if (iforce_device[i].idvendor == iforce->dev.id.vendor &&
456 iforce_device[i].idproduct == iforce->dev.id.product)
457 break;
458
459 iforce->type = iforce_device + i;
460 iforce->dev.name = iforce->type->name;
461
462/*
463 * Set input device bitfields and ranges.
464 */
465
466 iforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_FF) | BIT(EV_FF_STATUS);
467
468 for (i = 0; iforce->type->btn[i] >= 0; i++) {
469 signed short t = iforce->type->btn[i];
470 set_bit(t, iforce->dev.keybit);
471 }
472 set_bit(BTN_DEAD, iforce->dev.keybit);
473
474 for (i = 0; iforce->type->abs[i] >= 0; i++) {
475
476 signed short t = iforce->type->abs[i];
477 set_bit(t, iforce->dev.absbit);
478
479 switch (t) {
480
481 case ABS_X:
482 case ABS_Y:
483 case ABS_WHEEL:
484
485 iforce->dev.absmax[t] = 1920;
486 iforce->dev.absmin[t] = -1920;
487 iforce->dev.absflat[t] = 128;
488 iforce->dev.absfuzz[t] = 16;
489
490 set_bit(t, iforce->dev.ffbit);
491 break;
492
493 case ABS_THROTTLE:
494 case ABS_GAS:
495 case ABS_BRAKE:
496
497 iforce->dev.absmax[t] = 255;
498 iforce->dev.absmin[t] = 0;
499 break;
500
501 case ABS_RUDDER:
502
503 iforce->dev.absmax[t] = 127;
504 iforce->dev.absmin[t] = -128;
505 break;
506
507 case ABS_HAT0X:
508 case ABS_HAT0Y:
509 case ABS_HAT1X:
510 case ABS_HAT1Y:
511 iforce->dev.absmax[t] = 1;
512 iforce->dev.absmin[t] = -1;
513 break;
514 }
515 }
516
517 for (i = 0; iforce->type->ff[i] >= 0; i++)
518 set_bit(iforce->type->ff[i], iforce->dev.ffbit);
519
520/*
521 * Register input device.
522 */
523
524 input_register_device(&iforce->dev);
525
526 printk(KERN_DEBUG "iforce->dev.open = %p\n", iforce->dev.open);
527
528 printk(KERN_INFO "input: %s [%d effects, %ld bytes memory]\n",
529 iforce->dev.name, iforce->dev.ff_effects_max,
530 iforce->device_memory.end);
531
532 return 0;
533}
534
535static int __init iforce_init(void)
536{
537#ifdef CONFIG_JOYSTICK_IFORCE_USB
538 usb_register(&iforce_usb_driver);
539#endif
540#ifdef CONFIG_JOYSTICK_IFORCE_232
541 serio_register_driver(&iforce_serio_drv);
542#endif
543 return 0;
544}
545
546static void __exit iforce_exit(void)
547{
548#ifdef CONFIG_JOYSTICK_IFORCE_USB
549 usb_deregister(&iforce_usb_driver);
550#endif
551#ifdef CONFIG_JOYSTICK_IFORCE_232
552 serio_unregister_driver(&iforce_serio_drv);
553#endif
554}
555
556module_init(iforce_init);
557module_exit(iforce_exit);
diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c
new file mode 100644
index 000000000000..58728ebaaf80
--- /dev/null
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -0,0 +1,319 @@
1/*
2 * $Id: iforce-packets.c,v 1.16 2002/07/07 10:22:50 jdeneux Exp $
3 *
4 * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
5 * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
6 *
7 * USB/RS232 I-Force joysticks and wheels.
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * Should you need to contact me, the author, you can do so either by
26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
28 */
29
30#include "iforce.h"
31
32static struct {
33 __s32 x;
34 __s32 y;
35} iforce_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
36
37
38void iforce_dump_packet(char *msg, u16 cmd, unsigned char *data)
39{
40 int i;
41
42 printk(KERN_DEBUG "iforce.c: %s ( cmd = %04x, data = ", msg, cmd);
43 for (i = 0; i < LO(cmd); i++)
44 printk("%02x ", data[i]);
45 printk(")\n");
46}
47
48/*
49 * Send a packet of bytes to the device
50 */
51int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data)
52{
53 /* Copy data to buffer */
54 int n = LO(cmd);
55 int c;
56 int empty;
57 int head, tail;
58 unsigned long flags;
59
60/*
61 * Update head and tail of xmit buffer
62 */
63 spin_lock_irqsave(&iforce->xmit_lock, flags);
64
65 head = iforce->xmit.head;
66 tail = iforce->xmit.tail;
67
68 if (CIRC_SPACE(head, tail, XMIT_SIZE) < n+2) {
69 printk(KERN_WARNING "iforce.c: not enough space in xmit buffer to send new packet\n");
70 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
71 return -1;
72 }
73
74 empty = head == tail;
75 XMIT_INC(iforce->xmit.head, n+2);
76
77/*
78 * Store packet in xmit buffer
79 */
80 iforce->xmit.buf[head] = HI(cmd);
81 XMIT_INC(head, 1);
82 iforce->xmit.buf[head] = LO(cmd);
83 XMIT_INC(head, 1);
84
85 c = CIRC_SPACE_TO_END(head, tail, XMIT_SIZE);
86 if (n < c) c=n;
87
88 memcpy(&iforce->xmit.buf[head],
89 data,
90 c);
91 if (n != c) {
92 memcpy(&iforce->xmit.buf[0],
93 data + c,
94 n - c);
95 }
96 XMIT_INC(head, n);
97
98 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
99/*
100 * If necessary, start the transmission
101 */
102 switch (iforce->bus) {
103
104#ifdef CONFIG_JOYSTICK_IFORCE_232
105 case IFORCE_232:
106 if (empty)
107 iforce_serial_xmit(iforce);
108 break;
109#endif
110#ifdef CONFIG_JOYSTICK_IFORCE_USB
111 case IFORCE_USB:
112
113 if (iforce->usbdev && empty &&
114 !test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) {
115
116 iforce_usb_xmit(iforce);
117 }
118 break;
119#endif
120 }
121 return 0;
122}
123
124/* Start or stop an effect */
125int iforce_control_playback(struct iforce* iforce, u16 id, unsigned int value)
126{
127 unsigned char data[3];
128
129printk(KERN_DEBUG "iforce-packets.c: control_playback %d %d\n", id, value);
130
131 data[0] = LO(id);
132 data[1] = (value > 0) ? ((value > 1) ? 0x41 : 0x01) : 0;
133 data[2] = LO(value);
134 return iforce_send_packet(iforce, FF_CMD_PLAY, data);
135}
136
137/* Mark an effect that was being updated as ready. That means it can be updated
138 * again */
139static int mark_core_as_ready(struct iforce *iforce, unsigned short addr)
140{
141 int i;
142 for (i=0; i<iforce->dev.ff_effects_max; ++i) {
143 if (test_bit(FF_CORE_IS_USED, iforce->core_effects[i].flags) &&
144 (iforce->core_effects[i].mod1_chunk.start == addr ||
145 iforce->core_effects[i].mod2_chunk.start == addr)) {
146 clear_bit(FF_CORE_UPDATE, iforce->core_effects[i].flags);
147 return 0;
148 }
149 }
150 printk(KERN_WARNING "iforce-packets.c: unused effect %04x updated !!!\n", addr);
151 return -1;
152}
153
154void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, struct pt_regs *regs)
155{
156 struct input_dev *dev = &iforce->dev;
157 int i;
158 static int being_used = 0;
159
160 if (being_used)
161 printk(KERN_WARNING "iforce-packets.c: re-entrant call to iforce_process %d\n", being_used);
162 being_used++;
163
164#ifdef CONFIG_JOYSTICK_IFORCE_232
165 if (HI(iforce->expect_packet) == HI(cmd)) {
166 iforce->expect_packet = 0;
167 iforce->ecmd = cmd;
168 memcpy(iforce->edata, data, IFORCE_MAX_LENGTH);
169 wake_up(&iforce->wait);
170 }
171#endif
172
173 if (!iforce->type) {
174 being_used--;
175 return;
176 }
177
178 switch (HI(cmd)) {
179
180 case 0x01: /* joystick position data */
181 case 0x03: /* wheel position data */
182
183 input_regs(dev, regs);
184
185 if (HI(cmd) == 1) {
186 input_report_abs(dev, ABS_X, (__s16) (((__s16)data[1] << 8) | data[0]));
187 input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[3] << 8) | data[2]));
188 input_report_abs(dev, ABS_THROTTLE, 255 - data[4]);
189 if (LO(cmd) >= 8 && test_bit(ABS_RUDDER ,dev->absbit))
190 input_report_abs(dev, ABS_RUDDER, (__s8)data[7]);
191 } else {
192 input_report_abs(dev, ABS_WHEEL, (__s16) (((__s16)data[1] << 8) | data[0]));
193 input_report_abs(dev, ABS_GAS, 255 - data[2]);
194 input_report_abs(dev, ABS_BRAKE, 255 - data[3]);
195 }
196
197 input_report_abs(dev, ABS_HAT0X, iforce_hat_to_axis[data[6] >> 4].x);
198 input_report_abs(dev, ABS_HAT0Y, iforce_hat_to_axis[data[6] >> 4].y);
199
200 for (i = 0; iforce->type->btn[i] >= 0; i++)
201 input_report_key(dev, iforce->type->btn[i], data[(i >> 3) + 5] & (1 << (i & 7)));
202
203 /* If there are untouched bits left, interpret them as the second hat */
204 if (i <= 8) {
205 int btns = data[6];
206 if (test_bit(ABS_HAT1X, dev->absbit)) {
207 if (btns & 8) input_report_abs(dev, ABS_HAT1X, -1);
208 else if (btns & 2) input_report_abs(dev, ABS_HAT1X, 1);
209 else input_report_abs(dev, ABS_HAT1X, 0);
210 }
211 if (test_bit(ABS_HAT1Y, dev->absbit)) {
212 if (btns & 1) input_report_abs(dev, ABS_HAT1Y, -1);
213 else if (btns & 4) input_report_abs(dev, ABS_HAT1Y, 1);
214 else input_report_abs(dev, ABS_HAT1Y, 0);
215 }
216 }
217
218 input_sync(dev);
219
220 break;
221
222 case 0x02: /* status report */
223 input_regs(dev, regs);
224 input_report_key(dev, BTN_DEAD, data[0] & 0x02);
225 input_sync(dev);
226
227 /* Check if an effect was just started or stopped */
228 i = data[1] & 0x7f;
229 if (data[1] & 0x80) {
230 if (!test_and_set_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
231 /* Report play event */
232 input_report_ff_status(dev, i, FF_STATUS_PLAYING);
233 }
234 }
235 else if (test_and_clear_bit(FF_CORE_IS_PLAYED, iforce->core_effects[i].flags)) {
236 /* Report stop event */
237 input_report_ff_status(dev, i, FF_STATUS_STOPPED);
238 }
239 if (LO(cmd) > 3) {
240 int j;
241 for (j=3; j<LO(cmd); j+=2) {
242 mark_core_as_ready(iforce, data[j] | (data[j+1]<<8));
243 }
244 }
245 break;
246 }
247 being_used--;
248}
249
250int iforce_get_id_packet(struct iforce *iforce, char *packet)
251{
252 DECLARE_WAITQUEUE(wait, current);
253 int timeout = HZ; /* 1 second */
254
255 switch (iforce->bus) {
256
257 case IFORCE_USB:
258
259#ifdef CONFIG_JOYSTICK_IFORCE_USB
260 iforce->cr.bRequest = packet[0];
261 iforce->ctrl->dev = iforce->usbdev;
262
263 set_current_state(TASK_INTERRUPTIBLE);
264 add_wait_queue(&iforce->wait, &wait);
265
266 if (usb_submit_urb(iforce->ctrl, GFP_ATOMIC)) {
267 set_current_state(TASK_RUNNING);
268 remove_wait_queue(&iforce->wait, &wait);
269 return -1;
270 }
271
272 while (timeout && iforce->ctrl->status == -EINPROGRESS)
273 timeout = schedule_timeout(timeout);
274
275 set_current_state(TASK_RUNNING);
276 remove_wait_queue(&iforce->wait, &wait);
277
278 if (!timeout) {
279 usb_unlink_urb(iforce->ctrl);
280 return -1;
281 }
282#else
283 printk(KERN_ERR "iforce_get_id_packet: iforce->bus = USB!\n");
284#endif
285 break;
286
287 case IFORCE_232:
288
289#ifdef CONFIG_JOYSTICK_IFORCE_232
290 iforce->expect_packet = FF_CMD_QUERY;
291 iforce_send_packet(iforce, FF_CMD_QUERY, packet);
292
293 set_current_state(TASK_INTERRUPTIBLE);
294 add_wait_queue(&iforce->wait, &wait);
295
296 while (timeout && iforce->expect_packet)
297 timeout = schedule_timeout(timeout);
298
299 set_current_state(TASK_RUNNING);
300 remove_wait_queue(&iforce->wait, &wait);
301
302 if (!timeout) {
303 iforce->expect_packet = 0;
304 return -1;
305 }
306#else
307 printk(KERN_ERR "iforce_get_id_packet: iforce->bus = SERIO!\n");
308#endif
309 break;
310
311 default:
312 printk(KERN_ERR "iforce_get_id_packet: iforce->bus = %d\n",
313 iforce->bus);
314 break;
315 }
316
317 return -(iforce->edata[0] != packet[0]);
318}
319
diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
new file mode 100644
index 000000000000..11f51905cba7
--- /dev/null
+++ b/drivers/input/joystick/iforce/iforce-serio.c
@@ -0,0 +1,193 @@
1/*
2 * $Id: iforce-serio.c,v 1.4 2002/01/28 22:45:00 jdeneux Exp $
3 *
4 * Copyright (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
5 * Copyright (c) 2001 Johann Deneux <deneux@ifrance.com>
6 *
7 * USB/RS232 I-Force joysticks and wheels.
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * Should you need to contact me, the author, you can do so either by
26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
28 */
29
30#include "iforce.h"
31
32void iforce_serial_xmit(struct iforce *iforce)
33{
34 unsigned char cs;
35 int i;
36 unsigned long flags;
37
38 if (test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) {
39 set_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags);
40 return;
41 }
42
43 spin_lock_irqsave(&iforce->xmit_lock, flags);
44
45again:
46 if (iforce->xmit.head == iforce->xmit.tail) {
47 clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
48 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
49 return;
50 }
51
52 cs = 0x2b;
53
54 serio_write(iforce->serio, 0x2b);
55
56 serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
57 cs ^= iforce->xmit.buf[iforce->xmit.tail];
58 XMIT_INC(iforce->xmit.tail, 1);
59
60 for (i=iforce->xmit.buf[iforce->xmit.tail]; i >= 0; --i) {
61 serio_write(iforce->serio, iforce->xmit.buf[iforce->xmit.tail]);
62 cs ^= iforce->xmit.buf[iforce->xmit.tail];
63 XMIT_INC(iforce->xmit.tail, 1);
64 }
65
66 serio_write(iforce->serio, cs);
67
68 if (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags))
69 goto again;
70
71 clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
72
73 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
74}
75
76static void iforce_serio_write_wakeup(struct serio *serio)
77{
78 struct iforce *iforce = serio_get_drvdata(serio);
79
80 iforce_serial_xmit(iforce);
81}
82
83static irqreturn_t iforce_serio_irq(struct serio *serio,
84 unsigned char data, unsigned int flags, struct pt_regs *regs)
85{
86 struct iforce *iforce = serio_get_drvdata(serio);
87
88 if (!iforce->pkt) {
89 if (data == 0x2b)
90 iforce->pkt = 1;
91 goto out;
92 }
93
94 if (!iforce->id) {
95 if (data > 3 && data != 0xff)
96 iforce->pkt = 0;
97 else
98 iforce->id = data;
99 goto out;
100 }
101
102 if (!iforce->len) {
103 if (data > IFORCE_MAX_LENGTH) {
104 iforce->pkt = 0;
105 iforce->id = 0;
106 } else {
107 iforce->len = data;
108 }
109 goto out;
110 }
111
112 if (iforce->idx < iforce->len) {
113 iforce->csum += iforce->data[iforce->idx++] = data;
114 goto out;
115 }
116
117 if (iforce->idx == iforce->len) {
118 iforce_process_packet(iforce, (iforce->id << 8) | iforce->idx, iforce->data, regs);
119 iforce->pkt = 0;
120 iforce->id = 0;
121 iforce->len = 0;
122 iforce->idx = 0;
123 iforce->csum = 0;
124 }
125out:
126 return IRQ_HANDLED;
127}
128
129static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
130{
131 struct iforce *iforce;
132 int err;
133
134 if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL)))
135 return -ENOMEM;
136
137 memset(iforce, 0, sizeof(struct iforce));
138
139 iforce->bus = IFORCE_232;
140 iforce->serio = serio;
141
142 serio_set_drvdata(serio, iforce);
143
144 err = serio_open(serio, drv);
145 if (err) {
146 serio_set_drvdata(serio, NULL);
147 kfree(iforce);
148 return err;
149 }
150
151 if (iforce_init_device(iforce)) {
152 serio_close(serio);
153 serio_set_drvdata(serio, NULL);
154 kfree(iforce);
155 return -ENODEV;
156 }
157
158 return 0;
159}
160
161static void iforce_serio_disconnect(struct serio *serio)
162{
163 struct iforce *iforce = serio_get_drvdata(serio);
164
165 input_unregister_device(&iforce->dev);
166 serio_close(serio);
167 serio_set_drvdata(serio, NULL);
168 kfree(iforce);
169}
170
171static struct serio_device_id iforce_serio_ids[] = {
172 {
173 .type = SERIO_RS232,
174 .proto = SERIO_IFORCE,
175 .id = SERIO_ANY,
176 .extra = SERIO_ANY,
177 },
178 { 0 }
179};
180
181MODULE_DEVICE_TABLE(serio, iforce_serio_ids);
182
183struct serio_driver iforce_serio_drv = {
184 .driver = {
185 .name = "iforce",
186 },
187 .description = "RS232 I-Force joysticks and wheels driver",
188 .id_table = iforce_serio_ids,
189 .write_wakeup = iforce_serio_write_wakeup,
190 .interrupt = iforce_serio_irq,
191 .connect = iforce_serio_connect,
192 .disconnect = iforce_serio_disconnect,
193};
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
new file mode 100644
index 000000000000..617c0b0e5a39
--- /dev/null
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -0,0 +1,243 @@
1 /*
2 * $Id: iforce-usb.c,v 1.16 2002/06/09 11:08:04 jdeneux Exp $
3 *
4 * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
5 * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
6 *
7 * USB/RS232 I-Force joysticks and wheels.
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * Should you need to contact me, the author, you can do so either by
26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
28 */
29
30#include "iforce.h"
31
32void iforce_usb_xmit(struct iforce *iforce)
33{
34 int n, c;
35 unsigned long flags;
36
37 spin_lock_irqsave(&iforce->xmit_lock, flags);
38
39 if (iforce->xmit.head == iforce->xmit.tail) {
40 clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
41 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
42 return;
43 }
44
45 ((char *)iforce->out->transfer_buffer)[0] = iforce->xmit.buf[iforce->xmit.tail];
46 XMIT_INC(iforce->xmit.tail, 1);
47 n = iforce->xmit.buf[iforce->xmit.tail];
48 XMIT_INC(iforce->xmit.tail, 1);
49
50 iforce->out->transfer_buffer_length = n + 1;
51 iforce->out->dev = iforce->usbdev;
52
53 /* Copy rest of data then */
54 c = CIRC_CNT_TO_END(iforce->xmit.head, iforce->xmit.tail, XMIT_SIZE);
55 if (n < c) c=n;
56
57 memcpy(iforce->out->transfer_buffer + 1,
58 &iforce->xmit.buf[iforce->xmit.tail],
59 c);
60 if (n != c) {
61 memcpy(iforce->out->transfer_buffer + 1 + c,
62 &iforce->xmit.buf[0],
63 n-c);
64 }
65 XMIT_INC(iforce->xmit.tail, n);
66
67 if ( (n=usb_submit_urb(iforce->out, GFP_ATOMIC)) ) {
68 printk(KERN_WARNING "iforce-usb.c: iforce_usb_xmit: usb_submit_urb failed %d\n", n);
69 }
70
71 /* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
72 * As long as the urb completion handler is not called, the transmiting
73 * is considered to be running */
74 spin_unlock_irqrestore(&iforce->xmit_lock, flags);
75}
76
77static void iforce_usb_irq(struct urb *urb, struct pt_regs *regs)
78{
79 struct iforce *iforce = urb->context;
80 int status;
81
82 switch (urb->status) {
83 case 0:
84 /* success */
85 break;
86 case -ECONNRESET:
87 case -ENOENT:
88 case -ESHUTDOWN:
89 /* this urb is terminated, clean up */
90 dbg("%s - urb shutting down with status: %d",
91 __FUNCTION__, urb->status);
92 return;
93 default:
94 dbg("%s - urb has status of: %d", __FUNCTION__, urb->status);
95 goto exit;
96 }
97
98 iforce_process_packet(iforce,
99 (iforce->data[0] << 8) | (urb->actual_length - 1), iforce->data + 1, regs);
100
101exit:
102 status = usb_submit_urb (urb, GFP_ATOMIC);
103 if (status)
104 err ("%s - usb_submit_urb failed with result %d",
105 __FUNCTION__, status);
106}
107
108static void iforce_usb_out(struct urb *urb, struct pt_regs *regs)
109{
110 struct iforce *iforce = urb->context;
111
112 if (urb->status) {
113 printk(KERN_DEBUG "iforce_usb_out: urb->status %d, exiting", urb->status);
114 return;
115 }
116
117 iforce_usb_xmit(iforce);
118
119 wake_up(&iforce->wait);
120}
121
122static void iforce_usb_ctrl(struct urb *urb, struct pt_regs *regs)
123{
124 struct iforce *iforce = urb->context;
125 if (urb->status) return;
126 iforce->ecmd = 0xff00 | urb->actual_length;
127 wake_up(&iforce->wait);
128}
129
130static int iforce_usb_probe(struct usb_interface *intf,
131 const struct usb_device_id *id)
132{
133 struct usb_device *dev = interface_to_usbdev(intf);
134 struct usb_host_interface *interface;
135 struct usb_endpoint_descriptor *epirq, *epout;
136 struct iforce *iforce;
137
138 interface = intf->cur_altsetting;
139
140 epirq = &interface->endpoint[0].desc;
141 epout = &interface->endpoint[1].desc;
142
143 if (!(iforce = kmalloc(sizeof(struct iforce) + 32, GFP_KERNEL)))
144 goto fail;
145
146 memset(iforce, 0, sizeof(struct iforce));
147
148 if (!(iforce->irq = usb_alloc_urb(0, GFP_KERNEL))) {
149 goto fail;
150 }
151
152 if (!(iforce->out = usb_alloc_urb(0, GFP_KERNEL))) {
153 goto fail;
154 }
155
156 if (!(iforce->ctrl = usb_alloc_urb(0, GFP_KERNEL))) {
157 goto fail;
158 }
159
160 iforce->bus = IFORCE_USB;
161 iforce->usbdev = dev;
162
163 iforce->cr.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_INTERFACE;
164 iforce->cr.wIndex = 0;
165 iforce->cr.wLength = 16;
166
167 usb_fill_int_urb(iforce->irq, dev, usb_rcvintpipe(dev, epirq->bEndpointAddress),
168 iforce->data, 16, iforce_usb_irq, iforce, epirq->bInterval);
169
170 usb_fill_bulk_urb(iforce->out, dev, usb_sndbulkpipe(dev, epout->bEndpointAddress),
171 iforce + 1, 32, iforce_usb_out, iforce);
172
173 usb_fill_control_urb(iforce->ctrl, dev, usb_rcvctrlpipe(dev, 0),
174 (void*) &iforce->cr, iforce->edata, 16, iforce_usb_ctrl, iforce);
175
176 if (iforce_init_device(iforce)) goto fail;
177
178 usb_set_intfdata(intf, iforce);
179 return 0;
180
181fail:
182 if (iforce) {
183 if (iforce->irq) usb_free_urb(iforce->irq);
184 if (iforce->out) usb_free_urb(iforce->out);
185 if (iforce->ctrl) usb_free_urb(iforce->ctrl);
186 kfree(iforce);
187 }
188
189 return -ENODEV;
190}
191
192/* Called by iforce_delete() */
193void iforce_usb_delete(struct iforce* iforce)
194{
195 usb_unlink_urb(iforce->irq);
196/* Is it ok to unlink those ? */
197 usb_unlink_urb(iforce->out);
198 usb_unlink_urb(iforce->ctrl);
199
200 usb_free_urb(iforce->irq);
201 usb_free_urb(iforce->out);
202 usb_free_urb(iforce->ctrl);
203}
204
205static void iforce_usb_disconnect(struct usb_interface *intf)
206{
207 struct iforce *iforce = usb_get_intfdata(intf);
208 int open = 0; /* FIXME! iforce->dev.handle->open; */
209
210 usb_set_intfdata(intf, NULL);
211 if (iforce) {
212 iforce->usbdev = NULL;
213 input_unregister_device(&iforce->dev);
214
215 if (!open) {
216 iforce_delete_device(iforce);
217 kfree(iforce);
218 }
219 }
220}
221
222static struct usb_device_id iforce_usb_ids [] = {
223 { USB_DEVICE(0x044f, 0xa01c) }, /* Thrustmaster Motor Sport GT */
224 { USB_DEVICE(0x046d, 0xc281) }, /* Logitech WingMan Force */
225 { USB_DEVICE(0x046d, 0xc291) }, /* Logitech WingMan Formula Force */
226 { USB_DEVICE(0x05ef, 0x020a) }, /* AVB Top Shot Pegasus */
227 { USB_DEVICE(0x05ef, 0x8884) }, /* AVB Mag Turbo Force */
228 { USB_DEVICE(0x05ef, 0x8888) }, /* AVB Top Shot FFB Racing Wheel */
229 { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */
230 { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */
231 { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */
232 { } /* Terminating entry */
233};
234
235MODULE_DEVICE_TABLE (usb, iforce_usb_ids);
236
237struct usb_driver iforce_usb_driver = {
238 .owner = THIS_MODULE,
239 .name = "iforce",
240 .probe = iforce_usb_probe,
241 .disconnect = iforce_usb_disconnect,
242 .id_table = iforce_usb_ids,
243};
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h
new file mode 100644
index 000000000000..bce247bc300b
--- /dev/null
+++ b/drivers/input/joystick/iforce/iforce.h
@@ -0,0 +1,191 @@
1/*
2 * $Id: iforce.h,v 1.13 2002/07/07 10:22:50 jdeneux Exp $
3 *
4 * Copyright (c) 2000-2002 Vojtech Pavlik <vojtech@ucw.cz>
5 * Copyright (c) 2001-2002 Johann Deneux <deneux@ifrance.com>
6 *
7 * USB/RS232 I-Force joysticks and wheels.
8 */
9
10/*
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * Should you need to contact me, the author, you can do so either by
26 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
27 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
28 */
29
30#include <linux/kernel.h>
31#include <linux/slab.h>
32#include <linux/input.h>
33#include <linux/module.h>
34#include <linux/init.h>
35#include <linux/spinlock.h>
36#include <linux/usb.h>
37#include <linux/serio.h>
38#include <linux/config.h>
39#include <linux/circ_buf.h>
40#include <asm/semaphore.h>
41
42/* This module provides arbitrary resource management routines.
43 * I use it to manage the device's memory.
44 * Despite the name of this module, I am *not* going to access the ioports.
45 */
46#include <linux/ioport.h>
47
48#define IFORCE_MAX_LENGTH 16
49
50/* iforce::bus */
51#define IFORCE_232 1
52#define IFORCE_USB 2
53
54#define FALSE 0
55#define TRUE 1
56
57#define FF_EFFECTS_MAX 32
58
59/* Each force feedback effect is made of one core effect, which can be
60 * associated to at most to effect modifiers
61 */
62#define FF_MOD1_IS_USED 0
63#define FF_MOD2_IS_USED 1
64#define FF_CORE_IS_USED 2
65#define FF_CORE_IS_PLAYED 3 /* Effect is currently being played */
66#define FF_CORE_SHOULD_PLAY 4 /* User wants the effect to be played */
67#define FF_CORE_UPDATE 5 /* Effect is being updated */
68#define FF_MODCORE_MAX 5
69
70#define CHECK_OWNERSHIP(i, iforce) \
71 ((i) < FF_EFFECTS_MAX && i >= 0 && \
72 test_bit(FF_CORE_IS_USED, (iforce)->core_effects[(i)].flags) && \
73 (current->pid == 0 || \
74 (iforce)->core_effects[(i)].owner == current->pid))
75
76struct iforce_core_effect {
77 /* Information about where modifiers are stored in the device's memory */
78 struct resource mod1_chunk;
79 struct resource mod2_chunk;
80 unsigned long flags[NBITS(FF_MODCORE_MAX)];
81 pid_t owner;
82 /* Used to keep track of parameters of an effect. They are needed
83 * to know what parts of an effect changed in an update operation.
84 * We try to send only parameter packets if possible, as sending
85 * effect parameter requires the effect to be stoped and restarted
86 */
87 struct ff_effect effect;
88};
89
90#define FF_CMD_EFFECT 0x010e
91#define FF_CMD_ENVELOPE 0x0208
92#define FF_CMD_MAGNITUDE 0x0303
93#define FF_CMD_PERIOD 0x0407
94#define FF_CMD_CONDITION 0x050a
95
96#define FF_CMD_AUTOCENTER 0x4002
97#define FF_CMD_PLAY 0x4103
98#define FF_CMD_ENABLE 0x4201
99#define FF_CMD_GAIN 0x4301
100
101#define FF_CMD_QUERY 0xff01
102
103/* Buffer for async write */
104#define XMIT_SIZE 256
105#define XMIT_INC(var, n) (var)+=n; (var)&= XMIT_SIZE -1
106/* iforce::xmit_flags */
107#define IFORCE_XMIT_RUNNING 0
108#define IFORCE_XMIT_AGAIN 1
109
110struct iforce_device {
111 u16 idvendor;
112 u16 idproduct;
113 char *name;
114 signed short *btn;
115 signed short *abs;
116 signed short *ff;
117};
118
119struct iforce {
120 struct input_dev dev; /* Input device interface */
121 struct iforce_device *type;
122 int bus;
123
124 unsigned char data[IFORCE_MAX_LENGTH];
125 unsigned char edata[IFORCE_MAX_LENGTH];
126 u16 ecmd;
127 u16 expect_packet;
128
129#ifdef CONFIG_JOYSTICK_IFORCE_232
130 struct serio *serio; /* RS232 transfer */
131 int idx, pkt, len, id;
132 unsigned char csum;
133#endif
134#ifdef CONFIG_JOYSTICK_IFORCE_USB
135 struct usb_device *usbdev; /* USB transfer */
136 struct urb *irq, *out, *ctrl;
137 struct usb_ctrlrequest cr;
138#endif
139 spinlock_t xmit_lock;
140 /* Buffer used for asynchronous sending of bytes to the device */
141 struct circ_buf xmit;
142 unsigned char xmit_data[XMIT_SIZE];
143 long xmit_flags[1];
144
145 /* Force Feedback */
146 wait_queue_head_t wait;
147 struct resource device_memory;
148 struct iforce_core_effect core_effects[FF_EFFECTS_MAX];
149 struct semaphore mem_mutex;
150};
151
152/* Get hi and low bytes of a 16-bits int */
153#define HI(a) ((unsigned char)((a) >> 8))
154#define LO(a) ((unsigned char)((a) & 0xff))
155
156/* For many parameters, it seems that 0x80 is a special value that should
157 * be avoided. Instead, we replace this value by 0x7f
158 */
159#define HIFIX80(a) ((unsigned char)(((a)<0? (a)+255 : (a))>>8))
160
161/* Encode a time value */
162#define TIME_SCALE(a) (a)
163
164
165/* Public functions */
166/* iforce-serio.c */
167void iforce_serial_xmit(struct iforce *iforce);
168
169/* iforce-usb.c */
170void iforce_usb_xmit(struct iforce *iforce);
171void iforce_usb_delete(struct iforce *iforce);
172
173/* iforce-main.c */
174int iforce_init_device(struct iforce *iforce);
175void iforce_delete_device(struct iforce *iforce);
176
177/* iforce-packets.c */
178int iforce_control_playback(struct iforce*, u16 id, unsigned int);
179void iforce_process_packet(struct iforce *iforce, u16 cmd, unsigned char *data, struct pt_regs *regs);
180int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data);
181void iforce_dump_packet(char *msg, u16 cmd, unsigned char *data) ;
182int iforce_get_id_packet(struct iforce *iforce, char *packet);
183
184/* iforce-ff.c */
185int iforce_upload_periodic(struct iforce*, struct ff_effect*, int is_update);
186int iforce_upload_constant(struct iforce*, struct ff_effect*, int is_update);
187int iforce_upload_condition(struct iforce*, struct ff_effect*, int is_update);
188
189/* Public variables */
190extern struct serio_driver iforce_serio_drv;
191extern struct usb_driver iforce_usb_driver;
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
new file mode 100644
index 000000000000..9d3f8c38cb09
--- /dev/null
+++ b/drivers/input/joystick/interact.c
@@ -0,0 +1,322 @@
1/*
2 * $Id: interact.c,v 1.16 2002/01/22 20:28:25 vojtech Exp $
3 *
4 * Copyright (c) 2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Toby Deshane
8 */
9
10/*
11 * InterAct digital gamepad/joystick driver for Linux
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/kernel.h>
35#include <linux/slab.h>
36#include <linux/module.h>
37#include <linux/delay.h>
38#include <linux/init.h>
39#include <linux/gameport.h>
40#include <linux/input.h>
41
42#define DRIVER_DESC "InterAct digital joystick driver"
43
44MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
45MODULE_DESCRIPTION(DRIVER_DESC);
46MODULE_LICENSE("GPL");
47
48#define INTERACT_MAX_START 600 /* 400 us */
49#define INTERACT_MAX_STROBE 60 /* 40 us */
50#define INTERACT_MAX_LENGTH 32 /* 32 bits */
51
52#define INTERACT_TYPE_HHFX 0 /* HammerHead/FX */
53#define INTERACT_TYPE_PP8D 1 /* ProPad 8 */
54
55struct interact {
56 struct gameport *gameport;
57 struct input_dev dev;
58 int bads;
59 int reads;
60 unsigned char type;
61 unsigned char length;
62 char phys[32];
63};
64
65static short interact_abs_hhfx[] =
66 { ABS_RX, ABS_RY, ABS_X, ABS_Y, ABS_HAT0X, ABS_HAT0Y, -1 };
67static short interact_abs_pp8d[] =
68 { ABS_X, ABS_Y, -1 };
69
70static short interact_btn_hhfx[] =
71 { 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 };
72static short interact_btn_pp8d[] =
73 { BTN_C, BTN_TL, BTN_TR, BTN_A, BTN_B, BTN_Y, BTN_Z, BTN_X, -1 };
74
75struct interact_type {
76 int id;
77 short *abs;
78 short *btn;
79 char *name;
80 unsigned char length;
81 unsigned char b8;
82};
83
84static struct interact_type interact_type[] = {
85 { 0x6202, interact_abs_hhfx, interact_btn_hhfx, "InterAct HammerHead/FX", 32, 4 },
86 { 0x53f8, interact_abs_pp8d, interact_btn_pp8d, "InterAct ProPad 8 Digital", 16, 0 },
87 { 0 }};
88
89/*
90 * interact_read_packet() reads and InterAct joystick data.
91 */
92
93static int interact_read_packet(struct gameport *gameport, int length, u32 *data)
94{
95 unsigned long flags;
96 unsigned char u, v;
97 unsigned int t, s;
98 int i;
99
100 i = 0;
101 data[0] = data[1] = data[2] = 0;
102 t = gameport_time(gameport, INTERACT_MAX_START);
103 s = gameport_time(gameport, INTERACT_MAX_STROBE);
104
105 local_irq_save(flags);
106 gameport_trigger(gameport);
107 v = gameport_read(gameport);
108
109 while (t > 0 && i < length) {
110 t--;
111 u = v; v = gameport_read(gameport);
112 if (v & ~u & 0x40) {
113 data[0] = (data[0] << 1) | ((v >> 4) & 1);
114 data[1] = (data[1] << 1) | ((v >> 5) & 1);
115 data[2] = (data[2] << 1) | ((v >> 7) & 1);
116 i++;
117 t = s;
118 }
119 }
120
121 local_irq_restore(flags);
122
123 return i;
124}
125
126/*
127 * interact_poll() reads and analyzes InterAct joystick data.
128 */
129
130static void interact_poll(struct gameport *gameport)
131{
132 struct interact *interact = gameport_get_drvdata(gameport);
133 struct input_dev *dev = &interact->dev;
134 u32 data[3];
135 int i;
136
137 interact->reads++;
138
139 if (interact_read_packet(interact->gameport, interact->length, data) < interact->length) {
140 interact->bads++;
141 } else {
142
143 for (i = 0; i < 3; i++)
144 data[i] <<= INTERACT_MAX_LENGTH - interact->length;
145
146 switch (interact->type) {
147
148 case INTERACT_TYPE_HHFX:
149
150 for (i = 0; i < 4; i++)
151 input_report_abs(dev, interact_abs_hhfx[i], (data[i & 1] >> ((i >> 1) << 3)) & 0xff);
152
153 for (i = 0; i < 2; i++)
154 input_report_abs(dev, ABS_HAT0Y - i,
155 ((data[1] >> ((i << 1) + 17)) & 1) - ((data[1] >> ((i << 1) + 16)) & 1));
156
157 for (i = 0; i < 8; i++)
158 input_report_key(dev, interact_btn_hhfx[i], (data[0] >> (i + 16)) & 1);
159
160 for (i = 0; i < 4; i++)
161 input_report_key(dev, interact_btn_hhfx[i + 8], (data[1] >> (i + 20)) & 1);
162
163 break;
164
165 case INTERACT_TYPE_PP8D:
166
167 for (i = 0; i < 2; i++)
168 input_report_abs(dev, interact_abs_pp8d[i],
169 ((data[0] >> ((i << 1) + 20)) & 1) - ((data[0] >> ((i << 1) + 21)) & 1));
170
171 for (i = 0; i < 8; i++)
172 input_report_key(dev, interact_btn_pp8d[i], (data[1] >> (i + 16)) & 1);
173
174 break;
175 }
176 }
177
178 input_sync(dev);
179}
180
181/*
182 * interact_open() is a callback from the input open routine.
183 */
184
185static int interact_open(struct input_dev *dev)
186{
187 struct interact *interact = dev->private;
188
189 gameport_start_polling(interact->gameport);
190 return 0;
191}
192
193/*
194 * interact_close() is a callback from the input close routine.
195 */
196
197static void interact_close(struct input_dev *dev)
198{
199 struct interact *interact = dev->private;
200
201 gameport_stop_polling(interact->gameport);
202}
203
204/*
205 * interact_connect() probes for InterAct joysticks.
206 */
207
208static int interact_connect(struct gameport *gameport, struct gameport_driver *drv)
209{
210 struct interact *interact;
211 __u32 data[3];
212 int i, t;
213 int err;
214
215 if (!(interact = kcalloc(1, sizeof(struct interact), GFP_KERNEL)))
216 return -ENOMEM;
217
218 interact->gameport = gameport;
219
220 gameport_set_drvdata(gameport, interact);
221
222 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
223 if (err)
224 goto fail1;
225
226 i = interact_read_packet(gameport, INTERACT_MAX_LENGTH * 2, data);
227
228 if (i != 32 || (data[0] >> 24) != 0x0c || (data[1] >> 24) != 0x02) {
229 err = -ENODEV;
230 goto fail2;
231 }
232
233 for (i = 0; interact_type[i].length; i++)
234 if (interact_type[i].id == (data[2] >> 16))
235 break;
236
237 if (!interact_type[i].length) {
238 printk(KERN_WARNING "interact.c: Unknown joystick on %s. [len %d d0 %08x d1 %08x i2 %08x]\n",
239 gameport->phys, i, data[0], data[1], data[2]);
240 err = -ENODEV;
241 goto fail2;
242 }
243
244 gameport_set_poll_handler(gameport, interact_poll);
245 gameport_set_poll_interval(gameport, 20);
246
247 sprintf(interact->phys, "%s/input0", gameport->phys);
248
249 interact->type = i;
250 interact->length = interact_type[i].length;
251
252 interact->dev.private = interact;
253 interact->dev.open = interact_open;
254 interact->dev.close = interact_close;
255
256 interact->dev.name = interact_type[i].name;
257 interact->dev.phys = interact->phys;
258 interact->dev.id.bustype = BUS_GAMEPORT;
259 interact->dev.id.vendor = GAMEPORT_ID_VENDOR_INTERACT;
260 interact->dev.id.product = interact_type[i].id;
261 interact->dev.id.version = 0x0100;
262
263 interact->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
264
265 for (i = 0; (t = interact_type[interact->type].abs[i]) >= 0; i++) {
266 set_bit(t, interact->dev.absbit);
267 if (i < interact_type[interact->type].b8) {
268 interact->dev.absmin[t] = 0;
269 interact->dev.absmax[t] = 255;
270 } else {
271 interact->dev.absmin[t] = -1;
272 interact->dev.absmax[t] = 1;
273 }
274 }
275
276 for (i = 0; (t = interact_type[interact->type].btn[i]) >= 0; i++)
277 set_bit(t, interact->dev.keybit);
278
279 input_register_device(&interact->dev);
280 printk(KERN_INFO "input: %s on %s\n",
281 interact_type[interact->type].name, gameport->phys);
282
283 return 0;
284
285fail2: gameport_close(gameport);
286fail1: gameport_set_drvdata(gameport, NULL);
287 kfree(interact);
288 return err;
289}
290
291static void interact_disconnect(struct gameport *gameport)
292{
293 struct interact *interact = gameport_get_drvdata(gameport);
294
295 input_unregister_device(&interact->dev);
296 gameport_close(gameport);
297 gameport_set_drvdata(gameport, NULL);
298 kfree(interact);
299}
300
301static struct gameport_driver interact_drv = {
302 .driver = {
303 .name = "interact",
304 },
305 .description = DRIVER_DESC,
306 .connect = interact_connect,
307 .disconnect = interact_disconnect,
308};
309
310static int __init interact_init(void)
311{
312 gameport_register_driver(&interact_drv);
313 return 0;
314}
315
316static void __exit interact_exit(void)
317{
318 gameport_unregister_driver(&interact_drv);
319}
320
321module_init(interact_init);
322module_exit(interact_exit);
diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c
new file mode 100644
index 000000000000..4234ccaf9146
--- /dev/null
+++ b/drivers/input/joystick/joydump.c
@@ -0,0 +1,175 @@
1/*
2 * $Id: joydump.c,v 1.1 2002/01/23 06:56:16 jsimmons Exp $
3 *
4 * Copyright (c) 1996-2001 Vojtech Pavlik
5 */
6
7/*
8 * This is just a very simple driver that can dump the data
9 * out of the joystick port into the syslog ...
10 */
11
12/*
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 * Should you need to contact me, the author, you can do so either by
28 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
29 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
30 */
31
32#include <linux/module.h>
33#include <linux/gameport.h>
34#include <linux/kernel.h>
35#include <linux/delay.h>
36#include <linux/init.h>
37
38#define DRIVER_DESC "Gameport data dumper module"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44#define BUF_SIZE 256
45
46struct joydump {
47 unsigned int time;
48 unsigned char data;
49};
50
51static int joydump_connect(struct gameport *gameport, struct gameport_driver *drv)
52{
53 struct joydump *buf; /* all entries */
54 struct joydump *dump, *prev; /* one entry each */
55 int axes[4], buttons;
56 int i, j, t, timeout;
57 unsigned long flags;
58 unsigned char u;
59
60 printk(KERN_INFO "joydump: ,------------------ START ----------------.\n");
61 printk(KERN_INFO "joydump: | Dumping: %30s |\n", gameport->phys);
62 printk(KERN_INFO "joydump: | Speed: %28d kHz |\n", gameport->speed);
63
64 if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {
65
66 printk(KERN_INFO "joydump: | Raw mode not available - trying cooked. |\n");
67
68 if (gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) {
69
70 printk(KERN_INFO "joydump: | Cooked not available either. Failing. |\n");
71 printk(KERN_INFO "joydump: `------------------- END -----------------'\n");
72 return -ENODEV;
73 }
74
75 gameport_cooked_read(gameport, axes, &buttons);
76
77 for (i = 0; i < 4; i++)
78 printk(KERN_INFO "joydump: | Axis %d: %4d. |\n", i, axes[i]);
79 printk(KERN_INFO "joydump: | Buttons %02x. |\n", buttons);
80 printk(KERN_INFO "joydump: `------------------- END -----------------'\n");
81 }
82
83 timeout = gameport_time(gameport, 10000); /* 10 ms */
84
85 buf = kmalloc(BUF_SIZE * sizeof(struct joydump), GFP_KERNEL);
86 if (!buf) {
87 printk(KERN_INFO "joydump: no memory for testing\n");
88 goto jd_end;
89 }
90 dump = buf;
91 t = 0;
92 i = 1;
93
94 local_irq_save(flags);
95
96 u = gameport_read(gameport);
97
98 dump->data = u;
99 dump->time = t;
100 dump++;
101
102 gameport_trigger(gameport);
103
104 while (i < BUF_SIZE && t < timeout) {
105
106 dump->data = gameport_read(gameport);
107
108 if (dump->data ^ u) {
109 u = dump->data;
110 dump->time = t;
111 i++;
112 dump++;
113 }
114 t++;
115 }
116
117 local_irq_restore(flags);
118
119/*
120 * Dump data.
121 */
122
123 t = i;
124 dump = buf;
125 prev = dump;
126
127 printk(KERN_INFO "joydump: >------------------ DATA -----------------<\n");
128 printk(KERN_INFO "joydump: | index: %3d delta: %3d us data: ", 0, 0);
129 for (j = 7; j >= 0; j--)
130 printk("%d", (dump->data >> j) & 1);
131 printk(" |\n");
132 dump++;
133
134 for (i = 1; i < t; i++, dump++, prev++) {
135 printk(KERN_INFO "joydump: | index: %3d delta: %3d us data: ",
136 i, dump->time - prev->time);
137 for (j = 7; j >= 0; j--)
138 printk("%d", (dump->data >> j) & 1);
139 printk(" |\n");
140 }
141 kfree(buf);
142
143jd_end:
144 printk(KERN_INFO "joydump: `------------------- END -----------------'\n");
145
146 return 0;
147}
148
149static void joydump_disconnect(struct gameport *gameport)
150{
151 gameport_close(gameport);
152}
153
154static struct gameport_driver joydump_drv = {
155 .driver = {
156 .name = "joydump",
157 },
158 .description = DRIVER_DESC,
159 .connect = joydump_connect,
160 .disconnect = joydump_disconnect,
161};
162
163static int __init joydump_init(void)
164{
165 gameport_register_driver(&joydump_drv);
166 return 0;
167}
168
169static void __exit joydump_exit(void)
170{
171 gameport_unregister_driver(&joydump_drv);
172}
173
174module_init(joydump_init);
175module_exit(joydump_exit);
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
new file mode 100644
index 000000000000..1ba503627242
--- /dev/null
+++ b/drivers/input/joystick/magellan.c
@@ -0,0 +1,247 @@
1/*
2 * $Id: magellan.c,v 1.16 2002/01/22 20:28:39 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
6
7/*
8 * Magellan and Space Mouse 6dof controller driver for Linux
9 */
10
11/*
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/slab.h>
34#include <linux/input.h>
35#include <linux/serio.h>
36#include <linux/init.h>
37
38#define DRIVER_DESC "Magellan and SpaceMouse 6dof controller driver"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44/*
45 * Definitions & global arrays.
46 */
47
48#define MAGELLAN_MAX_LENGTH 32
49
50static int magellan_buttons[] = { BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 };
51static int magellan_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
52static char *magellan_name = "LogiCad3D Magellan / SpaceMouse";
53
54/*
55 * Per-Magellan data.
56 */
57
58struct magellan {
59 struct input_dev dev;
60 int idx;
61 unsigned char data[MAGELLAN_MAX_LENGTH];
62 char phys[32];
63};
64
65/*
66 * magellan_crunch_nibbles() verifies that the bytes sent from the Magellan
67 * have correct upper nibbles for the lower ones, if not, the packet will
68 * be thrown away. It also strips these upper halves to simplify further
69 * processing.
70 */
71
72static int magellan_crunch_nibbles(unsigned char *data, int count)
73{
74 static unsigned char nibbles[16] = "0AB3D56GH9:K<MN?";
75
76 do {
77 if (data[count] == nibbles[data[count] & 0xf])
78 data[count] = data[count] & 0xf;
79 else
80 return -1;
81 } while (--count);
82
83 return 0;
84}
85
86static void magellan_process_packet(struct magellan* magellan, struct pt_regs *regs)
87{
88 struct input_dev *dev = &magellan->dev;
89 unsigned char *data = magellan->data;
90 int i, t;
91
92 if (!magellan->idx) return;
93
94 input_regs(dev, regs);
95
96 switch (magellan->data[0]) {
97
98 case 'd': /* Axis data */
99 if (magellan->idx != 25) return;
100 if (magellan_crunch_nibbles(data, 24)) return;
101 for (i = 0; i < 6; i++)
102 input_report_abs(dev, magellan_axes[i],
103 (data[(i << 2) + 1] << 12 | data[(i << 2) + 2] << 8 |
104 data[(i << 2) + 3] << 4 | data[(i << 2) + 4]) - 32768);
105 break;
106
107 case 'k': /* Button data */
108 if (magellan->idx != 4) return;
109 if (magellan_crunch_nibbles(data, 3)) return;
110 t = (data[1] << 1) | (data[2] << 5) | data[3];
111 for (i = 0; i < 9; i++) input_report_key(dev, magellan_buttons[i], (t >> i) & 1);
112 break;
113 }
114
115 input_sync(dev);
116}
117
118static irqreturn_t magellan_interrupt(struct serio *serio,
119 unsigned char data, unsigned int flags, struct pt_regs *regs)
120{
121 struct magellan* magellan = serio_get_drvdata(serio);
122
123 if (data == '\r') {
124 magellan_process_packet(magellan, regs);
125 magellan->idx = 0;
126 } else {
127 if (magellan->idx < MAGELLAN_MAX_LENGTH)
128 magellan->data[magellan->idx++] = data;
129 }
130 return IRQ_HANDLED;
131}
132
133/*
134 * magellan_disconnect() is the opposite of magellan_connect()
135 */
136
137static void magellan_disconnect(struct serio *serio)
138{
139 struct magellan* magellan = serio_get_drvdata(serio);
140
141 input_unregister_device(&magellan->dev);
142 serio_close(serio);
143 serio_set_drvdata(serio, NULL);
144 kfree(magellan);
145}
146
147/*
148 * magellan_connect() is the routine that is called when someone adds a
149 * new serio device that supports Magellan protocol and registers it as
150 * an input device.
151 */
152
153static int magellan_connect(struct serio *serio, struct serio_driver *drv)
154{
155 struct magellan *magellan;
156 int i, t;
157 int err;
158
159 if (!(magellan = kmalloc(sizeof(struct magellan), GFP_KERNEL)))
160 return -ENOMEM;
161
162 memset(magellan, 0, sizeof(struct magellan));
163
164 magellan->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
165
166 for (i = 0; i < 9; i++)
167 set_bit(magellan_buttons[i], magellan->dev.keybit);
168
169 for (i = 0; i < 6; i++) {
170 t = magellan_axes[i];
171 set_bit(t, magellan->dev.absbit);
172 magellan->dev.absmin[t] = -360;
173 magellan->dev.absmax[t] = 360;
174 }
175
176 sprintf(magellan->phys, "%s/input0", serio->phys);
177
178 init_input_dev(&magellan->dev);
179 magellan->dev.private = magellan;
180 magellan->dev.name = magellan_name;
181 magellan->dev.phys = magellan->phys;
182 magellan->dev.id.bustype = BUS_RS232;
183 magellan->dev.id.vendor = SERIO_MAGELLAN;
184 magellan->dev.id.product = 0x0001;
185 magellan->dev.id.version = 0x0100;
186 magellan->dev.dev = &serio->dev;
187
188 serio_set_drvdata(serio, magellan);
189
190 err = serio_open(serio, drv);
191 if (err) {
192 serio_set_drvdata(serio, NULL);
193 kfree(magellan);
194 return err;
195 }
196
197 input_register_device(&magellan->dev);
198
199 printk(KERN_INFO "input: %s on %s\n", magellan_name, serio->phys);
200
201 return 0;
202}
203
204/*
205 * The serio driver structure.
206 */
207
208static struct serio_device_id magellan_serio_ids[] = {
209 {
210 .type = SERIO_RS232,
211 .proto = SERIO_MAGELLAN,
212 .id = SERIO_ANY,
213 .extra = SERIO_ANY,
214 },
215 { 0 }
216};
217
218MODULE_DEVICE_TABLE(serio, magellan_serio_ids);
219
220static struct serio_driver magellan_drv = {
221 .driver = {
222 .name = "magellan",
223 },
224 .description = DRIVER_DESC,
225 .id_table = magellan_serio_ids,
226 .interrupt = magellan_interrupt,
227 .connect = magellan_connect,
228 .disconnect = magellan_disconnect,
229};
230
231/*
232 * The functions for inserting/removing us as a module.
233 */
234
235static int __init magellan_init(void)
236{
237 serio_register_driver(&magellan_drv);
238 return 0;
239}
240
241static void __exit magellan_exit(void)
242{
243 serio_unregister_driver(&magellan_drv);
244}
245
246module_init(magellan_init);
247module_exit(magellan_exit);
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
new file mode 100644
index 000000000000..47144a7ed9e7
--- /dev/null
+++ b/drivers/input/joystick/sidewinder.c
@@ -0,0 +1,807 @@
1/*
2 * Copyright (c) 1998-2005 Vojtech Pavlik
3 */
4
5/*
6 * Microsoft SideWinder joystick family driver for Linux
7 */
8
9/*
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Should you need to contact me, the author, you can do so either by
25 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
26 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
27 */
28
29#include <linux/delay.h>
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/slab.h>
33#include <linux/init.h>
34#include <linux/input.h>
35#include <linux/gameport.h>
36
37#define DRIVER_DESC "Microsoft SideWinder joystick family driver"
38
39MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
40MODULE_DESCRIPTION(DRIVER_DESC);
41MODULE_LICENSE("GPL");
42
43/*
44 * These are really magic values. Changing them can make a problem go away,
45 * as well as break everything.
46 */
47
48#undef SW_DEBUG
49#undef SW_DEBUG_DATA
50
51#define SW_START 600 /* The time we wait for the first bit [600 us] */
52#define SW_STROBE 60 /* Max time per bit [60 us] */
53#define SW_TIMEOUT 6 /* Wait for everything to settle [6 ms] */
54#define SW_KICK 45 /* Wait after A0 fall till kick [45 us] */
55#define SW_END 8 /* Number of bits before end of packet to kick */
56#define SW_FAIL 16 /* Number of packet read errors to fail and reinitialize */
57#define SW_BAD 2 /* Number of packet read errors to switch off 3d Pro optimization */
58#define SW_OK 64 /* Number of packet read successes to switch optimization back on */
59#define SW_LENGTH 512 /* Max number of bits in a packet */
60
61#ifdef SW_DEBUG
62#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg)
63#else
64#define dbg(format, arg...) do {} while (0)
65#endif
66
67/*
68 * SideWinder joystick types ...
69 */
70
71#define SW_ID_3DP 0
72#define SW_ID_GP 1
73#define SW_ID_PP 2
74#define SW_ID_FFP 3
75#define SW_ID_FSP 4
76#define SW_ID_FFW 5
77
78/*
79 * Names, buttons, axes ...
80 */
81
82static char *sw_name[] = { "3D Pro", "GamePad", "Precision Pro", "Force Feedback Pro", "FreeStyle Pro",
83 "Force Feedback Wheel" };
84
85static char sw_abs[][7] = {
86 { ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
87 { ABS_X, ABS_Y },
88 { ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
89 { ABS_X, ABS_Y, ABS_RZ, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
90 { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y },
91 { ABS_RX, ABS_RUDDER, ABS_THROTTLE }};
92
93static char sw_bit[][7] = {
94 { 10, 10, 9, 10, 1, 1 },
95 { 1, 1 },
96 { 10, 10, 6, 7, 1, 1 },
97 { 10, 10, 6, 7, 1, 1 },
98 { 10, 10, 6, 1, 1 },
99 { 10, 7, 7, 1, 1 }};
100
101static short sw_btn[][12] = {
102 { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_MODE },
103 { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE },
104 { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT },
105 { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT },
106 { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT },
107 { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4 }};
108
109static struct {
110 int x;
111 int y;
112} sw_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
113
114struct sw {
115 struct gameport *gameport;
116 struct input_dev dev[4];
117 char name[64];
118 char phys[4][32];
119 int length;
120 int type;
121 int bits;
122 int number;
123 int fail;
124 int ok;
125 int reads;
126 int bads;
127};
128
129/*
130 * sw_read_packet() is a function which reads either a data packet, or an
131 * identification packet from a SideWinder joystick. The protocol is very,
132 * very, very braindamaged. Microsoft patented it in US patent #5628686.
133 */
134
135static int sw_read_packet(struct gameport *gameport, unsigned char *buf, int length, int id)
136{
137 unsigned long flags;
138 int timeout, bitout, sched, i, kick, start, strobe;
139 unsigned char pending, u, v;
140
141 i = -id; /* Don't care about data, only want ID */
142 timeout = id ? gameport_time(gameport, SW_TIMEOUT * 1000) : 0; /* Set up global timeout for ID packet */
143 kick = id ? gameport_time(gameport, SW_KICK) : 0; /* Set up kick timeout for ID packet */
144 start = gameport_time(gameport, SW_START);
145 strobe = gameport_time(gameport, SW_STROBE);
146 bitout = start;
147 pending = 0;
148 sched = 0;
149
150 local_irq_save(flags); /* Quiet, please */
151
152 gameport_trigger(gameport); /* Trigger */
153 v = gameport_read(gameport);
154
155 do {
156 bitout--;
157 u = v;
158 v = gameport_read(gameport);
159 } while (!(~v & u & 0x10) && (bitout > 0)); /* Wait for first falling edge on clock */
160
161 if (bitout > 0)
162 bitout = strobe; /* Extend time if not timed out */
163
164 while ((timeout > 0 || bitout > 0) && (i < length)) {
165
166 timeout--;
167 bitout--; /* Decrement timers */
168 sched--;
169
170 u = v;
171 v = gameport_read(gameport);
172
173 if ((~u & v & 0x10) && (bitout > 0)) { /* Rising edge on clock - data bit */
174 if (i >= 0) /* Want this data */
175 buf[i] = v >> 5; /* Store it */
176 i++; /* Advance index */
177 bitout = strobe; /* Extend timeout for next bit */
178 }
179
180 if (kick && (~v & u & 0x01)) { /* Falling edge on axis 0 */
181 sched = kick; /* Schedule second trigger */
182 kick = 0; /* Don't schedule next time on falling edge */
183 pending = 1; /* Mark schedule */
184 }
185
186 if (pending && sched < 0 && (i > -SW_END)) { /* Second trigger time */
187 gameport_trigger(gameport); /* Trigger */
188 bitout = start; /* Long bit timeout */
189 pending = 0; /* Unmark schedule */
190 timeout = 0; /* Switch from global to bit timeouts */
191 }
192 }
193
194 local_irq_restore(flags); /* Done - relax */
195
196#ifdef SW_DEBUG_DATA
197 {
198 int j;
199 printk(KERN_DEBUG "sidewinder.c: Read %d triplets. [", i);
200 for (j = 0; j < i; j++) printk("%d", buf[j]);
201 printk("]\n");
202 }
203#endif
204
205 return i;
206}
207
208/*
209 * sw_get_bits() and GB() compose bits from the triplet buffer into a __u64.
210 * Parameter 'pos' is bit number inside packet where to start at, 'num' is number
211 * of bits to be read, 'shift' is offset in the resulting __u64 to start at, bits
212 * is number of bits per triplet.
213 */
214
215#define GB(pos,num) sw_get_bits(buf, pos, num, sw->bits)
216
217static __u64 sw_get_bits(unsigned char *buf, int pos, int num, char bits)
218{
219 __u64 data = 0;
220 int tri = pos % bits; /* Start position */
221 int i = pos / bits;
222 int bit = 0;
223
224 while (num--) {
225 data |= (__u64)((buf[i] >> tri++) & 1) << bit++; /* Transfer bit */
226 if (tri == bits) {
227 i++; /* Next triplet */
228 tri = 0;
229 }
230 }
231
232 return data;
233}
234
235/*
236 * sw_init_digital() initializes a SideWinder 3D Pro joystick
237 * into digital mode.
238 */
239
240static void sw_init_digital(struct gameport *gameport)
241{
242 int seq[] = { 140, 140+725, 140+300, 0 };
243 unsigned long flags;
244 int i, t;
245
246 local_irq_save(flags);
247
248 i = 0;
249 do {
250 gameport_trigger(gameport); /* Trigger */
251 t = gameport_time(gameport, SW_TIMEOUT * 1000);
252 while ((gameport_read(gameport) & 1) && t) t--; /* Wait for axis to fall back to 0 */
253 udelay(seq[i]); /* Delay magic time */
254 } while (seq[++i]);
255
256 gameport_trigger(gameport); /* Last trigger */
257
258 local_irq_restore(flags);
259}
260
261/*
262 * sw_parity() computes parity of __u64
263 */
264
265static int sw_parity(__u64 t)
266{
267 int x = t ^ (t >> 32);
268
269 x ^= x >> 16;
270 x ^= x >> 8;
271 x ^= x >> 4;
272 x ^= x >> 2;
273 x ^= x >> 1;
274 return x & 1;
275}
276
277/*
278 * sw_ccheck() checks synchronization bits and computes checksum of nibbles.
279 */
280
281static int sw_check(__u64 t)
282{
283 unsigned char sum = 0;
284
285 if ((t & 0x8080808080808080ULL) ^ 0x80) /* Sync */
286 return -1;
287
288 while (t) { /* Sum */
289 sum += t & 0xf;
290 t >>= 4;
291 }
292
293 return sum & 0xf;
294}
295
296/*
297 * sw_parse() analyzes SideWinder joystick data, and writes the results into
298 * the axes and buttons arrays.
299 */
300
301static int sw_parse(unsigned char *buf, struct sw *sw)
302{
303 int hat, i, j;
304 struct input_dev *dev = sw->dev;
305
306 switch (sw->type) {
307
308 case SW_ID_3DP:
309
310 if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8)
311 return -1;
312
313 input_report_abs(dev, ABS_X, (GB( 3,3) << 7) | GB(16,7));
314 input_report_abs(dev, ABS_Y, (GB( 0,3) << 7) | GB(24,7));
315 input_report_abs(dev, ABS_RZ, (GB(35,2) << 7) | GB(40,7));
316 input_report_abs(dev, ABS_THROTTLE, (GB(32,3) << 7) | GB(48,7));
317
318 input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
319 input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
320
321 for (j = 0; j < 7; j++)
322 input_report_key(dev, sw_btn[SW_ID_3DP][j], !GB(j+8,1));
323
324 input_report_key(dev, BTN_BASE4, !GB(38,1));
325 input_report_key(dev, BTN_BASE5, !GB(37,1));
326
327 input_sync(dev);
328
329 return 0;
330
331 case SW_ID_GP:
332
333 for (i = 0; i < sw->number; i ++) {
334
335 if (sw_parity(GB(i*15,15)))
336 return -1;
337
338 input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
339 input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
340
341 for (j = 0; j < 10; j++)
342 input_report_key(dev + i, sw_btn[SW_ID_GP][j], !GB(i*15+j+4,1));
343
344 input_sync(dev + i);
345 }
346
347 return 0;
348
349 case SW_ID_PP:
350 case SW_ID_FFP:
351
352 if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8)
353 return -1;
354
355 input_report_abs(dev, ABS_X, GB( 9,10));
356 input_report_abs(dev, ABS_Y, GB(19,10));
357 input_report_abs(dev, ABS_RZ, GB(36, 6));
358 input_report_abs(dev, ABS_THROTTLE, GB(29, 7));
359
360 input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
361 input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
362
363 for (j = 0; j < 9; j++)
364 input_report_key(dev, sw_btn[SW_ID_PP][j], !GB(j,1));
365
366 input_sync(dev);
367
368 return 0;
369
370 case SW_ID_FSP:
371
372 if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8)
373 return -1;
374
375 input_report_abs(dev, ABS_X, GB( 0,10));
376 input_report_abs(dev, ABS_Y, GB(16,10));
377 input_report_abs(dev, ABS_THROTTLE, GB(32, 6));
378
379 input_report_abs(dev, ABS_HAT0X, sw_hat_to_axis[hat].x);
380 input_report_abs(dev, ABS_HAT0Y, sw_hat_to_axis[hat].y);
381
382 for (j = 0; j < 6; j++)
383 input_report_key(dev, sw_btn[SW_ID_FSP][j], !GB(j+10,1));
384
385 input_report_key(dev, BTN_TR, !GB(26,1));
386 input_report_key(dev, BTN_START, !GB(27,1));
387 input_report_key(dev, BTN_MODE, !GB(38,1));
388 input_report_key(dev, BTN_SELECT, !GB(39,1));
389
390 input_sync(dev);
391
392 return 0;
393
394 case SW_ID_FFW:
395
396 if (!sw_parity(GB(0,33)))
397 return -1;
398
399 input_report_abs(dev, ABS_RX, GB( 0,10));
400 input_report_abs(dev, ABS_RUDDER, GB(10, 6));
401 input_report_abs(dev, ABS_THROTTLE, GB(16, 6));
402
403 for (j = 0; j < 8; j++)
404 input_report_key(dev, sw_btn[SW_ID_FFW][j], !GB(j+22,1));
405
406 input_sync(dev);
407
408 return 0;
409 }
410
411 return -1;
412}
413
414/*
415 * sw_read() reads SideWinder joystick data, and reinitializes
416 * the joystick in case of persistent problems. This is the function that is
417 * called from the generic code to poll the joystick.
418 */
419
420static int sw_read(struct sw *sw)
421{
422 unsigned char buf[SW_LENGTH];
423 int i;
424
425 i = sw_read_packet(sw->gameport, buf, sw->length, 0);
426
427 if (sw->type == SW_ID_3DP && sw->length == 66 && i != 66) { /* Broken packet, try to fix */
428
429 if (i == 64 && !sw_check(sw_get_bits(buf,0,64,1))) { /* Last init failed, 1 bit mode */
430 printk(KERN_WARNING "sidewinder.c: Joystick in wrong mode on %s"
431 " - going to reinitialize.\n", sw->gameport->phys);
432 sw->fail = SW_FAIL; /* Reinitialize */
433 i = 128; /* Bogus value */
434 }
435
436 if (i < 66 && GB(0,64) == GB(i*3-66,64)) /* 1 == 3 */
437 i = 66; /* Everything is fine */
438
439 if (i < 66 && GB(0,64) == GB(66,64)) /* 1 == 2 */
440 i = 66; /* Everything is fine */
441
442 if (i < 66 && GB(i*3-132,64) == GB(i*3-66,64)) { /* 2 == 3 */
443 memmove(buf, buf + i - 22, 22); /* Move data */
444 i = 66; /* Carry on */
445 }
446 }
447
448 if (i == sw->length && !sw_parse(buf, sw)) { /* Parse data */
449
450 sw->fail = 0;
451 sw->ok++;
452
453 if (sw->type == SW_ID_3DP && sw->length == 66 /* Many packets OK */
454 && sw->ok > SW_OK) {
455
456 printk(KERN_INFO "sidewinder.c: No more trouble on %s"
457 " - enabling optimization again.\n", sw->gameport->phys);
458 sw->length = 22;
459 }
460
461 return 0;
462 }
463
464 sw->ok = 0;
465 sw->fail++;
466
467 if (sw->type == SW_ID_3DP && sw->length == 22 && sw->fail > SW_BAD) { /* Consecutive bad packets */
468
469 printk(KERN_INFO "sidewinder.c: Many bit errors on %s"
470 " - disabling optimization.\n", sw->gameport->phys);
471 sw->length = 66;
472 }
473
474 if (sw->fail < SW_FAIL)
475 return -1; /* Not enough, don't reinitialize yet */
476
477 printk(KERN_WARNING "sidewinder.c: Too many bit errors on %s"
478 " - reinitializing joystick.\n", sw->gameport->phys);
479
480 if (!i && sw->type == SW_ID_3DP) { /* 3D Pro can be in analog mode */
481 mdelay(3 * SW_TIMEOUT);
482 sw_init_digital(sw->gameport);
483 }
484
485 mdelay(SW_TIMEOUT);
486 i = sw_read_packet(sw->gameport, buf, SW_LENGTH, 0); /* Read normal data packet */
487 mdelay(SW_TIMEOUT);
488 sw_read_packet(sw->gameport, buf, SW_LENGTH, i); /* Read ID packet, this initializes the stick */
489
490 sw->fail = SW_FAIL;
491
492 return -1;
493}
494
495static void sw_poll(struct gameport *gameport)
496{
497 struct sw *sw = gameport_get_drvdata(gameport);
498
499 sw->reads++;
500 if (sw_read(sw))
501 sw->bads++;
502}
503
504static int sw_open(struct input_dev *dev)
505{
506 struct sw *sw = dev->private;
507
508 gameport_start_polling(sw->gameport);
509 return 0;
510}
511
512static void sw_close(struct input_dev *dev)
513{
514 struct sw *sw = dev->private;
515
516 gameport_stop_polling(sw->gameport);
517}
518
519/*
520 * sw_print_packet() prints the contents of a SideWinder packet.
521 */
522
523static void sw_print_packet(char *name, int length, unsigned char *buf, char bits)
524{
525 int i;
526
527 printk(KERN_INFO "sidewinder.c: %s packet, %d bits. [", name, length);
528 for (i = (((length + 3) >> 2) - 1); i >= 0; i--)
529 printk("%x", (int)sw_get_bits(buf, i << 2, 4, bits));
530 printk("]\n");
531}
532
533/*
534 * sw_3dp_id() translates the 3DP id into a human legible string.
535 * Unfortunately I don't know how to do this for the other SW types.
536 */
537
538static void sw_3dp_id(unsigned char *buf, char *comment)
539{
540 int i;
541 char pnp[8], rev[9];
542
543 for (i = 0; i < 7; i++) /* ASCII PnP ID */
544 pnp[i] = sw_get_bits(buf, 24+8*i, 8, 1);
545
546 for (i = 0; i < 8; i++) /* ASCII firmware revision */
547 rev[i] = sw_get_bits(buf, 88+8*i, 8, 1);
548
549 pnp[7] = rev[8] = 0;
550
551 sprintf(comment, " [PnP %d.%02d id %s rev %s]",
552 (int) ((sw_get_bits(buf, 8, 6, 1) << 6) | /* Two 6-bit values */
553 sw_get_bits(buf, 16, 6, 1)) / 100,
554 (int) ((sw_get_bits(buf, 8, 6, 1) << 6) |
555 sw_get_bits(buf, 16, 6, 1)) % 100,
556 pnp, rev);
557}
558
559/*
560 * sw_guess_mode() checks the upper two button bits for toggling -
561 * indication of that the joystick is in 3-bit mode. This is documented
562 * behavior for 3DP ID packet, and for example the FSP does this in
563 * normal packets instead. Fun ...
564 */
565
566static int sw_guess_mode(unsigned char *buf, int len)
567{
568 int i;
569 unsigned char xor = 0;
570
571 for (i = 1; i < len; i++)
572 xor |= (buf[i - 1] ^ buf[i]) & 6;
573
574 return !!xor * 2 + 1;
575}
576
577/*
578 * sw_connect() probes for SideWinder type joysticks.
579 */
580
581static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
582{
583 struct sw *sw;
584 int i, j, k, l;
585 int err;
586 unsigned char *buf = NULL; /* [SW_LENGTH] */
587 unsigned char *idbuf = NULL; /* [SW_LENGTH] */
588 unsigned char m = 1;
589 char comment[40];
590
591 comment[0] = 0;
592
593 sw = kcalloc(1, sizeof(struct sw), GFP_KERNEL);
594 buf = kmalloc(SW_LENGTH, GFP_KERNEL);
595 idbuf = kmalloc(SW_LENGTH, GFP_KERNEL);
596 if (!sw || !buf || !idbuf) {
597 err = -ENOMEM;
598 goto fail1;
599 }
600
601 sw->gameport = gameport;
602
603 gameport_set_drvdata(gameport, sw);
604
605 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
606 if (err)
607 goto fail1;
608
609 dbg("Init 0: Opened %s, io %#x, speed %d",
610 gameport->phys, gameport->io, gameport->speed);
611
612 i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Read normal packet */
613 msleep(SW_TIMEOUT);
614 dbg("Init 1: Mode %d. Length %d.", m , i);
615
616 if (!i) { /* No data. 3d Pro analog mode? */
617 sw_init_digital(gameport); /* Switch to digital */
618 msleep(SW_TIMEOUT);
619 i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Retry reading packet */
620 msleep(SW_TIMEOUT);
621 dbg("Init 1b: Length %d.", i);
622 if (!i) { /* No data -> FAIL */
623 err = -ENODEV;
624 goto fail2;
625 }
626 }
627
628 j = sw_read_packet(gameport, idbuf, SW_LENGTH, i); /* Read ID. This initializes the stick */
629 m |= sw_guess_mode(idbuf, j); /* ID packet should carry mode info [3DP] */
630 dbg("Init 2: Mode %d. ID Length %d.", m, j);
631
632 if (j <= 0) { /* Read ID failed. Happens in 1-bit mode on PP */
633 msleep(SW_TIMEOUT);
634 i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Retry reading packet */
635 m |= sw_guess_mode(buf, i);
636 dbg("Init 2b: Mode %d. Length %d.", m, i);
637 if (!i) {
638 err = -ENODEV;
639 goto fail2;
640 }
641 msleep(SW_TIMEOUT);
642 j = sw_read_packet(gameport, idbuf, SW_LENGTH, i); /* Retry reading ID */
643 dbg("Init 2c: ID Length %d.", j);
644 }
645
646 sw->type = -1;
647 k = SW_FAIL; /* Try SW_FAIL times */
648 l = 0;
649
650 do {
651 k--;
652 msleep(SW_TIMEOUT);
653 i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Read data packet */
654 dbg("Init 3: Mode %d. Length %d. Last %d. Tries %d.", m, i, l, k);
655
656 if (i > l) { /* Longer? As we can only lose bits, it makes */
657 /* no sense to try detection for a packet shorter */
658 l = i; /* than the previous one */
659
660 sw->number = 1;
661 sw->gameport = gameport;
662 sw->length = i;
663 sw->bits = m;
664
665 dbg("Init 3a: Case %d.\n", i * m);
666
667 switch (i * m) {
668 case 60:
669 sw->number++;
670 case 45: /* Ambiguous packet length */
671 if (j <= 40) { /* ID length less or eq 40 -> FSP */
672 case 43:
673 sw->type = SW_ID_FSP;
674 break;
675 }
676 sw->number++;
677 case 30:
678 sw->number++;
679 case 15:
680 sw->type = SW_ID_GP;
681 break;
682 case 33:
683 case 31:
684 sw->type = SW_ID_FFW;
685 break;
686 case 48: /* Ambiguous */
687 if (j == 14) { /* ID length 14*3 -> FFP */
688 sw->type = SW_ID_FFP;
689 sprintf(comment, " [AC %s]", sw_get_bits(idbuf,38,1,3) ? "off" : "on");
690 } else
691 sw->type = SW_ID_PP;
692 break;
693 case 66:
694 sw->bits = 3;
695 case 198:
696 sw->length = 22;
697 case 64:
698 sw->type = SW_ID_3DP;
699 if (j == 160) sw_3dp_id(idbuf, comment);
700 break;
701 }
702 }
703
704 } while (k && sw->type == -1);
705
706 if (sw->type == -1) {
707 printk(KERN_WARNING "sidewinder.c: unknown joystick device detected "
708 "on %s, contact <vojtech@ucw.cz>\n", gameport->phys);
709 sw_print_packet("ID", j * 3, idbuf, 3);
710 sw_print_packet("Data", i * m, buf, m);
711 err = -ENODEV;
712 goto fail2;
713 }
714
715#ifdef SW_DEBUG
716 sw_print_packet("ID", j * 3, idbuf, 3);
717 sw_print_packet("Data", i * m, buf, m);
718#endif
719
720 gameport_set_poll_handler(gameport, sw_poll);
721 gameport_set_poll_interval(gameport, 20);
722
723 k = i;
724 l = j;
725
726 for (i = 0; i < sw->number; i++) {
727 int bits, code;
728
729 sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]);
730 sprintf(sw->phys[i], "%s/input%d", gameport->phys, i);
731
732 sw->dev[i].private = sw;
733
734 sw->dev[i].open = sw_open;
735 sw->dev[i].close = sw_close;
736
737 sw->dev[i].name = sw->name;
738 sw->dev[i].phys = sw->phys[i];
739 sw->dev[i].id.bustype = BUS_GAMEPORT;
740 sw->dev[i].id.vendor = GAMEPORT_ID_VENDOR_MICROSOFT;
741 sw->dev[i].id.product = sw->type;
742 sw->dev[i].id.version = 0x0100;
743
744 sw->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
745
746 for (j = 0; (bits = sw_bit[sw->type][j]); j++) {
747 code = sw_abs[sw->type][j];
748 set_bit(code, sw->dev[i].absbit);
749 sw->dev[i].absmax[code] = (1 << bits) - 1;
750 sw->dev[i].absmin[code] = (bits == 1) ? -1 : 0;
751 sw->dev[i].absfuzz[code] = ((bits >> 1) >= 2) ? (1 << ((bits >> 1) - 2)) : 0;
752 if (code != ABS_THROTTLE)
753 sw->dev[i].absflat[code] = (bits >= 5) ? (1 << (bits - 5)) : 0;
754 }
755
756 for (j = 0; (code = sw_btn[sw->type][j]); j++)
757 set_bit(code, sw->dev[i].keybit);
758
759 input_register_device(sw->dev + i);
760 printk(KERN_INFO "input: %s%s on %s [%d-bit id %d data %d]\n",
761 sw->name, comment, gameport->phys, m, l, k);
762 }
763
764 return 0;
765
766fail2: gameport_close(gameport);
767fail1: gameport_set_drvdata(gameport, NULL);
768 kfree(sw);
769 kfree(buf);
770 kfree(idbuf);
771 return err;
772}
773
774static void sw_disconnect(struct gameport *gameport)
775{
776 struct sw *sw = gameport_get_drvdata(gameport);
777 int i;
778
779 for (i = 0; i < sw->number; i++)
780 input_unregister_device(sw->dev + i);
781 gameport_close(gameport);
782 gameport_set_drvdata(gameport, NULL);
783 kfree(sw);
784}
785
786static struct gameport_driver sw_drv = {
787 .driver = {
788 .name = "sidewinder",
789 },
790 .description = DRIVER_DESC,
791 .connect = sw_connect,
792 .disconnect = sw_disconnect,
793};
794
795static int __init sw_init(void)
796{
797 gameport_register_driver(&sw_drv);
798 return 0;
799}
800
801static void __exit sw_exit(void)
802{
803 gameport_unregister_driver(&sw_drv);
804}
805
806module_init(sw_init);
807module_exit(sw_exit);
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
new file mode 100644
index 000000000000..ec0a2a64d49c
--- /dev/null
+++ b/drivers/input/joystick/spaceball.c
@@ -0,0 +1,319 @@
1/*
2 * $Id: spaceball.c,v 1.17 2002/01/22 20:29:03 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * David Thompson
8 * Joseph Krahn
9 */
10
11/*
12 * SpaceTec SpaceBall 2003/3003/4000 FLX driver for Linux
13 */
14
15/*
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 * Should you need to contact me, the author, you can do so either by
31 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
32 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
33 */
34
35#include <linux/kernel.h>
36#include <linux/slab.h>
37#include <linux/module.h>
38#include <linux/init.h>
39#include <linux/input.h>
40#include <linux/serio.h>
41
42#define DRIVER_DESC "SpaceTec SpaceBall 2003/3003/4000 FLX driver"
43
44MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
45MODULE_DESCRIPTION(DRIVER_DESC);
46MODULE_LICENSE("GPL");
47
48/*
49 * Constants.
50 */
51
52#define SPACEBALL_MAX_LENGTH 128
53#define SPACEBALL_MAX_ID 8
54
55#define SPACEBALL_1003 1
56#define SPACEBALL_2003B 3
57#define SPACEBALL_2003C 4
58#define SPACEBALL_3003C 7
59#define SPACEBALL_4000FLX 8
60#define SPACEBALL_4000FLX_L 9
61
62static int spaceball_axes[] = { ABS_X, ABS_Z, ABS_Y, ABS_RX, ABS_RZ, ABS_RY };
63static char *spaceball_names[] = {
64 "?", "SpaceTec SpaceBall 1003", "SpaceTec SpaceBall 2003", "SpaceTec SpaceBall 2003B",
65 "SpaceTec SpaceBall 2003C", "SpaceTec SpaceBall 3003", "SpaceTec SpaceBall SpaceController",
66 "SpaceTec SpaceBall 3003C", "SpaceTec SpaceBall 4000FLX", "SpaceTec SpaceBall 4000FLX Lefty" };
67
68/*
69 * Per-Ball data.
70 */
71
72struct spaceball {
73 struct input_dev dev;
74 struct serio *serio;
75 int idx;
76 int escape;
77 unsigned char data[SPACEBALL_MAX_LENGTH];
78 char phys[32];
79};
80
81/*
82 * spaceball_process_packet() decodes packets the driver receives from the
83 * SpaceBall.
84 */
85
86static void spaceball_process_packet(struct spaceball* spaceball, struct pt_regs *regs)
87{
88 struct input_dev *dev = &spaceball->dev;
89 unsigned char *data = spaceball->data;
90 int i;
91
92 if (spaceball->idx < 2) return;
93
94 input_regs(dev, regs);
95
96 switch (spaceball->data[0]) {
97
98 case 'D': /* Ball data */
99 if (spaceball->idx != 15) return;
100 for (i = 0; i < 6; i++)
101 input_report_abs(dev, spaceball_axes[i],
102 (__s16)((data[2 * i + 3] << 8) | data[2 * i + 2]));
103 break;
104
105 case 'K': /* Button data */
106 if (spaceball->idx != 3) return;
107 input_report_key(dev, BTN_1, (data[2] & 0x01) || (data[2] & 0x20));
108 input_report_key(dev, BTN_2, data[2] & 0x02);
109 input_report_key(dev, BTN_3, data[2] & 0x04);
110 input_report_key(dev, BTN_4, data[2] & 0x08);
111 input_report_key(dev, BTN_5, data[1] & 0x01);
112 input_report_key(dev, BTN_6, data[1] & 0x02);
113 input_report_key(dev, BTN_7, data[1] & 0x04);
114 input_report_key(dev, BTN_8, data[1] & 0x10);
115 break;
116
117 case '.': /* Advanced button data */
118 if (spaceball->idx != 3) return;
119 input_report_key(dev, BTN_1, data[2] & 0x01);
120 input_report_key(dev, BTN_2, data[2] & 0x02);
121 input_report_key(dev, BTN_3, data[2] & 0x04);
122 input_report_key(dev, BTN_4, data[2] & 0x08);
123 input_report_key(dev, BTN_5, data[2] & 0x10);
124 input_report_key(dev, BTN_6, data[2] & 0x20);
125 input_report_key(dev, BTN_7, data[2] & 0x80);
126 input_report_key(dev, BTN_8, data[1] & 0x01);
127 input_report_key(dev, BTN_9, data[1] & 0x02);
128 input_report_key(dev, BTN_A, data[1] & 0x04);
129 input_report_key(dev, BTN_B, data[1] & 0x08);
130 input_report_key(dev, BTN_C, data[1] & 0x10);
131 input_report_key(dev, BTN_MODE, data[1] & 0x20);
132 break;
133
134 case 'E': /* Device error */
135 spaceball->data[spaceball->idx - 1] = 0;
136 printk(KERN_ERR "spaceball: Device error. [%s]\n", spaceball->data + 1);
137 break;
138
139 case '?': /* Bad command packet */
140 spaceball->data[spaceball->idx - 1] = 0;
141 printk(KERN_ERR "spaceball: Bad command. [%s]\n", spaceball->data + 1);
142 break;
143 }
144
145 input_sync(dev);
146}
147
148/*
149 * Spaceball 4000 FLX packets all start with a one letter packet-type decriptor,
150 * and end in 0x0d. It uses '^' as an escape for CR, XOFF and XON characters which
151 * can occur in the axis values.
152 */
153
154static irqreturn_t spaceball_interrupt(struct serio *serio,
155 unsigned char data, unsigned int flags, struct pt_regs *regs)
156{
157 struct spaceball *spaceball = serio_get_drvdata(serio);
158
159 switch (data) {
160 case 0xd:
161 spaceball_process_packet(spaceball, regs);
162 spaceball->idx = 0;
163 spaceball->escape = 0;
164 break;
165 case '^':
166 if (!spaceball->escape) {
167 spaceball->escape = 1;
168 break;
169 }
170 spaceball->escape = 0;
171 case 'M':
172 case 'Q':
173 case 'S':
174 if (spaceball->escape) {
175 spaceball->escape = 0;
176 data &= 0x1f;
177 }
178 default:
179 if (spaceball->escape)
180 spaceball->escape = 0;
181 if (spaceball->idx < SPACEBALL_MAX_LENGTH)
182 spaceball->data[spaceball->idx++] = data;
183 break;
184 }
185 return IRQ_HANDLED;
186}
187
188/*
189 * spaceball_disconnect() is the opposite of spaceball_connect()
190 */
191
192static void spaceball_disconnect(struct serio *serio)
193{
194 struct spaceball* spaceball = serio_get_drvdata(serio);
195
196 input_unregister_device(&spaceball->dev);
197 serio_close(serio);
198 serio_set_drvdata(serio, NULL);
199 kfree(spaceball);
200}
201
202/*
203 * spaceball_connect() is the routine that is called when someone adds a
204 * new serio device that supports Spaceball protocol and registers it as
205 * an input device.
206 */
207
208static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
209{
210 struct spaceball *spaceball;
211 int i, t, id;
212 int err;
213
214 if ((id = serio->id.id) > SPACEBALL_MAX_ID)
215 return -ENODEV;
216
217 if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL)))
218 return - ENOMEM;
219
220 memset(spaceball, 0, sizeof(struct spaceball));
221
222 spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
223
224 switch (id) {
225 case SPACEBALL_4000FLX:
226 case SPACEBALL_4000FLX_L:
227 spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_9);
228 spaceball->dev.keybit[LONG(BTN_A)] |= BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_MODE);
229 default:
230 spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4)
231 | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7) | BIT(BTN_8);
232 case SPACEBALL_3003C:
233 spaceball->dev.keybit[LONG(BTN_0)] |= BIT(BTN_1) | BIT(BTN_8);
234 }
235
236 for (i = 0; i < 6; i++) {
237 t = spaceball_axes[i];
238 set_bit(t, spaceball->dev.absbit);
239 spaceball->dev.absmin[t] = i < 3 ? -8000 : -1600;
240 spaceball->dev.absmax[t] = i < 3 ? 8000 : 1600;
241 spaceball->dev.absflat[t] = i < 3 ? 40 : 8;
242 spaceball->dev.absfuzz[t] = i < 3 ? 8 : 2;
243 }
244
245 spaceball->serio = serio;
246 spaceball->dev.private = spaceball;
247
248 sprintf(spaceball->phys, "%s/input0", serio->phys);
249
250 init_input_dev(&spaceball->dev);
251 spaceball->dev.name = spaceball_names[id];
252 spaceball->dev.phys = spaceball->phys;
253 spaceball->dev.id.bustype = BUS_RS232;
254 spaceball->dev.id.vendor = SERIO_SPACEBALL;
255 spaceball->dev.id.product = id;
256 spaceball->dev.id.version = 0x0100;
257 spaceball->dev.dev = &serio->dev;
258
259 serio_set_drvdata(serio, spaceball);
260
261 err = serio_open(serio, drv);
262 if (err) {
263 serio_set_drvdata(serio, NULL);
264 kfree(spaceball);
265 return err;
266 }
267
268 input_register_device(&spaceball->dev);
269
270 printk(KERN_INFO "input: %s on serio%s\n",
271 spaceball_names[id], serio->phys);
272
273 return 0;
274}
275
276/*
277 * The serio driver structure.
278 */
279
280static struct serio_device_id spaceball_serio_ids[] = {
281 {
282 .type = SERIO_RS232,
283 .proto = SERIO_SPACEBALL,
284 .id = SERIO_ANY,
285 .extra = SERIO_ANY,
286 },
287 { 0 }
288};
289
290MODULE_DEVICE_TABLE(serio, spaceball_serio_ids);
291
292static struct serio_driver spaceball_drv = {
293 .driver = {
294 .name = "spaceball",
295 },
296 .description = DRIVER_DESC,
297 .id_table = spaceball_serio_ids,
298 .interrupt = spaceball_interrupt,
299 .connect = spaceball_connect,
300 .disconnect = spaceball_disconnect,
301};
302
303/*
304 * The functions for inserting/removing us as a module.
305 */
306
307static int __init spaceball_init(void)
308{
309 serio_register_driver(&spaceball_drv);
310 return 0;
311}
312
313static void __exit spaceball_exit(void)
314{
315 serio_unregister_driver(&spaceball_drv);
316}
317
318module_init(spaceball_init);
319module_exit(spaceball_exit);
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
new file mode 100644
index 000000000000..c76cf8ff29c0
--- /dev/null
+++ b/drivers/input/joystick/spaceorb.c
@@ -0,0 +1,263 @@
1/*
2 * $Id: spaceorb.c,v 1.15 2002/01/22 20:29:19 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * David Thompson
8 */
9
10/*
11 * SpaceTec SpaceOrb 360 and Avenger 6dof controller driver for Linux
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/kernel.h>
35#include <linux/slab.h>
36#include <linux/module.h>
37#include <linux/init.h>
38#include <linux/input.h>
39#include <linux/serio.h>
40
41#define DRIVER_DESC "SpaceTec SpaceOrb 360 and Avenger 6dof controller driver"
42
43MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
44MODULE_DESCRIPTION(DRIVER_DESC);
45MODULE_LICENSE("GPL");
46
47/*
48 * Constants.
49 */
50
51#define SPACEORB_MAX_LENGTH 64
52
53static int spaceorb_buttons[] = { BTN_TL, BTN_TR, BTN_Y, BTN_X, BTN_B, BTN_A };
54static int spaceorb_axes[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ };
55static char *spaceorb_name = "SpaceTec SpaceOrb 360 / Avenger";
56
57/*
58 * Per-Orb data.
59 */
60
61struct spaceorb {
62 struct input_dev dev;
63 struct serio *serio;
64 int idx;
65 unsigned char data[SPACEORB_MAX_LENGTH];
66 char phys[32];
67};
68
69static unsigned char spaceorb_xor[] = "SpaceWare";
70
71static unsigned char *spaceorb_errors[] = { "EEPROM storing 0 failed", "Receive queue overflow", "Transmit queue timeout",
72 "Bad packet", "Power brown-out", "EEPROM checksum error", "Hardware fault" };
73
74/*
75 * spaceorb_process_packet() decodes packets the driver receives from the
76 * SpaceOrb.
77 */
78
79static void spaceorb_process_packet(struct spaceorb *spaceorb, struct pt_regs *regs)
80{
81 struct input_dev *dev = &spaceorb->dev;
82 unsigned char *data = spaceorb->data;
83 unsigned char c = 0;
84 int axes[6];
85 int i;
86
87 if (spaceorb->idx < 2) return;
88 for (i = 0; i < spaceorb->idx; i++) c ^= data[i];
89 if (c) return;
90
91 input_regs(dev, regs);
92
93 switch (data[0]) {
94
95 case 'R': /* Reset packet */
96 spaceorb->data[spaceorb->idx - 1] = 0;
97 for (i = 1; i < spaceorb->idx && spaceorb->data[i] == ' '; i++);
98 printk(KERN_INFO "input: %s [%s] on %s\n",
99 spaceorb_name, spaceorb->data + i, spaceorb->serio->phys);
100 break;
101
102 case 'D': /* Ball + button data */
103 if (spaceorb->idx != 12) return;
104 for (i = 0; i < 9; i++) spaceorb->data[i+2] ^= spaceorb_xor[i];
105 axes[0] = ( data[2] << 3) | (data[ 3] >> 4);
106 axes[1] = ((data[3] & 0x0f) << 6) | (data[ 4] >> 1);
107 axes[2] = ((data[4] & 0x01) << 9) | (data[ 5] << 2) | (data[4] >> 5);
108 axes[3] = ((data[6] & 0x1f) << 5) | (data[ 7] >> 2);
109 axes[4] = ((data[7] & 0x03) << 8) | (data[ 8] << 1) | (data[7] >> 6);
110 axes[5] = ((data[9] & 0x3f) << 4) | (data[10] >> 3);
111 for (i = 0; i < 6; i++)
112 input_report_abs(dev, spaceorb_axes[i], axes[i] - ((axes[i] & 0x200) ? 1024 : 0));
113 for (i = 0; i < 6; i++)
114 input_report_key(dev, spaceorb_buttons[i], (data[1] >> i) & 1);
115 break;
116
117 case 'K': /* Button data */
118 if (spaceorb->idx != 5) return;
119 for (i = 0; i < 7; i++)
120 input_report_key(dev, spaceorb_buttons[i], (data[2] >> i) & 1);
121
122 break;
123
124 case 'E': /* Error packet */
125 if (spaceorb->idx != 4) return;
126 printk(KERN_ERR "joy-spaceorb: Device error. [ ");
127 for (i = 0; i < 7; i++) if (data[1] & (1 << i)) printk("%s ", spaceorb_errors[i]);
128 printk("]\n");
129 break;
130 }
131
132 input_sync(dev);
133}
134
135static irqreturn_t spaceorb_interrupt(struct serio *serio,
136 unsigned char data, unsigned int flags, struct pt_regs *regs)
137{
138 struct spaceorb* spaceorb = serio_get_drvdata(serio);
139
140 if (~data & 0x80) {
141 if (spaceorb->idx) spaceorb_process_packet(spaceorb, regs);
142 spaceorb->idx = 0;
143 }
144 if (spaceorb->idx < SPACEORB_MAX_LENGTH)
145 spaceorb->data[spaceorb->idx++] = data & 0x7f;
146 return IRQ_HANDLED;
147}
148
149/*
150 * spaceorb_disconnect() is the opposite of spaceorb_connect()
151 */
152
153static void spaceorb_disconnect(struct serio *serio)
154{
155 struct spaceorb* spaceorb = serio_get_drvdata(serio);
156
157 input_unregister_device(&spaceorb->dev);
158 serio_close(serio);
159 serio_set_drvdata(serio, NULL);
160 kfree(spaceorb);
161}
162
163/*
164 * spaceorb_connect() is the routine that is called when someone adds a
165 * new serio device that supports SpaceOrb/Avenger protocol and registers
166 * it as an input device.
167 */
168
169static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
170{
171 struct spaceorb *spaceorb;
172 int i, t;
173 int err;
174
175 if (!(spaceorb = kmalloc(sizeof(struct spaceorb), GFP_KERNEL)))
176 return -ENOMEM;
177
178 memset(spaceorb, 0, sizeof(struct spaceorb));
179
180 spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
181
182 for (i = 0; i < 6; i++)
183 set_bit(spaceorb_buttons[i], spaceorb->dev.keybit);
184
185 for (i = 0; i < 6; i++) {
186 t = spaceorb_axes[i];
187 set_bit(t, spaceorb->dev.absbit);
188 spaceorb->dev.absmin[t] = -508;
189 spaceorb->dev.absmax[t] = 508;
190 }
191
192 spaceorb->serio = serio;
193 spaceorb->dev.private = spaceorb;
194
195 sprintf(spaceorb->phys, "%s/input0", serio->phys);
196
197 init_input_dev(&spaceorb->dev);
198 spaceorb->dev.name = spaceorb_name;
199 spaceorb->dev.phys = spaceorb->phys;
200 spaceorb->dev.id.bustype = BUS_RS232;
201 spaceorb->dev.id.vendor = SERIO_SPACEORB;
202 spaceorb->dev.id.product = 0x0001;
203 spaceorb->dev.id.version = 0x0100;
204 spaceorb->dev.dev = &serio->dev;
205
206 serio_set_drvdata(serio, spaceorb);
207
208 err = serio_open(serio, drv);
209 if (err) {
210 serio_set_drvdata(serio, NULL);
211 kfree(spaceorb);
212 return err;
213 }
214
215 input_register_device(&spaceorb->dev);
216
217 return 0;
218}
219
220/*
221 * The serio driver structure.
222 */
223
224static struct serio_device_id spaceorb_serio_ids[] = {
225 {
226 .type = SERIO_RS232,
227 .proto = SERIO_SPACEORB,
228 .id = SERIO_ANY,
229 .extra = SERIO_ANY,
230 },
231 { 0 }
232};
233
234MODULE_DEVICE_TABLE(serio, spaceorb_serio_ids);
235
236static struct serio_driver spaceorb_drv = {
237 .driver = {
238 .name = "spaceorb",
239 },
240 .description = DRIVER_DESC,
241 .id_table = spaceorb_serio_ids,
242 .interrupt = spaceorb_interrupt,
243 .connect = spaceorb_connect,
244 .disconnect = spaceorb_disconnect,
245};
246
247/*
248 * The functions for inserting/removing us as a module.
249 */
250
251static int __init spaceorb_init(void)
252{
253 serio_register_driver(&spaceorb_drv);
254 return 0;
255}
256
257static void __exit spaceorb_exit(void)
258{
259 serio_unregister_driver(&spaceorb_drv);
260}
261
262module_init(spaceorb_init);
263module_exit(spaceorb_exit);
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
new file mode 100644
index 000000000000..6f6e6753d590
--- /dev/null
+++ b/drivers/input/joystick/stinger.c
@@ -0,0 +1,236 @@
1/*
2 * $Id: stinger.c,v 1.10 2002/01/22 20:29:31 vojtech Exp $
3 *
4 * Copyright (c) 2000-2001 Vojtech Pavlik
5 * Copyright (c) 2000 Mark Fletcher
6 */
7
8/*
9 * Gravis Stinger gamepad driver for Linux
10 */
11
12/*
13 * This program is free warftware; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 * Should you need to contact me, the author, you can do so either by
28 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
29 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
30 */
31
32#include <linux/kernel.h>
33#include <linux/module.h>
34#include <linux/slab.h>
35#include <linux/input.h>
36#include <linux/serio.h>
37#include <linux/init.h>
38
39#define DRIVER_DESC "Gravis Stinger gamepad driver"
40
41MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
42MODULE_DESCRIPTION(DRIVER_DESC);
43MODULE_LICENSE("GPL");
44
45/*
46 * Constants.
47 */
48
49#define STINGER_MAX_LENGTH 8
50
51static char *stinger_name = "Gravis Stinger";
52
53/*
54 * Per-Stinger data.
55 */
56
57struct stinger {
58 struct input_dev dev;
59 int idx;
60 unsigned char data[STINGER_MAX_LENGTH];
61 char phys[32];
62};
63
64/*
65 * stinger_process_packet() decodes packets the driver receives from the
66 * Stinger. It updates the data accordingly.
67 */
68
69static void stinger_process_packet(struct stinger *stinger, struct pt_regs *regs)
70{
71 struct input_dev *dev = &stinger->dev;
72 unsigned char *data = stinger->data;
73
74 if (!stinger->idx) return;
75
76 input_regs(dev, regs);
77
78 input_report_key(dev, BTN_A, ((data[0] & 0x20) >> 5));
79 input_report_key(dev, BTN_B, ((data[0] & 0x10) >> 4));
80 input_report_key(dev, BTN_C, ((data[0] & 0x08) >> 3));
81 input_report_key(dev, BTN_X, ((data[0] & 0x04) >> 2));
82 input_report_key(dev, BTN_Y, ((data[3] & 0x20) >> 5));
83 input_report_key(dev, BTN_Z, ((data[3] & 0x10) >> 4));
84 input_report_key(dev, BTN_TL, ((data[3] & 0x08) >> 3));
85 input_report_key(dev, BTN_TR, ((data[3] & 0x04) >> 2));
86 input_report_key(dev, BTN_SELECT, ((data[3] & 0x02) >> 1));
87 input_report_key(dev, BTN_START, (data[3] & 0x01));
88
89 input_report_abs(dev, ABS_X, (data[1] & 0x3F) - ((data[0] & 0x01) << 6));
90 input_report_abs(dev, ABS_Y, ((data[0] & 0x02) << 5) - (data[2] & 0x3F));
91
92 input_sync(dev);
93
94 return;
95}
96
97/*
98 * stinger_interrupt() is called by the low level driver when characters
99 * are ready for us. We then buffer them for further processing, or call the
100 * packet processing routine.
101 */
102
103static irqreturn_t stinger_interrupt(struct serio *serio,
104 unsigned char data, unsigned int flags, struct pt_regs *regs)
105{
106 struct stinger *stinger = serio_get_drvdata(serio);
107
108 /* All Stinger packets are 4 bytes */
109
110 if (stinger->idx < STINGER_MAX_LENGTH)
111 stinger->data[stinger->idx++] = data;
112
113 if (stinger->idx == 4) {
114 stinger_process_packet(stinger, regs);
115 stinger->idx = 0;
116 }
117
118 return IRQ_HANDLED;
119}
120
121/*
122 * stinger_disconnect() is the opposite of stinger_connect()
123 */
124
125static void stinger_disconnect(struct serio *serio)
126{
127 struct stinger *stinger = serio_get_drvdata(serio);
128
129 input_unregister_device(&stinger->dev);
130 serio_close(serio);
131 serio_set_drvdata(serio, NULL);
132 kfree(stinger);
133}
134
135/*
136 * stinger_connect() is the routine that is called when someone adds a
137 * new serio device that supports Stinger protocol and registers it as
138 * an input device.
139 */
140
141static int stinger_connect(struct serio *serio, struct serio_driver *drv)
142{
143 struct stinger *stinger;
144 int i;
145 int err;
146
147 if (!(stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL)))
148 return -ENOMEM;
149
150 memset(stinger, 0, sizeof(struct stinger));
151
152 stinger->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
153 stinger->dev.keybit[LONG(BTN_A)] = BIT(BTN_A) | BIT(BTN_B) | BIT(BTN_C) | BIT(BTN_X) | \
154 BIT(BTN_Y) | BIT(BTN_Z) | BIT(BTN_TL) | BIT(BTN_TR) | \
155 BIT(BTN_START) | BIT(BTN_SELECT);
156 stinger->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
157
158 sprintf(stinger->phys, "%s/serio0", serio->phys);
159
160 init_input_dev(&stinger->dev);
161 stinger->dev.name = stinger_name;
162 stinger->dev.phys = stinger->phys;
163 stinger->dev.id.bustype = BUS_RS232;
164 stinger->dev.id.vendor = SERIO_STINGER;
165 stinger->dev.id.product = 0x0001;
166 stinger->dev.id.version = 0x0100;
167 stinger->dev.dev = &serio->dev;
168
169 for (i = 0; i < 2; i++) {
170 stinger->dev.absmax[ABS_X+i] = 64;
171 stinger->dev.absmin[ABS_X+i] = -64;
172 stinger->dev.absflat[ABS_X+i] = 4;
173 }
174
175 stinger->dev.private = stinger;
176
177 serio_set_drvdata(serio, stinger);
178
179 err = serio_open(serio, drv);
180 if (err) {
181 serio_set_drvdata(serio, NULL);
182 kfree(stinger);
183 return err;
184 }
185
186 input_register_device(&stinger->dev);
187
188 printk(KERN_INFO "input: %s on %s\n", stinger_name, serio->phys);
189
190 return 0;
191}
192
193/*
194 * The serio driver structure.
195 */
196
197static struct serio_device_id stinger_serio_ids[] = {
198 {
199 .type = SERIO_RS232,
200 .proto = SERIO_STINGER,
201 .id = SERIO_ANY,
202 .extra = SERIO_ANY,
203 },
204 { 0 }
205};
206
207MODULE_DEVICE_TABLE(serio, stinger_serio_ids);
208
209static struct serio_driver stinger_drv = {
210 .driver = {
211 .name = "stinger",
212 },
213 .description = DRIVER_DESC,
214 .id_table = stinger_serio_ids,
215 .interrupt = stinger_interrupt,
216 .connect = stinger_connect,
217 .disconnect = stinger_disconnect,
218};
219
220/*
221 * The functions for inserting/removing us as a module.
222 */
223
224static int __init stinger_init(void)
225{
226 serio_register_driver(&stinger_drv);
227 return 0;
228}
229
230static void __exit stinger_exit(void)
231{
232 serio_unregister_driver(&stinger_drv);
233}
234
235module_init(stinger_init);
236module_exit(stinger_exit);
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
new file mode 100644
index 000000000000..aaee52ceb920
--- /dev/null
+++ b/drivers/input/joystick/tmdc.c
@@ -0,0 +1,384 @@
1/*
2 * $Id: tmdc.c,v 1.31 2002/01/22 20:29:52 vojtech Exp $
3 *
4 * Copyright (c) 1998-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Trystan Larey-Williams
8 */
9
10/*
11 * ThrustMaster DirectConnect (BSP) joystick family driver for Linux
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/delay.h>
35#include <linux/kernel.h>
36#include <linux/slab.h>
37#include <linux/module.h>
38#include <linux/init.h>
39#include <linux/gameport.h>
40#include <linux/input.h>
41
42#define DRIVER_DESC "ThrustMaster DirectConnect joystick driver"
43
44MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
45MODULE_DESCRIPTION(DRIVER_DESC);
46MODULE_LICENSE("GPL");
47
48#define TMDC_MAX_START 600 /* 600 us */
49#define TMDC_MAX_STROBE 60 /* 60 us */
50#define TMDC_MAX_LENGTH 13
51
52#define TMDC_MODE_M3DI 1
53#define TMDC_MODE_3DRP 3
54#define TMDC_MODE_AT 4
55#define TMDC_MODE_FM 8
56#define TMDC_MODE_FGP 163
57
58#define TMDC_BYTE_ID 10
59#define TMDC_BYTE_REV 11
60#define TMDC_BYTE_DEF 12
61
62#define TMDC_ABS 7
63#define TMDC_ABS_HAT 4
64#define TMDC_BTN 16
65
66static unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 };
67static unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 };
68
69static signed char tmdc_abs[TMDC_ABS] =
70 { ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE, ABS_RX, ABS_RY, ABS_RZ };
71static signed char tmdc_abs_hat[TMDC_ABS_HAT] =
72 { ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
73static signed char tmdc_abs_at[TMDC_ABS] =
74 { ABS_X, ABS_Y, ABS_RUDDER, -1, ABS_THROTTLE };
75static signed char tmdc_abs_fm[TMDC_ABS] =
76 { ABS_RX, ABS_RY, ABS_X, ABS_Y };
77
78static short tmdc_btn_pad[TMDC_BTN] =
79 { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR };
80static short tmdc_btn_joy[TMDC_BTN] =
81 { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE,
82 BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z };
83static short tmdc_btn_fm[TMDC_BTN] =
84 { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 };
85static short tmdc_btn_at[TMDC_BTN] =
86 { BTN_TRIGGER, BTN_THUMB2, BTN_PINKIE, BTN_THUMB, BTN_BASE6, BTN_BASE5, BTN_BASE4,
87 BTN_BASE3, BTN_BASE2, BTN_BASE };
88
89static struct {
90 int x;
91 int y;
92} tmdc_hat_to_axis[] = {{ 0, 0}, { 1, 0}, { 0,-1}, {-1, 0}, { 0, 1}};
93
94struct tmdc {
95 struct gameport *gameport;
96 struct input_dev dev[2];
97 char name[2][64];
98 char phys[2][32];
99 int mode[2];
100 signed char *abs[2];
101 short *btn[2];
102 unsigned char absc[2];
103 unsigned char btnc[2][4];
104 unsigned char btno[2][4];
105 int reads;
106 int bads;
107 unsigned char exists;
108};
109
110/*
111 * tmdc_read_packet() reads a ThrustMaster packet.
112 */
113
114static int tmdc_read_packet(struct gameport *gameport, unsigned char data[2][TMDC_MAX_LENGTH])
115{
116 unsigned char u, v, w, x;
117 unsigned long flags;
118 int i[2], j[2], t[2], p, k;
119
120 p = gameport_time(gameport, TMDC_MAX_STROBE);
121
122 for (k = 0; k < 2; k++) {
123 t[k] = gameport_time(gameport, TMDC_MAX_START);
124 i[k] = j[k] = 0;
125 }
126
127 local_irq_save(flags);
128 gameport_trigger(gameport);
129
130 w = gameport_read(gameport) >> 4;
131
132 do {
133 x = w;
134 w = gameport_read(gameport) >> 4;
135
136 for (k = 0, v = w, u = x; k < 2; k++, v >>= 2, u >>= 2) {
137 if (~v & u & 2) {
138 if (t[k] <= 0 || i[k] >= TMDC_MAX_LENGTH) continue;
139 t[k] = p;
140 if (j[k] == 0) { /* Start bit */
141 if (~v & 1) t[k] = 0;
142 data[k][i[k]] = 0; j[k]++; continue;
143 }
144 if (j[k] == 9) { /* Stop bit */
145 if (v & 1) t[k] = 0;
146 j[k] = 0; i[k]++; continue;
147 }
148 data[k][i[k]] |= (~v & 1) << (j[k]++ - 1); /* Data bit */
149 }
150 t[k]--;
151 }
152 } while (t[0] > 0 || t[1] > 0);
153
154 local_irq_restore(flags);
155
156 return (i[0] == TMDC_MAX_LENGTH) | ((i[1] == TMDC_MAX_LENGTH) << 1);
157}
158
159/*
160 * tmdc_poll() reads and analyzes ThrustMaster joystick data.
161 */
162
163static void tmdc_poll(struct gameport *gameport)
164{
165 unsigned char data[2][TMDC_MAX_LENGTH];
166 struct tmdc *tmdc = gameport_get_drvdata(gameport);
167 struct input_dev *dev;
168 unsigned char r, bad = 0;
169 int i, j, k, l;
170
171 tmdc->reads++;
172
173 if ((r = tmdc_read_packet(tmdc->gameport, data)) != tmdc->exists)
174 bad = 1;
175 else
176
177 for (j = 0; j < 2; j++)
178 if (r & (1 << j) & tmdc->exists) {
179
180 if (data[j][TMDC_BYTE_ID] != tmdc->mode[j]) {
181 bad = 1;
182 continue;
183 }
184
185 dev = tmdc->dev + j;
186
187 for (i = 0; i < tmdc->absc[j]; i++) {
188 if (tmdc->abs[j][i] < 0) continue;
189 input_report_abs(dev, tmdc->abs[j][i], data[j][tmdc_byte_a[i]]);
190 }
191
192 switch (tmdc->mode[j]) {
193
194 case TMDC_MODE_M3DI:
195
196 i = tmdc_byte_d[0];
197 input_report_abs(dev, ABS_HAT0X, ((data[j][i] >> 3) & 1) - ((data[j][i] >> 1) & 1));
198 input_report_abs(dev, ABS_HAT0Y, ((data[j][i] >> 2) & 1) - ( data[j][i] & 1));
199 break;
200
201 case TMDC_MODE_AT:
202
203 i = tmdc_byte_a[3];
204 input_report_abs(dev, ABS_HAT0X, tmdc_hat_to_axis[(data[j][i] - 141) / 25].x);
205 input_report_abs(dev, ABS_HAT0Y, tmdc_hat_to_axis[(data[j][i] - 141) / 25].y);
206 break;
207
208 }
209
210 for (k = l = 0; k < 4; k++) {
211 for (i = 0; i < tmdc->btnc[j][k]; i++)
212 input_report_key(dev, tmdc->btn[j][i + l],
213 ((data[j][tmdc_byte_d[k]] >> (i + tmdc->btno[j][k])) & 1));
214 l += tmdc->btnc[j][k];
215 }
216
217 input_sync(dev);
218 }
219
220 tmdc->bads += bad;
221}
222
223static int tmdc_open(struct input_dev *dev)
224{
225 struct tmdc *tmdc = dev->private;
226
227 gameport_start_polling(tmdc->gameport);
228 return 0;
229}
230
231static void tmdc_close(struct input_dev *dev)
232{
233 struct tmdc *tmdc = dev->private;
234
235 gameport_stop_polling(tmdc->gameport);
236}
237
238/*
239 * tmdc_probe() probes for ThrustMaster type joysticks.
240 */
241
242static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
243{
244 static struct models {
245 unsigned char id;
246 char *name;
247 char abs;
248 char hats;
249 char btnc[4];
250 char btno[4];
251 signed char *axes;
252 short *buttons;
253 } models[] = { { 1, "ThrustMaster Millenium 3D Inceptor", 6, 2, { 4, 2 }, { 4, 6 }, tmdc_abs, tmdc_btn_joy },
254 { 3, "ThrustMaster Rage 3D Gamepad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
255 { 4, "ThrustMaster Attack Throttle", 5, 2, { 4, 6 }, { 4, 2 }, tmdc_abs_at, tmdc_btn_at },
256 { 8, "ThrustMaster FragMaster", 4, 0, { 8, 2 }, { 0, 0 }, tmdc_abs_fm, tmdc_btn_fm },
257 { 163, "Thrustmaster Fusion GamePad", 2, 0, { 8, 2 }, { 0, 0 }, tmdc_abs, tmdc_btn_pad },
258 { 0, "Unknown %d-axis, %d-button TM device %d", 0, 0, { 0, 0 }, { 0, 0 }, tmdc_abs, tmdc_btn_joy }};
259
260 unsigned char data[2][TMDC_MAX_LENGTH];
261 struct tmdc *tmdc;
262 int i, j, k, l, m;
263 int err;
264
265 if (!(tmdc = kcalloc(1, sizeof(struct tmdc), GFP_KERNEL)))
266 return -ENOMEM;
267
268 tmdc->gameport = gameport;
269
270 gameport_set_drvdata(gameport, tmdc);
271
272 err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
273 if (err)
274 goto fail1;
275
276 if (!(tmdc->exists = tmdc_read_packet(gameport, data))) {
277 err = -ENODEV;
278 goto fail2;
279 }
280
281 gameport_set_poll_handler(gameport, tmdc_poll);
282 gameport_set_poll_interval(gameport, 20);
283
284 for (j = 0; j < 2; j++)
285 if (tmdc->exists & (1 << j)) {
286
287 tmdc->mode[j] = data[j][TMDC_BYTE_ID];
288
289 for (m = 0; models[m].id && models[m].id != tmdc->mode[j]; m++);
290
291 tmdc->abs[j] = models[m].axes;
292 tmdc->btn[j] = models[m].buttons;
293
294 if (!models[m].id) {
295 models[m].abs = data[j][TMDC_BYTE_DEF] >> 4;
296 for (k = 0; k < 4; k++)
297 models[m].btnc[k] = k < (data[j][TMDC_BYTE_DEF] & 0xf) ? 8 : 0;
298 }
299
300 tmdc->absc[j] = models[m].abs;
301 for (k = 0; k < 4; k++) {
302 tmdc->btnc[j][k] = models[m].btnc[k];
303 tmdc->btno[j][k] = models[m].btno[k];
304 }
305
306 sprintf(tmdc->name[j], models[m].name, models[m].abs,
307 (data[j][TMDC_BYTE_DEF] & 0xf) << 3, tmdc->mode[j]);
308
309 sprintf(tmdc->phys[j], "%s/input%d", gameport->phys, j);
310
311 tmdc->dev[j].private = tmdc;
312 tmdc->dev[j].open = tmdc_open;
313 tmdc->dev[j].close = tmdc_close;
314
315 tmdc->dev[j].name = tmdc->name[j];
316 tmdc->dev[j].phys = tmdc->phys[j];
317 tmdc->dev[j].id.bustype = BUS_GAMEPORT;
318 tmdc->dev[j].id.vendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
319 tmdc->dev[j].id.product = models[m].id;
320 tmdc->dev[j].id.version = 0x0100;
321
322 tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
323
324 for (i = 0; i < models[m].abs && i < TMDC_ABS; i++)
325 if (tmdc->abs[j][i] >= 0)
326 input_set_abs_params(&tmdc->dev[j], tmdc->abs[j][i], 8, 248, 2, 4);
327
328 for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++)
329 input_set_abs_params(&tmdc->dev[j], tmdc_abs_hat[i], -1, 1, 0, 0);
330
331
332 for (k = l = 0; k < 4; k++) {
333 for (i = 0; i < models[m].btnc[k] && i < TMDC_BTN; i++)
334 set_bit(tmdc->btn[j][i + l], tmdc->dev[j].keybit);
335 l += models[m].btnc[k];
336 }
337
338 input_register_device(tmdc->dev + j);
339 printk(KERN_INFO "input: %s on %s\n", tmdc->name[j], gameport->phys);
340 }
341
342 return 0;
343
344fail2: gameport_close(gameport);
345fail1: gameport_set_drvdata(gameport, NULL);
346 kfree(tmdc);
347 return err;
348}
349
350static void tmdc_disconnect(struct gameport *gameport)
351{
352 struct tmdc *tmdc = gameport_get_drvdata(gameport);
353 int i;
354
355 for (i = 0; i < 2; i++)
356 if (tmdc->exists & (1 << i))
357 input_unregister_device(tmdc->dev + i);
358 gameport_close(gameport);
359 gameport_set_drvdata(gameport, NULL);
360 kfree(tmdc);
361}
362
363static struct gameport_driver tmdc_drv = {
364 .driver = {
365 .name = "tmdc",
366 },
367 .description = DRIVER_DESC,
368 .connect = tmdc_connect,
369 .disconnect = tmdc_disconnect,
370};
371
372static int __init tmdc_init(void)
373{
374 gameport_register_driver(&tmdc_drv);
375 return 0;
376}
377
378static void __exit tmdc_exit(void)
379{
380 gameport_unregister_driver(&tmdc_drv);
381}
382
383module_init(tmdc_init);
384module_exit(tmdc_exit);
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
new file mode 100644
index 000000000000..dd88b9cb49fa
--- /dev/null
+++ b/drivers/input/joystick/turbografx.c
@@ -0,0 +1,258 @@
1/*
2 * $Id: turbografx.c,v 1.14 2002/01/22 20:30:39 vojtech Exp $
3 *
4 * Copyright (c) 1998-2001 Vojtech Pavlik
5 *
6 * Based on the work of:
7 * Steffen Schwenke
8 */
9
10/*
11 * TurboGraFX parallel port interface driver for Linux.
12 */
13
14/*
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 * Should you need to contact me, the author, you can do so either by
30 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
31 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
32 */
33
34#include <linux/kernel.h>
35#include <linux/parport.h>
36#include <linux/input.h>
37#include <linux/module.h>
38#include <linux/moduleparam.h>
39#include <linux/init.h>
40
41MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
42MODULE_DESCRIPTION("TurboGraFX parallel port interface driver");
43MODULE_LICENSE("GPL");
44
45static int tgfx[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
46static int tgfx_nargs __initdata = 0;
47module_param_array_named(map, tgfx, int, &tgfx_nargs, 0);
48MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<js1>,<js2>,..<js7>");
49
50static int tgfx_2[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
51static int tgfx_nargs_2 __initdata = 0;
52module_param_array_named(map2, tgfx_2, int, &tgfx_nargs_2, 0);
53MODULE_PARM_DESC(map2, "Describes second set of devices");
54
55static int tgfx_3[] __initdata = { -1, 0, 0, 0, 0, 0, 0, 0 };
56static int tgfx_nargs_3 __initdata = 0;
57module_param_array_named(map3, tgfx_3, int, &tgfx_nargs_3, 0);
58MODULE_PARM_DESC(map3, "Describes third set of devices");
59
60__obsolete_setup("tgfx=");
61__obsolete_setup("tgfx_2=");
62__obsolete_setup("tgfx_3=");
63
64#define TGFX_REFRESH_TIME HZ/100 /* 10 ms */
65
66#define TGFX_TRIGGER 0x08
67#define TGFX_UP 0x10
68#define TGFX_DOWN 0x20
69#define TGFX_LEFT 0x40
70#define TGFX_RIGHT 0x80
71
72#define TGFX_THUMB 0x02
73#define TGFX_THUMB2 0x04
74#define TGFX_TOP 0x01
75#define TGFX_TOP2 0x08
76
77static int tgfx_buttons[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2 };
78static char *tgfx_name = "TurboGraFX Multisystem joystick";
79
80static struct tgfx {
81 struct pardevice *pd;
82 struct timer_list timer;
83 struct input_dev dev[7];
84 char phys[7][32];
85 int sticks;
86 int used;
87} *tgfx_base[3];
88
89/*
90 * tgfx_timer() reads and analyzes TurboGraFX joystick data.
91 */
92
93static void tgfx_timer(unsigned long private)
94{
95 struct tgfx *tgfx = (void *) private;
96 struct input_dev *dev;
97 int data1, data2, i;
98
99 for (i = 0; i < 7; i++)
100 if (tgfx->sticks & (1 << i)) {
101
102 dev = tgfx->dev + i;
103
104 parport_write_data(tgfx->pd->port, ~(1 << i));
105 data1 = parport_read_status(tgfx->pd->port) ^ 0x7f;
106 data2 = parport_read_control(tgfx->pd->port) ^ 0x04; /* CAVEAT parport */
107
108 input_report_abs(dev, ABS_X, !!(data1 & TGFX_RIGHT) - !!(data1 & TGFX_LEFT));
109 input_report_abs(dev, ABS_Y, !!(data1 & TGFX_DOWN ) - !!(data1 & TGFX_UP ));
110
111 input_report_key(dev, BTN_TRIGGER, (data1 & TGFX_TRIGGER));
112 input_report_key(dev, BTN_THUMB, (data2 & TGFX_THUMB ));
113 input_report_key(dev, BTN_THUMB2, (data2 & TGFX_THUMB2 ));
114 input_report_key(dev, BTN_TOP, (data2 & TGFX_TOP ));
115 input_report_key(dev, BTN_TOP2, (data2 & TGFX_TOP2 ));
116
117 input_sync(dev);
118 }
119
120 mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
121}
122
123static int tgfx_open(struct input_dev *dev)
124{
125 struct tgfx *tgfx = dev->private;
126 if (!tgfx->used++) {
127 parport_claim(tgfx->pd);
128 parport_write_control(tgfx->pd->port, 0x04);
129 mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME);
130 }
131 return 0;
132}
133
134static void tgfx_close(struct input_dev *dev)
135{
136 struct tgfx *tgfx = dev->private;
137 if (!--tgfx->used) {
138 del_timer(&tgfx->timer);
139 parport_write_control(tgfx->pd->port, 0x00);
140 parport_release(tgfx->pd);
141 }
142}
143
144/*
145 * tgfx_probe() probes for tg gamepads.
146 */
147
148static struct tgfx __init *tgfx_probe(int *config, int nargs)
149{
150 struct tgfx *tgfx;
151 struct parport *pp;
152 int i, j;
153
154 if (config[0] < 0)
155 return NULL;
156
157 if (nargs < 2) {
158 printk(KERN_ERR "turbografx.c: at least one joystick must be specified\n");
159 return NULL;
160 }
161
162 pp = parport_find_number(config[0]);
163
164 if (!pp) {
165 printk(KERN_ERR "turbografx.c: no such parport\n");
166 return NULL;
167 }
168
169 if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL))) {
170 parport_put_port(pp);
171 return NULL;
172 }
173 memset(tgfx, 0, sizeof(struct tgfx));
174
175 tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
176
177 parport_put_port(pp);
178
179 if (!tgfx->pd) {
180 printk(KERN_ERR "turbografx.c: parport busy already - lp.o loaded?\n");
181 kfree(tgfx);
182 return NULL;
183 }
184
185 init_timer(&tgfx->timer);
186 tgfx->timer.data = (long) tgfx;
187 tgfx->timer.function = tgfx_timer;
188
189 tgfx->sticks = 0;
190
191 for (i = 0; i < nargs - 1; i++)
192 if (config[i+1] > 0 && config[i+1] < 6) {
193
194 tgfx->sticks |= (1 << i);
195
196 tgfx->dev[i].private = tgfx;
197 tgfx->dev[i].open = tgfx_open;
198 tgfx->dev[i].close = tgfx_close;
199
200 sprintf(tgfx->phys[i], "%s/input0", tgfx->pd->port->name);
201
202 tgfx->dev[i].name = tgfx_name;
203 tgfx->dev[i].phys = tgfx->phys[i];
204 tgfx->dev[i].id.bustype = BUS_PARPORT;
205 tgfx->dev[i].id.vendor = 0x0003;
206 tgfx->dev[i].id.product = config[i+1];
207 tgfx->dev[i].id.version = 0x0100;
208
209 tgfx->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
210 tgfx->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
211
212 for (j = 0; j < config[i+1]; j++)
213 set_bit(tgfx_buttons[j], tgfx->dev[i].keybit);
214
215 tgfx->dev[i].absmin[ABS_X] = -1; tgfx->dev[i].absmax[ABS_X] = 1;
216 tgfx->dev[i].absmin[ABS_Y] = -1; tgfx->dev[i].absmax[ABS_Y] = 1;
217
218 input_register_device(tgfx->dev + i);
219 printk(KERN_INFO "input: %d-button Multisystem joystick on %s\n",
220 config[i+1], tgfx->pd->port->name);
221 }
222
223 if (!tgfx->sticks) {
224 parport_unregister_device(tgfx->pd);
225 kfree(tgfx);
226 return NULL;
227 }
228
229 return tgfx;
230}
231
232static int __init tgfx_init(void)
233{
234 tgfx_base[0] = tgfx_probe(tgfx, tgfx_nargs);
235 tgfx_base[1] = tgfx_probe(tgfx_2, tgfx_nargs_2);
236 tgfx_base[2] = tgfx_probe(tgfx_3, tgfx_nargs_3);
237
238 if (tgfx_base[0] || tgfx_base[1] || tgfx_base[2])
239 return 0;
240
241 return -ENODEV;
242}
243
244static void __exit tgfx_exit(void)
245{
246 int i, j;
247
248 for (i = 0; i < 3; i++)
249 if (tgfx_base[i]) {
250 for (j = 0; j < 7; j++)
251 if (tgfx_base[i]->sticks & (1 << j))
252 input_unregister_device(tgfx_base[i]->dev + j);
253 parport_unregister_device(tgfx_base[i]->pd);
254 }
255}
256
257module_init(tgfx_init);
258module_exit(tgfx_exit);
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
new file mode 100644
index 000000000000..0379bc166525
--- /dev/null
+++ b/drivers/input/joystick/twidjoy.c
@@ -0,0 +1,296 @@
1/*
2 * $Id: twidjoy.c,v 1.5 2002/01/22 20:31:53 vojtech Exp $
3 *
4 * derived from CVS-ID "stinger.c,v 1.5 2001/05/29 12:57:18 vojtech Exp"
5 *
6 * Copyright (c) 2001 Arndt Schoenewald
7 * Copyright (c) 2000-2001 Vojtech Pavlik
8 * Copyright (c) 2000 Mark Fletcher
9 *
10 * Sponsored by Quelltext AG (http://www.quelltext-ag.de), Dortmund, Germany
11 */
12
13/*
14 * Driver to use Handykey's Twiddler (the first edition, i.e. the one with
15 * the RS232 interface) as a joystick under Linux
16 *
17 * The Twiddler is a one-handed chording keyboard featuring twelve buttons on
18 * the front, six buttons on the top, and a built-in tilt sensor. The buttons
19 * on the front, which are grouped as four rows of three buttons, are pressed
20 * by the four fingers (this implies only one button per row can be held down
21 * at the same time) and the buttons on the top are for the thumb. The tilt
22 * sensor delivers X and Y axis data depending on how the Twiddler is held.
23 * Additional information can be found at http://www.handykey.com.
24 *
25 * This driver does not use the Twiddler for its intended purpose, i.e. as
26 * a chording keyboard, but as a joystick: pressing and releasing a button
27 * immediately sends a corresponding button event, and tilting it generates
28 * corresponding ABS_X and ABS_Y events. This turns the Twiddler into a game
29 * controller with amazing 18 buttons :-)
30 *
31 * Note: The Twiddler2 (the successor of the Twiddler that connects directly
32 * to the PS/2 keyboard and mouse ports) is NOT supported by this driver!
33 *
34 * For questions or feedback regarding this driver module please contact:
35 * Arndt Schoenewald <arndt@quelltext.com>
36 */
37
38/*
39 * This program is free software; you can redistribute it and/or modify
40 * it under the terms of the GNU General Public License as published by
41 * the Free Software Foundation; either version 2 of the License, or
42 * (at your option) any later version.
43 *
44 * This program is distributed in the hope that it will be useful,
45 * but WITHOUT ANY WARRANTY; without even the implied warranty of
46 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47 * GNU General Public License for more details.
48 *
49 * You should have received a copy of the GNU General Public License
50 * along with this program; if not, write to the Free Software
51 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
52 */
53
54#include <linux/kernel.h>
55#include <linux/module.h>
56#include <linux/slab.h>
57#include <linux/input.h>
58#include <linux/serio.h>
59#include <linux/init.h>
60
61#define DRIVER_DESC "Handykey Twiddler keyboard as a joystick driver"
62
63MODULE_DESCRIPTION(DRIVER_DESC);
64MODULE_LICENSE("GPL");
65
66/*
67 * Constants.
68 */
69
70#define TWIDJOY_MAX_LENGTH 5
71
72static char *twidjoy_name = "Handykey Twiddler";
73
74static struct twidjoy_button_spec {
75 int bitshift;
76 int bitmask;
77 int buttons[3];
78}
79twidjoy_buttons[] = {
80 { 0, 3, { BTN_A, BTN_B, BTN_C } },
81 { 2, 3, { BTN_X, BTN_Y, BTN_Z } },
82 { 4, 3, { BTN_TL, BTN_TR, BTN_TR2 } },
83 { 6, 3, { BTN_SELECT, BTN_START, BTN_MODE } },
84 { 8, 1, { BTN_BASE5 } },
85 { 9, 1, { BTN_BASE } },
86 { 10, 1, { BTN_BASE3 } },
87 { 11, 1, { BTN_BASE4 } },
88 { 12, 1, { BTN_BASE2 } },
89 { 13, 1, { BTN_BASE6 } },
90 { 0, 0, { 0 } }
91};
92
93/*
94 * Per-Twiddler data.
95 */
96
97struct twidjoy {
98 struct input_dev dev;
99 int idx;
100 unsigned char data[TWIDJOY_MAX_LENGTH];
101 char phys[32];
102};
103
104/*
105 * twidjoy_process_packet() decodes packets the driver receives from the
106 * Twiddler. It updates the data accordingly.
107 */
108
109static void twidjoy_process_packet(struct twidjoy *twidjoy, struct pt_regs *regs)
110{
111 if (twidjoy->idx == TWIDJOY_MAX_LENGTH) {
112 struct input_dev *dev = &twidjoy->dev;
113 unsigned char *data = twidjoy->data;
114 struct twidjoy_button_spec *bp;
115 int button_bits, abs_x, abs_y;
116
117 button_bits = ((data[1] & 0x7f) << 7) | (data[0] & 0x7f);
118
119 input_regs(dev, regs);
120
121 for (bp = twidjoy_buttons; bp->bitmask; bp++) {
122 int value = (button_bits & (bp->bitmask << bp->bitshift)) >> bp->bitshift;
123 int i;
124
125 for (i = 0; i < bp->bitmask; i++)
126 input_report_key(dev, bp->buttons[i], i+1 == value);
127 }
128
129 abs_x = ((data[4] & 0x07) << 5) | ((data[3] & 0x7C) >> 2);
130 if (data[4] & 0x08) abs_x -= 256;
131
132 abs_y = ((data[3] & 0x01) << 7) | ((data[2] & 0x7F) >> 0);
133 if (data[3] & 0x02) abs_y -= 256;
134
135 input_report_abs(dev, ABS_X, -abs_x);
136 input_report_abs(dev, ABS_Y, +abs_y);
137
138 input_sync(dev);
139 }
140
141 return;
142}
143
144/*
145 * twidjoy_interrupt() is called by the low level driver when characters
146 * are ready for us. We then buffer them for further processing, or call the
147 * packet processing routine.
148 */
149
150static irqreturn_t twidjoy_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs)
151{
152 struct twidjoy *twidjoy = serio_get_drvdata(serio);
153
154 /* All Twiddler packets are 5 bytes. The fact that the first byte
155 * has a MSB of 0 and all other bytes have a MSB of 1 can be used
156 * to check and regain sync. */
157
158 if ((data & 0x80) == 0)
159 twidjoy->idx = 0; /* this byte starts a new packet */
160 else if (twidjoy->idx == 0)
161 return IRQ_HANDLED; /* wrong MSB -- ignore this byte */
162
163 if (twidjoy->idx < TWIDJOY_MAX_LENGTH)
164 twidjoy->data[twidjoy->idx++] = data;
165
166 if (twidjoy->idx == TWIDJOY_MAX_LENGTH) {
167 twidjoy_process_packet(twidjoy, regs);
168 twidjoy->idx = 0;
169 }
170
171 return IRQ_HANDLED;
172}
173
174/*
175 * twidjoy_disconnect() is the opposite of twidjoy_connect()
176 */
177
178static void twidjoy_disconnect(struct serio *serio)
179{
180 struct twidjoy *twidjoy = serio_get_drvdata(serio);
181
182 input_unregister_device(&twidjoy->dev);
183 serio_close(serio);
184 serio_set_drvdata(serio, NULL);
185 kfree(twidjoy);
186}
187
188/*
189 * twidjoy_connect() is the routine that is called when someone adds a
190 * new serio device. It looks for the Twiddler, and if found, registers
191 * it as an input device.
192 */
193
194static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
195{
196 struct twidjoy_button_spec *bp;
197 struct twidjoy *twidjoy;
198 int i;
199 int err;
200
201 if (!(twidjoy = kmalloc(sizeof(struct twidjoy), GFP_KERNEL)))
202 return -ENOMEM;
203
204 memset(twidjoy, 0, sizeof(struct twidjoy));
205
206 sprintf(twidjoy->phys, "%s/input0", serio->phys);
207
208 init_input_dev(&twidjoy->dev);
209 twidjoy->dev.name = twidjoy_name;
210 twidjoy->dev.phys = twidjoy->phys;
211 twidjoy->dev.id.bustype = BUS_RS232;
212 twidjoy->dev.id.vendor = SERIO_TWIDJOY;
213 twidjoy->dev.id.product = 0x0001;
214 twidjoy->dev.id.version = 0x0100;
215 twidjoy->dev.dev = &serio->dev;
216
217 twidjoy->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
218
219 for (bp = twidjoy_buttons; bp->bitmask; bp++) {
220 for (i = 0; i < bp->bitmask; i++)
221 set_bit(bp->buttons[i], twidjoy->dev.keybit);
222 }
223
224 twidjoy->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
225
226 for (i = 0; i < 2; i++) {
227 twidjoy->dev.absmax[ABS_X+i] = 50;
228 twidjoy->dev.absmin[ABS_X+i] = -50;
229
230 /* TODO: arndt 20010708: Are these values appropriate? */
231 twidjoy->dev.absfuzz[ABS_X+i] = 4;
232 twidjoy->dev.absflat[ABS_X+i] = 4;
233 }
234
235 twidjoy->dev.private = twidjoy;
236
237 serio_set_drvdata(serio, twidjoy);
238
239 err = serio_open(serio, drv);
240 if (err) {
241 serio_set_drvdata(serio, NULL);
242 kfree(twidjoy);
243 return err;
244 }
245
246 input_register_device(&twidjoy->dev);
247
248 printk(KERN_INFO "input: %s on %s\n", twidjoy_name, serio->phys);
249
250 return 0;
251}
252
253/*
254 * The serio driver structure.
255 */
256
257static struct serio_device_id twidjoy_serio_ids[] = {
258 {
259 .type = SERIO_RS232,
260 .proto = SERIO_TWIDJOY,
261 .id = SERIO_ANY,
262 .extra = SERIO_ANY,
263 },
264 { 0 }
265};
266
267MODULE_DEVICE_TABLE(serio, twidjoy_serio_ids);
268
269static struct serio_driver twidjoy_drv = {
270 .driver = {
271 .name = "twidjoy",
272 },
273 .description = DRIVER_DESC,
274 .id_table = twidjoy_serio_ids,
275 .interrupt = twidjoy_interrupt,
276 .connect = twidjoy_connect,
277 .disconnect = twidjoy_disconnect,
278};
279
280/*
281 * The functions for inserting/removing us as a module.
282 */
283
284int __init twidjoy_init(void)
285{
286 serio_register_driver(&twidjoy_drv);
287 return 0;
288}
289
290void __exit twidjoy_exit(void)
291{
292 serio_unregister_driver(&twidjoy_drv);
293}
294
295module_init(twidjoy_init);
296module_exit(twidjoy_exit);
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
new file mode 100644
index 000000000000..6976a219504c
--- /dev/null
+++ b/drivers/input/joystick/warrior.c
@@ -0,0 +1,248 @@
1/*
2 * $Id: warrior.c,v 1.14 2002/01/22 20:32:10 vojtech Exp $
3 *
4 * Copyright (c) 1999-2001 Vojtech Pavlik
5 */
6
7/*
8 * Logitech WingMan Warrior joystick driver for Linux
9 */
10
11/*
12 * This program is free warftware; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 * Should you need to contact me, the author, you can do so either by
27 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29 */
30
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/slab.h>
34#include <linux/input.h>
35#include <linux/serio.h>
36#include <linux/init.h>
37
38#define DRIVER_DESC "Logitech WingMan Warrior joystick driver"
39
40MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
41MODULE_DESCRIPTION(DRIVER_DESC);
42MODULE_LICENSE("GPL");
43
44/*
45 * Constants.
46 */
47
48#define WARRIOR_MAX_LENGTH 16
49static char warrior_lengths[] = { 0, 4, 12, 3, 4, 4, 0, 0 };
50static char *warrior_name = "Logitech WingMan Warrior";
51
52/*
53 * Per-Warrior data.
54 */
55
56struct warrior {
57 struct input_dev dev;
58 int idx, len;
59 unsigned char data[WARRIOR_MAX_LENGTH];
60 char phys[32];
61};
62
63/*
64 * warrior_process_packet() decodes packets the driver receives from the
65 * Warrior. It updates the data accordingly.
66 */
67
68static void warrior_process_packet(struct warrior *warrior, struct pt_regs *regs)
69{
70 struct input_dev *dev = &warrior->dev;
71 unsigned char *data = warrior->data;
72
73 if (!warrior->idx) return;
74
75 input_regs(dev, regs);
76
77 switch ((data[0] >> 4) & 7) {
78 case 1: /* Button data */
79 input_report_key(dev, BTN_TRIGGER, data[3] & 1);
80 input_report_key(dev, BTN_THUMB, (data[3] >> 1) & 1);
81 input_report_key(dev, BTN_TOP, (data[3] >> 2) & 1);
82 input_report_key(dev, BTN_TOP2, (data[3] >> 3) & 1);
83 break;
84 case 3: /* XY-axis info->data */
85 input_report_abs(dev, ABS_X, ((data[0] & 8) << 5) - (data[2] | ((data[0] & 4) << 5)));
86 input_report_abs(dev, ABS_Y, (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7));
87 break;
88 case 5: /* Throttle, spinner, hat info->data */
89 input_report_abs(dev, ABS_THROTTLE, (data[1] | ((data[0] & 1) << 7)) - ((data[0] & 2) << 7));
90 input_report_abs(dev, ABS_HAT0X, (data[3] & 2 ? 1 : 0) - (data[3] & 1 ? 1 : 0));
91 input_report_abs(dev, ABS_HAT0Y, (data[3] & 8 ? 1 : 0) - (data[3] & 4 ? 1 : 0));
92 input_report_rel(dev, REL_DIAL, (data[2] | ((data[0] & 4) << 5)) - ((data[0] & 8) << 5));
93 break;
94 }
95 input_sync(dev);
96}
97
98/*
99 * warrior_interrupt() is called by the low level driver when characters
100 * are ready for us. We then buffer them for further processing, or call the
101 * packet processing routine.
102 */
103
104static irqreturn_t warrior_interrupt(struct serio *serio,
105 unsigned char data, unsigned int flags, struct pt_regs *regs)
106{
107 struct warrior *warrior = serio_get_drvdata(serio);
108
109 if (data & 0x80) {
110 if (warrior->idx) warrior_process_packet(warrior, regs);
111 warrior->idx = 0;
112 warrior->len = warrior_lengths[(data >> 4) & 7];
113 }
114
115 if (warrior->idx < warrior->len)
116 warrior->data[warrior->idx++] = data;
117
118 if (warrior->idx == warrior->len) {
119 if (warrior->idx) warrior_process_packet(warrior, regs);
120 warrior->idx = 0;
121 warrior->len = 0;
122 }
123 return IRQ_HANDLED;
124}
125
126/*
127 * warrior_disconnect() is the opposite of warrior_connect()
128 */
129
130static void warrior_disconnect(struct serio *serio)
131{
132 struct warrior *warrior = serio_get_drvdata(serio);
133
134 input_unregister_device(&warrior->dev);
135 serio_close(serio);
136 serio_set_drvdata(serio, NULL);
137 kfree(warrior);
138}
139
140/*
141 * warrior_connect() is the routine that is called when someone adds a
142 * new serio device. It looks for the Warrior, and if found, registers
143 * it as an input device.
144 */
145
146static int warrior_connect(struct serio *serio, struct serio_driver *drv)
147{
148 struct warrior *warrior;
149 int i;
150 int err;
151
152 if (!(warrior = kmalloc(sizeof(struct warrior), GFP_KERNEL)))
153 return -ENOMEM;
154
155 memset(warrior, 0, sizeof(struct warrior));
156
157 warrior->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
158 warrior->dev.keybit[LONG(BTN_TRIGGER)] = BIT(BTN_TRIGGER) | BIT(BTN_THUMB) | BIT(BTN_TOP) | BIT(BTN_TOP2);
159 warrior->dev.relbit[0] = BIT(REL_DIAL);
160 warrior->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y);
161
162 sprintf(warrior->phys, "%s/input0", serio->phys);
163
164 init_input_dev(&warrior->dev);
165 warrior->dev.name = warrior_name;
166 warrior->dev.phys = warrior->phys;
167 warrior->dev.id.bustype = BUS_RS232;
168 warrior->dev.id.vendor = SERIO_WARRIOR;
169 warrior->dev.id.product = 0x0001;
170 warrior->dev.id.version = 0x0100;
171 warrior->dev.dev = &serio->dev;
172
173 for (i = 0; i < 2; i++) {
174 warrior->dev.absmax[ABS_X+i] = -64;
175 warrior->dev.absmin[ABS_X+i] = 64;
176 warrior->dev.absflat[ABS_X+i] = 8;
177 }
178
179 warrior->dev.absmax[ABS_THROTTLE] = -112;
180 warrior->dev.absmin[ABS_THROTTLE] = 112;
181
182 for (i = 0; i < 2; i++) {
183 warrior->dev.absmax[ABS_HAT0X+i] = -1;
184 warrior->dev.absmin[ABS_HAT0X+i] = 1;
185 }
186
187 warrior->dev.private = warrior;
188
189 serio_set_drvdata(serio, warrior);
190
191 err = serio_open(serio, drv);
192 if (err) {
193 serio_set_drvdata(serio, NULL);
194 kfree(warrior);
195 return err;
196 }
197
198 input_register_device(&warrior->dev);
199
200 printk(KERN_INFO "input: Logitech WingMan Warrior on %s\n", serio->phys);
201
202 return 0;
203}
204
205/*
206 * The serio driver structure.
207 */
208
209static struct serio_device_id warrior_serio_ids[] = {
210 {
211 .type = SERIO_RS232,
212 .proto = SERIO_WARRIOR,
213 .id = SERIO_ANY,
214 .extra = SERIO_ANY,
215 },
216 { 0 }
217};
218
219MODULE_DEVICE_TABLE(serio, warrior_serio_ids);
220
221static struct serio_driver warrior_drv = {
222 .driver = {
223 .name = "warrior",
224 },
225 .description = DRIVER_DESC,
226 .id_table = warrior_serio_ids,
227 .interrupt = warrior_interrupt,
228 .connect = warrior_connect,
229 .disconnect = warrior_disconnect,
230};
231
232/*
233 * The functions for inserting/removing us as a module.
234 */
235
236static int __init warrior_init(void)
237{
238 serio_register_driver(&warrior_drv);
239 return 0;
240}
241
242static void __exit warrior_exit(void)
243{
244 serio_unregister_driver(&warrior_drv);
245}
246
247module_init(warrior_init);
248module_exit(warrior_exit);