aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/joystick/gamecon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/joystick/gamecon.c')
-rw-r--r--drivers/input/joystick/gamecon.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index 8732f52bdd08..95bbdd302aad 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -1,12 +1,12 @@
1/* 1/*
2 * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux 2 * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux
3 * 3 *
4 * Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz> 4 * Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz>
5 * Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org> 5 * Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org>
6 * 6 *
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 */ 10 */
11 11
12/* 12/*
@@ -81,6 +81,7 @@ struct gc {
81 struct timer_list timer; 81 struct timer_list timer;
82 unsigned char pads[GC_MAX + 1]; 82 unsigned char pads[GC_MAX + 1];
83 int used; 83 int used;
84 struct semaphore sem;
84 char phys[5][32]; 85 char phys[5][32];
85}; 86};
86 87
@@ -433,7 +434,7 @@ static void gc_timer(unsigned long private)
433 gc_psx_read_packet(gc, data_psx, data); 434 gc_psx_read_packet(gc, data_psx, data);
434 435
435 for (i = 0; i < 5; i++) { 436 for (i = 0; i < 5; i++) {
436 switch (data[i]) { 437 switch (data[i]) {
437 438
438 case GC_PSX_RUMBLE: 439 case GC_PSX_RUMBLE:
439 440
@@ -503,22 +504,33 @@ static void gc_timer(unsigned long private)
503static int gc_open(struct input_dev *dev) 504static int gc_open(struct input_dev *dev)
504{ 505{
505 struct gc *gc = dev->private; 506 struct gc *gc = dev->private;
507 int err;
508
509 err = down_interruptible(&gc->sem);
510 if (err)
511 return err;
512
506 if (!gc->used++) { 513 if (!gc->used++) {
507 parport_claim(gc->pd); 514 parport_claim(gc->pd);
508 parport_write_control(gc->pd->port, 0x04); 515 parport_write_control(gc->pd->port, 0x04);
509 mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); 516 mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME);
510 } 517 }
518
519 up(&gc->sem);
511 return 0; 520 return 0;
512} 521}
513 522
514static void gc_close(struct input_dev *dev) 523static void gc_close(struct input_dev *dev)
515{ 524{
516 struct gc *gc = dev->private; 525 struct gc *gc = dev->private;
526
527 down(&gc->sem);
517 if (!--gc->used) { 528 if (!--gc->used) {
518 del_timer(&gc->timer); 529 del_timer_sync(&gc->timer);
519 parport_write_control(gc->pd->port, 0x00); 530 parport_write_control(gc->pd->port, 0x00);
520 parport_release(gc->pd); 531 parport_release(gc->pd);
521 } 532 }
533 up(&gc->sem);
522} 534}
523 535
524static struct gc __init *gc_probe(int *config, int nargs) 536static struct gc __init *gc_probe(int *config, int nargs)
@@ -542,11 +554,12 @@ static struct gc __init *gc_probe(int *config, int nargs)
542 return NULL; 554 return NULL;
543 } 555 }
544 556
545 if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) { 557 if (!(gc = kcalloc(1, sizeof(struct gc), GFP_KERNEL))) {
546 parport_put_port(pp); 558 parport_put_port(pp);
547 return NULL; 559 return NULL;
548 } 560 }
549 memset(gc, 0, sizeof(struct gc)); 561
562 init_MUTEX(&gc->sem);
550 563
551 gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); 564 gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
552 565