* add p cc
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / char / joystick / joy-gravis.c
blob9185d3113d72dc55874c0a15b015964f4f13b190
1 /*
2 * joy-gravis.c Version 1.2
4 * Copyright (c) 1998 Vojtech Pavlik
5 */
7 /*
8 * This is a module for the Linux joystick driver, supporting
9 * Gravis GrIP digital joystick family.
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.
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.
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
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, Ucitelska 1576, Prague 8, 182 00 Czech Republic
32 #include <asm/io.h>
33 #include <asm/system.h>
34 #include <linux/errno.h>
35 #include <linux/ioport.h>
36 #include <linux/joystick.h>
37 #include <linux/kernel.h>
38 #include <linux/module.h>
39 #include <linux/string.h>
41 #define JS_GR_MODE_GPP 1
42 #define JS_GR_LENGTH_GPP 24
43 #define JS_GR_STROBE_GPP 75
45 #define JS_GR_MODE_XT 2
46 #define JS_GR_MODE_BD 3
47 #define JS_GR_LENGTH_XT 4
48 #define JS_GR_STROBE_XT 30
49 #define JS_GR_MAX_CHUNKS_XT 10
50 #define JS_GR_MAX_BITS_XT 30
52 static int js_gr_port_list[] __initdata = {0x201, 0};
53 static struct js_port* js_gr_port __initdata = NULL;
55 struct js_gr_info {
56 int io;
57 unsigned char mode[2];
61 * js_gr_gpp_read_packet() reads a Gravis GamePad Pro packet.
64 static int js_gr_gpp_read_packet(int io, int shift, unsigned int *data)
66 unsigned int t, t1;
67 unsigned char u, v;
68 int i;
69 unsigned long flags;
71 int strobe = (js_time_speed * JS_GR_STROBE_GPP) >> 10;
73 i = 0;
74 data[0] = 0;
76 __save_flags(flags);
77 __cli();
78 u = inb(io) >> shift;
79 t = js_get_time();
81 do {
82 v = (inb(io) >> shift) & 3;
83 t1 = js_get_time();
84 if ((u ^ v) & u & 1) {
85 data[0] |= (v >> 1) << i++;
86 t = t1;
88 u = v;
89 } while (i < JS_GR_LENGTH_GPP && js_delta(t1,t) < strobe);
91 __restore_flags(flags);
93 if (i < JS_GR_LENGTH_GPP) return -1;
95 for (i = 0; i < JS_GR_LENGTH_GPP && (data[0] & 0xfe4210) ^ 0x7c0000; i++)
96 data[0] = data[0] >> 1 | (data[0] & 1) << 23;
98 return -(i == JS_GR_LENGTH_GPP);
102 * js_gr_xt_read_packet() reads a Gravis Xterminator packet.
105 static int js_gr_xt_read_packet(int io, int shift, unsigned int *data)
107 unsigned int t, t1;
108 unsigned char u, v, w;
109 unsigned int i, j, buf, crc;
110 unsigned long flags;
111 char status;
113 int strobe = (js_time_speed * JS_GR_STROBE_XT) >> 10;
115 data[0] = data[1] = data[2] = data[3] = 0;
116 status = buf = i = j = 0;
118 __save_flags(flags);
119 __cli();
121 v = w = (inb(io) >> shift) & 3;
122 t = js_get_time();
124 do {
125 u = (inb(io) >> shift) & 3;
126 t1 = js_get_time();
128 if (u ^ v) {
130 if ((u ^ v) & 1) {
131 buf = (buf << 1) | (u >> 1);
132 i++;
133 } else
135 if ((((u ^ v) & (v ^ w)) >> 1) & ~(u | v | w) & 1) {
136 if (i == 20) {
137 crc = buf ^ (buf >> 7) ^ (buf >> 14);
138 if (!((crc ^ (0x25cb9e70 >> ((crc >> 2) & 0x1c))) & 0xf)) {
139 data[buf >> 18] = buf >> 4;
140 status |= 1 << (buf >> 18);
142 j++;
144 buf = 0;
145 i = 0;
148 t = t1;
149 w = v;
150 v = u;
153 } while (status != 0xf && i < JS_GR_MAX_BITS_XT && j < JS_GR_MAX_CHUNKS_XT && js_delta(t1,t) < strobe);
155 __restore_flags(flags);
157 return -(status != 0xf);
161 * js_gr_read() reads and analyzes GrIP joystick data.
164 static int js_gr_read(void *xinfo, int **axes, int **buttons)
166 struct js_gr_info *info = xinfo;
167 unsigned int data[JS_GR_LENGTH_XT];
168 int i;
170 for (i = 0; i < 2; i++)
171 switch (info->mode[i]) {
173 case JS_GR_MODE_GPP:
175 if (js_gr_gpp_read_packet(info->io, (i << 1) + 4, data)) return -1;
177 axes[i][0] = ((data[0] >> 15) & 1) - ((data[0] >> 16) & 1);
178 axes[i][1] = ((data[0] >> 13) & 1) - ((data[0] >> 12) & 1);
180 data[0] = ((data[0] >> 6) & 0x37) | (data[0] & 0x08) | ((data[0] << 1) & 0x40) |
181 ((data[0] << 5) & 0x80) | ((data[0] << 8) & 0x300);
183 buttons[i][0] = (data[0] & 0xfc) | ((data[0] >> 1) & 0x101) | ((data[0] << 1) & 0x202);
185 break;
187 case JS_GR_MODE_XT:
189 if (js_gr_xt_read_packet(info->io, (i << 1) + 4, data)) return -1;
191 axes[i][0] = (data[0] >> 2) & 0x3f;
192 axes[i][1] = 63 - ((data[0] >> 8) & 0x3f);
193 axes[i][2] = (data[1] >> 2) & 0x3f;
194 axes[i][3] = (data[1] >> 8) & 0x3f;
195 axes[i][4] = (data[2] >> 8) & 0x3f;
197 axes[i][5] = ((data[2] >> 1) & 1) - ( data[2] & 1);
198 axes[i][6] = ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1);
199 axes[i][7] = ((data[2] >> 5) & 1) - ((data[2] >> 4) & 1);
200 axes[i][8] = ((data[2] >> 6) & 1) - ((data[2] >> 7) & 1);
202 buttons[i][0] = (data[3] >> 3) & 0x7ff;
204 break;
206 case JS_GR_MODE_BD:
208 if (js_gr_xt_read_packet(info->io, (i << 1) + 4, data)) return -1;
210 axes[i][0] = (data[0] >> 2) & 0x3f;
211 axes[i][1] = 63 - ((data[0] >> 8) & 0x3f);
212 axes[i][2] = (data[2] >> 8) & 0x3f;
214 axes[i][3] = ((data[2] >> 1) & 1) - ( data[2] & 1);
215 axes[i][4] = ((data[2] >> 2) & 1) - ((data[2] >> 3) & 1);
217 buttons[i][0] = ((data[3] >> 6) & 0x01) | ((data[3] >> 3) & 0x06)
218 | ((data[3] >> 4) & 0x18);
220 break;
222 default:
223 break;
228 return 0;
232 * js_gr_open() is a callback from the file open routine.
235 static int js_gr_open(struct js_dev *jd)
237 MOD_INC_USE_COUNT;
238 return 0;
242 * js_gr_close() is a callback from the file release routine.
245 static int js_gr_close(struct js_dev *jd)
247 MOD_DEC_USE_COUNT;
248 return 0;
252 * js_gr_init_corr() initializes correction values of
253 * GrIP joysticks.
256 static void __init js_gr_init_corr(int mode, struct js_corr *corr)
258 int i;
260 switch (mode) {
262 case JS_GR_MODE_GPP:
264 for (i = 0; i < 2; i++) {
265 corr[i].type = JS_CORR_BROKEN;
266 corr[i].prec = 0;
267 corr[i].coef[0] = 0;
268 corr[i].coef[1] = 0;
269 corr[i].coef[2] = (1 << 29);
270 corr[i].coef[3] = (1 << 29);
273 break;
275 case JS_GR_MODE_XT:
277 for (i = 0; i < 5; i++) {
278 corr[i].type = JS_CORR_BROKEN;
279 corr[i].prec = 0;
280 corr[i].coef[0] = 31 - 4;
281 corr[i].coef[1] = 32 + 4;
282 corr[i].coef[2] = (1 << 29) / (32 - 14);
283 corr[i].coef[3] = (1 << 29) / (32 - 14);
286 for (i = 5; i < 9; i++) {
287 corr[i].type = JS_CORR_BROKEN;
288 corr[i].prec = 0;
289 corr[i].coef[0] = 0;
290 corr[i].coef[1] = 0;
291 corr[i].coef[2] = (1 << 29);
292 corr[i].coef[3] = (1 << 29);
295 break;
297 case JS_GR_MODE_BD:
299 for (i = 0; i < 3; i++) {
300 corr[i].type = JS_CORR_BROKEN;
301 corr[i].prec = 0;
302 corr[i].coef[0] = 31 - 4;
303 corr[i].coef[1] = 32 + 4;
304 corr[i].coef[2] = (1 << 29) / (32 - 14);
305 corr[i].coef[3] = (1 << 29) / (32 - 14);
308 for (i = 3; i < 5; i++) {
309 corr[i].type = JS_CORR_BROKEN;
310 corr[i].prec = 0;
311 corr[i].coef[0] = 0;
312 corr[i].coef[1] = 0;
313 corr[i].coef[2] = (1 << 29);
314 corr[i].coef[3] = (1 << 29);
317 break;
323 * js_gr_probe() probes fro GrIP joysticks.
326 static struct js_port __init *js_gr_probe(int io, struct js_port *port)
328 struct js_gr_info info;
329 char *names[] = { NULL, "Gravis GamePad Pro", "Gravis Xterminator", "Gravis Blackhawk Digital"};
330 char axes[] = { 0, 2, 9, 5};
331 char buttons[] = { 0, 10, 11, 5};
332 unsigned int data[JS_GR_LENGTH_XT];
333 int i;
335 if (check_region(io, 1)) return port;
337 info.mode[0] = info.mode[1] = 0;
339 for (i = 0; i < 2; i++) {
340 if (!js_gr_gpp_read_packet(io, (i << 1) + 4, data)) info.mode[i] = JS_GR_MODE_GPP;
341 if (!js_gr_xt_read_packet(io, (i << 1) + 4, data)) {
342 if ((data[3] & 7) == 7)
343 info.mode[i] = JS_GR_MODE_XT;
344 if ((data[3] & 7) == 0)
345 info.mode[i] = JS_GR_MODE_BD;
349 if (!info.mode[0] && !info.mode[1]) return port;
351 info.io = io;
353 request_region(io, 1, "joystick (gravis)");
354 port = js_register_port(port, &info, 2, sizeof(struct js_gr_info), js_gr_read);
356 for (i = 0; i < 2; i++)
357 if (info.mode[i]) {
358 printk(KERN_INFO "js%d: %s at %#x\n",
359 js_register_device(port, i, axes[info.mode[i]], buttons[info.mode[i]],
360 names[info.mode[i]], js_gr_open, js_gr_close),
361 names[info.mode[i]], io);
362 js_gr_init_corr(info.mode[i], port->corr[i]);
365 return port;
368 #ifdef MODULE
369 int init_module(void)
370 #else
371 int __init js_gr_init(void)
372 #endif
374 int *p;
376 for (p = js_gr_port_list; *p; p++) js_gr_port = js_gr_probe(*p, js_gr_port);
377 if (js_gr_port) return 0;
379 #ifdef MODULE
380 printk(KERN_WARNING "joy-gravis: no joysticks found\n");
381 #endif
383 return -ENODEV;
386 #ifdef MODULE
387 void cleanup_module(void)
389 int i;
390 struct js_gr_info *info;
392 while (js_gr_port != NULL) {
393 for (i = 0; i < js_gr_port->ndevs; i++)
394 if (js_gr_port->devs[i] != NULL)
395 js_unregister_device(js_gr_port->devs[i]);
396 info = js_gr_port->info;
397 release_region(info->io, 1);
398 js_gr_port = js_unregister_port(js_gr_port);
401 #endif