diff options
| -rw-r--r-- | drivers/input/joystick/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/input/joystick/gamecon.c | 125 |
2 files changed, 120 insertions, 6 deletions
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index b11419590cfe..5b596165b571 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig | |||
| @@ -221,6 +221,7 @@ config JOYSTICK_DB9 | |||
| 221 | config JOYSTICK_GAMECON | 221 | config JOYSTICK_GAMECON |
| 222 | tristate "Multisystem, NES, SNES, N64, PSX joysticks and gamepads" | 222 | tristate "Multisystem, NES, SNES, N64, PSX joysticks and gamepads" |
| 223 | depends on PARPORT | 223 | depends on PARPORT |
| 224 | select INPUT_FF_MEMLESS | ||
| 224 | ---help--- | 225 | ---help--- |
| 225 | Say Y here if you have a Nintendo Entertainment System gamepad, | 226 | Say Y here if you have a Nintendo Entertainment System gamepad, |
| 226 | Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad, | 227 | Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad, |
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 07a32aff5a31..bbde4e524da3 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c | |||
| @@ -85,6 +85,10 @@ struct gc { | |||
| 85 | char phys[GC_MAX_DEVICES][32]; | 85 | char phys[GC_MAX_DEVICES][32]; |
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| 88 | struct gc_subdev { | ||
| 89 | unsigned int idx; | ||
| 90 | }; | ||
| 91 | |||
| 88 | static struct gc *gc_base[3]; | 92 | static struct gc *gc_base[3]; |
| 89 | 93 | ||
| 90 | static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; | 94 | static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; |
| @@ -100,9 +104,16 @@ static unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 }; | |||
| 100 | static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START }; | 104 | static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START }; |
| 101 | 105 | ||
| 102 | #define GC_N64_LENGTH 32 /* N64 bit length, not including stop bit */ | 106 | #define GC_N64_LENGTH 32 /* N64 bit length, not including stop bit */ |
| 103 | #define GC_N64_REQUEST_LENGTH 37 /* transmit request sequence is 9 bits long */ | 107 | #define GC_N64_STOP_LENGTH 5 /* Length of encoded stop bit */ |
| 108 | #define GC_N64_CMD_00 0x11111111UL | ||
| 109 | #define GC_N64_CMD_01 0xd1111111UL | ||
| 110 | #define GC_N64_CMD_03 0xdd111111UL | ||
| 111 | #define GC_N64_CMD_1b 0xdd1dd111UL | ||
| 112 | #define GC_N64_CMD_c0 0x111111ddUL | ||
| 113 | #define GC_N64_CMD_80 0x1111111dUL | ||
| 114 | #define GC_N64_STOP_BIT 0x1d /* Encoded stop bit */ | ||
| 115 | #define GC_N64_REQUEST_DATA GC_N64_CMD_01 /* the request data command */ | ||
| 104 | #define GC_N64_DELAY 133 /* delay between transmit request, and response ready (us) */ | 116 | #define GC_N64_DELAY 133 /* delay between transmit request, and response ready (us) */ |
| 105 | #define GC_N64_REQUEST 0x1dd1111111ULL /* the request data command (encoded for 000000011) */ | ||
| 106 | #define GC_N64_DWS 3 /* delay between write segments (required for sound playback because of ISA DMA) */ | 117 | #define GC_N64_DWS 3 /* delay between write segments (required for sound playback because of ISA DMA) */ |
| 107 | /* GC_N64_DWS > 24 is known to fail */ | 118 | /* GC_N64_DWS > 24 is known to fail */ |
| 108 | #define GC_N64_POWER_W 0xe2 /* power during write (transmit request) */ | 119 | #define GC_N64_POWER_W 0xe2 /* power during write (transmit request) */ |
| @@ -114,6 +125,37 @@ static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, | |||
| 114 | #define GC_N64_CLOCK 0x02 /* clock bits for read */ | 125 | #define GC_N64_CLOCK 0x02 /* clock bits for read */ |
| 115 | 126 | ||
| 116 | /* | 127 | /* |
| 128 | * Used for rumble code. | ||
| 129 | */ | ||
| 130 | |||
| 131 | /* Send encoded command */ | ||
| 132 | static void gc_n64_send_command(struct gc *gc, unsigned long cmd, | ||
| 133 | unsigned char target) | ||
| 134 | { | ||
| 135 | struct parport *port = gc->pd->port; | ||
| 136 | int i; | ||
| 137 | |||
| 138 | for (i = 0; i < GC_N64_LENGTH; i++) { | ||
| 139 | unsigned char data = (cmd >> i) & 1 ? target : 0; | ||
| 140 | parport_write_data(port, GC_N64_POWER_W | data); | ||
| 141 | udelay(GC_N64_DWS); | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | /* Send stop bit */ | ||
| 146 | static void gc_n64_send_stop_bit(struct gc *gc, unsigned char target) | ||
| 147 | { | ||
| 148 | struct parport *port = gc->pd->port; | ||
| 149 | int i; | ||
| 150 | |||
| 151 | for (i = 0; i < GC_N64_STOP_LENGTH; i++) { | ||
| 152 | unsigned char data = (GC_N64_STOP_BIT >> i) & 1 ? target : 0; | ||
| 153 | parport_write_data(port, GC_N64_POWER_W | data); | ||
| 154 | udelay(GC_N64_DWS); | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | /* | ||
| 117 | * gc_n64_read_packet() reads an N64 packet. | 159 | * gc_n64_read_packet() reads an N64 packet. |
| 118 | * Each pad uses one bit per byte. So all pads connected to this port are read in parallel. | 160 | * Each pad uses one bit per byte. So all pads connected to this port are read in parallel. |
| 119 | */ | 161 | */ |
| @@ -128,10 +170,8 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) | |||
| 128 | */ | 170 | */ |
| 129 | 171 | ||
| 130 | local_irq_save(flags); | 172 | local_irq_save(flags); |
| 131 | for (i = 0; i < GC_N64_REQUEST_LENGTH; i++) { | 173 | gc_n64_send_command(gc, GC_N64_REQUEST_DATA, GC_N64_OUT); |
| 132 | parport_write_data(gc->pd->port, GC_N64_POWER_W | ((GC_N64_REQUEST >> i) & 1 ? GC_N64_OUT : 0)); | 174 | gc_n64_send_stop_bit(gc, GC_N64_OUT); |
| 133 | udelay(GC_N64_DWS); | ||
| 134 | } | ||
| 135 | local_irq_restore(flags); | 175 | local_irq_restore(flags); |
| 136 | 176 | ||
| 137 | /* | 177 | /* |
| @@ -146,6 +186,7 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) | |||
| 146 | 186 | ||
| 147 | for (i = 0; i < GC_N64_LENGTH; i++) { | 187 | for (i = 0; i < GC_N64_LENGTH; i++) { |
| 148 | parport_write_data(gc->pd->port, GC_N64_POWER_R); | 188 | parport_write_data(gc->pd->port, GC_N64_POWER_R); |
| 189 | udelay(2); | ||
| 149 | data[i] = parport_read_status(gc->pd->port); | 190 | data[i] = parport_read_status(gc->pd->port); |
| 150 | parport_write_data(gc->pd->port, GC_N64_POWER_R | GC_N64_CLOCK); | 191 | parport_write_data(gc->pd->port, GC_N64_POWER_R | GC_N64_CLOCK); |
| 151 | } | 192 | } |
| @@ -199,6 +240,70 @@ static void gc_n64_process_packet(struct gc *gc) | |||
| 199 | } | 240 | } |
| 200 | } | 241 | } |
| 201 | 242 | ||
| 243 | static int gc_n64_play_effect(struct input_dev *dev, void *data, | ||
| 244 | struct ff_effect *effect) | ||
| 245 | { | ||
| 246 | int i; | ||
| 247 | unsigned long flags; | ||
| 248 | struct gc *gc = input_get_drvdata(dev); | ||
| 249 | struct gc_subdev *sdev = data; | ||
| 250 | unsigned char target = 1 << sdev->idx; /* select desired pin */ | ||
| 251 | |||
| 252 | if (effect->type == FF_RUMBLE) { | ||
| 253 | struct ff_rumble_effect *rumble = &effect->u.rumble; | ||
| 254 | unsigned int cmd = | ||
| 255 | rumble->strong_magnitude || rumble->weak_magnitude ? | ||
| 256 | GC_N64_CMD_01 : GC_N64_CMD_00; | ||
| 257 | |||
| 258 | local_irq_save(flags); | ||
| 259 | |||
| 260 | /* Init Rumble - 0x03, 0x80, 0x01, (34)0x80 */ | ||
| 261 | gc_n64_send_command(gc, GC_N64_CMD_03, target); | ||
| 262 | gc_n64_send_command(gc, GC_N64_CMD_80, target); | ||
| 263 | gc_n64_send_command(gc, GC_N64_CMD_01, target); | ||
| 264 | for (i = 0; i < 32; i++) | ||
| 265 | gc_n64_send_command(gc, GC_N64_CMD_80, target); | ||
| 266 | gc_n64_send_stop_bit(gc, target); | ||
| 267 | |||
| 268 | udelay(GC_N64_DELAY); | ||
| 269 | |||
| 270 | /* Now start or stop it - 0x03, 0xc0, 0zx1b, (32)0x01/0x00 */ | ||
| 271 | gc_n64_send_command(gc, GC_N64_CMD_03, target); | ||
| 272 | gc_n64_send_command(gc, GC_N64_CMD_c0, target); | ||
| 273 | gc_n64_send_command(gc, GC_N64_CMD_1b, target); | ||
| 274 | for (i = 0; i < 32; i++) | ||
| 275 | gc_n64_send_command(gc, cmd, target); | ||
| 276 | gc_n64_send_stop_bit(gc, target); | ||
| 277 | |||
| 278 | local_irq_restore(flags); | ||
| 279 | |||
| 280 | } | ||
| 281 | |||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | |||
| 285 | static int __init gc_n64_init_ff(struct input_dev *dev, int i) | ||
| 286 | { | ||
| 287 | struct gc_subdev *sdev; | ||
| 288 | int err; | ||
| 289 | |||
| 290 | sdev = kmalloc(sizeof(*sdev), GFP_KERNEL); | ||
| 291 | if (!sdev) | ||
| 292 | return -ENOMEM; | ||
| 293 | |||
| 294 | sdev->idx = i; | ||
| 295 | |||
| 296 | input_set_capability(dev, EV_FF, FF_RUMBLE); | ||
| 297 | |||
| 298 | err = input_ff_create_memless(dev, sdev, gc_n64_play_effect); | ||
| 299 | if (err) { | ||
| 300 | kfree(sdev); | ||
| 301 | return err; | ||
| 302 | } | ||
| 303 | |||
| 304 | return 0; | ||
| 305 | } | ||
| 306 | |||
| 202 | /* | 307 | /* |
| 203 | * NES/SNES support. | 308 | * NES/SNES support. |
| 204 | */ | 309 | */ |
| @@ -624,6 +729,7 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) | |||
| 624 | { | 729 | { |
| 625 | struct input_dev *input_dev; | 730 | struct input_dev *input_dev; |
| 626 | int i; | 731 | int i; |
| 732 | int err; | ||
| 627 | 733 | ||
| 628 | if (!pad_type) | 734 | if (!pad_type) |
| 629 | return 0; | 735 | return 0; |
| @@ -673,6 +779,13 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) | |||
| 673 | input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); | 779 | input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); |
| 674 | } | 780 | } |
| 675 | 781 | ||
| 782 | err = gc_n64_init_ff(input_dev, idx); | ||
| 783 | if (err) { | ||
| 784 | printk(KERN_WARNING "gamecon.c: Failed to initiate rumble for N64 device %d\n", idx); | ||
| 785 | input_free_device(input_dev); | ||
| 786 | return err; | ||
| 787 | } | ||
| 788 | |||
| 676 | break; | 789 | break; |
| 677 | 790 | ||
| 678 | case GC_SNESMOUSE: | 791 | case GC_SNESMOUSE: |
