diff options
Diffstat (limited to 'drivers/input/joystick/gamecon.c')
-rw-r--r-- | drivers/input/joystick/gamecon.c | 96 |
1 files changed, 77 insertions, 19 deletions
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 900587acdb47..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 | /* |
@@ -36,6 +37,7 @@ | |||
36 | #include <linux/init.h> | 37 | #include <linux/init.h> |
37 | #include <linux/parport.h> | 38 | #include <linux/parport.h> |
38 | #include <linux/input.h> | 39 | #include <linux/input.h> |
40 | #include <linux/mutex.h> | ||
39 | 41 | ||
40 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 42 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
41 | MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver"); | 43 | MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver"); |
@@ -72,8 +74,9 @@ __obsolete_setup("gc_3="); | |||
72 | #define GC_N64 6 | 74 | #define GC_N64 6 |
73 | #define GC_PSX 7 | 75 | #define GC_PSX 7 |
74 | #define GC_DDR 8 | 76 | #define GC_DDR 8 |
77 | #define GC_SNESMOUSE 9 | ||
75 | 78 | ||
76 | #define GC_MAX 8 | 79 | #define GC_MAX 9 |
77 | 80 | ||
78 | #define GC_REFRESH_TIME HZ/100 | 81 | #define GC_REFRESH_TIME HZ/100 |
79 | 82 | ||
@@ -83,7 +86,7 @@ struct gc { | |||
83 | struct timer_list timer; | 86 | struct timer_list timer; |
84 | unsigned char pads[GC_MAX + 1]; | 87 | unsigned char pads[GC_MAX + 1]; |
85 | int used; | 88 | int used; |
86 | struct semaphore sem; | 89 | struct mutex mutex; |
87 | char phys[GC_MAX_DEVICES][32]; | 90 | char phys[GC_MAX_DEVICES][32]; |
88 | }; | 91 | }; |
89 | 92 | ||
@@ -93,7 +96,7 @@ static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; | |||
93 | 96 | ||
94 | static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick", | 97 | static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick", |
95 | "Multisystem 2-button joystick", "N64 controller", "PSX controller", | 98 | "Multisystem 2-button joystick", "N64 controller", "PSX controller", |
96 | "PSX DDR controller" }; | 99 | "PSX DDR controller", "SNES mouse" }; |
97 | /* | 100 | /* |
98 | * N64 support. | 101 | * N64 support. |
99 | */ | 102 | */ |
@@ -205,9 +208,12 @@ static void gc_n64_process_packet(struct gc *gc) | |||
205 | * NES/SNES support. | 208 | * NES/SNES support. |
206 | */ | 209 | */ |
207 | 210 | ||
208 | #define GC_NES_DELAY 6 /* Delay between bits - 6us */ | 211 | #define GC_NES_DELAY 6 /* Delay between bits - 6us */ |
209 | #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 */ |
210 | #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 */ | ||
211 | 217 | ||
212 | #define GC_NES_POWER 0xfc | 218 | #define GC_NES_POWER 0xfc |
213 | #define GC_NES_CLOCK 0x01 | 219 | #define GC_NES_CLOCK 0x01 |
@@ -242,11 +248,15 @@ static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data) | |||
242 | 248 | ||
243 | static void gc_nes_process_packet(struct gc *gc) | 249 | static void gc_nes_process_packet(struct gc *gc) |
244 | { | 250 | { |
245 | unsigned char data[GC_SNES_LENGTH]; | 251 | unsigned char data[GC_SNESMOUSE_LENGTH]; |
246 | struct input_dev *dev; | 252 | struct input_dev *dev; |
247 | 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); | ||
248 | 258 | ||
249 | gc_nes_read_packet(gc, gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH, data); | 259 | gc_nes_read_packet(gc, len, data); |
250 | 260 | ||
251 | for (i = 0; i < GC_MAX_DEVICES; i++) { | 261 | for (i = 0; i < GC_MAX_DEVICES; i++) { |
252 | 262 | ||
@@ -269,6 +279,44 @@ static void gc_nes_process_packet(struct gc *gc) | |||
269 | for (j = 0; j < 8; j++) | 279 | for (j = 0; j < 8; j++) |
270 | 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]]); |
271 | 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 | } | ||
272 | input_sync(dev); | 320 | input_sync(dev); |
273 | } | 321 | } |
274 | } | 322 | } |
@@ -524,10 +572,10 @@ static void gc_timer(unsigned long private) | |||
524 | gc_n64_process_packet(gc); | 572 | gc_n64_process_packet(gc); |
525 | 573 | ||
526 | /* | 574 | /* |
527 | * NES and SNES pads | 575 | * NES and SNES pads or mouse |
528 | */ | 576 | */ |
529 | 577 | ||
530 | if (gc->pads[GC_NES] || gc->pads[GC_SNES]) | 578 | if (gc->pads[GC_NES] || gc->pads[GC_SNES] || gc->pads[GC_SNESMOUSE]) |
531 | gc_nes_process_packet(gc); | 579 | gc_nes_process_packet(gc); |
532 | 580 | ||
533 | /* | 581 | /* |
@@ -552,7 +600,7 @@ static int gc_open(struct input_dev *dev) | |||
552 | struct gc *gc = dev->private; | 600 | struct gc *gc = dev->private; |
553 | int err; | 601 | int err; |
554 | 602 | ||
555 | err = down_interruptible(&gc->sem); | 603 | err = mutex_lock_interruptible(&gc->mutex); |
556 | if (err) | 604 | if (err) |
557 | return err; | 605 | return err; |
558 | 606 | ||
@@ -562,7 +610,7 @@ static int gc_open(struct input_dev *dev) | |||
562 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); | 610 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); |
563 | } | 611 | } |
564 | 612 | ||
565 | up(&gc->sem); | 613 | mutex_unlock(&gc->mutex); |
566 | return 0; | 614 | return 0; |
567 | } | 615 | } |
568 | 616 | ||
@@ -570,13 +618,13 @@ static void gc_close(struct input_dev *dev) | |||
570 | { | 618 | { |
571 | struct gc *gc = dev->private; | 619 | struct gc *gc = dev->private; |
572 | 620 | ||
573 | down(&gc->sem); | 621 | mutex_lock(&gc->mutex); |
574 | if (!--gc->used) { | 622 | if (!--gc->used) { |
575 | del_timer_sync(&gc->timer); | 623 | del_timer_sync(&gc->timer); |
576 | parport_write_control(gc->pd->port, 0x00); | 624 | parport_write_control(gc->pd->port, 0x00); |
577 | parport_release(gc->pd); | 625 | parport_release(gc->pd); |
578 | } | 626 | } |
579 | up(&gc->sem); | 627 | mutex_unlock(&gc->mutex); |
580 | } | 628 | } |
581 | 629 | ||
582 | static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) | 630 | static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) |
@@ -609,10 +657,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) | |||
609 | input_dev->open = gc_open; | 657 | input_dev->open = gc_open; |
610 | input_dev->close = gc_close; | 658 | input_dev->close = gc_close; |
611 | 659 | ||
612 | 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); | ||
613 | 662 | ||
614 | for (i = 0; i < 2; i++) | 663 | for (i = 0; i < 2; i++) |
615 | 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); | ||
616 | 667 | ||
617 | gc->pads[0] |= gc_status_bit[idx]; | 668 | gc->pads[0] |= gc_status_bit[idx]; |
618 | gc->pads[pad_type] |= gc_status_bit[idx]; | 669 | gc->pads[pad_type] |= gc_status_bit[idx]; |
@@ -630,6 +681,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) | |||
630 | 681 | ||
631 | break; | 682 | break; |
632 | 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 | |||
633 | case GC_SNES: | 691 | case GC_SNES: |
634 | for (i = 4; i < 8; i++) | 692 | for (i = 4; i < 8; i++) |
635 | set_bit(gc_snes_btn[i], input_dev->keybit); | 693 | set_bit(gc_snes_btn[i], input_dev->keybit); |
@@ -693,7 +751,7 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) | |||
693 | goto err_unreg_pardev; | 751 | goto err_unreg_pardev; |
694 | } | 752 | } |
695 | 753 | ||
696 | init_MUTEX(&gc->sem); | 754 | mutex_init(&gc->mutex); |
697 | gc->pd = pd; | 755 | gc->pd = pd; |
698 | init_timer(&gc->timer); | 756 | init_timer(&gc->timer); |
699 | gc->timer.data = (long) gc; | 757 | gc->timer.data = (long) gc; |