2 * $Id: analog.c,v 1.52 2000/06/07 13:07:06 vojtech Exp $
4 * Copyright (c) 1996-2000 Vojtech Pavlik
10 * Analog joystick and gamepad driver for Linux
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Should you need to contact me, the author, you can do so either by
29 * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
30 * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
33 #include <linux/delay.h>
34 #include <linux/kernel.h>
35 #include <linux/module.h>
36 #include <linux/malloc.h>
37 #include <linux/bitops.h>
38 #include <linux/init.h>
39 #include <linux/input.h>
40 #include <linux/gameport.h>
42 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
48 MODULE_PARM(js
,"1-16s");
50 #define ANALOG_PORTS 16
52 static char *js
[ANALOG_PORTS
];
53 static int analog_options
[ANALOG_PORTS
];
56 * Times, feature definitions.
59 #define ANALOG_RUDDER 0x00004
60 #define ANALOG_THROTTLE 0x00008
61 #define ANALOG_AXES_STD 0x0000f
62 #define ANALOG_BTNS_STD 0x000f0
64 #define ANALOG_BTNS_CHF 0x00100
65 #define ANALOG_HAT1_CHF 0x00200
66 #define ANALOG_HAT2_CHF 0x00400
67 #define ANALOG_HAT_FCS 0x00800
68 #define ANALOG_HATS_ALL 0x00e00
69 #define ANALOG_BTN_TL 0x01000
70 #define ANALOG_BTN_TR 0x02000
71 #define ANALOG_BTN_TL2 0x04000
72 #define ANALOG_BTN_TR2 0x08000
73 #define ANALOG_BTNS_TLR 0x03000
74 #define ANALOG_BTNS_TLR2 0x0c000
75 #define ANALOG_BTNS_GAMEPAD 0x0f000
77 #define ANALOG_HBTN_CHF 0x10000
78 #define ANALOG_ANY_CHF 0x10700
79 #define ANALOG_SAITEK 0x20000
80 #define ANALOG_EXTENSIONS 0x7ff00
81 #define ANALOG_GAMEPAD 0x80000
83 #define ANALOG_MAX_TIME 3 /* 3 ms */
84 #define ANALOG_LOOP_TIME 2000 /* 2 * loop */
85 #define ANALOG_REFRESH_TIME HZ/100 /* 10 ms */
86 #define ANALOG_SAITEK_DELAY 200 /* 200 us */
87 #define ANALOG_SAITEK_TIME 2000 /* 2000 us */
88 #define ANALOG_AXIS_TIME 2 /* 2 * refresh */
89 #define ANALOG_INIT_RETRIES 8 /* 8 times */
90 #define ANALOG_FUZZ_BITS 2 /* 2 bit more */
91 #define ANALOG_FUZZ_MAGIC 36 /* 36 u*ms/loop */
93 #define ANALOG_MAX_NAME_LENGTH 128
95 static short analog_axes
[] = { ABS_X
, ABS_Y
, ABS_RUDDER
, ABS_THROTTLE
};
96 static short analog_hats
[] = { ABS_HAT0X
, ABS_HAT0Y
, ABS_HAT1X
, ABS_HAT1Y
, ABS_HAT2X
, ABS_HAT2Y
};
97 static short analog_pads
[] = { BTN_Y
, BTN_Z
, BTN_TL
, BTN_TR
};
98 static short analog_exts
[] = { ANALOG_HAT1_CHF
, ANALOG_HAT2_CHF
, ANALOG_HAT_FCS
};
99 static short analog_pad_btn
[] = { BTN_A
, BTN_B
, BTN_C
, BTN_X
, BTN_TL2
, BTN_TR2
, BTN_SELECT
, BTN_START
, BTN_MODE
, BTN_BASE
};
100 static short analog_joy_btn
[] = { BTN_TRIGGER
, BTN_THUMB
, BTN_TOP
, BTN_TOP2
, BTN_BASE
, BTN_BASE2
,
101 BTN_BASE3
, BTN_BASE4
, BTN_BASE5
, BTN_BASE6
};
103 static unsigned char analog_chf
[] = { 0xf, 0x0, 0x1, 0x9, 0x2, 0x4, 0xc, 0x8, 0x3, 0x5, 0xb, 0x7, 0xd, 0xe, 0xa, 0x6 };
106 struct input_dev dev
;
109 char name
[ANALOG_MAX_NAME_LENGTH
];
113 struct gameport
*gameport
;
114 struct timer_list timer
;
115 struct analog analog
[2];
136 #ifdef CONFIG_X86_TSC
137 #define GET_TIME(x) __asm__ __volatile__ ( "rdtsc" : "=a" (x) : : "dx" )
138 #define DELTA(x,y) ((y)-(x))
139 #define TIME_NAME "TSC"
141 #define GET_TIME(x) do { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } while (0)
142 #define DELTA(x,y) ((x)-(y)+((x)<(y)?1193180L/HZ:0))
143 #define TIME_NAME "PIT"
146 #define GET_TIME(x) __asm__ __volatile__ ( "rpcc %0" : "=r" (x) )
147 #define DELTA(x,y) ((y)-(x))
148 #define TIME_NAME "PCC"
153 static unsigned long analog_faketime
= 0;
154 #define GET_TIME(x) do { x = analog_faketime++; } while(0)
155 #define DELTA(x,y) ((y)-(x))
156 #define TIME_NAME "Unreliable"
160 * analog_decode() decodes analog joystick data and reports input events.
163 static void analog_decode(struct analog
*analog
, int *axes
, int *initial
, int buttons
)
165 struct input_dev
*dev
= &analog
->dev
;
168 if (analog
->mask
& ANALOG_HAT_FCS
)
169 for (i
= 0; i
< 4; i
++)
170 if (axes
[3] < ((initial
[3] * ((i
<< 1) + 1)) >> 3)) {
171 buttons
|= 1 << (i
+ 14);
175 for (i
= j
= 0; i
< 6; i
++)
176 if (analog
->mask
& (0x10 << i
))
177 input_report_key(dev
, analog
->buttons
[j
++], (buttons
>> i
) & 1);
179 if (analog
->mask
& ANALOG_HBTN_CHF
)
180 for (i
= 0; i
< 4; i
++)
181 input_report_key(dev
, analog
->buttons
[j
++], (buttons
>> (i
+ 10)) & 1);
183 if (analog
->mask
& ANALOG_BTN_TL
)
184 input_report_key(dev
, analog_pads
[0], axes
[2] < (initial
[2] >> 1));
185 if (analog
->mask
& ANALOG_BTN_TR
)
186 input_report_key(dev
, analog_pads
[1], axes
[3] < (initial
[3] >> 1));
187 if (analog
->mask
& ANALOG_BTN_TL2
)
188 input_report_key(dev
, analog_pads
[2], axes
[2] > (initial
[2] + (initial
[2] >> 1)));
189 if (analog
->mask
& ANALOG_BTN_TR2
)
190 input_report_key(dev
, analog_pads
[3], axes
[3] > (initial
[3] + (initial
[3] >> 1)));
192 for (i
= j
= 0; i
< 4; i
++)
193 if (analog
->mask
& (1 << i
))
194 input_report_abs(dev
, analog_axes
[j
++], axes
[i
]);
196 for (i
= j
= 0; i
< 3; i
++)
197 if (analog
->mask
& analog_exts
[i
]) {
198 input_report_abs(dev
, analog_hats
[j
++],
199 ((buttons
>> ((i
<< 2) + 7)) & 1) - ((buttons
>> ((i
<< 2) + 9)) & 1));
200 input_report_abs(dev
, analog_hats
[j
++],
201 ((buttons
>> ((i
<< 2) + 8)) & 1) - ((buttons
>> ((i
<< 2) + 6)) & 1));
206 * analog_cooked_read() reads analog joystick data.
209 static int analog_cooked_read(struct analog_port
*port
)
211 struct gameport
*gameport
= port
->gameport
;
212 unsigned int time
[4], start
, loop
, now
, loopout
, timeout
;
213 unsigned char data
[4], this, last
;
217 loopout
= (ANALOG_LOOP_TIME
* port
->loop
) / 1000;
218 timeout
= ANALOG_MAX_TIME
* port
->speed
;
222 gameport_trigger(gameport
);
224 __restore_flags(flags
);
235 this = gameport_read(gameport
) & port
->mask
;
237 __restore_flags(flags
);
239 if ((last
^ this) && (DELTA(loop
, now
) < loopout
)) {
240 data
[i
] = last
^ this;
245 } while (this && (i
< 4) && (DELTA(start
, now
) < timeout
));
249 for (--i
; i
>= 0; i
--) {
251 for (j
= 0; j
< 4; j
++)
252 if (data
[i
] & (1 << j
))
253 port
->axes
[j
] = (DELTA(start
, time
[i
]) << ANALOG_FUZZ_BITS
) / port
->loop
;
256 return -(this != port
->mask
);
259 static int analog_button_read(struct analog_port
*port
, char saitek
, char chf
)
263 int strobe
= gameport_time(port
->gameport
, ANALOG_SAITEK_TIME
);
265 u
= gameport_read(port
->gameport
);
268 port
->buttons
= (~u
>> 4) & 0xf;
274 while ((~u
& 0xf0) && (i
< 16) && t
) {
275 port
->buttons
|= 1 << analog_chf
[(~u
>> 4) & 0xf];
276 if (!saitek
) return 0;
277 udelay(ANALOG_SAITEK_DELAY
);
279 gameport_trigger(port
->gameport
);
280 while (((u
= gameport_read(port
->gameport
)) & port
->mask
) && t
) t
--;
284 return -(!t
|| (i
== 16));
288 * analog_timer() repeatedly polls the Analog joysticks.
291 static void analog_timer(unsigned long data
)
293 struct analog_port
*port
= (void *) data
;
296 char saitek
= !!(port
->analog
[0].mask
& ANALOG_SAITEK
);
297 char chf
= !!(port
->analog
[0].mask
& ANALOG_ANY_CHF
);
300 port
->bads
-= gameport_cooked_read(port
->gameport
, port
->axes
, &port
->buttons
);
302 port
->buttons
= port
->buttons
? (1 << analog_chf
[port
->buttons
]) : 0;
305 if (!port
->axtime
--) {
306 port
->bads
-= analog_cooked_read(port
);
307 port
->bads
-= analog_button_read(port
, saitek
, chf
);
309 port
->axtime
= ANALOG_AXIS_TIME
- 1;
312 analog_button_read(port
, saitek
, chf
);
316 for (i
= 0; i
< 2; i
++)
317 if (port
->analog
[i
].mask
)
318 analog_decode(port
->analog
+ i
, port
->axes
, port
->initial
, port
->buttons
);
320 mod_timer(&port
->timer
, jiffies
+ ANALOG_REFRESH_TIME
);
324 * analog_open() is a callback from the input open routine.
327 static int analog_open(struct input_dev
*dev
)
329 struct analog_port
*port
= dev
->private;
331 mod_timer(&port
->timer
, jiffies
+ ANALOG_REFRESH_TIME
);
336 * analog_close() is a callback from the input close routine.
339 static void analog_close(struct input_dev
*dev
)
341 struct analog_port
*port
= dev
->private;
343 del_timer(&port
->timer
);
347 * analog_calibrate_timer() calibrates the timer and computes loop
348 * and timeout values for a joystick port.
351 static void analog_calibrate_timer(struct analog_port
*port
)
353 struct gameport
*gameport
= port
->gameport
;
354 unsigned int i
, t
, tx
, t1
, t2
, t3
;
361 analog_faketime
+= 830;
366 restore_flags(flags
);
368 port
->speed
= DELTA(t1
, t2
) - DELTA(t2
, t3
);
372 for (i
= 0; i
< 50; i
++) {
376 for (t
= 0; t
< 50; t
++) { gameport_read(gameport
); GET_TIME(t2
); }
378 restore_flags(flags
);
380 t
= DELTA(t1
, t2
) - DELTA(t2
, t3
);
384 port
->loop
= tx
/ 50;
388 * analog_name() constructs a name for an analog joystick.
391 static void analog_name(struct analog
*analog
)
393 sprintf(analog
->name
, "Analog %d-axis %d-button",
394 hweight8(analog
->mask
& ANALOG_AXES_STD
),
395 hweight8(analog
->mask
& ANALOG_BTNS_STD
) + !!(analog
->mask
& ANALOG_BTNS_CHF
) * 2 +
396 hweight16(analog
->mask
& ANALOG_BTNS_GAMEPAD
) + !!(analog
->mask
& ANALOG_HBTN_CHF
) * 4);
398 if (analog
->mask
& ANALOG_HATS_ALL
)
399 sprintf(analog
->name
, "%s %d-hat",
400 analog
->name
, hweight16(analog
->mask
& ANALOG_HATS_ALL
));
402 if (analog
->mask
& ANALOG_HAT_FCS
)
403 strcat(analog
->name
, " FCS");
404 if (analog
->mask
& ANALOG_ANY_CHF
)
405 strcat(analog
->name
, (analog
->mask
& ANALOG_SAITEK
) ? " Saitek" : " CHF");
407 strcat(analog
->name
, (analog
->mask
& ANALOG_GAMEPAD
) ? " gamepad": " joystick");
411 * analog_init_device()
414 static void analog_init_device(struct analog_port
*port
, struct analog
*analog
, int index
)
416 int i
, j
, t
, v
, w
, x
, y
, z
;
420 analog
->buttons
= (analog
->mask
& ANALOG_GAMEPAD
) ? analog_pad_btn
: analog_joy_btn
;
422 analog
->dev
.name
= analog
->name
;
423 analog
->dev
.idbus
= BUS_GAMEPORT
;
424 analog
->dev
.idvendor
= GAMEPORT_ID_VENDOR_ANALOG
;
425 analog
->dev
.idproduct
= analog
->mask
>> 4;
426 analog
->dev
.idversion
= 0x0100;
428 analog
->dev
.open
= analog_open
;
429 analog
->dev
.close
= analog_close
;
430 analog
->dev
.private = port
;
431 analog
->dev
.evbit
[0] = BIT(EV_KEY
) | BIT(EV_ABS
);
433 for (i
= j
= 0; i
< 4; i
++)
434 if (analog
->mask
& (1 << i
)) {
438 y
= (port
->axes
[0] + port
->axes
[1]) >> 1;
439 z
= y
- port
->axes
[i
];
444 set_bit(t
, analog
->dev
.absbit
);
446 if ((i
== 2 || i
== 3) && (j
== 2 || j
== 3) && (z
> (y
>> 3)))
449 if (analog
->mask
& ANALOG_SAITEK
) {
450 if (i
== 2) x
= port
->axes
[i
];
455 analog
->dev
.absmax
[t
] = (x
<< 1) - v
;
456 analog
->dev
.absmin
[t
] = v
;
457 analog
->dev
.absfuzz
[t
] = port
->fuzz
;
458 analog
->dev
.absflat
[t
] = w
;
463 for (i
= j
= 0; i
< 3; i
++)
464 if (analog
->mask
& analog_exts
[i
])
465 for (x
= 0; x
< 2; x
++) {
466 t
= analog_hats
[j
++];
467 set_bit(t
, analog
->dev
.absbit
);
468 analog
->dev
.absmax
[t
] = 1;
469 analog
->dev
.absmin
[t
] = -1;
472 for (i
= j
= 0; i
< 4; i
++)
473 if (analog
->mask
& (0x10 << i
))
474 set_bit(analog
->buttons
[j
++], analog
->dev
.keybit
);
476 if (analog
->mask
& ANALOG_BTNS_CHF
)
477 for (i
= 0; i
< 2; i
++)
478 set_bit(analog
->buttons
[j
++], analog
->dev
.keybit
);
480 if (analog
->mask
& ANALOG_HBTN_CHF
)
481 for (i
= 0; i
< 4; i
++)
482 set_bit(analog
->buttons
[j
++], analog
->dev
.keybit
);
484 for (i
= 0; i
< 4; i
++)
485 if (analog
->mask
& (ANALOG_BTN_TL
<< i
))
486 set_bit(analog_pads
[i
], analog
->dev
.keybit
);
488 analog_decode(analog
, port
->axes
, port
->initial
, port
->buttons
);
490 input_register_device(&analog
->dev
);
492 printk(KERN_INFO
"input%d: %s at gameport%d.%d",
493 analog
->dev
.number
, analog
->name
, port
->gameport
->number
, index
);
496 printk(" [ADC port]\n");
498 printk(" ["TIME_NAME
" timer, %d %sHz clock, %d ns res]\n",
499 port
->speed
> 10000 ? (port
->speed
+ 800) / 1000 : port
->speed
,
500 port
->speed
> 10000 ? "M" : "k", (port
->loop
* 1000000) / port
->speed
);
504 * analog_init_devices() sets up device-specific values and registers the input devices.
507 static int analog_init_masks(struct analog_port
*port
)
510 struct analog
*analog
= port
->analog
;
516 if ((port
->mask
& 3) != 3 && port
->mask
!= 0xc) {
517 printk(KERN_WARNING
"analog.c: Unknown joystick device found "
518 "(data=%#x, gameport%d), probably not analog joystick.\n",
519 port
->mask
, port
->gameport
->number
);
523 i
= port
->gameport
->number
< ANALOG_PORTS
? analog_options
[port
->gameport
->number
] : 0xff;
525 analog
[0].mask
= i
& 0xfffff;
527 analog
[0].mask
&= ~(ANALOG_AXES_STD
| ANALOG_HAT_FCS
| ANALOG_BTNS_GAMEPAD
)
528 | port
->mask
| ((port
->mask
<< 8) & ANALOG_HAT_FCS
)
529 | ((port
->mask
<< 10) & ANALOG_BTNS_TLR
) | ((port
->mask
<< 12) & ANALOG_BTNS_TLR2
);
531 analog
[0].mask
&= ~(ANALOG_HAT2_CHF
)
532 | ((analog
[0].mask
& ANALOG_HBTN_CHF
) ? 0 : ANALOG_HAT2_CHF
);
534 analog
[0].mask
&= ~(ANALOG_THROTTLE
| ANALOG_BTN_TR
| ANALOG_BTN_TR2
)
535 | ((~analog
[0].mask
& ANALOG_HAT_FCS
) >> 8)
536 | ((~analog
[0].mask
& ANALOG_HAT_FCS
) << 2)
537 | ((~analog
[0].mask
& ANALOG_HAT_FCS
) << 4);
539 analog
[0].mask
&= ~(ANALOG_THROTTLE
| ANALOG_RUDDER
)
540 | (((~analog
[0].mask
& ANALOG_BTNS_TLR
) >> 10)
541 & ((~analog
[0].mask
& ANALOG_BTNS_TLR2
) >> 12));
543 analog
[1].mask
= ((i
>> 20) & 0xff) | ((i
>> 12) & 0xf0000);
545 analog
[1].mask
&= (analog
[0].mask
& ANALOG_EXTENSIONS
) ? ANALOG_GAMEPAD
546 : (((ANALOG_BTNS_STD
| port
->mask
) & ~analog
[0].mask
) | ANALOG_GAMEPAD
);
550 for (i
= 0; i
< 4; i
++) max
[i
] = port
->axes
[i
] << 1;
552 if ((analog
[0].mask
& 0x7) == 0x7) max
[2] = (max
[0] + max
[1]) >> 1;
553 if ((analog
[0].mask
& 0xb) == 0xb) max
[3] = (max
[0] + max
[1]) >> 1;
554 if ((analog
[0].mask
& ANALOG_BTN_TL
) && !(analog
[0].mask
& ANALOG_BTN_TL2
)) max
[2] >>= 1;
555 if ((analog
[0].mask
& ANALOG_BTN_TR
) && !(analog
[0].mask
& ANALOG_BTN_TR2
)) max
[3] >>= 1;
556 if ((analog
[0].mask
& ANALOG_HAT_FCS
)) max
[3] >>= 1;
558 gameport_calibrate(port
->gameport
, port
->axes
, max
);
561 for (i
= 0; i
< 4; i
++)
562 port
->initial
[i
] = port
->axes
[i
];
564 return -!(analog
[0].mask
|| analog
[1].mask
);
567 static int analog_init_port(struct gameport
*gameport
, struct gameport_dev
*dev
, struct analog_port
*port
)
571 gameport
->private = port
;
572 port
->gameport
= gameport
;
573 init_timer(&port
->timer
);
574 port
->timer
.data
= (long) port
;
575 port
->timer
.function
= analog_timer
;
577 if (!gameport_open(gameport
, dev
, GAMEPORT_MODE_RAW
)) {
579 analog_calibrate_timer(port
);
581 gameport_trigger(gameport
);
582 t
= gameport_read(gameport
);
583 wait_ms(ANALOG_MAX_TIME
);
584 port
->mask
= (gameport_read(gameport
) ^ t
) & t
& 0xf;
585 port
->fuzz
= (port
->speed
* ANALOG_FUZZ_MAGIC
) / port
->loop
/ 1000 + ANALOG_FUZZ_BITS
;
587 for (i
= 0; i
< ANALOG_INIT_RETRIES
; i
++) {
588 if (!analog_cooked_read(port
)) break;
589 wait_ms(ANALOG_MAX_TIME
);
594 wait_ms(ANALOG_MAX_TIME
);
595 t
= gameport_time(gameport
, ANALOG_MAX_TIME
* 1000);
596 gameport_trigger(gameport
);
597 while ((gameport_read(port
->gameport
) & port
->mask
) && (u
< t
)) u
++;
598 udelay(ANALOG_SAITEK_DELAY
);
599 t
= gameport_time(gameport
, ANALOG_SAITEK_TIME
);
600 gameport_trigger(gameport
);
601 while ((gameport_read(port
->gameport
) & port
->mask
) && (v
< t
)) v
++;
603 if (v
< (u
>> 1) && port
->gameport
->number
< ANALOG_PORTS
) {
604 analog_options
[port
->gameport
->number
] |=
605 ANALOG_SAITEK
| ANALOG_BTNS_CHF
| ANALOG_HBTN_CHF
| ANALOG_HAT1_CHF
;
609 gameport_close(gameport
);
612 if (!gameport_open(gameport
, dev
, GAMEPORT_MODE_COOKED
)) {
614 for (i
= 0; i
< ANALOG_INIT_RETRIES
; i
++)
615 if (!gameport_cooked_read(gameport
, port
->axes
, &port
->buttons
))
617 for (i
= 0; i
< 4; i
++)
618 if (port
->axes
[i
] != -1) port
->mask
|= 1 << i
;
620 port
->fuzz
= gameport
->fuzz
;
625 if (!gameport_open(gameport
, dev
, GAMEPORT_MODE_RAW
))
631 static void analog_connect(struct gameport
*gameport
, struct gameport_dev
*dev
)
633 struct analog_port
*port
;
636 if (!(port
= kmalloc(sizeof(struct analog_port
), GFP_KERNEL
)))
638 memset(port
, 0, sizeof(struct analog_port
));
640 if (analog_init_port(gameport
, dev
, port
)) {
645 if (analog_init_masks(port
)) {
646 gameport_close(gameport
);
651 for (i
= 0; i
< 2; i
++)
652 if (port
->analog
[i
].mask
)
653 analog_init_device(port
, port
->analog
+ i
, i
);
656 static void analog_disconnect(struct gameport
*gameport
)
660 struct analog_port
*port
= gameport
->private;
661 for (i
= 0; i
< 2; i
++)
662 if (port
->analog
[i
].mask
)
663 input_unregister_device(&port
->analog
[i
].dev
);
664 gameport_close(gameport
);
665 printk(KERN_INFO
"analog.c: %d out of %d reads (%d%%) on gameport%d failed\n",
666 port
->bads
, port
->reads
, port
->reads
? (port
->bads
* 100 / port
->reads
) : 0,
667 port
->gameport
->number
);
671 struct analog_types
{
676 struct analog_types analog_types
[] = {
677 { "none", 0x00000000 },
678 { "auto", 0x000000ff },
679 { "2btn", 0x0000003f },
680 { "y-joy", 0x0cc00033 },
681 { "y-pad", 0x8cc80033 },
682 { "fcs", 0x000008f7 },
683 { "chf", 0x000002ff },
684 { "fullchf", 0x000007ff },
685 { "gamepad", 0x000830f3 },
686 { "gamepad8", 0x0008f0f3 },
690 static void analog_parse_options(void)
695 for (i
= 0; i
< ANALOG_PORTS
&& js
[i
]; i
++) {
697 for (j
= 0; analog_types
[j
].name
; j
++)
698 if (!strcmp(analog_types
[j
].name
, js
[i
])) {
699 analog_options
[i
] = analog_types
[j
].value
;
702 if (analog_types
[j
].name
) continue;
704 analog_options
[i
] = simple_strtoul(js
[i
], &end
, 0);
705 if (end
!= js
[i
]) continue;
707 analog_options
[i
] = 0xff;
708 if (!strlen(js
[i
])) continue;
710 printk(KERN_WARNING
"analog.c: Bad config for port %d - \"%s\"\n", i
, js
[i
]);
713 for (; i
< ANALOG_PORTS
; i
++)
714 analog_options
[i
] = 0xff;
718 * The gameport device structure.
721 static struct gameport_dev analog_dev
= {
722 connect
: analog_connect
,
723 disconnect
: analog_disconnect
,
727 static int __init
analog_setup(char *str
)
732 if (!str
|| !*str
) return 0;
734 while ((str
= s
) && (i
< ANALOG_PORTS
)) {
735 if ((s
= strchr(str
,','))) *s
++ = 0;
741 __setup("js=", analog_setup
);
744 int __init
analog_init(void)
746 analog_parse_options();
747 gameport_register_device(&analog_dev
);
751 void __exit
analog_exit(void)
753 gameport_unregister_device(&analog_dev
);
756 module_init(analog_init
);
757 module_exit(analog_exit
);