diff options
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); |
