aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/joystick/gamecon.c
diff options
context:
space:
mode:
authorScott Moreau <oreaus@gmail.com>2010-02-21 23:53:55 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-02-22 01:09:43 -0500
commit7aa9e0e8263259f4517ba1788f4fbaa88e878400 (patch)
tree1735ed924c5f6705e1f91b9ae22618b5fdfbbfd7 /drivers/input/joystick/gamecon.c
parent49b764aebde6ceea393f56cd3449bfa5720f8383 (diff)
Input: gamecon - add rumble support for N64 pads
Add force-feedback support for N64 pads with rumble pak accessory installed. Actually we do not check for the presence of rumble pad but simply assume it is installed and expect the device to ignore FF commands if rumble pak is missing. Signed-off-by: Scott Moreau <oreaus@gmail.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/joystick/gamecon.c')
-rw-r--r--drivers/input/joystick/gamecon.c125
1 files changed, 119 insertions, 6 deletions
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
88struct gc_subdev {
89 unsigned int idx;
90};
91
88static struct gc *gc_base[3]; 92static struct gc *gc_base[3];
89 93
90static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; 94static 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 };
100static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START }; 104static 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 */
132static 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 */
146static 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
243static 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
285static 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: