aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaphael Assenat <raph@raphnet.net>2006-04-02 00:10:05 -0500
committerDmitry Torokhov <dtor_core@ameritech.net>2006-04-02 00:10:05 -0500
commitb157d55eef38f014015b8058a9f733d1c1c49cb4 (patch)
treead1a04c9be6aa67b11fd40686d06fc5d8d271b6b
parentac648a6a704f73cc2a0f128d9deeb57aa6d76f6d (diff)
Input: gamecon - add SNES mouse support
SNES gamepads and mice share the same type of interface so they both can be connected to the parallel port using a simple interface. Adding mouse support to a gamepad driver may sound funny at first, but doing so in this case makes it possible to connect and SNES gamepads and mice at the same time, on the same port. Signed-off-by: Raphael Assenat <raph@raphnet.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--Documentation/input/joystick-parport.txt11
-rw-r--r--drivers/input/joystick/gamecon.c83
2 files changed, 76 insertions, 18 deletions
diff --git a/Documentation/input/joystick-parport.txt b/Documentation/input/joystick-parport.txt
index 88a011c9f985..d537c48cc6d0 100644
--- a/Documentation/input/joystick-parport.txt
+++ b/Documentation/input/joystick-parport.txt
@@ -36,12 +36,12 @@ with them.
36 36
37 All NES and SNES use the same synchronous serial protocol, clocked from 37 All NES and SNES use the same synchronous serial protocol, clocked from
38the computer's side (and thus timing insensitive). To allow up to 5 NES 38the computer's side (and thus timing insensitive). To allow up to 5 NES
39and/or SNES gamepads connected to the parallel port at once, the output 39and/or SNES gamepads and/or SNES mice connected to the parallel port at once,
40lines of the parallel port are shared, while one of 5 available input lines 40the output lines of the parallel port are shared, while one of 5 available
41is assigned to each gamepad. 41input lines is assigned to each gamepad.
42 42
43 This protocol is handled by the gamecon.c driver, so that's the one 43 This protocol is handled by the gamecon.c driver, so that's the one
44you'll use for NES and SNES gamepads. 44you'll use for NES, SNES gamepads and SNES mice.
45 45
46 The main problem with PC parallel ports is that they don't have +5V power 46 The main problem with PC parallel ports is that they don't have +5V power
47source on any of their pins. So, if you want a reliable source of power 47source on any of their pins. So, if you want a reliable source of power
@@ -106,7 +106,7 @@ A, Turbo B, Select and Start, and is connected through 5 wires, then it is
106either a NES or NES clone and will work with this connection. SNES gamepads 106either a NES or NES clone and will work with this connection. SNES gamepads
107also use 5 wires, but have more buttons. They will work as well, of course. 107also use 5 wires, but have more buttons. They will work as well, of course.
108 108
109Pinout for NES gamepads Pinout for SNES gamepads 109Pinout for NES gamepads Pinout for SNES gamepads and mice
110 110
111 +----> Power +-----------------------\ 111 +----> Power +-----------------------\
112 | 7 | o o o o | x x o | 1 112 | 7 | o o o o | x x o | 1
@@ -454,6 +454,7 @@ uses the following kernel/module command line:
454 6 | N64 pad 454 6 | N64 pad
455 7 | Sony PSX controller 455 7 | Sony PSX controller
456 8 | Sony PSX DDR controller 456 8 | Sony PSX DDR controller
457 9 | SNES mouse
457 458
458 The exact type of the PSX controller type is autoprobed when used so 459 The exact type of the PSX controller type is autoprobed when used so
459hot swapping should work (but is not recomended). 460hot swapping should work (but is not recomended).
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index aa3ef89d8188..ecbdb6b9bbd6 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -7,6 +7,7 @@
7 * Based on the work of: 7 * Based on the work of:
8 * Andree Borrmann John Dahlstrom 8 * Andree Borrmann John Dahlstrom
9 * David Kuder Nathan Hand 9 * David Kuder Nathan Hand
10 * Raphael Assenat
10 */ 11 */
11 12
12/* 13/*
@@ -73,8 +74,9 @@ __obsolete_setup("gc_3=");
73#define GC_N64 6 74#define GC_N64 6
74#define GC_PSX 7 75#define GC_PSX 7
75#define GC_DDR 8 76#define GC_DDR 8
77#define GC_SNESMOUSE 9
76 78
77#define GC_MAX 8 79#define GC_MAX 9
78 80
79#define GC_REFRESH_TIME HZ/100 81#define GC_REFRESH_TIME HZ/100
80 82
@@ -94,7 +96,7 @@ static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
94 96
95static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick", 97static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick",
96 "Multisystem 2-button joystick", "N64 controller", "PSX controller", 98 "Multisystem 2-button joystick", "N64 controller", "PSX controller",
97 "PSX DDR controller" }; 99 "PSX DDR controller", "SNES mouse" };
98/* 100/*
99 * N64 support. 101 * N64 support.
100 */ 102 */
@@ -206,9 +208,12 @@ static void gc_n64_process_packet(struct gc *gc)
206 * NES/SNES support. 208 * NES/SNES support.
207 */ 209 */
208 210
209#define GC_NES_DELAY 6 /* Delay between bits - 6us */ 211#define GC_NES_DELAY 6 /* Delay between bits - 6us */
210#define GC_NES_LENGTH 8 /* The NES pads use 8 bits of data */ 212#define GC_NES_LENGTH 8 /* The NES pads use 8 bits of data */
211#define GC_SNES_LENGTH 12 /* The SNES true length is 16, but the last 4 bits are unused */ 213#define GC_SNES_LENGTH 12 /* The SNES true length is 16, but the
214 last 4 bits are unused */
215#define GC_SNESMOUSE_LENGTH 32 /* The SNES mouse uses 32 bits, the first
216 16 bits are equivalent to a gamepad */
212 217
213#define GC_NES_POWER 0xfc 218#define GC_NES_POWER 0xfc
214#define GC_NES_CLOCK 0x01 219#define GC_NES_CLOCK 0x01
@@ -243,11 +248,15 @@ static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data)
243 248
244static void gc_nes_process_packet(struct gc *gc) 249static void gc_nes_process_packet(struct gc *gc)
245{ 250{
246 unsigned char data[GC_SNES_LENGTH]; 251 unsigned char data[GC_SNESMOUSE_LENGTH];
247 struct input_dev *dev; 252 struct input_dev *dev;
248 int i, j, s; 253 int i, j, s, len;
254 char x_rel, y_rel;
255
256 len = gc->pads[GC_SNESMOUSE] ? GC_SNESMOUSE_LENGTH :
257 (gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH);
249 258
250 gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data); 259 gc_nes_read_packet(gc, len, data);
251 260
252 for (i = 0; i < GC_MAX_DEVICES; i++) { 261 for (i = 0; i < GC_MAX_DEVICES; i++) {
253 262
@@ -270,6 +279,44 @@ static void gc_nes_process_packet(struct gc *gc)
270 for (j = 0; j < 8; j++) 279 for (j = 0; j < 8; j++)
271 input_report_key(dev, gc_snes_btn[j], s & data[gc_snes_bytes[j]]); 280 input_report_key(dev, gc_snes_btn[j], s & data[gc_snes_bytes[j]]);
272 281
282 if (s & gc->pads[GC_SNESMOUSE]) {
283 /*
284 * The 4 unused bits from SNES controllers appear to be ID bits
285 * so use them to make sure iwe are dealing with a mouse.
286 * gamepad is connected. This is important since
287 * my SNES gamepad sends 1's for bits 16-31, which
288 * cause the mouse pointer to quickly move to the
289 * upper left corner of the screen.
290 */
291 if (!(s & data[12]) && !(s & data[13]) &&
292 !(s & data[14]) && (s & data[15])) {
293 input_report_key(dev, BTN_LEFT, s & data[9]);
294 input_report_key(dev, BTN_RIGHT, s & data[8]);
295
296 x_rel = y_rel = 0;
297 for (j = 0; j < 7; j++) {
298 x_rel <<= 1;
299 if (data[25 + j] & s)
300 x_rel |= 1;
301
302 y_rel <<= 1;
303 if (data[17 + j] & s)
304 y_rel |= 1;
305 }
306
307 if (x_rel) {
308 if (data[24] & s)
309 x_rel = -x_rel;
310 input_report_rel(dev, REL_X, x_rel);
311 }
312
313 if (y_rel) {
314 if (data[16] & s)
315 y_rel = -y_rel;
316 input_report_rel(dev, REL_Y, y_rel);
317 }
318 }
319 }
273 input_sync(dev); 320 input_sync(dev);
274 } 321 }
275} 322}
@@ -525,10 +572,10 @@ static void gc_timer(unsigned long private)
525 gc_n64_process_packet(gc); 572 gc_n64_process_packet(gc);
526 573
527/* 574/*
528 * NES and SNES pads 575 * NES and SNES pads or mouse
529 */ 576 */
530 577
531 if (gc->pads[GC_NES] || gc->pads[GC_SNES]) 578 if (gc->pads[GC_NES] || gc->pads[GC_SNES] || gc->pads[GC_SNESMOUSE])
532 gc_nes_process_packet(gc); 579 gc_nes_process_packet(gc);
533 580
534/* 581/*
@@ -610,10 +657,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
610 input_dev->open = gc_open; 657 input_dev->open = gc_open;
611 input_dev->close = gc_close; 658 input_dev->close = gc_close;
612 659
613 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 660 if (pad_type != GC_SNESMOUSE) {
661 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
614 662
615 for (i = 0; i < 2; i++) 663 for (i = 0; i < 2; i++)
616 input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0); 664 input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0);
665 } else
666 input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
617 667
618 gc->pads[0] |= gc_status_bit[idx]; 668 gc->pads[0] |= gc_status_bit[idx];
619 gc->pads[pad_type] |= gc_status_bit[idx]; 669 gc->pads[pad_type] |= gc_status_bit[idx];
@@ -631,6 +681,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type)
631 681
632 break; 682 break;
633 683
684 case GC_SNESMOUSE:
685 set_bit(BTN_LEFT, input_dev->keybit);
686 set_bit(BTN_RIGHT, input_dev->keybit);
687 set_bit(REL_X, input_dev->relbit);
688 set_bit(REL_Y, input_dev->relbit);
689 break;
690
634 case GC_SNES: 691 case GC_SNES:
635 for (i = 4; i < 8; i++) 692 for (i = 4; i < 8; i++)
636 set_bit(gc_snes_btn[i], input_dev->keybit); 693 set_bit(gc_snes_btn[i], input_dev->keybit);