Import 2.4.0-test2pre7
[davej-history.git] / drivers / char / joystick / tmdc.c
blobf356f7dd5c2c92dc8ee4b33a620d336f605bd0be
1 /*
2 * $Id: tmdc.c,v 1.18 2000/06/08 19:59:59 vojtech Exp $
4 * Copyright (c) 1998-2000 Vojtech Pavlik
6 * Sponsored by SuSE
8 * Based on the work of:
9 * Trystan Larey-Williams
14 * ThrustMaster DirectConnect (BSP) joystick family driver for Linux
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 * Should you need to contact me, the author, you can do so either by
33 * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
34 * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
37 #include <linux/delay.h>
38 #include <linux/kernel.h>
39 #include <linux/malloc.h>
40 #include <linux/module.h>
41 #include <linux/init.h>
42 #include <linux/gameport.h>
43 #include <linux/input.h>
45 #define TMDC_MAX_START 400 /* 400 us */
46 #define TMDC_MAX_STROBE 45 /* 45 us */
47 #define TMDC_MAX_LENGTH 13
48 #define TMDC_REFRESH_TIME HZ/50 /* 20 ms */
50 #define TMDC_MODE_M3DI 1
51 #define TMDC_MODE_3DRP 3
52 #define TMDC_MODE_FGP 163
54 #define TMDC_BYTE_ID 10
55 #define TMDC_BYTE_REV 11
56 #define TMDC_BYTE_DEF 12
58 #define TMDC_ABS 7
59 #define TMDC_ABS_HAT 4
60 #define TMDC_BTN_PAD 10
61 #define TMDC_BTN_JOY 16
63 static unsigned char tmdc_byte_a[16] = { 0, 1, 3, 4, 6, 7 };
64 static unsigned char tmdc_byte_d[16] = { 2, 5, 8, 9 };
66 static unsigned char tmdc_abs[TMDC_ABS] =
67 { ABS_X, ABS_Y, ABS_RUDDER, ABS_THROTTLE, ABS_RX, ABS_RY, ABS_RZ };
68 static unsigned char tmdc_abs_hat[TMDC_ABS_HAT] =
69 { ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };
70 static unsigned short tmdc_btn_pad[TMDC_BTN_PAD] =
71 { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR };
72 static unsigned short tmdc_btn_joy[TMDC_BTN_JOY] =
73 { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE,
74 BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z };
76 struct tmdc {
77 struct gameport *gameport;
78 struct timer_list timer;
79 struct input_dev dev[2];
80 char name[2][64];
81 int mode[2];
82 int used;
83 int reads;
84 int bads;
85 unsigned char exists;
89 * tmdc_read_packet() reads a ThrustMaster packet.
92 static int tmdc_read_packet(struct gameport *gameport, unsigned char data[2][TMDC_MAX_LENGTH])
94 unsigned char u, v, w, x;
95 unsigned long flags;
96 int i[2], j[2], t[2], p, k;
98 p = gameport_time(gameport, TMDC_MAX_STROBE);
100 for (k = 0; k < 2; k++) {
101 t[k] = gameport_time(gameport, TMDC_MAX_START);
102 i[k] = j[k] = 0;
105 __save_flags(flags);
106 __cli();
107 gameport_trigger(gameport);
109 w = gameport_read(gameport) >> 4;
111 do {
112 x = w;
113 w = gameport_read(gameport) >> 4;
115 for (k = 0, v = w, u = x; k < 2; k++, v >>= 2, u >>= 2) {
116 if (~v & u & 2) {
117 if (t[k] <= 0 || i[k] >= TMDC_MAX_LENGTH) continue;
118 t[k] = p;
119 if (j[k] == 0) { /* Start bit */
120 if (~v & 1) t[k] = 0;
121 data[k][i[k]] = 0; j[k]++; continue;
123 if (j[k] == 9) { /* Stop bit */
124 if (v & 1) t[k] = 0;
125 j[k] = 0; i[k]++; continue;
127 data[k][i[k]] |= (~v & 1) << (j[k]++ - 1); /* Data bit */
129 t[k]--;
131 } while (t[0] > 0 || t[1] > 0);
133 __restore_flags(flags);
135 return (i[0] == TMDC_MAX_LENGTH) | ((i[1] == TMDC_MAX_LENGTH) << 1);
139 * tmdc_read() reads and analyzes ThrustMaster joystick data.
142 static void tmdc_timer(unsigned long private)
144 unsigned char data[2][TMDC_MAX_LENGTH];
145 struct tmdc *tmdc = (void *) private;
146 struct input_dev *dev;
147 unsigned char r, bad = 0;
148 int i, j;
150 tmdc->reads++;
152 if ((r = tmdc_read_packet(tmdc->gameport, data)) != tmdc->exists)
153 bad = 1;
155 for (j = 0; j < 2; j++)
156 if (r & (1 << j) & tmdc->exists) {
158 if (data[j][TMDC_BYTE_ID] != tmdc->mode[j]) {
159 bad = 1;
160 continue;
163 dev = tmdc->dev + j;
165 for (i = 0; i < data[j][TMDC_BYTE_DEF] >> 4; i++)
166 input_report_abs(dev, tmdc_abs[i], data[j][tmdc_byte_a[i]]);
168 switch (tmdc->mode[j]) {
170 case TMDC_MODE_M3DI:
172 i = tmdc_byte_d[0];
174 input_report_abs(dev, ABS_HAT0X, ((data[j][i] >> 3) & 1) - ((data[j][i] >> 1) & 1));
175 input_report_abs(dev, ABS_HAT0Y, ((data[j][i] >> 2) & 1) - ( data[j][i] & 1));
177 for (i = 0; i < 4; i++)
178 input_report_key(dev, tmdc_btn_joy[i],
179 (data[j][tmdc_byte_d[0]] >> (i + 4)) & 1);
180 for (i = 0; i < 2; i++)
181 input_report_key(dev, tmdc_btn_joy[i + 4],
182 (data[j][tmdc_byte_d[1]] >> (i + 6)) & 1);
184 break;
186 case TMDC_MODE_3DRP:
187 case TMDC_MODE_FGP:
189 for (i = 0; i < 10; i++)
190 input_report_key(dev, tmdc_btn_pad[i],
191 (data[j][tmdc_byte_d[i >> 3]] >> (i & 7)) & 1);
193 break;
195 default:
197 for (i = 0; i < ((data[j][TMDC_BYTE_DEF] & 0xf) << 3) && i < TMDC_BTN_JOY; i++)
198 input_report_key(dev, tmdc_btn_joy[i],
199 (data[j][tmdc_byte_d[i >> 3]] >> (i & 7)) & 1);
201 break;
206 tmdc->bads += bad;
208 mod_timer(&tmdc->timer, jiffies + TMDC_REFRESH_TIME);
211 static int tmdc_open(struct input_dev *dev)
213 struct tmdc *tmdc = dev->private;
214 if (!tmdc->used++)
215 mod_timer(&tmdc->timer, jiffies + TMDC_REFRESH_TIME);
216 return 0;
219 static void tmdc_close(struct input_dev *dev)
221 struct tmdc *tmdc = dev->private;
222 if (!--tmdc->used)
223 del_timer(&tmdc->timer);
227 * tmdc_probe() probes for ThrustMaster type joysticks.
230 static void tmdc_connect(struct gameport *gameport, struct gameport_dev *dev)
232 struct tmdc *tmdc;
233 struct js_tm_models {
234 unsigned char id;
235 char *name;
236 char abs;
237 char hats;
238 char joybtn;
239 char padbtn;
240 } models[] = { { 1, "ThrustMaster Millenium 3D Inceptor", 6, 0, 6, 0 },
241 { 3, "ThrustMaster Rage 3D Gamepad", 2, 0, 0, 10 },
242 { 163, "Thrustmaster Fusion GamePad", 2, 0, 0, 10 },
243 { 0, "Unknown %d-axis, %d-button TM device %d", 0, 0, 0, 0 }};
244 unsigned char data[2][TMDC_MAX_LENGTH];
245 int i, j, m;
247 if (!(tmdc = kmalloc(sizeof(struct tmdc), GFP_KERNEL)))
248 return;
249 memset(tmdc, 0, sizeof(struct tmdc));
251 gameport->private = tmdc;
253 tmdc->gameport = gameport;
254 init_timer(&tmdc->timer);
255 tmdc->timer.data = (long) tmdc;
256 tmdc->timer.function = tmdc_timer;
258 if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
259 goto fail1;
261 if (!(tmdc->exists = tmdc_read_packet(gameport, data)))
262 goto fail2;
264 for (j = 0; j < 2; j++)
265 if (tmdc->exists & (1 << j)) {
267 tmdc->mode[j] = data[j][TMDC_BYTE_ID];
269 for (m = 0; models[m].id && models[m].id != tmdc->mode[j]; m++);
271 if (!models[m].id) {
272 models[m].abs = data[j][TMDC_BYTE_DEF] >> 4;
273 models[m].joybtn = (data[j][TMDC_BYTE_DEF] & 0xf) << 3;
276 sprintf(tmdc->name[j], models[m].name, models[m].abs, models[m].joybtn, tmdc->mode[j]);
278 tmdc->dev[j].private = tmdc;
279 tmdc->dev[j].open = tmdc_open;
280 tmdc->dev[j].close = tmdc_close;
282 tmdc->dev[j].name = tmdc->name[j];
283 tmdc->dev[j].idbus = BUS_GAMEPORT;
284 tmdc->dev[j].idvendor = GAMEPORT_ID_VENDOR_THRUSTMASTER;
285 tmdc->dev[j].idproduct = models[m].id;
286 tmdc->dev[j].idversion = 0x0100;
288 tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
290 for (i = 0; i < models[m].abs && i < TMDC_ABS; i++) {
291 set_bit(tmdc_abs[i], tmdc->dev[j].absbit);
292 tmdc->dev[j].absmin[tmdc_abs[i]] = 8;
293 tmdc->dev[j].absmax[tmdc_abs[i]] = 248;
294 tmdc->dev[j].absfuzz[tmdc_abs[i]] = 2;
295 tmdc->dev[j].absflat[tmdc_abs[i]] = 4;
298 for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++) {
299 set_bit(tmdc_abs_hat[i], tmdc->dev[j].absbit);
300 tmdc->dev[j].absmin[tmdc_abs_hat[i]] = -1;
301 tmdc->dev[j].absmax[tmdc_abs_hat[i]] = 1;
304 for (i = 0; i < models[m].joybtn && i < TMDC_BTN_JOY; i++)
305 set_bit(tmdc_btn_joy[i], tmdc->dev[j].keybit);
307 for (i = 0; i < models[m].padbtn && i < TMDC_BTN_PAD; i++)
308 set_bit(tmdc_btn_pad[i], tmdc->dev[j].keybit);
310 input_register_device(tmdc->dev + j);
311 printk(KERN_INFO "input%d: %s on gameport%d.%d\n",
312 tmdc->dev[j].number, tmdc->name[j], gameport->number, j);
315 return;
316 fail2: gameport_close(gameport);
317 fail1: kfree(tmdc);
320 static void tmdc_disconnect(struct gameport *gameport)
322 struct tmdc *tmdc = gameport->private;
323 int i;
324 for (i = 0; i < 2; i++)
325 if (tmdc->exists & (1 << i))
326 input_unregister_device(tmdc->dev + i);
327 gameport_close(gameport);
328 kfree(tmdc);
331 static struct gameport_dev tmdc_dev = {
332 connect: tmdc_connect,
333 disconnect: tmdc_disconnect,
336 int __init tmdc_init(void)
338 gameport_register_device(&tmdc_dev);
339 return 0;
342 void __exit tmdc_exit(void)
344 gameport_unregister_device(&tmdc_dev);
347 module_init(tmdc_init);
348 module_exit(tmdc_exit);