diff options
author | Dmitry Torokhov <dtor_core@ameritech.net> | 2005-09-15 03:01:52 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-10-28 12:52:53 -0400 |
commit | 17dd3f0f7aa729a042af5d3318ff9b3e7781b45b (patch) | |
tree | 261580f0229e6365f044cd26925dfb2735e0754d /drivers/input/joystick/gamecon.c | |
parent | 0259567ad60df13a55583b84d2cddb5526705907 (diff) |
[PATCH] drivers/input/joystick: convert to dynamic input_dev allocation
Input: convert drivers/input/joystick to dynamic input_dev allocation
This is required for input_dev sysfs integration
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/input/joystick/gamecon.c')
-rw-r--r-- | drivers/input/joystick/gamecon.c | 396 |
1 files changed, 216 insertions, 180 deletions
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 5427bf9fc862..7df2d82f2c83 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c | |||
@@ -41,20 +41,22 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | |||
41 | MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver"); | 41 | MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver"); |
42 | MODULE_LICENSE("GPL"); | 42 | MODULE_LICENSE("GPL"); |
43 | 43 | ||
44 | static int gc[] __initdata = { -1, 0, 0, 0, 0, 0 }; | 44 | #define GC_MAX_PORTS 3 |
45 | static int gc_nargs __initdata = 0; | 45 | #define GC_MAX_DEVICES 5 |
46 | module_param_array_named(map, gc, int, &gc_nargs, 0); | ||
47 | MODULE_PARM_DESC(map, "Describers first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)"); | ||
48 | 46 | ||
49 | static int gc_2[] __initdata = { -1, 0, 0, 0, 0, 0 }; | 47 | struct gc_config { |
50 | static int gc_nargs_2 __initdata = 0; | 48 | int args[GC_MAX_DEVICES + 1]; |
51 | module_param_array_named(map2, gc_2, int, &gc_nargs_2, 0); | 49 | int nargs; |
52 | MODULE_PARM_DESC(map2, "Describers second set of devices"); | 50 | }; |
51 | |||
52 | static struct gc_config gc[GC_MAX_PORTS] __initdata; | ||
53 | 53 | ||
54 | static int gc_3[] __initdata = { -1, 0, 0, 0, 0, 0 }; | 54 | module_param_array_named(map, gc[0].args, int, &gc[0].nargs, 0); |
55 | static int gc_nargs_3 __initdata = 0; | 55 | MODULE_PARM_DESC(map, "Describes first set of devices (<parport#>,<pad1>,<pad2>,..<pad5>)"); |
56 | module_param_array_named(map3, gc_3, int, &gc_nargs_3, 0); | 56 | module_param_array_named(map2, gc[1].args, int, &gc[1].nargs, 0); |
57 | MODULE_PARM_DESC(map3, "Describers third set of devices"); | 57 | MODULE_PARM_DESC(map2, "Describes second set of devices"); |
58 | module_param_array_named(map3, gc[2].args, int, &gc[2].nargs, 0); | ||
59 | MODULE_PARM_DESC(map3, "Describes third set of devices"); | ||
58 | 60 | ||
59 | __obsolete_setup("gc="); | 61 | __obsolete_setup("gc="); |
60 | __obsolete_setup("gc_2="); | 62 | __obsolete_setup("gc_2="); |
@@ -77,12 +79,12 @@ __obsolete_setup("gc_3="); | |||
77 | 79 | ||
78 | struct gc { | 80 | struct gc { |
79 | struct pardevice *pd; | 81 | struct pardevice *pd; |
80 | struct input_dev dev[5]; | 82 | struct input_dev *dev[GC_MAX_DEVICES]; |
81 | struct timer_list timer; | 83 | struct timer_list timer; |
82 | unsigned char pads[GC_MAX + 1]; | 84 | unsigned char pads[GC_MAX + 1]; |
83 | int used; | 85 | int used; |
84 | struct semaphore sem; | 86 | struct semaphore sem; |
85 | char phys[5][32]; | 87 | char phys[GC_MAX_DEVICES][32]; |
86 | }; | 88 | }; |
87 | 89 | ||
88 | static struct gc *gc_base[3]; | 90 | static struct gc *gc_base[3]; |
@@ -330,7 +332,6 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES | |||
330 | static void gc_timer(unsigned long private) | 332 | static void gc_timer(unsigned long private) |
331 | { | 333 | { |
332 | struct gc *gc = (void *) private; | 334 | struct gc *gc = (void *) private; |
333 | struct input_dev *dev = gc->dev; | ||
334 | unsigned char data[GC_MAX_LENGTH]; | 335 | unsigned char data[GC_MAX_LENGTH]; |
335 | unsigned char data_psx[5][GC_PSX_BYTES]; | 336 | unsigned char data_psx[5][GC_PSX_BYTES]; |
336 | int i, j, s; | 337 | int i, j, s; |
@@ -357,16 +358,16 @@ static void gc_timer(unsigned long private) | |||
357 | if (data[31 - j] & s) axes[1] |= 1 << j; | 358 | if (data[31 - j] & s) axes[1] |= 1 << j; |
358 | } | 359 | } |
359 | 360 | ||
360 | input_report_abs(dev + i, ABS_X, axes[0]); | 361 | input_report_abs(gc->dev[i], ABS_X, axes[0]); |
361 | input_report_abs(dev + i, ABS_Y, -axes[1]); | 362 | input_report_abs(gc->dev[i], ABS_Y, -axes[1]); |
362 | 363 | ||
363 | input_report_abs(dev + i, ABS_HAT0X, !(s & data[6]) - !(s & data[7])); | 364 | input_report_abs(gc->dev[i], ABS_HAT0X, !(s & data[6]) - !(s & data[7])); |
364 | input_report_abs(dev + i, ABS_HAT0Y, !(s & data[4]) - !(s & data[5])); | 365 | input_report_abs(gc->dev[i], ABS_HAT0Y, !(s & data[4]) - !(s & data[5])); |
365 | 366 | ||
366 | for (j = 0; j < 10; j++) | 367 | for (j = 0; j < 10; j++) |
367 | input_report_key(dev + i, gc_n64_btn[j], s & data[gc_n64_bytes[j]]); | 368 | input_report_key(gc->dev[i], gc_n64_btn[j], s & data[gc_n64_bytes[j]]); |
368 | 369 | ||
369 | input_sync(dev + i); | 370 | input_sync(gc->dev[i]); |
370 | } | 371 | } |
371 | } | 372 | } |
372 | } | 373 | } |
@@ -384,19 +385,19 @@ static void gc_timer(unsigned long private) | |||
384 | s = gc_status_bit[i]; | 385 | s = gc_status_bit[i]; |
385 | 386 | ||
386 | if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) { | 387 | if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) { |
387 | input_report_abs(dev + i, ABS_X, !(s & data[6]) - !(s & data[7])); | 388 | input_report_abs(gc->dev[i], ABS_X, !(s & data[6]) - !(s & data[7])); |
388 | input_report_abs(dev + i, ABS_Y, !(s & data[4]) - !(s & data[5])); | 389 | input_report_abs(gc->dev[i], ABS_Y, !(s & data[4]) - !(s & data[5])); |
389 | } | 390 | } |
390 | 391 | ||
391 | if (s & gc->pads[GC_NES]) | 392 | if (s & gc->pads[GC_NES]) |
392 | for (j = 0; j < 4; j++) | 393 | for (j = 0; j < 4; j++) |
393 | input_report_key(dev + i, gc_snes_btn[j], s & data[gc_nes_bytes[j]]); | 394 | input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_nes_bytes[j]]); |
394 | 395 | ||
395 | if (s & gc->pads[GC_SNES]) | 396 | if (s & gc->pads[GC_SNES]) |
396 | for (j = 0; j < 8; j++) | 397 | for (j = 0; j < 8; j++) |
397 | input_report_key(dev + i, gc_snes_btn[j], s & data[gc_snes_bytes[j]]); | 398 | input_report_key(gc->dev[i], gc_snes_btn[j], s & data[gc_snes_bytes[j]]); |
398 | 399 | ||
399 | input_sync(dev + i); | 400 | input_sync(gc->dev[i]); |
400 | } | 401 | } |
401 | } | 402 | } |
402 | 403 | ||
@@ -413,15 +414,15 @@ static void gc_timer(unsigned long private) | |||
413 | s = gc_status_bit[i]; | 414 | s = gc_status_bit[i]; |
414 | 415 | ||
415 | if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) { | 416 | if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) { |
416 | input_report_abs(dev + i, ABS_X, !(s & data[2]) - !(s & data[3])); | 417 | input_report_abs(gc->dev[i], ABS_X, !(s & data[2]) - !(s & data[3])); |
417 | input_report_abs(dev + i, ABS_Y, !(s & data[0]) - !(s & data[1])); | 418 | input_report_abs(gc->dev[i], ABS_Y, !(s & data[0]) - !(s & data[1])); |
418 | input_report_key(dev + i, BTN_TRIGGER, s & data[4]); | 419 | input_report_key(gc->dev[i], BTN_TRIGGER, s & data[4]); |
419 | } | 420 | } |
420 | 421 | ||
421 | if (s & gc->pads[GC_MULTI2]) | 422 | if (s & gc->pads[GC_MULTI2]) |
422 | input_report_key(dev + i, BTN_THUMB, s & data[5]); | 423 | input_report_key(gc->dev[i], BTN_THUMB, s & data[5]); |
423 | 424 | ||
424 | input_sync(dev + i); | 425 | input_sync(gc->dev[i]); |
425 | } | 426 | } |
426 | } | 427 | } |
427 | 428 | ||
@@ -438,44 +439,44 @@ static void gc_timer(unsigned long private) | |||
438 | 439 | ||
439 | case GC_PSX_RUMBLE: | 440 | case GC_PSX_RUMBLE: |
440 | 441 | ||
441 | input_report_key(dev + i, BTN_THUMBL, ~data_psx[i][0] & 0x04); | 442 | input_report_key(gc->dev[i], BTN_THUMBL, ~data_psx[i][0] & 0x04); |
442 | input_report_key(dev + i, BTN_THUMBR, ~data_psx[i][0] & 0x02); | 443 | input_report_key(gc->dev[i], BTN_THUMBR, ~data_psx[i][0] & 0x02); |
443 | 444 | ||
444 | case GC_PSX_NEGCON: | 445 | case GC_PSX_NEGCON: |
445 | case GC_PSX_ANALOG: | 446 | case GC_PSX_ANALOG: |
446 | 447 | ||
447 | if(gc->pads[GC_DDR] & gc_status_bit[i]) { | 448 | if (gc->pads[GC_DDR] & gc_status_bit[i]) { |
448 | for(j = 0; j < 4; j++) | 449 | for(j = 0; j < 4; j++) |
449 | input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j)); | 450 | input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j)); |
450 | } else { | 451 | } else { |
451 | for (j = 0; j < 4; j++) | 452 | for (j = 0; j < 4; j++) |
452 | input_report_abs(dev + i, gc_psx_abs[j+2], data_psx[i][j + 2]); | 453 | input_report_abs(gc->dev[i], gc_psx_abs[j+2], data_psx[i][j + 2]); |
453 | 454 | ||
454 | input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128); | 455 | input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128); |
455 | input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128); | 456 | input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128); |
456 | } | 457 | } |
457 | 458 | ||
458 | for (j = 0; j < 8; j++) | 459 | for (j = 0; j < 8; j++) |
459 | input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j)); | 460 | input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j)); |
460 | 461 | ||
461 | input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08); | 462 | input_report_key(gc->dev[i], BTN_START, ~data_psx[i][0] & 0x08); |
462 | input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01); | 463 | input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01); |
463 | 464 | ||
464 | input_sync(dev + i); | 465 | input_sync(gc->dev[i]); |
465 | 466 | ||
466 | break; | 467 | break; |
467 | 468 | ||
468 | case GC_PSX_NORMAL: | 469 | case GC_PSX_NORMAL: |
469 | if(gc->pads[GC_DDR] & gc_status_bit[i]) { | 470 | if (gc->pads[GC_DDR] & gc_status_bit[i]) { |
470 | for(j = 0; j < 4; j++) | 471 | for(j = 0; j < 4; j++) |
471 | input_report_key(dev + i, gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j)); | 472 | input_report_key(gc->dev[i], gc_psx_ddr_btn[j], ~data_psx[i][0] & (0x10 << j)); |
472 | } else { | 473 | } else { |
473 | input_report_abs(dev + i, ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128); | 474 | input_report_abs(gc->dev[i], ABS_X, 128 + !(data_psx[i][0] & 0x20) * 127 - !(data_psx[i][0] & 0x80) * 128); |
474 | input_report_abs(dev + i, ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128); | 475 | input_report_abs(gc->dev[i], ABS_Y, 128 + !(data_psx[i][0] & 0x40) * 127 - !(data_psx[i][0] & 0x10) * 128); |
475 | 476 | ||
476 | /* for some reason if the extra axes are left unset they drift */ | 477 | /* for some reason if the extra axes are left unset they drift */ |
477 | /* for (j = 0; j < 4; j++) | 478 | /* for (j = 0; j < 4; j++) |
478 | input_report_abs(dev + i, gc_psx_abs[j+2], 128); | 479 | input_report_abs(gc->dev[i], gc_psx_abs[j+2], 128); |
479 | * This needs to be debugged properly, | 480 | * This needs to be debugged properly, |
480 | * maybe fuzz processing needs to be done in input_sync() | 481 | * maybe fuzz processing needs to be done in input_sync() |
481 | * --vojtech | 482 | * --vojtech |
@@ -483,12 +484,12 @@ static void gc_timer(unsigned long private) | |||
483 | } | 484 | } |
484 | 485 | ||
485 | for (j = 0; j < 8; j++) | 486 | for (j = 0; j < 8; j++) |
486 | input_report_key(dev + i, gc_psx_btn[j], ~data_psx[i][1] & (1 << j)); | 487 | input_report_key(gc->dev[i], gc_psx_btn[j], ~data_psx[i][1] & (1 << j)); |
487 | 488 | ||
488 | input_report_key(dev + i, BTN_START, ~data_psx[i][0] & 0x08); | 489 | input_report_key(gc->dev[i], BTN_START, ~data_psx[i][0] & 0x08); |
489 | input_report_key(dev + i, BTN_SELECT, ~data_psx[i][0] & 0x01); | 490 | input_report_key(gc->dev[i], BTN_SELECT, ~data_psx[i][0] & 0x01); |
490 | 491 | ||
491 | input_sync(dev + i); | 492 | input_sync(gc->dev[i]); |
492 | 493 | ||
493 | break; | 494 | break; |
494 | 495 | ||
@@ -533,177 +534,212 @@ static void gc_close(struct input_dev *dev) | |||
533 | up(&gc->sem); | 534 | up(&gc->sem); |
534 | } | 535 | } |
535 | 536 | ||
536 | static struct gc __init *gc_probe(int *config, int nargs) | 537 | static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) |
537 | { | 538 | { |
538 | struct gc *gc; | 539 | struct input_dev *input_dev; |
539 | struct parport *pp; | 540 | int i; |
540 | int i, j; | ||
541 | 541 | ||
542 | if (config[0] < 0) | 542 | if (!pad_type) |
543 | return NULL; | 543 | return 0; |
544 | 544 | ||
545 | if (nargs < 2) { | 545 | if (pad_type < 1 || pad_type > GC_MAX) { |
546 | printk(KERN_ERR "gamecon.c: at least one device must be specified\n"); | 546 | printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", pad_type); |
547 | return NULL; | 547 | return -EINVAL; |
548 | } | 548 | } |
549 | 549 | ||
550 | pp = parport_find_number(config[0]); | 550 | gc->dev[idx] = input_dev = input_allocate_device(); |
551 | 551 | if (!input_dev) { | |
552 | if (!pp) { | 552 | printk(KERN_ERR "gamecon.c: Not enough memory for input device\n"); |
553 | printk(KERN_ERR "gamecon.c: no such parport\n"); | 553 | return -ENOMEM; |
554 | return NULL; | ||
555 | } | 554 | } |
556 | 555 | ||
557 | if (!(gc = kzalloc(sizeof(struct gc), GFP_KERNEL))) { | 556 | input_dev->name = gc_names[pad_type]; |
558 | parport_put_port(pp); | 557 | input_dev->phys = gc->phys[idx]; |
559 | return NULL; | 558 | input_dev->id.bustype = BUS_PARPORT; |
559 | input_dev->id.vendor = 0x0001; | ||
560 | input_dev->id.product = pad_type; | ||
561 | input_dev->id.version = 0x0100; | ||
562 | input_dev->private = gc; | ||
563 | |||
564 | input_dev->open = gc_open; | ||
565 | input_dev->close = gc_close; | ||
566 | |||
567 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
568 | |||
569 | for (i = 0; i < 2; i++) | ||
570 | input_set_abs_params(input_dev, ABS_X + i, -1, 1, 0, 0); | ||
571 | |||
572 | gc->pads[0] |= gc_status_bit[idx]; | ||
573 | gc->pads[pad_type] |= gc_status_bit[idx]; | ||
574 | |||
575 | switch (pad_type) { | ||
576 | |||
577 | case GC_N64: | ||
578 | for (i = 0; i < 10; i++) | ||
579 | set_bit(gc_n64_btn[i], input_dev->keybit); | ||
580 | |||
581 | for (i = 0; i < 2; i++) { | ||
582 | input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2); | ||
583 | input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); | ||
584 | } | ||
585 | |||
586 | break; | ||
587 | |||
588 | case GC_SNES: | ||
589 | for (i = 4; i < 8; i++) | ||
590 | set_bit(gc_snes_btn[i], input_dev->keybit); | ||
591 | case GC_NES: | ||
592 | for (i = 0; i < 4; i++) | ||
593 | set_bit(gc_snes_btn[i], input_dev->keybit); | ||
594 | break; | ||
595 | |||
596 | case GC_MULTI2: | ||
597 | set_bit(BTN_THUMB, input_dev->keybit); | ||
598 | case GC_MULTI: | ||
599 | set_bit(BTN_TRIGGER, input_dev->keybit); | ||
600 | break; | ||
601 | |||
602 | case GC_PSX: | ||
603 | for (i = 0; i < 6; i++) | ||
604 | input_set_abs_params(input_dev, gc_psx_abs[i], 4, 252, 0, 2); | ||
605 | for (i = 0; i < 12; i++) | ||
606 | set_bit(gc_psx_btn[i], input_dev->keybit); | ||
607 | |||
608 | break; | ||
609 | |||
610 | case GC_DDR: | ||
611 | for (i = 0; i < 4; i++) | ||
612 | set_bit(gc_psx_ddr_btn[i], input_dev->keybit); | ||
613 | for (i = 0; i < 12; i++) | ||
614 | set_bit(gc_psx_btn[i], input_dev->keybit); | ||
615 | |||
616 | break; | ||
560 | } | 617 | } |
561 | 618 | ||
562 | init_MUTEX(&gc->sem); | 619 | return 0; |
620 | } | ||
563 | 621 | ||
564 | gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); | 622 | static struct gc __init *gc_probe(int parport, int *pads, int n_pads) |
623 | { | ||
624 | struct gc *gc; | ||
625 | struct parport *pp; | ||
626 | struct pardevice *pd; | ||
627 | int i; | ||
628 | int err; | ||
565 | 629 | ||
566 | parport_put_port(pp); | 630 | pp = parport_find_number(parport); |
631 | if (!pp) { | ||
632 | printk(KERN_ERR "gamecon.c: no such parport\n"); | ||
633 | err = -EINVAL; | ||
634 | goto err_out; | ||
635 | } | ||
567 | 636 | ||
568 | if (!gc->pd) { | 637 | pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); |
638 | if (!pd) { | ||
569 | printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n"); | 639 | printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n"); |
570 | kfree(gc); | 640 | err = -EBUSY; |
571 | return NULL; | 641 | goto err_put_pp; |
572 | } | 642 | } |
573 | 643 | ||
574 | parport_claim(gc->pd); | 644 | gc = kzalloc(sizeof(struct gc), GFP_KERNEL); |
645 | if (!gc) { | ||
646 | printk(KERN_ERR "gamecon.c: Not enough memory\n"); | ||
647 | err = -ENOMEM; | ||
648 | goto err_unreg_pardev; | ||
649 | } | ||
575 | 650 | ||
651 | init_MUTEX(&gc->sem); | ||
652 | gc->pd = pd; | ||
576 | init_timer(&gc->timer); | 653 | init_timer(&gc->timer); |
577 | gc->timer.data = (long) gc; | 654 | gc->timer.data = (long) gc; |
578 | gc->timer.function = gc_timer; | 655 | gc->timer.function = gc_timer; |
579 | 656 | ||
580 | for (i = 0; i < nargs - 1; i++) { | 657 | for (i = 0; i < n_pads; i++) { |
581 | 658 | if (!pads[i]) | |
582 | if (!config[i + 1]) | ||
583 | continue; | 659 | continue; |
584 | 660 | ||
585 | if (config[i + 1] < 1 || config[i + 1] > GC_MAX) { | 661 | sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i); |
586 | printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", config[i + 1]); | 662 | err = gc_setup_pad(gc, i, pads[i]); |
587 | continue; | 663 | if (err) |
588 | } | 664 | goto err_free_devs; |
589 | |||
590 | gc->dev[i].private = gc; | ||
591 | gc->dev[i].open = gc_open; | ||
592 | gc->dev[i].close = gc_close; | ||
593 | 665 | ||
594 | gc->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | 666 | input_register_device(gc->dev[i]); |
667 | } | ||
595 | 668 | ||
596 | for (j = 0; j < 2; j++) { | 669 | if (!gc->pads[0]) { |
597 | set_bit(ABS_X + j, gc->dev[i].absbit); | 670 | printk(KERN_ERR "gamecon.c: No valid devices specified\n"); |
598 | gc->dev[i].absmin[ABS_X + j] = -1; | 671 | err = -EINVAL; |
599 | gc->dev[i].absmax[ABS_X + j] = 1; | 672 | goto err_free_gc; |
600 | } | 673 | } |
601 | 674 | ||
602 | gc->pads[0] |= gc_status_bit[i]; | 675 | parport_put_port(pp); |
603 | gc->pads[config[i + 1]] |= gc_status_bit[i]; | 676 | return gc; |
604 | 677 | ||
605 | switch(config[i + 1]) { | 678 | err_free_devs: |
679 | while (--i >= 0) | ||
680 | input_unregister_device(gc->dev[i]); | ||
681 | err_free_gc: | ||
682 | kfree(gc); | ||
683 | err_unreg_pardev: | ||
684 | parport_unregister_device(pd); | ||
685 | err_put_pp: | ||
686 | parport_put_port(pp); | ||
687 | err_out: | ||
688 | return ERR_PTR(err); | ||
689 | } | ||
606 | 690 | ||
607 | case GC_N64: | 691 | static void __exit gc_remove(struct gc *gc) |
608 | for (j = 0; j < 10; j++) | 692 | { |
609 | set_bit(gc_n64_btn[j], gc->dev[i].keybit); | 693 | int i; |
610 | |||
611 | for (j = 0; j < 2; j++) { | ||
612 | set_bit(ABS_X + j, gc->dev[i].absbit); | ||
613 | gc->dev[i].absmin[ABS_X + j] = -127; | ||
614 | gc->dev[i].absmax[ABS_X + j] = 126; | ||
615 | gc->dev[i].absflat[ABS_X + j] = 2; | ||
616 | set_bit(ABS_HAT0X + j, gc->dev[i].absbit); | ||
617 | gc->dev[i].absmin[ABS_HAT0X + j] = -1; | ||
618 | gc->dev[i].absmax[ABS_HAT0X + j] = 1; | ||
619 | } | ||
620 | 694 | ||
621 | break; | 695 | for (i = 0; i < GC_MAX_DEVICES; i++) |
696 | if (gc->dev[i]) | ||
697 | input_unregister_device(gc->dev[i]); | ||
698 | parport_unregister_device(gc->pd); | ||
699 | kfree(gc); | ||
700 | } | ||
622 | 701 | ||
623 | case GC_SNES: | 702 | static int __init gc_init(void) |
624 | for (j = 4; j < 8; j++) | 703 | { |
625 | set_bit(gc_snes_btn[j], gc->dev[i].keybit); | 704 | int i; |
626 | case GC_NES: | 705 | int have_dev = 0; |
627 | for (j = 0; j < 4; j++) | 706 | int err = 0; |
628 | set_bit(gc_snes_btn[j], gc->dev[i].keybit); | ||
629 | break; | ||
630 | |||
631 | case GC_MULTI2: | ||
632 | set_bit(BTN_THUMB, gc->dev[i].keybit); | ||
633 | case GC_MULTI: | ||
634 | set_bit(BTN_TRIGGER, gc->dev[i].keybit); | ||
635 | break; | ||
636 | |||
637 | case GC_PSX: | ||
638 | case GC_DDR: | ||
639 | if(config[i + 1] == GC_DDR) { | ||
640 | for (j = 0; j < 4; j++) | ||
641 | set_bit(gc_psx_ddr_btn[j], gc->dev[i].keybit); | ||
642 | } else { | ||
643 | for (j = 0; j < 6; j++) { | ||
644 | set_bit(gc_psx_abs[j], gc->dev[i].absbit); | ||
645 | gc->dev[i].absmin[gc_psx_abs[j]] = 4; | ||
646 | gc->dev[i].absmax[gc_psx_abs[j]] = 252; | ||
647 | gc->dev[i].absflat[gc_psx_abs[j]] = 2; | ||
648 | } | ||
649 | } | ||
650 | 707 | ||
651 | for (j = 0; j < 12; j++) | 708 | for (i = 0; i < GC_MAX_PORTS; i++) { |
652 | set_bit(gc_psx_btn[j], gc->dev[i].keybit); | 709 | if (gc[i].nargs == 0 || gc[i].args[0] < 0) |
710 | continue; | ||
653 | 711 | ||
654 | break; | 712 | if (gc[i].nargs < 2) { |
713 | printk(KERN_ERR "gamecon.c: at least one device must be specified\n"); | ||
714 | err = -EINVAL; | ||
715 | break; | ||
655 | } | 716 | } |
656 | 717 | ||
657 | sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i); | 718 | gc_base[i] = gc_probe(gc[i].args[0], gc[i].args + 1, gc[i].nargs - 1); |
719 | if (IS_ERR(gc_base[i])) { | ||
720 | err = PTR_ERR(gc_base[i]); | ||
721 | break; | ||
722 | } | ||
658 | 723 | ||
659 | gc->dev[i].name = gc_names[config[i + 1]]; | 724 | have_dev = 1; |
660 | gc->dev[i].phys = gc->phys[i]; | ||
661 | gc->dev[i].id.bustype = BUS_PARPORT; | ||
662 | gc->dev[i].id.vendor = 0x0001; | ||
663 | gc->dev[i].id.product = config[i + 1]; | ||
664 | gc->dev[i].id.version = 0x0100; | ||
665 | } | 725 | } |
666 | 726 | ||
667 | parport_release(gc->pd); | 727 | if (err) { |
668 | 728 | while (--i >= 0) | |
669 | if (!gc->pads[0]) { | 729 | gc_remove(gc_base[i]); |
670 | parport_unregister_device(gc->pd); | 730 | return err; |
671 | kfree(gc); | ||
672 | return NULL; | ||
673 | } | 731 | } |
674 | 732 | ||
675 | for (i = 0; i < 5; i++) | 733 | return have_dev ? 0 : -ENODEV; |
676 | if (gc->pads[0] & gc_status_bit[i]) { | ||
677 | input_register_device(gc->dev + i); | ||
678 | printk(KERN_INFO "input: %s on %s\n", gc->dev[i].name, gc->pd->port->name); | ||
679 | } | ||
680 | |||
681 | return gc; | ||
682 | } | ||
683 | |||
684 | static int __init gc_init(void) | ||
685 | { | ||
686 | gc_base[0] = gc_probe(gc, gc_nargs); | ||
687 | gc_base[1] = gc_probe(gc_2, gc_nargs_2); | ||
688 | gc_base[2] = gc_probe(gc_3, gc_nargs_3); | ||
689 | |||
690 | if (gc_base[0] || gc_base[1] || gc_base[2]) | ||
691 | return 0; | ||
692 | |||
693 | return -ENODEV; | ||
694 | } | 734 | } |
695 | 735 | ||
696 | static void __exit gc_exit(void) | 736 | static void __exit gc_exit(void) |
697 | { | 737 | { |
698 | int i, j; | 738 | int i; |
699 | 739 | ||
700 | for (i = 0; i < 3; i++) | 740 | for (i = 0; i < GC_MAX_PORTS; i++) |
701 | if (gc_base[i]) { | 741 | if (gc_base[i]) |
702 | for (j = 0; j < 5; j++) | 742 | gc_remove(gc_base[i]); |
703 | if (gc_base[i]->pads[0] & gc_status_bit[j]) | ||
704 | input_unregister_device(gc_base[i]->dev + j); | ||
705 | parport_unregister_device(gc_base[i]->pd); | ||
706 | } | ||
707 | } | 743 | } |
708 | 744 | ||
709 | module_init(gc_init); | 745 | module_init(gc_init); |