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; |
